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