use of org.drools.core.rule.SingleAccumulate in project drools by kiegroup.
the class JavaAccumulateBuilder method buildInlineAccumulate.
private Accumulate buildInlineAccumulate(final RuleBuildContext context, final AccumulateDescr accumDescr, final RuleConditionElement source, Map<String, Declaration> decls, Map<String, Class<?>> declCls, final boolean readLocalsFromTuple) {
// ELSE, if it is not an external function, build it using the regular java builder
final String className = "Accumulate" + context.getNextId();
accumDescr.setClassName(className);
BoundIdentifiers available = new BoundIdentifiers(declCls, context);
final JavaAnalysisResult initCodeAnalysis = (JavaAnalysisResult) context.getDialect().analyzeBlock(context, accumDescr, accumDescr.getInitCode(), available);
final AnalysisResult actionCodeAnalysis = context.getDialect().analyzeBlock(context, accumDescr, accumDescr.getActionCode(), available);
final AnalysisResult resultCodeAnalysis = context.getDialect().analyzeExpression(context, accumDescr, accumDescr.getResultCode(), available);
if (initCodeAnalysis == null || actionCodeAnalysis == null || resultCodeAnalysis == null) {
// not possible to get the analysis results - compilation error has been already logged
return null;
}
final Set<String> requiredDeclarations = new HashSet<String>(initCodeAnalysis.getBoundIdentifiers().getDeclrClasses().keySet());
requiredDeclarations.addAll(actionCodeAnalysis.getBoundIdentifiers().getDeclrClasses().keySet());
requiredDeclarations.addAll(resultCodeAnalysis.getBoundIdentifiers().getDeclrClasses().keySet());
final Map<String, Class<?>> requiredGlobals = new HashMap<String, Class<?>>(initCodeAnalysis.getBoundIdentifiers().getGlobals());
requiredGlobals.putAll(actionCodeAnalysis.getBoundIdentifiers().getGlobals());
requiredGlobals.putAll(resultCodeAnalysis.getBoundIdentifiers().getGlobals());
if (accumDescr.getReverseCode() != null) {
final AnalysisResult reverseCodeAnalysis = context.getDialect().analyzeBlock(context, accumDescr, accumDescr.getActionCode(), available);
requiredDeclarations.addAll(reverseCodeAnalysis.getBoundIdentifiers().getDeclrClasses().keySet());
requiredGlobals.putAll(reverseCodeAnalysis.getBoundIdentifiers().getGlobals());
}
final Declaration[] declarations = new Declaration[requiredDeclarations.size()];
int i = 0;
for (Iterator<String> it = requiredDeclarations.iterator(); it.hasNext(); i++) {
declarations[i] = decls.get(it.next());
}
final Declaration[] sourceDeclArr = source.getOuterDeclarations().values().toArray(new Declaration[source.getOuterDeclarations().size()]);
Arrays.sort(sourceDeclArr, RuleTerminalNode.SortDeclarations.instance);
final Map<String, Object> map = createVariableContext(className, null, context, declarations, null, requiredGlobals);
map.put("className", accumDescr.getClassName());
map.put("innerDeclarations", sourceDeclArr);
map.put("isMultiPattern", readLocalsFromTuple ? Boolean.TRUE : Boolean.FALSE);
final String initCode = this.fixInitCode(initCodeAnalysis, accumDescr.getInitCode());
final String actionCode = accumDescr.getActionCode();
final String resultCode = accumDescr.getResultCode();
String[] attributesTypes = new String[initCodeAnalysis.getLocalVariablesMap().size()];
String[] attributes = new String[initCodeAnalysis.getLocalVariablesMap().size()];
int index = 0;
for (Map.Entry<String, JavaLocalDeclarationDescr> entry : initCodeAnalysis.getLocalVariablesMap().entrySet()) {
attributes[index] = entry.getKey();
attributesTypes[index] = entry.getValue().getType();
index++;
}
map.put("attributes", attributes);
map.put("attributesTypes", attributesTypes);
map.put("initCode", initCode);
map.put("actionCode", actionCode);
map.put("resultCode", resultCode);
if (accumDescr.getReverseCode() == null) {
map.put("reverseCode", "");
map.put("supportsReverse", "false");
} else {
map.put("reverseCode", accumDescr.getReverseCode());
map.put("supportsReverse", "true");
}
map.put("hashCode", actionCode.hashCode());
SingleAccumulate accumulate = new SingleAccumulate(source, declarations);
generateTemplates("accumulateInnerClass", "accumulateInvoker", context, className, map, accumulate.new Wirer(), accumDescr);
return accumulate;
}
use of org.drools.core.rule.SingleAccumulate in project drools by kiegroup.
the class JavaAccumulateBuilder method buildExternalFunctionCall.
private Accumulate buildExternalFunctionCall(RuleBuildContext context, AccumulateDescr accumDescr, RuleConditionElement source, Map<String, Declaration> declsInScope, Map<String, Class<?>> declCls, boolean readLocalsFromTuple) {
// list of functions to build
final List<AccumulateFunctionCallDescr> funcCalls = accumDescr.getFunctions();
// list of available source declarations
final Declaration[] sourceDeclArr = source.getOuterDeclarations().values().toArray(new Declaration[source.getOuterDeclarations().size()]);
Arrays.sort(sourceDeclArr, RuleTerminalNode.SortDeclarations.instance);
// set of required previous declarations
Set<Declaration> requiredDecl = new HashSet<Declaration>();
Pattern pattern = (Pattern) context.getDeclarationResolver().peekBuildStack();
if (accumDescr.isMultiFunction()) {
// the accumulator array
Accumulator[] accumulators = new Accumulator[funcCalls.size()];
// creating the custom array reader
InternalReadAccessor reader = new SelfReferenceClassFieldReader(Object[].class);
int index = 0;
for (AccumulateFunctionCallDescr fc : funcCalls) {
AccumulateFunction function = getAccumulateFunction(context, accumDescr, fc, source, declCls);
if (function == null) {
return null;
}
bindReaderToDeclaration(context, accumDescr, pattern, fc, new ArrayElementReader(reader, index, function.getResultType()), function.getResultType(), index);
accumulators[index++] = buildAccumulator(context, accumDescr, declsInScope, declCls, readLocalsFromTuple, sourceDeclArr, requiredDecl, fc, function);
}
return new MultiAccumulate(source, requiredDecl.toArray(new Declaration[requiredDecl.size()]), accumulators);
} else {
AccumulateFunctionCallDescr fc = accumDescr.getFunctions().get(0);
AccumulateFunction function = getAccumulateFunction(context, accumDescr, fc, source, declCls);
if (function == null) {
return null;
}
Class<?> returnType = function.getResultType();
if (!pattern.isCompatibleWithAccumulateReturnType(returnType)) {
context.addError(new DescrBuildError(accumDescr, context.getRuleDescr(), null, "Pattern of type: '" + pattern.getObjectType() + "' on rule '" + context.getRuleDescr().getName() + "' is not compatible with type " + returnType.getCanonicalName() + " returned by accumulate function."));
return null;
}
bindReaderToDeclaration(context, accumDescr, pattern, fc, new SelfReferenceClassFieldReader(function.getResultType()), function.getResultType(), -1);
Accumulator accumulator = buildAccumulator(context, accumDescr, declsInScope, declCls, readLocalsFromTuple, sourceDeclArr, requiredDecl, fc, function);
return new SingleAccumulate(source, requiredDecl.toArray(new Declaration[requiredDecl.size()]), accumulator);
}
}
use of org.drools.core.rule.SingleAccumulate in project drools by kiegroup.
the class JavaAccumulateBuilder method buildInlineAccumulate.
private Accumulate buildInlineAccumulate(final RuleBuildContext context, final AccumulateDescr accumDescr, final RuleConditionElement source, Map<String, Declaration> decls, Map<String, Class<?>> declCls, final boolean readLocalsFromTuple) {
// ELSE, if it is not an external function, build it using the regular java builder
final String className = "Accumulate" + context.getNextId();
accumDescr.setClassName(className);
BoundIdentifiers available = new BoundIdentifiers(declCls, context);
final JavaAnalysisResult initCodeAnalysis = (JavaAnalysisResult) context.getDialect().analyzeBlock(context, accumDescr, accumDescr.getInitCode(), available);
final AnalysisResult actionCodeAnalysis = context.getDialect().analyzeBlock(context, accumDescr, accumDescr.getActionCode(), available);
final AnalysisResult resultCodeAnalysis = context.getDialect().analyzeExpression(context, accumDescr, accumDescr.getResultCode(), available);
if (initCodeAnalysis == null || actionCodeAnalysis == null || resultCodeAnalysis == null) {
// not possible to get the analysis results - compilation error has been already logged
return null;
}
final Set<String> requiredDeclarations = new HashSet<String>(initCodeAnalysis.getBoundIdentifiers().getDeclrClasses().keySet());
requiredDeclarations.addAll(actionCodeAnalysis.getBoundIdentifiers().getDeclrClasses().keySet());
requiredDeclarations.addAll(resultCodeAnalysis.getBoundIdentifiers().getDeclrClasses().keySet());
final Map<String, Class<?>> requiredGlobals = new HashMap<String, Class<?>>(initCodeAnalysis.getBoundIdentifiers().getGlobals());
requiredGlobals.putAll(actionCodeAnalysis.getBoundIdentifiers().getGlobals());
requiredGlobals.putAll(resultCodeAnalysis.getBoundIdentifiers().getGlobals());
if (accumDescr.getReverseCode() != null) {
final AnalysisResult reverseCodeAnalysis = context.getDialect().analyzeBlock(context, accumDescr, accumDescr.getActionCode(), available);
requiredDeclarations.addAll(reverseCodeAnalysis.getBoundIdentifiers().getDeclrClasses().keySet());
requiredGlobals.putAll(reverseCodeAnalysis.getBoundIdentifiers().getGlobals());
}
final Declaration[] declarations = new Declaration[requiredDeclarations.size()];
int i = 0;
for (Iterator<String> it = requiredDeclarations.iterator(); it.hasNext(); i++) {
declarations[i] = decls.get(it.next());
}
final Declaration[] sourceDeclArr = source.getOuterDeclarations().values().toArray(new Declaration[source.getOuterDeclarations().size()]);
Arrays.sort(sourceDeclArr, RuleTerminalNode.SortDeclarations.instance);
final Map<String, Object> map = createVariableContext(className, null, context, declarations, null, requiredGlobals);
map.put("className", accumDescr.getClassName());
map.put("innerDeclarations", sourceDeclArr);
map.put("isMultiPattern", readLocalsFromTuple ? Boolean.TRUE : Boolean.FALSE);
final String initCode = this.fixInitCode(initCodeAnalysis, accumDescr.getInitCode());
final String actionCode = accumDescr.getActionCode();
final String resultCode = accumDescr.getResultCode();
String[] attributesTypes = new String[initCodeAnalysis.getLocalVariablesMap().size()];
String[] attributes = new String[initCodeAnalysis.getLocalVariablesMap().size()];
int index = 0;
for (Map.Entry<String, JavaLocalDeclarationDescr> entry : initCodeAnalysis.getLocalVariablesMap().entrySet()) {
attributes[index] = entry.getKey();
attributesTypes[index] = entry.getValue().getType();
index++;
}
map.put("attributes", attributes);
map.put("attributesTypes", attributesTypes);
map.put("initCode", initCode);
map.put("actionCode", actionCode);
map.put("resultCode", resultCode);
if (accumDescr.getReverseCode() == null) {
map.put("reverseCode", "");
map.put("supportsReverse", "false");
} else {
map.put("reverseCode", accumDescr.getReverseCode());
map.put("supportsReverse", "true");
}
map.put("hashCode", actionCode.hashCode());
SingleAccumulate accumulate = new SingleAccumulate(source, declarations);
generateTemplates("accumulateInnerClass", "accumulateInvoker", context, className, map, accumulate.new Wirer(), accumDescr);
return accumulate;
}
use of org.drools.core.rule.SingleAccumulate in project drools by kiegroup.
the class MVELAccumulateBuilder method build.
@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, Class<?>> declarationClasses = DeclarationScopeResolver.getDeclarationClasses(decls);
declarationClasses.putAll(DeclarationScopeResolver.getDeclarationClasses(sourceOuterDeclr));
BoundIdentifiers boundIds = new BoundIdentifiers(declarationClasses, context);
final boolean readLocalsFromTuple = PackageBuilderUtil.isReadLocalsFromTuple(context, accumDescr, source);
Accumulator[] accumulators;
if (accumDescr.isExternalFunction()) {
// uses accumulate functions
accumulators = buildExternalFunctions(context, accumDescr, dialect, decls, sourceOuterDeclr, boundIds, readLocalsFromTuple, source, declarationClasses);
} 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, accumulators.length);
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) {
AsmUtil.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);
}
}
use of org.drools.core.rule.SingleAccumulate in project drools by kiegroup.
the class KiePackagesBuilder method addPatternForVariable.
private Pattern addPatternForVariable(RuleContext ctx, GroupElement group, Variable patternVariable, Condition.Type type) {
Pattern pattern = null;
// If the variable is already bound to the result of previous accumulate result pattern, then find it.
if (patternVariable instanceof org.drools.model.Declaration) {
org.drools.model.Declaration decl = (org.drools.model.Declaration) patternVariable;
if (decl.getSource() == null) {
Accumulate accSource = ctx.getAccumulateSource(patternVariable);
if (accSource != null) {
for (RuleConditionElement element : group.getChildren()) {
if (element instanceof Pattern && ((Pattern) element).getSource() == accSource) {
pattern = (Pattern) element;
break;
}
}
}
}
}
PatternSource priorSource = null;
if (pattern != null && type == Condition.Type.ACCUMULATE) {
// so it would be potentially tricky if this was a multi var, with multiple bindings.
if (pattern.getSource() instanceof SingleAccumulate) {
group.getChildren().remove(pattern);
priorSource = pattern.getSource();
pattern = null;
}
}
if (pattern == null) {
pattern = new Pattern(ctx.getNextPatternIndex(), // tupleIndex will be set by ReteooBuilder
0, // tupleIndex will be set by ReteooBuilder
0, getObjectType(patternVariable), patternVariable.getName(), true);
pattern.setSource(priorSource);
}
if (patternVariable instanceof org.drools.model.Declaration) {
org.drools.model.Declaration decl = (org.drools.model.Declaration) patternVariable;
if (decl.getSource() != null) {
if (decl.getSource() instanceof EntryPoint) {
pattern.setSource(new EntryPointId(((EntryPoint) decl.getSource()).getName()));
} else if (decl.getSource() instanceof WindowReference) {
WindowReference<?> window = (WindowReference) decl.getSource();
if (!ctx.getPkg().getWindowDeclarations().containsKey(window.getName())) {
createWindowReference(ctx, window);
}
pattern.setSource(new org.drools.core.rule.WindowReference(window.getName()));
} else if (decl.getSource() instanceof From) {
pattern.setSource(buildFrom(ctx, pattern, (From) decl.getSource()));
} else if (decl.getSource() instanceof UnitData) {
UnitData unitData = (UnitData) decl.getSource();
pattern.setSource(new EntryPointId(ctx.getRule().getRuleUnitClassName() + "." + unitData.getName()));
} else {
throw new UnsupportedOperationException("Unknown source: " + decl.getSource());
}
}
if (decl.getWindow() != null) {
pattern.addBehavior(createWindow(decl.getWindow()));
ctx.setNeedStreamMode();
}
} else if (patternVariable instanceof Exchange) {
if (type == Condition.Type.SENDER) {
Function0 supplier = ((Exchange) patternVariable).getMessageSupplier();
DataProvider provider = new LambdaDataProvider(x -> supplier.apply(), false);
pattern.setSource(new AsyncSend(pattern, patternVariable.getName(), provider));
} else if (type == Condition.Type.RECEIVER) {
pattern.setSource(new AsyncReceive(pattern, patternVariable.getName()));
} else {
throw new UnsupportedOperationException();
}
}
ctx.registerPattern(patternVariable, pattern);
return pattern;
}
Aggregations