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.Dimension;
    17  import java.awt.GridLayout;
    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.Action;
    28  import javax.swing.BorderFactory;
    29  import javax.swing.DefaultComboBoxModel;
    30  import javax.swing.DefaultListModel;
    31  import javax.swing.Icon;
    32  import javax.swing.JButton;
    33  import javax.swing.JCheckBox;
    34  import javax.swing.JComboBox;
    35  import javax.swing.JComponent;
    36  import javax.swing.JLabel;
    37  import javax.swing.JList;
    38  import javax.swing.JPanel;
    39  import javax.swing.JScrollPane;
    40  import javax.swing.JSplitPane;
    41  import javax.swing.JTextArea;
    42  import javax.swing.ListSelectionModel;
    43  import javax.swing.event.ChangeEvent;
    44  import javax.swing.event.ChangeListener;
    45  import javax.swing.event.ListSelectionEvent;
    46  import javax.swing.event.ListSelectionListener;
    47  import javax.swing.text.Document;
    48
    49  import com.eviware.soapui.SoapUI;
    50  import com.eviware.soapui.impl.wsdl.actions.support.ShowOnlineHelpAction;
    51  import com.eviware.soapui.impl.wsdl.panels.support.TestRunComponentEnabler;
    52  import com.eviware.soapui.impl.wsdl.support.HelpUrls;
    53  import com.eviware.soapui.impl.wsdl.testcase.WsdlTestRunContext;
    54  import com.eviware.soapui.impl.wsdl.teststeps.PropertyTransfer;
    55  import com.eviware.soapui.impl.wsdl.teststeps.TransferResponseValuesTestStep;
    56  import com.eviware.soapui.impl.wsdl.teststeps.WsdlTestRequest;
    57  import com.eviware.soapui.impl.wsdl.teststeps.WsdlTestRequestStep;
    58  import com.eviware.soapui.impl.wsdl.teststeps.WsdlTestStep;
    59  import com.eviware.soapui.impl.wsdl.teststeps.WsdlTestStepListener;
    60  import com.eviware.soapui.impl.wsdl.teststeps.TransferResponseValuesTestStep.ValueTransferResult;
    61  import com.eviware.soapui.impl.wsdl.teststeps.actions.ShowTransferValuesResultsAction;
    62  import com.eviware.soapui.model.ModelItem;
    63  import com.eviware.soapui.model.support.TestSuiteListenerAdapter;
    64  import com.eviware.soapui.model.testsuite.TestStep;
    65  import com.eviware.soapui.model.testsuite.TestStepProperty;
    66  import com.eviware.soapui.support.DocumentListenerAdapter;
    67  import com.eviware.soapui.support.UISupport;
    68  import com.eviware.soapui.support.components.JUndoableTextArea;
    69  import com.eviware.soapui.support.components.JXToolBar;
    70  import com.eviware.soapui.support.xml.XmlUtils;
    71  import com.eviware.soapui.ui.desktop.DesktopPanel;
    72
    73  /***
    74   * DesktopPanel for TransferResponseValuesTestStep
    75   *
    76   * @author Ole.Matzura
    77   */
    78
    79  public class TransferResponseValuesDesktopPanel extends JPanel implements DesktopPanel
    80  {
    81  	private final TransferResponseValuesTestStep transferStep;
    82  	private DefaultListModel listModel;
    83  	private JList transferList;
    84  	private JTextArea sourceArea;
    85  	private JTextArea targetArea;
    86  	private JButton copyButton;
    87  	private JButton deleteButton;
    88  	private JButton declareButton;
    89  	private JComboBox sourcePropertyCombo;
    90  	private JComboBox targetPropertyCombo;
    91  	private JComboBox sourceStepCombo;
    92  	private JComboBox targetStepCombo;
    93  	private DefaultComboBoxModel sourceStepModel;
    94  	private DefaultComboBoxModel targetStepModel;
    95  	private TestStepNameListener sourceTestStepNameListener;
    96  	private TestStepNameListener targetStepNameListener;
    97  	private TestStepPropertiesListener sourceStepPropertiesListener;
    98  	private TestStepPropertiesListener targetStepPropertiesListener;
    99  	private TransferPropertyChangeListener transferPropertyChangeListener = new TransferPropertyChangeListener();
    100 	private boolean selecting;
    101 	private InternalTestSuiteListener testSuiteListener;
    102 	private TestRunComponentEnabler componentEnabler;
    103 	private JCheckBox failTransferCheckBox;
    104 	private JButton runButton;
    105 	private JButton renameButton;
    106 	private JCheckBox setNullCheckBox;
    107 	private JCheckBox transferTextContentCheckBox;
    108 	private JCheckBox ignoreEmptyCheckBox;
    109 	private JCheckBox transferAllCheckBox;
    110 	private DesktopPanel resultDesktopPanel;
    111
    112 	public TransferResponseValuesDesktopPanel(TransferResponseValuesTestStep testStep)
    113 	{
    114 		super( new BorderLayout() );
    115 		this.transferStep = testStep;
    116 		componentEnabler = new TestRunComponentEnabler( testStep.getTestCase() );
    117
    118 		buildUI();
    119
    120 		testSuiteListener = new InternalTestSuiteListener();
    121 		transferStep.getTestCase().getTestSuite().addTestSuiteListener( testSuiteListener );
    122 	}
    123
    124 	protected void buildUI()
    125 	{
    126 		JSplitPane splitPane = UISupport.createHorizontalSplit();
    127
    128 		listModel = new DefaultListModel();
    129
    130 		for( int c = 0; c < transferStep.getTransferCount(); c++ )
    131 		{
    132 			listModel.addElement( transferStep.getTransferAt( c  ).getName() );
    133 		}
    134
    135 		transferList = new JList( listModel );
    136 		transferList.setSelectionMode( ListSelectionModel.SINGLE_SELECTION );
    137 		transferList.addListSelectionListener( new TransferListSelectionListener());
    138 		componentEnabler.add( transferList );
    139
    140 		JScrollPane listScrollPane = new JScrollPane( transferList );
    141 		listScrollPane.setBorder(
    142 				BorderFactory.createCompoundBorder(
    143 				BorderFactory.createTitledBorder( BorderFactory.createEmptyBorder(), "Transfers" ),
    144 				BorderFactory.createEmptyBorder()));
    145
    146 		splitPane.setLeftComponent( listScrollPane);
    147
    148 		JSplitPane innerSplit = UISupport.createVerticalSplit();
    149 		innerSplit.setBorder( null );
    150 		sourceArea = new JUndoableTextArea();
    151 		sourceArea.setToolTipText( "XPath selection from source property" );
    152 		sourceArea.setEnabled( false );
    153 		sourceArea.getDocument().addDocumentListener( new SourceAreaDocumentListener());
    154 		componentEnabler.add( sourceArea );
    155
    156 		targetArea = new JUndoableTextArea();
    157 		targetArea.setToolTipText( "XPath target in target property" );
    158 		targetArea.setEnabled( false );
    159 		targetArea.getDocument().addDocumentListener( new TargetAreaDocumentListener());
    160 		componentEnabler.add( targetArea );
    161
    162 		JPanel sourcePanel = new JPanel( new BorderLayout() );
    163 		sourcePanel.add( new JScrollPane( sourceArea ), BorderLayout.CENTER );
    164 		JXToolBar toolbar = createSourceToolbar();
    165 		sourcePanel.add( toolbar, BorderLayout.NORTH );
    166 		sourcePanel.setBorder( BorderFactory.createEmptyBorder( 0, 3, 3, 3 ));
    167
    168 		innerSplit.setTopComponent( sourcePanel );
    169
    170 		JPanel targetPanel = new JPanel( new BorderLayout() );
    171 		targetPanel.add( new JScrollPane( targetArea ), BorderLayout.CENTER );
    172 		toolbar = createTargetToolbar();
    173 		targetPanel.add( toolbar, BorderLayout.NORTH );
    174 		targetPanel.setBorder( BorderFactory.createEmptyBorder( 0, 3, 3, 3 ));
    175
    176 		innerSplit.setBottomComponent( targetPanel );
    177
    178 		innerSplit.setResizeWeight( 0.5 );
    179 		innerSplit.setDividerLocation( 0.5 );
    180
    181 		JPanel panel = createTransferOptions();
    182
    183 		JPanel innerPanel = new JPanel( new BorderLayout() );
    184 		innerPanel.add( innerSplit, BorderLayout.CENTER );
    185 		innerPanel.add( panel, BorderLayout.SOUTH );
    186
    187 		splitPane.setRightComponent( innerPanel );
    188 		splitPane.setResizeWeight( 0.1 );
    189 		splitPane.setDividerLocation( 120 );
    190
    191 		add( splitPane, BorderLayout.CENTER );
    192 		add( createButtonBar(), BorderLayout.NORTH );
    193
    194 		setBorder( BorderFactory.createEmptyBorder( 3, 3, 3, 3 ));
    195 		setPreferredSize( new Dimension( 550, 400 ));
    196
    197 		if( listModel.getSize() > 0 )
    198 			transferList.setSelectedIndex( 0 );
    199
    200 		componentEnabler.add( deleteButton );
    201 		componentEnabler.add( declareButton );
    202 		componentEnabler.add( runButton );
    203 		componentEnabler.add( copyButton );
    204 		componentEnabler.add( renameButton );
    205 		componentEnabler.add( failTransferCheckBox );
    206 		componentEnabler.add( setNullCheckBox );
    207 		componentEnabler.add( transferTextContentCheckBox );
    208 		componentEnabler.add( ignoreEmptyCheckBox );
    209 		componentEnabler.add( transferAllCheckBox );
    210 	}
    211
    212 	protected JXToolBar createButtonBar()
    213 	{
    214 		JXToolBar builder = UISupport.createToolbar();
    215 		builder.addFixed( new JButton( new AddAction() ) );
    216 		builder.addRelatedGap();
    217 		copyButton = new JButton( new CopyAction() );
    218 		copyButton.setEnabled( false );
    219 		builder.addFixed( copyButton);
    220 		builder.addRelatedGap();
    221 		renameButton = new JButton( new RenameAction() );
    222 		renameButton.setEnabled( false );
    223 		builder.addFixed( renameButton);
    224 		builder.addRelatedGap();
    225 		deleteButton = new JButton( new DeleteAction() );
    226 		deleteButton.setEnabled( false );
    227 		builder.addFixed( deleteButton);
    228 		builder.addRelatedGap();
    229 		declareButton = new JButton( new DeclareNamespacesAction() );
    230 		declareButton.setEnabled( false );
    231 		builder.addFixed( declareButton);
    232 		builder.addRelatedGap();
    233 		runButton = new JButton( new RunAction() );
    234 		runButton.setEnabled( transferStep.getTransferCount() > 0 );
    235 		builder.addFixed( runButton);
    236 		builder.addGlue();
    237 //		JButton closeButton = new JButton( new CloseAction() );
    238 //		builder.addFixed( closeButton);
    239 //		builder.addRelatedGap();
    240 		builder.addFixed( UISupport.createToolbarButton( new ShowOnlineHelpAction( HelpUrls.TRANSFERSTEPEDITOR_HELP_URL )));
    241 		return builder;
    242 	}
    243
    244 	protected JPanel createTransferOptions()
    245 	{
    246 		JPanel panel = new JPanel( new GridLayout( 3, 2 ));
    247 		failTransferCheckBox = new JCheckBox( "Fail transfer on error", false );
    248 		failTransferCheckBox.setToolTipText( "Fails the Property Transfer Step if an error occurs" );
    249 		failTransferCheckBox.addChangeListener( new ChangeListener() {
    250
    251 			public void stateChanged(ChangeEvent e)
    252 			{
    253 				PropertyTransfer currentTransfer = getCurrentTransfer();
    254 				if( currentTransfer != null )
    255 				{
    256 					currentTransfer.setFailOnError( failTransferCheckBox.isSelected() );
    257 				}
    258 			}} );
    259
    260 		setNullCheckBox = new JCheckBox( "Set null on missing source", false );
    261 		setNullCheckBox.setToolTipText( "Will set target to null if source is missing or null" );
    262 		setNullCheckBox.addChangeListener( new ChangeListener() {
    263
    264 			public void stateChanged(ChangeEvent e)
    265 			{
    266 				PropertyTransfer currentTransfer = getCurrentTransfer();
    267 				if( currentTransfer != null )
    268 				{
    269 					currentTransfer.setSetNullOnMissingSource( setNullCheckBox.isSelected() );
    270 				}
    271 			}} );
    272
    273 		transferTextContentCheckBox = new JCheckBox( "Transfer text content", false );
    274 		transferTextContentCheckBox.setToolTipText( "Will only transfer text content of source/target elements" );
    275 		transferTextContentCheckBox.addChangeListener( new ChangeListener() {
    276
    277 			public void stateChanged(ChangeEvent e)
    278 			{
    279 				PropertyTransfer currentTransfer = getCurrentTransfer();
    280 				if( currentTransfer != null )
    281 				{
    282 					currentTransfer.setTransferTextContent( transferTextContentCheckBox.isSelected() );
    283 				}
    284 			}} );
    285
    286 		ignoreEmptyCheckBox = new JCheckBox( "Ignore empty/missing values", false );
    287 		ignoreEmptyCheckBox.setToolTipText( "Will not transfer empty or missing values" );
    288 		ignoreEmptyCheckBox.addChangeListener( new ChangeListener() {
    289
    290 			public void stateChanged(ChangeEvent e)
    291 			{
    292 				PropertyTransfer currentTransfer = getCurrentTransfer();
    293 				if( currentTransfer != null )
    294 				{
    295 					currentTransfer.setIgnoreEmpty( ignoreEmptyCheckBox.isSelected() );
    296 				}
    297 			}} );
    298
    299 		transferAllCheckBox = new JCheckBox( "Transfer to all", false );
    300 		transferAllCheckBox.setToolTipText( "Will transfer to all matching target selections" );
    301 		transferAllCheckBox.addChangeListener( new ChangeListener() {
    302
    303 			public void stateChanged(ChangeEvent e)
    304 			{
    305 				PropertyTransfer currentTransfer = getCurrentTransfer();
    306 				if( currentTransfer != null )
    307 				{
    308 					currentTransfer.setTransferToAll( transferAllCheckBox.isSelected() );
    309 				}
    310 			}} );
    311
    312
    313 		panel.add( failTransferCheckBox );
    314 		panel.add( setNullCheckBox );
    315 		panel.add( transferTextContentCheckBox );
    316 		panel.add( ignoreEmptyCheckBox );
    317 		panel.add( transferAllCheckBox );
    318 		panel.setBorder( BorderFactory.createEmptyBorder( 3, 3, 3, 3 ) );
    319 		return panel;
    320 	}
    321
    322 	protected JXToolBar createTargetToolbar()
    323 	{
    324 		JXToolBar toolbar;
    325 		toolbar = UISupport.createToolbar();
    326 		toolbar.addSpace( 3 );
    327 		toolbar.addFixed( new JLabel( "<html><b>Target:</b></html>"));
    328 		toolbar.addGlue();
    329
    330 		targetStepCombo.setSelectedItem( null );
    331 		targetStepCombo.setToolTipText( "The step the value will be transferred to" );
    332 		targetStepCombo.setEnabled( false );
    333 		targetStepCombo.addItemListener(
    334 				new StepComboItemListener( targetPropertyCombo, targetStepPropertiesListener ) );
    335 		targetStepCombo.addItemListener( new ItemListener() {
    336
    337 			public void itemStateChanged(ItemEvent e)
    338 			{
    339 				if( e.getStateChange() == ItemEvent.SELECTED && !selecting )
    340 				{
    341 					String targetStep = (String) targetStepCombo.getSelectedItem();
    342 					PropertyTransfer valueTransfer = getCurrentTransfer();
    343
    344 					if( valueTransfer != null )
    345 					{
    346 						valueTransfer.setTargetStepName( targetStep );
    347 					}
    348 				}
    349 			}} );
    350
    351 		toolbar.addFixed( new JLabel( "Step:"));
    352 		toolbar.addRelatedGap();
    353 		toolbar.add( targetStepCombo );
    354 		toolbar.addRelatedGap();
    355
    356 		toolbar.addFixed( new JLabel( "Property:"));
    357 		toolbar.addRelatedGap();
    358
    359 		targetPropertyCombo.setToolTipText( "The property the value will be transferred to" );
    360 		targetPropertyCombo.setEnabled( false );
    361 		targetPropertyCombo.addItemListener( new ItemListener() {
    362
    363 			public void itemStateChanged(ItemEvent e)
    364 			{
    365 				if( e.getStateChange() == ItemEvent.SELECTED && !selecting )
    366 				{
    367 					String targetProperty = (String) targetPropertyCombo.getSelectedItem();
    368 					PropertyTransfer valueTransfer = getCurrentTransfer();
    369
    370 					if( valueTransfer != null )
    371 					{
    372 						valueTransfer.setTargetPropertyName( targetProperty );
    373 					}
    374 				}
    375 			}} );
    376
    377 		toolbar.add( targetPropertyCombo);
    378 		return toolbar;
    379 	}
    380
    381 	protected JXToolBar createSourceToolbar()
    382 	{
    383 		JXToolBar toolbar = UISupport.createToolbar();
    384 		toolbar.addSpace( 3 );
    385 		toolbar.addFixed( new JLabel( "<html><b>Source:</b></html>"));
    386 		toolbar.addGlue();
    387
    388 		sourcePropertyCombo = new JComboBox();
    389 		sourceStepModel = new DefaultComboBoxModel();
    390 		sourceStepCombo = new JComboBox( sourceStepModel );
    391 		sourceTestStepNameListener = new TestStepNameListener( sourceStepModel );
    392
    393 		componentEnabler.add( sourcePropertyCombo );
    394 		componentEnabler.add( sourceStepCombo );
    395
    396 		targetPropertyCombo = new JComboBox();
    397 		targetStepModel = new DefaultComboBoxModel();
    398 		targetStepCombo = new JComboBox( targetStepModel );
    399 		targetStepNameListener = new TestStepNameListener( targetStepModel );
    400
    401 		componentEnabler.add( targetPropertyCombo );
    402 		componentEnabler.add( targetStepCombo );
    403
    404 		sourceStepPropertiesListener = new TestStepPropertiesListener( sourcePropertyCombo );
    405 		targetStepPropertiesListener = new TestStepPropertiesListener( targetPropertyCombo );
    406
    407 		for( int c = 0; c < transferStep.getTestCase().getTestStepCount(); c++ )
    408 		{
    409 			WsdlTestStep testStep = (WsdlTestStep) transferStep.getTestCase().getTestStepAt( c );
    410 			if( testStep == transferStep )
    411 				continue;
    412
    413 			testStep.addPropertyChangeListener( TestStep.NAME_PROPERTY, sourceTestStepNameListener);
    414 			testStep.addPropertyChangeListener( TestStep.NAME_PROPERTY, targetStepNameListener);
    415
    416 			String nm = testStep.getName();
    417 			sourceStepModel.addElement( nm );
    418 			targetStepModel.addElement( nm );
    419 		}
    420
    421 		sourceStepCombo.setSelectedItem( null );
    422 		sourceStepCombo.setToolTipText( "The step the value will be transferred from" );
    423 		sourceStepCombo.setEnabled( false );
    424 		sourceStepCombo.addItemListener(
    425 				new StepComboItemListener( sourcePropertyCombo, sourceStepPropertiesListener ) );
    426 		sourceStepCombo.addItemListener( new ItemListener() {
    427
    428 			public void itemStateChanged(ItemEvent e)
    429 			{
    430 				if( e.getStateChange() == ItemEvent.SELECTED && !selecting )
    431 				{
    432 					String sourceStep = (String) sourceStepCombo.getSelectedItem();
    433 					PropertyTransfer valueTransfer = getCurrentTransfer();
    434
    435 					if( valueTransfer != null )
    436 					{
    437 						valueTransfer.setSourceStepName( sourceStep );
    438 					}
    439 				}
    440 			}} );
    441
    442 		toolbar.addFixed( new JLabel( "Step:"));
    443 		toolbar.addRelatedGap();
    444 		toolbar.add( sourceStepCombo );
    445 		toolbar.addRelatedGap();
    446
    447 		toolbar.addFixed( new JLabel( "Property:"));
    448 		toolbar.addRelatedGap();
    449
    450 		sourcePropertyCombo.setToolTipText( "The property the value will be transferred from" );
    451 		sourcePropertyCombo.setEnabled( false );
    452 		sourcePropertyCombo.addItemListener( new ItemListener() {
    453
    454 			public void itemStateChanged(ItemEvent e)
    455 			{
    456 				if( e.getStateChange() == ItemEvent.SELECTED && !selecting )
    457 				{
    458 					String sourceProperty = (String) sourcePropertyCombo.getSelectedItem();
    459 					PropertyTransfer valueTransfer = getCurrentTransfer();
    460
    461 					if( valueTransfer != null )
    462 					{
    463 						valueTransfer.setSourcePropertyName( sourceProperty );
    464 					}
    465 				}
    466 			}} );
    467
    468 		toolbar.add( sourcePropertyCombo);
    469 		return toolbar;
    470 	}
    471
    472 	public PropertyTransfer getCurrentTransfer()
    473 	{
    474 		int ix = transferList.getSelectedIndex();
    475 		return ix == -1 ? null : transferStep.getTransferAt( ix );
    476 	}
    477
    478 	/***
    479 	 * Listen for testStep property changes and update properties combo accordingly
    480 	 */
    481
    482 	private static final class TestStepPropertiesListener implements WsdlTestStepListener
    483 	{
    484 		private final JComboBox combo;
    485
    486 		public TestStepPropertiesListener(JComboBox combo)
    487 		{
    488 			this.combo = combo;
    489 		}
    490
    491 		public void propertyAdded(String name)
    492 		{
    493 			combo.addItem( name );
    494 			combo.setEnabled( true );
    495 		}
    496
    497 		public void propertyRemoved(String name)
    498 		{
    499 			if( combo.getSelectedItem().equals( name ))
    500 				combo.setSelectedItem( null );
    501
    502 			combo.removeItem( name );
    503 			combo.setEnabled( combo.getItemCount() > 0 );
    504 		}
    505
    506 		public void propertyRenamed(String oldName, String newName)
    507 		{
    508 			DefaultComboBoxModel model = (DefaultComboBoxModel) combo.getModel();
    509
    510 			int stepIndex = model.getIndexOf( oldName );
    511 			if( stepIndex != -1 )
    512 			{
    513 				Object selectedItem = model.getSelectedItem();
    514
    515 				model.removeElementAt( stepIndex );
    516 				model.insertElementAt( newName, stepIndex );
    517
    518 				// ensure selection
    519 				if( selectedItem.equals( oldName ) )
    520 					model.setSelectedItem( newName );
    521 			}
    522 		}
    523
    524 		public void propertyValueChanged(String name, String oldValue, String newValue)
    525 		{
    526 		}
    527 	}
    528
    529 	/***
    530 	 * Listen for teststep changes and update source/target step combos accordingly
    531 	 */
    532
    533 	private final class InternalTestSuiteListener extends TestSuiteListenerAdapter
    534 	{
    535 		public void testStepAdded(TestStep testStep, int index)
    536 		{
    537 			if( testStep.getTestCase() == transferStep.getTestCase() )
    538 			{
    539 				sourceStepModel.addElement( testStep.getName() );
    540 				targetStepModel.addElement( testStep.getName() );
    541
    542 				testStep.addPropertyChangeListener( TestStep.NAME_PROPERTY, sourceTestStepNameListener);
    543 				testStep.addPropertyChangeListener( TestStep.NAME_PROPERTY, targetStepNameListener);
    544 			}
    545 		}
    546
    547 		public void testStepMoved(TestStep testStep, int fromIndex, int offset)
    548 		{
    549 			if( testStep.getTestCase() == transferStep.getTestCase() )
    550 			{
    551 				String testStepName = testStep.getName();
    552 				if( sourceStepModel.getIndexOf( testStepName ) == fromIndex )
    553 				{
    554 					String sourceStep = ( String ) sourceStepCombo.getSelectedItem();
    555 					String sourceProperty = ( String ) sourcePropertyCombo.getSelectedItem();
    556
    557 					sourceStepModel.removeElementAt( fromIndex );
    558 					if( fromIndex + offset > sourceStepModel.getSize() )
    559 						sourceStepModel.addElement( testStepName );
    560 					else
    561 						sourceStepModel.insertElementAt( testStepName, fromIndex + offset );
    562
    563 					sourceStepCombo.setSelectedItem( sourceStep );
    564 					sourcePropertyCombo.setSelectedItem( sourceProperty );
    565 				}
    566
    567 				if( targetStepModel.getIndexOf( testStepName ) == fromIndex )
    568 				{
    569 					String targetStep = ( String ) targetStepCombo.getSelectedItem();
    570 					String targetProperty = ( String ) targetPropertyCombo.getSelectedItem();
    571
    572 					targetStepModel.removeElementAt( fromIndex );
    573 					if( fromIndex + offset > targetStepModel.getSize() )
    574 						targetStepModel.addElement( testStepName );
    575 					else
    576 						targetStepModel.insertElementAt( testStepName, fromIndex + offset );
    577
    578 					targetStepCombo.setSelectedItem( targetStep );
    579 					targetPropertyCombo.setSelectedItem( targetProperty );
    580 				}
    581 			}
    582 		}
    583
    584 		public void testStepRemoved(TestStep testStep, int index)
    585 		{
    586 			if( testStep.getTestCase() == transferStep.getTestCase() )
    587 			{
    588 				sourceStepModel.removeElement( testStep.getName() );
    589 				targetStepModel.removeElement( testStep.getName() );
    590
    591 				testStep.removePropertyChangeListener( TestStep.NAME_PROPERTY, sourceTestStepNameListener);
    592 				testStep.removePropertyChangeListener( TestStep.NAME_PROPERTY, targetStepNameListener);
    593 			}
    594 		}
    595 	}
    596
    597 	/***
    598 	 * Listen for testStep name changes and modify comboBox model accordingly
    599 	 */
    600
    601 	private final class TestStepNameListener implements PropertyChangeListener
    602 	{
    603 		private final DefaultComboBoxModel model;
    604
    605 		public TestStepNameListener(DefaultComboBoxModel model)
    606 		{
    607 			this.model = model;
    608 		}
    609
    610 		public void propertyChange(PropertyChangeEvent evt)
    611 		{
    612 			Object oldItem = evt.getOldValue();
    613 			int stepIndex = model.getIndexOf( oldItem );
    614 			if( stepIndex != -1 )
    615 			{
    616 				Object selectedItem = model.getSelectedItem();
    617 				Object newItem = evt.getNewValue();
    618
    619 				selecting = true;
    620 				model.removeElementAt( stepIndex );
    621 				model.insertElementAt( newItem, stepIndex );
    622 				selecting = false;
    623
    624 				// ensure selection
    625 				if( selectedItem.equals( oldItem ) )
    626 					model.setSelectedItem( newItem );
    627 			}
    628 		}
    629 	}
    630
    631 	/***
    632 	 * Listen to step selections and update properties combo accordingly
    633 	 */
    634
    635 	private final class StepComboItemListener implements ItemListener
    636 	{
    637 		private final JComboBox propertyCombo;
    638 		private final TestStepPropertiesListener testStepPropertiesListener;
    639
    640 		public StepComboItemListener(final JComboBox propertyCombo, TestStepPropertiesListener testStepPropertiesListener)
    641 		{
    642 			this.propertyCombo = propertyCombo;
    643 			this.testStepPropertiesListener = testStepPropertiesListener;
    644 		}
    645
    646 		public void itemStateChanged(ItemEvent e)
    647 		{
    648 			if( e.getStateChange() == ItemEvent.DESELECTED )
    649 			{
    650 				WsdlTestStep step = (WsdlTestStep) transferStep.getTestCase().getTestStepByName( (String) e.getItem() );
    651 				if( step != null )
    652 					step.removeTestStepListener( testStepPropertiesListener );
    653 			}
    654
    655 			if( e.getStateChange() == ItemEvent.SELECTED )
    656 			{
    657 				String selectedItem = (String) e.getItem();
    658 				WsdlTestStep step = (WsdlTestStep) transferStep.getTestCase().getTestStepByName( selectedItem );
    659
    660 				String[] propertyNames = step == null ? new String[0] : step.getPropertyNames();
    661
    662 				// remove read-only properties from target property
    663 				if( propertyCombo == targetPropertyCombo )
    664 				{
    665 					List<String> names = new ArrayList<String>();
    666 					for( String name : propertyNames )
    667 					{
    668 						TestStepProperty property = step.getProperty( name );
    669 						if( !property.isReadOnly() )
    670 							names.add( property.getName() );
    671 					}
    672
    673 					propertyNames = names.toArray( new String[names.size()] );
    674 				}
    675
    676 				propertyCombo.setModel( new DefaultComboBoxModel( propertyNames ));
    677 				propertyCombo.setEnabled( propertyNames.length > 0 );
    678
    679 				if( propertyCombo == targetPropertyCombo )
    680 					propertyCombo.setSelectedItem( getCurrentTransfer().getTargetPropertyName() );
    681 				else
    682 					propertyCombo.setSelectedItem( getCurrentTransfer().getSourcePropertyName() );
    683
    684 				step.addTestStepListener( testStepPropertiesListener );
    685 			}
    686 			else
    687 			{
    688 				propertyCombo.removeAllItems();
    689 				propertyCombo.setEnabled( false );
    690 			}
    691 		}
    692 	}
    693
    694 	/***
    695 	 * Handle updates to source path
    696 	 */
    697
    698 	private final class SourceAreaDocumentListener extends DocumentListenerAdapter
    699 	{
    700 		public void update(Document document)
    701 		{
    702 			int ix = transferList.getSelectedIndex();
    703 			if( ix != -1 )
    704 			{
    705 				transferStep.getTransferAt( ix ).setSourcePath( sourceArea.getText() );
    706 			}
    707 		}
    708 	}
    709
    710 	/***
    711 	 * Handle updates to target path
    712 	 */
    713
    714 	private final class TargetAreaDocumentListener extends DocumentListenerAdapter
    715 	{
    716 		public void update( Document document )
    717 		{
    718 			int ix = transferList.getSelectedIndex();
    719 			if( ix != -1 )
    720 			{
    721 				transferStep.getTransferAt( ix ).setTargetPath( targetArea.getText() );
    722 			}
    723 		}
    724 	}
    725
    726 	/***
    727 	 * Listen to selection changes in transfer list and update controls accordingly
    728 	 */
    729
    730 	private final class TransferListSelectionListener implements ListSelectionListener
    731 	{
    732 		private PropertyTransfer transfer;
    733
    734 		public void valueChanged(ListSelectionEvent e)
    735 		{
    736 			selecting = true;
    737
    738 			if( transfer != null )
    739 			{
    740 				transfer.removePropertyChangeListener( transferPropertyChangeListener );
    741 			}
    742
    743 			transfer = getCurrentTransfer();
    744
    745 			if( transfer == null )
    746 			{
    747 				sourceArea.setText( "" );
    748 				targetArea.setText( "" );
    749
    750 				sourcePropertyCombo.removeAllItems();
    751 				targetPropertyCombo.removeAllItems();
    752
    753 				sourceStepCombo.setSelectedIndex( -1 );
    754 				targetStepCombo.setSelectedIndex( -1 );
    755 			}
    756 			else
    757 			{
    758 				transfer.addPropertyChangeListener( transferPropertyChangeListener );
    759
    760 				sourceArea.setText( transfer.getSourcePath() );
    761 				targetArea.setText( transfer.getTargetPath() );
    762
    763 				sourceStepCombo.setSelectedItem( transfer.getSourceStepName() );
    764 				sourcePropertyCombo.setSelectedItem( transfer.getSourcePropertyName() );
    765
    766 				targetStepCombo.setSelectedItem( transfer.getTargetStepName() );
    767 				targetPropertyCombo.setSelectedItem( transfer.getTargetPropertyName() );
    768
    769 				failTransferCheckBox.setSelected( transfer.getFailOnError() );
    770 				setNullCheckBox.setSelected( transfer.getSetNullOnMissingSource() );
    771 				transferTextContentCheckBox.setSelected( transfer.getTransferTextContent() );
    772 				ignoreEmptyCheckBox.setSelected( transfer.getIgnoreEmpty() );
    773 				transferAllCheckBox.setSelected( transfer.getTransferToAll() );
    774 			}
    775
    776 			copyButton.setEnabled( transfer != null );
    777 			renameButton.setEnabled( transfer != null );
    778 			deleteButton.setEnabled( transfer != null );
    779 			declareButton.setEnabled( transfer != null );
    780 			sourceStepCombo.setEnabled( transfer != null );
    781 			targetStepCombo.setEnabled( transfer != null );
    782 			sourceArea.setEnabled( transfer != null );
    783 			targetArea.setEnabled( transfer != null );
    784 			failTransferCheckBox.setEnabled( transfer != null );
    785 			setNullCheckBox.setEnabled( transfer != null );
    786 			transferTextContentCheckBox.setEnabled( transfer != null );
    787 			ignoreEmptyCheckBox.setEnabled( transfer != null );
    788 			transferAllCheckBox.setEnabled( transfer != null );
    789
    790 			runButton.setEnabled( transferList.getModel().getSize() > 0 );
    791
    792 			sourcePropertyCombo.setEnabled( transfer != null );
    793 			targetPropertyCombo.setEnabled( transfer != null );
    794
    795 			selecting = false;
    796 		}
    797 	}
    798
    799 	/***
    800 	 * Listen to property changes and update UI objects. These may have been triggered by UI so first check
    801 	 * for actual difference so we dont end up in loop.
    802 	 */
    803
    804 	private class TransferPropertyChangeListener implements PropertyChangeListener
    805 	{
    806 		public void propertyChange(PropertyChangeEvent evt)
    807 		{
    808 			Object newValue = evt.getNewValue();
    809
    810 			if( evt.getPropertyName().equals( PropertyTransfer.SOURCE_PATH_PROPERTY ))
    811 			{
    812 				if( !sourceArea.getText().equals( newValue ))
    813 					sourceArea.setText( (String) newValue );
    814 			}
    815 			else if( evt.getPropertyName().equals( PropertyTransfer.TARGET_PATH_PROPERTY ))
    816 			{
    817 				if( !targetArea.getText().equals( newValue ))
    818 					targetArea.setText( (String) newValue );
    819 			}
    820 			else if( evt.getPropertyName().equals( PropertyTransfer.SOURCE_STEP_PROPERTY ))
    821 			{
    822 				Object selectedItem = sourceStepCombo.getSelectedItem();
    823 				if( newValue == null || selectedItem == null || !selectedItem.equals( newValue ))
    824 				{
    825 					selecting = true;
    826 					sourceStepCombo.setSelectedItem( newValue );
    827 					selecting = false;
    828 				}
    829 			}
    830 			else if( evt.getPropertyName().equals( PropertyTransfer.TARGET_STEP_PROPERTY ))
    831 			{
    832 				Object selectedItem = targetStepCombo.getSelectedItem();
    833 				if( newValue == null || selectedItem == null || !selectedItem.equals( newValue ))
    834 				{
    835 					selecting = true;
    836 					targetStepCombo.setSelectedItem( newValue );
    837 					selecting = false;
    838 				}
    839 			}
    840 			else if( evt.getPropertyName().equals( PropertyTransfer.SOURCE_TYPE_PROPERTY ))
    841 			{
    842 				Object selectedItem = sourcePropertyCombo.getSelectedItem();
    843 				if( selectedItem == null || !selectedItem.equals( newValue ))
    844 					sourcePropertyCombo.setSelectedItem( newValue );
    845 			}
    846 			else if( evt.getPropertyName().equals( PropertyTransfer.TARGET_TYPE_PROPERTY ))
    847 			{
    848 				Object selectedItem = targetPropertyCombo.getSelectedItem();
    849 				if( selectedItem == null || !selectedItem.equals( newValue ))
    850 					targetPropertyCombo.setSelectedItem( newValue );
    851 			}
    852 		}
    853 	}
    854
    855 	private final class AddAction extends AbstractAction
    856 	{
    857 		public AddAction()
    858 		{
    859 			super( "Add" );
    860 			putValue( Action.SHORT_DESCRIPTION, "Adds a new Property Transfer" );
    861 		}
    862
    863 		public void actionPerformed(ActionEvent e)
    864 		{
    865 			String name = UISupport.prompt( "Specify name for value transfer", "Add Transfer", "" );
    866 			if( name == null || name.trim().length() == 0 ) return;
    867
    868 			transferStep.addTransfer( name );
    869
    870 			listModel.addElement( name );
    871 			transferList.setSelectedIndex( listModel.getSize()-1 );
    872 		}
    873 	}
    874
    875 	private final class CopyAction extends AbstractAction
    876 	{
    877 		public CopyAction()
    878 		{
    879 			super( "Copy" );
    880 			putValue( Action.SHORT_DESCRIPTION, "Copies the selected Property Transfer" );
    881 		}
    882
    883 		public void actionPerformed(ActionEvent e)
    884 		{
    885 			int ix = transferList.getSelectedIndex();
    886 			PropertyTransfer config = transferStep.getTransferAt( ix );
    887
    888 			String name = UISupport.prompt( "Specify name for value transfer", "Copy Transfer", config.getName() );
    889 			if( name == null || name.trim().length() == 0 ) return;
    890
    891 			PropertyTransfer transfer = transferStep.addTransfer( name );
    892 			transfer.setSourceStepName( config.getSourceStepName() );
    893 			transfer.setSourcePropertyName( config.getSourcePropertyName() );
    894 			transfer.setSourcePath( config.getSourcePath() );
    895 			transfer.setTargetStepName( config.getTargetStepName() );
    896 			transfer.setTargetPropertyName( config.getTargetPropertyName() );
    897 			transfer.setTargetPath( config.getTargetPath() );
    898
    899 			listModel.addElement( name );
    900 			transferList.setSelectedIndex( listModel.getSize()-1 );
    901 		}
    902 	}
    903
    904 	private final class DeleteAction extends AbstractAction
    905 	{
    906 		public DeleteAction()
    907 		{
    908 			super( "Delete" );
    909 			putValue( Action.SHORT_DESCRIPTION, "Deletes the selected Property Transfer" );
    910 		}
    911
    912 		public void actionPerformed(ActionEvent e)
    913 		{
    914 			if( UISupport.confirm( "Delete selected transfer", "Delete Transfer" ))
    915 			{
    916 				transferList.setSelectedIndex( -1 );
    917
    918 				int ix = transferList.getSelectedIndex();
    919 				transferStep.removeTransferAt( ix );
    920 				listModel.remove( ix );
    921
    922 				if( listModel.getSize() > 0 )
    923 				{
    924 					transferList.setSelectedIndex( ix > listModel.getSize()-1 ? listModel.getSize()-1 : ix );
    925 				}
    926 			}
    927 		}
    928 	}
    929
    930 	private final class RenameAction extends AbstractAction
    931 	{
    932 		public RenameAction()
    933 		{
    934 			super( "Rename" );
    935 			putValue( Action.SHORT_DESCRIPTION, "Renames the selected Property Transfer" );
    936 		}
    937
    938 		public void actionPerformed(ActionEvent e)
    939 		{
    940 			PropertyTransfer transfer = getCurrentTransfer();
    941
    942 			String newName = UISupport.prompt( "Specify new name for transfer", "Rename Transfer", transfer.getName() );
    943
    944 			if( newName != null && !transfer.getName().equals( newName ))
    945 			{
    946 				listModel.setElementAt( newName, transferList.getSelectedIndex() );
    947 				transfer.setName( newName );
    948 			}
    949 		}
    950 	}
    951
    952 	private final class DeclareNamespacesAction extends AbstractAction
    953 	{
    954 		public DeclareNamespacesAction()
    955 		{
    956 			super( "Declare" );
    957 			putValue( Action.SHORT_DESCRIPTION, "Declare available response/request namespaces in source/target expressions" );
    958 		}
    959
    960 		public void actionPerformed(ActionEvent e)
    961 		{
    962 			try
    963 			{
    964 				TestStep previousStep = getCurrentTransfer().getSourceStep();
    965
    966 				if ( previousStep instanceof WsdlTestRequestStep )
    967 				{
    968 					WsdlTestRequest testRequest = ((WsdlTestRequestStep)previousStep).getTestRequest();
    969 					sourceArea.setText( XmlUtils.declareXPathNamespaces( testRequest.getOperation().getInterface() ) + sourceArea.getText() );
    970 				}
    971 				else UISupport.showErrorMessage( "Source step is not a request" );
    972
    973 				TestStep nextStep = getCurrentTransfer().getTargetStep();
    974
    975 				if (nextStep instanceof WsdlTestRequestStep)
    976 				{
    977 					WsdlTestRequest testRequest = ((WsdlTestRequestStep)nextStep).getTestRequest();
    978 					targetArea.setText( XmlUtils.declareXPathNamespaces( testRequest.getOperation().getInterface()) + targetArea.getText() );
    979 				}
    980 				else UISupport.showErrorMessage( "Target step is not a request" );
    981 			}
    982 			catch (Exception e1)
    983 			{
    984 				UISupport.showErrorMessage( e1 );
    985 			}
    986 		}
    987 	}
    988
    989 	private final class RunAction extends AbstractAction
    990 	{
    991 		public RunAction()
    992 		{
    993 			super( "Run" );
    994 			putValue( Action.SHORT_DESCRIPTION, "Runs all Property Transfers" );
    995 		}
    996
    997 		public void actionPerformed(ActionEvent e)
    998 		{
    999 			if( listModel.getSize() == 0 )
    1000 			{
    1001 				UISupport.showErrorMessage( "Missing transfers!" );
    1002 				return;
    1003 			}
    1004
    1005 			WsdlTestRunContext context = new WsdlTestRunContext( transferStep );
    1006 			ValueTransferResult result = (ValueTransferResult) transferStep.run( null, context );
    1007
    1008 			if( resultDesktopPanel != null )
    1009 				SoapUI.getDesktop().closeDesktopPanel( resultDesktopPanel );
    1010
    1011 			ShowTransferValuesResultsAction action = new ShowTransferValuesResultsAction( result );
    1012 			resultDesktopPanel = action.showDesktopPanel();
    1013 		}
    1014 	}
    1015
    1016 	public ModelItem getModelItem()
    1017 	{
    1018 		return transferStep;
    1019 	}
    1020
    1021 	public boolean onClose( boolean canCancel )
    1022 	{
    1023 		transferStep.getTestCase().getTestSuite().removeTestSuiteListener( testSuiteListener );
    1024
    1025 		PropertyTransfer transfer = getCurrentTransfer();
    1026
    1027 		if( transfer != null )
    1028 		{
    1029 			transfer.removePropertyChangeListener( transferPropertyChangeListener );
    1030 		}
    1031
    1032 		for( int c = 0; c < transferStep.getTestCase().getTestStepCount(); c++ )
    1033 		{
    1034 			WsdlTestStep testStep = (WsdlTestStep) transferStep.getTestCase().getTestStepAt( c );
    1035
    1036 			testStep.removePropertyChangeListener( TestStep.NAME_PROPERTY, sourceTestStepNameListener);
    1037 			testStep.removePropertyChangeListener( TestStep.NAME_PROPERTY, targetStepNameListener);
    1038 		}
    1039
    1040 		Object item = sourceStepCombo.getSelectedItem();
    1041 		if( item != null )
    1042 		{
    1043 			WsdlTestStep step = (WsdlTestStep) transferStep.getTestCase().getTestStepByName( (String) item );
    1044 			if( step != null )
    1045 				step.removeTestStepListener( sourceStepPropertiesListener );
    1046 		}
    1047
    1048 		item = targetStepCombo.getSelectedItem();
    1049 		if( item != null )
    1050 		{
    1051 			WsdlTestStep step = (WsdlTestStep) transferStep.getTestCase().getTestStepByName( (String) item );
    1052 			if( step != null )
    1053 				step.removeTestStepListener( targetStepPropertiesListener );
    1054 		}
    1055
    1056 		componentEnabler.release();
    1057 		if( resultDesktopPanel != null )
    1058 			SoapUI.getDesktop().closeDesktopPanel( resultDesktopPanel );
    1059
    1060 		return true;
    1061 	}
    1062
    1063 	public JComponent getComponent()
    1064 	{
    1065 		return this;
    1066 	}
    1067
    1068 	public boolean dependsOn(ModelItem modelItem)
    1069 	{
    1070 		return modelItem == transferStep || modelItem == transferStep.getTestCase() ||
    1071 				modelItem == transferStep.getTestCase().getTestSuite() ||
    1072 				modelItem == transferStep.getTestCase().getTestSuite().getProject();
    1073 	}
    1074
    1075 	public String getTitle()
    1076 	{
    1077 		return transferStep.getTestCase().getName() + " - " +  transferStep.getName();
    1078 	}
    1079
    1080 	public String getDescription()
    1081 	{
    1082 		return "Property Transfer: [" + transferStep.getName() + "] - " + transferStep.getTestStepTitle();
    1083 	}
    1084
    1085 	public Icon getIcon()
    1086 	{
    1087 		return getModelItem().getIcon();
    1088 	}
    1089
    1090 	public boolean selectTransfer(PropertyTransfer transfer)
    1091 	{
    1092 		for( int c = 0; c < transferStep.getTransferCount(); c++ )
    1093 		{
    1094 			if( transferStep.getTransferAt( c ) == transfer )
    1095 			{
    1096 				transferList.setSelectedIndex( c );
    1097 				return true;
    1098 			}
    1099 		}
    1100
    1101 		return false;
    1102 	}
    1103 }