Search in sources :

Example 16 with WorkingMemory

use of org.mvel2.tests.core.res.WorkingMemory in project drools by kiegroup.

the class MVELConsequence method evaluate.

@Override
public void evaluate(KnowledgeHelper knowledgeHelper, WorkingMemory workingMemory) throws Exception {
    // same as lambda consequence...
    Tuple tuple = knowledgeHelper.getTuple();
    Declaration[] declarations = ((RuleTerminalNode) knowledgeHelper.getMatch().getTuple().getTupleSink()).getRequiredDeclarations();
    Variable[] vars = consequence.getVariables();
    // ...but the facts are association of Variable and its value, preserving order.
    Map<Variable, Object> facts = new LinkedHashMap<>();
    int declrCounter = 0;
    for (Variable var : vars) {
        if (var.isFact()) {
            Declaration declaration = declarations[declrCounter++];
            InternalFactHandle fh = tuple.get(declaration);
            facts.put(var, declaration.getValue((InternalWorkingMemory) workingMemory, fh.getObject()));
        } else {
            facts.put(var, workingMemory.getGlobal(var.getName()));
        }
    }
    ScriptBlock scriptBlock = null;
    try {
        scriptBlock = (ScriptBlock) consequence.getBlock();
    } catch (ClassCastException e) {
        throw new RuntimeException("I tried to access a ScriptBlock but it was not. So something is thinking is a MVEL consequence but did not set the MVEL script textual representation", e);
    }
    String originalRHS = scriptBlock.getScript();
    String name = context.getRule().getPackageName() + "." + context.getRule().getName();
    String expression = MVELConsequenceBuilder.processMacros(originalRHS);
    String[] globalIdentifiers = new String[] {};
    String[] default_inputIdentifiers = new String[] { "this", "drools", "kcontext", "rule" };
    String[] inputIdentifiers = Stream.concat(Arrays.asList(default_inputIdentifiers).stream(), facts.entrySet().stream().map(kv -> kv.getKey().getName())).collect(Collectors.toList()).toArray(new String[] {});
    String[] default_inputTypes = new String[] { "org.drools.core.spi.KnowledgeHelper", "org.drools.core.spi.KnowledgeHelper", "org.drools.core.spi.KnowledgeHelper", "org.kie.api.definition.rule.Rule" };
    String[] inputTypes = Stream.concat(Arrays.asList(default_inputTypes).stream(), facts.entrySet().stream().map(kv -> kv.getKey().getType().getName())).collect(Collectors.toList()).toArray(new String[] {});
    // ^^ please notice about inputTypes, it is to use the Class.getName(), because is later used by the Classloader internally in MVEL to load the class,
    // do NOT replace with getCanonicalName() otherwise inner classes will not be loaded correctly.
    int languageLevel = 4;
    boolean strictMode = true;
    boolean readLocalsFromTuple = false;
    EvaluatorWrapper[] operators = new EvaluatorWrapper[] {};
    Declaration[] previousDeclarations = new Declaration[] {};
    Declaration[] localDeclarations = new Declaration[] {};
    String[] otherIdentifiers = new String[] {};
    MVELCompilationUnit cu = new MVELCompilationUnit(name, expression, globalIdentifiers, operators, previousDeclarations, localDeclarations, otherIdentifiers, inputIdentifiers, inputTypes, languageLevel, strictMode, readLocalsFromTuple);
    // TODO unfortunately the MVELDialectRuntimeData would be the one of compile time
    // the one from runtime is not helpful, in fact the dialect registry for runtime is empty:
    // MVELDialectRuntimeData runtimeData = (MVELDialectRuntimeData) context.getPkg().getDialectRuntimeRegistry().getDialectData("mvel");
    MVELDialectRuntimeData runtimeData = new MVELDialectRuntimeData();
    // this classloader will be used by the CompilationUnit to load the imports.
    runtimeData.onAdd(null, Thread.currentThread().getContextClassLoader());
    runtimeData.addPackageImport(context.getPkg().getName());
    runtimeData.addPackageImport("java.lang");
    // therefore we assume for the ScriptBlock all available KBPackages are the default available and imported for the scope of the Script itself.
    for (KiePackage kp : context.getKnowledgePackages()) {
        if (!kp.getName().equals(context.getPkg().getName())) {
            runtimeData.addPackageImport(kp.getName());
        }
    }
    // sometimes here it was passed as a 2nd argument a String?? similar to `rule R in file file.drl`
    Serializable cuResult = cu.getCompiledExpression(runtimeData);
    ExecutableStatement compiledExpression = (ExecutableStatement) cuResult;
    // TODO the part above up to the ExecutableStatement compiledExpression should be cached.
    Map<String, Object> mvelContext = new HashMap<>();
    mvelContext.put("this", knowledgeHelper);
    mvelContext.put("drools", knowledgeHelper);
    mvelContext.put("kcontext", knowledgeHelper);
    mvelContext.put("rule", knowledgeHelper.getRule());
    for (Entry<Variable, Object> kv : facts.entrySet()) {
        mvelContext.put(kv.getKey().getName(), kv.getValue());
    }
    CachingMapVariableResolverFactory cachingFactory = new CachingMapVariableResolverFactory(mvelContext);
    VariableResolverFactory factory = cu.getFactory(knowledgeHelper, ((AgendaItem) knowledgeHelper.getMatch()).getTerminalNode().getRequiredDeclarations(), knowledgeHelper.getRule(), knowledgeHelper.getTuple(), null, (InternalWorkingMemory) workingMemory, workingMemory.getGlobalResolver());
    cachingFactory.setNextFactory(factory);
    MVEL.executeExpression(compiledExpression, knowledgeHelper, cachingFactory);
}
Also used : ScriptBlock(org.drools.model.functions.ScriptBlock) AgendaItem(org.drools.core.common.AgendaItem) ExecutableStatement(org.mvel2.compiler.ExecutableStatement) Arrays(java.util.Arrays) RuleTerminalNode(org.drools.core.reteoo.RuleTerminalNode) InternalFactHandle(org.drools.core.common.InternalFactHandle) HashMap(java.util.HashMap) RuleContext(org.drools.modelcompiler.RuleContext) LinkedHashMap(java.util.LinkedHashMap) MVELConsequenceBuilder(org.drools.compiler.rule.builder.dialect.mvel.MVELConsequenceBuilder) Map(java.util.Map) Declaration(org.drools.core.rule.Declaration) KnowledgeHelper(org.drools.core.spi.KnowledgeHelper) KiePackage(org.kie.api.definition.KiePackage) WorkingMemory(org.drools.core.WorkingMemory) Variable(org.drools.model.Variable) InternalWorkingMemory(org.drools.core.common.InternalWorkingMemory) VariableResolverFactory(org.mvel2.integration.VariableResolverFactory) Consequence(org.drools.core.spi.Consequence) MVELDialectRuntimeData(org.drools.core.rule.MVELDialectRuntimeData) Collectors(java.util.stream.Collectors) Serializable(java.io.Serializable) MVELCompilationUnit(org.drools.core.base.mvel.MVELCompilationUnit) CachingMapVariableResolverFactory(org.mvel2.integration.impl.CachingMapVariableResolverFactory) Stream(java.util.stream.Stream) RuleImpl(org.drools.core.definitions.rule.impl.RuleImpl) Tuple(org.drools.core.spi.Tuple) ScriptBlock(org.drools.model.functions.ScriptBlock) Entry(java.util.Map.Entry) MVEL(org.mvel2.MVEL) EvaluatorWrapper(org.drools.core.base.EvaluatorWrapper) Serializable(java.io.Serializable) Variable(org.drools.model.Variable) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) MVELCompilationUnit(org.drools.core.base.mvel.MVELCompilationUnit) AgendaItem(org.drools.core.common.AgendaItem) LinkedHashMap(java.util.LinkedHashMap) InternalWorkingMemory(org.drools.core.common.InternalWorkingMemory) MVELDialectRuntimeData(org.drools.core.rule.MVELDialectRuntimeData) KiePackage(org.kie.api.definition.KiePackage) CachingMapVariableResolverFactory(org.mvel2.integration.impl.CachingMapVariableResolverFactory) Declaration(org.drools.core.rule.Declaration) InternalFactHandle(org.drools.core.common.InternalFactHandle) RuleTerminalNode(org.drools.core.reteoo.RuleTerminalNode) ExecutableStatement(org.mvel2.compiler.ExecutableStatement) EvaluatorWrapper(org.drools.core.base.EvaluatorWrapper) VariableResolverFactory(org.mvel2.integration.VariableResolverFactory) CachingMapVariableResolverFactory(org.mvel2.integration.impl.CachingMapVariableResolverFactory) Tuple(org.drools.core.spi.Tuple)

