Search in sources :

Example 16 with ASTReference

use of org.apache.commons.jexl3.parser.ASTReference in project commons-jexl by apache.

the class Interpreter method executeAssign.

/**
 * Executes an assignment with an optional side-effect operator.
 * @param node     the node
 * @param assignop the assignment operator or null if simply assignment
 * @param data     the data
 * @return the left hand side
 */
protected Object executeAssign(final JexlNode node, final JexlOperator assignop, final Object data) {
    // CSOFF: MethodLength
    cancelCheck(node);
    // left contains the reference to assign to
    final JexlNode left = node.jjtGetChild(0);
    ASTIdentifier var = null;
    Object object = null;
    int symbol = -1;
    // check var decl with assign is ok
    if (left instanceof ASTIdentifier) {
        var = (ASTIdentifier) left;
        symbol = var.getSymbol();
        if (symbol >= 0 && options.isLexical()) {
            if (var instanceof ASTVar) {
                if (!defineVariable((ASTVar) var, block)) {
                    return redefinedVariable(var, var.getName());
                }
            } else if (options.isLexicalShade() && var.isShaded()) {
                return undefinedVariable(var, var.getName());
            }
        }
    }
    boolean antish = options.isAntish();
    // 0: determine initial object & property:
    final int last = left.jjtGetNumChildren() - 1;
    // right is the value expression to assign
    Object right = node.jjtGetChild(1).jjtAccept(this, data);
    // a (var?) v = ... expression
    if (var != null) {
        if (symbol >= 0) {
            // check we are not assigning a symbol itself
            if (last < 0) {
                if (assignop != null) {
                    final Object self = getVariable(frame, block, var);
                    right = operators.tryAssignOverload(node, assignop, self, right);
                    if (right == JexlOperator.ASSIGN) {
                        return self;
                    }
                }
                frame.set(symbol, right);
                // make the closure accessible to itself, ie capture the currently set variable after frame creation
                if (right instanceof Closure) {
                    ((Closure) right).setCaptured(symbol, right);
                }
                // 1
                return right;
            }
            object = getVariable(frame, block, var);
            // top level is a symbol, can not be an antish var
            antish = false;
        } else {
            // check we are not assigning direct global
            if (last < 0) {
                if (assignop != null) {
                    final Object self = context.get(var.getName());
                    right = operators.tryAssignOverload(node, assignop, self, right);
                    if (right == JexlOperator.ASSIGN) {
                        return self;
                    }
                }
                setContextVariable(node, var.getName(), right);
                // 2
                return right;
            }
            object = context.get(var.getName());
            // top level accesses object, can not be an antish var
            if (object != null) {
                antish = false;
            }
        }
    } else if (!(left instanceof ASTReference)) {
        throw new JexlException(left, "illegal assignment form 0");
    }
    // 1: follow children till penultimate, resolve dot/array
    JexlNode objectNode = null;
    StringBuilder ant = null;
    int v = 1;
    // start at 1 if symbol
    main: for (int c = symbol >= 0 ? 1 : 0; c < last; ++c) {
        objectNode = left.jjtGetChild(c);
        object = objectNode.jjtAccept(this, object);
        if (object != null) {
            // disallow mixing antish variable & bean with same root; avoid ambiguity
            antish = false;
        } else if (antish) {
            // initialize if first time
            if (ant == null) {
                final JexlNode first = left.jjtGetChild(0);
                final ASTIdentifier firstId = first instanceof ASTIdentifier ? (ASTIdentifier) first : null;
                if ((firstId == null) || (firstId.getSymbol() >= 0)) {
                    // ant remains null, object is null, stop solving
                    antish = false;
                    break main;
                }
                ant = new StringBuilder(firstId.getName());
            }
            // catch up to current child
            for (; v <= c; ++v) {
                final JexlNode child = left.jjtGetChild(v);
                final ASTIdentifierAccess aid = child instanceof ASTIdentifierAccess ? (ASTIdentifierAccess) child : null;
                // remain antish only if unsafe navigation
                if ((aid == null) || aid.isSafe() || aid.isExpression()) {
                    antish = false;
                    break main;
                }
                ant.append('.');
                ant.append(aid.getName());
            }
            // solve antish
            object = context.get(ant.toString());
        } else {
            throw new JexlException(objectNode, "illegal assignment form");
        }
    }
    // 2: last objectNode will perform assignement in all cases
    JexlNode propertyNode = left.jjtGetChild(last);
    final ASTIdentifierAccess propertyId = propertyNode instanceof ASTIdentifierAccess ? (ASTIdentifierAccess) propertyNode : null;
    final Object property;
    if (propertyId != null) {
        // deal with creating/assignining antish variable
        if (antish && ant != null && object == null && !propertyId.isSafe() && !propertyId.isExpression()) {
            if (last > 0) {
                ant.append('.');
            }
            ant.append(propertyId.getName());
            if (assignop != null) {
                final Object self = context.get(ant.toString());
                right = operators.tryAssignOverload(node, assignop, self, right);
                if (right == JexlOperator.ASSIGN) {
                    return self;
                }
            }
            setContextVariable(propertyNode, ant.toString(), right);
            // 3
            return right;
        }
        // property of an object ?
        property = evalIdentifier(propertyId);
    } else if (propertyNode instanceof ASTArrayAccess) {
        // can have multiple nodes - either an expression, integer literal or reference
        final int numChildren = propertyNode.jjtGetNumChildren() - 1;
        for (int i = 0; i < numChildren; i++) {
            final JexlNode nindex = propertyNode.jjtGetChild(i);
            final Object index = nindex.jjtAccept(this, null);
            object = getAttribute(object, index, nindex);
        }
        propertyNode = propertyNode.jjtGetChild(numChildren);
        property = propertyNode.jjtAccept(this, null);
    } else {
        throw new JexlException(objectNode, "illegal assignment form");
    }
    // we can not *have* a null object though.
    if (object == null) {
        // no object, we fail
        return unsolvableProperty(objectNode, "<null>.<?>", true, null);
    }
    // 3: one before last, assign
    if (assignop != null) {
        final Object self = getAttribute(object, property, propertyNode);
        right = operators.tryAssignOverload(node, assignop, self, right);
        if (right == JexlOperator.ASSIGN) {
            return self;
        }
    }
    setAttribute(object, property, right, propertyNode);
    // 4
    return right;
}
Also used : ASTVar(org.apache.commons.jexl3.parser.ASTVar) JexlException(org.apache.commons.jexl3.JexlException) JexlNode(org.apache.commons.jexl3.parser.JexlNode) ASTIdentifier(org.apache.commons.jexl3.parser.ASTIdentifier) ASTReference(org.apache.commons.jexl3.parser.ASTReference) ASTIdentifierAccess(org.apache.commons.jexl3.parser.ASTIdentifierAccess) ASTArrayAccess(org.apache.commons.jexl3.parser.ASTArrayAccess)

