You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by ok...@apache.org on 2015/06/22 19:29:23 UTC

incubator-tinkerpop git commit: P.hashCode() is now based on P.originalValue() as it causes problems with MatchStep if not where where()-steps have dynamic P's based on bindings. Added MatchAlgorithmStrategy which allows the user to specify the MatchAlgo

Repository: incubator-tinkerpop
Updated Branches:
  refs/heads/master 859e90c4b -> c20b46ebd


P.hashCode() is now based on P.originalValue() as it causes problems with MatchStep if not where where()-steps have dynamic P's based on bindings. Added MatchAlgorithmStrategy which allows the user to specify the MatchAlgorithm they want to use. Default is CountMatchAlgorithm for now.


Project: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/commit/c20b46eb
Tree: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/tree/c20b46eb
Diff: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/diff/c20b46eb

Branch: refs/heads/master
Commit: c20b46ebdbfd14b8320ee66cd54c5f0ee2e5be84
Parents: 859e90c
Author: Marko A. Rodriguez <ok...@gmail.com>
Authored: Mon Jun 22 11:29:17 2015 -0600
Committer: Marko A. Rodriguez <ok...@gmail.com>
Committed: Mon Jun 22 11:29:17 2015 -0600

----------------------------------------------------------------------
 .../tinkerpop/gremlin/process/traversal/P.java  |  8 +--
 .../process/traversal/TraversalStrategies.java  |  2 +
 .../process/traversal/step/map/MatchStep.java   | 59 +++++++--------
 .../finalization/MatchAlgorithmStrategy.java    | 75 ++++++++++++++++++++
 .../step/filter/GroovyWhereTest.groovy          |  4 +-
 .../traversal/step/filter/WhereTest.java        |  8 +--
 6 files changed, 114 insertions(+), 42 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/c20b46eb/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/P.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/P.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/P.java
