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.Component;
    17  import java.awt.Dimension;
    18  import java.awt.event.ActionEvent;
    19  import java.awt.event.ItemEvent;
    20  import java.awt.event.ItemListener;
    21  import java.beans.PropertyChangeEvent;
    22  import java.beans.PropertyChangeListener;
    23  import java.util.ArrayList;
    24  import java.util.List;
    25
    26  import javax.swing.AbstractAction;
    27  import javax.swing.AbstractListModel;
    28  import javax.swing.Action;
    29  import javax.swing.BorderFactory;
    30  import javax.swing.JComboBox;
    31  import javax.swing.JComponent;
    32  import javax.swing.JLabel;
    33  import javax.swing.JList;
    34  import javax.swing.JPanel;
    35  import javax.swing.JScrollPane;
    36  import javax.swing.ListCellRenderer;
    37  import javax.swing.ListModel;
    38
    39  import org.apache.xmlbeans.XmlObject;
    40
    41  import com.eviware.soapui.SoapUI;
    42  import com.eviware.soapui.config.DispatchStyleConfig;
    43  import com.eviware.soapui.config.DispatchStyleConfig.Enum;
    44  import com.eviware.soapui.impl.wsdl.WsdlInterface;
    45  import com.eviware.soapui.impl.wsdl.WsdlOperation;
    46  import com.eviware.soapui.impl.wsdl.actions.mockoperation.NewMockResponseAction;
    47  import com.eviware.soapui.impl.wsdl.actions.mockoperation.OpenRequestForMockOperationAction;
    48  import com.eviware.soapui.impl.wsdl.actions.support.ShowOnlineHelpAction;
    49  import com.eviware.soapui.impl.wsdl.mock.WsdlMockOperation;
    50  import com.eviware.soapui.impl.wsdl.mock.WsdlMockRequest;
    51  import com.eviware.soapui.impl.wsdl.mock.WsdlMockResponse;
    52  import com.eviware.soapui.impl.wsdl.mock.WsdlMockResult;
    53  import com.eviware.soapui.impl.wsdl.panels.teststeps.support.GroovyEditor;
    54  import com.eviware.soapui.impl.wsdl.panels.teststeps.support.GroovyEditorModel;
    55  import com.eviware.soapui.impl.wsdl.support.HelpUrls;
    56  import com.eviware.soapui.model.ModelItem;
    57  import com.eviware.soapui.model.iface.Interface;
    58  import com.eviware.soapui.model.iface.Operation;
    59  import com.eviware.soapui.model.mock.MockOperation;
    60  import com.eviware.soapui.model.mock.MockResponse;
    61  import com.eviware.soapui.model.mock.MockServiceListener;
    62  import com.eviware.soapui.model.settings.Settings;
    63  import com.eviware.soapui.model.support.InterfaceListenerAdapter;
    64  import com.eviware.soapui.model.support.ProjectListenerAdapter;
    65  import com.eviware.soapui.model.util.ModelItemNames;
    66  import com.eviware.soapui.support.UISupport;
    67  import com.eviware.soapui.support.action.swing.ActionList;
    68  import com.eviware.soapui.support.action.swing.ActionSupport;
    69  import com.eviware.soapui.support.action.swing.SwingActionDelegate;
    70  import com.eviware.soapui.support.components.JComponentInspector;
    71  import com.eviware.soapui.support.components.JInspectorPanel;
    72  import com.eviware.soapui.support.components.JXToolBar;
    73  import com.eviware.soapui.support.swing.ExtendedComboBoxModel;
    74  import com.eviware.soapui.support.swing.ModelItemListMouseListener;
    75  import com.eviware.soapui.support.types.StringList;
    76  import com.eviware.soapui.support.xml.XmlUtils;
    77  import com.eviware.soapui.ui.support.ModelItemDesktopPanel;
    78  import com.jgoodies.forms.builder.ButtonBarBuilder;
    79
    80  /***
    81   * DesktopPanel for WsdlGroovyTestSteps
    82   *
    83   * @author Ole.Matzura
    84   */
    85
    86  public class WsdlMockOperationDesktopPanel extends ModelItemDesktopPanel<WsdlMockOperation>
    87  {
    88  	private JList responseList;
    89  	private JComboBox interfaceCombo;
    90  	private JComboBox operationCombo;
    91  	private JComboBox dispatchCombo;
    92  	private JPanel dispatchPanel;
    93  	private InternalInterfaceListener interfaceListener = new InternalInterfaceListener();
    94  	private InternalProjectListener projectListener = new InternalProjectListener();
    95  	private WsdlInterface currentInterface;
    96  	private JPanel groovyEditorPanel;
    97  	private JPanel xpathEditorPanel;
    98  	private JComboBox defaultResponseCombo;
    99  	private ResponseListModel responseListModel;
    100 	private GroovyEditor xpathEditor;
    101 	private GroovyEditor groovyEditor;
    102 	private JComponentInspector dispatchInspector;
    103
    104 	public WsdlMockOperationDesktopPanel(WsdlMockOperation mockOperation)
    105 	{
    106 		super( mockOperation );
    107
    108 		buildUI();
    109 		setPreferredSize( new Dimension( 600, 440 ));
    110
    111 		mockOperation.getMockService().getProject().addProjectListener( projectListener );
    112
    113 		WsdlOperation operation = getModelItem().getOperation();
    114 		if( operation != null )
    115 		{
    116 			currentInterface = operation.getInterface();
    117 			currentInterface.addInterfaceListener( interfaceListener );
    118 		}
    119 	}
    120
    121 	private void buildUI()
    122 	{
    123 		add( buildToolbar(), BorderLayout.NORTH );
    124
    125       JInspectorPanel inspectorPanel = new JInspectorPanel( buildResponseList() );
    126       inspectorPanel.setDefaultDividerLocation( 0.5F );
    127       dispatchInspector = new JComponentInspector(
    128 				      			buildDispatchEditor(), "Dispatch (" + getModelItem().getDispatchStyle().toString() + ")",
    129 				      			"Configures current dispatch style", true );
    130 		inspectorPanel.addInspector( dispatchInspector);
    131       inspectorPanel.activate( dispatchInspector );
    132
    133       add( inspectorPanel, BorderLayout.CENTER );
    134 	}
    135
    136 	private JComponent buildResponseList()
    137 	{
    138 		responseListModel = new ResponseListModel();
    139 		responseList = new JList( responseListModel );
    140 		responseList.addMouseListener( new ModelItemListMouseListener() {
    141
    142 			@Override
    143 			protected ActionList getActionsForRow( JList list, int row )
    144 			{
    145 				ActionList actions = super.getActionsForRow( list, row );
    146
    147 				actions.insertAction( SwingActionDelegate.createDelegate( NewMockResponseAction.SOAPUI_ACTION_ID, getModelItem(), null,
    148 							"/addToMockService.gif"	), 0 );
    149
    150 				actions.insertAction( SwingActionDelegate.createDelegate( OpenRequestForMockOperationAction.SOAPUI_ACTION_ID, getModelItem(), null,
    151 							"/open_request.gif"), 1 );
    152
    153 				if( actions.getActionCount() > 2 )
    154 					actions.insertAction( ActionSupport.SEPARATOR_ACTION, 2 );
    155
    156 				return actions;
    157 			}
    158 		} );
    159 		responseList.setCellRenderer( new ResponseListCellRenderer() );
    160
    161 		JScrollPane scrollPane = new JScrollPane( responseList );
    162 		UISupport.addTitledBorder( scrollPane, "MockResponses" );
    163 		return scrollPane;
    164 	}
    165
    166 	private JComponent buildDispatchEditor()
    167 	{
    168 		buildGroovyEditor();
    169 		buildXPathEditor();
    170
    171 		dispatchPanel = new JPanel( new BorderLayout() );
    172 		dispatchPanel.setOpaque( true );
    173 		ButtonBarBuilder builder = new ButtonBarBuilder();
    174 		builder.addFixed( new JLabel( "Dispatch: ") );
    175 		builder.addRelatedGap();
    176 		dispatchCombo = new JComboBox( new Object[] { "Sequence", "Random", "XPath", "Script"} );
    177
    178 		dispatchCombo.addItemListener( new ItemListener() {
    179
    180 			public void itemStateChanged( ItemEvent e )
    181 			{
    182 				if( dispatchPanel.getComponentCount() > 1 )
    183 					dispatchPanel.remove( 1 );
    184
    185 				String item = ( String ) dispatchCombo.getSelectedItem();
    186 				if( item.equalsIgnoreCase( "Script" ))
    187 				{
    188 					getModelItem().setDispatchStyle( DispatchStyleConfig.SCRIPT );
    189 					dispatchPanel.add( groovyEditorPanel );
    190 					groovyEditor.getEditArea().setText( getModelItem().getDispatchPath() );
    191 					defaultResponseCombo.setEnabled( true );
    192 				}
    193 				else if( item.equalsIgnoreCase( "XPath" ))
    194 				{
    195 					getModelItem().setDispatchStyle( DispatchStyleConfig.XPATH );
    196 					dispatchPanel.add( xpathEditorPanel );
    197 					xpathEditor.getEditArea().setText( getModelItem().getDispatchPath() );
    198 					defaultResponseCombo.setEnabled( true );
    199 				}
    200 				else if( item.equalsIgnoreCase( "Sequence" ))
    201 				{
    202 					getModelItem().setDispatchStyle( DispatchStyleConfig.SEQUENCE );
    203 					defaultResponseCombo.setEnabled( false );
    204 				}
    205 				else if( item.equalsIgnoreCase( "Random" ))
    206 				{
    207 					getModelItem().setDispatchStyle( DispatchStyleConfig.RANDOM );
    208 					defaultResponseCombo.setEnabled( false );
    209 				}
    210
    211 				dispatchPanel.revalidate();
    212 				dispatchPanel.repaint();
    213
    214 				Enum dispatchStyle = getModelItem().getDispatchStyle();
    215 				if( dispatchInspector != null && dispatchStyle != null )
    216 					dispatchInspector.setTitle( "Dispatch (" + dispatchStyle + ")" );
    217 			}} );
    218
    219 		builder.addFixed( dispatchCombo );
    220
    221 		builder.addUnrelatedGap();
    222 		builder.addFixed( new JLabel( "Default Response: ") );
    223 		builder.addRelatedGap();
    224
    225 		ModelItemNames<MockResponse> names = new ModelItemNames<MockResponse>(getModelItem().getMockResponses());
    226 		defaultResponseCombo = new JComboBox( new ExtendedComboBoxModel( names.getNames() ) );
    227 		defaultResponseCombo.setPreferredSize( new Dimension( 150, 20 ) );
    228 		defaultResponseCombo.addItemListener( new ItemListener() {
    229
    230 			public void itemStateChanged( ItemEvent e )
    231 			{
    232 				Object selectedItem = defaultResponseCombo.getSelectedItem();
    233 				getModelItem().setDefaultResponse( ( String ) selectedItem );
    234 			}} );
    235
    236 		builder.addFixed( defaultResponseCombo );
    237 		builder.setBorder( BorderFactory.createEmptyBorder( 2, 3, 3, 3 ) );
    238
    239 		dispatchPanel.add( builder.getPanel(), BorderLayout.NORTH );
    240
    241 		// init data
    242 		defaultResponseCombo.setSelectedItem( getModelItem().getDefaultResponse() );
    243 		DispatchStyleConfig.Enum dispatchStyle = getModelItem().getDispatchStyle();
    244 		if( dispatchStyle.equals( DispatchStyleConfig.SEQUENCE ))
    245 		{
    246 			dispatchCombo.setSelectedItem( "Sequence" );
    247 			defaultResponseCombo.setEnabled( false );
    248 		}
    249 		else if( dispatchStyle.equals( DispatchStyleConfig.RANDOM ))
    250 		{
    251 			dispatchCombo.setSelectedItem( "Random" );
    252 			defaultResponseCombo.setEnabled( false );
    253 		}
    254 		else if( dispatchStyle.equals( DispatchStyleConfig.SCRIPT ))
    255 		{
    256 			dispatchCombo.setSelectedItem( "Script" );
    257 		}
    258 		else if( dispatchStyle.equals( DispatchStyleConfig.XPATH ))
    259 		{
    260 			dispatchCombo.setSelectedItem( "XPath" );
    261 		}
    262
    263 		return dispatchPanel;
    264 	}
    265
    266 	private void buildXPathEditor()
    267 	{
    268 		xpathEditorPanel = new JPanel( new BorderLayout() );
    269 		DispatchXPathGroovyEditorModel editorModel = new DispatchXPathGroovyEditorModel();
    270 		xpathEditor = new GroovyEditor( editorModel );
    271 		xpathEditorPanel.add( new JScrollPane( xpathEditor), BorderLayout.CENTER );
    272 		xpathEditorPanel.add( buildXPathEditorToolbar( editorModel ), BorderLayout.PAGE_START );
    273 	}
    274
    275 	public GroovyEditor getXPathEditor()
    276 	{
    277 		return xpathEditor;
    278 	}
    279
    280 	protected JXToolBar buildXPathEditorToolbar( DispatchXPathGroovyEditorModel editorModel )
    281 	{
    282 		JXToolBar toolbar = UISupport.createToolbar();
    283 		toolbar.addSpace( 3 );
    284 		toolbar.addFixed( UISupport.createToolbarButton( editorModel.getRunAction() ));
    285 		toolbar.addGlue();
    286 		toolbar.addFixed( createActionButton( new ShowOnlineHelpAction(HelpUrls.MOCKOPERATION_XPATHDISPATCH_HELP_URL), true ) );
    287 		return toolbar;
    288 	}
    289
    290 	private void buildGroovyEditor()
    291 	{
    292 		groovyEditorPanel = new JPanel( new BorderLayout() );
    293 		DispatchScriptGroovyEditorModel editorModel = new DispatchScriptGroovyEditorModel();
    294 		groovyEditor = new GroovyEditor( editorModel );
    295 		groovyEditorPanel.add( new JScrollPane( groovyEditor ), BorderLayout.CENTER );
    296 		groovyEditorPanel.add( buildGroovyEditorToolbar( editorModel ), BorderLayout.PAGE_START );
    297 	}
    298
    299 	protected JXToolBar buildGroovyEditorToolbar( DispatchScriptGroovyEditorModel editorModel )
    300 	{
    301 		JXToolBar toolbar = UISupport.createToolbar();
    302 		toolbar.addSpace( 3 );
    303 		toolbar.addFixed( UISupport.createToolbarButton( editorModel.getRunAction() ));
    304 		toolbar.addGlue();
    305
    306 		JLabel label = new JLabel("<html>Script is invoked with <code>log</code>, <code>context</code>, " +
    307 				"<code>requestContext</code>, <code>mockRequest</code> and <code>mockOperation</code> variables</html>");
    308 		label.setToolTipText( label.getText() );
    309 		label.setMaximumSize( label.getPreferredSize() );
    310
    311 		toolbar.add( label);
    312 		toolbar.addFixed( createActionButton( new ShowOnlineHelpAction(HelpUrls.MOCKOPERATION_SCRIPTDISPATCH_HELP_URL), true ) );
    313 		return toolbar;
    314 	}
    315
    316 	private Component buildToolbar()
    317 	{
    318 		JXToolBar toolbar = UISupport.createToolbar();
    319 		toolbar.addSpace( 3 );
    320
    321 		toolbar.addFixed( UISupport.createToolbarButton(
    322 					SwingActionDelegate.createDelegate( NewMockResponseAction.SOAPUI_ACTION_ID, getModelItem(), null,
    323 							"/addToMockService.gif"	)));
    324 		toolbar.addFixed( UISupport.createToolbarButton(
    325 					SwingActionDelegate.createDelegate( OpenRequestForMockOperationAction.SOAPUI_ACTION_ID, getModelItem(), null,
    326 								"/open_request.gif") ));
    327 		toolbar.addUnrelatedGap();
    328
    329 		ModelItemNames<Interface> names = new ModelItemNames<Interface>(getModelItem().getMockService().getProject().getInterfaces());
    330 		interfaceCombo = new JComboBox( names.getNames() );
    331 		interfaceCombo.setSelectedIndex( -1 );
    332 		interfaceCombo.addItemListener( new InterfaceComboListener() );
    333
    334 		toolbar.addLabeledFixed( "Interface", interfaceCombo );
    335 		toolbar.addUnrelatedGap();
    336 		operationCombo = new JComboBox( new ExtendedComboBoxModel() );
    337 		operationCombo.setPreferredSize( new Dimension( 150, 20 ) );
    338 		operationCombo.addItemListener( new OperationComboListener() );
    339
    340 		toolbar.addLabeledFixed( "Operation", operationCombo );
    341
    342 		WsdlOperation operation = getModelItem().getOperation();
    343 		interfaceCombo.setSelectedItem( operation == null ? null : operation.getInterface().getName() );
    344 		operationCombo.setSelectedItem( operation == null ? null : operation.getName() );
    345
    346 		toolbar.addGlue();
    347 		toolbar.addFixed( createActionButton( new ShowOnlineHelpAction(HelpUrls.MOCKOPERATION_HELP_URL), true ) );
    348
    349 		return toolbar;
    350 	}
    351
    352 	public boolean onClose( boolean canCancel )
    353 	{
    354 		if( currentInterface != null )
    355 			currentInterface.removeInterfaceListener( interfaceListener );
    356
    357 		getModelItem().getMockService().getProject().removeProjectListener( projectListener );
    358 		responseListModel.release();
    359
    360 		groovyEditor.release();
    361 		xpathEditor.release();
    362
    363 		return release();
    364 	}
    365
    366 	public boolean dependsOn(ModelItem modelItem)
    367 	{
    368 		return modelItem == getModelItem() || modelItem == getModelItem().getMockService()
    369 				|| modelItem == getModelItem().getMockService().getProject();
    370 	}
    371
    372 	private final class OperationComboListener implements ItemListener
    373 	{
    374 		public void itemStateChanged( ItemEvent e )
    375 		{
    376 			WsdlInterface iface = getModelItem().getMockService().getProject().getInterfaceByName( interfaceCombo.getSelectedItem().toString() );
    377 			WsdlOperation operation = iface.getOperationByName( operationCombo.getSelectedItem().toString() );
    378 			getModelItem().setOperation( operation );
    379 		}
    380 	}
    381
    382 	private final class InterfaceComboListener implements ItemListener
    383 	{
    384 		public void itemStateChanged( ItemEvent e )
    385 		{
    386 			if( currentInterface != null )
    387 			{
    388 				currentInterface.removeInterfaceListener( interfaceListener );
    389 			}
    390
    391 			Object selectedItem = interfaceCombo.getSelectedItem();
    392 			if( selectedItem == null )
    393 			{
    394 				operationCombo.setModel( new ExtendedComboBoxModel() );
    395 				currentInterface = null;
    396 			}
    397 			else
    398 			{
    399 				currentInterface = getModelItem().getMockService().getProject().getInterfaceByName( selectedItem.toString() );
    400 				ModelItemNames<Operation> names = new ModelItemNames<Operation>( currentInterface.getOperations() );
    401 				operationCombo.setModel( new ExtendedComboBoxModel( names.getNames()) );
    402
    403 				currentInterface.addInterfaceListener( interfaceListener );
    404 			}
    405 		}
    406 	}
    407
    408 	private final class InternalProjectListener extends ProjectListenerAdapter
    409 	{
    410 		@Override
    411 		public void interfaceAdded( Interface iface )
    412 		{
    413 			interfaceCombo.addItem( iface.getName() );
    414 		}
    415
    416 		@Override
    417 		public void interfaceRemoved( Interface iface )
    418 		{
    419 			if( interfaceCombo.getSelectedItem().equals( iface.getName() ))
    420 			{
    421 				getModelItem().setOperation( null );
    422 			}
    423 		}
    424 	}
    425
    426 	private final class InternalInterfaceListener extends InterfaceListenerAdapter
    427 	{
    428 		@Override
    429 		public void operationAdded( Operation operation )
    430 		{
    431 			operationCombo.addItem( operation.getName() );
    432 		}
    433
    434 		@Override
    435 		public void operationRemoved( Operation operation )
    436 		{
    437 			Object selectedItem = operationCombo.getSelectedItem();
    438 			operationCombo.removeItem( operation.getName() );
    439
    440 			if( selectedItem.equals( operation.getName() ))
    441 			{
    442 				getModelItem().setOperation( null );
    443 				interfaceCombo.setSelectedIndex( -1 );
    444 			}
    445 		}
    446
    447 		@Override
    448 		public void operationUpdated( Operation operation )
    449 		{
    450 			ExtendedComboBoxModel model = ((ExtendedComboBoxModel)operationCombo.getModel());
    451 			int ix = model.getIndexOf( operation.getName() );
    452 			if( ix != -1 )
    453 			{
    454 				model.setElementAt( operation.getName(), ix );
    455 			}
    456 		}
    457 	}
    458
    459 	public class DispatchScriptGroovyEditorModel implements GroovyEditorModel
    460 	{
    461 		private RunScriptAction runScriptAction = new RunScriptAction();
    462
    463 		public String[] getKeywords()
    464 		{
    465 			return new String[] { "mockRequest", "context", "requestContext", "log", "mockOperation" };
    466 		}
    467
    468 		public Action getRunAction()
    469 		{
    470 			return runScriptAction;
    471 		}
    472
    473 		public String getScript()
    474 		{
    475 			return getModelItem().getDispatchPath();
    476 		}
    477
    478 		public Settings getSettings()
    479 		{
    480 			return getModelItem().getSettings();
    481 		}
    482
    483 		public void setScript( String text )
    484 		{
    485 			getModelItem().setDispatchPath( text );
    486 		}
    487 	}
    488
    489 	public class DispatchXPathGroovyEditorModel implements GroovyEditorModel
    490 	{
    491 		private RunXPathAction runXPathAction = new RunXPathAction();
    492
    493 		public String[] getKeywords()
    494 		{
    495 			return new String[] { "define", "namespace"};
    496 		}
    497
    498 		public Action getRunAction()
    499 		{
    500 			return runXPathAction;
    501 		}
    502
    503 		public String getScript()
    504 		{
    505 			return getModelItem().getDispatchPath();
    506 		}
    507
    508 		public Settings getSettings()
    509 		{
    510 			return getModelItem().getSettings();
    511 		}
    512
    513 		public void setScript( String text )
    514 		{
    515 			getModelItem().setDispatchPath( text );
    516 		}
    517 	}
    518
    519 	public class ResponseListModel extends AbstractListModel implements ListModel, MockServiceListener, PropertyChangeListener
    520 	{
    521 		private List<WsdlMockResponse> responses = new ArrayList<WsdlMockResponse>();
    522
    523 		public ResponseListModel()
    524 		{
    525 			for( int c = 0; c < getModelItem().getMockResponseCount(); c++ )
    526 			{
    527 				WsdlMockResponse mockResponse = ( WsdlMockResponse ) getModelItem().getMockResponseAt( c );
    528 				mockResponse.addPropertyChangeListener( this );
    529
    530 				responses.add( mockResponse);
    531 			}
    532
    533 			getModelItem().getMockService().addMockServiceListener( this );
    534 		}
    535
    536 		public Object getElementAt( int arg0 )
    537 		{
    538 			return responses.get( arg0 );
    539 		}
    540
    541 		public int getSize()
    542 		{
    543 			return responses.size();
    544 		}
    545
    546 		public void mockOperationAdded( MockOperation operation )
    547 		{
    548
    549 		}
    550
    551 		public void mockOperationRemoved( MockOperation operation )
    552 		{
    553
    554 		}
    555
    556 		public void mockResponseAdded( MockResponse response )
    557 		{
    558 			if( response.getMockOperation() != getModelItem() )
    559 				return;
    560
    561 			responses.add( ( WsdlMockResponse ) response );
    562 			response.addPropertyChangeListener( this );
    563 			fireIntervalAdded( this, responses.size()-1, responses.size()-1 );
    564
    565 			defaultResponseCombo.addItem( response.getName() );
    566 		}
    567
    568 		public void mockResponseRemoved( MockResponse response )
    569 		{
    570 			if( response.getMockOperation() != getModelItem() )
    571 				return;
    572
    573 			int ix = responses.indexOf( response );
    574 			responses.remove( ix );
    575 			response.removePropertyChangeListener( this );
    576 			fireIntervalRemoved( this, ix, ix );
    577
    578 			defaultResponseCombo.removeItem( response.getName() );
    579 		}
    580
    581 		public void propertyChange( PropertyChangeEvent arg0 )
    582 		{
    583 			if( arg0.getPropertyName().equals( WsdlMockOperation.NAME_PROPERTY ))
    584 			{
    585 				int ix = responses.indexOf( arg0.getSource() );
    586 				fireContentsChanged( this, ix, ix );
    587
    588 				ExtendedComboBoxModel model = ( ExtendedComboBoxModel ) defaultResponseCombo.getModel();
    589 				model.setElementAt( arg0.getNewValue(), ix );
    590
    591 				if( model.getSelectedItem().equals( arg0.getOldValue()  ))
    592 						model.setSelectedItem( arg0.getNewValue() );
    593 			}
    594 		}
    595
    596 		public void release()
    597 		{
    598 			for( WsdlMockResponse operation : responses )
    599 			{
    600 				operation.removePropertyChangeListener( this );
    601 			}
    602
    603 			getModelItem().getMockService().removeMockServiceListener( this );
    604 		}
    605 	}
    606
    607 	private final static class ResponseListCellRenderer extends JLabel implements ListCellRenderer
    608 	{
    609 		public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected,
    610 				boolean cellHasFocus)
    611 		{
    612 			MockResponse testStep = (MockResponse) value;
    613 			setText(testStep.getName());
    614 			setIcon(testStep.getIcon());
    615
    616 			if (isSelected)
    617 			{
    618 				setBackground(list.getSelectionBackground());
    619 				setForeground(list.getSelectionForeground());
    620 			}
    621 			else
    622 			{
    623 				setBackground(list.getBackground());
    624 				setForeground(list.getForeground());
    625 			}
    626
    627 			setEnabled(list.isEnabled());
    628 			setFont(list.getFont());
    629 			setOpaque(true);
    630 			setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3));
    631
    632 			return this;
    633 		}
    634 	}
    635
    636 	private class RunScriptAction extends AbstractAction
    637 	{
    638 		public RunScriptAction()
    639 		{
    640 			putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/run_groovy_script.gif" ));
    641 			putValue( Action.SHORT_DESCRIPTION, "Runs this script using a mockRequest and context" );
    642 		}
    643
    644 		public void actionPerformed( ActionEvent e )
    645 		{
    646 			WsdlMockResult lastMockResult = getModelItem().getLastMockResult();
    647 			WsdlMockRequest mockRequest = lastMockResult == null ? null : lastMockResult.getMockRequest();
    648
    649 			try
    650 			{
    651 				Object retVal = getModelItem().evaluateDispatchScript( mockRequest );
    652 				UISupport.showInfoMessage( "Script returned [" + retVal + "]" );
    653 			}
    654 			catch( Exception e1 )
    655 			{
    656 				UISupport.showErrorMessage( e1 );
    657 			}
    658 		}}
    659
    660 	private class RunXPathAction extends AbstractAction
    661 	{
    662 		public RunXPathAction()
    663 		{
    664 			putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/run_groovy_script.gif" ));
    665 			putValue( Action.SHORT_DESCRIPTION, "Evaluates this xpath expression against the latest request" );
    666 		}
    667
    668 		public void actionPerformed( ActionEvent e )
    669 		{
    670 			WsdlMockResult lastMockResult = getModelItem().getLastMockResult();
    671 			if( lastMockResult == null )
    672 			{
    673 				UISupport.showErrorMessage( "Missing last request to select from" );
    674 				return;
    675 			}
    676
    677 			try
    678 			{
    679 				XmlObject[] retVal = getModelItem().evaluateDispatchXPath( lastMockResult.getMockRequest() );
    680 				StringList list = new StringList();
    681 				for( XmlObject xmlObject : retVal )
    682 				{
    683 					list.add( XmlUtils.getNodeValue( xmlObject.getDomNode() ) );
    684 				}
    685
    686 				UISupport.showInfoMessage( "XPath returned " + list.toString() );
    687 			}
    688 			catch( Exception e1 )
    689 			{
    690 				SoapUI.logError( e1 );
    691 			}
    692 		}}
    693 }