Example 17 with ASTReference

use of org.apache.commons.jexl3.parser.ASTReference in project datawave by NationalSecurityAgency.

the class PruneLessSelectiveFieldsVisitor method visit.

@Override
public Object visit(ASTAndNode node, Object data) {
    JexlNode mostSelectiveChild = null;
    Double maxSelectivity = Double.valueOf("-1");
    boolean foundSelectivity = false;
    ASTAndNode newNode = new ASTAndNode(ParserTreeConstants.JJTANDNODE);
    newNode.image = node.image;
    newNode.jjtSetParent(node.jjtGetParent());
    for (int i = 0; i < node.jjtGetNumChildren(); i++) {
        JexlNode child = (JexlNode) node.jjtGetChild(i).jjtAccept(this, null);
        Double selectivity;
        if (child instanceof ASTOrNode || child instanceof ASTReference || child instanceof ASTReferenceExpression) {
            // Check for the selectivity of the OR
            selectivity = getOrSelectivity(child);
        } else {
            selectivity = JexlASTHelper.getNodeSelectivity(child, config, stats);
        }
        // Don't want to fail if there's an issue with one child...
        if (!selectivity.equals(IndexStatsClient.DEFAULT_VALUE) && selectivity > maxSelectivity) {
            foundSelectivity = true;
            // Hold on to the most selective child
            mostSelectiveChild = RebuildingVisitor.copy(child);
            maxSelectivity = selectivity;
        }
    }
    if (!foundSelectivity || null == mostSelectiveChild) {
        // Something went wrong, so just return the node we started with
        return RebuildingVisitor.copy(node);
    } else {
        newNode.jjtAddChild(mostSelectiveChild, newNode.jjtGetNumChildren());
    }
    return newNode;
}
Also used : ASTOrNode(org.apache.commons.jexl2.parser.ASTOrNode) ASTReferenceExpression(org.apache.commons.jexl2.parser.ASTReferenceExpression) JexlNode(org.apache.commons.jexl2.parser.JexlNode) ASTReference(org.apache.commons.jexl2.parser.ASTReference) ASTAndNode(org.apache.commons.jexl2.parser.ASTAndNode)

