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);
}
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;
}
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);
}
});
}
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());
}
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);
}
Aggregations