package org.phenoscape.util;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.apache.log4j.Logger;
import org.obo.datamodel.LinkedObject;
import org.obo.datamodel.OBOClass;
import org.obo.datamodel.OBOSession;
import org.obo.util.TermUtil;
import org.phenoscape.model.DataSet;
import org.phenoscape.model.Taxon;
public class TreeBuilder {
/**
* @return Map<nodeID, parentID>
*/
public static Map<LinkedObject, LinkedObject> buildTree(DataSet data, OBOSession session) {
final Set<LinkedObject> allAncestors = new HashSet<LinkedObject>();
for (Taxon taxon : data.getTaxa()) {
if (taxon.getValidName() != null) {
allAncestors.addAll(TermUtil.getisaAncestors(taxon.getValidName(), true));
}
}
final Map<LinkedObject, LinkedObject> treeNodes = new HashMap<LinkedObject, LinkedObject>();
if (!allAncestors.isEmpty()) {
final Collection<OBOClass> roots = TermUtil.getRoots(session);
logger().debug(roots);
roots.retainAll(allAncestors);
if (roots.size() != 1) {
logger().error("Should only be one taxon root.");
}
final LinkedObject taxonRoot = TermUtil.getRoot(allAncestors.iterator().next());
logger().debug("Root taxon: " + taxonRoot);
final Set<LinkedObject> retainTaxa = new HashSet<LinkedObject>();
for (Taxon taxon : data.getTaxa()) {
if (taxon.getValidName() != null) {
retainTaxa.add(taxon.getValidName());
}
}
processNode(taxonRoot, treeNodes, allAncestors, null, retainTaxa);
}
return treeNodes;
}
private static void processNode(LinkedObject node, Map<LinkedObject, LinkedObject> treeNodes, Set<LinkedObject> allAncestors, LinkedObject parent, Collection<LinkedObject> retainTaxa) {
final Set<LinkedObject> children = new HashSet<LinkedObject>(TermUtil.getChildren(node));
children.retainAll(allAncestors);
if ((children.size() == 1) && (!retainTaxa.contains(node))) { //retain needed internal nodes
processNode(children.iterator().next(), treeNodes, allAncestors, parent, retainTaxa);
} else {
if (parent != null) {
treeNodes.put(node, parent);
}
for (LinkedObject child : children) {
processNode(child, treeNodes, allAncestors, node, retainTaxa);
}
}
}
private static Logger logger() {
return Logger.getLogger(TreeBuilder.class);
}
}