Search in sources :

Example 16 with BaseDescr

use of org.drools.drl.ast.descr.BaseDescr in project drools by kiegroup.

the class MVELExprAnalyzer method analyzeExpression.

// ------------------------------------------------------------
// Instance methods
// ------------------------------------------------------------
/**
 * Analyze an expression.
 *
 * @param expr
 *            The expression to analyze.
 * @param availableIdentifiers
 *            Total set of declarations available.
 *
 * @return The <code>Set</code> of declarations used by the expression.
 * @throws RecognitionException
 *             If an error occurs in the parser.
 */
@SuppressWarnings("unchecked")
public static MVELAnalysisResult analyzeExpression(final PackageBuildContext context, final String expr, final BoundIdentifiers availableIdentifiers, final Map<String, Class<?>> localTypes, String contextIdentifier, Class kcontextClass) {
    if (expr.trim().length() <= 0) {
        MVELAnalysisResult result = analyze((Set<String>) Collections.EMPTY_SET, availableIdentifiers);
        result.setMvelVariables(new HashMap<String, Class<?>>());
        result.setTypesafe(true);
        return result;
    }
    MVEL.COMPILER_OPT_ALLOW_NAKED_METH_CALL = true;
    MVEL.COMPILER_OPT_ALLOW_OVERRIDE_ALL_PROPHANDLING = true;
    MVEL.COMPILER_OPT_ALLOW_RESOLVE_INNERCLASSES_WITH_DOTNOTATION = true;
    MVEL.COMPILER_OPT_SUPPORT_JAVA_STYLE_CLASS_LITERALS = true;
    MVELDialect dialect = (MVELDialect) context.getDialect("mvel");
    ParserConfiguration conf = getMVELDialectRuntimeData(context).getParserConfiguration();
    conf.setClassLoader(context.getKnowledgeBuilder().getRootClassLoader());
    // first compilation is for verification only
    // @todo proper source file name
    final ParserContext parserContext1 = new ParserContext(conf);
    if (localTypes != null) {
        for (Entry entry : localTypes.entrySet()) {
            parserContext1.addInput((String) entry.getKey(), (Class) entry.getValue());
        }
    }
    if (availableIdentifiers.getThisClass() != null) {
        parserContext1.addInput("this", availableIdentifiers.getThisClass());
    }
    if (availableIdentifiers.getOperators() != null) {
        for (Entry<String, EvaluatorWrapper> opEntry : availableIdentifiers.getOperators().entrySet()) {
            parserContext1.addInput(opEntry.getKey(), opEntry.getValue().getClass());
        }
    }
    parserContext1.setStrictTypeEnforcement(false);
    parserContext1.setStrongTyping(false);
    Class<?> returnType;
    try {
        returnType = MVEL.analyze(expr, parserContext1);
    } catch (Exception e) {
        BaseDescr base = (context instanceof RuleBuildContext) ? ((RuleBuildContext) context).getRuleDescr() : context.getParentDescr();
        if (e instanceof CompileException && e.getCause() != null && e.getMessage().startsWith("[Error: null]")) {
            // rewrite error message in cause original message is null
            e = new CompileException(e.getCause().toString(), ((CompileException) e).getExpr(), ((CompileException) e).getCursor(), e.getCause());
        }
        AsmUtil.copyErrorLocation(e, context.getParentDescr());
        context.addError(new DescrBuildError(base, context.getParentDescr(), null, "Unable to Analyse Expression " + expr + ":\n" + e.getMessage()));
        return null;
    }
    Set<String> requiredInputs = new HashSet<String>();
    requiredInputs.addAll(parserContext1.getInputs().keySet());
    HashMap<String, Class<?>> variables = (HashMap<String, Class<?>>) ((Map) parserContext1.getVariables());
    if (localTypes != null) {
        for (String str : localTypes.keySet()) {
            // we have to do this due to mvel regressions on detecting true local vars
            variables.remove(str);
        }
    }
    // MVEL includes direct fields of context object in non-strict mode. so we need to strip those
    if (availableIdentifiers.getThisClass() != null) {
        requiredInputs.removeIf(s -> PropertyTools.getFieldOrAccessor(availableIdentifiers.getThisClass(), s) != null);
    }
    // now, set the required input types and compile again
    final ParserContext parserContext2 = new ParserContext(conf);
    parserContext2.setStrictTypeEnforcement(true);
    parserContext2.setStrongTyping(true);
    for (String input : requiredInputs) {
        if ("this".equals(input)) {
            continue;
        }
        if (WM_ARGUMENT.equals(input)) {
            parserContext2.addInput(input, InternalWorkingMemory.class);
            continue;
        }
        Class<?> cls = availableIdentifiers.resolveType(input);
        if (cls == null) {
            if (input.equals(contextIdentifier) || input.equals("kcontext")) {
                cls = kcontextClass;
            } else if (input.equals("rule")) {
                cls = Rule.class;
            } else if (localTypes != null) {
                cls = localTypes.get(input);
            }
        }
        if (cls != null) {
            parserContext2.addInput(input, cls);
        }
    }
    if (availableIdentifiers.getThisClass() != null) {
        parserContext2.addInput("this", availableIdentifiers.getThisClass());
    }
    boolean typesafe = context.isTypesafe();
    try {
        returnType = MVEL.analyze(expr, parserContext2);
        typesafe = true;
    } catch (Exception e) {
        // is this an error, or can we fall back to non-typesafe mode?
        if (typesafe) {
            BaseDescr base = (context instanceof RuleBuildContext) ? ((RuleBuildContext) context).getRuleDescr() : context.getParentDescr();
            AsmUtil.copyErrorLocation(e, context.getParentDescr());
            context.addError(new DescrBuildError(base, context.getParentDescr(), null, "Unable to Analyse Expression " + expr + ":\n" + e.getMessage()));
            return null;
        }
    }
    if (typesafe) {
        requiredInputs = new HashSet<String>();
        requiredInputs.addAll(parserContext2.getInputs().keySet());
        requiredInputs.addAll(variables.keySet());
        variables = (HashMap<String, Class<?>>) ((Map) parserContext2.getVariables());
        if (localTypes != null) {
            for (String str : localTypes.keySet()) {
                // we have to do this due to mvel regressions on detecting true local vars
                variables.remove(str);
            }
        }
    }
    MVELAnalysisResult result = analyze(requiredInputs, availableIdentifiers);
    result.setReturnType(returnType);
    result.setMvelVariables(variables);
    result.setTypesafe(typesafe);
    return result;
}
Also used : EvaluatorWrapper(org.drools.compiler.rule.builder.EvaluatorWrapper) RuleBuildContext(org.drools.compiler.rule.builder.RuleBuildContext) HashMap(java.util.HashMap) CompileException(org.mvel2.CompileException) RecognitionException(org.antlr.runtime.RecognitionException) ParserConfiguration(org.mvel2.ParserConfiguration) Entry(java.util.Map.Entry) DescrBuildError(org.drools.compiler.compiler.DescrBuildError) CompileException(org.mvel2.CompileException) BaseDescr(org.drools.drl.ast.descr.BaseDescr) Rule(org.kie.api.definition.rule.Rule) ParserContext(org.mvel2.ParserContext) HashMap(java.util.HashMap) Map(java.util.Map) HashSet(java.util.HashSet)

Example 17 with BaseDescr

use of org.drools.drl.ast.descr.BaseDescr in project drools by kiegroup.

the class DescrDumper method processConnectiveDescr.

protected void processConnectiveDescr(StringBuilder sbuilder, BaseDescr base, int parentPriority, boolean isInsideRelCons, DumperContext context) {
    ConstraintConnectiveDescr ccd = (ConstraintConnectiveDescr) base;
    boolean wrapParenthesis = parentPriority > ccd.getConnective().getPrecedence();
    if (wrapParenthesis) {
        sbuilder.append("( ");
    }
    boolean first = true;
    List<BaseDescr> descrs = new ArrayList<>(ccd.getDescrs());
    for (BaseDescr constr : descrs) {
        if (!(constr instanceof BindingDescr)) {
            if (first) {
                first = false;
            } else {
                sbuilder.append(" ");
                sbuilder.append(ccd.getConnective().toString());
                sbuilder.append(" ");
            }
        }
        context.incOpenCcd();
        dump(sbuilder, constr, ccd, ccd.getDescrs().indexOf(constr), ccd.getConnective().getPrecedence(), isInsideRelCons, context);
        context.decOpenCcd();
    }
    if (first) {
        // means all children were actually only bindings, replace by just true
        sbuilder.append("true");
    }
    if (wrapParenthesis) {
        sbuilder.append(" )");
    }
}
Also used : BindingDescr(org.drools.drl.ast.descr.BindingDescr) ArrayList(java.util.ArrayList) BaseDescr(org.drools.drl.ast.descr.BaseDescr) ConstraintConnectiveDescr(org.drools.drl.ast.descr.ConstraintConnectiveDescr)

Example 18 with BaseDescr

use of org.drools.drl.ast.descr.BaseDescr in project drools by kiegroup.

the class DescrDumper method processNullSafeDereferencing.

private String[] processNullSafeDereferencing(String expr, AtomicExprDescr atomicExpr, ConstraintConnectiveDescr ccd, int nullSafePos, int parentIdx, int childIdx) {
    // convert "field1!.field2" in ["field1 != null && ", "field1.field2"]
    String field1 = expr.substring(0, nullSafePos).trim();
    expr = field1 + "." + expr.substring(nullSafePos + 2).trim();
    RelationalExprDescr check = new RelationalExprDescr("!=", false, null, new AtomicExprDescr(getPreconditionsToAppend(field1)), new AtomicExprDescr("null"));
    if (ccd.getConnective() == ConnectiveType.AND || ccd.getConnective() == ConnectiveType.INC_AND) {
        ccd.getDescrs().add(childIdx, check);
    } else {
        BaseDescr desc = ccd.getDescrs().get(parentIdx);
        if (desc instanceof ConstraintConnectiveDescr) {
            ((ConstraintConnectiveDescr) desc).getDescrs().add(childIdx, check);
        } else {
            ConstraintConnectiveDescr localAnd = new ConstraintConnectiveDescr(ConnectiveType.AND);
            BaseDescr original = ccd.getDescrs().remove(parentIdx);
            localAnd.getDescrs().add(check);
            localAnd.getDescrs().add(original);
            ccd.getDescrs().add(parentIdx, localAnd);
        }
    }
    String innerCheck = check + " && ";
    String[] nullCheckAndExpr = new String[] { innerCheck, expr };
    atomicExpr.setRewrittenExpression(expr);
    return nullCheckAndExpr;
}
Also used : AtomicExprDescr(org.drools.drl.ast.descr.AtomicExprDescr) BaseDescr(org.drools.drl.ast.descr.BaseDescr) ConstraintConnectiveDescr(org.drools.drl.ast.descr.ConstraintConnectiveDescr) RelationalExprDescr(org.drools.drl.ast.descr.RelationalExprDescr)

Example 19 with BaseDescr

use of org.drools.drl.ast.descr.BaseDescr in project drools by kiegroup.

the class DRL6Expressions method andExpression.

// $ANTLR end "exclusiveOrExpression"
// $ANTLR start "andExpression"
// src/main/resources/org/drools/compiler/lang/DRL6Expressions.g:286:1: andExpression returns [BaseDescr result] : left= equalityExpression ( AMPER right= equalityExpression )* ;
public final BaseDescr andExpression() throws RecognitionException {
    BaseDescr result = null;
    BaseDescr left = null;
    BaseDescr right = null;
    try {
        // src/main/resources/org/drools/compiler/lang/DRL6Expressions.g:287:3: (left= equalityExpression ( AMPER right= equalityExpression )* )
        // src/main/resources/org/drools/compiler/lang/DRL6Expressions.g:287:5: left= equalityExpression ( AMPER right= equalityExpression )*
        {
            pushFollow(FOLLOW_equalityExpression_in_andExpression1430);
            left = equalityExpression();
            state._fsp--;
            if (state.failed)
                return result;
            if (state.backtracking == 0) {
                if (buildDescr) {
                    result = left;
                }
            }
            // src/main/resources/org/drools/compiler/lang/DRL6Expressions.g:288:3: ( AMPER right= equalityExpression )*
            loop30: while (true) {
                int alt30 = 2;
                int LA30_0 = input.LA(1);
                if ((LA30_0 == AMPER)) {
                    alt30 = 1;
                }
                switch(alt30) {
                    case 1:
                        // src/main/resources/org/drools/compiler/lang/DRL6Expressions.g:288:5: AMPER right= equalityExpression
                        {
                            match(input, AMPER, FOLLOW_AMPER_in_andExpression1438);
                            if (state.failed)
                                return result;
                            pushFollow(FOLLOW_equalityExpression_in_andExpression1442);
                            right = equalityExpression();
                            state._fsp--;
                            if (state.failed)
                                return result;
                            if (state.backtracking == 0) {
                                if (buildDescr) {
                                    ConstraintConnectiveDescr descr = ConstraintConnectiveDescr.newIncAnd();
                                    descr.addOrMerge(result);
                                    descr.addOrMerge(right);
                                    result = descr;
                                }
                            }
                        }
                        break;
                    default:
                        break loop30;
                }
            }
        }
    } catch (RecognitionException re) {
        throw re;
    } finally {
    // do for sure before leaving
    }
    return result;
}
Also used : BaseDescr(org.drools.drl.ast.descr.BaseDescr) ConstraintConnectiveDescr(org.drools.drl.ast.descr.ConstraintConnectiveDescr)

