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