View Javadoc

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