public void visitExprConstraintDescr(final ExprConstraintDescr descr) { this.template = "<expr>" + XmlDumper.eol + StringUtils.escapeXmlString(descr.getExpression()) + XmlDumper.eol + "</expr>"; // if ( !descr.getRestrictions().isEmpty() ) { // this.template = "<field-constraint field-name=\"" + descr.getFieldName() + "\"> " // + XmlDumper.eol + processFieldConstraint( descr.getRestrictions() ) + XmlDumper.eol + // "</field-constraint>"; // } }
@SuppressWarnings("unchecked") public RuleConditionElement build( RuleBuildContext context, BaseDescr descr, Pattern prefixPattern, Query query) { PatternDescr patternDescr = (PatternDescr) descr; Declaration[] params = query.getParameters(); List<BaseDescr> args = (List<BaseDescr>) patternDescr.getDescrs(); List<Integer> declrIndexes = new ArrayList<Integer>(); List<Integer> varIndexes = new ArrayList<Integer>(); List<Object> arguments = new ArrayList<Object>(params.length); for (int i = 0; i < params.length; i++) { // as these could be set in any order, initialise first, to allow setting later. arguments.add(null); } List<Declaration> requiredDeclarations = new ArrayList<Declaration>(); ObjectType argsObjectType = ClassObjectType.ObjectArray_ObjectType; InternalReadAccessor arrayReader = new SelfReferenceClassFieldReader(Object[].class, "this"); Pattern pattern = new Pattern(context.getNextPatternId(), 0, argsObjectType, null); // Deal with the constraints, both positional and bindings for (int i = 0, length = args.size(); i < length; i++) { BaseDescr base = args.get(i); String expression = null; boolean isPositional = false; boolean isBinding = false; BindingDescr bind = null; ConstraintConnectiveDescr result = null; if (base instanceof BindingDescr) { bind = (BindingDescr) base; expression = bind.getVariable() + (bind.isUnification() ? " := " : " : ") + bind.getExpression(); isBinding = true; } else { if (base instanceof ExprConstraintDescr) { ExprConstraintDescr ecd = (ExprConstraintDescr) base; expression = ecd.getExpression(); isPositional = ecd.getType() == ExprConstraintDescr.Type.POSITIONAL; } else { expression = base.getText(); } result = parseExpression(context, patternDescr, expression); if (result == null) { // error, can't parse expression. context.addError( new DescrBuildError( context.getParentDescr(), descr, null, "Unable to parse constraint: \n" + expression)); continue; } isBinding = result.getDescrs().size() == 1 && result.getDescrs().get(0) instanceof BindingDescr; if (isBinding) { bind = (BindingDescr) result.getDescrs().get(0); } } if ((!isPositional) && (!isBinding)) { // error, can't have non binding slots. context.addError( new DescrBuildError( context.getParentDescr(), descr, null, "Query's must use positional or bindings, not field constraints:\n" + expression)); continue; } else if (isPositional && isBinding) { // error, can't have positional binding slots. context.addError( new DescrBuildError( context.getParentDescr(), descr, null, "Query's can't use positional bindings:\n" + expression)); continue; } else if (isPositional) { processPositional( context, query, params, declrIndexes, varIndexes, arguments, requiredDeclarations, arrayReader, pattern, base, expression, result); } else { // it is binding processBinding( context, descr, params, declrIndexes, varIndexes, arguments, requiredDeclarations, arrayReader, pattern, bind, result); } } Declaration[] declrsArray = requiredDeclarations.toArray(new Declaration[requiredDeclarations.size()]); int[] declrIndexArray = new int[declrIndexes.size()]; for (int i = 0; i < declrsArray.length; i++) { declrIndexArray[i] = declrIndexes.get(i); } int[] varIndexesArray = new int[varIndexes.size()]; for (int i = 0; i < varIndexesArray.length; i++) { varIndexesArray[i] = varIndexes.get(i); } return new QueryElement( pattern, query.getName(), arguments.toArray(new Object[arguments.size()]), declrsArray, declrIndexArray, varIndexesArray, !patternDescr.isQuery()); }
@Test public void testRuleWithQuery() throws Exception { final PackageBuilder builder = new PackageBuilder(); final PackageDescr packageDescr = new PackageDescr("p1"); QueryDescr queryDescr = new QueryDescr("query1"); queryDescr.addParameter("String", "$name"); queryDescr.addParameter("int", "$age"); queryDescr.addParameter("String", "$likes"); packageDescr.addRule(queryDescr); AndDescr lhs = new AndDescr(); queryDescr.setLhs(lhs); PatternDescr pattern = new PatternDescr(Person.class.getName()); lhs.addDescr(pattern); pattern.addConstraint(new BindingDescr("$name", "name", true)); pattern.addConstraint(new BindingDescr("$age", "age", true)); pattern.addConstraint(new BindingDescr("$likes", "likes", true)); RuleDescr ruleDescr = new RuleDescr("rule-1"); packageDescr.addRule(ruleDescr); lhs = new AndDescr(); ruleDescr.setLhs(lhs); pattern = new PatternDescr(Cheese.class.getName()); lhs.addDescr(pattern); pattern.addConstraint(new BindingDescr("$type", "type")); pattern = new PatternDescr("query1"); pattern.setQuery(true); lhs.addDescr(pattern); ExprConstraintDescr expr = new ExprConstraintDescr("'bobba'"); expr.setPosition(0); expr.setType(Type.POSITIONAL); pattern.addConstraint(expr); expr = new ExprConstraintDescr("$age"); expr.setPosition(1); expr.setType(Type.POSITIONAL); pattern.addConstraint(expr); expr = new ExprConstraintDescr("$type"); expr.setPosition(2); expr.setType(Type.POSITIONAL); pattern.addConstraint(expr); ruleDescr.setConsequence("System.out.println(\"age: \" + $age);"); builder.addPackage(packageDescr); assertLength(0, builder.getErrors().getErrors()); KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase(); kbase.addKnowledgePackages( Arrays.asList(new KnowledgePackage[] {new KnowledgePackageImp(builder.getPackage())})); final KieSession session = kbase.newStatefulKnowledgeSession(); session.insert(new Person("bobba", "stilton", 90)); session.insert(new Person("bobba", "brie", 80)); session.insert(new Person("bobba", "brie", 75)); session.insert(new Person("darth", "brie", 100)); session.insert(new Person("luke", "brie", 25)); session.insert(new Cheese("brie", 25)); session.fireAllRules(); }