This is an automated email from the ASF dual-hosted git repository. spmallette pushed a commit to branch gvalue in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
commit c9e6744b7289e12f45ecfb6e5f25d533e9b3e691 Author: Stephen Mallette <[email protected]> AuthorDate: Tue Aug 27 12:38:32 2024 -0400 wip - removed admin interface methods - doesn't work nice --- .../traversal/dsl/graph/GraphTraversal.java | 867 +++++++++------------ .../traversal/dsl/graph/GraphTraversalSource.java | 105 +-- .../gremlin/process/traversal/dsl/graph/__.java | 114 +++ .../gremlin/process/traversal/step/GValue.java | 42 + .../process/traversal/step/map/GraphStep.java | 10 +- .../process/traversal/step/map/VertexStep.java | 16 +- .../traversal/step/sideEffect/InjectStep.java | 8 +- .../process/traversal/step/util/AbstractStep.java | 44 -- .../optimization/InlineFilterStrategy.java | 2 +- .../tinkerpop/gremlin/util/CollectionUtil.java | 21 + 10 files changed, 597 insertions(+), 632 deletions(-) diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java index 5cf66f4d6c..5f6825acdc 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java @@ -205,8 +205,10 @@ import org.apache.tinkerpop.gremlin.structure.PropertyType; import org.apache.tinkerpop.gremlin.structure.T; import org.apache.tinkerpop.gremlin.structure.Vertex; import org.apache.tinkerpop.gremlin.structure.VertexProperty; +import org.apache.tinkerpop.gremlin.util.CollectionUtil; import org.apache.tinkerpop.gremlin.util.function.ConstantSupplier; +import java.lang.reflect.Array; import java.time.OffsetDateTime; import java.util.ArrayList; import java.util.Arrays; @@ -243,463 +245,6 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> { */ public interface Admin<S, E> extends Traversal.Admin<S, E>, GraphTraversal<S, E> { - /** - * Filter the <code>E</code> object given a biased coin toss. For internal use for parameterization features. - * - * @param probability the probability that the object will pass through the filter - * @return the traversal with an appended {@link CoinStep}. - * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#coin-step" target="_blank">Reference Documentation - Coin Step</a> - * @since 3.7.3 - */ - public default GraphTraversal<S, E> coin(final GValue<Double> probability) { - this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.coin, probability); - return this.asAdmin().addStep(new CoinStep<>(this.asAdmin(), probability)); - } - - /** - * Map any object to a fixed <code>E</code> value. For internal use for parameterization features. - * - * @return the traversal with an appended {@link ConstantStep}. - * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#constant-step" target="_blank">Reference Documentation - Constant Step</a> - * @since 3.7.3 - */ - public default <E2> GraphTraversal<S, E2> constant(final GValue<E2> e) { - this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.constant, e); - return this.asAdmin().addStep(new ConstantStep<E, E2>(this.asAdmin(), e)); - } - - /** - * Map the {@link Vertex} to its adjacent vertices given a direction and edge labels. The arguments for the - * labels must be either a {@code String} or a {@link GValue<String>}. For internal use for parameterization. - * - * @param direction the direction to traverse from the current vertex - * @param edgeLabels the edge labels to traverse - * @return the traversal with an appended {@link VertexStep}. - * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#vertex-steps" target="_blank">Reference Documentation - Vertex Step</a> - * @since 3.7.3 - */ - public default GraphTraversal<S, Vertex> to(final Direction direction, final Object... edgeLabels) { - this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.to, direction, edgeLabels); - return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Vertex.class, direction, edgeLabels)); - } - - /** - * Map the {@link Vertex} to its outgoing adjacent vertices given the edge labels. The arguments for the - * labels must be either a {@code String} or a {@link GValue<String>}. For internal use for parameterization. - * - * @param edgeLabels the edge labels to traverse - * @return the traversal with an appended {@link VertexStep}. - * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#vertex-steps" target="_blank">Reference Documentation - Vertex Step</a> - * @since 3.7.3 - */ - public default GraphTraversal<S, Vertex> out(final Object... edgeLabels) { - this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.out, edgeLabels); - return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Vertex.class, Direction.OUT, edgeLabels)); - } - - /** - * Map the {@link Vertex} to its incoming adjacent vertices given the edge labels. The arguments for the - * labels must be either a {@code String} or a {@link GValue<String>}. For internal use for parameterization. - * - * @param edgeLabels the edge labels to traverse - * @return the traversal with an appended {@link VertexStep}. - * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#vertex-steps" target="_blank">Reference Documentation - Vertex Step</a> - * @since 3.7.3 - */ - public default GraphTraversal<S, Vertex> in(final Object... edgeLabels) { - this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.in, edgeLabels); - return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Vertex.class, Direction.IN, edgeLabels)); - } - - /** - * Map the {@link Vertex} to its adjacent vertices given the edge labels. The arguments for the labels must be - * either a {@code String} or a {@link GValue<String>}. For internal use for parameterization. - * - * @param edgeLabels the edge labels to traverse - * @return the traversal with an appended {@link VertexStep}. - * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#vertex-steps" target="_blank">Reference Documentation - Vertex Step</a> - * @since 3.7.3 - */ - public default GraphTraversal<S, Vertex> both(final Object... edgeLabels) { - this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.both, edgeLabels); - return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Vertex.class, Direction.BOTH, edgeLabels)); - } - - /** - * Map the {@link Vertex} to its incident edges given the direction and edge labels. The arguments for the - * labels must be either a {@code String} or a {@link GValue<String>}. For internal use for parameterization. - * - * @param direction the direction to traverse from the current vertex - * @param edgeLabels the edge labels to traverse - * @return the traversal with an appended {@link VertexStep}. - * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#vertex-steps" target="_blank">Reference Documentation - Vertex Step</a> - * @since 3.7.3 - */ - public default GraphTraversal<S, Edge> toE(final Direction direction, final Object... edgeLabels) { - this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.toE, direction, edgeLabels); - return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Edge.class, direction, edgeLabels)); - } - - /** - * Map the {@link Vertex} to its outgoing incident edges given the edge labels. The arguments for the labels - * must be either a {@code String} or a {@link GValue<String>}. For internal use for parameterization. - * - * @param edgeLabels the edge labels to traverse - * @return the traversal with an appended {@link VertexStep}. - * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#vertex-steps" target="_blank">Reference Documentation - Vertex Step</a> - * @since 3.7.3 - */ - public default GraphTraversal<S, Edge> outE(final Object... edgeLabels) { - this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.outE, edgeLabels); - return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Edge.class, Direction.OUT, edgeLabels)); - } - - /** - * Map the {@link Vertex} to its incoming incident edges given the edge labels. The arguments for the labels - * must be either a {@code String} or a {@link GValue<String>}. For internal use for parameterization. - * - * @param edgeLabels the edge labels to traverse - * @return the traversal with an appended {@link VertexStep}. - * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#vertex-steps" target="_blank">Reference Documentation - Vertex Step</a> - * @since 3.7.3 - */ - public default GraphTraversal<S, Edge> inE(final Object... edgeLabels) { - this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.inE, edgeLabels); - return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Edge.class, Direction.IN, edgeLabels)); - } - - /** - * Map the {@link Vertex} to its incident edges given the edge labels. The arguments for the labels must be - * either a {@code String} or a {@link GValue<String>}. For internal use for parameterization. - * - * @param edgeLabels the edge labels to traverse - * @return the traversal with an appended {@link VertexStep}. - * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#vertex-steps" target="_blank">Reference Documentation - Vertex Step</a> - * @since 3.7.3 - */ - public default GraphTraversal<S, Edge> bothE(final Object... edgeLabels) { - this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.bothE, edgeLabels); - return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Edge.class, Direction.BOTH, edgeLabels)); - } - - /** - * Adds a {@link Vertex}. - * - * @param vertexLabel the label of the {@link Vertex} to add - * @return the traversal with the {@link AddVertexStep} added - * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#addvertex-step" target="_blank">Reference Documentation - AddVertex Step</a> - * @since 3.7.3 - */ - public default GraphTraversal<S, Vertex> addV(final GValue<String> vertexLabel) { - if (null == vertexLabel || null == vertexLabel.get()) throw new IllegalArgumentException("vertexLabel cannot be null"); - this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.addV, vertexLabel); - return this.asAdmin().addStep(new AddVertexStep<>(this.asAdmin(), vertexLabel)); - } - - /** - * Performs a merge (i.e. upsert) style operation for an {@link Vertex} using a {@code Map} as an argument. - * The {@code Map} represents search criteria and will match each of the supplied key/value pairs where the keys - * may be {@code String} property values or a value of {@link T}. If a match is not made it will use that search - * criteria to create the new {@link Vertex}. - * - * @param searchCreate This {@code Map} can have a key of {@link T} or a {@code String}. - * @since 3.7.3 - */ - public default GraphTraversal<S, Vertex> mergeV(final GValue<Map<Object, Object>> searchCreate) { - this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.mergeV, searchCreate); - final MergeVertexStep<S> step = new MergeVertexStep(this.asAdmin(), false, null == searchCreate ? GValue.ofMap(null) : searchCreate); - return this.asAdmin().addStep(step); - } - - /** - * Spawns a {@link GraphTraversal} by doing a merge (i.e. upsert) style operation for an {@link Edge} using a - * {@code Map} as an argument. - * - * @param searchCreate This {@code Map} can have a key of {@link T} {@link Direction} or a {@code String}. - * @since 3.7.3 - */ - public default GraphTraversal<S, Edge> mergeE(final GValue<Map<Object, Object>> searchCreate) { - // get a construction time exception if the Map is bad - this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.mergeE, searchCreate); - final MergeEdgeStep<S> step = new MergeEdgeStep(this.asAdmin(), false, null == searchCreate ? GValue.ofMap(null) : searchCreate); - return this.asAdmin().addStep(step); - } - - /** - * Adds an {@link Edge} with the specified edge label. - * - * @param edgeLabel the label of the newly added edge - * @return the traversal with the {@link AddEdgeStep} added - * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#addedge-step" target="_blank">Reference Documentation - AddEdge Step</a> - * @since 3.7.3 - */ - public default GraphTraversal<S, Edge> addE(final GValue<String> edgeLabel) { - this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.addE, edgeLabel); - return this.asAdmin().addStep(new AddEdgeStep<>(this.asAdmin(), edgeLabel)); - } - - /** - * Filters vertices, edges and vertex properties based on their label. - * - * @param label the label of the {@link Element} - * @param otherLabels additional labels of the {@link Element} - * @return the traversal with an appended {@link HasStep} - * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#has-step" target="_blank">Reference Documentation - Has Step</a> - * @since 3.2.2 - */ - public default GraphTraversal<S, E> hasLabel(final GValue<String> label, final GValue<String>... otherLabels) { - this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.hasLabel, label, otherLabels); - - // groovy evaluation seems to do strange things with varargs given hasLabel(null, null). odd someone would - // do this but the failure is ugly if not handled. - final int otherLabelsLength = null == otherLabels ? 0 : otherLabels.length; - final Object[] labels = new Object[otherLabelsLength + 1]; - labels[0] = label; - if (otherLabelsLength > 0) - System.arraycopy(otherLabels, 0, labels, 1, otherLabelsLength); - return TraversalHelper.addHasContainer(this.asAdmin(), new HasContainer(T.label.getAccessor(), labels.length == 1 ? P.eq(labels[0]) : P.within(labels))); - } - - /** - * This is a step modulator to a {@link TraversalOptionParent} like {@code choose()} or {@code mergeV()} where the - * provided argument associated to the {@code token} is applied according to the semantics of the step. Please see - * the documentation of such steps to understand the usage context. - * - * @param token the token that would trigger this option which may be a {@link Pick}, {@link Merge}, - * a {@link Traversal}, {@link Predicate}, or object depending on the step being modulated. - * @param traversalOption the option as a traversal - * @return the traversal with the modulated step - * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#choose-step" target="_blank">Reference Documentation - Choose Step</a> - * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#mergev-step" target="_blank">Reference Documentation - MergeV Step</a> - * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#mergee-step" target="_blank">Reference Documentation - MergeE Step</a> - * @since 3.0.0-incubating - */ - public default <M, E2> GraphTraversal<S, E> option(final GValue<M> token, final Traversal<?, E2> traversalOption) { - this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.option, token, traversalOption); - - // handle null similar to how option() with Map handles it, otherwise we get a NPE if this one gets used - final Traversal.Admin<E,E2> t = null == traversalOption ? - new ConstantTraversal<>(null) : (Traversal.Admin<E, E2>) traversalOption.asAdmin(); - ((TraversalOptionParent<M, E, E2>) this.asAdmin().getEndStep()).addChildOption(token.get(), t); - return this; - } - - /** - * This is a step modulator to a {@link TraversalOptionParent} like {@code choose()} or {@code mergeV()} where the - * provided argument associated to the {@code token} is applied according to the semantics of the step. Please see - * the documentation of such steps to understand the usage context. - * - * @param m Provides a {@code Map} as the option which is the same as doing {@code constant(m)}. - * @return the traversal with the modulated step - * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#mergev-step" target="_blank">Reference Documentation - MergeV Step</a> - * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#mergee-step" target="_blank">Reference Documentation - MergeE Step</a> - * @since 3.7.3 - */ - public default <M, E2> GraphTraversal<S, E> option(final M token, final GValue<Map<Object, Object>> m) { - this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.option, token, m); - ((TraversalOptionParent<M, E, E2>) this.asAdmin().getEndStep()).addChildOption(token, (Traversal.Admin<E, E2>) new ConstantTraversal<>(m).asAdmin()); - return this; - } - - /** - * This is a step modulator to a {@link TraversalOptionParent} like {@code choose()} or {@code mergeV()} where the - * provided argument associated to the {@code token} is applied according to the semantics of the step. Please see - * the documentation of such steps to understand the usage context. - * - * @param m Provides a {@code Map} as the option which is the same as doing {@code constant(m)}. - * @return the traversal with the modulated step - * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#mergev-step" target="_blank">Reference Documentation - MergeV Step</a> - * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#mergee-step" target="_blank">Reference Documentation - MergeE Step</a> - * @since 3.7.3 - */ - public default <M, E2> GraphTraversal<S, E> option(final Merge merge, final GValue<Map<Object, Object>> m, final VertexProperty.Cardinality cardinality) { - this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.option, merge, m, cardinality); - - final Map<Object, Object> map = m.get(); - - // do explicit cardinality for every single pair in the map - for (Object k : map.keySet()) { - final Object o = map.get(k); - if (!(o instanceof CardinalityValueTraversal)) - map.put(k, new CardinalityValueTraversal(cardinality, o)); - } - ((TraversalOptionParent<M, E, E2>) this.asAdmin().getEndStep()).addChildOption((M) merge, (Traversal.Admin<E, E2>) new ConstantTraversal<>(m).asAdmin()); - return this; - } - - /** - * Combines the list traverser and list argument. Also known as concatenation or append. - * - * @return the traversal with an appended {@link CombineStep}. - * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#combine-step" target="_blank">Reference Documentation - Combine Step</a> - * @since 3.7.3 - */ - public default GraphTraversal<S, List<?>> combine(final GValue<Object> values) { - this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.combine, values); - return this.asAdmin().addStep(new CombineStep<>(this.asAdmin(), values)); - } - - /** - * Joins together the elements of the incoming list traverser together with the provided delimiter. - * - * @return the traversal with an appended {@link ConjoinStep}. - * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#conjoin-step" target="_blank">Reference Documentation - Conjoin Step</a> - * @since 3.7.3 - */ - public default GraphTraversal<S, String> conjoin(final GValue<String> delimiter) { - this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.conjoin, delimiter); - return this.asAdmin().addStep(new ConjoinStep<>(this.asAdmin(), delimiter)); - } - - /** - * Calculates the difference between the list traverser and list argument. - * - * @return the traversal with an appended {@link DifferenceStep}. - * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#difference-step" target="_blank">Reference Documentation - Difference Step</a> - * @since 3.7.1 - */ - public default GraphTraversal<S, Set<?>> difference(final GValue<Object> values) { - this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.difference, values); - return this.asAdmin().addStep(new DifferenceStep<>(this.asAdmin(), values)); - } - - /** - * Calculates the disjunction between the list traverser and list argument. - * - * @return the traversal with an appended {@link DisjunctStep}. - * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#disjunct-step" target="_blank">Reference Documentation - Disjunct Step</a> - * @since 3.7.3 - */ - public default GraphTraversal<S, Set<?>> disjunct(final GValue<Object> values) { - this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.disjunct, values); - return this.asAdmin().addStep(new DisjunctStep<>(this.asAdmin(), values)); - } - - /** - * Calculates the intersection between the list traverser and list argument. - * - * @return the traversal with an appended {@link IntersectStep}. - * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#intersect-step" target="_blank">Reference Documentation - Intersect Step</a> - * @since 3.7.3 - */ - public default GraphTraversal<S, Set<?>> intersect(final GValue<Object> values) { - this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.intersect, values); - return this.asAdmin().addStep(new IntersectStep<>(this.asAdmin(), values)); - } - - /** - * Merges the list traverser and list argument. Also known as union. - * - * @return the traversal with an appended {@link MergeStep}. - * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#merge-step" target="_blank">Reference Documentation - Merge Step</a> - * @since 3.7.3 - */ - public default <E2> GraphTraversal<S, E2> merge(final GValue<Object> values) { - this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.merge, values); - return this.asAdmin().addStep(new MergeStep<>(this.asAdmin(), values)); - } - - /** - * Calculates the cartesian product between the list traverser and list argument. - * - * @return the traversal with an appended {@link ProductStep}. - * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#product-step" target="_blank">Reference Documentation - Product Step</a> - * @since 3.7.3 - */ - public default GraphTraversal<S, List<List<?>>> product(final GValue<Object> values) { - this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.product, values); - return this.asAdmin().addStep(new ProductStep<>(this.asAdmin(), values)); - } - - /** - * When used as a modifier to {@link #addE(String)} this method specifies the traversal to use for selecting the - * incoming vertex of the newly added {@link Edge}. - * - * @param toVertex the vertex for selecting the incoming vertex - * @return the traversal with the modified {@link AddEdgeStep} - * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#addedge-step" target="_blank">Reference Documentation - From Step</a> - * @since 4.0.0 - */ - public default GraphTraversal<S, E> to(final GValue<Vertex> toVertex) { - final Step<?,?> prev = this.asAdmin().getEndStep(); - if (!(prev instanceof FromToModulating)) - throw new IllegalArgumentException(String.format( - "The to() step cannot follow %s", prev.getClass().getSimpleName())); - - this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.to, toVertex); - ((FromToModulating) prev).addTo(__.constant(toVertex).asAdmin()); - return this; - } - - /** - * When used as a modifier to {@link #addE(String)} this method specifies the traversal to use for selecting the - * outgoing vertex of the newly added {@link Edge}. - * - * @param fromVertex the vertex for selecting the outgoing vertex - * @return the traversal with the modified {@link AddEdgeStep} - * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#addedge-step" target="_blank">Reference Documentation - From Step</a> - * @since 4.0.0 - */ - public default GraphTraversal<S, E> from(final GValue<Vertex> fromVertex) { - final Step<?,?> prev = this.asAdmin().getEndStep(); - if (!(prev instanceof FromToModulating)) - throw new IllegalArgumentException(String.format( - "The from() step cannot follow %s", prev.getClass().getSimpleName())); - - this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.from, fromVertex); - ((FromToModulating) prev).addFrom(__.constant(fromVertex).asAdmin()); - return this; - } - - /** - * Perform the specified service call with the specified static parameters. - * - * @param service the name of the service call - * @param params static parameter map (no nested traversals) - * @return the traversal with an appended {@link CallStep}. - * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#call-step" target="_blank">Reference Documentation - Call Step</a> - * @since 4.0.0 - */ - default <E> GraphTraversal<S, E> call(final String service, final GValue<Map> params) { - this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.call, service, params); - final CallStep<S,E> call = new CallStep<>(this.asAdmin(), false, service, params); - return this.asAdmin().addStep(call); - } - /** - * Perform the specified service call with both static and dynamic parameters produced by the specified child - * traversal. These parameters will be merged at execution time per the provider implementation. Reference - * implementation merges dynamic into static (dynamic will overwrite static). - * - * @param service the name of the service call - * @param params static parameter map (no nested traversals) - * @param childTraversal a traversal that will produce a Map of parameters for the service call when invoked. - * @return the traversal with an appended {@link CallStep}. - * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#call-step" target="_blank">Reference Documentation - Call Step</a> - * @since 4.0.0 - */ - default <E> GraphTraversal<S, E> call(final String service, final GValue<Map> params, final Traversal<?, Map<?,?>> childTraversal) { - this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.call, service, params, childTraversal); - final CallStep<S,E> step = null == childTraversal ? new CallStep(this.asAdmin(), false, service, params) : - new CallStep(this.asAdmin(), false, service, params, childTraversal.asAdmin()); - return this.asAdmin().addStep(step); - } - - /** - * Filters vertices, edges and vertex properties based on their properties. - * - * @param label the label of the {@link Element} - * @param propertyKey the key of the property to filter on - * @param value the value to compare the accessor value to for equality - * @return the traversal with an appended {@link HasStep} - * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#has-step" target="_blank">Reference Documentation - Has Step</a> - * @since 4.0.0 - */ - public default GraphTraversal<S, E> has(final GValue<String> label, final String propertyKey, final Object value) { - this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.has, label.get(), propertyKey, value); - TraversalHelper.addHasContainer(this.asAdmin(), new HasContainer(T.label.getAccessor(), P.eq(label))); - return TraversalHelper.addHasContainer(this.asAdmin(), new HasContainer(propertyKey, value instanceof P ? (P) value : P.eq(value))); - } - @Override public default <E2> GraphTraversal.Admin<S, E2> addStep(final Step<?, E2> step) { return (GraphTraversal.Admin<S, E2>) Traversal.Admin.super.addStep((Step) step); @@ -824,6 +369,18 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> { return this.asAdmin().addStep(new ConstantStep<E, E2>(this.asAdmin(), e)); } + /** + * Map any object to a fixed <code>E</code> value. For internal use for parameterization features. + * + * @return the traversal with an appended {@link ConstantStep}. + * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#constant-step" target="_blank">Reference Documentation - Constant Step</a> + * @since 4.0.0 + */ + public default <E2> GraphTraversal<S, E2> constant(final GValue<E2> e) { + this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.constant, e); + return this.asAdmin().addStep(new ConstantStep<E, E2>(this.asAdmin(), e)); + } + /** * A {@code V} step is usually used to start a traversal but it may also be used mid-traversal. * @@ -868,6 +425,22 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> { return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Vertex.class, direction, edgeLabels)); } + /** + * Map the {@link Vertex} to its adjacent vertices given a direction and edge labels. The arguments for the + * labels must be either a {@code String} or a {@link GValue<String>}. For internal use for parameterization. + * + * @param direction the direction to traverse from the current vertex + * @param edgeLabels the edge labels to traverse + * @return the traversal with an appended {@link VertexStep}. + * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#vertex-steps" target="_blank">Reference Documentation - Vertex Step</a> + * @since 4.0.0 + */ + public default GraphTraversal<S, Vertex> to(final Direction direction, final GValue<String> edgeLabel, final GValue<String>... edgeLabels) { + this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.to, direction, edgeLabel, edgeLabels); + final GValue<String>[] labels = CollectionUtil.addFirst(edgeLabels, edgeLabel, GValue.class); + return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Vertex.class, direction, labels)); + } + /** * Map the {@link Vertex} to its outgoing adjacent vertices given the edge labels. * @@ -881,6 +454,21 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> { return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Vertex.class, Direction.OUT, edgeLabels)); } + /** + * Map the {@link Vertex} to its outgoing adjacent vertices given the edge labels. The arguments for the + * labels must be either a {@code String} or a {@link GValue<String>}. For internal use for parameterization. + * + * @param edgeLabels the edge labels to traverse + * @return the traversal with an appended {@link VertexStep}. + * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#vertex-steps" target="_blank">Reference Documentation - Vertex Step</a> + * @since 3.7.3 + */ + public default GraphTraversal<S, Vertex> out(final GValue<String> label, final GValue<String>... edgeLabels) { + final GValue<String>[] labels = CollectionUtil.addFirst(edgeLabels, label, GValue.class); + this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.out, label, edgeLabels); + return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Vertex.class, Direction.OUT, labels)); + } + /** * Map the {@link Vertex} to its incoming adjacent vertices given the edge labels. * @@ -894,6 +482,21 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> { return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Vertex.class, Direction.IN, edgeLabels)); } + /** + * Map the {@link Vertex} to its incoming adjacent vertices given the edge labels. The arguments for the + * labels must be either a {@code String} or a {@link GValue<String>}. For internal use for parameterization. + * + * @param edgeLabels the edge labels to traverse + * @return the traversal with an appended {@link VertexStep}. + * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#vertex-steps" target="_blank">Reference Documentation - Vertex Step</a> + * @since 4.0.0 + */ + public default GraphTraversal<S, Vertex> in(final GValue<String> label, final GValue<String>... edgeLabels) { + final GValue<String>[] labels = CollectionUtil.addFirst(edgeLabels, label, GValue.class); + this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.in, label, edgeLabels); + return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Vertex.class, Direction.IN, labels)); + } + /** * Map the {@link Vertex} to its adjacent vertices given the edge labels. * @@ -907,6 +510,21 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> { return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Vertex.class, Direction.BOTH, edgeLabels)); } + /** + * Map the {@link Vertex} to its adjacent vertices given the edge labels. The arguments for the labels must be + * either a {@code String} or a {@link GValue<String>}. For internal use for parameterization. + * + * @param edgeLabels the edge labels to traverse + * @return the traversal with an appended {@link VertexStep}. + * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#vertex-steps" target="_blank">Reference Documentation - Vertex Step</a> + * @since 4.0.0 + */ + public default GraphTraversal<S, Vertex> both(final GValue<String> label, final GValue<String>... edgeLabels) { + final GValue<String>[] labels = CollectionUtil.addFirst(edgeLabels, label, GValue.class); + this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.both, label, edgeLabels); + return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Vertex.class, Direction.BOTH, labels)); + } + /** * Map the {@link Vertex} to its incident edges given the direction and edge labels. * @@ -921,6 +539,23 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> { return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Edge.class, direction, edgeLabels)); } + + /** + * Map the {@link Vertex} to its incident edges given the direction and edge labels. The arguments for the + * labels must be either a {@code String} or a {@link GValue<String>}. For internal use for parameterization. + * + * @param direction the direction to traverse from the current vertex + * @param edgeLabels the edge labels to traverse + * @return the traversal with an appended {@link VertexStep}. + * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#vertex-steps" target="_blank">Reference Documentation - Vertex Step</a> + * @since 4.0.0 + */ + public default GraphTraversal<S, Edge> toE(final Direction direction, final GValue<String> edgeLabel, final GValue<String>... edgeLabels) { + this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.toE, direction, edgeLabel, edgeLabels); + final GValue<String>[] labels = CollectionUtil.addFirst(edgeLabels, edgeLabel, GValue.class); + return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Edge.class, direction, labels)); + } + /** * Map the {@link Vertex} to its outgoing incident edges given the edge labels. * @@ -934,6 +569,21 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> { return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Edge.class, Direction.OUT, edgeLabels)); } + /** + * Map the {@link Vertex} to its outgoing incident edges given the edge labels. The arguments for the labels + * must be either a {@code String} or a {@link GValue<String>}. For internal use for parameterization. + * + * @param edgeLabels the edge labels to traverse + * @return the traversal with an appended {@link VertexStep}. + * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#vertex-steps" target="_blank">Reference Documentation - Vertex Step</a> + * @since 4.0.0 + */ + public default GraphTraversal<S, Edge> outE(final GValue<String> label, final GValue<String>... edgeLabels) { + final GValue<String>[] labels = CollectionUtil.addFirst(edgeLabels, label, GValue.class); + this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.outE, label, edgeLabels); + return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Edge.class, Direction.OUT, labels)); + } + /** * Map the {@link Vertex} to its incoming incident edges given the edge labels. * @@ -947,6 +597,22 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> { return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Edge.class, Direction.IN, edgeLabels)); } + /** + * Map the {@link Vertex} to its incoming incident edges given the edge labels. The arguments for the labels + * must be either a {@code String} or a {@link GValue<String>}. For internal use for parameterization. + * + * @param edgeLabels the edge labels to traverse + * @return the traversal with an appended {@link VertexStep}. + * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#vertex-steps" target="_blank">Reference Documentation - Vertex Step</a> + * @since 4.0.0 + */ + public default GraphTraversal<S, Edge> inE(final GValue<String> label, final GValue<String>... edgeLabels) { + final GValue<String>[] labels = CollectionUtil.addFirst(edgeLabels, label, GValue.class); + this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.inE, label, edgeLabels); + return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Edge.class, Direction.IN, labels)); + } + + /** * Map the {@link Vertex} to its incident edges given the edge labels. * @@ -960,6 +626,21 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> { return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Edge.class, Direction.BOTH, edgeLabels)); } + /** + * Map the {@link Vertex} to its incident edges given the edge labels. The arguments for the labels must be + * either a {@code String} or a {@link GValue<String>}. For internal use for parameterization. + * + * @param edgeLabels the edge labels to traverse + * @return the traversal with an appended {@link VertexStep}. + * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#vertex-steps" target="_blank">Reference Documentation - Vertex Step</a> + * @since 4.0.0 + */ + public default GraphTraversal<S, Edge> bothE(final GValue<String> label, final GValue<String>... edgeLabels) { + final GValue<String>[] labels = CollectionUtil.addFirst(edgeLabels, label, GValue.class); + this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.bothE, label, edgeLabels); + return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Edge.class, Direction.BOTH, labels)); + } + /** * Map the {@link Edge} to its incident vertices given the direction. * @@ -1589,6 +1270,20 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> { return this.asAdmin().addStep(new AddVertexStep<>(this.asAdmin(), vertexLabelTraversal.asAdmin())); } + /** + * Adds a {@link Vertex}. + * + * @param vertexLabel the label of the {@link Vertex} to add + * @return the traversal with the {@link AddVertexStep} added + * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#addvertex-step" target="_blank">Reference Documentation - AddVertex Step</a> + * @since 4.0.0 + */ + public default GraphTraversal<S, Vertex> addV(final GValue<String> vertexLabel) { + if (null == vertexLabel || null == vertexLabel.get()) throw new IllegalArgumentException("vertexLabel cannot be null"); + this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.addV, vertexLabel); + return this.asAdmin().addStep(new AddVertexStep<>(this.asAdmin(), vertexLabel)); + } + /** * Adds a {@link Vertex} with a default vertex label. * @@ -1647,6 +1342,21 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> { return this.asAdmin().addStep(step); } + /** + * Performs a merge (i.e. upsert) style operation for an {@link Vertex} using a {@code Map} as an argument. + * The {@code Map} represents search criteria and will match each of the supplied key/value pairs where the keys + * may be {@code String} property values or a value of {@link T}. If a match is not made it will use that search + * criteria to create the new {@link Vertex}. + * + * @param searchCreate This {@code Map} can have a key of {@link T} or a {@code String}. + * @since 4.0.0 + */ + public default GraphTraversal<S, Vertex> mergeV(final GValue<Map<Object, Object>> searchCreate) { + this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.mergeV, searchCreate); + final MergeVertexStep<S> step = new MergeVertexStep(this.asAdmin(), false, null == searchCreate ? GValue.ofMap(null) : searchCreate); + return this.asAdmin().addStep(step); + } + /** * Spawns a {@link GraphTraversal} by doing a merge (i.e. upsert) style operation for an {@link Edge} using an * incoming {@code Map} as an argument. @@ -1688,6 +1398,20 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> { return this.asAdmin().addStep(step); } + /** + * Spawns a {@link GraphTraversal} by doing a merge (i.e. upsert) style operation for an {@link Edge} using a + * {@code Map} as an argument. + * + * @param searchCreate This {@code Map} can have a key of {@link T} {@link Direction} or a {@code String}. + * @since 4.0.0 + */ + public default GraphTraversal<S, Edge> mergeE(final GValue<Map<Object, Object>> searchCreate) { + // get a construction time exception if the Map is bad + this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.mergeE, searchCreate); + final MergeEdgeStep<S> step = new MergeEdgeStep(this.asAdmin(), false, null == searchCreate ? GValue.ofMap(null) : searchCreate); + return this.asAdmin().addStep(step); + } + /** * Adds an {@link Edge} with the specified edge label. * @@ -1714,21 +1438,35 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> { } /** - * Provide {@code to()}-modulation to respective steps. + * Adds an {@link Edge} with the specified edge label. * - * @param toStepLabel the step label to modulate to. - * @return the traversal with the modified {@link FromToModulating} step. - * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#to-step" target="_blank">Reference Documentation - To Step</a> + * @param edgeLabel the label of the newly added edge + * @return the traversal with the {@link AddEdgeStep} added + * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#addedge-step" target="_blank">Reference Documentation - AddEdge Step</a> + * @since 4.0.0 + */ + public default GraphTraversal<S, Edge> addE(final GValue<String> edgeLabel) { + this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.addE, edgeLabel); + return this.asAdmin().addStep(new AddEdgeStep<>(this.asAdmin(), edgeLabel)); + } + + /** + * When used as a modifier to {@link #addE(String)} this method specifies the traversal to use for selecting the + * outgoing vertex of the newly added {@link Edge}. + * + * @param fromVertex the traversal for selecting the outgoing vertex + * @return the traversal with the modified {@link AddEdgeStep} + * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#addedge-step" target="_blank">Reference Documentation - From Step</a> * @since 3.1.0-incubating */ - public default GraphTraversal<S, E> to(final String toStepLabel) { + public default GraphTraversal<S, E> from(final Traversal<?, Vertex> fromVertex) { final Step<?,?> prev = this.asAdmin().getEndStep(); if (!(prev instanceof FromToModulating)) throw new IllegalArgumentException(String.format( - "The to() step cannot follow %s", prev.getClass().getSimpleName())); + "The from() step cannot follow %s", prev.getClass().getSimpleName())); - this.asAdmin().getGremlinLang().addStep(Symbols.to, toStepLabel); - ((FromToModulating) prev).addTo(toStepLabel); + this.asAdmin().getGremlinLang().addStep(Symbols.from, fromVertex); + ((FromToModulating) prev).addFrom(fromVertex.asAdmin()); return this; } @@ -1753,21 +1491,21 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> { /** * When used as a modifier to {@link #addE(String)} this method specifies the traversal to use for selecting the - * incoming vertex of the newly added {@link Edge}. + * outgoing vertex of the newly added {@link Edge}. * - * @param toVertex the traversal for selecting the incoming vertex + * @param fromVertex the vertex for selecting the outgoing vertex * @return the traversal with the modified {@link AddEdgeStep} * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#addedge-step" target="_blank">Reference Documentation - From Step</a> - * @since 3.1.0-incubating + * @since 4.0.0 */ - public default GraphTraversal<S, E> to(final Traversal<?, Vertex> toVertex) { + public default GraphTraversal<S, E> from(final GValue<Vertex> fromVertex) { final Step<?,?> prev = this.asAdmin().getEndStep(); if (!(prev instanceof FromToModulating)) throw new IllegalArgumentException(String.format( - "The to() step cannot follow %s", prev.getClass().getSimpleName())); + "The from() step cannot follow %s", prev.getClass().getSimpleName())); - this.asAdmin().getGremlinLang().addStep(Symbols.to, toVertex); - ((FromToModulating) prev).addTo(toVertex.asAdmin()); + this.asAdmin().getGremlinLang().addStep(GraphTraversal.Symbols.from, fromVertex); + ((FromToModulating) prev).addFrom(__.constant(fromVertex).asAdmin()); return this; } @@ -1775,19 +1513,38 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> { * When used as a modifier to {@link #addE(String)} this method specifies the traversal to use for selecting the * outgoing vertex of the newly added {@link Edge}. * - * @param fromVertex the traversal for selecting the outgoing vertex + * @param fromVertex the vertex for selecting the outgoing vertex * @return the traversal with the modified {@link AddEdgeStep} * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#addedge-step" target="_blank">Reference Documentation - From Step</a> - * @since 3.1.0-incubating + * @since 3.3.0 */ - public default GraphTraversal<S, E> from(final Traversal<?, Vertex> fromVertex) { + public default GraphTraversal<S, E> from(final Vertex fromVertex) { final Step<?,?> prev = this.asAdmin().getEndStep(); if (!(prev instanceof FromToModulating)) throw new IllegalArgumentException(String.format( "The from() step cannot follow %s", prev.getClass().getSimpleName())); this.asAdmin().getGremlinLang().addStep(Symbols.from, fromVertex); - ((FromToModulating) prev).addFrom(fromVertex.asAdmin()); + ((FromToModulating) prev).addFrom(__.constant(fromVertex).asAdmin()); + return this; + } + + /** + * Provide {@code to()}-modulation to respective steps. + * + * @param toStepLabel the step label to modulate to. + * @return the traversal with the modified {@link FromToModulating} step. + * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#to-step" target="_blank">Reference Documentation - To Step</a> + * @since 3.1.0-incubating + */ + public default GraphTraversal<S, E> to(final String toStepLabel) { + final Step<?,?> prev = this.asAdmin().getEndStep(); + if (!(prev instanceof FromToModulating)) + throw new IllegalArgumentException(String.format( + "The to() step cannot follow %s", prev.getClass().getSimpleName())); + + this.asAdmin().getBytecode().addStep(Symbols.to, toStepLabel); + ((FromToModulating) prev).addTo(toStepLabel); return this; } @@ -1798,36 +1555,56 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> { * @param toVertex the vertex for selecting the incoming vertex * @return the traversal with the modified {@link AddEdgeStep} * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#addedge-step" target="_blank">Reference Documentation - From Step</a> - * @since 3.3.0 + * @since 4.0.0 */ - public default GraphTraversal<S, E> to(final Vertex toVertex) { + public default GraphTraversal<S, E> to(final GValue<Vertex> toVertex) { final Step<?,?> prev = this.asAdmin().getEndStep(); if (!(prev instanceof FromToModulating)) throw new IllegalArgumentException(String.format( "The to() step cannot follow %s", prev.getClass().getSimpleName())); - this.asAdmin().getGremlinLang().addStep(Symbols.to, toVertex); + this.asAdmin().getGremlinLang().addStep(GraphTraversal.Symbols.to, toVertex); ((FromToModulating) prev).addTo(__.constant(toVertex).asAdmin()); return this; } /** * When used as a modifier to {@link #addE(String)} this method specifies the traversal to use for selecting the - * outgoing vertex of the newly added {@link Edge}. + * incoming vertex of the newly added {@link Edge}. * - * @param fromVertex the vertex for selecting the outgoing vertex + * @param toVertex the traversal for selecting the incoming vertex + * @return the traversal with the modified {@link AddEdgeStep} + * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#addedge-step" target="_blank">Reference Documentation - From Step</a> + * @since 3.1.0-incubating + */ + public default GraphTraversal<S, E> to(final Traversal<?, Vertex> toVertex) { + final Step<?,?> prev = this.asAdmin().getEndStep(); + if (!(prev instanceof FromToModulating)) + throw new IllegalArgumentException(String.format( + "The to() step cannot follow %s", prev.getClass().getSimpleName())); + + this.asAdmin().getGremlinLang().addStep(Symbols.to, toVertex); + ((FromToModulating) prev).addTo(toVertex.asAdmin()); + return this; + } + + /** + * When used as a modifier to {@link #addE(String)} this method specifies the traversal to use for selecting the + * incoming vertex of the newly added {@link Edge}. + * + * @param toVertex the vertex for selecting the incoming vertex * @return the traversal with the modified {@link AddEdgeStep} * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#addedge-step" target="_blank">Reference Documentation - From Step</a> * @since 3.3.0 */ - public default GraphTraversal<S, E> from(final Vertex fromVertex) { + public default GraphTraversal<S, E> to(final Vertex toVertex) { final Step<?,?> prev = this.asAdmin().getEndStep(); if (!(prev instanceof FromToModulating)) throw new IllegalArgumentException(String.format( - "The from() step cannot follow %s", prev.getClass().getSimpleName())); + "The to() step cannot follow %s", prev.getClass().getSimpleName())); - this.asAdmin().getGremlinLang().addStep(Symbols.from, fromVertex); - ((FromToModulating) prev).addFrom(__.constant(fromVertex).asAdmin()); + this.asAdmin().getGremlinLang().addStep(Symbols.to, toVertex); + ((FromToModulating) prev).addTo(__.constant(toVertex).asAdmin()); return this; } @@ -2778,6 +2555,22 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> { return this.asAdmin().addStep(new TraversalFilterStep(this.asAdmin(), __.values(propertyKey))); } + /** + * Filters vertices, edges and vertex properties based on their properties. + * + * @param label the label of the {@link Element} + * @param propertyKey the key of the property to filter on + * @param value the value to compare the accessor value to for equality + * @return the traversal with an appended {@link HasStep} + * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#has-step" target="_blank">Reference Documentation - Has Step</a> + * @since 4.0.0 + */ + public default GraphTraversal<S, E> has(final GValue<String> label, final String propertyKey, final Object value) { + this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.has, label.get(), propertyKey, value); + TraversalHelper.addHasContainer(this.asAdmin(), new HasContainer(T.label.getAccessor(), P.eq(label))); + return TraversalHelper.addHasContainer(this.asAdmin(), new HasContainer(propertyKey, value instanceof P ? (P) value : P.eq(value))); + } + /** * Filters vertices, edges and vertex properties based on the non-existence of properties. * @@ -2805,11 +2598,7 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> { // groovy evaluation seems to do strange things with varargs given hasLabel(null, null). odd someone would // do this but the failure is ugly if not handled. - final int otherLabelsLength = null == otherLabels ? 0 : otherLabels.length; - final String[] labels = new String[otherLabelsLength + 1]; - labels[0] = label; - if (otherLabelsLength > 0) - System.arraycopy(otherLabels, 0, labels, 1, otherLabelsLength); + final String[] labels = CollectionUtil.addFirst(otherLabels, label, String.class); return TraversalHelper.addHasContainer(this.asAdmin(), new HasContainer(T.label.getAccessor(), labels.length == 1 ? P.eq(labels[0]) : P.within(labels))); } @@ -2832,6 +2621,24 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> { } } + /** + * Filters vertices, edges and vertex properties based on their label. + * + * @param label the label of the {@link Element} + * @param otherLabels additional labels of the {@link Element} + * @return the traversal with an appended {@link HasStep} + * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#has-step" target="_blank">Reference Documentation - Has Step</a> + * @since 4.0.0 + */ + public default GraphTraversal<S, E> hasLabel(final GValue<String> label, final GValue<String>... otherLabels) { + this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.hasLabel, label, otherLabels); + + // groovy evaluation seems to do strange things with varargs given hasLabel(null, null). odd someone would + // do this but the failure is ugly if not handled. + final Object[] labels = CollectionUtil.addFirst(otherLabels, label, GValue.class); + return TraversalHelper.addHasContainer(this.asAdmin(), new HasContainer(T.label.getAccessor(), labels.length == 1 ? P.eq(labels[0]) : P.within(labels))); + } + /** * Filters vertices, edges and vertex properties based on their identifier. * @@ -3049,6 +2856,19 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> { return this.asAdmin().addStep(new CoinStep<>(this.asAdmin(), probability)); } + /** + * Filter the <code>E</code> object given a biased coin toss. For internal use for parameterization features. + * + * @param probability the probability that the object will pass through the filter + * @return the traversal with an appended {@link CoinStep}. + * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#coin-step" target="_blank">Reference Documentation - Coin Step</a> + * @since 4.0.0 + */ + public default GraphTraversal<S, E> coin(final GValue<Double> probability) { + this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.coin, probability); + return this.asAdmin().addStep(new CoinStep<>(this.asAdmin(), probability)); + } + /** * Filter the objects in the traversal by the number of them to pass through the stream. Those before the value * of {@code low} do not pass through and those that exceed the value of {@code high} will end the iteration. @@ -4444,6 +4264,73 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> { return this; } + /** + * This is a step modulator to a {@link TraversalOptionParent} like {@code choose()} or {@code mergeV()} where the + * provided argument associated to the {@code token} is applied according to the semantics of the step. Please see + * the documentation of such steps to understand the usage context. + * + * @param token the token that would trigger this option which may be a {@link Pick}, {@link Merge}, + * a {@link Traversal}, {@link Predicate}, or object depending on the step being modulated. + * @param traversalOption the option as a traversal + * @return the traversal with the modulated step + * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#choose-step" target="_blank">Reference Documentation - Choose Step</a> + * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#mergev-step" target="_blank">Reference Documentation - MergeV Step</a> + * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#mergee-step" target="_blank">Reference Documentation - MergeE Step</a> + * @since 3.0.0-incubating + */ + public default <M, E2> GraphTraversal<S, E> option(final GValue<M> token, final Traversal<?, E2> traversalOption) { + this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.option, token, traversalOption); + + // handle null similar to how option() with Map handles it, otherwise we get a NPE if this one gets used + final Traversal.Admin<E,E2> t = null == traversalOption ? + new ConstantTraversal<>(null) : (Traversal.Admin<E, E2>) traversalOption.asAdmin(); + ((TraversalOptionParent<M, E, E2>) this.asAdmin().getEndStep()).addChildOption(token.get(), t); + return this; + } + + /** + * This is a step modulator to a {@link TraversalOptionParent} like {@code choose()} or {@code mergeV()} where the + * provided argument associated to the {@code token} is applied according to the semantics of the step. Please see + * the documentation of such steps to understand the usage context. + * + * @param m Provides a {@code Map} as the option which is the same as doing {@code constant(m)}. + * @return the traversal with the modulated step + * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#mergev-step" target="_blank">Reference Documentation - MergeV Step</a> + * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#mergee-step" target="_blank">Reference Documentation - MergeE Step</a> + * @since 3.7.3 + */ + public default <M, E2> GraphTraversal<S, E> option(final M token, final GValue<Map<Object, Object>> m) { + this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.option, token, m); + ((TraversalOptionParent<M, E, E2>) this.asAdmin().getEndStep()).addChildOption(token, (Traversal.Admin<E, E2>) new ConstantTraversal<>(m).asAdmin()); + return this; + } + + /** + * This is a step modulator to a {@link TraversalOptionParent} like {@code choose()} or {@code mergeV()} where the + * provided argument associated to the {@code token} is applied according to the semantics of the step. Please see + * the documentation of such steps to understand the usage context. + * + * @param m Provides a {@code Map} as the option which is the same as doing {@code constant(m)}. + * @return the traversal with the modulated step + * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#mergev-step" target="_blank">Reference Documentation - MergeV Step</a> + * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#mergee-step" target="_blank">Reference Documentation - MergeE Step</a> + * @since 3.7.3 + */ + public default <M, E2> GraphTraversal<S, E> option(final Merge merge, final GValue<Map<Object, Object>> m, final VertexProperty.Cardinality cardinality) { + this.asAdmin().getBytecode().addStep(GraphTraversal.Symbols.option, merge, m, cardinality); + + final Map<Object, Object> map = m.get(); + + // do explicit cardinality for every single pair in the map + for (Object k : map.keySet()) { + final Object o = map.get(k); + if (!(o instanceof CardinalityValueTraversal)) + map.put(k, new CardinalityValueTraversal(cardinality, o)); + } + ((TraversalOptionParent<M, E, E2>) this.asAdmin().getEndStep()).addChildOption((M) merge, (Traversal.Admin<E, E2>) new ConstantTraversal<>(m).asAdmin()); + return this; + } + //// ///////////////////// IO STEPS ///////////////////// diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversalSource.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversalSource.java index 61081d91e5..f6292c47de 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversalSource.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversalSource.java @@ -69,7 +69,6 @@ public class GraphTraversalSource implements TraversalSource { protected final Graph graph; protected TraversalStrategies strategies; protected GremlinLang gremlinLang = new GremlinLang(); - protected Admin admin; //////////////// @@ -102,12 +101,6 @@ public class GraphTraversalSource implements TraversalSource { this.strategies.addStrategies(new RemoteStrategy(connection)); } - public GraphTraversalSource.Admin asAdmin() { - if (null == this.admin) - this.admin = new Admin(); - return this.admin; - } - @Override public Optional<Class<?>> getAnonymousTraversalClass() { return Optional.of(__.class); @@ -414,6 +407,22 @@ public class GraphTraversalSource implements TraversalSource { return traversal.addStep(step); } + /** + * Spawns a {@link GraphTraversal} by doing a merge (i.e. upsert) style operation for an {@link Vertex} using a + * {@code Map} as an argument. The {@code Map} represents search criteria and will match each of the supplied + * key/value pairs where the keys may be {@code String} property values or a value of {@link T}. If a match is not + * made it will use that search criteria to create the new {@link Vertex}. + * + * @param searchCreate This {@code Map} can have a key of {@link T} or a {@code String}. + * @since 4.0.0 + */ + public GraphTraversal<Vertex, Vertex> mergeV(final GValue<Map<Object, Object>> searchCreate) { + final GraphTraversalSource clone = GraphTraversalSource.this.clone(); + clone.bytecode.addStep(GraphTraversal.Symbols.mergeV, searchCreate); + final GraphTraversal.Admin<Vertex, Vertex> traversal = new DefaultGraphTraversal<>(clone); + return traversal.addStep(new MergeVertexStep(traversal, true, searchCreate)); + } + /** * Spawns a {@link GraphTraversal} by doing a merge (i.e. upsert) style operation for an {@link Edge} using a * {@code Map} as an argument. @@ -446,6 +455,20 @@ public class GraphTraversalSource implements TraversalSource { return traversal.addStep(step); } + /** + * Spawns a {@link GraphTraversal} by doing a merge (i.e. upsert) style operation for an {@link Edge} using a + * {@code Map} as an argument. + * + * @param searchCreate This {@code Map} can have a key of {@link T} {@link Direction} or a {@code String}. + * @since 4.0.0 + */ + public GraphTraversal<Edge, Edge> mergeE(final GValue<Map<?, Object>> searchCreate) { + final GraphTraversalSource clone = GraphTraversalSource.this.clone(); + clone.bytecode.addStep(GraphTraversal.Symbols.mergeE, searchCreate); + final GraphTraversal.Admin<Edge, Edge> traversal = new DefaultGraphTraversal<>(clone); + return traversal.addStep(new MergeEdgeStep(traversal, true, searchCreate)); + } + /** * Spawns a {@link GraphTraversal} starting it with arbitrary values. */ @@ -626,72 +649,4 @@ public class GraphTraversalSource implements TraversalSource { return StringFactory.traversalSourceString(this); } - - /** - * This class masks spawn steps that are more reserved for advanced usage. - */ - public class Admin { - - /** - * Spawns a {@link GraphTraversal} starting with values produced by the specified service call with the specified - * static parameters. - * - * @param service the name of the service call - * @param params static parameter map (no nested traversals) - * @since 4.0.0 - */ - public <S> GraphTraversal<S, S> call(final String service, final GValue<Map> params) { - final GraphTraversalSource clone = GraphTraversalSource.this.clone(); - clone.bytecode.addStep(GraphTraversal.Symbols.call, service, params); - final GraphTraversal.Admin<S, S> traversal = new DefaultGraphTraversal<>(clone); - return traversal.addStep(new CallStep<>(traversal, true, service, params)); - } - - /** - * Spawns a {@link GraphTraversal} starting with values produced by the specified service call with the specified - * static parameters. - * - * @param service the name of the service call - * @param params static parameter map (no nested traversals) - * @since 4.0.0 - */ - public <S> GraphTraversal<S, S> call(final String service, final GValue<Map> params, final Traversal<S, Map> childTraversal) { - final GraphTraversalSource clone = GraphTraversalSource.this.clone(); - clone.bytecode.addStep(GraphTraversal.Symbols.call, service, params); - final GraphTraversal.Admin<S, S> traversal = new DefaultGraphTraversal<>(clone); - return traversal.addStep(new CallStep<>(traversal, true, service, params, childTraversal.asAdmin())); - } - - /** - * Spawns a {@link GraphTraversal} by doing a merge (i.e. upsert) style operation for an {@link Vertex} using a - * {@code Map} as an argument. The {@code Map} represents search criteria and will match each of the supplied - * key/value pairs where the keys may be {@code String} property values or a value of {@link T}. If a match is not - * made it will use that search criteria to create the new {@link Vertex}. - * - * @param searchCreate This {@code Map} can have a key of {@link T} or a {@code String}. - * @since 4.0.0 - */ - public GraphTraversal<Vertex, Vertex> mergeV(final GValue<Map<Object, Object>> searchCreate) { - final GraphTraversalSource clone = GraphTraversalSource.this.clone(); - clone.bytecode.addStep(GraphTraversal.Symbols.mergeV, searchCreate); - final GraphTraversal.Admin<Vertex, Vertex> traversal = new DefaultGraphTraversal<>(clone); - return traversal.addStep(new MergeVertexStep(traversal, true, searchCreate)); - } - - /** - * Spawns a {@link GraphTraversal} by doing a merge (i.e. upsert) style operation for an {@link Edge} using a - * {@code Map} as an argument. - * - * @param searchCreate This {@code Map} can have a key of {@link T} {@link Direction} or a {@code String}. - * @since 4.0.0 - */ - public GraphTraversal<Edge, Edge> mergeE(final GValue<Map<?, Object>> searchCreate) { - final GraphTraversalSource clone = GraphTraversalSource.this.clone(); - clone.bytecode.addStep(GraphTraversal.Symbols.mergeE, searchCreate); - final GraphTraversal.Admin<Edge, Edge> traversal = new DefaultGraphTraversal<>(clone); - return traversal.addStep(new MergeEdgeStep(traversal, true, searchCreate)); - } - - } - } diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java index 57776db82e..a72f31289e 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java @@ -25,6 +25,8 @@ import org.apache.tinkerpop.gremlin.process.traversal.Pop; import org.apache.tinkerpop.gremlin.process.traversal.Scope; import org.apache.tinkerpop.gremlin.process.traversal.Traversal; import org.apache.tinkerpop.gremlin.process.traversal.Traverser; +import org.apache.tinkerpop.gremlin.process.traversal.step.GValue; +import org.apache.tinkerpop.gremlin.process.traversal.step.map.FormatStep; import org.apache.tinkerpop.gremlin.process.traversal.step.util.Tree; import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.TraverserSet; import org.apache.tinkerpop.gremlin.structure.Column; @@ -110,6 +112,13 @@ public class __ { return __.<A>start().constant(a); } + /** + * @see GraphTraversal#constant(GValue) + */ + public static <A> GraphTraversal<A, A> constant(final GValue<A> a) { + return __.<A>start().constant(a); + } + /** * @see GraphTraversal#label() */ @@ -145,6 +154,13 @@ public class __ { return __.<Vertex>start().to(direction, edgeLabels); } + /** + * @see GraphTraversal#to(Direction, GValue, GValue...) + */ + public static GraphTraversal<Vertex, Vertex> to(final Direction direction, final GValue<String> edgeLabel, final GValue<String>... edgeLabels) { + return __.<Vertex>start().to(direction, edgeLabel, edgeLabels); + } + /** * @see GraphTraversal#out(String...) */ @@ -152,6 +168,13 @@ public class __ { return __.<Vertex>start().out(edgeLabels); } + /** + * @see GraphTraversal#out(GValue, GValue...) + */ + public static GraphTraversal<Vertex, Vertex> out(final GValue<String> edgeLabel, final GValue<String>... edgeLabels) { + return __.<Vertex>start().out(edgeLabel, edgeLabels); + } + /** * @see GraphTraversal#in(String...) */ @@ -159,6 +182,13 @@ public class __ { return __.<Vertex>start().in(edgeLabels); } + /** + * @see GraphTraversal#in(String...) + */ + public static GraphTraversal<Vertex, Vertex> in(final GValue<String> edgeLabel, final GValue<String>... edgeLabels) { + return __.<Vertex>start().in(edgeLabel, edgeLabels); + } + /** * @see GraphTraversal#both(String...) */ @@ -166,6 +196,13 @@ public class __ { return __.<Vertex>start().both(edgeLabels); } + /** + * @see GraphTraversal#both(GValue, GValue...) + */ + public static GraphTraversal<Vertex, Vertex> both(final GValue<String> edgeLabel, final GValue<String>... edgeLabels) { + return __.<Vertex>start().both(edgeLabel, edgeLabels); + } + /** * @see GraphTraversal#toE(Direction, String...) */ @@ -173,6 +210,13 @@ public class __ { return __.<Vertex>start().toE(direction, edgeLabels); } + /** + * @see GraphTraversal#toE(Direction, GValue, GValue...) + */ + public static GraphTraversal<Vertex, Edge> toE(final Direction direction, final GValue<String> edgeLabel, final GValue<String>... edgeLabels) { + return __.<Vertex>start().toE(direction, edgeLabel, edgeLabels); + } + /** * @see GraphTraversal#outE(String...) */ @@ -180,6 +224,13 @@ public class __ { return __.<Vertex>start().outE(edgeLabels); } + /** + * @see GraphTraversal#outE(GValue, GValue...) + */ + public static GraphTraversal<Vertex, Edge> outE(final GValue<String> edgeLabel, final GValue<String>... edgeLabels) { + return __.<Vertex>start().outE(edgeLabel, edgeLabels); + } + /** * @see GraphTraversal#inE(String...) */ @@ -187,6 +238,13 @@ public class __ { return __.<Vertex>start().inE(edgeLabels); } + /** + * @see GraphTraversal#inE(GValue, GValue...) + */ + public static GraphTraversal<Vertex, Edge> inE(final GValue<String> edgeLabel, final GValue<String>... edgeLabels) { + return __.<Vertex>start().inE(edgeLabel, edgeLabels); + } + /** * @see GraphTraversal#bothE(String...) */ @@ -194,6 +252,13 @@ public class __ { return __.<Vertex>start().bothE(edgeLabels); } + /** + * @see GraphTraversal#bothE(GValue, GValue...) + */ + public static GraphTraversal<Vertex, Edge> bothE(final GValue<String> edgeLabel, final GValue<String>... edgeLabels) { + return __.<Vertex>start().bothE(edgeLabel, edgeLabels); + } + /** * @see GraphTraversal#toV(Direction) */ @@ -512,6 +577,13 @@ public class __ { return __.<A>start().addV(vertexLabel); } + /** + * @see GraphTraversal#addV(GValue) + */ + public static <A> GraphTraversal<A, Vertex> addV(final GValue<String> vertexLabel) { + return __.<A>start().addV(vertexLabel); + } + /** * @see GraphTraversal#addV(org.apache.tinkerpop.gremlin.process.traversal.Traversal) */ @@ -540,6 +612,13 @@ public class __ { return __.<A>start().mergeV(searchCreate); } + /** + * @see GraphTraversal#mergeV(GValue) + */ + public static <A> GraphTraversal<A, Vertex> mergeV(final GValue<Map<Object, Object>> searchCreate) { + return __.<A>start().mergeV(searchCreate); + } + /** * @see GraphTraversal#mergeV(Traversal) */ @@ -554,6 +633,13 @@ public class __ { return __.<A>start().addE(edgeLabel); } + /** + * @see GraphTraversal#addE(GValue) + */ + public static <A> GraphTraversal<A, Edge> addE(final GValue<String> edgeLabel) { + return __.<A>start().addE(edgeLabel); + } + /** * @see GraphTraversal#addE(Traversal) */ @@ -575,6 +661,13 @@ public class __ { return __.<A>start().mergeE(searchCreate); } + /** + * @see GraphTraversal#mergeE(GValue) + */ + public static <A> GraphTraversal<A, Edge> mergeE(final GValue<Map<Object, Object>> searchCreate) { + return __.<A>start().mergeE(searchCreate); + } + /** * @see GraphTraversal#mergeE(Traversal) */ @@ -934,6 +1027,13 @@ public class __ { return __.<A>start().has(label, propertyKey, value); } + /** + * @see GraphTraversal#has(GValue, String, Object) + */ + public static <A> GraphTraversal<A, A> has(final GValue<String> label, final String propertyKey, final Object value) { + return __.<A>start().has(label, propertyKey, value); + } + /** * @see GraphTraversal#has(String, String, P) */ @@ -976,6 +1076,13 @@ public class __ { return __.<A>start().hasLabel(label, otherLabels); } + /** + * @see GraphTraversal#hasLabel(GValue, GValue...) + */ + public static <A> GraphTraversal<A, A> hasLabel(final GValue<String> label, GValue<String>... otherLabels) { + return __.<A>start().hasLabel(label, otherLabels); + } + /** * @see GraphTraversal#hasLabel(P) */ @@ -1074,6 +1181,13 @@ public class __ { return __.<A>start().coin(probability); } + /** + * @see GraphTraversal#coin(GValue) + */ + public static <A> GraphTraversal<A, A> coin(final GValue<Double> probability) { + return __.<A>start().coin(probability); + } + /** * @see GraphTraversal#range(long, long) */ diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/GValue.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/GValue.java index cb18dec8b9..0b1e88b15c 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/GValue.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/GValue.java @@ -33,6 +33,7 @@ import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; +import java.util.stream.Stream; /** * A {@code GValue} is a variable or literal value that is used in a {@link Traversal}. It is composed of a key-value @@ -56,6 +57,47 @@ public class GValue<V> implements Cloneable, Serializable { this.value = value; } + /** + * The elements in object array argument are examined to see if they are {@link GValue} objects. If they are, they + * are preserved as is. If they are not then they are wrapped in a {@link GValue} object. + */ + public static <T> GValue<T>[] convertToGValues(final Object[] args) { + return Stream.of(args).map(id -> { + if (id instanceof GValue) + return (GValue<?>) id; + else + return of(id); + }).toArray(GValue[]::new); + } + + /** + * Converts {@link GValue} objects arguments to their values to prevent them from leaking to the Graph API. + * Providers extending from this step should use this method to get actual values to prevent any {@link GValue} + * objects from leaking to the Graph API. + */ + public static Object[] resolveToValues(final List<GValue<?>> gvalues) { + // convert gvalues to array + final Object[] newIds = new Object[gvalues.size()]; + int i = 0; + for (final GValue<?> gvalue : gvalues) { + newIds[i++] = gvalue.get(); + } + return newIds; + } + + /** + * Converts {@link GValue} objects argument array to their values to prevent them from leaking to the Graph API. + * Providers extending from this step should use this method to get actual values to prevent any {@link GValue} + * objects from leaking to the Graph API. + */ + public static Object[] resolveToValues(final GValue<?>[] gvalues) { + final Object[] newIds = new Object[gvalues.length]; + for (int i = 0; i < gvalues.length; i++) { + newIds[i] = gvalues[i].get(); + } + return newIds; + } + /** * Determines if the value held by this object was defined as a variable or a literal value. Literal values simply * have no name. diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GraphStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GraphStep.java index 0a4635240a..f65ecb7e81 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GraphStep.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GraphStep.java @@ -70,13 +70,13 @@ public class GraphStep<S, E extends Element> extends AbstractStep<S, E> implemen this.returnClass = returnClass; // if ids is a single collection like g.V(['a','b','c']), then unroll it into an array of ids - this.ids = convertToGValues(tryUnrollSingleCollectionArgument(ids)); + this.ids = GValue.convertToGValues(tryUnrollSingleCollectionArgument(ids)); this.isStart = isStart; this.iteratorSupplier = () -> (Iterator<E>) (Vertex.class.isAssignableFrom(this.returnClass) ? - this.getTraversal().getGraph().get().vertices(resolveToValues(this.ids)) : - this.getTraversal().getGraph().get().edges(resolveToValues(this.ids))); + this.getTraversal().getGraph().get().vertices(GValue.resolveToValues(this.ids)) : + this.getTraversal().getGraph().get().edges(GValue.resolveToValues(this.ids))); } /** @@ -155,7 +155,7 @@ public class GraphStep<S, E extends Element> extends AbstractStep<S, E> implemen */ public Object[] getIdsAsValues() { if (legacyLogicForPassingNoIds) return null; - return resolveToValues(this.ids); + return GValue.resolveToValues(this.ids); } public void addIds(final Object... newIds) { @@ -169,7 +169,7 @@ public class GraphStep<S, E extends Element> extends AbstractStep<S, E> implemen this.legacyLogicForPassingNoIds = newIds.length == 1 && ((newIds[0] instanceof List && ((List) newIds[0]).isEmpty()) || (newIds[0] instanceof GValue && ((GValue) newIds[0]).getType().isCollection() && ((List) ((GValue) newIds[0]).get()).isEmpty())); - final GValue[] gvalues = convertToGValues(tryUnrollSingleCollectionArgument(newIds)); + final GValue[] gvalues = GValue.convertToGValues(tryUnrollSingleCollectionArgument(newIds)); this.ids = ArrayUtils.addAll(this.ids, gvalues); } diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/VertexStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/VertexStep.java index e27fbb3802..896934668d 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/VertexStep.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/VertexStep.java @@ -54,24 +54,14 @@ public class VertexStep<E extends Element> extends FlatMapStep<Vertex, E> implem private final Class<E> returnClass; public VertexStep(final Traversal.Admin traversal, final Class<E> returnClass, final Direction direction, final String... edgeLabels) { - this(traversal, returnClass, direction, (Object[]) edgeLabels); + this(traversal, returnClass, direction, GValue.convertToGValues(edgeLabels)); } - public VertexStep(final Traversal.Admin traversal, final Class<E> returnClass, final Direction direction, final Object... edgeLabels) { + public VertexStep(final Traversal.Admin traversal, final Class<E> returnClass, final Direction direction, final GValue<String>... edgeLabels) { super(traversal); this.direction = direction; this.returnClass = returnClass; - - // check each edgeLabel to ensure it is a string or a GValue with a GType.STRING in it. if it is just a string - // then convert edgeLabels to a GValue<String> or otherwise throw an exception - this.edgeLabelsGValue = Arrays.stream(edgeLabels).map(edgeLabel -> { - if (edgeLabel instanceof String) - return GValue.ofString((String) edgeLabel); - else if (edgeLabel instanceof GValue && ((GValue<String>) edgeLabel).get().getClass().equals(String.class)) - return (GValue<String>) edgeLabel; - else - throw new IllegalArgumentException("All edge labels must be strings"); - }).toArray(GValue[]::new); + this.edgeLabelsGValue = edgeLabels; // convert the GValue<String> to a String[] for the edgeLabels field to cache the values this.edgeLabels = Arrays.stream(this.edgeLabelsGValue).map(GValue::get).toArray(String[]::new); diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/InjectStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/InjectStep.java index 0dae0ed01d..59e3909b62 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/InjectStep.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/InjectStep.java @@ -32,21 +32,21 @@ public final class InjectStep<S> extends StartStep<S> { @SafeVarargs public InjectStep(final Traversal.Admin traversal, final S... injections) { super(traversal); - this.injections = convertToGValues(injections); - this.start = new ArrayIterator<>(resolveToValues(this.injections)); + this.injections = GValue.convertToGValues(injections); + this.start = new ArrayIterator<>(GValue.resolveToValues(this.injections)); } @Override public InjectStep<S> clone() { final InjectStep<S> clone = (InjectStep<S>) super.clone(); - clone.start = new ArrayIterator<>(resolveToValues(clone.injections)); + clone.start = new ArrayIterator<>(GValue.resolveToValues(clone.injections)); return clone; } @Override public void reset() { super.reset(); - this.start = new ArrayIterator<>(resolveToValues(this.injections)); + this.start = new ArrayIterator<>(GValue.resolveToValues(this.injections)); } /** diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/AbstractStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/AbstractStep.java index dd6f5fb849..f0af790c73 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/AbstractStep.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/AbstractStep.java @@ -21,7 +21,6 @@ package org.apache.tinkerpop.gremlin.process.traversal.step.util; import org.apache.tinkerpop.gremlin.process.traversal.Step; import org.apache.tinkerpop.gremlin.process.traversal.Traversal; import org.apache.tinkerpop.gremlin.process.traversal.Traverser; -import org.apache.tinkerpop.gremlin.process.traversal.step.GValue; import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.EmptyTraverser; import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.TraverserSet; import org.apache.tinkerpop.gremlin.process.traversal.util.EmptyTraversal; @@ -32,11 +31,9 @@ import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.LinkedHashSet; -import java.util.List; import java.util.NoSuchElementException; import java.util.Objects; import java.util.Set; -import java.util.stream.Stream; /** * @author Marko A. Rodriguez (http://markorodriguez.com) @@ -232,45 +229,4 @@ public abstract class AbstractStep<S, E> implements Step<S, E> { } return traverser; } - - /** - * The elements in object array argument are examined to see if they are {@link GValue} objects. If they are, they - * are preserved as is. If they are not then they are wrapped in a {@link GValue} object. - */ - protected static <T> GValue<T>[] convertToGValues(final Object[] args) { - return Stream.of(args).map(id -> { - if (id instanceof GValue) - return (GValue<?>) id; - else - return GValue.of(id); - }).toArray(GValue[]::new); - } - - /** - * Converts {@link GValue} objects arguments to their values to prevent them from leaking to the Graph API. - * Providers extending from this step should use this method to get actual values to prevent any {@link GValue} - * objects from leaking to the Graph API. - */ - protected Object[] resolveToValues(final List<GValue<?>> gvalues) { - // convert gvalues to array - final Object[] newIds = new Object[gvalues.size()]; - int i = 0; - for (final GValue<?> gvalue : gvalues) { - newIds[i++] = gvalue.get(); - } - return newIds; - } - - /** - * Converts {@link GValue} objects argument array to their values to prevent them from leaking to the Graph API. - * Providers extending from this step should use this method to get actual values to prevent any {@link GValue} - * objects from leaking to the Graph API. - */ - protected Object[] resolveToValues(final GValue<?>[] gvalues) { - final Object[] newIds = new Object[gvalues.length]; - for (int i = 0; i < gvalues.length; i++) { - newIds[i] = gvalues[i].get(); - } - return newIds; - } } diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/InlineFilterStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/InlineFilterStrategy.java index f7ff96009d..ad0ccf395f 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/InlineFilterStrategy.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/InlineFilterStrategy.java @@ -158,7 +158,7 @@ public final class InlineFilterStrategy extends AbstractTraversalStrategy<Traver } } if (!edgeLabels.isEmpty()) { - final VertexStep<Edge> newVertexStep = new VertexStep<>(traversal, Edge.class, previousStep.getDirection(), edgeLabels.toArray(new Object[edgeLabels.size()])); + final VertexStep<Edge> newVertexStep = new VertexStep<>(traversal, Edge.class, previousStep.getDirection(), GValue.convertToGValues(edgeLabels.toArray())); TraversalHelper.replaceStep(previousStep, newVertexStep, traversal); TraversalHelper.copyLabels(previousStep, newVertexStep, false); if (step.getHasContainers().isEmpty()) { diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/CollectionUtil.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/CollectionUtil.java index 1242d16af7..61d9d7573d 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/CollectionUtil.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/CollectionUtil.java @@ -19,6 +19,9 @@ package org.apache.tinkerpop.gremlin.util; +import org.apache.commons.lang3.ArrayUtils; + +import java.lang.reflect.Array; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -74,4 +77,22 @@ public final class CollectionUtil { return result; } + + /** + * Adds the element argument to the start of the supplied array argument, but if the array is null then return the + * element as a new array with just that item in it. + */ + public static <T> T[] addFirst(final T[] array, final T element, final Class<T> clazz) { + if (null == array && null == element) { + final T[] singleElementArray = (T[]) Array.newInstance(clazz, 1); + singleElementArray[0] = null; + return singleElementArray; + } else if (null == array) { + final T[] singleElementArray = (T[]) Array.newInstance(clazz, 1); + singleElementArray[0] = element; + return singleElementArray; + } else { + return ArrayUtils.addFirst(array, element); + } + } }
