All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.wildfly.apigen.invocation.Marshaller Maven / Gradle / Ivy
package org.wildfly.apigen.invocation;
import org.jboss.as.controller.PathAddress;
import org.jboss.dmr.ModelNode;
import org.jboss.jandex.*;
import org.wildfly.apigen.model.AddressTemplate;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.*;
/**
* @author Lance Ball
*/
public class Marshaller {
private static HashMap, EntityAdapter>> adapters = new HashMap<>();
private static HashMap, Optional> subresources = new HashMap<>();
public static LinkedList marshal(Object root) throws Exception {
return appendNode(root, PathAddress.EMPTY_ADDRESS, new LinkedList<>());
}
@SuppressWarnings("unchecked")
private static LinkedList appendNode(Object entity, PathAddress address, LinkedList list) throws Exception {
final PathAddress resourceAddress = resourceAddress(entity, address);
final ModelNode modelNode = addressNodeFor(resourceAddress);
EntityAdapter adapter = adapterFor(entity.getClass());
list.add( adapter.fromEntity(entity, modelNode) );
return marshalSubresources(entity, resourceAddress, list);
}
private static PathAddress resourceAddress(Object resource, PathAddress pathAddress) {
final Class> entityClass = resource.getClass();
Index index = IndexFactory.createIndex(entityClass);
ClassInfo clazz = index.getClassByName(DotName.createSimple(entityClass.getName()));
PathAddress address = getPathElements(resource, pathAddress, entityClass, clazz);
if (address != null) return address;
throw new RuntimeException("Cannot determine resource address for " + resource);
}
private static PathAddress getPathElements(Object resource, PathAddress pathAddress, Class> entityClass, ClassInfo clazz) {
for (AnnotationInstance annotation : clazz.classAnnotations()) {
if (annotation.name().equals(IndexFactory.ADDRESS_META)) {
AddressTemplate address = AddressTemplate.of(annotation.value().asString());
String name = address.getResourceName();
if (name.equals("*")) {
try {
Method keyMethod = entityClass.getMethod("getKey");
name = (String) keyMethod.invoke(resource);
if (name == null) name = address.getResourceName();
} catch (NoSuchMethodException e) {
// Caught if the entity does not have a getKey method
// e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
pathAddress = pathAddress.append(address.getResourceType(), name);
return pathAddress;
}
}
if (clazz.superName() != null) {
// go up the object hierarchy looking for the annotation,
// just in case our API objects are subclassed
Index index = IndexFactory.createIndex(resource.getClass().getSuperclass());
ClassInfo superClazz = index.getClassByName(clazz.superName());
return getPathElements(resource, pathAddress, entityClass, superClazz);
}
return null;
}
private static ModelNode addressNodeFor(PathAddress address) {
ModelNode node = new ModelNode();
node.get(OP_ADDR).set(address.toModelNode());
node.get(OP).set(ADD);
return node;
}
private static synchronized EntityAdapter adapterFor(Class> type) {
if (!adapters.containsKey(type)) {
adapters.put(type, new EntityAdapter<>(type));
}
return adapters.get(type);
}
public static synchronized Optional subresourcesFor(Object entity) {
Class> type = entity.getClass();
if (!subresources.containsKey(type)) {
try {
Method target = type.getMethod("subresources");
subresources.put(type, Optional.of(new Subresource(target.getReturnType(), target, entity)));
} catch (Exception e) {
// If no subresources() method, then no subresources exist
subresources.put(type, Optional.empty());
}
}
return subresources.get(type);
}
private static LinkedList singletonSubresourcesFor(Object entity, PathAddress address) throws Exception {
final LinkedList list = new LinkedList<>();
for(Method target : orderedSubresources(entity)) {
final Object result = target.invoke(entity);
if (result != null) appendNode(result, address, list);
}
return list;
}
private static List orderedSubresources(Object parent) throws NoSuchMethodException {
final Class> parentClass = parent.getClass();
return new SubresourceFilter(parentClass).invoke();
}
private static LinkedList marshalSubresources(Object parent, PathAddress address, LinkedList list) {
try {
// Handle lists
Optional optional = subresourcesFor(parent);
if (optional.isPresent()) {
Object subresources = optional.get().invoke();
for(Method target : orderedSubresources(subresources)) {
List> resourceList = (List>) target.invoke(subresources);
for (Object o : resourceList) {
appendNode(o, address, list);
}
}
}
// Then handle singletons
list.addAll(singletonSubresourcesFor(parent, address));
} catch (Exception e) {
System.err.println("Error getting subresources for " + parent.getClass().getSimpleName());
e.printStackTrace();
}
return list;
}
private static class Subresource {
public final Class> type;
public final Method method;
private final Object parent;
public Subresource(Class> type, Method method, Object parent) {
this.type = type;
this.method = method;
this.parent = parent;
}
public Object invoke() throws InvocationTargetException, IllegalAccessException {
return method.invoke(parent);
}
}
}