You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@atlas.apache.org by ma...@apache.org on 2017/11/05 20:31:57 UTC
[35/40] atlas git commit: ATLAS-2251: Remove TypeSystem and related
implementation, to avoid unncessary duplicate of type details in cache
http://git-wip-us.apache.org/repos/asf/atlas/blob/0877e47c/repository/src/main/java/org/apache/atlas/gremlin/optimizer/ExpandOrsOptimization.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/gremlin/optimizer/ExpandOrsOptimization.java b/repository/src/main/java/org/apache/atlas/gremlin/optimizer/ExpandOrsOptimization.java
deleted file mode 100644
index a48a007..0000000
--- a/repository/src/main/java/org/apache/atlas/gremlin/optimizer/ExpandOrsOptimization.java
+++ /dev/null
@@ -1,588 +0,0 @@
-/**
- * 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.atlas.gremlin.optimizer;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-
-import org.apache.atlas.gremlin.GremlinExpressionFactory;
-import org.apache.atlas.groovy.AbstractFunctionExpression;
-import org.apache.atlas.groovy.ClosureExpression;
-import org.apache.atlas.groovy.FunctionCallExpression;
-import org.apache.atlas.groovy.GroovyExpression;
-import org.apache.atlas.groovy.LiteralExpression;
-import org.apache.atlas.groovy.StatementListExpression;
-import org.apache.atlas.groovy.TraversalStepType;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.collect.Lists;
-
-
-
-/**
- * Optimization that removes 'or' expressions from a graph traversal when possible
- * and replaces them with separate calls that are combined using a logical union operation.
- * Unfortunately, Titan does not use indices when executing the child graph traversals associated
- * with an 'or' call. In order to make the index be used, we split queries with
- * or expressions into multiple queries. These queries are executed individually,
- * using indices, and then the results are combined back together. Here is a
- * simple example to illustrate this:
- *
- * <h4>Original Query</h4>
- *
- * <pre>
- * g.V().or(has('name','Fred'),has('age','17'))
- * </pre>
- *
- *<h4>Optimized Query</h4>
- *
- * <pre>
- * def r = [] as Set;
- * g.V().has('name','Fred').fill(r);
- * g.V().has('age','17').fill(r);
- * r;
- * </pre>
- *
- * Here, we introduce an intermediate variable "r" which is declared as a Set. The Set is performing
- * the union for us. If there are vertices that happen to both have "Fred" as the name and "17" as the age,
- * the Set will prevent the second query execution from adding a duplicate vertex to the result. Recall that
- * in Groovy scripts, the last expression is the one that will be returned back to the caller. We refer to
- * that expression is the "result expression". For this example, the result expression is simply "r", which
- * contains the vertices that matched the query.
- * <p/>
- * If the query does any kind of transformation of the vertices to produce the query result, that needs
- * to be done in the result expression. To understand why that is, let's take a look at another example:
- *
- * <h4>Original Query</h4>
- *
- * <pre>
- * g.V().or(has('name','Fred'),has('age','17')).as('person').select('person').by('gender')
- * </pre>
- *
- * <h4>Incorrect Optimized Query</h4>
- *
- * <pre>
- * def r = [] as Set;
- * g.V().has('name','Fred').as('person').select('person').by('gender').fill(r)
- * g.V().has('age','17').as('person').select('person').by('gender').fill(r)
- * r;
- * </pre>
- *
- * The problem with this query is that now 'r' contains Strings (the gender of the person). Suppose
- * that there is one person named Fred and there are 3 people whose age is 17 (let's say Fred's age is 16).
- * The original query would have produced 4 rows, one corresponding to each of those people. The new
- * query would produce at most 2 rows - one for 'male' and one for 'female'. This is happening because
- * we are now performing the union on the Strings, not on the vertices. To fix this, we need to split
- * the original query and put the end portion into the result expression:
- *
- * <h4>Correct Optimized Query</h4>
- *
- * <pre>
- * def r = [] as Set;
- * g.V().has('name','Fred').fill(r)
- * g.V().has('age','17').fill(r)
- * __.inject(r as Object[]).as('person').select('person').by('gender')
- * </pre>
- *
- * The logic for doing this splitting is described in more detail in
- * {@link #moveTransformationsToResultExpression(GroovyExpression, OptimizationContext)}.
- * <p/>
- * There is one more problematic case that this optimizer is able to handle. Let's look at the following example:
- *
- * <h4>Original Query</h4>
- *
- * <pre>
- * g.V().or(has('type','Person'),has('superType','Person')).as('x').has('qualifiedName','Fred').as('y').select('x','y').by('name').by('name')
- * </pre>
- *
- * Queries of this form appear often when translating DSL queries.
- *
- * If we were to optimize this query using the logic described above, we would get something like this:
- *
- * <h4>Incorrect Optimized Query</h4>
- *
- * <pre>
- * def r = [] as Set;
- * g.V().has('type','Person').fill(r);
- * g.V().has('superType','Person').fill(r);
- * __.inject(r as Object[]).as('x').has('qualifiedName','Fred').as('y').select('x','y');
- * </pre>
- *
- * While not strictly incorrect, this query will not perform well since the index on qualifiedName will
- * not be used. In order for that index to be used, the 'has' expression needs to be part of the original
- * query. However, if we do that alone, the query will be broken, since the select
- * will now refer to an undefined label:
- *
- * <h4>Incorrect Optimized Query</h4>
- *
- * <pre>
- * def r = [] as Set;
- * g.V().has('type','Person').as('x').has('qualifiedName','Fred').fill(r);
- * g.V().has('superType','Person').as('x').has('qualifiedName','Fred').fill(r);
- * __.inject(r as Object[]).as('y').select('x','y')
- * </pre>
- *
- * To fix this, we need to save the values of the aliased vertices in the original
- * query, and create labels in the result expression that refer to them. We do this
- * as follows:
- *
- * <h4>Correct Optimized Query</h4>
- *
- * <pre>
- * def r = [] as Set;
- * g.V().has('type','Person').as('x').has('qualifiedName','Fred').as('y').select('x','y').fill(r);
- * g.V().has('superType','Person').as('x').has('qualifiedName','Fred').select('x','y').fill(r);
- * __.inject(r as Object[]).as('__tmp').map({((Map)it.get()).get('x')}).as('x').select('__tmp').map({((Map)it.get()).get('x')}).as('y').select('x','y').by('name').by('name')
- * </pre>
- *
- * This is not pretty, but is the best solution we've found so far for supporting expressions that contain aliases in this optimization.
- * What ends up happening is that r gets populated with alias->Vertex maps. In the result expression, we make 'x' point
- * to a step where the value in the traverser is the vertex for 'x', and we do the same thing for y. The <code>select('_tmp')</code> step in the middle restores the value of
- * the traverser back to the map.
- * <p/>
- * The one known issue with the alias rearrangement is that it breaks loop expressions. As a result, expressions containing loops are currently excluded
- * from this optimization.
- *
- * ExpandOrsOptimization expands the entire expression tree recursively, so it is not invoked
- * recursively by GremlinQueryOptimizer.
- *
- */
-public class ExpandOrsOptimization implements GremlinOptimization {
-
- private static final Logger logger_ = LoggerFactory.getLogger(ExpandOrsOptimization.class);
-
- private final GremlinExpressionFactory factory;
-
- public ExpandOrsOptimization(GremlinExpressionFactory factory) {
- this.factory = factory;
- }
-
- @Override
- public boolean appliesTo(GroovyExpression expr, OptimizationContext contxt) {
-
- ExpressionFinder finder = new ExpressionFinder(IsOr.INSTANCE);
- GremlinQueryOptimizer.visitCallHierarchy(expr, finder);
- return finder.isExpressionFound();
- }
-
- @Override
- public GroovyExpression apply(GroovyExpression expr, OptimizationContext context) {
-
- setupRangeOptimization(expr, context);
- GroovyExpression traveralExpression = moveTransformationsToResultExpression(expr, context);
-
- FunctionGenerator functionGenerator = new FunctionGenerator(factory, context);
- GremlinQueryOptimizer.visitCallHierarchy(traveralExpression, functionGenerator);
- traveralExpression = functionGenerator.getNewRootExpression();
- List<GroovyExpression> bodyExpressions = expandOrs(traveralExpression, context);
-
-
- //Adds a statement to define the result variable 'v' in the
- //groovy script. The variable is declared as a Set. The type
- //of the objects in the Set depend on the number of aliases in the Groovy
- // expression:
- // - 0 or 1 alias : Vertex
- // - multiple aliases: Map<String,Vertex>
- StatementListExpression result = new StatementListExpression();
- context.prependStatement(context.getDefineResultVariableStmt());
-
-
- for (GroovyExpression bodyExpression : bodyExpressions) {
- result.addStatement(bodyExpression);
- }
- result.addStatement(context.getResultExpression());
- return result;
- }
-
- private void setupRangeOptimization(GroovyExpression expr, OptimizationContext context) {
-
- // Find any range expressions in the expression tree.
- RangeFinder rangeFinder = new RangeFinder(factory);
- GremlinQueryOptimizer.visitCallHierarchy(expr, rangeFinder);
- List<AbstractFunctionExpression> rangeExpressions = rangeFinder.getRangeExpressions();
- if (rangeExpressions.size() == 1) {
- OrderFinder orderFinder = new OrderFinder(factory);
- GremlinQueryOptimizer.visitCallHierarchy(expr, orderFinder);
- if (!orderFinder.hasOrderExpression()) {
- // If there is one range expression and no order expression in the unoptimized gremlin,
- // save the range parameters to use for adding a range expression to
- // each expanded "or" expression result, such that it will only contain the specified range of vertices.
- // For now, apply this optimization only if the range start index is zero.
- AbstractFunctionExpression rangeExpression = rangeExpressions.get(0);
- int[] rangeParameters = factory.getRangeParameters(rangeExpression);
- if (rangeParameters[0] == 0) {
- context.setRangeExpression(rangeExpression);
- }
- }
- }
- }
-
- private GroovyExpression moveTransformationsToResultExpression(GroovyExpression expr, OptimizationContext context) {
- GroovyExpression traveralExpression = expr;
-
- // Determine the 'split point'. This is the expression that will become
- // the deepest function call in the result expression. If a split
- // point is found, its caller is changed. The new caller is
- // set to the graph traversal expression in the result expression.
- // The original caller becomes the new traversal expression that
- // will be carried through the rest of the 'or' expansion processing.
- //
- // Example: g.V().has('x').as('x').select('x')
- // Here, select('x') is the split expression
- // so :
- // 1) the result expression in OptimizationContext becomes [base result expression].select('x')
- // 2) we return g.V().has('x').as('x')
-
- SplitPointFinder finder = new SplitPointFinder(factory);
- GremlinQueryOptimizer.visitCallHierarchy(traveralExpression, finder);
- AbstractFunctionExpression splitPoint = finder.getSplitPoint();
-
-
- List<LiteralExpression> aliases = new ArrayList<>();
-
- //If we're not splitting the query, there is no need to save/restore
- //the aliases.
- if(splitPoint != null) {
-
- traveralExpression = splitPoint.getCaller();
-
- AliasFinder aliasFinder = new AliasFinder();
- GremlinQueryOptimizer.visitCallHierarchy(traveralExpression, aliasFinder);
- aliases.addAll(aliasFinder.getAliases());
- if(aliasFinder.isFinalAliasNeeded()) {
- //The last alias in the expression does not capture the final vertex in the traverser,
- //so we need to create an alias to record that.
- traveralExpression = factory.generateAliasExpression(traveralExpression, context.getFinalAliasName());
- aliases.add(new LiteralExpression(context.getFinalAliasName()));
- }
-
- GroovyExpression resultExpr = getBaseResultExpression(context, aliases);
- splitPoint.setCaller(resultExpr);
- expr = removeMapFromPathsIfNeeded(expr, aliases);
- context.setResultExpression(expr);
- }
-
- //Add expression(s) to the end of the traversal expression to add the vertices
- //that were found into the intermediate variable ('r')
- traveralExpression = addCallToUpdateResultVariable(traveralExpression, aliases, context);
- return traveralExpression;
- }
-
- private GroovyExpression removeMapFromPathsIfNeeded(GroovyExpression expr, List<LiteralExpression> aliases) {
- if(aliases.size() > 0 && factory.isSelectGeneratesMap(aliases.size())) {
- RepeatExpressionFinder repeatExprFinder = new RepeatExpressionFinder(factory);
- GremlinQueryOptimizer.visitCallHierarchy(expr, repeatExprFinder);
- boolean hasRepeat = repeatExprFinder.isRepeatExpressionFound();
-
- PathExpressionFinder pathExprFinder = new PathExpressionFinder();
- GremlinQueryOptimizer.visitCallHierarchy(expr, pathExprFinder);
- boolean hasPath = pathExprFinder.isPathExpressionFound();
- if(! hasRepeat && hasPath) {
- //the path will now start with the map that we added. That is an artifact
- //of the optimization process and must be removed.
- if(expr.getType() != TraversalStepType.END && expr.getType() != TraversalStepType.NONE) {
- //we're still in the pipeline, need to execute the query before we can
- //modify the result
- expr = factory.generateToListExpression(expr);
- }
- expr = factory.removeExtraMapFromPathInResult(expr);
- }
-
- }
- return expr;
- }
-
- /**
- * This method adds steps to the end of the initial traversal to add the vertices
- * that were found into an intermediate variable (defined as a Set). If there is one alias,
- * this set will contain the vertices associated with that Alias. If there are multiple
- * aliases, the values in the set will be alias->vertex maps that have the vertex
- * associated with the alias for each result.
-
- * @param expr
- * @param aliasNames
- * @param context
- * @return
- */
- private GroovyExpression addCallToUpdateResultVariable(GroovyExpression expr,List<LiteralExpression> aliasNames, OptimizationContext context) {
-
- GroovyExpression result = expr;
- // If there is one range expression in the unoptimized gremlin,
- // add a range expression here so that the intermediate variable will only contain
- // the specified range of vertices.
- AbstractFunctionExpression rangeExpression = context.getRangeExpression();
- if (rangeExpression != null) {
- int[] rangeParameters = factory.getRangeParameters(rangeExpression);
- result = factory.generateRangeExpression(result, rangeParameters[0], rangeParameters[1]);
- }
- if( ! aliasNames.isEmpty()) {
- result = factory.generateSelectExpression(result, aliasNames, Collections.<GroovyExpression>emptyList());
- }
- return factory.generateFillExpression(result, context.getResultVariable());
- }
-
- /**
- * Recursively traverses the given expression, expanding or expressions
- * wherever they are found.
- *
- * @param expr
- * @param context
- * @return expressions that should be unioned together to get the query result
- */
- private List<GroovyExpression> expandOrs(GroovyExpression expr, OptimizationContext context) {
-
- if (GremlinQueryOptimizer.isOrExpression(expr)) {
- return expandOrFunction(expr, context);
- }
- return processOtherExpression(expr, context);
- }
-
- /**
- * This method takes an 'or' expression and expands it into multiple expressions.
- *
- * For example:
- *
- * g.V().or(has('x'),has('y')
- *
- * is expanded to:
- *
- * g.V().has('x')
- * g.V().has('y')
- *
- * There are certain cases where it is not safe to move an expression out
- * of the 'or'. For example, in the expression
- *
- * g.V().or(has('x').out('y'),has('z'))
- *
- * has('x').out('y') cannot be moved out of the 'or', since it changes the value of the traverser.
- *
- * At this time, the ExpandOrsOptimizer is not able to handle this scenario, so we don't remove
- * that expression. In cases like this, a final expression is created that ors together
- * all of the expressions that could not be extracted. In this case that would be:
- *
- * g.V().has('z')
- * g.V().or(has('y').out('z'))
- *
- * This processing is done recursively.
- *
- *
- * @param expr
- * @param context
- * @return the expressions that should be unioned together to get the query result
- */
- private List<GroovyExpression> expandOrFunction(GroovyExpression expr, OptimizationContext context) {
- FunctionCallExpression functionCall = (FunctionCallExpression) expr;
- GroovyExpression caller = functionCall.getCaller();
- List<GroovyExpression> updatedCallers = null;
- if (caller != null) {
- updatedCallers = expandOrs(caller, context);
- } else {
- updatedCallers = Collections.singletonList(null);
- }
- UpdatedExpressions newArguments = getUpdatedChildren(functionCall.getArguments(), context);
- List<GroovyExpression> allUpdatedArguments = new ArrayList<>();
- for (List<GroovyExpression> exprs : newArguments.getUpdatedChildren()) {
- allUpdatedArguments.addAll(exprs);
- }
- List<AbstractFunctionExpression> extractableArguments = new ArrayList<>();
- List<GroovyExpression> nonExtractableArguments = new ArrayList<>();
- for (GroovyExpression argument : allUpdatedArguments) {
-
- if (GremlinQueryOptimizer.isExtractable(argument)) {
- extractableArguments.add((AbstractFunctionExpression) argument);
- } else {
- logger_.warn("Found non-extractable argument '{}; in the 'or' expression '{}'",argument.toString(), expr.toString());
- nonExtractableArguments.add(argument);
- }
- }
-
- List<GroovyExpression> result = new ArrayList<>();
- for (GroovyExpression updatedCaller : updatedCallers) {
-
- for (AbstractFunctionExpression arg : extractableArguments) {
- GroovyExpression updated = GremlinQueryOptimizer.copyWithNewLeafNode(arg, updatedCaller);
- result.add(updated);
- }
- if (!nonExtractableArguments.isEmpty()) {
- result.add(factory.generateLogicalExpression(updatedCaller, "or", nonExtractableArguments));
- }
-
- }
- return result;
- }
-
- private UpdatedExpressions getUpdatedChildren(List<GroovyExpression> children, OptimizationContext context) {
- List<List<GroovyExpression>> updatedChildren = new ArrayList<>();
- boolean changed = false;
- for (GroovyExpression child : children) {
- List<GroovyExpression> childChoices = expandOrs(child, context);
- if (childChoices.size() != 1 || childChoices.iterator().next() != child) {
- changed = true;
- }
- updatedChildren.add(childChoices);
- }
- return new UpdatedExpressions(changed, updatedChildren);
- }
-
- private UpdatedExpressions getUpdatedChildren(GroovyExpression expr, OptimizationContext context) {
- return getUpdatedChildren(expr.getChildren(), context);
- }
-
- /**
- * This is called when we encounter an expression that is not an "or", for example an "and" expressio. For these
- * expressions, we process the children and create copies with the cartesian product of the updated
- * arguments.
- *
- * Example:
- *
- * g.V().and(or(has('x),has('y'), or(has('a'),has('b')))
- *
- * Here, we have an "and" expression with two children:
- *
- * 1) or(has('x),has('y')
- * 2) or(has('a'),has('b'))
- *
- * We first process these children. They each yield 2 expressions:
- *
- * 1 -> [ has('x'), has('y') ]
- * 2 -> [ has('a'), has('b') ]
- *
- * The cartesian product of these gives this:
- *
- * [ has('x'), has('a') ]
- * [ has('x'), has('b') ]
- * [ has('y'), has('a') ]
- * [ has('y'), has('b') ]
- *
- * So the overall result is:
- *
- * g.V().and(has('x'), has('a'))
- * g.V().and(has('x'), has('b'))
- * g.V().and(has('y'), has('a'))
- * g.V().and(has('y'), has('b'))
- *
- *
- * @param source
- * @param context
- * @return expressions that should be unioned together to get the query result
- */
- private List<GroovyExpression> processOtherExpression(GroovyExpression source, OptimizationContext context) {
- UpdatedExpressions updatedChildren = getUpdatedChildren(source, context);
- if (!updatedChildren.hasChanges()) {
- return Collections.singletonList(source);
- }
- List<GroovyExpression> result = new ArrayList<GroovyExpression>();
-
- //The updated children list we get back has the possible values for each child
- //in the expression. We compute a cartesian product to get all possible
- //combinations of child values.
- List<List<GroovyExpression>> updateChildLists = Lists.cartesianProduct(updatedChildren.getUpdatedChildren());
-
- for (List<GroovyExpression> updatedChildList : updateChildLists) {
- result.add(source.copy(updatedChildList));
- }
- return result;
- }
-
- @Override
- public boolean isApplyRecursively() {
- return false;
- }
-
- /**
- *
- * This method creates a base result expression that recreates the state of the
- * graph traverser at start of the result expression to what it would have been
- * if we had been executing one Gremlin query (instead of many and doing a union).
- *
- * To do this, we start with an anonymous graph traversal that will iterate
- * through the values in the intermediate Set that was created. We then need
- * to set things up so that the aliases that were in the original gremlin query
- * refer to steps with the correct traverser value.
- *
- * The way we do this depends on the number of aliases. If there are 0 or 1 alias,
- * the intermediate variable already contains Vertices, so we just create the alias.
- *
- * If there are multiple aliases, the intermediate variable contains a String->Vertex
- * map. We first create a temporary alias that refers to that map. For each alias,
- * we use a MapStep to map the map to the Vertex for that alias. We then add back
- * the alias, making it refer to the MapStep. Between the alias restorations, we restore the
- * traverser object back to the map.
- *
- * @param context
- * @param aliases
- * @return
- */
- private GroovyExpression getBaseResultExpression(OptimizationContext context,
- List<LiteralExpression> aliases) {
-
- //Start with an anonymous traversal that gets its objects from the intermediate result variable.
- GroovyExpression parent = factory.generateSeededTraversalExpresssion(aliases.size() > 1, context.getResultVariable());
-
- if(aliases.isEmpty()) {
- return parent;
- }
-
- //The expression we will return.
- GroovyExpression result = parent;
-
- //We use a temporary alias to save/restore the original value of the traverser
- //at the start of the query. We do this so we can set the value of the traverser
- //back to being the map after we retrieve each alias. If there is only one
- //alias, the save/restore is not needed, so there is no need to create this alias.
- if(aliases.size() > 1) {
-
- result = factory.generateAliasExpression(result, context.getTempAliasName());
- }
-
- Iterator<LiteralExpression> it = aliases.iterator();
- while(it.hasNext()) {
- LiteralExpression curAlias = it.next();
- //A map is only generated by Gremlin when there is more than one alias. When there is only one
- //alias, the intermediate variable will directly contain the vertices.`
- if(factory.isSelectGeneratesMap(aliases.size())) {
- //Since there is more than one alias, the current traverser object is an alias->vertex
- //map. We use a MapStep to map that map to the Vertex for the current alias. This sets
- //the current traverser object to that Vertex. We do this by defining the closure we
- //pass to the MapStep call [map].get(aliasName) where [map] is the expression
- //that refers to the map.
-
- GroovyExpression rowMapExpr = factory.getCurrentTraverserObject(factory.getClosureArgumentValue());
- GroovyExpression getExpr = factory.generateGetSelectedValueExpression(curAlias, rowMapExpr);
- result = factory.generateMapExpression(result, new ClosureExpression(getExpr));
- }
-
- //Create alias that points to the previous step. The traverser value at that step
- //is the Vertex associated with this alias.
- result = factory.generateAliasExpression(result, curAlias.getValue().toString());
- if(it.hasNext()) {
- //Restore the current value of the traverser back to the current alias->vertex map
- result = factory.generateBackReferenceExpression(result, false, context.getTempAliasName());
- }
- }
- return result;
- }
-
-
-
-
-}
-
http://git-wip-us.apache.org/repos/asf/atlas/blob/0877e47c/repository/src/main/java/org/apache/atlas/gremlin/optimizer/ExpressionFinder.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/gremlin/optimizer/ExpressionFinder.java b/repository/src/main/java/org/apache/atlas/gremlin/optimizer/ExpressionFinder.java
deleted file mode 100644
index 2721049..0000000
--- a/repository/src/main/java/org/apache/atlas/gremlin/optimizer/ExpressionFinder.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/**
- * 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.atlas.gremlin.optimizer;
-
-import com.google.common.base.Function;
-
-import org.apache.atlas.groovy.AbstractFunctionExpression;
-import org.apache.atlas.groovy.GroovyExpression;
-
-/**
- * Call hierarchy visitor that checks if an expression
- * matching the specified criteria is present
- * in the call hierarch.
- */
-public class ExpressionFinder implements CallHierarchyVisitor {
-
- private final Function<GroovyExpression, Boolean> predicate;
- private boolean expressionFound = false;
-
- public ExpressionFinder(Function<GroovyExpression, Boolean> predicate) {
- this.predicate = predicate;
- }
- @Override
- public boolean preVisitFunctionCaller(AbstractFunctionExpression expr) {
- if (predicate.apply(expr)) {
- expressionFound = true;
- return false;
- }
- return true;
- }
-
- @Override
- public void visitNonFunctionCaller(GroovyExpression expr) {
- if (predicate.apply(expr)) {
- expressionFound = true;
- }
- }
-
- @Override
- public void visitNullCaller() {
- //nothing to do
- }
-
- @Override
- public boolean postVisitFunctionCaller(AbstractFunctionExpression functionCall) {
- //nothing to do
- return true;
- }
-
- public boolean isExpressionFound() {
- return expressionFound;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/atlas/blob/0877e47c/repository/src/main/java/org/apache/atlas/gremlin/optimizer/FunctionGenerator.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/gremlin/optimizer/FunctionGenerator.java b/repository/src/main/java/org/apache/atlas/gremlin/optimizer/FunctionGenerator.java
deleted file mode 100644
index 1a93d0f..0000000
--- a/repository/src/main/java/org/apache/atlas/gremlin/optimizer/FunctionGenerator.java
+++ /dev/null
@@ -1,326 +0,0 @@
-/**
- * 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.atlas.gremlin.optimizer;
-
-import java.util.List;
-
-import org.apache.atlas.gremlin.GremlinExpressionFactory;
-import org.apache.atlas.groovy.AbstractFunctionExpression;
-import org.apache.atlas.groovy.ClosureExpression;
-import org.apache.atlas.groovy.ClosureExpression.VariableDeclaration;
-import org.apache.atlas.groovy.FunctionCallExpression;
-import org.apache.atlas.groovy.GroovyExpression;
-import org.apache.atlas.groovy.IdentifierExpression;
-
-/**
- * Extracts common expressions from an or-containing expression
- * into functions. These expressions would otherwise be duplicated
- * as part of expanding the "or". Doing this shortens the overall length
- * of the Gremlin script so we can maximize query performance.
- *
- */
-public class FunctionGenerator implements CallHierarchyVisitor {
-
- //Function length constants.
- //These assume we won't reach more than 9 function definition. Even if we do, this is still
- //a reasonable approximation.
- private static final int INITIAL_FUNCTION_DEF_LENGTH = "def f1={};".length();
- private final int functionDefLength;
- private static final int FUNCTION_CALL_OVERHEAD = "f1()".length();
-
- /**
- * The expression that should be the first (deepest) expression
- * in the body of the next generated function. As we go up the
- * expression tree in the post visit, this is updated based on the
- * expressions we see. During the post visits, if it is null,
- * the body expression is set to the expression we're visiting.
- * As we go up the tree, it is nulled out if we create a function
- * or encounter an or expression. This guarantees that the
- * next function body will not contain any or expressions
- * and that it will not have expressions that are already
- * part of some other function.
- */
- private GroovyExpression nextFunctionBodyStart;
-
- /**
- * The number of times expressions will be duplicated.
- */
- private int scaleFactor = 1;
-
- private final OptimizationContext context;
-
- /**
- * The current depth in the expression tree.
- */
- private int depth = 0;
-
- /**
- * The name of the last function that was generated. If set,
- * we can safely update this function instead of creating a new one.
- */
- private String currentFunctionName;
-
- /**
- * The updated expression we will pass back to the caller.
- */
- private GroovyExpression newRootExpression;
-
- private final GremlinExpressionFactory factory;
-
- public FunctionGenerator(GremlinExpressionFactory factory, OptimizationContext context) {
- this.context = context;
- this.factory = factory;
- functionDefLength = ("def f1={" + factory.getTraversalExpressionClass() + " x->};").length();
- }
-
- @Override
- public boolean preVisitFunctionCaller(AbstractFunctionExpression expr) {
- depth++;
- if (IsOr.INSTANCE.apply(expr)) {
- FunctionCallExpression functionCall = (FunctionCallExpression) expr;
- scaleFactor *= functionCall.getArguments().size();
- }
- if (newRootExpression == null) {
- newRootExpression = expr;
- }
-
- return true;
- }
-
- @Override
- public void visitNonFunctionCaller(GroovyExpression expr) {
- if (nextFunctionBodyStart == null) {
- nextFunctionBodyStart = expr;
- }
-
- }
-
- @Override
- public void visitNullCaller() {
- //nothing to do
- }
-
- @Override
- public boolean postVisitFunctionCaller(AbstractFunctionExpression expr) {
- boolean isRootExpr = depth == 1;
- visitParentExpression(expr);
-
- //The root expression has no parent. To simplify the logic, we create
- //a dummy expression so it does have a parent, then call visitParentExpression again
- //to examine the root expression.
- if (isRootExpr) {
- FunctionCallExpression dummyParent = new FunctionCallExpression(expr, "dummy");
- visitParentExpression(dummyParent);
- newRootExpression = dummyParent.getCaller();
- }
-
- depth--;
- return true;
- }
-
- /**
- * Checks to see if the *caller* of this expression should become part
- * of a function. If so, either a new function is created, or the
- * expression becomes part of the last function we created.
- *
- * @param parentExpr
- */
- private void visitParentExpression(AbstractFunctionExpression parentExpr) {
-
- if (nextFunctionBodyStart == null) {
- nextFunctionBodyStart = parentExpr;
- }
-
- if (currentFunctionName != null) {
- updateCurrentFunction(parentExpr);
- } else {
- createFunctionIfNeeded(parentExpr);
- }
-
- if (GremlinQueryOptimizer.isOrExpression(parentExpr)) {
- //reset
- currentFunctionName = null;
- //don't include 'or' in generated functions
- nextFunctionBodyStart = null;
- }
-
- }
-
- /**
- * Creates a function whose body goes from the child of parentExpr
- * up to (and including) the functionBodyEndExpr.
- * @param parentExpr
- */
- private void createFunctionIfNeeded(AbstractFunctionExpression parentExpr) {
- GroovyExpression potentialFunctionBody = parentExpr.getCaller();
-
- if (creatingFunctionShortensGremlin(potentialFunctionBody)) {
- GroovyExpression functionCall = null;
-
- if (nextFunctionBodyStart instanceof AbstractFunctionExpression) {
- //The function body start is a a function call. In this
- //case, we generate a function that takes one argument, which
- //is a graph traversal. We have an expression tree that
- //looks kind of like the following:
- //
- // parentExpr
- // /
- // / caller
- // |/_
- // potentialFunctionBody
- // /
- // / caller
- // |/_
- // ...
- // /
- // / caller
- // |/_
- // nextFunctionBodyStart
- // /
- // / caller
- // |/_
- // oldCaller
- //
- //
- // Note that potentialFunctionBody and nextFunctionBodyStart
- // could be the same expression. Let's say that the next
- // function name is f1
- //
- // We reshuffle these expressions to the following:
- //
- // parentExpr
- // /
- // / caller
- // |/_
- // f1(oldCaller)
- //
- //
- // potentialFunctionBody <- body of new function "f1(GraphTraversal x)"
- // /
- // / caller
- // |/_
- // ...
- // /
- // / caller
- // |/_
- // nextFunctionBodyStart
- // /
- // / caller
- // |/_
- // x
- //
- // As an example, suppose parentExpr is g.V().or(x,y).has(a).has(b).has(c)
- // where has(a) is nextFunctionBodyStart.
- //
- // We generate a function f1 = { GraphTraversal x -> x.has(a).has(b) }
- // parentExpr would become : f1(g.V().or(x,y)).has(c)
-
- AbstractFunctionExpression nextFunctionBodyStartFunction=
- (AbstractFunctionExpression) nextFunctionBodyStart;
- String variableName = "x";
- IdentifierExpression var = new IdentifierExpression(variableName);
- GroovyExpression oldCaller = nextFunctionBodyStartFunction.getCaller();
- nextFunctionBodyStartFunction.setCaller(var);
-
- currentFunctionName = context.addFunctionDefinition(new VariableDeclaration(factory.getTraversalExpressionClass(), "x"),
- potentialFunctionBody);
- functionCall = new FunctionCallExpression(potentialFunctionBody.getType(),
- currentFunctionName, oldCaller);
-
- } else {
- //The function body start is a not a function call. In this
- //case, we generate a function that takes no arguments.
-
- // As an example, suppose parentExpr is g.V().has(a).has(b).has(c)
- // where g is nextFunctionBodyStart.
- //
- // We generate a function f1 = { g.V().has(a).has(b) }
- // parentExpr would become : f1().has(c)
-
- currentFunctionName = context.addFunctionDefinition(null, potentialFunctionBody);
- functionCall = new FunctionCallExpression(potentialFunctionBody.getType(), currentFunctionName);
- }
-
- //functionBodyEnd is now part of a function definition, don't propagate it
- nextFunctionBodyStart = null;
- parentExpr.setCaller(functionCall);
- }
- }
-
- /**
- * Adds the caller of parentExpr to the current body of the last
- * function that was created.
- *
- * @param parentExpr
- */
- private void updateCurrentFunction(AbstractFunctionExpression parentExpr) {
- GroovyExpression expr = parentExpr.getCaller();
- if (expr instanceof AbstractFunctionExpression) {
- AbstractFunctionExpression exprAsFunction = (AbstractFunctionExpression) expr;
- GroovyExpression exprCaller = exprAsFunction.getCaller();
- parentExpr.setCaller(exprCaller);
- updateCurrentFunctionDefintion(exprAsFunction);
- }
- }
-
- private void updateCurrentFunctionDefintion(AbstractFunctionExpression exprToAdd) {
- ClosureExpression functionBodyClosure = context.getUserDefinedFunctionBody(currentFunctionName);
- if (functionBodyClosure == null) {
- throw new IllegalStateException("User-defined function " + currentFunctionName + " not found!");
- }
- List<GroovyExpression> exprs = functionBodyClosure.getStatements();
- GroovyExpression currentFunctionBody = exprs.get(exprs.size() - 1);
- //Update the expression so it is called by the current return
- //value of the function.
- exprToAdd.setCaller(currentFunctionBody);
- functionBodyClosure.replaceStatement(exprs.size() - 1, exprToAdd);
- }
-
- //Determines if extracting this expression into a function will shorten
- //the overall length of the Groovy script.
- private boolean creatingFunctionShortensGremlin(GroovyExpression headExpr) {
- int tailLength = getTailLength();
- int length = headExpr.toString().length() - tailLength;
-
- int overhead = 0;
- if (nextFunctionBodyStart instanceof AbstractFunctionExpression) {
- overhead = functionDefLength;
- } else {
- overhead = INITIAL_FUNCTION_DEF_LENGTH;
- }
- overhead += FUNCTION_CALL_OVERHEAD * scaleFactor;
- //length * scaleFactor = space taken by having the expression be inlined [scaleFactor] times
- //overhead + length = space taken by the function definition and its calls
- return length * scaleFactor > overhead + length;
- }
-
- private int getTailLength() {
- if (nextFunctionBodyStart == null) {
- return 0;
- }
- if (!(nextFunctionBodyStart instanceof AbstractFunctionExpression)) {
- return 0;
- }
- AbstractFunctionExpression bodyEndAsFunction = (AbstractFunctionExpression) nextFunctionBodyStart;
- return bodyEndAsFunction.getCaller().toString().length();
- }
-
- public GroovyExpression getNewRootExpression() {
- return newRootExpression;
- }
-}
http://git-wip-us.apache.org/repos/asf/atlas/blob/0877e47c/repository/src/main/java/org/apache/atlas/gremlin/optimizer/GremlinOptimization.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/gremlin/optimizer/GremlinOptimization.java b/repository/src/main/java/org/apache/atlas/gremlin/optimizer/GremlinOptimization.java
deleted file mode 100644
index bfa45af..0000000
--- a/repository/src/main/java/org/apache/atlas/gremlin/optimizer/GremlinOptimization.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/**
- * 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.atlas.gremlin.optimizer;
-
-import org.apache.atlas.groovy.GroovyExpression;
-
-/**
- * An optimization that can be applied to a gremlin query.
- */
-public interface GremlinOptimization {
-
- /**
- * Whether or not this optimization should be applied to the given expression
- * @param expr
- * @param contxt
- * @return
- */
- boolean appliesTo(GroovyExpression expr, OptimizationContext contxt);
- /**
- * Whether or not GremlinQueryOptimizer should call this optimization recursively
- * on the updated children.
- */
- boolean isApplyRecursively();
-
- /**
- * Applies the optimization.
- *
- * @param expr
- * @param context
- * @return the optimized expression
- */
- GroovyExpression apply(GroovyExpression expr, OptimizationContext context);
-}
http://git-wip-us.apache.org/repos/asf/atlas/blob/0877e47c/repository/src/main/java/org/apache/atlas/gremlin/optimizer/GremlinQueryOptimizer.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/gremlin/optimizer/GremlinQueryOptimizer.java b/repository/src/main/java/org/apache/atlas/gremlin/optimizer/GremlinQueryOptimizer.java
deleted file mode 100644
index a0c08fd..0000000
--- a/repository/src/main/java/org/apache/atlas/gremlin/optimizer/GremlinQueryOptimizer.java
+++ /dev/null
@@ -1,262 +0,0 @@
-/**
- * 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.atlas.gremlin.optimizer;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.atlas.gremlin.GremlinExpressionFactory;
-import org.apache.atlas.groovy.AbstractFunctionExpression;
-import org.apache.atlas.groovy.GroovyExpression;
-import org.apache.atlas.groovy.StatementListExpression;
-import org.apache.atlas.groovy.TraversalStepType;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.annotations.VisibleForTesting;
-
-
-
-/**
- * Optimizer for gremlin queries. This class provides a framework for applying optimizations
- * to gremlin queries. Each optimization is implemented as a class that implements {@link GremlinOptimization}.
- *
- * The GremlinQueryOptimizer is the entry point for applying these optimizations.
- *
- *
- */
-public final class GremlinQueryOptimizer {
-
- private static final Logger LOGGER = LoggerFactory.getLogger(GremlinQueryOptimizer.class);
-
-
- private final List<GremlinOptimization> optimizations = new ArrayList<>();
-
- //Allows expression factory to be substituted in unit tests.
- private static volatile GremlinExpressionFactory FACTORY = GremlinExpressionFactory.INSTANCE;
-
- private static volatile GremlinQueryOptimizer INSTANCE = null;
-
- private GremlinQueryOptimizer() {
-
- }
-
- private void addOptimization(GremlinOptimization opt) {
- optimizations.add(opt);
- }
-
- public static GremlinQueryOptimizer getInstance() {
- if(INSTANCE == null) {
- synchronized(GremlinQueryOptimizer.class) {
- if(INSTANCE == null) {
- GremlinQueryOptimizer createdInstance = new GremlinQueryOptimizer();
- //The order here is important. If there is an "or" nested within an "and",
- //that will not be found if ExpandOrsOptimization runs before ExpandAndsOptimization.
- createdInstance.addOptimization(new ExpandAndsOptimization(FACTORY));
- createdInstance.addOptimization(new ExpandOrsOptimization(FACTORY));
- INSTANCE = createdInstance;
- }
- }
- }
- return INSTANCE;
- }
-
- /**
- * For testing only
- */
- @VisibleForTesting
- public static void setExpressionFactory(GremlinExpressionFactory factory) {
- GremlinQueryOptimizer.FACTORY = factory;
- }
-
- /**
- * For testing only
- */
- @VisibleForTesting
- public static void reset() {
- INSTANCE = null;
- }
-
- /**
- * Optimizes the provided groovy expression. Note that the optimization
- * is a <i>destructive</i> process. The source GroovyExpression will be
- * modified as part of the optimization process. This is done to avoid
- * expensive copying operations where possible.
- *
- * @param source what to optimize
- * @return the optimized query
- */
- public GroovyExpression optimize(GroovyExpression source) {
- LOGGER.debug("Optimizing gremlin query: " + source);
- OptimizationContext context = new OptimizationContext();
- GroovyExpression updatedExpression = source;
- for (GremlinOptimization opt : optimizations) {
- updatedExpression = optimize(updatedExpression, opt, context);
- LOGGER.debug("After "+ opt.getClass().getSimpleName() + ", query = " + updatedExpression);
- }
-
- StatementListExpression result = new StatementListExpression();
- result.addStatements(context.getInitialStatements());
- result.addStatement(updatedExpression);
- LOGGER.debug("Final optimized query: " + result.toString());
- return result;
- }
-
- /**
- * Optimizes the expression using the given optimization
- * @param source
- * @param optimization
- * @param context
- * @return
- */
- private GroovyExpression optimize(GroovyExpression source, GremlinOptimization optimization,
- OptimizationContext context) {
- GroovyExpression result = source;
- if (optimization.appliesTo(source, context)) {
- //Apply the optimization to the expression.
- result = optimization.apply(source, context);
- }
- if (optimization.isApplyRecursively()) {
- //Visit the children, update result with the optimized
- //children.
- List<GroovyExpression> updatedChildren = new ArrayList<>();
- boolean changed = false;
- for (GroovyExpression child : result.getChildren()) {
- //Recursively optimize this child.
- GroovyExpression updatedChild = optimize(child, optimization, context);
- changed |= updatedChild != child;
- updatedChildren.add(updatedChild);
- }
- if (changed) {
- //TBD - Can we update in place rather than making a copy?
- result = result.copy(updatedChildren);
- }
- }
- return result;
- }
-
- /**
- * Visits all expressions in the call hierarchy of an expression. For example,
- * in the expression g.V().has('x','y'), the order would be
- * <ol>
- * <li>pre-visit has('x','y')</li>
- * <li>pre-visit V()</li>
- * <li>visit g (non-function caller)</li>
- * <li>post-visit V()</li>
- * <li>post-visit has('x','y')</li>
- * </ol>
- * @param expr
- * @param visitor
- */
- public static void visitCallHierarchy(GroovyExpression expr, CallHierarchyVisitor visitor) {
-
- if (expr == null) {
- visitor.visitNullCaller();
- return;
- }
- if (expr instanceof AbstractFunctionExpression) {
- AbstractFunctionExpression functionCall = (AbstractFunctionExpression)expr;
- if (!visitor.preVisitFunctionCaller(functionCall)) {
- return;
- }
- GroovyExpression caller = functionCall.getCaller();
- visitCallHierarchy(caller, visitor);
- if (!visitor.postVisitFunctionCaller(functionCall)) {
- return;
- }
- } else {
- visitor.visitNonFunctionCaller(expr);
- }
- }
-
- /**
- * Determines if the given expression is an "or" expression.
- * @param expr
- * @return
- */
- public static boolean isOrExpression(GroovyExpression expr) {
- return IsOr.INSTANCE.apply(expr);
- }
-
- /**
- * Determines whether the given expression can safely
- * be pulled out of an and/or expression.
- *
- * @param expr an argument to an and or or function
- * @return
- */
- public static boolean isExtractable(GroovyExpression expr) {
-
- HasForbiddenType hasForbiddenTypePredicate = new HasForbiddenType(FACTORY);
-
- //alias could conflict with alias in parent traversal
- hasForbiddenTypePredicate.addForbiddenType(TraversalStepType.SIDE_EFFECT);
-
- //inlining out(), in() steps will change the result of calls after the and/or()
- hasForbiddenTypePredicate.addForbiddenType(TraversalStepType.FLAT_MAP_TO_ELEMENTS);
- hasForbiddenTypePredicate.addForbiddenType(TraversalStepType.FLAT_MAP_TO_VALUES);
- hasForbiddenTypePredicate.addForbiddenType(TraversalStepType.BARRIER);
- hasForbiddenTypePredicate.addForbiddenType(TraversalStepType.MAP_TO_ELEMENT);
- hasForbiddenTypePredicate.addForbiddenType(TraversalStepType.MAP_TO_VALUE);
-
- //caller expects to be able to continue the traversal. We can't end it
- hasForbiddenTypePredicate.addForbiddenType(TraversalStepType.END);
-
-
- //we can't inline child traversals
- hasForbiddenTypePredicate.addForbiddenType(TraversalStepType.SOURCE);
- hasForbiddenTypePredicate.addForbiddenType(TraversalStepType.START);
- hasForbiddenTypePredicate.addForbiddenType(TraversalStepType.SIDE_EFFECT);
- hasForbiddenTypePredicate.addForbiddenType(TraversalStepType.NONE);
- hasForbiddenTypePredicate.addForbiddenType(TraversalStepType.BRANCH);
-
- ExpressionFinder forbiddenExpressionFinder = new ExpressionFinder(hasForbiddenTypePredicate);
- GremlinQueryOptimizer.visitCallHierarchy(expr, forbiddenExpressionFinder);
- return ! forbiddenExpressionFinder.isExpressionFound();
- }
-
- /**
- * Recursively copies and follows the caller hierarchy of the expression until we come
- * to a function call with a null caller. The caller of that expression is set
- * to newLeaf.
- *
- * @param expr
- * @param newLeaf
- * @return the updated (/copied) expression
- */
- public static GroovyExpression copyWithNewLeafNode(AbstractFunctionExpression expr, GroovyExpression newLeaf) {
-
-
- AbstractFunctionExpression result = (AbstractFunctionExpression)expr.copy();
-
- //remove leading anonymous traversal expression, if there is one
- if(FACTORY.isLeafAnonymousTraversalExpression(expr)) {
- result = (AbstractFunctionExpression)newLeaf;
- } else {
- GroovyExpression newCaller = null;
- if (expr.getCaller() == null) {
- newCaller = newLeaf;
- } else {
- newCaller = copyWithNewLeafNode((AbstractFunctionExpression)result.getCaller(), newLeaf);
- }
- result.setCaller(newCaller);
- }
- return result;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/atlas/blob/0877e47c/repository/src/main/java/org/apache/atlas/gremlin/optimizer/HasForbiddenType.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/gremlin/optimizer/HasForbiddenType.java b/repository/src/main/java/org/apache/atlas/gremlin/optimizer/HasForbiddenType.java
deleted file mode 100644
index 3fb9faa..0000000
--- a/repository/src/main/java/org/apache/atlas/gremlin/optimizer/HasForbiddenType.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/**
- * 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.atlas.gremlin.optimizer;
-
-import java.util.HashSet;
-import java.util.Set;
-import com.google.common.base.Function;
-
-import org.apache.atlas.gremlin.GremlinExpressionFactory;
-import org.apache.atlas.groovy.GroovyExpression;
-import org.apache.atlas.groovy.TraversalStepType;
-
-/**
- * Function that tests whether the expression is an 'or'
- * graph traversal function.
- */
-public final class HasForbiddenType implements Function<GroovyExpression, Boolean> {
-
- private Set<TraversalStepType> forbiddenTypes = new HashSet<>();
- private final GremlinExpressionFactory factory;
-
- public HasForbiddenType(GremlinExpressionFactory factory) {
- this.factory = factory;
- }
-
- public void addForbiddenType(TraversalStepType type) {
- forbiddenTypes.add(type);
- }
-
- @Override
- public Boolean apply(GroovyExpression expr) {
- if(factory.isLeafAnonymousTraversalExpression(expr)) {
- return false;
- }
- return forbiddenTypes.contains(expr.getType());
- }
-}
http://git-wip-us.apache.org/repos/asf/atlas/blob/0877e47c/repository/src/main/java/org/apache/atlas/gremlin/optimizer/IsOr.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/gremlin/optimizer/IsOr.java b/repository/src/main/java/org/apache/atlas/gremlin/optimizer/IsOr.java
deleted file mode 100644
index ab74087..0000000
--- a/repository/src/main/java/org/apache/atlas/gremlin/optimizer/IsOr.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/**
- * 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.atlas.gremlin.optimizer;
-
-import com.google.common.base.Function;
-
-import org.apache.atlas.groovy.FunctionCallExpression;
-import org.apache.atlas.groovy.GroovyExpression;
-import org.apache.atlas.groovy.TraversalStepType;
-
-/**
- * Function that tests whether the expression is an 'or'
- * graph traversal function.
- */
-public final class IsOr implements Function<GroovyExpression, Boolean> {
-
- public static final IsOr INSTANCE = new IsOr();
-
- private IsOr() {
- }
-
- @Override
- public Boolean apply(GroovyExpression expr) {
- if (!(expr instanceof FunctionCallExpression)) {
- return false;
- }
- if (expr.getType() != TraversalStepType.FILTER) {
- return false;
- }
- FunctionCallExpression functionCall = (FunctionCallExpression)expr;
- return functionCall.getFunctionName().equals("or");
- }
-}
http://git-wip-us.apache.org/repos/asf/atlas/blob/0877e47c/repository/src/main/java/org/apache/atlas/gremlin/optimizer/IsOrParent.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/gremlin/optimizer/IsOrParent.java b/repository/src/main/java/org/apache/atlas/gremlin/optimizer/IsOrParent.java
deleted file mode 100644
index 72085d0..0000000
--- a/repository/src/main/java/org/apache/atlas/gremlin/optimizer/IsOrParent.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/**
- * 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.atlas.gremlin.optimizer;
-
-import com.google.common.base.Function;
-
-import org.apache.atlas.groovy.AbstractFunctionExpression;
-import org.apache.atlas.groovy.FunctionCallExpression;
-import org.apache.atlas.groovy.GroovyExpression;
-import org.apache.atlas.groovy.TraversalStepType;
-
-/**
- * Matches an expression that gets called after calling or(). For example,
- * in g.V().or(x,y).toList(), "toList()" is the "or parent", so calling
- * "apply()" on this expression would return true and calling it on all
- * the other ones would return false.
- */
-public final class IsOrParent implements Function<GroovyExpression, Boolean> {
-
- public static final IsOrParent INSTANCE = new IsOrParent();
-
- private IsOrParent() {
-
- }
-
- @Override
- public Boolean apply(GroovyExpression expr) {
- if (!(expr instanceof AbstractFunctionExpression)) {
- return false;
- }
- AbstractFunctionExpression functionCall = (AbstractFunctionExpression)expr;
- GroovyExpression target = functionCall.getCaller();
-
- if (!(target instanceof FunctionCallExpression)) {
- return false;
- }
-
- if (target.getType() != TraversalStepType.FILTER) {
- return false;
- }
-
- FunctionCallExpression targetFunction = (FunctionCallExpression)target;
- return targetFunction.getFunctionName().equals("or");
- }
-}
http://git-wip-us.apache.org/repos/asf/atlas/blob/0877e47c/repository/src/main/java/org/apache/atlas/gremlin/optimizer/OptimizationContext.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/gremlin/optimizer/OptimizationContext.java b/repository/src/main/java/org/apache/atlas/gremlin/optimizer/OptimizationContext.java
deleted file mode 100644
index 86c8b98..0000000
--- a/repository/src/main/java/org/apache/atlas/gremlin/optimizer/OptimizationContext.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/**
- * 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.atlas.gremlin.optimizer;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.atlas.groovy.AbstractFunctionExpression;
-import org.apache.atlas.groovy.ClosureExpression;
-import org.apache.atlas.groovy.ClosureExpression.VariableDeclaration;
-import org.apache.atlas.groovy.GroovyExpression;
-import org.apache.atlas.groovy.IdentifierExpression;
-import org.apache.atlas.groovy.ListExpression;
-import org.apache.atlas.groovy.TypeCoersionExpression;
-import org.apache.atlas.groovy.VariableAssignmentExpression;
-
-/**
- * Maintains state information during gremlin optimization.
- */
-public class OptimizationContext {
-
- private static final String TMP_ALIAS_NAME = "__tmp";
- private static final String FINAL_ALIAS_NAME = "__res";
- private static final String RESULT_VARIABLE = "r";
- private final List<GroovyExpression> initialStatements = new ArrayList<>();
- private GroovyExpression resultExpression = getResultVariable();
- private int counter = 1;
- private final Map<String, ClosureExpression> functionBodies = new HashMap<>();
- private AbstractFunctionExpression rangeExpression;
-
- public OptimizationContext() {
-
- }
-
- /**
- * @return
- */
- public List<GroovyExpression> getInitialStatements() {
- return initialStatements;
- }
-
- public void prependStatement(GroovyExpression expr) {
- initialStatements.add(0, expr);
- }
-
- public String getUniqueFunctionName() {
- return "f" + (counter++);
- }
-
-
- public GroovyExpression getDefineResultVariableStmt() {
- GroovyExpression castExpression = new TypeCoersionExpression(new ListExpression(), "Set");
- GroovyExpression resultVarDef = new VariableAssignmentExpression(RESULT_VARIABLE, castExpression);
- return resultVarDef;
-
- }
- public void setResultExpression(GroovyExpression expr) {
- resultExpression = expr;
- }
-
- public GroovyExpression getResultExpression() {
- return resultExpression;
- }
-
- public GroovyExpression getResultVariable() {
- return new IdentifierExpression(RESULT_VARIABLE);
- }
-
- public ClosureExpression getUserDefinedFunctionBody(String functionName) {
- return functionBodies.get(functionName);
- }
-
- public String addFunctionDefinition(VariableDeclaration decl, GroovyExpression body) {
- String functionName = getUniqueFunctionName();
- List<VariableDeclaration> decls = (decl == null) ? Collections.<VariableDeclaration>emptyList() : Collections.singletonList(decl);
- ClosureExpression bodyClosure = new ClosureExpression(body, decls);
- VariableAssignmentExpression expr = new VariableAssignmentExpression(functionName, bodyClosure);
- initialStatements.add(expr);
- functionBodies.put(functionName, bodyClosure);
- return functionName;
- }
-
- public String getFinalAliasName() {
- return FINAL_ALIAS_NAME;
- }
-
- public String getTempAliasName() {
- return TMP_ALIAS_NAME;
- }
-
- public void setRangeExpression(AbstractFunctionExpression rangeExpression) {
- this.rangeExpression = rangeExpression;
- }
-
- public AbstractFunctionExpression getRangeExpression() {
- return rangeExpression;
- }
-}
http://git-wip-us.apache.org/repos/asf/atlas/blob/0877e47c/repository/src/main/java/org/apache/atlas/gremlin/optimizer/OrderFinder.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/gremlin/optimizer/OrderFinder.java b/repository/src/main/java/org/apache/atlas/gremlin/optimizer/OrderFinder.java
deleted file mode 100644
index 792fc52..0000000
--- a/repository/src/main/java/org/apache/atlas/gremlin/optimizer/OrderFinder.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/**
- * 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.atlas.gremlin.optimizer;
-
-import org.apache.atlas.gremlin.GremlinExpressionFactory;
-import org.apache.atlas.groovy.AbstractFunctionExpression;
-import org.apache.atlas.groovy.GroovyExpression;
-
-
-/**
- * Finds order expression in the call hierarchy.
- *
- */
-public class OrderFinder implements CallHierarchyVisitor {
-
- private boolean hasOrderExpression;
- private GremlinExpressionFactory gremlinFactory;
-
- public OrderFinder(GremlinExpressionFactory gremlinFactory) {
- this.gremlinFactory = gremlinFactory;
- }
-
- @Override
- public boolean preVisitFunctionCaller(AbstractFunctionExpression expr) {
-
- return true;
- }
-
- @Override
- public void visitNonFunctionCaller(GroovyExpression expr) {
- }
-
- @Override
- public void visitNullCaller() {
- }
-
- @Override
- public boolean postVisitFunctionCaller(AbstractFunctionExpression functionCall) {
-
- if (gremlinFactory.isOrderExpression(functionCall)) {
- hasOrderExpression = true;
- return false;
- }
- return true;
- }
-
-
- public boolean hasOrderExpression() {
-
- return hasOrderExpression;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/atlas/blob/0877e47c/repository/src/main/java/org/apache/atlas/gremlin/optimizer/PathExpressionFinder.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/gremlin/optimizer/PathExpressionFinder.java b/repository/src/main/java/org/apache/atlas/gremlin/optimizer/PathExpressionFinder.java
deleted file mode 100644
index 0e9070d..0000000
--- a/repository/src/main/java/org/apache/atlas/gremlin/optimizer/PathExpressionFinder.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/**
- * 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.atlas.gremlin.optimizer;
-
-import org.apache.atlas.groovy.AbstractFunctionExpression;
-import org.apache.atlas.groovy.FunctionCallExpression;
-import org.apache.atlas.groovy.GroovyExpression;
-
-/**
- * Determines whether an expression contains a path() function.
- */
-public class PathExpressionFinder implements CallHierarchyVisitor {
-
- private boolean found = false;
-
- @Override
- public boolean preVisitFunctionCaller(AbstractFunctionExpression expr) {
- if(expr instanceof FunctionCallExpression) {
- found = ((FunctionCallExpression)expr).getFunctionName().equals("path");
- if(found) {
- return false;
- }
- }
- return true;
- }
-
- @Override
- public void visitNonFunctionCaller(GroovyExpression expr) {
-
- }
-
- @Override
- public void visitNullCaller() {
-
- }
-
- public boolean isPathExpressionFound() {
- return found;
- }
-
- @Override
- public boolean postVisitFunctionCaller(AbstractFunctionExpression functionCall) {
-
- return false;
- }
-}
http://git-wip-us.apache.org/repos/asf/atlas/blob/0877e47c/repository/src/main/java/org/apache/atlas/gremlin/optimizer/RangeFinder.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/gremlin/optimizer/RangeFinder.java b/repository/src/main/java/org/apache/atlas/gremlin/optimizer/RangeFinder.java
deleted file mode 100644
index fa8ca85..0000000
--- a/repository/src/main/java/org/apache/atlas/gremlin/optimizer/RangeFinder.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/**
- * 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.atlas.gremlin.optimizer;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.atlas.gremlin.GremlinExpressionFactory;
-import org.apache.atlas.groovy.AbstractFunctionExpression;
-import org.apache.atlas.groovy.GroovyExpression;
-
-
-/**
- * Finds all range expressions in the call hierarchy.
- *
- */
-public class RangeFinder implements CallHierarchyVisitor {
-
- private List<AbstractFunctionExpression> rangeExpressions = new ArrayList<>();
- private GremlinExpressionFactory factory;
-
- public RangeFinder(GremlinExpressionFactory factory) {
- this.factory = factory;
- }
-
- @Override
- public boolean preVisitFunctionCaller(AbstractFunctionExpression expr) {
-
- return true;
- }
-
- @Override
- public void visitNonFunctionCaller(GroovyExpression expr) {
- }
-
- @Override
- public void visitNullCaller() {
- }
-
- @Override
- public boolean postVisitFunctionCaller(AbstractFunctionExpression functionCall) {
-
- if (factory.isRangeExpression(functionCall)) {
- rangeExpressions.add(functionCall);
- }
- return true;
- }
-
- public List<AbstractFunctionExpression> getRangeExpressions() {
- return rangeExpressions;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/atlas/blob/0877e47c/repository/src/main/java/org/apache/atlas/gremlin/optimizer/RepeatExpressionFinder.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/gremlin/optimizer/RepeatExpressionFinder.java b/repository/src/main/java/org/apache/atlas/gremlin/optimizer/RepeatExpressionFinder.java
deleted file mode 100644
index 8344f36..0000000
--- a/repository/src/main/java/org/apache/atlas/gremlin/optimizer/RepeatExpressionFinder.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/**
- * 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.atlas.gremlin.optimizer;
-
-import org.apache.atlas.gremlin.GremlinExpressionFactory;
-import org.apache.atlas.groovy.AbstractFunctionExpression;
-import org.apache.atlas.groovy.GroovyExpression;
-
-/**
- * Determines whether an expression contains a repeat/loop function.
- */
-public class RepeatExpressionFinder implements CallHierarchyVisitor {
-
- private boolean found = false;
- private GremlinExpressionFactory factory;
-
- public RepeatExpressionFinder(GremlinExpressionFactory factory) {
- this.factory = factory;
- }
-
- @Override
- public boolean preVisitFunctionCaller(AbstractFunctionExpression expr) {
-
- found = factory.isRepeatExpression(expr);
- if(found) {
- return false;
- }
- return true;
- }
-
- @Override
- public void visitNonFunctionCaller(GroovyExpression expr) {
-
- }
-
- @Override
- public void visitNullCaller() {
-
- }
-
- public boolean isRepeatExpressionFound() {
- return found;
- }
-
- @Override
- public boolean postVisitFunctionCaller(AbstractFunctionExpression functionCall) {
-
- return false;
- }
-}
http://git-wip-us.apache.org/repos/asf/atlas/blob/0877e47c/repository/src/main/java/org/apache/atlas/gremlin/optimizer/SplitPointFinder.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/gremlin/optimizer/SplitPointFinder.java b/repository/src/main/java/org/apache/atlas/gremlin/optimizer/SplitPointFinder.java
deleted file mode 100644
index f0295e7..0000000
--- a/repository/src/main/java/org/apache/atlas/gremlin/optimizer/SplitPointFinder.java
+++ /dev/null
@@ -1,161 +0,0 @@
-/**
- * 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.atlas.gremlin.optimizer;
-
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-import org.apache.atlas.gremlin.GremlinExpressionFactory;
-import org.apache.atlas.groovy.AbstractFunctionExpression;
-import org.apache.atlas.groovy.FunctionCallExpression;
-import org.apache.atlas.groovy.GroovyExpression;
-import org.apache.atlas.groovy.TraversalStepType;
-
-
-/**
- * This class finds the first place in the expression where the value of the
- * traverser is changed from being a vertex to being something else. This is
- * important in the "or" optimization logic, since the union operation must be
- * done on *vertices* in order to preserve the semantics of the query. In addition,
- * expressions that have side effects must be moved as well, so that those
- * side effects will be available to the steps that need them.
- */
-public class SplitPointFinder implements CallHierarchyVisitor {
-
- //Any steps that change the traverser value to something that is not a vertex or edge
- //must be included here, so that the union created by ExpandOrsOptimization
- //is done over vertices/edges.
- private static final Set<TraversalStepType> TYPES_REQUIRED_IN_RESULT_EXPRESSION = new HashSet<>(
- Arrays.asList(
- TraversalStepType.BARRIER,
- TraversalStepType.BRANCH,
- TraversalStepType.SIDE_EFFECT,
- TraversalStepType.MAP_TO_VALUE,
- TraversalStepType.FLAT_MAP_TO_VALUES,
- TraversalStepType.END,
- TraversalStepType.NONE));
-
- private final Set<String> requiredAliases = new HashSet<>();
-
- //Exceptions to the requirement that all expressions with a type
- //in the above list must be in the result expression. If the
- //function name is in this list, it is ok for that expression
- //to not be in the result expression. This mechanism allows
- //aliases to remain outside the result expression. Other
- //exceptions may be found in the future.
- private static final Map<TraversalStepType, WhiteList> WHITE_LISTS = new HashMap<>();
- static {
- WHITE_LISTS.put(TraversalStepType.SIDE_EFFECT, new WhiteList("as"));
- }
-
- private final GremlinExpressionFactory factory;
-
- public SplitPointFinder(GremlinExpressionFactory factory) {
- this.factory = factory;
- }
-
- /**
- * Represents a set of function names.
- */
- private static final class WhiteList {
- private Set<String> allowedFunctionNames = new HashSet<>();
- public WhiteList(String... names) {
- for(String name : names) {
- allowedFunctionNames.add(name);
- }
- }
- public boolean contains(String name) {
- return allowedFunctionNames.contains(name);
- }
- }
-
- private AbstractFunctionExpression splitPoint;
-
- @Override
- public boolean preVisitFunctionCaller(AbstractFunctionExpression expr) {
- requiredAliases.addAll(factory.getAliasesRequiredByExpression(expr));
- return true;
- }
-
- @Override
- public void visitNonFunctionCaller(GroovyExpression expr) {
-
- }
-
- @Override
- public void visitNullCaller() {
-
- }
-
- public AbstractFunctionExpression getSplitPoint() {
- return splitPoint;
- }
-
- @Override
- public boolean postVisitFunctionCaller(AbstractFunctionExpression functionCall) {
- String aliasName = factory.getAliasNameIfRelevant(functionCall);
- if (splitPoint == null) {
-
- boolean required = isRequiredAlias(aliasName) ||
- isRequiredInResultExpression(functionCall);
- if (required) {
- splitPoint = functionCall;
- }
- }
- removeSeenAlias(aliasName);
-
- return true;
- }
-
- private void removeSeenAlias(String aliasName) {
- if(aliasName != null) {
- requiredAliases.remove(aliasName);
- }
- }
-
- private boolean isRequiredAlias(String aliasName) {
- if(aliasName != null) {
- return requiredAliases.contains(aliasName);
- }
- return false;
- }
-
- private boolean isRequiredInResultExpression(AbstractFunctionExpression expr) {
-
- TraversalStepType type = expr.getType();
- if (!TYPES_REQUIRED_IN_RESULT_EXPRESSION.contains(type)) {
- return false;
- }
-
- if(expr instanceof FunctionCallExpression) {
- FunctionCallExpression functionCall = (FunctionCallExpression)expr;
- //check if the white list permits this function call. If there is
- //no white list, all expressions with the current step type must go in the
- //result expression.
- WhiteList whiteList = WHITE_LISTS.get(type);
- if(whiteList != null && whiteList.contains(functionCall.getFunctionName())) {
- return false;
- }
- }
- return true;
-
- }
-}
http://git-wip-us.apache.org/repos/asf/atlas/blob/0877e47c/repository/src/main/java/org/apache/atlas/gremlin/optimizer/UpdatedExpressions.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/gremlin/optimizer/UpdatedExpressions.java b/repository/src/main/java/org/apache/atlas/gremlin/optimizer/UpdatedExpressions.java
deleted file mode 100644
index 06351ea..0000000
--- a/repository/src/main/java/org/apache/atlas/gremlin/optimizer/UpdatedExpressions.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/**
- * 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.atlas.gremlin.optimizer;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.atlas.groovy.GroovyExpression;
-
-/**
- * Represents a list of updated expressions.
- */
-public class UpdatedExpressions {
-
- private List<List<GroovyExpression>> updatedChildren = new ArrayList<>();
- private boolean changed = false;
-
- public UpdatedExpressions(boolean changed, List<List<GroovyExpression>> updatedChildren) {
- this.changed = changed;
- this.updatedChildren = updatedChildren;
- }
-
- public List<List<GroovyExpression>> getUpdatedChildren() {
- return updatedChildren;
- }
-
- public boolean hasChanges() {
- return changed;
- }
-}