Search in sources :

Example 6 with PluralAttribute

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

the class EntityViewBuilderBaseImpl method withMapBuilder.

private <V> EntityViewNestedBuilder<V, ? extends BuilderType, ?> withMapBuilder(AbstractAttribute<?, ?> attr, Object key) {
    if (key == null) {
        throw new IllegalArgumentException("Illegal null key!");
    }
    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)

Example 7 with PluralAttribute

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

the class GraphQLEntityViewSupportFactory method create.

/**
 * Returns a new {@link GraphQLEntityViewSupport} after registering the entity view types from {@link EntityViewManager}
 * on the given {@link TypeDefinitionRegistry}.
 *
 * @param typeRegistry The registry to register types
 * @param entityViewManager The entity view manager
 * @return a new {@link GraphQLEntityViewSupport}
 */
public GraphQLEntityViewSupport create(TypeDefinitionRegistry typeRegistry, EntityViewManager entityViewManager) {
    EntityMetamodel entityMetamodel = entityViewManager.getService(EntityMetamodel.class);
    Map<String, Class<?>> typeNameToClass = new HashMap<>();
    Map<String, Map<String, String>> typeNameToFieldMapping = new HashMap<>();
    for (ManagedViewType<?> managedView : entityViewManager.getMetamodel().getManagedViews()) {
        if (typeFilterPattern != null && !typeFilterPattern.matcher(managedView.getJavaType().getName()).matches()) {
            continue;
        }
        String typeName = getObjectTypeName(managedView);
        String inputTypeName = typeName + "Input";
        String description = getDescription(managedView.getJavaType());
        List<FieldDefinition> fieldDefinitions = new ArrayList<>(managedView.getAttributes().size());
        List<InputValueDefinition> valueDefinitions = new ArrayList<>(managedView.getAttributes().size());
        for (MethodAttribute<?, ?> attribute : managedView.getAttributes()) {
            if (isIgnored(attribute.getJavaMethod())) {
                continue;
            }
            Type type;
            Type inputType;
            if (attribute instanceof SingularAttribute<?, ?>) {
                SingularAttribute<?, ?> singularAttribute = (SingularAttribute<?, ?>) attribute;
                if (singularAttribute.isId() && !singularAttribute.isSubview()) {
                    // Usual numeric ID
                    type = getIdType(typeRegistry, singularAttribute);
                    inputType = getInputIdType(typeRegistry, singularAttribute);
                } else {
                    type = getElementType(typeRegistry, singularAttribute, entityMetamodel);
                    inputType = getInputElementType(typeRegistry, singularAttribute, entityMetamodel);
                }
            } else if (attribute instanceof MapAttribute<?, ?, ?>) {
                MapAttribute<?, ?, ?> mapAttribute = (MapAttribute<?, ?, ?>) attribute;
                type = getEntryType(typeRegistry, attribute, getKeyType(typeRegistry, mapAttribute), getElementType(typeRegistry, mapAttribute));
                inputType = getInputEntryType(typeRegistry, attribute, getInputKeyType(typeRegistry, mapAttribute), getInputElementType(typeRegistry, mapAttribute));
            } else {
                type = new ListType(getElementType(typeRegistry, (PluralAttribute<?, ?, ?>) attribute));
                inputType = new ListType(getInputElementType(typeRegistry, (PluralAttribute<?, ?, ?>) attribute));
            }
            String fieldName = getFieldName(attribute);
            FieldDefinition fieldDefinition = new FieldDefinition(fieldName, type);
            fieldDefinitions.add(fieldDefinition);
            addFieldMapping(typeNameToFieldMapping, typeName, attribute, fieldName);
            valueDefinitions.add(new InputValueDefinition(fieldName, inputType));
            addFieldMapping(typeNameToFieldMapping, inputTypeName, attribute, fieldName);
        }
        addObjectTypeDefinition(typeRegistry, typeNameToClass, managedView, newObjectTypeDefinition(typeName, fieldDefinitions, description), newInputObjectTypeDefinition(inputTypeName, valueDefinitions, description));
    }
    Set<String> serializableBasicTypes = new HashSet<>();
    for (javax.persistence.metamodel.Type<?> basicType : entityMetamodel.getBasicTypes()) {
        for (Class<?> superType : ReflectionUtils.getSuperTypes(basicType.getJavaType())) {
            serializableBasicTypes.add(superType.getName());
        }
        serializableBasicTypes.add(basicType.getJavaType().getName());
    }
    serializableBasicTypes.add(Serializable[].class.getName());
    serializableBasicTypes.add(GraphQLCursor.class.getName());
    return new GraphQLEntityViewSupport(typeNameToClass, typeNameToFieldMapping, serializableBasicTypes);
}
Also used : HashMap(java.util.HashMap) GraphQLFieldDefinition(graphql.schema.GraphQLFieldDefinition) FieldDefinition(graphql.language.FieldDefinition) ArrayList(java.util.ArrayList) ListType(graphql.language.ListType) HashSet(java.util.HashSet) PluralAttribute(com.blazebit.persistence.view.metamodel.PluralAttribute) InputValueDefinition(graphql.language.InputValueDefinition) SingularAttribute(com.blazebit.persistence.view.metamodel.SingularAttribute) MapAttribute(com.blazebit.persistence.view.metamodel.MapAttribute) GraphQLInputObjectType(graphql.schema.GraphQLInputObjectType) GraphQLInterfaceType(graphql.schema.GraphQLInterfaceType) Type(graphql.language.Type) GraphQLObjectType(graphql.schema.GraphQLObjectType) GraphQLInputType(graphql.schema.GraphQLInputType) NonNullType(graphql.language.NonNullType) GraphQLEnumType(graphql.schema.GraphQLEnumType) ListType(graphql.language.ListType) GraphQLScalarType(graphql.schema.GraphQLScalarType) GraphQLType(graphql.schema.GraphQLType) GraphQLOutputType(graphql.schema.GraphQLOutputType) ManagedViewType(com.blazebit.persistence.view.metamodel.ManagedViewType) EntityMetamodel(com.blazebit.persistence.parser.EntityMetamodel) Map(java.util.Map) HashMap(java.util.HashMap)

