Search in sources :

Example 11 with RuleBuildContext

use of org.drools.compiler.rule.builder.RuleBuildContext in project drools by kiegroup.

the class MVELDialect method getMVELCompilationUnit.

public static MVELCompilationUnit getMVELCompilationUnit(final String expression, final AnalysisResult analysis, Declaration[] previousDeclarations, Declaration[] localDeclarations, final Map<String, Class<?>> otherInputVariables, final PackageBuildContext context, String contextIndeifier, Class kcontextClass, boolean readLocalsFromTuple, MVELCompilationUnit.Scope scope) {
    Map<String, Class> resolvedInputs = new LinkedHashMap<String, Class>();
    List<String> ids = new ArrayList<String>();
    if (analysis.getBoundIdentifiers().getThisClass() != null || (localDeclarations != null && localDeclarations.length > 0)) {
        Class cls = analysis.getBoundIdentifiers().getThisClass();
        ids.add("this");
        resolvedInputs.put("this", // the only time cls is null is in accumumulate's acc/reverse
        (cls != null) ? cls : Object.class);
    }
    ids.add(contextIndeifier);
    resolvedInputs.put(contextIndeifier, kcontextClass);
    ids.add("kcontext");
    resolvedInputs.put("kcontext", kcontextClass);
    if (scope.hasRule()) {
        ids.add("rule");
        resolvedInputs.put("rule", Rule.class);
    }
    List<String> strList = new ArrayList<String>();
    for (String identifier : analysis.getIdentifiers()) {
        Class<?> type = identifier.equals(WM_ARGUMENT) ? InternalWorkingMemory.class : analysis.getBoundIdentifiers().resolveVarType(identifier);
        if (type != null) {
            strList.add(identifier);
            ids.add(identifier);
            resolvedInputs.put(identifier, type);
        }
    }
    String[] globalIdentifiers = strList.toArray(new String[strList.size()]);
    strList.clear();
    for (String op : analysis.getBoundIdentifiers().getOperators().keySet()) {
        strList.add(op);
        ids.add(op);
        resolvedInputs.put(op, EvaluatorWrapper.class);
    }
    EvaluatorWrapper[] operators = new EvaluatorWrapper[strList.size()];
    for (int i = 0; i < operators.length; i++) {
        operators[i] = analysis.getBoundIdentifiers().getOperators().get(strList.get(i));
    }
    if (previousDeclarations != null) {
        for (Declaration decl : previousDeclarations) {
            if (analysis.getBoundIdentifiers().getDeclrClasses().containsKey(decl.getIdentifier())) {
                ids.add(decl.getIdentifier());
                resolvedInputs.put(decl.getIdentifier(), decl.getDeclarationClass());
            }
        }
    }
    if (localDeclarations != null) {
        for (Declaration decl : localDeclarations) {
            if (analysis.getBoundIdentifiers().getDeclrClasses().containsKey(decl.getIdentifier())) {
                ids.add(decl.getIdentifier());
                resolvedInputs.put(decl.getIdentifier(), decl.getDeclarationClass());
            }
        }
    }
    // "not bound" identifiers could be drools, kcontext and rule
    // but in the case of accumulate it could be vars from the "init" section.
    // String[] otherIdentifiers = otherInputVariables == null ? new String[]{} : new String[otherInputVariables.size()];
    strList = new ArrayList<String>();
    if (otherInputVariables != null) {
        MVELAnalysisResult mvelAnalysis = (MVELAnalysisResult) analysis;
        for (Entry<String, Class<?>> stringClassEntry : otherInputVariables.entrySet()) {
            if ((!analysis.getNotBoundedIdentifiers().contains(stringClassEntry.getKey()) && !mvelAnalysis.getMvelVariables().keySet().contains(stringClassEntry.getKey())) || "rule".equals(stringClassEntry.getKey())) {
                // and rule was already included
                continue;
            }
            ids.add(stringClassEntry.getKey());
            strList.add(stringClassEntry.getKey());
            resolvedInputs.put(stringClassEntry.getKey(), stringClassEntry.getValue());
        }
    }
    String[] otherIdentifiers = strList.toArray(new String[strList.size()]);
    String[] inputIdentifiers = new String[resolvedInputs.size()];
    String[] inputTypes = new String[resolvedInputs.size()];
    int i = 0;
    for (String id : ids) {
        inputIdentifiers[i] = id;
        inputTypes[i++] = resolvedInputs.get(id).getName();
    }
    String name;
    if (context != null && context.getPkg() != null && context.getPkg().getName() != null) {
        if (context instanceof RuleBuildContext) {
            name = context.getPkg().getName() + "." + ((RuleBuildContext) context).getRuleDescr().getClassName();
        } else {
            name = context.getPkg().getName() + ".Unknown";
        }
    } else {
        name = "Unknown";
    }
    return new MVELCompilationUnit(name, expression, globalIdentifiers, operators, previousDeclarations, localDeclarations, otherIdentifiers, inputIdentifiers, inputTypes, ((MVELAnalysisResult) analysis).isTypesafe(), readLocalsFromTuple);
}
Also used : EvaluatorWrapper(org.drools.compiler.rule.builder.EvaluatorWrapper) RuleBuildContext(org.drools.compiler.rule.builder.RuleBuildContext) ArrayList(java.util.ArrayList) MVELCompilationUnit(org.drools.mvel.expr.MVELCompilationUnit) LinkedHashMap(java.util.LinkedHashMap) Declaration(org.drools.core.rule.Declaration)

Example 12 with RuleBuildContext

use of org.drools.compiler.rule.builder.RuleBuildContext 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 13 with RuleBuildContext

use of org.drools.compiler.rule.builder.RuleBuildContext in project drools by kiegroup.

the class RuleBuilderTest method testBuildDurationExpression.

@Test
public void testBuildDurationExpression() throws Exception {
    // creates mock objects
    final RuleBuildContext context = mock(RuleBuildContext.class);
    final RuleImpl rule = mock(RuleImpl.class);
    // creates input object
    final RuleDescr ruleDescr = new RuleDescr("my rule");
    ruleDescr.addAttribute(new AttributeDescr("duration", "( 1h30m )"));
    ruleDescr.addAttribute(new AttributeDescr("calendars", "[\"cal1\", \"cal2\"]"));
    // defining expectations on the mock object
    when(context.getRule()).thenReturn(rule);
    when(context.getRuleDescr()).thenReturn(ruleDescr);
    // calling the build method
    RuleBuilder.buildAttributes(context);
    // check expectations
    verify(rule).setTimer(new IntervalTimer(null, null, -1, TimeUtils.parseTimeString("1h30m"), 0));
    verify(rule).setCalendars(new String[] { "cal1", "cal2" });
}
Also used : RuleBuildContext(org.drools.compiler.rule.builder.RuleBuildContext) RuleDescr(org.drools.drl.ast.descr.RuleDescr) IntervalTimer(org.drools.core.time.impl.IntervalTimer) RuleImpl(org.drools.core.definitions.rule.impl.RuleImpl) AttributeDescr(org.drools.drl.ast.descr.AttributeDescr) Test(org.junit.Test)

Example 14 with RuleBuildContext

use of org.drools.compiler.rule.builder.RuleBuildContext in project drools by kiegroup.

the class RuleBuilderTest method testBuildMetaAttributes.

@Test
public void testBuildMetaAttributes() throws Exception {
    // creates mock objects
    final RuleBuildContext context = mock(RuleBuildContext.class);
    final RuleImpl rule = mock(RuleImpl.class);
    // creates input object
    final RuleDescr ruleDescr = new RuleDescr("my rule");
    ruleDescr.addAnnotation("ruleId", "123");
    ruleDescr.addAnnotation("author", "Bob Doe");
    ruleDescr.addAnnotation("text", "\"It's a quoted\\\" string\"");
    // creates expected results
    // defining expectations on the mock object
    when(context.getRule()).thenReturn(rule);
    when(context.getRuleDescr()).thenReturn(ruleDescr);
    when(context.getKnowledgeBuilder()).thenReturn(new KnowledgeBuilderImpl());
    // calling the build method
    RuleBuilder.buildMetaAttributes(context);
    // check expectations
    verify(rule).addMetaAttribute("ruleId", 123);
    verify(rule).addMetaAttribute("author", "Bob Doe");
    verify(rule).addMetaAttribute("text", "It's a quoted\" string");
}
Also used : RuleBuildContext(org.drools.compiler.rule.builder.RuleBuildContext) KnowledgeBuilderImpl(org.drools.compiler.builder.impl.KnowledgeBuilderImpl) RuleDescr(org.drools.drl.ast.descr.RuleDescr) RuleImpl(org.drools.core.definitions.rule.impl.RuleImpl) Test(org.junit.Test)