Example 18 with ASTReference

use of org.apache.commons.jexl3.parser.ASTReference in project datawave by NationalSecurityAgency.

the class PushdownLargeFieldedListsVisitor method assignNodeByField.

protected void assignNodeByField(JexlNode origNode, JexlNode subNode, Multimap<String, JexlNode> eqNodes, Multimap<String, JexlNode> rangeNodes, List<JexlNode> otherNodes) {
    QueryPropertyMarker.Instance instance = QueryPropertyMarker.findInstance(subNode);
    if (subNode instanceof ASTEQNode) {
        String identifier = JexlASTHelper.getIdentifier(subNode, false);
        if (identifier != null) {
            eqNodes.put(JexlASTHelper.getIdentifier(subNode, false), origNode);
        } else {
            otherNodes.add(origNode);
        }
    } else if (instance.isType(ExceededValueThresholdMarkerJexlNode.class)) {
        assignNodeByField(origNode, instance.getSource(), eqNodes, rangeNodes, otherNodes);
    } else if (instance.isType(BoundedRange.class)) {
        LiteralRange range = JexlASTHelper.findRange().getRange(subNode);
        rangeNodes.put(JexlASTHelper.rebuildIdentifier(range.getFieldName()), origNode);
    } else if ((subNode.jjtGetNumChildren() == 1) && (subNode instanceof ASTReferenceExpression || subNode instanceof ASTReference || subNode instanceof ASTAndNode)) {
        assignNodeByField(origNode, subNode.jjtGetChild(0), eqNodes, rangeNodes, otherNodes);
    } else {
        otherNodes.add(origNode);
    }
}
Also used : ASTReferenceExpression(org.apache.commons.jexl2.parser.ASTReferenceExpression) ASTEQNode(org.apache.commons.jexl2.parser.ASTEQNode) QueryPropertyMarker(datawave.query.jexl.nodes.QueryPropertyMarker) ExceededValueThresholdMarkerJexlNode(datawave.query.jexl.nodes.ExceededValueThresholdMarkerJexlNode) LiteralRange(datawave.query.jexl.LiteralRange) ASTReference(org.apache.commons.jexl2.parser.ASTReference) ASTAndNode(org.apache.commons.jexl2.parser.ASTAndNode)

Example 19 with ASTReference

use of org.apache.commons.jexl3.parser.ASTReference in project datawave by NationalSecurityAgency.

the class JexlStringBuildingVisitor method visit.

@Override
public Object visit(ASTMethodNode node, Object data) {
    StringBuilder sb = (StringBuilder) data;
    StringBuilder methodStringBuilder = new StringBuilder();
    StringBuilder argumentStringBuilder = new StringBuilder();
    int kidCount = node.jjtGetNumChildren();
    for (int i = 0; i < kidCount; i++) {
        if (i == 0) {
            JexlNode methodNode = node.jjtGetChild(i);
            methodStringBuilder.append(".");
            if (allowedMethods.contains(methodNode.image) == false) {
                QueryException qe = new QueryException(DatawaveErrorCode.METHOD_COMPOSITION_ERROR, MessageFormat.format("{0}", methodNode.image));
                throw new DatawaveFatalQueryException(qe);
            }
            methodStringBuilder.append(methodNode.image);
            // parens are open. don't forget to close
            methodStringBuilder.append("(");
        } else {
            // adding any method arguments
            JexlNode argumentNode = node.jjtGetChild(i);
            if (argumentNode instanceof ASTReference) {
                // a method may have an argument that is another method. In this case, descend the visit tree for it
                if (JexlASTHelper.HasMethodVisitor.hasMethod(argumentNode)) {
                    this.visit((ASTReference) argumentNode, argumentStringBuilder);
                } else {
                    for (int j = 0; j < argumentNode.jjtGetNumChildren(); j++) {
                        JexlNode argKid = argumentNode.jjtGetChild(j);
                        if (argKid instanceof ASTFunctionNode) {
                            this.visit((ASTFunctionNode) argKid, argumentStringBuilder);
                        } else {
                            if (argumentStringBuilder.length() > 0) {
                                argumentStringBuilder.append(",");
                            }
                            if (argKid instanceof ASTStringLiteral) {
                                argumentStringBuilder.append("'");
                            }
                            argumentStringBuilder.append(argKid.image);
                            if (argKid instanceof ASTStringLiteral) {
                                argumentStringBuilder.append("'");
                            }
                        }
                    }
                }
            } else if (argumentNode instanceof ASTNumberLiteral) {
                if (argumentStringBuilder.length() > 0) {
                    argumentStringBuilder.append(",");
                }
                argumentStringBuilder.append(argumentNode.image);
            }
        }
    }
    methodStringBuilder.append(argumentStringBuilder);
    // close parens in method
    methodStringBuilder.append(")");
    sb.append(methodStringBuilder);
    return sb;
}
Also used : ASTStringLiteral(org.apache.commons.jexl2.parser.ASTStringLiteral) DatawaveFatalQueryException(datawave.query.exceptions.DatawaveFatalQueryException) QueryException(datawave.webservice.query.exception.QueryException) ASTFunctionNode(org.apache.commons.jexl2.parser.ASTFunctionNode) DatawaveFatalQueryException(datawave.query.exceptions.DatawaveFatalQueryException) JexlNode(org.apache.commons.jexl2.parser.JexlNode) ASTReference(org.apache.commons.jexl2.parser.ASTReference) ASTNumberLiteral(org.apache.commons.jexl2.parser.ASTNumberLiteral)

