View Javadoc

1   /*
2    *  soapUI, copyright (C) 2004-2010 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.rest;
14  
15  import java.beans.PropertyChangeEvent;
16  import java.beans.PropertyChangeListener;
17  import java.util.ArrayList;
18  import java.util.Arrays;
19  import java.util.HashSet;
20  import java.util.List;
21  import java.util.Map;
22  import java.util.Set;
23  
24  import com.eviware.soapui.config.OldRestRequestConfig;
25  import com.eviware.soapui.config.RestMethodConfig;
26  import com.eviware.soapui.config.RestResourceConfig;
27  import com.eviware.soapui.impl.rest.support.RestParamProperty;
28  import com.eviware.soapui.impl.rest.support.RestParamsPropertyHolder;
29  import com.eviware.soapui.impl.rest.support.RestRequestConverter;
30  import com.eviware.soapui.impl.rest.support.XmlBeansRestParamsTestPropertyHolder;
31  import com.eviware.soapui.impl.support.AbstractHttpOperation;
32  import com.eviware.soapui.impl.wsdl.AbstractWsdlModelItem;
33  import com.eviware.soapui.impl.wsdl.MutableTestPropertyHolder;
34  import com.eviware.soapui.model.ModelItem;
35  import com.eviware.soapui.model.iface.MessagePart;
36  import com.eviware.soapui.model.iface.Request;
37  import com.eviware.soapui.model.iface.Attachment.AttachmentEncoding;
38  import com.eviware.soapui.model.propertyexpansion.PropertyExpansionContext;
39  import com.eviware.soapui.model.testsuite.TestProperty;
40  import com.eviware.soapui.model.testsuite.TestPropertyListener;
41  import com.eviware.soapui.support.StringUtils;
42  
43  /***
44   * WSDL implementation of Operation, maps to a WSDL BindingOperation
45   * 
46   * @author Ole.Matzura
47   */
48  
49  public class RestResource extends AbstractWsdlModelItem<RestResourceConfig> implements AbstractHttpOperation,
50  		MutableTestPropertyHolder, RestResourceContainer, PropertyChangeListener
51  {
52  	public static final String PATH_PROPERTY = "path";
53  	private List<RestMethod> methods = new ArrayList<RestMethod>();
54  	private List<RestResource> resources = new ArrayList<RestResource>();
55  	private RestResource parentResource;
56  	private XmlBeansRestParamsTestPropertyHolder params;
57  
58  	public RestResource( RestService service, RestResourceConfig resourceConfig )
59  	{
60  		this( service, null, resourceConfig );
61  	}
62  
63  	public RestResource( RestResource restResource, RestResourceConfig resourceConfig )
64  	{
65  		this( restResource.getInterface(), restResource, resourceConfig );
66  
67  		parentResource.addPropertyChangeListener( this );
68  	}
69  
70  	private RestResource( RestService service, RestResource parent, RestResourceConfig resourceConfig )
71  	{
72  		super( resourceConfig, service, "/rest_resource.gif" );
73  
74  		parentResource = parent;
75  
76  		if( resourceConfig.getParameters() == null )
77  			resourceConfig.addNewParameters();
78  
79  		params = new XmlBeansRestParamsTestPropertyHolder( this, resourceConfig.getParameters() );
80  
81  		for( RestMethodConfig config : resourceConfig.getMethodList() )
82  		{
83  			methods.add( new RestMethod( this, config ) );
84  		}
85  
86  		for( RestResourceConfig config : resourceConfig.getResourceList() )
87  		{
88  			resources.add( new RestResource( this, config ) );
89  		}
90  
91  		for( OldRestRequestConfig config : resourceConfig.getRequestList() )
92  		{
93  			RestRequestConverter.convert( this, config );
94  		}
95  		resourceConfig.setRequestArray( new OldRestRequestConfig[] {} );
96  
97  		service.addPropertyChangeListener( this );
98  	}
99  
100 	public RestResource getParentResource()
101 	{
102 		return parentResource;
103 	}
104 
105 	public RestResourceContainer getResourceContainer()
106 	{
107 		return parentResource == null ? getInterface() : parentResource;
108 	}
109 
110 	@Override
111 	public List<? extends ModelItem> getChildren()
112 	{
113 		List<ModelItem> result = new ArrayList<ModelItem>();
114 
115 		result.addAll( getRestMethodList() );
116 		result.addAll( getChildResourceList() );
117 
118 		return result;
119 	}
120 
121 	public MessagePart[] getDefaultRequestParts()
122 	{
123 		return new MessagePart[0];
124 	}
125 
126 	public MessagePart[] getDefaultResponseParts()
127 	{
128 		return new MessagePart[0];
129 	}
130 
131 	public RestService getInterface()
132 	{
133 		return ( RestService )getParent();
134 	}
135 
136 	public String[] getRequestMediaTypes()
137 	{
138 		return new String[0];
139 	}
140 
141 	public String[] getResponseMediaTypes()
142 	{
143 		return new String[0];
144 	}
145 
146 	public RestResource getChildResourceByName( String name )
147 	{
148 		return ( RestResource )getWsdlModelItemByName( resources, name );
149 	}
150 
151 	public RestResource addNewChildResource( String name, String path )
152 	{
153 		RestResourceConfig resourceConfig = getConfig().addNewResource();
154 		resourceConfig.setName( name );
155 		resourceConfig.setPath( path );
156 
157 		RestResource resource = new RestResource( this, resourceConfig );
158 		resources.add( resource );
159 
160 		getInterface().fireOperationAdded( resource );
161 
162 		notifyPropertyChanged( "childResources", null, resource );
163 
164 		return resource;
165 	}
166 
167 	public int getChildResourceCount()
168 	{
169 		return resources.size();
170 	}
171 
172 	public List<RestResource> getChildResourceList()
173 	{
174 		return new ArrayList<RestResource>( resources );
175 	}
176 
177 	public RestRequest getRequestAt( int index )
178 	{
179 		for( RestMethod m : methods )
180 		{
181 			if( index < m.getRequestCount() )
182 				return m.getRequestAt( index );
183 			else
184 				index -= m.getRequestCount();
185 		}
186 		throw new IndexOutOfBoundsException();
187 	}
188 
189 	public RestRequest getRequestByName( String name )
190 	{
191 		for( RestMethod m : methods )
192 		{
193 			RestRequest r = m.getRequestByName( name );
194 			if( r != null )
195 				return r;
196 		}
197 		return null;
198 	}
199 
200 	public RestMethod addNewMethod( String name )
201 	{
202 		RestMethodConfig methodConfig = getConfig().addNewMethod();
203 		methodConfig.setName( name );
204 
205 		RestMethod method = new RestMethod( this, methodConfig );
206 		/*
207 		 * for (RestParamProperty prop : getDefaultParams()) { if
208 		 * (!method.hasProperty(prop.getName()))
209 		 * method.addProperty(prop.getName()).setValue(prop.getDefaultValue()); }
210 		 */
211 		methods.add( method );
212 
213 		notifyPropertyChanged( "childMethods", null, method );
214 		return method;
215 	}
216 
217 	public int getRestMethodCount()
218 	{
219 		return methods.size();
220 	}
221 
222 	public List<RestMethod> getRestMethodList()
223 	{
224 		return new ArrayList<RestMethod>( methods );
225 	}
226 
227 	public RestMethod getRestMethodByName( String name )
228 	{
229 		return ( RestMethod )getWsdlModelItemByName( methods, name );
230 	}
231 
232 	public int getRequestCount()
233 	{
234 		int size = 0;
235 		for( RestMethod m : methods )
236 			size += m.getRequestCount();
237 		return size;
238 	}
239 
240 	public List<Request> getRequestList()
241 	{
242 		List<Request> rs = new ArrayList<Request>();
243 		for( RestMethod m : methods )
244 			rs.addAll( m.getRequestList() );
245 		return rs;
246 	}
247 
248 	public String getPath()
249 	{
250 		return getConfig().getPath();
251 	}
252 
253 	public void setPath( String path )
254 	{
255 		String old = getPath();
256 		getConfig().setPath( path );
257 		notifyPropertyChanged( "path", old, path );
258 	}
259 
260 	public boolean isBidirectional()
261 	{
262 		return false;
263 	}
264 
265 	public boolean isNotification()
266 	{
267 		return false;
268 	}
269 
270 	public boolean isOneWay()
271 	{
272 		return false;
273 	}
274 
275 	public boolean isRequestResponse()
276 	{
277 		return true;
278 	}
279 
280 	public boolean isSolicitResponse()
281 	{
282 		return false;
283 	}
284 
285 	public boolean isUnidirectional()
286 	{
287 		return false;
288 	}
289 
290 	public AttachmentEncoding getAttachmentEncoding( String part, boolean isRequest )
291 	{
292 		return AttachmentEncoding.NONE;
293 	}
294 
295 	public RestParamProperty[] getDefaultParams()
296 	{
297 		List<RestParamProperty> result = new ArrayList<RestParamProperty>();
298 		Set<String> names = new HashSet<String>();
299 
300 		if( parentResource != null )
301 			result.addAll( Arrays.asList( parentResource.getDefaultParams() ) );
302 
303 		for( int c = 0; c < getPropertyCount(); c++ )
304 		{
305 			if( names.contains( getPropertyAt( c ).getName() ) )
306 				continue;
307 
308 			result.add( getPropertyAt( c ) );
309 			names.add( getPropertyAt( c ).getName() );
310 		}
311 
312 		return result.toArray( new RestParamProperty[result.size()] );
313 	}
314 
315 	public String getFullPath()
316 	{
317 		return getFullPath( true );
318 	}
319 
320 	public String getFullPath( boolean includeBasePath )
321 	{
322 		String base = parentResource == null ? ( includeBasePath ? getInterface().getBasePath() : "" ) : parentResource
323 				.getFullPath( includeBasePath );
324 
325 		String path = getPath();
326 		if( StringUtils.hasContent( path ) && base != null && !base.endsWith( "/" ) && !path.startsWith( "/" ) )
327 			base += "/";
328 
329 		return path == null ? base : base + path;
330 	}
331 
332 	public RestParamProperty addProperty( String name )
333 	{
334 		return params.addProperty( name );
335 	}
336 
337 	public void moveProperty( String propertyName, int targetIndex )
338 	{
339 		params.moveProperty( propertyName, targetIndex );
340 	}
341 
342 	public RestParamProperty removeProperty( String propertyName )
343 	{
344 		return params.removeProperty( propertyName );
345 	}
346 
347 	public boolean renameProperty( String name, String newName )
348 	{
349 		return params.renameProperty( name, newName );
350 	}
351 
352 	public void addTestPropertyListener( TestPropertyListener listener )
353 	{
354 		params.addTestPropertyListener( listener );
355 	}
356 
357 	public RestParamsPropertyHolder getParams()
358 	{
359 		return params;
360 	}
361 
362 	public ModelItem getModelItem()
363 	{
364 		return this;
365 	}
366 
367 	public Map<String, TestProperty> getProperties()
368 	{
369 		return params.getProperties();
370 	}
371 
372 	public RestParamProperty getProperty( String name )
373 	{
374 		return params.getProperty( name );
375 	}
376 
377 	public RestParamProperty getPropertyAt( int index )
378 	{
379 		return params.getPropertyAt( index );
380 	}
381 
382 	public int getPropertyCount()
383 	{
384 		return params.getPropertyCount();
385 	}
386 
387 	public String[] getPropertyNames()
388 	{
389 		return params.getPropertyNames();
390 	}
391 
392 	public String getPropertyValue( String name )
393 	{
394 		return params.getPropertyValue( name );
395 	}
396 
397 	public boolean hasProperty( String name )
398 	{
399 		return params.hasProperty( name );
400 	}
401 
402 	public void removeTestPropertyListener( TestPropertyListener listener )
403 	{
404 		params.removeTestPropertyListener( listener );
405 	}
406 
407 	public void setPropertyValue( String name, String value )
408 	{
409 		params.setPropertyValue( name, value );
410 	}
411 
412 	public String getPropertiesLabel()
413 	{
414 		return "Resource Params";
415 	}
416 
417 	public String buildPath( PropertyExpansionContext context )
418 	{
419 		return getFullPath( true );
420 	}
421 
422 	public RestResource cloneChildResource( RestResource resource, String name )
423 	{
424 		return cloneResource( resource, name );
425 	}
426 
427 	public RestResource cloneResource( RestResource resource, String name )
428 	{
429 		RestResourceConfig resourceConfig = ( RestResourceConfig )getConfig().addNewResource().set( resource.getConfig() );
430 		resourceConfig.setName( name );
431 
432 		RestResource newResource = new RestResource( this, resourceConfig );
433 		resources.add( newResource );
434 
435 		getInterface().fireOperationAdded( newResource );
436 		return newResource;
437 	}
438 
439 	public RestMethod cloneMethod( RestMethod method, String name )
440 	{
441 		RestMethodConfig methodConfig = ( RestMethodConfig )getConfig().addNewMethod().set( method.getConfig() );
442 		methodConfig.setName( name );
443 
444 		RestMethod newMethod = new RestMethod( this, methodConfig );
445 		methods.add( newMethod );
446 
447 		notifyPropertyChanged( "childMethods", null, newMethod );
448 		return newMethod;
449 	}
450 
451 	@Override
452 	public void release()
453 	{
454 		super.release();
455 		params.release();
456 		getService().removePropertyChangeListener( this );
457 		if( parentResource != null )
458 			parentResource.removePropertyChangeListener( this );
459 
460 		for( RestResource resource : resources )
461 		{
462 			resource.release();
463 		}
464 		for( RestMethod method : methods )
465 		{
466 			method.release();
467 		}
468 	}
469 
470 	public void deleteMethod( RestMethod method )
471 	{
472 		int ix = methods.indexOf( method );
473 		if( !methods.remove( method ) )
474 			return;
475 		notifyPropertyChanged( "childMethods", method, null );
476 		method.release();
477 		getConfig().removeMethod( ix );
478 	}
479 
480 	public void deleteChildResource( RestResource resource )
481 	{
482 		deleteResource( resource );
483 	}
484 
485 	public void deleteResource( RestResource resource )
486 	{
487 		int ix = resources.indexOf( resource );
488 		if( !resources.remove( resource ) )
489 			return;
490 
491 		getInterface().fireOperationRemoved( resource );
492 
493 		notifyPropertyChanged( "childResources", resource, null );
494 
495 		getConfig().removeResource( ix );
496 		resource.release();
497 	}
498 
499 	public String createRequest( boolean b )
500 	{
501 		return null;
502 	}
503 
504 	public String createResponse( boolean b )
505 	{
506 		return null;
507 	}
508 
509 	public RestResource getChildResourceAt( int c )
510 	{
511 		return resources.get( c );
512 	}
513 
514 	public RestMethod getRestMethodAt( int c )
515 	{
516 		return methods.get( c );
517 	}
518 
519 	public RestService getService()
520 	{
521 		return ( RestService )( getParentResource() == null ? getParent() : getParentResource().getService() );
522 	}
523 
524 	public void propertyChange( PropertyChangeEvent evt )
525 	{
526 		if( evt.getPropertyName().equals( "path" ) || evt.getPropertyName().equals( "basePath" ) )
527 		{
528 			notifyPropertyChanged( "path", null, getPath() );
529 		}
530 	}
531 
532 	public RestResource[] getAllChildResources()
533 	{
534 		List<RestResource> result = new ArrayList<RestResource>();
535 		for( RestResource resource : resources )
536 		{
537 			addResourcesToResult( resource, result );
538 		}
539 
540 		return result.toArray( new RestResource[result.size()] );
541 	}
542 
543 	private void addResourcesToResult( RestResource resource, List<RestResource> result )
544 	{
545 		result.add( resource );
546 
547 		for( RestResource res : resource.getChildResourceList() )
548 		{
549 			addResourcesToResult( res, result );
550 		}
551 	}
552 
553 	public List<TestProperty> getPropertyList()
554 	{
555 		return params.getPropertyList();
556 	}
557 
558 }