public RuleConditionElement build( final RuleBuildContext context, final BaseDescr descr, final Pattern prefixPattern) { final AccumulateDescr accumDescr = (AccumulateDescr) descr; if (!accumDescr.hasValidInput()) { return null; } final RuleConditionBuilder builder = 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(); final Declaration[] sourceDeclArr = (Declaration[]) source.getOuterDeclarations().values().toArray(new Declaration[0]); Accumulator accumulator = null; Declaration[] declarations = null; if (accumDescr.isExternalFunction()) { // build an external function executor final Dialect.AnalysisResult analysis = dialect.analyzeExpression( context, accumDescr, accumDescr.getExpression(), new Set[] { context.getDeclarationResolver().getDeclarations().keySet(), context.getPkg().getGlobals().keySet() }); int size = analysis.getBoundIdentifiers()[0].size(); declarations = new Declaration[size]; for (int i = 0; i < size; i++) { declarations[i] = context .getDeclarationResolver() .getDeclaration((String) analysis.getBoundIdentifiers()[0].get(i)); } final Serializable expression = dialect.compile( (String) accumDescr.getExpression(), analysis, null, source.getOuterDeclarations(), null, context); AccumulateFunction function = context.getConfiguration().getAccumulateFunction(accumDescr.getFunctionIdentifier()); final DroolsMVELFactory factory = new DroolsMVELFactory( context.getDeclarationResolver().getDeclarations(), source.getOuterDeclarations(), context.getPkg().getGlobals()); MVELDialectRuntimeData data = (MVELDialectRuntimeData) context.getPkg().getDialectRuntimeRegistry().getDialectData("mvel"); factory.setNextFactory(data.getFunctionFactory()); accumulator = new MVELAccumulatorFunctionExecutor(factory, expression, function); } else { // it is a custom accumulate final MVELAnalysisResult initCodeAnalysis = (MVELAnalysisResult) dialect.analyzeBlock( context, accumDescr, accumDescr.getInitCode(), new Set[] { context.getDeclarationResolver().getDeclarations().keySet(), context.getPkg().getGlobals().keySet() }); final MVELAnalysisResult actionCodeAnalysis = (MVELAnalysisResult) dialect.analyzeBlock( context, accumDescr, null, accumDescr.getActionCode(), new Set[] { context.getDeclarationResolver().getDeclarations().keySet(), context.getPkg().getGlobals().keySet() }, initCodeAnalysis.getMvelVariables()); // actionCodeAnalysis.setMvelVariables( initCodeAnalysis.getMvelVariables() ); final MVELAnalysisResult resultCodeAnalysis = (MVELAnalysisResult) dialect.analyzeExpression( context, accumDescr, accumDescr.getResultCode(), new Set[] { context.getDeclarationResolver().getDeclarations().keySet(), context.getPkg().getGlobals().keySet() }, initCodeAnalysis.getMvelVariables()); // resultCodeAnalysis.setMvelVariables( initCodeAnalysis.getMvelVariables() ); final List requiredDeclarations = new ArrayList(initCodeAnalysis.getBoundIdentifiers()[0]); requiredDeclarations.addAll(actionCodeAnalysis.getBoundIdentifiers()[0]); requiredDeclarations.addAll(resultCodeAnalysis.getBoundIdentifiers()[0]); Dialect.AnalysisResult reverseCodeAnalysis = null; if (accumDescr.getReverseCode() != null) { reverseCodeAnalysis = context .getDialect() .analyzeBlock( context, accumDescr, accumDescr.getActionCode(), new Set[] { context.getDeclarationResolver().getDeclarations().keySet(), context.getPkg().getGlobals().keySet() }); requiredDeclarations.addAll(reverseCodeAnalysis.getBoundIdentifiers()[0]); } declarations = new Declaration[requiredDeclarations.size()]; for (int i = 0, size = requiredDeclarations.size(); i < size; i++) { declarations[i] = context.getDeclarationResolver().getDeclaration((String) requiredDeclarations.get(i)); } final Serializable init = dialect.compile( (String) accumDescr.getInitCode(), initCodeAnalysis, null, source.getOuterDeclarations(), null, context); final Serializable action = dialect.compile( (String) accumDescr.getActionCode(), actionCodeAnalysis, null, source.getOuterDeclarations(), initCodeAnalysis.getMvelVariables(), context); Serializable reverse = null; if (accumDescr.getReverseCode() != null) { reverse = dialect.compile( (String) accumDescr.getReverseCode(), resultCodeAnalysis, null, source.getOuterDeclarations(), initCodeAnalysis.getMvelVariables(), context); } final Serializable result = dialect.compile( (String) accumDescr.getResultCode(), resultCodeAnalysis, null, source.getOuterDeclarations(), initCodeAnalysis.getMvelVariables(), context); DroolsMVELFactory factory = null; if (reverse == null) { // does not support reverse, so create a regular factory factory = new DroolsMVELFactory( context.getDeclarationResolver().getDeclarations(), source.getOuterDeclarations(), context.getPkg().getGlobals()); } else { Set<String> shadow = new HashSet<String>(source.getOuterDeclarations().keySet()); shadow.retainAll(reverseCodeAnalysis.getNotBoundedIdentifiers()); shadow.addAll(reverseCodeAnalysis.getBoundIdentifiers()[0]); // supports reverse, so create a shadowing factory factory = new DroolsMVELShadowFactory( context.getDeclarationResolver().getDeclarations(), source.getOuterDeclarations(), context.getPkg().getGlobals(), shadow); } MVELDialectRuntimeData data = (MVELDialectRuntimeData) context.getPkg().getDialectRuntimeRegistry().getDialectData("mvel"); factory.setNextFactory(data.getFunctionFactory()); accumulator = new MVELAccumulator(factory, init, action, reverse, result); } final Accumulate accumulate = new Accumulate(source, declarations, sourceDeclArr, accumulator); return accumulate; }
@SuppressWarnings("unchecked") public RuleConditionElement build( final RuleBuildContext context, final BaseDescr descr, final Pattern prefixPattern) { try { final AccumulateDescr accumDescr = (AccumulateDescr) descr; if (!accumDescr.hasValidInput()) { return null; } final RuleConditionBuilder builder = (RuleConditionBuilder) context.getDialect().getBuilder(accumDescr.getInput().getClass()); Declaration[] previousDeclarations = (Declaration[]) context .getDeclarationResolver() .getDeclarations(context.getRule()) .values() .toArray( new Declaration [context .getDeclarationResolver() .getDeclarations(context.getRule()) .size()]); // create source CE final RuleConditionElement source = builder.build(context, accumDescr.getInput()); if (source == null) { return null; } MVELDialect dialect = (MVELDialect) context.getDialect(); final Declaration[] sourceDeclArr = (Declaration[]) source .getOuterDeclarations() .values() .toArray(new Declaration[source.getOuterDeclarations().size()]); Accumulator accumulator = null; Declaration[] declarations = null; if (accumDescr.isExternalFunction()) { // build an external function executor AccumulateFunction function = context.getConfiguration().getAccumulateFunction(accumDescr.getFunctionIdentifier()); if (function == null) { context .getErrors() .add( new DescrBuildError( accumDescr, context.getRuleDescr(), null, "Unknown accumulate function: '" + accumDescr.getFunctionIdentifier() + "' on rule '" + context.getRuleDescr().getName() + "'. All accumulate functions must be registered before building a resource.")); return null; } Map<String, Class<?>> declarationsMap = context.getDeclarationResolver().getDeclarationClasses(context.getRule()); final Dialect.AnalysisResult analysis = dialect.analyzeExpression( context, accumDescr, accumDescr.getExpression(), new Map[] {declarationsMap, context.getPackageBuilder().getGlobals()}); MVELCompilationUnit unit = dialect.getMVELCompilationUnit( (String) accumDescr.getExpression(), analysis, previousDeclarations, (Declaration[]) source .getOuterDeclarations() .values() .toArray(new Declaration[source.getOuterDeclarations().size()]), null, context); accumulator = new MVELAccumulatorFunctionExecutor(unit, function); } else { // it is a custom accumulate Map<String, Class<?>> declarationsMap = context.getDeclarationResolver().getDeclarationClasses(context.getRule()); final MVELAnalysisResult initCodeAnalysis = (MVELAnalysisResult) dialect.analyzeBlock( context, accumDescr, accumDescr.getInitCode(), new Map[] {declarationsMap, context.getPackageBuilder().getGlobals()}); final MVELAnalysisResult actionCodeAnalysis = (MVELAnalysisResult) dialect.analyzeBlock( context, accumDescr, null, accumDescr.getActionCode(), new Map[] {declarationsMap, context.getPackageBuilder().getGlobals()}, initCodeAnalysis.getMvelVariables()); final MVELAnalysisResult resultCodeAnalysis = (MVELAnalysisResult) dialect.analyzeExpression( context, accumDescr, accumDescr.getResultCode(), new Map[] {declarationsMap, context.getPackageBuilder().getGlobals()}, initCodeAnalysis.getMvelVariables()); Dialect.AnalysisResult reverseCodeAnalysis = null; if (accumDescr.getReverseCode() != null) { reverseCodeAnalysis = dialect.analyzeBlock( context, accumDescr, null, accumDescr.getActionCode(), new Map[] {declarationsMap, context.getPackageBuilder().getGlobals()}, initCodeAnalysis.getMvelVariables()); } MVELCompilationUnit initUnit = dialect.getMVELCompilationUnit( (String) accumDescr.getInitCode(), initCodeAnalysis, previousDeclarations, (Declaration[]) source .getOuterDeclarations() .values() .toArray(new Declaration[source.getOuterDeclarations().size()]), null, context); MVELCompilationUnit actionUnit = dialect.getMVELCompilationUnit( (String) accumDescr.getActionCode(), actionCodeAnalysis, previousDeclarations, (Declaration[]) source .getOuterDeclarations() .values() .toArray(new Declaration[source.getOuterDeclarations().size()]), initCodeAnalysis.getMvelVariables(), context); MVELCompilationUnit reverseUnit = null; if (accumDescr.getReverseCode() != null) { reverseUnit = dialect.getMVELCompilationUnit( (String) accumDescr.getReverseCode(), reverseCodeAnalysis, previousDeclarations, (Declaration[]) source .getOuterDeclarations() .values() .toArray(new Declaration[source.getOuterDeclarations().size()]), initCodeAnalysis.getMvelVariables(), context); } MVELCompilationUnit resultUnit = dialect.getMVELCompilationUnit( (String) accumDescr.getResultCode(), resultCodeAnalysis, previousDeclarations, (Declaration[]) source .getOuterDeclarations() .values() .toArray(new Declaration[source.getOuterDeclarations().size()]), initCodeAnalysis.getMvelVariables(), context); if (reverseUnit != null) { Set<String> shadow = new HashSet<String>(source.getOuterDeclarations().keySet()); shadow.retainAll(reverseCodeAnalysis.getNotBoundedIdentifiers()); shadow.addAll(reverseCodeAnalysis.getBoundIdentifiers()[0]); String[] shadowVars = (String[]) shadow.toArray(new String[shadow.size()]); actionUnit.setShadowIdentifiers(shadowVars); reverseUnit.setShadowIdentifiers(shadowVars); } accumulator = new MVELAccumulator(initUnit, actionUnit, reverseUnit, resultUnit); } final Accumulate accumulate = new Accumulate(source, declarations, sourceDeclArr, new Accumulator[] {accumulator}); MVELDialectRuntimeData data = (MVELDialectRuntimeData) context.getPkg().getDialectRuntimeRegistry().getDialectData("mvel"); data.addCompileable(accumulate, (MVELCompileable) accumulator); ((MVELCompileable) accumulator).compile(context.getPackageBuilder().getRootClassLoader()); return accumulate; } catch (Exception e) { context .getErrors() .add( new DescrBuildError( context.getParentDescr(), descr, e, "Unable to build expression for 'accumulate' : " + e.getMessage())); return null; } }