Example 17 with WorkingMemory

use of org.mvel2.tests.core.res.WorkingMemory in project drools by kiegroup.

the class MvelConstraintTestUtil method getParserConfiguration.

@Override
protected ParserConfiguration getParserConfiguration(InternalWorkingMemory workingMemory) {
    ParserConfiguration parserConfiguration = new ParserConfiguration();
    parserConfiguration.addImport(Cheese.class);
    return parserConfiguration;
}
Also used : ParserConfiguration(org.mvel2.ParserConfiguration)

Example 18 with WorkingMemory

use of org.mvel2.tests.core.res.WorkingMemory in project drools by kiegroup.

the class ASMEvalStubBuilder method createStubEval.

private void createStubEval(final ClassGenerator generator, final InvokerDataProvider data, final Map vars) {
    generator.setInterfaces(EvalStub.class, CompiledInvoker.class).addField(ACC_PRIVATE + ACC_VOLATILE, "eval", EvalExpression.class);
    generator.addMethod(ACC_PUBLIC, "createContext", generator.methodDescr(Object.class), new ClassGenerator.MethodBody() {

        public void body(MethodVisitor mv) {
            mv.visitInsn(ACONST_NULL);
            mv.visitInsn(ARETURN);
        }
    }).addMethod(ACC_PUBLIC, "clone", generator.methodDescr(EvalExpression.class), new ClassGenerator.MethodBody() {

        public void body(MethodVisitor mv) {
            String internalClassName = generator.getClassName().replace('.', '/');
            mv.visitTypeInsn(NEW, internalClassName);
            mv.visitInsn(DUP);
            mv.visitMethodInsn(INVOKESPECIAL, internalClassName, "<init>", "()V", false);
            mv.visitInsn(ARETURN);
        }
    }).addMethod(ACC_PUBLIC, "replaceDeclaration", generator.methodDescr(null, Declaration.class, Declaration.class)).addMethod(ACC_PUBLIC, "evaluate", generator.methodDescr(Boolean.TYPE, Tuple.class, Declaration[].class, WorkingMemory.class, Object.class), new String[] { "java/lang/Exception" }, new ClassGenerator.MethodBody() {

        public void body(MethodVisitor mv) {
            Label syncStart = new Label();
            Label syncEnd = new Label();
            Label l1 = new Label();
            Label l2 = new Label();
            mv.visitTryCatchBlock(syncStart, l1, l2, null);
            Label l3 = new Label();
            mv.visitTryCatchBlock(l2, l3, l2, null);
            getFieldFromThis("eval", EvalExpression.class);
            mv.visitJumpInsn(IFNONNULL, syncEnd);
            mv.visitVarInsn(ALOAD, 0);
            mv.visitInsn(DUP);
            mv.visitVarInsn(ASTORE, 5);
            // synchronized(this) {
            mv.visitInsn(MONITORENTER);
            mv.visitLabel(syncStart);
            getFieldFromThis("eval", EvalExpression.class);
            // if (eval == null) ...
            Label ifNotInitialized = new Label();
            mv.visitJumpInsn(IFNONNULL, ifNotInitialized);
            mv.visitVarInsn(ALOAD, 0);
            mv.visitVarInsn(ALOAD, 1);
            mv.visitVarInsn(ALOAD, 2);
            mv.visitVarInsn(ALOAD, 3);
            // ... EvalGenerator.generate(this, tuple, declarations, workingMemory)
            invokeStatic(EvalGenerator.class, "generate", null, EvalStub.class, Tuple.class, Declaration[].class, WorkingMemory.class);
            mv.visitLabel(ifNotInitialized);
            mv.visitVarInsn(ALOAD, 5);
            mv.visitInsn(MONITOREXIT);
            mv.visitLabel(l1);
            mv.visitJumpInsn(GOTO, syncEnd);
            mv.visitLabel(l2);
            mv.visitVarInsn(ASTORE, 6);
            mv.visitVarInsn(ALOAD, 5);
            mv.visitInsn(MONITOREXIT);
            mv.visitLabel(l3);
            mv.visitVarInsn(ALOAD, 6);
            mv.visitInsn(ATHROW);
            mv.visitLabel(syncEnd);
            // } end of synchronized
            getFieldFromThis("eval", EvalExpression.class);
            mv.visitVarInsn(ALOAD, 1);
            mv.visitVarInsn(ALOAD, 2);
            mv.visitVarInsn(ALOAD, 3);
            mv.visitVarInsn(ALOAD, 4);
            invokeInterface(EvalExpression.class, "evaluate", Boolean.TYPE, Tuple.class, Declaration[].class, WorkingMemory.class, Object.class);
            mv.visitInsn(IRETURN);
        }
    }).addMethod(ACC_PUBLIC, "setEval", generator.methodDescr(null, EvalExpression.class), new ClassGenerator.MethodBody() {

        public void body(MethodVisitor mv) {
            putFieldInThisFromRegistry("eval", EvalExpression.class, 1);
            mv.visitInsn(RETURN);
        }
    });
}
Also used : EvalExpression(org.drools.core.spi.EvalExpression) ClassGenerator(org.drools.core.rule.builder.dialect.asm.ClassGenerator) EvalStub(org.drools.core.rule.builder.dialect.asm.EvalStub) Label(org.mvel2.asm.Label) Declaration(org.drools.core.rule.Declaration) CompiledInvoker(org.drools.core.spi.CompiledInvoker) MethodVisitor(org.mvel2.asm.MethodVisitor)

