/** * */ package org.minnal.instrument.resource; import java.util.Set; import javassist.CtClass; import org.minnal.instrument.MinnalInstrumentationException; import org.minnal.instrument.NamingStrategy; import org.minnal.instrument.UnderscoreNamingStrategy; import org.minnal.instrument.entity.EntityNode; import org.minnal.instrument.entity.EntityNode.EntityNodePath; import org.minnal.instrument.entity.metadata.ActionMetaData; import org.minnal.instrument.resource.creator.ActionMethodCreator; import org.minnal.instrument.resource.creator.CreateMethodCreator; import org.minnal.instrument.resource.creator.DeleteMethodCreator; import org.minnal.instrument.resource.creator.ListMethodCreator; import org.minnal.instrument.resource.creator.ReadMethodCreator; import org.minnal.instrument.resource.creator.ResourceClassCreator; import org.minnal.instrument.resource.creator.UpdateMethodCreator; import org.minnal.instrument.resource.metadata.ResourceMetaData; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.base.Strings; /** * @author ganeshs * */ public class ResourceWrapper { private CtClass generatedClass; private ResourceMetaData resource; private Class<?> entityClass; private Class<?> handlerClass; private String path; private NamingStrategy namingStrategy = new UnderscoreNamingStrategy(); private static final Logger logger = LoggerFactory.getLogger(ResourceWrapper.class); /** * @param resource * @param entityClass */ public ResourceWrapper(ResourceMetaData resource, Class<?> entityClass) { this.resource = resource; this.entityClass = entityClass; init(); } /** * Initializes the wrapper */ protected void init() { this.path = resource != null ? resource.getPath() : namingStrategy.getResourceName(entityClass); this.generatedClass = getResourceClassCreator().create(); } /** * Returns the resource class creator * * @return */ protected ResourceClassCreator getResourceClassCreator() { return new ResourceClassCreator(resource, namingStrategy, entityClass, path); } public void addPath(EntityNodePath path) { logger.debug("Adding the path {}", path); try { if (path.isReadAllowed()) { getReadMethodCreator(new ResourcePath(path, false, namingStrategy)).create(); getListMethodCreator(new ResourcePath(path, true, namingStrategy)).create(); } if (path.isCreateAllowed()) { getCreateMethodCreator(new ResourcePath(path, true, namingStrategy)).create(); } if (path.isUpdateAllowed()) { getUpdateMethodCreator(new ResourcePath(path, false, namingStrategy)).create(); addActionMethods(new ResourcePath(path, false, namingStrategy)); } if (path.isDeleteAllowed()) { getDeleteMethodCreator(new ResourcePath(path, false, namingStrategy)).create(); } } catch (Exception e) { logger.error("Failed while adding the path", e); throw new MinnalInstrumentationException(e); } } protected ReadMethodCreator getReadMethodCreator(ResourcePath path) { return new ReadMethodCreator(generatedClass, resource, path, this.path); } protected ListMethodCreator getListMethodCreator(ResourcePath path) { return new ListMethodCreator(generatedClass, resource, path, this.path); } protected CreateMethodCreator getCreateMethodCreator(ResourcePath path) { return new CreateMethodCreator(generatedClass, resource, path, this.path); } protected UpdateMethodCreator getUpdateMethodCreator(ResourcePath path) { return new UpdateMethodCreator(generatedClass, resource, path, this.path); } protected DeleteMethodCreator getDeleteMethodCreator(ResourcePath path) { return new DeleteMethodCreator(generatedClass, resource, path, this.path); } protected ActionMethodCreator getActionMethodCreator(ResourcePath path, ActionMetaData action) { return new ActionMethodCreator(generatedClass, resource, path, this.path, action); } protected void addActionMethods(ResourcePath resourcePath) throws Exception { logger.debug("Adding the action methods for the resource path {} and method {}", resourcePath); if (resourcePath.getNodePath().size() > 1) { logger.debug("Not adding the action methods for the non root paths. Resource path - {} and method - {}", resourcePath); // Actions will be added only for the root paths return; } Set<ActionMetaData> actions = resourcePath.getNodePath().get(0).getEntityMetaData().getActionMethods(); EntityNode node = resourcePath.getNodePath().get(0); ResourcePath actionPath = null; for (ActionMetaData action : actions) { EntityNodePath path = node.getEntityNodePath(action.getPath()); actionPath = new ResourcePath(path, action.getName(), namingStrategy); getActionMethodCreator(actionPath, action).create(); } } /** * Wraps the generated class to the resource class */ public Class<?> wrap() { logger.info("Wrapping the generated class {} to the resource class", generatedClass); try { handlerClass = generatedClass.toClass(); } catch (Exception e) { logger.error("Failed while wrapping the generated class to the resource class", e); throw new MinnalInstrumentationException(e); } return handlerClass; } /** * @return the generatedClass */ public CtClass getGeneratedClass() { return generatedClass; } /** * @return */ protected Class<?> getHandlerClass() { return handlerClass; } /** * @author ganeshs * */ public static class ResourcePath { private EntityNodePath nodePath; private boolean bulk; private String action; private NamingStrategy namingStrategy; /** * @param nodePath * @param bulk * @param namingStrategy */ public ResourcePath(EntityNodePath nodePath, boolean bulk, NamingStrategy namingStrategy) { this.nodePath = nodePath; this.bulk = bulk; this.namingStrategy = namingStrategy; } /** * @param nodePath * @param action * @param namingStrategy */ public ResourcePath(EntityNodePath nodePath, String action, NamingStrategy namingStrategy) { this(nodePath, false, namingStrategy); this.action = action; } /** * @return the nodePath */ public EntityNodePath getNodePath() { return nodePath; } /** * @return the bulk */ public boolean isBulk() { return bulk; } /** * @return the action */ public boolean isAction() { return ! Strings.isNullOrEmpty(action); } /** * @return the action */ public String getActionPath() { return getSinglePath() + "/" + namingStrategy.getPathSegment(action); } public String getSinglePath() { return nodePath.getSinglePath(); } public String getBulkPath() { return nodePath.getBulkPath(); } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((action == null) ? 0 : action.hashCode()); result = prime * result + (bulk ? 1231 : 1237); result = prime * result + ((nodePath == null) ? 0 : nodePath.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; ResourcePath other = (ResourcePath) obj; if (action == null) { if (other.action != null) return false; } else if (!action.equals(other.action)) return false; if (bulk != other.bulk) return false; if (nodePath == null) { if (other.nodePath != null) return false; } else if (!nodePath.equals(other.nodePath)) return false; return true; } @Override public String toString() { return "ResourcePath [nodePath=" + nodePath + ", bulk=" + bulk + ", action=" + action + "]"; } } }