124 lines
3.0 KiB
Java
124 lines
3.0 KiB
Java
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<T> {
|
|
|
|
private boolean allowMultipleInheritance;
|
|
|
|
private Node<T> rootNode;
|
|
private NodeInformation<T> ni;
|
|
private Map<String, Node<T>> locate;
|
|
|
|
public Tree() {
|
|
this.allowMultipleInheritance = true;
|
|
this.locate = new HashMap<>();
|
|
}
|
|
|
|
public Tree(NodeInformation<T> ni) {
|
|
this();
|
|
setNodeInformation(ni);
|
|
}
|
|
|
|
public Tree(T root, NodeInformation<T> 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<T> 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<T> getNodeInformation() {
|
|
return ni;
|
|
}
|
|
|
|
public Node<T> addNode(T t) {
|
|
String identifier = ni.getIdentifier(t);
|
|
if(locate.containsKey(identifier)) {
|
|
// has been already added
|
|
return locate.get(identifier);
|
|
}
|
|
|
|
Node<T> node = new Node<>(t);
|
|
node.setTree(this);
|
|
|
|
Set<String> 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<T> 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<T> getRootNode() {
|
|
return rootNode;
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
return rootNode.toString();
|
|
}
|
|
|
|
public void elaborate(NodeElaborator<T> nodeElaborator) throws Exception {
|
|
rootNode.elaborate(nodeElaborator);
|
|
}
|
|
|
|
public Node<T> getNodeByIdentifier(String identifier){
|
|
return locate.get(identifier);
|
|
}
|
|
} |