use of org.drools.core.rule.SingleAccumulate in project drools by kiegroup.
the class KiePackagesBuilder method buildAccumulate.
private Accumulate buildAccumulate(RuleContext ctx, AccumulatePattern accPattern, RuleConditionElement source, Pattern pattern, List<String> usedVariableName, Binding binding) {
AccumulateFunction[] accFunctions = accPattern.getAccumulateFunctions();
Accumulate accumulate;
if (accFunctions.length == 1) {
final Class<?> functionClass = accFunctions[0].getFunctionClass();
final Accumulator accumulator = createAccumulator(usedVariableName, binding, functionClass);
final Variable boundVar = accPattern.getBoundVariables()[0];
final Declaration declaration = new Declaration(boundVar.getName(), getReadAcessor(JAVA_CLASS_OBJECT_TYPE), pattern, true);
pattern.addDeclaration(declaration);
Declaration[] bindingDeclaration = binding != null ? new Declaration[0] : new Declaration[] { ctx.getPattern(accFunctions[0].getSource()).getDeclaration() };
accumulate = new SingleAccumulate(source, bindingDeclaration, accumulator);
} else {
InternalReadAccessor reader = new SelfReferenceClassFieldReader(Object[].class);
Accumulator[] accumulators = new Accumulator[accFunctions.length];
for (int i = 0; i < accFunctions.length; i++) {
final Class<?> functionClass = accFunctions[i].getFunctionClass();
final Accumulator accumulator = createAccumulator(usedVariableName, binding, functionClass);
Variable boundVar = accPattern.getBoundVariables()[i];
pattern.addDeclaration(new Declaration(boundVar.getName(), new ArrayElementReader(reader, i, boundVar.getType()), pattern, true));
accumulators[i] = accumulator;
}
accumulate = new MultiAccumulate(source, new Declaration[0], accumulators);
}
for (Variable boundVar : accPattern.getBoundVariables()) {
ctx.addAccumulateSource(boundVar, accumulate);
}
return accumulate;
}
use of org.drools.core.rule.SingleAccumulate in project drools by kiegroup.
the class CollectBuilder method build.
/**
* @inheritDoc
*/
public void build(final BuildContext context, final BuildUtils utils, final RuleConditionElement rce) {
boolean existSubNetwort = false;
final Collect collect = (Collect) rce;
context.pushRuleComponent(collect);
final List<BetaNodeFieldConstraint> resultBetaConstraints = context.getBetaconstraints();
final List<AlphaNodeFieldConstraint> resultAlphaConstraints = context.getAlphaConstraints();
final Pattern sourcePattern = collect.getSourcePattern();
// get builder for the pattern
final ReteooComponentBuilder builder = utils.getBuilderFor(sourcePattern);
// save tuple source and pattern offset for later if needed
final LeftTupleSource tupleSource = context.getTupleSource();
// builds the source pattern
builder.build(context, utils, sourcePattern);
// if object source is null, then we need to adapt tuple source into a subnetwork
if (context.getObjectSource() == null) {
RightInputAdapterNode riaNode = CoreComponentFactory.get().getNodeFactoryService().buildRightInputNode(context.getNextNodeId(), context.getTupleSource(), tupleSource, context);
// attach right input adapter node to convert tuple source into an object source
context.setObjectSource(utils.attachNode(context, riaNode));
// restore tuple source from before the start of the sub network
context.setTupleSource(tupleSource);
// create a tuple start equals constraint and set it in the context
final TupleStartEqualsConstraint constraint = TupleStartEqualsConstraint.getInstance();
final List<BetaNodeFieldConstraint> betaConstraints = new ArrayList<BetaNodeFieldConstraint>();
betaConstraints.add(constraint);
context.setBetaconstraints(betaConstraints);
existSubNetwort = true;
}
BetaConstraints binder = utils.createBetaNodeConstraint(context, context.getBetaconstraints(), false);
// indexing for the results should be always disabled
BetaConstraints resultBinder = utils.createBetaNodeConstraint(context, resultBetaConstraints, true);
// The node needs to declare the vars it returns
Pattern resultPattern = collect.getResultPattern();
Accumulate accumulate = new SingleAccumulate(sourcePattern, sourcePattern.getRequiredDeclarations(), new CollectAccumulator(collect, existSubNetwort));
AccumulateNode accNode = CoreComponentFactory.get().getNodeFactoryService().buildAccumulateNode(context.getNextNodeId(), context.getTupleSource(), context.getObjectSource(), resultAlphaConstraints.toArray(new AlphaNodeFieldConstraint[resultAlphaConstraints.size()]), // source binder
binder, resultBinder, accumulate, context);
context.setTupleSource(utils.attachNode(context, accNode));
// source pattern was bound, so nulling context
context.setObjectSource(null);
context.popRuleComponent();
}
use of org.drools.core.rule.SingleAccumulate in project drools by kiegroup.
the class KiePackagesBuilder method buildAccumulate.
private Accumulate buildAccumulate(RuleContext ctx, AccumulatePattern accPattern, RuleConditionElement source, Pattern pattern, Set<String> usedVariableName, Collection<Binding> bindings) {
boolean isGroupBy = accPattern instanceof GroupByPattern;
AccumulateFunction[] accFunctions = accPattern.getAccumulateFunctions();
Declaration groupByDeclaration = null;
Class selfType = (isGroupBy || accFunctions.length > 1) ? Object[].class : accFunctions[0].getResult().getType();
InternalReadAccessor selfReader = new SelfReferenceClassFieldReader(selfType);
int arrayIndexOffset = 0;
if (isGroupBy) {
if (accFunctions.length == 0) {
// In this situation the result is anonymous, but it still uses element position 0.
// For this reason the i used to populate hte array index must be offset by 1.
accFunctions = new AccumulateFunction[] { new AccumulateFunction(null, CountAccumulateFunction::new) };
arrayIndexOffset = 1;
}
// GroupBy key is always the last element in the result array
Variable groupVar = ((GroupByPattern<?, ?>) accPattern).getVarKey();
groupByDeclaration = new Declaration(groupVar.getName(), new ArrayElementReader(selfReader, accFunctions.length, groupVar.getType()), pattern, true);
pattern.addDeclaration(groupByDeclaration);
}
Accumulate accumulate;
Accumulator[] accumulators = new Accumulator[accFunctions.length];
List<Declaration> requiredDeclarationList = new ArrayList<>();
for (int i = 0; i < accFunctions.length; i++) {
Variable boundVar = processFunctions(ctx, accPattern, source, pattern, usedVariableName, bindings, isGroupBy, accFunctions[i], selfReader, accumulators, requiredDeclarationList, arrayIndexOffset, i);
if (isGroupBy) {
ctx.addGroupByDeclaration(((GroupByPattern) accPattern).getVarKey(), groupByDeclaration);
}
}
if (accFunctions.length == 1) {
accumulate = new SingleAccumulate(source, requiredDeclarationList.toArray(new Declaration[requiredDeclarationList.size()]), accumulators[0]);
} else {
if (source instanceof Pattern) {
requiredDeclarationList.forEach(((Pattern) source)::addDeclaration);
}
accumulate = new MultiAccumulate(source, new Declaration[0], accumulators, // if this is a groupby +1 for the key
accumulators.length + ((isGroupBy) ? 1 : 0));
}
if (isGroupBy) {
GroupByPatternImpl groupBy = (GroupByPatternImpl) accPattern;
Declaration[] groupingDeclarations = new Declaration[groupBy.getVars().length];
for (int i = 0; i < groupBy.getVars().length; i++) {
groupingDeclarations[i] = ctx.getDeclaration(groupBy.getVars()[i]);
}
accumulate = new LambdaGroupByAccumulate(accumulate, groupingDeclarations, groupBy.getGroupingFunction());
}
for (Variable boundVar : accPattern.getBoundVariables()) {
ctx.addAccumulateSource(boundVar, accumulate);
}
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, accumulators.length);
} 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 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);
} 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);
}
}
Aggregations