public static Map<TraversalParent, Pair<Boolean, Set<String>>> getTraversalParentCache(
            final List<Pair<TraversalParent, List<Step<?,?>>>> traversalParentsStepsCollection) {
        final Map<TraversalParent, Pair<Boolean, Set<String>>> traversalParentCache = new HashMap<>();

        // build the cache and use it to detect if any children impact the Pair in any way. in the case of a
        // child with a lambda, the parent would simply inherit that true. in the case of additional labels they
        // would just be appended to the list for the parent.
        traversalParentsStepsCollection.forEach(pair -> {
            final TraversalParent k = pair.getValue0();
            final List<Step<?,?>> v = pair.getValue1();
            final boolean hasLambda = v.stream().anyMatch(s -> s instanceof LambdaHolder ||
                    (traversalParentCache.containsKey(s) && traversalParentCache.get(s).getValue0()));
            if (hasLambda) {
                traversalParentCache.put(k, Pair.with(true, Collections.emptySet()));
            } else {
                final Set<String> currentEntryScopeLabels = v.stream().filter(s -> s instanceof Scoping).
                        flatMap(s -> ((Scoping) s).getScopeKeys().stream()).collect(Collectors.toSet());
                final Set<String> allScopeLabels = new HashSet<>(currentEntryScopeLabels);
                v.stream().filter(traversalParentCache::containsKey).forEach(s -> {
                    final TraversalParent parent = (TraversalParent) s;
                    allScopeLabels.addAll(traversalParentCache.get(parent).getValue1());
                });
                traversalParentCache.put(k, Pair.with(false, allScopeLabels));
            }
        });
        return traversalParentCache;
    }
{@code FilterRankingStrategy} reorders filter- and order-steps according to their rank. Step ranks are defined within
the strategy and indicate when it is reasonable for a step to move in front of another. It will also do its best to
push step labels as far "right" as possible in order to keep traversers as small and bulkable as possible prior to
the absolute need for path-labeling.

@author Daniel Kuppitz (http://gremlin.guru)
@author Marko A. Rodriguez (http://markorodriguez.com)
@example <pre>
__.order().dedup()                        // is replaced by __.dedup().order()
__.dedup().filter(out()).has("value", 0)  // is replaced by __.has("value", 0).filter(out()).dedup()
</pre>
gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/FilterRankingStrategy.java