Repository: tinkerpop
Updated Branches:
  refs/heads/TINKERPOP-1490 c97d6830a -> d6e4af455 (forced update)


TraversalStrategy.GlobalCache.getStrategies() is now the point where static{} 
code blocks are loaded for Graph and GraphComputer classes. Added a test case 
to TraversalStrategiesTset that demonstrates that the GlobalCache can be 
manipulated without fear of static{} re-registering strategies. This is a much 
much safer model and, moreover, proved correct via testing.


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

Branch: refs/heads/TINKERPOP-1490
Commit: f9bf0444e4bfe09dcea9b8dc05870ddaec4b6180
Parents: 285ff35
Author: Marko A. Rodriguez <okramma...@gmail.com>
Authored: Tue Oct 25 13:02:29 2016 -0600
Committer: Marko A. Rodriguez <okramma...@gmail.com>
Committed: Tue Oct 25 13:02:29 2016 -0600

----------------------------------------------------------------------
 CHANGELOG.asciidoc                              |   1 +
 .../decoration/VertexProgramStrategy.java       |   5 -
 .../process/traversal/TraversalStrategies.java  |  11 +-
 .../process/TraversalStrategiesTest.java        | 194 ++++++++++++++++++-
 4 files changed, 200 insertions(+), 11 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f9bf0444/CHANGELOG.asciidoc
----------------------------------------------------------------------
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index a281c38..1c7441b 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -26,6 +26,7 @@ 
image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
 TinkerPop 3.2.4 (Release Date: NOT OFFICIALLY RELEASED YET)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
+* Added a class loader to `TraversalStrategies.GlobalCache` which guarantees 
strategies are registered prior to `GlobalCache.getStrategies()`.
 * Fixed a severe bug where `GraphComputer` strategies are not being loaded 
until the second use of the traversal source.
 
 [[release-3-2-3]]

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f9bf0444/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/strategy/decoration/VertexProgramStrategy.java
----------------------------------------------------------------------
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/strategy/decoration/VertexProgramStrategy.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/strategy/decoration/VertexProgramStrategy.java
index 0eeae3c..89e40cb 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/strategy/decoration/VertexProgramStrategy.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/strategy/decoration/VertexProgramStrategy.java
@@ -171,11 +171,6 @@ public final class VertexProgramStrategy extends 
AbstractTraversalStrategy<Trave
             }
         } else
             graphComputerClass = this.computer.getGraphComputerClass();
-        try {
-            Class.forName(graphComputerClass.getCanonicalName());
-        } catch (final ClassNotFoundException e) {
-            throw new IllegalStateException(e.getMessage(), e);
-        }
         final List<TraversalStrategy<?>> graphComputerStrategies = 
TraversalStrategies.GlobalCache.getStrategies(graphComputerClass).toList();
         
traversalSource.getStrategies().addStrategies(graphComputerStrategies.toArray(new
 TraversalStrategy[graphComputerStrategies.size()]));
     }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f9bf0444/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 c271a37..015df70 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
@@ -225,7 +225,6 @@ public interface TraversalStrategies extends Serializable, 
Cloneable {
                     OrderLimitStrategy.instance(),
                     PathProcessorStrategy.instance(),
                     ComputerVerificationStrategy.instance());
-
             GRAPH_COMPUTER_CACHE.put(GraphComputer.class, 
graphComputerStrategies);
         }
 
