use of org.drools.model.view.ExprViewItem in project drools by kiegroup.
the class ViewFlowBuilder method viewItems2Condition.
private static CompositePatterns viewItems2Condition(BuildContext ctx, Condition.Type type, boolean topLevel) {
List<Condition> conditions = new ArrayList<>();
Map<Variable<?>, Condition> conditionMap = new HashMap<>();
Map<String, Consequence> consequences = topLevel ? new LinkedHashMap<>() : null;
Iterator<RuleItem> ruleItemIterator = ctx.ruleItems.iterator();
while (ruleItemIterator.hasNext()) {
Map<Variable<?>, InputViewItemImpl<?>> scopedInputs = type.createsScope() ? new LinkedHashMap<>(ctx.inputs) : ctx.inputs;
RuleItem ruleItem = ruleItemIterator.next();
if (ruleItem instanceof FixedValueItem) {
conditions.add(new EvalImpl(((FixedValueItem) ruleItem).isValue()));
continue;
}
if (ruleItem instanceof Consequence) {
if (!topLevel) {
throw new IllegalStateException("A consequence can be only a top level item");
}
Consequence consequence = (Consequence) ruleItem;
String name = ruleItemIterator.hasNext() ? generateName("consequence") : RuleImpl.DEFAULT_CONSEQUENCE_NAME;
consequences.put(name, consequence);
conditions.add(new NamedConsequenceImpl(name, consequence.isBreaking()));
continue;
}
if (ruleItem instanceof ConditionalConsequence) {
if (!topLevel) {
throw new IllegalStateException("A consequence can be only a top level item");
}
conditions.add(createConditionalNamedConsequence(consequences, (ConditionalConsequence) ruleItem));
continue;
}
ViewItem viewItem = (ViewItem) ruleItem;
if (viewItem instanceof CombinedExprViewItem) {
CombinedExprViewItem combined = (CombinedExprViewItem) viewItem;
conditions.add(viewItems2Condition(new BuildContext(ctx, combined.getExpressions(), scopedInputs), combined.getType(), false));
continue;
}
if (viewItem instanceof QueryCallViewItem) {
QueryCallViewItem query = ((QueryCallViewItem) viewItem);
for (Argument arg : query.getArguments()) {
if (arg instanceof Variable) {
ctx.usedVars.add(((Variable) arg));
}
}
conditions.add(new QueryCallPattern(query));
continue;
}
if (viewItem instanceof Binding) {
Binding bindViewItem = (Binding) viewItem;
PatternImpl pattern = (PatternImpl) conditionMap.get(bindViewItem.getInputVariable());
if (pattern == null) {
// This should probably be the bindViewItem.getBoundVariable() instead of the input
// as the input variables can be many
pattern = new PatternImpl(bindViewItem.getInputVariable());
pattern.addWatchedProps(bindViewItem.getWatchedProps());
ctx.usedVars.add(bindViewItem.getInputVariable());
conditions.add(pattern);
conditionMap.put(bindViewItem.getInputVariable(), pattern);
}
pattern.addBinding(bindViewItem);
ctx.usedVars.add(viewItem.getFirstVariable());
ctx.addBinding(bindViewItem);
scopedInputs.putIfAbsent(viewItem.getFirstVariable(), (InputViewItemImpl) input(viewItem.getFirstVariable()));
continue;
}
Variable<?> patterVariable = findPatterVariable(viewItem, scopedInputs.keySet());
if (viewItem instanceof InputViewItemImpl) {
scopedInputs.put(patterVariable, (InputViewItemImpl) viewItem);
PatternImpl condition = new PatternImpl(patterVariable);
condition.addWatchedProps(((InputViewItemImpl) viewItem).getWatchedProps());
conditions.add(condition);
conditionMap.put(patterVariable, condition);
ctx.usedVars.add(patterVariable);
continue;
}
if (viewItem instanceof ExistentialExprViewItem) {
ExistentialExprViewItem existential = ((ExistentialExprViewItem) viewItem);
if (patterVariable != null && !existential.isQueryExpression()) {
registerInputsFromViewItem(existential.getExpression(), conditionMap, scopedInputs, patterVariable);
}
Condition condition = new PatternImpl(patterVariable, SingleConstraint.TRUE, ctx.bindings.get(patterVariable));
conditions.add(new ExistentialPatternImpl(viewItem2Condition(existential.getExpression(), condition, new BuildContext(ctx, new LinkedHashMap<>())), existential.getType()));
continue;
}
if (ruleItem instanceof ExprViewItem && ctx.boundVars.contains(patterVariable)) {
conditions.add(new EvalImpl(createConstraint((ExprViewItem) ruleItem)));
continue;
}
ctx.usedVars.add(patterVariable);
Condition condition;
if (type == Type.AND) {
condition = conditionMap.get(patterVariable);
if (condition == null) {
condition = new PatternImpl(patterVariable, SingleConstraint.TRUE, ctx.bindings.get(patterVariable));
conditions.add(condition);
if (!(viewItem instanceof AccumulateExprViewItem)) {
conditionMap.put(patterVariable, condition);
}
scopedInputs.putIfAbsent(patterVariable, (InputViewItemImpl) input(patterVariable));
}
} else {
condition = new PatternImpl(patterVariable);
conditions.add(condition);
}
addInputFromVariableSource(scopedInputs, patterVariable);
registerInputsFromViewItem(viewItem, conditionMap, scopedInputs, null);
Condition modifiedPattern = viewItem2Condition(viewItem, condition, new BuildContext(ctx, scopedInputs));
conditions.set(conditions.indexOf(condition), modifiedPattern);
if (type == Type.AND && !(viewItem instanceof AccumulateExprViewItem)) {
conditionMap.put(patterVariable, modifiedPattern);
}
}
return new CompositePatterns(type, conditions, ctx.usedVars, consequences);
}
use of org.drools.model.view.ExprViewItem in project drools by kiegroup.
the class GroupByTest method testWithNull.
@Test
public void testWithNull() {
Variable<MyType> var = D.declarationOf(MyType.class);
Variable<MyType> groupKey = D.declarationOf(MyType.class);
Variable<Long> count = D.declarationOf(Long.class);
AtomicInteger mappingFunctionCallCounter = new AtomicInteger(0);
Function1<MyType, MyType> mappingFunction = (a) -> {
mappingFunctionCallCounter.incrementAndGet();
return a.getNested();
};
D.PatternDef<MyType> onlyOnesWithNested = D.pattern(var).expr(myType -> myType.getNested() != null);
ExprViewItem groupBy = D.groupBy(onlyOnesWithNested, var, groupKey, mappingFunction, D.accFunction(CountAccumulateFunction::new).as(count));
List<MyType> result = new ArrayList<>();
Rule rule = D.rule("R").build(groupBy, D.on(groupKey, count).execute((drools, key, acc) -> result.add(key)));
Model model = new ModelImpl().addRule(rule);
KieBase kieBase = KieBaseBuilder.createKieBaseFromModel(model);
MyType objectWithoutNestedObject = new MyType(null);
MyType objectWithNestedObject = new MyType(objectWithoutNestedObject);
KieSession ksession = kieBase.newKieSession();
ksession.insert(objectWithNestedObject);
ksession.insert(objectWithoutNestedObject);
ksession.fireAllRules();
// Side issue: this number is unusually high. Perhaps we should try to implement some cache for this?
System.out.println("GroupKey mapping function was called " + mappingFunctionCallCounter.get() + " times.");
Assertions.assertThat(result).containsOnly(objectWithoutNestedObject);
}
use of org.drools.model.view.ExprViewItem in project drools by kiegroup.
the class GroupByTest method testUnexpectedRuleMatch.
@Test
public void testUnexpectedRuleMatch() {
final Global<List> var_results = D.globalOf(List.class, "defaultpkg", "results");
// $a: Parent()
Variable<Parent> patternVar = D.declarationOf(Parent.class);
PatternDSL.PatternDef<Parent> pattern = D.pattern(patternVar);
// exists Child($a.getChild() == this)
Variable<Child> existsPatternVar = D.declarationOf(Child.class);
PatternDSL.PatternDef<Child> existsPattern = D.pattern(existsPatternVar).expr(patternVar, (child, parent) -> Objects.equals(parent.getChild(), child));
// count(Parent::getChild)
Variable<Child> groupKeyVar = D.declarationOf(Child.class);
Variable<Long> accumulateResult = D.declarationOf(Long.class);
ExprViewItem groupBy = PatternDSL.groupBy(D.and(pattern, D.exists(existsPattern)), patternVar, groupKeyVar, Parent::getChild, DSL.accFunction(CountAccumulateFunction::new).as(accumulateResult));
Rule rule1 = D.rule("R1").build(groupBy, D.on(var_results, groupKeyVar, accumulateResult).execute((results, $child, $count) -> results.add(Arrays.asList($child, $count))));
Model model = new ModelImpl().addRule(rule1).addGlobal(var_results);
KieSession ksession = KieBaseBuilder.createKieBaseFromModel(model).newKieSession();
List results = new ArrayList();
ksession.setGlobal("results", results);
Child child1 = new Child("Child1", 1);
Parent parent1 = new Parent("Parent1", child1);
Child child2 = new Child("Child2", 2);
Parent parent2 = new Parent("Parent2", child2);
ksession.insert(parent1);
ksession.insert(parent2);
FactHandle toRemove = ksession.insert(child1);
ksession.insert(child2);
// Remove child1, therefore it does not exist, therefore there should be no groupBy matches for the child.
ksession.delete(toRemove);
// Yet, we still get (Child1, 0).
ksession.fireAllRules();
Assertions.assertThat(results).containsOnly(Arrays.asList(child2, 1L));
}
use of org.drools.model.view.ExprViewItem in project drools by kiegroup.
the class ToStringTest method testToString.
/**
* Users may depend on seeing {@link Rule#toString()} in log files giving useful information, in order to understand
* the rules that are being created. The format is not required to be backwards compatible - this test merely checks
* that it does not change unknowingly.
*/
@Test
public void testToString() {
Variable<Person> markV = declarationOf(Person.class);
Variable<Integer> markAge = declarationOf(Integer.class);
Variable<Person> olderV = declarationOf(Person.class);
Variable<Double> resultAvg = declarationOf(Double.class);
Variable<Integer> age = declarationOf(Integer.class);
String person = "Mark";
Function1<Person, String> nameGetter = Person::getName;
Function1<Person, Integer> ageGetter = Person::getAge;
Predicate1<Person> markPredicate = p -> p.getName().equals(person);
PatternDSL.PatternDef<Person> pattern1 = pattern(markV).expr("exprA", markPredicate, alphaIndexedBy(String.class, Index.ConstraintType.EQUAL, 0, nameGetter, person)).bind(markAge, ageGetter);
Predicate1<Person> notMarkPredicate = markPredicate.negate();
Predicate2<Person, Integer> agePredicate = (p1, someAge) -> p1.getAge() > someAge;
Function1<Integer, Integer> ageCaster = int.class::cast;
PatternDSL.PatternDef<Person> pattern2 = pattern(olderV).expr("exprB", notMarkPredicate, alphaIndexedBy(String.class, Index.ConstraintType.NOT_EQUAL, 1, nameGetter, person)).expr("exprC", markAge, agePredicate, betaIndexedBy(int.class, Index.ConstraintType.GREATER_THAN, 0, ageGetter, ageCaster));
AccumulateFunction<AverageAccumulateFunction.AverageData> f = new AverageAccumulateFunction();
Supplier<AccumulateFunction<AverageAccumulateFunction.AverageData>> accumulateSupplier = () -> f;
org.drools.model.functions.accumulate.AccumulateFunction actualAccumulate = accFunction(accumulateSupplier, age);
ExprViewItem<Person> accumulate = accumulate(pattern(olderV).expr("exprD", notMarkPredicate).bind(age, ageGetter), actualAccumulate.as(resultAvg));
Rule rule = rule("beta").build(pattern1, pattern2, accumulate, on(olderV, markV).execute((drools, p1, p2) -> drools.insert(p1.getName() + " is older than " + p2.getName())));
String pattern1toString = "PatternImpl (type: PATTERN, inputVars: null, " + "outputVar: " + markV + ", " + "constraint: Constraint for 'exprA' (index: AlphaIndex #0 (EQUAL, left: lambda " + System.identityHashCode(nameGetter) + ", right: " + person + ")))";
String pattern2toString = "PatternImpl (type: PATTERN, inputVars: null, " + "outputVar: " + olderV + ", " + "constraint: MultipleConstraints (constraints: [" + "Constraint for 'exprB' (index: AlphaIndex #1 (NOT_EQUAL, left: lambda " + System.identityHashCode(nameGetter) + ", right: " + person + ")), " + "Constraint for 'exprC' (index: BetaIndex #0 (GREATER_THAN, left: lambda " + System.identityHashCode(ageGetter) + ", right: lambda " + System.identityHashCode(ageCaster) + "))]))";
String accumulatePatternToString = "PatternImpl (type: PATTERN, inputVars: null, " + "outputVar: " + olderV + ", " + "constraint: Constraint for 'exprD' (index: null))";
String accumulateToString = "AccumulatePatternImpl (functions: [" + actualAccumulate + "], " + "condition: " + accumulatePatternToString + ", " + "pattern: " + accumulatePatternToString + ")";
String consequenceToString = "ConsequenceImpl (variables: [" + olderV + ", " + markV + "], language: java, breaking: false)";
String expectedToString = "Rule: defaultpkg.beta (" + "view: CompositePatterns of AND (vars: null, patterns: [" + pattern1toString + ", " + pattern2toString + ", " + accumulateToString + ", NamedConsequenceImpl 'default' (breaking: false)], " + "consequences: {default=" + consequenceToString + "}), consequences: {default=" + consequenceToString + "})";
Assertions.assertThat(rule).hasToString(expectedToString);
}
use of org.drools.model.view.ExprViewItem in project drools by kiegroup.
the class ViewPatternBuilder method ruleItem2Condition.
public static Condition ruleItem2Condition(RuleItem ruleItem) {
if (ruleItem instanceof PatternDefImpl) {
PatternDefImpl<?> patternDef = (PatternDefImpl) ruleItem;
Variable<?> patternVariable = patternDef.getFirstVariable();
PatternImpl pattern = new PatternImpl(patternVariable, patternVariable instanceof Exchange ? Condition.Type.RECEIVER : Condition.Type.PATTERN);
for (PatternItem patternItem : patternDef.getItems()) {
if (patternItem instanceof PatternExprImpl) {
pattern.addConstraint(((PatternExprImpl) patternItem).asConstraint(patternDef));
} else if (patternItem instanceof PatternBindingImpl) {
pattern.addBinding(((PatternBindingImpl) patternItem).asBinding(patternDef));
} else {
throw new UnsupportedOperationException("Unknown pattern item type: " + patternItem);
}
}
pattern.addWatchedProps(patternDef.getWatch());
pattern.setPassive(patternDef.isPassive());
return pattern;
}
if (ruleItem instanceof FixedValueItem) {
return new EvalImpl(((FixedValueItem) ruleItem).isValue());
}
if (ruleItem instanceof QueryCallViewItem) {
return new QueryCallPattern((QueryCallViewItem) ruleItem);
}
if (ruleItem instanceof CombinedExprViewItem) {
CombinedExprViewItem combined = (CombinedExprViewItem) ruleItem;
List<Condition> conditions = new ArrayList<>();
for (ViewItem expr : combined.getExpressions()) {
conditions.add(ruleItem2Condition(expr));
}
return new CompositePatterns(combined.getType(), conditions);
}
if (ruleItem instanceof ExistentialExprViewItem) {
ExistentialExprViewItem existential = (ExistentialExprViewItem) ruleItem;
return new ExistentialPatternImpl(ruleItem2Condition(existential.getExpression()), existential.getType());
}
if (ruleItem instanceof GroupByExprViewItem) {
GroupByExprViewItem groupBy = (GroupByExprViewItem) ruleItem;
return new GroupByPatternImpl(ruleItem2Condition(groupBy.getExpr()), groupBy.getVars(), groupBy.getVarKey(), groupBy.getGroupingFunction(), groupBy.getAccumulateFunctions());
}
if (ruleItem instanceof AccumulateExprViewItem) {
AccumulateExprViewItem acc = (AccumulateExprViewItem) ruleItem;
return new AccumulatePatternImpl(ruleItem2Condition(acc.getExpr()), null, acc.getAccumulateFunctions());
}
if (ruleItem instanceof ExprViewItem) {
return new EvalImpl(createConstraint((ExprViewItem) ruleItem));
}
if (ruleItem instanceof ExchangeDefImpl) {
ExchangeDefImpl<?> exchangeDef = (ExchangeDefImpl) ruleItem;
return new PatternImpl(exchangeDef.getFirstVariable(), Condition.Type.SENDER);
}
throw new UnsupportedOperationException("Unknown " + ruleItem);
}
Aggregations