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

121808 gjames: RA-774 Improving action tests


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@126421 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Jamal Kaabi-Mofrad
2016-05-10 10:51:36 +00:00
parent 6e0f375fb5
commit 3a6d18ba6a
5 changed files with 89 additions and 13 deletions

View File

@@ -362,7 +362,10 @@ public class ResourceInspector
private static void inspectBodyParamAndReturnType(Class<?> resource, Method aMethod, List<ResourceParameter> params) private static void inspectBodyParamAndReturnType(Class<?> resource, Method aMethod, List<ResourceParameter> params)
{ {
Class<?> dType = ResourceInspectorUtil.determineType(resource,aMethod); Class<?> dType = ResourceInspectorUtil.determineType(resource,aMethod);
params.add(ResourceParameter.valueOf(dType.getSimpleName().toUpperCase(), "The entity", "Unique entity properties", true, KIND.HTTP_BODY_OBJECT, true, dType)); if (dType!= null)
{
params.add(ResourceParameter.valueOf(dType.getSimpleName().toUpperCase(), "The entity", "Unique entity properties", true, KIND.HTTP_BODY_OBJECT, true, dType));
}
} }
@@ -532,11 +535,11 @@ public class ResourceInspector
{ {
if (isDeleted(opera.getValue().getSecond())) if (isDeleted(opera.getValue().getSecond()))
{ {
metainfo.add(new ResourceMetadata(opera.getKey(), RESOURCE_TYPE.ACTION, null, api, new HashSet(Arrays.asList(opera.getValue().getFirst())), null)); metainfo.add(new ActionResourceMetaData(opera.getKey(), api, new HashSet(Arrays.asList(opera.getValue().getFirst()))));
} }
else else
{ {
metainfo.add(new ResourceMetadata(opera.getKey(), RESOURCE_TYPE.ACTION, Arrays.asList(opera.getValue().getFirst()), api, null, null)); metainfo.add(new ActionResourceMetaData(opera.getKey(), Arrays.asList(opera.getValue().getFirst()), api, opera.getValue().getSecond()));
} }
} }
} }

View File

