View Javadoc

1   /*
2    *  soapUI, copyright (C) 2004-2007 eviware.com 
3    *
4    *  soapUI is free software; you can redistribute it and/or modify it under the 
5    *  terms of version 2.1 of the GNU Lesser General Public License as published by 
6    *  the Free Software Foundation.
7    *
8    *  soapUI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without 
9    *  even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
10   *  See the GNU Lesser General Public License for more details at gnu.org.
11   */
12  
13  package com.eviware.soapui.impl.wsdl.panels.mockoperation;
14  
15  import java.awt.BorderLayout;
16  import java.awt.Dimension;
17  import java.awt.event.ActionEvent;
18  import java.awt.event.FocusAdapter;
19  import java.awt.event.FocusEvent;
20  import java.awt.event.FocusListener;
21  import java.beans.PropertyChangeEvent;
22  import java.beans.PropertyChangeListener;
23  
24  import javax.swing.AbstractAction;
25  import javax.swing.Action;
26  import javax.swing.BorderFactory;
27  import javax.swing.Box;
28  import javax.swing.JButton;
29  import javax.swing.JComponent;
30  import javax.swing.JPanel;
31  import javax.swing.JPopupMenu;
32  import javax.swing.JSeparator;
33  import javax.swing.JSplitPane;
34  import javax.swing.JTabbedPane;
35  import javax.swing.JToggleButton;
36  import javax.swing.JToolBar;
37  
38  import com.eviware.soapui.SoapUI;
39  import com.eviware.soapui.impl.wsdl.actions.mockresponse.OpenRequestForMockResponseAction;
40  import com.eviware.soapui.impl.wsdl.actions.support.ShowOnlineHelpAction;
41  import com.eviware.soapui.impl.wsdl.mock.WsdlMockRequest;
42  import com.eviware.soapui.impl.wsdl.mock.WsdlMockResponse;
43  import com.eviware.soapui.impl.wsdl.panels.mockoperation.actions.CreateEmptyMockResponseAction;
44  import com.eviware.soapui.impl.wsdl.panels.mockoperation.actions.CreateFaultMockResponseAction;
45  import com.eviware.soapui.impl.wsdl.panels.mockoperation.actions.RecreateMockResponseAction;
46  import com.eviware.soapui.impl.wsdl.panels.mockoperation.actions.WSIValidateResponseAction;
47  import com.eviware.soapui.impl.wsdl.panels.request.components.RequestMessageXmlEditor;
48  import com.eviware.soapui.impl.wsdl.panels.request.components.ResponseMessageXmlEditor;
49  import com.eviware.soapui.impl.wsdl.panels.request.components.SoapMessageXmlEditor;
50  import com.eviware.soapui.impl.wsdl.panels.request.components.editor.XmlDocument;
51  import com.eviware.soapui.impl.wsdl.panels.request.components.editor.views.source.XmlSourceEditorView;
52  import com.eviware.soapui.impl.wsdl.support.HelpUrls;
53  import com.eviware.soapui.model.ModelItem;
54  import com.eviware.soapui.model.mock.MockRunner;
55  import com.eviware.soapui.settings.UISettings;
56  import com.eviware.soapui.support.UISupport;
57  import com.eviware.soapui.support.action.swing.SwingActionDelegate;
58  import com.eviware.soapui.support.actions.ChangeSplitPaneOrientationAction;
59  import com.eviware.soapui.support.components.JEditorStatusBarWithProgress;
60  import com.eviware.soapui.support.components.JXToolBar;
61  import com.eviware.soapui.support.swing.SoapUISplitPaneUI;
62  import com.eviware.soapui.support.xml.JXEditTextArea;
63  import com.eviware.soapui.ui.support.ModelItemDesktopPanel;
64  
65  /***
66   * Abstract base DesktopPanel for WsdlMockResponses
67   * 
68   * @author Ole.Matzura
69   */
70  
71  public class AbstractWsdlMockResponseDesktopPanel<T extends ModelItem, T2 extends WsdlMockResponse> extends ModelItemDesktopPanel<T>
72  {
73  	//private final static Log log = Logger.getLogger(WsdlMockOperationDesktopPanel.class);
74  	private JEditorStatusBarWithProgress statusBar;
75  	private JButton splitButton;
76  	private MockRunner mockRunner;
77  	private JButton recreateButton;
78  	private JButton createEmptyButton;
79  	private JSplitPane requestSplitPane;
80  	private MoveFocusAction moveFocusAction;
81  	private ClosePanelAction closePanelAction = new ClosePanelAction();
82  
83  	private SoapMessageXmlEditor requestEditor;
84  	private SoapMessageXmlEditor responseEditor;
85  
86  	public AbstractAction wsiValidateAction;
87  
88  	private JTabbedPane requestTabs;
89  	private JPanel requestTabPanel;
90  	private JToggleButton tabsButton;
91  
92  	public boolean responseHasFocus;
93  
94  	private InternalPropertyChangeListener propertyChangeListener = new InternalPropertyChangeListener();
95  	private JButton createFaultButton;
96  	private T2 mockResponse;
97  	private JButton openRequestButton;
98  
99  	public AbstractWsdlMockResponseDesktopPanel(T modelItem)
100 	{
101 		super(modelItem);
102 	}
103 	
104 	protected void init( T2 mockResponse )
105 	{
106 		this.mockResponse = mockResponse;
107 		
108 		add(buildContent(), BorderLayout.CENTER);
109 		add(buildToolbar(), BorderLayout.NORTH);
110 		add(buildStatusLabel(), BorderLayout.SOUTH);
111 
112 		setPreferredSize(new Dimension(600, 500));
113 		
114 		mockResponse.addPropertyChangeListener( propertyChangeListener );
115 		
116 		addFocusListener( new FocusAdapter() {
117 
118 			@Override
119 			public void focusGained( FocusEvent e )
120 			{
121 				if( requestTabs.getSelectedIndex() == 1 || responseHasFocus )
122 					responseEditor.requestFocus();
123 				else
124 					requestEditor.requestFocus();
125 			}} );
126 	}
127 
128 	protected WsdlMockResponse getMockResponse()
129 	{
130 		return mockResponse;
131 	}
132 
133 	public final SoapMessageXmlEditor getRequestEditor()
134 	{
135 		return requestEditor;
136 	}
137 
138 	public final SoapMessageXmlEditor getResponseEditor()
139 	{
140 		return responseEditor;
141 	}
142 	
143 	public MockRunner getSubmit()
144 	{
145 		return mockRunner;
146 	}
147 
148 	protected JComponent buildStatusLabel()
149 	{
150 		statusBar = new JEditorStatusBarWithProgress();
151 		statusBar.setBorder( BorderFactory.createEmptyBorder( 1, 0, 0, 0 ));
152 		
153 		return statusBar;
154 	}
155 
156 	public JEditorStatusBarWithProgress getStatusBar()
157 	{
158 		return statusBar;
159 	}
160 
161 	@SuppressWarnings("unchecked")
162 	protected JComponent buildContent()
163 	{
164 		requestSplitPane = UISupport.createHorizontalSplit();
165 		requestSplitPane.setResizeWeight(0.5);
166 		requestSplitPane.setBorder(null);
167 		
168 		splitButton = createActionButton(new ChangeSplitPaneOrientationAction(requestSplitPane), true);
169 		
170 		tabsButton = new JToggleButton( new ChangeToTabsAction() );
171 		tabsButton.setPreferredSize( UISupport.TOOLBAR_BUTTON_DIMENSION );
172 		
173 		openRequestButton = createActionButton(
174 					SwingActionDelegate.createDelegate( OpenRequestForMockResponseAction.SOAPUI_ACTION_ID, mockResponse, null,
175 						"/open_request.gif"), true);
176 		recreateButton = createActionButton(new RecreateMockResponseAction( mockResponse ), true);
177 		createEmptyButton = createActionButton(new CreateEmptyMockResponseAction(mockResponse), true);
178 		createFaultButton = createActionButton(new CreateFaultMockResponseAction(mockResponse), true);
179 
180 		moveFocusAction = new MoveFocusAction();
181 		wsiValidateAction = //new WSIValidateResponseAction( mockResponse );
182 			SwingActionDelegate.createDelegate( new WSIValidateResponseAction(), mockResponse, "alt W" ); 
183 
184 		requestEditor = buildRequestEditor();
185 		responseEditor = buildResponseEditor();
186 		
187 		requestTabs = new JTabbedPane();
188 	   requestTabPanel = UISupport.createTabPanel( requestTabs, true );
189 	   
190 		JComponent component = null;
191 		
192 		if( mockResponse.getSettings().getBoolean( UISettings.START_WITH_REQUEST_TABS ))
193 	   {
194 	   	requestTabs.addTab( "Last Request", requestEditor );
195 	   	requestTabs.addTab( "Mock Response", responseEditor );
196 	   	splitButton.setEnabled( false );
197 	   	tabsButton.setSelected( true );
198 	   	component = requestTabPanel;
199 	   	
200 	   	requestTabs.setSelectedIndex( 1 );
201 	   }
202 	   else
203 	   {
204 	   	requestSplitPane.setTopComponent(requestEditor);
205 	   	requestSplitPane.setBottomComponent(responseEditor);
206 	   	requestSplitPane.setDividerLocation(0.5);
207 	   	component = requestSplitPane;
208 	   }
209 		
210 		return component;
211 	}
212 
213 	protected SoapMessageXmlEditor buildResponseEditor()
214 	{
215 		return new WsdlMockResponseMessageEditor( new MockResponseXmlDocument( mockResponse ));
216 	}
217 
218 	protected SoapMessageXmlEditor buildRequestEditor()
219 	{
220 		return new WsdlMockRequestMessageEditor( new MockRequestXmlDocument( mockResponse ));
221 	}
222 
223 	protected JComponent buildToolbar()
224 	{
225 		JXToolBar toolbar =  UISupport.createToolbar(); 
226 		
227 		toolbar.add( openRequestButton);
228 		toolbar.addUnrelatedGap();
229 		toolbar.add(recreateButton);
230 		toolbar.add(createEmptyButton);
231 		toolbar.add(createFaultButton);
232 		
233 		createToolbar( toolbar );
234 		
235 		toolbar.add( Box.createHorizontalGlue() );
236 		toolbar.add( tabsButton );
237 		toolbar.add(splitButton);
238 		toolbar.add(UISupport.createToolbarButton(new ShowOnlineHelpAction(getHelpUrl())));
239 		
240 		return toolbar;
241 	}
242 
243 	protected void createToolbar( JXToolBar toolbar )
244 	{
245 	}
246 
247 	protected String getHelpUrl()
248 	{
249 		return HelpUrls.REQUESTEDITOR_HELP_URL;
250 	}
251 
252 	protected void insertButtons(JToolBar toolbar)
253 	{
254 	}
255 
256 	public void setEnabled(boolean enabled)
257 	{
258 		requestEditor.getSourceEditor().setEditable(enabled);
259 		responseEditor.getSourceEditor().setEditable(enabled);
260 		recreateButton.setEnabled(enabled);
261 		createEmptyButton.setEnabled(enabled);
262 		statusBar.setIndeterminate( !enabled );
263 	}
264 
265 	private final class InternalPropertyChangeListener implements PropertyChangeListener
266 	{
267 		public void propertyChange(PropertyChangeEvent evt)
268 		{
269 			if( evt.getPropertyName().equals( WsdlMockResponse.MOCKRESULT_PROPERTY ))
270 			{
271 				WsdlMockRequest mockRequest = mockResponse.getMockResult().getMockRequest();
272 				requestEditor.getXmlDocument().setXml( mockRequest == null ? "" : mockRequest.getRequestContent());
273 				
274 				wsiValidateAction.setEnabled( true );
275 			}
276 		}
277 	}
278 
279 	public class WsdlMockRequestMessageEditor extends RequestMessageXmlEditor<WsdlMockResponse>
280 	{
281 		public WsdlMockRequestMessageEditor(XmlDocument document)
282 		{
283 			super(document, mockResponse);
284 		}
285 
286 		protected XmlSourceEditorView buildSourceEditor()
287 		{
288 			XmlSourceEditorView editor = getSourceEditor();
289 			JXEditTextArea inputArea = editor.getInputArea();
290 
291 			inputArea.addFocusListener(new InputAreaFocusListener());
292 			
293 			inputArea.getInputHandler().addKeyBinding("AC+TAB", moveFocusAction);
294 			inputArea.getInputHandler().addKeyBinding("F5", recreateButton.getAction());
295 			inputArea.getInputHandler().addKeyBinding("C+F4", closePanelAction);
296 
297 			return editor;
298 		}
299 	}
300 
301 	public class WsdlMockResponseMessageEditor extends ResponseMessageXmlEditor<WsdlMockResponse>
302 	{
303 		public WsdlMockResponseMessageEditor(XmlDocument document)
304 		{
305 			super(document, mockResponse );
306 
307 			XmlSourceEditorView editor = getSourceEditor();
308 			
309 			if( !getModelItem().getMockOperation().isOneWay())
310 			{
311 				JXEditTextArea inputArea = editor.getInputArea();
312 				inputArea.addFocusListener(new ResultAreaFocusListener());
313 				
314 				inputArea.getInputHandler().addKeyBinding("AC+TAB", moveFocusAction);
315 				inputArea.getInputHandler().addKeyBinding("C+F4", closePanelAction);
316 				
317 				JPopupMenu inputPopup = editor.getEditorPopup();
318 				inputPopup.insert( new JSeparator(), 2 );
319 				inputPopup.insert( wsiValidateAction, 3 );
320 			}
321 		}
322 	}
323 	
324 	protected final class InputAreaFocusListener implements FocusListener
325 	{
326 		public void focusGained(FocusEvent e)
327 		{
328 			responseHasFocus = false;
329 			
330 			statusBar.setTarget( requestEditor.getSourceEditor().getInputArea() );
331 			if( !splitButton.isEnabled() )
332 			{
333 				requestTabs.setSelectedIndex( 0 );
334 				return;
335 			}
336 			
337 			if (getModelItem().getSettings().getBoolean(UISettings.NO_RESIZE_REQUEST_EDITOR))
338 				return;
339 
340 			// dont resize if split has been dragged
341 			if (((SoapUISplitPaneUI) requestSplitPane.getUI()).hasBeenDragged())
342 				return;
343 
344 			int pos = requestSplitPane.getDividerLocation();
345 			if (pos >= 600)
346 				return;
347 			if (requestSplitPane.getMaximumDividerLocation() > 700)
348 				requestSplitPane.setDividerLocation(600);
349 			else
350 				requestSplitPane.setDividerLocation(0.8);
351 		}
352 
353 		public void focusLost(FocusEvent e)
354 		{
355 		}
356 	}
357 
358 	protected final class ResultAreaFocusListener implements FocusListener
359 	{
360 		public void focusGained(FocusEvent e)
361 		{
362 			responseHasFocus = true;
363 			
364 			statusBar.setTarget( responseEditor.getSourceEditor().getInputArea() );
365 			if( !splitButton.isEnabled() )
366 			{
367 				requestTabs.setSelectedIndex( 1 );
368 				return;
369 			}
370 			
371 			if (getModelItem().getSettings().getBoolean(UISettings.NO_RESIZE_REQUEST_EDITOR))
372 				return;
373 
374 			// dont resize if split has been dragged or result is empty
375 			if (((SoapUISplitPaneUI) requestSplitPane.getUI()).hasBeenDragged() )
376 				return;
377 
378 			int pos = requestSplitPane.getDividerLocation();
379 			int maximumDividerLocation = requestSplitPane.getMaximumDividerLocation();
380 			if (pos + 600 < maximumDividerLocation)
381 				return;
382 
383 			if (maximumDividerLocation > 700)
384 				requestSplitPane.setDividerLocation(maximumDividerLocation - 600);
385 			else
386 				requestSplitPane.setDividerLocation(0.2);
387 		}
388 
389 		public void focusLost(FocusEvent e)
390 		{
391 		}
392 	}
393 
394 	private class ClosePanelAction extends AbstractAction
395 	{
396 		public void actionPerformed(ActionEvent e)
397 		{
398 			SoapUI.getDesktop().closeDesktopPanel(getModelItem());
399 		}
400 	}
401 
402 	private class MoveFocusAction extends AbstractAction
403 	{
404 		public void actionPerformed(ActionEvent e)
405 		{
406 			if (requestEditor.hasFocus())
407 			{
408 				responseEditor.requestFocus();
409 			}
410 			else
411 			{
412 				requestEditor.requestFocus();
413 			}
414 		}
415 	}
416 
417 	public boolean dependsOn(ModelItem modelItem)
418 	{
419 		return modelItem == getModelItem() || modelItem == mockResponse.getMockOperation()
420 				|| modelItem == mockResponse.getMockOperation().getMockService()
421 				|| modelItem == mockResponse.getMockOperation().getMockService().getProject();
422 	}
423 
424 	private final class ChangeToTabsAction extends AbstractAction
425 	{
426 		public ChangeToTabsAction()
427 		{
428 			putValue(Action.SMALL_ICON, UISupport.createImageIcon("/toggle_tabs.gif"));
429 			putValue(Action.SHORT_DESCRIPTION, "Toggles to tab-based layout");
430 		}
431 		
432 		public void actionPerformed(ActionEvent e)
433 		{
434 			if( splitButton.isEnabled() )
435 			{
436 				splitButton.setEnabled( false );
437 				removeContent( requestSplitPane );
438 				setContent( requestTabPanel );
439 				requestTabs.addTab( "Last Request", requestEditor );
440 				requestTabs.addTab( "Mock Response", responseEditor );
441 			}
442 			else
443 			{
444 				int selectedIndex = requestTabs.getSelectedIndex();
445 				
446 				splitButton.setEnabled( true );
447 				removeContent( requestTabPanel );
448 				setContent( requestSplitPane );
449 				requestSplitPane.setTopComponent(requestEditor);
450 		   	requestSplitPane.setBottomComponent(responseEditor);
451 		   	requestSplitPane.setDividerLocation(0.5);
452 		   	
453 		   	if( selectedIndex == 0 )
454 		   		requestEditor.requestFocus();
455 		   	else
456 		   		responseEditor.requestFocus();
457 			}
458 			
459 			revalidate();
460 		}
461 	}
462 
463 	public void setContent(JComponent content)
464 	{
465 		add( content, BorderLayout.CENTER );
466 	}
467 
468 	public void removeContent(JComponent content)
469 	{
470 		remove( content );
471 	}
472 	
473 	public boolean onClose( boolean canCancel )
474 	{
475 		mockResponse.removePropertyChangeListener( propertyChangeListener );
476 		
477 		requestEditor.release();
478 		responseEditor.release();
479 		
480 		responseEditor.getParent().remove( responseEditor );
481 		responseEditor = null;
482 		requestEditor.getParent().remove( requestEditor );
483 		requestEditor = null;
484 		
485 		return release();
486 	}
487 }