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.teststeps;
    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.util.Date;
    20
    21  import javax.swing.AbstractAction;
    22  import javax.swing.Action;
    23  import javax.swing.BorderFactory;
    24  import javax.swing.DefaultListModel;
    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.testcase.WsdlTestRunContext;
    46  import com.eviware.soapui.impl.wsdl.teststeps.WsdlGotoTestStep;
    47  import com.eviware.soapui.impl.wsdl.teststeps.WsdlTestRequestStep;
    48  import com.eviware.soapui.impl.wsdl.teststeps.WsdlGotoTestStep.GotoCondition;
    49  import com.eviware.soapui.model.ModelItem;
    50  import com.eviware.soapui.model.support.TestRunListenerAdapter;
    51  import com.eviware.soapui.model.testsuite.TestRunContext;
    52  import com.eviware.soapui.model.testsuite.TestRunner;
    53  import com.eviware.soapui.model.testsuite.TestStepResult;
    54  import com.eviware.soapui.support.DocumentListenerAdapter;
    55  import com.eviware.soapui.support.StringUtils;
    56  import com.eviware.soapui.support.UISupport;
    57  import com.eviware.soapui.support.components.JComponentInspector;
    58  import com.eviware.soapui.support.components.JInspectorPanel;
    59  import com.eviware.soapui.support.components.JUndoableTextArea;
    60  import com.eviware.soapui.support.components.JXToolBar;
    61  import com.eviware.soapui.support.log.JLogList;
    62  import com.eviware.soapui.support.xml.XmlUtils;
    63  import com.eviware.soapui.ui.support.ModelItemDesktopPanel;
    64
    65  /***
    66   * DesktopPanel for WsdlGotoTestSteps
    67   *
    68   * @author Ole.Matzura
    69   */
    70
    71  public class GotoStepDesktopPanel extends ModelItemDesktopPanel<WsdlGotoTestStep>
    72  {
    73  	private final WsdlGotoTestStep gotoStep;
    74  	private DefaultListModel listModel;
    75  	private JList conditionList;
    76  	private JTextArea expressionArea;
    77  	private JButton copyButton;
    78  	private JButton deleteButton;
    79  	private JButton declareButton;
    80  	private GotoTestStepsComboBoxModel testStepsModel;
    81  	private JComboBox testStepsCombo;
    82  	private JButton testConditionButton;
    83  	private TestRunComponentEnabler componentEnabler;
    84  	private GotoCondition currentCondition;
    85  	private JButton renameButton;
    86  	private JButton runButton;
    87  	private JButton addButton;
    88  	private JLogList logList;
    89  	private InternalTestRunListener testRunListener = new InternalTestRunListener();
    90  	private JInspectorPanel inspectorPanel;
    91
    92  	public GotoStepDesktopPanel(WsdlGotoTestStep testStep)
    93  	{
    94  		super( testStep );
    95  		this.gotoStep = testStep;
    96  		componentEnabler = new TestRunComponentEnabler( testStep.getTestCase() );
    97  		gotoStep.getTestCase().addTestRunListener( testRunListener );
    98
    99  		buildUI();
    100 	}
    101
    102 	public TestRunComponentEnabler getComponentEnabler()
    103 	{
    104 		return componentEnabler;
    105 	}
    106
    107 	public JList getConditionList()
    108 	{
    109 		return conditionList;
    110 	}
    111
    112 	public JButton getCopyButton()
    113 	{
    114 		return copyButton;
    115 	}
    116
    117 	public JButton getDeclareButton()
    118 	{
    119 		return declareButton;
    120 	}
    121
    122 	public JButton getDeleteButton()
    123 	{
    124 		return deleteButton;
    125 	}
    126
    127 	public JTextArea getExpressionArea()
    128 	{
    129 		return expressionArea;
    130 	}
    131
    132 	public WsdlGotoTestStep getGotoStep()
    133 	{
    134 		return gotoStep;
    135 	}
    136
    137 	public DefaultListModel getListModel()
    138 	{
    139 		return listModel;
    140 	}
    141
    142 	public JButton getTestConditionButton()
    143 	{
    144 		return testConditionButton;
    145 	}
    146
    147 	public JComboBox getTestStepsCombo()
    148 	{
    149 		return testStepsCombo;
    150 	}
    151
    152 	public GotoTestStepsComboBoxModel getTestStepsModel()
    153 	{
    154 		return testStepsModel;
    155 	}
    156
    157 	private void buildUI()
    158 	{
    159 		JSplitPane splitPane = UISupport.createHorizontalSplit();
    160 		splitPane.setLeftComponent( buildConditionList() );
    161
    162 		splitPane.setRightComponent( buildExpressionArea() );
    163 		splitPane.setResizeWeight( 0.1 );
    164 		splitPane.setDividerLocation( 120 );
    165
    166 		inspectorPanel = new JInspectorPanel( splitPane );
    167 		inspectorPanel.addInspector( new JComponentInspector( buildLog(), "Log", "A log of evaluated conditions", true ) );
    168
    169 		add( inspectorPanel, BorderLayout.CENTER );
    170
    171 		setBorder( BorderFactory.createEmptyBorder( 3, 3, 3, 3 ));
    172 		setPreferredSize( new Dimension( 550, 300 ));
    173
    174 		if( listModel.getSize() > 0 )
    175 			conditionList.setSelectedIndex( 0 );
    176
    177 		componentEnabler.add( conditionList );
    178 		componentEnabler.add( expressionArea );
    179 		componentEnabler.add( testStepsCombo );
    180 		componentEnabler.add( testConditionButton );
    181 		componentEnabler.add( copyButton );
    182 		componentEnabler.add( declareButton );
    183 		componentEnabler.add( deleteButton );
    184 		componentEnabler.add( addButton );
    185 		componentEnabler.add( runButton );
    186 		componentEnabler.add( renameButton );
    187 	}
    188
    189 	private JComponent buildLog()
    190 	{
    191 		logList = new JLogList( "ConditionLog" + getModelItem().getName() );
    192 		return logList;
    193 	}
    194
    195 	private JPanel buildExpressionArea()
    196 	{
    197 		expressionArea = new JUndoableTextArea();
    198 		expressionArea.setEnabled( false );
    199 		expressionArea.getDocument().addDocumentListener( new SourceAreaDocumentListener());
    200
    201 		JPanel expressionPanel = new JPanel( new BorderLayout() );
    202 		JScrollPane scrollPane = new JScrollPane( expressionArea );
    203 		UISupport.addTitledBorder( scrollPane, "Condition XPath Expression" );
    204
    205 		expressionPanel.add( scrollPane, BorderLayout.CENTER );
    206 		expressionPanel.add( buildConditionToolbar(), BorderLayout.NORTH );
    207 		expressionPanel.add( buildTargetToolbar(), BorderLayout.SOUTH );
    208 		return expressionPanel;
    209 	}
    210
    211 	private JPanel buildConditionList()
    212 	{
    213 		listModel = new DefaultListModel();
    214
    215 		for( int c = 0; c < gotoStep.getConditionCount(); c++ )
    216 		{
    217 			listModel.addElement( gotoStep.getConditionAt( c  ).getName() );
    218 		}
    219
    220 		conditionList = new JList( listModel );
    221 		conditionList.setSelectionMode( ListSelectionModel.SINGLE_SELECTION );
    222 		conditionList.addListSelectionListener( new ConditionListSelectionListener());
    223
    224 		JScrollPane listScrollPane = new JScrollPane( conditionList );
    225 		UISupport.addTitledBorder( listScrollPane, "Conditions" );
    226
    227 		JPanel p = new JPanel( new BorderLayout() );
    228 		p.add( buildConditionListToolbar(), BorderLayout.NORTH );
    229 		p.add( listScrollPane, BorderLayout.CENTER );
    230 		return p;
    231 	}
    232
    233 	private Component buildConditionListToolbar()
    234 	{
    235 		JXToolBar toolbar = UISupport.createSmallToolbar();
    236
    237 		addButton = new JButton( new AddAction() );
    238 		toolbar.addFixed( addButton );
    239 		copyButton = new JButton( new CopyAction() );
    240 		copyButton.setEnabled( false );
    241 		toolbar.addFixed( copyButton);
    242 		deleteButton = new JButton( new DeleteAction() );
    243 		deleteButton.setEnabled( false );
    244 		toolbar.addFixed( deleteButton);
    245 		renameButton = new JButton( new RenameAction() );
    246 		renameButton.setEnabled( false );
    247 		toolbar.addFixed( renameButton);
    248 		return toolbar;
    249 	}
    250
    251 	private Component buildConditionToolbar()
    252 	{
    253 		JXToolBar toolbar = UISupport.createSmallToolbar();
    254
    255 		declareButton = new JButton( new DeclareNamespacesAction() );
    256 		declareButton.setEnabled( false );
    257 		toolbar.addFixed( declareButton);
    258 		runButton = new JButton( new RunAction() );
    259 		toolbar.addFixed( runButton);
    260
    261 		toolbar.addGlue();
    262 		toolbar.addFixed( UISupport.createToolbarButton( new ShowOnlineHelpAction( HelpUrls.GOTOSTEPEDITOR_HELP_URL )));
    263 		return toolbar;
    264 	}
    265
    266 	protected JXToolBar buildTargetToolbar()
    267 	{
    268 		JXToolBar builder = UISupport.createSmallToolbar();
    269 		testStepsModel = new GotoTestStepsComboBoxModel( gotoStep.getTestCase(), null );
    270 		testStepsCombo = new JComboBox( testStepsModel );
    271 		testStepsCombo.setToolTipText( "The step the test case will go to if the current condition is true" );
    272 		testStepsCombo.setEnabled( false );
    273 		builder.addFixed( new JLabel( "<html><b>Target step:</b></html>"));
    274 		builder.addRelatedGap();
    275 		builder.addFixed( testStepsCombo );
    276 		builder.addGlue();
    277 		testConditionButton = new JButton( new TestConditionAction() );
    278 		testConditionButton.setEnabled( false );
    279 		builder.addFixed( testConditionButton);
    280 		builder.setBorder( BorderFactory.createEmptyBorder( 3, 3, 3, 3 ));
    281 		return builder;
    282 	}
    283
    284 	private final class SourceAreaDocumentListener extends DocumentListenerAdapter
    285 	{
    286 		@Override
    287 		public void update( Document document )
    288 		{
    289 			int ix = conditionList.getSelectedIndex();
    290 			if( ix != -1 )
    291 			{
    292 				gotoStep.getConditionAt( ix ).setExpression( expressionArea.getText() );
    293 			}
    294 		}
    295 	}
    296
    297 	private final class ConditionListSelectionListener implements ListSelectionListener
    298 	{
    299 		public void valueChanged(ListSelectionEvent e)
    300 		{
    301 			int ix = conditionList.getSelectedIndex();
    302 			if( ix == -1 )
    303 			{
    304 				expressionArea.setText( "" );
    305 				testStepsModel.setCondition( null );
    306 				currentCondition = null;
    307 			}
    308 			else
    309 			{
    310 				currentCondition = gotoStep.getConditionAt( ix );
    311 				expressionArea.setText( currentCondition.getExpression() );
    312 				testStepsModel.setCondition( currentCondition );
    313 			}
    314
    315 			boolean b = ix != -1;
    316 			enableEditComponents( b );
    317 		}
    318 	}
    319
    320 	private final class AddAction extends AbstractAction
    321 	{
    322 		public AddAction()
    323 		{
    324 			putValue( Action.SHORT_DESCRIPTION, "Adds a new Conditionr" );
    325 			putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/add_property.gif" ));
    326 		}
    327
    328 		public void actionPerformed(ActionEvent e)
    329 		{
    330 			String name = UISupport.prompt( "Specify name for condition", "Add Condition", "Condition " +
    331 					(gotoStep.getConditionCount()+1) );
    332 			if( name == null || name.trim().length() == 0 ) return;
    333
    334 			gotoStep.addCondition( name );
    335
    336 			listModel.addElement( name );
    337 			conditionList.setSelectedIndex( listModel.getSize()-1 );
    338 		}
    339 	}
    340
    341 	private final class CopyAction extends AbstractAction
    342 	{
    343 		public CopyAction()
    344 		{
    345 			putValue( Action.SHORT_DESCRIPTION, "Copies the selected Condition" );
    346 			putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/clone_request.gif" ));
    347 		}
    348
    349 		public void actionPerformed(ActionEvent e)
    350 		{
    351 			int ix = conditionList.getSelectedIndex();
    352 			GotoCondition config = gotoStep.getConditionAt( ix );
    353
    354 			String name = UISupport.prompt( "Specify name for condition", "Copy Condition", config.getName() );
    355 			if( name == null || name.trim().length() == 0 ) return;
    356
    357 			GotoCondition condition = gotoStep.addCondition( name );
    358 			condition.setExpression( config.getExpression() );
    359 			condition.setTargetStep( config.getTargetStep() );
    360 			condition.setType( config.getType() );
    361
    362 			listModel.addElement( name );
    363 			conditionList.setSelectedIndex( listModel.getSize()-1 );
    364 		}
    365 	}
    366
    367 	private final class DeleteAction extends AbstractAction
    368 	{
    369 		public DeleteAction()
    370 		{
    371 			putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/remove_property.gif" ));
    372 			putValue( Action.SHORT_DESCRIPTION, "Deletes the selected Condition" );
    373 		}
    374
    375 		public void actionPerformed(ActionEvent e)
    376 		{
    377 			if( UISupport.confirm( "Delete selected condition", "Delete Condition" ))
    378 			{
    379 				int ix = conditionList.getSelectedIndex();
    380
    381 				conditionList.setSelectedIndex( -1 );
    382
    383 				gotoStep.removeConditionAt( ix );
    384 				listModel.remove( ix );
    385
    386 				if( listModel.getSize() > 0 )
    387 				{
    388 					conditionList.setSelectedIndex( ix > listModel.getSize()-1 ? listModel.getSize()-1 : ix );
    389 				}
    390 			}
    391 		}
    392 	}
    393
    394 	private final class RenameAction extends AbstractAction
    395 	{
    396 		public RenameAction()
    397 		{
    398 			putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/rename.gif" ));
    399 			putValue( Action.SHORT_DESCRIPTION, "Renames the selected Condition" );
    400 		}
    401
    402 		public void actionPerformed(ActionEvent e)
    403 		{
    404 			int ix = conditionList.getSelectedIndex();
    405 			GotoCondition config = gotoStep.getConditionAt( ix );
    406
    407 			String name = UISupport.prompt( "Specify name for condition", "Copy Condition", config.getName() );
    408 			if( name == null || name.trim().length() == 0 ) return;
    409
    410 			config.setName( name );
    411 			listModel.setElementAt( name, ix );
    412 		}
    413 	}
    414
    415 	private final class DeclareNamespacesAction extends AbstractAction
    416 	{
    417 		public DeclareNamespacesAction()
    418 		{
    419 			putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/declareNs.gif" ));
    420 			putValue( Action.SHORT_DESCRIPTION, "Declare available response namespaces in condition expression" );
    421 		}
    422
    423 		public void actionPerformed(ActionEvent e)
    424 		{
    425 			try
    426 			{
    427 				WsdlTestRequestStep previousStep = (WsdlTestRequestStep) gotoStep.getTestCase().findPreviousStepOfType(
    428 						gotoStep, WsdlTestRequestStep.class );
    429
    430 				if (previousStep  != null )
    431 				{
    432 					WsdlResponse response = previousStep.getTestRequest().getResponse();
    433 					String xml = response == null ? null : response.getContentAsString();
    434 					if ( xml != null && xml.trim().length() > 0)
    435 					{
    436 						expressionArea.setText(XmlUtils.declareXPathNamespaces(xml)
    437 								+ expressionArea.getText());
    438 					}
    439 					else
    440 					{
    441 						UISupport.showErrorMessage( "Missing response in previous request step [" + previousStep.getName() + "]" );
    442 					}
    443 				}
    444 				else
    445 				{
    446 					UISupport.showErrorMessage( "Missing previous request step" );
    447 				}
    448 			}
    449 			catch (Exception e1)
    450 			{
    451 				SoapUI.logError( e1 );
    452 			}
    453 		}
    454 	}
    455
    456 	private final class RunAction extends AbstractAction
    457 	{
    458 		public RunAction()
    459 		{
    460 			putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/run_all.gif" ));
    461 			putValue( Action.SHORT_DESCRIPTION, "Runs the current conditions against the previous response" );
    462 		}
    463
    464 		public void actionPerformed(ActionEvent e)
    465 		{
    466 			if( listModel.getSize() == 0 )
    467 			{
    468 				UISupport.showErrorMessage( "Missing conditions!" );
    469 				return;
    470 			}
    471
    472 			WsdlTestRequestStep previousStep = (WsdlTestRequestStep) gotoStep.getTestCase().findPreviousStepOfType(
    473 					gotoStep, WsdlTestRequestStep.class );
    474
    475 			if( previousStep == null )
    476 			{
    477 				UISupport.showErrorMessage( "Missing previous request step" );
    478 			}
    479 			else
    480 			{
    481 				if( previousStep.getTestRequest().getResponse() == null ||
    482 					 StringUtils.isNullOrEmpty( previousStep.getTestRequest().getResponse().getContentAsString()) )
    483 				{
    484 					UISupport.showErrorMessage( "Missing response in previous message" );
    485 					return;
    486 				}
    487
    488 				WsdlTestRunContext context = new WsdlTestRunContext( gotoStep );
    489 				GotoCondition target = gotoStep.runConditions( previousStep, context );
    490 				if( target == null )
    491 				{
    492 					logList.addLine( "No condition true for current response in [" + previousStep.getName() + "]" );
    493 				}
    494 				else
    495 				{
    496 					logList.addLine( "Condition triggered for go to [" + target.getTargetStep() + "]" );
    497 				}
    498
    499 				inspectorPanel.setCurrentInspector( "Log" );
    500 			}
    501 		}
    502 	}
    503
    504 	private final class TestConditionAction extends AbstractAction
    505 	{
    506 		public TestConditionAction()
    507 		{
    508 			putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/run.gif" ));
    509 			putValue( Action.SHORT_DESCRIPTION, "Runs the current condition against the previous response and shows the result" );
    510 		}
    511
    512 		public void actionPerformed(ActionEvent e)
    513 		{
    514 			WsdlTestRequestStep previousStep = (WsdlTestRequestStep) gotoStep.getTestCase().findPreviousStepOfType(
    515 					gotoStep, WsdlTestRequestStep.class );
    516
    517 			if( previousStep == null )
    518 			{
    519 				UISupport.showErrorMessage( "Missing previous request step" );
    520 			}
    521 			else
    522 			{
    523 				if( previousStep.getTestRequest().getResponse() == null ||
    524 					 previousStep.getTestRequest().getResponse().getContentAsString().trim().length() == 0 )
    525 				{
    526 					UISupport.showErrorMessage( "Missing response in previous request step [" +
    527 							previousStep.getName() + "]" );
    528 					return;
    529 				}
    530
    531 				try
    532 				{
    533 					GotoCondition condition = gotoStep.getConditionAt( conditionList.getSelectedIndex() );
    534 					WsdlTestRunContext context = new WsdlTestRunContext( gotoStep );
    535 					boolean evaluate = condition.evaluate( previousStep, context );
    536 					if( !evaluate )
    537 					{
    538 						UISupport.showInfoMessage( "Condition not true for current response in [" + previousStep.getName() + "]" );
    539 					}
    540 					else
    541 					{
    542 						UISupport.showInfoMessage( "Condition true for current response in [" + previousStep.getName() + "]" );
    543 					}
    544 				}
    545 				catch (Exception e1)
    546 				{
    547 					UISupport.showErrorMessage( "Error checking condition: " + e1.getMessage() );
    548 				}
    549 			}
    550 		}
    551 	}
    552
    553 	public boolean onClose( boolean canCancel )
    554 	{
    555 		super.release();
    556 		componentEnabler.release();
    557 		gotoStep.getTestCase().removeTestRunListener( testRunListener );
    558
    559 		return true;
    560 	}
    561
    562 	public JComponent getComponent()
    563 	{
    564 		return this;
    565 	}
    566
    567 	public boolean dependsOn(ModelItem modelItem)
    568 	{
    569 		return modelItem == gotoStep || modelItem == gotoStep.getTestCase() ||
    570 				modelItem == gotoStep.getTestCase().getTestSuite() ||
    571 				modelItem == gotoStep.getTestCase().getTestSuite().getProject();
    572 	}
    573
    574 	public GotoCondition getCurrentCondition()
    575 	{
    576 		return currentCondition;
    577 	}
    578
    579 	protected void enableEditComponents( boolean b )
    580 	{
    581 		expressionArea.setEnabled( b );
    582 		testStepsCombo.setEnabled( b );
    583 		copyButton.setEnabled( b );
    584 		deleteButton.setEnabled( b );
    585 		declareButton.setEnabled( b );
    586 		testConditionButton.setEnabled( b );
    587 		renameButton.setEnabled( b );
    588 	}
    589
    590 	private class InternalTestRunListener extends TestRunListenerAdapter
    591 	{
    592 		@Override
    593 		public void afterStep( TestRunner testRunner, TestRunContext runContext, TestStepResult result )
    594 		{
    595 			if( result.getTestStep() == gotoStep )
    596 			{
    597 				logList.addLine( new Date( result.getTimeStamp() ).toString() + ": " + result.getMessages()[0] );
    598 				inspectorPanel.setCurrentInspector( "Log" );
    599 			}
    600 		}
    601 	}
    602 }