package org.codefx.libfx.collection.tree.stream; import java.util.ArrayDeque; import java.util.Deque; import java.util.List; import java.util.NoSuchElementException; import java.util.Objects; import java.util.Optional; /** * A {@link TreePath} which uses a stack to manage the path. * * @param <N> * the type of nodes in this path */ final class StackTreePath<N> implements TreePath<N> { /** * The path from the root to the current node as a stack with the root at the bottom and the most recently visited * node at the top. */ private final Deque<N> path; /** * Creates an empty path. */ public StackTreePath() { this.path = new ArrayDeque<>(); } /** * Creates a new path which is initialized to the specified list of nodes. * <p> * The list is interpreted as a path which starts in the list's first element. Hence for an initial path from * {@code start} to {@code end} the list should be such that {@code initialPath.indexOf(start) == 0} and * {@code initialPath.indexOf(end) == initialPath.size() - 1}. * * @param initialPath * the initial path */ public StackTreePath(List<? extends N> initialPath) { this(); Objects.requireNonNull(initialPath, "The argument 'initialPath' must not be null."); initialPath.forEach(this::append); } @Override public boolean isEmpty() { return path.isEmpty(); } @Override public Optional<N> getEnd() { return Optional.ofNullable(path.peek()); } @Override public void append(N node) { Objects.requireNonNull(node, "The argument 'node' must not be null."); path.push(node); } @Override public N removeEnd() throws NoSuchElementException { return path.pop(); } }