TreeNode implements Iterable<TreeNode<T>>, Serializable, Cloneable { public Collection<? extends TreeNode<T>> findAll(final T data) { if (isLeaf()) { return (data() == null ? data == null : data().equals(data)) ? Collections.singleton(this) : Collections.<TreeNode<T>>emptySet(); } final Collection<TreeNode<T>> searchedNodes = new HashSet<>(); traversePreOrder(new TraversalAction<TreeNode<T>>() { @Override public void perform(TreeNode<T> node) { if ((node.data() == null ? data == null : node.data().equals(data))) { searchedNodes.add(node); } } @Override public boolean isCompleted() { return false; } }); return searchedNodes; } TreeNode(T data);  TreeNode(); abstract Collection<? extends TreeNode<T>> subtrees(); abstract boolean add(TreeNode<T> subtree); abstract boolean dropSubtree(TreeNode<T> subtree); abstract void clear(); abstract TreeNodeIterator iterator(); T data(); void setData(T data); boolean isRoot(); TreeNode<T> root(); TreeNode<T> parent(); boolean isLeaf(); @SuppressWarnings("unchecked") TreeNode<T> find(final T data); Collection<? extends TreeNode<T>> findAll(final T data); boolean hasSubtree(TreeNode<T> subtree); boolean contains(TreeNode<T> node); boolean containsAll(Collection<TreeNode<T>> nodes); boolean remove(TreeNode<T> node); boolean removeAll(Collection<TreeNode<T>> nodes); void traversePreOrder(TraversalAction<TreeNode<T>> action); void traversePostOrder(TraversalAction<TreeNode<T>> action); Collection<TreeNode<T>> preOrdered(); Collection<TreeNode<T>> postOrdered(); Collection<? extends TreeNode<T>> path(TreeNode<T> descendant); TreeNode<T> commonAncestor(TreeNode<T> node); boolean isSiblingOf(TreeNode<T> node); boolean isAncestorOf(TreeNode<T> node); boolean isDescendantOf(TreeNode<T> node); long size(); int height(); int level(); @SuppressWarnings("unchecked") @Override TreeNode<T> clone(); @SuppressWarnings("unchecked") @Override boolean equals(Object obj); @Override int hashCode(); @Override String toString();  }
@Test public void testFindAll() { String messageSingletonCollectionFoundExpected = "The single tree node was expected to have the searched data, but actually was not"; assertEquals(messageSingletonCollectionFoundExpected, Collections.singleton(node6), node6.findAll(NODE_DATA_4)); assertEquals(messageSingletonCollectionFoundExpected, Collections.singleton(node7), node7.findAll(null)); assertEquals(messageSingletonCollectionFoundExpected, Collections.singleton(node2), root.findAll(NODE_DATA_2)); String messageCollectionFoundExpected = "The tree nodes was expected to have the searched data, but actually was not"; Collection<TreeNode<String>> expectedMany = new HashSet<>(); expectedMany.add(node4); expectedMany.add(node6); expectedMany.add(node9); assertEquals(messageCollectionFoundExpected, expectedMany, root.findAll(NODE_DATA_4)); String messageEmptyCollectionFoundExpected = "Three tree nodes with the searched data was not expected to be found, but actually was"; assertEquals(messageEmptyCollectionFoundExpected, Collections.emptySet(), node10.findAll("data")); }