Search in sources :

Example 1 with ExtendedManagedType

use of com.blazebit.persistence.spi.ExtendedManagedType in project blaze-persistence by Blazebit.

the class JoinManager method implicitJoin.

private JoinResult implicitJoin(JoinNode current, List<String> resultFields, PathExpression pathExpression, ClauseType fromClause, JoinType joinType, JoinNode currentJoinNode, Set<String> currentlyResolvingAliases, int start, int end, boolean allowParentAliases, boolean joinAllowed, boolean singularJoinAllowed, boolean idRemovable) {
    List<PathElementExpression> pathElements = pathExpression.getExpressions();
    PathElementExpression elementExpr;
    int singleValuedAssociationNameStartIndex = -1;
    int singleValuedAssociationNameEndIndex = -1;
    for (int i = start; i < end; i++) {
        AliasInfo aliasInfo;
        elementExpr = pathElements.get(i);
        if (elementExpr instanceof ArrayExpression) {
            ArrayExpression arrayExpr = (ArrayExpression) elementExpr;
            String joinRelationName;
            List<String> joinRelationAttributes;
            if (!resultFields.isEmpty()) {
                resultFields.add(arrayExpr.getBase().toString());
                joinRelationAttributes = resultFields;
                resultFields = new ArrayList<>();
                joinRelationName = StringUtils.join(".", joinRelationAttributes);
            } else {
                joinRelationName = arrayExpr.getBase().toString();
                joinRelationAttributes = Arrays.asList(joinRelationName);
            }
            current = current == null ? getRootNodeOrFail("Ambiguous join path [", joinRelationName, "] because of multiple root nodes!") : current;
            implicitJoinIndex(arrayExpr);
            // Find a node by a predicate match
            JoinNode matchingNode = findNode(current, joinRelationName, arrayExpr);
            if (matchingNode != null) {
                current = matchingNode;
            } else if (i == 0 && (aliasInfo = aliasManager.getAliasInfoForBottomLevel(joinRelationName)) != null) {
                // The first node is allowed to be a join alias
                if (aliasInfo instanceof SelectInfo) {
                    throw new IllegalArgumentException("Illegal reference to the select alias '" + joinRelationName + "'");
                }
                current = ((JoinAliasInfo) aliasInfo).getJoinNode();
                generateAndApplyOnPredicate(current, arrayExpr);
            } else {
                String joinAlias = getJoinAlias(arrayExpr);
                if (arrayExpr.getBase() instanceof PropertyExpression) {
                    final JoinResult result = createOrUpdateNode(current, joinRelationAttributes, null, joinAlias, joinType, currentJoinNode, true, false, joinAllowed, singularJoinAllowed);
                    current = result.baseNode;
                    resultFields = result.addToList(resultFields);
                } else {
                    joinAlias = aliasManager.generateJoinAlias(joinAlias);
                    Class<?> entityClass = ((EntityLiteral) arrayExpr.getBase()).getValue();
                    joinOn(null, current.getAlias(), entityClass, joinAlias, JoinType.LEFT, false).end();
                    current = ((JoinAliasInfo) aliasManager.getAliasInfo(joinAlias)).getJoinNode();
                }
                generateAndApplyOnPredicate(current, arrayExpr);
            }
        } else if (elementExpr instanceof TreatExpression) {
            if (i != 0 || current != null) {
                throw new IllegalArgumentException("A treat expression should be the first element in a path!");
            }
            TreatExpression treatExpression = (TreatExpression) elementExpr;
            boolean fromSubquery = false;
            boolean fromSelectAlias = false;
            boolean joinRequired = false;
            boolean fetch = false;
            current = implicitJoinTreatExpression((TreatExpression) elementExpr, joinAllowed, singularJoinAllowed, fromClause, joinType, currentJoinNode, currentlyResolvingAliases, fromSubquery, fromSelectAlias, true, false, fetch, false);
        } else if (elementExpr instanceof MapKeyExpression) {
            MapKeyExpression mapKeyExpression = (MapKeyExpression) elementExpr;
            boolean fromSubquery = false;
            boolean fromSelectAlias = false;
            boolean joinRequired = true;
            boolean fetch = false;
            current = joinMapKey(mapKeyExpression, null, fromClause, currentlyResolvingAliases, fromSubquery, fromSelectAlias, joinRequired, fetch, true, true);
        } else if (elementExpr instanceof MapValueExpression) {
            MapValueExpression mapValueExpression = (MapValueExpression) elementExpr;
            boolean fromSubquery = false;
            boolean fromSelectAlias = false;
            boolean joinRequired = true;
            boolean fetch = false;
            implicitJoin(mapValueExpression.getPath(), joinAllowed, singularJoinAllowed, true, null, fromClause, currentlyResolvingAliases, fromSubquery, fromSelectAlias, joinRequired, fetch);
            current = (JoinNode) mapValueExpression.getPath().getBaseNode();
        } else if (pathElements.size() == 1 && (aliasInfo = aliasManager.getAliasInfoForBottomLevel(elementExpr.toString())) != null) {
            if (aliasInfo instanceof SelectInfo) {
                throw new IllegalArgumentException("Can't dereference a select alias");
            } else {
                // Join alias usage like in "joinAlias.relationName"
                current = ((JoinAliasInfo) aliasInfo).getJoinNode();
            }
        } else {
            String elementExpressionString = elementExpr.toString();
            if (current == null) {
                // When no base is given, check if the attribute name is an alias
                aliasInfo = allowParentAliases ? aliasManager.getAliasInfo(elementExpressionString) : aliasManager.getAliasInfoForBottomLevel(elementExpressionString);
                if (aliasInfo instanceof JoinAliasInfo) {
                    current = ((JoinAliasInfo) aliasInfo).getJoinNode();
                    // We can only "consider" this path a single valued association id when we are about to "remove" the id part
                    if (idRemovable && current.getNodeType() instanceof ManagedType<?> && pathElements.size() == i + 2) {
                        ExtendedManagedType<?> managedType = metamodel.getManagedType(ExtendedManagedType.class, current.getManagedType());
                        if (contains(managedType.getIdAttributes(), pathElements.get(i + 1))) {
                            singleValuedAssociationNameStartIndex = 0;
                            singleValuedAssociationNameEndIndex = 0;
                            break;
                        }
                    }
                    continue;
                } else {
                    current = getRootNodeOrFail("Ambiguous join path [", elementExpressionString, "] because of multiple root nodes!");
                }
            }
            int pathElementsSize = pathElements.size();
            if (joinType != JoinType.INNER && (idRemovable || mainQuery.jpaProvider.supportsSingleValuedAssociationIdExpressions()) && (current.getManagedType().getPersistenceType() != Type.PersistenceType.EMBEDDABLE || current.getValuesLikeAttribute() != null) && i + 1 < pathElementsSize) {
                // If the current type is not an embeddable, we check if the path elements access a singular association id
                List<PathElementExpression> pathElementExpressions = new ArrayList<>(pathElementsSize - i);
                for (int j = i; j < pathElementsSize; j++) {
                    PathElementExpression pathElementExpression = pathElements.get(j);
                    if (!(pathElementExpression instanceof PropertyExpression)) {
                        break;
                    }
                    pathElementExpressions.add(pathElementExpression);
                }
                ExtendedManagedType<?> extendedManagedType = metamodel.getManagedType(ExtendedManagedType.class, current.getManagedType());
                // We collect and check if we have only property expressions
                if (pathElementExpressions.size() == pathElementsSize - i) {
                    // Only if all path elements are property expressions, we check if this is single valued association id
                    PathExpression pathRestExpression = new PathExpression(pathElementExpressions);
                    String pathRestString = pathRestExpression.toString();
                    int idx = 0;
                    ExtendedAttribute<?, ?> extendedAttribute;
                    if (current.getValuesLikeAttribute() == null) {
                        extendedAttribute = extendedManagedType.getOwnedSingularAttributes().get(pathRestString);
                    } else {
                        extendedAttribute = extendedManagedType.getAttributes().get(pathRestString);
                    }
                    if (extendedAttribute != null && !JpaMetamodelUtils.isAssociation(extendedAttribute.getAttribute())) {
                        ExtendedAttribute<?, ?> associationAttribute = null;
                        ExtendedAttribute<?, ?> attr;
                        singleValuedAssociationNameStartIndex = i;
                        List<String> newResultFields = new ArrayList<>();
                        for (int j = i; j < end; j++) {
                            idx = pathRestString.indexOf('.', idx + 1);
                            if (idx != -1 && JpaMetamodelUtils.isAssociation((attr = extendedManagedType.getAttribute(pathRestString.substring(0, idx))).getAttribute())) {
                                associationAttribute = attr;
                                singleValuedAssociationNameEndIndex = j;
                            }
                            newResultFields.add(pathElements.get(j).toString());
                        }
                        if (singleValuedAssociationNameEndIndex == -1) {
                            // The expression ends at an association, so this can't be a single valued association id expression
                            singleValuedAssociationNameStartIndex = -1;
                        } else if (current.getValueType() == null && mainQuery.jpaProvider.isForeignJoinColumn((EntityType<?>) current.getManagedType(), new PathExpression(pathElements.subList(singleValuedAssociationNameStartIndex, singleValuedAssociationNameEndIndex + 1)).toString()) || current.getValueType() != null && mainQuery.jpaProvider.isForeignJoinColumn(current.getValueType(), current.getValuesLikeAttribute() + "." + new PathExpression(pathElements.subList(singleValuedAssociationNameStartIndex, singleValuedAssociationNameEndIndex + 1)).toString())) {
                            // If the column is "foreign", we can't do any optimizations
                            singleValuedAssociationNameStartIndex = -1;
                        } else if (!mainQuery.jpaProvider.supportsSingleValuedAssociationNaturalIdExpressions() && !contains(metamodel.getManagedType(ExtendedManagedType.class, associationAttribute.getElementClass()), new PathExpression(pathElements.subList(singleValuedAssociationNameEndIndex + 1, pathElementsSize)))) {
                            // If the jpa provider doesn't support any optimizations, we are done
                            singleValuedAssociationNameStartIndex = -1;
                        } else {
                            resultFields.addAll(newResultFields);
                            break;
                        }
                    }
                }
            }
            if (resultFields.isEmpty()) {
                final JoinResult result = implicitJoinSingle(current, elementExpressionString, null, joinType, currentJoinNode, allowParentAliases, joinAllowed, singularJoinAllowed);
                if (current != result.baseNode) {
                    current = result.baseNode;
                }
                resultFields = result.addToList(resultFields);
            } else {
                resultFields.add(elementExpressionString);
                JoinResult currentResult = createOrUpdateNode(current, resultFields, null, null, joinType, currentJoinNode, true, true, joinAllowed, singularJoinAllowed);
                current = currentResult.baseNode;
                if (!currentResult.hasField()) {
                    resultFields.clear();
                }
            }
        }
    }
    if (resultFields.isEmpty()) {
        return new JoinResult(current, null, current == null ? null : current.getNodeType(), singleValuedAssociationNameStartIndex, singleValuedAssociationNameEndIndex);
    } else {
        List<PathElementExpression> pathElementExpressions = new ArrayList<>(resultFields.size());
        for (int i = 0; i < resultFields.size(); i++) {
            pathElementExpressions.add(new PropertyExpression(resultFields.get(i)));
        }
        Expression expression = new PathExpression(pathElementExpressions);
        Type<?> type = JpaUtils.getAttributeForJoining(metamodel, current.getNodeType(), expression, null).getAttributeType();
        return new JoinResult(current, resultFields, type, singleValuedAssociationNameStartIndex, singleValuedAssociationNameEndIndex);
    }
}
Also used : TreatExpression(com.blazebit.persistence.parser.expression.TreatExpression) MapValueExpression(com.blazebit.persistence.parser.expression.MapValueExpression) ArrayList(java.util.ArrayList) MapKeyExpression(com.blazebit.persistence.parser.expression.MapKeyExpression) PathExpression(com.blazebit.persistence.parser.expression.PathExpression) PropertyExpression(com.blazebit.persistence.parser.expression.PropertyExpression) ManagedType(javax.persistence.metamodel.ManagedType) ExtendedManagedType(com.blazebit.persistence.spi.ExtendedManagedType) ExtendedManagedType(com.blazebit.persistence.spi.ExtendedManagedType) EntityType(javax.persistence.metamodel.EntityType) PathElementExpression(com.blazebit.persistence.parser.expression.PathElementExpression) ListIndexExpression(com.blazebit.persistence.parser.expression.ListIndexExpression) Expression(com.blazebit.persistence.parser.expression.Expression) QualifiedExpression(com.blazebit.persistence.parser.expression.QualifiedExpression) TreatExpression(com.blazebit.persistence.parser.expression.TreatExpression) ParameterExpression(com.blazebit.persistence.parser.expression.ParameterExpression) PathExpression(com.blazebit.persistence.parser.expression.PathExpression) PropertyExpression(com.blazebit.persistence.parser.expression.PropertyExpression) ArrayExpression(com.blazebit.persistence.parser.expression.ArrayExpression) FunctionExpression(com.blazebit.persistence.parser.expression.FunctionExpression) SubqueryExpression(com.blazebit.persistence.parser.expression.SubqueryExpression) PathElementExpression(com.blazebit.persistence.parser.expression.PathElementExpression) GeneralCaseExpression(com.blazebit.persistence.parser.expression.GeneralCaseExpression) MapEntryExpression(com.blazebit.persistence.parser.expression.MapEntryExpression) MapValueExpression(com.blazebit.persistence.parser.expression.MapValueExpression) MapKeyExpression(com.blazebit.persistence.parser.expression.MapKeyExpression) ArrayExpression(com.blazebit.persistence.parser.expression.ArrayExpression)

