code: private boolean advance() {
      // done when there are depth iterators and the last iterator has an item
      while (iterators.size() < depth || !iterators.getLast().hasNext()) {
        // each iteration: add an iterator for the next level from the current
        // last iterator, or remove the last iterator because it is empty
        if (iterators.getLast().hasNext()) {
          current.add(iterators.getLast().next());
          iterators.add(getLevel(current).iterator());
        } else {
          iterators.removeLast();
          if (iterators.isEmpty()) {
            return false;
          } else {
            current.removeLast();
          }
        }
      }
  
      return true;
    }
docs: Advance the iterator stack to the next item or return false if there are
  none left.
  
  If this function returns true, then there are {@code depth} iterators in
  the iterator stack and {@code hasNext()} is true for the last iterator.
  
  If this function returns false, then there are no more items in the multi-
  level iterator. The top-most iterator, and the tree under it, have been
  exhausted.
  
  @return true if there is a next item, false if this iterator is exhausted