Example 15 with RuleBuildContext

use of org.drools.compiler.rule.builder.RuleBuildContext in project drools by kiegroup.

the class MVELAccumulateBuilderTest method testSimpleExpression.

@Test
public void testSimpleExpression() {
    KnowledgeBuilderImpl pkgBuilder = new KnowledgeBuilderImpl();
    pkgBuilder.addPackage(new PackageDescr("pkg1"));
    InternalKnowledgePackage pkg = pkgBuilder.getPackage("pkg1");
    final RuleDescr ruleDescr = new RuleDescr("rule 1");
    final KnowledgeBuilderConfigurationImpl conf = pkgBuilder.getBuilderConfiguration();
    DialectCompiletimeRegistry dialectRegistry = pkgBuilder.getPackageRegistry(pkg.getName()).getDialectCompiletimeRegistry();
    MVELDialect mvelDialect = (MVELDialect) dialectRegistry.getDialect("mvel");
    final RuleBuildContext context = new RuleBuildContext(pkgBuilder, ruleDescr, dialectRegistry, pkg, mvelDialect);
    final AccumulateDescr accDescr = new AccumulateDescr();
    final PatternDescr inputPattern = new PatternDescr("org.drools.mvel.compiler.Cheese", "$cheese");
    accDescr.setInputPattern(inputPattern);
    accDescr.setInitCode("total = 0;");
    accDescr.setActionCode("total += $cheese.price;");
    accDescr.setReverseCode("total -= $cheese.price;");
    accDescr.setResultCode("new Integer(total)");
    final MVELAccumulateBuilder builder = new MVELAccumulateBuilder();
    final Accumulate acc = (Accumulate) builder.build(context, accDescr);
    ((MVELCompileable) acc.getAccumulators()[0]).compile((MVELDialectRuntimeData) pkgBuilder.getPackageRegistry(pkg.getName()).getDialectRuntimeRegistry().getDialectData("mvel"));
    InternalKnowledgeBase kBase = KnowledgeBaseFactory.newKnowledgeBase();
    StatefulKnowledgeSessionImpl ksession = (StatefulKnowledgeSessionImpl) kBase.newKieSession();
    BuildContext buildContext = new BuildContext(kBase, Collections.emptyList());
    MockLeftTupleSink sink = new MockLeftTupleSink(buildContext);
    MockTupleSource source = new MockTupleSource(1, buildContext);
    source.setObjectCount(1);
    sink.setLeftTupleSource(source);
    final Cheese cheddar1 = new Cheese("cheddar", 10);
    final Cheese cheddar2 = new Cheese("cheddar", 8);
    final InternalFactHandle f0 = (InternalFactHandle) ksession.insert(new InitialFactImpl());
    final InternalFactHandle f1 = (InternalFactHandle) ksession.insert(cheddar1);
    final InternalFactHandle f2 = (InternalFactHandle) ksession.insert(cheddar2);
    final LeftTupleImpl tuple = new LeftTupleImpl(f0, sink, true);
    Object wmContext = acc.createWorkingMemoryContext();
    AccumulateNode.AccumulateContext accContext = new AccumulateNode.AccumulateContext();
    Object funcContext = acc.createFunctionContext();
    funcContext = acc.init(wmContext, accContext, funcContext, tuple, ksession);
    accContext.setFunctionContext(funcContext);
    Object value1 = acc.accumulate(wmContext, accContext, tuple, f1, ksession);
    acc.accumulate(wmContext, accContext, tuple, f2, ksession);
    assertEquals(new Integer(18), acc.getResult(wmContext, accContext, tuple, ksession));
    LeftTuple match = new FromNodeLeftTuple();
    match.setContextObject(value1);
    acc.tryReverse(wmContext, accContext, tuple, f1, null, match, ksession);
    assertEquals(new Integer(8), acc.getResult(wmContext, accContext, tuple, ksession));
}
Also used : MVELCompileable(org.drools.mvel.expr.MVELCompileable) PatternDescr(org.drools.drl.ast.descr.PatternDescr) KnowledgeBuilderConfigurationImpl(org.drools.compiler.builder.impl.KnowledgeBuilderConfigurationImpl) AccumulateNode(org.drools.core.reteoo.AccumulateNode) MockLeftTupleSink(org.drools.core.reteoo.MockLeftTupleSink) Cheese(org.drools.mvel.compiler.Cheese) AccumulateDescr(org.drools.drl.ast.descr.AccumulateDescr) LeftTuple(org.drools.core.reteoo.LeftTuple) FromNodeLeftTuple(org.drools.core.reteoo.FromNodeLeftTuple) Accumulate(org.drools.core.rule.Accumulate) MVELAccumulateBuilder(org.drools.mvel.builder.MVELAccumulateBuilder) FromNodeLeftTuple(org.drools.core.reteoo.FromNodeLeftTuple) MockTupleSource(org.drools.core.reteoo.MockTupleSource) LeftTupleImpl(org.drools.core.reteoo.LeftTupleImpl) PackageDescr(org.drools.drl.ast.descr.PackageDescr) InternalFactHandle(org.drools.core.common.InternalFactHandle) InternalKnowledgeBase(org.drools.kiesession.rulebase.InternalKnowledgeBase) RuleBuildContext(org.drools.compiler.rule.builder.RuleBuildContext) DialectCompiletimeRegistry(org.drools.compiler.compiler.DialectCompiletimeRegistry) MVELDialect(org.drools.mvel.builder.MVELDialect) InitialFactImpl(org.drools.core.reteoo.InitialFactImpl) BuildContext(org.drools.core.reteoo.builder.BuildContext) RuleBuildContext(org.drools.compiler.rule.builder.RuleBuildContext) KnowledgeBuilderImpl(org.drools.compiler.builder.impl.KnowledgeBuilderImpl) StatefulKnowledgeSessionImpl(org.drools.kiesession.session.StatefulKnowledgeSessionImpl) RuleDescr(org.drools.drl.ast.descr.RuleDescr) InternalKnowledgePackage(org.drools.core.definitions.InternalKnowledgePackage) Test(org.junit.Test)

