Search in sources :

Example 6 with KnowledgeHelper

use of org.mvel2.tests.core.res.KnowledgeHelper 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 7 with KnowledgeHelper

use of org.mvel2.tests.core.res.KnowledgeHelper 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 8 with KnowledgeHelper

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

the class ModifyInterceptor method calculateModificationMask.

private void calculateModificationMask(KnowledgeHelper knowledgeHelper, WithNode node) {
    Class<?> nodeClass = node.getEgressType();
    TypeDeclaration typeDeclaration = knowledgeHelper.getWorkingMemory().getKnowledgeBase().getTypeDeclaration(nodeClass);
    if (typeDeclaration == null || !typeDeclaration.isPropertyReactive()) {
        modificationMask = allSetButTraitBitMask();
        return;
    }
    List<String> settableProperties = typeDeclaration.getAccessibleProperties();
    modificationMask = getEmptyPropertyReactiveMask(settableProperties.size());
    // TODO: access parmValuePairs without reflection
    WithNode.ParmValuePair[] parmValuePairs = getFieldValue(WithNode.class, "withExpressions", node);
    for (WithNode.ParmValuePair parmValuePair : parmValuePairs) {
        Method method = extractMethod(parmValuePair);
        if (method == null) {
            modificationMask = allSetButTraitBitMask();
            return;
        }
        String propertyName = setter2property(method.getName());
        if (propertyName != null) {
            int index = settableProperties.indexOf(propertyName);
            if (index >= 0) {
                modificationMask = setPropertyOnMask(modificationMask, index);
            }
        }
        List<String> modifiedProps = typeDeclaration.getTypeClassDef().getModifiedPropsByMethod(method);
        if (modifiedProps != null) {
            for (String modifiedProp : modifiedProps) {
                int index = settableProperties.indexOf(modifiedProp);
                if (index >= 0) {
                    modificationMask = setPropertyOnMask(modificationMask, index);
                }
            }
        }
    }
}
Also used : Method(java.lang.reflect.Method) TypeDeclaration(org.drools.core.rule.TypeDeclaration) WithNode(org.mvel2.ast.WithNode)

Example 9 with KnowledgeHelper

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

the class MVELCompilationUnit method getFactory.

public VariableResolverFactory getFactory(final Object knowledgeHelper, final Declaration[] prevDecl, final Rule rule, final InternalFactHandle rightHandle, final Tuple tuple, final Object[] otherVars, final InternalWorkingMemory workingMemory, final GlobalResolver globals) {
    VariableResolverFactory factory = createFactory();
    updateFactory(knowledgeHelper, prevDecl, rule, rightHandle, rightHandle != null ? rightHandle.getObject() : null, tuple, otherVars, workingMemory, globals, factory);
    return factory;
}
Also used : VariableResolverFactory(org.mvel2.integration.VariableResolverFactory)

Example 10 with KnowledgeHelper

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

the class MVELConsequence method evaluate.

public void evaluate(final KnowledgeHelper knowledgeHelper, final WorkingMemory workingMemory) throws Exception {
    VariableResolverFactory factory = unit.getFactory(knowledgeHelper, ((AgendaItem) knowledgeHelper.getMatch()).getTerminalNode().getRequiredDeclarations(), knowledgeHelper.getRule(), knowledgeHelper.getTuple(), null, (InternalWorkingMemory) workingMemory, workingMemory.getGlobalResolver());
    // do we have any functions for this namespace?
    InternalKnowledgePackage pkg = workingMemory.getKnowledgeBase().getPackage("MAIN");
    if (pkg != null) {
        MVELDialectRuntimeData data = (MVELDialectRuntimeData) pkg.getDialectRuntimeRegistry().getDialectData(this.id);
        factory.setNextFactory(data.getFunctionFactory());
    }
    CompiledExpression compexpr = (CompiledExpression) this.expr;
    if (MVELDebugHandler.isDebugMode()) {
        if (MVELDebugHandler.verbose) {
            logger.info(DebugTools.decompile(compexpr));
        }
        MVEL.executeDebugger(compexpr, knowledgeHelper, factory);
    } else {
        MVEL.executeExpression(compexpr, knowledgeHelper, factory);
    }
}
Also used : MVELDialectRuntimeData(org.drools.core.rule.MVELDialectRuntimeData) VariableResolverFactory(org.mvel2.integration.VariableResolverFactory) AgendaItem(org.drools.core.common.AgendaItem) CompiledExpression(org.mvel2.compiler.CompiledExpression) InternalKnowledgePackage(org.drools.core.definitions.InternalKnowledgePackage)

Aggregations

VariableResolverFactory (org.mvel2.integration.VariableResolverFactory)5 WorkingMemory (org.drools.core.WorkingMemory)3 InternalFactHandle (org.drools.core.common.InternalFactHandle)3 InternalWorkingMemory (org.drools.core.common.InternalWorkingMemory)3 RuleTerminalNode (org.drools.core.reteoo.RuleTerminalNode)3 Declaration (org.drools.core.rule.Declaration)3 MVELDialectRuntimeData (org.drools.core.rule.MVELDialectRuntimeData)3 KnowledgeHelper (org.drools.core.spi.KnowledgeHelper)3 Tuple (org.drools.core.spi.Tuple)3 MethodVisitor (org.mvel2.asm.MethodVisitor)3 HashMap (java.util.HashMap)2 LinkedHashMap (java.util.LinkedHashMap)2 Map (java.util.Map)2 AgendaItem (org.drools.core.common.AgendaItem)2 InternalKnowledgePackage (org.drools.core.definitions.InternalKnowledgePackage)2 LeftTuple (org.drools.core.reteoo.LeftTuple)2 Sink (org.drools.core.reteoo.Sink)2 ClassGenerator (org.drools.core.rule.builder.dialect.asm.ClassGenerator)2 Activation (org.drools.core.spi.Activation)2 Consequence (org.drools.core.spi.Consequence)2