package com.tinkerpop.blueprints.strategy;

import com.tinkerpop.blueprints.Edge;
import com.tinkerpop.blueprints.Graph;
import com.tinkerpop.blueprints.Strategy;
import com.tinkerpop.blueprints.Vertex;
import com.tinkerpop.blueprints.query.GraphQuery;
import com.tinkerpop.blueprints.util.function.TriFunction;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.function.UnaryOperator;

/**
 * @author Stephen Mallette (http://stephen.genoprime.com)
 */
public class SequenceGraphStrategy implements GraphStrategy {
    private final List<GraphStrategy> graphStrategySequence;

    public SequenceGraphStrategy(final GraphStrategy... strategies) {
        this.graphStrategySequence = new ArrayList<>(Arrays.asList(strategies));
    }

    @Override
    public UnaryOperator<Function<Object[], Vertex>> getAddVertexStrategy(final Strategy.Context<Graph> ctx) {
        return this.composeStrategyUnaryOperator(s -> s.getAddVertexStrategy(ctx));
    }

    @Override
    public UnaryOperator<TriFunction<String, Vertex, Object[], Edge>> getAddEdgeStrategy(final Strategy.Context<Vertex> ctx) {
        return this.composeStrategyUnaryOperator(s -> s.getAddEdgeStrategy(ctx));
    }

    @Override
    public UnaryOperator<Supplier<Iterable<Vertex>>> getGraphQueryVerticesStrategy(Strategy.Context<GraphQuery> ctx) {
        return this.composeStrategyUnaryOperator(s -> s.getGraphQueryVerticesStrategy(ctx));
    }

    @Override
    public UnaryOperator<Function<Object[], GraphQuery>> getGraphQueryIdsStrategy(Strategy.Context<GraphQuery> ctx) {
        return this.composeStrategyUnaryOperator(s -> s.getGraphQueryIdsStrategy(ctx));
    }

    /**
     * Compute a new strategy function from the sequence of supplied {@link GraphStrategy} objects.
     *
     * @param f a {@link Function} that extracts a particular strategy implementation from a {@link GraphStrategy}
     * @return a newly constructed {@link UnaryOperator} that applies each extracted strategy implementation in
     *         the order supplied
     */
    private UnaryOperator composeStrategyUnaryOperator(final Function<GraphStrategy, UnaryOperator> f) {
        return this.graphStrategySequence.stream().map(f).reduce(null,
                (acc, next) -> acc == null ? next : toUnaryOp(acc.compose(next)));
    }

    /**
     * Converts a {@link Function} to a {@link UnaryOperator} since the call to
     * {@link UnaryOperator#andThen(java.util.function.Function)} doesn't return {@link UnaryOperator} and can't
     * be casted to one.
     *
     * @param f a {@link Function} that has the same argument and return type
     * @return a {@link UnaryOperator} of the supplied {@code f}
     */
    private static <T> UnaryOperator<T> toUnaryOp(final Function<T,T> f) {
        return new UnaryOperator<T>() {
            @Override
            public T apply(T t) {
                return f.apply(t);
            }
        };
    }
}
@@ -107,21 +107,104 @@
 eprints.
-Graph
+Element;%0Aimport com.tinkerpop.blueprints.Graph;%0Aimport com.tinkerpop.blueprints.Property
 ;%0Aimport
@@ -461,24 +461,62 @@
 .util.List;%0A
+import java.util.function.BiConsumer;%0A
 import java.
@@ -1769,32 +1769,32 @@
 phQuery%3E ctx) %7B%0A
-
         return t
@@ -1864,32 +1864,1148 @@
 y(ctx));%0A    %7D%0A%0A
+    @Override%0A    public UnaryOperator%3CSupplier%3CVoid%3E%3E getRemoveElementStrategy(Strategy.Context%3C? extends Element%3E ctx) %7B%0A        return this.composeStrategyUnaryOperator(s -%3E s.getRemoveElementStrategy(ctx));%0A    %7D%0A%0A    @Override%0A    public %3CV%3E UnaryOperator%3CSupplier%3CVoid%3E%3E getRemovePropertyStrategy(Strategy.Context%3CProperty%3CV%3E%3E ctx) %7B%0A        return this.composeStrategyUnaryOperator(s -%3E s.getRemovePropertyStrategy(ctx));%0A    %7D%0A%0A    @Override%0A    public %3CV%3E UnaryOperator%3CFunction%3CString, Property%3CV%3E%3E%3E getElementGetProperty(Strategy.Context%3C? extends Element%3E ctx) %7B%0A        return this.composeStrategyUnaryOperator(s -%3E s.getElementGetProperty(ctx));%0A    %7D%0A%0A    @Override%0A    public %3CV%3E UnaryOperator%3CBiConsumer%3CString, V%3E%3E getElementSetProperty(Strategy.Context%3C? extends Element%3E ctx) %7B%0A        return this.composeStrategyUnaryOperator(s -%3E s.getElementSetProperty(ctx));%0A    %7D%0A%0A    @Override%0A    public UnaryOperator%3CBiConsumer%3CString, Object%3E%3E getGraphAnnotationsSet(Strategy.Context%3CGraph.Annotations%3E ctx) %7B%0A        return this.composeStrategyUnaryOperator(s -%3E s.getGraphAnnotationsSet(ctx));%0A    %7D%0A%0A
     /**%0A     * C

Add implementations for SequenceGraphStrategy.