Example 2 with ExtendedManagedType

use of com.blazebit.persistence.spi.ExtendedManagedType in project blaze-persistence by Blazebit.

the class ResolvingQueryGenerator method visit.

@Override
public void visit(PathExpression expression) {
    if (resolveSelectAliases && expression.getExpressions().size() == 1) {
        AliasInfo aliasInfo;
        String potentialAlias = expression.getExpressions().get(0).toString();
        try {
            if (currentlyResolvingAliases.add(potentialAlias) && (aliasInfo = aliasManager.getAliasInfo(potentialAlias)) != null) {
                if (aliasInfo instanceof SelectInfo) {
                    SelectInfo selectAliasInfo = (SelectInfo) aliasInfo;
                    if (selectAliasInfo.getExpression() instanceof PathExpression) {
                        PathExpression aliasedExpression = (PathExpression) selectAliasInfo.getExpression();
                        boolean collectionKeyPath = aliasedExpression.isCollectionQualifiedPath();
                        boolean usedInCollectionFunction = aliasedExpression.isUsedInCollectionFunction();
                        aliasedExpression.setCollectionQualifiedPath(expression.isCollectionQualifiedPath());
                        aliasedExpression.setUsedInCollectionFunction(expression.isUsedInCollectionFunction());
                        try {
                            selectAliasInfo.getExpression().accept(this);
                        } finally {
                            aliasedExpression.setCollectionQualifiedPath(collectionKeyPath);
                            aliasedExpression.setUsedInCollectionFunction(usedInCollectionFunction);
                        }
                    } else {
                        selectAliasInfo.getExpression().accept(this);
                    }
                    return;
                }
            }
        } finally {
            currentlyResolvingAliases.remove(potentialAlias);
        }
    }
    JoinNode baseNode;
    String field;
    if ((baseNode = (JoinNode) expression.getBaseNode()) == null) {
        super.visit(expression);
    } else {
        String collectionValueFunction = jpaProvider.getCollectionValueFunction();
        if ((field = expression.getField()) == null) {
            if (expression.isUsedInCollectionFunction() || renderAbsolutePath(expression)) {
                super.visit(expression);
            } else {
                // NOTE: Hibernate uses the column from a join table if VALUE is used which is wrong, so drop the VALUE here
                boolean valueFunction = collectionValueFunction != null && needsValueFunction(expression, baseNode, field);
                if (valueFunction) {
                    sb.append(collectionValueFunction);
                    sb.append('(');
                }
                if (aliasPrefix != null) {
                    sb.append(aliasPrefix);
                }
                baseNode.appendAlias(sb, externalRepresentation);
                if (valueFunction) {
                    sb.append(')');
                }
            }
        } else {
            List<JoinNode> treatedJoinNodes = baseNode.getJoinNodesForTreatConstraint();
            Type<?> baseNodeType = baseNode.getBaseType();
            boolean addTypeCaseWhen = false;
            if (!treatedJoinNodes.isEmpty() && baseNodeType instanceof EntityType<?> && baseNode.getTreatType() != null && (jpaProvider.supportsSubtypePropertyResolving() || !jpaProvider.supportsRootTreat())) {
                ExtendedManagedType<?> extendedManagedType = entityMetamodel.getManagedType(ExtendedManagedType.class, baseNode.getTreatType().getName());
                ExtendedAttribute<?, ?> extendedAttribute = extendedManagedType.getAttributes().get(field);
                if (extendedAttribute.isColumnShared()) {
                    // To disambiguate shared column access, we also must use the type constraint
                    addTypeCaseWhen = jpaProvider.needsTypeConstraintForColumnSharing();
                } else {
                    // If the attribute is declared by an entity sub-type of the treat target type, we don't need the case when
                    ExtendedAttribute<?, ?> baseTypeAttribute = (ExtendedAttribute<?, ?>) entityMetamodel.getManagedType(ExtendedManagedType.class, ((EntityType<?>) baseNode.getBaseType()).getName()).getAttributes().get(field);
                    addTypeCaseWhen = baseTypeAttribute != null && !baseNode.getTreatType().getJavaType().isAssignableFrom(baseTypeAttribute.getAttributePath().get(0).getDeclaringType().getJavaType());
                }
            }
            if (addTypeCaseWhen) {
                sb.append("CASE WHEN ");
                boolean first = true;
                for (int i = 0; i < treatedJoinNodes.size(); i++) {
                    JoinNode treatedJoinNode = treatedJoinNodes.get(i);
                    // we skip the type constraint as that is already applied through the join
                    if (jpaProvider.supportsTreatJoin() && treatedJoinNode.isTreatJoinNode()) {
                        continue;
                    }
                    if (first) {
                        first = false;
                    } else {
                        sb.append(" AND ");
                    }
                    sb.append("TYPE(");
                    treatedJoinNode.appendAlias(sb, externalRepresentation);
                    sb.append(") IN (");
                    for (EntityType<?> entitySubtype : entityMetamodel.getEntitySubtypes(treatedJoinNode.getTreatType())) {
                        sb.append(entitySubtype.getName());
                        sb.append(", ");
                    }
                    sb.setLength(sb.length() - 2);
                    sb.append(')');
                }
                if (first) {
                    sb.setLength(sb.length() - "CASE WHEN ".length());
                    addTypeCaseWhen = false;
                } else {
                    sb.append(" THEN ");
                }
            }
            boolean valueFunction = collectionValueFunction != null && needsValueFunction(expression, baseNode, field);
            // NOTE: There is no need to check for whether the JPA provider support implicit downcasting here
            // If it didn't, the query building would have already failed before. Here we just decide whether to render the treat or not
            boolean renderTreat = jpaProvider.supportsRootTreat();
            if (valueFunction) {
                sb.append(collectionValueFunction);
                sb.append('(');
                if (aliasPrefix != null) {
                    sb.append(aliasPrefix);
                }
                baseNode.appendAlias(sb, renderTreat, externalRepresentation);
                sb.append(')');
                sb.append(".").append(field);
            } else {
                if (aliasPrefix != null) {
                    sb.append(aliasPrefix);
                }
                baseNode.appendDeReference(sb, field, renderTreat, externalRepresentation, jpaProvider.needsElementCollectionIdCutoff());
            }
            if (addTypeCaseWhen) {
                if (jpaProvider.needsCaseWhenElseBranch()) {
                    sb.append(" ELSE NULL");
                }
                sb.append(" END");
            }
        }
    }
}
Also used : ExtendedAttribute(com.blazebit.persistence.spi.ExtendedAttribute) ExtendedManagedType(com.blazebit.persistence.spi.ExtendedManagedType) EntityType(javax.persistence.metamodel.EntityType) PathExpression(com.blazebit.persistence.parser.expression.PathExpression)

