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/10/20 12:52:38 UTC
[tinkerpop] branch TINKERPOP-2443 created (now bbcda03)
This is an automated email from the ASF dual-hosted git repository.
spmallette pushed a change to branch TINKERPOP-2443
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git.
at bbcda03 TINKERPOP-2443 Refactored TypeTranslator
This branch includes the following new commits:
new bbcda03 TINKERPOP-2443 Refactored TypeTranslator
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 Refactored TypeTranslator
Posted by sp...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
spmallette pushed a commit to branch TINKERPOP-2443
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
commit bbcda032cd1b3cbf3d8be0e6c5ad1c75ecf45cc5
Author: Stephen Mallette <st...@amazon.com>
AuthorDate: Tue Oct 20 08:51:31 2020 -0400
TINKERPOP-2443 Refactored TypeTranslator
Tried to make better re-use of the logic of the TypeTranslator. There was a lot of duplication between python and groovy and it seemed like that could be abstracted a bit so that the language specific implementations could focus more solely on the actual types that needed to be translated.
---
.../gremlin/process/traversal/Translator.java | 259 +++++++++++++++
.../traversal/translator/GroovyTranslator.java | 368 ++++++++++-----------
.../traversal/translator/PythonTranslator.java | 331 +++++++++---------
3 files changed, 612 insertions(+), 346 deletions(-)
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Translator.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Translator.java
index 796f63f..d7dc61b 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Translator.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Translator.java
@@ -19,6 +19,19 @@
package org.apache.tinkerpop.gremlin.process.traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalOptionParent;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.TraversalStrategyProxy;
+import org.apache.tinkerpop.gremlin.structure.Edge;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.apache.tinkerpop.gremlin.structure.VertexProperty;
+import org.apache.tinkerpop.gremlin.util.function.Lambda;
+
+import java.sql.Timestamp;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
import java.util.function.BiFunction;
/**
@@ -68,6 +81,252 @@ public interface Translator<S, T> {
* representations in their target language.
*/
public interface TypeTranslator extends BiFunction<String, Object, Script> { }
+
+ public abstract class AbstractTypeTranslator implements ScriptTranslator.TypeTranslator {
+ protected static final String ANONYMOUS_TRAVERSAL_PREFIX = "__";
+ protected final boolean withParameters;
+ protected final Script script;
+
+ protected AbstractTypeTranslator(final boolean withParameters) {
+ this.withParameters = withParameters;
+ this.script = new Script();
+ }
+
+ @Override
+ public Script apply(final String traversalSource, final Object o) {
+ this.script.init();
+ if (o instanceof Bytecode) {
+ return produceScript(traversalSource, (Bytecode) o);
+ } else {
+ return convertToScript(o);
+ }
+ }
+
+ /**
+ * Gets the syntax for the spawn of an anonymous traversal which is traditionally the double underscore.
+ */
+ protected String getAnonymousTraversalPrefix() {
+ return ANONYMOUS_TRAVERSAL_PREFIX;
+ }
+
+ /**
+ * Gets the syntax for a {@code null} value as a string representation.
+ */
+ protected abstract String getNullSyntax();
+
+ /**
+ * Take the string argument and convert it to a string representation in the target language (i.e. escape,
+ * enclose in appropriate quotes, etc.)
+ */
+ protected abstract String getSyntax(final String o);
+
+ /**
+ * Take the boolean argument and convert it to a string representation in the target language.
+ */
+ protected abstract String getSyntax(final Boolean o);
+
+ /**
+ * Take the {@code Date} argument and convert it to a string representation in the target language.
+ */
+ protected abstract String getSyntax(final Date o);
+
+ /**
+ * Take the {@code Timestamp} argument and convert it to a string representation in the target language.
+ */
+ protected abstract String getSyntax(final Timestamp o);
+
+ /**
+ * Take the {@code UUID} argument and convert it to a string representation in the target language.
+ */
+ protected abstract String getSyntax(final UUID o);
+
+ /**
+ * Take the {@link Lambda} argument and convert it to a string representation in the target language.
+ */
+ protected abstract String getSyntax(final Lambda o);
+
+ /**
+ * Take the {@link SackFunctions.Barrier} argument and convert it to a string representation in the target language.
+ */
+ protected abstract String getSyntax(final SackFunctions.Barrier o);
+
+ /**
+ * Take the {@link VertexProperty.Cardinality} argument and convert it to a string representation in the target language.
+ */
+ protected abstract String getSyntax(final VertexProperty.Cardinality o);
+
+ /**
+ * Take the {@link TraversalOptionParent.Pick} argument and convert it to a string representation in the target language.
+ */
+ protected abstract String getSyntax(final TraversalOptionParent.Pick o);
+
+ /**
+ * Take the numeric argument and convert it to a string representation in the target language. Languages
+ * that can discern differences in types of numbers will wish to further check the type of the
+ * {@code Number} instance itself (i.e. {@code Double}, {@code Integer}, etc.)
+ */
+ protected abstract String getSyntax(final Number o);
+
+ /**
+ * Take the {@code Set} and writes the syntax directly to the member {@link #script} variable.
+ */
+ protected abstract Script produceScript(final Set<?> o);
+
+ /**
+ * Take the {@code List} and writes the syntax directly to the member {@link #script} variable.
+ */
+ protected abstract Script produceScript(final List<?> o);
+
+ /**
+ * Take the {@code Map} and writes the syntax directly to the member {@link #script} variable.
+ */
+ protected abstract Script produceScript(final Map<?,?> o);
+
+ /**
+ * Take the {@code Class} and writes the syntax directly to the member {@link #script} variable.
+ */
+ protected abstract Script produceScript(final Class<?> o);
+
+ /**
+ * Take the {@code Enum} and writes the syntax directly to the member {@link #script} variable.
+ */
+ protected abstract Script produceScript(final Enum<?> o);
+
+ /**
+ * Take the {@link Vertex} and writes the syntax directly to the member {@link #script} variable.
+ */
+ protected abstract Script produceScript(final Vertex o);
+
+ /**
+ * Take the {@link Edge} and writes the syntax directly to the member {@link #script} variable.
+ */
+ protected abstract Script produceScript(final Edge o);
+
+ /**
+ * Take the {@link VertexProperty} and writes the syntax directly to the member {@link #script} variable.
+ */
+ protected abstract Script produceScript(final VertexProperty<?> o);
+
+ /**
+ * Take the {@link TraversalStrategyProxy} and writes the syntax directly to the member {@link #script} variable.
+ */
+ protected abstract Script produceScript(final TraversalStrategyProxy<?> o);
+
+ /**
+ * Take the {@link Bytecode} and writes the syntax directly to the member {@link #script} variable.
+ */
+ protected abstract Script produceScript(final String traversalSource, final Bytecode o);
+
+ /**
+ * Take the {@link P} and writes the syntax directly to the member {@link #script} variable.
+ */
+ protected abstract Script produceScript(final P<?> p);
+
+ /**
+ * Take the {@link TextP} and writes the syntax directly to the member {@link #script} variable.
+ */
+ protected abstract Script produceScript(final TextP p);
+
+ /**
+ * For each operator argument, if withParameters set true, try parametrization as follows:
+ *
+ * -----------------------------------------------
+ * if unpack, why ? ObjectType
+ * -----------------------------------------------
+ * (Yes) Bytecode.Binding
+ * (Recursion, No) Bytecode
+ * (Recursion, No) Traversal
+ * (Yes) String
+ * (Recursion, No) Set
+ * (Recursion, No) List
+ * (Recursion, No) Map
+ * (Yes) Long
+ * (Yes) Double
+ * (Yes) Float
+ * (Yes) Integer
+ * (Yes) Timestamp
+ * (Yes) Date
+ * (Yes) Uuid
+ * (Recursion, No) P
+ * (Enumeration, No) SackFunctions.Barrier
+ * (Enumeration, No) VertexProperty.Cardinality
+ * (Enumeration, No) TraversalOptionParent.Pick
+ * (Enumeration, No) Enum
+ * (Recursion, No) Vertex
+ * (Recursion, No) Edge
+ * (Recursion, No) VertexProperty
+ * (Yes) Lambda
+ * (Recursion, No) TraversalStrategyProxy
+ * (Enumeration, No) TraversalStrategy
+ * (Yes) Other
+ * -------------------------------------------------
+ *
+ * @param object
+ * @return String Repres
+ */
+ protected Script convertToScript(final Object object) {
+ if (object instanceof Bytecode.Binding) {
+ return script.getBoundKeyOrAssign(withParameters, ((Bytecode.Binding) object).variable());
+ } else if (object instanceof Bytecode) {
+ return produceScript(getAnonymousTraversalPrefix(), (Bytecode) object);
+ } else if (object instanceof Traversal) {
+ return convertToScript(((Traversal) object).asAdmin().getBytecode());
+ } else if (object instanceof String) {
+ final Object objectOrWrapper = withParameters ? object : getSyntax((String) object);
+ return script.getBoundKeyOrAssign(withParameters, objectOrWrapper);
+ } else if (object instanceof Boolean) {
+ final Object objectOrWrapper = withParameters ? object : getSyntax((Boolean) object);
+ return script.getBoundKeyOrAssign(withParameters, objectOrWrapper);
+ } else if (object instanceof Set) {
+ return produceScript((Set<?>) object);
+ } else if (object instanceof List) {
+ return produceScript((List<?>) object);
+ } else if (object instanceof Map) {
+ return produceScript((Map<?, ?>) object);
+ } else if (object instanceof Number) {
+ final Object objectOrWrapper = withParameters ? object : getSyntax((Number) object);
+ return script.getBoundKeyOrAssign(withParameters, objectOrWrapper);
+ } else if (object instanceof Class) {
+ return produceScript((Class<?>) object);
+ } else if (object instanceof Timestamp) {
+ final Object objectOrWrapper = withParameters ? object : getSyntax((Timestamp) object);
+ return script.getBoundKeyOrAssign(withParameters, objectOrWrapper);
+ } else if (object instanceof Date) {
+ final Object objectOrWrapper = withParameters ? object : getSyntax((Date) object);
+ return script.getBoundKeyOrAssign(withParameters, objectOrWrapper);
+ } else if (object instanceof UUID) {
+ final Object objectOrWrapper = withParameters ? object : getSyntax((UUID) object);
+ return script.getBoundKeyOrAssign(withParameters, objectOrWrapper);
+ } else if (object instanceof TextP) {
+ return produceScript((TextP) object);
+ } else if (object instanceof P) {
+ return produceScript((P<?>) object);
+ } else if (object instanceof SackFunctions.Barrier) {
+ return script.append(getSyntax((SackFunctions.Barrier) object));
+ } else if (object instanceof VertexProperty.Cardinality) {
+ return script.append(getSyntax((VertexProperty.Cardinality) object));
+ } else if (object instanceof TraversalOptionParent.Pick) {
+ return script.append(getSyntax((TraversalOptionParent.Pick) object));
+ } else if (object instanceof Enum) {
+ return produceScript((Enum<?>) object);
+ } else if (object instanceof Vertex) {
+ return produceScript((Vertex) object);
+ } else if (object instanceof Edge) {
+ return produceScript((Edge) object);
+ } else if (object instanceof VertexProperty) {
+ return produceScript((VertexProperty<?>) object);
+ } else if (object instanceof Lambda) {
+ final Object objectOrWrapper = withParameters ? object : getSyntax((Lambda) object);
+ return script.getBoundKeyOrAssign(withParameters,objectOrWrapper);
+ } else if (object instanceof TraversalStrategyProxy) {
+ return produceScript((TraversalStrategyProxy<?>) object);
+ } else if (object instanceof TraversalStrategy) {
+ return convertToScript(new TraversalStrategyProxy(((TraversalStrategy) object)));
+ } else {
+ return null == object ? script.append(getNullSyntax()) : script.getBoundKeyOrAssign(withParameters, object);
+ }
+ }
+ }
}
/**
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/translator/GroovyTranslator.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/translator/GroovyTranslator.java
index 3a8f8a5..c4c7d35 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/translator/GroovyTranslator.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/translator/GroovyTranslator.java
@@ -27,28 +27,27 @@ import org.apache.tinkerpop.gremlin.process.traversal.SackFunctions;
import org.apache.tinkerpop.gremlin.process.traversal.Script;
import org.apache.tinkerpop.gremlin.process.traversal.TextP;
import org.apache.tinkerpop.gremlin.process.traversal.Translator;
-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.TraversalOptionParent;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.TraversalStrategyProxy;
import org.apache.tinkerpop.gremlin.process.traversal.util.ConnectiveP;
import org.apache.tinkerpop.gremlin.process.traversal.util.OrP;
import org.apache.tinkerpop.gremlin.structure.Edge;
-import org.apache.tinkerpop.gremlin.structure.Element;
import org.apache.tinkerpop.gremlin.structure.Vertex;
import org.apache.tinkerpop.gremlin.structure.VertexProperty;
import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
import org.apache.tinkerpop.gremlin.util.function.Lambda;
+import java.math.BigDecimal;
+import java.math.BigInteger;
import java.sql.Timestamp;
+import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
-import java.util.stream.Collectors;
import java.util.function.BinaryOperator;
import java.util.function.Supplier;
import java.util.function.UnaryOperator;
@@ -87,12 +86,13 @@ public final class GroovyTranslator implements Translator.ScriptTranslator {
return of(traversalSource, new DefaultTypeTranslator(withParameters));
}
+ /**
+ * Creates the translator with a custom {@link TypeTranslator} instance.
+ */
public static GroovyTranslator of(final String traversalSource, final TypeTranslator typeTranslator) {
return new GroovyTranslator(traversalSource, typeTranslator);
}
- ///////
-
@Override
public Script translate(final Bytecode bytecode) {
return typeTranslator.apply(traversalSource, bytecode);
@@ -116,194 +116,189 @@ public final class GroovyTranslator implements Translator.ScriptTranslator {
/**
* Performs standard type translation for the TinkerPop types to Groovy.
*/
- public static class DefaultTypeTranslator implements TypeTranslator {
- protected final boolean withParameters;
- protected final Script script;
+ public static class DefaultTypeTranslator extends AbstractTypeTranslator {
public DefaultTypeTranslator(final boolean withParameters) {
- this.withParameters = withParameters;
- this.script = new Script();
+ super(withParameters);
}
@Override
- public Script apply(final String traversalSource, final Object o) {
- this.script.init();
- if (o instanceof Bytecode) {
- return internalTranslate(traversalSource, (Bytecode) o);
- } else {
- return convertToScript(o);
- }
+ protected String getNullSyntax() {
+ return "null";
}
- /**
- * For each operator argument, if withParameters set true, try parametrization as follows:
- *
- * -----------------------------------------------
- * if unpack, why ? ObjectType
- * -----------------------------------------------
- * (Yes) Bytecode.Binding
- * (Recursion, No) Bytecode
- * (Recursion, No) Traversal
- * (Yes) String
- * (Recursion, No) Set
- * (Recursion, No) List
- * (Recursion, No) Map
- * (Yes) Long
- * (Yes) Double
- * (Yes) Float
- * (Yes) Integer
- * (Yes) Timestamp
- * (Yes) Date
- * (Yes) Uuid
- * (Recursion, No) P
- * (Enumeration, No) SackFunctions.Barrier
- * (Enumeration, No) VertexProperty.Cardinality
- * (Enumeration, No) TraversalOptionParent.Pick
- * (Enumeration, No) Enum
- * (Recursion, No) Vertex
- * (Recursion, No) Edge
- * (Recursion, No) VertexProperty
- * (Yes) Lambda
- * (Recursion, No) TraversalStrategyProxy
- * (Enumeration, No) TraversalStrategy
- * (Yes) Other
- * -------------------------------------------------
- *
- * @param object
- * @return String Repres
- */
- protected Script convertToScript(final Object object) {
- if (object instanceof Bytecode.Binding) {
- return script.getBoundKeyOrAssign(withParameters, ((Bytecode.Binding) object).variable());
- } else if (object instanceof Bytecode) {
- return internalTranslate("__", (Bytecode) object);
- } else if (object instanceof Traversal) {
- return convertToScript(((Traversal) object).asAdmin().getBytecode());
- } else if (object instanceof String) {
- final String wrapper = (((String) object).contains("\"") ? "\"\"\"" + StringEscapeUtils.escapeJava((String) object) + "\"\"\"" : "\"" + StringEscapeUtils.escapeJava((String) object) + "\"")
- .replace("$", "\\$");
- return script.getBoundKeyOrAssign(withParameters, withParameters ? object : wrapper);
- } else if (object instanceof Set) {
- convertToScript(((Set)object).stream().collect(Collectors.toList()));
- return script.append(" as Set");
- } else if (object instanceof List) {
- final Iterator<?> iterator = ((List)object).iterator();
- if (!iterator.hasNext()) {
- return script.append("[]");
- } else {
- script.append("[");
- for (;;) {
- Object e = iterator.next();
- convertToScript(e);
- if (!iterator.hasNext()) {
- return script.append("]");
- } else {
- script.append(",").append(" ");
- }
- }
- }
- } else if (object instanceof Map) {
- script.append("[");
- for (final Map.Entry<?, ?> entry : ((Map<?, ?>) object).entrySet()) {
- script.append("(");
- convertToScript(entry.getKey());
- script.append("):(");
- convertToScript(entry.getValue());
- script.append("),");
- }
+ @Override
+ protected String getSyntax(final String o) {
+ return (o.contains("\"") ? "\"\"\"" + StringEscapeUtils.escapeJava(o) + "\"\"\"" : "\"" + StringEscapeUtils.escapeJava(o) + "\"")
+ .replace("$", "\\$");
+ }
- // only need to remove this last bit if entries were added
- if (!((Map<?, ?>) object).isEmpty()) {
- return script.setCharAtEnd(']');
- } else {
- return script.append("]");
- }
- } else if (object instanceof Long) {
- return script.getBoundKeyOrAssign(withParameters, withParameters ? object : object + "L");
- } else if (object instanceof Double) {
- return script.getBoundKeyOrAssign(withParameters, withParameters ? object : object + "d");
- } else if (object instanceof Float) {
- return script.getBoundKeyOrAssign(withParameters, withParameters ? object : object + "f");
- } else if (object instanceof Integer) {
- return script.getBoundKeyOrAssign(withParameters, withParameters ? object : "(int) " + object);
- } else if (object instanceof Class) {
- return script.append(((Class) object).getCanonicalName());
- } else if (object instanceof Timestamp) {
- return script.getBoundKeyOrAssign(withParameters, withParameters ? object : "new java.sql.Timestamp(" + ((Timestamp) object).getTime() + ")");
- } else if (object instanceof Date) {
- return script.getBoundKeyOrAssign(withParameters, withParameters ? object : "new java.util.Date(" + ((Date) object).getTime() + ")");
- } else if (object instanceof UUID) {
- return script.getBoundKeyOrAssign(withParameters, withParameters ? object : "java.util.UUID.fromString('" + object.toString() + "')");
- } else if (object instanceof P) {
- return convertPToScript((P) object);
- } else if (object instanceof SackFunctions.Barrier) {
- return script.append("SackFunctions.Barrier." + object.toString());
- } else if (object instanceof VertexProperty.Cardinality) {
- return script.append("VertexProperty.Cardinality." + object.toString());
- } else if (object instanceof TraversalOptionParent.Pick) {
- return script.append("TraversalOptionParent.Pick." + object.toString());
- } else if (object instanceof Enum) {
- return script.append(((Enum) object).getDeclaringClass().getSimpleName() + "." + object.toString());
- } else if (object instanceof Element) {
- if (object instanceof Vertex) {
- final Vertex vertex = (Vertex) object;
- script.append("new org.apache.tinkerpop.gremlin.structure.util.detached.DetachedVertex(");
- convertToScript(vertex.id());
- script.append(",");
- convertToScript(vertex.label());
- return script.append(", Collections.emptyMap())");
- } else if (object instanceof Edge) {
- final Edge edge = (Edge) object;
- script.append("new org.apache.tinkerpop.gremlin.structure.util.detached.DetachedEdge(");
- convertToScript(edge.id());
- script.append(",");
- convertToScript(edge.label());
- script.append(",");
- script.append("Collections.emptyMap(),");
- convertToScript(edge.outVertex().id());
- script.append(",");
- convertToScript(edge.outVertex().label());
- script.append(",");
- convertToScript(edge.inVertex().id());
- script.append(",");
- convertToScript(edge.inVertex().label());
- return script.append(")");
- } else {// VertexProperty
- final VertexProperty vertexProperty = (VertexProperty) object;
- script.append("new org.apache.tinkerpop.gremlin.structure.util.detached.DetachedVertexProperty(");
- convertToScript(vertexProperty.id());
- script.append(",");
- convertToScript(vertexProperty.label());
- script.append(",");
- convertToScript(vertexProperty.value());
+ @Override
+ protected String getSyntax(final Boolean o) {
+ return o.toString();
+ }
+
+ @Override
+ protected String getSyntax(final Date o) {
+ return "new java.util.Date(" + o.getTime() + ")";
+ }
+
+ @Override
+ protected String getSyntax(final Timestamp o) {
+ return "new java.sql.Timestamp(" + o.getTime() + ")";
+ }
+
+ @Override
+ protected String getSyntax(final UUID o) {
+ return "java.util.UUID.fromString('" + o.toString() + "')";
+ }
+
+ @Override
+ protected String getSyntax(final Lambda o) {
+ final String lambdaString = o.getLambdaScript().trim();
+ return lambdaString.startsWith("{") ? lambdaString : "{" + lambdaString + "}";
+ }
+
+ @Override
+ protected String getSyntax(final SackFunctions.Barrier o) {
+ return "SackFunctions.Barrier." + o.toString();
+ }
+
+ @Override
+ protected String getSyntax(final VertexProperty.Cardinality o) {
+ return "VertexProperty.Cardinality." + o.toString();
+ }
+
+ @Override
+ protected String getSyntax(final TraversalOptionParent.Pick o) {
+ return "TraversalOptionParent.Pick." + o.toString();
+ }
+
+ @Override
+ protected String getSyntax(final Number o) {
+ if (o instanceof Long)
+ return o + "L";
+ else if (o instanceof Double)
+ return o + "d";
+ else if (o instanceof Float)
+ return o + "f";
+ else if (o instanceof Integer)
+ return "(int) " + o;
+ else if (o instanceof Byte)
+ return "(byte) " + o;
+ if (o instanceof Short)
+ return "(short) " + o;
+ else if (o instanceof BigInteger)
+ return "new java.math.BigInteger(" + o.toString() + ")";
+ else if (o instanceof BigDecimal)
+ return "new java.math.BigDecimal(" + o.toString() + ")";
+ else
+ return o.toString();
+ }
+
+ @Override
+ protected Script produceScript(final Set<?> o) {
+ return produceScript(new ArrayList<>(o)).append(" as Set");
+ }
+
+ @Override
+ protected Script produceScript(final List<?> o) {
+ final Iterator<?> iterator = ((List<?>) o).iterator();
+ script.append("[");
+
+ while (iterator.hasNext()) {
+ final Object nextItem = iterator.next();
+ convertToScript(nextItem);
+ if (iterator.hasNext())
+ script.append(",").append(" ");
+ }
+
+ return script.append("]");
+ }
+
+ @Override
+ protected Script produceScript(final Map<?, ?> o) {
+ script.append("[");
+ final Iterator<? extends Map.Entry<?, ?>> itty = ((Map<?, ?>) o).entrySet().iterator();
+ while (itty.hasNext()) {
+ final Map.Entry<?,?> entry = itty.next();
+ script.append("(");
+ convertToScript(entry.getKey());
+ script.append("):(");
+ convertToScript(entry.getValue());
+ script.append(")");
+ if (itty.hasNext())
script.append(",");
- script.append("Collections.emptyMap(),");
- convertToScript(vertexProperty.element());
- return script.append(")");
- }
- } else if (object instanceof Lambda) {
- final String lambdaString = ((Lambda) object).getLambdaScript().trim();
- final String wrapper = lambdaString.startsWith("{") ? lambdaString : "{" + lambdaString + "}";
- return script.getBoundKeyOrAssign(withParameters, withParameters ? object : wrapper);
- } else if (object instanceof TraversalStrategyProxy) {
- final TraversalStrategyProxy proxy = (TraversalStrategyProxy) object;
- if (proxy.getConfiguration().isEmpty()) {
- return script.append(proxy.getStrategyClass().getCanonicalName() + ".instance()");
- } else {
- script.append(proxy.getStrategyClass().getCanonicalName() + ".create(new org.apache.commons.configuration2.MapConfiguration(");
- convertToScript(ConfigurationConverter.getMap(proxy.getConfiguration()));
- return script.append("))");
- }
- } else if (object instanceof TraversalStrategy) {
- return convertToScript(new TraversalStrategyProxy(((TraversalStrategy) object)));
+ }
+ return script.append("]");
+ }
+
+ @Override
+ protected Script produceScript(final Class<?> o) {
+ return script.append(o.getCanonicalName());
+ }
+
+ @Override
+ protected Script produceScript(final Enum<?> o) {
+ return script.append(o.getDeclaringClass().getSimpleName() + "." + o.toString());
+ }
+
+ @Override
+ protected Script produceScript(final Vertex o) {
+ script.append("new org.apache.tinkerpop.gremlin.structure.util.detached.DetachedVertex(");
+ convertToScript(o.id());
+ script.append(",");
+ convertToScript(o.label());
+ return script.append(", Collections.emptyMap())");
+ }
+
+ @Override
+ protected Script produceScript(final Edge o) {
+ script.append("new org.apache.tinkerpop.gremlin.structure.util.detached.DetachedEdge(");
+ convertToScript(o.id());
+ script.append(",");
+ convertToScript(o.label());
+ script.append(",");
+ script.append("Collections.emptyMap(),");
+ convertToScript(o.outVertex().id());
+ script.append(",");
+ convertToScript(o.outVertex().label());
+ script.append(",");
+ convertToScript(o.inVertex().id());
+ script.append(",");
+ convertToScript(o.inVertex().label());
+ return script.append(")");
+ }
+
+ @Override
+ protected Script produceScript(final VertexProperty<?> o) {
+ script.append("new org.apache.tinkerpop.gremlin.structure.util.detached.DetachedVertexProperty(");
+ convertToScript(o.id());
+ script.append(",");
+ convertToScript(o.label());
+ script.append(",");
+ convertToScript(o.value());
+ script.append(",");
+ script.append("Collections.emptyMap(),");
+ convertToScript(o.element());
+ return script.append(")");
+ }
+
+ @Override
+ protected Script produceScript(final TraversalStrategyProxy<?> o) {
+ if (o.getConfiguration().isEmpty()) {
+ return script.append(o.getStrategyClass().getCanonicalName() + ".instance()");
} else {
- return null == object ? script.append("null") : script.getBoundKeyOrAssign(withParameters, object);
+ script.append(o.getStrategyClass().getCanonicalName() + ".create(new org.apache.commons.configuration2.MapConfiguration(");
+ convertToScript(ConfigurationConverter.getMap(o.getConfiguration()));
+ return script.append("))");
}
}
- protected Script internalTranslate(final String start, final Bytecode bytecode) {
- script.append(start);
- for (final Bytecode.Instruction instruction : bytecode.getInstructions()) {
+ @Override
+ protected Script produceScript(final String traversalSource, final Bytecode o) {
+ script.append(traversalSource);
+ for (final Bytecode.Instruction instruction : o.getInstructions()) {
final String methodName = instruction.getOperator();
if (0 == instruction.getArguments().length) {
script.append(".").append(methodName).append("()");
@@ -343,14 +338,12 @@ public final class GroovyTranslator implements Translator.ScriptTranslator {
return script;
}
- protected Script convertPToScript(final P p) {
- if (p instanceof TextP) {
- return convertTextPToScript((TextP) p);
- }
+ @Override
+ protected Script produceScript(final P<?> p) {
if (p instanceof ConnectiveP) {
final List<P<?>> list = ((ConnectiveP) p).getPredicates();
for (int i = 0; i < list.size(); i++) {
- convertPToScript(list.get(i));
+ produceScript(list.get(i));
if (i < list.size() - 1) {
script.append(p instanceof OrP ? ".or(" : ".and(");
}
@@ -363,7 +356,8 @@ public final class GroovyTranslator implements Translator.ScriptTranslator {
return script;
}
- protected Script convertTextPToScript(final TextP p) {
+ @Override
+ protected Script produceScript(final TextP p) {
script.append("TextP.").append(p.getBiPredicate().toString()).append("(");
convertToScript(p.getValue());
script.append(")");
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/translator/PythonTranslator.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/translator/PythonTranslator.java
index 360c58e..049ca53 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/translator/PythonTranslator.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/translator/PythonTranslator.java
@@ -28,25 +28,27 @@ import org.apache.tinkerpop.gremlin.process.traversal.TextP;
import org.apache.tinkerpop.gremlin.process.traversal.Translator;
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.dsl.graph.GraphTraversal;
import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalOptionParent;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.TraversalStrategyProxy;
import org.apache.tinkerpop.gremlin.process.traversal.util.ConnectiveP;
import org.apache.tinkerpop.gremlin.process.traversal.util.OrP;
import org.apache.tinkerpop.gremlin.structure.Edge;
-import org.apache.tinkerpop.gremlin.structure.Element;
import org.apache.tinkerpop.gremlin.structure.Vertex;
import org.apache.tinkerpop.gremlin.structure.VertexProperty;
import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
import org.apache.tinkerpop.gremlin.util.function.Lambda;
import java.lang.reflect.Method;
+import java.math.BigDecimal;
+import java.sql.Timestamp;
+import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.UUID;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -65,19 +67,31 @@ public final class PythonTranslator implements Translator.ScriptTranslator {
private final String traversalSource;
private final TypeTranslator typeTranslator;
- PythonTranslator(final String traversalSource, final TypeTranslator typeTranslator) {
+ private PythonTranslator(final String traversalSource, final TypeTranslator typeTranslator) {
this.traversalSource = traversalSource;
this.typeTranslator = typeTranslator;
}
- public static PythonTranslator of(final String traversalSource, final boolean withParameters) {
- return of(traversalSource, new DefaultTypeTranslator(withParameters));
- }
-
+ /**
+ * Creates the translator with a {@code false} argument to {@code withParameters} using
+ * {@link #of(String, boolean)}.
+ */
public static PythonTranslator of(final String traversalSource) {
return of(traversalSource, false);
}
+ /**
+ * Creates the translator with the {@link DefaultTypeTranslator} passing the {@code withParameters} option to it
+ * which will handle type translation in a fashion that should typically increase cache hits and reduce
+ * compilation times if enabled at the sacrifice to rewriting of the script that could reduce readability.
+ */
+ public static PythonTranslator of(final String traversalSource, final boolean withParameters) {
+ return of(traversalSource, new DefaultTypeTranslator(withParameters));
+ }
+
+ /**
+ * Creates the translator with a custom {@link TypeTranslator} instance.
+ */
public static PythonTranslator of(final String traversalSource, final TypeTranslator typeTranslator) {
return new PythonTranslator(traversalSource, typeTranslator);
}
@@ -107,153 +121,163 @@ public final class PythonTranslator implements Translator.ScriptTranslator {
/**
* Performs standard type translation for the TinkerPop types to Python.
*/
- public static class DefaultTypeTranslator implements TypeTranslator {
- protected final boolean withParameters;
- protected final Script script;
+ public static class DefaultTypeTranslator extends AbstractTypeTranslator {
public DefaultTypeTranslator(final boolean withParameters) {
- this.withParameters = withParameters;
- this.script = new Script();
+ super(withParameters);
}
@Override
- public Script apply(final String traversalSource, final Object o) {
- this.script.init();
- if (o instanceof Bytecode) {
- return internalTranslate(traversalSource, (Bytecode) o);
- } else {
- return convertToScript(o);
+ protected String getNullSyntax() {
+ return "None";
+ }
+
+ @Override
+ protected String getSyntax(final String o) {
+ return o.contains("'") || o.contains(System.lineSeparator()) ?
+ "\"\"\"" + o + "\"\"\"" : "'" + o + "'";
+ }
+
+ @Override
+ protected String getSyntax(final Boolean o) {
+ return o ? "True" : "False";
+ }
+
+ @Override
+ protected String getSyntax(final Date o) {
+ return "datetime.datetime.utcfromtimestamp(" + o.getTime() + " / 1000.0)";
+ }
+
+ @Override
+ protected String getSyntax(final Timestamp o) {
+ return "timestamp(" + o.getTime() + " / 1000.0)";
+ }
+
+ @Override
+ protected String getSyntax(final UUID o) {
+ return "UUID('" + o.toString() +"')";
+ }
+
+ @Override
+ protected String getSyntax(final Lambda o) {
+ final String lambdaString = o.getLambdaScript().trim();
+ return lambdaString.startsWith("lambda") ? lambdaString : "lambda " + lambdaString;
+ }
+
+ @Override
+ protected String getSyntax(final Number o) {
+ // todo: nan/inf
+ // all int/short/BigInteger/long are just python int/bignum
+ if (o instanceof Double || o instanceof Float || o instanceof BigDecimal)
+ return "float(" + o + ")";
+ else if (o instanceof Byte)
+ return "SingleByte(" + o + ")";
+ else
+ return o.toString();
+ }
+
+ @Override
+ protected String getSyntax(final SackFunctions.Barrier o) {
+ return "Barrier." + resolveSymbol(o.toString());
+ }
+
+ @Override
+ protected String getSyntax(final VertexProperty.Cardinality o) {
+ return "Cardinality." + resolveSymbol(o.toString());
+ }
+
+ @Override
+ protected String getSyntax(final TraversalOptionParent.Pick o) {
+ return "Pick." + resolveSymbol(o.toString());
+ }
+
+ @Override
+ protected Script produceScript(final Set<?> o) {
+ final Iterator<?> iterator = o.iterator();
+ script.append("set(");
+ while(iterator.hasNext()) {
+ convertToScript(iterator.next());
+ if (iterator.hasNext())
+ script.append(",");
}
+ return script.append(")");
}
- /**
- * For each operator argument, if withParameters set true, try parametrization as follows:
- * <p>
- * -----------------------------------------------
- * if unpack, why? ObjectType
- * -----------------------------------------------
- * (Yes) Bytecode.Binding
- * (Recursion, No) Bytecode
- * (Recursion, No) Traversal
- * (Yes) String
- * (Recursion, No) Set
- * (Recursion, No) List
- * (Recursion, No) Map
- * (Yes) Long
- * (Yes) Double
- * (Yes) Float
- * (Yes) Integer
- * (Yes) Timestamp
- * (Yes) Date
- * (Yes) Uuid
- * (Recursion, No) P
- * (Enumeration, No) SackFunctions.Barrier
- * (Enumeration, No) VertexProperty.Cardinality
- * (Enumeration, No) TraversalOptionParent.Pick
- * (Enumeration, No) Enum
- * (Recursion, No) Vertex
- * (Recursion, No) Edge
- * (Recursion, No) VertexProperty
- * (Yes) Lambda
- * (Recursion, No) TraversalStrategyProxy
- * (Enumeration, No) TraversalStrategy
- * (Yes) Other
- * -------------------------------------------------
- *
- * @param object
- * @return String Repres
- */
- protected Script convertToScript(final Object object) {
- if (object instanceof Bytecode.Binding)
- return script.getBoundKeyOrAssign(withParameters, ((Bytecode.Binding) object).variable());
- else if (object instanceof Bytecode)
- return this.internalTranslate("__", (Bytecode) object);
- else if (object instanceof Traversal)
- return convertToScript(((Traversal) object).asAdmin().getBytecode());
- else if (object instanceof String) {
- final String wrapper = ((String) object).contains("'") || ((String) object).contains(System.lineSeparator()) ?
- "\"\"\"" + object + "\"\"\"" : "'" + object + "'";
- return script.getBoundKeyOrAssign(withParameters, withParameters ? object : wrapper);
- } else if (object instanceof Set) {
- final Iterator<?> iterator = ((Set) object).iterator();
- script.append("set(");
- while(iterator.hasNext()) {
- convertToScript(iterator.next());
- if (iterator.hasNext())
- script.append(",");
- }
+ @Override
+ protected Script produceScript(final List<?> o) {
+ final Iterator<?> iterator = o.iterator();
+ script.append("[");
+ while(iterator.hasNext()) {
+ convertToScript(iterator.next());
+ if (iterator.hasNext())
+ script.append(",");
+ }
+ return script.append("]");
+ }
+
+ @Override
+ protected Script produceScript(final Map<?, ?> o) {
+ script.append("{");
+ final Iterator<? extends Map.Entry<?, ?>> itty = o.entrySet().iterator();
+ while (itty.hasNext()) {
+ final Map.Entry<?,?> entry = itty.next();
+ convertToScript(entry.getKey()).append(":");
+ convertToScript(entry.getValue());
+ if (itty.hasNext())
+ script.append(",");
+ }
+ return script.append("}");
+ }
+
+ @Override
+ protected Script produceScript(final Class<?> o) {
+ return script.append("GremlinType(" + o.getCanonicalName() + ")");
+ }
+
+ @Override
+ protected Script produceScript(final Enum<?> o) {
+ return script.append(o.getDeclaringClass().getSimpleName() + "." + resolveSymbol(o.toString()));
+ }
+
+ @Override
+ protected Script produceScript(final Vertex o) {
+ script.append("Vertex(");
+ convertToScript(o.id()).append(",");
+ return convertToScript(o.label()).append(")");
+ }
+
+ @Override
+ protected Script produceScript(final Edge o) {
+ script.append("Edge(");
+ convertToScript(o.id()).append(",");
+ convertToScript(o.outVertex()).append(",");
+ convertToScript(o.label()).append(",");
+ return convertToScript(o.inVertex()).append(")");
+ }
+
+ @Override
+ protected Script produceScript(final VertexProperty<?> o) {
+ script.append("VertexProperty(");
+ convertToScript(o.id()).append(",");
+ convertToScript(o.label()).append(",");
+ return convertToScript(o.value()).append(")");
+ }
+
+ @Override
+ protected Script produceScript(final TraversalStrategyProxy<?> o) {
+ if (o.getConfiguration().isEmpty())
+ return script.append("TraversalStrategy('" + o.getStrategyClass().getSimpleName() + "')");
+ else {
+ script.append("TraversalStrategy('").append(o.getStrategyClass().getSimpleName()).append("',");
+ convertToScript(ConfigurationConverter.getMap(o.getConfiguration()));
return script.append(")");
- } else if (object instanceof List) {
- final Iterator<?> iterator = ((List) object).iterator();
- script.append("[");
- while(iterator.hasNext()) {
- convertToScript(iterator.next());
- if (iterator.hasNext())
- script.append(",");
- }
- return script.append("]");
- } else if (object instanceof Map) {
- script.append("{");
- final Iterator<? extends Map.Entry<?, ?>> itty = ((Map<?, ?>) object).entrySet().iterator();
- while (itty.hasNext()) {
- final Map.Entry<?,?> entry = itty.next();
- convertToScript(entry.getKey()).append(":");
- convertToScript(entry.getValue());
- if (itty.hasNext())
- script.append(",");
- }
- return script.append("}");
- } else if (object instanceof Long)
- return script.getBoundKeyOrAssign(withParameters, withParameters ? object : "long(" + object + ")");
- else if (object instanceof TraversalStrategyProxy) {
- return resolveTraversalStrategyProxy((TraversalStrategyProxy) object);
- } else if (object instanceof TraversalStrategy) {
- return convertToScript(new TraversalStrategyProxy((TraversalStrategy) object));
- } else if (object instanceof Boolean)
- return script.getBoundKeyOrAssign(withParameters, withParameters ? object : object.equals(Boolean.TRUE) ? "True" : "False");
- else if (object instanceof Class)
- return script.append(((Class) object).getCanonicalName());
- else if (object instanceof VertexProperty.Cardinality)
- return script.append("Cardinality." + resolveSymbol(object.toString()));
- else if (object instanceof SackFunctions.Barrier)
- return script.append("Barrier." + resolveSymbol(object.toString()));
- else if (object instanceof TraversalOptionParent.Pick)
- return script.append("Pick." + resolveSymbol(object.toString()));
- else if (object instanceof Enum)
- return script.append(((Enum) object).getDeclaringClass().getSimpleName() + "." + resolveSymbol(object.toString()));
- else if (object instanceof P)
- return convertPToScript((P) object);
- else if (object instanceof Element) {
- if (object instanceof Vertex) {
- final Vertex vertex = (Vertex) object;
- script.append("Vertex(");
- convertToScript(vertex.id()).append(",");
- return convertToScript(vertex.label()).append(")");
- } else if (object instanceof Edge) {
- final Edge edge = (Edge) object;
- script.append("Edge(");
- convertToScript(edge.id()).append(",");
- convertToScript(edge.outVertex()).append(",");
- convertToScript(edge.label()).append(",");
- return convertToScript(edge.inVertex()).append(")");
- } else {
- final VertexProperty vertexProperty = (VertexProperty) object;
- script.append("VertexProperty(");
- convertToScript(vertexProperty.id()).append(",");
- convertToScript(vertexProperty.label()).append(",");
- return convertToScript(vertexProperty.value()).append(")");
- }
- } else if (object instanceof Lambda) {
- final String lambdaString = ((Lambda) object).getLambdaScript().trim();
- final String wrapper = lambdaString.startsWith("lambda") ? lambdaString : "lambda " + lambdaString;;
- return script.getBoundKeyOrAssign(withParameters, withParameters ? object : wrapper);
- } else
- return null == object ? script.append("None") : script.getBoundKeyOrAssign(withParameters, object);
+ }
}
- private Script internalTranslate(final String start, final Bytecode bytecode) {
- script.append(start);
- for (final Bytecode.Instruction instruction : bytecode.getInstructions()) {
+ @Override
+ protected Script produceScript(final String traversalSource, final Bytecode o) {
+ script.append(traversalSource);
+ for (final Bytecode.Instruction instruction : o.getInstructions()) {
final String methodName = instruction.getOperator();
final Object[] arguments = instruction.getArguments();
if (0 == arguments.length)
@@ -289,14 +313,12 @@ public final class PythonTranslator implements Translator.ScriptTranslator {
return script;
}
- protected Script convertPToScript(final P p) {
- if (p instanceof TextP) {
- return convertTextPToScript((TextP) p);
- }
+ @Override
+ protected Script produceScript(final P<?> p) {
if (p instanceof ConnectiveP) {
final List<P<?>> list = ((ConnectiveP) p).getPredicates();
for (int i = 0; i < list.size(); i++) {
- convertPToScript(list.get(i));
+ produceScript(list.get(i));
if (i < list.size() - 1) {
script.append(p instanceof OrP ? ".or_(" : ".and_(");
}
@@ -309,7 +331,8 @@ public final class PythonTranslator implements Translator.ScriptTranslator {
return script;
}
- protected Script convertTextPToScript(final TextP p) {
+ @Override
+ protected Script produceScript(final TextP p) {
script.append("TextP.").append(p.getBiPredicate().toString()).append("(");
convertToScript(p.getValue());
script.append(")");
@@ -319,16 +342,6 @@ public final class PythonTranslator implements Translator.ScriptTranslator {
protected String resolveSymbol(final String methodName) {
return SymbolHelper.toPython(methodName);
}
-
- protected Script resolveTraversalStrategyProxy(final TraversalStrategyProxy proxy) {
- if (proxy.getConfiguration().isEmpty())
- return script.append("TraversalStrategy('" + proxy.getStrategyClass().getSimpleName() + "')");
- else {
- script.append("TraversalStrategy('").append(proxy.getStrategyClass().getSimpleName()).append("',");
- convertToScript(ConfigurationConverter.getMap(proxy.getConfiguration()));
- return script.append(")");
- }
- }
}
static final class SymbolHelper {