private VerifierAccumulateDescr visitAccumulateDescr(AccumulateDescr descr) throws UnknownDescriptionException { VerifierAccumulateDescr accumulate = new VerifierAccumulateDescr(pattern); PatternDescrVisitor visitor = new PatternDescrVisitor(data, rule, solvers); Pattern parentPattern = visitor.visitPatternDescr(descr.getInputPattern(), null, 0); accumulate.setInitCode(descr.getInitCode()); accumulate.setActionCode(descr.getActionCode()); accumulate.setReverseCode(descr.getReverseCode()); accumulate.setResultCode(descr.getResultCode()); // XXX: Array seems to be always null. // accumulate.setDeclarations(descr.getDeclarations()); accumulate.setClassName(descr.getClassName()); accumulate.setExternalFunction(descr.isExternalFunction()); accumulate.setFunctionIdentifier(descr.getFunctions().get(0).getFunction()); accumulate.setExpression(descr.getFunctions().get(0).getParams()[0]); accumulate.setParentPath(parentPattern.getPath()); accumulate.setParentType(parentPattern.getVerifierComponentType()); data.add(accumulate); return accumulate; }
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; } }
@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 = context.getDeclarationResolver().getDeclarationClasses(decls); declarationClasses.putAll( context.getDeclarationResolver().getDeclarationClasses(sourceOuterDeclr)); BoundIdentifiers boundIds = new BoundIdentifiers(declarationClasses, context.getPackageBuilder().getGlobals()); boundIds.setDeclarations(mergedDecl); Accumulator[] accumulators = null; final boolean readLocalsFromTuple = PackageBuilderUtil.isReadLocalsFromTuple(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, source, dialect, decls, sourceOuterDeclr, boundIds, readLocalsFromTuple); } final Accumulate accumulate = new Accumulate(source, null, accumulators, accumDescr.isMultiFunction()); MVELDialectRuntimeData data = (MVELDialectRuntimeData) context.getPkg().getDialectRuntimeRegistry().getDialectData("mvel"); int index = 0; for (Accumulator accumulator : accumulators) { data.addCompileable(accumulate.new Wirer(index++), (MVELCompileable) accumulator); ((MVELCompileable) accumulator).compile(data); } return accumulate; } catch (Exception e) { 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, final RuleConditionElement source, 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, null, accumDescr.getActionCode(), boundIds, initCodeAnalysis.getMvelVariables(), "drools", KnowledgeHelper.class); final MVELAnalysisResult resultCodeAnalysis = (MVELAnalysisResult) dialect.analyzeExpression( context, accumDescr, accumDescr.getResultCode(), boundIds, initCodeAnalysis.getMvelVariables()); // MVELAnalysisResult reverseCodeAnalysis = null; // if ( accumDescr.getReverseCode() != null ) { // reverseCodeAnalysis = (MVELAnalysisResult) dialect.analyzeBlock( context, // accumDescr, // null, // // accumDescr.getActionCode(), // boundIds, // // initCodeAnalysis.getMvelVariables(), // "drools", // // KnowledgeHelper.class ); // } context.setTypesafe(initCodeAnalysis.isTypesafe()); MVELCompilationUnit initUnit = dialect.getMVELCompilationUnit( (String) accumDescr.getInitCode(), initCodeAnalysis, getUsedDeclarations(decls, initCodeAnalysis), getUsedDeclarations(sourceOuterDeclr, initCodeAnalysis), initCodeAnalysis.getMvelVariables(), context, "drools", KnowledgeHelper.class, readLocalsFromTuple); context.setTypesafe(actionCodeAnalysis.isTypesafe()); MVELCompilationUnit actionUnit = dialect.getMVELCompilationUnit( (String) accumDescr.getActionCode(), actionCodeAnalysis, getUsedDeclarations(decls, actionCodeAnalysis), getUsedDeclarations(sourceOuterDeclr, actionCodeAnalysis), initCodeAnalysis.getMvelVariables(), context, "drools", KnowledgeHelper.class, readLocalsFromTuple); MVELCompilationUnit reverseUnit = null; if (accumDescr.getReverseCode() != null) { context.setTypesafe(actionCodeAnalysis.isTypesafe()); reverseUnit = dialect.getMVELCompilationUnit( (String) accumDescr.getReverseCode(), actionCodeAnalysis, getUsedDeclarations(decls, actionCodeAnalysis), getUsedDeclarations(sourceOuterDeclr, actionCodeAnalysis), initCodeAnalysis.getMvelVariables(), context, "drools", KnowledgeHelper.class, readLocalsFromTuple); } context.setTypesafe(resultCodeAnalysis.isTypesafe()); MVELCompilationUnit resultUnit = dialect.getMVELCompilationUnit( (String) accumDescr.getResultCode(), resultCodeAnalysis, getUsedDeclarations(decls, resultCodeAnalysis), getUsedDeclarations(sourceOuterDeclr, resultCodeAnalysis), initCodeAnalysis.getMvelVariables(), context, "drools", KnowledgeHelper.class, readLocalsFromTuple); // if ( reverseUnit != null ) { // Set<String> shadow = new HashSet<String>( source.getOuterDeclarations().keySet() // ); // shadow.retainAll( reverseCodeAnalysis.getNotBoundedIdentifiers() ); // shadow.addAll( // reverseCodeAnalysis.getBoundIdentifiers().getDeclrClasses().keySet() ); // // String[] shadowVars = (String[]) shadow.toArray( new String[shadow.size()] ); // // actionUnit.setShadowIdentifiers( shadowVars ); // reverseUnit.setShadowIdentifiers( shadowVars ); // } accumulators = new Accumulator[] {new MVELAccumulator(initUnit, actionUnit, reverseUnit, resultUnit)}; return accumulators; }
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.getBuildStack().peek(); for (AccumulateFunctionCallDescr func : functions) { // build an external function executor AccumulateFunction function = context.getConfiguration().getAccumulateFunction(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; } // if there is a binding, create the binding if (func.getBind() != null) { if (pattern.getDeclaration(func.getBind()) != null) { context.addError( new DescrBuildError( context.getParentDescr(), accumDescr, null, "Duplicate declaration for variable '" + func.getBind() + "' in the rule '" + context.getRule().getName() + "'")); } else { createResultBind(pattern, index, arrayReader, func, function); } } 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); accumulators[index++] = new MVELAccumulatorFunctionExecutor(unit, function); } return accumulators; }