View Javadoc

1   /*
2    *  soapUI, copyright (C) 2006 eviware.com 
3    *
4    *  soapUI is free software; you can redistribute it and/or modify it under the 
5    *  terms of the GNU Lesser General Public License as published by the Free Software Foundation; 
6    *  either version 2.1 of the License, or (at your option) any later version.
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.teststeps;
14  
15  import java.awt.BorderLayout;
16  import java.awt.Color;
17  import java.awt.Dimension;
18  import java.awt.event.ActionEvent;
19  
20  import javax.swing.AbstractAction;
21  import javax.swing.Action;
22  import javax.swing.BorderFactory;
23  import javax.swing.DefaultListModel;
24  import javax.swing.Icon;
25  import javax.swing.JButton;
26  import javax.swing.JComboBox;
27  import javax.swing.JComponent;
28  import javax.swing.JLabel;
29  import javax.swing.JList;
30  import javax.swing.JPanel;
31  import javax.swing.JScrollPane;
32  import javax.swing.JSplitPane;
33  import javax.swing.JTextArea;
34  import javax.swing.ListSelectionModel;
35  import javax.swing.event.ListSelectionEvent;
36  import javax.swing.event.ListSelectionListener;
37  import javax.swing.text.Document;
38  
39  import com.eviware.soapui.SoapUI;
40  import com.eviware.soapui.impl.wsdl.actions.support.ShowOnlineHelpAction;
41  import com.eviware.soapui.impl.wsdl.panels.support.TestRunComponentEnabler;
42  import com.eviware.soapui.impl.wsdl.panels.teststeps.support.GotoTestStepsComboBoxModel;
43  import com.eviware.soapui.impl.wsdl.submit.transports.http.WsdlResponse;
44  import com.eviware.soapui.impl.wsdl.support.HelpUrls;
45  import com.eviware.soapui.impl.wsdl.teststeps.WsdlGotoTestStep;
46  import com.eviware.soapui.impl.wsdl.teststeps.WsdlTestRequestStep;
47  import com.eviware.soapui.impl.wsdl.teststeps.WsdlGotoTestStep.GotoCondition;
48  import com.eviware.soapui.model.ModelItem;
49  import com.eviware.soapui.support.DocumentListenerAdapter;
50  import com.eviware.soapui.support.UISupport;
51  import com.eviware.soapui.support.components.JUndoableTextArea;
52  import com.eviware.soapui.support.xml.XmlUtils;
53  import com.eviware.soapui.ui.desktop.DesktopPanel;
54  import com.jgoodies.forms.builder.ButtonBarBuilder;
55  
56  /***
57   * DesktopPanel for WsdlGotoTestSteps
58   * 
59   * @author Ole.Matzura
60   */
61  
62  public class GotoStepDesktopPanel extends JPanel implements DesktopPanel
63  {
64  	private final WsdlGotoTestStep gotoStep;
65  	private DefaultListModel listModel;
66  	private JList conditionList;
67  	private JTextArea expressionArea;
68  	private JButton copyButton;
69  	private JButton deleteButton;
70  	private JButton declareButton;
71  	private GotoTestStepsComboBoxModel testStepsModel;
72  	private JComboBox testStepsCombo;
73  	private JButton testConditionButton;
74  	private TestRunComponentEnabler componentEnabler;
75  	private GotoCondition currentCondition;
76  	
77  	public GotoStepDesktopPanel(WsdlGotoTestStep testStep)
78  	{
79  		super( new BorderLayout() );
80  		this.gotoStep = testStep;
81  		componentEnabler = new TestRunComponentEnabler( testStep.getTestCase() );
82  		
83  		buildUI();
84  	}
85  	
86  	public TestRunComponentEnabler getComponentEnabler()
87  	{
88  		return componentEnabler;
89  	}
90  
91  	public JList getConditionList()
92  	{
93  		return conditionList;
94  	}
95  
96  	public JButton getCopyButton()
97  	{
98  		return copyButton;
99  	}
100 
101 	public JButton getDeclareButton()
102 	{
103 		return declareButton;
104 	}
105 
106 	public JButton getDeleteButton()
107 	{
108 		return deleteButton;
109 	}
110 
111 	public JTextArea getExpressionArea()
112 	{
113 		return expressionArea;
114 	}
115 
116 	public WsdlGotoTestStep getGotoStep()
117 	{
118 		return gotoStep;
119 	}
120 
121 	public DefaultListModel getListModel()
122 	{
123 		return listModel;
124 	}
125 
126 	public JButton getTestConditionButton()
127 	{
128 		return testConditionButton;
129 	}
130 
131 	public JComboBox getTestStepsCombo()
132 	{
133 		return testStepsCombo;
134 	}
135 
136 	public GotoTestStepsComboBoxModel getTestStepsModel()
137 	{
138 		return testStepsModel;
139 	}
140 
141 	private void buildUI()
142 	{
143 		JSplitPane splitPane = UISupport.createHorizontalSplit();
144 		
145 		listModel = new DefaultListModel();
146 		
147 		for( int c = 0; c < gotoStep.getConditionCount(); c++ )
148 		{
149 			listModel.addElement( gotoStep.getConditionAt( c  ).getName() );
150 		}
151 		
152 		conditionList = new JList( listModel );
153 		conditionList.setSelectionMode( ListSelectionModel.SINGLE_SELECTION );
154 		conditionList.addListSelectionListener( new ConditionListSelectionListener());
155 		
156 		JScrollPane listScrollPane = new JScrollPane( conditionList );
157 		listScrollPane.setBorder( 
158 				BorderFactory.createCompoundBorder(
159 				BorderFactory.createTitledBorder( BorderFactory.createEmptyBorder(), "Conditions" ), 
160 				BorderFactory.createLineBorder( Color.GRAY )));
161 		
162 		splitPane.setLeftComponent( listScrollPane);
163 		
164 		expressionArea = new JUndoableTextArea();
165 		expressionArea.setEnabled( false );
166 		expressionArea.getDocument().addDocumentListener( new SourceAreaDocumentListener());
167 		
168 		JPanel expressionPanel = new JPanel( new BorderLayout() );
169 		expressionPanel.add( new JScrollPane( expressionArea ), BorderLayout.CENTER );
170 		ButtonBarBuilder builder = new ButtonBarBuilder();
171 		builder.addFixed( new JLabel( "<html><b>Condition XPath Expression</b></html>"));
172 		builder.addGlue();
173 		builder.setBorder( BorderFactory.createEmptyBorder( 3, 3, 3, 3 ));
174 		expressionPanel.add( builder.getPanel(), BorderLayout.NORTH );
175 		expressionPanel.setBorder( BorderFactory.createEmptyBorder( 3, 3, 3, 3 ));
176 		
177 		builder = buildToolbar();
178 		expressionPanel.add( builder.getPanel(), BorderLayout.SOUTH );
179 		
180 		splitPane.setRightComponent( expressionPanel );
181 		splitPane.setResizeWeight( 0.1 );
182 		splitPane.setDividerLocation( 120 );
183 		
184 		add( splitPane, BorderLayout.CENTER );
185 		
186 		builder = new ButtonBarBuilder();
187 		JButton addButton = new JButton( new AddAction() );
188 		builder.addFixed( addButton );
189 		builder.addRelatedGap();
190 		copyButton = new JButton( new CopyAction() );
191 		copyButton.setEnabled( false );
192 		builder.addFixed( copyButton);
193 		builder.addRelatedGap();
194 		deleteButton = new JButton( new DeleteAction() );
195 		deleteButton.setEnabled( false );
196 		builder.addFixed( deleteButton);
197 		builder.addRelatedGap();
198 		declareButton = new JButton( new DeclareNamespacesAction() );
199 		declareButton.setEnabled( false );
200 		builder.addFixed( declareButton);
201 		builder.addRelatedGap();
202 		JButton runButton = new JButton( new RunAction() );
203 		builder.addFixed( runButton);
204 		
205 		builder.addGlue();
206 		builder.addFixed( new JButton( new CloseAction() ));
207 		builder.addRelatedGap();
208 		builder.addFixed( UISupport.createToolbarButton( new ShowOnlineHelpAction( HelpUrls.GOTOSTEPEDITOR_HELP_URL )));
209 		builder.setBorder( BorderFactory.createEmptyBorder( 3, 3, 3, 3 ) );
210 		
211 		add( builder.getPanel(), BorderLayout.SOUTH );
212 		
213 		setBorder( BorderFactory.createEmptyBorder( 3, 3, 3, 3 ));
214 		setPreferredSize( new Dimension( 550, 300 ));
215 		
216 		if( listModel.getSize() > 0 ) 
217 			conditionList.setSelectedIndex( 0 );
218 		
219 		componentEnabler.add( conditionList );
220 		componentEnabler.add( expressionArea );
221 		componentEnabler.add( testStepsCombo );
222 		componentEnabler.add( testConditionButton );
223 		componentEnabler.add( copyButton );
224 		componentEnabler.add( declareButton );
225 		componentEnabler.add( deleteButton );
226 		componentEnabler.add( addButton );
227 		componentEnabler.add( runButton );
228 	}
229 
230 	protected ButtonBarBuilder buildToolbar()
231 	{
232 		ButtonBarBuilder builder;
233 		builder = new ButtonBarBuilder();
234 		testStepsModel = new GotoTestStepsComboBoxModel( gotoStep.getTestCase(), null );
235 		testStepsCombo = new JComboBox( testStepsModel );
236 		testStepsCombo.setToolTipText( "The step the test case will go to if the current condition is true" );
237 		testStepsCombo.setEnabled( false );
238 		builder.addFixed( new JLabel( "<html><b>Target step:</b></html>"));
239 		builder.addRelatedGap();
240 		builder.addFixed( testStepsCombo );
241 		builder.addGlue();
242 		testConditionButton = new JButton( new TestConditionAction() );
243 		testConditionButton.setEnabled( false );
244 		builder.addFixed( testConditionButton);
245 		builder.setBorder( BorderFactory.createEmptyBorder( 3, 3, 3, 3 ));
246 		return builder;
247 	}
248 	
249 	private final class SourceAreaDocumentListener extends DocumentListenerAdapter
250 	{
251 		@Override
252 		public void update( Document document )
253 		{
254 			int ix = conditionList.getSelectedIndex();
255 			if( ix != -1 )
256 			{
257 				gotoStep.getConditionAt( ix ).setExpression( expressionArea.getText() );
258 			}
259 		}
260 	}
261 	
262 	private final class ConditionListSelectionListener implements ListSelectionListener
263 	{
264 		public void valueChanged(ListSelectionEvent e)
265 		{
266 			int ix = conditionList.getSelectedIndex();
267 			if( ix == -1 )
268 			{
269 				expressionArea.setText( "" );
270 				testStepsModel.setCondition( null );
271 				currentCondition = null;
272 			}
273 			else
274 			{
275 				currentCondition = gotoStep.getConditionAt( ix );
276 				expressionArea.setText( currentCondition.getExpression() );
277 				testStepsModel.setCondition( currentCondition );
278 			}
279 
280 			boolean b = ix != -1;
281 			enableEditComponents( b );
282 		}
283 	}
284 
285 	private final class AddAction extends AbstractAction
286 	{
287 		public AddAction()
288 		{
289 			super( "Add" );
290 		}
291 		
292 		public void actionPerformed(ActionEvent e)
293 		{
294 			String name = UISupport.prompt( "Specify name for condition", "Add Condition", "Condition " + 
295 					(gotoStep.getConditionCount()+1) );
296 			if( name == null || name.trim().length() == 0 ) return;
297 			
298 			gotoStep.addCondition( name );
299 			
300 			listModel.addElement( name );
301 			conditionList.setSelectedIndex( listModel.getSize()-1 );
302 		}
303 	}
304 	
305 	private final class CopyAction extends AbstractAction
306 	{
307 		public CopyAction()
308 		{
309 			super( "Copy" );
310 		}
311 		
312 		public void actionPerformed(ActionEvent e)
313 		{
314 			int ix = conditionList.getSelectedIndex();
315 			GotoCondition config = gotoStep.getConditionAt( ix );
316 			
317 			String name = UISupport.prompt( "Specify name for condition", "Copy Condition", config.getName() );
318 			if( name == null || name.trim().length() == 0 ) return;
319 			
320 			GotoCondition condition = gotoStep.addCondition( name );
321 			condition.setExpression( config.getExpression() );
322 			condition.setTargetStep( config.getTargetStep() );
323 			condition.setType( config.getType() );
324 			
325 			listModel.addElement( name );
326 			conditionList.setSelectedIndex( listModel.getSize()-1 );
327 		}
328 	}
329 	
330 	private final class DeleteAction extends AbstractAction
331 	{
332 		public DeleteAction()
333 		{
334 			super( "Delete" );
335 		}
336 		
337 		public void actionPerformed(ActionEvent e)
338 		{
339 			if( UISupport.confirm( "Delete selected condition", "Delete Condition" )) 
340 			{
341 				int ix = conditionList.getSelectedIndex();
342 				
343 				conditionList.setSelectedIndex( -1 );
344 				
345 				gotoStep.removeConditionAt( ix );
346 				listModel.remove( ix );
347 				
348 				if( listModel.getSize() > 0 )
349 				{
350 					conditionList.setSelectedIndex( ix > listModel.getSize()-1 ? listModel.getSize()-1 : ix );
351 				}
352 			}
353 		}
354 	}
355 	
356 	private final class DeclareNamespacesAction extends AbstractAction
357 	{
358 		public DeclareNamespacesAction()
359 		{
360 			super( "Declare" );
361 			putValue( Action.SHORT_DESCRIPTION, "Declare available response namespaces in condition expression" );
362 		}
363 		
364 		public void actionPerformed(ActionEvent e)
365 		{
366 			try
367 			{
368 				WsdlTestRequestStep previousStep = (WsdlTestRequestStep) gotoStep.getTestCase().findPreviousStepOfType( 
369 						gotoStep, WsdlTestRequestStep.class );
370 				
371 				if (previousStep  != null )
372 				{
373 					WsdlResponse response = previousStep.getTestRequest().getResponse();
374 					String xml = response == null ? null : response.getContentAsString();
375 					if ( xml != null && xml.trim().length() > 0)
376 					{
377 						expressionArea.setText(XmlUtils.declareXPathNamespaces(xml)
378 								+ expressionArea.getText());
379 					}
380 					else
381 					{
382 						UISupport.showErrorMessage( "Missing response in previous request step [" + previousStep.getName() + "]" );
383 					}
384 				}
385 				else
386 				{
387 					UISupport.showErrorMessage( "Missing previous request step" );
388 				}
389 			}
390 			catch (Exception e1)
391 			{
392 				e1.printStackTrace();
393 			}
394 		}
395 	}
396 	
397 	private final class RunAction extends AbstractAction
398 	{
399 		public RunAction()
400 		{
401 			super( "Run" );
402 		}
403 		
404 		public void actionPerformed(ActionEvent e)
405 		{
406 			if( listModel.getSize() == 0 )
407 			{
408 				UISupport.showErrorMessage( "Missing conditions!" );
409 				return;
410 			}
411 
412 			WsdlTestRequestStep previousStep = (WsdlTestRequestStep) gotoStep.getTestCase().findPreviousStepOfType( 
413 					gotoStep, WsdlTestRequestStep.class );
414 			
415 			if( previousStep == null ) 
416 			{
417 				UISupport.showErrorMessage( "Missing previous request step" );
418 			}
419 			else
420 			{
421 				if( previousStep.getTestRequest().getResponse().getContentAsString() == null )
422 				{
423 					UISupport.showErrorMessage( "Missing response in previous message" );
424 					return;
425 				}
426 				
427 				GotoCondition target = gotoStep.runConditions( previousStep );
428 				if( target == null )
429 				{
430 					UISupport.showInfoMessage( "No condition true for current response in [" + previousStep.getName() + "]" );
431 				}
432 				else
433 				{
434 					UISupport.showInfoMessage( "Condition triggered for go to [" + target.getTargetStep() + "]" );
435 				}
436 			}
437 		}
438 	}
439 	
440 	private final class TestConditionAction extends AbstractAction
441 	{
442 		public TestConditionAction()
443 		{
444 			super( "Test Condition" );
445 		}
446 		
447 		public void actionPerformed(ActionEvent e)
448 		{
449 			WsdlTestRequestStep previousStep = (WsdlTestRequestStep) gotoStep.getTestCase().findPreviousStepOfType( 
450 					gotoStep, WsdlTestRequestStep.class );
451 			
452 			if( previousStep == null ) 
453 			{
454 				UISupport.showErrorMessage( "Missing previous request step" );
455 			}
456 			else
457 			{
458 				if( previousStep.getTestRequest().getResponse() == null || 
459 					 previousStep.getTestRequest().getResponse().getContentAsString().trim().length() == 0 )
460 				{
461 					UISupport.showErrorMessage( "Missing response in previous request step [" + 
462 							previousStep.getName() + "]" );
463 					return;
464 				}
465 				
466 				try
467 				{
468 					GotoCondition condition = gotoStep.getConditionAt( conditionList.getSelectedIndex() );
469 					boolean evaluate = condition.evaluate( previousStep );
470 					if( !evaluate )
471 					{
472 						UISupport.showInfoMessage( "Condition not true for current response in [" + previousStep.getName() + "]" );
473 					}
474 					else
475 					{
476 						UISupport.showInfoMessage( "Condition true for current response in [" + previousStep.getName() + "]" );
477 					}
478 				}
479 				catch (Exception e1)
480 				{
481 					UISupport.showErrorMessage( "Error checking condition: " + e1.getMessage() );
482 				}
483 			}
484 		}
485 	}
486 	
487 	private final class CloseAction extends AbstractAction
488 	{
489 		public CloseAction()
490 		{
491 			super( "Close" );
492 		}
493 		
494 		public void actionPerformed(ActionEvent e)
495 		{
496 			SoapUI.getDesktop().closeDesktopPanel( gotoStep );
497 		}
498 	}
499 
500 	public WsdlGotoTestStep getModelItem()
501 	{
502 		return gotoStep;
503 	}
504 
505 	public boolean onClose( boolean canCancel )
506 	{
507 		componentEnabler.release();
508 		return true;
509 	}
510 
511 	public JComponent getComponent()
512 	{
513 		return this;
514 	}
515 
516 	public boolean dependsOn(ModelItem modelItem)
517 	{
518 		return modelItem == gotoStep || modelItem == gotoStep.getTestCase() ||
519 				modelItem == gotoStep.getTestCase().getTestSuite() ||
520 				modelItem == gotoStep.getTestCase().getTestSuite().getProject();
521 	}
522 
523 	public String getTitle()
524 	{
525 		return gotoStep.getTestCase().getName() + " - " + gotoStep.getName();
526 	}
527 	
528 	public String getDescription()
529 	{
530 		return "Goto: [" + gotoStep.getName() + "] - " + gotoStep.getTestStepTitle();
531 	}
532 
533 	public Icon getIcon()
534 	{
535 		return getModelItem().getIcon();
536 	}
537 
538 	public GotoCondition getCurrentCondition()
539 	{
540 		return currentCondition;
541 	}
542 
543 	protected void enableEditComponents( boolean b )
544 	{
545 		expressionArea.setEnabled( b );
546 		testStepsCombo.setEnabled( b );
547 		copyButton.setEnabled( b );
548 		deleteButton.setEnabled( b );
549 		declareButton.setEnabled( b );
550 		testConditionButton.setEnabled( b );
551 	}
552 }