Merged FILE-FOLDER-API (5.2.0) to HEAD (5.2)

121907 gjames: RA-774 Renaming action to operation


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@126435 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Jamal Kaabi-Mofrad
2016-05-10 10:54:32 +00:00
parent 0632a4db9a
commit bd65bbf529
11 changed files with 71 additions and 76 deletions

View File

@@ -21,7 +21,7 @@ package org.alfresco.rest.api.nodes;
import org.alfresco.rest.api.Nodes;
import org.alfresco.rest.api.model.Node;
import org.alfresco.rest.api.model.NodeTarget;
import org.alfresco.rest.framework.Action;
import org.alfresco.rest.framework.Operation;
import org.alfresco.rest.framework.BinaryProperties;
import org.alfresco.rest.framework.WebApiDescription;
import org.alfresco.rest.framework.WebApiParam;
@@ -123,14 +123,14 @@ public class NodesEntityResource implements
nodes.deleteNode(nodeId);
}
@Action("copy")
@Operation("copy")
@WebApiDescription(title = "Copy Node", description="Copy one or more nodes (files or folders) to a new target folder, with option to rename.")
public Node copyById(String nodeId, NodeTarget target, Parameters parameters)
{
return nodes.copyNode(nodeId, target.getTargetParentId(), target.getName(), parameters);
}
@Action("move")
@Operation("move")
@WebApiDescription(title = "Move Node", description="Moves one or more nodes (files or folders) to a new target folder, with option to rename.")
public Node moveById(String nodeId, NodeTarget target, Parameters parameters)
{

View File

@@ -6,13 +6,13 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* An action as on an entity in the Rest API
* An Operation as on an entity in the Rest API
*
* @author Gethin James
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Action
public @interface Operation
{
String value();
}

View File

@@ -22,34 +22,33 @@ import org.alfresco.rest.framework.Api;
import org.alfresco.rest.framework.resource.actions.interfaces.ResourceAction;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* Extends ResourceMetaData to give more information about an Action
* Extends ResourceMetaData to give more information about an Operation
*
* @author Gethin James
*/
public class ActionResourceMetaData extends ResourceMetadata
public class OperationResourceMetaData extends ResourceMetadata
{
private final Method actionMethod;
private final Method operationMethod;
/**
* Use this constructor to create the resource metadata
* @param uniqueId
* @param operations
* @param api
* @param actionMethod
* @param operationMethod
*/
public ActionResourceMetaData(String uniqueId, List<ResourceOperation> operations, Api api, Method actionMethod)
public OperationResourceMetaData(String uniqueId, List<ResourceOperation> operations, Api api, Method operationMethod)
{
super(uniqueId, RESOURCE_TYPE.ACTION, operations, api, null, null, null);
super(uniqueId, RESOURCE_TYPE.OPERATION, operations, api, null, null, null);
if (operations.size()!= 1)
{
throw new IllegalArgumentException("Only 1 action per url is supported for an entity");
throw new IllegalArgumentException("Only 1 operation per url is supported for an entity");
}
this.actionMethod = actionMethod;
this.operationMethod = operationMethod;
}
/**
@@ -58,22 +57,22 @@ public class ActionResourceMetaData extends ResourceMetadata
* @param api
* @param apiDeleted
*/
public ActionResourceMetaData(String uniqueId, Api api, Set<Class<? extends ResourceAction>> apiDeleted)
public OperationResourceMetaData(String uniqueId, Api api, Set<Class<? extends ResourceAction>> apiDeleted)
{
super(uniqueId, RESOURCE_TYPE.ACTION, null, api, apiDeleted, null, null);
this.actionMethod = null;
super(uniqueId, RESOURCE_TYPE.OPERATION, null, api, apiDeleted, null, null);
this.operationMethod = null;
}
public Method getActionMethod()
public Method getOperationMethod()
{
return actionMethod;
return operationMethod;
}
@Override
public String toString()
{
final StringBuilder builder = new StringBuilder();
builder.append("ActionResourceMetaData [api=");
builder.append("OperationResourceMetaData [api=");
builder.append(this.getApi());
builder.append(", uniqueId=");
builder.append(this.getUniqueId());
@@ -85,7 +84,7 @@ public class ActionResourceMetaData extends ResourceMetadata
builder.append(this.getOperations());
builder.append(", apiDeleted=");
builder.append(this.getApiDeleted());
builder.append("actionMethod=").append(actionMethod);
builder.append("operationMethod=").append(operationMethod);
builder.append("]");
return builder.toString();
}

View File

@@ -29,7 +29,7 @@ import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.alfresco.rest.framework.Action;
import org.alfresco.rest.framework.Operation;
import org.alfresco.rest.framework.Api;
import org.alfresco.rest.framework.BinaryProperties;
import org.alfresco.rest.framework.WebApi;
@@ -134,7 +134,7 @@ public class ResourceInspector
}
inspectAddressedProperties(api, resource, urlPath, metainfo);
inspectActions(api, resource, urlPath, metainfo);
inspectOperations(api, resource, urlPath, metainfo);
return metainfo;
}
@@ -535,46 +535,46 @@ public class ResourceInspector
}
/**
* Inspect a resource to find actions on it.
* Inspect a resource to find operations on it.
* @param api Api
* @param resource Class<?>
* @param entityPath String
* @param metainfo List<ResourceMetadata>
*/
public static void inspectActions(Api api, Class<?> resource, final String entityPath, List<ResourceMetadata> metainfo)
public static void inspectOperations(Api api, Class<?> resource, final String entityPath, List<ResourceMetadata> metainfo)
{
Map<String,Pair<ResourceOperation,Method>> operations = findActions(entityPath, resource);
Map<String,Pair<ResourceOperation,Method>> operations = findOperations(entityPath, resource);
if (operations != null && !operations.isEmpty())
{
for (Entry<String, Pair<ResourceOperation, Method>> opera : operations.entrySet())
{
if (isDeleted(opera.getValue().getSecond()))
{
metainfo.add(new ActionResourceMetaData(opera.getKey(), api, new HashSet(Arrays.asList(opera.getValue().getFirst()))));
metainfo.add(new OperationResourceMetaData(opera.getKey(), api, new HashSet(Arrays.asList(opera.getValue().getFirst()))));
}
else
{
metainfo.add(new ActionResourceMetaData(opera.getKey(), Arrays.asList(opera.getValue().getFirst()), api, opera.getValue().getSecond()));
metainfo.add(new OperationResourceMetaData(opera.getKey(), Arrays.asList(opera.getValue().getFirst()), api, opera.getValue().getSecond()));
}
}
}
}
/**
* Finds actions on an entity
* Finds operations on an entity
* @param entityPath path to the entity
* @param anyClass resource clause
* @return The operations
*/
private static Map<String,Pair<ResourceOperation,Method>> findActions(String entityPath, Class<?> anyClass)
private static Map<String,Pair<ResourceOperation,Method>> findOperations(String entityPath, Class<?> anyClass)
{
Map<String, Pair<ResourceOperation,Method>> embeds = new HashMap<String, Pair<ResourceOperation,Method>>();
List<Method> annotatedMethods = ResourceInspectorUtil.findMethodsByAnnotation(anyClass, Action.class);
List<Method> annotatedMethods = ResourceInspectorUtil.findMethodsByAnnotation(anyClass, Operation.class);
if (annotatedMethods != null && !annotatedMethods.isEmpty())
{
for (Method annotatedMethod : annotatedMethods)
{
Annotation annot = AnnotationUtils.findAnnotation(annotatedMethod, Action.class);
Annotation annot = AnnotationUtils.findAnnotation(annotatedMethod, Operation.class);
if (annot != null)
{
Map<String, Object> annotAttribs = AnnotationUtils.getAnnotationAttributes(annot);

View File

@@ -6,8 +6,7 @@ import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import org.alfresco.rest.framework.Action;
import org.alfresco.rest.framework.resource.parameters.Parameters;
import org.alfresco.rest.framework.Operation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.core.BridgeMethodResolver;
@@ -36,13 +35,14 @@ public class ResourceInspectorUtil
/*
* The api is consistent that the object passed in must match the object passed out
* however, actions are different, they don't even need a param, and if its supplied
* then it doesn't have to match. So we need special logic for actions
* however, operations are different, if the param is supplied it doesn't have to match
* the return type.
* So we need special logic for operations
*/
Annotation annot = AnnotationUtils.findAnnotation(resolvedMethod, Action.class);
Annotation annot = AnnotationUtils.findAnnotation(resolvedMethod, Operation.class);
if (annot != null)
{
return determinActionType(resource, method);
return determineOperationType(resource, method);
}
else
{
@@ -55,16 +55,16 @@ public class ResourceInspectorUtil
}
}
protected static Class determinActionType(Class resource, Method method)
protected static Class determineOperationType(Class resource, Method method)
{
//Its an Action annotated method and its a bit special
//Its an operation annotated method and its a bit special
Class<?>[] paramTypes = method.getParameterTypes();
if (paramTypes!= null)
{
switch (paramTypes.length)
{
case 3:
//EntityResource action by id, same logic as RelationshipEntityResource action by id
//EntityResource operation by id, same logic as RelationshipEntityResource operation by id
case 4:
int position = paramTypes.length-2;
if (Void.class.equals(paramTypes[position]))
@@ -78,7 +78,7 @@ public class ResourceInspectorUtil
}
}
throw new IllegalArgumentException("An action method signature should have 3 parameters (uniqueId, typePassedin, Parameters)," +
throw new IllegalArgumentException("An operation method signature should have 3 parameters (uniqueId, typePassedin, Parameters)," +
" use Void if you are not interested in the second argument.");
}

View File

@@ -36,7 +36,7 @@ import org.springframework.http.HttpMethod;
*/
public class ResourceMetadata
{
public enum RESOURCE_TYPE {ENTITY, RELATIONSHIP, PROPERTY, ACTION};
public enum RESOURCE_TYPE {ENTITY, RELATIONSHIP, PROPERTY, OPERATION};
private final String uniqueId;
private final RESOURCE_TYPE type;
private final List<ResourceOperation> operations;

View File

@@ -23,7 +23,7 @@ import java.util.Arrays;
import java.util.List;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.rest.framework.core.ActionResourceMetaData;
import org.alfresco.rest.framework.core.OperationResourceMetaData;
import org.alfresco.rest.framework.core.ResourceInspector;
import org.alfresco.rest.framework.core.ResourceInspectorUtil;
import org.alfresco.rest.framework.core.ResourceLocator;
@@ -93,15 +93,15 @@ public class ResourceWebScriptPost extends AbstractResourceWebScript implements
Object postedRel = processRequest(resourceMeta, req);
return Params.valueOf(entityId, params, postedRel);
}
case ACTION:
final String actionName = req.getServiceMatch().getTemplateVars().get(ResourceLocator.RELATIONSHIP_RESOURCE);
if (StringUtils.isNotBlank(entityId) && StringUtils.isNotBlank(actionName))
case OPERATION:
final String operationName = req.getServiceMatch().getTemplateVars().get(ResourceLocator.RELATIONSHIP_RESOURCE);
if (StringUtils.isNotBlank(entityId) && StringUtils.isNotBlank(operationName))
{
Class objectType = resourceMeta.getObjectType(HttpMethod.POST);
Object postedObj = null;
if (objectType!= null)
{
//Actions don't support a List as json body
//Operations don't support a List as json body
postedObj = ResourceWebScriptHelper.extractJsonContent(req, jsonHelper, objectType);
}
return Params.valueOf(entityId, params, postedObj);
@@ -170,26 +170,26 @@ public class ResourceWebScriptPost extends AbstractResourceWebScript implements
/**
* Execute a generic action method
* Execute a generic operation method
* @param resource
* @param params
* @return the result of the execution.
*/
private Object executeAction(ResourceWithMetadata resource, Params params) throws Throwable
private Object executeOperation(ResourceWithMetadata resource, Params params) throws Throwable
{
ActionResourceMetaData actionResourceMetaData = (ActionResourceMetaData) resource.getMetaData();
OperationResourceMetaData operationResourceMetaData = (OperationResourceMetaData) resource.getMetaData();
switch (actionResourceMetaData.getActionMethod().getParameterTypes().length)
switch (operationResourceMetaData.getOperationMethod().getParameterTypes().length)
{
case 3:
//EntityResource action by id
return ResourceInspectorUtil.invokeMethod(actionResourceMetaData.getActionMethod(),resource.getResource(), params.getEntityId(), params.getPassedIn(), params);
//EntityResource operation by id
return ResourceInspectorUtil.invokeMethod(operationResourceMetaData.getOperationMethod(),resource.getResource(), params.getEntityId(), params.getPassedIn(), params);
case 4:
//RelationshipEntityResource action by id
return ResourceInspectorUtil.invokeMethod(actionResourceMetaData.getActionMethod(),resource.getResource(), params.getEntityId(), params.getRelationshipId(), params.getPassedIn(), params);
//RelationshipEntityResource operation by id
return ResourceInspectorUtil.invokeMethod(operationResourceMetaData.getOperationMethod(),resource.getResource(), params.getEntityId(), params.getRelationshipId(), params.getPassedIn(), params);
}
throw new UnsupportedResourceOperationException("The action method has an invalid signature");
throw new UnsupportedResourceOperationException("The operation method has an invalid signature");
}
/**
@@ -256,8 +256,8 @@ public class ResourceWebScriptPost extends AbstractResourceWebScript implements
return wrapWithCollectionWithPaging(createdRel);
}
}
case ACTION:
return executeAction(resource, params);
case OPERATION:
return executeOperation(resource, params);
default:
throw new UnsupportedResourceOperationException("POST not supported for Actions");
}

View File

@@ -1,6 +1,6 @@
package org.alfresco.rest.framework.tests.api.mocks;
import org.alfresco.rest.framework.Action;
import org.alfresco.rest.framework.Operation;
import org.alfresco.rest.framework.WebApiDescription;
import org.alfresco.rest.framework.WebApiParam;
import org.alfresco.rest.framework.core.ResourceParameter;
@@ -19,12 +19,12 @@ public class GrassEntityResource implements EntityResourceAction.ReadById<Grass>
return new Grass(id);
}
@Action("cut")
@Operation("cut")
public String cutLawn(String id, Void notused, Parameters parameters) {
return "All done";
}
@Action("grow")
@Operation("grow")
@WebApiDescription(title = "Grow the grass")
@WebApiParam(name = "Grass", title = "The grass.",required=true, kind = ResourceParameter.KIND.HTTP_BODY_OBJECT)
public String growTheLawn(String id, Grass grass, Parameters parameters) {

View File

@@ -15,10 +15,8 @@ import java.util.Map;
import org.alfresco.rest.api.model.Comment;
import org.alfresco.rest.api.nodes.NodeCommentsRelation;
import org.alfresco.rest.framework.Action;
import org.alfresco.rest.framework.Api;
import org.alfresco.rest.framework.BinaryProperties;
import org.alfresco.rest.framework.core.ActionResourceMetaData;
import org.alfresco.rest.framework.core.OperationResourceMetaData;
import org.alfresco.rest.framework.core.ResourceInspector;
import org.alfresco.rest.framework.core.ResourceInspectorUtil;
import org.alfresco.rest.framework.core.ResourceMetadata;
@@ -391,20 +389,20 @@ public class InspectorTests
}
@Test
public void testInspectActions() throws IllegalAccessException, InstantiationException, Throwable
public void testInspectOperations() throws IllegalAccessException, InstantiationException, Throwable
{
Api api = Api.valueOf("alfrescomock", "private", "1");
List<ResourceMetadata> metainfo = new ArrayList<ResourceMetadata>();
GrassEntityResource grassEntityResource = new GrassEntityResource();
ResourceInspector.inspectActions(api, GrassEntityResource.class,"-root-", metainfo);
ResourceInspector.inspectOperations(api, GrassEntityResource.class,"-root-", metainfo);
assertTrue(metainfo.size()==2);
for (ResourceMetadata resourceMetadata : metainfo)
{
assertEquals(ResourceMetadata.RESOURCE_TYPE.ACTION, resourceMetadata.getType());
ActionResourceMetaData actionResourceMetaData = (ActionResourceMetaData) resourceMetadata;
Method actionMethod = actionResourceMetaData.getActionMethod();
assertEquals(ResourceMetadata.RESOURCE_TYPE.OPERATION, resourceMetadata.getType());
OperationResourceMetaData operationResourceMetaData = (OperationResourceMetaData) resourceMetadata;
Method actionMethod = operationResourceMetaData.getOperationMethod();
String result = null;
switch (resourceMetadata.getUniqueId())
{

View File

@@ -432,13 +432,13 @@ public class ParamsExtractorTests
}
/**
* Mocks an action
* Mocks an operation
* @return ResourceMetadata a Entity
*/
private static ResourceMetadata mockAction()
private static ResourceMetadata mockOperation()
{
ResourceMetadata resourceMock = mock(ResourceMetadata.class);
when(resourceMock.getType()).thenReturn(ResourceMetadata.RESOURCE_TYPE.ACTION);
when(resourceMock.getType()).thenReturn(ResourceMetadata.RESOURCE_TYPE.OPERATION);
return resourceMock;
}

View File

@@ -7,11 +7,9 @@ import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
@@ -147,7 +145,7 @@ public class ResourceLocatorTests
collResource = locator.locateResource(api, templateVars, HttpMethod.POST);
assertEquals(GrassEntityResource.class, collResource.getResource().getClass());
assertEquals(ResourceMetadata.RESOURCE_TYPE.ACTION, collResource.getMetaData().getType());
assertEquals(ResourceMetadata.RESOURCE_TYPE.OPERATION, collResource.getMetaData().getType());
}
@Test