View Javadoc

1   /*
2    *  soapUI, copyright (C) 2004-2007 eviware.com 
3    *
4    *  soapUI is free software; you can redistribute it and/or modify it under the 
5    *  terms of version 2.1 of the GNU Lesser General Public License as published by 
6    *  the Free Software Foundation.
7    *
8    *  soapUI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without 
9    *  even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
10   *  See the GNU Lesser General Public License for more details at gnu.org.
11   */
12  
13  package com.eviware.soapui.impl.wsdl.teststeps.assertions;
14  
15  import java.awt.BorderLayout;
16  import java.awt.Dimension;
17  import java.awt.event.ActionEvent;
18  import java.awt.event.WindowAdapter;
19  import java.awt.event.WindowEvent;
20  import java.util.ArrayList;
21  import java.util.List;
22  
23  import javax.swing.AbstractAction;
24  import javax.swing.Action;
25  import javax.swing.BorderFactory;
26  import javax.swing.JButton;
27  import javax.swing.JCheckBox;
28  import javax.swing.JDialog;
29  import javax.swing.JPanel;
30  import javax.swing.JScrollPane;
31  import javax.swing.JSplitPane;
32  import javax.swing.JTextArea;
33  import javax.swing.SwingUtilities;
34  
35  import org.apache.log4j.Logger;
36  import org.apache.xmlbeans.XmlAnySimpleType;
37  import org.apache.xmlbeans.XmlCursor;
38  import org.apache.xmlbeans.XmlObject;
39  import org.apache.xmlbeans.XmlOptions;
40  import org.custommonkey.xmlunit.Diff;
41  import org.custommonkey.xmlunit.Difference;
42  import org.custommonkey.xmlunit.DifferenceEngine;
43  import org.custommonkey.xmlunit.DifferenceListener;
44  import org.custommonkey.xmlunit.XMLAssert;
45  import org.w3c.dom.Element;
46  import org.w3c.dom.Node;
47  
48  import com.eviware.soapui.SoapUI;
49  import com.eviware.soapui.config.RequestAssertionConfig;
50  import com.eviware.soapui.impl.wsdl.WsdlInterface;
51  import com.eviware.soapui.impl.wsdl.actions.support.ShowOnlineHelpAction;
52  import com.eviware.soapui.impl.wsdl.submit.WsdlMessageExchange;
53  import com.eviware.soapui.impl.wsdl.support.HelpUrls;
54  import com.eviware.soapui.impl.wsdl.support.assertions.AssertedXPathImpl;
55  import com.eviware.soapui.impl.wsdl.support.assertions.AssertedXPathsContainer;
56  import com.eviware.soapui.impl.wsdl.testcase.WsdlTestRunContext;
57  import com.eviware.soapui.impl.wsdl.teststeps.WsdlMessageAssertion;
58  import com.eviware.soapui.impl.wsdl.teststeps.WsdlTestRequestStep;
59  import com.eviware.soapui.model.TestModelItem;
60  import com.eviware.soapui.model.iface.SubmitContext;
61  import com.eviware.soapui.model.propertyexpansion.PropertyExpansion;
62  import com.eviware.soapui.model.propertyexpansion.PropertyExpansionUtils;
63  import com.eviware.soapui.model.support.XPathReference;
64  import com.eviware.soapui.model.support.XPathReferenceContainer;
65  import com.eviware.soapui.model.support.XPathReferenceImpl;
66  import com.eviware.soapui.model.testsuite.Assertable;
67  import com.eviware.soapui.model.testsuite.AssertionError;
68  import com.eviware.soapui.model.testsuite.AssertionException;
69  import com.eviware.soapui.model.testsuite.RequestAssertion;
70  import com.eviware.soapui.model.testsuite.ResponseAssertion;
71  import com.eviware.soapui.model.testsuite.TestProperty;
72  import com.eviware.soapui.model.testsuite.TestStep;
73  import com.eviware.soapui.support.StringUtils;
74  import com.eviware.soapui.support.UISupport;
75  import com.eviware.soapui.support.components.JUndoableTextArea;
76  import com.eviware.soapui.support.components.JXToolBar;
77  import com.eviware.soapui.support.types.StringList;
78  import com.eviware.soapui.support.xml.XmlObjectConfigurationBuilder;
79  import com.eviware.soapui.support.xml.XmlObjectConfigurationReader;
80  import com.eviware.soapui.support.xml.XmlUtils;
81  import com.jgoodies.forms.builder.ButtonBarBuilder;
82  
83  /***
84   * Assertion that matches a specified XPath expression and its expected result
85   * against the associated WsdlTestRequests response message
86   * 
87   * @author Ole.Matzura
88   */
89  
90  public class XPathContainsAssertion extends WsdlMessageAssertion implements RequestAssertion, ResponseAssertion, XPathReferenceContainer
91  {
92  	private final static Logger log = Logger.getLogger( XPathContainsAssertion.class );
93  	private String expectedContent;
94  	private String path;
95  	private JDialog configurationDialog;
96  	private JTextArea pathArea;
97  	private JTextArea contentArea;
98  	private boolean configureResult;
99  	private boolean allowWildcards;
100 
101 	public static final String ID = "XPath Match";
102 	public static final String LABEL = "XPath Match";
103 	private JCheckBox allowWildcardsCheckBox;
104 
105 	public XPathContainsAssertion( RequestAssertionConfig assertionConfig, Assertable assertable )
106 	{
107 		super( assertionConfig, assertable, true, true, true, true );
108 
109 		XmlObjectConfigurationReader reader = new XmlObjectConfigurationReader( getConfiguration() );
110 		path = reader.readString( "path", null );
111 		expectedContent = reader.readString( "content", null );
112 		allowWildcards = reader.readBoolean( "allowWildcards", false );
113 	}
114 
115 	public String getExpectedContent()
116 	{
117 		return expectedContent;
118 	}
119 
120 	public void setExpectedContent( String expectedContent )
121 	{
122 		this.expectedContent = expectedContent;
123 		setConfiguration( createConfiguration() );
124 	}
125 	
126 	/***
127 	 * @deprecated
128 	 */
129 	
130 	@Deprecated
131    public void setContent( String content )
132 	{
133 		setExpectedContent( content );
134 	}
135 
136 	public String getPath()
137 	{
138 		return path;
139 	}
140 
141 	public void setPath( String path )
142 	{
143 		this.path = path;
144 		setConfiguration( createConfiguration() );
145 	}
146 
147 	public boolean isAllowWildcards()
148 	{
149 		return allowWildcards;
150 	}
151 
152 	public void setAllowWildcards( boolean allowWildcards )
153 	{
154 		this.allowWildcards = allowWildcards;
155 	}
156 
157 	@Override
158    protected String internalAssertResponse( WsdlMessageExchange messageExchange, SubmitContext context )
159 				throws AssertionException
160 	{
161 		return assertContent( messageExchange.getResponseContent(), context, "Response" );
162 	}
163 
164 	public String assertContent( String response, SubmitContext context, String type ) throws AssertionException
165 	{
166 		try
167 		{
168 			if( path == null )
169 				return "Missing path for XPath assertion";
170 			if( expectedContent == null )
171 				return "Missing content for XPath assertion";
172 
173 			XmlObject xml = XmlObject.Factory.parse( response );
174 			String expandedPath = PropertyExpansionUtils.expandProperties( context, path );
175 			XmlObject[] items = xml.selectPath( expandedPath );
176 			AssertedXPathsContainer assertedXPathsContainer = ( AssertedXPathsContainer ) 
177 				context.getProperty( AssertedXPathsContainer.ASSERTEDXPATHSCONTAINER_PROPERTY );
178 
179 			XmlObject contentObj = null;
180 			String expandedContent = PropertyExpansionUtils.expandProperties( context, expectedContent );
181 
182 			try
183 			{
184 				contentObj = XmlObject.Factory.parse( expandedContent );
185 			}
186 			catch( Exception e )
187 			{
188 				// this is ok.. it just means that the content to match is not xml
189 				// but
190 				// (hopefully) just a string
191 			}
192 
193 			if( items.length == 0 )
194 				throw new Exception( "Missing content for xpath [" + path + "] in " + type );
195 
196 			XmlOptions options = new XmlOptions();
197 			options.setSavePrettyPrint();
198 			options.setSaveOuter();
199 
200 			for( int c = 0; c < items.length; c++ )
201 			{
202 				try
203 				{
204 					AssertedXPathImpl assertedXPathImpl = null;
205 					if( assertedXPathsContainer != null )
206                {
207                   String xpath = XmlUtils.createAbsoluteXPath( items[c].getDomNode() );
208                   if(xpath != null)
209 						{
210                   	XmlObject xmlObj = items[c]; //XmlObject.Factory.parse( items[c].xmlText( options ) );
211                   	
212 							assertedXPathImpl = new AssertedXPathImpl( this, xpath, xmlObj );
213 							assertedXPathsContainer.addAssertedXPath( assertedXPathImpl );
214 						}
215                }
216 					
217 					if( contentObj == null )
218 					{
219 						if( items[c] instanceof XmlAnySimpleType )
220 						{
221 							String value = ( ( XmlAnySimpleType ) items[c] ).getStringValue();
222 							String expandedValue = PropertyExpansionUtils.expandProperties( context, value );
223 							XMLAssert.assertEquals( expandedContent, expandedValue );
224 						}
225 						else
226 						{
227 							Node domNode = items[c].getDomNode();
228 							if( domNode.getNodeType() == Node.ELEMENT_NODE )
229 							{
230 								String expandedValue = PropertyExpansionUtils.expandProperties( context, XmlUtils
231 											.getElementText( ( Element ) domNode ) );
232 								XMLAssert.assertEquals( expandedContent, expandedValue );
233 							}
234 							else
235 							{
236 								String expandedValue = PropertyExpansionUtils.expandProperties( context, domNode
237 											.getNodeValue() );
238 								XMLAssert.assertEquals( expandedContent, expandedValue );
239 							}
240 						}
241 					}
242 					else
243 					{
244 						compareValues( contentObj.xmlText( options ), items[c].xmlText( options ), items[c] );
245 					}
246 
247 					break;
248 				}
249 				catch( Throwable e )
250 				{
251 					if( c == items.length - 1 )
252 						throw e;
253 				}
254 			}
255 		}
256 		catch( Throwable e )
257 		{
258 			String msg = "XPathContains assertion failed for path [" + path + "] : " + e.getClass().getSimpleName() + ":"
259 						+ e.getMessage();
260 
261 			throw new AssertionException( new AssertionError( msg ) );
262 		}
263 
264 		return type + " matches content for [" + path + "]";
265 	}
266 	
267 	private void compareValues( String expandedContent, String expandedValue, XmlObject object ) throws Exception
268 	{
269 		Diff diff = new Diff( expandedContent, expandedValue );
270 		InternalDifferenceListener internalDifferenceListener = new InternalDifferenceListener();
271 		diff.overrideDifferenceListener( internalDifferenceListener );
272 
273 		if( !diff.identical() )
274 			throw new Exception( diff.toString() );
275 		
276 		StringList nodesToRemove = internalDifferenceListener.getNodesToRemove();
277 		
278 		if( !nodesToRemove.isEmpty())
279 		{
280 			for( String node : nodesToRemove )
281 			{
282 				int ix = node.indexOf( "\n/" );
283 				if( ix != -1 )
284 					node = node.substring( 0, ix+1 ) + "/" + node.substring( ix+1 );
285 				else if( node.startsWith( "/" ))
286 					node = "/" + node;
287 				
288 				XmlObject[] paths = object.selectPath( node );
289 				if( paths.length > 0 )
290 				{
291 					Node domNode = paths[0].getDomNode();
292 					domNode.getParentNode().removeChild( domNode );
293 				}
294 			}
295 		}
296 	}
297 
298 	@Override
299    public boolean configure()
300 	{
301 		if( configurationDialog == null )
302 			buildConfigurationDialog();
303 
304 		pathArea.setText( path );
305 		contentArea.setText( expectedContent );
306 		allowWildcardsCheckBox.setSelected( allowWildcards );
307 
308 		UISupport.showDialog( configurationDialog );
309 		return configureResult;
310 	}
311 
312 	protected void buildConfigurationDialog()
313 	{
314 		configurationDialog = new JDialog( UISupport.getMainFrame() );
315 		configurationDialog.setTitle( "XPath Match configuration" );
316 		configurationDialog.addWindowListener( new WindowAdapter()
317 		{
318 			@Override
319          public void windowOpened( WindowEvent event )
320 			{
321 				SwingUtilities.invokeLater( new Runnable()
322 				{
323 					public void run()
324 					{
325 						pathArea.requestFocusInWindow();
326 					}
327 				} );
328 			}
329 		} );
330 
331 		JPanel contentPanel = new JPanel( new BorderLayout() );
332 		contentPanel.add( UISupport.buildDescription( "Specify xpath expression and expected result",
333 					"declare namespaces with <code>declare namespace &lt;prefix&gt;='&lt;namespace&gt;';</code>", null ),
334 					BorderLayout.NORTH );
335 
336 		JSplitPane splitPane = UISupport.createVerticalSplit();
337 
338 		JPanel pathPanel = new JPanel( new BorderLayout() );
339 		JXToolBar pathToolbar = UISupport.createToolbar();
340 		addPathEditorActions( pathToolbar );
341 
342 		pathArea = new JUndoableTextArea();
343 		pathArea.setToolTipText( "Specifies the XPath expression to select from the message for validation" );
344 
345 		pathPanel.add( pathToolbar, BorderLayout.NORTH );
346 		pathPanel.add( new JScrollPane( pathArea ), BorderLayout.CENTER );
347 
348 		splitPane.setTopComponent( UISupport.addTitledBorder( pathPanel, "XPath Expression" ) );
349 
350 		JPanel matchPanel = new JPanel( new BorderLayout() );
351 		JXToolBar contentToolbar = UISupport.createToolbar();
352 		addMatchEditorActions( contentToolbar );
353 
354 		contentArea = new JUndoableTextArea();
355 		contentArea.setToolTipText( "Specifies the expected result of the XPath expression" );
356 
357 		matchPanel.add( contentToolbar, BorderLayout.NORTH );
358 		matchPanel.add( new JScrollPane( contentArea ), BorderLayout.CENTER );
359 
360 		splitPane.setBottomComponent( UISupport.addTitledBorder( matchPanel, "Expected Result" ) );
361 		splitPane.setDividerLocation( 150 );
362 		splitPane.setBorder( BorderFactory.createEmptyBorder( 0, 1, 0, 1 ) );
363 
364 		contentPanel.add( splitPane, BorderLayout.CENTER );
365 
366 		ButtonBarBuilder builder = new ButtonBarBuilder();
367 
368 		ShowOnlineHelpAction showOnlineHelpAction = new ShowOnlineHelpAction( HelpUrls.XPATHASSERTIONEDITOR_HELP_URL );
369 		builder.addFixed( UISupport.createToolbarButton( showOnlineHelpAction ) );
370 		builder.addGlue();
371 
372 		JButton okButton = new JButton( new OkAction() );
373 		builder.addFixed( okButton );
374 		builder.addRelatedGap();
375 		builder.addFixed( new JButton( new CancelAction() ) );
376 
377 		builder.setBorder( BorderFactory.createEmptyBorder( 1, 5, 5, 5 ) );
378 
379 		contentPanel.add( builder.getPanel(), BorderLayout.SOUTH );
380 
381 		configurationDialog.setContentPane( contentPanel );
382 		configurationDialog.setSize( 600, 500 );
383 		configurationDialog.setModal( true );
384 		UISupport.initDialogActions( configurationDialog, showOnlineHelpAction, okButton );
385 	}
386 
387 	protected void addPathEditorActions( JXToolBar toolbar )
388 	{
389 		toolbar.addFixed( new JButton( new DeclareNamespacesFromCurrentAction() ) );
390 	}
391 
392 	protected void addMatchEditorActions( JXToolBar toolbar )
393 	{
394 		toolbar.addFixed( new JButton( new SelectFromCurrentAction() ) );
395 		toolbar.addRelatedGap();
396 		toolbar.addFixed( new JButton( new TestPathAction() ) );
397 		allowWildcardsCheckBox = new JCheckBox( "Allow Wildcards" );
398 
399 		Dimension dim = new Dimension( 100, 20 );
400 
401 		allowWildcardsCheckBox.setSize( dim );
402 		allowWildcardsCheckBox.setPreferredSize( dim );
403 
404 		allowWildcardsCheckBox.setOpaque( false );
405 		toolbar.addRelatedGap();
406 		toolbar.addFixed( allowWildcardsCheckBox );
407 	}
408 
409 	public XmlObject createConfiguration()
410 	{
411 		XmlObjectConfigurationBuilder builder = new XmlObjectConfigurationBuilder();
412 		builder.add( "path", path );
413 		builder.add( "content", expectedContent );
414 		builder.add( "allowWildcards", allowWildcards );
415 		return builder.finish();
416 	}
417 
418 	public void selectFromCurrent()
419 	{
420 		XmlCursor cursor = null;
421 
422 		try
423 		{
424 			XmlOptions options = new XmlOptions();
425 			options.setSavePrettyPrint();
426 			options.setSaveOuter();
427 			options.setSaveAggressiveNamespaces();
428 
429 			String assertableContent = getAssertable().getAssertableContent();
430 			if( assertableContent == null || assertableContent.trim().length() == 0 )
431 			{
432 				UISupport.showErrorMessage( "Missing content to select from" );
433 				return;
434 			}
435 
436 			XmlObject xml = XmlObject.Factory.parse( assertableContent );
437 
438 			String txt = pathArea == null || !pathArea.isVisible() ? getPath() : pathArea.getSelectedText();
439 			if( txt == null )
440 				txt = pathArea == null ? "" : pathArea.getText();
441 
442 			WsdlTestRunContext context = new WsdlTestRunContext( ( TestStep ) getAssertable().getModelItem() );
443 
444 			String expandedPath = PropertyExpansionUtils.expandProperties( context, txt.trim() );
445 
446 			if( contentArea != null && contentArea.isVisible() )
447 				contentArea.setText( "" );
448 
449 			cursor = xml.newCursor();
450 			cursor.selectPath( expandedPath );
451 			if( !cursor.toNextSelection() )
452 			{
453 				UISupport.showErrorMessage( "No match in current response" );
454 			}
455 			else if( cursor.hasNextSelection() )
456 			{
457 				UISupport.showErrorMessage( "More than one match in current response" );
458 			}
459 			else
460 			{
461 				Node domNode = cursor.getDomNode();
462 				String stringValue = null;
463 
464 				if( domNode.getNodeType() == Node.ATTRIBUTE_NODE || domNode.getNodeType() == Node.TEXT_NODE )
465 				{
466 					stringValue = domNode.getNodeValue();
467 				}
468 				else if( cursor.getObject() instanceof XmlAnySimpleType )
469 				{
470 					stringValue = ( ( XmlAnySimpleType ) cursor.getObject() ).getStringValue();
471 				}
472 				else
473 				{
474 					if( domNode.getNodeType() == Node.ELEMENT_NODE )
475 					{
476 						Element elm = ( Element ) domNode;
477 						if( elm.getChildNodes().getLength() == 1 && elm.getAttributes().getLength() == 0 )
478 							stringValue = XmlUtils.getElementText( elm );
479 						else
480 							stringValue = cursor.getObject().xmlText( options );
481 					}
482 					else
483 					{
484 						stringValue = domNode.getNodeValue();
485 					}
486 				}
487 
488 				if( contentArea != null && contentArea.isVisible() )
489 					contentArea.setText( stringValue );
490 				else
491 					setExpectedContent( stringValue );
492 			}
493 		}
494 		catch( Throwable e )
495 		{
496 			UISupport.showErrorMessage( e.toString() );
497 			SoapUI.logError( e );
498 		}
499 		finally
500 		{
501 			if( cursor != null )
502 				cursor.dispose();
503 		}
504 	}
505 
506 	private final class InternalDifferenceListener implements DifferenceListener
507 	{
508 		private StringList nodesToRemove = new StringList();
509 		
510 		public int differenceFound( Difference diff )
511 		{
512 			if( allowWildcards
513 						&& ( diff.getId() == DifferenceEngine.TEXT_VALUE.getId() || diff.getId() == DifferenceEngine.ATTR_VALUE.getId() ) )
514 			{
515 				if( diff.getControlNodeDetail().getValue().equals( "*" ) )
516 				{
517 					String xp = XmlUtils.createAbsoluteXPath( diff.getTestNodeDetail().getNode().getParentNode() );
518 					nodesToRemove.add( xp );
519 					return Diff.RETURN_IGNORE_DIFFERENCE_NODES_IDENTICAL;
520 				}
521 			}
522 		
523 			return Diff.RETURN_ACCEPT_DIFFERENCE;
524 		}
525 
526 		public void skippedComparison( Node arg0, Node arg1 )
527 		{
528 		
529 		}
530 
531 		public StringList getNodesToRemove()
532 		{
533 			return nodesToRemove;
534 		}
535 	}
536 
537 	public class OkAction extends AbstractAction
538 	{
539 		public OkAction()
540 		{
541 			super( "Save" );
542 		}
543 
544 		public void actionPerformed( ActionEvent arg0 )
545 		{
546 			setPath( pathArea.getText().trim() );
547 			setExpectedContent( contentArea.getText() );
548 			setAllowWildcards( allowWildcardsCheckBox.isSelected() );
549 			setConfiguration( createConfiguration() );
550 			configureResult = true;
551 			configurationDialog.setVisible( false );
552 		}
553 	}
554 
555 	public class CancelAction extends AbstractAction
556 	{
557 		public CancelAction()
558 		{
559 			super( "Cancel" );
560 		}
561 
562 		public void actionPerformed( ActionEvent arg0 )
563 		{
564 			configureResult = false;
565 			configurationDialog.setVisible( false );
566 		}
567 	}
568 
569 	public class DeclareNamespacesFromCurrentAction extends AbstractAction
570 	{
571 		public DeclareNamespacesFromCurrentAction()
572 		{
573 			super( "Declare" );
574 			putValue( Action.SHORT_DESCRIPTION, "Add namespace declaration from current message to XPath expression" );
575 		}
576 
577 		public void actionPerformed( ActionEvent arg0 )
578 		{
579 			try
580 			{
581 				String content = getAssertable().getAssertableContent();
582 				if( content != null && content.trim().length() > 0 )
583 				{
584 					pathArea.setText( XmlUtils.declareXPathNamespaces( content ) + pathArea.getText() );
585 				}
586 				else if( UISupport.confirm( "Declare namespaces from schema instead?", "Missing Response" ) )
587 				{
588 					pathArea.setText( XmlUtils.declareXPathNamespaces( (WsdlInterface)getAssertable().getInterface() )
589 											+ pathArea.getText() );
590 				}
591 			}
592 			catch( Exception e )
593 			{
594 				log.error( e.getMessage() );
595 			}
596 		}
597 	}
598 
599 	public class TestPathAction extends AbstractAction
600 	{
601 		public TestPathAction()
602 		{
603 			super( "Test" );
604 			putValue( Action.SHORT_DESCRIPTION,
605 						"Tests the XPath expression for the current message against the Expected Content field" );
606 		}
607 
608 		public void actionPerformed( ActionEvent arg0 )
609 		{
610 			String oldPath = getPath();
611 			String oldContent = getExpectedContent();
612 			boolean oldAllowWildcards = isAllowWildcards();
613 
614 			setPath( pathArea.getText().trim() );
615 			setContent( contentArea.getText() );
616 			setAllowWildcards( allowWildcardsCheckBox.isSelected() );
617 
618 			try
619 			{
620 				String msg = assertContent( getAssertable().getAssertableContent(), new WsdlTestRunContext( ( TestStep ) getAssertable()
621 							.getModelItem() ), "Response" );
622 				UISupport.showInfoMessage( msg, "Success" );
623 			}
624 			catch( AssertionException e )
625 			{
626 				UISupport.showErrorMessage( e.getMessage() );
627 			}
628 
629 			setPath( oldPath );
630 			setContent( oldContent );
631 			setAllowWildcards( oldAllowWildcards );
632 		}
633 	}
634 
635 	public class SelectFromCurrentAction extends AbstractAction
636 	{
637 		public SelectFromCurrentAction()
638 		{
639 			super( "Select from current" );
640 			putValue( Action.SHORT_DESCRIPTION,
641 						"Selects the XPath expression from the current message into the Expected Content field" );
642 		}
643 
644 		public void actionPerformed( ActionEvent arg0 )
645 		{
646 			selectFromCurrent();
647 		}
648 	}
649 
650 	@Override
651 	protected String internalAssertRequest( WsdlMessageExchange messageExchange, SubmitContext context )
652 				throws AssertionException
653 	{
654 		if( !messageExchange.hasRequest( true ) )
655 			return "Missing Request";
656 		else
657 			return assertContent( messageExchange.getRequestContent(), context, "Request" );
658 	}
659 
660 	public JTextArea getContentArea()
661 	{
662 		return contentArea;
663 	}
664 
665 	public JTextArea getPathArea()
666 	{
667 		return pathArea;
668 	}
669 	
670    @Override
671    public PropertyExpansion[] getPropertyExpansions()
672 	{
673 		List<PropertyExpansion> result = new ArrayList<PropertyExpansion>();
674 		
675 		result.addAll( PropertyExpansionUtils.extractPropertyExpansions( getAssertable().getModelItem(), this, "expectedContent") );
676 		result.addAll( PropertyExpansionUtils.extractPropertyExpansions( getAssertable().getModelItem(), this, "path") );
677 		
678 		return result.toArray( new PropertyExpansion[result.size()] );
679 	}
680 
681 	public XPathReference[] getXPathReferences()
682 	{
683 		List<XPathReference> result = new ArrayList<XPathReference>();
684 			
685 		if( StringUtils.hasContent( getPath() ))
686 		{
687 			TestModelItem testStep = ( TestModelItem ) getAssertable().getModelItem();
688 			TestProperty property = testStep instanceof WsdlTestRequestStep ? testStep.getProperty( "Response" ) : testStep.getProperty( "Request" );
689 			result.add( new XPathReferenceImpl( "XPath for " + getName() + " XPathContainsAssertion in " + testStep.getName(), property, this, "path" ));
690 		}
691 		
692 		return result.toArray( new XPathReference[result.size()] );
693 	}
694 }