Example 3 with ExtendedManagedType

use of com.blazebit.persistence.spi.ExtendedManagedType in project blaze-persistence by Blazebit.

the class BlazeCriteriaBuilderRenderer method serializeSubQuery.

private Object serializeSubQuery(Object criteriaBuilder, Expression<?> expression) {
    Object result = expression.accept(new Visitor<Object, Object>() {

        @Override
        public Object visit(Constant<?> constant, Object criteriaBuilder) {
            throw new UnsupportedOperationException();
        }

        @Override
        public Object visit(FactoryExpression<?> factoryExpression, Object criteriaBuilder) {
            throw new UnsupportedOperationException();
        }

        @Override
        public Object visit(Operation<?> setOperation, Object criteriaBuilder) {
            Expression<?> lhs = setOperation.getArg(0);
            SubQueryExpression<?> lhsSubquery = lhs.accept(GetSubQueryVisitor.INSTANCE, null);
            SetOperationFlag setOperationFlag = lhsSubquery != null ? getSetOperationFlag(lhsSubquery.getMetadata()) : null;
            boolean lhsNestedSet = setOperationFlag != null && LEFT_NESTED_SET_OPERATIONS.contains(setOperation.getOperator());
            if (lhsNestedSet) {
                if (criteriaBuilder instanceof StartOngoingSetOperationBuilder) {
                    StartOngoingSetOperationBuilder<?, ?, ?> ob = (StartOngoingSetOperationBuilder<?, ?, ?>) criteriaBuilder;
                    criteriaBuilder = ob.startSet();
                } else if (criteriaBuilder instanceof SubqueryInitiator) {
                    SubqueryInitiator<?> subqueryInitiator = (SubqueryInitiator<?>) criteriaBuilder;
                    criteriaBuilder = subqueryInitiator.startSet();
                } else {
                    criteriaBuilder = criteriaBuilderFactory.startSet(entityManager, Object.class);
                }
                criteriaBuilder = setOperationFlag.getFlag().accept(this, criteriaBuilder);
                if (criteriaBuilder instanceof OngoingSetOperationBuilder) {
                    criteriaBuilder = ((OngoingSetOperationBuilder<?, ?, ?>) criteriaBuilder).endSetWith();
                    renderOrderBy(lhsSubquery.getMetadata(), (OrderByBuilder<?>) criteriaBuilder);
                    renderModifiers(lhsSubquery.getMetadata().getModifiers(), (LimitBuilder<?>) criteriaBuilder);
                    criteriaBuilder = ((BaseOngoingFinalSetOperationBuilder) criteriaBuilder).endSet();
                } else {
                    throw new UnsupportedOperationException();
                }
            } else {
                criteriaBuilder = lhs.accept(this, criteriaBuilder);
            }
            Expression<?> rhs = setOperation.getArg(1);
            SubQueryExpression<?> rhsSubquery = rhs.accept(GetSubQueryVisitor.INSTANCE, null);
            setOperationFlag = rhsSubquery != null ? getSetOperationFlag(rhsSubquery.getMetadata()) : null;
            boolean isNestedSet = setOperationFlag != null;
            SetOperationBuilder<?, ?> setOperationBuilder = (SetOperationBuilder<?, ?>) criteriaBuilder;
            switch((JPQLNextOps) setOperation.getOperator()) {
                // CHECKSTYLE:OFF: FallThrough
                case SET_UNION:
                case LEFT_NESTED_SET_UNION:
                    criteriaBuilder = isNestedSet ? setOperationBuilder.startUnion() : setOperationBuilder.union();
                    break;
                case SET_UNION_ALL:
                case LEFT_NESTED_SET_UNION_ALL:
                    criteriaBuilder = isNestedSet ? setOperationBuilder.startUnionAll() : setOperationBuilder.unionAll();
                    break;
                case SET_EXCEPT:
                case LEFT_NESTED_SET_EXCEPT:
                    criteriaBuilder = isNestedSet ? setOperationBuilder.startExcept() : setOperationBuilder.except();
                    break;
                case SET_EXCEPT_ALL:
                case LEFT_NESTED_SET_EXCEPT_ALL:
                    criteriaBuilder = isNestedSet ? setOperationBuilder.startExceptAll() : setOperationBuilder.exceptAll();
                    break;
                case SET_INTERSECT:
                case LEFT_NESTED_SET_INTERSECT:
                    criteriaBuilder = isNestedSet ? setOperationBuilder.startIntersect() : setOperationBuilder.intersect();
                    break;
                case SET_INTERSECT_ALL:
                case LEFT_NESTED_SET_INTERSECT_ALL:
                    criteriaBuilder = isNestedSet ? setOperationBuilder.startIntersectAll() : setOperationBuilder.intersectAll();
                    break;
                default:
                    throw new UnsupportedOperationException("No support for set operation " + setOperation.getOperator());
            }
            if (isNestedSet) {
                criteriaBuilder = setOperationFlag.getFlag().accept(this, criteriaBuilder);
                if (criteriaBuilder instanceof OngoingSetOperationBuilder) {
                    criteriaBuilder = ((OngoingSetOperationBuilder<?, ?, ?>) criteriaBuilder).endSetWith();
                    renderOrderBy(rhsSubquery.getMetadata(), (OrderByBuilder<?>) criteriaBuilder);
                    renderModifiers(rhsSubquery.getMetadata().getModifiers(), (LimitBuilder<?>) criteriaBuilder);
                    criteriaBuilder = ((BaseOngoingFinalSetOperationBuilder) criteriaBuilder).endSet();
                } else {
                    throw new UnsupportedOperationException();
                }
            } else {
                criteriaBuilder = rhs.accept(this, criteriaBuilder);
            }
            return criteriaBuilder;
        }

        @Override
        public Object visit(ParamExpression<?> paramExpression, Object criteriaBuilder) {
            throw new UnsupportedOperationException();
        }

        @Override
        public Object visit(Path<?> path, Object criteriaBuilder) {
            throw new UnsupportedOperationException();
        }

        @Override
        public Object visit(SubQueryExpression<?> subQuery, Object criteriaBuilder) {
            QueryMetadata subQueryMetadata = subQuery.getMetadata();
            SetOperationFlag setOperationFlag = getSetOperationFlag(subQueryMetadata);
            if (setOperationFlag != null) {
                return setOperationFlag.getFlag().accept(this, criteriaBuilder);
            }
            renderCTEs(subQueryMetadata);
            criteriaBuilder = renderJoins(subQueryMetadata, (FromBaseBuilder) criteriaBuilder);
            criteriaBuilder = renderNamedWindows(subQueryMetadata, (WindowContainerBuilder) criteriaBuilder);
            renderDistinct(subQueryMetadata, (DistinctBuilder<?>) criteriaBuilder);
            renderWhere(subQueryMetadata, (WhereBuilder<?>) criteriaBuilder);
            renderGroupBy(subQueryMetadata, (GroupByBuilder<?>) criteriaBuilder);
            renderHaving(subQueryMetadata, (HavingBuilder<?>) criteriaBuilder);
            Expression<?> select = subQueryMetadata.getProjection();
            if (select instanceof FactoryExpression<?> && criteriaBuilder instanceof FullQueryBuilder<?, ?>) {
                FactoryExpression<T> factoryExpression = (FactoryExpression<T>) select;
                FullQueryBuilder<?, ?> fullQueryBuilder = (FullQueryBuilder<?, ?>) criteriaBuilder;
                criteriaBuilder = fullQueryBuilder.selectNew(new FactoryExpressionObjectBuilder(factoryExpression));
            } else {
                List<? extends Expression<?>> projection = expandProjection(subQueryMetadata.getProjection());
                if (criteriaBuilder instanceof SelectBaseCTECriteriaBuilder) {
                    SelectBaseCTECriteriaBuilder<?> selectBaseCriteriaBuilder = (SelectBaseCTECriteriaBuilder<?>) criteriaBuilder;
                    boolean bindEntity = projection.size() == 1 && subQueryMetadata.getJoins().get(0).getTarget().accept(new JoinTargetAliasPathResolver(), null).equals(projection.get(0));
                    if (bindEntity) {
                        EntityMetamodel metamodel = criteriaBuilderFactory.getService(EntityMetamodel.class);
                        Path<?> pathExpression = (Path<?>) projection.get(0);
                        ExtendedManagedType<?> managedType = metamodel.getManagedType(ExtendedManagedType.class, pathExpression.getType());
                        Map<String, ? extends ExtendedAttribute<?, ?>> ownedSingularAttributes = managedType.getOwnedSingularAttributes();
                        for (Map.Entry<String, ? extends ExtendedAttribute<?, ?>> ownedSingularAttribute : ownedSingularAttributes.entrySet()) {
                            String attributeName = ownedSingularAttribute.getKey();
                            ExtendedAttribute<?, ?> attribute = ownedSingularAttribute.getValue();
                            if (!JpaMetamodelUtils.isAssociation(attribute.getAttribute())) {
                                final SelectBuilder<?> bindBuilder = selectBaseCriteriaBuilder.bind(attributeName);
                                BeanPath<?> beanPath = new BeanPath<Object>(attribute.getElementClass(), pathExpression, attributeName);
                                setExpressionSubqueries(beanPath, null, bindBuilder, SelectBuilderExpressionSetter.INSTANCE);
                            }
                        }
                    } else {
                        for (int i = 0; i < projection.size(); i++) {
                            Expression<?> projExpression = projection.get(i);
                            BindResolverContext bindResolverContext = new BindResolverContext();
                            projExpression = projExpression.accept(BindResolver.INSTANCE, bindResolverContext);
                            Path<?> cteAttribute = bindResolverContext.getCteAttribute();
                            String alias = bindResolverContext.getAliasString();
                            if (cteAttribute == null && cteAliases != null) {
                                cteAttribute = cteAliases.get(i);
                            }
                            if (cteAttribute != null) {
                                Path<?> cteEntityPath = cteAttribute.getRoot();
                                String relativeCteAttributePath = relativePathString(cteEntityPath, cteAttribute);
                                final SelectBuilder<?> bindBuilder = selectBaseCriteriaBuilder.bind(relativeCteAttributePath);
                                setExpressionSubqueries(projExpression, alias, bindBuilder, SelectBuilderExpressionSetter.INSTANCE);
                            } else {
                                throw new UnsupportedOperationException("Select statement should be bound to any CTE attribute");
                            }
                        }
                    }
                } else {
                    for (Expression<?> selection : projection) {
                        renderSingleSelect(selection, (SelectBuilder<?>) criteriaBuilder);
                    }
                }
            }
            renderOrderBy(subQueryMetadata, (OrderByBuilder<?>) criteriaBuilder);
            renderParameters(subQueryMetadata, (ParameterHolder<?>) criteriaBuilder);
            // Limit / offset on full query is set outside of the renderer, based on whether we're rendering a full count query or not
            if (!(criteriaBuilder instanceof Queryable)) {
                renderModifiers(subQueryMetadata.getModifiers(), (LimitBuilder<?>) criteriaBuilder);
            }
            return criteriaBuilder;
        }

        @Override
        public Object visit(TemplateExpression<?> templateExpression, Object criteriaBuilder) {
            throw new UnsupportedOperationException();
        }
    }, criteriaBuilder);
    if (result instanceof BaseOngoingSetOperationBuilder) {
        result = ((BaseOngoingSetOperationBuilder<?, ?, ?>) result).endSet();
    }
    if ((result instanceof FinalSetOperationCriteriaBuilder || result instanceof FinalSetOperationCTECriteriaBuilder || result instanceof FinalSetOperationSubqueryBuilder) && expression instanceof SubQueryExpression<?>) {
        QueryMetadata metadata = ((SubQueryExpression<?>) expression).getMetadata();
        renderOrderBy(metadata, (OrderByBuilder<?>) result);
        // Limit / offset on full query is set outside of the renderer, based on whether we're rendering a full count query or not
        if (!(criteriaBuilder instanceof Queryable)) {
            renderModifiers(metadata.getModifiers(), (LimitBuilder<?>) result);
        }
    }
    return result;
}
Also used : SubQueryExpression(com.querydsl.core.types.SubQueryExpression) QueryMetadata(com.querydsl.core.QueryMetadata) FinalSetOperationCTECriteriaBuilder(com.blazebit.persistence.FinalSetOperationCTECriteriaBuilder) BaseOngoingFinalSetOperationBuilder(com.blazebit.persistence.BaseOngoingFinalSetOperationBuilder) BeanPath(com.querydsl.core.types.dsl.BeanPath) BaseOngoingFinalSetOperationBuilder(com.blazebit.persistence.BaseOngoingFinalSetOperationBuilder) SetOperationBuilder(com.blazebit.persistence.SetOperationBuilder) StartOngoingSetOperationBuilder(com.blazebit.persistence.StartOngoingSetOperationBuilder) BaseOngoingSetOperationBuilder(com.blazebit.persistence.BaseOngoingSetOperationBuilder) OngoingSetOperationBuilder(com.blazebit.persistence.OngoingSetOperationBuilder) SelectBaseCTECriteriaBuilder(com.blazebit.persistence.SelectBaseCTECriteriaBuilder) StartOngoingSetOperationBuilder(com.blazebit.persistence.StartOngoingSetOperationBuilder) FinalSetOperationCriteriaBuilder(com.blazebit.persistence.FinalSetOperationCriteriaBuilder) FullQueryBuilder(com.blazebit.persistence.FullQueryBuilder) OrderByBuilder(com.blazebit.persistence.OrderByBuilder) List(java.util.List) ArrayList(java.util.ArrayList) SubqueryInitiator(com.blazebit.persistence.SubqueryInitiator) MultipleSubqueryInitiator(com.blazebit.persistence.MultipleSubqueryInitiator) HavingBuilder(com.blazebit.persistence.HavingBuilder) ExtendedAttribute(com.blazebit.persistence.spi.ExtendedAttribute) FinalSetOperationSubqueryBuilder(com.blazebit.persistence.FinalSetOperationSubqueryBuilder) DistinctBuilder(com.blazebit.persistence.DistinctBuilder) ExtendedManagedType(com.blazebit.persistence.spi.ExtendedManagedType) GroupByBuilder(com.blazebit.persistence.GroupByBuilder) Map(java.util.Map) IdentityHashMap(java.util.IdentityHashMap) ParameterHolder(com.blazebit.persistence.ParameterHolder) SetOperationFlag.getSetOperationFlag(com.blazebit.persistence.querydsl.SetOperationFlag.getSetOperationFlag) FactoryExpression(com.querydsl.core.types.FactoryExpression) Queryable(com.blazebit.persistence.Queryable) WhereBuilder(com.blazebit.persistence.WhereBuilder) SelectBuilder(com.blazebit.persistence.SelectBuilder) Path(com.querydsl.core.types.Path) BeanPath(com.querydsl.core.types.dsl.BeanPath) LimitBuilder(com.blazebit.persistence.LimitBuilder) BaseOngoingSetOperationBuilder(com.blazebit.persistence.BaseOngoingSetOperationBuilder) StartOngoingSetOperationBuilder(com.blazebit.persistence.StartOngoingSetOperationBuilder) BaseOngoingSetOperationBuilder(com.blazebit.persistence.BaseOngoingSetOperationBuilder) OngoingSetOperationBuilder(com.blazebit.persistence.OngoingSetOperationBuilder) ParamExpression(com.querydsl.core.types.ParamExpression) Expression(com.querydsl.core.types.Expression) TemplateExpression(com.querydsl.core.types.TemplateExpression) FactoryExpression(com.querydsl.core.types.FactoryExpression) SubQueryExpression(com.querydsl.core.types.SubQueryExpression) JoinExpression(com.querydsl.core.JoinExpression) EntityMetamodel(com.blazebit.persistence.parser.EntityMetamodel)

