code: private <ElementType extends Element> Iterator<? extends ElementType> elements(
        BiFunction<OGraph, Object[], Iterator<ElementType>> getElementsByIds,
        TriFunction<OGraph, OIndex<Object>, Iterator<Object>, Stream<? extends ElementType>> getElementsByIndex,
        Function<OGraph, Iterator<ElementType>> getAllElements, Function<OGremlinResult, ElementType> getElement) {
      final OGraph graph = getGraph();
  
      if (this.ids != null && this.ids.length > 0) {
        /** Got some element IDs, so just get the elements using those */
        return this.iteratorList(getElementsByIds.apply(graph, this.ids));
      } else {
        Optional<? extends Iterator<? extends ElementType>> streamIterator = buildQuery().map(
            (query) -> query.execute(getGraph()).stream().map(getElement::apply)
                .filter(element -> HasContainer.testAll(element, this.hasContainers)))
            .map(stream -> new DefaultCloseableIterator<ElementType>(stream.iterator()) {
              @Override
              public void close() {
                stream.close();
              }
            });
        if (streamIterator.isPresent()) {
          return streamIterator.get();
        } else {
          return this.iteratorList(getAllElements.apply(graph));
        }
      }
  
    }
docs: Gets an iterator over those vertices/edges that have the specific IDs wanted, or those that have indexed properties with the
  wanted values, or failing that by just getting all of the vertices or edges.
  
  @param getElementsByIds   Function that will return an iterator over all the vertices/edges in the graph that have the specific
  IDs
  @param getElementsByIndex Function that returns a stream of all the vertices/edges in the graph that have an indexed property
  with a specific value
  @param getAllElements     Function that returns an iterator of all the vertices or all the edges (i.e. full scan)
  
  @return An iterator for all the vertices/edges for this step