blob: 30dccc44aa53a590fbfe180bdd61d27532e195d9 [file] [log] [blame]
/*
* 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;
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;
/**
* A Translator will translate {@link Bytecode} into another representation. That representation may be a
* Java instance via {@link StepTranslator} or a String script in some language via {@link ScriptTranslator}.
* The parameterization of Translator is S (traversal source) and T (full translation).
*
* @author Marko A. Rodriguez (http://markorodriguez.com)
* @author Stark Arya (sandszhou.zj@alibaba-inc.com)
* @author Stephen Mallette (http://stephen.genoprime.com)
*/
public interface Translator<S, T> {
/**
* Get the {@link TraversalSource} representation rooting this translator.
* For string-based translators ({@link ScriptTranslator}), this is typically a "g".
* For java-based translators ({@link StepTranslator}), this is typically the {@link TraversalSource} instance
* which the {@link Traversal} will be built from.
*
* @return the traversal source representation
*/
public S getTraversalSource();
/**
* Translate {@link Bytecode} into a new representation. Typically, for language translations, the translation is
* to a string representing the traversal in the respective scripting language.
*
* @param bytecode the bytecode representing traversal source and traversal manipulations.
* @return the translated object
*/
public T translate(final Bytecode bytecode);
/**
* Translates a {@link Traversal} into the specified form
*/
public default T translate(final Traversal<?,?> t) {
return translate(t.asAdmin().getBytecode());
}
/**
* Get the language that the translator is converting the traversal byte code to.
*
* @return the language of the translation
*/
public String getTargetLanguage();
///
/**
* Translates bytecode to a Script representation.
*/
public interface ScriptTranslator extends Translator<String, Script> {
/**
* Provides a way for the {@link ScriptTranslator} to convert various data types to their string
* 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. This
* implementation should also consider {@link TextP}.
*/
protected abstract Script produceScript(final P<?> 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 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);
}
}
}
}
/**
* Translates bytecode to actual steps.
*/
public interface StepTranslator<S extends TraversalSource, T extends Traversal.Admin<?, ?>> extends Translator<S, T> {
}
}