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