package com.tinkerpop.pipes.util.structures; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; /** * A Tree can be seen as an embedded Map object with various tree-like access methods. * * @author Marko A. Rodriguez (http://markorodriguez.com) */ public class Tree<T> extends HashMap<T, Tree<T>> { public Tree() { super(); } public Tree(final T... children) { this(); for (final T t : children) { this.put(t, new Tree<T>()); } } public Tree(final Map.Entry<T, Tree<T>>... children) { this(); for (final Map.Entry<T, Tree<T>> entry : children) { this.put(entry.getKey(), entry.getValue()); } } public List<Tree<T>> getTreesAtDepth(final int depth) { final List<Tree<T>> branches = new ArrayList<Tree<T>>(); List<Tree<T>> currentDepth = Arrays.asList(this); for (int i = 0; i < depth; i++) { if (i == depth - 1) { return currentDepth; } else { final List<Tree<T>> temp = new ArrayList<Tree<T>>(); for (final Tree<T> t : currentDepth) { temp.addAll(t.values()); } currentDepth = temp; } } return branches; } public List<T> getObjectsAtDepth(final int depth) { final List<T> list = new ArrayList<T>(); for (final Tree<T> t : this.getTreesAtDepth(depth)) { list.addAll(t.keySet()); } return list; } public List<Tree<T>> getLeafTrees() { final List<Tree<T>> leaves = new ArrayList<Tree<T>>(); List<Tree<T>> currentDepth = Arrays.asList(this); boolean allLeaves = false; while (!allLeaves) { allLeaves = true; final List<Tree<T>> temp = new ArrayList<Tree<T>>(); for (final Tree<T> t : currentDepth) { if (t.isLeaf()) { for (Map.Entry<T, Tree<T>> t2 : t.entrySet()) { leaves.add(new Tree<T>(t2)); } } else { allLeaves = false; temp.addAll(t.values()); } } currentDepth = temp; } return leaves; } public List<T> getLeafObjects() { final List<T> leaves = new ArrayList<T>(); for (final Tree<T> t : this.getLeafTrees()) { leaves.addAll(t.keySet()); } return leaves; } public boolean isLeaf() { Collection<Tree<T>> values = this.values(); return values.iterator().next().isEmpty(); } public static <T> Map.Entry<T, Tree<T>> createTree(T key, Tree<T> tree) { return new SimpleEntry<T, Tree<T>>(key, tree); } }