Example 19 with WorkingMemory

use of org.mvel2.tests.core.res.WorkingMemory in project drools by kiegroup.

the class ConsequenceGenerator method generate.

public static void generate(final ConsequenceStub stub, KnowledgeHelper knowledgeHelper, WorkingMemory workingMemory) {
    RuleTerminalNode rtn = (RuleTerminalNode) knowledgeHelper.getMatch().getTuple().getTupleSink();
    final Declaration[] declarations = rtn.getRequiredDeclarations();
    final Tuple tuple = knowledgeHelper.getTuple();
    // Sort declarations based on their offset, so it can ascend the tuple's parents stack only once
    final List<DeclarationMatcher> declarationMatchers = matchDeclarationsToTuple(declarations);
    final ClassGenerator generator = createInvokerClassGenerator(stub, workingMemory).setInterfaces(Consequence.class, CompiledInvoker.class);
    generator.addMethod(ACC_PUBLIC, "getName", generator.methodDescr(String.class), new ClassGenerator.MethodBody() {

        public void body(MethodVisitor mv) {
            push(stub.getGeneratedInvokerClassName());
            mv.visitInsn(ARETURN);
        }
    }).addMethod(ACC_PUBLIC, "evaluate", generator.methodDescr(null, KnowledgeHelper.class, WorkingMemory.class), new String[] { "java/lang/Exception" }, new GeneratorHelper.EvaluateMethod() {

        public void body(MethodVisitor mv) {
            // Tuple tuple = knowledgeHelper.getTuple();
            mv.visitVarInsn(ALOAD, 1);
            invokeInterface(KnowledgeHelper.class, "getTuple", Tuple.class);
            cast(LeftTuple.class);
            // LeftTuple
            mv.visitVarInsn(ASTORE, 3);
            // Declaration[] declarations = ((RuleTerminalNode)knowledgeHelper.getMatch().getTuple().getTupleSink()).getDeclarations();
            mv.visitVarInsn(ALOAD, 1);
            invokeInterface(KnowledgeHelper.class, "getMatch", Activation.class);
            invokeInterface(Activation.class, "getTuple", Tuple.class);
            invokeInterface(Tuple.class, "getTupleSink", Sink.class);
            cast(RuleTerminalNode.class);
            invokeVirtual(RuleTerminalNode.class, "getRequiredDeclarations", Declaration[].class);
            mv.visitVarInsn(ASTORE, 4);
            Tuple currentTuple = tuple;
            // astore start position for objects to store in loop
            objAstorePos = 6;
            int[] paramsPos = new int[declarations.length];
            // declarationMatchers is already sorted by offset with tip declarations now first
            for (DeclarationMatcher matcher : declarationMatchers) {
                // original index refers to the array position with RuleTerminalNode.getDeclarations()
                int i = matcher.getOriginalIndex();
                int handlePos = objAstorePos;
                int objPos = ++objAstorePos;
                paramsPos[i] = handlePos;
                currentTuple = traverseTuplesUntilDeclaration(currentTuple, matcher.getRootDistance(), 3);
                // handle = tuple.getFactHandle()
                mv.visitVarInsn(ALOAD, 3);
                invokeInterface(Tuple.class, "getOriginalFactHandle", InternalFactHandle.class);
                mv.visitVarInsn(ASTORE, handlePos);
                String declarationType = declarations[i].getTypeName();
                if (stub.getNotPatterns()[i]) {
                    // notPattern indexes field declarations
                    // declarations[i].getValue((InternalWorkingMemory)workingMemory, fact[i].getObject());
                    // org.kie.rule.Declaration[]
                    mv.visitVarInsn(ALOAD, 4);
                    // i
                    push(i);
                    // declarations[i]
                    mv.visitInsn(AALOAD);
                    // WorkingMemory
                    mv.visitVarInsn(ALOAD, 2);
                    cast(InternalWorkingMemory.class);
                    // handle[i]
                    mv.visitVarInsn(ALOAD, handlePos);
                    invokeInterface(InternalFactHandle.class, "getObject", Object.class);
                    storeObjectFromDeclaration(declarations[i], declarationType);
                    // The facthandle should be set to that of the field, if it's an object, otherwise this will return null
                    // fact[i] = (InternalFactHandle)workingMemory.getFactHandle(obj);
                    mv.visitVarInsn(ALOAD, 2);
                    loadAsObject(objPos);
                    invokeInterface(WorkingMemory.class, "getFactHandle", FactHandle.class, Object.class);
                    cast(InternalFactHandle.class);
                    mv.visitVarInsn(ASTORE, handlePos);
                } else {
                    // handle[i]
                    mv.visitVarInsn(ALOAD, handlePos);
                    invokeInterface(InternalFactHandle.class, "getObject", Object.class);
                    mv.visitTypeInsn(CHECKCAST, internalName(declarationType));
                    // obj[i]
                    objAstorePos += store(objPos, declarationType);
                }
            }
            // @{ruleClassName}.@{methodName}(KnowledgeHelper, @foreach{declr : declarations} Object, FactHandle @end)
            StringBuilder consequenceMethodDescr = new StringBuilder("(L" + KnowledgeHelper.class.getName().replace('.', '/') + ";");
            // KnowledgeHelper
            mv.visitVarInsn(ALOAD, 1);
            for (int i = 0; i < declarations.length; i++) {
                // obj[i]
                load(paramsPos[i] + 1);
                // handle[i]
                mv.visitVarInsn(ALOAD, paramsPos[i]);
                consequenceMethodDescr.append(typeDescr(declarations[i].getTypeName())).append("L" + FactHandle.class.getName().replace('.', '/') + ";");
            }
            // @foreach{type : globalTypes, identifier : globals} @{type} @{identifier} = ( @{type} ) workingMemory.getGlobal( "@{identifier}" );
            parseGlobals(stub.getGlobals(), stub.getGlobalTypes(), 2, consequenceMethodDescr);
            consequenceMethodDescr.append(")V");
            mv.visitMethodInsn(INVOKESTATIC, stub.getInternalRuleClassName(), stub.getMethodName(), consequenceMethodDescr.toString());
            mv.visitInsn(RETURN);
        }
    });
    stub.setConsequence(generator.<Consequence>newInstance());
}
Also used : InternalFactHandle(org.drools.core.common.InternalFactHandle) FactHandle(org.kie.api.runtime.rule.FactHandle) InternalWorkingMemory(org.drools.core.common.InternalWorkingMemory) WorkingMemory(org.drools.core.WorkingMemory) Activation(org.drools.core.spi.Activation) DeclarationMatcher(org.drools.core.rule.builder.dialect.asm.GeneratorHelper.DeclarationMatcher) LeftTuple(org.drools.core.reteoo.LeftTuple) MethodVisitor(org.mvel2.asm.MethodVisitor) InternalWorkingMemory(org.drools.core.common.InternalWorkingMemory) GeneratorHelper.createInvokerClassGenerator(org.drools.core.rule.builder.dialect.asm.GeneratorHelper.createInvokerClassGenerator) Sink(org.drools.core.reteoo.Sink) KnowledgeHelper(org.drools.core.spi.KnowledgeHelper) Declaration(org.drools.core.rule.Declaration) InternalFactHandle(org.drools.core.common.InternalFactHandle) GeneratorHelper.matchDeclarationsToTuple(org.drools.core.rule.builder.dialect.asm.GeneratorHelper.matchDeclarationsToTuple) LeftTuple(org.drools.core.reteoo.LeftTuple) Tuple(org.drools.core.spi.Tuple) RuleTerminalNode(org.drools.core.reteoo.RuleTerminalNode)