Example 4 with ExtendedManagedType

use of com.blazebit.persistence.spi.ExtendedManagedType in project blaze-persistence by Blazebit.

the class EntityViewUpdaterImpl method createPluralAttributeSubFlusher.

private DirtyAttributeFlusher<?, ?, ?> createPluralAttributeSubFlusher(EntityViewManagerImpl evm, Map<Object, EntityViewUpdaterImpl> localCache, ManagedViewTypeImplementor<?> viewType, AbstractMethodAttribute<?, ?> attribute, String name, Type<?> type, EntityViewUpdaterImpl owner, String ownerMapping) {
    EntityMetamodel entityMetamodel = evm.getMetamodel().getEntityMetamodel();
    String attributeName = attribute.getName() + "_" + name;
    String attributeMapping = attribute.getMapping();
    String attributeLocation = attribute.getLocation();
    Set<Type<?>> readOnlyAllowedSubtypes = attribute.getReadOnlyAllowedSubtypes();
    Set<Type<?>> persistAllowedSubtypes = attribute.getPersistCascadeAllowedSubtypes();
    Set<Type<?>> updateAllowedSubtypes = attribute.getUpdateCascadeAllowedSubtypes();
    if (type instanceof ManagedViewType<?>) {
        ManagedViewTypeImplementor<?> subviewType = (ManagedViewTypeImplementor<?>) type;
        if (!(subviewType.getJpaManagedType() instanceof EntityType<?>)) {
            // A singular attribute where the subview refers to an embeddable type
            EmbeddableUpdaterBasedViewToEntityMapper viewToEntityMapper = new EmbeddableUpdaterBasedViewToEntityMapper(attributeLocation, evm, subviewType.getJavaType(), readOnlyAllowedSubtypes, persistAllowedSubtypes, updateAllowedSubtypes, EntityLoaders.referenceLoaderForAttribute(evm, localCache, subviewType, attribute), false, null, owner, ownerMapping == null ? attributeMapping : ownerMapping + "." + attributeMapping, localCache);
            String parameterName = attributeName + "_";
            String updateFragment = attributeMapping + ".";
            return new EmbeddableAttributeFlusher<>(attributeName, attributeMapping, updateFragment, parameterName, false, false, false, null, null, viewToEntityMapper);
        } else {
            ViewTypeImplementor<?> attributeViewType = (ViewTypeImplementor<?>) subviewType;
            InitialValueAttributeAccessor viewAttributeAccessor = Accessors.forMutableViewAttribute(evm, attribute);
            AttributeAccessor subviewIdAccessor;
            ManagedType<?> ownerManagedType = owner == null ? viewType.getJpaManagedType() : owner.managedViewType.getJpaManagedType();
            EntityType<?> ownerEntityType = ownerManagedType instanceof EntityType<?> ? (EntityType<?>) ownerManagedType : null;
            String attributeElementIdMapping;
            if (ownerEntityType != null && attribute.getMapping() != null) {
                ExtendedManagedType<?> extendedManagedType = evm.getMetamodel().getEntityMetamodel().getManagedType(ExtendedManagedType.class, attributeViewType.getEntityClass());
                attributeElementIdMapping = TypeDescriptor.getAttributeElementIdentifier(evm, ownerEntityType, attribute.getName(), ownerMapping, attribute.getMapping(), extendedManagedType.getType());
            } else {
                attributeElementIdMapping = ((MappingAttribute<?, ?>) attributeViewType.getIdAttribute()).getMapping();
            }
            subviewIdAccessor = Accessors.forSubviewAssociationId(evm, attributeViewType, attributeElementIdMapping, true);
            Attribute<?, ?> attributeIdAttribute = attributeViewType.getJpaManagedType().getAttribute(attributeElementIdMapping);
            javax.persistence.metamodel.Type<?> attributeIdAttributeType = entityMetamodel.type(JpaMetamodelUtils.resolveFieldClass(attributeViewType.getEntityClass(), attributeIdAttribute));
            List<String> idComponentMappings;
            boolean requiresComponentWiseSetInUpdate = true;
            if (requiresComponentWiseSetInUpdate && attributeIdAttributeType instanceof EmbeddableType<?>) {
                // If the identifier used for the association is an embeddable, we must collect the individual attribute components since updates don't work on embeddables directly
                Set<Attribute<?, ?>> idAttributeComponents = (Set<Attribute<?, ?>>) ((EmbeddableType<?>) attributeIdAttributeType).getAttributes();
                idComponentMappings = new ArrayList<>(idAttributeComponents.size());
                for (Attribute<?, ?> idAttributeComponent : idAttributeComponents) {
                    idComponentMappings.add(attributeMapping + "." + attributeElementIdMapping + "." + idAttributeComponent);
                }
            } else {
                idComponentMappings = Collections.singletonList(attributeMapping + "." + attributeElementIdMapping);
            }
            String[] idAttributeMappings = idComponentMappings.toArray(new String[idComponentMappings.size()]);
            ViewToEntityMapper viewToEntityMapper = createViewToEntityMapper(attributeLocation, evm, localCache, ownerEntityType, attributeName, attributeMapping, attributeViewType, false, false, readOnlyAllowedSubtypes, persistAllowedSubtypes, updateAllowedSubtypes, EntityLoaders.referenceLoaderForAttribute(evm, localCache, attributeViewType, attribute.getViewTypes(), attributeElementIdMapping), owner, ownerMapping);
            String parameterName = attributeName;
            return new SubviewAttributeFlusher<>(attributeName, attributeMapping, false, true, false, false, false, subviewType.getConverter(), false, idAttributeMappings, parameterName, false, owner != null, null, viewAttributeAccessor, subviewIdAccessor, viewToEntityMapper, null, null);
        }
    } else {
        TypeDescriptor elementDescriptor = TypeDescriptor.forType(evm, localCache, this, attribute, type, owner, ownerMapping);
        String parameterName = attributeName;
        String updateFragment = attributeMapping;
        // TODO: Why?
        boolean supportsQueryFlush = !elementDescriptor.isJpaEmbeddable();
        return new BasicAttributeFlusher<>(attributeName, attributeMapping, supportsQueryFlush, false, true, false, false, false, null, elementDescriptor, updateFragment, parameterName, null, null, null, null, null);
    }
}
Also used : ViewTypeImplementor(com.blazebit.persistence.view.impl.metamodel.ViewTypeImplementor) ManagedViewTypeImplementor(com.blazebit.persistence.view.impl.metamodel.ManagedViewTypeImplementor) Set(java.util.Set) HashSet(java.util.HashSet) MappingAttribute(com.blazebit.persistence.view.metamodel.MappingAttribute) SingularAttribute(javax.persistence.metamodel.SingularAttribute) Attribute(javax.persistence.metamodel.Attribute) AbstractMethodAttribute(com.blazebit.persistence.view.impl.metamodel.AbstractMethodAttribute) PluralAttribute(com.blazebit.persistence.view.metamodel.PluralAttribute) ExtendedAttribute(com.blazebit.persistence.spi.ExtendedAttribute) MapAttribute(com.blazebit.persistence.view.metamodel.MapAttribute) MethodAttribute(com.blazebit.persistence.view.metamodel.MethodAttribute) InitialValueAttributeAccessor(com.blazebit.persistence.view.impl.accessor.InitialValueAttributeAccessor) EmbeddableAttributeFlusher(com.blazebit.persistence.view.impl.update.flush.EmbeddableAttributeFlusher) LoadOrPersistViewToEntityMapper(com.blazebit.persistence.view.impl.entity.LoadOrPersistViewToEntityMapper) LoadOnlyViewToEntityMapper(com.blazebit.persistence.view.impl.entity.LoadOnlyViewToEntityMapper) SimpleMapViewToEntityMapper(com.blazebit.persistence.view.impl.update.flush.SimpleMapViewToEntityMapper) UpdaterBasedViewToEntityMapper(com.blazebit.persistence.view.impl.entity.UpdaterBasedViewToEntityMapper) EmbeddableUpdaterBasedViewToEntityMapper(com.blazebit.persistence.view.impl.entity.EmbeddableUpdaterBasedViewToEntityMapper) MapViewToEntityMapper(com.blazebit.persistence.view.impl.entity.MapViewToEntityMapper) ViewToEntityMapper(com.blazebit.persistence.view.impl.entity.ViewToEntityMapper) SubviewAttributeFlusher(com.blazebit.persistence.view.impl.update.flush.SubviewAttributeFlusher) ManagedViewType(com.blazebit.persistence.view.metamodel.ManagedViewType) ManagedViewTypeImplementor(com.blazebit.persistence.view.impl.metamodel.ManagedViewTypeImplementor) EntityType(javax.persistence.metamodel.EntityType) ManagedType(javax.persistence.metamodel.ManagedType) BasicType(com.blazebit.persistence.view.metamodel.BasicType) EntityType(javax.persistence.metamodel.EntityType) Type(com.blazebit.persistence.view.metamodel.Type) ExtendedManagedType(com.blazebit.persistence.spi.ExtendedManagedType) VersionBasicUserType(com.blazebit.persistence.view.spi.type.VersionBasicUserType) ManagedViewType(com.blazebit.persistence.view.metamodel.ManagedViewType) EmbeddableType(javax.persistence.metamodel.EmbeddableType) ViewType(com.blazebit.persistence.view.metamodel.ViewType) TypeDescriptor(com.blazebit.persistence.view.impl.update.flush.TypeDescriptor) BasicAttributeFlusher(com.blazebit.persistence.view.impl.update.flush.BasicAttributeFlusher) InitialValueAttributeAccessor(com.blazebit.persistence.view.impl.accessor.InitialValueAttributeAccessor) AttributeAccessor(com.blazebit.persistence.view.impl.accessor.AttributeAccessor) EntityMetamodel(com.blazebit.persistence.parser.EntityMetamodel) EmbeddableUpdaterBasedViewToEntityMapper(com.blazebit.persistence.view.impl.entity.EmbeddableUpdaterBasedViewToEntityMapper)