@@ -239,6 +238,16 @@ public interface TraversalStrategies extends Serializable, 
Cloneable {
         }
 
         public static TraversalStrategies getStrategies(final Class 
graphOrGraphComputerClass) {
+            try {
+                // be sure to load the class so that its static{} traversal 
strategy registration component is loaded.
+                // this is more important for GraphComputer classes as they 
are typically not instantiated prior to strategy usage like Graph classes.
+                final String graphComputerClassName = null != 
graphOrGraphComputerClass.getDeclaringClass() ?
+                        
graphOrGraphComputerClass.getCanonicalName().replace("." + 
graphOrGraphComputerClass.getSimpleName(), "$" + 
graphOrGraphComputerClass.getSimpleName()) :
+                        graphOrGraphComputerClass.getCanonicalName();
+                Class.forName(graphComputerClassName);
+            } catch (final ClassNotFoundException e) {
+                throw new IllegalStateException(e.getMessage(), e);
+            }
             if (Graph.class.isAssignableFrom(graphOrGraphComputerClass)) {
                 final TraversalStrategies traversalStrategies = 
GRAPH_CACHE.get(graphOrGraphComputerClass);
                 return null == traversalStrategies ? 
GRAPH_CACHE.get(Graph.class) : traversalStrategies;

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f9bf0444/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/TraversalStrategiesTest.java
----------------------------------------------------------------------
diff --git 
a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/TraversalStrategiesTest.java
 
b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/TraversalStrategiesTest.java
index f316836..3d320db 100644
--- 
a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/TraversalStrategiesTest.java
+++ 
b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/TraversalStrategiesTest.java
@@ -18,26 +18,211 @@
  */
 package org.apache.tinkerpop.gremlin.process;
 
+import org.apache.commons.configuration.BaseConfiguration;
+import org.apache.commons.configuration.Configuration;
+import org.apache.tinkerpop.gremlin.process.computer.ComputerResult;
+import org.apache.tinkerpop.gremlin.process.computer.GraphComputer;
+import org.apache.tinkerpop.gremlin.process.computer.MapReduce;
+import org.apache.tinkerpop.gremlin.process.computer.VertexProgram;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategies;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
 import 
org.apache.tinkerpop.gremlin.process.traversal.strategy.AbstractTraversalStrategy;
+import org.apache.tinkerpop.gremlin.structure.Edge;
+import org.apache.tinkerpop.gremlin.structure.Graph;
+import org.apache.tinkerpop.gremlin.structure.Transaction;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
 import org.junit.Test;
 
-import java.util.Arrays;
 import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.Future;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
 /**
  * @author Matthias Broecheler (m...@matthiasb.com)
  */
 public class TraversalStrategiesTest {
 
+    @Test
+    public void shouldAllowUserManipulationOfGlobalCache() throws Exception {
+        ///////////
+        // GRAPH //
+        ///////////
+        TestGraph graph = new TestGraph();
+        TraversalStrategies strategies = graph.traversal().getStrategies();
+        
assertFalse(TraversalStrategies.GlobalCache.getStrategies(Graph.class).toList().isEmpty());
+        for (final TraversalStrategy strategy : 
TraversalStrategies.GlobalCache.getStrategies(Graph.class).toList()) {
+            
assertTrue(strategies.getStrategy(strategy.getClass()).isPresent());
+        }
+        for (final TraversalStrategy strategy : 
TraversalStrategies.GlobalCache.getStrategies(TestGraphComputer.class).toList())
 {
+            
assertFalse(strategies.getStrategy(strategy.getClass()).isPresent());
+        }
+        assertTrue(strategies.getStrategy(StrategyA.class).isPresent());
+        assertTrue(strategies.getStrategy(StrategyB.class).isPresent());
+        assertFalse(strategies.getStrategy(StrategyC.class).isPresent());
+        assertFalse(strategies.getStrategy(StrategyD.class).isPresent());
+        strategies.addStrategies(new StrategyD());
+        strategies.removeStrategies(StrategyA.class);
+        assertFalse(strategies.getStrategy(StrategyA.class).isPresent());
+        assertTrue(strategies.getStrategy(StrategyD.class).isPresent());
+        ///
+        graph = new TestGraph();
+        strategies = graph.traversal().getStrategies();
+        for (final TraversalStrategy strategy : 
TraversalStrategies.GlobalCache.getStrategies(Graph.class).toList()) {
+            
assertTrue(strategies.getStrategy(strategy.getClass()).isPresent());
+        }
+        for (final TraversalStrategy strategy : 
TraversalStrategies.GlobalCache.getStrategies(TestGraphComputer.class).toList())
 {
+            
assertFalse(strategies.getStrategy(strategy.getClass()).isPresent());
+        }
+        assertFalse(strategies.getStrategy(StrategyA.class).isPresent());
+        assertTrue(strategies.getStrategy(StrategyB.class).isPresent());
+        assertFalse(strategies.getStrategy(StrategyC.class).isPresent());
+        assertTrue(strategies.getStrategy(StrategyD.class).isPresent());
+        //////////////////////
+        /// GRAPH COMPUTER ///
+        //////////////////////
+        strategies = 
TraversalStrategies.GlobalCache.getStrategies(TestGraphComputer.class);
+        
assertFalse(TraversalStrategies.GlobalCache.getStrategies(GraphComputer.class).toList().isEmpty());
+        for (final TraversalStrategy strategy : 
TraversalStrategies.GlobalCache.getStrategies(GraphComputer.class).toList()) {
+            
assertTrue(strategies.getStrategy(strategy.getClass()).isPresent());
+        }
+        for (final TraversalStrategy strategy : 
TraversalStrategies.GlobalCache.getStrategies(TestGraph.class).toList()) {
+            
assertFalse(strategies.getStrategy(strategy.getClass()).isPresent());
+        }
+        assertFalse(strategies.getStrategy(StrategyA.class).isPresent());
+        assertFalse(strategies.getStrategy(StrategyB.class).isPresent());
+        assertTrue(strategies.getStrategy(StrategyC.class).isPresent());
+        strategies.addStrategies(new StrategyE());
+        strategies.removeStrategies(StrategyC.class);
+        //
+        strategies = 
TraversalStrategies.GlobalCache.getStrategies(TestGraphComputer.class);
+        
assertFalse(TraversalStrategies.GlobalCache.getStrategies(GraphComputer.class).toList().isEmpty());
+        for (final TraversalStrategy strategy : 
TraversalStrategies.GlobalCache.getStrategies(GraphComputer.class).toList()) {
+            
assertTrue(strategies.getStrategy(strategy.getClass()).isPresent());
+        }
+        for (final TraversalStrategy strategy : 
TraversalStrategies.GlobalCache.getStrategies(TestGraph.class).toList()) {
+            
assertFalse(strategies.getStrategy(strategy.getClass()).isPresent());
+        }
+        assertFalse(strategies.getStrategy(StrategyA.class).isPresent());
+        assertFalse(strategies.getStrategy(StrategyB.class).isPresent());
+        assertFalse(strategies.getStrategy(StrategyC.class).isPresent());
+        assertFalse(strategies.getStrategy(StrategyD.class).isPresent());
+        assertTrue(strategies.getStrategy(StrategyE.class).isPresent());
+    }
+
+    public static class TestGraphComputer implements GraphComputer {
+
+        static {
+            
TraversalStrategies.GlobalCache.registerStrategies(TestGraphComputer.class,
+                    
TraversalStrategies.GlobalCache.getStrategies(GraphComputer.class).clone().addStrategies(new
 StrategyC()));
+        }
+
+        @Override
+        public GraphComputer result(ResultGraph resultGraph) {
+            return this;
+        }
+
+        @Override
+        public GraphComputer persist(Persist persist) {
+            return this;
+        }
+
+        @Override
+        public GraphComputer program(VertexProgram vertexProgram) {
+            return this;
+        }
+
+        @Override
+        public GraphComputer mapReduce(MapReduce mapReduce) {
+            return this;
+        }
+
+        @Override
+        public GraphComputer workers(int workers) {
+            return this;
+        }
+
+        @Override
+        public GraphComputer vertices(Traversal<Vertex, Vertex> vertexFilter) 
throws IllegalArgumentException {
+            return this;
+        }
+
+        @Override
+        public GraphComputer edges(Traversal<Vertex, Edge> edgeFilter) throws 
IllegalArgumentException {
+            return this;
+        }
+
+        @Override
+        public Future<ComputerResult> submit() {
+            return new CompletableFuture<>();
+        }
+    }
+
+    public static class TestGraph implements Graph {
+
+        static {
+            TraversalStrategies.GlobalCache.registerStrategies(TestGraph.class,
+                    
TraversalStrategies.GlobalCache.getStrategies(Graph.class).clone().addStrategies(new
 StrategyA(), new StrategyB()));
+        }
+
+        @Override
+        public Vertex addVertex(Object... keyValues) {
+            return null;
+        }
+
+        @Override
+        public <C extends GraphComputer> C compute(Class<C> 
graphComputerClass) throws IllegalArgumentException {
+            return (C) new TestGraphComputer();
+        }
+
+        @Override
+        public GraphComputer compute() throws IllegalArgumentException {
+            return new TestGraphComputer();
+        }
+
+        @Override
+        public Iterator<Vertex> vertices(Object... vertexIds) {
+            return Collections.emptyIterator();
+        }
+
+        @Override
+        public Iterator<Edge> edges(Object... edgeIds) {
+            return Collections.emptyIterator();
+        }
+
+        @Override
+        public Transaction tx() {
+            return null;
+        }
+
+        @Override
+        public void close() throws Exception {
+
+        }
+
+        @Override
+        public Variables variables() {
+            return null;
+        }
+
+        @Override
+        public Configuration configuration() {
+            return new BaseConfiguration();
+        }
+    }
+
     /**
      * Tests that {@link 
org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategies#sortStrategies(java.util.List)}
      * works as advertised. This class defines a bunch of dummy strategies 
which define an order. It is verified
@@ -113,7 +298,7 @@ public class TraversalStrategiesTest {
         assertTrue(s.indexOf(a) < s.indexOf(b));
 
         // sort and then add more
-        s = new ArrayList<>((List)Arrays.asList(b,a,c));
+        s = new ArrayList<>((List) Arrays.asList(b, a, c));
         s = TraversalStrategies.sortStrategies(s);
         assertEquals(3, s.size());
         assertEquals(a, s.get(0));
@@ -220,7 +405,6 @@ public class TraversalStrategiesTest {
     }
 
 
-
     private static class DummyStrategy<S extends TraversalStrategy> extends 
AbstractTraversalStrategy<S> {
 
         @Override
@@ -262,7 +446,7 @@ public class TraversalStrategiesTest {
         assertEquals(e, s.get(3));
 
         //full reverse sorting
-        s = Arrays.asList(k,e,d,c,b,a);
+        s = Arrays.asList(k, e, d, c, b, a);
         s = TraversalStrategies.sortStrategies(s);
         assertEquals(6, s.size());
         assertEquals(a, s.get(0));

Reply via email to