index 8fc78a0..2340048 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/P.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/P.java
@@ -78,7 +78,7 @@ public class P<V> implements Predicate<V>, Serializable, Cloneable {
 
     @Override
     public int hashCode() {
-        return this.biPredicate.hashCode() ^ (null == this.value ? "null".hashCode() : this.value.hashCode());
+        return this.biPredicate.hashCode() ^ (null == this.originalValue ? "null".hashCode() : this.originalValue.hashCode());
     }
 
     @Override
@@ -86,17 +86,17 @@ public class P<V> implements Predicate<V>, Serializable, Cloneable {
         return other instanceof P &&
                 ((P) other).getClass().equals(this.getClass()) &&
                 ((P) other).getBiPredicate().equals(this.biPredicate) &&
-                ((((P) other).getValue() == null && this.value == null) || ((P) other).getValue().equals(this.value));
+                ((((P) other).getOriginalValue() == null && this.originalValue == null) || ((P) other).getOriginalValue().equals(this.originalValue));
     }
 
     @Override
     public String toString() {
-        return null == this.value ? this.biPredicate.toString() : this.biPredicate.toString() + "(" + this.value + ")";
+        return null == this.originalValue ? this.biPredicate.toString() : this.biPredicate.toString() + "(" + this.originalValue + ")";
     }
 
     @Override
     public P<V> negate() {
-        return new P<>(this.biPredicate.negate(), this.value);
+        return new P<>(this.biPredicate.negate(), this.originalValue);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/c20b46eb/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalStrategies.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalStrategies.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalStrategies.java
index fb35ead..2fb7232 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalStrategies.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalStrategies.java
@@ -18,8 +18,10 @@
  */
 package org.apache.tinkerpop.gremlin.process.traversal;
 
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.MatchStep;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.ConjunctionStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.finalization.EngineDependentStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.finalization.MatchAlgorithmStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.finalization.ProfileStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.finalization.ScopingStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.AdjacentToIncidentStrategy;

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/c20b46eb/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MatchStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MatchStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MatchStep.java
index 1ac0663..97d509d 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MatchStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MatchStep.java
@@ -45,6 +45,7 @@ import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
 import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
 
 import java.io.Serializable;
+import java.lang.reflect.InvocationTargetException;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
@@ -56,7 +57,6 @@ import java.util.NoSuchElementException;
 import java.util.Optional;
 import java.util.Set;
 import java.util.function.Function;
-import java.util.function.Supplier;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
@@ -65,8 +65,6 @@ import java.util.stream.Stream;
  */
 public final class MatchStep<S, E> extends ComputerAwareStep<S, Map<String, E>> implements TraversalParent, Scoping {
 
-    private static final Supplier<MatchAlgorithm> MATCH_ALGORITHM = CountMatchAlgorithm::new;
-
     private List<Traversal.Admin<Object, Object>> matchTraversals = new ArrayList<>();
     private boolean first = true;
     private Set<String> matchStartLabels = new HashSet<>();
@@ -74,7 +72,8 @@ public final class MatchStep<S, E> extends ComputerAwareStep<S, Map<String, E>>
     private Set<String> scopeKeys = null;
     private final ConjunctionStep.Conjunction conjunction;
     private final String startKey;
-    private MatchAlgorithm matchAlgorithm = MATCH_ALGORITHM.get();
+    private MatchAlgorithm matchAlgorithm;
+    private Class<? extends MatchAlgorithm> matchAlgorithmClass = CountMatchAlgorithm.class; // default is CountMatchAlgorithm (use MatchAlgorithmStrategy to change)
 
     public MatchStep(final Traversal.Admin traversal, final String startKey, final ConjunctionStep.Conjunction conjunction, final Traversal... matchTraversals) {
         super(traversal);
@@ -206,9 +205,11 @@ public final class MatchStep<S, E> extends ComputerAwareStep<S, Map<String, E>>
         this.first = true;
     }
 
+    public void setMatchAlgorithm(final Class<? extends MatchAlgorithm> matchAlgorithmClass) {
+        this.matchAlgorithmClass = matchAlgorithmClass;
+    }
+
     public MatchAlgorithm getMatchAlgorithm() {
-        if (!this.matchAlgorithm.initialized())  // this is important in clone()ing situations where you need the match algorithm to reinitialize
-            this.matchAlgorithm.initialize(this.matchTraversals);
         return this.matchAlgorithm;
     }
 
@@ -219,7 +220,7 @@ public final class MatchStep<S, E> extends ComputerAwareStep<S, Map<String, E>>
         for (final Traversal.Admin<Object, Object> traversal : this.matchTraversals) {
             clone.matchTraversals.add(clone.integrateChild(traversal.clone()));
         }
-        clone.matchAlgorithm = MATCH_ALGORITHM.get();
+        clone.initializeMatchAlgorithm();
         return clone;
     }
 
@@ -246,12 +247,22 @@ public final class MatchStep<S, E> extends ComputerAwareStep<S, Map<String, E>>
         return bindings;
     }
 
+    private void initializeMatchAlgorithm() {
+        try {
+            this.matchAlgorithm = this.matchAlgorithmClass.getConstructor().newInstance();
+        } catch (final NoSuchMethodException | IllegalAccessException | InvocationTargetException | InstantiationException e) {
+            throw new IllegalStateException(e.getMessage(), e);
+        }
+        this.matchAlgorithm.initialize(this.matchTraversals);
+    }
+
     @Override
     protected Iterator<Traverser<Map<String, E>>> standardAlgorithm() throws NoSuchElementException {
         while (true) {
             Traverser.Admin traverser = null;
             if (this.first) {
                 this.first = false;
+                this.initializeMatchAlgorithm();
             } else {
                 for (final Traversal.Admin<?, ?> matchTraversal : this.matchTraversals) {
                     if (matchTraversal.hasNext()) {
@@ -285,7 +296,6 @@ public final class MatchStep<S, E> extends ComputerAwareStep<S, Map<String, E>>
             traverser.setStepId(this.getNextStep().getId());
             return IteratorUtils.of(traverser.split(this.getBindings(traverser), this));
         }
-
         if (this.conjunction == ConjunctionStep.Conjunction.AND) {
             final Traversal.Admin<Object, Object> matchTraversal = this.getMatchAlgorithm().apply(traverser); // determine which sub-pattern the traverser should try next
             traverser.setStepId(matchTraversal.getStartStep().getId()); // go down the traversal match sub-pattern
@@ -443,8 +453,6 @@ public final class MatchStep<S, E> extends ComputerAwareStep<S, Map<String, E>>
             return traversal.getStartStep() instanceof WhereStep || traversal.getStartStep().getNextStep() instanceof WhereStep;
         }
 
-        public boolean initialized();
-
         public void initialize(final List<Traversal.Admin<Object, Object>> traversals);
 
         public default void recordStart(final Traverser.Admin<Object> traverser, final Traversal.Admin<Object, Object> traversal) {
@@ -459,19 +467,14 @@ public final class MatchStep<S, E> extends ComputerAwareStep<S, Map<String, E>>
     public static class GreedyMatchAlgorithm implements MatchAlgorithm {
 
         private List<Traversal.Admin<Object, Object>> traversals;
-        private List<String> traversalLabels = new ArrayList<>();
-        private List<Set<String>> requiredLabels = new ArrayList<>();
-        private boolean initialized = false;
-
-        @Override
-        public boolean initialized() {
-            return this.initialized;
-        }
+        private List<String> traversalLabels;
+        private List<Set<String>> requiredLabels;
 
         @Override
         public void initialize(final List<Traversal.Admin<Object, Object>> traversals) {
-            this.initialized = true;
             this.traversals = traversals;
+            this.traversalLabels = new ArrayList<>();
+            this.requiredLabels = new ArrayList<>();
             for (final Traversal.Admin<Object, Object> traversal : this.traversals) {
                 this.traversalLabels.add(traversal.getStartStep().getId());
                 this.requiredLabels.add(MatchAlgorithm.getRequiredLabels(traversal));
@@ -493,20 +496,13 @@ public final class MatchStep<S, E> extends ComputerAwareStep<S, Map<String, E>>
     public static class CountMatchAlgorithm implements MatchAlgorithm {
 
         protected List<Traversal.Admin<Object, Object>> traversals;
-        protected List<Integer[]> counts = new ArrayList<>();
-        protected List<String> traversalLabels = new ArrayList<>();
-        protected List<Set<String>> requiredLabels = new ArrayList<>();
-        protected Map<Traversal.Admin<Object, Object>, Boolean> whereTraversals = new HashMap<>();
-        private boolean initialized = false;
-
-        @Override
-        public boolean initialized() {
-            return this.initialized;
-        }
+        protected List<Integer[]> counts;
+        protected List<String> traversalLabels;
+        protected List<Set<String>> requiredLabels;
+        protected Map<Traversal.Admin<Object, Object>, Boolean> whereTraversals;
 
         @Override
         public void initialize(final List<Traversal.Admin<Object, Object>> traversals) {
-            this.initialized = true;
             this.traversals = traversals;
             this.whereTraversals = new HashMap<>();
             this.counts = new ArrayList<>();
@@ -535,8 +531,7 @@ public final class MatchStep<S, E> extends ComputerAwareStep<S, Map<String, E>>
         public void recordEnd(final Traverser.Admin<Object> traverser, final Traversal.Admin<Object, Object> traversal) {
             final int currentIndex = this.traversals.indexOf(traversal);
             this.counts.stream().filter(array -> currentIndex == array[0]).findAny().get()[1]++;
-            final boolean isWhereTraversal = MatchAlgorithm.isWhereTraversal(traversal); // this.whereTraversals.get(traversal); // TODO: cloning issue again!
-            Collections.sort(this.counts, (a, b) -> isWhereTraversal ? 1 : a[1].compareTo(b[1]));
+            Collections.sort(this.counts, (a, b) -> this.whereTraversals.get(traversal) ? 1 : a[1].compareTo(b[1]));
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/c20b46eb/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/finalization/MatchAlgorithmStrategy.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/finalization/MatchAlgorithmStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/finalization/MatchAlgorithmStrategy.java
new file mode 100644
index 0000000..32e0ea0
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/finalization/MatchAlgorithmStrategy.java
@@ -0,0 +1,75 @@
+/*
+ *
+ *  * 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.process.traversal.strategy.finalization;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.MatchStep;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.AbstractTraversalStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
+import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public final class MatchAlgorithmStrategy extends AbstractTraversalStrategy<TraversalStrategy.FinalizationStrategy> implements TraversalStrategy.FinalizationStrategy {
+
+    private final Class<? extends MatchStep.MatchAlgorithm> matchAlgorithmClass;
+
+    private MatchAlgorithmStrategy(final Class<? extends MatchStep.MatchAlgorithm> matchAlgorithmClass) {
+        this.matchAlgorithmClass = matchAlgorithmClass;
+    }
+
+    @Override
+    public void apply(final Traversal.Admin<?, ?> traversal) {
+        if (!TraversalHelper.hasStepOfClass(MatchStep.class, traversal))
+            return;
+        TraversalHelper.getStepsOfClass(MatchStep.class, traversal).forEach(matchStep -> matchStep.setMatchAlgorithm(this.matchAlgorithmClass));
+    }
+
+    public static Builder build() {
+        return new Builder();
+    }
+
+    @Override
+    public String toString() {
+        return StringFactory.traversalStrategyString(this);
+    }
+
+    public final static class Builder {
+
+        private Class<? extends MatchStep.MatchAlgorithm> matchAlgorithmClass = MatchStep.CountMatchAlgorithm.class;
+
+        private Builder() {
+        }
+
+        public Builder algorithm(final Class<? extends MatchStep.MatchAlgorithm> matchAlgorithmClass) {
+            this.matchAlgorithmClass = matchAlgorithmClass;
+            return this;
+        }
+
+
+        public MatchAlgorithmStrategy create() {
+            return new MatchAlgorithmStrategy(this.matchAlgorithmClass);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/c20b46eb/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/filter/GroovyWhereTest.groovy
----------------------------------------------------------------------
diff --git a/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/filter/GroovyWhereTest.groovy b/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/filter/GroovyWhereTest.groovy
index a52fe4f..0a1b13f 100644
--- a/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/filter/GroovyWhereTest.groovy
+++ b/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/filter/GroovyWhereTest.groovy
@@ -81,8 +81,8 @@ public abstract class GroovyWhereTest {
         }
 
         @Override
-        public Traversal<Vertex, Vertex> get_g_VX1X_out_aggregateXxX_out_whereXwithoutXaXX(final Object v1Id) {
-            TraversalScriptHelper.compute("g.V(v1Id).out.aggregate('x').out.where(without('x'))", g, "v1Id", v1Id)
+        public Traversal<Vertex, Vertex> get_g_VX1X_out_aggregateXxX_out_whereXnotXwithinXaXXX(final Object v1Id) {
+            TraversalScriptHelper.compute("g.V(v1Id).out.aggregate('x').out.where(not(within('x')))", g, "v1Id", v1Id)
         }
 
         @Override

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/c20b46eb/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WhereTest.java
----------------------------------------------------------------------
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WhereTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WhereTest.java
index 77e753c..de7939a 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WhereTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WhereTest.java
@@ -68,7 +68,7 @@ public abstract class WhereTest extends AbstractGremlinProcessTest {
 
     public abstract Traversal<Vertex, String> get_g_VX1X_asXaX_outXcreatedX_inXcreatedX_whereXneqXaXX_name(final Object v1Id);
 
-    public abstract Traversal<Vertex, Vertex> get_g_VX1X_out_aggregateXxX_out_whereXwithoutXaXX(final Object v1Id);
+    public abstract Traversal<Vertex, Vertex> get_g_VX1X_out_aggregateXxX_out_whereXnotXwithinXaXXX(final Object v1Id);
 
     public abstract Traversal<Vertex, Vertex> get_g_withSideEffectXa_graph_verticesX2XX_VX1X_out_whereXneqXaXX(final Object v1Id, final Object v2Id);
 
@@ -221,7 +221,7 @@ public abstract class WhereTest extends AbstractGremlinProcessTest {
     @Test
     @LoadGraphWith(MODERN)
     public void g_VX1X_out_aggregateXxX_out_whereXwithout_xX() {
-        final Traversal<Vertex, Vertex> traversal = get_g_VX1X_out_aggregateXxX_out_whereXwithoutXaXX(convertToVertexId("marko"));
+        final Traversal<Vertex, Vertex> traversal = get_g_VX1X_out_aggregateXxX_out_whereXnotXwithinXaXXX(convertToVertexId("marko"));
         printTraversalForm(traversal);
         assertEquals("ripple", traversal.next().<String>value("name"));
         assertFalse(traversal.hasNext());
@@ -369,8 +369,8 @@ public abstract class WhereTest extends AbstractGremlinProcessTest {
         }
 
         @Override
-        public Traversal<Vertex, Vertex> get_g_VX1X_out_aggregateXxX_out_whereXwithoutXaXX(final Object v1Id) {
-            return g.V(v1Id).out().aggregate("x").out().where(without("x"));
+        public Traversal<Vertex, Vertex> get_g_VX1X_out_aggregateXxX_out_whereXnotXwithinXaXXX(final Object v1Id) {
+            return g.V(v1Id).out().aggregate("x").out().where(not(within("x")));
         }
 
         @Override