@SuppressWarnings("unchecked") public RuleConditionElement build( final RuleBuildContext context, final BaseDescr descr, final Pattern prefixPattern) { boolean typesafe = context.isTypesafe(); try { final AccumulateDescr accumDescr = (AccumulateDescr) descr; if (!accumDescr.hasValidInput()) { return null; } final RuleConditionBuilder builder = (RuleConditionBuilder) context.getDialect().getBuilder(accumDescr.getInput().getClass()); // create source CE final RuleConditionElement source = builder.build(context, accumDescr.getInput()); if (source == null) { return null; } MVELDialect dialect = (MVELDialect) context.getDialect(); Map<String, Declaration> decls = context.getDeclarationResolver().getDeclarations(context.getRule()); Map<String, Declaration> sourceOuterDeclr = source.getOuterDeclarations(); Map<String, Declaration> mergedDecl = new HashMap(decls); mergedDecl.putAll(sourceOuterDeclr); Map<String, Class<?>> declarationClasses = DeclarationScopeResolver.getDeclarationClasses(decls); declarationClasses.putAll(DeclarationScopeResolver.getDeclarationClasses(sourceOuterDeclr)); BoundIdentifiers boundIds = new BoundIdentifiers(declarationClasses, context.getKnowledgeBuilder().getGlobals()); boundIds.setDeclarations(mergedDecl); Accumulator[] accumulators; final boolean readLocalsFromTuple = PackageBuilderUtil.isReadLocalsFromTuple(context, accumDescr, source); if (accumDescr.isExternalFunction()) { // uses accumulate functions accumulators = buildExternalFunctions( context, accumDescr, dialect, decls, sourceOuterDeclr, boundIds, readLocalsFromTuple); } else { // it is a custom accumulate accumulators = buildCustomAccumulate( context, accumDescr, dialect, decls, sourceOuterDeclr, boundIds, readLocalsFromTuple); } List<Declaration> requiredDeclarations = new ArrayList<Declaration>(); for (Accumulator acc : accumulators) { MvelAccumulator mvelAcc = (MvelAccumulator) acc; Collections.addAll(requiredDeclarations, mvelAcc.getRequiredDeclarations()); } MVELDialectRuntimeData data = (MVELDialectRuntimeData) context.getPkg().getDialectRuntimeRegistry().getDialectData("mvel"); Accumulate accumulate; if (accumDescr.isMultiFunction()) { accumulate = new MultiAccumulate( source, requiredDeclarations.toArray(new Declaration[requiredDeclarations.size()]), accumulators); int index = 0; for (Accumulator accumulator : accumulators) { data.addCompileable( ((MultiAccumulate) accumulate).new Wirer(index++), (MVELCompileable) accumulator); ((MVELCompileable) accumulator).compile(data, context.getRule()); } } else { accumulate = new SingleAccumulate( source, requiredDeclarations.toArray(new Declaration[requiredDeclarations.size()]), accumulators[0]); data.addCompileable( ((SingleAccumulate) accumulate).new Wirer(), (MVELCompileable) accumulators[0]); ((MVELCompileable) accumulators[0]).compile(data, context.getRule()); } return accumulate; } catch (Exception e) { DialectUtil.copyErrorLocation(e, descr); context.addError( new DescrBuildError( context.getParentDescr(), descr, e, "Unable to build expression for 'accumulate' : " + e.getMessage())); return null; } finally { context.setTypesafe(typesafe); } }
private Accumulator[] buildCustomAccumulate( final RuleBuildContext context, final AccumulateDescr accumDescr, MVELDialect dialect, Map<String, Declaration> decls, Map<String, Declaration> sourceOuterDeclr, BoundIdentifiers boundIds, boolean readLocalsFromTuple) { Accumulator[] accumulators; final MVELAnalysisResult initCodeAnalysis = (MVELAnalysisResult) dialect.analyzeBlock(context, accumDescr, accumDescr.getInitCode(), boundIds); // need to copy boundIds, as this as a "this" object. final MVELAnalysisResult actionCodeAnalysis = (MVELAnalysisResult) dialect.analyzeBlock( context, accumDescr.getActionCode(), boundIds, initCodeAnalysis.getMvelVariables(), "drools", KnowledgeHelper.class); final MVELAnalysisResult resultCodeAnalysis = (MVELAnalysisResult) dialect.analyzeExpression( context, accumDescr, accumDescr.getResultCode(), boundIds, initCodeAnalysis.getMvelVariables()); context.setTypesafe(initCodeAnalysis.isTypesafe()); MVELCompilationUnit initUnit = dialect.getMVELCompilationUnit( accumDescr.getInitCode(), initCodeAnalysis, getUsedDeclarations(decls, initCodeAnalysis), getUsedDeclarations(sourceOuterDeclr, initCodeAnalysis), initCodeAnalysis.getMvelVariables(), context, "drools", KnowledgeHelper.class, readLocalsFromTuple, MVELCompilationUnit.Scope.CONSTRAINT); context.setTypesafe(actionCodeAnalysis.isTypesafe()); MVELCompilationUnit actionUnit = dialect.getMVELCompilationUnit( accumDescr.getActionCode(), actionCodeAnalysis, getUsedDeclarations(decls, actionCodeAnalysis), getUsedDeclarations(sourceOuterDeclr, actionCodeAnalysis), initCodeAnalysis.getMvelVariables(), context, "drools", KnowledgeHelper.class, readLocalsFromTuple, MVELCompilationUnit.Scope.CONSTRAINT); MVELCompilationUnit reverseUnit = null; if (accumDescr.getReverseCode() != null) { context.setTypesafe(actionCodeAnalysis.isTypesafe()); reverseUnit = dialect.getMVELCompilationUnit( accumDescr.getReverseCode(), actionCodeAnalysis, getUsedDeclarations(decls, actionCodeAnalysis), getUsedDeclarations(sourceOuterDeclr, actionCodeAnalysis), initCodeAnalysis.getMvelVariables(), context, "drools", KnowledgeHelper.class, readLocalsFromTuple, MVELCompilationUnit.Scope.CONSTRAINT); } context.setTypesafe(resultCodeAnalysis.isTypesafe()); MVELCompilationUnit resultUnit = dialect.getMVELCompilationUnit( accumDescr.getResultCode(), resultCodeAnalysis, getUsedDeclarations(decls, resultCodeAnalysis), getUsedDeclarations(sourceOuterDeclr, resultCodeAnalysis), initCodeAnalysis.getMvelVariables(), context, "drools", KnowledgeHelper.class, readLocalsFromTuple, MVELCompilationUnit.Scope.CONSTRAINT); accumulators = new Accumulator[] {new MVELAccumulator(initUnit, actionUnit, reverseUnit, resultUnit)}; return accumulators; }