Example 20 with WorkingMemory

use of org.mvel2.tests.core.res.WorkingMemory in project drools by kiegroup.

the class MvelConditionEvaluator method evaluate.

private boolean evaluate(ExecutableStatement statement, InternalFactHandle handle, InternalWorkingMemory workingMemory, Tuple tuple) {
    if (compilationUnit == null) {
        Map<String, Object> vars = valuesAsMap(handle.getObject(), workingMemory, tuple, declarations);
        if (operators.length > 0) {
            if (vars == null) {
                vars = new HashMap<String, Object>();
            }
            InternalFactHandle[] handles = tuple != null ? tuple.toFactHandles() : new InternalFactHandle[0];
            for (EvaluatorWrapper operator : operators) {
                vars.put(operator.getBindingName(), operator);
                operator.loadHandles(workingMemory, handles, handle);
            }
        }
        return evaluate(statement, handle.getObject(), vars);
    }
    VariableResolverFactory factory = compilationUnit.createFactory();
    compilationUnit.updateFactory(handle, tuple, null, workingMemory, workingMemory.getGlobalResolver(), factory);
    return (Boolean) MVELSafeHelper.getEvaluator().executeExpression(statement, handle.getObject(), factory);
}
Also used : EvaluatorWrapper(org.drools.core.base.EvaluatorWrapper) VariableResolverFactory(org.mvel2.integration.VariableResolverFactory) InternalFactHandle(org.drools.core.common.InternalFactHandle)

