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;
14  
15  import java.util.ArrayList;
16  import java.util.HashMap;
17  import java.util.List;
18  import java.util.Map;
19  
20  import javax.swing.ImageIcon;
21  import javax.wsdl.BindingOperation;
22  import javax.wsdl.BindingOutput;
23  import javax.wsdl.Definition;
24  import javax.wsdl.Message;
25  import javax.wsdl.extensions.mime.MIMEContent;
26  import javax.wsdl.extensions.mime.MIMEMultipartRelated;
27  import javax.wsdl.extensions.mime.MIMEPart;
28  import javax.xml.namespace.QName;
29  
30  import org.apache.log4j.Logger;
31  import org.apache.xmlbeans.SchemaGlobalElement;
32  import org.apache.xmlbeans.SchemaType;
33  
34  import com.eviware.soapui.SoapUI;
35  import com.eviware.soapui.config.CallConfig;
36  import com.eviware.soapui.config.OperationConfig;
37  import com.eviware.soapui.config.PartsConfig.Part;
38  import com.eviware.soapui.impl.wsdl.support.soap.SoapMessageBuilder;
39  import com.eviware.soapui.impl.wsdl.support.wsdl.WsdlContext;
40  import com.eviware.soapui.impl.wsdl.support.wsdl.WsdlUtils;
41  import com.eviware.soapui.impl.wsdl.support.wsdl.WsdlUtils.SoapHeader;
42  import com.eviware.soapui.model.ModelItem;
43  import com.eviware.soapui.model.iface.MessagePart;
44  import com.eviware.soapui.model.iface.Operation;
45  import com.eviware.soapui.model.iface.Request;
46  import com.eviware.soapui.model.iface.MessagePart.FaultPart;
47  import com.eviware.soapui.support.UISupport;
48  
49  /***
50   * WSDL implementation of Operation, maps to a WSDL BindingOperation
51   * 
52   * @author Ole.Matzura
53   */
54  
55  public class WsdlOperation extends AbstractWsdlModelItem<OperationConfig> implements Operation
56  {
57     public static final String STYLE_DOCUMENT = "Document";
58  	public static final String STYLE_RPC = "RPC";
59  	
60  	public final static Logger log = Logger.getLogger( WsdlOperation.class );
61  	private List<WsdlRequest> requests = new ArrayList<WsdlRequest>();
62     private WsdlInterface iface;
63  	private ImageIcon oneWayIcon;
64  
65     public WsdlOperation( WsdlInterface iface, OperationConfig operationConfig )
66     {
67     	super( operationConfig, iface, "/operation.gif" );
68        this.iface = iface;
69        
70        if( !operationConfig.isSetIsOneWay())
71        {
72        	operationConfig.setIsOneWay( false );
73        }
74        
75        List<CallConfig> requestConfigs = getConfig().getCallList();
76        for (CallConfig config : requestConfigs)
77        {
78           requests.add( new WsdlRequest( this, config));
79        }
80        
81        oneWayIcon = UISupport.createImageIcon( "/onewayoperation.gif" );
82     }
83     
84  	public String getAction()
85     {
86        String action = getConfig().getAction();
87  		return action == null ? "" : action;
88     }
89  
90     public WsdlRequest getRequestAt(int index)
91     {
92        return requests.get( index );
93     }
94     
95     public WsdlRequest getRequestByName(String requestName)
96  	{
97  		return (WsdlRequest) getWsdlModelItemByName( requests, requestName );
98  	}
99  
100 	public int getRequestCount()
101    {
102       return requests.size();
103    }
104 
105    @Override
106    public ImageIcon getIcon()
107 	{
108 		if( isOneWay() )
109 			return oneWayIcon;
110 		else
111 			return super.getIcon();
112 	}
113 
114 	public WsdlRequest addNewRequest( String name )
115    {
116       WsdlRequest requestImpl = new WsdlRequest( this, getConfig().addNewCall() );
117       requestImpl.setName( name );
118       requests.add( requestImpl );
119       (getInterface()).fireRequestAdded( requestImpl );
120       return requestImpl;
121    }
122 
123    public WsdlInterface getInterface()
124    {
125       return iface;
126    }
127 
128    public void setAction(String soapAction)
129    {
130       String old = getAction();
131       getConfig().setAction( soapAction );
132       notifyPropertyChanged( ACTION_PROPERTY, old, soapAction );
133    }
134 
135    public String createRequest( boolean buildOptional )
136    {
137       if( iface.getBindingName() == null )
138       {
139       	UISupport.showErrorMessage( "Missing binding name, please try to refresh " +
140                "Interface\nfor request generation to work correctly" );
141          return null;
142       }
143       
144       if( getBindingOperationName() == null )
145       {
146       	UISupport.showErrorMessage(  "Missing bindingOperation name, please try to refresh " +
147                "Interface\nfor request generation to work correctly" );
148          return null;
149       }
150       
151       try
152       {
153          SoapMessageBuilder builder = iface.getMessageBuilder();
154          BindingOperation bindingOperation = findBindingOperation( iface.getWsdlContext().getDefinition() );
155          
156          if( bindingOperation == null )
157          {
158          	UISupport.showErrorMessage( "Failed to find bindingOperation, please try to refresh " +
159                   "Interface\nfor request generation to work correctly" );
160             return null;
161          }
162          
163 			return builder.buildSoapRequest( bindingOperation, buildOptional );
164       }
165       catch (Exception e)
166       {
167          SoapUI.logError( e );
168          return null;
169       }
170    }
171    
172    public String createResponse( boolean buildOptional )
173    {
174    	if( isOneWay() )
175    	{
176    		return null;
177    	}
178    	
179       if( iface.getBindingName() == null )
180       {
181       	UISupport.showErrorMessage( "Missing binding name, please try to refresh " +
182                "Interface\nfor request generation to work correctly" );
183          return null;
184       }
185       
186       if( getBindingOperationName() == null )
187       {
188       	UISupport.showErrorMessage(  "Missing bindingOperation name, please try to refresh " +
189                "Interface\nfor request generation to work correctly" );
190          return null;
191       }
192       
193       try
194       {
195          SoapMessageBuilder builder = iface.getMessageBuilder();
196          BindingOperation bindingOperation = findBindingOperation( iface.getWsdlContext().getDefinition() );
197          
198          if( bindingOperation == null )
199          {
200          	UISupport.showErrorMessage( "Failed to find bindingOperation, please try to refresh " +
201                   "Interface\nfor request generation to work correctly" );
202             return null;
203          }
204          
205 			return builder.buildSoapResponse( bindingOperation, buildOptional );
206       }
207       catch (Exception e)
208       {
209          SoapUI.logError( e );
210          return null;
211       }
212    }
213    
214    public BindingOperation findBindingOperation(Definition definition)
215    {
216       String bindingOperationName = getConfig().getBindingOperationName();
217       return iface.findBindingOperation( definition, bindingOperationName, getInputName(), getOutputName());
218    }
219   
220    public void removeRequest( WsdlRequest request )
221    {
222       int ix = requests.indexOf( request );
223       requests.remove( ix );
224 
225       try
226       {
227       	(getInterface()).fireRequestRemoved( request );
228       }
229       finally
230       {
231 	      request.release();
232 	      getConfig().removeCall( ix );
233       }
234    }
235 
236    public String getBindingOperationName()
237    {
238       return getConfig().getBindingOperationName();
239    }
240    
241    public void setBindingOperationName( String name )
242    {
243       getConfig().setBindingOperationName( name );
244    }
245    
246    public void setInputName( String name )
247    {
248    	getConfig().setInputName( name );
249    }
250 
251    public String getInputName()
252    {
253    	String inputName = getConfig().getInputName();
254    	return inputName == null || inputName.trim().length() == 0 ? null : inputName;
255    }
256    
257    public void setOutputName( String name )
258    {
259    	if( name == null )
260    	{
261    		if( getConfig().isSetOutputName() )
262    			getConfig().unsetOutputName();
263    	}
264    	else
265    		getConfig().setOutputName( name );
266    }
267 
268    public String getOutputName()
269    {
270    	String outputName = getConfig().getOutputName();
271    	return outputName == null || outputName.trim().length() == 0 ? null : outputName;
272    }
273    
274    public void setOneWay( boolean isOneWay )
275    {
276    	getConfig().setIsOneWay( isOneWay );
277    }
278    
279    public boolean isOneWay()
280    {
281    	return getConfig().getIsOneWay();
282    }
283    
284 	public void initFromBindingOperation(BindingOperation operation )
285 	{
286       setAction( WsdlUtils.getSoapAction( operation ));
287       setName( operation.getOperation().getName() );
288       setBindingOperationName( operation.getName() );
289       setInputName( operation.getBindingInput().getName() );
290       
291       BindingOutput bindingOutput = operation.getBindingOutput();
292       
293       // bindingOutput is null for oneway operations
294 		if( bindingOutput != null )
295       	setOutputName( bindingOutput.getName() );
296 		else
297 			setOutputName( null );
298 
299       setOneWay( bindingOutput == null );
300       
301       initAttachments(operation);
302 	}
303 
304 	@SuppressWarnings("unchecked")
305 	private void initAttachments(BindingOperation operation)
306 	{
307 		if( getConfig().isSetRequestParts() )
308 			getConfig().unsetRequestParts();
309 		
310 		if( getConfig().isSetResponseParts() )
311 			getConfig().unsetResponseParts();
312 		
313 		BindingOutput bindingOutput = operation.getBindingOutput();
314 		
315 		if( bindingOutput != null )
316 	   {
317 		   MIMEMultipartRelated multipartOutput = WsdlUtils.getExtensiblityElement( 
318 		    		bindingOutput.getExtensibilityElements(), MIMEMultipartRelated.class );
319 		 
320 		   getConfig().setReceivesAttachments( multipartOutput != null );
321 		   if( multipartOutput != null )
322 	      {
323 	      	List<MIMEPart> parts = multipartOutput.getMIMEParts();
324 	      	Map<String,Part> partMap = new HashMap<String,Part>();
325 
326 	      	for( int c = 0; c < parts.size(); c++ )
327 	      	{
328 		      	List<MIMEContent> contentParts = WsdlUtils.getExtensiblityElements( parts.get(c).getExtensibilityElements(), MIMEContent.class );
329 		      	
330 		      	for( MIMEContent content : contentParts )
331 		      	{
332 		      		Part part = partMap.get( content.getPart());
333 		      		if( part != null )
334 		      		{ 
335 		      			if( !part.getContentTypeList().contains( content.getType() ))
336 		      				part.addContentType( content.getType() );
337 		      		}
338 		      		else
339 		      		{
340 		      			if( !getConfig().isSetResponseParts() )
341 		      				getConfig().addNewResponseParts();
342 		      			
343 		      			Part responsePart = getConfig().getResponseParts().addNewPart();
344 		      			responsePart.addContentType( content.getType() );
345 		      			responsePart.setName( content.getPart() );
346 		      			
347 		      			partMap.put( responsePart.getName(), responsePart );
348 		      		}
349 		      	}
350 	      	}
351 	      }
352 	   }
353 		
354 		MIMEMultipartRelated multipartInput = WsdlUtils.getExtensiblityElement( 
355       		operation.getBindingInput().getExtensibilityElements(), MIMEMultipartRelated.class );
356  
357       getConfig().setSendsAttachments( multipartInput != null );
358       if( multipartInput != null )
359       {
360       	List<MIMEPart> parts = multipartInput.getMIMEParts();
361       	Map<String,Part> partMap = new HashMap<String,Part>();
362 
363       	for( int c = 0; c < parts.size(); c++ )
364       	{
365 	      	List<MIMEContent> contentParts = WsdlUtils.getExtensiblityElements( parts.get(c).getExtensibilityElements(), MIMEContent.class );
366 	      	
367 	      	for( MIMEContent content : contentParts )
368 	      	{
369 	      		Part part = partMap.get( content.getPart());
370 	      		if( part != null )
371 	      		{ 
372 	      			if( !part.getContentTypeList().contains( content.getType() ))
373 	      				part.addContentType( content.getType() );
374 	      		}
375 	      		else
376 	      		{
377 	      			if( !getConfig().isSetRequestParts() )
378 	      				getConfig().addNewRequestParts();
379 	      			
380 	      			Part requestPart = getConfig().getRequestParts().addNewPart();
381 	      			requestPart.addContentType( content.getType() );
382 	      			requestPart.setName( content.getPart() );
383 	      			
384 	      			partMap.put( requestPart.getName(), requestPart );
385 	      		}
386 	      	}
387       	}
388       }
389 	}
390 	
391 	public boolean getReceivesAttachments()
392 	{
393 		return getConfig().getReceivesAttachments();
394 	}
395 	
396 	public boolean getSendsAttachments()
397 	{
398 		return getConfig().getSendsAttachments();
399 	}
400 	
401 	@SuppressWarnings("unchecked")
402 	public QName getRequestBodyElementQName() throws Exception
403 	{
404 		WsdlInterface iface = getInterface();
405 		
406 		Definition definition = iface.getWsdlContext().getDefinition();
407 		BindingOperation bindingOperation = findBindingOperation( definition );
408 		if( WsdlUtils.isRpc( definition, bindingOperation))
409 		{
410 			String ns = WsdlUtils.getSoapBodyNamespace( bindingOperation.getBindingInput().getExtensibilityElements() );
411 	      if( ns == null )
412 	      {
413 	      	ns = definition.getTargetNamespace();
414 	      }
415 			
416 			return new QName( ns, bindingOperation.getName() );
417 		}
418 		else
419 		{
420 			Message message = bindingOperation.getOperation().getInput().getMessage();
421 			List<javax.wsdl.Part> parts = message.getOrderedParts( null );
422 			if( parts == null || parts.isEmpty() )
423 				return null;
424 			
425 			int ix = 0;
426 			javax.wsdl.Part part = parts.get( 0 );
427 			
428 			while( part != null && (WsdlUtils.isAttachmentInputPart( part, bindingOperation  ) || WsdlUtils.isHeaderInputPart( part, message, bindingOperation )) )
429 			{
430 				ix++;
431 				if( ix < parts.size() )
432 					part = parts.get( ix );
433 				else 
434 					part = null;
435 			}
436 			
437 			if( part == null )
438 				return null; 
439 			
440 			if( part.getElementName() != null )
441 			{
442 				return part.getElementName();
443 			}
444 			else
445 			{
446 				return new QName( definition.getTargetNamespace(), part.getName() );	
447 			}
448 		}
449 	}
450 	
451 	@SuppressWarnings("unchecked")
452 	public QName getResponseBodyElementQName() throws Exception
453 	{
454 		if( isOneWay() )
455 			return null;
456 		
457 		WsdlInterface iface = getInterface();
458 		
459 		Definition definition = iface.getWsdlContext().getDefinition();
460 		BindingOperation bindingOperation = findBindingOperation( definition );
461 		if( WsdlUtils.isRpc( definition, bindingOperation))
462 		{
463 			String ns = WsdlUtils.getSoapBodyNamespace( bindingOperation.getBindingOutput().getExtensibilityElements() );
464 	      if( ns == null )
465 	      {
466 	      	ns = definition.getTargetNamespace();
467 	      }
468 			
469 			return new QName( ns, bindingOperation.getName() + "Response" );
470 		}
471 		else
472 		{
473 			Message message = bindingOperation.getOperation().getOutput().getMessage();
474 			List<javax.wsdl.Part> parts = message.getOrderedParts( null );
475 			if( parts == null || parts.isEmpty() )
476 				return null;
477 			
478 			int ix = 0;
479 			javax.wsdl.Part part = parts.get( 0 );
480 			
481 			while( part != null && (WsdlUtils.isAttachmentOutputPart( part, bindingOperation  ) || WsdlUtils.isHeaderOutputPart( part, message, bindingOperation )) )
482 			{
483 				ix++;
484 				if( ix < parts.size() )
485 					part = parts.get( ix );
486 				else 
487 					part = null;
488 			}
489 			
490 			if( part == null )
491 				return null; 
492 			
493 			if( part.getElementName() != null )
494 			{
495 				return part.getElementName();
496 			}
497 			else
498 			{
499 				return new QName( definition.getTargetNamespace(), part.getName() );	
500 			}
501 		}
502 	}
503 	
504 	public String getStyle()
505 	{
506 		WsdlContext wsdlContext = iface.getWsdlContext();
507 		if( !wsdlContext.isLoaded() )
508 			return "<not loaded>";
509 		
510 		try
511 		{
512 			Definition definition = wsdlContext.getDefinition();
513 			BindingOperation bindingOperation = findBindingOperation( definition);
514 			
515 			if( bindingOperation == null )
516 				return "<missing bindingOperation>";
517 			
518 			if( WsdlUtils.isRpc( definition, bindingOperation ))
519 			{
520 				return WsdlOperation.STYLE_RPC;
521 			}
522 			else
523 			{
524 				return WsdlOperation.STYLE_DOCUMENT;
525 			}
526 		}
527 		catch (Exception e)
528 		{
529 			SoapUI.logError( e );
530 			return "<error>";
531 		}
532 	}
533 
534 	@Override
535    public void release()
536 	{
537 		super.release();
538 		
539 		for( WsdlRequest request : requests )
540 			request.release();
541 	}
542 
543 	public BindingOperation getBindingOperation()
544 	{
545 		try
546 		{
547 			return findBindingOperation( getInterface().getWsdlContext().getDefinition() );
548 		}
549 		catch( Exception e )
550 		{
551 			SoapUI.logError( e );
552 			return null;
553 		}
554 	}
555 
556 	public List<Request> getRequests()
557 	{
558 		return new ArrayList<Request>( requests );
559 	}
560 
561 	public MessagePart[] getDefaultRequestParts()
562 	{
563 		try
564 		{
565 			// init
566 			List<MessagePart> result = new ArrayList<MessagePart>();
567 			WsdlContext wsdlContext = getInterface().getWsdlContext();
568 			BindingOperation bindingOperation = findBindingOperation(wsdlContext.getDefinition());
569 			
570 			if( bindingOperation == null )
571 				return new MessagePart[0];
572 			
573 			// header parts
574 			List<SoapHeader> headers = WsdlUtils.getSoapHeaders( bindingOperation.getBindingInput()
575 		            .getExtensibilityElements());
576 
577 	      for (int i = 0; i < headers.size(); i++)
578 	      {
579 	      	SoapHeader header = headers.get( i );
580 	         
581 	         Message message = wsdlContext.getDefinition().getMessage( header.getMessage() );
582 	         if( message == null )
583 	         {
584 	         	log.error( "Missing message for header: " + header.getMessage() );
585 	         	continue;
586 	         }
587 	         
588 				javax.wsdl.Part part = message.getPart( header.getPart() );
589 
590 	         if( part != null )
591 	         {
592 	         	SchemaType schemaType = WsdlUtils.getSchemaTypeForPart( wsdlContext, part );
593 	         	SchemaGlobalElement schemaElement = WsdlUtils.getSchemaElementForPart( wsdlContext, part );
594 					if( schemaType != null )
595 						result.add( new WsdlHeaderPart( part.getName(), schemaType, part.getElementName(), schemaElement ));
596 	         }
597 	         else
598 	         	log.error( "Missing part for header; " + header.getPart() );
599 	      }
600 	
601 			// content parts
602 			javax.wsdl.Part[] parts = WsdlUtils.getInputParts( bindingOperation );
603 			
604 			for( int i = 0; i < parts.length; i++ )
605 	      {
606 	      	javax.wsdl.Part part = parts[i];
607 	      	
608 				if( !WsdlUtils.isAttachmentInputPart( part, bindingOperation ))
609 	      	{
610 					SchemaType schemaType = WsdlUtils.getSchemaTypeForPart( wsdlContext, part );
611 					SchemaGlobalElement schemaElement = WsdlUtils.getSchemaElementForPart( wsdlContext, part );
612 					if( schemaType != null )
613 						result.add( new WsdlContentPart( part.getName(), schemaType, part.getElementName(), schemaElement ));
614       	   }
615 	      }
616 			
617 			return result.toArray( new MessagePart[result.size()] );
618 		}
619 		catch (Exception e)
620 		{
621 			SoapUI.logError( e );
622 			return new MessagePart [0];
623 		}		
624 	}
625 	
626 	public MessagePart[] getDefaultResponseParts()
627 	{
628 		try
629 		{
630 			// init
631 			List<MessagePart> result = new ArrayList<MessagePart>();
632 			WsdlContext wsdlContext = getInterface().getWsdlContext();
633 			BindingOperation bindingOperation = findBindingOperation(wsdlContext.getDefinition());
634 			
635 			if( bindingOperation == null )
636 				return new MessagePart[0];
637 			
638 			// header parts
639 			List<SoapHeader> headers = WsdlUtils.getSoapHeaders( bindingOperation.getBindingOutput()
640 			            .getExtensibilityElements());
641 
642 	      for (int i = 0; i < headers.size(); i++)
643 	      {
644 	      	SoapHeader header = headers.get( i );
645 	         
646 	         Message message = wsdlContext.getDefinition().getMessage( header.getMessage() );
647 	         if( message == null )
648 	         {
649 	         	log.error( "Missing message for header: " + header.getMessage() );
650 	         	continue;
651 	         }
652 	         
653 				javax.wsdl.Part part = message.getPart( header.getPart() );
654 
655 	         if( part != null )
656 	         {
657 	         	SchemaType schemaType = WsdlUtils.getSchemaTypeForPart( wsdlContext, part );
658 	         	SchemaGlobalElement schemaElement = WsdlUtils.getSchemaElementForPart( wsdlContext, part );
659 					if( schemaType != null )
660 						result.add( new WsdlHeaderPart( part.getName(), schemaType, part.getElementName(), schemaElement ));
661 	         }
662 	         else
663 	         	log.error( "Missing part for header; " + header.getPart() );
664 	      }
665 	
666 			// content parts
667 			javax.wsdl.Part[] parts = WsdlUtils.getOutputParts( bindingOperation );
668 			
669 			for( int i = 0; i < parts.length; i++ )
670 	      {
671 	      	javax.wsdl.Part part = parts[i];
672 	      	
673 				if( !WsdlUtils.isAttachmentOutputPart( part, bindingOperation ))
674 	      	{
675 					SchemaType schemaType = WsdlUtils.getSchemaTypeForPart( wsdlContext, part );
676 					SchemaGlobalElement schemaElement = WsdlUtils.getSchemaElementForPart( wsdlContext, part );
677 					if( schemaType != null )
678 						result.add( new WsdlContentPart( part.getName(), schemaType, part.getElementName(), schemaElement ));
679       	   }
680 	      }
681 			
682 			return result.toArray( new MessagePart[result.size()] );
683 		}
684 		catch (Exception e)
685 		{
686 			SoapUI.logError( e );
687 			return new MessagePart [0];
688 		}		
689 	}
690 	
691 	public FaultPart [] getFaultParts()
692 	{
693 		BindingOperation bindingOperation = getBindingOperation();
694 		Map bindingFaults = bindingOperation.getBindingFaults();
695 
696 		List<FaultPart> result = new ArrayList<FaultPart>();
697 		for( Object key : bindingFaults.keySet() )
698 		{
699 			result.add( new WsdlFaultPart( (String)key ));
700 		}
701 	
702 		return result.toArray( new FaultPart[result.size()] );
703 	}
704 	
705 	private class WsdlFaultPart extends FaultPart
706 	{
707 		private final String name;
708 
709 		public WsdlFaultPart( String name )
710 		{
711 			this.name = name;
712 		}
713 
714 		@Override
715 		public javax.wsdl.Part[] getWsdlParts()
716 		{
717 			try
718 			{
719 				return WsdlUtils.getFaultParts( getBindingOperation(), name );
720 			}
721 			catch( Exception e )
722 			{
723 				log.error( e.toString(), e );
724 			}
725 			
726 			return new javax.wsdl.Part[0];
727 		}
728 
729 		@Override
730 		public QName getPartElementName()
731 		{
732 			return null;
733 		}
734 
735 		public String getDescription()
736 		{
737 			return null;
738 		}
739 
740 		public String getName()
741 		{
742 			return name;
743 		}
744 
745 		@Override
746 		public SchemaType getSchemaType()
747 		{
748 			return null;
749 		}
750 
751 		@Override
752 		public SchemaGlobalElement getPartElement()
753 		{
754 			return null;
755 		}}
756 
757 	@Override
758 	public void beforeSave()
759 	{
760 		for( WsdlRequest request : requests )
761 			request.beforeSave();
762 	}
763    
764    public List<? extends ModelItem> getChildren()
765    {
766       return getRequests();
767    }
768 }