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.Arrays;
17  import java.util.HashMap;
18  import java.util.HashSet;
19  import java.util.Iterator;
20  import java.util.List;
21  import java.util.Map;
22  import java.util.Set;
23  
24  import javax.wsdl.Binding;
25  import javax.wsdl.BindingOperation;
26  import javax.wsdl.Definition;
27  import javax.wsdl.Port;
28  import javax.wsdl.Service;
29  import javax.xml.namespace.QName;
30  
31  import org.apache.log4j.Logger;
32  
33  import com.eviware.soapui.SoapUI;
34  import com.eviware.soapui.config.DefinitionCacheConfig;
35  import com.eviware.soapui.config.EndpointsConfig;
36  import com.eviware.soapui.config.InterfaceConfig;
37  import com.eviware.soapui.config.OperationConfig;
38  import com.eviware.soapui.config.SoapVersionTypesConfig;
39  import com.eviware.soapui.impl.wsdl.mock.WsdlMockResponse;
40  import com.eviware.soapui.impl.wsdl.support.soap.SoapMessageBuilder;
41  import com.eviware.soapui.impl.wsdl.support.soap.SoapVersion;
42  import com.eviware.soapui.impl.wsdl.support.wsdl.CachedWsdlLoader;
43  import com.eviware.soapui.impl.wsdl.support.wsdl.UrlWsdlLoader;
44  import com.eviware.soapui.impl.wsdl.support.wsdl.WsdlContext;
45  import com.eviware.soapui.impl.wsdl.support.wsdl.WsdlLoader;
46  import com.eviware.soapui.impl.wsdl.support.wsdl.WsdlUtils;
47  import com.eviware.soapui.impl.wsdl.teststeps.WsdlTestRequest;
48  import com.eviware.soapui.impl.wsdl.teststeps.WsdlTestRequestStep;
49  import com.eviware.soapui.model.ModelItem;
50  import com.eviware.soapui.model.iface.Interface;
51  import com.eviware.soapui.model.iface.InterfaceListener;
52  import com.eviware.soapui.model.iface.Operation;
53  import com.eviware.soapui.settings.WsdlSettings;
54  import com.eviware.soapui.support.UISupport;
55  import com.eviware.soapui.support.types.StringList;
56  
57  /***
58   * WSDL implementation of Interface, maps to a WSDL Binding
59   * 
60   * @author Ole.Matzura
61   */
62  
63  public class WsdlInterface extends AbstractWsdlModelItem<InterfaceConfig> implements Interface
64  {
65  	public static final String STYLE_DOCUMENT = "Document";
66  	public static final String STYLE_RPC = "RPC";
67  
68  	public static final String JBOSSWS_ACTIONS = "jbossws";
69  	public static final String WSTOOLS_ACTIONS = "wstools";
70  	public static final String XML_ACTIONS = "xml";
71  
72  	private final static Logger log = Logger.getLogger( WsdlInterface.class );
73  	private List<WsdlOperation> operations = new ArrayList<WsdlOperation>();
74  	private WsdlProject project;
75  	private SoapMessageBuilder soapMessageBuilder;
76  	private WsdlContext wsdlContext;
77  	private Set<InterfaceListener> interfaceListeners = new HashSet<InterfaceListener>();
78  	private boolean updating = false;
79  
80  	public WsdlInterface( WsdlProject project, InterfaceConfig interfaceConfig )
81  	{
82  		super( interfaceConfig, project, "/interface2.gif" );
83  
84  		this.project = project;
85  
86  		if( interfaceConfig.getEndpoints() == null )
87  			interfaceConfig.addNewEndpoints();
88  
89  		List<OperationConfig> operationConfigs = interfaceConfig.getOperationList();
90  		for( int i = 0; i < operationConfigs.size(); i++ )
91  		{
92  			operations.add( new WsdlOperation( this, operationConfigs.get( i ) ) );
93  		}
94  
95  		for( InterfaceListener listener : SoapUI.getListenerRegistry().getListeners( InterfaceListener.class ) )
96  		{
97  			addInterfaceListener( listener );
98  		}
99  	}
100 
101 	public String[] getEndpoints()
102 	{
103 		EndpointsConfig endpoints = getConfig().getEndpoints();
104 		List<String> endpointArray = endpoints.getEndpointList();
105 		return endpointArray.toArray( new String[endpointArray.size()] );
106 	}
107 
108 	public WsdlOperation getOperationAt( int index )
109 	{
110 		return operations.get( index );
111 	}
112 
113 	public int getOperationCount()
114 	{
115 		return operations.size();
116 	}
117 	
118 	public WsdlOperation addNewOperation( BindingOperation operation )
119 	{
120 		WsdlOperation operationImpl = new WsdlOperation( this, getConfig().addNewOperation() );
121 		operations.add( operationImpl );
122 
123 		operationImpl.initFromBindingOperation( operation );
124 		fireOperationAdded( operationImpl );
125 		return operationImpl;
126 	}
127 
128 	public WsdlProject getProject()
129 	{
130 		return project;
131 	}
132 
133 	public void addEndpoint( String endpoint )
134 	{
135 		if( endpoint == null || endpoint.trim().length() == 0 )
136 			return;
137 
138 		endpoint = endpoint.trim();
139 		String[] endpoints = getEndpoints();
140 
141 		// dont add the same endpoint twice
142 		if( Arrays.asList( endpoints ).contains( endpoint ) )
143 			return;
144 
145 		getConfig().getEndpoints().addNewEndpoint().setStringValue( endpoint );
146 
147 		notifyPropertyChanged( ENDPOINT_PROPERTY, null, endpoint );
148 	}
149 
150 	public void changeEndpoint( String oldEndpoint, String newEndpoint )
151 	{
152 		if( oldEndpoint == null || oldEndpoint.trim().length() == 0 )
153 			return;
154 		if( newEndpoint == null || newEndpoint.trim().length() == 0 )
155 			return;
156 
157 		EndpointsConfig endpoints = getConfig().getEndpoints();
158 
159 		for( int c = 0; c < endpoints.sizeOfEndpointArray(); c++ )
160 		{
161 			if( endpoints.getEndpointArray( c ).equals( oldEndpoint ) )
162 			{
163 				endpoints.setEndpointArray( c, newEndpoint );
164 				notifyPropertyChanged( ENDPOINT_PROPERTY, oldEndpoint, newEndpoint );
165 				break;
166 			}
167 		}
168 	}
169 
170 	public void removeEndpoint( String endpoint )
171 	{
172 		EndpointsConfig endpoints = getConfig().getEndpoints();
173 
174 		for( int c = 0; c < endpoints.sizeOfEndpointArray(); c++ )
175 		{
176 			if( endpoints.getEndpointArray( c ).equals( endpoint ) )
177 			{
178 				endpoints.removeEndpoint( c );
179 				notifyPropertyChanged( ENDPOINT_PROPERTY, endpoint, null );
180 				break;
181 			}
182 		}
183 	}
184 
185 	public void setDefinition( String wsdlUrl, boolean cache )
186 	{
187 		String old = getDefinition();
188 
189 		getConfig().setDefinition( wsdlUrl );
190 
191 		if( wsdlContext != null )
192 		{
193 			wsdlContext.setDefinition( wsdlUrl, getConfig().getDefinitionCache() );
194 			wsdlContext.setSoapVersion( getSoapVersion() );
195 		}
196 
197 		notifyPropertyChanged( DEFINITION_PROPERTY, old, wsdlUrl );
198 		
199 		notifyPropertyChanged( UPDATING_PROPERTY, true, false );
200 	}
201 
202 	public DefinitionCacheConfig cacheDefinition( WsdlLoader loader ) throws Exception
203 	{
204 		log.debug( "Caching definition for [" + loader.getBaseURI() + "]" );
205 		if( getConfig().isSetDefinitionCache() )
206 			getConfig().unsetDefinitionCache();
207 
208 		DefinitionCacheConfig definitionCache = getConfig().addNewDefinitionCache();
209 		definitionCache.set( WsdlLoader.cacheWsdl( loader ) );
210 		return definitionCache;
211 	}
212 
213 	public String getDefinition()
214 	{
215 		return getConfig().isSetDefinition() ? getConfig().getDefinition() : null;
216 	}
217 
218 	public synchronized WsdlContext getWsdlContext()
219 	{
220 		if( wsdlContext == null )
221 		{
222 			wsdlContext = new WsdlContext( getDefinition(), getSoapVersion(), getConfig().getDefinitionCache(), this );
223 		}
224 
225 		return wsdlContext;
226 	}
227 
228 	/***
229 	 * Used by importer so we dont need to reload the context after importing..
230 	 * 
231 	 * @param wsdlContext
232 	 */
233 
234 	public void setWsdlContext( WsdlContext wsdlContext )
235 	{
236 		this.wsdlContext = wsdlContext;
237 		this.wsdlContext.setSoapVersion( getSoapVersion() );
238 		this.wsdlContext.setInterface( this );
239 
240 		if( !getConfig().isSetDefinitionCache() )
241 			getConfig().addNewDefinitionCache();
242 
243 		if( wsdlContext.getCacheConfig() != null )
244 		{
245 			// use cache from context
246 			getConfig().setDefinitionCache( wsdlContext.getCacheConfig() );
247 		}
248 	}
249 
250 	public SoapMessageBuilder getMessageBuilder()
251 	{
252 		if( soapMessageBuilder == null )
253 		{
254 			try
255 			{
256 				soapMessageBuilder = new SoapMessageBuilder( this );
257 			}
258 			catch( Exception e )
259 			{
260 				SoapUI.logError( e );
261 			}
262 		}
263 		return soapMessageBuilder;
264 	}
265 
266 	public void setSoapMessageBuilder( SoapMessageBuilder builder )
267 	{
268 		soapMessageBuilder = builder;
269 		soapMessageBuilder.setInterface( this );
270 	}
271 
272 	public QName getBindingName()
273 	{
274 		return getConfig().getBindingName() == null ? null : QName.valueOf( getConfig().getBindingName() );
275 	}
276 
277 	public void setBindingName( QName name )
278 	{
279 		getConfig().setBindingName( name.toString() );
280 	}
281 
282 	public SoapVersion getSoapVersion()
283 	{
284 		if( getConfig().getSoapVersion() == SoapVersionTypesConfig.X_1_2 )
285 			return SoapVersion.Soap12;
286 
287 		return SoapVersion.Soap11;
288 	}
289 
290 	public void setSoapVersion( SoapVersion version )
291 	{
292 		if( version == SoapVersion.Soap11 )
293 			getConfig().setSoapVersion( SoapVersionTypesConfig.X_1_1 );
294 		else if( version == SoapVersion.Soap12 )
295 			getConfig().setSoapVersion( SoapVersionTypesConfig.X_1_2 );
296 		else
297 			throw new RuntimeException( "Unknown soapVersion [" + version + "], must be 1.1 or 1.2" );
298 
299 		getWsdlContext().setSoapVersion( version );
300 	}
301 
302 	public boolean updateDefinition( String url, boolean createRequests ) throws Exception
303 	{
304 		if( getConfig().isSetDefinitionCache() )
305 			getConfig().unsetDefinitionCache();
306 
307 		WsdlContext newContext = getNewContext( url, getSettings().getBoolean( WsdlSettings.CACHE_WSDLS ) );
308 		if( !newContext.load() )
309 		{
310 			return false;
311 		}
312 
313 		BindingTuple tuple = findBinding( newContext );
314 		if( tuple == null )
315 			return false;
316 
317 		setBindingName( tuple.binding.getQName() );
318 
319 		// update name
320 		if( getSettings().getBoolean( WsdlSettings.NAME_WITH_BINDING ) )
321 			setName( tuple.binding.getQName().getLocalPart() );
322 
323 		// update context
324 		wsdlContext = newContext;
325 		if( soapMessageBuilder != null )
326 			soapMessageBuilder.setWsdlContext( wsdlContext );
327 
328 		transferOperations( tuple.binding, createRequests );
329 
330 		setDefinition( url, false );
331 
332 		transferEndpoints( tuple.port );
333 
334 		getProject().fireInterfaceUpdated( this );
335 
336 		return true;
337 	}
338 
339 	public BindingTuple prepareUpdateDefinition( String url ) throws Exception
340 	{
341 		WsdlContext newContext = getNewContext( url, false );
342 		if( !newContext.load() )
343 		{
344 			return null;
345 		}
346 
347 		BindingTuple tuple = findBinding( newContext );
348 		return tuple;
349 	}
350 
351 	public void updateDefinition( BindingTuple tuple ) throws Exception
352 	{
353 		setBindingName( tuple.binding.getQName() );
354 
355 		if( getConfig().isSetDefinitionCache() )
356 			getConfig().unsetDefinitionCache();
357 
358 		// update name
359 		if( getSettings().getBoolean( WsdlSettings.NAME_WITH_BINDING ) )
360 			setName( tuple.binding.getQName().getLocalPart() );
361 
362 		// update context
363 		wsdlContext = tuple.context;
364 		if( soapMessageBuilder != null )
365 			soapMessageBuilder.setWsdlContext( wsdlContext );
366 	}
367 
368 	private WsdlContext getNewContext( String url, boolean cache )
369 	{
370 		if( !cache )
371 		{
372 			return new WsdlContext( url, getSoapVersion(), null, null );
373 		}
374 		else
375 		{
376 			return new WsdlContext( url, getSoapVersion(), null, this );
377 		}
378 	}
379 
380 	public BindingOperation findBindingOperation( Definition definition, String bindingOperationName, String inputName,
381 				String outputName )
382 	{
383 		Binding binding = definition.getBinding( getBindingName() );
384 		return WsdlUtils.findBindingOperation( binding, bindingOperationName, inputName, outputName );
385 	}
386 
387 	@SuppressWarnings( "unchecked" )
388 	private BindingTuple findBinding( WsdlContext newContext ) throws Exception
389 	{
390 		BindingTuple tuple = new BindingTuple();
391 		tuple.context = newContext;
392 
393 		// start by finding the old binding in the new definition
394 		Definition definition = newContext.getDefinition();
395 		Map serviceMap = definition.getAllServices();
396 		Iterator<String> i = serviceMap.keySet().iterator();
397 		while( i.hasNext() )
398 		{
399 			tuple.service = ( Service ) serviceMap.get( i.next() );
400 			Map portMap = tuple.service.getPorts();
401 
402 			Iterator i2 = portMap.keySet().iterator();
403 			while( i2.hasNext() )
404 			{
405 				tuple.port = ( Port ) portMap.get( i2.next() );
406 				if( tuple.port.getBinding().getQName().equals( getBindingName() ) )
407 				{
408 					tuple.binding = tuple.port.getBinding();
409 				}
410 			}
411 
412 			if( tuple.binding != null )
413 				break;
414 			tuple.service = null;
415 		}
416 
417 		if( tuple.service == null && tuple.binding == null )
418 		{
419 			tuple.binding = definition.getBinding( getBindingName() );
420 		}
421 
422 		// missing matching binding, prompt for new one to use instead (will
423 		// happen if binding has been renamed)
424 		if( tuple.binding == null )
425 		{
426 			Map bindings = definition.getAllBindings();
427 
428 			Object retval = UISupport.prompt( "Missing matching binding [" + getBindingName()
429 						+ "] in definition, select new\nbinding to map to", "Map Binding", bindings.keySet().toArray() );
430 
431 			if( retval == null )
432 				return null;
433 
434 			tuple.binding = ( Binding ) bindings.get( retval );
435 		}
436 
437 		return tuple;
438 	}
439 
440 	@SuppressWarnings( "unchecked" )
441 	public void transferOperations( Binding binding, boolean createRequests )
442 	{
443 		// prepare for transfer of operations/requests
444 		List<BindingOperation> newOperations = new ArrayList<BindingOperation>( binding.getBindingOperations() );
445 		Map<String, WsdlOperation> oldOperations = new HashMap<String, WsdlOperation>();
446 		for( int c = 0; c < operations.size(); c++ )
447 			oldOperations.put( operations.get( c ).getBindingOperationName(), operations.get( c ) );
448 
449 		// clear existing from both collections
450 		for( int c = 0; c < newOperations.size(); c++ )
451 		{
452 			BindingOperation newOperation = newOperations.get( c );
453 			String bindingOperationName = newOperation.getName();
454 			if( oldOperations.containsKey( bindingOperationName ) )
455 			{
456 				log.info( "Synchronizing existing operation [" + bindingOperationName + "]" );
457 				WsdlOperation wsdlOperation = oldOperations.get( bindingOperationName );
458 				wsdlOperation.initFromBindingOperation( newOperation );
459 				fireOperationUpdated( wsdlOperation );
460 
461 				oldOperations.remove( bindingOperationName );
462 				newOperations.remove( c );
463 				c--;
464 			}
465 		}
466 
467 		// remove leftover operations
468 		Iterator<String> i = oldOperations.keySet().iterator();
469 		while( i.hasNext() )
470 		{
471 			String name = i.next();
472 
473 			if( newOperations.size() > 0 )
474 			{
475 				List<String> list = new ArrayList<String>();
476 				list.add( "none - delete operation" );
477 				for( int c = 0; c < newOperations.size(); c++ )
478 					list.add( newOperations.get( c ).getName() );
479 
480 				String retval = ( String ) UISupport.prompt( "Binding operation [" + name
481 							+ "] not found in new interface, select new\nbinding operation to map to", "Map Operation", list
482 							.toArray(), "none/cancel - delete operation" );
483 
484 				int ix = retval == null ? -1 : list.indexOf( retval ) - 1;
485 
486 				// delete operation?
487 				if( ix < 0 )
488 				{
489 					deleteOperation( name );
490 				}
491 				// change operation?
492 				else
493 				{
494 					BindingOperation newOperation = newOperations.get( ix );
495 					WsdlOperation wsdlOperation = oldOperations.get( name );
496 					wsdlOperation.initFromBindingOperation( newOperation );
497 					fireOperationUpdated( wsdlOperation );
498 					newOperations.remove( ix );
499 				}
500 
501 				oldOperations.remove( name );
502 			}
503 			else
504 			{
505 				deleteOperation( name );
506 				oldOperations.remove( name );
507 			}
508 
509 			i = oldOperations.keySet().iterator();
510 		}
511 
512 		// add leftover new operations
513 		if( newOperations.size() > 0 )
514 		{
515 			for( int c = 0; c < newOperations.size(); c++ )
516 			{
517 				BindingOperation newOperation = newOperations.get( c );
518 				WsdlOperation wsdlOperation = addNewOperation( newOperation );
519 
520 				if( createRequests )
521 				{
522 					WsdlRequest request = wsdlOperation.addNewRequest( "Request 1" );
523 					try
524 					{
525 						request.setRequestContent( wsdlOperation.createRequest( true ) );
526 					}
527 					catch( Exception e )
528 					{
529 						SoapUI.logError( e );
530 					}
531 				}
532 			}
533 		}
534 	}
535 
536 	public void transferEndpoints( Port port )
537 	{
538 		if( port != null )
539 		{
540 			String endpoint = WsdlUtils.getSoapEndpoint( port );
541 			if( endpoint != null )
542 			{
543 				StringList list = new StringList( getEndpoints() );
544 				if( !list.contains( endpoint ) )
545 				{
546 					if( UISupport.confirm( "Update existing requests with new endpoint\n[" + endpoint + "]",
547 								"Update Definition" ) )
548 					{
549 						for( int c = 0; c < getOperationCount(); c++ )
550 						{
551 							Operation operation = getOperationAt( c );
552 
553 							for( int ix = 0; ix < operation.getRequestCount(); ix++ )
554 							{
555 								operation.getRequestAt( ix ).setEndpoint( endpoint );
556 							}
557 						}
558 					}
559 
560 					addEndpoint( endpoint );
561 				}
562 			}
563 		}
564 	}
565 
566 	public void deleteOperation( String bindingOperationName )
567 	{
568 		for( int c = 0; c < operations.size(); c++ )
569 		{
570 			WsdlOperation wsdlOperation = operations.get( c );
571 			if( wsdlOperation.getBindingOperationName().equals( bindingOperationName ) )
572 			{
573 				log.info( "deleting operation [" + bindingOperationName + "]" );
574 
575 				// remove requests first (should this be done by some listener?)
576 				while( wsdlOperation.getRequestCount() > 0 )
577 					wsdlOperation.removeRequest( wsdlOperation.getRequestAt( 0 ) );
578 
579 				operations.remove( c );
580 
581 				try
582 				{
583 					fireOperationRemoved( wsdlOperation );
584 				}
585 				finally
586 				{
587 					wsdlOperation.release();
588 					getConfig().removeOperation( c );
589 				}
590 
591 				return;
592 			}
593 		}
594 	}
595 	
596 	public void removeOperation( WsdlOperation wsdlOperation )
597    {
598 	   int c = operations.indexOf( wsdlOperation );
599 	   if( c < 0)
600 	      throw new IllegalArgumentException( wsdlOperation.getName() + " not found" );
601 	   
602       log.info( "deleting operation [" + wsdlOperation.getName() + "]" );
603       
604       // remove requests first (should this be done by some listener?)
605       while( wsdlOperation.getRequestCount() > 0 )
606          wsdlOperation.removeRequest( wsdlOperation.getRequestAt( 0 ) );
607 
608       operations.remove( c );
609 
610       try
611       {
612          fireOperationRemoved( wsdlOperation );
613       }
614       finally
615       {
616          wsdlOperation.release();
617          getConfig().removeOperation( c );
618       }
619    }
620 
621 	public void fireOperationAdded( WsdlOperation operation )
622 	{
623 		InterfaceListener[] a = interfaceListeners.toArray( new InterfaceListener[interfaceListeners.size()] );
624 
625 		for( int c = 0; c < a.length; c++ )
626 		{
627 			a[c].operationAdded( operation );
628 		}
629 	}
630 
631 	public void fireOperationUpdated( WsdlOperation operation )
632 	{
633 		InterfaceListener[] a = interfaceListeners.toArray( new InterfaceListener[interfaceListeners.size()] );
634 
635 		for( int c = 0; c < a.length; c++ )
636 		{
637 			a[c].operationUpdated( operation );
638 		}
639 	}
640 
641 	public void fireOperationRemoved( WsdlOperation operation )
642 	{
643 		InterfaceListener[] a = interfaceListeners.toArray( new InterfaceListener[interfaceListeners.size()] );
644 
645 		for( int c = 0; c < a.length; c++ )
646 		{
647 			a[c].operationRemoved( operation );
648 		}
649 	}
650 
651 	public void fireRequestAdded( WsdlRequest request )
652 	{
653 		InterfaceListener[] a = interfaceListeners.toArray( new InterfaceListener[interfaceListeners.size()] );
654 
655 		for( int c = 0; c < a.length; c++ )
656 		{
657 			a[c].requestAdded( request );
658 		}
659 	}
660 
661 	public void fireRequestRemoved( WsdlRequest request )
662 	{
663 		InterfaceListener[] a = interfaceListeners.toArray( new InterfaceListener[interfaceListeners.size()] );
664 
665 		for( int c = 0; c < a.length; c++ )
666 		{
667 			a[c].requestRemoved( request );
668 		}
669 	}
670 
671 	public void addInterfaceListener( InterfaceListener listener )
672 	{
673 		interfaceListeners.add( listener );
674 	}
675 
676 	public void removeInterfaceListener( InterfaceListener listener )
677 	{
678 		interfaceListeners.remove( listener );
679 	}
680 
681 	public WsdlOperation getOperationByName( String name )
682 	{
683 		return ( WsdlOperation ) getWsdlModelItemByName( operations, name );
684 	}
685 
686 	public boolean isCached()
687 	{
688 		return getConfig().isSetDefinitionCache();
689 	}
690 
691 	public WsdlLoader createWsdlLoader()
692 	{
693 		return isCached() ? new CachedWsdlLoader( getConfig().getDefinitionCache() )
694 					: new UrlWsdlLoader( getDefinition() );
695 	}
696 
697 	public void clearCache()
698 	{
699 		if( wsdlContext != null )
700 			wsdlContext.setDefinitionCache( null );
701 
702 		if( getConfig().isSetDefinitionCache() )
703 			getConfig().unsetDefinitionCache();
704 	}
705 
706 	public String getStyle()
707 	{
708 		if( wsdlContext == null || !wsdlContext.isLoaded() )
709 			return "<not loaded>";
710 
711 		try
712 		{
713 			Binding binding = wsdlContext.getDefinition().getBinding( getBindingName() );
714 			if( binding == null )
715 				return "<missing binding>";
716 
717 			if( WsdlUtils.isRpc( binding ) )
718 			{
719 				return STYLE_RPC;
720 			}
721 			else
722 			{
723 				return STYLE_DOCUMENT;
724 			}
725 		}
726 		catch( Exception e )
727 		{
728 			SoapUI.logError( e );
729 			return "<error>";
730 		}
731 	}
732 
733 	@Override
734 	public void release()
735 	{
736 		super.release();
737 
738 		for( WsdlOperation operation : operations )
739 			operation.release();
740 
741 		interfaceListeners.clear();
742 	}
743 
744 	public List<Operation> getOperationList()
745 	{
746 		return new ArrayList<Operation>( operations );
747 	}
748 
749 	@Override
750 	public void beforeSave()
751 	{
752 		for( WsdlOperation operation : operations )
753 			operation.beforeSave();
754 	}
755 
756 	public static class BindingTuple
757 	{
758 		public WsdlContext context = null;
759 		public Service service = null;
760 		public Port port = null;
761 		public Binding binding = null;
762 	}
763 
764 	public List<? extends ModelItem> getChildren()
765 	{
766 		return getOperationList();
767 	}
768 
769 	public boolean isUpdating()
770 	{
771 		return updating;
772 	}
773 
774 	public void setUpdating( boolean updating )
775 	{
776 		if( this.updating == updating )
777 			return;
778 
779 		if( updating )
780 		{
781 			List<AbstractWsdlModelItem> messages = getAllMessages();
782 			for( AbstractWsdlModelItem modelItem : messages )
783 			{
784 				modelItem.beforeSave();
785 			}
786 		}
787 
788 		boolean oldValue = this.updating;
789 		this.updating = updating;
790 
791 		notifyPropertyChanged( UPDATING_PROPERTY, oldValue, updating );
792 	}
793 
794 	public List<AbstractWsdlModelItem> getAllMessages()
795 	{
796 		ArrayList<AbstractWsdlModelItem> list = new ArrayList<AbstractWsdlModelItem>();
797 		getAllMessages( getProject(), list );
798 		return list;
799 	}
800 
801 	private void getAllMessages( ModelItem modelItem, List<AbstractWsdlModelItem> list )
802 	{
803 		if( modelItem instanceof WsdlRequest )
804 		{
805 			WsdlRequest wsdlRequest = ( WsdlRequest ) modelItem;
806 			if( wsdlRequest.getOperation().getInterface() == this )
807 				list.add( wsdlRequest );
808 		}
809 		else if( modelItem instanceof WsdlTestRequestStep )
810 		{
811 			WsdlTestRequestStep testRequestStep = ( WsdlTestRequestStep ) modelItem;
812 			WsdlTestRequest testRequest = testRequestStep.getTestRequest();
813 			if( testRequest.getOperation().getInterface() == this )
814 				list.add( testRequest );
815 		}
816 		else if( modelItem instanceof WsdlMockResponse )
817 		{
818 			WsdlMockResponse mockResponse = ( WsdlMockResponse ) modelItem;
819 			if( mockResponse.getMockOperation().getOperation().getInterface() == this )
820 				list.add( mockResponse );
821 		}
822 
823 		// Traverse the ModelItem hierarchy.
824 		for( ModelItem child : modelItem.getChildren() )
825 		{
826 			getAllMessages( child, list );
827 		}
828 	}
829 }