Example 5 with ExtendedManagedType

use of com.blazebit.persistence.spi.ExtendedManagedType in project blaze-persistence by Blazebit.

the class TypeDescriptor method forType.

public static TypeDescriptor forType(EntityViewManagerImpl evm, Map<Object, EntityViewUpdaterImpl> localCache, EntityViewUpdaterImpl updater, AbstractMethodAttribute<?, ?> attribute, Type<?> type, EntityViewUpdaterImpl owner, String ownerMapping) {
    EntityMetamodel entityMetamodel = evm.getMetamodel().getEntityMetamodel();
    String attributeLocation = attribute.getLocation();
    boolean cascadePersist = attribute.isPersistCascaded();
    boolean cascadeUpdate = attribute.isUpdateCascaded();
    Set<Type<?>> readOnlyAllowedSubtypes = attribute.getReadOnlyAllowedSubtypes();
    Set<Type<?>> persistAllowedSubtypes = attribute.getPersistCascadeAllowedSubtypes();
    Set<Type<?>> updateAllowedSubtypes = attribute.getUpdateCascadeAllowedSubtypes();
    EntityToEntityMapper entityToEntityMapper = null;
    ViewToEntityMapper viewToEntityMapper = null;
    ViewToEntityMapper loadOnlyViewToEntityMapper = null;
    final ManagedType<?> managedType = entityMetamodel.getManagedType(type.getJavaType());
    final boolean jpaEntity = managedType instanceof EntityType<?>;
    final boolean jpaManaged = managedType != null;
    final boolean mutable;
    final boolean identifiable;
    TypeConverter<Object, Object> converter = (TypeConverter<Object, Object>) type.getConverter();
    BasicUserType<Object> basicUserType;
    ManagedType<?> ownerEntityType = owner == null ? attribute.getDeclaringType().getJpaManagedType() : owner.getManagedViewType().getJpaManagedType();
    String attributeIdAttributeName = null;
    String entityIdAttributeName = null;
    Class<?> jpaType;
    // TODO: currently we only check if the declared type is mutable, but we have to let the collection flusher which types are considered updatable/creatable
    if (type instanceof BasicType<?>) {
        jpaType = type.getJavaType();
        basicUserType = (BasicUserType<Object>) ((BasicType<?>) type).getUserType();
        mutable = basicUserType.isMutable();
        identifiable = jpaEntity || !jpaManaged;
        if (jpaEntity) {
            Map<String, Map<?, ?>> fetchGraph = null;
            UnmappedAttributeCascadeDeleter deleter = null;
            // We only need to know the fetch graph when we actually do updates
            if (cascadeUpdate) {
                fetchGraph = getFetchGraph(attribute.getFetches(), attribute.getMapping(), managedType);
            }
            if (ownerEntityType instanceof EntityType<?>) {
                ExtendedManagedType<?> extendedManagedType = evm.getMetamodel().getEntityMetamodel().getManagedType(ExtendedManagedType.class, type.getJavaType());
                entityIdAttributeName = extendedManagedType.getIdAttribute().getName();
                attributeIdAttributeName = getAttributeElementIdentifier(evm, (EntityType<?>) ownerEntityType, attribute.getName(), ownerMapping, attribute.getMapping(), extendedManagedType.getType());
                // Only construct when orphanRemoval or delete cascading is enabled, orphanRemoval implies delete cascading
                if (attribute.isDeleteCascaded()) {
                    String mapping = attribute.getMapping();
                    ExtendedManagedType elementManagedType = entityMetamodel.getManagedType(ExtendedManagedType.class, attribute.getDeclaringType().getJpaManagedType());
                    deleter = new UnmappedBasicAttributeCascadeDeleter(evm, mapping, elementManagedType.getAttribute(mapping), mapping + "." + attributeIdAttributeName, false);
                }
            }
            // TODO: EntityToEntityMapper should also use the attributeIdAttributeName
            entityToEntityMapper = new DefaultEntityToEntityMapper(cascadePersist, cascadeUpdate, jpaType, basicUserType, new DefaultEntityLoaderFetchGraphNode(evm, attribute.getName(), (EntityType<?>) managedType, fetchGraph), deleter);
        }
    } else {
        ManagedViewTypeImplementor<?> elementType = (ManagedViewTypeImplementor<?>) type;
        jpaType = elementType.getEntityClass();
        basicUserType = null;
        mutable = elementType.isUpdatable() || elementType.isCreatable() || !persistAllowedSubtypes.isEmpty() || !updateAllowedSubtypes.isEmpty();
        Set<ManagedViewType<?>> viewTypes = attribute.getViewTypes();
        if (elementType.getJpaManagedType() instanceof EntityType<?> && ownerEntityType instanceof EntityType<?>) {
            ExtendedManagedType<?> extendedManagedType = evm.getMetamodel().getEntityMetamodel().getManagedType(ExtendedManagedType.class, elementType.getEntityClass());
            entityIdAttributeName = extendedManagedType.getIdAttribute().getName();
            attributeIdAttributeName = getAttributeElementIdentifier(evm, (EntityType<?>) ownerEntityType, attribute.getName(), ownerMapping, attribute.getMapping(), extendedManagedType.getType());
        }
        viewToEntityMapper = createViewToEntityMapper(evm, localCache, updater, attributeIdAttributeName, attribute.getMapping(), attributeLocation, elementType, cascadePersist, cascadeUpdate, readOnlyAllowedSubtypes, persistAllowedSubtypes, updateAllowedSubtypes, EntityLoaders.referenceLoaderForAttribute(evm, localCache, elementType, viewTypes, attributeIdAttributeName), owner, ownerMapping);
        loadOnlyViewToEntityMapper = createLoadOnlyViewToEntityMapper(attributeLocation, evm, localCache, attributeIdAttributeName, attribute.getMapping(), elementType, cascadePersist, cascadeUpdate, readOnlyAllowedSubtypes, persistAllowedSubtypes, updateAllowedSubtypes, EntityLoaders.referenceLoaderForAttribute(evm, localCache, elementType, viewTypes, attributeIdAttributeName), owner, ownerMapping);
        identifiable = viewToEntityMapper.getViewIdAccessor() != null;
    }
    final boolean shouldJpaMerge = jpaEntity && mutable && cascadeUpdate;
    final boolean shouldJpaPersist = jpaEntity && mutable && cascadePersist;
    final boolean shouldFlushUpdates = cascadeUpdate && !updateAllowedSubtypes.isEmpty();
    final boolean shouldFlushPersists = cascadePersist && !persistAllowedSubtypes.isEmpty();
    return new TypeDescriptor(mutable, identifiable, jpaManaged, jpaEntity, shouldJpaMerge, shouldJpaPersist, shouldFlushPersists, shouldFlushUpdates, entityIdAttributeName, attributeIdAttributeName, jpaType, converter, basicUserType, entityToEntityMapper, viewToEntityMapper, loadOnlyViewToEntityMapper);
}
Also used : BasicType(com.blazebit.persistence.view.metamodel.BasicType) EntityToEntityMapper(com.blazebit.persistence.view.impl.entity.EntityToEntityMapper) DefaultEntityToEntityMapper(com.blazebit.persistence.view.impl.entity.DefaultEntityToEntityMapper) DefaultEntityLoaderFetchGraphNode(com.blazebit.persistence.view.impl.entity.DefaultEntityLoaderFetchGraphNode) LoadOrPersistViewToEntityMapper(com.blazebit.persistence.view.impl.entity.LoadOrPersistViewToEntityMapper) EmbeddableUpdaterBasedViewToEntityMapper(com.blazebit.persistence.view.impl.entity.EmbeddableUpdaterBasedViewToEntityMapper) UpdaterBasedViewToEntityMapper(com.blazebit.persistence.view.impl.entity.UpdaterBasedViewToEntityMapper) ViewToEntityMapper(com.blazebit.persistence.view.impl.entity.ViewToEntityMapper) ManagedViewType(com.blazebit.persistence.view.metamodel.ManagedViewType) DefaultEntityToEntityMapper(com.blazebit.persistence.view.impl.entity.DefaultEntityToEntityMapper) ManagedViewTypeImplementor(com.blazebit.persistence.view.impl.metamodel.ManagedViewTypeImplementor) ExtendedManagedType(com.blazebit.persistence.spi.ExtendedManagedType) EntityType(javax.persistence.metamodel.EntityType) TypeConverter(com.blazebit.persistence.view.spi.type.TypeConverter) BasicType(com.blazebit.persistence.view.metamodel.BasicType) EntityType(javax.persistence.metamodel.EntityType) Type(com.blazebit.persistence.view.metamodel.Type) BasicUserType(com.blazebit.persistence.view.spi.type.BasicUserType) ExtendedManagedType(com.blazebit.persistence.spi.ExtendedManagedType) MutableBasicUserType(com.blazebit.persistence.view.spi.type.MutableBasicUserType) ManagedType(javax.persistence.metamodel.ManagedType) ManagedViewType(com.blazebit.persistence.view.metamodel.ManagedViewType) ViewType(com.blazebit.persistence.view.metamodel.ViewType) EntityMetamodel(com.blazebit.persistence.parser.EntityMetamodel) HashMap(java.util.HashMap) Map(java.util.Map)

