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