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(); } }
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; }
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; }
@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; } }