/*
* soapUI, copyright (C) 2004-2011 eviware.com
*
* soapUI is free software; you can redistribute it and/or modify it under the
* terms of version 2.1 of the GNU Lesser General Public License as published by
* the Free Software Foundation.
*
* soapUI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details at gnu.org.
*/
package com.eviware.soapui.impl.rest;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.eviware.soapui.config.OldRestRequestConfig;
import com.eviware.soapui.config.RestMethodConfig;
import com.eviware.soapui.config.RestResourceConfig;
import com.eviware.soapui.impl.rest.support.RestParamProperty;
import com.eviware.soapui.impl.rest.support.RestParamsPropertyHolder;
import com.eviware.soapui.impl.rest.support.RestRequestConverter;
import com.eviware.soapui.impl.rest.support.XmlBeansRestParamsTestPropertyHolder;
import com.eviware.soapui.impl.support.AbstractHttpOperation;
import com.eviware.soapui.impl.wsdl.AbstractWsdlModelItem;
import com.eviware.soapui.impl.wsdl.MutableTestPropertyHolder;
import com.eviware.soapui.model.ModelItem;
import com.eviware.soapui.model.iface.Attachment.AttachmentEncoding;
import com.eviware.soapui.model.iface.MessagePart;
import com.eviware.soapui.model.iface.Request;
import com.eviware.soapui.model.propertyexpansion.PropertyExpansionContext;
import com.eviware.soapui.model.testsuite.TestProperty;
import com.eviware.soapui.model.testsuite.TestPropertyListener;
import com.eviware.soapui.support.StringUtils;
/**
* WSDL implementation of Operation, maps to a WSDL BindingOperation
*
* @author Ole.Matzura
*/
public class RestResource extends AbstractWsdlModelItem<RestResourceConfig> implements AbstractHttpOperation,
MutableTestPropertyHolder, RestResourceContainer, PropertyChangeListener
{
public static final String PATH_PROPERTY = "path";
private List<RestMethod> methods = new ArrayList<RestMethod>();
private List<RestResource> resources = new ArrayList<RestResource>();
private RestResource parentResource;
private XmlBeansRestParamsTestPropertyHolder params;
public RestResource( RestService service, RestResourceConfig resourceConfig )
{
this( service, null, resourceConfig );
}
public RestResource( RestResource restResource, RestResourceConfig resourceConfig )
{
this( restResource.getInterface(), restResource, resourceConfig );
parentResource.addPropertyChangeListener( this );
}
private RestResource( RestService service, RestResource parent, RestResourceConfig resourceConfig )
{
super( resourceConfig, service, "/rest_resource.gif" );
parentResource = parent;
if( resourceConfig.getParameters() == null )
resourceConfig.addNewParameters();
params = new XmlBeansRestParamsTestPropertyHolder( this, resourceConfig.getParameters() );
for( RestMethodConfig config : resourceConfig.getMethodList() )
{
methods.add( new RestMethod( this, config ) );
}
for( RestResourceConfig config : resourceConfig.getResourceList() )
{
resources.add( new RestResource( this, config ) );
}
for( OldRestRequestConfig config : resourceConfig.getRequestList() )
{
RestRequestConverter.convert( this, config );
}
resourceConfig.setRequestArray( new OldRestRequestConfig[] {} );
service.addPropertyChangeListener( this );
}
public RestResource getParentResource()
{
return parentResource;
}
public RestResourceContainer getResourceContainer()
{
return parentResource == null ? getInterface() : parentResource;
}
@Override
public List<? extends ModelItem> getChildren()
{
List<ModelItem> result = new ArrayList<ModelItem>();
result.addAll( getRestMethodList() );
result.addAll( getChildResourceList() );
return result;
}
public MessagePart[] getDefaultRequestParts()
{
return new MessagePart[0];
}
public MessagePart[] getDefaultResponseParts()
{
return new MessagePart[0];
}
public RestService getInterface()
{
return ( RestService )getParent();
}
public String[] getRequestMediaTypes()
{
return new String[0];
}
public String[] getResponseMediaTypes()
{
return new String[0];
}
public RestResource getChildResourceByName( String name )
{
return ( RestResource )getWsdlModelItemByName( resources, name );
}
public RestResource addNewChildResource( String name, String path )
{
RestResourceConfig resourceConfig = getConfig().addNewResource();
resourceConfig.setName( name );
resourceConfig.setPath( path );
RestResource resource = new RestResource( this, resourceConfig );
resources.add( resource );
getInterface().fireOperationAdded( resource );
notifyPropertyChanged( "childResources", null, resource );
return resource;
}
public int getChildResourceCount()
{
return resources.size();
}
public List<RestResource> getChildResourceList()
{
return new ArrayList<RestResource>( resources );
}
public RestRequest getRequestAt( int index )
{
for( RestMethod m : methods )
{
if( index < m.getRequestCount() )
return m.getRequestAt( index );
else
index -= m.getRequestCount();
}
throw new IndexOutOfBoundsException();
}
public RestRequest getRequestByName( String name )
{
for( RestMethod m : methods )
{
RestRequest r = m.getRequestByName( name );
if( r != null )
return r;
}
return null;
}
public RestMethod addNewMethod( String name )
{
RestMethodConfig methodConfig = getConfig().addNewMethod();
methodConfig.setName( name );
RestMethod method = new RestMethod( this, methodConfig );
/*
* for (RestParamProperty prop : getDefaultParams()) { if
* (!method.hasProperty(prop.getName()))
* method.addProperty(prop.getName()).setValue(prop.getDefaultValue()); }
*/
methods.add( method );
notifyPropertyChanged( "childMethods", null, method );
return method;
}
public int getRestMethodCount()
{
return methods.size();
}
public List<RestMethod> getRestMethodList()
{
return new ArrayList<RestMethod>( methods );
}
public RestMethod getRestMethodByName( String name )
{
return ( RestMethod )getWsdlModelItemByName( methods, name );
}
public int getRequestCount()
{
int size = 0;
for( RestMethod m : methods )
size += m.getRequestCount();
return size;
}
public List<Request> getRequestList()
{
List<Request> rs = new ArrayList<Request>();
for( RestMethod m : methods )
rs.addAll( m.getRequestList() );
return rs;
}
public String getPath()
{
return getConfig().getPath();
}
public void setPath( String path )
{
String old = getPath();
getConfig().setPath( path );
notifyPropertyChanged( "path", old, path );
}
public boolean isBidirectional()
{
return false;
}
public boolean isNotification()
{
return false;
}
public boolean isOneWay()
{
return false;
}
public boolean isRequestResponse()
{
return true;
}
public boolean isSolicitResponse()
{
return false;
}
public boolean isUnidirectional()
{
return false;
}
public AttachmentEncoding getAttachmentEncoding( String part, boolean isRequest )
{
return AttachmentEncoding.NONE;
}
public RestParamProperty[] getDefaultParams()
{
List<RestParamProperty> result = new ArrayList<RestParamProperty>();
Set<String> names = new HashSet<String>();
if( parentResource != null )
result.addAll( Arrays.asList( parentResource.getDefaultParams() ) );
for( int c = 0; c < getPropertyCount(); c++ )
{
if( names.contains( getPropertyAt( c ).getName() ) )
continue;
result.add( getPropertyAt( c ) );
names.add( getPropertyAt( c ).getName() );
}
return result.toArray( new RestParamProperty[result.size()] );
}
public String getFullPath()
{
return getFullPath( true );
}
public String getFullPath( boolean includeBasePath )
{
String base = parentResource == null ? ( includeBasePath ? getInterface().getBasePath() : "" ) : parentResource
.getFullPath( includeBasePath );
String path = getPath();
if( StringUtils.hasContent( path ) && base != null && !base.endsWith( "/" ) && !path.startsWith( "/" ) )
base += "/";
return path == null ? base : base + path;
}
public RestParamProperty addProperty( String name )
{
return params.addProperty( name );
}
public void moveProperty( String propertyName, int targetIndex )
{
params.moveProperty( propertyName, targetIndex );
}
public RestParamProperty removeProperty( String propertyName )
{
return params.removeProperty( propertyName );
}
public boolean renameProperty( String name, String newName )
{
return params.renameProperty( name, newName );
}
public void addTestPropertyListener( TestPropertyListener listener )
{
params.addTestPropertyListener( listener );
}
public RestParamsPropertyHolder getParams()
{
return params;
}
public ModelItem getModelItem()
{
return this;
}
public Map<String, TestProperty> getProperties()
{
return params.getProperties();
}
public RestParamProperty getProperty( String name )
{
return params.getProperty( name );
}
public RestParamProperty getPropertyAt( int index )
{
return params.getPropertyAt( index );
}
public int getPropertyCount()
{
return params.getPropertyCount();
}
public String[] getPropertyNames()
{
return params.getPropertyNames();
}
public String getPropertyValue( String name )
{
return params.getPropertyValue( name );
}
public boolean hasProperty( String name )
{
return params.hasProperty( name );
}
public void removeTestPropertyListener( TestPropertyListener listener )
{
params.removeTestPropertyListener( listener );
}
public void setPropertyValue( String name, String value )
{
params.setPropertyValue( name, value );
}
public String getPropertiesLabel()
{
return "Resource Params";
}
public String buildPath( PropertyExpansionContext context )
{
return getFullPath( true );
}
public RestResource cloneChildResource( RestResource resource, String name )
{
return cloneResource( resource, name );
}
public RestResource cloneResource( RestResource resource, String name )
{
RestResourceConfig resourceConfig = ( RestResourceConfig )getConfig().addNewResource().set( resource.getConfig() );
resourceConfig.setName( name );
RestResource newResource = new RestResource( this, resourceConfig );
resources.add( newResource );
getInterface().fireOperationAdded( newResource );
return newResource;
}
public RestMethod cloneMethod( RestMethod method, String name )
{
RestMethodConfig methodConfig = ( RestMethodConfig )getConfig().addNewMethod().set( method.getConfig() );
methodConfig.setName( name );
RestMethod newMethod = new RestMethod( this, methodConfig );
methods.add( newMethod );
notifyPropertyChanged( "childMethods", null, newMethod );
return newMethod;
}
@Override
public void release()
{
super.release();
params.release();
getService().removePropertyChangeListener( this );
if( parentResource != null )
parentResource.removePropertyChangeListener( this );
for( RestResource resource : resources )
{
resource.release();
}
for( RestMethod method : methods )
{
method.release();
}
}
public void deleteMethod( RestMethod method )
{
int ix = methods.indexOf( method );
if( !methods.remove( method ) )
return;
notifyPropertyChanged( "childMethods", method, null );
method.release();
getConfig().removeMethod( ix );
}
public void deleteChildResource( RestResource resource )
{
deleteResource( resource );
}
public void deleteResource( RestResource resource )
{
int ix = resources.indexOf( resource );
if( !resources.remove( resource ) )
return;
getInterface().fireOperationRemoved( resource );
notifyPropertyChanged( "childResources", resource, null );
getConfig().removeResource( ix );
resource.release();
}
public String createRequest( boolean b )
{
return null;
}
public String createResponse( boolean b )
{
return null;
}
public RestResource getChildResourceAt( int c )
{
return resources.get( c );
}
public RestMethod getRestMethodAt( int c )
{
return methods.get( c );
}
public RestService getService()
{
return ( RestService )( getParentResource() == null ? getParent() : getParentResource().getService() );
}
public void propertyChange( PropertyChangeEvent evt )
{
if( evt.getPropertyName().equals( "path" ) || evt.getPropertyName().equals( "basePath" ) )
{
notifyPropertyChanged( "path", null, getPath() );
}
}
public RestResource[] getAllChildResources()
{
List<RestResource> result = new ArrayList<RestResource>();
for( RestResource resource : resources )
{
addResourcesToResult( resource, result );
}
return result.toArray( new RestResource[result.size()] );
}
private void addResourcesToResult( RestResource resource, List<RestResource> result )
{
result.add( resource );
for( RestResource res : resource.getChildResourceList() )
{
addResourcesToResult( res, result );
}
}
public List<TestProperty> getPropertyList()
{
return params.getPropertyList();
}
}