@Override public void visit(ArrayExpression expression) { boolean wasParamsAllowed = parametersAllowed; List<PathPosition> currentPositions = pathPositions; PathPosition position = currentPosition; parametersAllowed = true; pathPositions = new ArrayList<>(); pathPositions.add(currentPosition = new PathPosition(managedType, null)); // Validate index against metamodel expression.getIndex().accept(this); parametersAllowed = wasParamsAllowed; currentPosition = position; pathPositions = currentPositions; // Only need the base to navigate down the path expression.getBase().accept(this); currentPosition.setCurrentType(currentPosition.getCurrentType()); }
int size = expressions.size(); EXPRESSION_LOOP: for (int i = 0; i < size; i++) { PathPosition position = currentPositions.get(j).copy(); pathPositions = new ArrayList<>(); pathPositions.add(currentPosition = position); if (newPosition.getCurrentClass() != null) { newPositions.add(newPosition); break EXPRESSION_LOOP; PathPosition position = currentPositions.get(j).copy(); pathPositions = new ArrayList<>(); pathPositions.add(currentPosition = position); if (newPosition.getCurrentClass() != null) { newPositions.add(newPosition);
public List<TargetType> getPossibleTargetTypes() { List<PathPosition> positions = pathPositions; int size = positions.size(); if (managedType != null && size == 1 && positions.get(0).getAttribute() == null && managedType.getJavaType().equals(positions.get(0).getRealCurrentClass())) { // When we didn't resolve any property, the expression is probably static and we can't give types in that case return Collections.emptyList(); } List<TargetType> possibleTargets = new ArrayList<>(size); for (int i = 0; i < size; i++) { PathPosition position = positions.get(i); possibleTargets.add(new TargetTypeImpl(position.hasCollectionJoin(), position.getAttribute(), position.getRealCurrentClass(), position.getKeyCurrentClass(), position.getCurrentClass())); } return possibleTargets; }
@Override public void visit(PropertyExpression expression) { String property = expression.getProperty(); if (currentPosition.getCurrentType() instanceof BasicType<?>) { throw new IllegalArgumentException("Can't access property '" + property + "' on basic type '" + JpaMetamodelUtils.getTypeName(currentPosition.getCurrentType()) + "'. Did you forget to add the embeddable type to your persistence.xml?"); Attribute<?, ?> attribute = JpaMetamodelUtils.getAttribute((ManagedType<?>) currentPosition.getCurrentType(), property); throw new IllegalArgumentException("Attribute '" + property + "' not found on type '" + JpaMetamodelUtils.getTypeName(currentPosition.getCurrentType()) + "'"); currentPosition.setAttribute(attribute); Type<?> type = getType(currentPosition.getCurrentType(), attribute); Type<?> valueType = null; Type<?> keyType = null; } else { if (attribute.getJavaMember() instanceof Field) { typeArguments = ReflectionUtils.getResolvedFieldTypeArguments(currentPosition.getCurrentClass(), (Field) attribute.getJavaMember()); } else if (attribute.getJavaMember() instanceof Method) { typeArguments = ReflectionUtils.getResolvedMethodReturnTypeArguments(currentPosition.getCurrentClass(), (Method) attribute.getJavaMember()); } else { typeArguments = EMPTY; valueType = metamodel.type(JpaMetamodelUtils.resolveFieldClass(currentPosition.getCurrentClass(), attribute)); currentPosition.setCurrentType(type); currentPosition.setValueType(valueType); currentPosition.setKeyType(keyType);
@Override public void visit(PropertyExpression expression) { String property = expression.getProperty(); if (currentPosition.getCurrentType() instanceof BasicType<?>) { throw new IllegalArgumentException("Can't access property '" + property + "' on basic type '" + JpaMetamodelUtils.getTypeName(currentPosition.getCurrentType()) + "'. Did you forget to add the embeddable type to your persistence.xml?"); Attribute<?, ?> attribute = JpaMetamodelUtils.getAttribute((ManagedType<?>) currentPosition.getCurrentType(), property); throw new IllegalArgumentException("Attribute '" + property + "' not found on type '" + JpaMetamodelUtils.getTypeName(currentPosition.getCurrentType()) + "'"); currentPosition.setAttribute(attribute); Type<?> type = getType(currentPosition.getCurrentType(), attribute); Type<?> valueType = null; Type<?> keyType = null; } else { if (attribute.getJavaMember() instanceof Field) { typeArguments = ReflectionUtils.getResolvedFieldTypeArguments(currentPosition.getCurrentClass(), (Field) attribute.getJavaMember()); } else if (attribute.getJavaMember() instanceof Method) { typeArguments = ReflectionUtils.getResolvedMethodReturnTypeArguments(currentPosition.getCurrentClass(), (Method) attribute.getJavaMember()); } else { typeArguments = EMPTY; valueType = metamodel.type(JpaMetamodelUtils.resolveFieldClass(currentPosition.getCurrentClass(), attribute)); currentPosition.setCurrentType(type); currentPosition.setValueType(valueType); currentPosition.setKeyType(keyType);
private void resolveFirst(List<Expression> expressions, boolean allowParams) { List<PathPosition> currentPositions = pathPositions; List<PathPosition> newPositions = new ArrayList<>(); int positionsSize = currentPositions.size(); for (int j = 0; j < positionsSize; j++) { int size = expressions.size(); EXPRESSION_LOOP: for (int i = 0; i < size; i++) { PathPosition position = currentPositions.get(j).copy(); pathPositions = new ArrayList<>(); pathPositions.add(currentPosition = position); if (allowParams) { parametersAllowed = true; } expressions.get(i).accept(this); if (allowParams) { parametersAllowed = false; } // We just use the type of the first path position that we find for (PathPosition newPosition : pathPositions) { if (newPosition.getCurrentClass() != null) { newPositions.add(newPosition); break EXPRESSION_LOOP; } } } } currentPosition = null; pathPositions = newPositions; }
@Override public void visit(GeneralCaseExpression expression) { List<PathPosition> currentPositions = pathPositions; List<PathPosition> newPositions = new ArrayList<PathPosition>(); int positionsSize = currentPositions.size(); for (int j = 0; j < positionsSize; j++) { List<WhenClauseExpression> expressions = expression.getWhenClauses(); int size = expressions.size(); for (int i = 0; i < size; i++) { PathPosition position = currentPositions.get(j).copy(); pathPositions = new ArrayList<>(); pathPositions.add(currentPosition = position); expressions.get(i).accept(this); newPositions.addAll(pathPositions); } if (expression.getDefaultExpr() != null) { PathPosition position = currentPositions.get(j).copy(); pathPositions = new ArrayList<>(); pathPositions.add(currentPosition = position); expression.getDefaultExpr().accept(this); newPositions.addAll(pathPositions); } } currentPosition = null; pathPositions = newPositions; }
@Override public void visit(GeneralCaseExpression expression) { List<PathPosition> currentPositions = pathPositions; List<PathPosition> newPositions = new ArrayList<PathPosition>(); int positionsSize = currentPositions.size(); for (int j = 0; j < positionsSize; j++) { List<WhenClauseExpression> expressions = expression.getWhenClauses(); int size = expressions.size(); for (int i = 0; i < size; i++) { PathPosition position = currentPositions.get(j).copy(); pathPositions = new ArrayList<>(); pathPositions.add(currentPosition = position); expressions.get(i).accept(this); newPositions.addAll(pathPositions); } if (expression.getDefaultExpr() != null) { PathPosition position = currentPositions.get(j).copy(); pathPositions = new ArrayList<>(); pathPositions.add(currentPosition = position); expression.getDefaultExpr().accept(this); newPositions.addAll(pathPositions); } } currentPosition = null; pathPositions = newPositions; }
@Override public void visit(PathExpression expression) { if (currentPosition.getCurrentType() == null) { currentPosition.setCurrentType(expression.getPathReference().getType()); return; } List<PathElementExpression> expressions = expression.getExpressions(); int size = expressions.size(); int i = 0; // Skip the base node in (absolute) path expressions otherwise the resolving will fail if (size > 1) { PathElementExpression firstExpression = expressions.get(0); if (firstExpression instanceof PropertyExpression) { if (((PropertyExpression) firstExpression).getProperty().equals(skipBaseNodeAlias)) { i = 1; } } } for (; i < size; i++) { expressions.get(i).accept(this); } }
@Override public void visit(PathExpression expression) { if (currentPosition.getCurrentType() == null) { currentPosition.setCurrentType(expression.getPathReference().getType()); return; } List<PathElementExpression> expressions = expression.getExpressions(); int size = expressions.size(); int i = 0; // Skip the base node in (absolute) path expressions otherwise the resolving will fail if (size > 1) { PathElementExpression firstExpression = expressions.get(0); if (firstExpression instanceof PropertyExpression) { if (((PropertyExpression) firstExpression).getProperty().equals(skipBaseNodeAlias)) { i = 1; } } } for (; i < size; i++) { expressions.get(i).accept(this); } }
@Override public void visit(ParameterExpression expression) { // We can't infer a type here if (parametersAllowed) { // NOTE: We use null as marker for ANY TYPE currentPosition.setCurrentType(null); } else { // If there are other branches (path positions) i.e. of a case when that have a type, we can allow parameters too for (PathPosition position : pathPositions) { if (position != currentPosition) { if (position.getCurrentClass() != null) { currentPosition.setCurrentType(null); return; } } } // NOTE: plain parameters are only supported in the select clause when having an insert! invalid(expression, "Parameters are not allowed as results in mapping. Please use @MappingParameter for this instead!"); } }
@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); } }
public Class<?> getCurrentClass() { return getCurrentType() == null ? null : getCurrentType().getJavaType(); }
public Class<?> getCurrentClass() { return getCurrentType() == null ? null : getCurrentType().getJavaType(); }
public void reset(Type<?> startClass) { pathPositions.clear(); pathPositions.add(currentPosition = new PathPosition(startClass, null)); }
@Override public void visit(BooleanLiteral expression) { currentPosition.setCurrentType(metamodel.type(Boolean.class)); }
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)); } }
public void reset(Type<?> startClass) { pathPositions.clear(); pathPositions.add(currentPosition = new PathPosition(startClass, null)); }