ParseTreeNode { public void traverseParent(BiPredicate<ParseTreeNode, ParseTreeNode> consumer) { if (parent != null) { final boolean test = consumer.test(parent, this); if (test) { parent.traverseParent(consumer); } } } ParseTreeNode(PhraseChunk chunk);  ParseTreeNode(List<ParseTreeNode> children); void traverseChildren(Consumer<List<ParseTreeNode>> consumer); void traverseParent(BiPredicate<ParseTreeNode, ParseTreeNode> consumer); boolean isRoot(); PhraseChunk getChunk(); void setParent(ParseTreeNode parent); List<ParseTreeNode> getChildren(); boolean hasChildren(); ParseTreeNode getParent(); void addChild(ParseTreeNode child); void addWords(Collection<WordToken> word); List<WordToken> getWords(); @Override String toString(); boolean containsWord(Predicate<WordToken> filter); void log(String indent);  }
@Test public void testTraverseParent() { a.traverseParent( (p, c) -> { if (p.equals(root)) { grandparentSeen = true; } return true; }); assertTrue(grandparentSeen); }