1
2
3
4
5
6
7
8
9
10
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.apache.xmlbeans.XmlCursor.TokenType;
27 import org.w3c.dom.Element;
28 import org.w3c.dom.Node;
29 import org.w3c.dom.NodeList;
30
31 import com.eviware.soapui.config.PropertyTransferConfig;
32 import com.eviware.soapui.impl.support.http.HttpRequestTestStep;
33 import com.eviware.soapui.model.TestPropertyHolder;
34 import com.eviware.soapui.model.iface.SubmitContext;
35 import com.eviware.soapui.model.propertyexpansion.PropertyExpander;
36 import com.eviware.soapui.model.propertyexpansion.PropertyExpansion;
37 import com.eviware.soapui.model.propertyexpansion.PropertyExpansionUtils;
38 import com.eviware.soapui.model.support.TestPropertyListenerAdapter;
39 import com.eviware.soapui.model.support.TestSuiteListenerAdapter;
40 import com.eviware.soapui.model.testsuite.TestCase;
41 import com.eviware.soapui.model.testsuite.TestProperty;
42 import com.eviware.soapui.model.testsuite.TestStep;
43 import com.eviware.soapui.support.PropertyChangeNotifier;
44 import com.eviware.soapui.support.resolver.ChooseAnotherPropertySourceResolver;
45 import com.eviware.soapui.support.resolver.ChooseAnotherPropertyTargetResolver;
46 import com.eviware.soapui.support.resolver.CreateMissingPropertyResolver;
47 import com.eviware.soapui.support.resolver.DisablePropertyTransferResolver;
48 import com.eviware.soapui.support.resolver.ResolveContext;
49 import com.eviware.soapui.support.resolver.ResolveContext.PathToResolve;
50 import com.eviware.soapui.support.xml.XmlUtils;
51
52 /***
53 * Class for transferring a property value between 2 test steps. This class is
54 * relatively complex due to backwards compatibility issues and to gracefull
55 * handling of references test steps and properties.
56 *
57 * @author Ole.Matzura
58 */
59
60 public class PropertyTransfer implements PropertyChangeNotifier
61 {
62 private final static Logger log = Logger.getLogger( PropertyTransfer.class );
63
64 public final static String SOURCE_PATH_PROPERTY = PropertyTransfer.class.getName() + "@sourcePath";
65 public final static String SOURCE_TYPE_PROPERTY = PropertyTransfer.class.getName() + "@sourceProperty";
66 public final static String SOURCE_STEP_PROPERTY = PropertyTransfer.class.getName() + "@sourceStep";
67 public final static String TARGET_PATH_PROPERTY = PropertyTransfer.class.getName() + "@targetPath";
68 public final static String TARGET_TYPE_PROPERTY = PropertyTransfer.class.getName() + "@targetProperty";
69 public final static String TARGET_STEP_PROPERTY = PropertyTransfer.class.getName() + "@targetStep";
70 public final static String NAME_PROPERTY = PropertyTransfer.class.getName() + "@name";
71 public final static String DISABLED_PROPERTY = PropertyTransfer.class.getName() + "@disabled";
72 public final static String CONFIG_PROPERTY = PropertyTransfer.class.getName() + "@config";
73
74 private TestStep testStep;
75
76
77
78 private PropertyTransferConfig config;
79 private String sourcePath;
80 private String sourceType;
81 private String targetPath;
82 private String name;
83 private String targetType;
84 private String sourceStep;
85 private String targetStep;
86
87 private TestPropertyHolder currentTargetStep;
88 private TestPropertyHolder currentSourceStep;
89 private TestProperty currentTargetProperty;
90 private TestProperty currentSourceProperty;
91
92 private PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport( this );
93 private StepNameChangeListener stepNameChangeListener = new StepNameChangeListener();
94 private InternalTestPropertyListener propertyNameChangeListener = new InternalTestPropertyListener();
95 private TestCase testCase;
96
97 private InternalTestSuiteListener testSuiteListener = new InternalTestSuiteListener();
98
99 public PropertyTransfer( TestStep testStep )
100 {
101 this( testStep, PropertyTransferConfig.Factory.newInstance() );
102 }
103
104 public PropertyTransfer( TestStep testStep, PropertyTransferConfig config )
105 {
106 this.testStep = testStep;
107
108 if( testStep != null )
109 {
110 this.testCase = testStep.getTestCase();
111 testCase.getTestSuite().addTestSuiteListener( testSuiteListener );
112 }
113
114 setConfig( config );
115 }
116
117 void setConfigOnMove( PropertyTransferConfig config )
118 {
119 this.config = config;
120 }
121
122 void setConfig( PropertyTransferConfig config )
123 {
124 releaseListeners();
125
126 this.config = config;
127
128 if( !config.isSetSetNullOnMissingSource() )
129 {
130 config.setSetNullOnMissingSource( true );
131 }
132
133 if( !config.isSetTransferTextContent() )
134 {
135 config.setTransferTextContent( true );
136 }
137
138 sourceStep = config.getSourceStep();
139 if( sourceStep == null )
140 {
141 sourceStep = getSourceStepName();
142 if( sourceStep != null )
143 config.setSourceStep( sourceStep );
144 }
145
146 currentSourceStep = getPropertyHolder( sourceStep );
147
148 sourceType = config.getSourceType();
149 currentSourceProperty = currentSourceStep == null || sourceType == null ? null : currentSourceStep
150 .getProperty( sourceType );
151
152 sourcePath = config.getSourcePath();
153
154 targetStep = config.getTargetStep();
155 if( targetStep == null )
156 {
157 targetStep = getTargetStepName();
158 if( targetStep != null )
159 config.setTargetStep( targetStep );
160 }
161
162 currentTargetStep = getPropertyHolder( targetStep );
163
164 targetType = config.getTargetType();
165 currentTargetProperty = currentTargetStep == null || targetType == null ? null : currentTargetStep
166 .getProperty( targetType );
167
168 targetPath = config.getTargetPath();
169
170 name = config.getName();
171 initListeners();
172
173 propertyChangeSupport.firePropertyChange( CONFIG_PROPERTY, null, null );
174 }
175
176 private void initListeners()
177 {
178 if( currentSourceStep != null )
179 {
180 if( currentSourceStep instanceof TestStep )
181 ( ( TestStep )currentSourceStep )
182 .addPropertyChangeListener( TestStep.NAME_PROPERTY, stepNameChangeListener );
183
184 currentSourceStep.addTestPropertyListener( propertyNameChangeListener );
185 }
186
187 if( currentTargetStep != null )
188 {
189 if( currentTargetStep instanceof TestStep )
190 ( ( TestStep )currentTargetStep )
191 .addPropertyChangeListener( TestStep.NAME_PROPERTY, stepNameChangeListener );
192
193 currentTargetStep.addTestPropertyListener( propertyNameChangeListener );
194 }
195 }
196
197 public void releaseListeners()
198 {
199 if( currentSourceStep != null )
200 {
201 if( currentSourceStep instanceof TestStep )
202 ( ( TestStep )currentSourceStep ).removePropertyChangeListener( TestStep.NAME_PROPERTY,
203 stepNameChangeListener );
204
205 currentSourceStep.removeTestPropertyListener( propertyNameChangeListener );
206 }
207
208 if( currentTargetStep != null )
209 {
210 if( currentTargetStep instanceof TestStep )
211 ( ( TestStep )currentTargetStep ).removePropertyChangeListener( TestStep.NAME_PROPERTY,
212 stepNameChangeListener );
213
214 currentTargetStep.removeTestPropertyListener( propertyNameChangeListener );
215 }
216
217 PropertyChangeListener[] listeners = propertyChangeSupport.getPropertyChangeListeners();
218 for( PropertyChangeListener listener : listeners )
219 propertyChangeSupport.removePropertyChangeListener( listener );
220 }
221
222 public void release()
223 {
224 releaseListeners();
225 testCase.getTestSuite().removeTestSuiteListener( testSuiteListener );
226 }
227
228 public PropertyTransferConfig getConfig()
229 {
230 return config;
231 }
232
233 public String getSourcePath()
234 {
235 return sourcePath;
236 }
237
238 public String getTargetPath()
239 {
240 return targetPath;
241 }
242
243 public TestProperty getSourceProperty()
244 {
245 if( sourceType == null )
246 return null;
247
248 if( currentSourceProperty != null )
249 return currentSourceProperty;
250
251 TestPropertyHolder actualSourceStep = getSourceStep();
252 return actualSourceStep == null ? null : actualSourceStep.getProperty( sourceType );
253 }
254
255 public String[] transferProperties( SubmitContext context ) throws PropertyTransferException
256 {
257 TestProperty sourceProperty = getSourceProperty();
258 TestProperty targetProperty = getTargetProperty();
259
260 try
261 {
262 if( sourceProperty == null )
263 throw new Exception( "Missing source property" );
264 if( targetProperty == null )
265 throw new Exception( "Missing target property" );
266 if( sourceProperty.getValue() == null && !getSetNullOnMissingSource() && !getIgnoreEmpty() )
267 throw new Exception( "Source property is null" );
268
269 if( !hasSourcePath() && !hasTargetPath() )
270 {
271 if( !getIgnoreEmpty() || ( sourceProperty.getValue() != null && sourceProperty.getValue().length() > 0 ) )
272 return transferStringToString( sourceProperty, targetProperty );
273 }
274 else if( hasSourcePath() && hasTargetPath() )
275 {
276 return transferXPathToXml( sourceProperty, targetProperty, context );
277 }
278 else if( hasSourcePath() && !hasTargetPath() )
279 {
280 return new String[] { transferXPathToString( sourceProperty, targetProperty, context ) };
281 }
282 else if( !hasSourcePath() && hasTargetPath() )
283 {
284 if( !getIgnoreEmpty() || ( sourceProperty.getValue() != null && sourceProperty.getValue().length() > 0 ) )
285 return transferStringToXml( sourceProperty, targetProperty, context );
286 }
287 }
288 catch( Exception e )
289 {
290 throw new PropertyTransferException( e.getMessage(), getSourceStepName(), sourceProperty, getTargetStepName(),
291 targetProperty );
292 }
293
294 return new String[0];
295 }
296
297 private boolean hasTargetPath()
298 {
299 String path = getTargetPath();
300 return path != null && path.trim().length() > 0;
301 }
302
303 private boolean hasSourcePath()
304 {
305 String path = getSourcePath();
306 return path != null && path.trim().length() > 0;
307 }
308
309 protected String[] transferStringToString( TestProperty sourceProperty, TestProperty targetProperty )
310 {
311 String value = sourceProperty.getValue();
312
313 if( getEntitize() )
314 value = XmlUtils.entitize( value );
315
316 targetProperty.setValue( value );
317 return new String[] { value };
318 }
319
320 protected String[] transferXPathToXml( TestProperty sourceProperty, TestProperty targetProperty,
321 SubmitContext context ) throws Exception
322 {
323 String sourcePropertyValue = sourceProperty.getValue();
324 XmlObject sourceXmlObject = sourcePropertyValue == null ? null : XmlObject.Factory.parse( sourcePropertyValue );
325 XmlCursor sourceXml = sourceXmlObject == null ? null : sourceXmlObject.newCursor();
326
327 String targetPropertyValue = targetProperty.getValue();
328 XmlObject targetXmlObject = XmlObject.Factory.parse( targetPropertyValue );
329 XmlCursor targetXml = targetXmlObject.newCursor();
330
331 XmlCursor lastSource = null;
332
333 try
334 {
335 List<String> result = new ArrayList<String>();
336
337 String tp = PropertyExpander.expandProperties( context, getTargetPath() );
338 targetXml.selectPath( tp );
339
340 if( !targetXml.hasNextSelection() )
341 throw new Exception( "Missing match for Target XPath [" + tp + "]" );
342
343 if( sourceXml == null )
344 {
345 if( getSetNullOnMissingSource() )
346 {
347 while( targetXml.toNextSelection() )
348 {
349 result.add( setNodeValue( null, targetXml.getDomNode() ) );
350 if( !getTransferToAll() )
351 break;
352 }
353 }
354 }
355 else if( getUseXQuery() )
356 {
357 String sp = PropertyExpander.expandProperties( context, getSourcePath() );
358 XmlCursor resultCursor = sourceXml.execQuery( sp );
359 sourceXml.dispose();
360 sourceXml = resultCursor;
361
362 if( sourceXml.toNextToken() != TokenType.START )
363 {
364 if( getSetNullOnMissingSource() )
365 {
366 while( targetXml.toNextSelection() )
367 {
368 result.add( setNodeValue( null, targetXml.getDomNode() ) );
369 if( !getTransferToAll() )
370 break;
371 }
372 }
373 else if( !getIgnoreEmpty() )
374 throw new Exception( "Missing match for Source XQuery [" + sp + "]" );
375 }
376
377 boolean hasTarget = targetXml.toNextSelection();
378
379 if( hasTarget )
380 {
381 lastSource = sourceXml.newCursor();
382 result.add( transferXmlValue( sourceXml, targetXml ) );
383 }
384 }
385 else
386 {
387 String sp = PropertyExpander.expandProperties( context, getSourcePath() );
388 sourceXml.selectPath( sp );
389
390 if( !sourceXml.hasNextSelection() )
391 {
392 if( getSetNullOnMissingSource() )
393 {
394 while( targetXml.toNextSelection() )
395 {
396 result.add( setNodeValue( null, targetXml.getDomNode() ) );
397 if( !getTransferToAll() )
398 break;
399 }
400 }
401 else if( !getIgnoreEmpty() )
402 throw new Exception( "Missing match for Source XPath [" + sp + "]" );
403 }
404 else
405 {
406 boolean hasSource = sourceXml.toNextSelection();
407 boolean hasTarget = targetXml.toNextSelection();
408
409 while( hasSource && hasTarget )
410 {
411 if( lastSource != null )
412 lastSource.dispose();
413
414 lastSource = sourceXml.newCursor();
415 result.add( transferXmlValue( sourceXml, targetXml ) );
416
417 hasSource = sourceXml.toNextSelection();
418 hasTarget = targetXml.toNextSelection();
419 }
420
421 if( getTransferToAll() && !hasSource && hasTarget && lastSource != null )
422 {
423 while( hasTarget )
424 {
425 result.add( transferXmlValue( lastSource, targetXml ) );
426 hasTarget = targetXml.toNextSelection();
427 }
428 }
429 }
430 }
431
432 if( result.size() > 0 )
433 {
434 String value = targetXmlObject.xmlText( new XmlOptions().setSaveAggressiveNamespaces() );
435 if( getEntitize() )
436 value = XmlUtils.entitize( value );
437
438 targetProperty.setValue( value );
439 }
440
441 return result.toArray( new String[result.size()] );
442 }
443 finally
444 {
445 sourceXml.dispose();
446 targetXml.dispose();
447
448 if( lastSource != null )
449 lastSource.dispose();
450 }
451 }
452
453 protected String[] transferStringToXml( TestProperty sourceProperty, TestProperty targetProperty,
454 SubmitContext context ) throws XmlException, Exception
455 {
456 XmlObject targetXml = XmlObject.Factory.parse( targetProperty.getValue() );
457 XmlCursor targetCursor = targetXml.newCursor();
458
459 try
460 {
461 List<String> result = new ArrayList<String>();
462
463 String tp = PropertyExpander.expandProperties( context, getTargetPath() );
464 targetCursor.selectPath( tp );
465
466 if( !targetCursor.toNextSelection() )
467 throw new Exception( "Missing match for Target XPath [" + tp + "]" );
468
469 String value = sourceProperty.getValue();
470
471 Node targetNode = targetCursor.getDomNode();
472 setNodeValue( value, targetNode );
473
474 result.add( value );
475
476 if( getTransferToAll() )
477 {
478 while( targetCursor.toNextSelection() )
479 {
480 targetNode = targetCursor.getDomNode();
481 setNodeValue( value, targetNode );
482
483 result.add( value );
484 }
485 }
486
487 targetProperty.setValue( targetXml.xmlText( new XmlOptions().setSaveAggressiveNamespaces() ) );
488
489 return result.toArray( new String[result.size()] );
490 }
491 finally
492 {
493 targetCursor.dispose();
494 }
495 }
496
497 private String setNodeValue( String value, Node node ) throws Exception
498 {
499 short targetNodeType = node.getNodeType();
500
501 if( targetNodeType == Node.DOCUMENT_FRAGMENT_NODE )
502 {
503 node = node.getFirstChild();
504 if( node != null )
505 targetNodeType = node.getNodeType();
506 else
507 throw new Exception( "Missing source value for " + getSourcePropertyName() );
508 }
509
510 if( !XmlUtils.setNodeValue( node, value ) )
511
512
513
514
515
516
517
518
519
520
521 {
522 throw new Exception( "Failed to set value to node [" + node.toString() + "] of type [" + targetNodeType + "]" );
523 }
524
525 return value;
526 }
527
528 protected String transferXPathToString( TestProperty sourceProperty, TestProperty targetProperty,
529 SubmitContext context ) throws Exception
530 {
531 String sourceValue = sourceProperty.getValue();
532
533 if( sourceValue == null )
534 {
535 if( !getIgnoreEmpty() )
536 throw new Exception( "Missing source value" );
537
538 if( getSetNullOnMissingSource() )
539 targetProperty.setValue( null );
540 }
541
542 XmlObject sourceXml = sourceValue == null ? null : XmlObject.Factory.parse( sourceValue );
543 XmlCursor sourceCursor = sourceValue == null ? null : sourceXml.newCursor();
544
545 try
546 {
547 String value = null;
548
549 String xquery = PropertyExpander.expandProperties( context, getSourcePath() );
550 if( getUseXQuery() )
551 {
552 XmlCursor resultCursor = sourceCursor.execQuery( xquery );
553 sourceCursor.dispose();
554 sourceCursor = resultCursor;
555 }
556 else
557 {
558 sourceCursor.selectPath( xquery );
559 }
560
561 if( !getUseXQuery() && !sourceCursor.toNextSelection() )
562 {
563 if( !getSetNullOnMissingSource() && !getIgnoreEmpty() )
564 throw new Exception( "Missing match for Source XPath [" + xquery + "]" );
565 }
566 else if( getUseXQuery() && sourceCursor.toNextToken() != TokenType.START )
567 {
568 if( !getSetNullOnMissingSource() && !getIgnoreEmpty() )
569 throw new Exception( "Missing match for Source XQuery [" + xquery + "]" );
570 }
571 else
572 {
573 Node sourceNode = sourceCursor.getDomNode();
574 short sourceNodeType = sourceNode.getNodeType();
575
576 if( sourceNodeType == Node.DOCUMENT_FRAGMENT_NODE )
577 {
578 sourceNode = sourceNode.getFirstChild();
579 if( sourceNode != null )
580 sourceNodeType = sourceNode.getNodeType();
581 else
582 throw new Exception( "Missing source value for " + getSourcePropertyName() );
583 }
584
585 if( sourceNodeType == Node.TEXT_NODE || sourceNodeType == Node.ATTRIBUTE_NODE )
586 {
587 value = sourceNode.getNodeValue();
588 }
589 else if( sourceNodeType == Node.ELEMENT_NODE )
590 {
591 if( getTransferTextContent() )
592 {
593 value = XmlUtils.getElementText( ( Element )sourceNode );
594 }
595
596 if( value == null || !getTransferTextContent() )
597 {
598 value = sourceCursor.getObject().xmlText(
599 new XmlOptions().setSaveOuter().setSaveAggressiveNamespaces() );
600 }
601 }
602 }
603
604 if( !getIgnoreEmpty() || ( value != null && value.length() > 0 ) )
605 {
606 if( getEntitize() )
607 value = XmlUtils.entitize( value );
608
609 targetProperty.setValue( value );
610 }
611 else
612 value = "";
613
614 return value;
615 }
616 finally
617 {
618 sourceCursor.dispose();
619 }
620 }
621
622 /***
623 * Method called for transferring between 2 xml properties..
624 */
625
626 private String transferXmlValue( XmlCursor source, XmlCursor dest ) throws Exception
627 {
628
629 Node destNode = dest.getDomNode();
630 Node sourceNode = source.getDomNode();
631 short destNodeType = destNode.getNodeType();
632 short sourceNodeType = sourceNode.getNodeType();
633 String value = null;
634
635 if( getTransferChildNodes() )
636 {
637 while( destNode.hasChildNodes() )
638 {
639 destNode.removeChild( destNode.getFirstChild() );
640 }
641
642 NodeList childNodes = sourceNode.getChildNodes();
643 for( int c = 0; c < childNodes.getLength(); c++ )
644 {
645 destNode.appendChild( destNode.getOwnerDocument().importNode( childNodes.item( c ), true ) );
646 }
647
648 return XmlUtils.serialize( destNode, false );
649 }
650
651 if( sourceNodeType == Node.DOCUMENT_FRAGMENT_NODE )
652 {
653 sourceNode = sourceNode.getFirstChild();
654 if( sourceNode != null )
655 sourceNodeType = sourceNode.getNodeType();
656 else
657 throw new Exception( "Missing source value for " + source );
658 }
659
660
661 if( destNodeType == sourceNodeType )
662 {
663 if( destNodeType == Node.TEXT_NODE || destNodeType == Node.ATTRIBUTE_NODE )
664 {
665 value = sourceNode.getNodeValue();
666 if( !getIgnoreEmpty() || ( value != null && value.length() > 0 ) )
667 {
668 if( getEntitize() )
669 value = XmlUtils.entitize( value );
670
671 destNode.setNodeValue( value );
672 }
673 }
674 else if( config.getTransferTextContent() && destNodeType == Node.ELEMENT_NODE )
675 {
676 value = XmlUtils.getElementText( ( Element )sourceNode );
677 if( value == null && sourceNode.getFirstChild() != null )
678 {
679 value = source.getObject().xmlText( new XmlOptions().setSaveOuter().setSaveAggressiveNamespaces() );
680
681 if( getEntitize() )
682 value = XmlUtils.entitize( value );
683
684 destNode.getParentNode().replaceChild( destNode.getOwnerDocument().importNode( sourceNode, true ),
685 destNode );
686 }
687 else if( !getIgnoreEmpty() || ( value != null && value.length() > 0 ) )
688 {
689 if( getEntitize() )
690 value = XmlUtils.entitize( value );
691
692 XmlUtils.setElementText( ( Element )destNode, value );
693 }
694 }
695 else
696 {
697 destNode = destNode.getParentNode().replaceChild(
698 destNode.getOwnerDocument().importNode( sourceNode, true ), destNode );
699
700 value = dest.xmlText();
701 }
702 }
703
704 else if( ( sourceNodeType == Node.TEXT_NODE && destNodeType == Node.ATTRIBUTE_NODE )
705 || ( sourceNodeType == Node.ATTRIBUTE_NODE && destNodeType == Node.TEXT_NODE ) )
706 {
707 value = sourceNode.getNodeValue();
708 if( !getIgnoreEmpty() || ( value != null && value.length() > 0 ) )
709 {
710 if( getEntitize() )
711 value = XmlUtils.entitize( value );
712
713 destNode.setNodeValue( value );
714 }
715 }
716 else if( sourceNodeType == Node.ELEMENT_NODE && destNodeType == Node.ATTRIBUTE_NODE
717 || destNodeType == Node.TEXT_NODE )
718 {
719 value = XmlUtils.getElementText( ( Element )sourceNode );
720 if( !getIgnoreEmpty() || ( value != null && value.length() > 0 ) )
721 {
722 if( getEntitize() )
723 value = XmlUtils.entitize( value );
724
725 destNode.setNodeValue( value );
726 }
727 }
728 else if( destNodeType == Node.ELEMENT_NODE && sourceNodeType == Node.ATTRIBUTE_NODE
729 || sourceNodeType == Node.TEXT_NODE )
730 {
731
732 value = sourceNode.getNodeValue();
733 if( !getIgnoreEmpty() || ( value != null && value.length() > 0 ) )
734 {
735 if( getEntitize() )
736 value = XmlUtils.entitize( value );
737
738 XmlUtils.setElementText( ( Element )destNode, value );
739 }
740 }
741
742 return value;
743 }
744
745 /***
746 * Returns the name of the source property.
747 */
748
749 public String getSourcePropertyName()
750 {
751 if( sourceType == null )
752 return null;
753
754 if( currentSourceProperty != null )
755 return currentSourceProperty.getName();
756
757 TestPropertyHolder actualSourceStep = getSourceStep();
758 if( actualSourceStep == null )
759 return sourceType;
760
761 TestProperty property = actualSourceStep.getProperty( sourceType );
762 return property == null ? sourceType : property.getName();
763 }
764
765 public void setSourcePropertyName( String name )
766 {
767 String old = getSourcePropertyName();
768
769
770 if( ( name == null && old == null ) || ( name != null && old != null && name.equals( old ) ) )
771 return;
772
773
774 sourceType = name;
775 config.setSourceType( name );
776
777
778 TestPropertyHolder sourceStep2 = getSourceStep();
779 currentSourceProperty = sourceStep2 != null && sourceType != null ? sourceStep2.getProperty( sourceType ) : null;
780
781
782 propertyChangeSupport.firePropertyChange( SOURCE_TYPE_PROPERTY, old, name );
783 }
784
785 public TestProperty getTargetProperty()
786 {
787 if( targetType == null )
788 return null;
789
790 if( currentTargetProperty != null )
791 return currentTargetProperty;
792
793 TestPropertyHolder actualTargetStep = getTargetStep();
794 return actualTargetStep == null ? null : actualTargetStep.getProperty( targetType );
795 }
796
797 public String getTargetPropertyName()
798 {
799 if( targetType == null )
800 return null;
801
802 if( currentTargetProperty != null )
803 return currentTargetProperty.getName();
804
805 TestPropertyHolder actualTargetStep = getTargetStep();
806 TestProperty property = actualTargetStep == null ? null : actualTargetStep.getProperty( targetType );
807 return actualTargetStep == null || property == null ? targetType : property.getName();
808 }
809
810 public void setTargetPropertyName( String name )
811 {
812 String old = getTargetPropertyName();
813
814
815 if( ( name == null && old == null ) || ( name != null && old != null && name.equals( old ) ) )
816 return;
817
818
819 targetType = name;
820 config.setTargetType( name );
821
822
823 TestPropertyHolder targetStep2 = getTargetStep();
824
825 currentTargetProperty = targetStep2 != null && targetType != null ? targetStep2.getProperty( targetType ) : null;
826
827
828 propertyChangeSupport.firePropertyChange( TARGET_TYPE_PROPERTY, old, name );
829 }
830
831 public String getName()
832 {
833 return config.getName();
834 }
835
836 public void setSourcePath( String path )
837 {
838 String old = sourcePath;
839 sourcePath = path;
840 config.setSourcePath( path );
841 propertyChangeSupport.firePropertyChange( SOURCE_PATH_PROPERTY, old, path );
842 }
843
844 public void setTargetPath( String path )
845 {
846 String old = targetPath;
847 targetPath = path;
848 config.setTargetPath( path );
849 propertyChangeSupport.firePropertyChange( TARGET_PATH_PROPERTY, old, path );
850 }
851
852 public void setName( String name )
853 {
854 String old = this.name;
855 this.name = name;
856 config.setName( name );
857 propertyChangeSupport.firePropertyChange( NAME_PROPERTY, old, name );
858 }
859
860 public TestPropertyHolder getSourceStep()
861 {
862 return getPropertyHolder( getSourceStepName() );
863 }
864
865 public String getSourceStepName()
866 {
867 if( sourceStep != null )
868 return sourceStep;
869
870 if( testCase == null )
871 return null;
872
873 HttpRequestTestStep step = testCase.findPreviousStepOfType( this.testStep, HttpRequestTestStep.class );
874 return step == null ? null : step.getName();
875 }
876
877 public void setSourceStepName( String sourceStep )
878 {
879 String old = getSourceStepName();
880
881
882 if( ( sourceStep == null && old == null ) || ( sourceStep != null && old != null && sourceStep.equals( old ) ) )
883 return;
884
885 if( sourceStep == null )
886 log.debug( "Setting sourceStep for transfer [" + getName() + "] to null" );
887
888 this.sourceStep = sourceStep;
889 config.setSourceStep( sourceStep );
890
891 if( currentSourceStep != null )
892 {
893 if( currentSourceStep instanceof TestStep )
894 ( ( TestStep )currentSourceStep ).removePropertyChangeListener( TestStep.NAME_PROPERTY,
895 stepNameChangeListener );
896
897 currentSourceStep.removeTestPropertyListener( propertyNameChangeListener );
898 }
899
900 currentSourceStep = getPropertyHolder( sourceStep );
901 if( currentSourceStep != null )
902 {
903 if( currentSourceStep instanceof TestStep )
904 ( ( TestStep )currentSourceStep )
905 .addPropertyChangeListener( TestStep.NAME_PROPERTY, stepNameChangeListener );
906
907 currentSourceStep.addTestPropertyListener( propertyNameChangeListener );
908 }
909 else
910 log.warn( "Failed to get sourceStep [" + sourceStep + "]" );
911
912 propertyChangeSupport.firePropertyChange( SOURCE_STEP_PROPERTY, old, sourceStep );
913 setSourcePropertyName( null );
914 }
915
916 public TestPropertyHolder getTargetStep()
917 {
918 return getPropertyHolder( getTargetStepName() );
919 }
920
921 public String getTargetStepName()
922 {
923 if( targetStep != null )
924 return targetStep;
925
926 if( testCase == null )
927 return null;
928
929 HttpRequestTestStep step = testCase.findNextStepOfType( this.testStep, HttpRequestTestStep.class );
930 return step == null ? null : step.getName();
931 }
932
933 public void setTargetStepName( String targetStep )
934 {
935 String old = getTargetStepName();
936
937
938 if( ( targetStep == null && old == null ) || ( targetStep != null && old != null && targetStep.equals( old ) ) )
939 return;
940
941 if( targetStep == null )
942 log.debug( "Setting targetStep for transfer [" + getName() + "] to null" );
943
944 this.targetStep = targetStep;
945 config.setTargetStep( targetStep );
946
947 if( currentTargetStep != null )
948 {
949 if( currentTargetStep instanceof TestStep )
950 ( ( TestStep )currentTargetStep ).removePropertyChangeListener( TestStep.NAME_PROPERTY,
951 stepNameChangeListener );
952
953 currentTargetStep.removeTestPropertyListener( propertyNameChangeListener );
954 }
955
956 currentTargetStep = getPropertyHolder( targetStep );
957 if( currentTargetStep != null )
958 {
959 if( currentTargetStep instanceof TestStep )
960 ( ( TestStep )currentTargetStep )
961 .addPropertyChangeListener( TestStep.NAME_PROPERTY, stepNameChangeListener );
962
963 currentTargetStep.addTestPropertyListener( propertyNameChangeListener );
964 }
965 else
966 log.warn( "Failed to get targetStep [" + targetStep + "]" );
967
968 propertyChangeSupport.firePropertyChange( TARGET_STEP_PROPERTY, old, targetStep );
969 setTargetPropertyName( null );
970 }
971
972 private TestPropertyHolder getPropertyHolder( String name )
973 {
974 if( name == null || testCase == null )
975 return null;
976
977 if( name.charAt( 0 ) == PropertyExpansion.SCOPE_PREFIX )
978 {
979 if( name.equals( PropertyExpansion.GLOBAL_REFERENCE ) )
980 return PropertyExpansionUtils.getGlobalProperties();
981
982 if( name.equals( PropertyExpansion.PROJECT_REFERENCE ) )
983 return testCase.getTestSuite().getProject();
984
985 if( name.equals( PropertyExpansion.TESTSUITE_REFERENCE ) )
986 return testCase.getTestSuite();
987
988 if( name.equals( PropertyExpansion.TESTCASE_REFERENCE ) )
989 return testCase;
990 }
991
992 return testStep.getTestCase().getTestStepByName( name );
993 }
994
995 public void addPropertyChangeListener( String propertyName, PropertyChangeListener listener )
996 {
997 propertyChangeSupport.addPropertyChangeListener( propertyName, listener );
998 }
999
1000 public void addPropertyChangeListener( PropertyChangeListener listener )
1001 {
1002 propertyChangeSupport.addPropertyChangeListener( listener );
1003 }
1004
1005 public void removePropertyChangeListener( PropertyChangeListener listener )
1006 {
1007 propertyChangeSupport.removePropertyChangeListener( listener );
1008 }
1009
1010 public void removePropertyChangeListener( String propertyName, PropertyChangeListener listener )
1011 {
1012 propertyChangeSupport.removePropertyChangeListener( propertyName, listener );
1013 }
1014
1015 public boolean getFailOnError()
1016 {
1017 return config.getFailOnError();
1018 }
1019
1020 public void setFailOnError( boolean failOnError )
1021 {
1022 config.setFailOnError( failOnError );
1023 }
1024
1025 public boolean getTransferToAll()
1026 {
1027 return config.getTransferToAll();
1028 }
1029
1030 public void setTransferToAll( boolean transferToAll )
1031 {
1032 config.setTransferToAll( transferToAll );
1033 }
1034
1035 public boolean getUseXQuery()
1036 {
1037 return config.getUseXQuery();
1038 }
1039
1040 public void setUseXQuery( boolean useXQuery )
1041 {
1042 config.setUseXQuery( useXQuery );
1043 }
1044
1045 public boolean getEntitize()
1046 {
1047 return config.getEntitize();
1048 }
1049
1050 public void setEntitize( boolean entitize )
1051 {
1052 config.setEntitize( entitize );
1053 }
1054
1055 public boolean getIgnoreEmpty()
1056 {
1057 return config.getIgnoreEmpty();
1058 }
1059
1060 public void setIgnoreEmpty( boolean ignoreEmpty )
1061 {
1062 config.setIgnoreEmpty( ignoreEmpty );
1063 }
1064
1065 public boolean getSetNullOnMissingSource()
1066 {
1067 return config.getSetNullOnMissingSource();
1068 }
1069
1070 public void setSetNullOnMissingSource( boolean setNullOnMissingSource )
1071 {
1072 config.setSetNullOnMissingSource( setNullOnMissingSource );
1073 }
1074
1075 public boolean getTransferTextContent()
1076 {
1077 return config.getTransferTextContent();
1078 }
1079
1080 public void setTransferTextContent( boolean transferTextContent )
1081 {
1082 config.setTransferTextContent( transferTextContent );
1083 }
1084
1085 public boolean isDisabled()
1086 {
1087 return config.getDisabled();
1088 }
1089
1090 public void setDisabled( boolean disabled )
1091 {
1092 config.setDisabled( disabled );
1093 }
1094
1095 public boolean getTransferChildNodes()
1096 {
1097 return config.getTransferChildNodes();
1098 }
1099
1100 public void setTransferChildNodes( boolean b )
1101 {
1102 config.setTransferChildNodes( b );
1103 }
1104
1105 private final class InternalTestSuiteListener extends TestSuiteListenerAdapter
1106 {
1107 public void testStepRemoved( TestStep testStep, int index )
1108 {
1109 if( testStep.getTestCase() == testCase )
1110 {
1111 String stepName = testStep.getName();
1112 if( stepName.equals( sourceStep ) )
1113 {
1114 setSourceStepName( null );
1115 }
1116
1117 if( stepName.equals( targetStep ) )
1118 {
1119 setTargetStepName( null );
1120 }
1121 }
1122 }
1123 }
1124
1125 /***
1126 * Handle changes to source/target testStep names
1127 *
1128 * @author Ole.Matzura
1129 */
1130
1131 private class StepNameChangeListener implements PropertyChangeListener
1132 {
1133 public void propertyChange( PropertyChangeEvent evt )
1134 {
1135 String oldName = ( String )evt.getOldValue();
1136 String newValue = ( String )evt.getNewValue();
1137
1138 if( newValue == null )
1139 {
1140 log.error( "Tried to change stepname to null!" );
1141 Thread.dumpStack();
1142 return;
1143 }
1144
1145 if( oldName.equals( sourceStep ) && currentSourceStep instanceof TestStep )
1146 {
1147 sourceStep = newValue;
1148 config.setSourceStep( sourceStep );
1149 propertyChangeSupport.firePropertyChange( SOURCE_STEP_PROPERTY, oldName, sourceStep );
1150 }
1151
1152 if( oldName.equals( targetStep ) && currentTargetStep instanceof TestStep )
1153 {
1154 targetStep = newValue;
1155 config.setTargetStep( targetStep );
1156 propertyChangeSupport.firePropertyChange( TARGET_STEP_PROPERTY, oldName, targetStep );
1157 }
1158 }
1159 }
1160
1161 /***
1162 * Handle changes to source/target property names
1163 *
1164 * @author Ole.Matzura
1165 */
1166
1167 private class InternalTestPropertyListener extends TestPropertyListenerAdapter
1168 {
1169 public void propertyRenamed( String oldName, String newName )
1170 {
1171 if( oldName.equals( sourceType ) )
1172 {
1173 sourceType = newName;
1174 config.setSourceType( sourceType );
1175 propertyChangeSupport.firePropertyChange( SOURCE_TYPE_PROPERTY, oldName, sourceType );
1176 }
1177
1178 if( oldName.equals( targetType ) )
1179 {
1180 targetType = newName;
1181 config.setTargetType( targetType );
1182 propertyChangeSupport.firePropertyChange( TARGET_TYPE_PROPERTY, oldName, targetType );
1183 }
1184 }
1185
1186 public void propertyRemoved( String name )
1187 {
1188 if( name.equals( sourceType ) )
1189 {
1190 log.warn( "source property for transfer [" + getName() + "] in teststep [" + testStep.getName() + "/"
1191 + testStep.getTestCase().getName() + "/" + testStep.getTestCase().getTestSuite().getName()
1192 + "] set to null, was [" + name + "]" );
1193
1194 currentSourceProperty = null;
1195 setSourcePropertyName( null );
1196 }
1197
1198 if( name.equals( targetType ) )
1199 {
1200 log.warn( "target property for transfer [" + getName() + "] in teststep [" + testStep.getName() + "/"
1201 + testStep.getTestCase().getName() + "/" + testStep.getTestCase().getTestSuite().getName()
1202 + "] set to null, was [" + name + "]" );
1203
1204 currentTargetProperty = null;
1205 setTargetPropertyName( null );
1206 }
1207 }
1208 }
1209
1210 @SuppressWarnings( "unchecked" )
1211 public void resolve( ResolveContext<?> context, PropertyTransfersTestStep parent )
1212 {
1213 if( isDisabled() )
1214 return;
1215
1216 if( getSourceProperty() == null )
1217 {
1218 if( context.hasThisModelItem( parent, "Resolve source property", getConfig().getSourceStep() ) )
1219 return;
1220 context.addPathToResolve( parent, "Resolve source property", getConfig().getSourceStep() ).addResolvers(
1221 new DisablePropertyTransferResolver( this ), new CreateMissingPropertyResolver( this, parent ),
1222 new ChooseAnotherPropertySourceResolver( this, parent ) );
1223 }
1224 else
1225 {
1226 if( context.hasThisModelItem( parent, "Resolve source property", getConfig().getSourceStep() ) )
1227 {
1228 PathToResolve path = context.getPath( parent, "Resolve source property", getConfig().getSourceStep() );
1229 path.setSolved( true );
1230 }
1231 }
1232
1233 if( getTargetProperty() == null )
1234 {
1235 if( context.hasThisModelItem( parent, "Resolve target property", getConfig().getTargetStep() ) )
1236 return;
1237 context.addPathToResolve( parent, "Resolve target property", getConfig().getTargetStep() ).addResolvers(
1238 new DisablePropertyTransferResolver( this ), new CreateMissingPropertyResolver( this, parent ),
1239 new ChooseAnotherPropertyTargetResolver( this, parent ) );
1240 }
1241 else
1242 {
1243 if( context.hasThisModelItem( parent, "Resolve target property", getConfig().getTargetStep() ) )
1244 {
1245 PathToResolve path = context.getPath( parent, "Resolve target property", getConfig().getTargetStep() );
1246 path.setSolved( true );
1247 }
1248 }
1249
1250 }
1251 }