JavaAction.java
package au.com.mountainpass.hyperstate.core;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import org.springframework.http.HttpMethod;
import au.com.mountainpass.hyperstate.annotations.PresentationType;
import au.com.mountainpass.hyperstate.core.entities.CreatedEntity;
import au.com.mountainpass.hyperstate.core.entities.EntityWrapper;
import au.com.mountainpass.hyperstate.core.entities.UpdatedEntity;
public class JavaAction<T> extends Action<T> {
private Method method;
private EntityWrapper<?> entity;
private HttpMethod nature;
protected JavaAction() {
}
public JavaAction(EntityWrapper<?> entity, Method method) {
super(null, method.getName(), new JavaLink(entity),
extractParameters(method));
this.method = method;
this.entity = entity;
this.nature = determineMethodNature(method);
}
public static HttpMethod determineMethodNature(Method method) {
Type type = method.getGenericReturnType();
if (ParameterizedType.class.isAssignableFrom(type.getClass())) {
ParameterizedType parameterizedType = (ParameterizedType) type;
Type rawType = parameterizedType.getRawType();
Class<? extends Type> rawTypeClass = rawType.getClass();
if (Class.class.isAssignableFrom(rawTypeClass)
&& CompletableFuture.class
.isAssignableFrom((Class<?>) rawType)) {
Type[] typeParams = parameterizedType.getActualTypeArguments();
if (typeParams.length == 1) {
Type typeParam = typeParams[0];
if (Class.class.isAssignableFrom(typeParam.getClass())
&& Void.class
.isAssignableFrom((Class<?>) typeParam)) {
return HttpMethod.DELETE;
} else if (Class.class
.isAssignableFrom(typeParam.getClass())
&& CreatedEntity.class
.isAssignableFrom((Class<?>) typeParam)) {
return HttpMethod.POST;
} else if (Class.class
.isAssignableFrom(typeParam.getClass())
&& UpdatedEntity.class
.isAssignableFrom((Class<?>) typeParam)) {
return HttpMethod.PUT;
} else if (ParameterizedType.class
.isAssignableFrom(typeParam.getClass())
&& EntityWrapper.class.isAssignableFrom(
(Class<?>) ((ParameterizedType) typeParam)
.getRawType())) {
return HttpMethod.GET;
}
}
}
}
return null;
}
private static au.com.mountainpass.hyperstate.core.Parameter[] extractParameters(
Method method) {
List<Parameter> params = Arrays.asList(method.getParameters());
List<au.com.mountainpass.hyperstate.core.Parameter> rval = new ArrayList<>();
for (int i = 0; i < params.size(); ++i) {
rval.add(new au.com.mountainpass.hyperstate.core.Parameter(
params.get(i).getName()));
}
rval.add(new au.com.mountainpass.hyperstate.core.Parameter("action",
PresentationType.SUBMIT, method.getName()));
return rval.toArray(new au.com.mountainpass.hyperstate.core.Parameter[0]);
}
@Override
public CompletableFuture<T> doInvoke(Resolver resolver,
Map<String, Object> filteredParameters) {
List<Object> args = new ArrayList<>(getParameters().size());
for (au.com.mountainpass.hyperstate.core.Parameter param : getParameters()) {
if (!PresentationType.SUBMIT.equals(param.getType())) {
args.add(filteredParameters.get(param.getIdentifier()));
}
}
try {
return (CompletableFuture<T>) method.invoke(entity, args.toArray());
} catch (IllegalAccessException | IllegalArgumentException
| InvocationTargetException e) {
throw new RuntimeException(e);
}
}
@Override
public HttpMethod getNature() {
return nature;
}
}