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.teststeps;
    14
    15  import java.beans.PropertyChangeEvent;
    16  import java.beans.PropertyChangeListener;
    17  import java.beans.PropertyChangeSupport;
    18  import java.util.ArrayList;
    19  import java.util.List;
    20
    21  import org.apache.log4j.Logger;
    22  import org.apache.xmlbeans.XmlCursor;
    23  import org.apache.xmlbeans.XmlException;
    24  import org.apache.xmlbeans.XmlObject;
    25  import org.apache.xmlbeans.XmlOptions;
    26  import org.w3c.dom.DocumentFragment;
    27  import org.w3c.dom.Element;
    28  import org.w3c.dom.Node;
    29
    30  import com.eviware.soapui.config.ValueTransferConfig;
    31  import com.eviware.soapui.impl.wsdl.submit.filters.PropertyExpansionRequestFilter;
    32  import com.eviware.soapui.model.iface.SubmitContext;
    33  import com.eviware.soapui.model.support.TestSuiteListenerAdapter;
    34  import com.eviware.soapui.model.testsuite.TestCase;
    35  import com.eviware.soapui.model.testsuite.TestStep;
    36  import com.eviware.soapui.model.testsuite.TestStepProperty;
    37  import com.eviware.soapui.support.PropertyChangeNotifier;
    38  import com.eviware.soapui.support.xml.XmlUtils;
    39
    40  /***
    41   * Class for transferring a property value between 2 test steps. This class is relatively complex due
    42   * to backwards compatibility issues and to gracefull handling of references test steps and properties.
    43   *
    44   * @author Ole.Matzura
    45   */
    46
    47  public class PropertyTransfer implements PropertyChangeNotifier
    48  {
    49  	private final static Logger log = Logger.getLogger( PropertyTransfer.class );
    50
    51  	public final static String SOURCE_PATH_PROPERTY = PropertyTransfer.class.getName() + "@sourcePath";
    52  	public final static String SOURCE_TYPE_PROPERTY = PropertyTransfer.class.getName() + "@sourceProperty";
    53  	public final static String SOURCE_STEP_PROPERTY = PropertyTransfer.class.getName() + "@sourceStep";
    54  	public final static String TARGET_PATH_PROPERTY = PropertyTransfer.class.getName() + "@targetPath";
    55  	public final static String TARGET_TYPE_PROPERTY = PropertyTransfer.class.getName() + "@targetProperty";
    56  	public final static String TARGET_STEP_PROPERTY = PropertyTransfer.class.getName() + "@targetStep";
    57  	public final static String NAME_PROPERTY = PropertyTransfer.class.getName() + "@name";
    58  	public final static String CONFIG_PROPERTY = PropertyTransfer.class.getName() + "@config";
    59
    60  	private TestStep testStep;
    61
    62  	// create local copies since a deleted/changed valuetransfer can be referred to from a result
    63  	private ValueTransferConfig config;
    64  	private String sourcePath;
    65  	private String sourceType;
    66  	private String targetPath;
    67  	private String name;
    68  	private String targetType;
    69  	private String sourceStep;
    70  	private String targetStep;
    71
    72  	private TestStep currentTargetStep;
    73  	private TestStep currentSourceStep;
    74  	private TestStepProperty currentTargetProperty;
    75  	private TestStepProperty currentSourceProperty;
    76
    77  	private PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport( this );
    78  	private StepNameChangeListener stepNameChangeListener = new StepNameChangeListener();
    79  	private PropertyNameChangeListener propertyNameChangeListener = new PropertyNameChangeListener();
    80  	private TestCase testCase;
    81
    82  	private InternalTestSuiteListener testSuiteListener = new InternalTestSuiteListener();
    83
    84  	public PropertyTransfer( TestStep testStep )
    85  	{
    86  		this( testStep, ValueTransferConfig.Factory.newInstance() );
    87  	}
    88
    89  	public PropertyTransfer( TestStep testStep, ValueTransferConfig config )
    90  	{
    91  		this.testStep = testStep;
    92
    93  		if( testStep != null )
    94  		{
    95  			this.testCase = testStep.getTestCase();
    96  			testCase.getTestSuite().addTestSuiteListener( testSuiteListener );
    97  		}
    98
    99  		setConfig( config );
    100 	}
    101
    102 	void setConfigOnMove( ValueTransferConfig config )
    103 	{
    104 		this.config = config;
    105 	}
    106
    107 	void setConfig(ValueTransferConfig config)
    108 	{
    109 		releaseListeners();
    110
    111 		this.config = config;
    112
    113 		if( !config.isSetSetNullOnMissingSource() )
    114 		{
    115 			config.setSetNullOnMissingSource( true );
    116 		}
    117
    118 		if( !config.isSetTransferTextContent() )
    119 		{
    120 			config.setTransferTextContent( true );
    121 		}
    122
    123 		sourceStep = config.getSourceStep();
    124 		if( sourceStep == null )
    125 		{
    126 			sourceStep = getSourceStepName();
    127 			if( sourceStep != null )
    128 				config.setSourceStep( sourceStep );
    129 		}
    130
    131 		currentSourceStep = (sourceStep == null || testCase == null ) ? null : testCase.getTestStepByName( sourceStep );
    132
    133 		sourceType = config.getSourceType();
    134 		currentSourceProperty = currentSourceStep == null || sourceType == null ? null : currentSourceStep.getProperty( sourceType );
    135
    136 		sourcePath = config.getSourcePath();
    137
    138 		targetStep = config.getTargetStep();
    139 		if( targetStep == null )
    140 		{
    141 			targetStep = getTargetStepName();
    142 			if( targetStep != null )
    143 				config.setTargetStep( targetStep );
    144 		}
    145
    146 		currentTargetStep = (targetStep == null || testCase == null ) ? null : testCase.getTestStepByName( targetStep );
    147
    148 		targetType = config.getTargetType();
    149 		currentTargetProperty = currentTargetStep == null || targetType == null ? null : currentTargetStep.getProperty( targetType );
    150
    151 		targetPath = config.getTargetPath();
    152
    153 		name = config.getName();
    154 		initListeners();
    155
    156 		propertyChangeSupport.firePropertyChange( CONFIG_PROPERTY, null, null );
    157 	}
    158
    159 	private void initListeners()
    160 	{
    161 		if( currentSourceStep != null )
    162 		{
    163 			currentSourceStep.addPropertyChangeListener( TestStep.NAME_PROPERTY, stepNameChangeListener );
    164 			((WsdlTestStep)currentSourceStep).addTestStepListener( propertyNameChangeListener );
    165 		}
    166
    167 		if( currentTargetStep != null )
    168 		{
    169 			currentTargetStep.addPropertyChangeListener( TestStep.NAME_PROPERTY, stepNameChangeListener );
    170 			((WsdlTestStep)currentTargetStep).addTestStepListener( propertyNameChangeListener );
    171 		}
    172 	}
    173
    174 	public void releaseListeners()
    175 	{
    176 		if( currentSourceStep != null )
    177 		{
    178 			currentSourceStep.removePropertyChangeListener( TestStep.NAME_PROPERTY, stepNameChangeListener );
    179 			((WsdlTestStep)currentSourceStep).removeTestStepListener( propertyNameChangeListener );
    180 		}
    181
    182 		if( currentTargetStep != null )
    183 		{
    184 			currentTargetStep.removePropertyChangeListener( TestStep.NAME_PROPERTY, stepNameChangeListener );
    185 			((WsdlTestStep)currentTargetStep).removeTestStepListener( propertyNameChangeListener );
    186 		}
    187
    188 		PropertyChangeListener[] listeners = propertyChangeSupport.getPropertyChangeListeners();
    189 		for( PropertyChangeListener listener : listeners )
    190 			propertyChangeSupport.removePropertyChangeListener( listener );
    191 	}
    192
    193 	public void release()
    194 	{
    195 		releaseListeners();
    196 		testCase.getTestSuite().removeTestSuiteListener( testSuiteListener );
    197 	}
    198
    199 	public ValueTransferConfig getConfig()
    200 	{
    201 		return config;
    202 	}
    203
    204 	public String getSourcePath()
    205 	{
    206 		return sourcePath;
    207 	}
    208
    209 	public String getTargetPath()
    210 	{
    211 		return targetPath;
    212 	}
    213
    214 	public TestStepProperty getSourceProperty()
    215 	{
    216 		if( sourceType == null )
    217 			return null;
    218
    219 		if( currentSourceProperty != null )
    220 			return currentSourceProperty;
    221
    222 		TestStep actualSourceStep = getSourceStep();
    223 		return actualSourceStep == null ? null : actualSourceStep.getProperty( sourceType );
    224 	}
    225
    226 	public String [] transferProperties(SubmitContext context) throws PropertyTransferException
    227 	{
    228 		TestStepProperty sourceProperty = getSourceProperty();
    229 		TestStepProperty targetProperty = getTargetProperty();
    230
    231 		try
    232 		{
    233 			if (sourceProperty == null)
    234 				throw new Exception("Missing source property");
    235 			if (targetProperty == null)
    236 				throw new Exception("Missing target property");
    237 			if (sourceProperty.getValue() == null && !getSetNullOnMissingSource() && !getIgnoreEmpty() )
    238 				throw new Exception("Source property is null");
    239
    240 			if (!hasSourcePath() && !hasTargetPath())
    241 			{
    242 				if( !getIgnoreEmpty() || (sourceProperty.getValue() != null && sourceProperty.getValue().length() > 0))
    243 					return transferStringToString(sourceProperty, targetProperty);
    244 			}
    245 			else if (hasSourcePath() && hasTargetPath())
    246 			{
    247 					return transferXmlToXml(sourceProperty, targetProperty, context);
    248 			}
    249 			else if (hasSourcePath() && !hasTargetPath())
    250 			{
    251 				return new String[] { transferXmlToString(sourceProperty, targetProperty, context) };
    252 			}
    253 			else if (!hasSourcePath() && hasTargetPath())
    254 			{
    255 				if( !getIgnoreEmpty() || (sourceProperty.getValue() != null && sourceProperty.getValue().length() > 0))
    256 					return transferStringToXml(sourceProperty, targetProperty, context);
    257 			}
    258 		}
    259 		catch (Exception e)
    260 		{
    261 			throw new PropertyTransferException( e.toString(), getSourceStepName(), sourceProperty,
    262 					getTargetStepName(), targetProperty );
    263 		}
    264
    265 		return new String[0];
    266 	}
    267
    268 	private boolean hasTargetPath()
    269 	{
    270 		String path = getTargetPath();
    271 		return path != null && path.trim().length() > 0 ;
    272 	}
    273
    274 	private boolean hasSourcePath()
    275 	{
    276 		String path = getSourcePath();
    277 		return path != null && path.trim().length() > 0 ;
    278 	}
    279
    280 	protected String[] transferStringToString(TestStepProperty sourceProperty, TestStepProperty targetProperty)
    281 	{
    282 		String value = sourceProperty.getValue();
    283 		targetProperty.setValue( value );
    284 		return new String[]{ value};
    285 	}
    286
    287 	protected String[] transferXmlToXml( TestStepProperty sourceProperty, TestStepProperty targetProperty, SubmitContext context) throws XmlException, Exception
    288 	{
    289 		String sourcePropertyValue = sourceProperty.getValue();
    290 		XmlObject sourceXmlObject = XmlObject.Factory.parse( sourcePropertyValue );
    291 		XmlCursor sourceXml = sourceXmlObject.newCursor();
    292
    293 		String targetPropertyValue = targetProperty.getValue();
    294 		XmlObject targetXmlObject = XmlObject.Factory.parse( targetPropertyValue );
    295 		XmlCursor targetXml = targetXmlObject.newCursor();
    296
    297 		XmlCursor lastSource = null;
    298
    299 		try
    300 		{
    301 			List<String> result = new ArrayList<String>();
    302
    303 			targetXml.selectPath( PropertyExpansionRequestFilter.expandProperties( context, getTargetPath()) );
    304
    305 			if( !targetXml.hasNextSelection() )
    306 				throw new Exception( "Missing match for Target path [" + getTargetPath() + "]" );
    307
    308 			sourceXml.selectPath( PropertyExpansionRequestFilter.expandProperties( context, getSourcePath()) );
    309
    310 			if( !sourceXml.hasNextSelection() )
    311 			{
    312 				if( getSetNullOnMissingSource() )
    313 				{
    314 					while( targetXml.toNextSelection() )
    315 					{
    316 						result.add( setNodeValue( null, targetXml.getDomNode() ));
    317 						if( !getTransferToAll())
    318 							break;
    319 					}
    320 				}
    321 				else if( !getIgnoreEmpty() )
    322 					throw new Exception( "Missing match for Source path [" + getSourcePath() + "]" );
    323 			}
    324 			else
    325 			{
    326 				boolean hasSource = sourceXml.toNextSelection();
    327 				boolean hasTarget = targetXml.toNextSelection();
    328
    329 				while( hasSource && hasTarget )
    330 				{
    331 					if( lastSource != null )
    332 						lastSource.dispose();
    333
    334 					lastSource = sourceXml.newCursor();
    335 					result.add( transferXmlValue( sourceXml, targetXml ));
    336
    337 					hasSource = sourceXml.toNextSelection();
    338 					hasTarget = targetXml.toNextSelection();
    339 				}
    340
    341 				if( getTransferToAll() && !hasSource && hasTarget && lastSource != null )
    342 				{
    343 					while( hasTarget )
    344 					{
    345 						result.add( transferXmlValue( lastSource, targetXml ));
    346 						hasTarget = targetXml.toNextSelection();
    347 					}
    348 				}
    349 			}
    350
    351 			if( result.size() > 0 )
    352 			{
    353 				targetProperty.setValue( targetXmlObject.xmlText( new XmlOptions().setSaveAggressiveNamespaces()) );
    354 			}
    355
    356 			return result.toArray( new String[result.size()] );
    357 		}
    358 		finally
    359 		{
    360 			sourceXml.dispose();
    361 			targetXml.dispose();
    362
    363 			if( lastSource != null )
    364 				lastSource.dispose();
    365 		}
    366 	}
    367
    368 	protected String [] transferStringToXml(TestStepProperty sourceProperty, TestStepProperty targetProperty, SubmitContext context) throws XmlException, Exception
    369 	{
    370 		XmlObject targetXml = XmlObject.Factory.parse( targetProperty.getValue() );
    371 		XmlCursor targetCursor = targetXml.newCursor();
    372
    373 		try
    374 		{
    375 			List<String> result = new ArrayList<String>();
    376
    377 			targetCursor.selectPath( PropertyExpansionRequestFilter.expandProperties( context,
    378 					getTargetPath() ));
    379
    380 			if( !targetCursor.toNextSelection() )
    381 				throw new Exception( "Missing match for Target path [" + getTargetPath() + "]" );
    382
    383 			String value = sourceProperty.getValue();
    384
    385 			Node targetNode = targetCursor.getDomNode();
    386 			setNodeValue(value, targetNode);
    387
    388 			result.add( value );
    389
    390 			if( getTransferToAll() )
    391 			{
    392 				while( targetCursor.toNextSelection())
    393 				{
    394 					targetNode = targetCursor.getDomNode();
    395 					setNodeValue(value, targetNode);
    396
    397 					result.add( value );
    398 				}
    399 			}
    400
    401 			targetProperty.setValue( targetXml.xmlText( new XmlOptions().setSaveAggressiveNamespaces()) );
    402
    403 			return result.toArray( new String[result.size()] );
    404 		}
    405 		finally
    406 		{
    407 			targetCursor.dispose();
    408 		}
    409 	}
    410
    411 	private String setNodeValue(String value, Node node) throws Exception
    412 	{
    413 		short targetNodeType = node.getNodeType();
    414
    415 		if( targetNodeType == Node.DOCUMENT_FRAGMENT_NODE )
    416 		{
    417 			node = ((DocumentFragment) node ).getFirstChild();
    418 			if( node != null )
    419 				targetNodeType = node.getNodeType();
    420 			else
    421 				throw new Exception( "Missing source value for " + getSourcePropertyName() );
    422 		}
    423
    424 		if( targetNodeType == Node.TEXT_NODE || targetNodeType == Node.ATTRIBUTE_NODE )
    425 		{
    426 			node.setNodeValue( value );
    427 		}
    428 		else if( targetNodeType == Node.ELEMENT_NODE )
    429 		{
    430 			XmlUtils.setElementText( (Element) node, value );
    431 		}
    432 		else
    433 		{
    434 			throw new Exception( "Failed to set value to node [" + node.toString() + "] of type [" + targetNodeType + "]" );
    435 		}
    436
    437 		return value;
    438 	}
    439
    440 	protected String transferXmlToString( TestStepProperty sourceProperty, TestStepProperty targetProperty, SubmitContext context) throws XmlException, Exception
    441 	{
    442 		XmlObject sourceXml = XmlObject.Factory.parse( sourceProperty.getValue() );
    443 		XmlCursor sourceCursor = sourceXml.newCursor();
    444
    445 		try
    446 		{
    447 			String value = null;
    448
    449 			sourceCursor.selectPath( PropertyExpansionRequestFilter.expandProperties( context,
    450 					getSourcePath()) );
    451
    452 			if( !sourceCursor.toNextSelection() )
    453 			{
    454 				if( !getSetNullOnMissingSource() && !getIgnoreEmpty() )
    455 					throw new Exception( "Missing match for Source path [" + getSourcePath() + "]" );
    456 			}
    457 			else
    458 			{
    459 				Node sourceNode = sourceCursor.getDomNode();
    460 				short sourceNodeType = sourceNode.getNodeType();
    461
    462 				if( sourceNodeType == Node.DOCUMENT_FRAGMENT_NODE )
    463 				{
    464 					sourceNode = ((DocumentFragment) sourceNode ).getFirstChild();
    465 					if( sourceNode != null )
    466 						sourceNodeType = sourceNode.getNodeType();
    467 					else
    468 						throw new Exception( "Missing source value for " + getSourcePropertyName() );
    469 				}
    470
    471 				if( sourceNodeType == Node.TEXT_NODE || sourceNodeType == Node.ATTRIBUTE_NODE )
    472 				{
    473 					value = sourceNode.getNodeValue();
    474 				}
    475 				else if( sourceNodeType == Node.ELEMENT_NODE )
    476 				{
    477 					value = XmlUtils.getElementText( (Element) sourceNode );
    478 				}
    479 			}
    480
    481 			if( !getIgnoreEmpty() || (value != null && value.length() > 0) )
    482 				targetProperty.setValue( value );
    483 			else
    484 				value = "";
    485
    486 			return value;
    487 		}
    488 		finally
    489 		{
    490 			sourceCursor.dispose();
    491 		}
    492 	}
    493
    494 	/***
    495 	 * Method called for transferring between 2 xml properties..
    496 	 */
    497
    498 	private String transferXmlValue(XmlCursor source, XmlCursor dest) throws Exception
    499 	{
    500 		// just copy if nodes are of same type
    501 		Node destNode = dest.getDomNode();
    502 		Node sourceNode = source.getDomNode();
    503 		short destNodeType = destNode.getNodeType();
    504 		short sourceNodeType = sourceNode.getNodeType();
    505 		String value = null;
    506
    507 		if( sourceNodeType == Node.DOCUMENT_FRAGMENT_NODE )
    508 		{
    509 			sourceNode = ((DocumentFragment) sourceNode ).getFirstChild();
    510 			if( sourceNode != null )
    511 				sourceNodeType = sourceNode.getNodeType();
    512 			else
    513 				throw new Exception( "Missing source value for " + source );
    514 		}
    515
    516 		// same type of node?
    517 		if( destNodeType == sourceNodeType )
    518 		{
    519 			if( destNodeType == Node.TEXT_NODE || destNodeType == Node.ATTRIBUTE_NODE )
    520 			{
    521 				value = sourceNode.getNodeValue();
    522 				if( !getIgnoreEmpty() || (value != null && value.length() > 0) )
    523 					destNode.setNodeValue( value );
    524 			}
    525 			else if( config.getTransferTextContent() && destNodeType == Node.ELEMENT_NODE )
    526 			{
    527 				value = XmlUtils.getElementText( (Element) sourceNode);
    528 				if( !getIgnoreEmpty() || (value != null && value.length() > 0) )
    529 					XmlUtils.setElementText( (Element) destNode, value );
    530 			}
    531 			else
    532 			{
    533 				destNode = destNode.getParentNode().replaceChild(
    534 						destNode.getOwnerDocument().importNode( sourceNode, true ), destNode );
    535
    536 				value = dest.xmlText();
    537 			}
    538 		}
    539 		// text to attribute?
    540 		else if( (sourceNodeType == Node.TEXT_NODE && destNodeType == Node.ATTRIBUTE_NODE) ||
    541 				(sourceNodeType == Node.ATTRIBUTE_NODE && destNodeType == Node.TEXT_NODE) )
    542 		{
    543 			value = sourceNode.getNodeValue();
    544 			if( !getIgnoreEmpty() || (value != null && value.length() > 0) )
    545 				destNode.setNodeValue( value );
    546 		}
    547 		else if( sourceNodeType == Node.ELEMENT_NODE &&
    548 				destNodeType == Node.ATTRIBUTE_NODE || destNodeType == Node.TEXT_NODE )
    549 		{
    550 			value = XmlUtils.getElementText( (Element) sourceNode );
    551 			if( !getIgnoreEmpty() || (value != null && value.length() > 0) )
    552 				destNode.setNodeValue( value );
    553 		}
    554 		else if( destNodeType == Node.ELEMENT_NODE &&
    555 				sourceNodeType == Node.ATTRIBUTE_NODE || sourceNodeType == Node.TEXT_NODE )
    556 		{
    557 			// hmm.. not sure xmlbeans handles this ok
    558 			value = sourceNode.getNodeValue();
    559 			if( !getIgnoreEmpty() || (value != null && value.length() > 0) )
    560 				XmlUtils.setElementText( (Element) destNode, value );
    561 		}
    562
    563 		return value;
    564 	}
    565
    566 	/***
    567 	 * Returns the name of the source property.
    568 	 */
    569
    570 	public String getSourcePropertyName()
    571 	{
    572 		if( sourceType == null )
    573 			return null;
    574
    575 		if( currentSourceProperty != null )
    576 			return currentSourceProperty.getName();
    577
    578 		TestStep actualSourceStep = getSourceStep();
    579 		if( actualSourceStep == null )
    580 			return sourceType;
    581
    582 		TestStepProperty property = actualSourceStep.getProperty( sourceType );
    583 		return property == null ? sourceType : property.getName();
    584 	}
    585
    586 	public void setSourcePropertyName( String name )
    587 	{
    588 		String old = getSourcePropertyName();
    589
    590 		// check for change
    591 		if( (name == null && old == null) || (name != null && old != null && name.equals( old ))) return;
    592
    593 		// update
    594 		sourceType = name;
    595 		config.setSourceType( name );
    596
    597 		// update actual property
    598 		TestStep sourceStep2 = getSourceStep();
    599 		currentSourceProperty = sourceStep2 != null && sourceType != null ?
    600 				sourceStep2.getProperty( sourceType ) : null;
    601
    602 		// notify!
    603 		propertyChangeSupport.firePropertyChange( SOURCE_TYPE_PROPERTY, old, name );
    604 	}
    605
    606 	public TestStepProperty getTargetProperty()
    607 	{
    608 		if( targetType == null )
    609 			return null;
    610
    611 		if( currentTargetProperty != null )
    612 			return currentTargetProperty;
    613
    614 		TestStep actualTargetStep = getTargetStep();
    615 		return actualTargetStep == null ? null : actualTargetStep.getProperty( targetType );
    616 	}
    617
    618 	public String getTargetPropertyName()
    619 	{
    620 		if( targetType == null )
    621 			return null;
    622
    623 		if( currentTargetProperty != null )
    624 			return currentTargetProperty.getName();
    625
    626 		TestStep actualTargetStep = getTargetStep();
    627 		TestStepProperty property = actualTargetStep == null ? null : actualTargetStep.getProperty( targetType );
    628 		return actualTargetStep == null || property == null ? targetType: property.getName();
    629 	}
    630
    631 	public void setTargetPropertyName( String name )
    632 	{
    633 		String old = getTargetPropertyName();
    634
    635 		// check for change
    636 		if( (name == null && old == null) || (name != null && old != null && name.equals( old ))) return;
    637
    638 		// update
    639 		targetType = name;
    640 		config.setTargetType( name );
    641
    642 		// update actual property
    643 		TestStep targetStep2 = getTargetStep();
    644
    645 		currentTargetProperty = targetStep2 != null && targetType != null ?
    646 				targetStep2.getProperty( targetType ) : null;
    647
    648 		// notify!
    649 		propertyChangeSupport.firePropertyChange( TARGET_TYPE_PROPERTY, old, name );
    650 	}
    651
    652 	public String getName()
    653 	{
    654 		return config.getName();
    655 	}
    656
    657 	public void setSourcePath( String path )
    658 	{
    659 		String old = sourcePath;
    660 		sourcePath = path;
    661 		config.setSourcePath( path );
    662 		propertyChangeSupport.firePropertyChange( SOURCE_PATH_PROPERTY, old, path );
    663 	}
    664
    665 	public void setTargetPath( String path )
    666 	{
    667 		String old = targetPath;
    668 		targetPath = path;
    669 		config.setTargetPath( path );
    670 		propertyChangeSupport.firePropertyChange( TARGET_PATH_PROPERTY, old, path );
    671 	}
    672
    673 	public void setName( String name )
    674 	{
    675 		String old = this.name;
    676 		this.name = name;
    677 		config.setName( name );
    678 		propertyChangeSupport.firePropertyChange( NAME_PROPERTY, old, name );
    679 	}
    680
    681 	public TestStep getSourceStep()
    682 	{
    683 		String sourceStepName = getSourceStepName();
    684 		return sourceStepName == null ? null : testCase.getTestStepByName( sourceStepName );
    685 	}
    686
    687 	public String getSourceStepName()
    688 	{
    689 		if( sourceStep != null )
    690 			return sourceStep;
    691
    692 		if( testCase == null )
    693 			return null;
    694
    695 		TestStep step = testCase.findPreviousStepOfType( this.testStep, WsdlTestRequestStep.class );
    696 		return step == null ? null : step.getName();
    697 	}
    698
    699 	public void setSourceStepName(String sourceStep)
    700 	{
    701 		String old = getSourceStepName();
    702
    703 		//	 check for change
    704 		if( (sourceStep == null && old == null) || (sourceStep != null && old != null && sourceStep.equals( old ))) return;
    705
    706 		if( sourceStep == null )
    707 			log.debug( "Setting sourceStep for transfer [" + getName() + "] to null" );
    708
    709 		this.sourceStep = sourceStep;
    710 		config.setSourceStep( sourceStep );
    711
    712 		if( currentSourceStep != null )
    713 		{
    714 			currentSourceStep.removePropertyChangeListener( stepNameChangeListener );
    715 			((WsdlTestStep)currentSourceStep).removeTestStepListener( propertyNameChangeListener );
    716 		}
    717
    718 		currentSourceStep = (WsdlTestStep) (sourceStep == null ? null : testStep.getTestCase().getTestStepByName( sourceStep ));
    719 		if( currentSourceStep != null )
    720 		{
    721 			currentSourceStep.addPropertyChangeListener( TestStep.NAME_PROPERTY, stepNameChangeListener );
    722 			((WsdlTestStep)currentSourceStep).addTestStepListener( propertyNameChangeListener );
    723 		}
    724
    725 		propertyChangeSupport.firePropertyChange( SOURCE_STEP_PROPERTY, old, sourceStep );
    726 		setSourcePropertyName( null );
    727 	}
    728
    729 	public TestStep getTargetStep()
    730 	{
    731 		String targetStepName = getTargetStepName();
    732 		return targetStepName == null ? null : testCase.getTestStepByName( targetStepName );
    733 	}
    734
    735 	public String getTargetStepName()
    736 	{
    737 		if( targetStep != null )
    738 			return targetStep;
    739
    740 		if( testCase == null )
    741 			return null;
    742
    743 		TestStep step = testCase.findNextStepOfType( this.testStep, WsdlTestRequestStep.class );
    744 		return step == null ? null : step.getName();
    745 	}
    746
    747 	public void setTargetStepName(String targetStep)
    748 	{
    749 		String old = getTargetStepName();
    750
    751 		//	 check for change
    752 		if( (targetStep == null && old == null) || (targetStep != null && old != null && targetStep.equals( old ))) return;
    753
    754 		if( targetStep == null )
    755 			log.debug( "Setting targetStep for transfer [" + getName() + "] to null" );
    756
    757 		this.targetStep = targetStep;
    758 		config.setTargetStep( targetStep );
    759
    760 		if( currentTargetStep != null )
    761 		{
    762 			currentTargetStep.removePropertyChangeListener( stepNameChangeListener );
    763 			((WsdlTestStep)currentTargetStep).removeTestStepListener( propertyNameChangeListener );
    764 		}
    765
    766 		currentTargetStep = (WsdlTestStep) (targetStep == null ? null : testStep.getTestCase().getTestStepByName( targetStep ));
    767 		if( currentTargetStep != null )
    768 		{
    769 			currentTargetStep.addPropertyChangeListener( TestStep.NAME_PROPERTY, stepNameChangeListener );
    770 			((WsdlTestStep)currentTargetStep).addTestStepListener( propertyNameChangeListener );
    771 		}
    772
    773 		propertyChangeSupport.firePropertyChange( TARGET_STEP_PROPERTY, old, targetStep );
    774 		setTargetPropertyName( null );
    775 	}
    776
    777 	public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener)
    778 	{
    779 		propertyChangeSupport.addPropertyChangeListener( propertyName, listener );
    780 	}
    781
    782 	public void addPropertyChangeListener(PropertyChangeListener listener)
    783 	{
    784 		propertyChangeSupport.addPropertyChangeListener( listener );
    785 	}
    786
    787 	public void removePropertyChangeListener(PropertyChangeListener listener)
    788 	{
    789 		propertyChangeSupport.removePropertyChangeListener( listener );
    790 	}
    791
    792 	public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener)
    793 	{
    794 		propertyChangeSupport.removePropertyChangeListener( propertyName, listener );
    795 	}
    796
    797 	public boolean getFailOnError()
    798 	{
    799 		return config.getFailOnError();
    800 	}
    801
    802 	public void setFailOnError( boolean failOnError )
    803 	{
    804 		config.setFailOnError( failOnError );
    805 	}
    806
    807 	public boolean getTransferToAll()
    808 	{
    809 		return config.getTransferToAll();
    810 	}
    811
    812 	public void setTransferToAll( boolean transferToAll )
    813 	{
    814 		config.setTransferToAll( transferToAll );
    815 	}
    816
    817 	public boolean getIgnoreEmpty()
    818 	{
    819 		return config.getIgnoreEmpty();
    820 	}
    821
    822 	public void setIgnoreEmpty( boolean ignoreEmpty )
    823 	{
    824 		config.setIgnoreEmpty( ignoreEmpty );
    825 	}
    826
    827 	public boolean getSetNullOnMissingSource()
    828 	{
    829 		return config.getSetNullOnMissingSource();
    830 	}
    831
    832 	public void setSetNullOnMissingSource( boolean setNullOnMissingSource )
    833 	{
    834 		config.setSetNullOnMissingSource( setNullOnMissingSource );
    835 	}
    836
    837 	public boolean getTransferTextContent()
    838 	{
    839 		return config.getTransferTextContent();
    840 	}
    841
    842 	public void setTransferTextContent( boolean transferTextContent )
    843 	{
    844 		config.setTransferTextContent( transferTextContent );
    845 	}
    846
    847 	private final class InternalTestSuiteListener extends TestSuiteListenerAdapter
    848 	{
    849 		public void testStepRemoved(TestStep testStep, int index)
    850 		{
    851 			if( testStep.getTestCase() == testCase )
    852 			{
    853 				String stepName = testStep.getName();
    854 				if( stepName.equals( sourceStep ) )
    855 				{
    856 					setSourceStepName( null );
    857 				}
    858
    859 				if( stepName.equals( targetStep ) )
    860 				{
    861 					setTargetStepName( null );
    862 				}
    863 			}
    864 		}
    865 	}
    866
    867 	/***
    868 	 * Handle changes to source/target testStep names
    869 	 *
    870 	 * @author Ole.Matzura
    871 	 */
    872
    873 	private class StepNameChangeListener implements PropertyChangeListener
    874 	{
    875 		public void propertyChange(PropertyChangeEvent evt)
    876 		{
    877 			String oldName = (String) evt.getOldValue();
    878 			String newValue = (String) evt.getNewValue();
    879
    880 			if( newValue == null )
    881 			{
    882 				log.error( "Tried to change stepname to null!" );
    883 				Thread.dumpStack();
    884 				return;
    885 			}
    886
    887 			if( oldName.equals( sourceStep ))
    888 			{
    889 				sourceStep = newValue;
    890 				config.setSourceStep( sourceStep );
    891 				propertyChangeSupport.firePropertyChange( SOURCE_STEP_PROPERTY, oldName, sourceStep );
    892 			}
    893
    894 			if( oldName.equals( targetStep ))
    895 			{
    896 				targetStep = newValue;
    897 				config.setTargetStep( targetStep );
    898 				propertyChangeSupport.firePropertyChange( TARGET_STEP_PROPERTY, oldName, targetStep );
    899 			}
    900 		}
    901 	}
    902
    903 	/***
    904 	 * Handle changes to source/target property names
    905 	 *
    906 	 * @author Ole.Matzura
    907 	 */
    908
    909 	private class PropertyNameChangeListener extends WsdlTestStepListenerAdapter
    910 	{
    911 		public void propertyRenamed(String oldName, String newName)
    912 		{
    913 			if( oldName.equals( sourceType ))
    914 			{
    915 				sourceType = newName;
    916 				config.setSourceType( sourceType );
    917 				propertyChangeSupport.firePropertyChange( SOURCE_TYPE_PROPERTY, oldName, sourceType );
    918 			}
    919
    920 			if( oldName.equals( targetType ))
    921 			{
    922 				targetType = newName;
    923 				config.setTargetType( targetType );
    924 				propertyChangeSupport.firePropertyChange( TARGET_TYPE_PROPERTY, oldName, targetType );
    925 			}
    926 		}
    927
    928 		public void propertyRemoved(String name)
    929 		{
    930 			if( name.equals( sourceType ))
    931 			{
    932 				log.warn( "source property for transfer [" + getName() + "] in teststep [" +
    933 						testStep.getName() + "] set to null, was [" + name + "]" );
    934
    935 				setSourcePropertyName( null );
    936 			}
    937
    938 			if( name.equals( targetType ))
    939 			{
    940 				log.warn( "target property for transfer [" + getName() + "] in teststep [" +
    941 						testStep.getName() + "] set to null, was [" + name + "]" );
    942
    943 				setTargetPropertyName( null );
    944 			}
    945 		}
    946 	}
    947 }