public void visitAccumulateDescr(final AccumulateDescr descr) { String tmpstr = new String(); tmpstr += this.template + " <from> <accumulate> "; if (descr.isSinglePattern()) { visitPatternDescr(descr.getInputPattern()); } else { this.patternContext = false; visit(descr.getInput()); } tmpstr += this.template; if (descr.isExternalFunction()) { AccumulateFunctionCallDescr func = descr.getFunctions().get(0); tmpstr += "<external-function evaluator=\"" + func.getFunction() + "\" expression=\"" + func.getParams()[0] + "\"/>"; } else tmpstr += "<init>" + descr.getInitCode() + "</init><action>" + descr.getActionCode() + "</action><result>" + descr.getResultCode() + "</result>"; this.template = tmpstr + " </accumulate> </from> "; }
private Accumulator[] buildExternalFunctions( final RuleBuildContext context, final AccumulateDescr accumDescr, MVELDialect dialect, Map<String, Declaration> decls, Map<String, Declaration> sourceOuterDeclr, BoundIdentifiers boundIds, boolean readLocalsFromTuple) { Accumulator[] accumulators; List<AccumulateFunctionCallDescr> functions = accumDescr.getFunctions(); accumulators = new Accumulator[functions.size()]; // creating the custom array reader InternalReadAccessor arrayReader = new SelfReferenceClassFieldReader(Object[].class, "this"); int index = 0; Pattern pattern = (Pattern) context.getDeclarationResolver().peekBuildStack(); for (AccumulateFunctionCallDescr func : functions) { // build an external function executor AccumulateFunction function = context.getConfiguration().getAccumulateFunction(func.getFunction()); if (function == null) { // might have been imported in the package function = context .getKnowledgeBuilder() .getPackage() .getAccumulateFunctions() .get(func.getFunction()); } if (function == null) { context.addError( new DescrBuildError( accumDescr, context.getRuleDescr(), null, "Unknown accumulate function: '" + func.getFunction() + "' on rule '" + context.getRuleDescr().getName() + "'. All accumulate functions must be registered before building a resource.")); return null; } final AnalysisResult analysis = dialect.analyzeExpression( context, accumDescr, func.getParams().length > 0 ? func.getParams()[0] : "\"\"", boundIds); MVELCompilationUnit unit = dialect.getMVELCompilationUnit( func.getParams().length > 0 ? func.getParams()[0] : "\"\"", analysis, getUsedDeclarations(decls, analysis), getUsedDeclarations(sourceOuterDeclr, analysis), null, context, "drools", KnowledgeHelper.class, readLocalsFromTuple, MVELCompilationUnit.Scope.CONSTRAINT); accumulators[index] = new MVELAccumulatorFunctionExecutor(unit, function); // if there is a binding, create the binding if (func.getBind() != null) { if (context .getDeclarationResolver() .isDuplicated(context.getRule(), func.getBind(), function.getResultType().getName())) { if (!func.isUnification()) { context.addError( new DescrBuildError( context.getParentDescr(), accumDescr, null, "Duplicate declaration for variable '" + func.getBind() + "' in the rule '" + context.getRule().getName() + "'")); } else { Declaration inner = context.getDeclarationResolver().getDeclaration(context.getRule(), func.getBind()); Constraint c = new MvelConstraint( Collections.singletonList(context.getPkg().getName()), accumDescr.isMultiFunction() ? "this[ " + index + " ] == " + func.getBind() : "this == " + func.getBind(), new Declaration[] {inner}, null, IndexUtil.ConstraintType.EQUAL, context .getDeclarationResolver() .getDeclaration(context.getRule(), func.getBind()), accumDescr.isMultiFunction() ? new ArrayElementReader(arrayReader, index, function.getResultType()) : new SelfReferenceClassFieldReader(function.getResultType(), "this"), true); ((MutableTypeConstraint) c).setType(Constraint.ConstraintType.BETA); pattern.addConstraint(c); index++; } } else { Declaration declr = pattern.addDeclaration(func.getBind()); if (accumDescr.isMultiFunction()) { declr.setReadAccessor( new ArrayElementReader(arrayReader, index, function.getResultType())); } else { declr.setReadAccessor( new SelfReferenceClassFieldReader(function.getResultType(), "this")); } } } index++; } return accumulators; }