net.craftforge.essential.controller.allocation.ResourceTree Maven / Gradle / Ivy
The newest version!
/*
* This file is part of essential.
*
* essential is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* essential is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with essential. If not, see .
*/
package net.craftforge.essential.controller.allocation;
import net.craftforge.essential.controller.utils.ControllerReflUtils;
import net.craftforge.essential.core.utils.UriUtils;
import net.craftforge.reflection.managers.ClassManager;
import net.craftforge.reflection.utils.PackageUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
/**
* A resource tree is a tree of {@link ResourceNode}s. A resource tree is created
* from all resource classes and their methods contained in a package. It holds
* the relationship between the external resource view and the internal
* implementations and structures.
*
* @author Christian Bick
* @since 30.07.11
*/
public class ResourceTree {
private static final Logger LOGGER = LoggerFactory.getLogger(ResourceTree.class);
/**
* The resource node comparator instance
*/
private static final ResourceNodeComparator RESOURCE_NODE_COMPARATOR = new ResourceNodeComparator();
/**
* A resource node comparator is used to order resource nodes by their path
*/
private static class ResourceNodeComparator implements Comparator {
public int compare(ResourceNode o1, ResourceNode o2) {
return o1.getPath().compareTo(o2.getPath());
}
}
/**
* Map of resource tree instances
*/
private static ConcurrentMap instances = new ConcurrentHashMap();
/**
* Gets an instance of a resource tree. Each package is represented by a single resource
* tree instance.
*
* @param packageName THe package name
* @return The resource tree instance
*/
public static ResourceTree getInstance(String packageName) {
if (! instances.containsKey(packageName)) {
LOGGER.info("[Resource tree initialization] {} ", packageName);
instances.putIfAbsent(packageName, new ResourceTree(packageName));
}
return instances.get(packageName);
}
/**
* The root node
*/
private ResourceNode root;
/**
* Initializes a resource tree for a package
*
* @param packageName The package name
*/
public ResourceTree(String packageName) {
this.root = new ResourceNode(new String[] { "/" }, 0);
List> resourceClasses = PackageUtils.findClasses(packageName);
for (Class> resourceClass : resourceClasses) {
if (Modifier.isAbstract(resourceClass.getModifiers())) {
continue;
}
String pathForClass = ControllerReflUtils.getPathFromClass(resourceClass);
if (pathForClass == null) {
continue;
}
for(java.lang.reflect.Method resourceMethod : ClassManager.getInstance(resourceClass).getCompleteClassHierarchyMethods()) {
String httpMethod = ControllerReflUtils.getHttpMethod(resourceMethod);
if (httpMethod == null) {
continue;
}
addResourceMethod(resourceClass, resourceMethod);
}
}
}
/**
* Finds the resource node matching the given (real) path.
*
* @param path The path
* @return The matching resource node or null if not found
*/
public ResourceNode findResourceNode(String path) {
path = UriUtils.standardPath(path);
String[] pathParts = UriUtils.splitPath(path);
return root.findResourceNode(pathParts);
}
/**
* Finds all resource nodes along a (real) path
*
* @param path The (real) path
* @return The resource nodes along this path
*/
public List findResourceNodesAlongPath(String path) {
path = UriUtils.standardPath(path);
String[] pathParts = UriUtils.splitPath(path);
List resourceNodes = root.findResourceNodesAlongPath(pathParts);
// The resource nodes are ordered from the end to the beginning of the path, so the order is reversed here
Collections.reverse(resourceNodes);
return resourceNodes;
}
/**
* Finds all resource nodes in a (real) path except of the base resource node
* representing the path. In other words: Finds a resource node matching
* path and then gets all its direct and indirect sub resources.
*
* @param path The (real) path
* @return The resources in the path
*/
public List findResourceNodesInPathSkippingRoot(String path) {
path = UriUtils.standardPath(path);
String[] pathParts = UriUtils.splitPath(path);
ResourceNode baseNode = root.findResourceNode(pathParts);
if (baseNode == null) {
return null;
}
List resourceNodes = baseNode.findAllSubNodesSkippingRoot();
Collections.sort(resourceNodes, RESOURCE_NODE_COMPARATOR);
return resourceNodes;
}
/**
* Adds a resource method for a resource class to the tree.
*
* @param resourceClass The resource class
* @param resourceMethod The resource method
*/
private void addResourceMethod(Class> resourceClass, Method resourceMethod) {
String path = ControllerReflUtils.getPathFromClass(resourceClass);
String pathForMethod = ControllerReflUtils.getPathFromMethod(resourceMethod);
if (pathForMethod != null) {
path = path + pathForMethod;
}
String[] pathParts = UriUtils.splitPath(path);
root.addResourceMethod(pathParts, 0, resourceClass, resourceMethod);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy