extract some methods in AttributeFactory

This commit is contained in:
Gavin King 2024-01-12 14:14:35 +01:00
parent e59e142e40
commit 2b6bef6548
2 changed files with 132 additions and 100 deletions

View File

@ -174,7 +174,8 @@ public class AttributeFactory {
final AttributeMetadata<X, Y> attributeMetadata =
determineAttributeMetadata( wrap( ownerType, property ), identifierMemberResolver );
final SingularAttributeMetadata<X, Y> singularAttributeMetadata = (SingularAttributeMetadata<X, Y>) attributeMetadata;
final SingularAttributeMetadata<X, Y> singularAttributeMetadata =
(SingularAttributeMetadata<X, Y>) attributeMetadata;
final DomainType<Y> domainType = determineSimpleType( singularAttributeMetadata.getValueContext() );
return new SingularAttributeImpl.Identifier<>(
ownerType,
@ -204,7 +205,8 @@ public class AttributeFactory {
final AttributeMetadata<X, Y> attributeMetadata =
determineAttributeMetadata( wrap( ownerType, property ), versionMemberResolver );
final SingularAttributeMetadata<X, Y> singularAttributeMetadata = (SingularAttributeMetadata<X, Y>) attributeMetadata;
final SingularAttributeMetadata<X, Y> singularAttributeMetadata =
(SingularAttributeMetadata<X, Y>) attributeMetadata;
final DomainType<Y> domainType = determineSimpleType( singularAttributeMetadata.getValueContext() );
return new SingularAttributeImpl.Version<>(
ownerType,
@ -298,23 +300,21 @@ public class AttributeFactory {
// Due to the use of generics, it can happen that a mapped super class uses a type
// for an attribute that is not a managed type. Since this case is not specifically mentioned
// in the Jakarta Persistence spec, we handle this by returning a "dummy" entity type
final JavaType<Y> domainJavaType = context.getJavaTypeRegistry().resolveDescriptor(
typeContext.getJpaBindableType()
);
return new EntityTypeImpl<>(domainJavaType, context.getJpaMetamodel());
final JavaType<Y> domainJavaType =
context.getJavaTypeRegistry().resolveDescriptor( typeContext.getJpaBindableType() );
return new EntityTypeImpl<>( domainJavaType, context.getJpaMetamodel() );
}
else {
return domainType;
}
return domainType;
}
assert type instanceof AnyType;
final AnyType anyType = (AnyType) type;
final JavaType<Y> baseJtd = context.getTypeConfiguration()
.getJavaTypeRegistry()
.resolveDescriptor( anyType.getReturnedClass() );
return new AnyMappingDomainTypeImpl<>(
(Any) typeContext.getHibernateValue(),
anyType,
baseJtd,
context.getTypeConfiguration().getJavaTypeRegistry().resolveDescriptor( anyType.getReturnedClass() ),
context.getRuntimeModelCreationContext().getSessionFactory().getMappingMetamodel()
);
}
@ -328,7 +328,7 @@ public class AttributeFactory {
}
else {
@SuppressWarnings("unchecked")
DomainType<Y> type = (DomainType<Y>) typeContext.getHibernateValue().getType();
final DomainType<Y> type = (DomainType<Y>) typeContext.getHibernateValue().getType();
return type;
}
}
@ -363,7 +363,8 @@ public class AttributeFactory {
return metadataContext.getMetamodel().getEntityDescriptor( ownerType.getTypeName() );
}
else if ( persistenceType == Type.PersistenceType.MAPPED_SUPERCLASS ) {
PersistentClass persistentClass = metadataContext.getPersistentClassHostingProperties( (MappedSuperclassTypeImpl<?>) ownerType );
final PersistentClass persistentClass =
metadataContext.getPersistentClassHostingProperties( (MappedSuperclassTypeImpl<?>) ownerType );
return metadataContext.getMetamodel().findEntityDescriptor( persistentClass.getClassName() );
}
else {
@ -432,69 +433,20 @@ public class AttributeFactory {
final org.hibernate.type.Type elementType = elementValue.getType();
final boolean isManyToMany = isManyToMany( member );
// First, determine the type of the elements and use that to help determine the
// collection type
final AttributeClassification elementClassification;
final AttributeClassification attributeClassification;
if ( elementType.isAnyType() ) {
attributeClassification = AttributeClassification.ELEMENT_COLLECTION;
elementClassification = AttributeClassification.ANY;
}
else if ( elementValue instanceof Component ) {
elementClassification = AttributeClassification.EMBEDDED;
attributeClassification = AttributeClassification.ELEMENT_COLLECTION;
}
else if ( elementType.isAssociationType() ) {
elementClassification = isManyToMany ?
AttributeClassification.MANY_TO_MANY :
AttributeClassification.ONE_TO_MANY;
attributeClassification = elementClassification;
}
else {
elementClassification = AttributeClassification.BASIC;
attributeClassification = AttributeClassification.ELEMENT_COLLECTION;
}
final AttributeClassification indexClassification;
// Finally, we determine the type of the map key (if needed)
if ( value instanceof Map ) {
final Value keyValue = ( (Map) value ).getIndex();
final org.hibernate.type.Type keyType = keyValue.getType();
if ( keyType.isAnyType() ) {
indexClassification = AttributeClassification.ANY;
}
else if ( keyValue instanceof Component ) {
indexClassification = AttributeClassification.EMBEDDED;
}
else if ( keyType.isAssociationType() ) {
indexClassification = AttributeClassification.MANY_TO_ONE;
}
else {
indexClassification = AttributeClassification.BASIC;
}
}
else if ( value instanceof List ) {
indexClassification = AttributeClassification.BASIC;
}
else {
indexClassification = null;
}
return new PluralAttributeMetadataImpl<>(
propertyMapping,
attributeContext.getOwnerType(),
member,
attributeClassification,
elementClassification,
indexClassification,
collectionClassification( elementType, elementValue, isManyToMany ),
elementClassification( elementType, elementValue, isManyToMany ),
indexClassification( value ),
context
);
}
else if ( value instanceof OneToMany ) {
// TODO : is this even possible??? Really OneToMany should be describing the
// element value within a o.h.mapping.Collection (see logic branch above)
throw new IllegalArgumentException( "HUH???" );
// TODO : is this even possible? Really OneToMany should be describing the
// element value within a o.h.mapping.Collection (see logic branch above)
throw new AssertionFailure( "Unexpected OneToMany" );
// final boolean isManyToMany = isManyToMany( member );
// //one to many with FK => entity
// return new PluralAttributeMetadataImpl(
@ -534,6 +486,71 @@ public class AttributeFactory {
throw new UnsupportedMappingException( "oops, we are missing something: " + propertyMapping );
}
private static AttributeClassification indexClassification(Value value) {
if ( value instanceof Map ) {
final Value keyValue = ( (Map) value).getIndex();
return keyClassification( keyValue.getType(), keyValue );
}
else if ( value instanceof List ) {
return AttributeClassification.BASIC;
}
else {
return null;
}
}
private static AttributeClassification elementClassification(
org.hibernate.type.Type elementType, Value elementValue, boolean isManyToMany) {
final AttributeClassification elementClassification;
if ( elementType.isAnyType() ) {
return AttributeClassification.ANY;
}
else if ( elementValue instanceof Component ) {
return AttributeClassification.EMBEDDED;
}
else if ( elementType.isAssociationType() ) {
return isManyToMany ?
AttributeClassification.MANY_TO_MANY :
AttributeClassification.ONE_TO_MANY;
}
else {
return AttributeClassification.BASIC;
}
}
private static AttributeClassification collectionClassification(
org.hibernate.type.Type elementType, Value elementValue, boolean isManyToMany) {
if ( elementType.isAnyType() ) {
return AttributeClassification.ELEMENT_COLLECTION;
}
else if ( elementValue instanceof Component ) {
return AttributeClassification.ELEMENT_COLLECTION;
}
else if ( elementType.isAssociationType() ) {
return isManyToMany ?
AttributeClassification.MANY_TO_MANY :
AttributeClassification.ONE_TO_MANY;
}
else {
return AttributeClassification.ELEMENT_COLLECTION;
}
}
private static AttributeClassification keyClassification(org.hibernate.type.Type keyType, Value keyValue) {
if ( keyType.isAnyType() ) {
return AttributeClassification.ANY;
}
else if ( keyValue instanceof Component ) {
return AttributeClassification.EMBEDDED;
}
else if ( keyType.isAssociationType() ) {
return AttributeClassification.MANY_TO_ONE;
}
else {
return AttributeClassification.BASIC;
}
}
public static AttributeClassification determineSingularAssociationClassification(Member member) {
if ( member instanceof Field ) {
return ( (Field) member ).getAnnotation( OneToOne.class ) != null
@ -565,7 +582,9 @@ public class AttributeFactory {
if ( type instanceof Class ) {
return null;
}
return (ParameterizedType) type;
else {
return (ParameterizedType) type;
}
}
public static boolean isManyToMany(Member member) {
@ -574,9 +593,10 @@ public class AttributeFactory {
}
else if ( member instanceof Method ) {
return ( (Method) member ).getAnnotation( ManyToMany.class ) != null;
}
return false;
}
else {
return false;
}
}
private static final MemberResolver embeddedMemberResolver = (attributeContext, metadataContext) -> {
@ -586,28 +606,13 @@ public class AttributeFactory {
final CompositeTypeImplementor ownerComponentType = (CompositeTypeImplementor) ownerBootDescriptor.getType();
final EmbeddableValuedModelPart ownerMappingModelDescriptor = ownerComponentType.getMappingModelPart();
final EmbeddableRepresentationStrategy ownerRepStrategy;
if ( ownerMappingModelDescriptor == null ) {
// When an entity uses a type variable, bound by a mapped superclass, for an embedded id,
// we will not create a model part for the component, but we still need the representation strategy here,
// in order to discover the property members to expose on the JPA metamodel
ownerRepStrategy = ownerBootDescriptor.getBuildingContext()
.getBootstrapContext()
.getRepresentationStrategySelector()
.resolveStrategy( ownerBootDescriptor, null, metadataContext.getRuntimeModelCreationContext() );
}
else {
ownerRepStrategy = ownerMappingModelDescriptor
.getEmbeddableTypeDescriptor()
.getRepresentationStrategy();
}
final EmbeddableRepresentationStrategy ownerRepStrategy =
ownerRepresentationStrategy( metadataContext, ownerMappingModelDescriptor, ownerBootDescriptor );
if ( ownerRepStrategy.getMode() == RepresentationMode.MAP ) {
return new MapMember(
attributeContext.getPropertyMapping().getName(),
attributeContext.getPropertyMapping().getType().getReturnedClass()
);
final Property propertyMapping = attributeContext.getPropertyMapping();
return new MapMember( propertyMapping.getName(), propertyMapping.getType().getReturnedClass() );
}
else {
return ownerRepStrategy
@ -617,6 +622,25 @@ public class AttributeFactory {
}
};
private static EmbeddableRepresentationStrategy ownerRepresentationStrategy(
MetadataContext metadataContext, EmbeddableValuedModelPart ownerMappingModelDescriptor, Component ownerBootDescriptor) {
if ( ownerMappingModelDescriptor == null ) {
// When an entity uses a type variable, bound by a mapped superclass, for an embedded id,
// we will not create a model part for the component, but we still need the representation strategy here,
// in order to discover the property members to expose on the JPA metamodel
return ownerBootDescriptor.getBuildingContext()
.getBootstrapContext()
.getRepresentationStrategySelector()
.resolveStrategy(ownerBootDescriptor, null,
metadataContext.getRuntimeModelCreationContext() );
}
else {
return ownerMappingModelDescriptor
.getEmbeddableTypeDescriptor()
.getRepresentationStrategy();
}
}
private static final MemberResolver virtualIdentifierMemberResolver = (attributeContext, metadataContext) -> {
final AbstractIdentifiableType<?> identifiableType = (AbstractIdentifiableType<?>) attributeContext.getOwnerType();
@ -666,7 +690,7 @@ public class AttributeFactory {
return virtualIdentifierMemberResolver.resolveMember( attributeContext, metadataContext );
}
else {
final Getter getter = declaringEntityPersister.getRepresentationStrategy().resolvePropertyAccess( property ).getGetter();
final Getter getter = getter( declaringEntityPersister, property );
return getter instanceof PropertyAccessMapImpl.GetterImpl
? new MapMember( propertyName, property.getType().getReturnedClass() )
: getter.getMember();
@ -678,16 +702,17 @@ public class AttributeFactory {
};
private final MemberResolver identifierMemberResolver = (attributeContext, metadataContext) -> {
final AbstractIdentifiableType<?> identifiableType = (AbstractIdentifiableType<?>) attributeContext.getOwnerType();
final AbstractIdentifiableType<?> identifiableType =
(AbstractIdentifiableType<?>) attributeContext.getOwnerType();
final EntityPersister declaringEntityMapping = getDeclaringEntity( identifiableType, metadataContext );
final EntityIdentifierMapping identifierMapping = declaringEntityMapping.getIdentifierMapping();
final String attributeName = attributeContext.getPropertyMapping().getName();
if ( !attributeName.equals( identifierMapping.getAttributeName() ) ) {
final Property propertyMapping = attributeContext.getPropertyMapping();
if ( !propertyMapping.getName().equals( identifierMapping.getAttributeName() ) ) {
// this *should* indicate processing part of an IdClass...
return virtualIdentifierMemberResolver.resolveMember( attributeContext, metadataContext );
}
final Getter getter = declaringEntityMapping.getRepresentationStrategy().resolvePropertyAccess( attributeContext.getPropertyMapping() ).getGetter();
final Getter getter = getter( declaringEntityMapping, propertyMapping );
if ( getter instanceof PropertyAccessMapImpl.GetterImpl ) {
return new MapMember( identifierMapping.getAttributeName(), identifierMapping.getJavaType().getJavaTypeClass() );
}
@ -697,7 +722,8 @@ public class AttributeFactory {
};
private final MemberResolver versionMemberResolver = (attributeContext, metadataContext) -> {
final AbstractIdentifiableType<?> identifiableType = (AbstractIdentifiableType<?>) attributeContext.getOwnerType();
final AbstractIdentifiableType<?> identifiableType =
(AbstractIdentifiableType<?>) attributeContext.getOwnerType();
final EntityPersister entityPersister = getDeclaringEntity( identifiableType, metadataContext );
final EntityVersionMapping versionMapping = entityPersister.getVersionMapping();
assert entityPersister.isVersioned();
@ -709,7 +735,7 @@ public class AttributeFactory {
throw new IllegalArgumentException( "Given property did not match declared version property" );
}
final Getter getter = entityPersister.getRepresentationStrategy().resolvePropertyAccess( attributeContext.getPropertyMapping() ).getGetter();
final Getter getter = getter( entityPersister, attributeContext.getPropertyMapping() );
if ( getter instanceof PropertyAccessMapImpl.GetterImpl ) {
return new MapMember( versionPropertyName, versionMapping.getJavaType().getJavaTypeClass() );
}
@ -717,4 +743,11 @@ public class AttributeFactory {
return getter.getMember();
}
};
private static Getter getter(EntityPersister declaringEntityMapping, Property propertyMapping) {
return declaringEntityMapping.getRepresentationStrategy()
.resolvePropertyAccess( propertyMapping )
.getGetter();
}
}

View File

@ -16,7 +16,6 @@ import org.hibernate.mapping.Property;
import org.hibernate.metamodel.AttributeClassification;
import org.hibernate.metamodel.CollectionClassification;
import org.hibernate.metamodel.UnsupportedMappingException;
import org.hibernate.metamodel.internal.AttributeFactory;
import org.hibernate.metamodel.internal.MetadataContext;
import org.hibernate.metamodel.internal.PluralAttributeMetadata;
import org.hibernate.metamodel.model.domain.DomainType;
@ -81,7 +80,7 @@ public class PluralAttributeBuilder<D, C, E, K> {
isGeneric,
attributeMetadata.getAttributeClassification(),
attributeMetadata.getCollectionClassification(),
AttributeFactory.determineSimpleType(
determineSimpleType(
attributeMetadata.getElementValueContext(),
metadataContext
),