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.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 				SoapUI.logError( e1 );
    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 }