private void resolveToFunctionReturnType(String functionName) { JpqlFunction function = functions.get(functionName.toLowerCase()); if (function == null) { return; } List<PathPosition> currentPositions = pathPositions; int positionsSize = currentPositions.size(); for (int i = 0; i < positionsSize; i++) { PathPosition position = currentPositions.get(i); Class<?> returnType = function.getReturnType(position.getCurrentClass()); position.setAttribute(null); position.setCurrentType(metamodel.type(returnType)); } }
@Override public void visit(TreatExpression expression) { boolean handled = false; if (expression.getExpression() instanceof PathExpression) { PathExpression treatPath = (PathExpression) expression.getExpression(); if (treatPath.getExpressions().size() == 1 && skipBaseNodeAlias.equals(treatPath.getExpressions().get(0).toString())) { // When we encounter a naked root treat like "TREAT(alias AS Subtype)" we always skip it handled = true; } } if (!handled) { expression.getExpression().accept(this); } EntityType<?> type = metamodel.getEntity(expression.getType()); // TODO: should we check if the type is actually a sub- or super type? currentPosition.setCurrentType(type); currentPosition.setValueType(type); }
@Override public void visit(TreatExpression expression) { boolean handled = false; if (expression.getExpression() instanceof PathExpression) { PathExpression treatPath = (PathExpression) expression.getExpression(); if (treatPath.getExpressions().size() == 1 && skipBaseNodeAlias.equals(treatPath.getExpressions().get(0).toString())) { // When we encounter a naked root treat like "TREAT(alias AS Subtype)" we always skip it handled = true; } } if (!handled) { expression.getExpression().accept(this); } EntityType<?> type = metamodel.getEntity(expression.getType()); // TODO: should we check if the type is actually a sub- or super type? currentPosition.setCurrentType(type); currentPosition.setValueType(type); }
@Override public void visit(FunctionExpression expression) { String name = expression.getFunctionName(); if ("FUNCTION".equalsIgnoreCase(name)) { // Skip the function name resolveFirst(expression.getExpressions().subList(1, expression.getExpressions().size()), true); resolveToFunctionReturnType(((StringLiteral) expression.getExpressions().get(0)).getValue()); } else if (ExpressionUtils.isSizeFunction(expression)) { // According to our grammar, we can only get a path here currentPosition.setAttribute(null); currentPosition.setCurrentType(metamodel.type(Long.class)); } else { resolveFirst(expression.getExpressions(), true); resolveToFunctionReturnType(name); } }
@Override public void visit(TimeLiteral expression) { currentPosition.setCurrentType(metamodel.type(Date.class)); }
@Override public void visit(MapEntryExpression expression) { expression.getPath().accept(this); currentPosition.setAttribute(new MapEntryAttribute<>((MapAttribute<?, Object, ?>) currentPosition.getAttribute())); currentPosition.setCurrentType(metamodel.type(Map.Entry.class)); }
@Override public void visit(TrimExpression expression) { currentPosition.setAttribute(null); currentPosition.setCurrentType(metamodel.type(String.class)); }
@Override public void visit(MapEntryExpression expression) { expression.getPath().accept(this); if (!(currentPosition.getAttribute() instanceof MapAttribute<?, ?, ?>)) { invalid(expression, "Does not resolve to java.util.Map!"); } else { currentPosition.setAttribute(null); currentPosition.setCurrentType(metamodel.type(Map.Entry.class)); } }
@Override public void visit(ListIndexExpression expression) { expression.getPath().accept(this); if (!(currentPosition.getAttribute() instanceof ListAttribute<?, ?>)) { invalid(expression, "Does not resolve to java.util.List!"); } else { currentPosition.setAttribute(new ListIndexAttribute<>((ListAttribute<?, ?>) currentPosition.getAttribute())); currentPosition.setCurrentType(metamodel.type(Integer.class)); } }
@Override public void visit(TreatExpression expression) { EntityType<?> type = metamodel.getEntity(expression.getType()); currentPosition.setAttribute(null); currentPosition.setCurrentType(type); }
@Override public void visit(BooleanLiteral expression) { currentPosition.setCurrentType(metamodel.type(Boolean.class)); }
@Override public void visit(StringLiteral expression) { currentPosition.setCurrentType(metamodel.type(String.class)); }
@Override public void visit(TimestampLiteral expression) { currentPosition.setCurrentType(metamodel.type(Date.class)); }
@Override public void visit(DateLiteral expression) { currentPosition.setCurrentType(metamodel.type(Date.class)); }
@Override public void visit(MapKeyExpression expression) { expression.getPath().accept(this); if (!(currentPosition.getAttribute() instanceof MapAttribute<?, ?, ?>)) { invalid(expression, "Does not resolve to java.util.Map!"); } else { currentPosition.setAttribute(new MapKeyAttribute<>((MapAttribute<?, Object, ?>) currentPosition.getAttribute())); currentPosition.setCurrentType(((MapAttribute<?, Object, ?>) currentPosition.getAttribute()).getKeyType()); } }
@Override public void visit(NumericLiteral expression) { if (expression.getNumericType() != null) { currentPosition.setCurrentType(metamodel.type(expression.getNumericType().getJavaType())); } }
@Override public void visit(ArithmeticFactor expression) { if (expression.getNumericType() != null) { currentPosition.setCurrentType(metamodel.type(expression.getNumericType().getJavaType())); } }
@Override public void visit(MapValueExpression expression) { expression.getPath().accept(this); if (!(currentPosition.getAttribute() instanceof MapAttribute<?, ?, ?>)) { invalid(expression, "Does not resolve to java.util.Map!"); } else { currentPosition.setCurrentType(currentPosition.getCurrentType()); } }
@Override public void visit(ArithmeticExpression expression) { if (expression.getNumericType() != null) { currentPosition.setCurrentType(metamodel.type(expression.getNumericType().getJavaType())); } }
@Override public void visit(MapEntryExpression expression) { expression.getPath().accept(this); currentPosition.setAttribute(new MapEntryAttribute<>((MapAttribute<?, Object, ?>) currentPosition.getAttribute())); currentPosition.setCurrentType(metamodel.type(Map.Entry.class)); }