Example 8 with PluralAttribute

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

the class GraphQLEntityViewSupportFactory method create.

/**
 * Returns a new {@link GraphQLEntityViewSupport} after registering the entity view types from {@link EntityViewManager}
 * on the given {@link TypeDefinitionRegistry}.
 *
 * @param schemaBuilder The registry to register types
 * @param entityViewManager The entity view manager
 * @return a new {@link GraphQLEntityViewSupport}
 */
public GraphQLEntityViewSupport create(GraphQLSchema.Builder schemaBuilder, EntityViewManager entityViewManager) {
    Set<GraphQLType> additionalTypes = isDefineNormalTypes() ? getAndClearAdditionalTypes(schemaBuilder) : Collections.emptySet();
    EntityMetamodel entityMetamodel = entityViewManager.getService(EntityMetamodel.class);
    Map<String, Class<?>> typeNameToClass = new HashMap<>();
    Map<String, Map<String, String>> typeNameToFieldMapping = new HashMap<>();
    Map<Class<?>, String> registeredTypeNames = new HashMap<>();
    for (ManagedViewType<?> managedView : entityViewManager.getMetamodel().getManagedViews()) {
        if (typeFilterPattern != null && !typeFilterPattern.matcher(managedView.getJavaType().getName()).matches()) {
            continue;
        }
        String typeName = getObjectTypeName(managedView);
        String inputTypeName = getInputObjectTypeName(managedView);
        String description = getDescription(managedView.getJavaType());
        GraphQLObjectType.Builder builder = GraphQLObjectType.newObject().name(typeName);
        GraphQLInputObjectType.Builder inputBuilder = GraphQLInputObjectType.newInputObject().name(inputTypeName);
        if (description != null) {
            builder.description(description);
            inputBuilder.description(description);
        }
        for (MethodAttribute<?, ?> attribute : managedView.getAttributes()) {
            if (isIgnored(attribute.getJavaMethod())) {
                continue;
            }
            GraphQLFieldDefinition.Builder fieldBuilder = GraphQLFieldDefinition.newFieldDefinition();
            String fieldName = getFieldName(attribute);
            fieldBuilder.name(fieldName);
            GraphQLOutputType type;
            GraphQLInputType inputType;
            if (attribute instanceof SingularAttribute<?, ?>) {
                SingularAttribute<?, ?> singularAttribute = (SingularAttribute<?, ?>) attribute;
                if (singularAttribute.isId() && !singularAttribute.isSubview()) {
                    type = getIdType(singularAttribute);
                    inputType = getInputIdType(singularAttribute);
                } else {
                    type = getElementType(schemaBuilder, singularAttribute, registeredTypeNames, entityMetamodel);
                    inputType = getInputElementType(schemaBuilder, singularAttribute, registeredTypeNames, entityMetamodel);
                }
            } else if (attribute instanceof MapAttribute<?, ?, ?>) {
                MapAttribute<?, ?, ?> mapAttribute = (MapAttribute<?, ?, ?>) attribute;
                type = getEntryType(schemaBuilder, attribute, getKeyType(schemaBuilder, mapAttribute, registeredTypeNames), getElementType(schemaBuilder, mapAttribute, registeredTypeNames));
                inputType = getInputEntryType(schemaBuilder, attribute, getInputKeyType(schemaBuilder, mapAttribute, registeredTypeNames), getInputElementType(schemaBuilder, mapAttribute, registeredTypeNames));
            } else {
                type = new GraphQLList(getElementType(schemaBuilder, (PluralAttribute<?, ?, ?>) attribute, registeredTypeNames));
                inputType = new GraphQLList(getInputElementType(schemaBuilder, (PluralAttribute<?, ?, ?>) attribute, registeredTypeNames));
            }
            fieldBuilder.type(type);
            builder.field(fieldBuilder);
            addFieldMapping(typeNameToFieldMapping, typeName, attribute, fieldName);
            inputBuilder.field(GraphQLInputObjectField.newInputObjectField().name(fieldName).type(inputType).build());
            addFieldMapping(typeNameToFieldMapping, inputTypeName, attribute, fieldName);
        }
        addObjectTypeDefinition(schemaBuilder, typeNameToClass, managedView, builder.build(), inputBuilder.build());
    }
    Set<String> serializableBasicTypes = new HashSet<>();
    for (javax.persistence.metamodel.Type<?> basicType : entityMetamodel.getBasicTypes()) {
        for (Class<?> superType : ReflectionUtils.getSuperTypes(basicType.getJavaType())) {
            serializableBasicTypes.add(superType.getName());
        }
        serializableBasicTypes.add(basicType.getJavaType().getName());
    }
    serializableBasicTypes.add(Serializable[].class.getName());
    serializableBasicTypes.add(GraphQLCursor.class.getName());
    for (GraphQLType additionalType : additionalTypes) {
        String typeName;
        if (additionalType instanceof GraphQLObjectType) {
            typeName = ((GraphQLObjectType) additionalType).getName();
        } else if (additionalType instanceof GraphQLInterfaceType) {
            typeName = ((GraphQLInterfaceType) additionalType).getName();
        } else {
            typeName = null;
        }
        if (typeName == null || typeNameToClass.get(typeName) == null) {
            schemaBuilder.additionalType(additionalType);
        }
    }
    return new GraphQLEntityViewSupport(typeNameToClass, typeNameToFieldMapping, serializableBasicTypes);
}
Also used : HashMap(java.util.HashMap) GraphQLType(graphql.schema.GraphQLType) GraphQLFieldDefinition(graphql.schema.GraphQLFieldDefinition) GraphQLInterfaceType(graphql.schema.GraphQLInterfaceType) GraphQLInputType(graphql.schema.GraphQLInputType) HashSet(java.util.HashSet) GraphQLList(graphql.schema.GraphQLList) PluralAttribute(com.blazebit.persistence.view.metamodel.PluralAttribute) SingularAttribute(com.blazebit.persistence.view.metamodel.SingularAttribute) MapAttribute(com.blazebit.persistence.view.metamodel.MapAttribute) GraphQLOutputType(graphql.schema.GraphQLOutputType) GraphQLInputObjectType(graphql.schema.GraphQLInputObjectType) GraphQLObjectType(graphql.schema.GraphQLObjectType) EntityMetamodel(com.blazebit.persistence.parser.EntityMetamodel) Map(java.util.Map) HashMap(java.util.HashMap)

