in gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/InlineFilterStrategy.java [116:185]
private static boolean processHasStep(final HasStep<?> step, final Traversal.Admin<?, ?> traversal) {
if (step.getPreviousStep() instanceof HasStep) {
final HasStep<?> previousStep = (HasStep<?>) step.getPreviousStep();
final List<HasContainer> hasContainers = new ArrayList<>(step.getHasContainers());
for (final HasContainer hasContainer : hasContainers) {
previousStep.addHasContainer(hasContainer);
}
TraversalHelper.copyLabels(step, previousStep, false);
TraversalHelper.removeStep(step, traversal);
return true;
} else if (step.getPreviousStep() instanceof VertexStepContract
&& ((VertexStepContract) step.getPreviousStep()).returnsEdge()
&& 0 == ((VertexStepContract) step.getPreviousStep()).getEdgeLabels().length) {
final VertexStepContract<Edge> previousStep = (VertexStepContract<Edge>) step.getPreviousStep();
final List<GValue<?>> edgeLabelGValues = new ArrayList<>();
for (final HasContainer hasContainer : new ArrayList<>(step.getHasContainers())) {
if (hasContainer.getKey().equals(T.label.getAccessor())) {
if (hasContainer.getBiPredicate() == Compare.eq &&
hasContainer.getValue() instanceof String &&
edgeLabelGValues.isEmpty()) {
edgeLabelGValues.add(hasContainer.getPredicate().isParameterized() ?
hasContainer.getPredicate().getGValues().iterator().next() :
GValue.ofString((String) hasContainer.getValue()));
step.removeHasContainer(hasContainer);
} else if (hasContainer.getBiPredicate() == Contains.within &&
hasContainer.getValue() instanceof Collection &&
((Collection) hasContainer.getValue()).containsAll(Arrays.asList(GValue.resolveToValues(edgeLabelGValues.stream().toArray(GValue[]::new))))) {
edgeLabelGValues.addAll(hasContainer.getPredicate().isParameterized() ?
hasContainer.getPredicate().getGValues() :
Arrays.asList(GValue.ensureGValues(((Collection<String>) hasContainer.getValue()).toArray())));
step.removeHasContainer(hasContainer);
} else if (hasContainer.getPredicate() instanceof OrP && edgeLabelGValues.isEmpty()) {
boolean removeContainer = true;
final List<P<?>> orps = ((OrP) hasContainer.getPredicate()).getPredicates();
final List<GValue<String>> newEdges = new ArrayList<>();
for (int i = 0; i < orps.size(); i++) {
if (orps.get(i).getBiPredicate() == Compare.eq && orps.get(i).getValue() instanceof String) {
newEdges.add(orps.get(i).isParameterized() ?
(GValue<String>) orps.get(i).getGValues().iterator().next() :
GValue.ofString((String) orps.get(i).getValue()));
} else {
removeContainer = false;
break;
}
}
if (removeContainer) {
edgeLabelGValues.addAll(newEdges);
step.removeHasContainer(hasContainer);
}
}
}
}
if (!edgeLabelGValues.isEmpty()) {
final VertexStepContract<Edge> newVertexStep = GValue.containsVariables(edgeLabelGValues.toArray()) ?
new VertexStepPlaceholder<>(traversal, Edge.class, previousStep.getDirection(), edgeLabelGValues.toArray(new GValue[edgeLabelGValues.size()])) :
new VertexStep<>(traversal, Edge.class, previousStep.getDirection(), Arrays.stream(GValue.resolveToValues(edgeLabelGValues.toArray(new GValue[edgeLabelGValues.size()]))).toArray(String[]::new));
TraversalHelper.replaceStep(previousStep, newVertexStep, traversal);
TraversalHelper.copyLabels(previousStep, newVertexStep, false);
if (step.getHasContainers().isEmpty()) {
TraversalHelper.copyLabels(step, newVertexStep, false);
TraversalHelper.removeStep(step, traversal);
}
return true;
}
return false;
} else
return false;
}