use of org.drools.modelcompiler.builder.generator.expressiontyper.TypedExpressionResult in project drools by kiegroup.
the class ConstraintParser method getDrlxParseResult.
private DrlxParseResult getDrlxParseResult(Class<?> patternType, String bindingId, String expression, DrlxExpression drlx, boolean isPositional) {
Expression drlxExpr = drlx.getExpr();
boolean isEnclosed = false;
while (drlxExpr instanceof EnclosedExpr) {
drlxExpr = ((EnclosedExpr) drlxExpr).getInner();
isEnclosed = true;
}
if (drlxExpr instanceof MethodCallExpr && !((MethodCallExpr) drlxExpr).getScope().isPresent() && ((MethodCallExpr) drlxExpr).getNameAsString().equals("eval")) {
drlxExpr = ((MethodCallExpr) drlxExpr).getArgument(0);
}
String exprId;
if (GENERATE_EXPR_ID) {
exprId = context.getExprId(patternType, expression);
}
if (drlxExpr instanceof BinaryExpr) {
BinaryExpr binaryExpr = (BinaryExpr) drlxExpr;
BinaryExpr.Operator operator = binaryExpr.getOperator();
IndexUtil.ConstraintType decodeConstraintType = DrlxParseUtil.toConstraintType(operator);
final ExpressionTyperContext expressionTyperContext = new ExpressionTyperContext();
final ExpressionTyper expressionTyper = new ExpressionTyper(context, patternType, bindingId, isPositional, expressionTyperContext);
TypedExpressionResult leftTypedExpressionResult = expressionTyper.toTypedExpression(binaryExpr.getLeft());
Optional<TypedExpression> optLeft = leftTypedExpressionResult.getTypedExpression();
if (!optLeft.isPresent()) {
return new DrlxParseFail();
}
List<String> usedDeclarationsOnLeft = drlx.getBind() == null ? null : new ArrayList<>(expressionTyperContext.getUsedDeclarations());
TypedExpressionResult rightExpressionResult = expressionTyper.toTypedExpression(binaryExpr.getRight());
Optional<TypedExpression> optRight = rightExpressionResult.getTypedExpression();
if (!optRight.isPresent()) {
context.addCompilationError(new ParseExpressionErrorResult(drlxExpr));
return new DrlxParseFail();
}
TypedExpression left = optLeft.get();
TypedExpression right = optRight.get();
Expression combo;
if (left.isPrimitive()) {
if (!right.getType().isPrimitive() && !Number.class.isAssignableFrom(right.getType()) && !Boolean.class.isAssignableFrom(right.getType()) && !String.class.isAssignableFrom(right.getType())) {
context.addCompilationError(new InvalidExpressionErrorResult("Comparison operation requires compatible types. Found " + left.getType() + " and " + right.getType()));
return new DrlxParseFail();
}
if (right.getExpression() instanceof StringLiteralExpr) {
right.setExpression(new IntegerLiteralExpr(((StringLiteralExpr) right.getExpression()).asString()));
} else if (right.getExpression() instanceof LiteralStringValueExpr) {
right.setExpression(coerceLiteralExprToType((LiteralStringValueExpr) right.getExpression(), left.getType()));
}
combo = new BinaryExpr(left.getExpression(), right.getExpression(), operator);
} else {
coerceRightExpression(left, right);
switch(operator) {
case EQUALS:
case NOT_EQUALS:
combo = getEqualityExpression(left, right, operator);
break;
default:
if (left.getExpression() == null || right.getExpression() == null) {
context.addCompilationError(new ParseExpressionErrorResult(drlxExpr));
return new DrlxParseFail();
}
combo = handleSpecialComparisonCases(operator, left, right);
}
}
for (Expression e : leftTypedExpressionResult.getPrefixExpressions()) {
combo = new BinaryExpr(e, combo, BinaryExpr.Operator.AND);
}
boolean isBetaNode = false;
if (right.getExpression() instanceof BinaryExpr) {
if (((BinaryExpr) right.getExpression()).getRight() instanceof MethodCallExpr) {
isBetaNode = true;
}
} else if (right.getExpression() instanceof NameExpr) {
isBetaNode = true;
}
if (isEnclosed) {
combo = new EnclosedExpr(combo);
}
return new DrlxParseSuccess(patternType, exprId, bindingId, combo, left.getType()).setDecodeConstraintType(decodeConstraintType).setUsedDeclarations(expressionTyperContext.getUsedDeclarations()).setUsedDeclarationsOnLeft(usedDeclarationsOnLeft).setReactOnProperties(expressionTyperContext.getReactOnProperties()).setLeft(left).setRight(right).setBetaNode(isBetaNode);
}
if (drlxExpr instanceof UnaryExpr) {
UnaryExpr unaryExpr = (UnaryExpr) drlxExpr;
TypedExpressionResult typedExpressionResult = new ExpressionTyper(context, patternType, bindingId, isPositional).toTypedExpression(unaryExpr);
return typedExpressionResult.getTypedExpression().<DrlxParseResult>map(left -> {
return new DrlxParseSuccess(patternType, exprId, bindingId, left.getExpression(), left.getType()).setUsedDeclarations(typedExpressionResult.getUsedDeclarations()).setReactOnProperties(typedExpressionResult.getReactOnProperties()).setLeft(left);
}).orElse(new DrlxParseFail());
}
if (drlxExpr instanceof PointFreeExpr) {
PointFreeExpr pointFreeExpr = (PointFreeExpr) drlxExpr;
TypedExpressionResult typedExpressionResult = new ExpressionTyper(context, patternType, bindingId, isPositional).toTypedExpression(pointFreeExpr);
final Optional<TypedExpression> optTypedExpression = typedExpressionResult.getTypedExpression();
return optTypedExpression.<DrlxParseResult>map(typedExpression -> {
final Expression returnExpression = typedExpression.getExpression();
final Class<?> returnType = typedExpression.getType();
return new DrlxParseSuccess(patternType, exprId, bindingId, returnExpression, returnType).setUsedDeclarations(typedExpressionResult.getUsedDeclarations()).setReactOnProperties(typedExpressionResult.getReactOnProperties()).setLeft(typedExpression.getLeft()).setStatic(typedExpression.isStatic()).setValidExpression(true);
}).orElse(new DrlxParseFail());
}
if (drlxExpr instanceof MethodCallExpr) {
MethodCallExpr methodCallExpr = (MethodCallExpr) drlxExpr;
// when the methodCallExpr will be placed in the model/DSL, any parameter being a "this" need to be implemented as _this by convention.
List<ThisExpr> rewriteThisExprs = recurseCollectArguments(methodCallExpr).stream().filter(ThisExpr.class::isInstance).map(ThisExpr.class::cast).collect(Collectors.toList());
for (ThisExpr t : rewriteThisExprs) {
methodCallExpr.replace(t, new NameExpr("_this"));
}
Optional<MethodDeclaration> functionCall = packageModel.getFunctions().stream().filter(m -> m.getName().equals(methodCallExpr.getName())).findFirst();
if (functionCall.isPresent()) {
Class<?> returnType = DrlxParseUtil.getClassFromContext(context.getTypeResolver(), functionCall.get().getType().asString());
NodeList<Expression> arguments = methodCallExpr.getArguments();
List<String> usedDeclarations = new ArrayList<>();
for (Expression arg : arguments) {
if (arg instanceof NameExpr && !arg.toString().equals("_this")) {
usedDeclarations.add(arg.toString());
} else if (arg instanceof MethodCallExpr) {
TypedExpressionResult typedExpressionResult = new ExpressionTyper(context, null, bindingId, isPositional).toTypedExpression(arg);
usedDeclarations.addAll(typedExpressionResult.getUsedDeclarations());
}
}
return new DrlxParseSuccess(patternType, exprId, bindingId, methodCallExpr, returnType).setUsedDeclarations(usedDeclarations);
} else if (methodCallExpr.getScope().isPresent() && methodCallExpr.getScope().get() instanceof StringLiteralExpr) {
TypedExpressionResult typedExpressionResult = new ExpressionTyper(context, String.class, bindingId, isPositional).toTypedExpression(methodCallExpr);
Optional<TypedExpression> optConverted = typedExpressionResult.getTypedExpression();
return optConverted.<DrlxParseResult>map(converted -> {
return new DrlxParseSuccess(String.class, exprId, bindingId, converted.getExpression(), converted.getType()).setLeft(converted).setUsedDeclarations(typedExpressionResult.getUsedDeclarations());
}).orElse(new DrlxParseFail());
} else if (patternType != null) {
NameExpr _this = new NameExpr("_this");
TypedExpression converted = DrlxParseUtil.toMethodCallWithClassCheck(context, methodCallExpr, bindingId, patternType, context.getTypeResolver());
Expression withThis = DrlxParseUtil.prepend(_this, converted.getExpression());
return new DrlxParseSuccess(patternType, exprId, bindingId, withThis, converted.getType()).setLeft(converted);
} else {
return new DrlxParseSuccess(patternType, exprId, bindingId, methodCallExpr, null);
}
}
if (drlxExpr instanceof FieldAccessExpr) {
FieldAccessExpr fieldCallExpr = (FieldAccessExpr) drlxExpr;
NameExpr _this = new NameExpr("_this");
TypedExpression converted = DrlxParseUtil.toMethodCallWithClassCheck(context, fieldCallExpr, bindingId, patternType, context.getTypeResolver());
Expression withThis = DrlxParseUtil.prepend(_this, converted.getExpression());
return new DrlxParseSuccess(patternType, exprId, bindingId, withThis, converted.getType()).setLeft(converted);
}
if (drlxExpr instanceof NameExpr) {
NameExpr nameExpr = (NameExpr) drlxExpr;
NameExpr _this = new NameExpr("_this");
TypedExpression converted = DrlxParseUtil.toMethodCallWithClassCheck(context, nameExpr, bindingId, patternType, context.getTypeResolver());
Expression withThis = DrlxParseUtil.prepend(_this, converted.getExpression());
if (drlx.getBind() != null) {
return new DrlxParseSuccess(patternType, exprId, bindingId, null, converted.getType()).setLeft(new TypedExpression(withThis, converted.getType())).addReactOnProperty(lcFirst(nameExpr.getNameAsString()));
} else {
return new DrlxParseSuccess(patternType, exprId, bindingId, withThis, converted.getType()).addReactOnProperty(nameExpr.getNameAsString());
}
}
if (drlxExpr instanceof OOPathExpr) {
return new DrlxParseSuccess(patternType, exprId, bindingId, drlxExpr, null);
}
if (drlxExpr instanceof LiteralExpr) {
return new DrlxParseSuccess(patternType, exprId, bindingId, drlxExpr, getLiteralExpressionType(((LiteralExpr) drlxExpr)));
}
// TODO
throw new UnsupportedOperationException("Unknown expression: " + toDrlx(drlxExpr));
}
use of org.drools.modelcompiler.builder.generator.expressiontyper.TypedExpressionResult in project drools by kiegroup.
the class ConstraintParser method parseFunctionInEval.
private DrlxParseResult parseFunctionInEval(MethodCallExpr methodCallExpr, Class<?> patternType, String bindingId, boolean isPositional, Optional<MethodDeclaration> functionCall) {
// when the methodCallExpr will be placed in the model/DSL, any parameter being a "this" need to be implemented as _this by convention.
List<ThisExpr> rewriteThisExprs = recurseCollectArguments(methodCallExpr).stream().filter(ThisExpr.class::isInstance).map(ThisExpr.class::cast).collect(Collectors.toList());
for (ThisExpr t : rewriteThisExprs) {
methodCallExpr.replace(t, new NameExpr(THIS_PLACEHOLDER));
}
if (functionCall.isPresent()) {
Class<?> returnType = DrlxParseUtil.getClassFromContext(context.getTypeResolver(), functionCall.get().getType().asString());
NodeList<Expression> arguments = methodCallExpr.getArguments();
List<String> usedDeclarations = new ArrayList<>();
for (Expression arg : arguments) {
String argString = printNode(arg);
if (arg instanceof DrlNameExpr && !argString.equals(THIS_PLACEHOLDER)) {
usedDeclarations.add(argString);
} else if (arg instanceof CastExpr) {
String s = printNode(((CastExpr) arg).getExpression());
usedDeclarations.add(s);
} else if (arg instanceof MethodCallExpr) {
TypedExpressionResult typedExpressionResult = new ExpressionTyper(context, null, bindingId, isPositional).toTypedExpression(arg);
usedDeclarations.addAll(typedExpressionResult.getUsedDeclarations());
}
}
return new SingleDrlxParseSuccess(patternType, bindingId, methodCallExpr, returnType).setUsedDeclarations(usedDeclarations).setIsPredicate(isBooleanBoxedUnboxed(returnType));
} else {
throw new IllegalArgumentException("Specified function call is not present!");
}
}
use of org.drools.modelcompiler.builder.generator.expressiontyper.TypedExpressionResult in project drools by kiegroup.
the class ConstraintParser method compileToJavaRecursive.
private DrlxParseResult compileToJavaRecursive(Class<?> patternType, String bindingId, ConstraintExpression constraint, Expression drlxExpr, boolean hasBind, boolean isPositional) {
boolean isEnclosed = false;
SimpleName bind = null;
if (drlxExpr instanceof FullyQualifiedInlineCastExpr) {
drlxExpr = transformFullyQualifiedInlineCastExpr(context.getTypeResolver(), (FullyQualifiedInlineCastExpr) drlxExpr);
}
while (drlxExpr instanceof EnclosedExpr) {
drlxExpr = ((EnclosedExpr) drlxExpr).getInner();
isEnclosed = true;
}
if (drlxExpr instanceof DrlxExpression) {
bind = ((DrlxExpression) drlxExpr).getBind();
drlxExpr = ((DrlxExpression) drlxExpr).getExpr();
}
if (drlxExpr instanceof MethodCallExpr && !((MethodCallExpr) drlxExpr).getScope().isPresent() && ((MethodCallExpr) drlxExpr).getNameAsString().equals("eval")) {
drlxExpr = ((MethodCallExpr) drlxExpr).getArgument(0);
}
if (drlxExpr instanceof BinaryExpr) {
DrlxParseResult result = parseBinaryExpr((BinaryExpr) drlxExpr, patternType, bindingId, constraint, drlxExpr, hasBind, isPositional, isEnclosed);
if (result instanceof SingleDrlxParseSuccess && bind != null) {
((SingleDrlxParseSuccess) result).setExprBinding(bind.asString());
}
return result;
}
if (drlxExpr instanceof UnaryExpr) {
return parseUnaryExpr((UnaryExpr) drlxExpr, patternType, bindingId, constraint, drlxExpr, hasBind, isPositional);
}
if (drlxExpr instanceof PointFreeExpr) {
return parsePointFreeExpr((PointFreeExpr) drlxExpr, patternType, bindingId, isPositional);
}
if (patternType == null && drlxExpr instanceof MethodCallExpr) {
MethodCallExpr methodCallExpr = (MethodCallExpr) drlxExpr;
Optional<MethodDeclaration> functionCall = packageModel.getFunctions().stream().filter(m -> m.getName().equals(methodCallExpr.getName())).findFirst();
if (functionCall.isPresent()) {
return parseFunctionInEval(methodCallExpr, patternType, bindingId, isPositional, functionCall);
}
}
if (drlxExpr instanceof FieldAccessExpr) {
return parseFieldAccessExpr((FieldAccessExpr) drlxExpr, patternType, bindingId);
}
String expression = constraint.getExpression();
if (drlxExpr instanceof DrlNameExpr) {
return parseNameExpr((DrlNameExpr) drlxExpr, patternType, bindingId, drlxExpr, hasBind, expression);
}
if (drlxExpr instanceof OOPathExpr) {
return parseOOPathExpr((OOPathExpr) drlxExpr, patternType, bindingId, drlxExpr, hasBind, expression);
}
if (drlxExpr instanceof LiteralExpr) {
Class<?> literalExpressionType = getLiteralExpressionType(((LiteralExpr) drlxExpr));
return new SingleDrlxParseSuccess(patternType, bindingId, drlxExpr, literalExpressionType).setIsPredicate(isBooleanBoxedUnboxed(literalExpressionType));
}
if (patternType != null) {
ExpressionTyperContext expressionTyperContext = new ExpressionTyperContext();
ExpressionTyper expressionTyper = new ExpressionTyper(context, patternType, bindingId, isPositional, expressionTyperContext);
TypedExpressionResult leftTypedExpressionResult = expressionTyper.toTypedExpression(drlxExpr);
Optional<TypedExpression> optLeft = leftTypedExpressionResult.getTypedExpression();
if (!optLeft.isPresent()) {
return new DrlxParseFail();
}
TypedExpression left = optLeft.get();
Expression combo = left.getExpression();
Type exprType = left.getType();
boolean isPredicate = isBooleanBoxedUnboxed(exprType);
if (isPredicate) {
combo = combineExpressions(leftTypedExpressionResult, combo);
}
return new SingleDrlxParseSuccess(patternType, bindingId, combo, exprType).setReactOnProperties(expressionTyperContext.getReactOnProperties()).setUsedDeclarations(expressionTyperContext.getUsedDeclarations()).setImplicitCastExpression(expressionTyperContext.getInlineCastExpression()).setNullSafeExpressions(expressionTyperContext.getNullSafeExpressions()).setIsPredicate(isPredicate);
} else {
final ExpressionTyperContext expressionTyperContext = new ExpressionTyperContext();
final ExpressionTyper expressionTyper = new ExpressionTyper(context, null, bindingId, isPositional, expressionTyperContext);
TypedExpressionResult leftTypedExpressionResult = expressionTyper.toTypedExpression(drlxExpr);
Optional<TypedExpression> optLeft = leftTypedExpressionResult.getTypedExpression();
if (!optLeft.isPresent()) {
return new DrlxParseFail();
}
TypedExpression left = optLeft.get();
return new SingleDrlxParseSuccess(null, bindingId, drlxExpr, left.getType()).setUsedDeclarations(expressionTyperContext.getUsedDeclarations()).setIsPredicate(true);
}
}
use of org.drools.modelcompiler.builder.generator.expressiontyper.TypedExpressionResult in project drools by kiegroup.
the class ExpressionTyperTest method pointFreeTest.
@Test
public void pointFreeTest() {
final PointFreeExpr expression = new PointFreeExpr(null, new NameExpr("name"), NodeList.nodeList(new StringLiteralExpr("[A-Z]")), new SimpleName("matches"), false, null, null, null, null);
TypedExpressionResult typedExpressionResult = new ExpressionTyper(ruleContext, Person.class, null, true).toTypedExpression(expression);
final TypedExpression actual = typedExpressionResult.getTypedExpression().get();
final TypedExpression expected = typedResult("D.eval(org.drools.model.operators.MatchesOperator.INSTANCE, _this.getName(), \"[A-Z]\")", String.class);
assertEquals(expected, actual);
}
use of org.drools.modelcompiler.builder.generator.expressiontyper.TypedExpressionResult in project drools by kiegroup.
the class ToTypedExpressionTest method pointFreeTest.
@Test
public void pointFreeTest() {
final PointFreeExpr expression = new PointFreeExpr(null, new NameExpr("name"), NodeList.nodeList(new StringLiteralExpr("[A-Z]")), new SimpleName("matches"), false, null, null, null, null);
TypedExpressionResult typedExpressionResult = new ExpressionTyper(ruleContext, Person.class, null, true).toTypedExpression(expression);
final TypedExpression actual = typedExpressionResult.getTypedExpression().get();
final TypedExpression expected = typedResult("eval(org.drools.model.operators.MatchesOperator.INSTANCE, _this.getName(), \"[A-Z]\")", String.class);
assertEquals(expected, actual);
}
Aggregations