use of org.drools.drl.ast.descr.ExprConstraintDescr in project drools by kiegroup.
the class PatternBuilder method lookupObjectType.
private Declaration lookupObjectType(RuleBuildContext context, PatternDescr patternDescr) {
List<? extends BaseDescr> descrs = patternDescr.getConstraint().getDescrs();
if (descrs.size() != 1 || !(descrs.get(0) instanceof ExprConstraintDescr)) {
return null;
}
ExprConstraintDescr descr = (ExprConstraintDescr) descrs.get(0);
String expr = descr.getExpression();
if (expr.charAt(0) != '/') {
return null;
}
XpathAnalysis xpathAnalysis = XpathAnalysis.analyze(expr);
if (xpathAnalysis.hasError()) {
registerDescrBuildError(context, patternDescr, "Invalid xpath expression '" + expr + "': " + xpathAnalysis.getError());
return null;
}
XpathPart firstXpathChunk = xpathAnalysis.getPart(0);
String identifier = firstXpathChunk.getField();
DeclarationScopeResolver resolver = context.getDeclarationResolver();
if (resolver.hasDataSource(identifier)) {
patternDescr.setObjectType(findObjectType(context, firstXpathChunk, identifier));
FromDescr fromDescr = new FromDescr();
fromDescr.setDataSource(new MVELExprDescr(identifier));
patternDescr.setSource(fromDescr);
patternDescr.removeAllConstraint();
firstXpathChunk.getConstraints().forEach(s -> patternDescr.addConstraint(new ExprConstraintDescr(s)));
if (!xpathAnalysis.isSinglePart()) {
String xpathExpr = (patternDescr.getIdentifier() == null ? "" : patternDescr.getIdentifier() + " : ") + expr.substring(xpathAnalysis.getPart(1).getStart());
patternDescr.addConstraint(new ExprConstraintDescr(xpathExpr));
patternDescr.setIdentifier("$void$");
}
} else {
Declaration declr = resolver.getDeclaration(identifier);
if (declr == null) {
registerDescrBuildError(context, patternDescr, "The identifier '" + identifier + "' is not in scope");
return null;
}
patternDescr.setObjectType(declr.getExtractor().getExtractToClassName());
expr = (patternDescr.getIdentifier() != null ? patternDescr.getIdentifier() + (patternDescr.isUnification() ? " := " : " : ") : "") + expr.substring(identifier.length() + 1);
descr.setExpression(expr);
return declr;
}
return null;
}
use of org.drools.drl.ast.descr.ExprConstraintDescr in project drools by kiegroup.
the class PatternBuilder method processConstraintsAndBinds.
/**
* Process all constraints and bindings on this pattern
*/
private void processConstraintsAndBinds(RuleBuildContext context, PatternDescr patternDescr, Declaration xpathStartDeclaration, Pattern pattern) {
DumperContext mvelCtx = new DumperContext().setRuleContext(context);
for (BaseDescr b : patternDescr.getDescrs()) {
String expression;
boolean isPositional = false;
if (b instanceof BindingDescr) {
BindingDescr bind = (BindingDescr) b;
expression = bind.getVariable() + (bind.isUnification() ? " := " : " : ") + bind.getExpression();
} else if (b instanceof ExprConstraintDescr) {
ExprConstraintDescr descr = (ExprConstraintDescr) b;
expression = descr.getExpression();
isPositional = descr.getType() == ExprConstraintDescr.Type.POSITIONAL;
} else {
expression = b.getText();
}
ConstraintConnectiveDescr result = parseExpression(context, patternDescr, b, expression);
if (result == null) {
return;
}
result.setNegated(b.isNegated());
isPositional &= !(result.getDescrs().size() == 1 && result.getDescrs().get(0) instanceof BindingDescr);
if (isPositional) {
processPositional(context, patternDescr, xpathStartDeclaration, pattern, (ExprConstraintDescr) b);
} else {
// need to build the actual constraint
List<Constraint> constraints = build(context, patternDescr, xpathStartDeclaration, pattern, result, mvelCtx);
pattern.addConstraints(constraints);
}
}
TypeDeclaration typeDeclaration = getTypeDeclaration(pattern, context);
if (typeDeclaration != null && typeDeclaration.isPropertyReactive()) {
for (String field : lookAheadFieldsOfIdentifier(context.getRuleDescr(), patternDescr)) {
addFieldToPatternWatchlist(pattern, typeDeclaration, field);
}
}
}
use of org.drools.drl.ast.descr.ExprConstraintDescr in project drools by kiegroup.
the class PatternBuilder method buildXPathDescr.
private Constraint buildXPathDescr(RuleBuildContext context, PatternDescr patternDescr, Declaration xpathStartDeclaration, Pattern pattern, ExpressionDescr descr, DumperContext mvelCtx) {
String expression = descr.getExpression();
XpathAnalysis xpathAnalysis = XpathAnalysis.analyze(expression);
if (xpathAnalysis.hasError()) {
registerDescrBuildError(context, patternDescr, "Invalid xpath expression '" + expression + "': " + xpathAnalysis.getError());
return null;
}
XpathConstraint xpathConstraint = new XpathConstraint();
ObjectType objectType = pattern.getObjectType();
if (objectType.isTemplate()) {
throw new UnsupportedOperationException("xpath is not supported with fact templates");
}
Class<?> patternClass = ((ClassObjectType) objectType).getClassType();
List<Class<?>> backReferenceClasses = new ArrayList<>();
backReferenceClasses.add(patternClass);
XpathBackReference backRef = new XpathBackReference(pattern, backReferenceClasses);
pattern.setBackRefDeclarations(backRef);
ObjectType originalType = pattern.getObjectType();
ObjectType currentObjectType = originalType;
mvelCtx.setInXpath(true);
try {
// then the xpathoffset must be adjusted by -1, as pattern is not actually added to the rete network
for (XpathAnalysis.XpathPart part : xpathAnalysis) {
XpathConstraint.XpathChunk xpathChunk = xpathConstraint.addChunck(patternClass, part.getField(), part.getIndex(), part.isIterate(), part.isLazy());
// make sure the Pattern is wired up to correct ClassObjectType and set as a target for rewiring
context.getPkg().wireObjectType(currentObjectType, xpathChunk);
if (xpathChunk == null) {
registerDescrBuildError(context, patternDescr, "Invalid xpath expression '" + expression + "': cannot access " + part.getField() + " on " + patternClass);
pattern.setObjectType(originalType);
return null;
}
if (part.getInlineCast() != null) {
try {
patternClass = context.getDialect().getTypeResolver().resolveType(part.getInlineCast());
} catch (ClassNotFoundException e) {
registerDescrBuildError(context, patternDescr, "Unknown class " + part.getInlineCast() + " in xpath expression '" + expression + "'");
return null;
}
part.addInlineCastConstraint(patternClass);
currentObjectType = getObjectType(context, patternDescr, patternClass.getName());
xpathChunk.setReturnedType(currentObjectType);
} else {
patternClass = xpathChunk.getReturnedClass();
currentObjectType = getObjectType(context, patternDescr, patternClass.getName());
}
context.increaseXpathChuckNr();
pattern.setObjectType(currentObjectType);
backReferenceClasses.add(0, patternClass);
backRef.reset();
for (String constraint : part.getConstraints()) {
ConstraintConnectiveDescr result = parseExpression(context, patternDescr, new ExprConstraintDescr(constraint), constraint);
if (result == null) {
continue;
}
// preserving this, as the recursive build() resets it
int chunkNbr = context.getXpathChuckNr();
for (Constraint c : build(context, patternDescr, xpathStartDeclaration, pattern, result, mvelCtx)) {
xpathChunk.addConstraint(c);
}
context.setXpathChuckNr(chunkNbr);
}
}
xpathConstraint.setXpathStartDeclaration(xpathStartDeclaration);
if (descr instanceof BindingDescr) {
Declaration pathDeclr = pattern.addDeclaration(((BindingDescr) descr).getVariable());
pathDeclr.setxPathOffset(context.getXpathChuckNr());
xpathConstraint.setDeclaration(pathDeclr);
}
} finally {
mvelCtx.setInXpath(false);
pattern.setBackRefDeclarations(null);
pattern.setObjectType(originalType);
context.resetXpathChuckNr();
}
return xpathConstraint;
}
use of org.drools.drl.ast.descr.ExprConstraintDescr in project drools by kiegroup.
the class PatternDescrBuilderImpl method constraint.
public PatternDescrBuilder<P> constraint(String constraint) {
ExprConstraintDescr constr = new ExprConstraintDescr(constraint);
constr.setType(ExprConstraintDescr.Type.NAMED);
constr.setPosition(descr.getConstraint().getDescrs().size());
constr.setResource(descr.getResource());
descr.addConstraint(constr);
return this;
}
use of org.drools.drl.ast.descr.ExprConstraintDescr in project drools by kiegroup.
the class Query method buildPattern.
@Override
public void buildPattern() {
NameExpr queryCall = new NameExpr(toQueryDef(pattern.getObjectType()));
MethodCallExpr callCall = new MethodCallExpr(queryCall, QUERY_INVOCATION_CALL);
callCall.addArgument("" + !pattern.isQuery());
if (!constraintDescrs.isEmpty()) {
List<QueryParameter> queryParams = packageModel.queryVariables(queryName);
if (queryParams.size() != constraintDescrs.size()) {
context.addCompilationError(new InvalidExpressionErrorResult("Wrong number of argument invoking query '" + queryName + "'"));
return;
}
Expression[] queryArgs = new Expression[queryParams.size()];
for (int i = 0; i < constraintDescrs.size(); i++) {
BaseDescr baseDescr = constraintDescrs.get(i);
String itemText = baseDescr.getText();
boolean isPositional = baseDescr instanceof ExprConstraintDescr && ((ExprConstraintDescr) baseDescr).getType() == ExprConstraintDescr.Type.POSITIONAL;
boolean isBinding = baseDescr instanceof BindingDescr || itemText.contains(":");
if ((!isPositional) && (!isBinding)) {
// error, can't have non binding slots.
context.addCompilationError(new InvalidExpressionErrorResult("Query's must use positional or bindings, not field constraints: " + itemText));
} else if (isPositional && isBinding) {
// error, can't have positional binding slots.
context.addCompilationError(new InvalidExpressionErrorResult("Query's can't use positional bindings: " + itemText));
}
int colonPos = itemText.indexOf(':');
if (colonPos > 0) {
String bindingId = itemText.substring(0, colonPos).trim();
String paramName = itemText.substring(colonPos + 1).trim();
for (int j = 0; j < queryParams.size(); j++) {
if (queryParams.get(j).getName().equals(paramName)) {
addQueryArg(queryParams, queryArgs, bindingId, j);
break;
} else if (queryParams.get(j).getName().equals(bindingId)) {
addQueryArg(queryParams, queryArgs, paramName, j);
break;
}
}
} else {
addQueryArg(queryParams, queryArgs, itemText, i);
}
}
for (Expression queryArg : queryArgs) {
callCall.addArgument(queryArg);
}
}
context.addExpression(callCall);
}
Aggregations