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 }