Example 20 with BaseDescr

use of org.drools.drl.ast.descr.BaseDescr in project drools by kiegroup.

the class DRL6Expressions method relationalExpression.

// $ANTLR start "relationalExpression"
// src/main/resources/org/drools/compiler/lang/DRL6Expressions.g:368:1: relationalExpression returns [BaseDescr result] : left= shiftExpression ( ( operator | LEFT_PAREN )=>right= orRestriction )* ;
public final BaseDescr relationalExpression() throws RecognitionException {
    relationalExpression_stack.push(new relationalExpression_scope());
    BaseDescr result = null;
    ParserRuleReturnScope left = null;
    BaseDescr right = null;
    relationalExpression_stack.peek().lsd = null;
    try {
        // src/main/resources/org/drools/compiler/lang/DRL6Expressions.g:371:3: (left= shiftExpression ( ( operator | LEFT_PAREN )=>right= orRestriction )* )
        // src/main/resources/org/drools/compiler/lang/DRL6Expressions.g:371:5: left= shiftExpression ( ( operator | LEFT_PAREN )=>right= orRestriction )*
        {
            pushFollow(FOLLOW_shiftExpression_in_relationalExpression1832);
            left = shiftExpression();
            state._fsp--;
            if (state.failed)
                return result;
            if (state.backtracking == 0) {
                if (buildDescr) {
                    if ((left != null ? ((DRL6Expressions.shiftExpression_return) left).result : null) == null) {
                        result = new AtomicExprDescr((left != null ? input.toString(left.start, left.stop) : null));
                    } else if ((left != null ? ((DRL6Expressions.shiftExpression_return) left).result : null) instanceof AtomicExprDescr) {
                        if ((left != null ? input.toString(left.start, left.stop) : null).equals(((AtomicExprDescr) (left != null ? ((DRL6Expressions.shiftExpression_return) left).result : null)).getExpression())) {
                            result = (left != null ? ((DRL6Expressions.shiftExpression_return) left).result : null);
                        } else {
                            result = new AtomicExprDescr((left != null ? input.toString(left.start, left.stop) : null));
                        }
                    } else if ((left != null ? ((DRL6Expressions.shiftExpression_return) left).result : null) instanceof BindingDescr) {
                        if ((left != null ? input.toString(left.start, left.stop) : null).equals(((BindingDescr) (left != null ? ((DRL6Expressions.shiftExpression_return) left).result : null)).getExpression())) {
                            result = (left != null ? ((DRL6Expressions.shiftExpression_return) left).result : null);
                        } else {
                            BindingDescr bind = (BindingDescr) (left != null ? ((DRL6Expressions.shiftExpression_return) left).result : null);
                            int offset = bind.isUnification() ? 2 : 1;
                            String fullExpression = (left != null ? input.toString(left.start, left.stop) : null).substring((left != null ? input.toString(left.start, left.stop) : null).indexOf(":") + offset).trim();
                            result = new BindingDescr(bind.getVariable(), bind.getExpression(), fullExpression, bind.isUnification());
                        }
                    } else {
                        result = (left != null ? ((DRL6Expressions.shiftExpression_return) left).result : null);
                    }
                    relationalExpression_stack.peek().lsd = result;
                }
            }
            // src/main/resources/org/drools/compiler/lang/DRL6Expressions.g:396:3: ( ( operator | LEFT_PAREN )=>right= orRestriction )*
            loop37: while (true) {
                int alt37 = 2;
                int LA37_0 = input.LA(1);
                if ((LA37_0 == ID)) {
                    int LA37_2 = input.LA(2);
                    if ((((((helper.validateIdentifierKey(DroolsSoftKeywords.NOT))) || ((helper.isPluggableEvaluator(false)))) && synpred9_DRL6Expressions()))) {
                        alt37 = 1;
                    }
                } else if ((LA37_0 == EQUALS)) {
                    int LA37_3 = input.LA(2);
                    if ((synpred9_DRL6Expressions())) {
                        alt37 = 1;
                    }
                } else if ((LA37_0 == NOT_EQUALS)) {
                    int LA37_4 = input.LA(2);
                    if ((synpred9_DRL6Expressions())) {
                        alt37 = 1;
                    }
                } else if ((LA37_0 == LESS)) {
                    int LA37_20 = input.LA(2);
                    if ((synpred9_DRL6Expressions())) {
                        alt37 = 1;
                    }
                } else if ((LA37_0 == GREATER)) {
                    int LA37_21 = input.LA(2);
                    if ((synpred9_DRL6Expressions())) {
                        alt37 = 1;
                    }
                } else if ((LA37_0 == TILDE) && (synpred9_DRL6Expressions())) {
                    alt37 = 1;
                } else if ((LA37_0 == LESS_EQUALS) && (synpred9_DRL6Expressions())) {
                    alt37 = 1;
                } else if ((LA37_0 == GREATER_EQUALS) && (synpred9_DRL6Expressions())) {
                    alt37 = 1;
                } else if ((LA37_0 == LEFT_PAREN) && (synpred9_DRL6Expressions())) {
                    alt37 = 1;
                }
                switch(alt37) {
                    case 1:
                        // src/main/resources/org/drools/compiler/lang/DRL6Expressions.g:396:5: ( operator | LEFT_PAREN )=>right= orRestriction
                        {
                            pushFollow(FOLLOW_orRestriction_in_relationalExpression1857);
                            right = orRestriction();
                            state._fsp--;
                            if (state.failed)
                                return result;
                            if (state.backtracking == 0) {
                                if (buildDescr) {
                                    result = right;
                                    relationalExpression_stack.peek().lsd = result;
                                }
                            }
                        }
                        break;
                    default:
                        break loop37;
                }
            }
        }
    } catch (RecognitionException re) {
        throw re;
    } finally {
        // do for sure before leaving
        relationalExpression_stack.pop();
    }
    return result;
}
Also used : BindingDescr(org.drools.drl.ast.descr.BindingDescr) BaseDescr(org.drools.drl.ast.descr.BaseDescr) AtomicExprDescr(org.drools.drl.ast.descr.AtomicExprDescr)

