use of com.blazebit.persistence.view.impl.metamodel.ManagedViewTypeImplementor 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()]));
}
use of com.blazebit.persistence.view.impl.metamodel.ManagedViewTypeImplementor 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);
}
}
use of com.blazebit.persistence.view.impl.metamodel.ManagedViewTypeImplementor 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);
}
use of com.blazebit.persistence.view.impl.metamodel.ManagedViewTypeImplementor 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);
}
}
}
}
use of com.blazebit.persistence.view.impl.metamodel.ManagedViewTypeImplementor 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;
}
Aggregations