TreePath (@NotNull TreeModel model, @NotNull TreeVisitor visitor) { Object root = model.getRoot(); if (root == null) return null; TreePath path = new TreePath(root); switch (visitor.visit(path)) { case INTERRUPT -> { return path; // root path is found } case CONTINUE -> { // visit children } default -> { return null; // skip children } } Deque<Deque<TreePath>> stack = new ArrayDeque<>(); stack.push(children(model, path)); while (path != null) { Deque<TreePath> siblings = stack.peek(); if (siblings == null) return null; // nothing to process TreePath next = siblings.poll(); if (next == null) { LOG.assertTrue(siblings == stack.poll()); path = path.getParentPath(); } else { switch (visitor.visit(next)) { case INTERRUPT -> { return next; // path is found } case CONTINUE -> { path = next; stack.push(children(model, path)); } case SKIP_SIBLINGS -> siblings.clear(); case SKIP_CHILDREN -> {} } } } LOG.assertTrue(stack.isEmpty()); return null; }