All Downloads are FREE. Search and download functionalities are using the official Maven repository.

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