Example 9 with PluralAttribute

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

the class ViewTypeObjectBuilderTemplate method applyMapping.

@SuppressWarnings("unchecked")
private void applyMapping(AbstractAttribute<?, ?> attribute, String parentAttributePath, TupleElementMapperBuilder mapperBuilder, Set<Feature> features, TupleIdDescriptor tupleIdDescriptor, ViewJpqlMacro viewJpqlMacro, EmbeddingViewJpqlMacro embeddingViewJpqlMacro, ExpressionFactory ef) {
    String attributePath = getAttributePath(parentAttributePath, attribute, false);
    int batchSize = attribute.getBatchSize();
    if (batchSize == -1) {
        batchSize = attribute.getDeclaringType().getDefaultBatchSize();
    }
    if (attribute.isSubquery()) {
        applySubqueryMapping((SubqueryAttribute<? super T, ?>) attribute, attributePath, mapperBuilder, embeddingViewJpqlMacro);
    } else {
        if (attribute.isCollection()) {
            PluralAttribute<? super T, ?, ?> pluralAttribute = (PluralAttribute<? super T, ?, ?>) attribute;
            TypeConverter<Object, Object> keyConverter = null;
            TypeConverter<Object, Object> valueConverter = (TypeConverter<Object, Object>) pluralAttribute.getElementType().getConverter();
            boolean listKey = pluralAttribute.isIndexed() && pluralAttribute instanceof ListAttribute<?, ?>;
            boolean mapKey = pluralAttribute.isIndexed() && pluralAttribute instanceof MapAttribute<?, ?, ?>;
            int startIndex = tupleOffset + mapperBuilder.mapperIndex();
            int valueStartIndex = startIndex + 1;
            if (pluralAttribute.getFetchStrategy() == FetchStrategy.JOIN) {
                if (listKey) {
                    MappingAttribute<? super T, ?> mappingAttribute = (MappingAttribute<? super T, ?>) attribute;
                    features.add(Feature.INDEXED_COLLECTIONS);
                    applyIndexCollectionFunctionMapping(IntegerBasicUserType.INSTANCE, mappingAttribute, attributePath, mapperBuilder, embeddingViewJpqlMacro);
                } else if (mapKey) {
                    MappingAttribute<? super T, ?> mappingAttribute = (MappingAttribute<? super T, ?>) attribute;
                    features.add(Feature.INDEXED_COLLECTIONS);
                    MapAttribute<?, ?, ?> mapAttribute = (MapAttribute<?, ?, ?>) pluralAttribute;
                    keyConverter = (TypeConverter<Object, Object>) mapAttribute.getKeyType().getConverter();
                    if (mapAttribute.isKeySubview()) {
                        features.add(Feature.SUBVIEWS);
                        ManagedViewTypeImpl<Object[]> managedViewType = (ManagedViewTypeImpl<Object[]>) mapAttribute.getKeyType();
                        applySubviewMapping(mappingAttribute, attributePath, tupleIdDescriptor, managedViewType, mapperBuilder, viewJpqlMacro, embeddingViewJpqlMacro, ef, true, true);
                        valueStartIndex = tupleOffset + mapperBuilder.mapperIndex();
                    } else {
                        applyIndexCollectionFunctionMapping(TypeUtils.forType(mapAttribute.getKeyType()), mappingAttribute, attributePath, mapperBuilder, embeddingViewJpqlMacro);
                    }
                }
            }
            boolean dirtyTracking = pluralAttribute instanceof MethodAttribute<?, ?> && attribute.needsDirtyTracker();
            if (pluralAttribute.isSubview()) {
                features.add(Feature.SUBVIEWS);
                TupleIdDescriptor newTupleIdDescriptor;
                if ((listKey || mapKey) && pluralAttribute.getFetchStrategy() == FetchStrategy.JOIN && !pluralAttribute.isCorrelated()) {
                    newTupleIdDescriptor = new TupleIdDescriptor(tupleIdDescriptor);
                    newTupleIdDescriptor.addIdPosition(startIndex);
                } else {
                    newTupleIdDescriptor = tupleIdDescriptor;
                }
                if (pluralAttribute.isCorrelated() || (pluralAttribute.getFetchStrategy() != FetchStrategy.JOIN || attribute.getLimitExpression() != null) && pluralAttribute.getFetchStrategy() != FetchStrategy.MULTISET) {
                    ManagedViewTypeImplementor<Object> managedViewType = (ManagedViewTypeImplementor<Object>) pluralAttribute.getElementType();
                    if (attribute.getFetchStrategy() == FetchStrategy.MULTISET) {
                        boolean updatableObjectCache = managedViewType.isUpdatable() || managedViewType.isCreatable();
                        boolean nullIfEmpty = managedViewType instanceof ViewType<?>;
                        ViewTypeObjectBuilderTemplate<Object[]>[] templates = applyCorrelatedSubviewMapping(attribute, attributePath, tupleIdDescriptor, (ManagedViewTypeImplementor<Object[]>) (ManagedViewTypeImplementor<?>) managedViewType, mapperBuilder, features, viewJpqlMacro, embeddingViewJpqlMacro, ef, batchSize, false);
                        ViewTypeObjectBuilderTemplate<Object[]> subviewTemplate = templates[0];
                        ViewTypeObjectBuilderTemplate<Object[]> indexTemplate = templates[1];
                        SubviewTupleTransformerFactory indexTransformerFactory = null;
                        BasicUserTypeStringSupport<?> indexBasicTypeSupport = null;
                        if (indexTemplate != null) {
                            boolean updatableKeyObjectCache = indexTemplate.viewType.isUpdatable() || indexTemplate.viewType.isCreatable();
                            indexTransformerFactory = new SubviewTupleTransformerFactory(attributePath, indexTemplate, updatableKeyObjectCache, true);
                        } else if (mapKey) {
                            indexBasicTypeSupport = TypeUtils.forType(((MapAttribute<?, ?, ?>) attribute).getKeyType());
                        } else if (listKey) {
                            indexBasicTypeSupport = IntegerBasicUserType.INSTANCE;
                        }
                        mapperBuilder.addTupleTransformerFactory(new CollectionMultisetTupleTransformerFactory(startIndex, null, attributePath, getMultisetResultAlias(attributePath), valueConverter, attribute.getContainerAccumulator(), dirtyTracking, subviewTemplate, indexTemplate, managedViewType.hasSelectOrSubselectFetchedAttributes(), new SubviewTupleTransformerFactory(attributePath, subviewTemplate, updatableObjectCache, nullIfEmpty), indexTransformerFactory, null, indexBasicTypeSupport));
                    } else {
                        applyCorrelatedSubviewMapping(attribute, attributePath, newTupleIdDescriptor, (ManagedViewTypeImplementor<Object[]>) (ManagedViewTypeImplementor<?>) managedViewType, mapperBuilder, features, viewJpqlMacro, embeddingViewJpqlMacro, ef, batchSize, dirtyTracking);
                    }
                } else {
                    MappingAttribute<? super T, ?> mappingAttribute = (MappingAttribute<? super T, ?>) attribute;
                    ManagedViewTypeImplementor<Object[]> managedViewType = (ManagedViewTypeImplementor<Object[]>) pluralAttribute.getElementType();
                    boolean nullIfEmpty = managedViewType instanceof ViewType<?> || !listKey && !mapKey;
                    if (pluralAttribute.getFetchStrategy() == FetchStrategy.MULTISET) {
                        boolean updatableObjectCache = managedViewType.isUpdatable() || managedViewType.isCreatable();
                        String mapping = mapperBuilder.getMapping(mappingAttribute);
                        ViewTypeObjectBuilderTemplate<Object[]>[] templates = applySubviewMapping(mappingAttribute, attributePath, newTupleIdDescriptor, managedViewType, mapperBuilder, viewJpqlMacro, embeddingViewJpqlMacro, ef, false, nullIfEmpty);
                        ViewTypeObjectBuilderTemplate<Object[]> subviewTemplate = templates[0];
                        ViewTypeObjectBuilderTemplate<Object[]> indexTemplate = templates[1];
                        SubviewTupleTransformerFactory indexTransformerFactory = null;
                        BasicUserTypeStringSupport<?> indexBasicTypeSupport = null;
                        if (indexTemplate != null) {
                            boolean updatableKeyObjectCache = indexTemplate.viewType.isUpdatable() || indexTemplate.viewType.isCreatable();
                            indexTransformerFactory = new SubviewTupleTransformerFactory(attributePath, indexTemplate, updatableKeyObjectCache, true);
                        } else if (mapKey) {
                            indexBasicTypeSupport = TypeUtils.forType(((MapAttribute<?, ?, ?>) attribute).getKeyType());
                        } else if (listKey) {
                            indexBasicTypeSupport = IntegerBasicUserType.INSTANCE;
                        }
                        mapperBuilder.addTupleTransformerFactory(new CollectionMultisetTupleTransformerFactory(startIndex, mapping, attributePath, getMultisetResultAlias(attributePath), valueConverter, attribute.getContainerAccumulator(), dirtyTracking, subviewTemplate, indexTemplate, managedViewType.hasSelectOrSubselectFetchedAttributes(), new SubviewTupleTransformerFactory(attributePath, subviewTemplate, updatableObjectCache, nullIfEmpty), indexTransformerFactory, null, indexBasicTypeSupport));
                    } else {
                        // Obviously, we produce null if the object type is identifiable i.e. a ViewType and it is empty = null id
                        // Additionally, we also consider empty embeddables as null when we have a non-indexed collection so we can filter out these elements
                        applySubviewMapping(mappingAttribute, attributePath, newTupleIdDescriptor, managedViewType, mapperBuilder, viewJpqlMacro, embeddingViewJpqlMacro, ef, false, nullIfEmpty);
                    }
                }
            } else if (mapKey) {
                MappingAttribute<? super T, ?> mappingAttribute = (MappingAttribute<? super T, ?>) attribute;
                applyCollectionFunctionMapping(TypeUtils.forType(getType(mappingAttribute)), mappingAttribute, attributePath, mapperBuilder, mappingAttribute.getFetches(), embeddingViewJpqlMacro);
            } else {
                // TODO: Multiset basic fetching?
                if (pluralAttribute.isCorrelated() || attribute.getFetchStrategy() == FetchStrategy.JOIN && !attribute.getOrderByItems().isEmpty() || pluralAttribute.getFetchStrategy() != FetchStrategy.JOIN && pluralAttribute.getFetchStrategy() != FetchStrategy.MULTISET) {
                    applyBasicCorrelatedMapping(attribute, attributePath, mapperBuilder, features, ef, batchSize, dirtyTracking, embeddingViewJpqlMacro);
                } else {
                    MappingAttribute<? super T, ?> mappingAttribute = (MappingAttribute<? super T, ?>) attribute;
                    applyBasicMapping(mappingAttribute, attributePath, mapperBuilder, embeddingViewJpqlMacro);
                }
            }
            if (pluralAttribute.getFetchStrategy() == FetchStrategy.JOIN) {
                if (listKey) {
                    if (pluralAttribute.isSorted()) {
                        throw new IllegalArgumentException("The list attribute '" + pluralAttribute + "' can not be sorted!");
                    } else {
                        mapperBuilder.addTupleListTransformer(new IndexedTupleListTransformer(tupleIdDescriptor.createIdPositions(), startIndex, valueStartIndex, attribute.getContainerAccumulator(), dirtyTracking, null, valueConverter));
                    }
                } else if (mapKey) {
                    mapperBuilder.addTupleListTransformer(new IndexedTupleListTransformer(tupleIdDescriptor.createIdPositions(), startIndex, valueStartIndex, attribute.getContainerAccumulator(), dirtyTracking, keyConverter, valueConverter));
                } else {
                    switch(pluralAttribute.getCollectionType()) {
                        case COLLECTION:
                            if (pluralAttribute.isSorted()) {
                                throw new IllegalArgumentException("The collection attribute '" + pluralAttribute + "' can not be sorted!");
                            }
                            break;
                        case LIST:
                            if (pluralAttribute.isSorted()) {
                                throw new IllegalArgumentException("The list attribute '" + pluralAttribute + "' can not be sorted!");
                            }
                            break;
                        case SET:
                            break;
                        case MAP:
                            throw new IllegalArgumentException("Ignoring the index on the attribute '" + pluralAttribute + "' is not possible!");
                        default:
                            throw new IllegalArgumentException("Unknown collection type: " + pluralAttribute.getCollectionType());
                    }
                    mapperBuilder.addTupleListTransformer(new NonIndexedTupleListTransformer(tupleIdDescriptor.createIdPositions(), startIndex, attribute.getCollectionInstantiator(), dirtyTracking, valueConverter));
                }
            }
        } else if (attribute.isQueryParameter()) {
            MappingAttribute<? super T, ?> mappingAttribute = (MappingAttribute<? super T, ?>) attribute;
            features.add(Feature.PARAMETERS);
            applyQueryParameterMapping(mappingAttribute, mapperBuilder);
        } else if (attribute.isSubview()) {
            features.add(Feature.SUBVIEWS);
            boolean nullIfEmpty = !((SingularAttribute<?, ?>) attribute).isCreateEmptyFlatView();
            if (attribute.isCorrelated() || attribute.getFetchStrategy() == FetchStrategy.JOIN && !attribute.getOrderByItems().isEmpty() || attribute.getFetchStrategy() != FetchStrategy.JOIN && attribute.getFetchStrategy() != FetchStrategy.MULTISET) {
                ManagedViewTypeImplementor<Object> managedViewType = (ManagedViewTypeImplementor<Object>) ((SingularAttribute<?, ?>) attribute).getType();
                if (attribute.getFetchStrategy() == FetchStrategy.MULTISET) {
                    int startIndex = tupleOffset + mapperBuilder.mapperIndex();
                    boolean updatableObjectCache = managedViewType.isUpdatable() || managedViewType.isCreatable();
                    ViewTypeObjectBuilderTemplate<Object[]> subviewTemplate = applyCorrelatedSubviewMapping(attribute, attributePath, tupleIdDescriptor, (ManagedViewTypeImplementor<Object[]>) (ManagedViewTypeImplementor<?>) managedViewType, mapperBuilder, features, viewJpqlMacro, embeddingViewJpqlMacro, ef, batchSize, false)[0];
                    TypeConverter<Object, Object> elementConverter = (TypeConverter<Object, Object>) (TypeConverter<?, ?>) managedViewType.getConverter();
                    mapperBuilder.addTupleTransformerFactory(new SingularMultisetTupleTransformerFactory(startIndex, null, attributePath, getMultisetResultAlias(attributePath), elementConverter, subviewTemplate, managedViewType.hasSelectOrSubselectFetchedAttributes(), new SubviewTupleTransformerFactory(attributePath, subviewTemplate, updatableObjectCache, nullIfEmpty)));
                } else {
                    applyCorrelatedSubviewMapping(attribute, attributePath, tupleIdDescriptor, (ManagedViewTypeImplementor<Object[]>) (ManagedViewTypeImplementor<?>) managedViewType, mapperBuilder, features, viewJpqlMacro, embeddingViewJpqlMacro, ef, batchSize, false);
                }
            } else {
                MappingAttribute<? super T, ?> mappingAttribute = (MappingAttribute<? super T, ?>) attribute;
                ManagedViewTypeImplementor<Object[]> managedViewType = (ManagedViewTypeImplementor<Object[]>) ((SingularAttribute<?, ?>) attribute).getType();
                if (attribute.getFetchStrategy() == FetchStrategy.MULTISET) {
                    int startIndex = tupleOffset + mapperBuilder.mapperIndex();
                    boolean updatableObjectCache = managedViewType.isUpdatable() || managedViewType.isCreatable();
                    String mapping = mapperBuilder.getMapping(mappingAttribute);
                    ViewTypeObjectBuilderTemplate<Object[]> subviewTemplate = applySubviewMapping(mappingAttribute, attributePath, tupleIdDescriptor, managedViewType, mapperBuilder, viewJpqlMacro, embeddingViewJpqlMacro, ef, false, nullIfEmpty)[0];
                    TypeConverter<Object, Object> elementConverter = (TypeConverter<Object, Object>) (TypeConverter<?, ?>) managedViewType.getConverter();
                    mapperBuilder.addTupleTransformerFactory(new SingularMultisetTupleTransformerFactory(startIndex, mapping, attributePath, getMultisetResultAlias(attributePath), elementConverter, subviewTemplate, managedViewType.hasSelectOrSubselectFetchedAttributes(), new SubviewTupleTransformerFactory(attributePath, subviewTemplate, updatableObjectCache, nullIfEmpty)));
                } else {
                    applySubviewMapping(mappingAttribute, attributePath, tupleIdDescriptor, managedViewType, mapperBuilder, viewJpqlMacro, embeddingViewJpqlMacro, ef, false, nullIfEmpty);
                }
            }
        } else {
            if (attribute.isCorrelated() || attribute.getFetchStrategy() == FetchStrategy.JOIN && !attribute.getOrderByItems().isEmpty() || attribute.getFetchStrategy() != FetchStrategy.JOIN && attribute.getFetchStrategy() != FetchStrategy.MULTISET) {
                applyBasicCorrelatedMapping(attribute, attributePath, mapperBuilder, features, ef, batchSize, false, embeddingViewJpqlMacro);
            } else {
                MappingAttribute<? super T, ?> mappingAttribute = (MappingAttribute<? super T, ?>) attribute;
                applyBasicMapping(mappingAttribute, attributePath, mapperBuilder, embeddingViewJpqlMacro);
            }
        }
    }
}
Also used : MappingAttribute(com.blazebit.persistence.view.metamodel.MappingAttribute) NonIndexedTupleListTransformer(com.blazebit.persistence.view.impl.objectbuilder.transformer.NonIndexedTupleListTransformer) IndexedTupleListTransformer(com.blazebit.persistence.view.impl.objectbuilder.transformer.IndexedTupleListTransformer) NonIndexedTupleListTransformer(com.blazebit.persistence.view.impl.objectbuilder.transformer.NonIndexedTupleListTransformer) ManagedViewTypeImpl(com.blazebit.persistence.view.impl.metamodel.ManagedViewTypeImpl) SubviewTupleTransformerFactory(com.blazebit.persistence.view.impl.objectbuilder.transformer.SubviewTupleTransformerFactory) CollectionMultisetTupleTransformerFactory(com.blazebit.persistence.view.impl.objectbuilder.transformer.CollectionMultisetTupleTransformerFactory) PluralAttribute(com.blazebit.persistence.view.metamodel.PluralAttribute) ManagedViewTypeImplementor(com.blazebit.persistence.view.impl.metamodel.ManagedViewTypeImplementor) TypeConverter(com.blazebit.persistence.view.spi.type.TypeConverter) MapAttribute(com.blazebit.persistence.view.metamodel.MapAttribute) SingularMultisetTupleTransformerFactory(com.blazebit.persistence.view.impl.objectbuilder.transformer.SingularMultisetTupleTransformerFactory) ManagedViewType(com.blazebit.persistence.view.metamodel.ManagedViewType) ViewType(com.blazebit.persistence.view.metamodel.ViewType)

Example 10 with PluralAttribute

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

the class ViewTypeObjectBuilderTemplate method applySubviewMapping.

@SuppressWarnings("unchecked")
private ViewTypeObjectBuilderTemplate<Object[]>[] applySubviewMapping(MappingAttribute<? super T, ?> mappingAttribute, String subviewAttributePath, TupleIdDescriptor tupleIdDescriptor, ManagedViewTypeImplementor<Object[]> managedViewType, TupleElementMapperBuilder mapperBuilder, ViewJpqlMacro viewJpqlMacro, EmbeddingViewJpqlMacro embeddingViewJpqlMacro, ExpressionFactory ef, boolean isKey, boolean nullIfEmpty) {
    AbstractAttribute<?, ?> attribute = (AbstractAttribute<?, ?>) mappingAttribute;
    String subviewAliasPrefix = mapperBuilder.getAlias(mappingAttribute, isKey);
    String subviewMappingPrefix;
    String subviewIdPrefix;
    int startIndex;
    if (mappingAttribute.getFetchStrategy() == FetchStrategy.MULTISET) {
        startIndex = 0;
    } else {
        startIndex = tupleOffset + mapperBuilder.mapperIndex();
    }
    boolean updatableObjectCache = managedViewType.isUpdatable() || managedViewType.isCreatable();
    TupleIdDescriptor subviewTupleIdDescriptor = new TupleIdDescriptor(tupleIdDescriptor);
    TupleIdDescriptor subviewIdDescriptor;
    String multisetCorrelationExpression;
    if (mappingAttribute.getFetchStrategy() != FetchStrategy.MULTISET) {
        if (isKey) {
            subviewMappingPrefix = mapperBuilder.getKeyMapping((MapAttribute<?, ?, ?>) mappingAttribute);
        } else {
            subviewMappingPrefix = mapperBuilder.getMapping(mappingAttribute);
        }
        subviewIdPrefix = subviewMappingPrefix;
        multisetCorrelationExpression = null;
    } else {
        // Must be in sync with com.blazebit.persistence.view.impl.objectbuilder.mapper.MultisetTupleElementMapper.applyMapping
        subviewMappingPrefix = getMultisetResultAlias(subviewAttributePath);
        subviewIdPrefix = subviewMappingPrefix;
        multisetCorrelationExpression = mapperBuilder.getMapping(mappingAttribute);
    }
    String oldViewPath = viewJpqlMacro.getViewPath();
    viewJpqlMacro.setViewPath(subviewMappingPrefix);
    if (managedViewType instanceof ViewType<?>) {
        // When the attribute is not update mappable i.e. joining over other associations, we use its parent's parent id
        if (attribute.isUpdateMappable()) {
            subviewIdDescriptor = new TupleIdDescriptor();
        } else {
            subviewIdDescriptor = new TupleIdDescriptor(tupleIdDescriptor);
        }
    } else {
        subviewIdDescriptor = new TupleIdDescriptor(tupleIdDescriptor);
        subviewIdDescriptor.addIdPosition(flatViewIdPosition(mappingAttribute));
        subviewTupleIdDescriptor.addIdPosition(flatViewIdPosition(mappingAttribute));
    }
    int endTupleElementsToAdd = 0;
    String indexExpression = null;
    ViewTypeObjectBuilderTemplate<Object[]> indexTemplate = null;
    if (mappingAttribute.getFetchStrategy() == FetchStrategy.MULTISET) {
        if (attribute.getKeyMappingExpression() != null) {
            MapAttribute<?, ?, ?> mapAttribute = (MapAttribute<?, ?, ?>) attribute;
            indexExpression = mapperBuilder.getKeyMapping(subviewMappingPrefix, mapAttribute);
            if (mapAttribute.isKeySubview()) {
                indexTemplate = new ViewTypeObjectBuilderTemplate<Object[]>(viewRoot, viewRootAlias, subviewAttributePath, subviewAliasPrefix, indexExpression, indexExpression, subviewTupleIdDescriptor, subviewIdDescriptor, 1, 0, viewJpqlMacro, embeddingViewJpqlMacro, (Map<ManagedViewType<? extends Object[]>, String>) (Map<?, ?>) mapAttribute.getKeyInheritanceSubtypeMappings(), evm, ef, (ManagedViewTypeImplementor<Object[]>) mapAttribute.getKeyType(), null, proxyFactory);
            }
        } else if (attribute.getMappingIndexExpression() != null) {
            indexExpression = mapperBuilder.getIndexMapping(subviewMappingPrefix, (ListAttribute<?, ?>) attribute);
        }
        if (updatableObjectCache && managedViewType.getMappingType() == Type.MappingType.FLAT_VIEW) {
            if (indexExpression != null) {
                endTupleElementsToAdd = 1;
            } else if (indexTemplate != null) {
                endTupleElementsToAdd = indexTemplate.effectiveTupleSize;
            }
        }
    }
    Map<ManagedViewType<? extends Object[]>, String> inheritanceSubtypeMappings;
    if (isKey) {
        inheritanceSubtypeMappings = (Map<ManagedViewType<? extends Object[]>, String>) (Map<?, ?>) ((MapAttribute<?, ?, ?>) mappingAttribute).getKeyInheritanceSubtypeMappings();
    } else if (mappingAttribute instanceof PluralAttribute<?, ?, ?>) {
        inheritanceSubtypeMappings = (Map<ManagedViewType<? extends Object[]>, String>) (Map<?, ?>) ((PluralAttribute<?, ?, ?>) mappingAttribute).getElementInheritanceSubtypeMappings();
    } else {
        inheritanceSubtypeMappings = (Map<ManagedViewType<? extends Object[]>, String>) (Map<?, ?>) ((SingularAttribute<?, ?>) mappingAttribute).getInheritanceSubtypeMappings();
    }
    String embeddingViewPath = mapperBuilder.getMapping();
    String oldEmbeddingViewPath = embeddingViewJpqlMacro.getEmbeddingViewPath();
    embeddingViewJpqlMacro.setEmbeddingViewPath(embeddingViewPath);
    ViewTypeObjectBuilderTemplate<Object[]> template = new ViewTypeObjectBuilderTemplate<Object[]>(viewRoot, viewRootAlias, subviewAttributePath, subviewAliasPrefix, subviewMappingPrefix, subviewIdPrefix, subviewTupleIdDescriptor, subviewIdDescriptor, startIndex, endTupleElementsToAdd, viewJpqlMacro, embeddingViewJpqlMacro, inheritanceSubtypeMappings, evm, ef, managedViewType, null, proxyFactory);
    ViewTypeObjectBuilderTemplate<Object[]>[] templates = null;
    if (mappingAttribute.getFetchStrategy() == FetchStrategy.MULTISET) {
        String multisetResultAlias = getMultisetResultAlias(subviewAttributePath);
        mapperBuilder.addMapper(new MultisetTupleElementMapper(template, multisetCorrelationExpression, subviewAttributePath, multisetResultAlias, embeddingViewPath, indexExpression, indexTemplate, createLimiter(mapperBuilder, multisetResultAlias, mappingAttribute)));
        templates = new ViewTypeObjectBuilderTemplate[] { template, indexTemplate };
    } else {
        mapperBuilder.addMappers(template.mappers);
        mapperBuilder.addSecondaryMappers(template.secondaryMappers);
        mapperBuilder.addTupleTransformatorFactory(template.tupleTransformatorFactory);
        mapperBuilder.addTupleTransformerFactory(new SubviewTupleTransformerFactory(subviewAttributePath, template, updatableObjectCache, nullIfEmpty));
    }
    embeddingViewJpqlMacro.setEmbeddingViewPath(oldEmbeddingViewPath);
    viewJpqlMacro.setViewPath(oldViewPath);
    return templates;
}
Also used : ManagedViewType(com.blazebit.persistence.view.metamodel.ManagedViewType) MultisetTupleElementMapper(com.blazebit.persistence.view.impl.objectbuilder.mapper.MultisetTupleElementMapper) CorrelationMultisetTupleElementMapper(com.blazebit.persistence.view.impl.objectbuilder.mapper.CorrelationMultisetTupleElementMapper) PluralAttribute(com.blazebit.persistence.view.metamodel.PluralAttribute) ManagedViewTypeImplementor(com.blazebit.persistence.view.impl.metamodel.ManagedViewTypeImplementor) MapAttribute(com.blazebit.persistence.view.metamodel.MapAttribute) SingularAttribute(com.blazebit.persistence.view.metamodel.SingularAttribute) AbstractAttribute(com.blazebit.persistence.view.impl.metamodel.AbstractAttribute) SubviewTupleTransformerFactory(com.blazebit.persistence.view.impl.objectbuilder.transformer.SubviewTupleTransformerFactory) Map(java.util.Map) LinkedHashMap(java.util.LinkedHashMap) HashMap(java.util.HashMap) ManagedViewType(com.blazebit.persistence.view.metamodel.ManagedViewType) ViewType(com.blazebit.persistence.view.metamodel.ViewType)