@@ -6,6 +6,8 @@ import java.lang.reflect.Method;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.alfresco.rest.framework.Action;
import org.alfresco.rest.framework.resource.parameters.Parameters;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.springframework.core.BridgeMethodResolver; import org.springframework.core.BridgeMethodResolver;
@@ -31,12 +33,50 @@ public class ResourceInspectorUtil
protected static Class determineType(Class resource, Method method) protected static Class determineType(Class resource, Method method)
{ {
Method resolvedMethod = BridgeMethodResolver.findBridgedMethod(method); Method resolvedMethod = BridgeMethodResolver.findBridgedMethod(method);
Class returnType = GenericTypeResolver.resolveReturnType(resolvedMethod, resource);
if (List.class.isAssignableFrom(returnType)) /*
* 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
*/
Annotation annot = AnnotationUtils.findAnnotation(resolvedMethod, Action.class);
if (annot != null)
{ {
return GenericCollectionTypeResolver.getCollectionReturnType(method); return determinActionType(resource, method);
}
else
{
Class returnType = GenericTypeResolver.resolveReturnType(resolvedMethod, resource);
if (List.class.isAssignableFrom(returnType))
{
return GenericCollectionTypeResolver.getCollectionReturnType(method);
}
return returnType;
}
}
protected static Class determinActionType(Class resource, Method method)
{
//Its an Action annotated method and its a bit special
Class<?>[] paramTypes = method.getParameterTypes();
if (!String.class.equals(paramTypes[0]) || !Parameters.class.equals(paramTypes[paramTypes.length-1]))
{
throw new IllegalArgumentException("An action method signature must start with a String uniqueId and end with the 'Parameters' object ");
}
if (paramTypes.length == 2)
{
//No parameter required
return null;
}
else if (paramTypes.length == 3)
{
return paramTypes[1]; // Return the middle parameter
}
else
{
throw new IllegalArgumentException("An action method signature should have 3 parameters (uniqueId, typePassedin, Parameters)");
} }
return returnType;
} }
/** /**
@@ -71,6 +111,16 @@ public class ResourceInspectorUtil
return annotatedMethods; return annotatedMethods;
} }
/**
* Invokes a no arg method and returns the result
* @param annotatedMethod Method
* @param obj Object
* @return result of method call
*/
public static Object invokeMethod(Method annotatedMethod, Object obj)
{
return invokeMethod(annotatedMethod, obj, null);
}
/** /**
* Invokes a method and returns the result * Invokes a method and returns the result
@@ -78,13 +128,13 @@ public class ResourceInspectorUtil
* @param obj Object * @param obj Object
* @return result of method call * @return result of method call
*/ */
public static Object invokeMethod(Method annotatedMethod, Object obj) public static Object invokeMethod(Method annotatedMethod, Object obj, Object... args)
{ {
if (annotatedMethod != null) if (annotatedMethod != null)
{ {
try try
{ {
return annotatedMethod.invoke(obj, null); return annotatedMethod.invoke(obj, args);
} }
catch (IllegalArgumentException error) catch (IllegalArgumentException error)
{ {

View File

@@ -11,6 +11,11 @@ public class Grass
final private String id; final private String id;
private String color = "green"; private String color = "green";
public Grass()
{
this.id = null;
}
public Grass(String id) public Grass(String id)
{ {
super(); super();

View File

@@ -3,6 +3,7 @@ package org.alfresco.rest.framework.tests.api.mocks;
import org.alfresco.rest.framework.Action; import org.alfresco.rest.framework.Action;
import org.alfresco.rest.framework.WebApiDescription; import org.alfresco.rest.framework.WebApiDescription;
import org.alfresco.rest.framework.WebApiParam; import org.alfresco.rest.framework.WebApiParam;
import org.alfresco.rest.framework.core.ResourceParameter;
import org.alfresco.rest.framework.resource.EntityResource; import org.alfresco.rest.framework.resource.EntityResource;
import org.alfresco.rest.framework.resource.actions.interfaces.EntityResourceAction; import org.alfresco.rest.framework.resource.actions.interfaces.EntityResourceAction;
import org.alfresco.rest.framework.resource.parameters.Parameters; import org.alfresco.rest.framework.resource.parameters.Parameters;
@@ -19,13 +20,13 @@ public class GrassEntityResource implements EntityResourceAction.ReadById<Grass>
} }
@Action("cut") @Action("cut")
@WebApiDescription(title = "Cuts the grass")
public String cutLawn(String id, Parameters parameters) { public String cutLawn(String id, Parameters parameters) {
return "All done"; return "All done";
} }
@Action("grow") @Action("grow")
@WebApiDescription(title = "Grow the grass") @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) { public String growTheLawn(String id, Grass grass, Parameters parameters) {
return "Growing well"; return "Growing well";
} }

View File

@@ -18,6 +18,7 @@ import org.alfresco.rest.api.nodes.NodeCommentsRelation;
import org.alfresco.rest.framework.Action; import org.alfresco.rest.framework.Action;
import org.alfresco.rest.framework.Api; import org.alfresco.rest.framework.Api;
import org.alfresco.rest.framework.BinaryProperties; import org.alfresco.rest.framework.BinaryProperties;
import org.alfresco.rest.framework.core.ActionResourceMetaData;
import org.alfresco.rest.framework.core.ResourceInspector; import org.alfresco.rest.framework.core.ResourceInspector;
import org.alfresco.rest.framework.core.ResourceInspectorUtil; import org.alfresco.rest.framework.core.ResourceInspectorUtil;
import org.alfresco.rest.framework.core.ResourceMetadata; import org.alfresco.rest.framework.core.ResourceMetadata;
@@ -26,6 +27,7 @@ import org.alfresco.rest.framework.core.ResourceParameter;
import org.alfresco.rest.framework.resource.actions.interfaces.BinaryResourceAction; import org.alfresco.rest.framework.resource.actions.interfaces.BinaryResourceAction;
import org.alfresco.rest.framework.resource.actions.interfaces.EntityResourceAction; import org.alfresco.rest.framework.resource.actions.interfaces.EntityResourceAction;
import org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction; import org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction;
import org.alfresco.rest.framework.resource.parameters.Params;
import org.alfresco.rest.framework.tests.api.mocks.Farmer; import org.alfresco.rest.framework.tests.api.mocks.Farmer;
import org.alfresco.rest.framework.tests.api.mocks.GoatEntityResource; import org.alfresco.rest.framework.tests.api.mocks.GoatEntityResource;
import org.alfresco.rest.framework.tests.api.mocks.Grass; import org.alfresco.rest.framework.tests.api.mocks.Grass;
@@ -352,7 +354,7 @@ public class InspectorTests
ResourceOperation op = ResourceInspector.inspectOperation(FlockEntityResource.class, aMethod, HttpMethod.PUT); ResourceOperation op = ResourceInspector.inspectOperation(FlockEntityResource.class, aMethod, HttpMethod.PUT);
assertNotNull(op); assertNotNull(op);
List<ResourceParameter> params = op.getParameters(); List<ResourceParameter> params = op.getParameters();
assertNotNull(params); assertTrue(params.size()==2);
for (ResourceParameter param:params) for (ResourceParameter param:params)
{ {
if (ResourceParameter.KIND.HTTP_BODY_OBJECT.equals(param.getParamType())) if (ResourceParameter.KIND.HTTP_BODY_OBJECT.equals(param.getParamType()))
@@ -365,7 +367,7 @@ public class InspectorTests
op = ResourceInspector.inspectOperation(SheepBlackSheepResource.class, aMethod, HttpMethod.POST); op = ResourceInspector.inspectOperation(SheepBlackSheepResource.class, aMethod, HttpMethod.POST);
assertNotNull(op); assertNotNull(op);
params = op.getParameters(); params = op.getParameters();
assertNotNull(params); assertTrue(params.size()==2);
for (ResourceParameter param:params) for (ResourceParameter param:params)
{ {
if (ResourceParameter.KIND.HTTP_BODY_OBJECT.equals(param.getParamType())) if (ResourceParameter.KIND.HTTP_BODY_OBJECT.equals(param.getParamType()))
@@ -389,29 +391,44 @@ public class InspectorTests
} }
@Test @Test
public void testInspectActions() public void testInspectActions() throws IllegalAccessException, InstantiationException
{ {
Api api = Api.valueOf("alfrescomock", "private", "1"); Api api = Api.valueOf("alfrescomock", "private", "1");
List<ResourceMetadata> metainfo = new ArrayList<ResourceMetadata>(); List<ResourceMetadata> metainfo = new ArrayList<ResourceMetadata>();
GrassEntityResource grassEntityResource = new GrassEntityResource();
ResourceInspector.inspectActions(api, GrassEntityResource.class,"-root-", metainfo); ResourceInspector.inspectActions(api, GrassEntityResource.class,"-root-", metainfo);
assertTrue(metainfo.size()==2); assertTrue(metainfo.size()==2);
for (ResourceMetadata resourceMetadata : metainfo) for (ResourceMetadata resourceMetadata : metainfo)
{ {
assertEquals(ResourceMetadata.RESOURCE_TYPE.ACTION, resourceMetadata.getType()); assertEquals(ResourceMetadata.RESOURCE_TYPE.ACTION, resourceMetadata.getType());
ActionResourceMetaData actionResourceMetaData = (ActionResourceMetaData) resourceMetadata;
Method actionMethod = actionResourceMetaData.getActionMethod();
String result = null;
switch (resourceMetadata.getUniqueId()) switch (resourceMetadata.getUniqueId())
{ {
case "/-root-/{entityId}/grow": case "/-root-/{entityId}/grow":
assertTrue("GrassEntityResource supports POST", resourceMetadata.supports(HttpMethod.POST)); assertTrue("GrassEntityResource supports POST", resourceMetadata.supports(HttpMethod.POST));
assertFalse("GrassEntityResource does not support DELETE", resourceMetadata.supports(HttpMethod.DELETE)); assertFalse("GrassEntityResource does not support DELETE", resourceMetadata.supports(HttpMethod.DELETE));
Class paramType = resourceMetadata.getObjectType(HttpMethod.POST);
Object paramObj = paramType.newInstance();
result = (String) ResourceInspectorUtil.invokeMethod(actionMethod,grassEntityResource, "xyz", paramObj, Params.valueOf("notUsed", null));
assertEquals("Growing well",result);
break; break;
case "/-root-/{entityId}/cut": case "/-root-/{entityId}/cut":
assertTrue("GrassEntityResource supports POST", resourceMetadata.supports(HttpMethod.POST)); assertTrue("GrassEntityResource supports POST", resourceMetadata.supports(HttpMethod.POST));
assertFalse("GrassEntityResource does not support GET", resourceMetadata.supports(HttpMethod.GET)); assertFalse("GrassEntityResource does not support GET", resourceMetadata.supports(HttpMethod.GET));
assertNull(resourceMetadata.getObjectType(HttpMethod.POST));
result = (String) ResourceInspectorUtil.invokeMethod(actionMethod,grassEntityResource, "xyz", Params.valueOf("notUsed", null));
assertEquals("All done",result);
break; break;
default: default:
fail("Invalid action information."); fail("Invalid action information.");
} }
} }
} }