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

org.kuali.maven.plugins.graph.tree.TreeHelper Maven / Gradle / Ivy

Go to download

Create customizable dependency graphs for Maven projects using Graphviz. The Graphviz "dot" executable needs to be installed and in your path for the plugin to produce graphs - http://www.graphviz.org/

There is a newer version: 1.2.3
Show newest version
/**
 * Copyright 2011-2012 The Kuali Foundation
 *
 * Licensed under the Educational Community License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.opensource.org/licenses/ecl2.php
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.kuali.maven.plugins.graph.tree;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.shared.dependency.tree.DependencyNode;
import org.codehaus.plexus.util.StringUtils;
import org.kuali.maven.plugins.graph.collector.ArtifactIdTokenCollector;
import org.kuali.maven.plugins.graph.collector.TokenCollector;
import org.kuali.maven.plugins.graph.collector.VersionFreeArtifactTokenCollector;
import org.kuali.maven.plugins.graph.dot.GraphHelper;
import org.kuali.maven.plugins.graph.filter.NodeFilter;
import org.kuali.maven.plugins.graph.pojo.Edge;
import org.kuali.maven.plugins.graph.pojo.GraphNode;
import org.kuali.maven.plugins.graph.pojo.MavenContext;
import org.kuali.maven.plugins.graph.pojo.Scope;
import org.kuali.maven.plugins.graph.pojo.State;
import org.kuali.maven.plugins.graph.util.Counter;
import org.kuali.maven.plugins.graph.util.Helper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;

/**
 * 

* Various helper methods for working with trees. *

* * @author jeffcaddel */ public class TreeHelper { private static final Logger logger = LoggerFactory.getLogger(TreeHelper.class); public static final String ROOT_FILL_COLOR = "#dddddd"; public static final String OPTIONAL = "optional"; public static final String REQUIRED = "required"; Counter counter = new Counter(); GraphHelper graphHelper = new GraphHelper(); public Node copy(Node node) { Node newNode = new Node(); MavenContext newMavenContext = copyWithoutEdges(node.getObject()); newNode.setObject(newMavenContext); for (Node child : node.getChildren()) { Node newChild = copy(child); newNode.add(newChild); } return newNode; } public MavenContext copyWithoutEdges(MavenContext context) { MavenContext copy = copy(context); copy.getGraphNode().setEdges(null); return copy; } public MavenContext copy(MavenContext context) { GraphNode newGraphNode = Helper.copyProperties(GraphNode.class, context.getGraphNode()); MavenContext newContext = Helper.copyProperties(MavenContext.class, context); newContext.setGraphNode(newGraphNode); return newContext; } public static Node findRequiredIncludedNode(Node root, String artifactId) { List> nodes = root.getBreadthFirstList(); for (Node node : nodes) { MavenContext context = node.getObject(); State state = context.getState(); String artifactIdentifier = context.getArtifactIdentifier(); boolean correctState = state == State.INCLUDED; boolean correctArtifact = artifactId.equals(artifactIdentifier); if (correctState && correctArtifact) { return node; } } throw new IllegalStateException("Can't locate " + artifactId); } /** *

* Logic for including nodes in a tree only if they match a filter. *

* *

* Any node where filter.isMatch() returns false, is hidden from view. *

* *

* The root node is never hidden, even if filter.isMatch() returns false on the root node. *

* *

* Any node where filter.isMatch() returns true, is displayed. Additionally, any nodes in the path from * that node back to the root node are displayed. *

* * @param node * @param filter */ public void include(Node node, NodeFilter filter) { if (!filter.isMatch(node) && !node.isRoot()) { hide(node); logger.debug("i:hiding {}", node.getObject().getArtifactIdentifier()); } else { logger.debug("i:showing path {}", node.getObject().getArtifactIdentifier()); showPath(node); } for (Node child : node.getChildren()) { include(child, filter); } } /** *

* Logic for excluding nodes from a tree if they match a filter. *

* *

* Any node where filter.isMatch() returns true, is hidden from view. The entire sub-tree rooted at * that node is also hidden from view. *

* *

* The root node is never hidden, even if filter.isMatch() returns true on the root node. *

* *

* Any node where filter.isMatch() returns false, is left untouched. *

* * @param node * @param filter */ public void exclude(Node node, NodeFilter filter) { if (filter.isMatch(node) && !node.isRoot()) { logger.debug("e:hiding {}", node.getObject().getArtifactIdentifier()); hideTree(node); } for (Node child : node.getChildren()) { exclude(child, filter); } } /** *

* Display every node in the path from this node back to the root. *

*/ public void showPath(Node node) { Node[] path = node.getPath(); List> pathList = Arrays.asList(path); Collections.reverse(pathList); for (Node pathNode : pathList) { show(pathNode); } } /** *

* Hide this node, and every node in the sub-tree below this node. *

* * @param node */ public void hideTree(Node node) { hide(node); for (Node child : node.getChildren()) { hideTree(child); } } /** *

* Show this node, and every node in the sub-tree below this node. *

* * @param node */ public void showTree(Node node) { show(node); for (Node child : node.getChildren()) { showTree(child); } } /** *

* Convenience method setting the hidden flag to false on the graph node contained inside the * MavenContext. *

* * @param node */ public void show(Node node) { MavenContext context = node.getObject(); GraphNode gn = context.getGraphNode(); if (gn.isHidden()) { logger.debug("showing node {}: {}", lpad(context.getId(), 4), context.getArtifactIdentifier()); gn.setHidden(false); } } /** *

* Convenience method setting the hidden flag to true on the graph node contained inside the * MavenContext. *

* * @param node */ public void hide(Node node) { MavenContext context = node.getObject(); GraphNode gn = node.getObject().getGraphNode(); if (!gn.isHidden()) { logger.debug(" hiding node {}: {}", lpad(context.getId(), 4), context.getArtifactIdentifier()); gn.setHidden(true); } } /** *

* Logic for altering a tree via removal of nodes that do not match the filter criteria. *

* *

* If the root node does not match the filter criteria, all of it's children are removed. Otherwise, the node and * all of its children are both removed. *

* * @param node */ public void prune(Node node, NodeFilter filter) { if (!filter.isMatch(node)) { if (node.isRoot()) { logger.debug("removing all children from root"); node.removeAllChildren(); } else { logger.debug("removing node at level={}", node.getLevel()); node.removeFromParent(); } } else { for (Node child : node.getChildren()) { prune(child, filter); } } } /** *

* Convenience method for generating a new MavenContext object from a GrapNode and a * DependencyNode. *

* * @param gn * @param dn */ protected MavenContext getMavenContext(GraphNode gn, DependencyNode dn) { int id = gn.getId(); String artifactIdentifier = getArtifactId(dn.getArtifact()); MavenContext context = new MavenContext(); context.setId(id); context.setArtifactIdentifier(artifactIdentifier); context.setArtifact(dn.getArtifact()); context.setGraphNode(gn); context.setDependencyNode(dn); context.setState(State.getState(dn.getState())); context.setOptional(dn.getArtifact().isOptional()); return context; } /** *

* Given a Maven DependencyNode tree return a type safe Node tree. *

* * @param dependencyNode */ public Node getTree(DependencyNode dependencyNode) { GraphNode gn = getGraphNode(dependencyNode); MavenContext context = getMavenContext(gn, dependencyNode); Node node = new Node(context); @SuppressWarnings("unchecked") List children = dependencyNode.getChildren(); for (DependencyNode child : children) { node.add(getTree(child)); } return node; } /** *

* Return true, if and only if, the two artifacts are an exact match of each other. *

* *

* More precisely, return true if [groupId]:[artfifactId]:[type]:[classifier]:[version] are an exact match, false * otherwise. *

* * @param a1 * @param a2 */ public boolean equals(Artifact a1, Artifact a2) { String id1 = getArtifactId(a1); String id2 = getArtifactId(a2); return id1.equals(id2); } /** *

* Return true, if and only if, the two artifacts are the same except for version. *

* *

* More precisely, return true if [groupId]:[artfifactId]:[type]:[classifier] are an exact match, false otherwise *

* * @param a1 * @param a2 */ public boolean similar(Artifact a1, Artifact a2) { String n1 = getPartialArtifactId(a1); String n2 = getPartialArtifactId(a2); return n1.equals(n2); } protected boolean isMatch(State state, State[] states) { for (State s : states) { if (state == s) { return true; } } return false; } public List> getNodeList(Node node, State... states) { Assert.notNull(states, "states are required"); List> contexts = new ArrayList>(); for (Node element : node.getBreadthFirstList()) { MavenContext context = element.getObject(); State elementState = context.getState(); if (isMatch(elementState, states)) { contexts.add(element); } } return contexts; } public List getList(Node node, State... states) { Assert.notNull(states, "states are required"); List contexts = new ArrayList(); for (Node element : node.getBreadthFirstList()) { MavenContext context = element.getObject(); State elementState = context.getState(); if (isMatch(elementState, states)) { contexts.add(context); } } return contexts; } public Map getMap(List contexts) { Map map = new HashMap(); for (MavenContext context : contexts) { map.put(context.getArtifactIdentifier(), context); } return map; } public Map getPartialIdMap(List contexts) { Map map = new HashMap(); for (MavenContext context : contexts) { map.put(getPartialArtifactId(context.getArtifact()), context); } return map; } protected void show(String label, List list) { logger.info(label); for (T element : list) { logger.info(element.toString()); } } protected GraphNode getGraphNode(DependencyNode dn) { Artifact a = dn.getArtifact(); GraphNode n = new GraphNode(); n.setId(counter.increment()); n.setLabel(graphHelper.getLabel(a)); String fillcolor = dn.getParent() == null ? ROOT_FILL_COLOR : n.getFillcolor(); n.setFillcolor(fillcolor); return n; } public List getGraphNodes(Node node) { List nodes = new ArrayList(); List> treeNodes = node.getBreadthFirstList(); for (Node treeNode : treeNodes) { nodes.add(treeNode.getObject().getGraphNode()); } return nodes; } public List getEdges(Node node) { List edges = new ArrayList(); List> list = node.getBreadthFirstList(); for (Node element : list) { MavenContext context = element.getObject(); GraphNode graphNode = context.getGraphNode(); Helper.addAll(edges, graphNode.getEdges()); } return edges; } // Omit normal info from the label public static String getRelationshipLabel(Scope scope, boolean optional, State state) { List labelTokens = new ArrayList(); if (!Scope.DEFAULT_SCOPE.equals(scope)) { labelTokens.add(scope.name().toLowerCase()); } if (optional) { // Using a dotted line for optional makes it clear enough // labelTokens.add(OPTIONAL); } if (!State.INCLUDED.equals(state)) { labelTokens.add(state.getValue()); } return toIdString(labelTokens); } public static String toIdString(List strings) { return toIdString(Helper.toArray(strings)); } public static String toIdString(String... strings) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < strings.length; i++) { if (i != 0) { sb.append(":"); } sb.append(Helper.toEmpty(strings[i])); } return sb.toString(); } public String getProperty(Object bean, String name) { try { return BeanUtils.getProperty(bean, name); } catch (Exception e) { throw new IllegalArgumentException(e); } } public void copyProperty(Object bean, String name, Object value) { try { BeanUtils.copyProperty(bean, name, value); } catch (Exception e) { throw new IllegalArgumentException(e); } } public void show(List nodes, List edges) { int nodeCount = nodes.size(); int edgeCount = edges.size(); int nodeCountShown = getNodeCount(nodes); int edgeCountShown = getEdgeCount(edges); int nodeCountHidden = nodeCount - nodeCountShown; int edgeCountHidden = edgeCount - edgeCountShown; logger.info("Generated " + nodes.size() + " graph nodes and " + edges.size() + " edges"); logger.info("Showing " + nodeCountShown + " nodes and " + edgeCountShown + " edges"); logger.info("Hiding " + nodeCountHidden + " nodes and " + edgeCountHidden + " edges"); } protected int getEdgeCount(List edges) { int count = 0; for (Edge edge : edges) { GraphNode parent = edge.getParent(); GraphNode child = edge.getChild(); boolean hidden = parent.isHidden() || child.isHidden(); count = hidden ? count : ++count; } return count; } protected int getNodeCount(List nodes) { int count = 0; for (GraphNode node : nodes) { count = node.isHidden() ? count : ++count; } return count; } /** * [groupId]:[artifactId]:[type]:[classifier] */ public static String getPartialArtifactId(Artifact a) { TokenCollector collector = new VersionFreeArtifactTokenCollector(); return toIdString(collector.getTokens(a)); } /** * [groupId]:[artifactId]:[type]:[classifier]:[version] */ public static String getArtifactId(Artifact a) { TokenCollector collector = new ArtifactIdTokenCollector(); return toIdString(collector.getTokens(a)); } protected String lpad(Object o, int count) { String s = Helper.toEmpty(o); return StringUtils.leftPad(s, count); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy