Search in sources :

Example 1 with ManagedViewType

use of com.blazebit.persistence.view.metamodel.ManagedViewType in project blaze-persistence by Blazebit.

the class ViewMapper method createAccessor.

private ObjectMapper createAccessor(ManagedViewType<S> sourceType, ManagedViewType<T> targetType, boolean ignoreMissing, EntityViewKindMapping entityViewKindMapping, EntityViewManager entityViewManager, ProxyFactory proxyFactory, MethodAttribute<? super T, ?> targetAttribute, String prefix, Map<String, Key<Object, Object>> subMappers) {
    String newPrefix;
    if (prefix.isEmpty()) {
        newPrefix = targetAttribute.getName();
    } else {
        newPrefix = prefix + "." + targetAttribute.getName();
    }
    Type<?> attributeType;
    MappingConstructorImpl<?> constructor = null;
    Boolean maybeMarkNew = entityViewKindMapping == EntityViewKindMapping.MARK_NEW ? null : false;
    Key<Object, Object> subMapperKey = subMappers.get(newPrefix);
    if (subMapperKey == Key.EXCLUDE_MARKER) {
        return null;
    } else if (subMapperKey != null) {
        ignoreMissing = subMapperKey.ignoreMissing;
        maybeMarkNew = subMapperKey.markNew;
    }
    // Try to find a source attribute
    MethodAttribute<?, ?> sourceAttribute;
    AttributeAccessor accessor;
    if (sourceType == null) {
        sourceAttribute = null;
        if (targetAttribute.getMappingType() == Attribute.MappingType.PARAMETER) {
            return new ParameterObjectMapper(((MappingAttribute<?, ?>) targetAttribute).getMapping());
        }
        accessor = Accessors.forEntityMapping((EntityViewManagerImpl) entityViewManager, targetAttribute);
        if (accessor == null) {
            if (ignoreMissing) {
                return null;
            }
            throw inconvertible("Attribute '" + targetAttribute.getName() + "' from target type is missing in source type!", targetType);
        }
    } else {
        sourceAttribute = sourceType.getAttribute(targetAttribute.getName());
        if (sourceAttribute == null) {
            if (targetAttribute.getMappingType() == Attribute.MappingType.PARAMETER) {
                return new ParameterObjectMapper(((MappingAttribute<?, ?>) targetAttribute).getMapping());
            }
            // Optionally ignore missing attributes
            if (ignoreMissing) {
                return null;
            }
            throw inconvertible("Attribute '" + targetAttribute.getName() + "' from target type is missing in source type!", sourceType, targetType);
        }
        accessor = Accessors.forViewAttribute(null, sourceAttribute, true);
    }
    // Handle conversion from one type to another
    if (targetAttribute.isCollection()) {
        if ((sourceAttribute != null) && (targetAttribute.getConvertedJavaType() != sourceAttribute.getConvertedJavaType())) {
            throw inconvertible("Attribute '" + targetAttribute.getName() + "' from target type has a different plural type than in source type!", sourceType, targetType);
        }
        PluralAttribute<?, ?, ?> targetPluralAttr = (PluralAttribute<?, ?, ?>) targetAttribute;
        Type<?> elementType = (sourceAttribute == null) ? null : ((PluralAttribute<?, ?, ?>) sourceAttribute).getElementType();
        ViewMapper<Object, Object> valueMapper = null;
        attributeType = targetPluralAttr.getElementType();
        if (subMapperKey != null) {
            attributeType = subMapperKey.targetType;
            constructor = subMapperKey.targetConstructor;
        }
        if (targetAttribute.isSubview()) {
            valueMapper = createViewMapper(elementType, attributeType, constructor, ignoreMissing, maybeMarkNew, entityViewManager, proxyFactory, newPrefix, subMappers);
        } else if ((sourceType != null) && (targetPluralAttr.getElementType() != elementType)) {
            throw inconvertible("Attribute '" + targetAttribute.getName() + "' from target type has a different element type than in source type!", sourceType, targetType);
        }
        boolean needsDirtyTracker = ((AbstractAttribute<?, ?>) targetAttribute).needsDirtyTracker();
        if (targetPluralAttr.getCollectionType() == PluralAttribute.CollectionType.MAP) {
            MapAttribute<?, ?, ?> targetMapAttr = (MapAttribute<?, ?, ?>) targetAttribute;
            Type<?> keyType = (sourceAttribute == null) ? null : ((MapAttribute<?, ?, ?>) sourceAttribute).getKeyType();
            ViewMapper<Object, Object> keyMapper = null;
            if (targetMapAttr.isKeySubview()) {
                String newKeyPrefix = "KEY(" + newPrefix + ")";
                Key<Object, Object> keySubMapperKey = subMappers.get(newKeyPrefix);
                if (keySubMapperKey == Key.EXCLUDE_MARKER) {
                    keyMapper = null;
                } else {
                    constructor = null;
                    Type<?> keyTargetType = targetMapAttr.getKeyType();
                    Boolean maybeMarkNewKey = entityViewKindMapping == EntityViewKindMapping.MARK_NEW ? null : false;
                    if (subMapperKey != null) {
                        constructor = keySubMapperKey.targetConstructor;
                        keyTargetType = keySubMapperKey.targetType;
                        ignoreMissing = keySubMapperKey.ignoreMissing;
                        maybeMarkNewKey = keySubMapperKey.markNew;
                    }
                    keyMapper = createViewMapper(keyType, keyTargetType, constructor, ignoreMissing, maybeMarkNewKey, entityViewManager, proxyFactory, newPrefix, subMappers);
                }
            } else if ((sourceType != null) && (targetMapAttr.getKeyType() != keyType)) {
                throw inconvertible("Attribute '" + targetAttribute.getName() + "' from target type has a different key type than in source type!", sourceType, targetType);
            }
            MapInstantiatorImplementor<?, ?> mapInstantiator = ((AbstractAttribute<?, ?>) targetAttribute).getMapInstantiator();
            return new MapObjectMapper(accessor, needsDirtyTracker, entityViewKindMapping != EntityViewKindMapping.MARK_NEW, mapInstantiator, keyMapper, valueMapper);
        } else {
            CollectionInstantiatorImplementor<?, ?> collectionInstantiator = ((AbstractAttribute<?, ?>) targetAttribute).getCollectionInstantiator();
            return new CollectionObjectMapper(accessor, needsDirtyTracker, entityViewKindMapping != EntityViewKindMapping.MARK_NEW, collectionInstantiator, valueMapper);
        }
    } else if (targetAttribute.isSubview()) {
        attributeType = ((SingularAttribute<?, ?>) targetAttribute).getType();
        if (subMapperKey != null) {
            attributeType = subMapperKey.targetType;
            constructor = subMapperKey.targetConstructor;
        }
        Type<?> type = (sourceAttribute == null) ? null : ((SingularAttribute<?, ?>) sourceAttribute).getType();
        ViewMapper<Object, Object> mapper = createViewMapper(type, attributeType, constructor, ignoreMissing, maybeMarkNew, entityViewManager, proxyFactory, newPrefix, subMappers);
        return new AttributeObjectMapper(accessor, mapper);
    } else if ((sourceAttribute != null) && (targetAttribute.getConvertedJavaType() != sourceAttribute.getConvertedJavaType())) {
        throw inconvertible("Attribute '" + targetAttribute.getName() + "' from target type has a different type than in source type!", sourceType, targetType);
    } else {
        return new PassthroughObjectMapper(accessor);
    }
}
Also used : AbstractAttribute(com.blazebit.persistence.view.impl.metamodel.AbstractAttribute) EntityViewManagerImpl(com.blazebit.persistence.view.impl.EntityViewManagerImpl) PluralAttribute(com.blazebit.persistence.view.metamodel.PluralAttribute) MapAttribute(com.blazebit.persistence.view.metamodel.MapAttribute) SingularAttribute(com.blazebit.persistence.view.metamodel.SingularAttribute) Type(com.blazebit.persistence.view.metamodel.Type) ManagedViewType(com.blazebit.persistence.view.metamodel.ManagedViewType) ViewType(com.blazebit.persistence.view.metamodel.ViewType) AttributeAccessor(com.blazebit.persistence.view.impl.accessor.AttributeAccessor)

Example 2 with ManagedViewType

use of com.blazebit.persistence.view.metamodel.ManagedViewType in project blaze-persistence by Blazebit.

the class AbstractAttribute method checkAttribute.

public void checkAttribute(ManagedType<?> managedType, MetamodelBuildingContext context) {
    Class<?> expressionType = getJavaType();
    Class<?> keyType = null;
    Class<?> elementType = null;
    ManagedType<?> elementManagedType;
    javax.persistence.metamodel.Attribute<?, ?> elementAttribute;
    if (possibleTargetTypes.size() != 1) {
        if (getElementType() instanceof ManagedViewType<?>) {
            elementManagedType = context.getEntityMetamodel().getManagedType(((ManagedViewType<?>) getElementType()).getEntityClass());
        } else {
            elementManagedType = context.getEntityMetamodel().getManagedType(getElementType().getJavaType());
        }
        elementAttribute = null;
    } else {
        elementManagedType = context.getEntityMetamodel().getManagedType(possibleTargetTypes.get(0).getLeafBaseValueClass());
        elementAttribute = possibleTargetTypes.get(0).getLeafMethod();
    }
    ScalarTargetResolvingExpressionVisitor visitor = new ScalarTargetResolvingExpressionVisitor(elementManagedType, elementAttribute, context.getEntityMetamodel(), context.getJpqlFunctions(), declaringType.getEntityViewRootTypes());
    if (fetches.length != 0) {
        if (context.getEntityMetamodel().getManagedType(getElementType().getJavaType()) == null) {
            context.addError("Specifying fetches for non-entity attribute type [" + Arrays.toString(fetches) + "] at the " + getLocation() + " is not allowed!");
        } else {
            for (int i = 0; i < fetches.length; i++) {
                final String fetch = fetches[i];
                final String errorLocation;
                if (fetches.length == 1) {
                    errorLocation = "the fetch expression";
                } else {
                    errorLocation = "the " + (i + 1) + ". fetch expression";
                }
                visitor.clear();
                try {
                    // Validate the fetch expression parses
                    context.getExpressionFactory().createPathExpression(fetch).accept(visitor);
                } catch (SyntaxErrorException ex) {
                    try {
                        context.getExpressionFactory().createSimpleExpression(fetch, false, false, true);
                        // The used expression is not usable for fetches
                        context.addError("Invalid fetch expression '" + fetch + "' of the " + getLocation() + ". Simplify the fetch expression to a simple path expression. Encountered error: " + ex.getMessage());
                    } catch (SyntaxErrorException ex2) {
                        // This is a real syntax error
                        context.addError("Syntax error in " + errorLocation + " '" + fetch + "' of the " + getLocation() + ": " + ex.getMessage());
                    }
                } catch (IllegalArgumentException ex) {
                    context.addError("An error occurred while trying to resolve the " + errorLocation + " '" + fetch + "' of the " + getLocation() + ": " + ex.getMessage());
                }
            }
        }
    }
    if (limitExpression != null) {
        try {
            Expression inItemExpression = context.getTypeValidationExpressionFactory().createInItemExpression(limitExpression);
            if (!(inItemExpression instanceof ParameterExpression) && !(inItemExpression instanceof NumericLiteral) || inItemExpression instanceof NumericLiteral && ((NumericLiteral) inItemExpression).getNumericType() != NumericType.INTEGER) {
                context.addError("Syntax error in the limit expression '" + limitExpression + "' of the " + getLocation() + ": The expression must be a integer literal or a parameter expression");
            }
        } catch (SyntaxErrorException ex) {
            context.addError("Syntax error in the limit expression '" + limitExpression + "' of the " + getLocation() + ": " + ex.getMessage());
        } catch (IllegalArgumentException ex) {
            context.addError("An error occurred while trying to resolve the limit expression '" + limitExpression + "' of the " + getLocation() + ": " + ex.getMessage());
        }
        try {
            Expression inItemExpression = context.getTypeValidationExpressionFactory().createInItemExpression(offsetExpression);
            if (!(inItemExpression instanceof ParameterExpression) && !(inItemExpression instanceof NumericLiteral) || inItemExpression instanceof NumericLiteral && ((NumericLiteral) inItemExpression).getNumericType() != NumericType.INTEGER) {
                context.addError("Syntax error in the offset expression '" + offsetExpression + "' of the " + getLocation() + ": The expression must be a integer literal or a parameter expression");
            }
        } catch (SyntaxErrorException ex) {
            context.addError("Syntax error in the offset expression '" + offsetExpression + "' of the " + getLocation() + ": " + ex.getMessage());
        } catch (IllegalArgumentException ex) {
            context.addError("An error occurred while trying to resolve the offset expression '" + offsetExpression + "' of the " + getLocation() + ": " + ex.getMessage());
        }
        for (int i = 0; i < orderByItems.size(); i++) {
            OrderByItem orderByItem = orderByItems.get(i);
            String expression = orderByItem.getExpression();
            try {
                visitor.clear();
                context.getTypeValidationExpressionFactory().createSimpleExpression(expression, false, false, true).accept(visitor);
            } catch (SyntaxErrorException ex) {
                context.addError("Syntax error in the " + (i + 1) + "th order by expression '" + expression + "' of the " + getLocation() + ": " + ex.getMessage());
            } catch (IllegalArgumentException ex) {
                context.addError("An error occurred while trying to resolve the " + (i + 1) + "th order by expression '" + expression + "' of the " + getLocation() + ": " + ex.getMessage());
            }
        }
    }
    if (fetchStrategy == FetchStrategy.MULTISET) {
        if (getElementType() instanceof ManagedViewTypeImplementor<?> && ((ManagedViewTypeImplementor<?>) getElementType()).hasJpaManagedAttributes()) {
            context.addError("Using the MULTISET fetch strategy is not allowed when the subview contains attributes with entity types. MULTISET at the " + getLocation() + " is not allowed!");
        } else if (getElementType() instanceof BasicTypeImpl<?> && ((BasicTypeImpl<?>) getElementType()).isJpaManaged()) {
            context.addError("Using the MULTISET fetch strategy is not allowed with entity types. MULTISET at the " + getLocation() + " is not allowed!");
        }
    }
    Expression indexExpression = null;
    if (isCollection()) {
        elementType = getElementType().getJavaType();
        if (!isUpdatable()) {
            // Updatable collection attributes are specially handled in the type compatibility check
            if (isIndexed()) {
                if (getCollectionType() == PluralAttribute.CollectionType.MAP) {
                    expressionType = Collection.class;
                    keyType = getKeyType().getJavaType();
                } else {
                    expressionType = Collection.class;
                    keyType = Integer.class;
                }
            } else {
                // We can assign e.g. a Set to a List, so let's use the common supertype
                expressionType = Collection.class;
            }
        }
        if (isIndexed()) {
            if (getCollectionType() == PluralAttribute.CollectionType.MAP) {
                indexExpression = getKeyMappingExpression();
                String[] keyFetches = getKeyFetches();
                if (keyFetches.length != 0) {
                    ManagedType<?> managedKeyType = context.getEntityMetamodel().getManagedType(getKeyType().getJavaType());
                    if (managedKeyType == null) {
                        context.addError("Specifying key fetches for non-entity attribute key type [" + Arrays.toString(keyFetches) + "] at the " + getLocation() + " is not allowed!");
                    } else {
                        ScalarTargetResolvingExpressionVisitor keyVisitor = new ScalarTargetResolvingExpressionVisitor(managedKeyType, context.getEntityMetamodel(), context.getJpqlFunctions(), declaringType.getEntityViewRootTypes());
                        for (int i = 0; i < keyFetches.length; i++) {
                            final String fetch = keyFetches[i];
                            final String errorLocation;
                            if (keyFetches.length == 1) {
                                errorLocation = "the key fetch expression";
                            } else {
                                errorLocation = "the " + (i + 1) + ". key fetch expression";
                            }
                            keyVisitor.clear();
                            try {
                                // Validate the fetch expression parses
                                context.getExpressionFactory().createPathExpression(fetch).accept(keyVisitor);
                            } catch (SyntaxErrorException ex) {
                                try {
                                    context.getExpressionFactory().createSimpleExpression(fetch, false, false, true);
                                    // The used expression is not usable for fetches
                                    context.addError("Invalid key fetch expression '" + fetch + "' of the " + getLocation() + ". Simplify the key fetch expression to a simple path expression. Encountered error: " + ex.getMessage());
                                } catch (SyntaxErrorException ex2) {
                                    // This is a real syntax error
                                    context.addError("Syntax error in " + errorLocation + " '" + fetch + "' of the " + getLocation() + ": " + ex.getMessage());
                                }
                            } catch (IllegalArgumentException ex) {
                                context.addError("An error occurred while trying to resolve the " + errorLocation + " '" + fetch + "' of the " + getLocation() + ": " + ex.getMessage());
                            }
                        }
                    }
                }
            } else {
                indexExpression = getMappingIndexExpression();
            }
        }
    }
    if (isSubview()) {
        ManagedViewTypeImplementor<?> subviewType = (ManagedViewTypeImplementor<?>) getElementType();
        if (isCollection()) {
            elementType = subviewType.getEntityClass();
        } else {
            expressionType = subviewType.getEntityClass();
        }
    } else {
        // If we determined, that the java type is a basic type, let's double check if the user didn't do something wrong
        Class<?> elementJavaType = getElementType().getJavaType();
        if ((elementJavaType.getModifiers() & Modifier.ABSTRACT) != 0) {
            // If the element type has an entity view annotation, although it is considered basic, we throw an error as this means, the view was probably not registered
            if (!isQueryParameter() && AnnotationUtils.findAnnotation(elementJavaType, EntityView.class) != null && getElementType().getConvertedType() == null) {
                context.addError("The element type '" + elementJavaType.getName() + "' is considered basic although the class is annotated with @EntityView. Add a type converter or add the java class to the entity view configuration! Problematic attribute " + getLocation());
            }
        }
    }
    if (isKeySubview()) {
        keyType = ((ManagedViewTypeImplementor<?>) getKeyType()).getEntityClass();
    }
    if (keyType != null) {
        validateTypesCompatible(possibleIndexTargetTypes, keyType, null, isUpdatable(), true, context, ExpressionLocation.MAPPING_INDEX, getLocation());
    }
    if (isCorrelated()) {
        // Validate that resolving "correlationBasis" on "managedType" is valid
        validateTypesCompatible(managedType, correlationBasisExpression, Object.class, null, false, true, declaringType.getEntityViewRootTypes(), context, ExpressionLocation.CORRELATION_BASIS, getLocation());
        if (correlated != null) {
            // Validate that resolving "correlationResult" on "correlated" is compatible with "expressionType" and "elementType"
            validateTypesCompatible(possibleTargetTypes, expressionType, elementType, false, !isCollection(), context, ExpressionLocation.CORRELATION_RESULT, getLocation());
            Predicate correlationPredicate = getCorrelationPredicate();
            if (correlationPredicate != null) {
                ExpressionFactory ef = context.getTypeValidationExpressionFactory();
                // First we need to prefix the correlation basis expression with an alias because we use that in the predicate
                PrefixingQueryGenerator prefixingQueryGenerator = new PrefixingQueryGenerator(ef, correlationKeyAlias, null, null, declaringType.getEntityViewRootTypes().keySet(), false, false);
                prefixingQueryGenerator.setQueryBuffer(new StringBuilder());
                correlationBasisExpression.accept(prefixingQueryGenerator);
                // Next we replace the plain alias usage with the prefixed correlation basis expression
                AliasReplacementVisitor aliasReplacementVisitor = new AliasReplacementVisitor(ef.createSimpleExpression(prefixingQueryGenerator.getQueryBuffer().toString()), correlationKeyAlias);
                correlationPredicate = correlationPredicate.copy(ExpressionCopyContext.EMPTY);
                correlationPredicate.accept(aliasReplacementVisitor);
                // Finally we validate that the expression
                try {
                    Map<String, javax.persistence.metamodel.Type<?>> rootTypes = new HashMap<>(declaringType.getEntityViewRootTypes());
                    rootTypes.put(correlationKeyAlias, managedType);
                    ScalarTargetResolvingExpressionVisitor correlationVisitor = new ScalarTargetResolvingExpressionVisitor(correlated, context.getEntityMetamodel(), context.getJpqlFunctions(), rootTypes);
                    correlationPredicate.accept(correlationVisitor);
                } catch (SyntaxErrorException ex) {
                    context.addError("Syntax error in the condition expression '" + correlationPredicate + "' of the " + getLocation() + ": " + ex.getMessage());
                } catch (IllegalArgumentException ex) {
                    context.addError("An error occurred while trying to resolve the condition expression '" + correlationPredicate + "' of the " + getLocation() + ": " + ex.getMessage());
                }
            }
        }
    } else if (isSubquery()) {
        if (subqueryExpression != null && !subqueryExpression.isEmpty()) {
            // If a converter is applied, we already know that there was a type match with the underlying type
            if (getElementType().getConvertedType() == null) {
                validateTypesCompatible(possibleTargetTypes, expressionType, elementType, false, !isCollection(), context, ExpressionLocation.SUBQUERY_EXPRESSION, getLocation());
            }
        }
    } else if (!isQueryParameter()) {
        // Forcing singular via @MappingSingular
        if (!isCollection() && (Collection.class.isAssignableFrom(expressionType) || Map.class.isAssignableFrom(expressionType))) {
            Class<?>[] typeArguments = getTypeArguments();
            elementType = typeArguments[typeArguments.length - 1];
        }
        // If a converter is applied, we already know that there was a type match with the underlying type
        if (getElementType().getConvertedType() == null) {
            // Validate that resolving "mapping" on "managedType" is compatible with "expressionType" and "elementType"
            validateTypesCompatible(possibleTargetTypes, expressionType, elementType, isUpdatable(), !isCollection(), context, ExpressionLocation.MAPPING, getLocation());
        }
        if (isMutable() && (declaringType.isUpdatable() || declaringType.isCreatable())) {
            UpdatableExpressionVisitor updatableVisitor = new UpdatableExpressionVisitor(context.getEntityMetamodel(), managedType.getJavaType(), isUpdatable(), declaringType.getEntityViewRootTypes());
            try {
                // NOTE: Not supporting "this" here because it doesn't make sense to have an updatable mapping that refers to this
                // The only thing that might be interesting is supporting "this" when we support cascading as properties could be nested
                // But not sure yet if the embeddable attributes would then be modeled as "updatable".
                // I guess these attributes are not "updatable" but that probably depends on the decision regarding collections as they have a similar problem
                // A collection itself might not be "updatable" but it's elements could be. This is roughly the same problem
                mappingExpression.accept(updatableVisitor);
                Map<javax.persistence.metamodel.Attribute<?, ?>, javax.persistence.metamodel.Type<?>> possibleTargets = updatableVisitor.getPossibleTargets();
                if (possibleTargets.size() > 1) {
                    context.addError("Multiple possible target type for the mapping in the " + getLocation() + ": " + possibleTargets);
                }
                // TODO: maybe allow to override this per-attribute?
                if (isDisallowOwnedUpdatableSubview()) {
                    for (Type<?> updateCascadeAllowedSubtype : getUpdateCascadeAllowedSubtypes()) {
                        ManagedViewType<?> managedViewType = (ManagedViewType<?>) updateCascadeAllowedSubtype;
                        if (managedViewType.isUpdatable()) {
                            context.addError("Invalid use of @UpdatableEntityView type '" + managedViewType.getJavaType().getName() + "' for the " + getLocation() + ". Consider using a read-only view type instead or use @AllowUpdatableEntityViews! " + "For further information on this topic, please consult the documentation https://persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#updatable-mappings-subview");
                        }
                    }
                }
            } catch (IllegalArgumentException ex) {
                context.addError("There is an error for the " + getLocation() + ": " + ex.getMessage());
            }
            if (isUpdatable()) {
                if (isCollection() && getElementCollectionType() != null) {
                    context.addError("The use of a multi-collection i.e. List<Collection<?>> or Map<?, Collection<?>> at the " + getLocation() + " is unsupported for updatable collections!");
                }
            }
            if ((isUpdatable() || isKeySubview() && ((ManagedViewTypeImplementor<?>) getKeyType()).isUpdatable()) && indexExpression != null) {
                boolean invalid;
                if (getCollectionType() == PluralAttribute.CollectionType.MAP) {
                    invalid = !(indexExpression instanceof MapKeyExpression) || !"this".equals(((MapKeyExpression) indexExpression).getPath().getPath());
                } else {
                    invalid = !(indexExpression instanceof ListIndexExpression) || !"this".equals(((ListIndexExpression) indexExpression).getPath().getPath());
                }
                if (invalid) {
                    context.addError("The @MappingIndex at the " + getLocation() + " is a complex mapping and can thus not be updatable!");
                }
            }
        }
    }
}
Also used : NumericLiteral(com.blazebit.persistence.parser.expression.NumericLiteral) HashMap(java.util.HashMap) MapAttribute(javax.persistence.metamodel.MapAttribute) PluralAttribute(com.blazebit.persistence.view.metamodel.PluralAttribute) ExtendedAttribute(com.blazebit.persistence.spi.ExtendedAttribute) ListAttribute(javax.persistence.metamodel.ListAttribute) Attribute(com.blazebit.persistence.view.metamodel.Attribute) Predicate(com.blazebit.persistence.parser.predicate.Predicate) AliasReplacementVisitor(com.blazebit.persistence.parser.AliasReplacementVisitor) MapKeyExpression(com.blazebit.persistence.parser.expression.MapKeyExpression) OrderByItem(com.blazebit.persistence.view.metamodel.OrderByItem) ListIndexExpression(com.blazebit.persistence.parser.expression.ListIndexExpression) UpdatableExpressionVisitor(com.blazebit.persistence.view.impl.UpdatableExpressionVisitor) ManagedViewType(com.blazebit.persistence.view.metamodel.ManagedViewType) ExpressionFactory(com.blazebit.persistence.parser.expression.ExpressionFactory) EntityView(com.blazebit.persistence.view.EntityView) SyntaxErrorException(com.blazebit.persistence.parser.expression.SyntaxErrorException) ScalarTargetResolvingExpressionVisitor(com.blazebit.persistence.view.impl.ScalarTargetResolvingExpressionVisitor) TargetType(com.blazebit.persistence.view.impl.ScalarTargetResolvingExpressionVisitor.TargetType) NumericType(com.blazebit.persistence.parser.expression.NumericType) ManagedType(javax.persistence.metamodel.ManagedType) Type(com.blazebit.persistence.view.metamodel.Type) ExtendedManagedType(com.blazebit.persistence.spi.ExtendedManagedType) ManagedViewType(com.blazebit.persistence.view.metamodel.ManagedViewType) ViewType(com.blazebit.persistence.view.metamodel.ViewType) ListIndexExpression(com.blazebit.persistence.parser.expression.ListIndexExpression) Expression(com.blazebit.persistence.parser.expression.Expression) ParameterExpression(com.blazebit.persistence.parser.expression.ParameterExpression) PathExpression(com.blazebit.persistence.parser.expression.PathExpression) PropertyExpression(com.blazebit.persistence.parser.expression.PropertyExpression) NullExpression(com.blazebit.persistence.parser.expression.NullExpression) MapKeyExpression(com.blazebit.persistence.parser.expression.MapKeyExpression) ParameterExpression(com.blazebit.persistence.parser.expression.ParameterExpression) Collection(java.util.Collection) PrefixingQueryGenerator(com.blazebit.persistence.view.impl.PrefixingQueryGenerator) Map(java.util.Map) HashMap(java.util.HashMap)

Example 3 with ManagedViewType

use of com.blazebit.persistence.view.metamodel.ManagedViewType in project blaze-persistence by Blazebit.

the class Mappers method forViewConvertToViewAttributeMapping.

public static <S, T> Mapper<S, T> forViewConvertToViewAttributeMapping(EntityViewManagerImpl evm, ViewType<S> sourceViewType, ViewType<T> targetViewType, Map<String, String> mapping, Mapper<S, T> additionalMapper) {
    List<Mapper<S, T>> mappers = new ArrayList<>();
    ExpressionFactory ef = evm.getCriteriaBuilderFactory().getService(ExpressionFactory.class);
    for (MethodAttribute<?, ?> attribute : targetViewType.getAttributes()) {
        if (attribute.isUpdatable() && attribute instanceof MappingAttribute<?, ?> && attribute instanceof SingularAttribute<?, ?>) {
            for (Map.Entry<String, String> entry : mapping.entrySet()) {
                if (entry.getValue().equals(((MappingAttribute) attribute).getMapping())) {
                    Type<?> attributeType = ((SingularAttribute<?, ?>) attribute).getType();
                    AttributeAccessor entityAccessor;
                    if (entry.getKey().isEmpty()) {
                        entityAccessor = Accessors.forEntityMapping(evm, sourceViewType.getEntityClass(), ((MappingAttribute<?, ?>) sourceViewType.getIdAttribute()).getMapping());
                    } else {
                        entityAccessor = Accessors.forEntityMapping(evm, sourceViewType.getEntityClass(), entry.getKey());
                    }
                    AttributeAccessor targetAttributeAccessor = Accessors.forMutableViewAttribute(evm, attribute);
                    if (attributeType instanceof ViewType<?>) {
                        ViewType<?> viewType = (ViewType<?>) attributeType;
                        Type<?> attributeViewIdType = ((SingularAttribute<?, ?>) viewType.getIdAttribute()).getType();
                        EntityTupleizer entityTupleizer = null;
                        ObjectBuilder<?> idViewBuilder = null;
                        if (attributeViewIdType instanceof ManagedViewType<?>) {
                            entityTupleizer = new DefaultEntityTupleizer(evm, (ManagedViewType<?>) attributeViewIdType);
                            idViewBuilder = (ObjectBuilder<Object>) evm.getTemplate(new MacroConfigurationExpressionFactory(ef, ef.getDefaultMacroConfiguration()), (ManagedViewTypeImplementor<?>) attributeViewIdType, null, null, new MutableViewJpqlMacro(), null, new MutableEmbeddingViewJpqlMacro(), 0).createObjectBuilder(null, null, null, 0, false, false);
                        }
                        mappers.add(new ReferenceViewAttributeMapper<S, T>(evm, entityAccessor, viewType.getJavaType(), entityTupleizer, targetAttributeAccessor, idViewBuilder));
                    } else {
                        mappers.add((Mapper<S, T>) new AttributeMapper<>(Collections.singletonList(entityAccessor), Collections.singletonList(targetAttributeAccessor)));
                    }
                }
            }
        }
    }
    if (mappers.isEmpty()) {
        return additionalMapper;
    }
    return new CompositeMapper<>(mappers.toArray(new Mapper[mappers.size()]));
}
Also used : DefaultEntityTupleizer(com.blazebit.persistence.view.impl.update.DefaultEntityTupleizer) EntityTupleizer(com.blazebit.persistence.view.impl.entity.EntityTupleizer) ArrayList(java.util.ArrayList) MappingAttribute(com.blazebit.persistence.view.metamodel.MappingAttribute) MutableEmbeddingViewJpqlMacro(com.blazebit.persistence.view.impl.macro.MutableEmbeddingViewJpqlMacro) DefaultEntityTupleizer(com.blazebit.persistence.view.impl.update.DefaultEntityTupleizer) ManagedViewType(com.blazebit.persistence.view.metamodel.ManagedViewType) ExpressionFactory(com.blazebit.persistence.parser.expression.ExpressionFactory) MacroConfigurationExpressionFactory(com.blazebit.persistence.view.impl.MacroConfigurationExpressionFactory) MutableViewJpqlMacro(com.blazebit.persistence.view.impl.macro.MutableViewJpqlMacro) ManagedViewTypeImplementor(com.blazebit.persistence.view.impl.metamodel.ManagedViewTypeImplementor) MacroConfigurationExpressionFactory(com.blazebit.persistence.view.impl.MacroConfigurationExpressionFactory) SingularAttribute(com.blazebit.persistence.view.metamodel.SingularAttribute) AttributeAccessor(com.blazebit.persistence.view.impl.accessor.AttributeAccessor) HashMap(java.util.HashMap) Map(java.util.Map) ManagedViewType(com.blazebit.persistence.view.metamodel.ManagedViewType) ViewType(com.blazebit.persistence.view.metamodel.ViewType)

Example 4 with ManagedViewType

use of com.blazebit.persistence.view.metamodel.ManagedViewType in project blaze-persistence by Blazebit.

the class EntityViewBuilderBaseImpl method withSetBuilder.

private <E> EntityViewNestedBuilder<E, ? extends BuilderType, ?> withSetBuilder(AbstractAttribute<?, ?> attr) {
    checkAttribute(attr, SetAttribute.class, "Set");
    checkType(attr.getElementType(), "element", attr);
    Map<ManagedViewType<? extends E>, String> inheritanceSubtypeMappings = ((PluralAttribute<?, ?, E>) attr).getElementInheritanceSubtypeMappings();
    return new EntityViewNestedBuilderImpl<>(evm, (ManagedViewTypeImplementor<E>) attr.getElementType(), inheritanceSubtypeMappings, optionalParameters, (BuilderType) this, new CollectionEntityViewBuilderListener(getCollection(attr)));
}
Also used : ManagedViewType(com.blazebit.persistence.view.metamodel.ManagedViewType) PluralAttribute(com.blazebit.persistence.view.metamodel.PluralAttribute) CollectionEntityViewBuilderListener(com.blazebit.persistence.view.CollectionEntityViewBuilderListener)

Example 5 with ManagedViewType

use of com.blazebit.persistence.view.metamodel.ManagedViewType in project blaze-persistence by Blazebit.

the class EntityViewBuilderBaseImpl method withBuilder.

@Override
public <K, V> EntityViewNestedBuilder<V, ? extends BuilderType, ?> withBuilder(MapAttribute<ViewType, K, V> attribute, K key) {
    if (key == null) {
        throw new IllegalArgumentException("Illegal null key!");
    }
    AbstractAttribute<?, ?> attr = getAttribute(attribute);
    checkAttribute(attr, MapAttribute.class, "Map");
    Type<?> keyType = ((MapAttribute<?, ?, ?>) attr).getKeyType();
    checkType(attr.getElementType(), "element", attr);
    key = getValue(keyType, key);
    Map<ManagedViewType<? extends V>, String> inheritanceSubtypeMappings = ((PluralAttribute<?, ?, V>) attr).getElementInheritanceSubtypeMappings();
    return new EntityViewNestedBuilderImpl<>(evm, (ManagedViewTypeImplementor<V>) attr.getElementType(), inheritanceSubtypeMappings, optionalParameters, (BuilderType) this, new MapEntityViewBuilderListener(getMap(attr), key));
}
Also used : MapAttribute(com.blazebit.persistence.view.metamodel.MapAttribute) ManagedViewType(com.blazebit.persistence.view.metamodel.ManagedViewType) PluralAttribute(com.blazebit.persistence.view.metamodel.PluralAttribute) MapEntityViewBuilderListener(com.blazebit.persistence.view.MapEntityViewBuilderListener)

