private Predicates getPredicates(Step step, Traversal.Admin traversal) {
    Predicates predicates = new Predicates();
    Step<?, ?> nextStep = step.getNextStep();

    while (true) {
      if (nextStep instanceof HasContainerHolder) {
        HasContainerHolder hasContainerHolder = (HasContainerHolder) nextStep;
        boolean skip = false;
        for (HasContainer has : hasContainerHolder.getHasContainers())
          if (has.getPredicate().getTraversals().size() > 0) skip = true;

        if (!skip) {
          hasContainerHolder.getHasContainers().forEach((has) -> predicates.hasContainers.add(has));
          nextStep.getLabels().forEach(label -> predicates.labels.add(label.toString()));
          traversal.removeStep(nextStep);
        }
      } else if (nextStep instanceof RangeGlobalStep) {
        RangeGlobalStep rangeGlobalStep = (RangeGlobalStep) nextStep;
        predicates.limitLow = rangeGlobalStep.getLowRange();
        predicates.limitHigh = rangeGlobalStep.getHighRange();
        traversal.removeStep(nextStep);
      } else return predicates;

      nextStep = nextStep.getNextStep();
    }
  }
 public static void reIdSteps(
     final StepPosition stepPosition, final Traversal.Admin<?, ?> traversal) {
   stepPosition.x = 0;
   stepPosition.y = -1;
   stepPosition.z = -1;
   stepPosition.parentId = null;
   Traversal.Admin<?, ?> current = traversal;
   while (!(current instanceof EmptyTraversal)) {
     stepPosition.y++;
     final TraversalParent parent = current.getParent();
     if (null == stepPosition.parentId && !(parent instanceof EmptyStep))
       stepPosition.parentId = parent.asStep().getId();
     if (-1 == stepPosition.z) {
       final int globalChildrenSize = parent.getGlobalChildren().size();
       for (int i = 0; i < globalChildrenSize; i++) {
         if (parent.getGlobalChildren().get(i) == current) {
           stepPosition.z = i;
         }
       }
       for (int i = 0; i < parent.getLocalChildren().size(); i++) {
         if (parent.getLocalChildren().get(i) == current) {
           stepPosition.z = i + globalChildrenSize;
         }
       }
     }
     current = parent.asStep().getTraversal();
   }
   if (-1 == stepPosition.z) stepPosition.z = 0;
   if (null == stepPosition.parentId) stepPosition.parentId = "";
   for (final Step<?, ?> step : traversal.getSteps()) {
     step.setId(stepPosition.nextXId());
   }
 }
 /**
  * Gets the index of a particular step in the {@link Traversal}.
  *
  * @param step the step to retrieve the index for
  * @param traversal the traversal to perform the action on
  * @return the index of the step or -1 if the step is not present
  */
 public static <S, E> int stepIndex(final Step<S, E> step, final Traversal.Admin<?, ?> traversal) {
   int i = 0;
   for (final Step s : traversal.getSteps()) {
     if (s.equals(step, true)) return i;
     i++;
   }
   return -1;
 }
 /**
  * Determine if the traversal has a step of an assignable class.
  *
  * @param superClass the step super class to look for
  * @param traversal the traversal to perform the action on
  * @return {@code true} if the class is found and {@code false} otherwise
  */
 public static boolean hasStepOfAssignableClass(
     final Class superClass, final Traversal.Admin<?, ?> traversal) {
   for (final Step<?, ?> step : traversal.getSteps()) {
     if (superClass.isAssignableFrom(step.getClass())) {
       return true;
     }
   }
   return false;
 }
 /**
  * Determine if the traversal has a step of a particular class.
  *
  * @param stepClass the step class to look for
  * @param traversal the traversal to perform the action on
  * @return {@code true} if the class is found and {@code false} otherwise
  */
 public static boolean hasStepOfClass(
     final Class stepClass, final Traversal.Admin<?, ?> traversal) {
   for (final Step<?, ?> step : traversal.getSteps()) {
     if (step.getClass().equals(stepClass)) {
       return true;
     }
   }
   return false;
 }
 public static <S> List<S> getStepsOfClass(
     final Class<S> stepClass, final Traversal.Admin<?, ?> traversal) {
   List<S> steps = new ArrayList<>();
   for (Step step : traversal.getSteps()) {
     if (step.getClass().equals(stepClass)) {
       steps.add((S) step);
     }
   }
   return steps;
 }
 private static Set<String> getLabels(
     final Set<String> labels, final Traversal.Admin<?, ?> traversal) {
   for (final Step<?, ?> step : traversal.getSteps()) {
     labels.addAll(step.getLabels());
     if (step instanceof TraversalParent) {
       ((TraversalParent) step).getLocalChildren().forEach(child -> getLabels(labels, child));
       ((TraversalParent) step).getGlobalChildren().forEach(child -> getLabels(labels, child));
     }
   }
   return labels;
 }
 public static <S, E> void removeToTraversal(
     final Step<S, ?> startStep,
     final Step<?, E> endStep,
     final Traversal.Admin<S, E> newTraversal) {
   final Traversal.Admin<?, ?> originalTraversal = startStep.getTraversal();
   Step<?, ?> currentStep = startStep;
   while (currentStep != endStep && !(currentStep instanceof EmptyStep)) {
     final Step<?, ?> temp = currentStep.getNextStep();
     originalTraversal.removeStep(currentStep);
     newTraversal.addStep(currentStep);
     currentStep = temp;
   }
 }
 public static <S> List<S> getStepsOfAssignableClassRecursively(
     final Class<S> stepClass, final Traversal.Admin<?, ?> traversal) {
   final List<S> list = new ArrayList<>();
   for (final Step<?, ?> step : traversal.getSteps()) {
     if (stepClass.isAssignableFrom(step.getClass())) list.add((S) step);
     if (step instanceof TraversalParent) {
       for (final Traversal.Admin<?, ?> globalChild :
           ((TraversalParent) step).getGlobalChildren()) {
         list.addAll(TraversalHelper.getStepsOfAssignableClassRecursively(stepClass, globalChild));
       }
     }
   }
   return list;
 }
 /**
  * Determine if the traversal has a step of an assignable class in the current {@link Traversal}
  * and its child traversals.
  *
  * @param stepClass the step class to look for
  * @param traversal the traversal in which to look for the given step class
  * @return <code>true</code> if any step in the given traversal (and its child traversals) is an
  *     instance of the given <code>stepClass</code>, otherwise <code>false</code>.
  */
 public static boolean hasStepOfAssignableClassRecursively(
     final Class stepClass, final Traversal.Admin<?, ?> traversal) {
   for (final Step<?, ?> step : traversal.getSteps()) {
     if (stepClass.isAssignableFrom(step.getClass())) {
       return true;
     }
     if (step instanceof TraversalParent) {
       for (final Traversal.Admin<?, ?> globalChild :
           ((TraversalParent) step).getGlobalChildren()) {
         if (hasStepOfAssignableClassRecursively(stepClass, globalChild)) return true;
       }
     }
   }
   return false;
 }
 /**
  * Determine if the traversal has any of the supplied steps of an assignable class in the current
  * {@link Traversal} and its child traversals.
  *
  * @param stepClasses the step classes to look for
  * @param traversal the traversal in which to look for the given step classes
  * @return <code>true</code> if any step in the given traversal (and its child traversals) is an
  *     instance of a class provided in <code>stepClasses</code>, otherwise <code>false</code>.
  */
 public static boolean hasStepOfAssignableClassRecursively(
     final Collection<Class> stepClasses, final Traversal.Admin<?, ?> traversal) {
   if (stepClasses.size() == 1)
     return hasStepOfAssignableClassRecursively(stepClasses.iterator().next(), traversal);
   for (final Step<?, ?> step : traversal.getSteps()) {
     if (IteratorUtils.anyMatch(
         stepClasses.iterator(), stepClass -> stepClass.isAssignableFrom(step.getClass()))) {
       return true;
     }
     if (step instanceof TraversalParent) {
       for (final Traversal.Admin<?, ?> globalChild :
           ((TraversalParent) step).getGlobalChildren()) {
         if (hasStepOfAssignableClassRecursively(stepClasses, globalChild)) return true;
       }
     }
   }
   return false;
 }
 private static Set<Scoping.Variable> getVariableLocations(
     final Set<Scoping.Variable> variables, final Traversal.Admin<?, ?> traversal) {
   if (variables.size() == 2)
     return variables; // has both START and END so no need to compute further
   final Step<?, ?> startStep = traversal.getStartStep();
   if (StartStep.isVariableStartStep(startStep)) variables.add(Scoping.Variable.START);
   else if (startStep instanceof WherePredicateStep) {
     if (((WherePredicateStep) startStep).getStartKey().isPresent())
       variables.add(Scoping.Variable.START);
   } else if (startStep instanceof WhereTraversalStep.WhereStartStep) {
     if (!((WhereTraversalStep.WhereStartStep) startStep).getScopeKeys().isEmpty())
       variables.add(Scoping.Variable.START);
   } else if (startStep instanceof MatchStep.MatchStartStep) {
     if (((MatchStep.MatchStartStep) startStep).getSelectKey().isPresent())
       variables.add(Scoping.Variable.START);
   } else if (startStep instanceof MatchStep) {
     ((MatchStep<?, ?>) startStep)
         .getGlobalChildren()
         .forEach(child -> TraversalHelper.getVariableLocations(variables, child));
   } else if (startStep instanceof ConnectiveStep
       || startStep instanceof NotStep
       || startStep instanceof WhereTraversalStep)
     ((TraversalParent) startStep)
         .getLocalChildren()
         .forEach(child -> TraversalHelper.getVariableLocations(variables, child));
   ///
   final Step<?, ?> endStep = traversal.getEndStep();
   if (endStep instanceof WherePredicateStep) {
     if (((WherePredicateStep) endStep).getStartKey().isPresent())
       variables.add(Scoping.Variable.END);
   } else if (endStep instanceof WhereTraversalStep.WhereEndStep) {
     if (!((WhereTraversalStep.WhereEndStep) endStep).getScopeKeys().isEmpty())
       variables.add(Scoping.Variable.END);
   } else if (endStep instanceof MatchStep.MatchEndStep) {
     if (((MatchStep.MatchEndStep) endStep).getMatchKey().isPresent())
       variables.add(Scoping.Variable.END);
   } else if (!endStep.getLabels().isEmpty()) variables.add(Scoping.Variable.END);
   ///
   return variables;
 }
 /**
  * Returns the name of <i>step</i> truncated to <i>maxLength</i>. An ellipses is appended when the
  * name exceeds <i>maxLength</i>.
  *
  * @param step
  * @param maxLength Includes the 3 "..." characters that will be appended when the length of the
  *     name exceeds maxLength.
  * @return short step name.
  */
 public static String getShortName(final Step step, final int maxLength) {
   final String name = step.toString();
   if (name.length() > maxLength) return name.substring(0, maxLength - 3) + "...";
   return name;
 }
 @Override
 public void apply(final Traversal.Admin<?, ?> traversal) {
   final TraversalParent parent = traversal.getParent();
   int size = traversal.getSteps().size();
   Step prev = null;
   for (int i = 0; i < size; i++) {
     final Step curr = traversal.getSteps().get(i);
     if (curr instanceof CountGlobalStep && i < size - 1) {
       final Step next = traversal.getSteps().get(i + 1);
       if (next instanceof IsStep
           && !(prev
               instanceof
               RangeGlobalStep)) { // if a RangeStep was provided, assume that the user knows what
                                   // he's doing
         final IsStep isStep = (IsStep) next;
         final P isStepPredicate = isStep.getPredicate();
         Long highRange = null;
         boolean useNotStep = false;
         for (P p :
             isStepPredicate instanceof ConnectiveP
                 ? ((ConnectiveP<?>) isStepPredicate).getPredicates()
                 : Collections.singletonList(isStepPredicate)) {
           final Object value = p.getValue();
           final BiPredicate predicate = p.getBiPredicate();
           if (value instanceof Number) {
             final long highRangeOffset =
                 INCREASED_OFFSET_SCALAR_PREDICATES.contains(predicate) ? 1L : 0L;
             final Long highRangeCandidate = ((Number) value).longValue() + highRangeOffset;
             final boolean update = highRange == null || highRangeCandidate > highRange;
             if (update) {
               if (parent instanceof EmptyStep) {
                 useNotStep = true;
               } else {
                 if (parent instanceof RepeatStep) {
                   final RepeatStep repeatStep = (RepeatStep) parent;
                   useNotStep =
                       Objects.equals(traversal, repeatStep.getUntilTraversal())
                           || Objects.equals(traversal, repeatStep.getEmitTraversal());
                 } else {
                   useNotStep = parent instanceof FilterStep || parent instanceof SideEffectStep;
                 }
               }
               highRange = highRangeCandidate;
               useNotStep &=
                   curr.getLabels().isEmpty()
                       && next.getLabels().isEmpty()
                       && next.getNextStep() instanceof EmptyStep
                       && ((highRange <= 1L && predicate.equals(Compare.lt))
                           || (highRange == 1L
                               && (predicate.equals(Compare.eq)
                                   || predicate.equals(Compare.lte))));
             }
           } else {
             final Long highRangeOffset = RANGE_PREDICATES.get(predicate);
             if (value instanceof Collection && highRangeOffset != null) {
               final Object high = Collections.max((Collection) value);
               if (high instanceof Number) {
                 final Long highRangeCandidate = ((Number) high).longValue() + highRangeOffset;
                 final boolean update = highRange == null || highRangeCandidate > highRange;
                 if (update) highRange = highRangeCandidate;
               }
             }
           }
         }
         if (highRange != null) {
           if (useNotStep) {
             traversal.asAdmin().removeStep(next); // IsStep
             traversal.asAdmin().removeStep(curr); // CountStep
             size -= 2;
             if (prev != null) {
               final Traversal.Admin inner = __.start().asAdmin();
               TraversalHelper.insertAfterStep(prev, inner.getStartStep(), inner);
               TraversalHelper.replaceStep(prev, new NotStep<>(traversal, inner), traversal);
             } else {
               traversal.asAdmin().addStep(new NotStep<>(traversal, __.identity()));
             }
           } else {
             TraversalHelper.insertBeforeStep(
                 new RangeGlobalStep<>(traversal, 0L, highRange), curr, traversal);
           }
           i++;
         }
       }
     }
     prev = curr;
   }
 }
 public static Step getNextNonIdentityStep(final Step start) {
   Step currentStep = start.getNextStep();
   // Skip over identity steps
   while (currentStep instanceof IdentityStep) currentStep = currentStep.getNextStep();
   return currentStep;
 }