Aggregations

VariableResolverFactory (org.mvel2.integration.VariableResolverFactory)14 MethodVisitor (org.mvel2.asm.MethodVisitor)9 MVELDialectRuntimeData (org.drools.core.rule.MVELDialectRuntimeData)8 InternalFactHandle (org.drools.core.common.InternalFactHandle)7 WorkingMemory (org.drools.core.WorkingMemory)6 InternalKnowledgePackage (org.drools.core.definitions.InternalKnowledgePackage)6 Tuple (org.drools.core.spi.Tuple)6 LeftTuple (org.drools.core.reteoo.LeftTuple)5 Declaration (org.drools.core.rule.Declaration)5 InternalWorkingMemory (org.drools.core.common.InternalWorkingMemory)4 ClassGenerator (org.drools.core.rule.builder.dialect.asm.ClassGenerator)4 DeclarationMatcher (org.drools.core.rule.builder.dialect.asm.GeneratorHelper.DeclarationMatcher)4 GeneratorHelper.createInvokerClassGenerator (org.drools.core.rule.builder.dialect.asm.GeneratorHelper.createInvokerClassGenerator)4 GeneratorHelper.matchDeclarationsToTuple (org.drools.core.rule.builder.dialect.asm.GeneratorHelper.matchDeclarationsToTuple)4 Label (org.mvel2.asm.Label)4 DroolsVarFactory (org.drools.core.base.mvel.MVELCompilationUnit.DroolsVarFactory)3 RuleTerminalNode (org.drools.core.reteoo.RuleTerminalNode)3 CompiledInvoker (org.drools.core.spi.CompiledInvoker)3 KnowledgeHelper (org.drools.core.spi.KnowledgeHelper)3 HashMap (java.util.HashMap)2