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