View Javadoc

1   /*
2    *  soapUI, copyright (C) 2004-2009 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.RestUtils;
31  import com.eviware.soapui.impl.rest.support.XmlBeansRestParamsTestPropertyHolder;
32  import com.eviware.soapui.impl.support.AbstractHttpOperation;
33  import com.eviware.soapui.impl.wsdl.AbstractWsdlModelItem;
34  import com.eviware.soapui.impl.wsdl.MutableTestPropertyHolder;
35  import com.eviware.soapui.model.ModelItem;
36  import com.eviware.soapui.model.iface.MessagePart;
37  import com.eviware.soapui.model.iface.Request;
38  import com.eviware.soapui.model.iface.Attachment.AttachmentEncoding;
39  import com.eviware.soapui.model.propertyexpansion.PropertyExpansionContext;
40  import com.eviware.soapui.model.testsuite.TestProperty;
41  import com.eviware.soapui.model.testsuite.TestPropertyListener;
42  import com.eviware.soapui.support.StringUtils;
43  
44  /***
45   * WSDL implementation of Operation, maps to a WSDL BindingOperation
46   * 
47   * @author Ole.Matzura
48   */
49  
50  public class RestResource extends AbstractWsdlModelItem<RestResourceConfig> implements AbstractHttpOperation,
51  		MutableTestPropertyHolder, RestResourceContainer, PropertyChangeListener
52  {
53  	public static final String PATH_PROPERTY = "path";
54  	private List<RestMethod> methods = new ArrayList<RestMethod>();
55  	private List<RestResource> resources = new ArrayList<RestResource>();
56  	private RestResource parentResource;
57  	private XmlBeansRestParamsTestPropertyHolder params;
58  
59  	public RestResource( RestService service, RestResourceConfig resourceConfig )
60  	{
61  		super( resourceConfig, service, "/rest_resource.gif" );
62  
63  		if( resourceConfig.getParameters() == null )
64  			resourceConfig.addNewParameters();
65  
66  		params = new XmlBeansRestParamsTestPropertyHolder( this, resourceConfig.getParameters() );
67  
68  		for( RestMethodConfig config : resourceConfig.getMethodList() )
69  		{
70  			methods.add( new RestMethod( this, config ) );
71  		}
72  
73  		for( RestResourceConfig config : resourceConfig.getResourceList() )
74  		{
75  			resources.add( new RestResource( this, config ) );
76  		}
77  
78  		for( OldRestRequestConfig config : resourceConfig.getRequestList() )
79  		{
80  			RestRequestConverter.convert( this, config );
81  		}
82  		resourceConfig.setRequestArray( new OldRestRequestConfig[] {} );
83  
84  		service.addPropertyChangeListener( this );
85  	}
86  
87  	public RestResource( RestResource restResource, RestResourceConfig config )
88  	{
89  		this( restResource.getInterface(), config );
90  		this.parentResource = restResource;
91  
92  		parentResource.addPropertyChangeListener( this );
93  	}
94  
95  	public RestResource getParentResource()
96  	{
97  		return parentResource;
98  	}
99  
100 	public RestResourceContainer getResourceContainer()
101 	{
102 		return parentResource == null ? getInterface() : parentResource;
103 	}
104 
105 	public List<? extends ModelItem> getChildren()
106 	{
107 		List<ModelItem> result = new ArrayList<ModelItem>();
108 
109 		result.addAll( getRestMethodList() );
110 		result.addAll( getChildResourceList() );
111 
112 		return result;
113 	}
114 
115 	public MessagePart[] getDefaultRequestParts()
116 	{
117 		return new MessagePart[0];
118 	}
119 
120 	public MessagePart[] getDefaultResponseParts()
121 	{
122 		return new MessagePart[0];
123 	}
124 
125 	public RestService getInterface()
126 	{
127 		return ( RestService )getParent();
128 	}
129 
130 	public String[] getRequestMediaTypes()
131 	{
132 		return new String[0];
133 	}
134 
135 	public String[] getResponseMediaTypes()
136 	{
137 		return new String[0];
138 	}
139 
140 	public RestResource getChildResourceByName( String name )
141 	{
142 		return ( RestResource )getWsdlModelItemByName( resources, name );
143 	}
144 
145 	public RestResource addNewChildResource( String name, String path )
146 	{
147 		RestResourceConfig resourceConfig = getConfig().addNewResource();
148 		resourceConfig.setName( name );
149 		resourceConfig.setPath( path );
150 
151 		RestResource resource = new RestResource( this, resourceConfig );
152 		resources.add( resource );
153 
154 		getInterface().fireOperationAdded( resource );
155 
156 		notifyPropertyChanged( "childResources", null, resource );
157 
158 		return resource;
159 	}
160 
161 	public int getChildResourceCount()
162 	{
163 		return resources.size();
164 	}
165 
166 	public List<RestResource> getChildResourceList()
167 	{
168 		return new ArrayList<RestResource>( resources );
169 	}
170 
171 	public RestRequest getRequestAt( int index )
172 	{
173 		for( RestMethod m : methods )
174 		{
175 			if( index < m.getRequestCount() )
176 				return m.getRequestAt( index );
177 			else
178 				index -= m.getRequestCount();
179 		}
180 		throw new IndexOutOfBoundsException();
181 	}
182 
183 	public RestRequest getRequestByName( String name )
184 	{
185 		for( RestMethod m : methods )
186 		{
187 			RestRequest r = m.getRequestByName( name );
188 			if( r != null )
189 				return r;
190 		}
191 		return null;
192 	}
193 
194 	public RestMethod addNewMethod( String name )
195 	{
196 		RestMethodConfig methodConfig = getConfig().addNewMethod();
197 		methodConfig.setName( name );
198 
199 		RestMethod method = new RestMethod( this, methodConfig );
200 		/*
201 		 * for (RestParamProperty prop : getDefaultParams()) { if
202 		 * (!method.hasProperty(prop.getName()))
203 		 * method.addProperty(prop.getName()).setValue(prop.getDefaultValue()); }
204 		 */
205 		methods.add( method );
206 
207 		notifyPropertyChanged( "childMethods", null, method );
208 		return method;
209 	}
210 
211 	public int getRestMethodCount()
212 	{
213 		return methods.size();
214 	}
215 
216 	public List<RestMethod> getRestMethodList()
217 	{
218 		return new ArrayList<RestMethod>( methods );
219 	}
220 
221 	public RestMethod getRestMethodByName( String name )
222 	{
223 		return ( RestMethod )getWsdlModelItemByName( methods, name );
224 	}
225 
226 	public int getRequestCount()
227 	{
228 		int size = 0;
229 		for( RestMethod m : methods )
230 			size += m.getRequestCount();
231 		return size;
232 	}
233 
234 	public List<Request> getRequestList()
235 	{
236 		List<Request> rs = new ArrayList<Request>();
237 		for( RestMethod m : methods )
238 			rs.addAll( m.getRequestList() );
239 		return rs;
240 	}
241 
242 	public String getPath()
243 	{
244 		return getConfig().getPath();
245 	}
246 
247 	public void setPath( String path )
248 	{
249 		String old = getPath();
250 		getConfig().setPath( path );
251 		notifyPropertyChanged( "path", old, path );
252 
253 		for( String param : RestUtils.extractTemplateParams( path ) )
254 		{
255 			if( !hasProperty( param ) )
256 				addProperty( param );
257 		}
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 }