Aggregations

RuleBuildContext (org.drools.compiler.rule.builder.RuleBuildContext)35 KnowledgeBuilderImpl (org.drools.compiler.builder.impl.KnowledgeBuilderImpl)24 DialectCompiletimeRegistry (org.drools.compiler.compiler.DialectCompiletimeRegistry)23 InternalKnowledgePackage (org.drools.core.definitions.InternalKnowledgePackage)22 Test (org.junit.Test)18 RuleDescr (org.drools.drl.ast.descr.RuleDescr)17 Pattern (org.drools.core.rule.Pattern)16 ClassObjectType (org.drools.core.base.ClassObjectType)15 RuleImpl (org.drools.core.definitions.rule.impl.RuleImpl)15 KnowledgeBuilderConfigurationImpl (org.drools.compiler.builder.impl.KnowledgeBuilderConfigurationImpl)14 Declaration (org.drools.core.rule.Declaration)14 RuleDescr (org.drools.compiler.lang.descr.RuleDescr)13 HashMap (java.util.HashMap)12 PackageRegistry (org.drools.compiler.compiler.PackageRegistry)11 ImportDeclaration (org.drools.core.rule.ImportDeclaration)11 InternalFactHandle (org.drools.core.common.InternalFactHandle)8 KnowledgePackageImpl (org.drools.core.definitions.impl.KnowledgePackageImpl)8 LeftTupleImpl (org.drools.core.reteoo.LeftTupleImpl)8 ObjectType (org.drools.core.spi.ObjectType)7 InternalReadAccessor (org.drools.core.spi.InternalReadAccessor)6