package org.intermine.app.core; /* * Copyright (C) 2015 InterMine * * This code may be freely distributed and modified under the * terms of the GNU Lesser General Public Licence. This should * be distributed with the code. See the LICENSE file for more * information or http://www.gnu.org/copyleft/lesser.html. * */ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.LinkedList; public class Tree { private final Node rootElement; public Tree() { this(null); } public Tree(final String rootValue) { this.rootElement = new Node(rootValue, null); } private static <T> boolean doVisit(final Node node, final NodeVisitor visitor) { boolean result = visitor.visit(node); if (result) { for (final Node subNode : node.children) { if (!doVisit(subNode, visitor)) { result = false; break; } } } return result; } public void visitNodes(final NodeVisitor visitor) { doVisit(rootElement, visitor); } public void compact(Node node) { LinkedList<Node> children = node.children; if (!children.isEmpty()) { for (Node subNode : children) { compact(subNode); } if (null != node.getValue() && 1 == children.size()) { Node onlyChild = children.get(0); if (!onlyChild.children.isEmpty()) { node.removeChild(onlyChild); node.setValue(node.getValue() + " > " + onlyChild.getValue()); node.addChildren(onlyChild.children); } } } } public void computeDepthOfEachNode(Node node) { LinkedList<Node> children = node.children; if (children.isEmpty()) { node.depth = 0; } else { for (Node subNode : children) { computeDepthOfEachNode(subNode); } Collections.sort(children, new Comparator<Node>() { @Override public int compare(Node lhs, Node rhs) { return lhs.depth - rhs.depth; } }); node.depth = node.children.getLast().depth + 1; } } public Node getRootElement() { return rootElement; } public interface NodeVisitor { boolean visit(Node node); } public static class Node { private final LinkedList<Node> children; private Node parent; private String value; private int depth; private int number; @SuppressWarnings("unchecked") Node(final String value, final Node parent) { this.value = value; this.parent = parent; children = new LinkedList<>(); } public ArrayList<Node> getChildren() { return new ArrayList<>(children); } public Node getParent() { return parent; } public String getValue() { return value; } public int getDepth() { return depth; } public void setValue(final String value) { this.value = value; } public int getNumber() { return number; } public void setNumber(int number) { this.number = number; } public Node addChild(final String value) { for (Node child : children) { if (child.getValue().equals(value)) { return child; } } final Node node = new Node(value, this); return children.add(node) ? node : null; } public void addChildren(final Collection<Node> children) { for (Node node : children) { node.parent = this; this.children.add(node); } } public void removeChild(final Node node) { children.remove(node); } } }