Aggregations

BaseDescr (org.drools.drl.ast.descr.BaseDescr)117 ConstraintConnectiveDescr (org.drools.drl.ast.descr.ConstraintConnectiveDescr)23 AndDescr (org.drools.drl.ast.descr.AndDescr)18 AtomicExprDescr (org.drools.drl.ast.descr.AtomicExprDescr)17 ConditionalElementDescr (org.drools.drl.ast.descr.ConditionalElementDescr)16 PatternDescr (org.drools.drl.ast.descr.PatternDescr)15 AnnotatedBaseDescr (org.drools.drl.ast.descr.AnnotatedBaseDescr)14 BindingDescr (org.drools.drl.ast.descr.BindingDescr)13 ExprConstraintDescr (org.drools.drl.ast.descr.ExprConstraintDescr)11 Test (org.junit.Test)10 RelationalExprDescr (org.drools.drl.ast.descr.RelationalExprDescr)9 DeclareDescrBuilder (org.drools.drl.ast.dsl.DeclareDescrBuilder)9 AnnotationDescr (org.drools.drl.ast.descr.AnnotationDescr)8 CEDescrBuilder (org.drools.drl.ast.dsl.CEDescrBuilder)7 OrDescr (org.drools.drl.ast.descr.OrDescr)6 AccumulateDescrBuilder (org.drools.drl.ast.dsl.AccumulateDescrBuilder)6 AnnotatedDescrBuilder (org.drools.drl.ast.dsl.AnnotatedDescrBuilder)6 AnnotationDescrBuilder (org.drools.drl.ast.dsl.AnnotationDescrBuilder)6 AttributeDescrBuilder (org.drools.drl.ast.dsl.AttributeDescrBuilder)6 BehaviorDescrBuilder (org.drools.drl.ast.dsl.BehaviorDescrBuilder)6