use of org.drools.mvel.parser.ast.expr.DrlNameExpr in project drools by kiegroup.
the class DrlxParseUtil method getExpressionType.
public static java.lang.reflect.Type getExpressionType(RuleContext context, TypeResolver typeResolver, Expression expr, Collection<String> usedDeclarations) {
if (expr instanceof LiteralExpr) {
return getLiteralExpressionType((LiteralExpr) expr);
}
if (expr instanceof UnaryExpr) {
return getExpressionType(context, typeResolver, expr.asUnaryExpr().getExpression(), usedDeclarations);
}
if (expr instanceof ArrayAccessExpr) {
return getClassFromContext(typeResolver, ((ArrayCreationExpr) ((ArrayAccessExpr) expr).getName()).getElementType().asString());
}
if (expr instanceof ArrayCreationExpr) {
return getClassFromContext(typeResolver, ((ArrayCreationExpr) expr).getElementType().asString());
}
if (expr instanceof MapCreationLiteralExpression) {
return Map.class;
}
if (expr instanceof ListCreationLiteralExpression) {
return List.class;
}
if (expr instanceof NameExpr) {
return expressionTypeNameExpr(context, usedDeclarations, ((NameExpr) expr).getNameAsString());
}
if (expr instanceof DrlNameExpr) {
return expressionTypeNameExpr(context, usedDeclarations, ((DrlNameExpr) expr).getNameAsString());
}
if (expr instanceof BinaryExpr) {
return boolean.class;
}
if (expr instanceof MethodCallExpr) {
MethodCallExpr methodCallExpr = (MethodCallExpr) expr;
Optional<Expression> scopeExpression = methodCallExpr.getScope();
if (scopeExpression.isPresent()) {
java.lang.reflect.Type scopeType = getExpressionType(context, typeResolver, scopeExpression.get(), usedDeclarations);
return returnTypeOfMethodCallExpr(context, typeResolver, methodCallExpr, scopeType, usedDeclarations);
} else {
throw new IllegalStateException("Scope expression is not present for " + ((MethodCallExpr) expr).getNameAsString() + "!");
}
}
if (expr instanceof ObjectCreationExpr) {
final ClassOrInterfaceType type = ((ObjectCreationExpr) expr).getType();
return getClassFromContext(typeResolver, type.asString());
}
if (expr.isCastExpr()) {
String typeName = expr.asCastExpr().getType().toString();
try {
return typeResolver.resolveType(expr.asCastExpr().getType().toString());
} catch (ClassNotFoundException e) {
context.addCompilationError(new InvalidExpressionErrorResult("Unknown type in cast expression: " + typeName));
throw new RuntimeException("Unknown type in cast expression: " + typeName);
}
}
if (expr instanceof ConditionalExpr) {
ConditionalExpr ternaryExpr = ((ConditionalExpr) expr);
java.lang.reflect.Type conditionType = getExpressionType(context, typeResolver, ternaryExpr.getCondition(), usedDeclarations);
if (conditionType != Boolean.class && conditionType != boolean.class) {
context.addCompilationError(new InvalidExpressionErrorResult("Condtion used in ternary expression '" + expr + "' isn't boolean"));
return Object.class;
}
java.lang.reflect.Type leftType = getExpressionType(context, typeResolver, ternaryExpr.getThenExpr(), usedDeclarations);
java.lang.reflect.Type rightType = getExpressionType(context, typeResolver, ternaryExpr.getElseExpr(), usedDeclarations);
Class<?> leftClass = toRawClass(leftType);
Class<?> rightClass = toRawClass(rightType);
if (leftClass.isAssignableFrom(rightClass)) {
return leftType;
}
if (rightClass.isAssignableFrom(leftClass)) {
return rightType;
}
return Object.class;
}
if (expr.isClassExpr()) {
return Class.class;
}
throw new RuntimeException("Unknown expression type: " + PrintUtil.printNode(expr));
}
use of org.drools.mvel.parser.ast.expr.DrlNameExpr in project drools by kiegroup.
the class DroolsMvelParserTest method testOOPathExprWithBackReference.
@Test
public void testOOPathExprWithBackReference() {
String expr = "$toy : /wife/children/toys[name.length == ../../name.length]";
DrlxExpression drlx = parseExpression(parser, expr);
assertEquals("$toy", drlx.getBind().asString());
Expression expression = drlx.getExpr();
assertTrue(expression instanceof OOPathExpr);
final OOPathChunk secondChunk = ((OOPathExpr) expression).getChunks().get(2);
final BinaryExpr secondChunkFirstCondition = (BinaryExpr) secondChunk.getConditions().get(0).getExpr();
final DrlNameExpr rightName = (DrlNameExpr) ((FieldAccessExpr) secondChunkFirstCondition.getRight()).getScope();
assertEquals(2, rightName.getBackReferencesCount());
assertEquals(expr, printNode(drlx));
}
use of org.drools.mvel.parser.ast.expr.DrlNameExpr in project drools by kiegroup.
the class ExpressionTyper method drlNameExpr.
private Optional<TypedExpressionCursor> drlNameExpr(Expression drlxExpr, DrlNameExpr firstNode, boolean isInLineCast, java.lang.reflect.Type originalTypeCursor) {
String firstName = firstNode.getName().getIdentifier();
java.lang.reflect.Type typeCursor;
// In OOPath a declaration is based on a position rather than a name.
// Only an OOPath chunk can have a backreference expression
Optional<DeclarationSpec> backReference = empty();
if (firstNode.getBackReferencesCount() > 0) {
List<DeclarationSpec> ooPathDeclarations = ruleContext.getOOPathDeclarations();
DeclarationSpec backReferenceDeclaration = ooPathDeclarations.get(ooPathDeclarations.size() - 1 - firstNode.getBackReferencesCount());
typeCursor = backReferenceDeclaration.getDeclarationClass();
backReference = of(backReferenceDeclaration);
context.addUsedDeclarations(backReferenceDeclaration.getBindingId());
} else {
typeCursor = originalTypeCursor;
}
try {
Class<?> resolvedType = ruleContext.getTypeResolver().resolveType(firstName);
return of(new TypedExpressionCursor(new NameExpr(firstName), resolvedType));
} catch (ClassNotFoundException e) {
// ignore
}
Class<?> classCursor = toRawClass(typeCursor);
if (classCursor != null) {
Method firstAccessor = DrlxParseUtil.getAccessor(!isInLineCast ? classCursor : patternType, firstName, ruleContext);
if (firstAccessor != null) {
if (!"".equals(firstName)) {
context.addReactOnProperties(firstName);
}
NameExpr thisAccessor = new NameExpr(THIS_PLACEHOLDER);
NameExpr scope = backReference.map(d -> new NameExpr(d.getBindingId())).orElse(thisAccessor);
Expression fieldAccessor = new MethodCallExpr(scope, firstAccessor.getName());
if (isInLineCast) {
return of(new TypedExpressionCursor(fieldAccessor, typeCursor));
}
Optional<java.lang.reflect.Type> castType = ruleContext.explicitCastType(firstName).flatMap(t -> safeResolveType(ruleContext.getTypeResolver(), t.asString()));
if (castType.isPresent()) {
java.lang.reflect.Type typeOfFirstAccessor = castType.get();
ClassOrInterfaceType typeWithoutDollar = toClassOrInterfaceType(typeOfFirstAccessor.getTypeName());
return of(new TypedExpressionCursor(addCastToExpression(typeWithoutDollar, fieldAccessor, false), typeOfFirstAccessor));
}
return of(new TypedExpressionCursor(fieldAccessor, firstAccessor.getGenericReturnType()));
}
Field field = DrlxParseUtil.getField(classCursor, firstName);
if (field != null) {
NameExpr scope = new NameExpr(Modifier.isStatic(field.getModifiers()) ? classCursor.getCanonicalName() : THIS_PLACEHOLDER);
return of(new TypedExpressionCursor(new FieldAccessExpr(scope, field.getName()), field.getType()));
}
}
Optional<DeclarationSpec> declarationById = ruleContext.getDeclarationById(firstName);
if (declarationById.isPresent()) {
// do NOT append any reactOnProperties.
// because reactOnProperties is referring only to the properties of the type of the pattern, not other declarations properites.
context.addUsedDeclarations(firstName);
typeCursor = isInLineCast ? originalTypeCursor : declarationById.get().getDeclarationClass();
return of(new TypedExpressionCursor(new NameExpr(firstName), typeCursor));
}
if (packageModel.getGlobals().containsKey(firstName)) {
context.addUsedDeclarations(firstName);
return of(new TypedExpressionCursor(new NameExpr(firstName), packageModel.getGlobals().get(firstName)));
}
final Optional<Node> rootNode = findRootNodeViaParent(drlxExpr);
rootNode.ifPresent(n -> {
// In the error messages HalfBinary are transformed to Binary
Node withHalfBinaryReplaced = replaceAllHalfBinaryChildren(n);
ruleContext.addCompilationError(new ParseExpressionErrorResult((Expression) withHalfBinaryReplaced, ruleContext.getCurrentConstraintDescr()));
});
return empty();
}
use of org.drools.mvel.parser.ast.expr.DrlNameExpr in project drools by kiegroup.
the class ExpressionTyper method processFirstNode.
private Optional<TypedExpressionCursor> processFirstNode(Expression drlxExpr, List<Node> childNodes, Node firstNode, boolean isInLineCast, java.lang.reflect.Type originalTypeCursor) {
Optional<TypedExpressionCursor> result;
if (isThisExpression(firstNode) || (firstNode instanceof DrlNameExpr && printNode(firstNode).equals(bindingId))) {
result = of(thisExpr(drlxExpr, childNodes, isInLineCast, originalTypeCursor));
} else if (firstNode instanceof DrlNameExpr) {
result = drlNameExpr(drlxExpr, (DrlNameExpr) firstNode, isInLineCast, originalTypeCursor);
} else if (firstNode instanceof NameExpr) {
result = drlNameExpr(drlxExpr, new DrlNameExpr(((NameExpr) firstNode).getName()), isInLineCast, originalTypeCursor);
} else if (firstNode instanceof FieldAccessExpr) {
if (((FieldAccessExpr) firstNode).getScope() instanceof ThisExpr) {
result = of(fieldAccessExpr(originalTypeCursor, ((FieldAccessExpr) firstNode).getName()));
} else {
try {
Class<?> resolvedType = ruleContext.getTypeResolver().resolveType(PrintUtil.printNode(firstNode));
result = of(new TypedExpressionCursor(new NameExpr(PrintUtil.printNode(firstNode)), resolvedType));
} catch (ClassNotFoundException e) {
result = empty();
}
}
} else if (firstNode instanceof NullSafeFieldAccessExpr && ((NullSafeFieldAccessExpr) firstNode).getScope() instanceof ThisExpr) {
result = of(fieldAccessExpr(originalTypeCursor, ((NullSafeFieldAccessExpr) firstNode).getName()));
} else if (firstNode instanceof MethodCallExpr) {
Optional<Expression> scopeExpr = ((MethodCallExpr) firstNode).getScope();
Optional<DeclarationSpec> scopeDecl = scopeExpr.flatMap(scope -> ruleContext.getDeclarationById(PrintUtil.printNode(scope)));
Expression scope;
java.lang.reflect.Type type;
if (scopeDecl.isPresent() && !scopeDecl.get().getBindingId().equals(bindingId)) {
type = scopeDecl.get().getDeclarationClass();
scope = new NameExpr(scopeDecl.get().getBindingId());
context.addUsedDeclarations(scopeDecl.get().getBindingId());
} else if (scopeExpr.isPresent()) {
TypedExpressionCursor parsedScope = processFirstNode(drlxExpr, childNodes, scopeExpr.get(), isInLineCast, originalTypeCursor).get();
type = parsedScope.typeCursor;
scope = parsedScope.expressionCursor;
} else {
type = originalTypeCursor;
scope = new NameExpr(THIS_PLACEHOLDER);
}
result = of(methodCallExpr((MethodCallExpr) firstNode, type, scope));
} else if (firstNode instanceof ObjectCreationExpr) {
result = of(objectCreationExpr((ObjectCreationExpr) firstNode));
} else if (firstNode instanceof StringLiteralExpr) {
result = of(stringLiteralExpr((StringLiteralExpr) firstNode));
} else if (firstNode instanceof EnclosedExpr) {
result = processFirstNode(drlxExpr, childNodes, ((EnclosedExpr) firstNode).getInner(), isInLineCast, originalTypeCursor);
} else if (firstNode instanceof CastExpr) {
result = castExpr((CastExpr) firstNode, drlxExpr, childNodes, isInLineCast, originalTypeCursor);
} else if (firstNode instanceof ArrayCreationExpr) {
result = of(arrayCreationExpr(((ArrayCreationExpr) firstNode)));
} else if (firstNode instanceof BinaryExpr) {
result = of(binaryExpr((BinaryExpr) firstNode));
} else if (firstNode instanceof ArrayAccessExpr) {
Optional<DeclarationSpec> scopeDecl = ruleContext.getDeclarationById(((ArrayAccessExpr) firstNode).getName().toString());
Expression scope;
java.lang.reflect.Type type;
if (scopeDecl.isPresent() && !scopeDecl.get().getBindingId().equals(bindingId)) {
type = scopeDecl.get().getDeclarationClass();
scope = new NameExpr(scopeDecl.get().getBindingId());
context.addUsedDeclarations(scopeDecl.get().getBindingId());
} else {
type = originalTypeCursor;
scope = new NameExpr(THIS_PLACEHOLDER);
}
result = arrayAccessExpr((ArrayAccessExpr) firstNode, type, scope);
} else if (firstNode instanceof MapCreationLiteralExpression) {
result = mapCreationLiteral((MapCreationLiteralExpression) firstNode, originalTypeCursor);
} else if (firstNode instanceof ListCreationLiteralExpression) {
result = listCreationLiteral((ListCreationLiteralExpression) firstNode, originalTypeCursor);
} else {
result = of(new TypedExpressionCursor((Expression) firstNode, getExpressionType(ruleContext, ruleContext.getTypeResolver(), (Expression) firstNode, context.getUsedDeclarations())));
}
if (result.isPresent()) {
processNullSafeDereferencing(drlxExpr);
}
return result.map(te -> {
if (isInLineCast) {
Expression exprWithInlineCast = addCastToExpression(toRawClass(te.typeCursor), te.expressionCursor, isInLineCast);
return new TypedExpressionCursor(exprWithInlineCast, te.typeCursor);
} else {
return te;
}
});
}
use of org.drools.mvel.parser.ast.expr.DrlNameExpr in project drools by kiegroup.
the class ConstraintParser method parseNameExpr.
private DrlxParseResult parseNameExpr(DrlNameExpr nameExpr, Class<?> patternType, String bindingId, Expression drlxExpr, boolean hasBind, String expression) {
TypedExpression converted;
final ExpressionTyperContext expressionTyperContext = new ExpressionTyperContext();
final ExpressionTyper expressionTyper = new ExpressionTyper(context, patternType, bindingId, false, expressionTyperContext);
Optional<TypedExpression> typedExpressionResult = expressionTyper.toTypedExpression(nameExpr).getTypedExpression();
if (!typedExpressionResult.isPresent()) {
return new DrlxParseFail();
}
converted = typedExpressionResult.get();
Expression withThis = DrlxParseUtil.prepend(new NameExpr(THIS_PLACEHOLDER), converted.getExpression());
if (hasBind) {
return new SingleDrlxParseSuccess(patternType, bindingId, null, converted.getType()).setLeft(new TypedExpression(withThis, converted.getType())).addReactOnProperty(lcFirstForBean(nameExpr.getNameAsString()));
} else if (context.hasDeclaration(expression)) {
Optional<DeclarationSpec> declarationSpec = context.getDeclarationById(expression);
if (declarationSpec.isPresent()) {
return new SingleDrlxParseSuccess(patternType, bindingId, context.getVarExpr(printNode(drlxExpr)), declarationSpec.get().getDeclarationClass()).setIsPredicate(true);
} else {
throw new IllegalArgumentException("Cannot find declaration specification by specified expression " + expression + "!");
}
} else {
return new SingleDrlxParseSuccess(patternType, bindingId, withThis, converted.getType()).addReactOnProperty(nameExpr.getNameAsString()).setIsPredicate(true);
}
}
Aggregations