@Override
    public GroovyExpression apply(GroovyExpression expr, OptimizationContext context) {

        FunctionCallExpression exprAsFunction = (FunctionCallExpression)expr;
        GroovyExpression result = exprAsFunction.getCaller();

        List<GroovyExpression> nonExtractableArguments = new ArrayList<>();
        for(GroovyExpression argument : exprAsFunction.getArguments()) {

            if (GremlinQueryOptimizer.isExtractable(argument)) {
                //Set the caller of the deepest expression in the call hierarchy
                //of the argument to point to the current result.
                //For example, if result is "g.V()" and the updatedArgument is "has('x').has('y')",
                //updatedArgument would be a tree like this:
                //
                //                  has('y')
                //                 /
                //                / caller
                //              |/_
                //           has('x')
                //             /
                //            / caller
                //          |/_
                //        (null)
                //
                //We would set the caller of has('x') to be g.V(), so result would become g.V().has('x').has('y').
                //
                // Note: This operation is currently done by making a copy of the argument tree.  That should
                // be changed.
                result = GremlinQueryOptimizer.copyWithNewLeafNode(
                        (AbstractFunctionExpression) argument, result);
            } else {
                logger_.warn("Found non-extractable argument '{}' in the 'and' expression '{}'",argument.toString(), expr.toString());
                nonExtractableArguments.add(argument);
            }
        }

        if (!nonExtractableArguments.isEmpty()) {
            //add a final 'and' call with the arguments that could not be extracted
            result =  factory.generateLogicalExpression(result, "and", nonExtractableArguments);
        }
        return result;
    }
@ Override public GroovyExpression apply ( GroovyExpression expr , OptimizationContext context ) { FunctionCallExpression exprAsFunction = ( FunctionCallExpression ) expr ; GroovyExpression result = exprAsFunction . getCaller ( ) ; List < GroovyExpression > nonExtractableArguments = new ArrayList < > ( ) ; for ( GroovyExpression argument : exprAsFunction . getArguments ( ) ) { if ( GremlinQueryOptimizer . isExtractable ( argument ) ) { result = GremlinQueryOptimizer . copyWithNewLeafNode ( ( AbstractFunctionExpression ) argument , result ) ; } else { logger_ . warn ( "Found non-extractable argument '{}' in the 'and' expression '{}'" , argument . toString ( ) , expr . toString ( ) ) ; nonExtractableArguments . add ( argument ) ; } } if ( ! nonExtractableArguments . isEmpty ( ) ) { result = factory . generateLogicalExpression ( result , "and" , nonExtractableArguments ) ; } return result ; }
Expands the given and expression.  There is no need to recursively
expand the children here.  This method is called recursively by
GremlinQueryOptimier on the children.