Aggregations

ManagedViewType (com.blazebit.persistence.view.metamodel.ManagedViewType)29 PluralAttribute (com.blazebit.persistence.view.metamodel.PluralAttribute)18 ViewType (com.blazebit.persistence.view.metamodel.ViewType)12 MapAttribute (com.blazebit.persistence.view.metamodel.MapAttribute)11 AttributeAccessor (com.blazebit.persistence.view.impl.accessor.AttributeAccessor)7 ManagedViewTypeImplementor (com.blazebit.persistence.view.impl.metamodel.ManagedViewTypeImplementor)7 HashMap (java.util.HashMap)7 ArrayList (java.util.ArrayList)6 Map (java.util.Map)6 CollectionEntityViewBuilderListener (com.blazebit.persistence.view.CollectionEntityViewBuilderListener)5 LoadOrPersistViewToEntityMapper (com.blazebit.persistence.view.impl.entity.LoadOrPersistViewToEntityMapper)5 SingularAttribute (com.blazebit.persistence.view.metamodel.SingularAttribute)5 GraphQLInputType (graphql.schema.GraphQLInputType)5 GraphQLOutputType (graphql.schema.GraphQLOutputType)5 EntityMetamodel (com.blazebit.persistence.parser.EntityMetamodel)4 EmbeddableUpdaterBasedViewToEntityMapper (com.blazebit.persistence.view.impl.entity.EmbeddableUpdaterBasedViewToEntityMapper)4 MappingAttribute (com.blazebit.persistence.view.metamodel.MappingAttribute)4 Type (com.blazebit.persistence.view.metamodel.Type)4 ListType (graphql.language.ListType)4 NonNullType (graphql.language.NonNullType)4