atlas-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From dkan...@apache.org
Subject [1/2] incubator-atlas git commit: ATLAS-1195 Clean up DSL Translation (jnhagelb via dkantor)
Date Thu, 27 Oct 2016 18:53:21 GMT
Repository: incubator-atlas
Updated Branches:
  refs/heads/master aa15cd0ae -> 69af0ae77


http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/69af0ae7/repository/src/main/java/org/apache/atlas/gremlin/GremlinExpressionFactory.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/gremlin/GremlinExpressionFactory.java b/repository/src/main/java/org/apache/atlas/gremlin/GremlinExpressionFactory.java
new file mode 100644
index 0000000..9a36e78
--- /dev/null
+++ b/repository/src/main/java/org/apache/atlas/gremlin/GremlinExpressionFactory.java
@@ -0,0 +1,409 @@
+/**
+ * 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_METHOD 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.atlas.gremlin;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.atlas.AtlasException;
+import org.apache.atlas.groovy.ArithmeticExpression;
+import org.apache.atlas.groovy.ClosureExpression;
+import org.apache.atlas.groovy.FieldExpression;
+import org.apache.atlas.groovy.FunctionCallExpression;
+import org.apache.atlas.groovy.GroovyExpression;
+import org.apache.atlas.groovy.IdentifierExpression;
+import org.apache.atlas.groovy.ListExpression;
+import org.apache.atlas.groovy.LiteralExpression;
+import org.apache.atlas.groovy.TypeCoersionExpression;
+import org.apache.atlas.groovy.VariableAssignmentExpression;
+import org.apache.atlas.groovy.ArithmeticExpression.ArithmeticOperator;
+import org.apache.atlas.query.GraphPersistenceStrategies;
+import org.apache.atlas.query.IntSequence;
+import org.apache.atlas.query.TypeUtils.FieldInfo;
+import org.apache.atlas.repository.graph.AtlasGraphProvider;
+import org.apache.atlas.repository.graphdb.AtlasEdgeDirection;
+import org.apache.atlas.repository.graphdb.GremlinVersion;
+import org.apache.atlas.typesystem.types.IDataType;
+
+/**
+ * Factory to generate Groovy expressions representing Gremlin syntax that that
+ * are independent of the specific version of Gremlin that is being used.
+ *
+ */
+public abstract class GremlinExpressionFactory {
+
+    private static final String G_VARIABLE = "g";
+    private static final String IT_VARIABLE = "it";
+
+    private static final String SET_CLASS = "Set";
+
+    private static final String OBJECT_FIELD = "object";
+
+    protected static final String V_METHOD = "V";
+    protected static final String FILTER_METHOD = "filter";
+    private static final String PATH_METHOD = "path";
+    private static final String AS_METHOD = "as";
+    private static final String FILL_METHOD = "fill";
+    protected static final String HAS_METHOD = "has";
+    protected static final String TO_LOWER_CASE_METHOD = "toLowerCase";
+    protected static final String SELECT_METHOD = "select";
+    protected static final String ORDER_METHOD = "order";
+
+    public static final GremlinExpressionFactory INSTANCE = AtlasGraphProvider.getGraphInstance()
+            .getSupportedGremlinVersion() == GremlinVersion.THREE ? new Gremlin3ExpressionFactory()
+                    : new Gremlin2ExpressionFactory();
+
+    /**
+     * Gets the expression to use as the parent when translating the loop
+     * expression in a loop
+     *
+     * @param inputQry
+     *            the
+     * @return
+     */
+    public abstract GroovyExpression getLoopExpressionParent(GroovyExpression inputQry);
+
+    /**
+     * Generates a loop expression.
+     *
+     * @param parent
+     *            the parent of the loop expression
+     * @param emitExpr
+     *            Expression with the value that should be emitted by the loop
+     *            expression.
+     * @param loopExpr
+     *            the query expression that is being executed repeatedly
+     *            executed in a loop
+     * @param alias
+     *            The alias of the expression being looped over
+     * @param times
+     *            the number of times to repeat, or null if a times condition
+     *            should not be used.
+     * @return
+     */
+    public abstract GroovyExpression generateLoopExpression(GroovyExpression parent, GraphPersistenceStrategies s, IDataType dataType,
+            GroovyExpression loopExpr, String alias, Integer times);
+
+
+    /**
+     * Generates a logical (and/or) expression with the given operands.
+     * @param parent
+     * @param operator
+     * @param operands
+     * @return
+     */
+    public abstract GroovyExpression generateLogicalExpression(GroovyExpression parent, String operator,
+            List<GroovyExpression> operands);
+
+    /**
+     * Generates a back reference expression that refers to the given alias.
+     *
+     * @param parent
+     * @param inSelect
+     * @param alias
+     * @return
+     */
+    public abstract GroovyExpression generateBackReferenceExpression(GroovyExpression parent, boolean inSelect,
+            String alias);
+
+    /**
+     * Generates a select expression
+     *
+     * @param parent
+     * @param sourceNames
+     *            the names of the select fields
+     * @param srcExprs
+     *            the corresponding values to return
+     * @return
+     */
+    public abstract GroovyExpression generateSelectExpression(GroovyExpression parent,
+            List<LiteralExpression> sourceNames, List<GroovyExpression> srcExprs);
+
+    /**
+     * Generates a an expression that gets the value of the given property from the
+     * vertex presented by the parent.
+     *
+     * @param parent
+     * @param fInfo
+     * @param propertyName
+     * @param inSelect
+     * @return
+     */
+    public abstract GroovyExpression generateFieldExpression(GroovyExpression parent, FieldInfo fInfo,
+            String propertyName, boolean inSelect);
+
+    /**
+     * Generates a has expression that checks whether the vertices match a specific condition
+     *
+     * @param s
+     * @param parent the object that we should call apply the "has" condition to.
+     * @param propertyName the name of the property whose value we are comparing
+     * @param symbol comparsion operator symbol ('=','<', etc.)
+     * @param requiredValue the value to compare against
+     * @param fInfo info about the field whose value we are checking
+     * @return
+     * @throws AtlasException
+     */
+    public abstract GroovyExpression generateHasExpression(GraphPersistenceStrategies s, GroovyExpression parent,
+            String propertyName, String symbol, GroovyExpression requiredValue, FieldInfo fInfo) throws AtlasException;
+
+    /**
+     * Generates a limit expression
+     *
+     * @param parent
+     * @param offset
+     * @param totalRows
+     * @return
+     */
+    public abstract GroovyExpression generateLimitExpression(GroovyExpression parent, int offset, int totalRows);
+
+    /**
+     * Generates an order by expression
+     *
+     * @param parent
+     * @param translatedOrderBy
+     * @param isAscending
+     * @return
+     */
+    public abstract GroovyExpression generateOrderByExpression(GroovyExpression parent,
+            List<GroovyExpression> translatedOrderBy, boolean isAscending);
+
+    /**
+     * Returns the Groovy expressions that should be used as the parents when
+     * translating an order by expression. This is needed because Gremlin 2 and
+     * 3 handle order by expressions very differently.
+     *
+     */
+    public abstract List<GroovyExpression> getOrderFieldParents();
+
+    /**
+     * Returns the expression that represents an anonymous graph traversal.
+     *
+     * @return
+     */
+    public abstract GroovyExpression getAnonymousTraversalExpression();
+
+    /**
+     * Returns an expression representing
+     *
+     * @return
+     */
+    public abstract GroovyExpression getFieldInSelect();
+
+    /**
+     * Generates the expression the serves as the root of the Gremlin query.
+     * @param s
+     * @param varExpr variable containing the vertices to traverse
+     * @return
+     */
+    protected abstract GroovyExpression initialExpression(GraphPersistenceStrategies s, GroovyExpression varExpr);
+
+
+    /**
+     * Generates an expression that tests whether the vertex represented by the 'toTest'
+     * expression represents an instance of the specified type, checking both the type
+     * and super type names.
+     *
+     * @param s
+     * @param typeName
+     * @param itRef
+     * @return
+     */
+    protected abstract GroovyExpression typeTestExpression(GraphPersistenceStrategies s, String typeName,
+            GroovyExpression vertexExpr);
+
+    /**
+     * Generates a sequence of groovy expressions that filter the vertices to only
+     * those that match the specified type.  If GraphPersistenceStrategies.collectTypeInstancesIntoVar()
+     * is set, the vertices are put into a variable whose name is geneated from the specified IntSequence.
+     * The last item in the result will be a graph traversal restricted to only the matching vertices.
+     */
+    public List<GroovyExpression> generateTypeTestExpression(GraphPersistenceStrategies s, GroovyExpression parent,
+            String typeName, IntSequence intSeq) {
+        if (s.collectTypeInstancesIntoVar()) {
+            return typeTestExpressionMultiStep(s, typeName, intSeq);
+        } else {
+            return typeTestExpressionUsingFilter(s, parent, typeName);
+        }
+    }
+
+    private List<GroovyExpression> typeTestExpressionMultiStep(GraphPersistenceStrategies s, String typeName,
+            IntSequence intSeq) {
+
+        String varName = "_var_" + intSeq.next();
+        GroovyExpression varExpr = new IdentifierExpression(varName);
+        List<GroovyExpression> result = new ArrayList<>();
+
+        result.add(newSetVar(varName));
+        result.add(fillVarWithTypeInstances(s, typeName, varName));
+        result.add(fillVarWithSubTypeInstances(s, typeName, varName));
+        result.add(initialExpression(s, varExpr));
+
+        return result;
+    }
+
+    private GroovyExpression newSetVar(String varName) {
+        GroovyExpression castExpr = new TypeCoersionExpression(new ListExpression(), SET_CLASS);
+        return new VariableAssignmentExpression(varName, castExpr);
+    }
+
+    private GroovyExpression fillVarWithTypeInstances(GraphPersistenceStrategies s, String typeName, String fillVar) {
+        GroovyExpression graphExpr = getAllVerticesExpr();
+        GroovyExpression typeAttributeNameExpr = new LiteralExpression(s.typeAttributeName());
+        GroovyExpression typeNameExpr = new LiteralExpression(typeName);
+        GroovyExpression hasExpr = new FunctionCallExpression(graphExpr, HAS_METHOD, typeAttributeNameExpr, typeNameExpr);
+        GroovyExpression fillExpr = new FunctionCallExpression(hasExpr, FILL_METHOD, new IdentifierExpression(fillVar));
+        return fillExpr;
+    }
+
+    private GroovyExpression fillVarWithSubTypeInstances(GraphPersistenceStrategies s, String typeName,
+            String fillVar) {
+        GroovyExpression graphExpr = getAllVerticesExpr();
+        GroovyExpression superTypeAttributeNameExpr = new LiteralExpression(s.superTypeAttributeName());
+        GroovyExpression typeNameExpr = new LiteralExpression(typeName);
+        GroovyExpression hasExpr = new FunctionCallExpression(graphExpr, HAS_METHOD, superTypeAttributeNameExpr,
+                typeNameExpr);
+        GroovyExpression fillExpr = new FunctionCallExpression(hasExpr, FILL_METHOD, new IdentifierExpression(fillVar));
+        return fillExpr;
+    }
+
+
+    private List<GroovyExpression> typeTestExpressionUsingFilter(GraphPersistenceStrategies s, GroovyExpression parent,
+            String typeName) {
+        GroovyExpression itExpr = getItVariable();
+        GroovyExpression typeTestExpr = typeTestExpression(s, typeName, itExpr);
+        GroovyExpression closureExpr = new ClosureExpression(typeTestExpr);
+        GroovyExpression filterExpr = new FunctionCallExpression(parent, FILTER_METHOD, closureExpr);
+        return Collections.singletonList(filterExpr);
+    }
+
+
+    /**
+     * Generates an expression which checks whether the vertices in the query have
+     * a field with the given name.
+     *
+     * @param parent
+     * @param fieldName
+     * @return
+     */
+    public GroovyExpression generateUnaryHasExpression(GroovyExpression parent, String fieldName) {
+        return new FunctionCallExpression(parent, HAS_METHOD, new LiteralExpression(fieldName));
+    }
+
+    /**
+     * Generates a path expression
+     *
+     * @param parent
+     * @return
+     */
+    public GroovyExpression generatePathExpression(GroovyExpression parent) {
+        return new FunctionCallExpression(parent, PATH_METHOD);
+    }
+
+    /**
+     * Generates the emit expression used in loop expressions.
+     * @param s
+     * @param dataType
+     * @return
+     */
+    protected GroovyExpression generateLoopEmitExpression(GraphPersistenceStrategies s, IDataType dataType) {
+        return typeTestExpression(s, dataType.getName(), getCurrentObjectExpression());
+    }
+
+    /**
+     * Generates an alias expression
+     *
+     * @param parent
+     * @param alias
+     * @return
+     */
+    public GroovyExpression generateAliasExpression(GroovyExpression parent, String alias) {
+        return new FunctionCallExpression(parent, AS_METHOD, new LiteralExpression(alias));
+    }
+
+    /**
+     * Generates an expression that gets the vertices adjacent to the vertex in 'parent'
+     * in the specified direction.
+     *
+     * @param parent
+     * @param dir
+     * @return
+     */
+    public GroovyExpression generateAdjacentVerticesExpression(GroovyExpression parent, AtlasEdgeDirection dir) {
+        return new FunctionCallExpression(parent, getGremlinFunctionName(dir));
+    }
+
+    private String getGremlinFunctionName(AtlasEdgeDirection dir) {
+        switch(dir) {
+            case IN:
+              return "in";
+            case OUT:
+                return "out";
+            case BOTH:
+                return "both";
+            default:
+                throw new RuntimeException("Unknown Atlas Edge Direction: " + dir);
+        }
+    }
+
+    /**
+     * Generates an expression that gets the vertices adjacent to the vertex in 'parent'
+     * in the specified direction, following only edges with the given label.
+     *
+     * @param parent
+     * @param dir
+     * @return
+     */
+    public GroovyExpression generateAdjacentVerticesExpression(GroovyExpression parent, AtlasEdgeDirection dir,
+            String label) {
+        return new FunctionCallExpression(parent, getGremlinFunctionName(dir), new LiteralExpression(label));
+    }
+
+    /**
+     * Generates an arithmetic expression, e.g. a + b
+     *
+     */
+    public GroovyExpression generateArithmeticExpression(GroovyExpression left, String operator,
+            GroovyExpression right) throws AtlasException {
+        ArithmeticOperator op = ArithmeticOperator.lookup(operator);
+        return new ArithmeticExpression(left, op, right);
+    }
+
+
+
+    protected GroovyExpression getItVariable() {
+        return new IdentifierExpression(IT_VARIABLE);
+    }
+
+
+    protected GroovyExpression getAllVerticesExpr() {
+        GroovyExpression gExpr = getGraph();
+        return new FunctionCallExpression(gExpr, V_METHOD);
+    }
+
+    protected IdentifierExpression getGraph() {
+        return new IdentifierExpression(G_VARIABLE);
+    }
+
+
+    protected GroovyExpression getCurrentObjectExpression() {
+        return new FieldExpression(getItVariable(), OBJECT_FIELD);
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/69af0ae7/repository/src/main/scala/org/apache/atlas/query/GraphPersistenceStrategies.scala
----------------------------------------------------------------------
diff --git a/repository/src/main/scala/org/apache/atlas/query/GraphPersistenceStrategies.scala b/repository/src/main/scala/org/apache/atlas/query/GraphPersistenceStrategies.scala
index 3ccc53f..eb6d119 100755
--- a/repository/src/main/scala/org/apache/atlas/query/GraphPersistenceStrategies.scala
+++ b/repository/src/main/scala/org/apache/atlas/query/GraphPersistenceStrategies.scala
@@ -21,23 +21,20 @@ package org.apache.atlas.query
 import java.util
 import java.util.Date
 
+import scala.collection.JavaConversions._
 import scala.collection.JavaConversions.seqAsJavaList
+import scala.language.existentials
 
-import org.apache.atlas.query.Expressions.{ComparisonExpression, ExpressionException}
+import org.apache.atlas.groovy.GroovyExpression
 import org.apache.atlas.query.TypeUtils.FieldInfo
-import org.apache.atlas.repository.graph.{GraphHelper, GraphBackedMetadataRepository}
 import org.apache.atlas.repository.RepositoryException
+import org.apache.atlas.repository.graph.GraphHelper
 import org.apache.atlas.repository.graphdb._
-import org.apache.atlas.typesystem.persistence.Id
-import org.apache.atlas.typesystem.types.DataTypes._
+import org.apache.atlas.typesystem.ITypedInstance
+import org.apache.atlas.typesystem.ITypedReferenceableInstance
 import org.apache.atlas.typesystem.persistence.Id
 import org.apache.atlas.typesystem.types._
-import org.apache.atlas.typesystem.{ITypedInstance, ITypedReferenceableInstance}
-
-
-import scala.collection.JavaConversions._
-import scala.collection.mutable
-import scala.collection.mutable.ArrayBuffer
+import org.apache.atlas.typesystem.types.DataTypes._
 
 /**
  * Represents the Bridge between the QueryProcessor and the Graph Persistence scheme used.
@@ -47,19 +44,19 @@ import scala.collection.mutable.ArrayBuffer
  * - how are attribute names mapped to Property Keys in Vertices.
  *
  * This is a work in progress.
- * 
+ *
  */
 trait GraphPersistenceStrategies {
 
     @throws(classOf[RepositoryException])
     def getGraph() : AtlasGraph[_,_]
-    
+
     def getSupportedGremlinVersion() : GremlinVersion = getGraph().getSupportedGremlinVersion;
-    def generatePersisentToLogicalConversionExpression(expr: String, t: IDataType[_]) : String = getGraph().generatePersisentToLogicalConversionExpression(expr, t);
+    def generatePersisentToLogicalConversionExpression(expr: GroovyExpression, t: IDataType[_]) : GroovyExpression = getGraph().generatePersisentToLogicalConversionExpression(expr, t);
     def isPropertyValueConversionNeeded(attrType: IDataType[_]) : Boolean = getGraph().isPropertyValueConversionNeeded(attrType);
-    
-    def initialQueryCondition = if (getGraph().requiresInitialIndexedPredicate()) { s""".${getGraph().getInitialIndexedPredicate}""" } else {""};
-   
+
+    def addInitialQueryCondition(parent: GroovyExpression) : GroovyExpression = if (getGraph().requiresInitialIndexedPredicate()) { getGraph().getInitialIndexedPredicate(parent) } else { parent };
+
     /**
      * Name of attribute used to store typeName in vertex
      */
@@ -87,11 +84,12 @@ trait GraphPersistenceStrategies {
 
     def traitLabel(cls: IDataType[_], traitName: String): String
 
-    def instanceToTraitEdgeDirection : String = "out"
-    def traitToInstanceEdgeDirection = instanceToTraitEdgeDirection match {
-      case "out" => "in"
-      case "in" => "out"
-      case x => x
+    def instanceToTraitEdgeDirection : AtlasEdgeDirection = AtlasEdgeDirection.OUT;
+
+    def traitToInstanceEdgeDirection : AtlasEdgeDirection = instanceToTraitEdgeDirection match {
+      case AtlasEdgeDirection.OUT => AtlasEdgeDirection.IN;
+      case AtlasEdgeDirection.IN => AtlasEdgeDirection.OUT;
+      case x => AtlasEdgeDirection.IN;
     }
 
     /**
@@ -115,27 +113,6 @@ trait GraphPersistenceStrategies {
         case FieldInfo(dataType, null, null, traitName) => traitLabel(dataType, traitName)
     }
 
-    def fieldPrefixInSelect(): String = {
-
-        if(getSupportedGremlinVersion() == GremlinVersion.THREE) {
-            //this logic is needed to remove extra results from
-            //what is emitted by repeat loops.  Technically
-            //for queries that don't have a loop in them we could just use "it"
-            //the reason for this is that in repeat loops with an alias,
-            //although the alias gets set to the right value, for some
-            //reason the select actually includes all vertices that were traversed
-            //through in the loop.  In these cases, we only want the last vertex
-            //traversed in the loop to be selected.  The logic here handles that
-            //case by converting the result to a list and just selecting the
-            //last item from it.
-            "((it as Vertex[]) as List<Vertex>).last()"
-        }
-        else {
-            "it"
-        }
-
-    }   
-
     /**
      * extract the Id from a Vertex.
      * @param dataTypeNm the dataType of the instance that the given vertex represents
@@ -146,50 +123,7 @@ trait GraphPersistenceStrategies {
 
     def constructInstance[U](dataType: IDataType[U], v: java.lang.Object): U
 
-    def gremlinCompOp(op: ComparisonExpression) = {
-         if( getSupportedGremlinVersion() == GremlinVersion.TWO) {
-             gremlin2CompOp(op);
-         }
-         else {
-            gremlin3CompOp(op);
-         }
-     }
-    
-     def gremlinPrimitiveOp(op: ComparisonExpression) = op.symbol match {
-        case "=" => "=="
-        case "!=" => "!="
-        case ">" => ">"
-        case ">=" => ">="
-        case "<" => "<"
-        case "<=" => "<="
-        case _ => throw new ExpressionException(op, "Comparison operator not supported in Gremlin")
-     }
-
-    private def gremlin2CompOp(op: ComparisonExpression) = op.symbol match {
-        case "=" => "T.eq"
-        case "!=" => "T.neq"
-        case ">" => "T.gt"
-        case ">=" => "T.gte"
-        case "<" => "T.lt"
-        case "<=" => "T.lte"
-        case _ => throw new ExpressionException(op, "Comparison operator not supported in Gremlin")
-    }
-
-    private def gremlin3CompOp(op: ComparisonExpression) = op.symbol match {
-        case "=" => "eq"
-        case "!=" => "neq"
-        case ">" => "gt"
-        case ">=" => "gte"
-        case "<" => "lt"
-        case "<=" => "lte"
-        case _ => throw new ExpressionException(op, "Comparison operator not supported in Gremlin")
-    }
-
-    def loopObjectExpression(dataType: IDataType[_]) = {
-      _typeTestExpression(dataType.getName, "it.object")
-    }
-
-    def addGraphVertexPrefix(preStatements : Traversable[String]) = !collectTypeInstancesIntoVar
+    def addGraphVertexPrefix(preStatements : Traversable[GroovyExpression]) = !collectTypeInstancesIntoVar
 
     /**
      * Controls behavior of how instances of a Type are discovered.
@@ -213,76 +147,14 @@ trait GraphPersistenceStrategies {
      */
     def collectTypeInstancesIntoVar = true
 
-    def typeTestExpression(typeName : String, intSeq : IntSequence) : Seq[String] = {
-        if (collectTypeInstancesIntoVar)
-            typeTestExpressionMultiStep(typeName, intSeq)
-        else
-            typeTestExpressionUsingFilter(typeName)
-    }
-
-    private def typeTestExpressionUsingFilter(typeName : String) : Seq[String] = {
-      Seq(s"""filter${_typeTestExpression(typeName, "it")}""")
-    }
-
-    /**
-     * type test expression that ends up in the emit clause in
-     * loop/repeat steps and a few other places
-     */
-    private def _typeTestExpression(typeName: String, itRef: String): String = {
-
-        if( getSupportedGremlinVersion() == GremlinVersion.TWO) {
-             s"""{(${itRef}.'${typeAttributeName}' == '${typeName}') |
-       | (${itRef}.'${superTypeAttributeName}' ?
-       | ${itRef}.'${superTypeAttributeName}'.contains('${typeName}') : false)}""".
-          stripMargin.replace(System.getProperty("line.separator"), "")
-        }
-        else {
-            //gremlin 3
-            s"""has('${typeAttributeName}',eq('${typeName}')).or().has('${superTypeAttributeName}',eq('${typeName}'))"""
-        }
-  }
 
     private def propertyValueSet(vertexRef : String, attrName: String) : String = {
         s"""org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils.set(${vertexRef}.values('${attrName})"""
     }
 
-    private def typeTestExpressionMultiStep(typeName : String, intSeq : IntSequence) : Seq[String] = {
-
-        val varName = s"_var_${intSeq.next}"
-        Seq(
-            newSetVar(varName),
-            fillVarWithTypeInstances(typeName, varName),
-            fillVarWithSubTypeInstances(typeName, varName),
-            if(getSupportedGremlinVersion() == GremlinVersion.TWO) {
-                s"$varName._()"
-            }
-            else {
-                //this bit of groovy magic converts the set of vertices in varName into
-                //a String containing the ids of all the vertices.  This becomes the argument
-                //to g.V().  This is needed because Gremlin 3 does not support
-                // _()
-                //s"g.V(${varName}.collect{it.id()} as String[])"
-                s"g.V(${varName} as Object[])${initialQueryCondition}"
-            }
-        )
-    }
-
-    private def newSetVar(varName : String) = s"def $varName = [] as Set"
-
-    private def fillVarWithTypeInstances(typeName : String, fillVar : String) = {
-        s"""g.V().has("${typeAttributeName}", "${typeName}").fill($fillVar)"""
-    }
 
-    private def fillVarWithSubTypeInstances(typeName : String, fillVar : String) = {
-        s"""g.V().has("${superTypeAttributeName}", "${typeName}").fill($fillVar)"""
-    }  
 }
 
-import scala.language.existentials;
-import org.apache.atlas.repository.RepositoryException
-import org.apache.atlas.repository.RepositoryException
-import org.apache.atlas.repository.RepositoryException
-import org.apache.atlas.repository.RepositoryException
 
 case class GraphPersistenceStrategy1(g: AtlasGraph[_,_]) extends GraphPersistenceStrategies {
 
@@ -293,8 +165,8 @@ case class GraphPersistenceStrategy1(g: AtlasGraph[_,_]) extends GraphPersistenc
 
     override def getGraph() : AtlasGraph[_,_] =  {
         return g;
-    }   
-    
+    }
+
     def edgeLabel(dataType: IDataType[_], aInfo: AttributeInfo) = s"__${dataType.getName}.${aInfo.name}"
 
     def edgeLabel(propertyName: String) = s"__${propertyName}"
@@ -458,8 +330,6 @@ case class GraphPersistenceStrategy1(g: AtlasGraph[_,_]) extends GraphPersistenc
         }
     }
 
-
-
     private def mapVertexToCollectionEntry(instanceVertex: AtlasVertex[_,_], attributeInfo: AttributeInfo, elementType: IDataType[_], i: ITypedInstance,  value: Any): Any = {
         elementType.getTypeCategory match {
             case DataTypes.TypeCategory.PRIMITIVE => value
@@ -474,5 +344,6 @@ case class GraphPersistenceStrategy1(g: AtlasGraph[_,_]) extends GraphPersistenc
                 throw new UnsupportedOperationException(s"load for ${attributeInfo.dataType()} not supported")
         }
     }
+
 }
 

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/69af0ae7/repository/src/main/scala/org/apache/atlas/query/GremlinQuery.scala
----------------------------------------------------------------------
diff --git a/repository/src/main/scala/org/apache/atlas/query/GremlinQuery.scala b/repository/src/main/scala/org/apache/atlas/query/GremlinQuery.scala
index 447622b..ee58eee 100755
--- a/repository/src/main/scala/org/apache/atlas/query/GremlinQuery.scala
+++ b/repository/src/main/scala/org/apache/atlas/query/GremlinQuery.scala
@@ -18,30 +18,61 @@
 
 package org.apache.atlas.query
 
+import java.lang.Boolean
+import java.lang.Byte
+import java.lang.Double
+import java.lang.Float
+import java.lang.Integer
+import java.lang.Long
+import java.lang.Short
+import java.util.ArrayList
+
+import scala.collection.JavaConversions.asScalaBuffer
+import scala.collection.JavaConversions.bufferAsJavaList
 import scala.collection.mutable
 import scala.collection.mutable.ArrayBuffer
 
-import org.apache.atlas.query.TypeUtils.FieldInfo;
-import org.apache.atlas.query.Expressions._
-import org.apache.atlas.repository.graphdb.GremlinVersion
+import org.apache.atlas.gremlin.GremlinExpressionFactory
+import org.apache.atlas.groovy.CastExpression
+import org.apache.atlas.groovy.CodeBlockExpression
+import org.apache.atlas.groovy.FunctionCallExpression
+import org.apache.atlas.groovy.GroovyExpression
+import org.apache.atlas.groovy.GroovyGenerationContext
+import org.apache.atlas.groovy.IdentifierExpression
+import org.apache.atlas.groovy.ListExpression
+import org.apache.atlas.groovy.LiteralExpression
+import org.apache.atlas.query.Expressions.AliasExpression
+import org.apache.atlas.query.Expressions.ArithmeticExpression
+import org.apache.atlas.query.Expressions.BackReference
+import org.apache.atlas.query.Expressions.ClassExpression
+import org.apache.atlas.query.Expressions.ComparisonExpression
+import org.apache.atlas.query.Expressions.Expression
+import org.apache.atlas.query.Expressions.ExpressionException
+import org.apache.atlas.query.Expressions.FieldExpression
+import org.apache.atlas.query.Expressions.FilterExpression
+import org.apache.atlas.query.Expressions.InstanceExpression
+import org.apache.atlas.query.Expressions.LimitExpression
+import org.apache.atlas.query.Expressions.ListLiteral
+import org.apache.atlas.query.Expressions.Literal
+import org.apache.atlas.query.Expressions.LogicalExpression
+import org.apache.atlas.query.Expressions.LoopExpression
+import org.apache.atlas.query.Expressions.OrderExpression
+import org.apache.atlas.query.Expressions.PathExpression
+import org.apache.atlas.query.Expressions.SelectExpression
+import org.apache.atlas.query.Expressions.TraitExpression
+import org.apache.atlas.query.Expressions.TraitInstanceExpression
+import org.apache.atlas.query.Expressions.hasFieldLeafExpression
+import org.apache.atlas.query.Expressions.hasFieldUnaryExpression
+import org.apache.atlas.query.Expressions.id
+import org.apache.atlas.query.Expressions.isTraitLeafExpression
+import org.apache.atlas.query.Expressions.isTraitUnaryExpression
+import org.apache.atlas.repository.RepositoryException
+import org.apache.atlas.repository.graphdb.AtlasEdgeDirection
 import org.apache.atlas.typesystem.types.DataTypes
 import org.apache.atlas.typesystem.types.DataTypes.TypeCategory
 import org.apache.atlas.typesystem.types.IDataType
-import org.apache.commons.lang.StringEscapeUtils
 import org.apache.atlas.typesystem.types.TypeSystem
-import org.apache.atlas.typesystem.types.AttributeInfo
 import org.joda.time.format.ISODateTimeFormat
-import org.apache.atlas.typesystem.types.DataTypes.BigDecimalType
-import org.apache.atlas.typesystem.types.DataTypes.ByteType
-import org.apache.atlas.typesystem.types.DataTypes.BooleanType
-import org.apache.atlas.typesystem.types.DataTypes.DateType
-import org.apache.atlas.typesystem.types.DataTypes.BigIntegerType
-import org.apache.atlas.typesystem.types.DataTypes.IntType
-import org.apache.atlas.typesystem.types.DataTypes.StringType
-import org.apache.atlas.typesystem.types.DataTypes.LongType
-import org.apache.atlas.typesystem.types.DataTypes.DoubleType
-import org.apache.atlas.typesystem.types.DataTypes.FloatType
-import org.apache.atlas.typesystem.types.DataTypes.ShortType
 
 trait IntSequence {
     def next: Int
@@ -127,7 +158,7 @@ trait SelectExpressionHandling {
     /**
      * For each Output Column in the SelectExpression compute the ArrayList(Src) this maps to and the position within
      * this list.
-     * 
+     *
      * @param sel
      * @return
      */
@@ -151,8 +182,8 @@ class GremlinTranslator(expr: Expression,
                         gPersistenceBehavior: GraphPersistenceStrategies)
     extends SelectExpressionHandling {
 
-    val preStatements = ArrayBuffer[String]()
-    val postStatements = ArrayBuffer[String]()
+    val preStatements = ArrayBuffer[GroovyExpression]()
+    val postStatements = ArrayBuffer[GroovyExpression]()
 
     val wrapAndRule: PartialFunction[Expression, Expression] = {
         case f: FilterExpression if !f.condExpr.isInstanceOf[LogicalExpression] =>
@@ -216,351 +247,287 @@ class GremlinTranslator(expr: Expression,
       }
     }
 
-    def typeTestExpression(typeName : String) : String = {
-        val stats = gPersistenceBehavior.typeTestExpression(escape(typeName), counter)
+    def typeTestExpression(parent: GroovyExpression, typeName : String) : GroovyExpression = {
+        val stats = GremlinExpressionFactory.INSTANCE.generateTypeTestExpression(gPersistenceBehavior, parent, typeName, counter)
+
         preStatements ++= stats.init
         stats.last
+
     }
 
-    def escape(str: String): String = {
-            if (str != null) {
-              return str.replace("\"", "\\\"").replace("$", "\\$");
-            }
-            str
+    val QUOTE = "\"";
+
+    private def cleanStringLiteral(l : Literal[_]) : String = {
+        return l.toString.stripPrefix(QUOTE).stripSuffix(QUOTE);
     }
-    
-    private def genQuery(expr: Expression, inSelect: Boolean): String = expr match {
-        case ClassExpression(clsName) =>
-            typeTestExpression(clsName)
-        case TraitExpression(clsName) =>
-            typeTestExpression(clsName)
+
+
+    private def genQuery(parent: GroovyExpression, expr: Expression, inSelect: Boolean): GroovyExpression = expr match {
+        case ClassExpression(clsName) => typeTestExpression(parent, clsName)
+        case TraitExpression(clsName) => typeTestExpression(parent, clsName)
         case fe@FieldExpression(fieldName, fInfo, child)
             if fe.dataType.getTypeCategory == TypeCategory.PRIMITIVE || fe.dataType.getTypeCategory == TypeCategory.ARRAY => {
-            val fN = "\"" + gPersistenceBehavior.fieldNameInVertex(fInfo.dataType, fInfo.attrInfo) + "\""
-            genPropertyAccessExpr(child, fInfo, fN, inSelect)
-
-        }
+                val fN = gPersistenceBehavior.fieldNameInVertex(fInfo.dataType, fInfo.attrInfo)
+                val childExpr = translateOptChild(parent, child, inSelect);
+                return GremlinExpressionFactory.INSTANCE.generateFieldExpression(childExpr, fInfo, fN, inSelect);
+            }
         case fe@FieldExpression(fieldName, fInfo, child)
             if fe.dataType.getTypeCategory == TypeCategory.CLASS || fe.dataType.getTypeCategory == TypeCategory.STRUCT => {
-            val direction = if (fInfo.isReverse) "in" else "out"
+            val childExpr = translateOptChild(parent, child, inSelect);
+            val direction = if (fInfo.isReverse) AtlasEdgeDirection.IN else AtlasEdgeDirection.OUT
             val edgeLbl = gPersistenceBehavior.edgeLabel(fInfo)
-            val step = s"""$direction("$edgeLbl")"""
-            generateAndPrependExpr(child, inSelect, s"""$step""")
-        }
+            return GremlinExpressionFactory.INSTANCE.generateAdjacentVerticesExpression(childExpr, direction, edgeLbl)
+
+            }
         case fe@FieldExpression(fieldName, fInfo, child) if fInfo.traitName != null => {
+            val childExpr = translateOptChild(parent, child, inSelect);
             val direction = gPersistenceBehavior.instanceToTraitEdgeDirection
             val edgeLbl = gPersistenceBehavior.edgeLabel(fInfo)
-            val step = s"""$direction("$edgeLbl")"""
-            generateAndPrependExpr(child, inSelect, s"""$step""")
+            return GremlinExpressionFactory.INSTANCE.generateAdjacentVerticesExpression(childExpr, direction, edgeLbl)
+
         }
         case c@ComparisonExpression(symb, f@FieldExpression(fieldName, fInfo, ch), l) => {
-          return genHasPredicate(ch, fInfo, fieldName, inSelect, c, l)
+            val qualifiedPropertyName = s"${gPersistenceBehavior.fieldNameInVertex(fInfo.dataType, fInfo.attrInfo)}"
+
+            val childExpr = translateOptChild(parent, ch, inSelect)
+            val persistentExprValue : GroovyExpression = if(l.isInstanceOf[Literal[_]]) {
+                translateLiteralValue(fInfo.attrInfo.dataType, l.asInstanceOf[Literal[_]]);
+            }
+            else {
+                genQuery(null, l, inSelect);
+            }
+
+           return GremlinExpressionFactory.INSTANCE.generateHasExpression(gPersistenceBehavior, childExpr, qualifiedPropertyName, c.symbol, persistentExprValue, fInfo);
         }
         case fil@FilterExpression(child, condExpr) => {
-            s"${genQuery(child, inSelect)}.${genQuery(condExpr, inSelect)}"
+            val newParent = genQuery(parent, child, inSelect);
+            return genQuery(newParent, condExpr, inSelect);
         }
         case l@LogicalExpression(symb, children) => {
-            if(gPersistenceBehavior.getSupportedGremlinVersion() == GremlinVersion.THREE) {
-                if(children.length == 1) {
-                    //gremlin 3 treats one element expressions as 'false'.  Avoid
-                    //creating a boolean expression in this case.  Inline the expression
-                    //note: we can't simply omit it, since it will cause us to traverse the edge!
-                    //use 'where' instead
-                    var child : Expression = children.head;
-                    //if child is a back expression, that expression becomes an argument to where
-
-                    return s"""where(${genQuery(child, inSelect)})""";
-                }
-                else {
-                    // Gremlin 3 does not support _() syntax
-                    //
-                   return s"""$symb${children.map( genQuery(_, inSelect)).mkString("(", ",", ")")}"""
-                }
-           }
-           else {
-                s"""$symb${children.map("_()." + genQuery(_, inSelect)).mkString("(", ",", ")")}"""
-           }
+            val translatedChildren : java.util.List[GroovyExpression] = translateList(children, true, inSelect);
+            return GremlinExpressionFactory.INSTANCE.generateLogicalExpression(parent, symb, translatedChildren);
         }
         case sel@SelectExpression(child, selList) => {
               val m = groupSelectExpressionsBySrc(sel)
-              var srcNamesList: List[String] = List()
-              var srcExprsList: List[List[String]] = List()
+              var srcNamesList: java.util.List[LiteralExpression] = new ArrayList()
+              var srcExprsList: List[java.util.List[GroovyExpression]] = List()
               val it = m.iterator
+
               while (it.hasNext) {
                   val (src, selExprs) = it.next
-                  srcNamesList = srcNamesList :+ s""""$src""""
-                  srcExprsList = srcExprsList :+ selExprs.map { selExpr =>
-                      genQuery(selExpr, true)
-                   }
+                  srcNamesList.add(new LiteralExpression(src));
+                  val translatedSelExprs : java.util.List[GroovyExpression] = translateList(selExprs, false, true);
+                  srcExprsList = srcExprsList :+ translatedSelExprs
                }
-               val srcExprsStringList = srcExprsList.map {
-                    _.mkString("[", ",", "]")
+               val srcExprsStringList : java.util.List[GroovyExpression] = new ArrayList();
+               srcExprsList.foreach { it =>
+                    srcExprsStringList.add(new ListExpression(it));
                }
 
-               if(gPersistenceBehavior.getSupportedGremlinVersion() == GremlinVersion.TWO) {
-                    val srcNamesString = srcNamesList.mkString("[", ",", "]")
-                    val srcExprsString = srcExprsStringList.foldLeft("")(_ + "{" + _ + "}")
-                    s"${genQuery(child, inSelect)}.select($srcNamesString)$srcExprsString"
-               }
-               else {
-                    //gremlin 3
-                    val srcNamesString = srcNamesList.mkString("", ",", "")
-                    val srcExprsString = srcExprsStringList.foldLeft("")(_ + ".by({" + _ + "} as Function)")
-                    s"${genQuery(child, inSelect)}.select($srcNamesString)$srcExprsString"
-               }
+               val childExpr = genQuery(parent, child, inSelect)
+               return GremlinExpressionFactory.INSTANCE.generateSelectExpression(childExpr, srcNamesList, srcExprsStringList);
+
         }
         case loop@LoopExpression(input, loopExpr, t) => {
 
-            if(gPersistenceBehavior.getSupportedGremlinVersion() == GremlinVersion.TWO) {
-               val inputQry = genQuery(input, inSelect)
-               val loopingPathGExpr = genQuery(loopExpr, inSelect)
-               val loopGExpr = s"""loop("${input.asInstanceOf[AliasExpression].alias}")"""
-               val untilCriteria = if (t.isDefined) s"{it.loops < ${t.get.value}}" else "{it.path.contains(it.object)?false:true}"
-               val loopObjectGExpr = gPersistenceBehavior.loopObjectExpression(input.dataType)
-               val enablePathExpr = s".enablePath()"
-               s"""${inputQry}.${loopingPathGExpr}.${loopGExpr}${untilCriteria}${loopObjectGExpr}${enablePathExpr}"""
+            val times : Integer = if(t.isDefined) {
+                t.get.rawValue.asInstanceOf[Integer]
             }
             else {
-                //gremlin 3 - TODO - add support for circular lineage
-               val inputQry = genQuery(input, inSelect)
-               val repeatExpr = s"""repeat(__.${genQuery(loopExpr, inSelect)})"""
-               val optTimesExpr = if (t.isDefined) s".times(${t.get.value})" else ""
-               val emitExpr = s""".emit(${gPersistenceBehavior.loopObjectExpression(input.dataType)})"""
-
-               s"""${inputQry}.${repeatExpr}${optTimesExpr}${emitExpr}"""
-
+                null.asInstanceOf[Integer]
             }
+            val alias = input.asInstanceOf[AliasExpression].alias;
+            val inputQry = genQuery(parent, input, inSelect)
+            val translatedLoopExpr = genQuery(GremlinExpressionFactory.INSTANCE.getLoopExpressionParent(inputQry), loopExpr, inSelect);
+            return GremlinExpressionFactory.INSTANCE.generateLoopExpression(inputQry, gPersistenceBehavior, input.dataType, translatedLoopExpr, alias, times);
         }
         case BackReference(alias, _, _) => {
 
-            if (inSelect) {
-                gPersistenceBehavior.fieldPrefixInSelect()
-            }
-            else {
-                if(gPersistenceBehavior.getSupportedGremlinVersion() == GremlinVersion.TWO) {
-                    s"""back("$alias")"""
-                }
-                else {
-                    s"""select("$alias")"""
-                }
-            }
+            return GremlinExpressionFactory.INSTANCE.generateBackReferenceExpression(parent, inSelect, alias);
+        }
+        case AliasExpression(child, alias) => {
+            var childExpr = genQuery(parent, child, inSelect);
+            return GremlinExpressionFactory.INSTANCE.generateAliasExpression(childExpr, alias);
+        }
+        case isTraitLeafExpression(traitName, Some(clsExp)) => {
+            val label = gPersistenceBehavior.traitLabel(clsExp.dataType, traitName);
+            return GremlinExpressionFactory.INSTANCE.generateAdjacentVerticesExpression(parent, AtlasEdgeDirection.OUT, label);
+        }
+        case isTraitUnaryExpression(traitName, child) => {
+            val label = gPersistenceBehavior.traitLabel(child.dataType, traitName);
+            return GremlinExpressionFactory.INSTANCE.generateAdjacentVerticesExpression(parent, AtlasEdgeDirection.OUT, label);
         }
-        case AliasExpression(child, alias) => s"""${genQuery(child, inSelect)}.as("$alias")"""
-        case isTraitLeafExpression(traitName, Some(clsExp)) =>
-            s"""out("${gPersistenceBehavior.traitLabel(clsExp.dataType, traitName)}")"""
-        case isTraitUnaryExpression(traitName, child) =>
-            s"""out("${gPersistenceBehavior.traitLabel(child.dataType, traitName)}")"""
         case hasFieldLeafExpression(fieldName, clsExp) => clsExp match {
-            case None => s"""has("$fieldName")"""
+            case None => GremlinExpressionFactory.INSTANCE.generateUnaryHasExpression(parent, fieldName)
             case Some(x) => {
                 val fi = TypeUtils.resolveReference(clsExp.get.dataType, fieldName);
                 if(! fi.isDefined) {
-                    s"""has("$fieldName")"""
+                    return GremlinExpressionFactory.INSTANCE.generateUnaryHasExpression(parent, fieldName);
                 }
                 else {
-                    s"""has("${gPersistenceBehavior.fieldNameInVertex(fi.get.dataType, fi.get.attrInfo)}")"""
+                    val fName = gPersistenceBehavior.fieldNameInVertex(fi.get.dataType, fi.get.attrInfo)
+                    return GremlinExpressionFactory.INSTANCE.generateUnaryHasExpression(parent, fName);
                 }
             }
         }
         case hasFieldUnaryExpression(fieldName, child) =>
-            s"""${genQuery(child, inSelect)}.has("$fieldName")"""
-        case ArithmeticExpression(symb, left, right) => s"${genQuery(left, inSelect)} $symb ${genQuery(right, inSelect)}"
-        case l: Literal[_] => l.toString
-        case list: ListLiteral[_] => list.toString
+            val childExpr = genQuery(parent, child, inSelect);
+            return GremlinExpressionFactory.INSTANCE.generateUnaryHasExpression(childExpr, fieldName);
+        case ArithmeticExpression(symb, left, right) => {
+            val leftExpr = genQuery(parent, left, inSelect);
+            val rightExpr = genQuery(parent, right, inSelect);
+            return GremlinExpressionFactory.INSTANCE.generateArithmeticExpression(leftExpr, symb, rightExpr);
+        }
+        case l: Literal[_] =>  {
+
+            if(parent != null) {
+                return new org.apache.atlas.groovy.FieldExpression(parent, cleanStringLiteral(l));
+            }
+            return translateLiteralValue(l.dataType, l);
+        }
+        case list: ListLiteral[_] =>  {
+            val  values : java.util.List[GroovyExpression] = translateList(list.rawValue, false, inSelect);
+            return new ListExpression(values);
+        }
         case in@TraitInstanceExpression(child) => {
-          val direction = gPersistenceBehavior.traitToInstanceEdgeDirection
-          s"${genQuery(child, inSelect)}.$direction()"
+          val childExpr = genQuery(parent, child, inSelect);
+          val direction = gPersistenceBehavior.traitToInstanceEdgeDirection;
+          return GremlinExpressionFactory.INSTANCE.generateAdjacentVerticesExpression(childExpr, direction);
         }
         case in@InstanceExpression(child) => {
-          s"${genQuery(child, inSelect)}"
+            return genQuery(parent, child, inSelect);
         }
         case pe@PathExpression(child) => {
-            if(gPersistenceBehavior.getSupportedGremlinVersion() == GremlinVersion.TWO) {
-                 s"${genQuery(child, inSelect)}.path"
-            }
-            else {
-                s"${genQuery(child, inSelect)}.path()"
-            }
+            val childExpr = genQuery(parent, child, inSelect)
+            return GremlinExpressionFactory.INSTANCE.generatePathExpression(childExpr);
         }
         case order@OrderExpression(child, odr, asc) => {
           var orderby = ""
           var orderExpression = odr
-          if(odr.isInstanceOf[BackReference]) { 
-              orderExpression = odr.asInstanceOf[BackReference].reference 
+          if(odr.isInstanceOf[BackReference]) {
+              orderExpression = odr.asInstanceOf[BackReference].reference
           }
-          else if (odr.isInstanceOf[AliasExpression]) { 
+          else if (odr.isInstanceOf[AliasExpression]) {
               orderExpression = odr.asInstanceOf[AliasExpression].child
           }
-          val orderbyProperty = genQuery(orderExpression, false)
-          if(gPersistenceBehavior.getSupportedGremlinVersion() == GremlinVersion.TWO) {
-
-              val bProperty = s"it.b.$orderbyProperty"
-              val aProperty = s"it.a.$orderbyProperty"
-              val aCondition = s"($aProperty != null ? $aProperty.toLowerCase(): $aProperty)"
-              val bCondition = s"($bProperty != null ? $bProperty.toLowerCase(): $bProperty)"
-              orderby = asc  match {
-                    //builds a closure comparison function based on provided order by clause in DSL. This will be used to sort the results by gremlin order pipe.
-                    //Ordering is case insensitive.
-                  case false=> s"order{$bCondition <=> $aCondition}"//descending
-                  case _ => s"order{$aCondition <=> $bCondition}"
-                }
-          }
-          else {
-               val orderbyProperty = genQuery(orderExpression, true);
-               val aPropertyExpr = gremlin3ToLowerCase("a");
-               val bPropertyExpr = gremlin3ToLowerCase("b");
-               
-               orderby = asc match {
-                   //builds a closure comparison function based on provided order by clause in DSL. This will be used to sort the results by gremlin order pipe.
-                  //Ordering is case insensitive.
-                  case false=> s"""order().by({$orderbyProperty'}, { a,b -> $bPropertyExpr <=> $aPropertyExpr })"""
-                  case _ => s"""order().by({$orderbyProperty},{ a,b -> $aPropertyExpr <=> $bPropertyExpr })"""
 
-                }
+          val childExpr = genQuery(parent, child, inSelect);
+          var orderByParents : java.util.List[GroovyExpression] = GremlinExpressionFactory.INSTANCE.getOrderFieldParents();
+
+          val translatedParents : java.util.List[GroovyExpression] = new ArrayList[GroovyExpression]();
+          var translatedOrderParents = orderByParents.foreach { it =>
+                 translatedParents.add(genQuery(it, orderExpression, false));
           }
-          s"""${genQuery(child, inSelect)}.$orderby"""
+          return GremlinExpressionFactory.INSTANCE.generateOrderByExpression(childExpr, translatedParents,asc);
+
         }
         case limitOffset@LimitExpression(child, limit, offset) => {
-            if(gPersistenceBehavior.getSupportedGremlinVersion() == GremlinVersion.TWO) {
-                val totalResultRows = limit.value + offset.value
-                s"""${genQuery(child, inSelect)} [$offset..<$totalResultRows]"""
-            }
-            else {
-                val totalResultRows = limit.value + offset.value
-                s"""${genQuery(child, inSelect)}.range($offset,$totalResultRows)"""
-            }
+            val childExpr = genQuery(parent, child, inSelect);
+            val totalResultRows = limit.value + offset.value;
+            return GremlinExpressionFactory.INSTANCE.generateLimitExpression(childExpr, offset.value, totalResultRows);
         }
         case x => throw new GremlinTranslationException(x, "expression not yet supported")
     }
 
-    def gremlin3ToLowerCase(varName : String) : String = {
-            s"""($varName != null ? $varName.toString().toLowerCase() : null)"""
-    }
-        
-    def genPropertyAccessExpr(e: Option[Expression], fInfo : FieldInfo, quotedPropertyName: String, inSelect: Boolean) : String = {
-
-        if(gPersistenceBehavior.getSupportedGremlinVersion() == GremlinVersion.TWO) {
-            generateAndPrependExpr(e, inSelect, s"""$quotedPropertyName""")
-        }
-        else {
-            val attrInfo : AttributeInfo = fInfo.attrInfo;
-            val attrType : IDataType[_] = attrInfo.dataType;
-            if(inSelect) {
-                val expr = generateAndPrependExpr(e, inSelect, s"""property($quotedPropertyName).orElse(null)""");
-                return gPersistenceBehavior.generatePersisentToLogicalConversionExpression(expr, attrType);
-            }
-            else {
-                val unmapped = s"""values($quotedPropertyName)"""
-                val expr = if(gPersistenceBehavior.isPropertyValueConversionNeeded(attrType)) {
-                    val conversionFunction = gPersistenceBehavior.generatePersisentToLogicalConversionExpression(s"""it.get()""", attrType);
-                    s"""$unmapped.map{ $conversionFunction }"""
-                 }
-                 else {
-                    unmapped
-                 }
-                 generateAndPrependExpr(e, inSelect, expr)
-            }
+    def translateList(exprs : List[Expressions.Expression], isAnonymousTraveral: Boolean, inSelect : Boolean) : java.util.List[GroovyExpression] = {
+        var parent = if(isAnonymousTraveral) {GremlinExpressionFactory.INSTANCE.getAnonymousTraversalExpression() } else { null }
+        var result : java.util.List[GroovyExpression] = new java.util.ArrayList(exprs.size);
+        exprs.foreach { it =>
+            result.add(genQuery(parent, it, inSelect));
         }
+        return result;
     }
 
-    def generateAndPrependExpr(e1: Option[Expression], inSelect: Boolean, e2: String) : String = e1 match {
+    def translateOptChild(parent : GroovyExpression, child : Option[Expressions.Expression] , inSelect: Boolean) : GroovyExpression = child match {
 
-        case Some(x) => s"""${genQuery(x, inSelect)}.$e2"""
-        case None => e2
+        case Some(x) => genQuery(parent, x, inSelect)
+        case None => parent
     }
 
-    def genHasPredicate(e: Option[Expression], fInfo : FieldInfo, fieldName: String, inSelect: Boolean, c: ComparisonExpression, expr: Expression) : String = {
+    def translateLiteralValue(dataType: IDataType[_], l: Literal[_]): GroovyExpression = {
+
 
-       val qualifiedPropertyName = s"${gPersistenceBehavior.fieldNameInVertex(fInfo.dataType, fInfo.attrInfo)}"
-       val persistentExprValue = translateValueToPersistentForm(fInfo, expr);
-       if(gPersistenceBehavior.getSupportedGremlinVersion() == GremlinVersion.TWO) {
-            return generateAndPrependExpr(e, inSelect, s"""has("${qualifiedPropertyName}", ${gPersistenceBehavior.gremlinCompOp(c)}, $persistentExprValue)""");
+      if (dataType == DataTypes.DATE_TYPE) {
+           try {
+               //Accepts both date, datetime formats
+               val dateStr = cleanStringLiteral(l)
+               val dateVal = ISODateTimeFormat.dateOptionalTimeParser().parseDateTime(dateStr).getMillis
+               return new LiteralExpression(dateVal)
+            } catch {
+                  case pe: java.text.ParseException =>
+                       throw new GremlinTranslationException(l,
+                                   "Date format " + l + " not supported. Should be of the format " +
+                                   TypeSystem.getInstance().getDateFormat.toPattern);
+            }
+       }
+       else if(dataType == DataTypes.BYTE_TYPE) {
+           //cast needed, otherwise get class cast exception when trying to compare, since the
+           //persist value is assumed to be an Integer
+           return new CastExpression(new LiteralExpression(Byte.valueOf(s"""${l}"""), true),"byte");
+       }
+       else if(dataType == DataTypes.INT_TYPE) {
+           return new LiteralExpression(Integer.valueOf(s"""${l}"""));
+       }
+       else if(dataType == DataTypes.BOOLEAN_TYPE) {
+           return new LiteralExpression(Boolean.valueOf(s"""${l}"""));
+       }
+       else if(dataType == DataTypes.SHORT_TYPE) {
+           return new CastExpression(new LiteralExpression(Short.valueOf(s"""${l}"""), true),"short");
+       }
+       else if(dataType == DataTypes.LONG_TYPE) {
+           return new LiteralExpression(Long.valueOf(s"""${l}"""), true);
+       }
+       else if(dataType == DataTypes.FLOAT_TYPE) {
+           return new LiteralExpression(Float.valueOf(s"""${l}"""), true);
+       }
+       else if(dataType == DataTypes.DOUBLE_TYPE) {
+           return new LiteralExpression(Double.valueOf(s"""${l}"""), true);
+       }
+       else if(dataType == DataTypes.STRING_TYPE) {
+           return new LiteralExpression(cleanStringLiteral(l));
        }
        else {
-           val attrInfo : AttributeInfo = fInfo.attrInfo;
-            val attrType : IDataType[_] = attrInfo.dataType;
-            if(gPersistenceBehavior.isPropertyValueConversionNeeded(attrType)) {
-                //for some types, the logical value cannot be stored directly in the underlying graph,
-                //and conversion logic is needed to convert the persistent form of the value
-                //to the actual value.  In cases like this, we generate a conversion expression to
-                //do this conversion and use the filter step to perform the comparsion in the gremlin query
-                val vertexExpr = "((Vertex)it.get())";
-                val conversionExpr = gPersistenceBehavior.generatePersisentToLogicalConversionExpression(s"""$vertexExpr.value("$qualifiedPropertyName")""", attrType);
-                return generateAndPrependExpr(e, inSelect, s"""filter{$vertexExpr.property("$qualifiedPropertyName").isPresent() && $conversionExpr ${gPersistenceBehavior.gremlinPrimitiveOp(c)} $persistentExprValue}""");
-            }
-            else {
-                return generateAndPrependExpr(e, inSelect, s"""has("${qualifiedPropertyName}", ${gPersistenceBehavior.gremlinCompOp(c)}($persistentExprValue))""");
-            }
-        }
-       
+           return new LiteralExpression(l.rawValue);
+       }
     }
 
-    def translateValueToPersistentForm(fInfo: FieldInfo, l: Expression): Any =  {
-    
-      val dataType = fInfo.attrInfo.dataType;
-      val QUOTE = "\"";
-      
-       if (dataType == DataTypes.DATE_TYPE) {
-            try {
-                //Accepts both date, datetime formats
-                val dateStr = l.toString.stripPrefix(QUOTE).stripSuffix(QUOTE)
-                val dateVal = ISODateTimeFormat.dateOptionalTimeParser().parseDateTime(dateStr).getMillis
-                return dateVal
-             } catch {
-                   case pe: java.text.ParseException =>
-                        throw new GremlinTranslationException(l,
-                                    "Date format " + l + " not supported. Should be of the format " +
-                                    TypeSystem.getInstance().getDateFormat.toPattern);
-             }
-        }
-        else if(dataType == DataTypes.BYTE_TYPE) {
-            //cast needed, otherwise get class cast exception when trying to compare, since the 
-            //persist value is assumed to be an Integer
-            return s"""(byte)$l"""
-        }
-        else if(dataType == DataTypes.SHORT_TYPE) {
-            return s"""(short)$l"""
-        }
-        else if(dataType == DataTypes.LONG_TYPE) {
-            return s"""${l}L"""
-        }
-        else if(dataType == DataTypes.FLOAT_TYPE) {
-            return s"""${l}f"""
-        }
-        else if(dataType == DataTypes.DOUBLE_TYPE) {
-            return s"""${l}d"""
-        }
-        else if(dataType == DataTypes.STRING_TYPE) {
-            return string(escape(l.toString.stripPrefix(QUOTE).stripSuffix(QUOTE)));
-        } 
-        else {
-            return l
-        }
-    }
-    
     def genFullQuery(expr: Expression, hasSelect: Boolean): String = {
-        
-        var q = genQuery(expr, false)
+
+        var q : GroovyExpression = new FunctionCallExpression(new IdentifierExpression("g"),"V");
+
+
         val debug:Boolean = false
         if(gPersistenceBehavior.addGraphVertexPrefix(preStatements)) {
-             q = s"g.V()${gPersistenceBehavior.initialQueryCondition}.$q"
+            q = gPersistenceBehavior.addInitialQueryCondition(q);
         }
 
-        q = s"$q.toList()${gPersistenceBehavior.getGraph().getOutputTransformationPredicate(hasSelect, expr.isInstanceOf[PathExpression])}"
-      
+        q = genQuery(q, expr, false)
+
+        q = new FunctionCallExpression(q, "toList");
+        q = gPersistenceBehavior.getGraph().addOutputTransformationPredicate(q, hasSelect, expr.isInstanceOf[PathExpression]);
+
+        var overallExpression = new CodeBlockExpression();
+        overallExpression.addStatements(preStatements);
+        overallExpression.addStatement(q)
+        overallExpression.addStatements(postStatements);
+
+        var qryStr = generateGremlin(overallExpression);
+
         if(debug) {
-          println(" query " + q)
+          println(" query " + qryStr)
         }
-       
-        q = (preStatements ++ Seq(q) ++ postStatements).mkString("", ";", "")
-
-        /*
-         * the L:{} represents a groovy code block; the label is needed
-         * to distinguish it from a groovy closure.
-         */
-        s"L:{$q}"
-        
+
+        qryStr;
+
+    }
+
+    def generateGremlin(expr: GroovyExpression) : String = {
+         val ctx : GroovyGenerationContext = new GroovyGenerationContext();
+         ctx.setParametersAllowed(false);
+         expr.generateGroovy(ctx);
+         return ctx.getQuery;
     }
+
     def translate(): GremlinQuery = {
         var e1 = expr.transformUp(wrapAndRule)
 
@@ -570,9 +537,9 @@ class GremlinTranslator(expr: Expression,
         e1 = e1.transformUp(addAliasToLoopInput())
         e1 = e1.transformUp(instanceClauseToTop(e1))
         e1 = e1.transformUp(traitClauseWithInstanceForTop(e1))
-    
+
         //Following code extracts the select expressions from expression tree.
-    
+
         val se = SelectExpressionHelper.extractSelectExpression(e1)
         if (se.isDefined) {
           val rMap = buildResultMapping(se.get)


Mime
View raw message