// Path: ontology-model/src/main/java/au/csiro/ontology/Ontology.java
// public class Ontology {
//     
//     /**
//      * The id of the ontology.
//      */
//     protected final String id;
//     
//     /**
//      * The version of the ontology.
//      */
//     protected final String version;
//     
//     /**
//      * The collection of stated axioms that form the ontology.
//      */
//     protected final Collection<Axiom> statedAxioms;
//     
//     /**
//      * The collection of inferred axioms that form the ontology.
//      */
//     protected final Collection<Axiom> inferredAxioms = new ArrayList<Axiom>();
//     
//     /**
//      * A map that contains references to all the nodes in the taxonomy indexed
//      * by id.
//      */
//     protected final Map<String, Node> nodeMap = new HashMap<String, Node>();
//     
//     /**
//      * Set of {@link Node}s potentially affected by the last incremental
//      * classification.
//      */
//     protected final Set<Node> lastAffectedNodes = new HashSet<Node>();
//     
//     /**
//      * Builds a new ontology.
//      * 
//      * @param id
//      * @param version
//      * @param statedAxioms
//      * @param nodeMap
//      * @param lastAffectedNodes
//      */
//     public Ontology(String id, String version, Collection<Axiom> statedAxioms, Map<String, Node> nodeMap, 
//             Set<Node> lastAffectedNodes) {
//         this.id = id;
//         this.version = version;
//         if(statedAxioms == null) {
//             this.statedAxioms = new ArrayList<Axiom>();
//         } else {
//             this.statedAxioms = statedAxioms;
//         }
//         if(nodeMap != null)
//             this.nodeMap.putAll(nodeMap);
//         if(lastAffectedNodes != null)
//             this.lastAffectedNodes.addAll(lastAffectedNodes);
//     }
//     
//     /**
//      * Builds a new ontology.
//      * 
//      * @param statedAxioms
//      * @param nodeMap
//      */
//     public Ontology(String id, String version, Collection<Axiom> statedAxioms, Map<String, Node> nodeMap) {
//     	this(id, version, statedAxioms, nodeMap, null);
//     }
//     
//     public Collection<Axiom> getStatedAxioms() {
//         return statedAxioms;
//     }
// 
//     public Collection<Axiom> getInferredAxioms() {
//         return inferredAxioms;
//     }
//     
//     public Node getNode(String id) {
//         return nodeMap.get(id);
//     }
// 
//     public Iterator<Node> nodeIterator() {
//         Set<Node> set = new HashSet<Node>(nodeMap.values());
//         return set.iterator();
//     }
//     
//     public Map<String, Node> getNodeMap() {
//         return nodeMap;
//     }
// 
//     public Node getTopNode() {
//         return getNode(NamedConcept.TOP);
//     }
//     
//     public Node getBottomNode() {
//         return getNode(NamedConcept.BOTTOM);
//     }
//     
//     public void setNodeMap(Map<String, Node> nodeMap) {
//         this.nodeMap.clear();
//         this.nodeMap.putAll(nodeMap);
//     }
// 
//     public Set<Node> getAffectedNodes() {
//         return lastAffectedNodes;
//     }
//     
//     public void setAffectedNodes(Set<Node> nodes) {
//         lastAffectedNodes.clear();
//         lastAffectedNodes.addAll(nodes);
//     }
//     
//     public String getId() {
//         return id;
//     }
// 
//     public String getVersion() {
//         return version;
//     }
//     
// }
// 
// Path: ontology-model/src/main/java/au/csiro/ontology/Node.java
// public class Node implements Serializable {
//     /**
//      * 
//      */
//     private static final long serialVersionUID = 1L;
// 
//     /**
//      * Set of equivalent concepts in this node.
//      */
//     protected final Set<String> equivalentConcepts = Collections.newSetFromMap(
//             new ConcurrentHashMap<String, Boolean>());
//     
//     /**
//      * Set of parents nodes.
//      */
//     protected final Set<Node> parents = Collections.newSetFromMap(
//             new ConcurrentHashMap<Node, Boolean>());
//     
//     /**
//      * Set of child nodes.
//      */
//     protected final Set<Node> children = Collections.newSetFromMap(
//             new ConcurrentHashMap<Node, Boolean>());
// 
//     /**
//      * @return the equivalentConcepts
//      */
//     public Set<String> getEquivalentConcepts() {
//         return equivalentConcepts;
//     }
// 
//     /**
//      * @return the parents
//      */
//     public Set<Node> getParents() {
//         return parents;
//     }
// 
//     /**
//      * @return the children
//      */
//     public Set<Node> getChildren() {
//         return children;
//     }
// 
//     @Override
//     public String toString() {
//         StringBuilder sb = new StringBuilder();
//         int size = equivalentConcepts.size();
//         int i = 0;
//         sb.append("{");
//         for (String equiv : equivalentConcepts) {
//             sb.append(equiv);
//             if (++i < size)
//                 sb.append(", ");
//         }
//         sb.append("}");
//         return sb.toString();
//     }
// 
// }


