You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by sp...@apache.org on 2020/11/05 13:19:27 UTC

[tinkerpop] branch TINKERPOP-2461 created (now bb784e3)

This is an automated email from the ASF dual-hosted git repository.

spmallette pushed a change to branch TINKERPOP-2461
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git.


      at bb784e3  TINKERPOP-2443 Provided more succinct syntax for withStrategies()

This branch includes the following new commits:

     new bb784e3  TINKERPOP-2443 Provided more succinct syntax for withStrategies()

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[tinkerpop] 01/01: TINKERPOP-2443 Provided more succinct syntax for withStrategies()

Posted by sp...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

spmallette pushed a commit to branch TINKERPOP-2461
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git

commit bb784e3561af855ce3dbc2cccf7235862a4d535d
Author: Stephen Mallette <st...@amazon.com>
AuthorDate: Thu Nov 5 08:11:25 2020 -0500

    TINKERPOP-2443 Provided more succinct syntax for withStrategies()
    
    Allowed scripts a more succinct and Groovy style for strategy construction when using withStrategies().
---
 .../strategy/decoration/EventStrategy.java         | 12 +--
 .../strategy/decoration/SackStrategy.java          |  4 +
 .../gremlin/groovy/loaders/GremlinLoader.groovy    |  4 +-
 .../gremlin/groovy/loaders/ObjectLoader.groovy     |  2 +-
 .../gremlin/groovy/loaders/StepLoader.groovy       | 22 +++++-
 .../gremlin/groovy/loaders/StrategyLoader.groovy   | 85 ++++++++++++++++++++++
 .../gremlin/groovy/loaders/SugarLoader.groovy      |  2 +-
 .../jsr223/GremlinGroovyScriptEngineTest.java      | 36 +++++++++
 8 files changed, 153 insertions(+), 14 deletions(-)

diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/EventStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/EventStrategy.java
index 2061e7f..c442e52 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/EventStrategy.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/EventStrategy.java
@@ -26,19 +26,10 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.util.event.EventCallb
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.event.MutationListener;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.AbstractTraversalStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
-import org.apache.tinkerpop.gremlin.structure.Edge;
-import org.apache.tinkerpop.gremlin.structure.Element;
 import org.apache.tinkerpop.gremlin.structure.Graph;
-import org.apache.tinkerpop.gremlin.structure.Property;
 import org.apache.tinkerpop.gremlin.structure.Transaction;
-import org.apache.tinkerpop.gremlin.structure.Vertex;
-import org.apache.tinkerpop.gremlin.structure.VertexProperty;
 import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedFactory;
-import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedProperty;
-import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedVertexProperty;
 import org.apache.tinkerpop.gremlin.structure.util.reference.ReferenceFactory;
-import org.apache.tinkerpop.gremlin.structure.util.reference.ReferenceProperty;
-import org.apache.tinkerpop.gremlin.structure.util.reference.ReferenceVertexProperty;
 
 import java.io.Serializable;
 import java.util.ArrayDeque;
@@ -51,7 +42,8 @@ import java.util.List;
  * A strategy that raises events when {@link Mutating} steps are encountered and successfully executed.
  * <p/>
  * Note that this implementation requires a {@link Graph} on the {@link Traversal} instance.  If that is not present
