package org.gcube.informationsystem.tree; import java.util.HashMap; import java.util.Map; import java.util.Set; /** * @author Luca Frosini (ISTI - CNR) */ public class Tree { private boolean allowMultipleInheritance; private Node rootNode; private NodeInformation ni; private Map> locate; public Tree() { this.allowMultipleInheritance = true; this.locate = new HashMap<>(); } public Tree(NodeInformation ni) { this(); setNodeInformation(ni); } public Tree(T root, NodeInformation ni) { this(ni); setRoot(root); } /** * Set the NodeInformation if and only if it was not previously set. * Otherwise this function has no effect. * @param ni the NodeInformation to set */ public void setNodeInformation(NodeInformation ni) { if(this.ni==null) { this.ni = ni; } } /** * Set the root if and only if it was not previously set. * Otherwise this function has no effect. * This function raises a RuntimeException is the * NodeInformation was not previously set. * @param root the root to set */ public void setRoot(T root) throws RuntimeException { if(this.ni==null) { throw new RuntimeException("You must set the NodeInformation instance first"); } if(this.rootNode==null) { this.rootNode = new Node<>(root); this.rootNode.setTree(this); String identifier = ni.getIdentifier(root); this.locate.put(identifier, rootNode); } } public void setAllowMultipleInheritance(boolean allowMultipleInheritance) { this.allowMultipleInheritance = allowMultipleInheritance; } public NodeInformation getNodeInformation() { return ni; } public Node addNode(T t) { String identifier = ni.getIdentifier(t); if(locate.containsKey(identifier)) { // has been already added return locate.get(identifier); } Node node = new Node<>(t); node.setTree(this); Set parentIdentifiers = ni.getParentIdentifiers(rootNode!= null ? rootNode.getNodeElement() : null, t); if(parentIdentifiers==null || parentIdentifiers.size()==0) { if(this.rootNode==null) { this.rootNode = node; }else { throw new RuntimeException("A Tree cannot have two root. " + t.toString() + " has not parent."); } } else { for(String parentIdentifier : parentIdentifiers) { Node parentNode = locate.get(parentIdentifier); if(parentNode==null) { throw new RuntimeException("I can find parent for " + identifier + ". Missing parent is " + parentIdentifier); } parentNode.addChild(node); if(!allowMultipleInheritance) { break; } } } this.locate.put(identifier, node); return node; } public Node getRootNode() { return rootNode; } @Override public String toString() { return rootNode.toString(); } public void elaborate(NodeElaborator nodeElaborator) throws Exception { rootNode.elaborate(nodeElaborator); } }