use of org.kie.api.runtime.rule.AccumulateFunction in project drools by kiegroup.
the class KnowledgePackageImpl method readExternal.
/**
* Handles the read serialization of the Package. Patterns in Rules may
* reference generated data which cannot be serialized by default methods.
* The Package uses PackageCompilationData to hold a reference to the
* generated bytecode; which must be restored before any Rules. A custom
* ObjectInputStream, able to resolve classes against the bytecode in the
* PackageCompilationData, is used to restore the Rules.
*
* @param stream, the stream to read data from in order to restore the object;
* should be an instance of DroolsObjectInputStream or
* InputStream
*/
public void readExternal(ObjectInput stream) throws IOException, ClassNotFoundException {
boolean isDroolsStream = stream instanceof DroolsObjectInputStream;
DroolsObjectInputStream in = isDroolsStream ? (DroolsObjectInputStream) stream : new DroolsObjectInputStream(new ByteArrayInputStream((byte[]) stream.readObject()));
this.name = (String) in.readObject();
this.classFieldAccessorStore = (ClassFieldAccessorStore) in.readObject();
in.setStore(this.classFieldAccessorStore);
this.dialectRuntimeRegistry = (DialectRuntimeRegistry) in.readObject();
this.typeDeclarations = (Map) in.readObject();
this.imports = (Map<String, ImportDeclaration>) in.readObject();
this.staticImports = (Set) in.readObject();
this.functions = (Map<String, Function>) in.readObject();
this.accumulateFunctions = (Map<String, AccumulateFunction>) in.readObject();
this.factTemplates = (Map) in.readObject();
this.ruleFlows = (Map) in.readObject();
this.globals = (Map<String, String>) in.readObject();
this.valid = in.readBoolean();
this.needStreamMode = in.readBoolean();
this.rules = (Map<String, RuleImpl>) in.readObject();
this.entryPointsIds = (Set<String>) in.readObject();
this.windowDeclarations = (Map<String, WindowDeclaration>) in.readObject();
this.traitRegistry = (TraitRegistry) in.readObject();
this.resourceTypePackages = (Map<ResourceType, ResourceTypePackage>) in.readObject();
in.setStore(null);
if (!isDroolsStream) {
in.close();
}
}
use of org.kie.api.runtime.rule.AccumulateFunction in project drools by kiegroup.
the class AccumulateVisitor method visit.
protected Optional<AccumulateVisitorPatternDSL.NewBinding> visit(RuleContext context, AccumulateDescr.AccumulateFunctionCallDescr function, MethodCallExpr accumulateDSL, PatternDescr basePattern, boolean inputPatternHasConstraints) {
context.pushExprPointer(accumulateDSL::addArgument);
final MethodCallExpr functionDSL = new MethodCallExpr(null, "accFunction");
final String expression = function.getParams()[0];
final Expression expr = DrlxParseUtil.parseExpression(expression).getExpr();
final String bindingId = Optional.ofNullable(function.getBind()).orElse(basePattern.getIdentifier());
Optional<AccumulateVisitorPatternDSL.NewBinding> newBinding = Optional.empty();
if (expr instanceof BinaryExpr) {
final DrlxParseResult parseResult = new ConstraintParser(context, packageModel).drlxParse(Object.class, bindingId, expression);
newBinding = parseResult.acceptWithReturnValue(new ParseResultVisitor<Optional<AccumulateVisitorPatternDSL.NewBinding>>() {
@Override
public Optional<AccumulateVisitorPatternDSL.NewBinding> onSuccess(DrlxParseSuccess drlxParseResult) {
final AccumulateFunction accumulateFunction = AccumulateVisitor.this.getAccumulateFunction(function, drlxParseResult.getExprType());
final String bindExpressionVariable = context.getExprId(accumulateFunction.getResultType(), drlxParseResult.getLeft().toString());
drlxParseResult.setExprBinding(bindExpressionVariable);
context.addDeclarationReplacing(new DeclarationSpec(drlxParseResult.getPatternBinding(), drlxParseResult.getExprType()));
functionDSL.addArgument(new ClassExpr(toType(accumulateFunction.getClass())));
final MethodCallExpr newBindingFromBinary = AccumulateVisitor.this.buildBinding(bindExpressionVariable, drlxParseResult.getUsedDeclarations(), drlxParseResult.getExpr());
context.addDeclarationReplacing(new DeclarationSpec(bindExpressionVariable, drlxParseResult.getExprType()));
functionDSL.addArgument(new NameExpr(toVar(bindExpressionVariable)));
return Optional.of(new AccumulateVisitorPatternDSL.NewBinding(Optional.empty(), newBindingFromBinary));
}
@Override
public Optional<AccumulateVisitorPatternDSL.NewBinding> onFail(DrlxParseFail failure) {
return Optional.empty();
}
});
} else if (expr instanceof MethodCallExpr) {
final DrlxParseUtil.RemoveRootNodeResult methodCallWithoutRootNode = DrlxParseUtil.removeRootNode(expr);
final String rootNodeName = getRootNodeName(methodCallWithoutRootNode);
final TypedExpression typedExpression = parseMethodCallType(context, rootNodeName, methodCallWithoutRootNode.getWithoutRootNode());
final Class<?> methodCallExprType = typedExpression.getType();
final AccumulateFunction accumulateFunction = getAccumulateFunction(function, methodCallExprType);
final Class accumulateFunctionResultType = accumulateFunction.getResultType();
functionDSL.addArgument(new ClassExpr(toType(accumulateFunction.getClass())));
// Every expression in an accumulate function gets transformed in a bind expression with a generated id
// Then the accumulate function will have that binding expression as a source
final String bindExpressionVariable = context.getExprId(accumulateFunctionResultType, typedExpression.toString());
Expression withThis = DrlxParseUtil.prepend(DrlxParseUtil._THIS_EXPR, typedExpression.getExpression());
DrlxParseSuccess result = new DrlxParseSuccess(accumulateFunctionResultType, "", rootNodeName, withThis, accumulateFunctionResultType).setLeft(typedExpression).setExprBinding(bindExpressionVariable);
final MethodCallExpr binding = expressionBuilder.buildBinding(result);
newBinding = Optional.of(new AccumulateVisitorPatternDSL.NewBinding(Optional.of(result.getPatternBinding()), binding));
context.addDeclarationReplacing(new DeclarationSpec(bindExpressionVariable, methodCallExprType));
functionDSL.addArgument(new NameExpr(toVar(bindExpressionVariable)));
context.addDeclarationReplacing(new DeclarationSpec(bindingId, accumulateFunctionResultType));
} else if (expr instanceof NameExpr) {
final Class<?> declarationClass = context.getDeclarationById(expr.toString()).orElseThrow(RuntimeException::new).getDeclarationClass();
final String nameExpr = ((NameExpr) expr).getName().asString();
final AccumulateFunction accumulateFunction = getAccumulateFunction(function, declarationClass);
functionDSL.addArgument(new ClassExpr(toType(accumulateFunction.getClass())));
functionDSL.addArgument(new NameExpr(toVar(nameExpr)));
Class accumulateFunctionResultType = accumulateFunction.getResultType();
if (accumulateFunctionResultType == Comparable.class && (Comparable.class.isAssignableFrom(declarationClass) || declarationClass.isPrimitive())) {
accumulateFunctionResultType = declarationClass;
}
context.addDeclarationReplacing(new DeclarationSpec(bindingId, accumulateFunctionResultType));
} else {
throw new UnsupportedOperationException("Unsupported expression " + expr);
}
final MethodCallExpr asDSL = new MethodCallExpr(functionDSL, "as");
asDSL.addArgument(new NameExpr(toVar(bindingId)));
accumulateDSL.addArgument(asDSL);
context.popExprPointer();
return newBinding;
}
use of org.kie.api.runtime.rule.AccumulateFunction 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);
}
}
Aggregations