Aggregations

PluralAttribute (com.blazebit.persistence.view.metamodel.PluralAttribute)20 ManagedViewType (com.blazebit.persistence.view.metamodel.ManagedViewType)16 MapAttribute (com.blazebit.persistence.view.metamodel.MapAttribute)13 CollectionEntityViewBuilderListener (com.blazebit.persistence.view.CollectionEntityViewBuilderListener)5 HashMap (java.util.HashMap)5 Map (java.util.Map)5 ManagedViewTypeImplementor (com.blazebit.persistence.view.impl.metamodel.ManagedViewTypeImplementor)4 SingularAttribute (com.blazebit.persistence.view.metamodel.SingularAttribute)4 ViewType (com.blazebit.persistence.view.metamodel.ViewType)4 ArrayList (java.util.ArrayList)4 EntityMetamodel (com.blazebit.persistence.parser.EntityMetamodel)3 CorrelationMultisetTupleElementMapper (com.blazebit.persistence.view.impl.objectbuilder.mapper.CorrelationMultisetTupleElementMapper)3 LinkedHashMap (java.util.LinkedHashMap)3 Expression (com.blazebit.persistence.parser.expression.Expression)2 CorrelationProviderFactory (com.blazebit.persistence.view.CorrelationProviderFactory)2 ListEntityViewBuilderListener (com.blazebit.persistence.view.ListEntityViewBuilderListener)2 MapEntityViewBuilderListener (com.blazebit.persistence.view.MapEntityViewBuilderListener)2 MapKeyEntityViewBuilderListener (com.blazebit.persistence.view.MapKeyEntityViewBuilderListener)2 AttributeAccessor (com.blazebit.persistence.view.impl.accessor.AttributeAccessor)2 AbstractAttribute (com.blazebit.persistence.view.impl.metamodel.AbstractAttribute)2