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