You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by co...@apache.org on 2024/10/01 18:08:59 UTC
(tinkerpop) 01/03: WIP update TraversalStrategyProxy to construct custom strategies
This is an automated email from the ASF dual-hosted git repository.
colegreer pushed a commit to branch customStrategyConstruction
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
commit 1455ccac7c0a087e8a282d77200465d36bac2ab0
Author: Cole-Greer <Co...@improving.com>
AuthorDate: Tue Oct 1 09:20:32 2024 -0700
WIP update TraversalStrategyProxy to construct custom strategies
---
.../gremlin/process/traversal/GremlinLang.java | 17 ++++-
.../traversal/strategy/TraversalStrategyProxy.java | 29 ++++++--
.../jsr223/GremlinLangScriptEngineTest.java | 66 ++++++++++++++++++
.../strategy/TraversalStrategyProxyTest.java | 81 ++++++++++++++++++++++
4 files changed, 185 insertions(+), 8 deletions(-)
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/GremlinLang.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/GremlinLang.java
index 1b50dee8c7..daacf02ecd 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/GremlinLang.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/GremlinLang.java
@@ -22,6 +22,7 @@ package org.apache.tinkerpop.gremlin.process.traversal;
import org.apache.commons.configuration2.Configuration;
import org.apache.commons.text.StringEscapeUtils;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.TraversalStrategyProxy;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.OptionsStrategy;
import org.apache.tinkerpop.gremlin.process.traversal.util.ConnectiveP;
import org.apache.tinkerpop.gremlin.process.traversal.util.DefaultTraversal;
@@ -372,13 +373,23 @@ public class GremlinLang implements Cloneable, Serializable {
break;
}
- final Configuration configuration = ((TraversalStrategy) arguments[i]).getConfiguration();
+ Configuration configuration;
+ String strategyName;
+
+ // special handling for TraversalStrategyProxy
+ if (arguments[i] instanceof TraversalStrategyProxy) {
+ configuration = ((TraversalStrategy) arguments[i]).getConfiguration();
+ strategyName = ((TraversalStrategyProxy) arguments[i]).getStrategyName();
+ } else {
+ configuration = ((TraversalStrategy) arguments[i]).getConfiguration();
+ strategyName = arguments[i].getClass().getSimpleName();
+ }
if (configuration.isEmpty()) {
- sb.append(arguments[i].getClass().getSimpleName());
+ sb.append(strategyName);
} else {
sb.append("new ")
- .append(arguments[i].getClass().getSimpleName())
+ .append(strategyName)
.append("(");
configuration.getKeys().forEachRemaining(key -> {
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/TraversalStrategyProxy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/TraversalStrategyProxy.java
index 363fd89b84..5dd39c26b7 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/TraversalStrategyProxy.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/TraversalStrategyProxy.java
@@ -20,13 +20,17 @@
package org.apache.tinkerpop.gremlin.process.traversal.strategy;
import org.apache.commons.configuration2.Configuration;
+import org.apache.commons.configuration2.MapConfiguration;
+import org.apache.tinkerpop.gremlin.language.grammar.TraversalStrategyVisitor;
import org.apache.tinkerpop.gremlin.process.traversal.GremlinLang;
import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
import org.apache.tinkerpop.gremlin.process.traversal.TraversalSource;
+import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategies;
import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
import java.io.Serializable;
+import java.util.Collections;
/**
* This class is for use with {@link GremlinLang} and for serialization purposes. It is not meant for direct use with
@@ -37,23 +41,38 @@ import java.io.Serializable;
public final class TraversalStrategyProxy<T extends TraversalStrategy> implements Serializable, TraversalStrategy {
private final Configuration configuration;
- private final Class<T> strategyClass;
+ private final String strategyName;
+ public TraversalStrategyProxy(final String strategyName) {
+ this(strategyName, new MapConfiguration(Collections.EMPTY_MAP));
+ }
+
+ public TraversalStrategyProxy(final String strategyName, final Configuration configuration) {
+ this.configuration = configuration;
+ this.strategyName = strategyName;
+ }
+
+ @Deprecated
public TraversalStrategyProxy(final T traversalStrategy) {
- this((Class<T>) traversalStrategy.getClass(), traversalStrategy.getConfiguration());
+ this(traversalStrategy.getClass().getSimpleName(), traversalStrategy.getConfiguration());
}
+ @Deprecated
public TraversalStrategyProxy(final Class<T> strategyClass, final Configuration configuration) {
- this.configuration = configuration;
- this.strategyClass = strategyClass;
+ this(strategyClass.getSimpleName(), configuration);
}
public Configuration getConfiguration() {
return this.configuration;
}
+ public String getStrategyName() {
+ return this.strategyName;
+ }
+
+ @Deprecated
public Class<T> getStrategyClass() {
- return this.strategyClass;
+ return (Class<T>) TraversalStrategies.GlobalCache.getRegisteredStrategyClass(strategyName).get();
}
@Override
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/jsr223/GremlinLangScriptEngineTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/jsr223/GremlinLangScriptEngineTest.java
index 9846363030..22dd49659e 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/jsr223/GremlinLangScriptEngineTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/jsr223/GremlinLangScriptEngineTest.java
@@ -18,8 +18,16 @@
*/
package org.apache.tinkerpop.gremlin.jsr223;
+import org.apache.commons.configuration2.Configuration;
+import org.apache.commons.configuration2.MapConfiguration;
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.dsl.graph.GraphTraversal;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.AbstractTraversalStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.TraversalStrategyProxy;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.TraversalStrategyProxyTest;
import org.apache.tinkerpop.gremlin.structure.util.empty.EmptyGraph;
import org.junit.Test;
@@ -27,9 +35,18 @@ import javax.script.Bindings;
import javax.script.ScriptException;
import javax.script.SimpleBindings;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.IsInstanceOf.instanceOf;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
public class GremlinLangScriptEngineTest {
@@ -59,4 +76,53 @@ public class GremlinLangScriptEngineTest {
assertThat(result, instanceOf(Traversal.Admin.class));
assertEquals(g.V(100, 1000, 10000).asAdmin().getGremlinLang(), ((Traversal.Admin) result).getGremlinLang());
}
+
+ public static class TestStrategy<S extends TraversalStrategy> extends AbstractTraversalStrategy<S> {
+ private final Configuration configuration;
+
+ private TestStrategy(final Configuration configuration) {
+ this.configuration = configuration;
+ }
+ @Override
+ public void apply(Traversal.Admin traversal) {
+ // Do nothing
+ }
+
+ @Override
+ public Configuration getConfiguration() {
+ return configuration;
+ }
+
+ public static TestStrategy create(Configuration configuration) {
+ return new TestStrategy(configuration);
+ }
+ }
+
+ @Test
+ public void shouldReconstructCustomRegisteredStrategy() throws ScriptException {
+ TraversalStrategies.GlobalCache.registerStrategy(TestStrategy.class);
+
+ GraphTraversal traversal = (GraphTraversal) scriptEngine.eval("g.withStrategies(new TestStrategy(stringKey:\"stringValue\",intKey:1,booleanKey:true)).V()");
+
+ TestStrategy reconstructedStrategy = traversal.asAdmin().getStrategies().getStrategy(TestStrategy.class).get();
+
+ assertNotNull(reconstructedStrategy);
+
+ MapConfiguration expectedConfig = new MapConfiguration(new HashMap<String, Object>() {{
+ put("stringKey", "stringValue");
+ put("intKey", 1);
+ put("booleanKey", true);
+ }});
+
+ Set<String> expectedKeys = new HashSet<>();
+ Set<String> actualKeys = new HashSet<>();
+ expectedConfig.getKeys().forEachRemaining((key) -> expectedKeys.add(key));
+ reconstructedStrategy.getConfiguration().getKeys().forEachRemaining((key) -> actualKeys.add(key));
+
+ assertEquals(expectedKeys, actualKeys);
+
+ expectedKeys.forEach((key) -> {
+ assertEquals(expectedConfig.get(Object.class, key), reconstructedStrategy.getConfiguration().get(Object.class, key));
+ });
+ }
}
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/TraversalStrategyProxyTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/TraversalStrategyProxyTest.java
new file mode 100644
index 0000000000..cf4a228176
--- /dev/null
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/TraversalStrategyProxyTest.java
@@ -0,0 +1,81 @@
+/*
+ * 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;
+
+import org.apache.commons.configuration2.MapConfiguration;
+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.dsl.graph.GraphTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
+import org.apache.tinkerpop.gremlin.structure.util.empty.EmptyGraph;
+import org.junit.Test;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+
+public class TraversalStrategyProxyTest {
+
+ private static class TestStrategy<S extends TraversalStrategy> extends AbstractTraversalStrategy<S> {
+ @Override
+ public void apply(Traversal.Admin traversal) {
+ // Do nothing
+ }
+ }
+
+ @Test
+ public void shouldAddCustomStrategyToGremlinScript() {
+ TraversalStrategyProxy strategyProxy = new TraversalStrategyProxy("TestStrategy");
+ GraphTraversalSource g = EmptyGraph.instance().traversal();
+ GraphTraversal traversal = g.withStrategies(strategyProxy).V();
+ assertEquals("g.withStrategies(TestStrategy).V()", traversal.asAdmin().getGremlinLang().getGremlin());
+ }
+
+ @Test
+ public void shouldAddCustomStrategyWithConfigToGremlinScript() {
+ Map<String, Object> configMap = new LinkedHashMap<>();
+ configMap.put("stringKey", "stringValue");
+ configMap.put("intKey", 1);
+ configMap.put("booleanKey", true);
+ TraversalStrategyProxy strategyProxy = new TraversalStrategyProxy("TestStrategy", new MapConfiguration(configMap));
+
+ GraphTraversalSource g = EmptyGraph.instance().traversal();
+ GraphTraversal traversal = g.withStrategies(strategyProxy).V();
+
+ assertEquals("g.withStrategies(new TestStrategy(stringKey:\"stringValue\",intKey:1,booleanKey:true)).V()", traversal.asAdmin().getGremlinLang().getGremlin());
+ }
+
+ @Test
+ public void gremlinLangShouldReconstructRegisteredCustomStrategyFromScript() {
+ TraversalStrategies.GlobalCache.registerStrategy(TestStrategy.class);
+
+ Map<String, Object> configMap = new LinkedHashMap<>();
+ configMap.put("stringKey", "stringValue");
+ configMap.put("intKey", 1);
+ configMap.put("booleanKey", true);
+ TraversalStrategyProxy strategyProxy = new TraversalStrategyProxy("TestStrategy", new MapConfiguration(configMap));
+
+ GraphTraversalSource g = EmptyGraph.instance().traversal();
+ GraphTraversal traversal = g.withStrategies(strategyProxy).V();
+
+ //GremlinLangScriptEngine
+ }
+
+}