Example 20 with ASTReference

use of org.apache.commons.jexl3.parser.ASTReference in project datawave by NationalSecurityAgency.

the class JexlStringBuildingVisitor method visit.

public Object visit(ASTStringLiteral node, Object data) {
    StringBuilder sb = (StringBuilder) data;
    String literal = node.image;
    JexlNode parent = node;
    do {
        parent = parent.jjtGetParent();
    } while (parent instanceof ASTReference);
    // visitor can be correctly parsed back into the current query tree.
    if (!(parent instanceof ASTERNode || parent instanceof ASTNRNode))
        literal = literal.replace(JexlASTHelper.SINGLE_BACKSLASH, JexlASTHelper.DOUBLE_BACKSLASH);
    int index = literal.indexOf(STRING_QUOTE);
    if (-1 != index) {
        // Slightly larger buffer
        int begin = 0;
        StringBuilder builder = new StringBuilder(literal.length() + 10);
        // Find every single quote and escape it
        while (-1 != index) {
            builder.append(literal.substring(begin, index));
            builder.append(BACKSLASH).append(STRING_QUOTE);
            begin = index + 1;
            index = literal.indexOf(STRING_QUOTE, begin);
        }
        // Tack on the end of the literal
        builder.append(literal.substring(begin));
        // Set the new version on the literal
        literal = builder.toString();
    }
    sb.append(STRING_QUOTE).append(literal).append(STRING_QUOTE);
    node.childrenAccept(this, sb);
    return sb;
}
Also used : ASTERNode(org.apache.commons.jexl2.parser.ASTERNode) ASTNRNode(org.apache.commons.jexl2.parser.ASTNRNode) JexlNode(org.apache.commons.jexl2.parser.JexlNode) ASTReference(org.apache.commons.jexl2.parser.ASTReference)

Aggregations

ASTReference (org.apache.commons.jexl2.parser.ASTReference)28 JexlNode (org.apache.commons.jexl2.parser.JexlNode)17 ASTReferenceExpression (org.apache.commons.jexl2.parser.ASTReferenceExpression)11 ASTIdentifier (org.apache.commons.jexl2.parser.ASTIdentifier)8 ASTAndNode (org.apache.commons.jexl2.parser.ASTAndNode)7 ASTOrNode (org.apache.commons.jexl2.parser.ASTOrNode)6 ASTStringLiteral (org.apache.commons.jexl2.parser.ASTStringLiteral)6 ASTEQNode (org.apache.commons.jexl2.parser.ASTEQNode)5 ArrayList (java.util.ArrayList)4 ASTERNode (org.apache.commons.jexl2.parser.ASTERNode)4 ASTNRNode (org.apache.commons.jexl2.parser.ASTNRNode)4 ASTIdentifierAccess (org.apache.commons.jexl3.parser.ASTIdentifierAccess)4 ExceededValueThresholdMarkerJexlNode (datawave.query.jexl.nodes.ExceededValueThresholdMarkerJexlNode)3 List (java.util.List)3 ASTAssignment (org.apache.commons.jexl2.parser.ASTAssignment)3 ASTFunctionNode (org.apache.commons.jexl2.parser.ASTFunctionNode)3 ASTJexlScript (org.apache.commons.jexl2.parser.ASTJexlScript)3 ASTNumberLiteral (org.apache.commons.jexl2.parser.ASTNumberLiteral)3 ASTIdentifier (org.apache.commons.jexl3.parser.ASTIdentifier)3 ASTReference (org.apache.commons.jexl3.parser.ASTReference)3