Aggregations

ExtendedManagedType (com.blazebit.persistence.spi.ExtendedManagedType)20 ExtendedAttribute (com.blazebit.persistence.spi.ExtendedAttribute)13 EntityType (javax.persistence.metamodel.EntityType)8 PathExpression (com.blazebit.persistence.parser.expression.PathExpression)7 ManagedType (javax.persistence.metamodel.ManagedType)7 HashMap (java.util.HashMap)6 Map (java.util.Map)6 EntityMetamodel (com.blazebit.persistence.parser.EntityMetamodel)5 ArrayList (java.util.ArrayList)4 Attribute (javax.persistence.metamodel.Attribute)4 EmbeddableType (javax.persistence.metamodel.EmbeddableType)4 SingularAttribute (javax.persistence.metamodel.SingularAttribute)4 PathReference (com.blazebit.persistence.parser.expression.PathReference)3 LinkedHashMap (java.util.LinkedHashMap)3 MapKeyExpression (com.blazebit.persistence.parser.expression.MapKeyExpression)2 PathElementExpression (com.blazebit.persistence.parser.expression.PathElementExpression)2 PropertyExpression (com.blazebit.persistence.parser.expression.PropertyExpression)2 JpaProvider (com.blazebit.persistence.spi.JpaProvider)2 InverseRemoveStrategy (com.blazebit.persistence.view.InverseRemoveStrategy)2 AttributeAccessor (com.blazebit.persistence.view.impl.accessor.AttributeAccessor)2