View Javadoc

1   /*
2    *  soapui, copyright (C) 2005 Ole Matzura / eviware.com 
3    *
4    *  SoapUI is free software; you can redistribute it and/or modify it under the 
5    *  terms of the GNU Lesser General Public License as published by the Free Software Foundation; 
6    *  either version 2.1 of the License, or (at your option) any later version.
7    *
8    *  SoapUI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without 
9    *  even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
10   *  See the GNU Lesser General Public License for more details at gnu.org.
11   */
12  
13  package com.eviware.soapui.impl.wsdl.teststeps;
14  
15  import java.util.ArrayList;
16  import java.util.List;
17  
18  import org.apache.log4j.Logger;
19  import org.apache.xmlbeans.XmlObject;
20  import org.w3c.dom.Element;
21  import org.w3c.dom.Node;
22  
23  import com.eviware.soapui.config.TestStepConfig;
24  import com.eviware.soapui.config.TransferValuesStepConfig;
25  import com.eviware.soapui.config.ValueTransferConfig;
26  import com.eviware.soapui.impl.wsdl.WsdlTestCase;
27  import com.eviware.soapui.impl.wsdl.WsdlTestStep;
28  import com.eviware.soapui.impl.wsdl.panels.testcase.TransferResponseValuesTestStepPanelBuilder;
29  import com.eviware.soapui.model.PanelBuilder;
30  import com.eviware.soapui.model.testsuite.TestRunner;
31  import com.eviware.soapui.model.testsuite.TestStep;
32  import com.eviware.soapui.support.XmlUtils;
33  
34  /***
35   * WsdlTestStep for transferring values from a WsdlTestRequest response to a 
36   * WsdlTestRequest request using XPath expressions
37   * 
38   * @author Ole.Matzura
39   */
40  
41  public class TransferResponseValuesTestStep extends WsdlTestStep
42  {
43  	private TransferValuesStepConfig transferStepConfig;
44  	private TransferResponseValuesTestStepPanelBuilder panelBuilder;
45  	private final static Logger log = Logger.getLogger( TransferResponseValuesTestStep.class );
46  	private boolean canceled;
47  	private List<ValueTransfer> transfers = new ArrayList<ValueTransfer>();
48  
49  	public TransferResponseValuesTestStep(WsdlTestCase testCase, TestStepConfig config)
50  	{
51  		super(testCase, config);
52  	
53        if( config.getConfig() != null )
54        {
55  			transferStepConfig = (TransferValuesStepConfig) config.getConfig().changeType(TransferValuesStepConfig.type);
56  			for( int c = 0; c < transferStepConfig.sizeOfTransfersArray(); c++ )
57  			{
58  				transfers.add( new ValueTransfer( transferStepConfig.getTransfersArray( c )));
59  			}				
60        }
61        else
62        {
63           transferStepConfig = (TransferValuesStepConfig) config.addNewConfig().changeType( TransferValuesStepConfig.type );
64        }
65  	}
66  	
67  	public TransferValuesStepConfig getTransferConfig()
68  	{
69  		return transferStepConfig;
70  	}
71  	
72  	protected void resetConfigOnMove(TestStepConfig config)
73  	{
74  		super.resetConfigOnMove(config);
75  		
76  		transferStepConfig = (TransferValuesStepConfig) config.getConfig().changeType(TransferValuesStepConfig.type);
77  		for( int c = 0; c < transferStepConfig.sizeOfTransfersArray(); c++ )
78  		{
79  			transfers.get( c ).setConfig( transferStepConfig.getTransfersArray( c ));
80  		}		
81  	}
82  
83  	public void run( TestRunner runner )
84  	{
85  		canceled = false;
86  		
87  		int ix = runner.getCurrentStepIndex();
88  		if( ix == 0 || ix == runner.getTestCase().getTestStepCount()-1 ) return;
89  		
90  		TestStep previousStep = runner.getTestCase().getTestStepAt( ix-1 );
91  		if( !(previousStep instanceof WsdlTestRequestStep )) return;
92  
93  		TestStep nextStep = runner.getTestCase().getTestStepAt( ix+1 );
94  		if( !(nextStep instanceof WsdlTestRequestStep )) return;
95  		
96  		runTransfer( ((WsdlTestRequestStep) previousStep)
97  					.getTestRequest(), ((WsdlTestRequestStep) nextStep)
98  					.getTestRequest());
99  	}
100 	
101 	public void runTransfer( WsdlTestRequest sourceRequest, WsdlTestRequest targetRequest )
102 	{
103 		ValueTransferConfig[] transfers = transferStepConfig.getTransfersArray();
104 		for( int c = 0; c < transfers.length; c++ )
105 		{
106 			try
107 			{
108 				if( canceled ) 
109 					return;
110 				
111 				transferValues( sourceRequest, targetRequest, transfers[c]);
112 			}
113 			catch (Exception e)
114 			{
115 				log.error( e.getMessage() );
116 				e.printStackTrace();
117 			}
118 		}
119 	}
120 
121 	public void transferValues(WsdlTestRequest sourceRequest, WsdlTestRequest targetRequest, ValueTransferConfig transfer) throws Exception
122 	{
123 		XmlObject previous = XmlObject.Factory.parse( sourceRequest.getResponseContent());
124 		XmlObject[] sourceValues = previous.selectPath( transfer.getSourcePath() );
125 		if( sourceValues.length == 0 ) 
126 		{
127 			log.info( "No match found for transfer sourcePath [" + transfer.getSourcePath() + 
128 					"] in transfer [" + transfer.getName() + "]");
129 			return;
130 		}
131 
132 		XmlObject next = XmlObject.Factory.parse( targetRequest.getRequestContent());
133 	   XmlObject[] destValues = next.selectPath( transfer.getTargetPath() );
134 	   if( destValues.length == 0 ) 
135 	   {
136 			log.info( "No match found for transfer targetPath [" + transfer.getTargetPath() + 
137 					"] in transfer [" + transfer.getName() + "]" );
138 			return;
139 		}
140 	   
141 	   if( sourceValues.length != destValues.length )
142 	   	throw new Exception( "Number of matching values must be same in source response and destination request" +
143 	   			"; " + sourceValues.length + ":" + destValues.length );
144 	   
145 	   for( int c = 0; c < sourceValues.length; c++ )
146 	   {
147 	   	transferValue( sourceValues[c], destValues[c], transfer );
148 	   }
149 	   
150 	   if( canceled ) 
151 			return;
152 	   
153 	   targetRequest.setRequest( next.xmlText() );
154 	}
155 
156 	private void transferValue(XmlObject source, XmlObject dest, ValueTransferConfig transfer) throws Exception
157 	{
158 		// just copy if nodes are of same type
159 		Node destNode = dest.getDomNode();
160 		Node sourceNode = source.getDomNode();
161 		short destNodeType = destNode.getNodeType();
162 		short sourceNodeType = sourceNode.getNodeType();
163 		
164 		// same type of node?
165 		if( destNodeType == sourceNodeType )
166 		{
167 			dest.set( source.copy() );
168 		}
169 		// text to attribute?
170 		else if( (sourceNodeType == Node.TEXT_NODE && destNodeType == Node.ATTRIBUTE_NODE) ||
171 				(sourceNodeType == Node.ATTRIBUTE_NODE && destNodeType == Node.TEXT_NODE) )
172 		{
173 			destNode.setNodeValue( sourceNode.getNodeValue() );
174 		}
175 		else if( sourceNodeType == Node.ELEMENT_NODE && 
176 				destNodeType == Node.ATTRIBUTE_NODE || destNodeType == Node.TEXT_NODE )
177 		{
178 			destNode.setNodeValue( XmlUtils.getElementText( (Element) sourceNode ));
179 		}
180 		else if( destNodeType == Node.ELEMENT_NODE && 
181 				sourceNodeType == Node.ATTRIBUTE_NODE || sourceNodeType == Node.TEXT_NODE )
182 		{
183 			// hmm.. not sure xmlbeans handles this ok
184 			XmlUtils.setElementText( (Element) destNode, sourceNode.getNodeValue() );
185 		}
186 	}
187 
188 	public PanelBuilder getPanelBuilder()
189 	{
190 		if( panelBuilder == null )
191 			panelBuilder = new TransferResponseValuesTestStepPanelBuilder( this );
192 		
193 		return panelBuilder;
194 	}
195 
196 	public boolean cancel()
197 	{
198 		canceled = true;
199 		return canceled;
200 	}
201 	
202 	public int getTransferCount()
203 	{
204 		return transferStepConfig.sizeOfTransfersArray();
205 	}
206 	
207 	public ValueTransfer getTransferAt( int index )
208 	{
209 		return transfers.get( index );
210 	}
211 	
212 	public ValueTransfer addTransfer( String name )
213 	{
214 		ValueTransfer transfer = new ValueTransfer( transferStepConfig.addNewTransfers());
215 		transfers.add( transfer );
216 		return transfer;
217 	}
218 	
219 	public void removeTransferAt( int index )
220 	{
221 		transfers.remove( index );
222 		transferStepConfig.removeTransfers( index );
223 	}
224 	
225 	public class ValueTransfer
226 	{
227 		private ValueTransferConfig config;
228 
229 		private ValueTransfer( ValueTransferConfig config )
230 		{
231 			this.config = config;
232 		}
233 		
234 		private void setConfig(ValueTransferConfig config)
235 		{
236 			this.config = config;
237 		}
238 
239 		public String getSourcePath()
240 		{
241 			return config.getSourcePath();
242 		}
243 		
244 		public String getTargetPath()
245 		{
246 			return config.getTargetPath();
247 		}
248 		
249 		public String getName()
250 		{
251 			return config.getName();
252 		}
253 		
254 		public void setSourcePath( String path )
255 		{
256 			config.setSourcePath( path );
257 		}
258 		
259 		public void setTargetPath( String path )
260 		{
261 			config.setTargetPath( path );
262 		}
263 		
264 		public void setName( String name )
265 		{
266 			config.setName( name );
267 		}
268 	}
269 }