- * an {@code IllegalStateException} will be thrown.
+ * an {@code IllegalStateException} will be thrown. Finally, this strategy is meant for use on the JVM only and has
+ * no analogous implementation in other Gremlin Language Variants.
  *
  * @author Stephen Mallette (http://stephen.genoprime.com)
  */
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/SackStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/SackStrategy.java
index 0598d17..7124b61 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/SackStrategy.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/SackStrategy.java
@@ -20,6 +20,7 @@
 package org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration;
 
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.TraversalSource;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.EmptyStep;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.AbstractTraversalStrategy;
@@ -29,6 +30,9 @@ import java.util.function.Supplier;
 import java.util.function.UnaryOperator;
 
 /**
+ * The {@code SackStrategy} is used internal to the {@code withSack()} steps of {@link TraversalSource} and is not
+ * typically constructed directly.
+ *
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  */
 public final class SackStrategy extends AbstractTraversalStrategy<TraversalStrategy.DecorationStrategy> implements TraversalStrategy.DecorationStrategy {
diff --git a/gremlin-groovy/src/main/groovy/org/apache/tinkerpop/gremlin/groovy/loaders/GremlinLoader.groovy b/gremlin-groovy/src/main/groovy/org/apache/tinkerpop/gremlin/groovy/loaders/GremlinLoader.groovy
index 758768e..b2e50d9 100644
--- a/gremlin-groovy/src/main/groovy/org/apache/tinkerpop/gremlin/groovy/loaders/GremlinLoader.groovy
+++ b/gremlin-groovy/src/main/groovy/org/apache/tinkerpop/gremlin/groovy/loaders/GremlinLoader.groovy
@@ -17,14 +17,16 @@
  * under the License.
  */
 package org.apache.tinkerpop.gremlin.groovy.loaders
+
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  * @author Stephen Mallette (http://stephen.genoprime.com)
  */
 class GremlinLoader {
 
-    public static void load() {
+    static void load() {
         ObjectLoader.load()
         StepLoader.load()
+        StrategyLoader.load()
     }
 }
diff --git a/gremlin-groovy/src/main/groovy/org/apache/tinkerpop/gremlin/groovy/loaders/ObjectLoader.groovy b/gremlin-groovy/src/main/groovy/org/apache/tinkerpop/gremlin/groovy/loaders/ObjectLoader.groovy
index b7f0ec2..9285d05 100644
--- a/gremlin-groovy/src/main/groovy/org/apache/tinkerpop/gremlin/groovy/loaders/ObjectLoader.groovy
+++ b/gremlin-groovy/src/main/groovy/org/apache/tinkerpop/gremlin/groovy/loaders/ObjectLoader.groovy
@@ -23,7 +23,7 @@ package org.apache.tinkerpop.gremlin.groovy.loaders
 
 class ObjectLoader {
 
-    public static void load() {
+    static void load() {
 
         Map.metaClass.getAt = { final IntRange range ->
             final int size = delegate.size();
diff --git a/gremlin-groovy/src/main/groovy/org/apache/tinkerpop/gremlin/groovy/loaders/StepLoader.groovy b/gremlin-groovy/src/main/groovy/org/apache/tinkerpop/gremlin/groovy/loaders/StepLoader.groovy
index b1cd97f..d04a2c4 100644
--- a/gremlin-groovy/src/main/groovy/org/apache/tinkerpop/gremlin/groovy/loaders/StepLoader.groovy
+++ b/gremlin-groovy/src/main/groovy/org/apache/tinkerpop/gremlin/groovy/loaders/StepLoader.groovy
@@ -19,6 +19,7 @@
 package org.apache.tinkerpop.gremlin.groovy.loaders
 
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalSource
+import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal
 
 import java.util.function.BinaryOperator
@@ -31,7 +32,7 @@ import java.util.function.UnaryOperator
  */
 class StepLoader {
 
-    public static void load() {
+    static void load() {
 
         GraphTraversal.metaClass.by = { final Closure closure ->
             return ((GraphTraversal) delegate).by(1 == closure.getMaximumNumberOfParameters() ? closure as Function : closure as Comparator);
@@ -63,5 +64,24 @@ class StepLoader {
             final Closure closure, final Closure splitOperator, final Closure mergeOperator ->
                 return ((TraversalSource) delegate).withSack(closure as Supplier, splitOperator as UnaryOperator, mergeOperator as BinaryOperator);
         }
+
+        /**
+         * Allows for a mix of arguments which may be either {@code TraversalStrategy} object or a
+         * {@code Class<TraversalStrategy>}. If the latter, then the class must be able to be instantiated by the
+         * common convention of {@code instance()}.
+         */
+        TraversalSource.metaClass.withStrategies = { Object... traversalStrategyClassOrInstances ->
+            def instances = traversalStrategyClassOrInstances.collect {
+                if (it instanceof TraversalStrategy) {
+                    return it
+                } else if (it instanceof Class<?>) {
+                    def inst = it.metaClass.respondsTo(it, "instance") ? it."instance"() : null
+                    if (null == inst) throw new IllegalArgumentException("${it.name} missing a static 'instance()' method")
+                    return inst
+                }
+            }
+
+            return ((TraversalSource) delegate).withStrategies(*instances)
+        }
     }
 }
diff --git a/gremlin-groovy/src/main/groovy/org/apache/tinkerpop/gremlin/groovy/loaders/StrategyLoader.groovy b/gremlin-groovy/src/main/groovy/org/apache/tinkerpop/gremlin/groovy/loaders/StrategyLoader.groovy
new file mode 100644
index 0000000..5396737
--- /dev/null
+++ b/gremlin-groovy/src/main/groovy/org/apache/tinkerpop/gremlin/groovy/loaders/StrategyLoader.groovy
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tinkerpop.gremlin.groovy.loaders
+
+import org.apache.commons.configuration.MapConfiguration
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.ElementIdStrategy
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.HaltedTraverserStrategy
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.OptionsStrategy
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.PartitionStrategy
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SubgraphStrategy
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.finalization.MatchAlgorithmStrategy
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.EdgeLabelVerificationStrategy
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ReservedKeysVerificationStrategy
+
+/**
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+class StrategyLoader {
+
+    static void load() {
+        // EventStrategy/SackStrategy are pretty much the oddballs here along with a few pure "internal" strategies
+        // which don't have create(Configuration). We don't support either EventStrategy or SackStrategy in non-JVM
+        // variants because of their style of usage (JVM specific class structures and lambdas respectively). this
+        // perhaps points to a shortcoming somewhere in the APIs, though i'm not sure EventStrategy would ever work
+        // properly off the JVM and SackStrategy doesn't need to since it's technically like OptionsStrategy which is
+        // constructed via bytecode translation where the lambdas are readily supported.
+
+        // decoration
+        // # ConnectiveStrategy is singleton
+        ElementIdStrategy.metaClass.constructor << { Map conf -> ElementIdStrategy.create(new MapConfiguration(conf)) }
+        //EventStrategy.metaClass.constructor << { Map conf -> EventStrategy.create(new MapConfiguration(conf)) }
+        HaltedTraverserStrategy.metaClass.constructor << { Map conf -> HaltedTraverserStrategy.create(new MapConfiguration(conf)) }
+        OptionsStrategy.metaClass.constructor << { Map conf -> OptionsStrategy.create(new MapConfiguration(conf)) }
+        PartitionStrategy.metaClass.constructor << { Map conf -> PartitionStrategy.create(new MapConfiguration(conf)) }
+        // # RequirementsStrategy is internal
+        // SackStrategy.metaClass.constructor << { Map conf -> SackStrategy.create(new MapConfiguration(conf)) }
+        // # SideEffectStrategy is internal
+        SubgraphStrategy.metaClass.constructor << { Map conf -> SubgraphStrategy.create(new MapConfiguration(conf)) }
+
+        // finalization
+        MatchAlgorithmStrategy.metaClass.constructor << { Map conf -> MatchAlgorithmStrategy.create(new MapConfiguration(conf)) }
+        // # ProfileStrategy is singleton/internal
+        // # ReferenceElementStrategy is singleton/internal
+
+        // optimization
+        // # AdjacentToIncidentStrategy is singleton/internal
+        // # CountStrategy is singleton/internal
+        // # EarlyLimitStrategy is singleton/internal
+        // # FilterRankingStrategy is singleton/internal
+        // # IdentityRemovalStrategy is singleton/internal
+        // # IncidentToAdjacentStrategy is singleton/internal
+        // # InlineFilterStrategy is singleton/internal
+        // # LazyBarrierStrategy is singleton/internal
+        // # MatchPredicateStrategy is singleton/internal
+        // # OrderLimitStrategy is singleton/internal
+        // # PathProcessorStrategy is singleton/internal
+        // # PathRetractionStrategy is singleton/internal
+        // # RepeatUnrollStrategy is singleton/internal
+
+        // verification
+        // # ComputerVerificationStrategy is singleton/internal
+        EdgeLabelVerificationStrategy.metaClass.constructor << { Map conf -> EdgeLabelVerificationStrategy.create(new MapConfiguration(conf)) }
+        // # LambdaRestrictionStrategy is singleton
+        // # ReadOnlyStrategy is singleton
+        ReservedKeysVerificationStrategy.metaClass.constructor << { Map conf -> ReservedKeysVerificationStrategy.create(new MapConfiguration(conf)) }
+        // # StandardVerificationStrategy is singleton/internal
+    }
+
+}
diff --git a/gremlin-groovy/src/main/groovy/org/apache/tinkerpop/gremlin/groovy/loaders/SugarLoader.groovy b/gremlin-groovy/src/main/groovy/org/apache/tinkerpop/gremlin/groovy/loaders/SugarLoader.groovy
index bfc877e..5dd202d 100644
--- a/gremlin-groovy/src/main/groovy/org/apache/tinkerpop/gremlin/groovy/loaders/SugarLoader.groovy
+++ b/gremlin-groovy/src/main/groovy/org/apache/tinkerpop/gremlin/groovy/loaders/SugarLoader.groovy
@@ -33,7 +33,7 @@ class SugarLoader {
 
     private static final String NAME = "name";
 
-    public static void load() {
+    static void load() {
 
         GremlinLoader.load();
 
diff --git a/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngineTest.java b/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngineTest.java
index d40dc19..efb6812 100644
--- a/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngineTest.java
+++ b/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngineTest.java
@@ -23,6 +23,13 @@ import groovy.lang.MissingMethodException;
 import groovy.lang.MissingPropertyException;
 import org.apache.commons.lang3.exception.ExceptionUtils;
 import org.apache.commons.lang3.concurrent.BasicThreadFactory;
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasStep;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SubgraphStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ReadOnlyStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.VerificationException;
+import org.apache.tinkerpop.gremlin.structure.util.empty.EmptyGraph;
 import org.apache.tinkerpop.gremlin.util.function.Lambda;
 import org.javatuples.Pair;
 import org.junit.Test;
@@ -38,12 +45,14 @@ import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.stream.IntStream;
 
+import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.hasLabel;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.core.Is.is;
 import static org.hamcrest.core.IsInstanceOf.instanceOf;
@@ -413,4 +422,31 @@ public class GremlinGroovyScriptEngineTest {
         final Lambda l = (Lambda) engine.eval(" org.apache.tinkerpop.gremlin.util.function.Lambda.function(\"{ it.get() }\")");
         assertEquals("{ it.get() }", l.getLambdaScript());
     }
+
+    @Test
+    public void shouldAllowGroovySyntaxForStrategies() throws Exception {
+        final GremlinGroovyScriptEngine engine = new GremlinGroovyScriptEngine();
+        final GraphTraversalSource g = EmptyGraph.instance().traversal();
+
+        final Bindings b = new SimpleBindings();
+        b.put("g", g);
+
+        Traversal t = (Traversal) engine.eval("g.withStrategies(ReadOnlyStrategy).V()", b);
+        Optional<ReadOnlyStrategy> ro = t.asAdmin().getStrategies().getStrategy(ReadOnlyStrategy.class);
+        assertThat(ro.isPresent(), is(true));
+        assertEquals(ReadOnlyStrategy.instance(), ro.get());
+
+        t = (Traversal) engine.eval("g.withStrategies(new SubgraphStrategy(vertices: __.hasLabel(\"person\"))).V()", b);
+        Optional<SubgraphStrategy> ss = t.asAdmin().getStrategies().getStrategy(SubgraphStrategy.class);
+        assertThat(ss.isPresent(), is(true));
+        assertEquals(HasStep.class, ss.get().getVertexCriterion().asAdmin().getStartStep().getClass());
+
+        t = (Traversal) engine.eval("g.withStrategies(ReadOnlyStrategy, new SubgraphStrategy(vertices: __.hasLabel(\"person\"))).V()", b);
+        ro = t.asAdmin().getStrategies().getStrategy(ReadOnlyStrategy.class);
+        assertThat(ro.isPresent(), is(true));
+        assertEquals(ReadOnlyStrategy.instance(), ro.get());
+        ss = t.asAdmin().getStrategies().getStrategy(SubgraphStrategy.class);
+        assertThat(ss.isPresent(), is(true));
+        assertEquals(HasStep.class, ss.get().getVertexCriterion().asAdmin().getStartStep().getClass());
+    }
 }
\ No newline at end of file