import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Map;
import java.util.Set;
import au.csiro.ontology.Ontology;
import au.csiro.ontology.Node;
                    int min;
                    int max;
                    
                    if (ont.getTopNode().equals(node)) {
                        min = max = 0;
                    } else {
                        min = Integer.MAX_VALUE;
                        max = Integer.MIN_VALUE;
                        for (Node parent: node.getParents()) {
                            min = Math.min(min, minLevel.get(parent) + 1);
                            max = Math.max(max, maxLevel.get(parent) + 1);
                        }
                    }
                    minLevel.put(node, min);
                    maxLevel.put(node, max);
                    
                    result.put(node, new int[] {min, max});
                }
            };

            BFS_MAX.accept(ont, v);
            
            return result;
        }
    }
    
}

abstract class AbstractTraversal implements Traversal {
    
// Path: ontology-model/src/main/java/au/csiro/ontology/Ontology.java
// public class Ontology {
//     
//     /**
//      * The id of the ontology.
//      */
//     protected final String id;
//     
//     /**
//      * The version of the ontology.
//      */
//     protected final String version;
//     
//     /**
//      * The collection of stated axioms that form the ontology.
//      */
//     protected final Collection<Axiom> statedAxioms;
//     
//     /**
//      * The collection of inferred axioms that form the ontology.
//      */
//     protected final Collection<Axiom> inferredAxioms = new ArrayList<Axiom>();
//     
//     /**
//      * A map that contains references to all the nodes in the taxonomy indexed
//      * by id.
//      */
//     protected final Map<String, Node> nodeMap = new HashMap<String, Node>();
//     
//     /**
//      * Set of {@link Node}s potentially affected by the last incremental
//      * classification.
//      */
//     protected final Set<Node> lastAffectedNodes = new HashSet<Node>();
//     
//     /**
//      * Builds a new ontology.
//      * 
//      * @param id
//      * @param version
//      * @param statedAxioms
//      * @param nodeMap
//      * @param lastAffectedNodes
//      */
//     public Ontology(String id, String version, Collection<Axiom> statedAxioms, Map<String, Node> nodeMap, 
//             Set<Node> lastAffectedNodes) {
//         this.id = id;
//         this.version = version;
//         if(statedAxioms == null) {
//             this.statedAxioms = new ArrayList<Axiom>();
//         } else {
//             this.statedAxioms = statedAxioms;
//         }
//         if(nodeMap != null)
//             this.nodeMap.putAll(nodeMap);
//         if(lastAffectedNodes != null)
//             this.lastAffectedNodes.addAll(lastAffectedNodes);
//     }
//     
//     /**
//      * Builds a new ontology.
//      * 
//      * @param statedAxioms
//      * @param nodeMap
//      */
//     public Ontology(String id, String version, Collection<Axiom> statedAxioms, Map<String, Node> nodeMap) {
//     	this(id, version, statedAxioms, nodeMap, null);
//     }
//     
//     public Collection<Axiom> getStatedAxioms() {
//         return statedAxioms;
//     }
// 
//     public Collection<Axiom> getInferredAxioms() {
//         return inferredAxioms;
//     }
//     
//     public Node getNode(String id) {
//         return nodeMap.get(id);
//     }
// 
//     public Iterator<Node> nodeIterator() {
//         Set<Node> set = new HashSet<Node>(nodeMap.values());
//         return set.iterator();
//     }
//     
//     public Map<String, Node> getNodeMap() {
//         return nodeMap;
//     }
// 
//     public Node getTopNode() {
//         return getNode(NamedConcept.TOP);
//     }
//     
//     public Node getBottomNode() {
//         return getNode(NamedConcept.BOTTOM);
//     }
//     
//     public void setNodeMap(Map<String, Node> nodeMap) {
//         this.nodeMap.clear();
//         this.nodeMap.putAll(nodeMap);
//     }
// 
//     public Set<Node> getAffectedNodes() {
//         return lastAffectedNodes;
//     }
//     
//     public void setAffectedNodes(Set<Node> nodes) {
//         lastAffectedNodes.clear();
//         lastAffectedNodes.addAll(nodes);
//     }
//     
//     public String getId() {
//         return id;
//     }
// 
//     public String getVersion() {
//         return version;
//     }
//     
// }
// 
// Path: ontology-model/src/main/java/au/csiro/ontology/Node.java
// public class Node implements Serializable {
//     /**
//      * 
//      */
//     private static final long serialVersionUID = 1L;
// 
//     /**
//      * Set of equivalent concepts in this node.
//      */
//     protected final Set<String> equivalentConcepts = Collections.newSetFromMap(
//             new ConcurrentHashMap<String, Boolean>());
//     
//     /**
//      * Set of parents nodes.
//      */
//     protected final Set<Node> parents = Collections.newSetFromMap(
//             new ConcurrentHashMap<Node, Boolean>());
//     
//     /**
//      * Set of child nodes.
//      */
//     protected final Set<Node> children = Collections.newSetFromMap(
//             new ConcurrentHashMap<Node, Boolean>());
// 
//     /**
//      * @return the equivalentConcepts
//      */
//     public Set<String> getEquivalentConcepts() {
//         return equivalentConcepts;
//     }
// 
//     /**
//      * @return the parents
//      */
//     public Set<Node> getParents() {
//         return parents;
//     }
// 
//     /**
//      * @return the children
//      */
//     public Set<Node> getChildren() {
//         return children;
//     }
// 
//     @Override
//     public String toString() {
//         StringBuilder sb = new StringBuilder();
//         int size = equivalentConcepts.size();
//         int i = 0;
//         sb.append("{");
//         for (String equiv : equivalentConcepts) {
//             sb.append(equiv);
//             if (++i < size)
//                 sb.append(", ");
//         }
//         sb.append("}");
//         return sb.toString();
//     }
// 
// }


// Path: ontology-model/src/main/java/au/csiro/ontology/util/Traversal.java
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Map;
import java.util.Set;
import au.csiro.ontology.Ontology;
import au.csiro.ontology.Node;

                    int min;
                    int max;
                    
                    if (ont.getTopNode().equals(node)) {
                        min = max = 0;
                    } else {
                        min = Integer.MAX_VALUE;
                        max = Integer.MIN_VALUE;
                        for (Node parent: node.getParents()) {
                            min = Math.min(min, minLevel.get(parent) + 1);
                            max = Math.max(max, maxLevel.get(parent) + 1);
                        }
                    }
                    minLevel.put(node, min);
                    maxLevel.put(node, max);
                    
                    result.put(node, new int[] {min, max});
                }
            };

            BFS_MAX.accept(ont, v);
            
            return result;
        }
    }
    
}

abstract class AbstractTraversal implements Traversal {
    
    public void accept(Ontology ont, Visitor... visitors) {