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:39 UTC
[tinkerpop] 01/01: TINKERPOP-2443 Refactored TypeTranslator
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 {