protected static Traversal.Admin<Vertex, Edge> getEdgeFilter(final Traversal.Admin<?, ?> traversal) {
        if (traversal.getStartStep() instanceof GraphStep && ((GraphStep) traversal.getStartStep()).returnsEdge())
            return null; // if the traversal is an edge traversal, don't filter (this can be made less stringent)
        if (TraversalHelper.hasStepOfAssignableClassRecursively(LambdaHolder.class, traversal))
            return null; // if the traversal contains lambdas, don't filter as you don't know what is being accessed by the lambdas
        final Map<Direction, Set<String>> directionLabels = new EnumMap<>(Direction.class);
        final Set<String> outLabels = new HashSet<>();
        final Set<String> inLabels = new HashSet<>();
        final Set<String> bothLabels = new HashSet<>();
        directionLabels.put(Direction.OUT, outLabels);
        directionLabels.put(Direction.IN, inLabels);
        directionLabels.put(Direction.BOTH, bothLabels);
        TraversalHelper.getStepsOfAssignableClassRecursively(VertexStep.class, traversal).forEach(step -> {
            // in-edge traversals require the outgoing edges for attachment
            final Direction direction = step.getDirection().equals(Direction.IN) && step.returnsEdge() ?
                    Direction.BOTH :
                    step.getDirection();
            final String[] edgeLabels = step.getEdgeLabels();
            if (edgeLabels.length == 0)
                directionLabels.get(direction).add(null); // null means all edges (don't filter)
            else
                Collections.addAll(directionLabels.get(direction), edgeLabels); // add edge labels associated with that direction
        });
        for (final String label : outLabels) { // if both in and out share the same labels, add them to both
            if (inLabels.contains(label)) {
                bothLabels.add(label);
            }
        }
        if (bothLabels.contains(null)) // if both on everything, you can't edges() filter
            return null;

        for (final String label : bothLabels) { // remove labels from out and in that are already handled by both
            outLabels.remove(label);
            inLabels.remove(label);
        }
        // construct edges(...)
        if (outLabels.isEmpty() && inLabels.isEmpty() && bothLabels.isEmpty())  // out/in/both are never called, thus, filter all edges
            return __.<Vertex>bothE().limit(0).asAdmin();
        else {
            final String[] ins = inLabels.contains(null) ? new String[]{} : inLabels.toArray(new String[inLabels.size()]);
            final String[] outs = outLabels.contains(null) ? new String[]{} : outLabels.toArray(new String[outLabels.size()]);
            final String[] boths = bothLabels.contains(null) ? new String[]{} : bothLabels.toArray(new String[bothLabels.size()]);

            if (outLabels.isEmpty() && inLabels.isEmpty()) // only both has labels
                return __.<Vertex>bothE(boths).asAdmin();
            else if (inLabels.isEmpty() && bothLabels.isEmpty()) // only out has labels
                return __.<Vertex>outE(outs).asAdmin();
            else if (outLabels.isEmpty() && bothLabels.isEmpty()) // only in has labels
                return __.<Vertex>inE(ins).asAdmin();
            else if (bothLabels.isEmpty())                        // out and in both have labels
                return __.<Vertex, Edge>union(__.inE(ins), __.outE(outs)).asAdmin();
            else if (outLabels.isEmpty() && ins.length > 0)       // in and both have labels (and in is not null)
                return __.<Vertex, Edge>union(__.inE(ins), __.bothE(boths)).asAdmin();
            else if (inLabels.isEmpty() && outs.length > 0)       // out and both have labels (and out is not null)
                return __.<Vertex, Edge>union(__.outE(outs), __.bothE(boths)).asAdmin();
            else
                return null;
            //throw new IllegalStateException("The label combination should not have reached this point: " + outLabels + "::" + inLabels + "::" + bothLabels);
        }
    }
@author Marko A. Rodriguez (http://markorodriguez.com)
gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/strategy/optimization/GraphFilterStrategy.java