diff --git a/hibernate-core/src/main/java/org/hibernate/collection/spi/CollectionSemantics.java b/hibernate-core/src/main/java/org/hibernate/collection/spi/CollectionSemantics.java new file mode 100644 index 0000000000..d23d76f1a3 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/collection/spi/CollectionSemantics.java @@ -0,0 +1,48 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later + * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html + */ +package org.hibernate.collection.spi; + +import java.util.Iterator; +import java.util.function.Consumer; + +import org.hibernate.engine.spi.SharedSessionContractImplementor; +import org.hibernate.metamodel.CollectionClassification; +import org.hibernate.persister.collection.CollectionPersister; + +/** + * Describes the semantics of a persistent collection such that Hibernate + * understands how to use it - create one, handle elements, etc. + * + * @apiNote The described collection need not be part of the "Java Collection Framework" + * + * @author Steve Ebersole + * @author Gavin King + */ +public interface CollectionSemantics { + /** + * Get the classification of collections described by this semantic + */ + CollectionClassification getCollectionClassification(); + + C instantiateRaw( + int anticipatedSize, + CollectionPersister collectionDescriptor); + + PersistentCollection instantiateWrapper( + Object key, + CollectionPersister collectionDescriptor, + SharedSessionContractImplementor session); + + PersistentCollection wrap( + Object rawCollection, + CollectionPersister collectionDescriptor, + SharedSessionContractImplementor session); + + Iterator getElementIterator(C rawCollection); + + void visitElements(C rawCollection, Consumer action); +} diff --git a/hibernate-core/src/main/java/org/hibernate/mapping/SimpleValue.java b/hibernate-core/src/main/java/org/hibernate/mapping/SimpleValue.java index 8844440831..7d0b445690 100644 --- a/hibernate-core/src/main/java/org/hibernate/mapping/SimpleValue.java +++ b/hibernate-core/src/main/java/org/hibernate/mapping/SimpleValue.java @@ -51,13 +51,9 @@ import org.hibernate.type.descriptor.JdbcTypeNameMapper; import org.hibernate.type.descriptor.converter.AttributeConverterSqlTypeDescriptorAdapter; import org.hibernate.type.descriptor.converter.AttributeConverterTypeAdapter; import org.hibernate.type.descriptor.java.BasicJavaDescriptor; -import org.hibernate.type.descriptor.java.JavaTypeDescriptor; -import org.hibernate.type.descriptor.spi.JdbcRecommendedSqlTypeMappingContext; -import org.hibernate.type.descriptor.sql.JdbcTypeJavaClassMappings; import org.hibernate.type.descriptor.sql.LobTypeMappings; import org.hibernate.type.descriptor.sql.NationalizedTypeMappings; import org.hibernate.type.descriptor.sql.SqlTypeDescriptor; -import org.hibernate.type.spi.TypeConfiguration; import org.hibernate.usertype.DynamicParameterizedType; /** diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/AttributeClassification.java b/hibernate-core/src/main/java/org/hibernate/metamodel/AttributeClassification.java similarity index 96% rename from hibernate-core/src/main/java/org/hibernate/metamodel/model/AttributeClassification.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/AttributeClassification.java index 50204da375..ee21130b91 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/AttributeClassification.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/AttributeClassification.java @@ -4,7 +4,7 @@ * License: GNU Lesser General Public License (LGPL), version 2.1 or later * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html */ -package org.hibernate.metamodel.model; +package org.hibernate.metamodel; import javax.persistence.metamodel.Attribute.PersistentAttributeType; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/ValueClassification.java b/hibernate-core/src/main/java/org/hibernate/metamodel/ValueClassification.java new file mode 100644 index 0000000000..fd805f475c --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/ValueClassification.java @@ -0,0 +1,17 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later + * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html + */ +package org.hibernate.metamodel; + +/** + * @author Steve Ebersole + */ +public enum ValueClassification { + BASIC, + ANY, + EMBEDDED, + ENTITY +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/AttributeFactory.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/AttributeFactory.java index 4ba82b369d..f4e6b3bdc7 100755 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/AttributeFactory.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/AttributeFactory.java @@ -29,7 +29,7 @@ import org.hibernate.mapping.OneToMany; import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.Property; import org.hibernate.mapping.Value; -import org.hibernate.metamodel.model.AttributeClassification; +import org.hibernate.metamodel.AttributeClassification; import org.hibernate.metamodel.model.domain.AbstractIdentifiableType; import org.hibernate.metamodel.model.domain.EmbeddableDomainType; import org.hibernate.metamodel.model.domain.IdentifiableDomainType; @@ -38,7 +38,6 @@ import org.hibernate.metamodel.model.domain.PersistentAttribute; import org.hibernate.metamodel.model.domain.PluralPersistentAttribute; import org.hibernate.metamodel.model.domain.SimpleDomainType; import org.hibernate.metamodel.model.domain.SingularPersistentAttribute; -import org.hibernate.metamodel.model.domain.internal.BasicTypeImpl; import org.hibernate.metamodel.model.domain.internal.EmbeddableTypeImpl; import org.hibernate.metamodel.model.domain.internal.MapMember; import org.hibernate.metamodel.model.domain.internal.MappedSuperclassTypeImpl; @@ -107,7 +106,8 @@ public class AttributeFactory { attributeMetadata.getMember(), false, false, - property.isOptional() + property.isOptional(), + context.getSessionFactory().getQueryEngine().getCriteriaBuilder() ); } @@ -149,7 +149,8 @@ public class AttributeFactory { property.getName(), determineSimpleType( attributeMetadata.getValueContext() ), attributeMetadata.getMember(), - attributeMetadata.getAttributeClassification() + attributeMetadata.getAttributeClassification(), + context.getSessionFactory().getQueryEngine().getCriteriaBuilder() ); } @@ -179,7 +180,8 @@ public class AttributeFactory { property.getName(), attributeMetadata.getAttributeClassification(), determineSimpleType( attributeMetadata.getValueContext() ), - attributeMetadata.getMember() + attributeMetadata.getMember(), + context.getSessionFactory().getQueryEngine().getCriteriaBuilder() ); } @@ -195,9 +197,8 @@ public class AttributeFactory { attributeMetadata.getOwnerType(), determineSimpleType( attributeMetadata.getElementValueContext() ), javaTypeDescriptor, - java.util.Map.class.isAssignableFrom( attributeMetadata.getJavaType() ) - ? determineSimpleType( attributeMetadata.getMapKeyValueContext() ) - : null + determineListIndexOrMapKeyType( attributeMetadata ), + context.getSessionFactory().getQueryEngine().getCriteriaBuilder() ); return info @@ -207,16 +208,24 @@ public class AttributeFactory { .build(); } + private SimpleDomainType determineListIndexOrMapKeyType(PluralAttributeMetadata attributeMetadata) { + if ( java.util.Map.class.isAssignableFrom( attributeMetadata.getJavaType() ) ) { + return determineSimpleType( attributeMetadata.getMapKeyValueContext() ); + } + + if ( java.util.List.class.isAssignableFrom( attributeMetadata.getJavaType() ) ) { + + } + return java.util.Map.class.isAssignableFrom( attributeMetadata.getJavaType() ) + ? determineSimpleType( attributeMetadata.getMapKeyValueContext() ) + : null; + } + @SuppressWarnings("unchecked") private SimpleDomainType determineSimpleType(ValueContext typeContext) { - final JavaTypeDescriptor javaTypeDescriptor = context.getSessionFactory() - .getMetamodel() - .getTypeConfiguration() - .getJavaTypeDescriptorRegistry() - .getDescriptor( typeContext.getJpaBindableType() ); switch ( typeContext.getValueClassification() ) { case BASIC: { - return new BasicTypeImpl<>( javaTypeDescriptor ); + return context.resolveBasicType( typeContext.getJpaBindableType() ); } case ENTITY: { final org.hibernate.type.EntityType type = (EntityType) typeContext.getHibernateValue().getType(); @@ -237,7 +246,7 @@ public class AttributeFactory { javaType, typeContext.getAttributeMetadata().getOwnerType(), (ComponentType) typeContext.getHibernateValue().getType(), - context.getSessionFactory() + context.getSessionFactory().getQueryEngine().getCriteriaBuilder() ); context.registerEmbeddableType( embeddableType ); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/MetadataContext.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/MetadataContext.java index 8fcfa2020e..0109570ca9 100755 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/MetadataContext.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/MetadataContext.java @@ -33,6 +33,7 @@ import org.hibernate.mapping.MappedSuperclass; import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.Property; import org.hibernate.metamodel.model.domain.AbstractIdentifiableType; +import org.hibernate.metamodel.model.domain.BasicDomainType; import org.hibernate.metamodel.model.domain.EmbeddableDomainType; import org.hibernate.metamodel.model.domain.EntityDomainType; import org.hibernate.metamodel.model.domain.IdentifiableDomainType; @@ -41,8 +42,11 @@ import org.hibernate.metamodel.model.domain.MappedSuperclassDomainType; import org.hibernate.metamodel.model.domain.PersistentAttribute; import org.hibernate.metamodel.model.domain.SingularPersistentAttribute; import org.hibernate.metamodel.model.domain.internal.AttributeContainer; +import org.hibernate.metamodel.model.domain.internal.BasicTypeImpl; import org.hibernate.metamodel.model.domain.internal.EntityTypeImpl; import org.hibernate.metamodel.model.domain.internal.MappedSuperclassTypeImpl; +import org.hibernate.type.descriptor.java.JavaTypeDescriptor; +import org.hibernate.type.descriptor.java.spi.JavaTypeDescriptorRegistry; /** * Defines a context for storing information during the building of the {@link MetamodelImpl}. @@ -143,7 +147,7 @@ class MetadataContext { } /*package*/ void registerEmbeddableType(EmbeddableDomainType embeddableType) { - if ( !( ignoreUnsupported && Map.class.isAssignableFrom( embeddableType.getJavaTypeDescriptor().getJavaType() ) ) ) { + if ( !( ignoreUnsupported && Map.class.isAssignableFrom( embeddableType.getExpressableJavaTypeDescriptor().getJavaType() ) ) ) { embeddables.add( embeddableType ); } } @@ -549,4 +553,19 @@ class MetadataContext { public Set getUnusedMappedSuperclasses() { return new HashSet( knownMappedSuperclasses ); } + + private final Map,BasicDomainType> basicDomainTypeMap = new HashMap<>(); + + public BasicDomainType resolveBasicType(Class javaType) { + return basicDomainTypeMap.computeIfAbsent( + javaType, + jt -> { + final JavaTypeDescriptorRegistry registry = getSessionFactory() + .getMetamodel() + .getTypeConfiguration() + .getJavaTypeDescriptorRegistry(); + return new BasicTypeImpl<>( registry.resolveDescriptor( javaType ) ); + } + ) + } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/AbstractDomainType.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/AbstractDomainType.java index 786eee2646..09f661768d 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/AbstractDomainType.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/AbstractDomainType.java @@ -30,12 +30,12 @@ public abstract class AbstractDomainType implements DomainType { } @Override - public JavaTypeDescriptor getJavaTypeDescriptor() { + public JavaTypeDescriptor getExpressableJavaTypeDescriptor() { return javaTypeDescriptor; } @Override public Class getJavaType() { - return getJavaTypeDescriptor().getJavaType(); + return getExpressableJavaTypeDescriptor().getJavaType(); } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/CollectionDomainType.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/AnyMappingDomainType.java similarity index 59% rename from hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/CollectionDomainType.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/AnyMappingDomainType.java index 8eae1c3f2f..af7440b3f3 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/CollectionDomainType.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/AnyMappingDomainType.java @@ -6,13 +6,12 @@ */ package org.hibernate.metamodel.model.domain; -import org.hibernate.metamodel.CollectionClassification; - /** - * DomainType for a plural attribute + * Models Hibernate's ANY mapping (reverse discrimination) as a JPA domain model type + * + * @param The base Java type defined for the any mapping * * @author Steve Ebersole */ -public interface CollectionDomainType extends DomainType { - CollectionClassification getCollectionClassification(); +public interface AnyMappingDomainType extends SimpleDomainType { } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/DomainType.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/DomainType.java index adaff80f99..6bf64f32ee 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/DomainType.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/DomainType.java @@ -35,7 +35,7 @@ public interface DomainType extends SqmExpressable { */ default String getTypeName() { // default impl to handle the general case returning the Java type name - return getJavaTypeDescriptor().getJavaType().getName(); + return getExpressableJavaTypeDescriptor().getJavaType().getName(); } /** @@ -44,5 +44,5 @@ public interface DomainType extends SqmExpressable { * * @see #getTypeName */ - JavaTypeDescriptor getJavaTypeDescriptor(); + JavaTypeDescriptor getExpressableJavaTypeDescriptor(); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/ListPersistentAttribute.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/ListPersistentAttribute.java index 1af7051b30..4e5cc2c220 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/ListPersistentAttribute.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/ListPersistentAttribute.java @@ -9,10 +9,13 @@ package org.hibernate.metamodel.model.domain; import java.util.List; import javax.persistence.metamodel.ListAttribute; +import org.hibernate.query.sqm.SqmPathSource; + /** * Hibernate extension to the JPA {@link ListAttribute} descriptor * * @author Steve Ebersole */ public interface ListPersistentAttribute extends ListAttribute, PluralPersistentAttribute,E> { + SqmPathSource getIndexPathSource(); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/ManagedDomainType.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/ManagedDomainType.java index f1dd3303d2..ee146f13c9 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/ManagedDomainType.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/ManagedDomainType.java @@ -6,6 +6,7 @@ */ package org.hibernate.metamodel.model.domain; +import java.util.function.Consumer; import javax.persistence.metamodel.ManagedType; import org.hibernate.graph.spi.SubGraphImplementor; @@ -39,6 +40,9 @@ public interface ManagedDomainType extends SimpleDomainType, ManagedType> action); + void visitDeclaredAttributes(Consumer> action); + @Override PersistentAttribute getAttribute(String name); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/MapPersistentAttribute.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/MapPersistentAttribute.java index 97a234d7f5..d1cfafa972 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/MapPersistentAttribute.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/MapPersistentAttribute.java @@ -9,12 +9,16 @@ package org.hibernate.metamodel.model.domain; import java.util.Map; import javax.persistence.metamodel.MapAttribute; +import org.hibernate.query.sqm.SqmPathSource; + /** * Hibernate extension to the JPA {@link MapAttribute} descriptor * * @author Steve Ebersole */ public interface MapPersistentAttribute extends MapAttribute, PluralPersistentAttribute,V> { + SqmPathSource getKeyPathSource(); + @Override SimpleDomainType getKeyType(); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/PersistentAttribute.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/PersistentAttribute.java index 8605437301..0dca52b856 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/PersistentAttribute.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/PersistentAttribute.java @@ -8,25 +8,25 @@ package org.hibernate.metamodel.model.domain; import javax.persistence.metamodel.Attribute; -import org.hibernate.metamodel.model.AttributeClassification; -import org.hibernate.query.sqm.SqmPathSource; +import org.hibernate.metamodel.AttributeClassification; +import org.hibernate.type.descriptor.java.JavaTypeDescriptor; /** * Hibernate extension to the JPA {@link Attribute} contract * * @author Steve Ebersole */ -public interface PersistentAttribute extends Attribute, SqmPathSource { +public interface PersistentAttribute extends Attribute { @Override ManagedDomainType getDeclaringType(); + JavaTypeDescriptor getAttributeJavaTypeDescriptor(); + /** * The classification of the attribute (is it a basic type, entity, etc) */ AttributeClassification getAttributeClassification(); - DomainType getType(); - SimpleDomainType getValueGraphType(); SimpleDomainType getKeyGraphType(); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/PluralPersistentAttribute.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/PluralPersistentAttribute.java index aac9e1b079..50436d68b7 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/PluralPersistentAttribute.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/PluralPersistentAttribute.java @@ -8,6 +8,10 @@ package org.hibernate.metamodel.model.domain; import javax.persistence.metamodel.PluralAttribute; +import org.hibernate.metamodel.CollectionClassification; +import org.hibernate.query.sqm.SqmJoinable; +import org.hibernate.query.sqm.SqmPathSource; + /** * Hibernate extension to the JPA {@link PluralAttribute} descriptor * @@ -16,12 +20,14 @@ import javax.persistence.metamodel.PluralAttribute; * * @author Steve Ebersole */ -public interface PluralPersistentAttribute extends PluralAttribute, PersistentAttribute { +public interface PluralPersistentAttribute + extends PersistentAttribute, SqmPathSource, SqmJoinable, PluralAttribute { @Override ManagedDomainType getDeclaringType(); - @Override - CollectionDomainType getType(); + CollectionClassification getCollectionClassification(); + + SqmPathSource getElementPathSource(); @Override SimpleDomainType getElementType(); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/SingularPersistentAttribute.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/SingularPersistentAttribute.java index 1c33c5ec64..ce8f719577 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/SingularPersistentAttribute.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/SingularPersistentAttribute.java @@ -8,12 +8,16 @@ package org.hibernate.metamodel.model.domain; import javax.persistence.metamodel.SingularAttribute; +import org.hibernate.query.sqm.SqmJoinable; +import org.hibernate.query.sqm.SqmPathSource; + /** * Hibernate extension to the JPA {@link SingularAttribute} descriptor * * @author Steve Ebersole */ -public interface SingularPersistentAttribute extends SingularAttribute, PersistentAttribute { +public interface SingularPersistentAttribute + extends SingularAttribute, PersistentAttribute, SqmPathSource, SqmJoinable { @Override SimpleDomainType getType(); @@ -21,7 +25,7 @@ public interface SingularPersistentAttribute extends SingularAttribute ManagedDomainType getDeclaringType(); @Override - SimpleDomainType getSqmNodeType(); + SimpleDomainType getSqmPathType(); /** * For a singular attribute, the value type is defined as the diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/AbstractAttribute.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/AbstractAttribute.java index aac86a3b43..a98b755b2f 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/AbstractAttribute.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/AbstractAttribute.java @@ -15,7 +15,7 @@ import java.lang.reflect.Method; import javax.persistence.metamodel.Attribute; import org.hibernate.internal.util.ReflectHelper; -import org.hibernate.metamodel.model.AttributeClassification; +import org.hibernate.metamodel.AttributeClassification; import org.hibernate.metamodel.model.domain.ManagedDomainType; import org.hibernate.metamodel.model.domain.PersistentAttribute; import org.hibernate.metamodel.model.domain.SimpleDomainType; @@ -29,8 +29,7 @@ import org.hibernate.type.descriptor.java.JavaTypeDescriptor; * * @author Steve Ebersole */ -public abstract class AbstractAttribute - implements PersistentAttribute, Serializable { +public abstract class AbstractAttribute implements PersistentAttribute, Serializable { private final ManagedDomainType declaringType; private final String name; private final JavaTypeDescriptor attributeType; @@ -72,13 +71,12 @@ public abstract class AbstractAttribute return attributeType.getJavaType(); } - @Override - public SimpleDomainType getSqmNodeType() { + public SimpleDomainType getSqmPathType() { return valueType; } @Override - public JavaTypeDescriptor getJavaTypeDescriptor() { + public JavaTypeDescriptor getAttributeJavaTypeDescriptor() { return attributeType; } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/AbstractPluralAttribute.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/AbstractPluralAttribute.java index 18753f45e8..365862e704 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/AbstractPluralAttribute.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/AbstractPluralAttribute.java @@ -10,10 +10,17 @@ import java.io.Serializable; import java.util.Collection; import org.hibernate.metamodel.CollectionClassification; +import org.hibernate.metamodel.ValueClassification; import org.hibernate.metamodel.model.domain.AbstractManagedType; -import org.hibernate.metamodel.model.domain.CollectionDomainType; +import org.hibernate.metamodel.model.domain.AnyMappingDomainType; +import org.hibernate.metamodel.model.domain.BasicDomainType; +import org.hibernate.metamodel.model.domain.EmbeddableDomainType; +import org.hibernate.metamodel.model.domain.EntityDomainType; import org.hibernate.metamodel.model.domain.PluralPersistentAttribute; import org.hibernate.metamodel.model.domain.SimpleDomainType; +import org.hibernate.query.NavigablePath; +import org.hibernate.query.sqm.NodeBuilder; +import org.hibernate.query.sqm.SqmPathSource; import org.hibernate.query.sqm.produce.spi.SqmCreationState; import org.hibernate.query.sqm.tree.domain.SqmPath; import org.hibernate.query.sqm.tree.domain.SqmPluralValuedSimplePath; @@ -29,18 +36,21 @@ import org.hibernate.type.descriptor.java.JavaTypeDescriptor; */ public abstract class AbstractPluralAttribute extends AbstractAttribute - implements PluralPersistentAttribute, CollectionDomainType, Serializable { + implements PluralPersistentAttribute, Serializable { public static PluralAttributeBuilder create( AbstractManagedType ownerType, SimpleDomainType attrType, JavaTypeDescriptor collectionClass, - SimpleDomainType keyType) { - return new PluralAttributeBuilder<>( ownerType, attrType, collectionClass, keyType ); + SimpleDomainType keyType, + NodeBuilder nodeBuilder) { + return new PluralAttributeBuilder<>( ownerType, attrType, collectionClass, keyType, nodeBuilder ); } private final CollectionClassification classification; + private final SqmPathSource elementPathSource; + @SuppressWarnings("WeakerAccess") protected AbstractPluralAttribute(PluralAttributeBuilder builder) { super( builder.getDeclaringType(), @@ -52,6 +62,36 @@ public abstract class AbstractPluralAttribute ); this.classification = builder.getCollectionClassification(); + + this.elementPathSource = DomainModelHelper.resolveSqmPathSource( + interpretValueClassification( builder.getValueType() ), + getName(), + builder.getValueType(), + BindableType.PLURAL_ATTRIBUTE, + builder.getNodeBuilder() + ); + } + + private ValueClassification interpretValueClassification(SimpleDomainType valueType) { + if ( valueType instanceof BasicDomainType ) { + return ValueClassification.BASIC; + } + + if ( valueType instanceof AnyMappingDomainType ) { + return ValueClassification.ANY; + } + + if ( valueType instanceof EmbeddableDomainType ) { + return ValueClassification.EMBEDDED; + } + + if ( valueType instanceof EntityDomainType ) { + return ValueClassification.ENTITY; + } + + throw new IllegalArgumentException( + "Unrecognized value type Java-type [" + valueType.getTypeName() + "] for plural attribute value" + ); } @Override @@ -59,21 +99,24 @@ public abstract class AbstractPluralAttribute return classification; } + @Override + public SqmPathSource getElementPathSource() { + return elementPathSource; + } + + @Override + public SqmPathSource findSubPathSource(String name) { + return elementPathSource.findSubPathSource( name ); + } + @Override public CollectionType getCollectionType() { return getCollectionClassification().toJpaClassification(); } @Override - public CollectionDomainType getType() { - return this; - } - - @Override - public String getTypeName() { - // todo (6.0) : this should return the "role" - // - for now just return the name of the collection type - return getCollectionType().name(); + public JavaTypeDescriptor getExpressableJavaTypeDescriptor() { + return getElementType().getExpressableJavaTypeDescriptor(); } @Override @@ -114,12 +157,14 @@ public abstract class AbstractPluralAttribute } @Override - public Class getJavaType() { - return getJavaTypeDescriptor().getJavaType(); - } - - @Override - public SqmPath createSqmPath(SqmPath lhs, SqmCreationState creationState) { - return new SqmPluralValuedSimplePath( ); + public SqmPath createSqmPath(SqmPath lhs, SqmCreationState creationState) { + final NavigablePath navigablePath = lhs.getNavigablePath().append( getPathName() ); + //noinspection unchecked + return new SqmPluralValuedSimplePath( + navigablePath, + this, + lhs, + creationState.getCreationContext().getNodeBuilder() + ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/AbstractSqmPathSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/AbstractSqmPathSource.java new file mode 100644 index 0000000000..5c36df24ef --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/AbstractSqmPathSource.java @@ -0,0 +1,62 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later + * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html + */ +package org.hibernate.metamodel.model.domain.internal; + +import org.hibernate.metamodel.model.domain.DomainType; +import org.hibernate.query.sqm.NodeBuilder; +import org.hibernate.query.sqm.SqmPathSource; +import org.hibernate.type.descriptor.java.JavaTypeDescriptor; + +/** + * @author Steve Ebersole + */ +public abstract class AbstractSqmPathSource implements SqmPathSource { + private final String localPathName; + private final DomainType domainType; + private final BindableType jpaBindableType; + private final NodeBuilder nodeBuilder; + + public AbstractSqmPathSource( + String localPathName, + DomainType domainType, + BindableType jpaBindableType, + NodeBuilder nodeBuilder) { + this.localPathName = localPathName; + this.domainType = domainType; + this.jpaBindableType = jpaBindableType; + this.nodeBuilder = nodeBuilder; + } + + protected NodeBuilder getNodeBuilder() { + return nodeBuilder; + } + + @Override + public String getPathName() { + return localPathName; + } + + @Override + public DomainType getSqmPathType() { + return domainType; + } + + @Override + public BindableType getBindableType() { + return jpaBindableType; + } + + @Override + public JavaTypeDescriptor getExpressableJavaTypeDescriptor() { + return domainType.getExpressableJavaTypeDescriptor(); + } + + @Override + public Class getBindableJavaType() { + return getExpressableJavaTypeDescriptor().getJavaType(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/AbstractType.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/AbstractType.java deleted file mode 100755 index a83f69106b..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/AbstractType.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * License: GNU Lesser General Public License (LGPL), version 2.1 or later - * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html - */ -package org.hibernate.metamodel.model.domain.internal; - -import java.io.Serializable; -import javax.persistence.metamodel.Type; - -import org.hibernate.metamodel.model.domain.spi.DomainTypeDescriptor; -import org.hibernate.type.descriptor.java.JavaTypeDescriptor; - -/** - * Defines commonality for the JPA {@link Type} hierarchy of interfaces. - * - * @author Steve Ebersole - * @author Brad Koehn - */ -public abstract class AbstractType implements DomainTypeDescriptor, Serializable { - private final JavaTypeDescriptor javaTypeDescriptor; - private final String typeName; - - /** - * Instantiates the type based on the given Java type. - */ - protected AbstractType(JavaTypeDescriptor javaTypeDescriptor) { - this( - javaTypeDescriptor, - javaTypeDescriptor.getJavaType() != null - ? javaTypeDescriptor.getJavaType().getName() - : null - ); - } - - /** - * Instantiates the type based on the given Java type. - */ - protected AbstractType(JavaTypeDescriptor javaTypeDescriptor, String typeName) { - this.javaTypeDescriptor = javaTypeDescriptor; - this.typeName = typeName == null ? "unknown" : typeName; - } - - @Override - public JavaTypeDescriptor getJavaTypeDescriptor() { - return javaTypeDescriptor; - } - - /** - * {@inheritDoc} - * - * @implNote The Hibernate impl may return {@code null} here in the case of either - * dynamic models or entity classes mapped multiple times using entity-name. In - * these cases, the {@link #getTypeName()} value should be used. - */ - @Override - public Class getJavaType() { - return javaTypeDescriptor.getJavaType(); - } - - /** - * Obtains the type name. See notes on {@link #getJavaType()} for details - * - * @return The type name - */ - public String getTypeName() { - return typeName; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/AnyMappingSqmPathSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/AnyMappingSqmPathSource.java new file mode 100644 index 0000000000..2038c6a1cb --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/AnyMappingSqmPathSource.java @@ -0,0 +1,44 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later + * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html + */ +package org.hibernate.metamodel.model.domain.internal; + +import org.hibernate.NotYetImplementedFor6Exception; +import org.hibernate.metamodel.model.domain.AnyMappingDomainType; +import org.hibernate.query.sqm.NodeBuilder; +import org.hibernate.query.sqm.SqmPathSource; +import org.hibernate.query.sqm.produce.spi.SqmCreationState; +import org.hibernate.query.sqm.tree.domain.SqmPath; + +/** + * @author Steve Ebersole + */ +public class AnyMappingSqmPathSource extends AbstractSqmPathSource { + @SuppressWarnings("WeakerAccess") + public AnyMappingSqmPathSource( + String localPathName, + AnyMappingDomainType domainType, + BindableType jpaBindableType, + NodeBuilder nodeBuilder) { + super( localPathName, domainType, jpaBindableType, nodeBuilder ); + } + + @Override + public AnyMappingDomainType getSqmPathType() { + //noinspection unchecked + return (AnyMappingDomainType) super.getSqmPathType(); + } + + @Override + public SqmPathSource findSubPathSource(String name) { + throw new NotYetImplementedFor6Exception(); + } + + @Override + public SqmPath createSqmPath(SqmPath lhs, SqmCreationState creationState) { + throw new NotYetImplementedFor6Exception(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/AttributeContainer.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/AttributeContainer.java index a563742550..8813d0582a 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/AttributeContainer.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/AttributeContainer.java @@ -21,7 +21,7 @@ public interface AttributeContainer { * Used during creation of the type */ interface InFlightAccess { - void addAttribute(PersistentAttribute attribute); + void addAttribute(PersistentAttribute attribute); default void applyIdAttribute(SingularPersistentAttribute idAttribute) { throw new UnsupportedOperationException( diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/BagAttributeImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/BagAttributeImpl.java index ceaab57a91..4221f23a2d 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/BagAttributeImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/BagAttributeImpl.java @@ -34,13 +34,4 @@ class BagAttributeImpl public SqmPathSource findSubPathSource(String name) { throw new NotYetImplementedFor6Exception(); } - - @Override - public SemanticPathPart resolvePathPart( - String name, - String currentContextKey, - boolean isTerminal, - SqmCreationState creationState) { - throw new NotYetImplementedFor6Exception(); - } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/BasicSqmPathSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/BasicSqmPathSource.java new file mode 100644 index 0000000000..a556f38f51 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/BasicSqmPathSource.java @@ -0,0 +1,51 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later + * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html + */ +package org.hibernate.metamodel.model.domain.internal; + +import org.hibernate.metamodel.model.domain.BasicDomainType; +import org.hibernate.query.NavigablePath; +import org.hibernate.query.sqm.NodeBuilder; +import org.hibernate.query.sqm.SqmPathSource; +import org.hibernate.query.sqm.produce.spi.SqmCreationState; +import org.hibernate.query.sqm.tree.domain.SqmBasicValuedSimplePath; +import org.hibernate.query.sqm.tree.domain.SqmPath; + +/** + * @author Steve Ebersole + */ +public class BasicSqmPathSource extends AbstractSqmPathSource { + @SuppressWarnings("WeakerAccess") + public BasicSqmPathSource( + String localPathName, + BasicDomainType domainType, + BindableType jpaBindableType, + NodeBuilder nodeBuilder) { + super( localPathName, domainType, jpaBindableType, nodeBuilder ); + } + + @Override + public BasicDomainType getSqmPathType() { + //noinspection unchecked + return (BasicDomainType) super.getSqmPathType(); + } + + @Override + public SqmPathSource findSubPathSource(String name) { + throw new IllegalArgumentException( "Basic paths cannot be dereferenced" ); + } + + @Override + public SqmPath createSqmPath(SqmPath lhs, SqmCreationState creationState) { + final NavigablePath navigablePath = lhs.getNavigablePath().append( getPathName() ); + return new SqmBasicValuedSimplePath<>( + navigablePath, + this, + lhs, + getNodeBuilder() + ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/BasicTypeImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/BasicTypeImpl.java index f52a324972..d58d93170b 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/BasicTypeImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/BasicTypeImpl.java @@ -26,11 +26,11 @@ public class BasicTypeImpl implements BasicDomainType, Serializable { } @Override - public JavaTypeDescriptor getJavaTypeDescriptor() { + public JavaTypeDescriptor getExpressableJavaTypeDescriptor() { return javaTypeDescriptor; } public Class getJavaType() { - return getJavaTypeDescriptor().getJavaType(); + return getExpressableJavaTypeDescriptor().getJavaType(); } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/DomainModelHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/DomainModelHelper.java index ba07fb51b0..b00ac70e97 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/DomainModelHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/DomainModelHelper.java @@ -6,13 +6,21 @@ */ package org.hibernate.metamodel.model.domain.internal; +import javax.persistence.metamodel.Bindable; + import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.metamodel.ValueClassification; +import org.hibernate.metamodel.model.domain.AnyMappingDomainType; +import org.hibernate.metamodel.model.domain.BasicDomainType; +import org.hibernate.metamodel.model.domain.DomainType; import org.hibernate.metamodel.model.domain.EmbeddableDomainType; import org.hibernate.metamodel.model.domain.EntityDomainType; import org.hibernate.metamodel.model.domain.ManagedDomainType; import org.hibernate.metamodel.spi.MetamodelImplementor; import org.hibernate.persister.entity.EntityPersister; +import org.hibernate.query.sqm.NodeBuilder; +import org.hibernate.query.sqm.SqmPathSource; /** * Helper containing utilities useful for domain model handling @@ -79,4 +87,48 @@ public class DomainModelHelper { return sessionFactory.getMetamodel().entityPersister( hibernateEntityName ); } + public static SqmPathSource resolveSqmPathSource( + ValueClassification classification, + String name, + DomainType valueDomainType, + Bindable.BindableType jpaBindableType, + NodeBuilder nodeBuilder) { + switch ( classification ) { + case BASIC: { + return new BasicSqmPathSource<>( + name, + (BasicDomainType) valueDomainType, + jpaBindableType, + nodeBuilder + ); + } + case ANY: { + return new AnyMappingSqmPathSource<>( + name, + (AnyMappingDomainType) valueDomainType, + jpaBindableType, + nodeBuilder + ); + } + case EMBEDDED: { + return new EmbeddedSqmPathSource<>( + name, + (EmbeddableDomainType) valueDomainType, + jpaBindableType, + nodeBuilder + ); + } + case ENTITY: { + return new EntitySqmPathSource<>( + name, + (EntityDomainType) valueDomainType, + jpaBindableType, + nodeBuilder + ); + } + default: { + throw new IllegalArgumentException( "Unrecognized ValueClassification : " + classification ); + } + } + } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/EmbeddedSqmPathSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/EmbeddedSqmPathSource.java new file mode 100644 index 0000000000..ee0703720d --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/EmbeddedSqmPathSource.java @@ -0,0 +1,53 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later + * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html + */ +package org.hibernate.metamodel.model.domain.internal; + +import org.hibernate.metamodel.model.domain.DomainType; +import org.hibernate.metamodel.model.domain.EmbeddableDomainType; +import org.hibernate.query.NavigablePath; +import org.hibernate.query.sqm.NodeBuilder; +import org.hibernate.query.sqm.SqmPathSource; +import org.hibernate.query.sqm.produce.spi.SqmCreationState; +import org.hibernate.query.sqm.tree.SqmJoinType; +import org.hibernate.query.sqm.tree.domain.SqmAnyValuedSimplePath; +import org.hibernate.query.sqm.tree.domain.SqmPath; +import org.hibernate.query.sqm.tree.from.SqmAttributeJoin; +import org.hibernate.query.sqm.tree.from.SqmFrom; + +/** + * @author Steve Ebersole + */ +public class EmbeddedSqmPathSource extends AbstractSqmPathSource { + public EmbeddedSqmPathSource( + String localPathName, + EmbeddableDomainType domainType, + BindableType jpaBindableType, + NodeBuilder nodeBuilder) { + super( localPathName, domainType, jpaBindableType, nodeBuilder ); + } + + @Override + public EmbeddableDomainType getSqmPathType() { + //noinspection unchecked + return (EmbeddableDomainType) super.getSqmPathType(); + } + + @Override + public SqmPathSource findSubPathSource(String name) { + return (SqmPathSource) getSqmPathType().findAttribute( name ); + } + + @Override + public SqmPath createSqmPath(SqmPath lhs, SqmCreationState creationState) { + return new SqmAnyValuedSimplePath<>( + lhs.getNavigablePath().append( getPathName() ), + this, + lhs, + getNodeBuilder() + ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/EntitySqmPathSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/EntitySqmPathSource.java new file mode 100644 index 0000000000..9a6862134c --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/EntitySqmPathSource.java @@ -0,0 +1,48 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later + * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html + */ +package org.hibernate.metamodel.model.domain.internal; + +import org.hibernate.metamodel.model.domain.EntityDomainType; +import org.hibernate.query.sqm.NodeBuilder; +import org.hibernate.query.sqm.SqmPathSource; +import org.hibernate.query.sqm.produce.spi.SqmCreationState; +import org.hibernate.query.sqm.tree.domain.SqmEntityValuedSimplePath; +import org.hibernate.query.sqm.tree.domain.SqmPath; + +/** + * @author Steve Ebersole + */ +public class EntitySqmPathSource extends AbstractSqmPathSource { + public EntitySqmPathSource( + String localPathName, + EntityDomainType domainType, + BindableType jpaBindableType, + NodeBuilder nodeBuilder) { + super( localPathName, domainType, jpaBindableType, nodeBuilder ); + } + + @Override + public EntityDomainType getSqmPathType() { + //noinspection unchecked + return (EntityDomainType) super.getSqmPathType(); + } + + @Override + public SqmPathSource findSubPathSource(String name) { + return (SqmPathSource) getSqmPathType().findAttribute( name ); + } + + @Override + public SqmPath createSqmPath(SqmPath lhs, SqmCreationState creationState) { + return new SqmEntityValuedSimplePath<>( + lhs.getNavigablePath().append( getPathName() ), + this, + lhs, + getNodeBuilder() + ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/EntityTypeImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/EntityTypeImpl.java index 65413b9d96..d16f75ac2a 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/EntityTypeImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/EntityTypeImpl.java @@ -68,7 +68,7 @@ public class EntityTypeImpl } @Override - public DomainType getSqmNodeType() { + public DomainType getSqmPathType() { return this; } @@ -97,7 +97,7 @@ public class EntityTypeImpl } @Override - public JavaTypeDescriptor getJavaTypeDescriptor() { + public JavaTypeDescriptor getExpressableJavaTypeDescriptor() { return null; } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/ListAttributeImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/ListAttributeImpl.java index 8056cb5a57..6ca0766507 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/ListAttributeImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/ListAttributeImpl.java @@ -9,17 +9,45 @@ package org.hibernate.metamodel.model.domain.internal; import java.util.List; import org.hibernate.metamodel.model.domain.ListPersistentAttribute; +import org.hibernate.query.sqm.SqmPathSource; +import org.hibernate.query.sqm.produce.spi.SqmCreationState; +import org.hibernate.query.sqm.tree.SqmJoinType; +import org.hibernate.query.sqm.tree.domain.SqmListJoin; +import org.hibernate.query.sqm.tree.from.SqmAttributeJoin; +import org.hibernate.query.sqm.tree.from.SqmFrom; /** * @author Steve Ebersole */ class ListAttributeImpl extends AbstractPluralAttribute, E> implements ListPersistentAttribute { + private final SqmPathSource indexPathSource; + ListAttributeImpl(PluralAttributeBuilder, E, ?> xceBuilder) { super( xceBuilder ); + + indexPathSource = } @Override public CollectionType getCollectionType() { return CollectionType.LIST; } + + @Override + public SqmAttributeJoin createSqmJoin( + SqmFrom lhs, + SqmJoinType joinType, + String alias, + boolean fetched, + SqmCreationState creationState) { + //noinspection unchecked + return new SqmListJoin( + lhs, + this, + alias, + joinType, + fetched, + creationState.getCreationContext().getNodeBuilder() + ); + } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/PluralAttributeBuilder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/PluralAttributeBuilder.java index 0e5eda1e2e..58bc76d092 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/PluralAttributeBuilder.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/PluralAttributeBuilder.java @@ -14,9 +14,10 @@ import java.util.Set; import org.hibernate.mapping.Property; import org.hibernate.metamodel.CollectionClassification; -import org.hibernate.metamodel.model.AttributeClassification; +import org.hibernate.metamodel.AttributeClassification; import org.hibernate.metamodel.model.domain.ManagedDomainType; import org.hibernate.metamodel.model.domain.SimpleDomainType; +import org.hibernate.query.sqm.NodeBuilder; import org.hibernate.type.descriptor.java.JavaTypeDescriptor; /** @@ -26,6 +27,8 @@ public class PluralAttributeBuilder { private final ManagedDomainType declaringType; private final SimpleDomainType valueType; + private final NodeBuilder nodeBuilder; + private SimpleDomainType keyType; private AttributeClassification attributeClassification; @@ -39,11 +42,17 @@ public class PluralAttributeBuilder { ManagedDomainType ownerType, SimpleDomainType elementType, JavaTypeDescriptor collectionJavaTypeDescriptor, - SimpleDomainType keyType) { + SimpleDomainType keyType, + NodeBuilder nodeBuilder) { this.declaringType = ownerType; this.valueType = elementType; this.collectionJavaTypeDescriptor = collectionJavaTypeDescriptor; this.keyType = keyType; + this.nodeBuilder = nodeBuilder; + } + + public NodeBuilder getNodeBuilder() { + return nodeBuilder; } public ManagedDomainType getDeclaringType() { diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/SingularAttributeImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/SingularAttributeImpl.java index 48b87b058b..3d6751e162 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/SingularAttributeImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/SingularAttributeImpl.java @@ -8,23 +8,23 @@ package org.hibernate.metamodel.model.domain.internal; import java.io.Serializable; import java.lang.reflect.Member; -import java.util.Locale; import java.util.function.Supplier; import org.hibernate.graph.spi.GraphHelper; -import org.hibernate.metamodel.model.AttributeClassification; +import org.hibernate.metamodel.AttributeClassification; +import org.hibernate.metamodel.ValueClassification; import org.hibernate.metamodel.model.domain.ManagedDomainType; import org.hibernate.metamodel.model.domain.SimpleDomainType; import org.hibernate.metamodel.model.domain.SingularPersistentAttribute; +import org.hibernate.query.sqm.NodeBuilder; import org.hibernate.query.sqm.SqmPathSource; -import org.hibernate.query.sqm.produce.path.spi.SemanticPathPart; import org.hibernate.query.sqm.produce.spi.SqmCreationState; -import org.hibernate.query.sqm.tree.domain.SqmAnyValuedSimplePath; -import org.hibernate.query.sqm.tree.domain.SqmBasicValuedSimplePath; -import org.hibernate.query.sqm.tree.domain.SqmEmbeddedValuedSimplePath; -import org.hibernate.query.sqm.tree.domain.SqmEntityValuedSimplePath; +import org.hibernate.query.sqm.tree.SqmJoinType; import org.hibernate.query.sqm.tree.domain.SqmPath; -import org.hibernate.query.sqm.tree.expression.SqmExpression; +import org.hibernate.query.sqm.tree.domain.SqmSingularJoin; +import org.hibernate.query.sqm.tree.from.SqmAttributeJoin; +import org.hibernate.query.sqm.tree.from.SqmFrom; +import org.hibernate.type.descriptor.java.JavaTypeDescriptor; /** * @author Emmanuel Bernard @@ -37,7 +37,7 @@ public class SingularAttributeImpl private final boolean isVersion; private final boolean isOptional; - private final SimpleDomainType attributeType; + private final SqmPathSource sqmPathSource; // NOTE : delay access for timing reasons private final DelayedKeyTypeAccess graphKeyTypeAccess = new DelayedKeyTypeAccess(); @@ -50,18 +50,55 @@ public class SingularAttributeImpl Member member, boolean isIdentifier, boolean isVersion, - boolean isOptional) { - super( declaringType, name, attributeType.getJavaTypeDescriptor(), attributeClassification, attributeType, member ); + boolean isOptional, + NodeBuilder nodeBuilder) { + super( declaringType, name, attributeType.getExpressableJavaTypeDescriptor(), attributeClassification, attributeType, member ); this.isIdentifier = isIdentifier; this.isVersion = isVersion; this.isOptional = isOptional; - this.attributeType = attributeType; + + this.sqmPathSource = DomainModelHelper.resolveSqmPathSource( + determineValueClassification( attributeClassification ), + name, + attributeType, + BindableType.SINGULAR_ATTRIBUTE, + nodeBuilder + ); + } + + private static ValueClassification determineValueClassification(AttributeClassification attributeClassification) { + switch ( attributeClassification ) { + case BASIC: { + return ValueClassification.BASIC; + } + case ANY: { + return ValueClassification.ANY; + } + case EMBEDDED: { + return ValueClassification.EMBEDDED; + } + case ONE_TO_ONE: + case MANY_TO_ONE: { + return ValueClassification.ENTITY; + } + default: { + throw new IllegalArgumentException( + "Unrecognized AttributeClassification (for singular attribute): " + attributeClassification + ); + } + } + } + + @Override + public SimpleDomainType getSqmPathType() { + //noinspection unchecked + return (SimpleDomainType) sqmPathSource.getSqmPathType(); } @Override public SimpleDomainType getValueGraphType() { - return attributeType; + return getSqmPathType(); } @Override @@ -70,43 +107,42 @@ public class SingularAttributeImpl } @Override - public SimpleDomainType getSqmNodeType() { - return super.getSqmNodeType(); + public SimpleDomainType getType() { + return getSqmPathType(); + } + + public JavaTypeDescriptor getExpressableJavaTypeDescriptor() { + return sqmPathSource.getExpressableJavaTypeDescriptor(); + } + + @Override + public Class getBindableJavaType() { + return getExpressableJavaTypeDescriptor().getJavaType(); } @Override public SqmPathSource findSubPathSource(String name) { - switch ( getAttributeClassification() ) { - case EMBEDDED: - case ONE_TO_ONE: - case MANY_TO_ONE: { - return ( (SqmPathSource) getSqmNodeType() ).findSubPathSource( name ); - } - default: { - throw new UnsupportedOperationException( "Attribute does not contain sub-paths" ); - } - } + return sqmPathSource.findSubPathSource( name ); } @Override - public SemanticPathPart resolvePathPart( - String name, - String currentContextKey, - boolean isTerminal, + public SqmAttributeJoin createSqmJoin( + SqmFrom lhs, + SqmJoinType joinType, + String alias, + boolean fetched, SqmCreationState creationState) { - return findSubPathSource( name ); + //noinspection unchecked + return new SqmSingularJoin( + lhs, + this, + alias, + joinType, + fetched, + creationState.getCreationContext().getNodeBuilder() + ); } - @Override - public SqmPath resolveIndexedAccess( - SqmExpression selector, - String currentContextKey, - boolean isTerminal, - SqmCreationState creationState) { - throw new UnsupportedOperationException( "Singular attribute cannot be index-accessed" ); - } - - /** * Subclass used to simplify instantiation of singular attributes representing an entity's * identifier. @@ -117,8 +153,19 @@ public class SingularAttributeImpl String name, SimpleDomainType attributeType, Member member, - AttributeClassification attributeClassification) { - super( declaringType, name, attributeClassification, attributeType, member, true, false, false ); + AttributeClassification attributeClassification, + NodeBuilder nodeBuilder) { + super( + declaringType, + name, + attributeClassification, + attributeType, + member, + true, + false, + false, + nodeBuilder + ); } } @@ -132,8 +179,19 @@ public class SingularAttributeImpl String name, AttributeClassification attributeClassification, SimpleDomainType attributeType, - Member member) { - super( declaringType, name, attributeClassification, attributeType, member, false, true, false ); + Member member, + NodeBuilder nodeBuilder) { + super( + declaringType, + name, + attributeClassification, + attributeType, + member, + false, + true, + false, + nodeBuilder + ); } } @@ -152,11 +210,6 @@ public class SingularAttributeImpl return isOptional; } - @Override - public SimpleDomainType getType() { - return attributeType; - } - @Override public boolean isAssociation() { return getPersistentAttributeType() == PersistentAttributeType.MANY_TO_ONE @@ -174,40 +227,10 @@ public class SingularAttributeImpl } @Override - public Class getBindableJavaType() { - return attributeType.getJavaType(); - } - - @Override - public SqmPath createSqmPath( + public SqmPath createSqmPath( SqmPath lhs, SqmCreationState creationState) { - switch ( getAttributeClassification() ) { - case BASIC: { - return new SqmBasicValuedSimplePath( ); - } - case EMBEDDED: { - return new SqmEmbeddedValuedSimplePath( ); - } - case ANY: { - return new SqmAnyValuedSimplePath( ); - } - case ONE_TO_ONE: - case MANY_TO_ONE: { - return new SqmEntityValuedSimplePath( ); - } - default: { - throw new UnsupportedOperationException( - String.format( - Locale.ROOT, - "Cannot create SqmPath from singular attribute [%s#%s] - unknown classification : %s", - getDeclaringType().getTypeName(), - getName(), - getAttributeClassification() - ) - ); - } - } + return sqmPathSource.createSqmPath( lhs, creationState ); } private class DelayedKeyTypeAccess implements Supplier>, Serializable { diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/PropertyMapping.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/PropertyMapping.java index c8cbfc0929..82a660b1c0 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/PropertyMapping.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/PropertyMapping.java @@ -6,6 +6,7 @@ */ package org.hibernate.persister.entity; +import org.hibernate.NotYetImplementedFor6Exception; import org.hibernate.QueryException; import org.hibernate.metamodel.model.domain.DomainType; import org.hibernate.persister.SqlExpressableType; @@ -33,29 +34,19 @@ import org.hibernate.type.Type; * @author Steve Ebersole */ public interface PropertyMapping { - /** - * Get the type of the thing containing the properties - * - * todo (6.0) : this really should be defined in terms of the Hibernate mapping model, not (just?) the JPA model - * - meaning maybe it exposes both - */ - DomainType getDomainType(); - SqlExpressableType getMappingType(); - - // /** - * @asciidoc - * - * Resolve a sub-reference relative to this PropertyMapping. E.g., + * @asciidoc Resolve a sub-reference relative to this PropertyMapping. E.g., * given the PropertyMapping for an entity named `Person` with an embedded * property `#name` calling this method with `"name"` returns the * PropertyMapping for the `Name` embeddable - * + *

* todo (6.0) : define an exception in the signature for cases where the PropertyMapping - * cannot be de-referenced (basic values) + * cannot be de-referenced (basic values) */ - PropertyMapping resolveSubMapping(String name); + default PropertyMapping resolveSubMapping(String name) { + throw new NotYetImplementedFor6Exception(); + } // todo (6.0) : add capability to create SqmPath, i.e. // SqmPath createSqmPath(SqmPath lhs, SqmCreationState creationState); diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/SqmExpressable.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/SqmExpressable.java index 4248d4c689..928f91e0dd 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/SqmExpressable.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/SqmExpressable.java @@ -15,5 +15,5 @@ import org.hibernate.type.descriptor.java.JavaTypeDescriptor; * @author Steve Ebersole */ public interface SqmExpressable { - JavaTypeDescriptor getJavaTypeDescriptor(); + JavaTypeDescriptor getExpressableJavaTypeDescriptor(); } diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/SqmJoinable.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/SqmJoinable.java index 4e92e65340..ffdcc11e62 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/SqmJoinable.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/SqmJoinable.java @@ -6,7 +6,6 @@ */ package org.hibernate.query.sqm; -import org.hibernate.metamodel.model.domain.spi.PersistentAttributeDescriptor; import org.hibernate.query.sqm.produce.spi.SqmCreationState; import org.hibernate.query.sqm.tree.SqmJoinType; import org.hibernate.query.sqm.tree.from.SqmAttributeJoin; @@ -20,7 +19,7 @@ import org.hibernate.query.sqm.tree.from.SqmFrom; * * @author Steve Ebersole */ -public interface SqmJoinable extends PersistentAttributeDescriptor { +public interface SqmJoinable { SqmAttributeJoin createSqmJoin( SqmFrom lhs, SqmJoinType joinType, diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/SqmPathSource.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/SqmPathSource.java index b49cb73d0a..b0fee9d494 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/SqmPathSource.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/SqmPathSource.java @@ -6,11 +6,11 @@ */ package org.hibernate.query.sqm; +import javax.persistence.metamodel.Bindable; + import org.hibernate.metamodel.model.domain.DomainType; -import org.hibernate.query.sqm.produce.path.spi.SemanticPathPart; import org.hibernate.query.sqm.produce.spi.SqmCreationState; import org.hibernate.query.sqm.tree.domain.SqmPath; -import org.hibernate.query.sqm.tree.expression.SqmExpression; /** * Represents parts of the application's domain model that can be used @@ -21,7 +21,7 @@ import org.hibernate.query.sqm.tree.expression.SqmExpression; * * @author Steve Ebersole */ -public interface SqmPathSource extends SqmExpressable, SemanticPathPart { +public interface SqmPathSource extends SqmExpressable, Bindable { /** * The name of this thing. Mainly used in logging and when creating a * {@link org.hibernate.query.NavigablePath} @@ -29,9 +29,10 @@ public interface SqmPathSource extends SqmExpressable, SemanticPathPart { String getPathName(); /** - * The type of SqmPaths this source creates + * The type of SqmPaths this source creates. Corollary to JPA's + * {@link Bindable#getBindableJavaType()} */ - DomainType getSqmNodeType(); + DomainType getSqmPathType(); SqmPathSource findSubPathSource(String name); @@ -39,13 +40,4 @@ public interface SqmPathSource extends SqmExpressable, SemanticPathPart { * Create an SQM path for this source relative to the given left-hand side */ SqmPath createSqmPath(SqmPath lhs, SqmCreationState creationState); - - @Override - default SqmPath resolveIndexedAccess( - SqmExpression selector, - String currentContextKey, - boolean isTerminal, - SqmCreationState creationState) { - throw new UnsupportedOperationException( "SqmPathSource [" + getClass().getName() + "] cannot be index accessed" ); - } } diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/SqmTypedNode.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/SqmTypedNode.java index dd46478609..1cc12ae66c 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/SqmTypedNode.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/SqmTypedNode.java @@ -16,13 +16,12 @@ import org.hibernate.type.descriptor.java.JavaTypeDescriptor; * @author Steve Ebersole */ public interface SqmTypedNode extends SqmNode { - /** * The Java type descriptor for this node. */ - default JavaTypeDescriptor getJavaTypeDescriptor() { + default JavaTypeDescriptor getNodeJavaTypeDescriptor() { final SqmExpressable nodeType = getNodeType(); - return nodeType != null ? nodeType.getJavaTypeDescriptor() : null; + return nodeType != null ? nodeType.getExpressableJavaTypeDescriptor() : null; } SqmExpressable getNodeType(); diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/AbstractSqmAttributeJoin.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/AbstractSqmAttributeJoin.java index be930ce76f..0eb6f24920 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/AbstractSqmAttributeJoin.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/AbstractSqmAttributeJoin.java @@ -11,7 +11,6 @@ import javax.persistence.criteria.JoinType; import javax.persistence.criteria.Predicate; import org.hibernate.metamodel.model.domain.PersistentAttribute; -import org.hibernate.metamodel.model.mapping.spi.Navigable; import org.hibernate.query.criteria.JpaExpression; import org.hibernate.query.criteria.JpaPredicate; import org.hibernate.query.sqm.NodeBuilder; @@ -24,8 +23,7 @@ import org.hibernate.query.sqm.tree.SqmJoinType; import org.hibernate.query.sqm.tree.from.SqmAttributeJoin; import org.hibernate.query.sqm.tree.from.SqmFrom; import org.hibernate.query.sqm.tree.predicate.SqmPredicate; -import org.hibernate.sql.ast.produce.metamodel.spi.Joinable; -import org.hibernate.type.descriptor.java.spi.JavaTypeDescriptor; +import org.hibernate.type.descriptor.java.JavaTypeDescriptor; import org.jboss.logging.Logger; @@ -44,16 +42,18 @@ public abstract class AbstractSqmAttributeJoin private SqmPredicate onClausePredicate; + @SuppressWarnings("WeakerAccess") public AbstractSqmAttributeJoin( SqmFrom lhs, - SqmJoinable joinedNavigable, + SqmJoinable joinedNavigable, String alias, SqmJoinType joinType, boolean fetched, NodeBuilder nodeBuilder) { + //noinspection unchecked super( - SqmCreationHelper.buildSubNavigablePath( lhs, joinedNavigable, alias ), - joinedNavigable, + SqmCreationHelper.buildSubNavigablePath( lhs, joinedNavigable.getName(), alias ), + (SqmPathSource) joinedNavigable, lhs, alias, joinType, @@ -69,13 +69,8 @@ public abstract class AbstractSqmAttributeJoin } @Override - public SqmJoinable getReferencedPathSource() { - return (SqmJoinable) super.getReferencedPathSource(); - } - - @Override - public JavaTypeDescriptor getJavaTypeDescriptor() { - return getReferencedPathSource().getJavaTypeDescriptor(); + public JavaTypeDescriptor getNodeJavaTypeDescriptor() { + return getJavaTypeDescriptor(); } public boolean isFetched() { @@ -113,7 +108,7 @@ public abstract class AbstractSqmAttributeJoin @Override public void prepareForSubNavigableReference( - Navigable subNavigable, + SqmPathSource subNavigable, boolean isSubReferenceTerminal, SqmCreationState creationState) { // nothing to prepare @@ -125,7 +120,8 @@ public abstract class AbstractSqmAttributeJoin @Override public PersistentAttribute getAttribute() { - return getReferencedPathSource(); + //noinspection unchecked + return (PersistentAttribute) getReferencedPathSource(); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/AbstractSqmCorrelatedFrom.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/AbstractSqmCorrelatedFrom.java index 5e58dd7e6a..86b821f5d4 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/AbstractSqmCorrelatedFrom.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/AbstractSqmCorrelatedFrom.java @@ -6,9 +6,7 @@ */ package org.hibernate.query.sqm.tree.domain; -import org.hibernate.metamodel.model.mapping.spi.NavigableContainer; import org.hibernate.query.sqm.NodeBuilder; -import org.hibernate.query.sqm.SqmPathSource; import org.hibernate.query.sqm.tree.from.SqmFrom; /** @@ -46,11 +44,4 @@ public abstract class AbstractSqmCorrelatedFrom public boolean isCorrelated() { return true; } - - @Override - public SqmPathSource getReferencedPathSource() { - return correlationParent.getReferencedPathSource(); - } - - } diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/AbstractSqmFrom.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/AbstractSqmFrom.java index 7ce00db35f..7a38b14f80 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/AbstractSqmFrom.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/AbstractSqmFrom.java @@ -26,8 +26,8 @@ import javax.persistence.metamodel.SingularAttribute; import org.hibernate.NotYetImplementedFor6Exception; import org.hibernate.metamodel.model.domain.BagPersistentAttribute; import org.hibernate.metamodel.model.domain.EntityDomainType; -import org.hibernate.metamodel.model.domain.spi.EntityTypeDescriptor; import org.hibernate.metamodel.model.domain.ListPersistentAttribute; +import org.hibernate.metamodel.model.domain.ManagedDomainType; import org.hibernate.metamodel.model.domain.MapPersistentAttribute; import org.hibernate.metamodel.model.domain.PluralPersistentAttribute; import org.hibernate.metamodel.model.domain.SetPersistentAttribute; @@ -37,7 +37,6 @@ import org.hibernate.query.criteria.JpaPath; import org.hibernate.query.criteria.JpaSubQuery; import org.hibernate.query.sqm.NodeBuilder; import org.hibernate.query.sqm.SemanticException; -import org.hibernate.query.sqm.SqmJoinable; import org.hibernate.query.sqm.SqmPathSource; import org.hibernate.query.sqm.UnknownPathException; import org.hibernate.query.sqm.produce.path.spi.SemanticPathPart; @@ -113,7 +112,7 @@ public abstract class AbstractSqmFrom extends AbstractSqmPath implements return creationState.getProcessingStateStack().getCurrent().getPathRegistry().resolvePath( subNavPath, snp -> { - final SqmPathSource subSource = getReferencedPathSource().findSubPathSource( name ); + final SqmPathSource subSource = getReferencedPathSource().findSubPathSource( name ); if ( subSource == null ) { throw UnknownPathException.unknownSubPath( this, name ); } @@ -249,7 +248,7 @@ public abstract class AbstractSqmFrom extends AbstractSqmPath implements @Override @SuppressWarnings("unchecked") public SqmAttributeJoin join(String attributeName, JoinType jt) { - final SqmPathSource subPathSource = getReferencedPathSource().findSubPathSource( attributeName ); + final SqmPathSource subPathSource = getReferencedPathSource().findSubPathSource( attributeName ); return buildJoin( subPathSource, SqmJoinType.from( jt ), false ); } @@ -263,7 +262,7 @@ public abstract class AbstractSqmFrom extends AbstractSqmPath implements @Override @SuppressWarnings("unchecked") public SqmBagJoin joinCollection(String attributeName, JoinType jt) { - final SqmPathSource joinedPathSource = getReferencedPathSource().findSubPathSource( attributeName ); + final SqmPathSource joinedPathSource = getReferencedPathSource().findSubPathSource( attributeName ); if ( joinedPathSource instanceof BagPersistentAttribute ) { return buildBagJoin( (BagPersistentAttribute) joinedPathSource, SqmJoinType.from( jt ), false ); @@ -289,7 +288,7 @@ public abstract class AbstractSqmFrom extends AbstractSqmPath implements @Override @SuppressWarnings("unchecked") public SqmSetJoin joinSet(String attributeName, JoinType jt) { - final SqmPathSource joinedPathSource = getReferencedPathSource().findSubPathSource( attributeName ); + final SqmPathSource joinedPathSource = getReferencedPathSource().findSubPathSource( attributeName ); if ( joinedPathSource instanceof SetPersistentAttribute ) { return buildSetJoin( (SetPersistentAttribute) joinedPathSource, SqmJoinType.from( jt ), false ); @@ -315,7 +314,7 @@ public abstract class AbstractSqmFrom extends AbstractSqmPath implements @Override @SuppressWarnings("unchecked") public SqmListJoin joinList(String attributeName, JoinType jt) { - final SqmPathSource joinedPathSource = getReferencedPathSource().findSubPathSource( attributeName ); + final SqmPathSource joinedPathSource = getReferencedPathSource().findSubPathSource( attributeName ); if ( joinedPathSource instanceof ListPersistentAttribute ) { return buildListJoin( (ListPersistentAttribute) joinedPathSource, SqmJoinType.from( jt ), false ); @@ -341,7 +340,7 @@ public abstract class AbstractSqmFrom extends AbstractSqmPath implements @Override @SuppressWarnings("unchecked") public SqmMapJoin joinMap(String attributeName, JoinType jt) { - final SqmPathSource joinedPathSource = getReferencedPathSource().findSubPathSource( attributeName ); + final SqmPathSource joinedPathSource = getReferencedPathSource().findSubPathSource( attributeName ); if ( joinedPathSource instanceof MapPersistentAttribute ) { return buildMapJoin( (MapPersistentAttribute) joinedPathSource, SqmJoinType.from( jt ), false ); @@ -404,12 +403,12 @@ public abstract class AbstractSqmFrom extends AbstractSqmPath implements @Override @SuppressWarnings("unchecked") public SqmAttributeJoin fetch(String attributeName, JoinType jt) { - final SqmPathSource fetchedPathSource = getReferencedPathSource().findSubPathSource( attributeName ); + final SqmPathSource fetchedPathSource = getReferencedPathSource().findSubPathSource( attributeName ); return buildJoin( fetchedPathSource, SqmJoinType.from( jt ), true ); } private SqmAttributeJoin buildJoin( - SqmPathSource joinedPathSource, + SqmPathSource joinedPathSource, SqmJoinType joinType, boolean fetched) { if ( joinedPathSource instanceof SingularPersistentAttribute ) { @@ -463,21 +462,22 @@ public abstract class AbstractSqmFrom extends AbstractSqmPath implements ); } - @SuppressWarnings("unchecked") private SqmSingularJoin buildSingularJoin( SingularPersistentAttribute attribute, SqmJoinType joinType, boolean fetched) { - if ( attribute instanceof SqmJoinable ) { - return new SqmSingularJoin<>( + if ( attribute.getSqmPathType() instanceof ManagedDomainType ) { + //noinspection unchecked + return new SqmSingularJoin( this, - (SqmJoinable) attribute, + attribute, null, joinType, fetched, nodeBuilder() ); } + throw new SemanticException( "Attribute [" + attribute + "] is not joinable" ); } diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/AbstractSqmJoin.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/AbstractSqmJoin.java index 6542a51600..2ab4a3c8ca 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/AbstractSqmJoin.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/AbstractSqmJoin.java @@ -21,7 +21,7 @@ public abstract class AbstractSqmJoin extends AbstractSqmFrom implemen public AbstractSqmJoin( NavigablePath navigablePath, - SqmPathSource referencedNavigable, + SqmPathSource referencedNavigable, SqmFrom lhs, String alias, SqmJoinType joinType, diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/AbstractSqmPath.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/AbstractSqmPath.java index ee6e3dc2a8..11204155f8 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/AbstractSqmPath.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/AbstractSqmPath.java @@ -10,7 +10,6 @@ import java.util.HashMap; import java.util.Locale; import java.util.Map; import java.util.function.BiFunction; -import javax.persistence.metamodel.Bindable; import javax.persistence.metamodel.MapAttribute; import javax.persistence.metamodel.PluralAttribute; import javax.persistence.metamodel.SingularAttribute; @@ -23,8 +22,11 @@ import org.hibernate.metamodel.model.domain.SingularPersistentAttribute; import org.hibernate.query.NavigablePath; import org.hibernate.query.sqm.NodeBuilder; import org.hibernate.query.sqm.SqmPathSource; +import org.hibernate.query.sqm.produce.path.spi.SemanticPathPart; +import org.hibernate.query.sqm.produce.spi.SqmCreationState; import org.hibernate.query.sqm.tree.expression.AbstractSqmExpression; import org.hibernate.query.sqm.tree.expression.SqmExpression; +import org.hibernate.type.descriptor.java.JavaTypeDescriptor; /** * @author Steve Ebersole @@ -38,7 +40,7 @@ public abstract class AbstractSqmPath extends AbstractSqmExpression implem @SuppressWarnings("WeakerAccess") protected AbstractSqmPath( NavigablePath navigablePath, - SqmPathSource referencedPathSource, + SqmPathSource referencedPathSource, SqmPath lhs, NodeBuilder nodeBuilder) { super( referencedPathSource, nodeBuilder ); @@ -46,8 +48,18 @@ public abstract class AbstractSqmPath extends AbstractSqmExpression implem this.lhs = lhs; } + @Override + public SqmPathSource getNodeType() { + return (SqmPathSource) super.getNodeType(); + } + + @Override + public SqmPathSource getReferencedPathSource() { + return (SqmPathSource) super.getNodeType(); + } + @SuppressWarnings("WeakerAccess") - protected AbstractSqmPath(SqmPathSource referencedPathSource, SqmPath lhs, NodeBuilder nodeBuilder) { + protected AbstractSqmPath(SqmPathSource referencedPathSource, SqmPath lhs, NodeBuilder nodeBuilder) { this( lhs == null ? new NavigablePath( referencedPathSource.getPathName() ) @@ -79,9 +91,8 @@ public abstract class AbstractSqmPath extends AbstractSqmExpression implem } @Override - @SuppressWarnings("unchecked") - public Bindable getModel() { - return (Bindable) getReferencedPathSource(); + public SqmPathSource getModel() { + return getReferencedPathSource(); } private SqmExpression pathTypeExpression; @@ -90,19 +101,70 @@ public abstract class AbstractSqmPath extends AbstractSqmExpression implem @SuppressWarnings("unchecked") public SqmExpression> type() { if ( pathTypeExpression == null ) { - final DomainType sqmNodeType = getReferencedPathSource().getSqmNodeType(); + final String discriminatorPathName = "{type}"; + final NavigablePath discriminatorNavigablePath = getNavigablePath().append( discriminatorPathName ); + + final DomainType sqmNodeType = getReferencedPathSource().getSqmPathType(); + if ( sqmNodeType instanceof EntityDomainType ) { + final SqmPathSource discriminatorPathSource = new SqmPathSource() { + @Override + public String getPathName() { + return discriminatorPathName; + } + + @Override + public DomainType getSqmPathType() { + return null; + } + + @Override + public SqmPathSource findSubPathSource(String name) { + throw new UnsupportedOperationException( "Entity discriminator cannot be de-referenced" ); + } + + @Override + public SqmPath createSqmPath(SqmPath lhs, SqmCreationState creationState) { + return new SqmBasicValuedSimplePath( discriminatorNavigablePath, this, AbstractSqmPath.this, nodeBuilder() ); + } + + @Override + public BindableType getBindableType() { + return BindableType.SINGULAR_ATTRIBUTE; + } + + @Override + public Class getBindableJavaType() { + return null; + } + + @Override + public JavaTypeDescriptor getExpressableJavaTypeDescriptor() { + return null; + } + + @Override + public SemanticPathPart resolvePathPart( + String name, + String currentContextKey, + boolean isTerminal, + SqmCreationState creationState) { + return findSubPathSource( name ); + } + }; pathTypeExpression = new SqmBasicValuedSimplePath( - getNavigablePath().append( "{type}" ), - ???, + discriminatorNavigablePath, + discriminatorPathSource, this, nodeBuilder() ); } else { - throw new ... + // todo (6.0) : not sure this is strictly true + throw new UnsupportedOperationException( "SqmPath [" + getClass().getName() + "] cannot be typed" ); } } + return pathTypeExpression; } @@ -121,39 +183,40 @@ public abstract class AbstractSqmPath extends AbstractSqmExpression implem final SqmPathSource subNavigable = getReferencedPathSource().findSubPathSource( attributeName ); if ( subNavigable instanceof SingularPersistentAttribute ) { - return createSingularPath( pathSource, (SingularPersistentAttribute) subNavigable ); + return createSingularPath( (SingularPersistentAttribute) subNavigable ); } else { assert subNavigable instanceof PluralPersistentAttribute; - return createPluralPath( pathSource, (PluralPersistentAttribute) subNavigable ); + return createPluralPath( (PluralPersistentAttribute) subNavigable ); } } ); } - private SqmPath createSingularPath(SqmPath lhs, SingularPersistentAttribute attribute) { + @SuppressWarnings("unchecked") + private SqmPath createSingularPath(SingularPersistentAttribute attribute) { final NavigablePath subNavPath = getNavigablePath().append( attribute.getPathName() ); switch ( attribute.getAttributeClassification() ) { case BASIC: { - return new SqmBasicValuedSimplePath( subNavPath, ); + return new SqmBasicValuedSimplePath( subNavPath, attribute, this, nodeBuilder() ); } case EMBEDDED: { - return new SqmEmbeddedValuedSimplePath( subNavPath, ); + return new SqmEmbeddedValuedSimplePath( subNavPath, attribute, this, nodeBuilder() ); } case ANY: { - return new SqmAnyValuedSimplePath( subNavPath, ); + return new SqmAnyValuedSimplePath( subNavPath, attribute, this, nodeBuilder() ); } case ONE_TO_ONE: case MANY_TO_ONE: { - return new SqmEntityValuedSimplePath( subNavPath, ); + return new SqmEntityValuedSimplePath( subNavPath, attribute, this, nodeBuilder() ); } default: { throw new UnsupportedOperationException( String.format( Locale.ROOT, "Cannot create SqmPath from singular attribute [%s#%s] - unknown classification : %s", - attribute.getDeclaringType().getName(), + attribute.getDeclaringType().getTypeName(), attribute.getName(), attribute.getAttributeClassification() ) @@ -162,11 +225,12 @@ public abstract class AbstractSqmPath extends AbstractSqmExpression implem } } - private SqmPath createPluralPath( - SqmPath lhs, - PluralPersistentAttribute pluralAttribute) { + private SqmPath createPluralPath(PluralPersistentAttribute pluralAttribute) { return new SqmPluralValuedSimplePath( - getNavigablePath().append( pluralAttribute.getPathName(), + getNavigablePath().append( pluralAttribute.getPathName() ), + pluralAttribute, + this, + nodeBuilder() ); } @@ -194,7 +258,7 @@ public abstract class AbstractSqmPath extends AbstractSqmExpression implem final SingularPersistentAttribute attribute = (SingularPersistentAttribute) jpaAttribute; return resolvePath( attribute.getName(), - (pathSource, name) -> createSingularPath( pathSource, attribute ) + (pathSource, name) -> createSingularPath( attribute ) ); } @@ -203,7 +267,7 @@ public abstract class AbstractSqmPath extends AbstractSqmExpression implem public SqmPath get(PluralAttribute attribute) { return resolvePath( attribute.getName(), - (pathSource, name) -> createPluralPath( pathSource, (PluralPersistentAttribute) attribute ) + (pathSource, name) -> createPluralPath( (PluralPersistentAttribute) attribute ) ); } @@ -212,7 +276,7 @@ public abstract class AbstractSqmPath extends AbstractSqmExpression implem public SqmPath get(MapAttribute map) { return resolvePath( map.getName(), - (pathSource, name) -> createPluralPath( pathSource, (MapPersistentAttribute) map ) + (pathSource, name) -> createPluralPath( (MapPersistentAttribute) map ) ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/AbstractSqmPluralJoin.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/AbstractSqmPluralJoin.java index 0a9ec71dd0..cf282b4fea 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/AbstractSqmPluralJoin.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/AbstractSqmPluralJoin.java @@ -8,19 +8,19 @@ package org.hibernate.query.sqm.tree.domain; import javax.persistence.criteria.PluralJoin; -import org.hibernate.metamodel.model.mapping.spi.PluralPersistentAttribute; +import org.hibernate.metamodel.model.domain.PluralPersistentAttribute; import org.hibernate.query.criteria.JpaJoin; import org.hibernate.query.sqm.NodeBuilder; -import org.hibernate.query.sqm.SqmPathSource; +import org.hibernate.query.sqm.SqmJoinable; import org.hibernate.query.sqm.tree.SqmJoinType; import org.hibernate.query.sqm.tree.from.SqmFrom; -import org.hibernate.sql.ast.produce.metamodel.spi.Joinable; /** * @author Steve Ebersole */ public abstract class AbstractSqmPluralJoin extends AbstractSqmAttributeJoin implements JpaJoin, PluralJoin { + @SuppressWarnings("WeakerAccess") public AbstractSqmPluralJoin( SqmFrom lhs, PluralPersistentAttribute joinedNavigable, @@ -28,9 +28,10 @@ public abstract class AbstractSqmPluralJoin extends AbstractSqmAttributeJ SqmJoinType joinType, boolean fetched, NodeBuilder nodeBuilder) { + //noinspection unchecked super( lhs, - (Joinable) joinedNavigable, + (SqmJoinable) joinedNavigable, alias, joinType, fetched, @@ -39,8 +40,8 @@ public abstract class AbstractSqmPluralJoin extends AbstractSqmAttributeJ } @Override - public SqmPathSource getReferencedPathSource() { - return (PluralPersistentAttribute) super.getReferencedPathSource(); + public PluralPersistentAttribute getReferencedPathSource() { + return (PluralPersistentAttribute) super.getReferencedPathSource(); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/AbstractSqmSimplePath.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/AbstractSqmSimplePath.java index d377c28ee0..3112905a88 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/AbstractSqmSimplePath.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/AbstractSqmSimplePath.java @@ -16,6 +16,7 @@ import org.hibernate.query.sqm.SqmPathSource; public abstract class AbstractSqmSimplePath extends AbstractSqmPath implements SqmNavigableReference { private final NavigablePath navigablePath; + @SuppressWarnings("WeakerAccess") public AbstractSqmSimplePath( NavigablePath navigablePath, SqmPathSource referencedPathSource, @@ -24,6 +25,7 @@ public abstract class AbstractSqmSimplePath extends AbstractSqmPath implem this( navigablePath, referencedPathSource, lhs, null, nodeBuilder ); } + @SuppressWarnings("WeakerAccess") public AbstractSqmSimplePath( NavigablePath navigablePath, SqmPathSource referencedPathSource, diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/AbstractSqmSpecificPluralPartPath.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/AbstractSqmSpecificPluralPartPath.java index 9c87fb9a0f..04cb71acbb 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/AbstractSqmSpecificPluralPartPath.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/AbstractSqmSpecificPluralPartPath.java @@ -7,9 +7,8 @@ package org.hibernate.query.sqm.tree.domain; import org.hibernate.NotYetImplementedFor6Exception; -import org.hibernate.metamodel.model.mapping.spi.EntityValuedNavigable; -import org.hibernate.metamodel.model.mapping.spi.Navigable; -import org.hibernate.metamodel.model.mapping.PersistentCollectionDescriptor; +import org.hibernate.metamodel.model.domain.EntityDomainType; +import org.hibernate.metamodel.model.domain.PluralPersistentAttribute; import org.hibernate.query.NavigablePath; import org.hibernate.query.criteria.PathException; @@ -19,33 +18,34 @@ import org.hibernate.query.criteria.PathException; public abstract class AbstractSqmSpecificPluralPartPath extends AbstractSqmPath implements SqmPath { private final NavigablePath navigablePath; private final SqmPath pluralDomainPath; - private final PersistentCollectionDescriptor collectionDescriptor; + private final PluralPersistentAttribute pluralAttribute; private String alias; + @SuppressWarnings("WeakerAccess") public AbstractSqmSpecificPluralPartPath( NavigablePath navigablePath, SqmPath pluralDomainPath, - Navigable referencedNavigable) { + PluralPersistentAttribute referencedAttribute) { super( navigablePath, - referencedNavigable, + referencedAttribute, pluralDomainPath, pluralDomainPath.nodeBuilder() ); this.navigablePath = navigablePath; this.pluralDomainPath = pluralDomainPath; - - //noinspection unchecked - this.collectionDescriptor = pluralDomainPath.sqmAs( PersistentCollectionDescriptor.class ); + this.pluralAttribute = referencedAttribute; } + @SuppressWarnings("WeakerAccess") public SqmPath getPluralDomainPath() { return pluralDomainPath; } - public PersistentCollectionDescriptor getCollectionDescriptor() { - return collectionDescriptor; + @SuppressWarnings("WeakerAccess") + public PluralPersistentAttribute getPluralAttribute() { + return pluralAttribute; } @Override @@ -70,7 +70,7 @@ public abstract class AbstractSqmSpecificPluralPartPath extends AbstractSqmPa @Override public SqmTreatedPath treatAs(Class treatJavaType) throws PathException { - if ( getReferencedPathSource() instanceof EntityValuedNavigable ) { + if ( getReferencedPathSource().getSqmPathType() instanceof EntityDomainType ) { throw new NotYetImplementedFor6Exception(); } diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmAnyValuedSimplePath.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmAnyValuedSimplePath.java index 47331079a5..d4c052e61b 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmAnyValuedSimplePath.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmAnyValuedSimplePath.java @@ -6,10 +6,12 @@ */ package org.hibernate.query.sqm.tree.domain; -import org.hibernate.persister.entity.PropertyMapping; +import org.hibernate.NotYetImplementedFor6Exception; +import org.hibernate.metamodel.model.domain.AnyMappingDomainType; import org.hibernate.query.NavigablePath; import org.hibernate.query.criteria.PathException; import org.hibernate.query.sqm.NodeBuilder; +import org.hibernate.query.sqm.SqmPathSource; import org.hibernate.query.sqm.consume.spi.SemanticQueryWalker; import org.hibernate.query.sqm.produce.path.spi.SemanticPathPart; import org.hibernate.query.sqm.produce.spi.SqmCreationState; @@ -18,33 +20,40 @@ import org.hibernate.query.sqm.produce.spi.SqmCreationState; * @author Steve Ebersole */ public class SqmAnyValuedSimplePath extends AbstractSqmSimplePath { + @SuppressWarnings("WeakerAccess") public SqmAnyValuedSimplePath( NavigablePath navigablePath, - Navigable referencedNavigable, - SqmPath lhs, NodeBuilder nodeBuilder) { - super( navigablePath, referencedNavigable, lhs, nodeBuilder ); + SqmPathSource referencedPathSource, + SqmPath lhs, + NodeBuilder nodeBuilder) { + super( navigablePath, referencedPathSource, lhs, nodeBuilder ); + + assert referencedPathSource.getSqmPathType() instanceof AnyMappingDomainType; } + @SuppressWarnings("unused") public SqmAnyValuedSimplePath( NavigablePath navigablePath, - Navigable referencedNavigable, - SqmPath lhs, String explicitAlias, NodeBuilder nodeBuilder) { - super( navigablePath, referencedNavigable, lhs, explicitAlias, nodeBuilder ); - } + SqmPathSource referencedPathSource, + SqmPath lhs, + String explicitAlias, + NodeBuilder nodeBuilder) { + super( navigablePath, referencedPathSource, lhs, explicitAlias, nodeBuilder ); - @Override - public PropertyMapping getReferencedPropertyMapping() { - return null; + assert referencedPathSource.getSqmPathType() instanceof AnyMappingDomainType; } @Override public SqmTreatedPath treatAs(Class treatJavaType) throws PathException { - return null; + throw new NotYetImplementedFor6Exception(); } @Override public SemanticPathPart resolvePathPart( - String name, String currentContextKey, boolean isTerminal, SqmCreationState creationState) { + String name, + String currentContextKey, + boolean isTerminal, + SqmCreationState creationState) { return null; } diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmBagJoin.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmBagJoin.java index 536c9ad57e..bbc1e0d0f1 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmBagJoin.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmBagJoin.java @@ -14,22 +14,23 @@ import javax.persistence.metamodel.PluralAttribute; import javax.persistence.metamodel.SingularAttribute; import org.hibernate.NotYetImplementedFor6Exception; -import org.hibernate.metamodel.model.mapping.spi.BagPersistentAttribute; -import org.hibernate.metamodel.model.mapping.EntityTypeDescriptor; +import org.hibernate.metamodel.model.domain.BagPersistentAttribute; +import org.hibernate.metamodel.model.domain.EntityDomainType; import org.hibernate.query.criteria.JpaCollectionJoin; import org.hibernate.query.criteria.JpaExpression; import org.hibernate.query.criteria.JpaPredicate; import org.hibernate.query.criteria.JpaSubQuery; import org.hibernate.query.sqm.NodeBuilder; -import org.hibernate.query.sqm.SqmPathSource; import org.hibernate.query.sqm.tree.SqmJoinType; import org.hibernate.query.sqm.tree.from.SqmAttributeJoin; import org.hibernate.query.sqm.tree.from.SqmFrom; +import org.hibernate.type.descriptor.java.JavaTypeDescriptor; /** * @author Steve Ebersole */ public class SqmBagJoin extends AbstractSqmPluralJoin, E> implements JpaCollectionJoin { + @SuppressWarnings("WeakerAccess") public SqmBagJoin( SqmFrom lhs, BagPersistentAttribute attribute, @@ -41,18 +42,19 @@ public class SqmBagJoin extends AbstractSqmPluralJoin, E> } @Override - public SqmPathSource getReferencedPathSource() { - return (BagPersistentAttribute) super.getReferencedPathSource(); + public JavaTypeDescriptor getJavaTypeDescriptor() { + return getModel().getExpressableJavaTypeDescriptor(); } @Override public BagPersistentAttribute getModel() { - return getReferencedPathSource(); + return (BagPersistentAttribute) getReferencedPathSource(); } @Override public BagPersistentAttribute getAttribute() { - return getReferencedPathSource(); + //noinspection unchecked + return (BagPersistentAttribute) super.getAttribute(); } @Override @@ -114,7 +116,8 @@ public class SqmBagJoin extends AbstractSqmPluralJoin, E> @Override public SqmTreatedBagJoin treatAs(Class treatAsType) { - final EntityTypeDescriptor entityTypeDescriptor = nodeBuilder().getDomainModel().entity( treatAsType ); - return new SqmTreatedBagJoin<>( this, entityTypeDescriptor, null ); + final EntityDomainType entityTypeDescriptor = nodeBuilder().getDomainModel().entity( treatAsType ); + //noinspection unchecked + return new SqmTreatedBagJoin( this, entityTypeDescriptor, null ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmBasicValuedSimplePath.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmBasicValuedSimplePath.java index 7aeb7208a7..095c2a6cd0 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmBasicValuedSimplePath.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmBasicValuedSimplePath.java @@ -6,7 +6,6 @@ */ package org.hibernate.query.sqm.tree.domain; -import org.hibernate.metamodel.model.mapping.spi.BasicValuedNavigable; import org.hibernate.query.NavigablePath; import org.hibernate.query.criteria.PathException; import org.hibernate.query.sqm.NodeBuilder; @@ -15,7 +14,7 @@ import org.hibernate.query.sqm.SqmPathSource; import org.hibernate.query.sqm.consume.spi.SemanticQueryWalker; import org.hibernate.query.sqm.produce.path.spi.SemanticPathPart; import org.hibernate.query.sqm.produce.spi.SqmCreationState; -import org.hibernate.type.descriptor.java.spi.BasicJavaDescriptor; +import org.hibernate.type.descriptor.java.BasicJavaDescriptor; /** * @author Steve Ebersole @@ -23,19 +22,19 @@ import org.hibernate.type.descriptor.java.spi.BasicJavaDescriptor; public class SqmBasicValuedSimplePath extends AbstractSqmSimplePath { public SqmBasicValuedSimplePath( NavigablePath navigablePath, - BasicValuedNavigable referencedNavigable, + SqmPathSource referencedPathSource, SqmPath lhs, NodeBuilder nodeBuilder) { - this( navigablePath, referencedNavigable, lhs, null, nodeBuilder ); + this( navigablePath, referencedPathSource, lhs, null, nodeBuilder ); } public SqmBasicValuedSimplePath( NavigablePath navigablePath, - BasicValuedNavigable referencedNavigable, + SqmPathSource referencedPathSource, SqmPath lhs, String explicitAlias, NodeBuilder nodeBuilder) { - super( navigablePath, referencedNavigable, lhs, explicitAlias, nodeBuilder ); + super( navigablePath, referencedPathSource, lhs, explicitAlias, nodeBuilder ); } @Override @@ -53,17 +52,16 @@ public class SqmBasicValuedSimplePath extends AbstractSqmSimplePath { } @Override - public SqmPathSource getReferencedPathSource() { - return (BasicValuedNavigable) super.getReferencedPathSource(); + public SqmPathSource getReferencedPathSource() { + return super.getReferencedPathSource(); } @Override - public BasicValuedNavigable getNodeType() { + public SqmPathSource getNodeType() { return getReferencedPathSource(); } @Override - @SuppressWarnings("unchecked") public BasicJavaDescriptor getJavaTypeDescriptor() { return (BasicJavaDescriptor) super.getJavaTypeDescriptor(); } diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmEmbeddedValuedSimplePath.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmEmbeddedValuedSimplePath.java index 8ef1b32590..cf509d4b36 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmEmbeddedValuedSimplePath.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmEmbeddedValuedSimplePath.java @@ -6,11 +6,11 @@ */ package org.hibernate.query.sqm.tree.domain; -import org.hibernate.metamodel.model.mapping.spi.EmbeddedValuedNavigable; -import org.hibernate.metamodel.model.mapping.spi.Navigable; +import org.hibernate.metamodel.model.domain.EmbeddableDomainType; import org.hibernate.query.NavigablePath; import org.hibernate.query.criteria.PathException; import org.hibernate.query.sqm.NodeBuilder; +import org.hibernate.query.sqm.SqmJoinable; import org.hibernate.query.sqm.SqmPathSource; import org.hibernate.query.sqm.UnknownPathException; import org.hibernate.query.sqm.consume.spi.SemanticQueryWalker; @@ -20,8 +20,6 @@ import org.hibernate.query.sqm.produce.spi.SqmCreationState; import org.hibernate.query.sqm.tree.SqmJoinType; import org.hibernate.query.sqm.tree.from.SqmAttributeJoin; import org.hibernate.query.sqm.tree.from.SqmFrom; -import org.hibernate.sql.ast.produce.metamodel.spi.Joinable; -import org.hibernate.type.descriptor.java.spi.EmbeddableJavaDescriptor; /** * @author Steve Ebersole @@ -29,19 +27,24 @@ import org.hibernate.type.descriptor.java.spi.EmbeddableJavaDescriptor; public class SqmEmbeddedValuedSimplePath extends AbstractSqmSimplePath { public SqmEmbeddedValuedSimplePath( NavigablePath navigablePath, - EmbeddedValuedNavigable referencedNavigable, + SqmPathSource referencedPathSource, SqmPath lhs, NodeBuilder nodeBuilder) { - super( navigablePath, referencedNavigable, lhs, nodeBuilder ); + super( navigablePath, referencedPathSource, lhs, nodeBuilder ); + + assert referencedPathSource.getSqmPathType() instanceof EmbeddableDomainType; } + @SuppressWarnings("unused") public SqmEmbeddedValuedSimplePath( NavigablePath navigablePath, - EmbeddedValuedNavigable referencedNavigable, + SqmPathSource referencedPathSource, SqmPath lhs, String explicitAlias, NodeBuilder nodeBuilder) { - super( navigablePath, referencedNavigable, lhs, explicitAlias, nodeBuilder ); + super( navigablePath, referencedPathSource, lhs, explicitAlias, nodeBuilder ); + + assert referencedPathSource.getSqmPathType() instanceof EmbeddableDomainType; } @Override @@ -50,33 +53,14 @@ public class SqmEmbeddedValuedSimplePath extends AbstractSqmSimplePath { String currentContextKey, boolean isTerminal, SqmCreationState creationState) { - final Navigable subNavigable = getReferencedPathSource().findNavigable( name ); - if ( subNavigable == null ) { + final SqmPathSource subPathSource = getReferencedPathSource().findSubPathSource( name ); + if ( subPathSource == null ) { throw UnknownPathException.unknownSubPath( this, name ); } - prepareForSubNavigableReference( subNavigable, isTerminal, creationState ); + prepareForSubNavigableReference( subPathSource, isTerminal, creationState ); - //noinspection unchecked - return subNavigable.createSqmExpression( - this, - creationState - ); - } - - @Override - public SqmPathSource getReferencedPathSource() { - return (EmbeddedValuedNavigable) super.getReferencedPathSource(); - } - - @Override - public EmbeddedValuedNavigable getNodeType() { - return getReferencedPathSource(); - } - - @Override - public EmbeddableJavaDescriptor getJavaTypeDescriptor() { - return getReferencedPathSource().getJavaTypeDescriptor(); + return subPathSource.createSqmPath( this, creationState ); } @Override @@ -88,7 +72,7 @@ public class SqmEmbeddedValuedSimplePath extends AbstractSqmSimplePath { @Override public void prepareForSubNavigableReference( - Navigable subNavigable, + SqmPathSource subNavigable, boolean isSubReferenceTerminal, SqmCreationState creationState) { if ( dereferenced ) { @@ -99,7 +83,7 @@ public class SqmEmbeddedValuedSimplePath extends AbstractSqmSimplePath { log.tracef( "`SqmEmbeddedValuedSimplePath#prepareForSubNavigableReference` : %s -> %s", getNavigablePath().getFullPath(), - subNavigable.getNavigableName() + subNavigable.getPathName() ); final SqmPathRegistry pathRegistry = creationState.getProcessingStateStack().getCurrent().getPathRegistry(); @@ -109,10 +93,10 @@ public class SqmEmbeddedValuedSimplePath extends AbstractSqmSimplePath { if ( fromByPath == null ) { getLhs().prepareForSubNavigableReference( getReferencedPathSource(), false, creationState ); - final SqmFrom lhsFrom = pathRegistry.findFromByPath( getLhs().getNavigablePath() ); + final SqmFrom lhsFrom = pathRegistry.findFromByPath( getLhs().getNavigablePath() ); - if ( getReferencedPathSource() instanceof Joinable ) { - final SqmAttributeJoin sqmJoin = ( (Joinable) getReferencedPathSource() ).createSqmJoin( + if ( getReferencedPathSource() instanceof SqmJoinable ) { + final SqmAttributeJoin sqmJoin = ( (SqmJoinable) getReferencedPathSource() ).createSqmJoin( lhsFrom, SqmJoinType.INNER, null, @@ -120,6 +104,7 @@ public class SqmEmbeddedValuedSimplePath extends AbstractSqmSimplePath { creationState ); pathRegistry.register( sqmJoin ); + //noinspection unchecked lhsFrom.addSqmJoin( sqmJoin ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmEntityValuedSimplePath.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmEntityValuedSimplePath.java index af1127ba36..a4d7715c66 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmEntityValuedSimplePath.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmEntityValuedSimplePath.java @@ -6,9 +6,7 @@ */ package org.hibernate.query.sqm.tree.domain; -import org.hibernate.metamodel.model.mapping.EntityTypeDescriptor; -import org.hibernate.metamodel.model.mapping.spi.EntityValuedNavigable; -import org.hibernate.metamodel.model.mapping.spi.Navigable; +import org.hibernate.metamodel.model.domain.EntityDomainType; import org.hibernate.query.NavigablePath; import org.hibernate.query.criteria.PathException; import org.hibernate.query.sqm.NodeBuilder; @@ -17,7 +15,6 @@ import org.hibernate.query.sqm.consume.spi.SemanticQueryWalker; import org.hibernate.query.sqm.produce.SqmCreationHelper; import org.hibernate.query.sqm.produce.path.spi.SemanticPathPart; import org.hibernate.query.sqm.produce.spi.SqmCreationState; -import org.hibernate.type.descriptor.java.spi.EntityJavaDescriptor; /** * @author Steve Ebersole @@ -25,10 +22,10 @@ import org.hibernate.type.descriptor.java.spi.EntityJavaDescriptor; public class SqmEntityValuedSimplePath extends AbstractSqmSimplePath { public SqmEntityValuedSimplePath( NavigablePath navigablePath, - EntityValuedNavigable referencedNavigable, + SqmPathSource referencedPathSource, SqmPath lhs, NodeBuilder nodeBuilder) { - super( navigablePath, referencedNavigable, lhs, nodeBuilder ); + super( navigablePath, referencedPathSource, lhs, nodeBuilder ); } @Override @@ -37,17 +34,18 @@ public class SqmEntityValuedSimplePath extends AbstractSqmSimplePath { String currentContextKey, boolean isTerminal, SqmCreationState creationState) { - final EntityValuedNavigable referencedNavigable = getReferencedPathSource(); - final Navigable navigable = referencedNavigable.findNavigable( name ); + final SqmPathSource referencedPathSource = getReferencedPathSource(); + final SqmPathSource subPathSource = referencedPathSource.findSubPathSource( name ); - prepareForSubNavigableReference( referencedNavigable, isTerminal, creationState ); + prepareForSubNavigableReference( subPathSource, isTerminal, creationState ); assert getLhs() == null || creationState.getProcessingStateStack() .getCurrent() .getPathRegistry() .findPath( getLhs().getNavigablePath() ) != null; - return navigable.createSqmExpression( this, creationState ); + //noinspection unchecked + return subPathSource.createSqmPath( this, creationState ); } @Override @@ -55,16 +53,11 @@ public class SqmEntityValuedSimplePath extends AbstractSqmSimplePath { return walker.visitEntityValuedPath( this ); } - @Override - public SqmPathSource getReferencedPathSource() { - return (EntityValuedNavigable) super.getReferencedPathSource(); - } - private boolean dereferenced; @Override public void prepareForSubNavigableReference( - Navigable subNavigable, + SqmPathSource subNavigable, boolean isSubReferenceTerminal, SqmCreationState creationState) { if ( dereferenced ) { @@ -75,7 +68,7 @@ public class SqmEntityValuedSimplePath extends AbstractSqmSimplePath { log.tracef( "`SqmEntityValuedSimplePath#prepareForSubNavigableReference` : %s -> %s", getNavigablePath().getFullPath(), - subNavigable.getNavigableName() + subNavigable.getPathName() ); SqmCreationHelper.resolveAsLhs( getLhs(), this, subNavigable, isSubReferenceTerminal, creationState ); @@ -84,24 +77,16 @@ public class SqmEntityValuedSimplePath extends AbstractSqmSimplePath { } @Override - public EntityValuedNavigable getNodeType() { - return getReferencedPathSource(); - } - - @Override - public EntityJavaDescriptor getJavaTypeDescriptor() { - return getReferencedPathSource().getJavaTypeDescriptor(); + public EntityDomainType getNodeType() { + //noinspection unchecked + return (EntityDomainType) getReferencedPathSource().getSqmPathType(); } @Override @SuppressWarnings("unchecked") public SqmTreatedSimplePath treatAs(Class treatJavaType) throws PathException { - final EntityTypeDescriptor treatTargetDescriptor = nodeBuilder().getDomainModel().entity( treatJavaType ); - return new SqmTreatedSimplePath( - this, - treatTargetDescriptor, - nodeBuilder() - ); + final EntityDomainType treatTargetDescriptor = nodeBuilder().getDomainModel().entity( treatJavaType ); + return new SqmTreatedSimplePath( this, treatTargetDescriptor, nodeBuilder() ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmIndexedCollectionAccessPath.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmIndexedCollectionAccessPath.java index 3d09485fab..6fcee256b3 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmIndexedCollectionAccessPath.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmIndexedCollectionAccessPath.java @@ -7,13 +7,11 @@ package org.hibernate.query.sqm.tree.domain; import org.hibernate.NotYetImplementedFor6Exception; -import org.hibernate.metamodel.model.mapping.spi.EntityValuedNavigable; -import org.hibernate.metamodel.model.mapping.spi.Navigable; -import org.hibernate.metamodel.model.mapping.spi.NavigableContainer; -import org.hibernate.metamodel.model.mapping.PersistentCollectionDescriptor; -import org.hibernate.metamodel.model.mapping.spi.PluralValuedNavigable; +import org.hibernate.metamodel.model.domain.EntityDomainType; +import org.hibernate.metamodel.model.domain.PluralPersistentAttribute; import org.hibernate.query.NavigablePath; import org.hibernate.query.criteria.PathException; +import org.hibernate.query.sqm.SqmPathSource; import org.hibernate.query.sqm.consume.spi.SemanticQueryWalker; import org.hibernate.query.sqm.produce.path.spi.SemanticPathPart; import org.hibernate.query.sqm.produce.spi.SqmCreationState; @@ -24,27 +22,32 @@ import org.hibernate.query.sqm.tree.expression.SqmExpression; */ public class SqmIndexedCollectionAccessPath extends AbstractSqmPath implements SqmPath { private final SqmExpression selectorExpression; - private final PersistentCollectionDescriptor collectionDescriptor; public SqmIndexedCollectionAccessPath( SqmPath pluralDomainPath, SqmExpression selectorExpression) { + //noinspection unchecked super( pluralDomainPath.getNavigablePath().append( "[]" ), - pluralDomainPath.sqmAs( PluralValuedNavigable.class ).getCollectionDescriptor().getElementDescriptor(), + (PluralPersistentAttribute) pluralDomainPath.getReferencedPathSource(), pluralDomainPath, pluralDomainPath.nodeBuilder() ); this.selectorExpression = selectorExpression; - this.collectionDescriptor = pluralDomainPath.sqmAs( PluralValuedNavigable.class ).getCollectionDescriptor(); } public SqmExpression getSelectorExpression() { return selectorExpression; } + @Override + public PluralPersistentAttribute getReferencedPathSource() { + //noinspection unchecked + return (PluralPersistentAttribute) super.getReferencedPathSource(); + } + @Override public NavigablePath getNavigablePath() { // todo (6.0) : this would require some String-ified form of the selector @@ -57,10 +60,9 @@ public class SqmIndexedCollectionAccessPath extends AbstractSqmPath implem String currentContextKey, boolean isTerminal, SqmCreationState creationState) { - final Navigable subNavigable = ( (NavigableContainer) collectionDescriptor.getElementDescriptor() ) - .findNavigable( name ); - - return subNavigable.createSqmExpression( this, creationState ); + final SqmPathSource subPathSource = getReferencedPathSource().getElementPathSource().findSubPathSource( name ); + //noinspection unchecked + return subPathSource.createSqmPath( this, creationState ); } @Override @@ -70,7 +72,7 @@ public class SqmIndexedCollectionAccessPath extends AbstractSqmPath implem @Override public SqmTreatedPath treatAs(Class treatJavaType) throws PathException { - if ( getReferencedPathSource() instanceof EntityValuedNavigable ) { + if ( getReferencedPathSource().getSqmPathType() instanceof EntityDomainType ) { throw new NotYetImplementedFor6Exception(); } diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmListJoin.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmListJoin.java index 179258dec0..ddb3d88265 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmListJoin.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmListJoin.java @@ -14,24 +14,24 @@ import javax.persistence.metamodel.PluralAttribute; import javax.persistence.metamodel.SingularAttribute; import org.hibernate.NotYetImplementedFor6Exception; -import org.hibernate.metamodel.model.mapping.spi.BasicValuedNavigable; -import org.hibernate.metamodel.model.mapping.spi.CollectionIndex; -import org.hibernate.metamodel.model.mapping.EntityTypeDescriptor; -import org.hibernate.metamodel.model.mapping.spi.ListPersistentAttribute; +import org.hibernate.metamodel.model.domain.EntityDomainType; +import org.hibernate.metamodel.model.domain.ListPersistentAttribute; +import org.hibernate.query.NavigablePath; import org.hibernate.query.criteria.JpaExpression; import org.hibernate.query.criteria.JpaListJoin; import org.hibernate.query.criteria.JpaPredicate; import org.hibernate.query.criteria.JpaSubQuery; import org.hibernate.query.sqm.NodeBuilder; -import org.hibernate.query.sqm.SqmPathSource; import org.hibernate.query.sqm.tree.SqmJoinType; import org.hibernate.query.sqm.tree.from.SqmAttributeJoin; import org.hibernate.query.sqm.tree.from.SqmFrom; +import org.hibernate.type.descriptor.java.JavaTypeDescriptor; /** * @author Steve Ebersole */ public class SqmListJoin extends AbstractSqmPluralJoin, E> implements JpaListJoin { + @SuppressWarnings("WeakerAccess") public SqmListJoin( SqmFrom lhs, ListPersistentAttribute listAttribute, @@ -42,22 +42,25 @@ public class SqmListJoin extends AbstractSqmPluralJoin, E> implem super( lhs, listAttribute, alias, sqmJoinType, fetched, nodeBuilder ); } - @Override - public SqmPathSource getReferencedPathSource() { - return (ListPersistentAttribute) super.getReferencedPathSource(); - } - @Override public ListPersistentAttribute getModel() { - return getReferencedPathSource(); + return (ListPersistentAttribute) super.getModel(); + } + + @Override + public JavaTypeDescriptor getJavaTypeDescriptor() { + return getNodeJavaTypeDescriptor(); } @Override - @SuppressWarnings("unchecked") public SqmPath index() { + final String navigableName = "{index}"; + final NavigablePath navigablePath = getNavigablePath().append( navigableName ); + + //noinspection unchecked return new SqmBasicValuedSimplePath<>( - getNavigablePath().append( CollectionIndex.NAVIGABLE_NAME ), - (BasicValuedNavigable) getReferencedPathSource().getCollectionDescriptor().getIndexDescriptor(), + navigablePath, + ( (ListPersistentAttribute) getReferencedPathSource() ).getIndexPathSource(), this, nodeBuilder() ); @@ -91,7 +94,7 @@ public class SqmListJoin extends AbstractSqmPluralJoin, E> implem @Override @SuppressWarnings("unchecked") public SqmTreatedListJoin treatAs(Class treatAsType) { - final EntityTypeDescriptor entityTypeDescriptor = nodeBuilder().getDomainModel().entity( treatAsType ); + final EntityDomainType entityTypeDescriptor = nodeBuilder().getDomainModel().entity( treatAsType ); return new SqmTreatedListJoin( this, entityTypeDescriptor, null ); } diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmMapEntryReference.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmMapEntryReference.java index 4c04f32cae..e1deed9834 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmMapEntryReference.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmMapEntryReference.java @@ -6,15 +6,22 @@ */ package org.hibernate.query.sqm.tree.domain; +import java.util.Collection; +import java.util.Collections; +import java.util.List; import java.util.Map; +import java.util.function.Consumer; -import org.hibernate.metamodel.model.mapping.spi.PluralValuedNavigable; +import javax.persistence.criteria.Expression; +import javax.persistence.criteria.Predicate; + +import org.hibernate.query.criteria.JpaSelection; import org.hibernate.query.sqm.NodeBuilder; +import org.hibernate.query.sqm.SqmExpressable; import org.hibernate.query.sqm.consume.spi.SemanticQueryWalker; -import org.hibernate.query.sqm.tree.expression.AbstractSqmExpression; -import org.hibernate.query.sqm.tree.expression.SqmExpression; -import org.hibernate.sql.ast.produce.metamodel.spi.ExpressableType; -import org.hibernate.type.descriptor.java.spi.BasicJavaDescriptor; +import org.hibernate.query.sqm.tree.select.SqmSelectableNode; +import org.hibernate.type.descriptor.java.JavaTypeDescriptor; + /** * Represents the reference to a Map attribute's {@link Map.Entry} entries @@ -23,58 +30,114 @@ import org.hibernate.type.descriptor.java.spi.BasicJavaDescriptor; * @author Gunnar Morling * @author Steve Ebersole */ -public class SqmMapEntryReference extends AbstractSqmExpression> implements SqmExpression>, ExpressableType> { +public class SqmMapEntryReference implements SqmSelectableNode>, Expression> { + @SuppressWarnings({"FieldCanBeLocal", "unused"}) private final SqmPath mapPath; - private final BasicJavaDescriptor> mapEntryTypeDescriptor; + private final NodeBuilder nodeBuilder; + + private final JavaTypeDescriptor> mapEntryTypeDescriptor; + + private String explicitAlias; public SqmMapEntryReference( SqmPath mapPath, - BasicJavaDescriptor> mapEntryTypeDescriptor, NodeBuilder nodeBuilder) { - super( - mapPath.sqmAs( PluralValuedNavigable.class ).getCollectionDescriptor().getDescribedAttribute(), - nodeBuilder - ); this.mapPath = mapPath; - this.mapEntryTypeDescriptor = mapEntryTypeDescriptor; - } + this.nodeBuilder = nodeBuilder; - public SqmPath getMapPath() { - return mapPath; - } - - public PluralValuedNavigable getMapNavigable() { - return mapPath.sqmAs( PluralValuedNavigable.class ); + //noinspection unchecked + this.mapEntryTypeDescriptor = (JavaTypeDescriptor) nodeBuilder.getDomainModel() + .getTypeConfiguration() + .getJavaTypeDescriptorRegistry() + .getDescriptor( Map.Entry.class ); } @Override - public BasicJavaDescriptor> getJavaTypeDescriptor() { - return mapEntryTypeDescriptor; + public String getAlias() { + return explicitAlias; } @Override - public ExpressableType> getNodeType() { + public JpaSelection> alias(String name) { + this.explicitAlias = name; return this; } @Override - public T accept(SemanticQueryWalker walker) { + public JavaTypeDescriptor> getJavaTypeDescriptor() { + return mapEntryTypeDescriptor; + } + + @Override + public JavaTypeDescriptor> getNodeJavaTypeDescriptor() { + return mapEntryTypeDescriptor; + } + + @Override + public X accept(SemanticQueryWalker walker) { return walker.visitMapEntryFunction( this ); } @Override - public String asLoggableText() { - return "MAP_ENTRY(" + getMapNavigable().asLoggableText() + ")"; + public void visitSubSelectableNodes(Consumer> jpaSelectionConsumer) { } @Override - public PersistenceType getPersistenceType() { - return PersistenceType.BASIC; + public boolean isCompoundSelection() { + return false; } @Override - @SuppressWarnings("unchecked") - public Class> getJavaType() { - return (Class) Map.Entry.class; + public List> getSelectionItems() { + return Collections.emptyList(); + } + + @Override + public SqmExpressable> getNodeType() { + return null; + } + + @Override + public NodeBuilder nodeBuilder() { + return nodeBuilder; + } + + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // JPA (ugh) + + @Override + public Predicate isNull() { + throw new UnsupportedOperationException( "Whatever JPA" ); + } + + @Override + public Predicate isNotNull() { + throw new UnsupportedOperationException( "Whatever JPA" ); + } + + @Override + public Predicate in(Object... values) { + throw new UnsupportedOperationException( "Whatever JPA" ); + } + + @Override + public Predicate in(Expression... values) { + throw new UnsupportedOperationException( "Whatever JPA" ); + } + + @Override + public Predicate in(Collection values) { + throw new UnsupportedOperationException( "Whatever JPA" ); + } + + @Override + public Predicate in(Expression> values) { + throw new UnsupportedOperationException( "Whatever JPA" ); + } + + @Override + public Expression as(Class type) { + throw new UnsupportedOperationException( "Whatever JPA" ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmMapJoin.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmMapJoin.java index f3080fbaa9..f39fa7abf1 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmMapJoin.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmMapJoin.java @@ -11,13 +11,10 @@ import javax.persistence.criteria.Expression; import javax.persistence.criteria.Path; import javax.persistence.criteria.Predicate; -import org.hibernate.metamodel.model.mapping.spi.BasicValuedNavigable; -import org.hibernate.metamodel.model.mapping.spi.CollectionElement; -import org.hibernate.metamodel.model.mapping.spi.CollectionIndex; -import org.hibernate.metamodel.model.mapping.spi.EmbeddedValuedNavigable; -import org.hibernate.metamodel.model.mapping.EntityTypeDescriptor; -import org.hibernate.metamodel.model.mapping.spi.EntityValuedNavigable; -import org.hibernate.metamodel.model.mapping.spi.MapPersistentAttribute; +import org.hibernate.metamodel.model.domain.BasicDomainType; +import org.hibernate.metamodel.model.domain.EmbeddableDomainType; +import org.hibernate.metamodel.model.domain.EntityDomainType; +import org.hibernate.metamodel.model.domain.MapPersistentAttribute; import org.hibernate.query.NavigablePath; import org.hibernate.query.criteria.JpaExpression; import org.hibernate.query.criteria.JpaMapJoin; @@ -28,12 +25,13 @@ import org.hibernate.query.sqm.NodeBuilder; import org.hibernate.query.sqm.SqmPathSource; import org.hibernate.query.sqm.tree.SqmJoinType; import org.hibernate.query.sqm.tree.from.SqmFrom; -import org.hibernate.type.descriptor.java.spi.BasicJavaDescriptor; +import org.hibernate.type.descriptor.java.JavaTypeDescriptor; /** * @author Steve Ebersole */ public class SqmMapJoin extends AbstractSqmPluralJoin,V> implements JpaMapJoin { + @SuppressWarnings("WeakerAccess") public SqmMapJoin( SqmFrom lhs, MapPersistentAttribute pluralValuedNavigable, @@ -45,10 +43,16 @@ public class SqmMapJoin extends AbstractSqmPluralJoin,V> imple } @Override - public SqmPathSource getReferencedPathSource() { + public MapPersistentAttribute getReferencedPathSource() { + //noinspection unchecked return(MapPersistentAttribute) super.getReferencedPathSource(); } + @Override + public JavaTypeDescriptor getJavaTypeDescriptor() { + return getNodeJavaTypeDescriptor(); + } + @Override public MapPersistentAttribute getModel() { return (MapPersistentAttribute) super.getModel(); @@ -61,86 +65,79 @@ public class SqmMapJoin extends AbstractSqmPluralJoin,V> imple @Override @SuppressWarnings("unchecked") public SqmPath key() { - final CollectionIndex mapKeyDescriptor = getReferencedPathSource().getCollectionDescriptor().getIndexDescriptor(); - final NavigablePath navigablePath = getNavigablePath().append( mapKeyDescriptor.getNavigableName() ); + final SqmPathSource keyPathSource = getReferencedPathSource().getKeyPathSource(); + final NavigablePath navigablePath = getNavigablePath().append( keyPathSource.getPathName() ); - if ( mapKeyDescriptor instanceof BasicValuedNavigable ) { + if ( keyPathSource.getSqmPathType() instanceof BasicDomainType ) { return new SqmBasicValuedSimplePath( navigablePath, - (BasicValuedNavigable) mapKeyDescriptor, + keyPathSource, this, null ); } - if ( mapKeyDescriptor instanceof EmbeddedValuedNavigable ) { + if ( keyPathSource.getSqmPathType() instanceof EmbeddableDomainType ) { return new SqmEmbeddedValuedSimplePath( navigablePath, - (EmbeddedValuedNavigable) mapKeyDescriptor, + keyPathSource, this, null ); } - if ( mapKeyDescriptor instanceof EntityValuedNavigable ) { + if ( keyPathSource.getSqmPathType() instanceof EntityDomainType ) { return new SqmEntityValuedSimplePath( navigablePath, - (EntityValuedNavigable) mapKeyDescriptor, + keyPathSource, this, null ); } - throw new UnsupportedOperationException( "Unrecognized Map key descriptor : " + mapKeyDescriptor ); + throw new UnsupportedOperationException( "Unrecognized Map key descriptor : " + keyPathSource ); } @Override @SuppressWarnings("unchecked") public Path value() { - final CollectionElement valueDescriptor = getReferencedPathSource().getCollectionDescriptor().getElementDescriptor(); - final NavigablePath navigablePath = getNavigablePath().append( valueDescriptor.getNavigableName() ); + final SqmPathSource elementPathSource = getReferencedPathSource().getElementPathSource(); + final NavigablePath navigablePath = getNavigablePath().append( elementPathSource.getPathName() ); - if ( valueDescriptor instanceof BasicValuedNavigable ) { + if ( elementPathSource.getSqmPathType() instanceof BasicDomainType ) { return new SqmBasicValuedSimplePath( navigablePath, - (BasicValuedNavigable) valueDescriptor, + elementPathSource, this, null ); } - if ( valueDescriptor instanceof EmbeddedValuedNavigable ) { + if ( elementPathSource.getSqmPathType() instanceof EmbeddableDomainType ) { return new SqmEmbeddedValuedSimplePath( navigablePath, - (EmbeddedValuedNavigable) valueDescriptor, + elementPathSource, this, null ); } - if ( valueDescriptor instanceof EntityValuedNavigable ) { + if ( elementPathSource.getSqmPathType() instanceof EntityDomainType ) { return new SqmEntityValuedSimplePath( navigablePath, - (EntityValuedNavigable) valueDescriptor, + elementPathSource, this, null ); } - throw new UnsupportedOperationException( "Unrecognized Map value descriptor : " + valueDescriptor ); + throw new UnsupportedOperationException( "Unrecognized Map value descriptor : " + elementPathSource ); } @Override @SuppressWarnings("unchecked") public Expression> entry() { - return new SqmMapEntryReference<>( - this, - (BasicJavaDescriptor) nodeBuilder().getDomainModel() - .getTypeConfiguration() - .getJavaTypeDescriptorRegistry() - .getDescriptor( Map.Entry.class ), - nodeBuilder() - ); + return new SqmMapEntryReference( this, nodeBuilder() ); } @Override @@ -171,7 +168,7 @@ public class SqmMapJoin extends AbstractSqmPluralJoin,V> imple @Override @SuppressWarnings("unchecked") public SqmTreatedMapJoin treatAs(Class treatJavaType) throws PathException { - final EntityTypeDescriptor targetDescriptor = nodeBuilder().getDomainModel().entity( treatJavaType ); + final EntityDomainType targetDescriptor = nodeBuilder().getDomainModel().entity( treatJavaType ); return new SqmTreatedMapJoin( this, targetDescriptor, null ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmMaxElementPath.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmMaxElementPath.java index 0e30d54b0d..9f3db52041 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmMaxElementPath.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmMaxElementPath.java @@ -6,9 +6,8 @@ */ package org.hibernate.query.sqm.tree.domain; -import org.hibernate.metamodel.model.mapping.spi.Navigable; -import org.hibernate.metamodel.model.mapping.spi.NavigableContainer; -import org.hibernate.metamodel.model.mapping.PersistentCollectionDescriptor; +import org.hibernate.metamodel.model.domain.ManagedDomainType; +import org.hibernate.metamodel.model.domain.PluralPersistentAttribute; import org.hibernate.query.sqm.SemanticException; import org.hibernate.query.sqm.SqmPathSource; import org.hibernate.query.sqm.consume.spi.SemanticQueryWalker; @@ -22,10 +21,11 @@ public class SqmMaxElementPath extends AbstractSqmSpecificPluralPartPath { public static final String NAVIGABLE_NAME = "{max-element}"; public SqmMaxElementPath(SqmPath pluralDomainPath) { + //noinspection unchecked super( pluralDomainPath.getNavigablePath().append( NAVIGABLE_NAME ), pluralDomainPath, - pluralDomainPath.sqmAs( PersistentCollectionDescriptor.class ).getElementDescriptor() + (PluralPersistentAttribute) pluralDomainPath.getReferencedPathSource() ); } @@ -35,18 +35,18 @@ public class SqmMaxElementPath extends AbstractSqmSpecificPluralPartPath { String currentContextKey, boolean isTerminal, SqmCreationState creationState) { - if ( getReferencedPathSource() instanceof NavigableContainer ) { - final Navigable subNavigable = ( (NavigableContainer) getReferencedPathSource() ).findNavigable( name ); - getPluralDomainPath().prepareForSubNavigableReference( subNavigable, isTerminal, creationState ); - return subNavigable.createSqmExpression( this, creationState ); + if ( getPluralAttribute().getElementPathSource().getSqmPathType() instanceof ManagedDomainType ) { + //noinspection unchecked + return getPluralAttribute().getElementPathSource().createSqmPath( this, creationState ); } throw new SemanticException( "Collection element cannot be de-referenced : " + getPluralDomainPath().getNavigablePath() ); } @Override - public SqmPathSource getReferencedPathSource() { - return getCollectionDescriptor().getElementDescriptor(); + public SqmPathSource getReferencedPathSource() { + //noinspection unchecked + return getPluralAttribute().getElementPathSource(); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmMaxIndexPath.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmMaxIndexPath.java index 3225aa7e62..1a60acc660 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmMaxIndexPath.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmMaxIndexPath.java @@ -6,10 +6,9 @@ */ package org.hibernate.query.sqm.tree.domain; -import org.hibernate.metamodel.model.mapping.spi.Navigable; -import org.hibernate.metamodel.model.mapping.spi.NavigableContainer; -import org.hibernate.metamodel.model.mapping.PersistentCollectionDescriptor; -import org.hibernate.query.sqm.SemanticException; +import org.hibernate.metamodel.model.domain.ListPersistentAttribute; +import org.hibernate.metamodel.model.domain.MapPersistentAttribute; +import org.hibernate.metamodel.model.domain.PluralPersistentAttribute; import org.hibernate.query.sqm.SqmPathSource; import org.hibernate.query.sqm.consume.spi.SemanticQueryWalker; import org.hibernate.query.sqm.produce.path.spi.SemanticPathPart; @@ -21,12 +20,27 @@ import org.hibernate.query.sqm.produce.spi.SqmCreationState; public class SqmMaxIndexPath extends AbstractSqmSpecificPluralPartPath { public static final String NAVIGABLE_NAME = "{max-index}"; + private final SqmPathSource indexPathSource; + public SqmMaxIndexPath(SqmPath pluralDomainPath) { + //noinspection unchecked super( pluralDomainPath.getNavigablePath().append( NAVIGABLE_NAME ), pluralDomainPath, - pluralDomainPath.sqmAs( PersistentCollectionDescriptor.class ).getIndexDescriptor() + (PluralPersistentAttribute) pluralDomainPath.getReferencedPathSource() ); + + if ( getPluralAttribute() instanceof ListPersistentAttribute ) { + //noinspection unchecked + this.indexPathSource = ( (ListPersistentAttribute) getPluralAttribute() ).getIndexPathSource(); + } + else if ( getPluralAttribute() instanceof MapPersistentAttribute ) { + //noinspection unchecked + this.indexPathSource = ( (MapPersistentAttribute) getPluralAttribute() ).getKeyPathSource(); + } + else { + throw new UnsupportedOperationException( "Plural attribute [" + getPluralAttribute() + "] is not indexed" ); + } } @Override @@ -35,18 +49,12 @@ public class SqmMaxIndexPath extends AbstractSqmSpecificPluralPartPath { String currentContextKey, boolean isTerminal, SqmCreationState creationState) { - if ( getReferencedPathSource() instanceof NavigableContainer ) { - final Navigable subNavigable = ( (NavigableContainer) getReferencedPathSource() ).findNavigable( name ); - getPluralDomainPath().prepareForSubNavigableReference( subNavigable, isTerminal, creationState ); - return subNavigable.createSqmExpression( this, creationState ); - } - - throw new SemanticException( "Collection index cannot be de-referenced : " + getPluralDomainPath().getNavigablePath() ); + return indexPathSource.createSqmPath( this, creationState ); } @Override - public SqmPathSource getReferencedPathSource() { - return getCollectionDescriptor().getIndexDescriptor(); + public SqmPathSource getReferencedPathSource() { + return indexPathSource; } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmMinElementPath.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmMinElementPath.java index 9c0b24dfd8..06da37f0a4 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmMinElementPath.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmMinElementPath.java @@ -6,9 +6,8 @@ */ package org.hibernate.query.sqm.tree.domain; -import org.hibernate.metamodel.model.mapping.spi.Navigable; -import org.hibernate.metamodel.model.mapping.spi.NavigableContainer; -import org.hibernate.metamodel.model.mapping.PersistentCollectionDescriptor; +import org.hibernate.metamodel.model.domain.ManagedDomainType; +import org.hibernate.metamodel.model.domain.PluralPersistentAttribute; import org.hibernate.query.sqm.SemanticException; import org.hibernate.query.sqm.SqmPathSource; import org.hibernate.query.sqm.consume.spi.SemanticQueryWalker; @@ -22,10 +21,11 @@ public class SqmMinElementPath extends AbstractSqmSpecificPluralPartPath { public static final String NAVIGABLE_NAME = "{min-element}"; public SqmMinElementPath(SqmPath pluralDomainPath) { + //noinspection unchecked super( pluralDomainPath.getNavigablePath().append( NAVIGABLE_NAME ), pluralDomainPath, - pluralDomainPath.sqmAs( PersistentCollectionDescriptor.class ).getElementDescriptor() + (PluralPersistentAttribute) pluralDomainPath.getReferencedPathSource() ); } @@ -35,18 +35,18 @@ public class SqmMinElementPath extends AbstractSqmSpecificPluralPartPath { String currentContextKey, boolean isTerminal, SqmCreationState creationState) { - if ( getReferencedPathSource() instanceof NavigableContainer ) { - final Navigable subNavigable = ( (NavigableContainer) getReferencedPathSource() ).findNavigable( name ); - getPluralDomainPath().prepareForSubNavigableReference( subNavigable, isTerminal, creationState ); - return subNavigable.createSqmExpression( this, creationState ); + if ( getPluralAttribute().getElementPathSource().getSqmPathType() instanceof ManagedDomainType ) { + //noinspection unchecked + return getPluralAttribute().getElementPathSource().createSqmPath( this, creationState ); } throw new SemanticException( "Collection element cannot be de-referenced : " + getPluralDomainPath().getNavigablePath() ); } @Override - public SqmPathSource getReferencedPathSource() { - return getCollectionDescriptor().getElementDescriptor(); + public SqmPathSource getReferencedPathSource() { + //noinspection unchecked + return getPluralAttribute().getElementPathSource(); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmMinIndexPath.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmMinIndexPath.java index 2759bd3d60..ec33c29e5b 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmMinIndexPath.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmMinIndexPath.java @@ -6,10 +6,9 @@ */ package org.hibernate.query.sqm.tree.domain; -import org.hibernate.metamodel.model.mapping.spi.Navigable; -import org.hibernate.metamodel.model.mapping.spi.NavigableContainer; -import org.hibernate.metamodel.model.mapping.PersistentCollectionDescriptor; -import org.hibernate.query.sqm.SemanticException; +import org.hibernate.metamodel.model.domain.ListPersistentAttribute; +import org.hibernate.metamodel.model.domain.MapPersistentAttribute; +import org.hibernate.metamodel.model.domain.PluralPersistentAttribute; import org.hibernate.query.sqm.SqmPathSource; import org.hibernate.query.sqm.consume.spi.SemanticQueryWalker; import org.hibernate.query.sqm.produce.path.spi.SemanticPathPart; @@ -21,12 +20,27 @@ import org.hibernate.query.sqm.produce.spi.SqmCreationState; public class SqmMinIndexPath extends AbstractSqmSpecificPluralPartPath { public static final String NAVIGABLE_NAME = "{min-index}"; + private final SqmPathSource indexPathSource; + public SqmMinIndexPath(SqmPath pluralDomainPath) { + //noinspection unchecked super( pluralDomainPath.getNavigablePath().append( NAVIGABLE_NAME ), pluralDomainPath, - pluralDomainPath.sqmAs( PersistentCollectionDescriptor.class ).getIndexDescriptor() + (PluralPersistentAttribute) pluralDomainPath.getReferencedPathSource() ); + + if ( getPluralAttribute() instanceof ListPersistentAttribute ) { + //noinspection unchecked + this.indexPathSource = ( (ListPersistentAttribute) getPluralAttribute() ).getIndexPathSource(); + } + else if ( getPluralAttribute() instanceof MapPersistentAttribute ) { + //noinspection unchecked + this.indexPathSource = ( (MapPersistentAttribute) getPluralAttribute() ).getKeyPathSource(); + } + else { + throw new UnsupportedOperationException( "Plural attribute [" + getPluralAttribute() + "] is not indexed" ); + } } @Override @@ -35,18 +49,12 @@ public class SqmMinIndexPath extends AbstractSqmSpecificPluralPartPath { String currentContextKey, boolean isTerminal, SqmCreationState creationState) { - if ( getReferencedPathSource() instanceof NavigableContainer ) { - final Navigable subNavigable = ( (NavigableContainer) getReferencedPathSource() ).findNavigable( name ); - getPluralDomainPath().prepareForSubNavigableReference( subNavigable, isTerminal, creationState ); - return subNavigable.createSqmExpression( this, creationState ); - } - - throw new SemanticException( "Collection index cannot be de-referenced : " + getPluralDomainPath().getNavigablePath() ); + return indexPathSource.createSqmPath( this, creationState ); } @Override - public SqmPathSource getReferencedPathSource() { - return getCollectionDescriptor().getIndexDescriptor(); + public SqmPathSource getReferencedPathSource() { + return indexPathSource; } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmPath.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmPath.java index 6fc4db5314..2ae0047f97 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmPath.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmPath.java @@ -6,10 +6,6 @@ */ package org.hibernate.query.sqm.tree.domain; -import java.util.Locale; -import java.util.function.Supplier; - -import org.hibernate.metamodel.model.domain.DomainType; import org.hibernate.query.NavigablePath; import org.hibernate.query.criteria.JpaPath; import org.hibernate.query.criteria.PathException; @@ -61,7 +57,7 @@ public interface SqmPath extends SqmExpression, SemanticPathPart, JpaPath< SqmPath getLhs(); @Override - DomainType getNodeType(); + SqmPathSource getNodeType(); @Override default void applyInferableType(SqmExpressable type) { @@ -70,7 +66,7 @@ public interface SqmPath extends SqmExpression, SemanticPathPart, JpaPath< @Override default JavaTypeDescriptor getJavaTypeDescriptor() { - return getNodeType().getJavaTypeDescriptor(); + return getNodeType().getExpressableJavaTypeDescriptor(); } @Override @@ -140,45 +136,48 @@ public interface SqmPath extends SqmExpression, SemanticPathPart, JpaPath< SqmCreationHelper.resolveAsLhs( getLhs(), this, subNavigable, isSubReferenceTerminal, creationState ); } - /** - * Treat this path as the given type. "Cast it" to the target type. - * - * May throw an exception if the Path is not treatable as the requested type. - * - * Also recognizes any {@link Navigable} target type and applies it to the - * {@link #getReferencedPathSource()}. - * - * @apiNote This is very different from JPA's {@link #as} (and variants like - * {@link #asInteger()}, etc) which are equivalent to SQL CAST function calls. - * - * @return The "casted" reference - */ - @SuppressWarnings("unchecked") - default X sqmAs(Class targetType) { - if ( targetType.isInstance( this ) ) { - return (X) this; - } - - if ( Navigable.class.isAssignableFrom( targetType ) ) { - return (X) ( (Navigable) getReferencedPathSource() ).as( targetType ); - } - - throw new IllegalArgumentException( - String.format( - Locale.ROOT, - "`%s` cannot be treated as `%s`", - getClass().getName(), - targetType.getName() - ) - ); - } - - default X sqmAs(Class targetType, Supplier exceptionSupplier) { - try { - return sqmAs( targetType ); - } - catch (IllegalArgumentException e) { - throw exceptionSupplier.get(); - } - } +// /** +// * Treat this path as the given type. "Cast it" to the target type. +// * +// * May throw an exception if the Path is not treatable as the requested type. +// * +// * Also recognizes any {@link Navigable} target type and applies it to the +// * {@link #getReferencedPathSource()}. +// * +// * @apiNote This is very different from JPA's {@link #as} (and variants like +// * {@link #asInteger()}, etc) which are equivalent to SQL CAST function calls. +// * +// * @return The "casted" reference +// */ +// @SuppressWarnings("unchecked") +// default X sqmAs(Class targetType) { +// if ( targetType.isInstance( this ) ) { +// return (X) this; +// } +// +// if ( getReferencedPathSource().getSqmPathType() +// .getExpressableJavaTypeDescriptor() +// .getJavaType() +// .isAssignableFrom( targetType ) ) { +// return (X) ( (Navigable) getReferencedPathSource() ).as( targetType ); +// } +// +// throw new IllegalArgumentException( +// String.format( +// Locale.ROOT, +// "`%s` cannot be treated as `%s`", +// getClass().getName(), +// targetType.getName() +// ) +// ); +// } +// +// default X sqmAs(Class targetType, Supplier exceptionSupplier) { +// try { +// return sqmAs( targetType ); +// } +// catch (IllegalArgumentException e) { +// throw exceptionSupplier.get(); +// } +// } } diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmPluralValuedSimplePath.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmPluralValuedSimplePath.java index 4447ddb76a..56dbd2e96e 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmPluralValuedSimplePath.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmPluralValuedSimplePath.java @@ -6,21 +6,23 @@ */ package org.hibernate.query.sqm.tree.domain; +import org.hibernate.metamodel.model.domain.EntityDomainType; +import org.hibernate.metamodel.model.domain.ListPersistentAttribute; +import org.hibernate.metamodel.model.domain.MapPersistentAttribute; import org.hibernate.metamodel.model.domain.PluralPersistentAttribute; -import org.hibernate.metamodel.model.mapping.spi.CollectionElement; -import org.hibernate.metamodel.model.mapping.spi.CollectionIndex; -import org.hibernate.metamodel.model.mapping.EntityTypeDescriptor; -import org.hibernate.metamodel.model.mapping.spi.PluralValuedNavigable; +import org.hibernate.persister.collection.CollectionPropertyNames; import org.hibernate.query.NavigablePath; import org.hibernate.query.criteria.PathException; import org.hibernate.query.sqm.NodeBuilder; -import org.hibernate.query.sqm.SqmPathSource; import org.hibernate.query.sqm.consume.spi.SemanticQueryWalker; import org.hibernate.query.sqm.produce.path.spi.SemanticPathPart; import org.hibernate.query.sqm.produce.spi.SqmCreationState; -import org.hibernate.type.descriptor.java.internal.CollectionJavaDescriptor; /** + * An SqmPath for plural attribute paths + * + * @param The collection element type, which is the "bindable" type in the SQM tree + * * @author Steve Ebersole */ public class SqmPluralValuedSimplePath extends AbstractSqmSimplePath { @@ -32,16 +34,35 @@ public class SqmPluralValuedSimplePath extends AbstractSqmSimplePath { this( navigablePath, referencedNavigable, lhs, null, nodeBuilder ); } + @SuppressWarnings("WeakerAccess") public SqmPluralValuedSimplePath( NavigablePath navigablePath, PluralPersistentAttribute referencedNavigable, SqmPath lhs, String explicitAlias, NodeBuilder nodeBuilder) { + //noinspection unchecked super( navigablePath, referencedNavigable, lhs, explicitAlias, nodeBuilder ); } @Override + public PluralPersistentAttribute getReferencedPathSource() { + //noinspection unchecked + return (PluralPersistentAttribute) super.getReferencedPathSource(); + } + + @Override + public PluralPersistentAttribute getNodeType() { + return getReferencedPathSource(); + } + + @Override + public T accept(SemanticQueryWalker walker) { + return walker.visitPluralValuedPath( this ); + } + + @Override + @SuppressWarnings("unchecked") public SemanticPathPart resolvePathPart( String name, String currentContextKey, @@ -62,21 +83,28 @@ public class SqmPluralValuedSimplePath extends AbstractSqmSimplePath { return creationState.getProcessingStateStack().getCurrent().getPathRegistry().resolvePath( navigablePath, np -> { - if ( CollectionElement.NAVIGABLE_NAME.equals( name ) ) { - return getReferencedPathSource().getCollectionDescriptor().getElementDescriptor().createSqmExpression( + final PluralPersistentAttribute referencedPathSource = getReferencedPathSource(); + + if ( CollectionPropertyNames.COLLECTION_ELEMENTS.equals( name ) ) { + return referencedPathSource.getElementPathSource().createSqmPath( this, creationState ); } - if ( CollectionIndex.NAVIGABLE_NAME.equals( name ) ) { - return getReferencedPathSource().getCollectionDescriptor().getIndexDescriptor().createSqmExpression( - this, - creationState - ); + if ( CollectionPropertyNames.COLLECTION_INDEX.equals( name ) + || CollectionPropertyNames.COLLECTION_INDICES.equals( name ) ) { + if ( referencedPathSource instanceof MapPersistentAttribute ) { + return ( (MapPersistentAttribute) referencedPathSource ).getKeyPathSource().createSqmPath( this, creationState ); + } + else if ( referencedPathSource instanceof ListPersistentAttribute ) { + return ( (ListPersistentAttribute) referencedPathSource ).getIndexPathSource().createSqmPath( this, creationState ); + } + + throw new UnsupportedOperationException( ); } - return getReferencedPathSource().getCollectionDescriptor().getElementDescriptor().createSqmExpression( + return referencedPathSource.getElementPathSource().createSqmPath( this, creationState ); @@ -84,17 +112,28 @@ public class SqmPluralValuedSimplePath extends AbstractSqmSimplePath { ); } + @Override + @SuppressWarnings("unchecked") + public SqmTreatedSimplePath treatAs(Class treatJavaType) throws PathException { + final EntityDomainType treatTargetDescriptor = nodeBuilder().getDomainModel().entity( treatJavaType ); + return new SqmTreatedSimplePath( + this, + treatTargetDescriptor, + nodeBuilder() + ); + } + // @Override // public DomainResult createDomainResult( // String resultVariable, // DomainResultCreationState creationState, // DomainResultCreationContext creationContext) { // return new CollectionResultImpl( -// getReferencedNavigable().getCollectionDescriptor().getDescribedAttribute(), +// getReferencedNavigable().getPluralAttribute().getDescribedAttribute(), // getNavigablePath(), // resultVariable, // LockMode.NONE, -// getReferencedNavigable().getCollectionDescriptor().getCollectionKeyDescriptor().createDomainResult( +// getReferencedNavigable().getPluralAttribute().getCollectionKeyDescriptor().createDomainResult( // getNavigablePath().append( "{id}" ), // null, // creationState, @@ -104,34 +143,4 @@ public class SqmPluralValuedSimplePath extends AbstractSqmSimplePath { // ); // } - @Override - public T accept(SemanticQueryWalker walker) { - return walker.visitPluralValuedPath( this ); - } - - @Override - public SqmPathSource getReferencedPathSource() { - return (PluralValuedNavigable) super.getReferencedPathSource(); - } - - @Override - public PluralValuedNavigable getNodeType() { - return getReferencedPathSource(); - } - - @Override - public CollectionJavaDescriptor getJavaTypeDescriptor() { - return (CollectionJavaDescriptor) super.getJavaTypeDescriptor(); - } - - @Override - @SuppressWarnings("unchecked") - public SqmTreatedSimplePath treatAs(Class treatJavaType) throws PathException { - final EntityTypeDescriptor treatTargetDescriptor = nodeBuilder().getDomainModel().entity( treatJavaType ); - return new SqmTreatedSimplePath( - this, - treatTargetDescriptor, - nodeBuilder() - ); - } } diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmPolymorphicRootDescriptor.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmPolymorphicRootDescriptor.java index bb93e6339c..d6da3b6270 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmPolymorphicRootDescriptor.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmPolymorphicRootDescriptor.java @@ -6,9 +6,7 @@ */ package org.hibernate.query.sqm.tree.domain; -import java.io.Serializable; import java.util.ArrayList; -import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; @@ -16,68 +14,30 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.function.Consumer; -import java.util.function.Predicate; +import java.util.stream.Collectors; +import javax.persistence.metamodel.Attribute; import javax.persistence.metamodel.CollectionAttribute; import javax.persistence.metamodel.ListAttribute; import javax.persistence.metamodel.MapAttribute; +import javax.persistence.metamodel.PluralAttribute; import javax.persistence.metamodel.SetAttribute; import javax.persistence.metamodel.SingularAttribute; -import org.hibernate.EntityNameResolver; -import org.hibernate.HibernateException; -import org.hibernate.LockMode; -import org.hibernate.LockOptions; -import org.hibernate.NotYetImplementedFor6Exception; -import org.hibernate.boot.model.domain.spi.ManagedTypeMappingImplementor; -import org.hibernate.bytecode.spi.BytecodeEnhancementMetadata; -import org.hibernate.cache.spi.entry.CacheEntry; -import org.hibernate.cache.spi.entry.CacheEntryStructure; -import org.hibernate.engine.spi.CascadeStyle; -import org.hibernate.engine.spi.EntityEntryFactory; -import org.hibernate.engine.spi.LoadQueryInfluencers; import org.hibernate.engine.spi.SessionFactoryImplementor; -import org.hibernate.engine.spi.SharedSessionContractImplementor; -import org.hibernate.engine.spi.ValueInclusion; import org.hibernate.graph.spi.SubGraphImplementor; -import org.hibernate.internal.FilterAliasGenerator; -import org.hibernate.loader.spi.EntityLocker; -import org.hibernate.loader.spi.MultiIdEntityLoader; -import org.hibernate.loader.spi.MultiIdLoaderSelectors; -import org.hibernate.loader.spi.NaturalIdLoader; -import org.hibernate.loader.spi.SingleIdEntityLoader; -import org.hibernate.loader.spi.SingleUniqueKeyEntityLoader; -import org.hibernate.metamodel.model.creation.spi.RuntimeModelCreationContext; +import org.hibernate.metamodel.RepresentationMode; +import org.hibernate.metamodel.model.domain.DomainType; +import org.hibernate.metamodel.model.domain.EntityDomainType; +import org.hibernate.metamodel.model.domain.IdentifiableDomainType; +import org.hibernate.metamodel.model.domain.ManagedDomainType; import org.hibernate.metamodel.model.domain.NavigableRole; -import org.hibernate.metamodel.model.mapping.spi.EntityHierarchy; -import org.hibernate.metamodel.model.mapping.EntityTypeDescriptor; -import org.hibernate.metamodel.model.mapping.spi.EntityValuedNavigable; -import org.hibernate.metamodel.model.mapping.IdentifiableTypeDescriptor; -import org.hibernate.metamodel.model.mapping.ManagedTypeDescriptor; -import org.hibernate.metamodel.model.mapping.spi.ManagedTypeRepresentationStrategy; -import org.hibernate.metamodel.model.mapping.spi.Navigable; -import org.hibernate.metamodel.model.mapping.spi.NavigableContainer; -import org.hibernate.metamodel.model.mapping.spi.NavigableVisitationStrategy; -import org.hibernate.metamodel.model.mapping.spi.NonIdPersistentAttribute; -import org.hibernate.metamodel.model.mapping.PersistentAttributeDescriptor; -import org.hibernate.metamodel.model.mapping.SimpleTypeDescriptor; -import org.hibernate.metamodel.model.mapping.spi.StateArrayContributor; -import org.hibernate.metamodel.model.mapping.spi.TableReferenceJoinCollector; -import org.hibernate.metamodel.model.relational.spi.JoinedTableBinding; -import org.hibernate.metamodel.model.relational.spi.Table; -import org.hibernate.query.NavigablePath; -import org.hibernate.sql.ast.JoinType; -import org.hibernate.sql.ast.produce.metamodel.spi.Fetchable; -import org.hibernate.sql.ast.produce.spi.ColumnReferenceQualifier; -import org.hibernate.sql.ast.produce.spi.SqlAliasBase; -import org.hibernate.sql.ast.produce.spi.SqlAstCreationState; -import org.hibernate.sql.ast.tree.from.TableGroup; -import org.hibernate.sql.results.spi.DomainResult; -import org.hibernate.sql.results.spi.DomainResultCreationState; -import org.hibernate.type.Type; -import org.hibernate.type.descriptor.java.internal.EntityJavaDescriptorImpl; -import org.hibernate.type.descriptor.java.spi.EntityJavaDescriptor; -import org.hibernate.type.descriptor.java.spi.ImmutableMutabilityPlan; -import org.hibernate.type.descriptor.java.spi.JavaTypeDescriptor; +import org.hibernate.metamodel.model.domain.PersistentAttribute; +import org.hibernate.metamodel.model.domain.PluralPersistentAttribute; +import org.hibernate.metamodel.model.domain.SimpleDomainType; +import org.hibernate.metamodel.model.domain.SingularPersistentAttribute; +import org.hibernate.query.sqm.SqmPathSource; +import org.hibernate.query.sqm.produce.spi.SqmCreationState; +import org.hibernate.type.descriptor.java.JavaTypeDescriptor; import org.hibernate.type.spi.TypeConfiguration; /** @@ -85,32 +45,39 @@ import org.hibernate.type.spi.TypeConfiguration; * * @author Steve Ebersole */ -public class SqmPolymorphicRootDescriptor implements EntityTypeDescriptor { - private final Set> implementors; - private final Map commonAttributes; +public class SqmPolymorphicRootDescriptor implements EntityDomainType { + private final Set> implementors; + private final Map> commonAttributes; private final NavigableRole navigableRole; - private final EntityJavaDescriptor polymorphicJavaDescriptor; + private final JavaTypeDescriptor polymorphicJavaDescriptor; private final SessionFactoryImplementor sessionFactory; public SqmPolymorphicRootDescriptor( JavaTypeDescriptor polymorphicJavaDescriptor, - Set> implementors) { + Set> implementors, + SessionFactoryImplementor sessionFactory) { + this.polymorphicJavaDescriptor = polymorphicJavaDescriptor; + this.navigableRole = new NavigableRole( polymorphicJavaDescriptor.getJavaType().getName() ); + this.sessionFactory = sessionFactory; + this.implementors = implementors; - final HashMap workMap = new HashMap<>(); - final ArrayList> implementorsList = new ArrayList<>( implementors ); + final HashMap workMap = new HashMap<>(); - final EntityTypeDescriptor firstImplementor = implementorsList.get( 0 ).getEntityDescriptor(); + final ArrayList> implementorsList = new ArrayList<>( implementors ); + + final EntityDomainType firstImplementor = implementorsList.get( 0 ); // basically we want to "expose" only the attributes that all the implementors expose... - // - visit all of the attributes defined on the first implementor in the list - final List> subList = implementorsList.subList( 1, implementors.size() - 1 ); + // - visit all of the attributes defined on the first implementor and check it against + // all of the others + final List> subList = implementorsList.subList( 1, implementors.size() - 1 ); firstImplementor.visitAttributes( attribute -> { // for each of its attributes, check whether the other implementors also expose it - for ( EntityValuedNavigable navigable : subList ) { - if ( navigable.findNavigable( attribute.getNavigableName() ) == null ) { + for ( EntityDomainType navigable : subList ) { + if ( navigable.findAttribute( attribute.getName() ) == null ) { // we found an implementor that does not expose that attribute, // so break-out to the next attribute break; @@ -120,99 +87,49 @@ public class SqmPolymorphicRootDescriptor implements EntityTypeDescriptor // // todo (6.0) : Atm We use the attribute from the first implementor directly for each implementor // need to handle this in QuerySplitter somehow - workMap.put( attribute.getNavigableName(), attribute ); + workMap.put( attribute.getName(), attribute ); } } ); this.commonAttributes = Collections.unmodifiableMap( workMap ); - - this.polymorphicJavaDescriptor = resolveEntityJavaTypeDescriptor( polymorphicJavaDescriptor ); - this.navigableRole = new NavigableRole( this.polymorphicJavaDescriptor.getEntityName() ); - this.sessionFactory = firstImplementor.getFactory(); } - - @SuppressWarnings("unchecked") - private EntityJavaDescriptor resolveEntityJavaTypeDescriptor(JavaTypeDescriptor javaTypeDescriptor) { - if ( javaTypeDescriptor instanceof EntityJavaDescriptor ) { - return (EntityJavaDescriptor) javaTypeDescriptor; - } - - return new EntityJavaDescriptorImpl<>( - javaTypeDescriptor.getTypeName(), - javaTypeDescriptor.getTypeName(), - javaTypeDescriptor.getJavaType(), - null, - ImmutableMutabilityPlan.INSTANCE, - null - ); - } - - public Set> getImplementors() { + public Set> getImplementors() { return new HashSet<>( implementors ); } - @Override public SessionFactoryImplementor getFactory() { return sessionFactory; } - @Override public TypeConfiguration getTypeConfiguration() { - return getFactory().getTypeConfiguration(); - } - - - @Override - public EntityJavaDescriptor getJavaTypeDescriptor() { - return polymorphicJavaDescriptor; - } - - @Override - public NavigableContainer getContainer() { - return null; - } - - @Override - public Class getMappedClass() { - return null; - } - - @Override - @SuppressWarnings("unchecked") - public EntityTypeDescriptor getEntityDescriptor() { - return this; - } - @Override - - public IdentifiableTypeDescriptor getSuperTypeDescriptor() { - return null; - } - - @Override - public Collection getSubclassTypes() { - return (Collection) Collections.unmodifiableSet( implementors ); - } - - @Override - public Object getDiscriminatorValue() { - return null; - } - - @Override - public String getEntityName() { - return getJavaType().getName(); - } - - @Override - public String getJpaEntityName() { - return getJavaTypeDescriptor().getJpaEntityName(); + return getFactory().getMetamodel().getTypeConfiguration(); } @Override public String getName() { - return getJavaTypeDescriptor().getJpaEntityName(); + return polymorphicJavaDescriptor.getJavaType().getName(); + } + + @Override + public String getHibernateEntityName() { + return getName(); + } + + @Override + public String getTypeName() { + return getName(); + } + + @Override + public String getPathName() { + return getName(); + } + + @Override + public DomainType getSqmPathType() { + return this; } @Override @@ -221,172 +138,250 @@ public class SqmPolymorphicRootDescriptor implements EntityTypeDescriptor } @Override - public Class getBindableJavaType() { - return getJavaTypeDescriptor().getJavaType(); + public Class getBindableJavaType() { + return polymorphicJavaDescriptor.getJavaType(); } @Override - public NavigableRole getNavigableRole() { - return navigableRole; + public PersistenceType getPersistenceType() { + return PersistenceType.ENTITY; } @Override - public String asLoggableText() { - return "PolymorphicEntityValuedNavigable( " + getEntityName() + ")"; + public Class getJavaType() { + return getBindableJavaType(); } @Override - public Navigable findNavigable(String navigableName) { - // only return navigables that all of the implementors define - Navigable navigable = null; - for ( EntityTypeDescriptor implementor : implementors ) { - final Navigable current = implementor.findNavigable( navigableName ); - if ( current == null ) { - return null; - } - if ( navigable == null ) { - navigable = current; - } + public JavaTypeDescriptor getExpressableJavaTypeDescriptor() { + return polymorphicJavaDescriptor; + } + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Attribute handling + + @Override + @SuppressWarnings("unchecked") + public PersistentAttribute findAttribute(String name) { + return commonAttributes.get( name ); + } + + @Override + public void visitAttributes(Consumer> action) { + commonAttributes.values().forEach( action ); + } + + @Override + public void visitDeclaredAttributes(Consumer> action) { + } + + @Override + public PersistentAttribute getAttribute(String name) { + final PersistentAttribute attribute = findAttribute( name ); + if ( attribute == null ) { + // per-JPA + throw new IllegalArgumentException(); } - - return navigable; + return attribute; } @Override - public void visitDeclaredNavigables(NavigableVisitationStrategy visitor) { - // nothing to do + public PersistentAttribute getDeclaredAttribute(String name) { + throw new IllegalArgumentException(); } @Override - public Navigable findDeclaredNavigable(String navigableName) { + public SingularPersistentAttribute findSingularAttribute(String name) { + //noinspection unchecked + return (SingularPersistentAttribute) findAttribute( name ); + } + + @Override + public PluralPersistentAttribute findPluralAttribute(String name) { + //noinspection unchecked + return (PluralPersistentAttribute) findAttribute( name ); + } + + @Override + public PersistentAttribute findDeclaredAttribute(String name) { return null; } @Override - public boolean isSubclassTypeName(String name) { - for ( EntityTypeDescriptor implementor : implementors ) { - final EntityJavaDescriptor implementorJtd = implementor.getJavaTypeDescriptor(); - if ( implementorJtd.getEntityName().equals( name ) - || implementorJtd.getJpaEntityName().equals( name ) - || implementorJtd.getTypeName().equals( name ) ) { - return true; - } - if ( implementor.isSubclassTypeName( name ) ) { - return true; - } - } - - return false; + public SingularPersistentAttribute findDeclaredSingularAttribute(String name) { + return null; } @Override - public boolean finishInitialization( - ManagedTypeMappingImplementor bootDescriptor, - RuntimeModelCreationContext creationContext) { - // nothing to do here - return true; - } - - - - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // todo (6.0) : yet to implement - - - @Override - public EntityHierarchy getHierarchy() { - throw new NotYetImplementedFor6Exception(); + public PluralPersistentAttribute findDeclaredPluralAttribute(String name) { + return null; } @Override - public boolean canReadFromCache() { - throw new NotYetImplementedFor6Exception( getClass() ); + public Set> getAttributes() { + //noinspection unchecked + return (Set>) commonAttributes; } @Override - public boolean canWriteToCache() { - throw new NotYetImplementedFor6Exception( getClass() ); + public Set> getDeclaredAttributes() { + return Collections.emptySet(); } @Override - public void visitNavigables(NavigableVisitationStrategy visitor) { - // todo (6.0) : not sure how visitation should work here - throw new NotYetImplementedFor6Exception(); + public SingularAttribute getSingularAttribute(String name, Class type) { + //noinspection unchecked + return (SingularAttribute) getAttribute( name ); } @Override - public void visitFetchables(Consumer fetchableConsumer) { - // none + public SingularAttribute getDeclaredSingularAttribute(String name, Class type) { + //noinspection unchecked + return (SingularAttribute) getDeclaredAttribute( name ); } @Override - public void visitNavigable(NavigableVisitationStrategy visitor) { - // todo (6.0) : not sure how visitation should work here - throw new NotYetImplementedFor6Exception(); + public Set> getSingularAttributes() { + //noinspection unchecked + return (Set) commonAttributes.values().stream() + .filter( attribute -> attribute instanceof SingularAttribute ) + .collect( Collectors.toSet() ); } @Override - public DomainResult createDomainResult( - NavigablePath navigablePath, - String resultVariable, - DomainResultCreationState creationState) { - throw new NotYetImplementedFor6Exception(); + public Set> getDeclaredSingularAttributes() { + return Collections.emptySet(); } @Override - public TableGroup createRootTableGroup( - NavigablePath navigablePath, - String explicitSourceAlias, - JoinType tableReferenceJoinType, - LockMode lockMode, - SqlAstCreationState creationState) { - throw new UnsupportedOperationException( ); + public CollectionAttribute getCollection(String name, Class elementType) { + //noinspection unchecked + return (CollectionAttribute) getAttribute( name ); } @Override - public boolean isNullable() { - return false; + public CollectionAttribute getDeclaredCollection(String name, Class elementType) { + throw new IllegalArgumentException(); + } + + @Override + public SetAttribute getSet(String name, Class elementType) { + //noinspection unchecked + return (SetAttribute) getAttribute( name ); + } + + @Override + public SetAttribute getDeclaredSet(String name, Class elementType) { + throw new IllegalArgumentException( ); + } + + @Override + public ListAttribute getList(String name, Class elementType) { + //noinspection unchecked + return (ListAttribute) getAttribute( name ); + } + + @Override + public ListAttribute getDeclaredList(String name, Class elementType) { + throw new IllegalArgumentException(); + } + + @Override + public MapAttribute getMap(String name, Class keyType, Class valueType) { + //noinspection unchecked + return (MapAttribute) getAttribute( name ); + } + + @Override + public MapAttribute getDeclaredMap(String name, Class keyType, Class valueType) { + throw new IllegalArgumentException(); + } + + @Override + public Set> getPluralAttributes() { + //noinspection unchecked + return (Set) commonAttributes.values().stream() + .filter( attribute -> attribute instanceof PluralAttribute ) + .collect( Collectors.toSet() ); + } + + @Override + public Set> getDeclaredPluralAttributes() { + return Collections.emptySet(); + } + + @Override + public SingularAttribute getSingularAttribute(String name) { + //noinspection unchecked + return (SingularAttribute) getAttribute( name ); + } + + @Override + public SingularAttribute getDeclaredSingularAttribute(String name) { + throw new IllegalArgumentException(); + } + + @Override + public CollectionAttribute getCollection(String name) { + //noinspection unchecked + return (CollectionAttribute) getAttribute( name ); + } + + @Override + public CollectionAttribute getDeclaredCollection(String name) { + throw new IllegalArgumentException(); + } + + @Override + public SetAttribute getSet(String name) { + //noinspection unchecked + return (SetAttribute) getAttribute( name ); + } + + @Override + public SetAttribute getDeclaredSet(String name) { + throw new IllegalArgumentException(); + } + + @Override + public ListAttribute getList(String name) { + //noinspection unchecked + return (ListAttribute) getAttribute( name ); + } + + @Override + public ListAttribute getDeclaredList(String name) { + throw new IllegalArgumentException(); + } + + @Override + public MapAttribute getMap(String name) { + //noinspection unchecked + return (MapAttribute) getAttribute( name ); + } + + @Override + public MapAttribute getDeclaredMap(String name) { + throw new IllegalArgumentException(); + } + + @Override + public SqmPathSource findSubPathSource(String name) { + return (SqmPathSource) findAttribute( name ); + } + + @Override + public SqmPath createSqmPath(SqmPath lhs, SqmCreationState creationState) { + throw new UnsupportedOperationException(); } // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // todo (6.0) : decide what to do for these. - // they are examples of some of the unwanted leakages mentioned on - // Navigable and NavigableSource - - - - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // unsupported operations + // Unsupported operations @Override - public ManagedTypeRepresentationStrategy getRepresentationStrategy() { - throw new UnsupportedOperationException( ); - } - - @Override - public List> getStateArrayContributors() { - throw new UnsupportedOperationException( ); - } - - @Override - public NonIdPersistentAttribute findPersistentAttribute(String name) { - throw new UnsupportedOperationException( ); - } - - @Override - public NonIdPersistentAttribute findDeclaredPersistentAttribute(String name) { - throw new UnsupportedOperationException( ); - } - - @Override - public List getPersistentAttributes() { - throw new UnsupportedOperationException( ); - } - - @Override - public List getDeclaredPersistentAttributes() { - throw new UnsupportedOperationException( ); + public RepresentationMode getRepresentationMode() { + return RepresentationMode.POJO; } @Override @@ -400,424 +395,68 @@ public class SqmPolymorphicRootDescriptor implements EntityTypeDescriptor } @Override - public ManagedTypeDescriptor findSubType(String subTypeName) { + public ManagedDomainType findSubType(String subTypeName) { // technically we could support this throw new UnsupportedOperationException( ); } @Override - public ManagedTypeDescriptor findSubType(Class type) { + public ManagedDomainType findSubType(Class type) { // technically we could support this throw new UnsupportedOperationException( ); } @Override - public void visitStateArrayContributors(Consumer consumer) { + public SingularPersistentAttribute getId(Class type) { throw new UnsupportedOperationException( ); } @Override - public EntityEntryFactory getEntityEntryFactory() { + public SingularPersistentAttribute getDeclaredId(Class type) { throw new UnsupportedOperationException( ); } @Override - public BytecodeEnhancementMetadata getBytecodeEnhancementMetadata() { + public SingularPersistentAttribute getVersion(Class type) { throw new UnsupportedOperationException( ); } @Override - public Table getPrimaryTable() { + public SingularPersistentAttribute getDeclaredVersion(Class type) { throw new UnsupportedOperationException( ); } @Override - public List getSecondaryTableBindings() { + public Set> getIdClassAttributes() { throw new UnsupportedOperationException( ); } @Override - public SingleIdEntityLoader getSingleIdLoader() { + public SimpleDomainType getIdType() { throw new UnsupportedOperationException( ); } @Override - public MultiIdEntityLoader getMultiIdLoader(MultiIdLoaderSelectors selectors) { + public IdentifiableDomainType getSupertype() { throw new UnsupportedOperationException( ); } @Override - public NaturalIdLoader getNaturalIdLoader() { + public boolean hasIdClass() { throw new UnsupportedOperationException( ); } @Override - public SingleUniqueKeyEntityLoader getSingleUniqueKeyLoader( - Navigable navigable, LoadQueryInfluencers loadQueryInfluencers) { + public SingularPersistentAttribute findIdAttribute() { throw new UnsupportedOperationException( ); } @Override - public EntityLocker getLocker( - LockOptions lockOptions, LoadQueryInfluencers loadQueryInfluencers) { - throw new UnsupportedOperationException( ); - } - - @Override - public void lock( - Object id, - Object version, - Object object, - LockMode lockMode, - SharedSessionContractImplementor session) { - throw new UnsupportedOperationException( ); - } - - @Override - public void lock( - Object id, - Object version, - Object object, - LockOptions lockOptions, - SharedSessionContractImplementor session) { - throw new UnsupportedOperationException( ); - } - - @Override - public Set getAffectedTableNames() { - throw new UnsupportedOperationException( ); - } - - @Override - public List getEntityNameResolvers() { - throw new UnsupportedOperationException( ); - } - - @Override - public boolean hasProxy() { - throw new UnsupportedOperationException( ); - } - - @Override - public int[] findDirty( - Object[] currentState, - Object[] previousState, - Object owner, - SharedSessionContractImplementor session) { - throw new UnsupportedOperationException( ); - } - - @Override - public int[] findModified( - Object[] old, - Object[] current, - Object object, - SharedSessionContractImplementor session) { - throw new UnsupportedOperationException( ); - } - - @Override - public void insert( - Object id, - Object[] fields, - Object object, - SharedSessionContractImplementor session) { - throw new UnsupportedOperationException( ); - } - - @Override - public Object insert( - Object[] fields, - Object object, - SharedSessionContractImplementor session) { - throw new UnsupportedOperationException( ); - } - - @Override - public void delete( - Object id, - Object version, - Object object, - SharedSessionContractImplementor session) { - throw new UnsupportedOperationException( ); - } - - @Override - public void update( - Object id, - Object[] fields, - int[] dirtyFields, - boolean hasDirtyCollection, - Object[] oldFields, - Object oldVersion, - Object object, - Object rowId, - SharedSessionContractImplementor session) { - throw new UnsupportedOperationException( ); - } - - @Override - public boolean hasCascades() { - throw new UnsupportedOperationException( ); - } - - @Override - public Type getIdentifierType() { - throw new UnsupportedOperationException( ); - } - - @Override - public String getIdentifierPropertyName() { - throw new UnsupportedOperationException( ); - } - - @Override - public boolean isCacheInvalidationRequired() { - throw new UnsupportedOperationException( ); - } - - @Override - public boolean isLazyPropertiesCacheable() { - throw new UnsupportedOperationException( ); - } - - @Override - public CacheEntryStructure getCacheEntryStructure() { - throw new UnsupportedOperationException( ); - } - - @Override - public CacheEntry buildCacheEntry( - Object entity, - Object[] state, - Object version, - SharedSessionContractImplementor session) { - throw new UnsupportedOperationException( ); - } - - @Override - public boolean isBatchLoadable() { - throw new UnsupportedOperationException( ); - } - - @Override - public boolean isSelectBeforeUpdateRequired() { - throw new UnsupportedOperationException( ); - } - - @Override - public Object[] getDatabaseSnapshot(Object id, SharedSessionContractImplementor session) { - throw new UnsupportedOperationException( ); - } - - @Override - public Serializable getIdByUniqueKey( - Serializable key, - String uniquePropertyName, - SharedSessionContractImplementor session) { - throw new UnsupportedOperationException( ); - } - - @Override - public Object getCurrentVersion(Object id, SharedSessionContractImplementor session) { - throw new UnsupportedOperationException( ); - } - - @Override - public Object forceVersionIncrement( - Object id, - Object currentVersion, - SharedSessionContractImplementor session) { - throw new UnsupportedOperationException( ); - } - - @Override - public boolean isInstrumented() { - throw new UnsupportedOperationException( ); - } - - @Override - public void afterInitialize(Object entity, SharedSessionContractImplementor session) { - throw new UnsupportedOperationException( ); - } - - @Override - public void afterReassociate(Object entity, SharedSessionContractImplementor session) { - throw new UnsupportedOperationException( ); - } - - @Override - public Object createProxy(Object id, SharedSessionContractImplementor session) throws HibernateException { - throw new UnsupportedOperationException( ); - } - - @Override - public Boolean isTransient(Object object, SharedSessionContractImplementor session) throws HibernateException { - throw new UnsupportedOperationException( ); - } - - @Override - public Object[] getPropertyValuesToInsert( - Object object, - Map mergeMap, - SharedSessionContractImplementor session) { - throw new UnsupportedOperationException( ); - } - - @Override - public void processInsertGeneratedProperties( - Object id, - Object entity, - Object[] state, - SharedSessionContractImplementor session) { - throw new UnsupportedOperationException( ); - } - - @Override - public void processUpdateGeneratedProperties( - Object id, - Object entity, - Object[] state, - SharedSessionContractImplementor session) { - throw new UnsupportedOperationException( ); - } - - @Override - public boolean implementsLifecycle() { - throw new UnsupportedOperationException( ); - } - - @Override - public Class getConcreteProxyClass() { - throw new UnsupportedOperationException( ); - } - - @Override - public Serializable getIdentifier(Object entity) { - throw new UnsupportedOperationException( ); - } - - @Override - public void setIdentifier(Object entity, Object id, SharedSessionContractImplementor session) { - throw new UnsupportedOperationException( ); - } - - @Override - public Object getVersion(Object object) { - throw new UnsupportedOperationException( ); - } - - @Override - public Object instantiate(Object id, SharedSessionContractImplementor session) { - throw new UnsupportedOperationException( ); - } - - @Override - public boolean isInstance(Object object) { - throw new UnsupportedOperationException( ); - } - - @Override - public boolean hasUninitializedLazyProperties(Object object) { - throw new UnsupportedOperationException( ); - } - - @Override - public void resetIdentifier( - Object entity, - Object currentId, - Object currentVersion, - SharedSessionContractImplementor session) { - throw new UnsupportedOperationException( ); - } - - @Override - public FilterAliasGenerator getFilterAliasGenerator(String rootAlias) { - throw new UnsupportedOperationException( ); - } - - @Override - public int[] resolveAttributeIndexes(String[] attributeNames) { - throw new UnsupportedOperationException( ); - } - - @Override - public boolean canUseReferenceCacheEntries() { - throw new UnsupportedOperationException( ); - } - - @Override - public void registerAffectingFetchProfile(String fetchProfileName) { - throw new UnsupportedOperationException( ); - } - - @Override - public boolean hasNaturalIdentifier() { - throw new UnsupportedOperationException( ); - } - - @Override - public boolean hasCollections() { - throw new UnsupportedOperationException( ); - } - - @Override - public org.hibernate.type.descriptor.java.JavaTypeDescriptor[] getPropertyJavaTypeDescriptors() { - throw new UnsupportedOperationException( ); - } - - @Override - public String[] getPropertyNames() { - throw new UnsupportedOperationException( ); - } - - @Override - public ValueInclusion[] getPropertyInsertGenerationInclusions() { - throw new UnsupportedOperationException( ); - } - - @Override - public ValueInclusion[] getPropertyUpdateGenerationInclusions() { - throw new UnsupportedOperationException( ); - } - - @Override - public boolean[] getPropertyUpdateability() { - throw new UnsupportedOperationException( ); - } - - @Override - public boolean[] getPropertyVersionability() { - throw new UnsupportedOperationException( ); - } - - @Override - public boolean[] getPropertyLaziness() { - throw new UnsupportedOperationException( ); - } - - @Override - public CascadeStyle[] getPropertyCascadeStyles() { - throw new UnsupportedOperationException( ); - } - - @Override - public SingularAttribute getId(Class type) { - throw new UnsupportedOperationException( ); - } - - @Override - public SingularAttribute getDeclaredId(Class type) { - throw new UnsupportedOperationException( ); - } - - @Override - public SingularAttribute getVersion(Class type) { - throw new UnsupportedOperationException( ); + public void visitIdClassAttributes(Consumer> action) { } @Override - public SingularAttribute getDeclaredVersion(Class type) { + public SingularPersistentAttribute findVersionAttribute() { throw new UnsupportedOperationException( ); } @@ -832,238 +471,7 @@ public class SqmPolymorphicRootDescriptor implements EntityTypeDescriptor } @Override - public Set getIdClassAttributes() { + public ManagedDomainType getSuperType() { throw new UnsupportedOperationException( ); } - - @Override - public SimpleTypeDescriptor getIdType() { - throw new UnsupportedOperationException( ); - } - - @Override - public boolean isAffectedByEnabledFilters(LoadQueryInfluencers loadQueryInfluencers) { - for ( EntityTypeDescriptor implementor : implementors ) { - if ( implementor.isAffectedByEnabledFilters( loadQueryInfluencers ) ) { - return true; - } - } - - return false; - } - - @Override - public boolean isAffectedByEnabledFetchProfiles(LoadQueryInfluencers loadQueryInfluencers) { - for ( EntityTypeDescriptor implementor : implementors ) { - if ( implementor.isAffectedByEnabledFetchProfiles( loadQueryInfluencers ) ) { - return true; - } - } - - return false; - } - - @Override - public boolean isAffectedByEntityGraph(LoadQueryInfluencers loadQueryInfluencers) { - for ( EntityTypeDescriptor implementor : implementors ) { - if ( implementor.isAffectedByEntityGraph( loadQueryInfluencers ) ) { - return true; - } - } - - return false; - } - - @Override - public Set getAttributes() { - throw new UnsupportedOperationException( ); - } - - @Override - public Set getDeclaredAttributes() { - throw new UnsupportedOperationException( ); - } - - @Override - public Set getSingularAttributes() { - throw new UnsupportedOperationException( ); - } - - @Override - public Set getDeclaredSingularAttributes() { - throw new UnsupportedOperationException( ); - } - - @Override - public Set getPluralAttributes() { - throw new UnsupportedOperationException( ); - } - - @Override - public Set getDeclaredPluralAttributes() { - throw new UnsupportedOperationException( ); - } - - @Override - public PersistentAttributeDescriptor getAttribute(String name) { - throw new UnsupportedOperationException( ); - } - - @Override - public PersistentAttributeDescriptor getDeclaredAttribute(String name) { - throw new UnsupportedOperationException( ); - } - - @Override - public SingularAttribute getSingularAttribute(String name) { - throw new UnsupportedOperationException( ); - } - - @Override - public SingularAttribute getDeclaredSingularAttribute(String name) { - throw new UnsupportedOperationException( ); - } - - @Override - public CollectionAttribute getCollection(String name) { - throw new UnsupportedOperationException( ); - } - - @Override - public CollectionAttribute getDeclaredCollection(String name) { - throw new UnsupportedOperationException( ); - } - - @Override - public SetAttribute getSet(String name) { - throw new UnsupportedOperationException( ); - } - - @Override - public SetAttribute getDeclaredSet(String name) { - throw new UnsupportedOperationException( ); - } - - @Override - public ListAttribute getList(String name) { - throw new UnsupportedOperationException( ); - } - - @Override - public ListAttribute getDeclaredList(String name) { - throw new UnsupportedOperationException( ); - } - - @Override - public MapAttribute getMap(String name) { - throw new UnsupportedOperationException( ); - } - - @Override - public MapAttribute getDeclaredMap(String name) { - throw new UnsupportedOperationException( ); - } - - @Override - public MapAttribute getDeclaredMap(String name, Class keyType, Class valueType) { - throw new UnsupportedOperationException( ); - } - - @Override - public MapAttribute getMap(String name, Class keyType, Class valueType) { - throw new UnsupportedOperationException( ); - } - - @Override - public ListAttribute getDeclaredList(String name, Class elementType) { - throw new UnsupportedOperationException( ); - } - - @Override - public ListAttribute getList(String name, Class elementType) { - throw new UnsupportedOperationException( ); - } - - @Override - public SetAttribute getDeclaredSet(String name, Class elementType) { - throw new UnsupportedOperationException( ); - } - - @Override - public SetAttribute getSet(String name, Class elementType) { - throw new UnsupportedOperationException( ); - } - - @Override - public CollectionAttribute getDeclaredCollection(String name, Class elementType) { - throw new UnsupportedOperationException( ); - } - - @Override - public CollectionAttribute getCollection(String name, Class elementType) { - throw new UnsupportedOperationException( ); - } - - @Override - public SingularAttribute getDeclaredSingularAttribute(String name, Class type) { - throw new UnsupportedOperationException( ); - } - - @Override - public SingularAttribute getSingularAttribute(String name, Class type) { - throw new UnsupportedOperationException( ); - } - - @Override - public boolean canCompositeContainCollections() { - throw new UnsupportedOperationException( ); - } - - @Override - public void applyTableReferenceJoins( - ColumnReferenceQualifier lhs, - JoinType joinType, - SqlAliasBase sqlAliasBase, - TableReferenceJoinCollector joinCollector) { - throw new UnsupportedOperationException( ); - } - - @Override - public String getSqlAliasStem() { - throw new UnsupportedOperationException( ); - } - - @Override - public EntityTypeDescriptor getSubclassEntityPersister( - Object instance, - SessionFactoryImplementor factory) { - throw new UnsupportedOperationException( ); - } - - @Override - public InFlightAccess getInFlightAccess() { - throw new UnsupportedOperationException( ); - } - - @Override - public void visitSubTypeDescriptors(Consumer> action) { - for ( EntityTypeDescriptor implementor : implementors ) { - action.accept( (EntityTypeDescriptor) implementor ); - } - } - - @Override - public void visitAllSubTypeDescriptors(Consumer> action) { - for ( EntityTypeDescriptor implementor : implementors ) { - action.accept( (IdentifiableTypeDescriptor) implementor ); - implementor.visitAllSubTypeDescriptors( (Consumer) action ); - } - - } - - @Override - public IdentifiableTypeDescriptor findMatchingSubTypeDescriptors(Predicate> matcher) { - return null; - } - } diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmSetJoin.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmSetJoin.java index 0b41b46b51..3bb48aac0f 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmSetJoin.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmSetJoin.java @@ -14,17 +14,17 @@ import javax.persistence.metamodel.PluralAttribute; import javax.persistence.metamodel.SingularAttribute; import org.hibernate.NotYetImplementedFor6Exception; -import org.hibernate.metamodel.model.mapping.EntityTypeDescriptor; -import org.hibernate.metamodel.model.mapping.spi.SetPersistentAttribute; +import org.hibernate.metamodel.model.domain.EntityDomainType; +import org.hibernate.metamodel.model.domain.SetPersistentAttribute; import org.hibernate.query.criteria.JpaExpression; import org.hibernate.query.criteria.JpaPredicate; import org.hibernate.query.criteria.JpaSetJoin; import org.hibernate.query.criteria.JpaSubQuery; import org.hibernate.query.sqm.NodeBuilder; -import org.hibernate.query.sqm.SqmPathSource; import org.hibernate.query.sqm.tree.SqmJoinType; import org.hibernate.query.sqm.tree.from.SqmAttributeJoin; import org.hibernate.query.sqm.tree.from.SqmFrom; +import org.hibernate.type.descriptor.java.JavaTypeDescriptor; /** * @author Steve Ebersole @@ -32,6 +32,7 @@ import org.hibernate.query.sqm.tree.from.SqmFrom; public class SqmSetJoin extends AbstractSqmPluralJoin, E> implements JpaSetJoin { + @SuppressWarnings("WeakerAccess") public SqmSetJoin( SqmFrom lhs, SetPersistentAttribute pluralValuedNavigable, @@ -43,10 +44,16 @@ public class SqmSetJoin } @Override - public SqmPathSource getReferencedPathSource() { + public SetPersistentAttribute getReferencedPathSource() { + //noinspection unchecked return (SetPersistentAttribute) super.getReferencedPathSource(); } + @Override + public JavaTypeDescriptor getJavaTypeDescriptor() { + return getReferencedPathSource().getExpressableJavaTypeDescriptor(); + } + @Override public SetPersistentAttribute getModel() { return getReferencedPathSource(); @@ -84,7 +91,7 @@ public class SqmSetJoin @Override public SqmTreatedSetJoin treatAs(Class treatAsType) { - final EntityTypeDescriptor entityTypeDescriptor = nodeBuilder().getDomainModel().entity( treatAsType ); + final EntityDomainType entityTypeDescriptor = nodeBuilder().getDomainModel().entity( treatAsType ); return new SqmTreatedSetJoin<>( this, entityTypeDescriptor, null ); } diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmSingularJoin.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmSingularJoin.java index 745d6c77bc..4d0832cf42 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmSingularJoin.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmSingularJoin.java @@ -9,11 +9,12 @@ package org.hibernate.query.sqm.tree.domain; import java.util.Locale; import org.hibernate.metamodel.model.domain.EntityDomainType; +import org.hibernate.metamodel.model.domain.SingularPersistentAttribute; import org.hibernate.query.criteria.PathException; import org.hibernate.query.sqm.NodeBuilder; -import org.hibernate.query.sqm.SqmJoinable; import org.hibernate.query.sqm.tree.SqmJoinType; import org.hibernate.query.sqm.tree.from.SqmFrom; +import org.hibernate.type.descriptor.java.JavaTypeDescriptor; /** * @author Steve Ebersole @@ -21,7 +22,7 @@ import org.hibernate.query.sqm.tree.from.SqmFrom; public class SqmSingularJoin extends AbstractSqmAttributeJoin { public SqmSingularJoin( SqmFrom lhs, - SqmJoinable joinedNavigable, + SingularPersistentAttribute joinedNavigable, String alias, SqmJoinType joinType, boolean fetched, @@ -29,10 +30,16 @@ public class SqmSingularJoin extends AbstractSqmAttributeJoin { super( lhs, joinedNavigable, alias, joinType, fetched, nodeBuilder ); } + @Override + public JavaTypeDescriptor getJavaTypeDescriptor() { + return getNodeJavaTypeDescriptor(); + } + @Override public SqmTreatedSingularJoin treatAs(Class treatJavaType) throws PathException { final EntityDomainType targetDescriptor = nodeBuilder().getDomainModel().entity( treatJavaType ); - return new SqmTreatedSingularJoin<>( this, targetDescriptor, null ); + //noinspection unchecked + return new SqmTreatedSingularJoin( this, targetDescriptor, null ); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmTreatedBagJoin.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmTreatedBagJoin.java index 9f34bc594b..2e55e36d0b 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmTreatedBagJoin.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmTreatedBagJoin.java @@ -6,21 +6,20 @@ */ package org.hibernate.query.sqm.tree.domain; -import org.hibernate.metamodel.model.mapping.spi.BagPersistentAttribute; -import org.hibernate.metamodel.model.mapping.EntityTypeDescriptor; -import org.hibernate.query.sqm.SqmPathSource; +import org.hibernate.metamodel.model.domain.BagPersistentAttribute; +import org.hibernate.metamodel.model.domain.EntityDomainType; /** * @author Steve Ebersole */ public class SqmTreatedBagJoin extends SqmBagJoin implements SqmTreatedPath { private final SqmBagJoin wrappedPath; - private final EntityTypeDescriptor treatTarget; + private final EntityDomainType treatTarget; @SuppressWarnings("unchecked") public SqmTreatedBagJoin( SqmBagJoin wrappedPath, - EntityTypeDescriptor treatTarget, + EntityDomainType treatTarget, String alias) { super( wrappedPath.getLhs(), @@ -40,19 +39,7 @@ public class SqmTreatedBagJoin extends SqmBagJoin impleme } @Override - public EntityTypeDescriptor getTreatTarget() { + public EntityDomainType getTreatTarget() { return treatTarget; } - - @Override - @SuppressWarnings("unchecked") - public SqmPathSource getReferencedPathSource() { - return super.getReferencedPathSource(); - } - - @Override - @SuppressWarnings("unchecked") - public BagPersistentAttribute getModel() { - return getReferencedPathSource(); - } } diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmTreatedCrossJoin.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmTreatedCrossJoin.java index 41542b9b2a..ca07ae38ba 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmTreatedCrossJoin.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmTreatedCrossJoin.java @@ -6,8 +6,7 @@ */ package org.hibernate.query.sqm.tree.domain; -import org.hibernate.metamodel.model.mapping.EntityTypeDescriptor; -import org.hibernate.query.sqm.SqmPathSource; +import org.hibernate.metamodel.model.domain.EntityDomainType; import org.hibernate.query.sqm.tree.from.SqmCrossJoin; /** @@ -15,14 +14,15 @@ import org.hibernate.query.sqm.tree.from.SqmCrossJoin; */ public class SqmTreatedCrossJoin extends SqmCrossJoin implements SqmTreatedPath { private final SqmCrossJoin wrappedPath; - private final EntityTypeDescriptor treatTarget; + private final EntityDomainType treatTarget; public SqmTreatedCrossJoin( SqmCrossJoin wrappedPath, String alias, - EntityTypeDescriptor treatTarget) { + EntityDomainType treatTarget) { + //noinspection unchecked super( - (EntityTypeDescriptor) wrappedPath.getReferencedPathSource(), + (EntityDomainType) wrappedPath.getReferencedPathSource().getSqmPathType(), alias, wrappedPath.getRoot() ); @@ -31,12 +31,12 @@ public class SqmTreatedCrossJoin extends SqmCrossJoin implemen } @Override - public EntityTypeDescriptor getTreatTarget() { + public EntityDomainType getTreatTarget() { return treatTarget; } @Override - public EntityTypeDescriptor getModel() { + public EntityDomainType getModel() { return getTreatTarget(); } @@ -46,7 +46,8 @@ public class SqmTreatedCrossJoin extends SqmCrossJoin implemen } @Override - public SqmPathSource getReferencedPathSource() { - return (EntityTypeDescriptor) wrappedPath.getReferencedPathSource(); + public EntityDomainType getReferencedPathSource() { + //noinspection unchecked + return (EntityDomainType) wrappedPath.getReferencedPathSource(); } } diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmTreatedEntityJoin.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmTreatedEntityJoin.java index e828ee01ae..6d14045b05 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmTreatedEntityJoin.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmTreatedEntityJoin.java @@ -6,8 +6,7 @@ */ package org.hibernate.query.sqm.tree.domain; -import org.hibernate.metamodel.model.mapping.EntityTypeDescriptor; -import org.hibernate.query.sqm.SqmPathSource; +import org.hibernate.metamodel.model.domain.EntityDomainType; import org.hibernate.query.sqm.tree.SqmJoinType; import org.hibernate.query.sqm.tree.from.SqmEntityJoin; @@ -16,11 +15,11 @@ import org.hibernate.query.sqm.tree.from.SqmEntityJoin; */ public class SqmTreatedEntityJoin extends SqmEntityJoin implements SqmTreatedPath { private final SqmEntityJoin wrapped; - private final EntityTypeDescriptor treatTarget; + private final EntityDomainType treatTarget; public SqmTreatedEntityJoin( SqmEntityJoin wrapped, - EntityTypeDescriptor treatTarget, + EntityDomainType treatTarget, String alias, SqmJoinType joinType) { super( @@ -34,7 +33,7 @@ public class SqmTreatedEntityJoin extends SqmEntityJoin imple } @Override - public EntityTypeDescriptor getTreatTarget() { + public EntityDomainType getTreatTarget() { return treatTarget; } @@ -44,7 +43,8 @@ public class SqmTreatedEntityJoin extends SqmEntityJoin imple } @Override - public SqmPathSource getReferencedPathSource() { - return super.getReferencedPathSource(); + public EntityDomainType getReferencedPathSource() { + //noinspection unchecked + return (EntityDomainType) wrapped.getReferencedPathSource(); } } diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmTreatedListJoin.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmTreatedListJoin.java index 979786ca9e..95d81f8a7f 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmTreatedListJoin.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmTreatedListJoin.java @@ -6,20 +6,21 @@ */ package org.hibernate.query.sqm.tree.domain; -import org.hibernate.metamodel.model.mapping.EntityTypeDescriptor; -import org.hibernate.metamodel.model.mapping.spi.ListPersistentAttribute; -import org.hibernate.query.sqm.SqmPathSource; +import org.hibernate.metamodel.model.domain.EntityDomainType; +import org.hibernate.metamodel.model.domain.ListPersistentAttribute; +import org.hibernate.query.sqm.produce.spi.SqmCreationState; +import org.hibernate.query.sqm.tree.expression.SqmExpression; /** * @author Steve Ebersole */ public class SqmTreatedListJoin extends SqmListJoin implements SqmTreatedPath { private final SqmListJoin wrappedPath; - private final EntityTypeDescriptor treatTarget; + private final EntityDomainType treatTarget; public SqmTreatedListJoin( SqmListJoin wrappedPath, - EntityTypeDescriptor treatTarget, + EntityDomainType treatTarget, String alias) { //noinspection unchecked super( @@ -40,19 +41,21 @@ public class SqmTreatedListJoin extends SqmListJoin imple } @Override - public EntityTypeDescriptor getTreatTarget() { + public ListPersistentAttribute getModel() { + return (ListPersistentAttribute) super.getModel(); + } + + @Override + public EntityDomainType getTreatTarget() { return treatTarget; } @Override - @SuppressWarnings("unchecked") - public SqmPathSource getReferencedPathSource() { - return super.getReferencedPathSource(); - } - - @Override - @SuppressWarnings("unchecked") - public ListPersistentAttribute getModel() { - return getReferencedPathSource(); + public SqmPath resolveIndexedAccess( + SqmExpression selector, + String currentContextKey, + boolean isTerminal, + SqmCreationState creationState) { + return getWrappedPath().resolveIndexedAccess( selector, currentContextKey, isTerminal, creationState ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmTreatedMapJoin.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmTreatedMapJoin.java index 4d09e1deb6..94ab8ea325 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmTreatedMapJoin.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmTreatedMapJoin.java @@ -6,25 +6,24 @@ */ package org.hibernate.query.sqm.tree.domain; -import org.hibernate.metamodel.model.mapping.EntityTypeDescriptor; -import org.hibernate.metamodel.model.mapping.spi.MapPersistentAttribute; -import org.hibernate.query.sqm.SqmPathSource; +import org.hibernate.metamodel.model.domain.EntityDomainType; +import org.hibernate.type.descriptor.java.JavaTypeDescriptor; /** * @author Steve Ebersole */ public class SqmTreatedMapJoin extends SqmMapJoin implements SqmTreatedPath { private final SqmMapJoin wrappedPath; - private final EntityTypeDescriptor treatTarget; + private final EntityDomainType treatTarget; public SqmTreatedMapJoin( SqmMapJoin wrappedPath, - EntityTypeDescriptor treatTarget, + EntityDomainType treatTarget, String alias) { //noinspection unchecked super( wrappedPath.getLhs(), - (MapPersistentAttribute) wrappedPath.getAttribute(), + ( (SqmMapJoin) wrappedPath ).getModel(), alias, wrappedPath.getSqmJoinType(), wrappedPath.isFetched(), @@ -40,13 +39,12 @@ public class SqmTreatedMapJoin extends SqmMapJoin imp } @Override - public EntityTypeDescriptor getTreatTarget() { + public EntityDomainType getTreatTarget() { return treatTarget; } @Override - @SuppressWarnings("unchecked") - public SqmPathSource getReferencedPathSource() { - return super.getReferencedPathSource(); + public JavaTypeDescriptor getJavaTypeDescriptor() { + return null; } } diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmTreatedPath.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmTreatedPath.java index f2d3f7f152..dda009a6ac 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmTreatedPath.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmTreatedPath.java @@ -6,13 +6,13 @@ */ package org.hibernate.query.sqm.tree.domain; -import org.hibernate.metamodel.model.mapping.EntityTypeDescriptor; +import org.hibernate.metamodel.model.domain.EntityDomainType; /** * @author Steve Ebersole */ public interface SqmTreatedPath extends SqmPathWrapper { - EntityTypeDescriptor getTreatTarget(); + EntityDomainType getTreatTarget(); @Override SqmPath getWrappedPath(); diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmTreatedRoot.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmTreatedRoot.java index 8ff88c1cd4..4a32571b5a 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmTreatedRoot.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmTreatedRoot.java @@ -6,10 +6,8 @@ */ package org.hibernate.query.sqm.tree.domain; -import org.hibernate.metamodel.model.mapping.EntityTypeDescriptor; -import org.hibernate.metamodel.model.mapping.spi.EntityValuedNavigable; +import org.hibernate.metamodel.model.domain.EntityDomainType; import org.hibernate.query.sqm.NodeBuilder; -import org.hibernate.query.sqm.SqmPathSource; import org.hibernate.query.sqm.tree.from.SqmRoot; /** @@ -17,15 +15,15 @@ import org.hibernate.query.sqm.tree.from.SqmRoot; */ public class SqmTreatedRoot extends SqmRoot implements SqmTreatedPath { private final SqmRoot wrappedPath; - private final EntityTypeDescriptor treatTarget; + private final EntityDomainType treatTarget; public SqmTreatedRoot( SqmRoot wrappedPath, - EntityTypeDescriptor treatTarget, + EntityDomainType treatTarget, NodeBuilder nodeBuilder) { //noinspection unchecked super( - ( (EntityValuedNavigable) wrappedPath.getReferencedPathSource() ).getEntityDescriptor(), + (EntityDomainType) wrappedPath.getReferencedPathSource(), null, nodeBuilder ); @@ -34,12 +32,12 @@ public class SqmTreatedRoot extends SqmRoot implements SqmTre } @Override - public EntityTypeDescriptor getTreatTarget() { + public EntityDomainType getTreatTarget() { return treatTarget; } @Override - public EntityTypeDescriptor getManagedType() { + public EntityDomainType getManagedType() { return getTreatTarget(); } @@ -49,8 +47,9 @@ public class SqmTreatedRoot extends SqmRoot implements SqmTre } @Override - public SqmPathSource getReferencedPathSource() { - return (EntityTypeDescriptor) wrappedPath.getReferencedPathSource(); + public EntityDomainType getReferencedPathSource() { + //noinspection unchecked + return (EntityDomainType) wrappedPath.getReferencedPathSource(); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmTreatedSetJoin.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmTreatedSetJoin.java index 43829e382b..77c198b562 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmTreatedSetJoin.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmTreatedSetJoin.java @@ -6,20 +6,20 @@ */ package org.hibernate.query.sqm.tree.domain; -import org.hibernate.metamodel.model.mapping.EntityTypeDescriptor; -import org.hibernate.metamodel.model.mapping.spi.SetPersistentAttribute; -import org.hibernate.query.sqm.SqmPathSource; +import org.hibernate.metamodel.model.domain.EntityDomainType; +import org.hibernate.metamodel.model.domain.SetPersistentAttribute; +import org.hibernate.type.descriptor.java.JavaTypeDescriptor; /** * @author Steve Ebersole */ public class SqmTreatedSetJoin extends SqmSetJoin implements SqmTreatedPath { private final SqmSetJoin wrappedPath; - private final EntityTypeDescriptor treatTarget; + private final EntityDomainType treatTarget; public SqmTreatedSetJoin( SqmSetJoin wrappedPath, - EntityTypeDescriptor treatTarget, + EntityDomainType treatTarget, String alias) { //noinspection unchecked super( @@ -40,13 +40,23 @@ public class SqmTreatedSetJoin extends SqmSetJoin impleme } @Override - public EntityTypeDescriptor getTreatTarget() { + public SetPersistentAttribute getModel() { + return super.getModel(); + } + + @Override + public EntityDomainType getTreatTarget() { return treatTarget; } @Override - @SuppressWarnings("unchecked") - public SqmPathSource getReferencedPathSource() { + public SetPersistentAttribute getReferencedPathSource() { return super.getReferencedPathSource(); } + + @Override + public JavaTypeDescriptor getJavaTypeDescriptor() { + //noinspection unchecked + return (JavaTypeDescriptor) wrappedPath.getJavaTypeDescriptor(); + } } diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmTreatedSimplePath.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmTreatedSimplePath.java index aa5a757c23..d7e35c6c02 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmTreatedSimplePath.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmTreatedSimplePath.java @@ -6,8 +6,7 @@ */ package org.hibernate.query.sqm.tree.domain; -import org.hibernate.metamodel.model.mapping.EntityTypeDescriptor; -import org.hibernate.metamodel.model.mapping.spi.EntityValuedNavigable; +import org.hibernate.metamodel.model.domain.EntityDomainType; import org.hibernate.query.criteria.PathException; import org.hibernate.query.sqm.NodeBuilder; import org.hibernate.query.sqm.consume.spi.SemanticQueryWalker; @@ -19,17 +18,17 @@ public class SqmTreatedSimplePath extends SqmEntityValuedSimplePath implements SqmNavigableReference, SqmTreatedPath { - private final EntityTypeDescriptor treatTarget; + private final EntityDomainType treatTarget; private final SqmPath wrappedPath; + @SuppressWarnings("WeakerAccess") public SqmTreatedSimplePath( SqmEntityValuedSimplePath wrappedPath, - EntityTypeDescriptor treatTarget, + EntityDomainType treatTarget, NodeBuilder nodeBuilder) { - //noinspection unchecked super( wrappedPath.getNavigablePath(), - (EntityValuedNavigable) wrappedPath.getReferencedPathSource(), + (EntityDomainType) wrappedPath.getReferencedPathSource(), wrappedPath.getLhs(), nodeBuilder ); @@ -37,14 +36,14 @@ public class SqmTreatedSimplePath this.wrappedPath = wrappedPath; } - @SuppressWarnings("unchecked") + @SuppressWarnings({"unchecked", "WeakerAccess"}) public SqmTreatedSimplePath( SqmPluralValuedSimplePath wrappedPath, - EntityTypeDescriptor treatTarget, + EntityDomainType treatTarget, NodeBuilder nodeBuilder) { super( wrappedPath.getNavigablePath(), - wrappedPath.sqmAs( EntityValuedNavigable.class ), + (EntityDomainType) wrappedPath.getReferencedPathSource(), wrappedPath.getLhs(), nodeBuilder ); @@ -53,7 +52,7 @@ public class SqmTreatedSimplePath } @Override - public EntityTypeDescriptor getTreatTarget() { + public EntityDomainType getTreatTarget() { return treatTarget; } @@ -64,7 +63,7 @@ public class SqmTreatedSimplePath @Override public SqmTreatedSimplePath treatAs(Class treatJavaType) throws PathException { - return (SqmTreatedSimplePath) super.treatAs( treatJavaType ); + return super.treatAs( treatJavaType ); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmTreatedSingularJoin.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmTreatedSingularJoin.java index 7b4e1951e1..c706caa83b 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmTreatedSingularJoin.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmTreatedSingularJoin.java @@ -6,26 +6,26 @@ */ package org.hibernate.query.sqm.tree.domain; -import org.hibernate.metamodel.model.mapping.internal.SingularPersistentAttributeEntity; -import org.hibernate.metamodel.model.mapping.EntityTypeDescriptor; -import org.hibernate.query.sqm.SqmPathSource; +import org.hibernate.metamodel.model.domain.EntityDomainType; +import org.hibernate.metamodel.model.domain.SingularPersistentAttribute; +import org.hibernate.type.descriptor.java.JavaTypeDescriptor; /** * @author Steve Ebersole */ public class SqmTreatedSingularJoin extends SqmSingularJoin implements SqmTreatedPath { private final SqmSingularJoin wrappedPath; - private final EntityTypeDescriptor treatTarget; + private final EntityDomainType treatTarget; public SqmTreatedSingularJoin( SqmSingularJoin wrappedPath, - EntityTypeDescriptor treatTarget, + EntityDomainType treatTarget, String alias) { //noinspection unchecked super( wrappedPath.getLhs(), - (SingularPersistentAttributeEntity) wrappedPath.getAttribute(), + (SingularPersistentAttribute) wrappedPath.getAttribute(), alias, wrappedPath.getSqmJoinType(), wrappedPath.isFetched(), @@ -41,13 +41,18 @@ public class SqmTreatedSingularJoin extends SqmSingularJoin getTreatTarget() { + public EntityDomainType getTreatTarget() { return treatTarget; } @Override @SuppressWarnings("unchecked") - public SqmPathSource getReferencedPathSource() { - return (SingularPersistentAttributeEntity) super.getReferencedPathSource(); + public SingularPersistentAttribute getReferencedPathSource() { + return (SingularPersistentAttribute) super.getReferencedPathSource(); + } + + @Override + public JavaTypeDescriptor getJavaTypeDescriptor() { + return treatTarget.getExpressableJavaTypeDescriptor(); } } diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/expression/function/SqmCoalesce.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/expression/function/SqmCoalesce.java index 0c0480a6d8..5862eb35b3 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/expression/function/SqmCoalesce.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/expression/function/SqmCoalesce.java @@ -45,7 +45,7 @@ public class SqmCoalesce extends AbstractSqmExpression implements JpaCoale return null; } - return getNodeType().getJavaTypeDescriptor(); + return getNodeType().getExpressableJavaTypeDescriptor(); } public void value(SqmExpression expression) { diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/from/SqmAttributeJoin.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/from/SqmAttributeJoin.java index 0fcf7e70e5..abedb4844e 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/from/SqmAttributeJoin.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/from/SqmAttributeJoin.java @@ -6,10 +6,12 @@ */ package org.hibernate.query.sqm.tree.from; +import org.hibernate.HibernateException; import org.hibernate.query.criteria.JpaFetch; import org.hibernate.query.criteria.JpaJoin; import org.hibernate.query.sqm.SqmPathSource; import org.hibernate.query.sqm.tree.predicate.SqmPredicate; +import org.hibernate.type.descriptor.java.JavaTypeDescriptor; /** * Models a join based on a mapped attribute reference. @@ -21,7 +23,7 @@ public interface SqmAttributeJoin extends SqmQualifiedJoin, JpaFetch getLhs(); @Override - SqmPathSource getReferencedPathSource(); + SqmPathSource getReferencedPathSource(); @Override JavaTypeDescriptor getJavaTypeDescriptor(); @@ -33,4 +35,13 @@ public interface SqmAttributeJoin extends SqmQualifiedJoin, JpaFetch extends AbstractSqmFrom implements SqmJoin joinedEntityDescriptor, + EntityDomainType joinedEntityDescriptor, String alias, SqmRoot sqmRoot) { super( - buildRootNavigablePath( alias, joinedEntityDescriptor.getEntityName() ), + buildRootNavigablePath( alias, joinedEntityDescriptor.getHibernateEntityName() ), joinedEntityDescriptor, sqmRoot, alias, @@ -49,12 +48,12 @@ public class SqmCrossJoin extends AbstractSqmFrom implements SqmJoin getReferencedPathSource() { - return (EntityTypeDescriptor) super.getReferencedPathSource(); + public EntityDomainType getReferencedPathSource() { + return (EntityDomainType) super.getReferencedPathSource(); } public String getEntityName() { - return getReferencedPathSource().getEntityName(); + return getReferencedPathSource().getHibernateEntityName(); } @Override @@ -69,7 +68,7 @@ public class SqmCrossJoin extends AbstractSqmFrom implements SqmJoin getJavaTypeDescriptor() { - return getReferencedPathSource().getJavaTypeDescriptor(); + return getReferencedPathSource().getExpressableJavaTypeDescriptor(); } @Override @@ -83,7 +82,7 @@ public class SqmCrossJoin extends AbstractSqmFrom implements SqmJoin SqmTreatedCrossJoin treatAs(Class treatJavaType) throws PathException { - final EntityTypeDescriptor treatTarget = nodeBuilder().getDomainModel().entity( treatJavaType ); + final EntityDomainType treatTarget = nodeBuilder().getDomainModel().entity( treatJavaType ); return new SqmTreatedCrossJoin<>( this, null, treatTarget ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/from/SqmEntityJoin.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/from/SqmEntityJoin.java index cf6306f1bb..b11ca8fb53 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/from/SqmEntityJoin.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/from/SqmEntityJoin.java @@ -6,9 +6,8 @@ */ package org.hibernate.query.sqm.tree.from; -import org.hibernate.metamodel.model.mapping.EntityTypeDescriptor; +import org.hibernate.metamodel.model.domain.EntityDomainType; import org.hibernate.query.criteria.PathException; -import org.hibernate.query.sqm.SqmPathSource; import org.hibernate.query.sqm.consume.spi.SemanticQueryWalker; import org.hibernate.query.sqm.produce.SqmCreationHelper; import org.hibernate.query.sqm.tree.SqmJoinType; @@ -16,7 +15,6 @@ import org.hibernate.query.sqm.tree.domain.AbstractSqmJoin; import org.hibernate.query.sqm.tree.domain.SqmPath; import org.hibernate.query.sqm.tree.domain.SqmTreatedEntityJoin; import org.hibernate.query.sqm.tree.predicate.SqmPredicate; -import org.hibernate.type.descriptor.java.spi.EntityJavaDescriptor; /** * @author Steve Ebersole @@ -26,12 +24,12 @@ public class SqmEntityJoin extends AbstractSqmJoin implements SqmQualifi private SqmPredicate joinPredicate; public SqmEntityJoin( - EntityTypeDescriptor joinedEntityDescriptor, + EntityDomainType joinedEntityDescriptor, String alias, SqmJoinType joinType, SqmRoot sqmRoot) { super( - SqmCreationHelper.buildRootNavigablePath( joinedEntityDescriptor.getEntityName(), alias ), + SqmCreationHelper.buildRootNavigablePath( joinedEntityDescriptor.getHibernateEntityName(), alias ), joinedEntityDescriptor, sqmRoot, alias, @@ -57,17 +55,12 @@ public class SqmEntityJoin extends AbstractSqmJoin implements SqmQualifi } @Override - public SqmPathSource getReferencedPathSource() { - return (EntityTypeDescriptor) super.getReferencedPathSource(); - } - - @Override - public EntityJavaDescriptor getJavaTypeDescriptor() { - return getReferencedPathSource().getJavaTypeDescriptor(); + public EntityDomainType getReferencedPathSource() { + return (EntityDomainType) super.getReferencedPathSource(); } public String getEntityName() { - return getReferencedPathSource().getEntityName(); + return getReferencedPathSource().getHibernateEntityName(); } @Override @@ -90,7 +83,7 @@ public class SqmEntityJoin extends AbstractSqmJoin implements SqmQualifi @Override public SqmTreatedEntityJoin treatAs(Class treatJavaType) throws PathException { - final EntityTypeDescriptor treatTarget = nodeBuilder().getDomainModel().entity( treatJavaType ); + final EntityDomainType treatTarget = nodeBuilder().getDomainModel().entity( treatJavaType ); return new SqmTreatedEntityJoin<>( this, treatTarget, null, getSqmJoinType() ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/from/SqmFrom.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/from/SqmFrom.java index 9508af481a..963eecaaa0 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/from/SqmFrom.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/from/SqmFrom.java @@ -19,7 +19,6 @@ import javax.persistence.metamodel.MapAttribute; import javax.persistence.metamodel.SetAttribute; import javax.persistence.metamodel.SingularAttribute; -import org.hibernate.metamodel.model.domain.Navigable; import org.hibernate.query.criteria.JpaFrom; import org.hibernate.query.sqm.SqmPathSource; import org.hibernate.query.sqm.produce.spi.SqmCreationState; @@ -44,7 +43,7 @@ public interface SqmFrom extends SqmVisitableNode, SqmPath, JpaFrom getReferencedPathSource(); + SqmPathSource getReferencedPathSource(); boolean hasJoins(); @@ -65,7 +64,7 @@ public interface SqmFrom extends SqmVisitableNode, SqmPath, JpaFrom extends AbstractSqmFrom implements JpaRoot { @Override public JavaTypeDescriptor getJavaTypeDescriptor() { - return getReferencedPathSource().getJavaTypeDescriptor(); + return getReferencedPathSource().getExpressableJavaTypeDescriptor(); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/BasicJavaDescriptor.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/BasicJavaDescriptor.java index 7bca9ce773..0c55859e22 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/BasicJavaDescriptor.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/BasicJavaDescriptor.java @@ -6,7 +6,7 @@ */ package org.hibernate.type.descriptor.java; -import org.hibernate.type.descriptor.spi.JdbcRecommendedSqlTypeMappingContext; +import org.hibernate.type.descriptor.sql.SqlTypeDescriptorIndicators; import org.hibernate.type.descriptor.sql.JdbcTypeJavaClassMappings; import org.hibernate.type.descriptor.sql.SqlTypeDescriptor; @@ -27,10 +27,15 @@ public interface BasicJavaDescriptor extends JavaTypeDescriptor { * * @return The recommended SQL type descriptor */ - default SqlTypeDescriptor getJdbcRecommendedSqlType(JdbcRecommendedSqlTypeMappingContext context) { + default SqlTypeDescriptor getJdbcRecommendedSqlType(SqlTypeDescriptorIndicators context) { // match legacy behavior return context.getTypeConfiguration().getSqlTypeDescriptorRegistry().getDescriptor( JdbcTypeJavaClassMappings.INSTANCE.determineJdbcTypeCodeForJavaClass( getJavaType() ) ); } + + @Override + default T fromString(String string) { + throw new UnsupportedOperationException(); + } } diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JavaTypeDescriptor.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JavaTypeDescriptor.java index 4636c2e0f7..92a37084cd 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JavaTypeDescriptor.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JavaTypeDescriptor.java @@ -10,8 +10,10 @@ import java.io.Serializable; import java.util.Comparator; import java.util.Objects; +import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.internal.util.compare.ComparableComparator; -import org.hibernate.type.descriptor.WrapperOptions; +import org.hibernate.type.descriptor.sql.SqlTypeDescriptor; +import org.hibernate.type.descriptor.sql.SqlTypeDescriptorIndicators; /** * Descriptor for the Java side of a value mapping. @@ -19,16 +21,6 @@ import org.hibernate.type.descriptor.WrapperOptions; * @author Steve Ebersole */ public interface JavaTypeDescriptor extends Serializable { - /** - * Retrieve the Java type handled here. - * - * @return The Java type. - * - * @deprecated Use {@link #getJavaType()} instead - */ - @Deprecated - Class getJavaTypeClass(); - /** * Get the Java type described */ @@ -45,6 +37,16 @@ public interface JavaTypeDescriptor extends Serializable { return ImmutableMutabilityPlan.INSTANCE; } + /** + * Obtain the "recommended" SQL type descriptor for this Java type. The recommended + * aspect comes from the JDBC spec (mostly). + * + * @param context Contextual information + * + * @return The recommended SQL type descriptor + */ + SqlTypeDescriptor getJdbcRecommendedSqlType(SqlTypeDescriptorIndicators context); + /** * Retrieve the natural comparator for this type. */ @@ -114,7 +116,7 @@ public interface JavaTypeDescriptor extends Serializable { * * @return The unwrapped value. */ - X unwrap(T value, Class type, WrapperOptions options); + X unwrap(T value, Class type, SharedSessionContractImplementor options); /** * Wrap a value as our handled Java type. @@ -127,5 +129,15 @@ public interface JavaTypeDescriptor extends Serializable { * * @return The wrapped value. */ - T wrap(X value, WrapperOptions options); + T wrap(X value, SharedSessionContractImplementor options); + + /** + * Retrieve the Java type handled here. + * + * @return The Java type. + * + * @deprecated Use {@link #getJavaType()} instead + */ + @Deprecated + Class getJavaTypeClass(); } diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/CollectionJavaTypeDescriptor.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/CollectionJavaTypeDescriptor.java new file mode 100644 index 0000000000..65af41bc97 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/CollectionJavaTypeDescriptor.java @@ -0,0 +1,79 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later + * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html + */ +package org.hibernate.type.descriptor.java.spi; + +import org.hibernate.collection.spi.CollectionSemantics; +import org.hibernate.collection.spi.PersistentCollection; +import org.hibernate.engine.spi.SharedSessionContractImplementor; +import org.hibernate.type.descriptor.java.AbstractTypeDescriptor; +import org.hibernate.type.descriptor.sql.SqlTypeDescriptor; +import org.hibernate.type.descriptor.sql.SqlTypeDescriptorIndicators; + +/** + * Extension of the general JavaTypeDescriptor for "collection types" + * + * @apiNote "Collection types" are defined loosely here to cover mapping + * collection types other than those from the "Java Collection Framework". + * + * @see CollectionSemantics + * + * @author Steve Ebersole + */ +public class CollectionJavaTypeDescriptor extends AbstractTypeDescriptor { + private final CollectionSemantics semantics; + + @SuppressWarnings("unchecked") + public CollectionJavaTypeDescriptor(Class type, CollectionSemantics semantics) { + super( (Class) type ); + this.semantics = semantics; + } + + public CollectionSemantics getSemantics() { + return semantics; + } + + @Override + public SqlTypeDescriptor getJdbcRecommendedSqlType(SqlTypeDescriptorIndicators context) { + // none + return null; + } + + @Override + public C fromString(String string) { + throw new UnsupportedOperationException( ); + } + + @Override + public X unwrap(C value, Class type, SharedSessionContractImplementor session) { + throw new UnsupportedOperationException( ); + } + + @Override + public C wrap(X value, SharedSessionContractImplementor session) { + throw new UnsupportedOperationException( ); + } + + @Override + public boolean areEqual(C one, C another) { + return one == another || + ( + one instanceof PersistentCollection && + ( (PersistentCollection) one ).wasInitialized() && + ( (PersistentCollection) one ).isWrapper( another ) + ) || + ( + another instanceof PersistentCollection && + ( (PersistentCollection) another ).wasInitialized() && + ( (PersistentCollection) another ).isWrapper( one ) + ); + } + + @Override + public int extractHashCode(C x) { + throw new UnsupportedOperationException(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/EnumJavaDescriptor.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/EnumJavaDescriptor.java new file mode 100644 index 0000000000..fb4d506d8e --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/EnumJavaDescriptor.java @@ -0,0 +1,99 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later + * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html + */ +package org.hibernate.type.descriptor.java.spi; + +import java.sql.Types; +import javax.persistence.EnumType; + +import org.hibernate.engine.spi.SharedSessionContractImplementor; +import org.hibernate.type.descriptor.java.AbstractTypeDescriptor; +import org.hibernate.type.descriptor.java.ImmutableMutabilityPlan; +import org.hibernate.type.descriptor.sql.SqlTypeDescriptor; +import org.hibernate.type.descriptor.sql.SqlTypeDescriptorIndicators; + +/** + * Describes a Java Enum type. + * + * @author Steve Ebersole + */ +public class EnumJavaDescriptor extends AbstractTypeDescriptor { + + @SuppressWarnings("unchecked") + public EnumJavaDescriptor(Class type) { + super( type, ImmutableMutabilityPlan.INSTANCE ); + } + + @Override + public SqlTypeDescriptor getJdbcRecommendedSqlType(SqlTypeDescriptorIndicators context) { + if ( context.getEnumeratedType() != null && context.getEnumeratedType() == EnumType.STRING ) { + return context.isNationalized() + ? context.getTypeConfiguration().getSqlTypeDescriptorRegistry().getDescriptor( Types.NVARCHAR ) + : context.getTypeConfiguration().getSqlTypeDescriptorRegistry().getDescriptor( Types.VARCHAR ); + } + else { + return context.getTypeConfiguration().getSqlTypeDescriptorRegistry().getDescriptor( Types.INTEGER ); + } + } + + @Override + public String toString(E value) { + return value == null ? "" : value.name(); + } + + @Override + @SuppressWarnings("unchecked") + public E fromString(String string) { + return string == null ? null : (E) Enum.valueOf( getJavaType(), string ); + } + + @Override + @SuppressWarnings("unchecked") + public X unwrap(E value, Class type, SharedSessionContractImplementor session) { + return (X) value; + } + + @Override + @SuppressWarnings("unchecked") + public E wrap(X value, SharedSessionContractImplementor session) { + return (E) value; + } + + public Integer toOrdinal(E domainForm) { + if ( domainForm == null ) { + return null; + } + return domainForm.ordinal(); + } + + @SuppressWarnings("unchecked") + public E fromOrdinal(Integer relationalForm) { + if ( relationalForm == null ) { + return null; + } + return (E) getJavaType().getEnumConstants()[ relationalForm ]; + } + + @SuppressWarnings("unchecked") + public E fromName(String relationalForm) { + if ( relationalForm == null ) { + return null; + } + return (E) Enum.valueOf( getJavaType(), relationalForm ); + } + + public String toName(E domainForm) { + if ( domainForm == null ) { + return null; + } + return domainForm.name(); + } + + @Override + public String toString() { + return getClass().getSimpleName() + "(" + getJavaType().getName() + ")"; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/JavaTypeDescriptorBaseline.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/JavaTypeDescriptorBaseline.java new file mode 100644 index 0000000000..10e69157af --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/JavaTypeDescriptorBaseline.java @@ -0,0 +1,148 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later + * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html + */ +package org.hibernate.type.descriptor.java.spi; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.SortedMap; +import java.util.SortedSet; +import java.util.TreeMap; +import java.util.TreeSet; + +import org.hibernate.collection.internal.StandardArraySemantics; +import org.hibernate.collection.internal.StandardBagSemantics; +import org.hibernate.collection.internal.StandardListSemantics; +import org.hibernate.collection.internal.StandardMapSemantics; +import org.hibernate.collection.internal.StandardOrderedMapSemantics; +import org.hibernate.collection.internal.StandardOrderedSetSemantics; +import org.hibernate.collection.internal.StandardSetSemantics; +import org.hibernate.collection.internal.StandardSortedMapSemantics; +import org.hibernate.collection.internal.StandardSortedSetSemantics; +import org.hibernate.type.descriptor.java.BigDecimalTypeDescriptor; +import org.hibernate.type.descriptor.java.BigIntegerTypeDescriptor; +import org.hibernate.type.descriptor.java.BlobTypeDescriptor; +import org.hibernate.type.descriptor.java.BooleanTypeDescriptor; +import org.hibernate.type.descriptor.java.ByteArrayTypeDescriptor; +import org.hibernate.type.descriptor.java.ByteTypeDescriptor; +import org.hibernate.type.descriptor.java.CalendarTypeDescriptor; +import org.hibernate.type.descriptor.java.CharacterArrayTypeDescriptor; +import org.hibernate.type.descriptor.java.CharacterTypeDescriptor; +import org.hibernate.type.descriptor.java.ClassTypeDescriptor; +import org.hibernate.type.descriptor.java.ClobTypeDescriptor; +import org.hibernate.type.descriptor.java.CurrencyTypeDescriptor; +import org.hibernate.type.descriptor.java.DateTypeDescriptor; +import org.hibernate.type.descriptor.java.DoubleTypeDescriptor; +import org.hibernate.type.descriptor.java.DurationJavaDescriptor; +import org.hibernate.type.descriptor.java.FloatTypeDescriptor; +import org.hibernate.type.descriptor.java.InstantJavaDescriptor; +import org.hibernate.type.descriptor.java.IntegerTypeDescriptor; +import org.hibernate.type.descriptor.java.JavaTypeDescriptor; +import org.hibernate.type.descriptor.java.JdbcDateTypeDescriptor; +import org.hibernate.type.descriptor.java.JdbcTimestampTypeDescriptor; +import org.hibernate.type.descriptor.java.LocalDateJavaDescriptor; +import org.hibernate.type.descriptor.java.LocalDateTimeJavaDescriptor; +import org.hibernate.type.descriptor.java.LocaleTypeDescriptor; +import org.hibernate.type.descriptor.java.LongTypeDescriptor; +import org.hibernate.type.descriptor.java.NClobTypeDescriptor; +import org.hibernate.type.descriptor.java.OffsetDateTimeJavaDescriptor; +import org.hibernate.type.descriptor.java.OffsetTimeJavaDescriptor; +import org.hibernate.type.descriptor.java.PrimitiveByteArrayTypeDescriptor; +import org.hibernate.type.descriptor.java.PrimitiveCharacterArrayTypeDescriptor; +import org.hibernate.type.descriptor.java.ShortTypeDescriptor; +import org.hibernate.type.descriptor.java.StringTypeDescriptor; +import org.hibernate.type.descriptor.java.TimeZoneTypeDescriptor; +import org.hibernate.type.descriptor.java.UUIDTypeDescriptor; +import org.hibernate.type.descriptor.java.UrlTypeDescriptor; +import org.hibernate.type.descriptor.java.ZonedDateTimeJavaDescriptor; + +/** + * + * @author Steve Ebersole + */ +public class JavaTypeDescriptorBaseline { + public interface BaselineTarget { + void addBaselineDescriptor(JavaTypeDescriptor descriptor); + void addBaselineDescriptor(Class describedJavaType, JavaTypeDescriptor descriptor); + } + + @SuppressWarnings("unchecked") + public static void prime(BaselineTarget target) { + primePrimitive( target, ByteTypeDescriptor.INSTANCE ); + primePrimitive( target, BooleanTypeDescriptor.INSTANCE ); + primePrimitive( target, CharacterTypeDescriptor.INSTANCE ); + primePrimitive( target, ShortTypeDescriptor.INSTANCE ); + primePrimitive( target, IntegerTypeDescriptor.INSTANCE ); + primePrimitive( target, LongTypeDescriptor.INSTANCE ); + primePrimitive( target, FloatTypeDescriptor.INSTANCE ); + primePrimitive( target, DoubleTypeDescriptor.INSTANCE ); + + target.addBaselineDescriptor( BigDecimalTypeDescriptor.INSTANCE ); + target.addBaselineDescriptor( BigIntegerTypeDescriptor.INSTANCE ); + + target.addBaselineDescriptor( StringTypeDescriptor.INSTANCE ); + + target.addBaselineDescriptor( BlobTypeDescriptor.INSTANCE ); + target.addBaselineDescriptor( ClobTypeDescriptor.INSTANCE ); + target.addBaselineDescriptor( NClobTypeDescriptor.INSTANCE ); + + target.addBaselineDescriptor( ByteArrayTypeDescriptor.INSTANCE ); + target.addBaselineDescriptor( CharacterArrayTypeDescriptor.INSTANCE ); + target.addBaselineDescriptor( PrimitiveByteArrayTypeDescriptor.INSTANCE ); + target.addBaselineDescriptor( PrimitiveCharacterArrayTypeDescriptor.INSTANCE ); + + target.addBaselineDescriptor( DurationJavaDescriptor.INSTANCE ); + target.addBaselineDescriptor( InstantJavaDescriptor.INSTANCE ); + target.addBaselineDescriptor( LocalDateJavaDescriptor.INSTANCE ); + target.addBaselineDescriptor( LocalDateTimeJavaDescriptor.INSTANCE ); + target.addBaselineDescriptor( OffsetDateTimeJavaDescriptor.INSTANCE ); + target.addBaselineDescriptor( OffsetTimeJavaDescriptor.INSTANCE ); + target.addBaselineDescriptor( ZonedDateTimeJavaDescriptor.INSTANCE ); + + target.addBaselineDescriptor( CalendarTypeDescriptor.INSTANCE ); + target.addBaselineDescriptor( DateTypeDescriptor.INSTANCE ); + target.addBaselineDescriptor( java.sql.Date.class, JdbcDateTypeDescriptor.INSTANCE ); + target.addBaselineDescriptor( java.sql.Time.class, JdbcTimestampTypeDescriptor.INSTANCE ); + target.addBaselineDescriptor( java.sql.Timestamp.class, JdbcTimestampTypeDescriptor.INSTANCE ); + target.addBaselineDescriptor( TimeZoneTypeDescriptor.INSTANCE ); + + target.addBaselineDescriptor( ClassTypeDescriptor.INSTANCE ); + + target.addBaselineDescriptor( CurrencyTypeDescriptor.INSTANCE ); + target.addBaselineDescriptor( LocaleTypeDescriptor.INSTANCE ); + target.addBaselineDescriptor( UrlTypeDescriptor.INSTANCE ); + target.addBaselineDescriptor( UUIDTypeDescriptor.INSTANCE ); + + target.addBaselineDescriptor( new CollectionJavaTypeDescriptor( Collection.class, StandardBagSemantics.INSTANCE ) ); + target.addBaselineDescriptor( new CollectionJavaTypeDescriptor( Object[].class, StandardArraySemantics.INSTANCE ) ); + target.addBaselineDescriptor( new CollectionJavaTypeDescriptor( List.class, StandardListSemantics.INSTANCE ) ); + target.addBaselineDescriptor( new CollectionJavaTypeDescriptor( ArrayList.class, StandardListSemantics.INSTANCE ) ); + target.addBaselineDescriptor( new CollectionJavaTypeDescriptor( Set.class, StandardSetSemantics.INSTANCE ) ); + target.addBaselineDescriptor( new CollectionJavaTypeDescriptor( HashSet.class, StandardSetSemantics.INSTANCE ) ); + target.addBaselineDescriptor( new CollectionJavaTypeDescriptor( SortedSet.class, StandardSortedSetSemantics.INSTANCE ) ); + target.addBaselineDescriptor( new CollectionJavaTypeDescriptor( TreeSet.class, StandardOrderedSetSemantics.INSTANCE ) ); + target.addBaselineDescriptor( new CollectionJavaTypeDescriptor( LinkedHashSet.class, StandardOrderedSetSemantics.INSTANCE ) ); + target.addBaselineDescriptor( new CollectionJavaTypeDescriptor( Map.class, StandardMapSemantics.INSTANCE ) ); + target.addBaselineDescriptor( new CollectionJavaTypeDescriptor( HashMap.class, StandardMapSemantics.INSTANCE ) ); + target.addBaselineDescriptor( new CollectionJavaTypeDescriptor( SortedMap.class, StandardSortedMapSemantics.INSTANCE ) ); + target.addBaselineDescriptor( new CollectionJavaTypeDescriptor( TreeMap.class, StandardSortedMapSemantics.INSTANCE ) ); + target.addBaselineDescriptor( new CollectionJavaTypeDescriptor( LinkedHashMap.class, StandardOrderedMapSemantics.INSTANCE ) ); + + target.addBaselineDescriptor( MapEntryJavaDescriptor.INSTANCE ); + } + + private static void primePrimitive(BaselineTarget target, JavaTypeDescriptor descriptor) { + target.addBaselineDescriptor( descriptor ); + target.addBaselineDescriptor( ( (Primitive) descriptor ).getPrimitiveClass(), descriptor ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/JavaTypeDescriptorBasicAdaptor.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/JavaTypeDescriptorBasicAdaptor.java new file mode 100644 index 0000000000..2ffab1dc9f --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/JavaTypeDescriptorBasicAdaptor.java @@ -0,0 +1,57 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later + * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html + */ +package org.hibernate.type.descriptor.java.spi; + +import org.hibernate.engine.spi.SharedSessionContractImplementor; +import org.hibernate.type.descriptor.java.AbstractTypeDescriptor; +import org.hibernate.type.descriptor.sql.SqlTypeDescriptor; +import org.hibernate.type.descriptor.sql.SqlTypeDescriptorIndicators; + +/** + * AbstractBasicTypeDescriptor adapter for cases where we do not know a proper JavaTypeDescriptor + * for a given Java type. + * + * @author Steve Ebersole + */ +public class JavaTypeDescriptorBasicAdaptor extends AbstractTypeDescriptor { + public JavaTypeDescriptorBasicAdaptor(Class type) { + super( type ); + } + + @Override + public SqlTypeDescriptor getJdbcRecommendedSqlType(SqlTypeDescriptorIndicators context) { + throw new UnsupportedOperationException( + "Recommended SqlTypeDescriptor not known for this Java type : " + getJavaType().getName() + ); + } + + @Override + public String toString(T value) { + return value.toString(); + } + + @Override + public T fromString(String string) { + throw new UnsupportedOperationException( + "Conversion from String strategy not known for this Java type : " + getJavaType().getName() + ); + } + + @Override + public X unwrap(T value, Class type, SharedSessionContractImplementor session) { + throw new UnsupportedOperationException( + "Unwrap strategy not known for this Java type : " + getJavaType().getName() + ); + } + + @Override + public T wrap(X value, SharedSessionContractImplementor session) { + throw new UnsupportedOperationException( + "Wrap strategy not known for this Java type : " + getJavaType().getName() + ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/JavaTypeDescriptorRegistry.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/JavaTypeDescriptorRegistry.java index a71b4529a1..41b64e6ab5 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/JavaTypeDescriptorRegistry.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/JavaTypeDescriptorRegistry.java @@ -8,9 +8,18 @@ package org.hibernate.type.descriptor.java.spi; import java.io.Serializable; import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Supplier; +import org.hibernate.boot.model.TypeContributor; +import org.hibernate.engine.spi.SharedSessionContractImplementor; +import org.hibernate.internal.util.SerializationHelper; +import org.hibernate.type.descriptor.java.AbstractTypeDescriptor; import org.hibernate.type.descriptor.java.JavaTypeDescriptor; +import org.hibernate.type.descriptor.sql.SqlTypeDescriptor; +import org.hibernate.type.descriptor.sql.SqlTypeDescriptorIndicators; +import org.hibernate.type.descriptor.sql.VarbinaryTypeDescriptor; import org.hibernate.type.spi.TypeConfiguration; +import org.hibernate.type.spi.TypeConfigurationAware; import org.jboss.logging.Logger; @@ -22,16 +31,46 @@ import org.jboss.logging.Logger; * * @since 5.3 */ -public class JavaTypeDescriptorRegistry implements Serializable { +public class JavaTypeDescriptorRegistry implements JavaTypeDescriptorBaseline.BaselineTarget, Serializable { private static final Logger log = Logger.getLogger( JavaTypeDescriptorRegistry.class ); - + private final TypeConfiguration typeConfiguration; private ConcurrentHashMap descriptorsByClass = new ConcurrentHashMap<>(); @SuppressWarnings("unused") public JavaTypeDescriptorRegistry(TypeConfiguration typeConfiguration) { + this.typeConfiguration = typeConfiguration; } + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // baseline descriptors + + @Override + public void addBaselineDescriptor(JavaTypeDescriptor descriptor) { + if ( descriptor.getJavaType() == null ) { + throw new IllegalStateException( "Illegal to add BasicJavaTypeDescriptor with null Java type" ); + } + addBaselineDescriptor( descriptor.getJavaType(), descriptor ); + } + + @Override + public void addBaselineDescriptor(Class describedJavaType, JavaTypeDescriptor descriptor) { + performInjections( descriptor ); + descriptorsByClass.put( describedJavaType, descriptor ); + } + + private void performInjections(JavaTypeDescriptor descriptor) { + if ( descriptor instanceof TypeConfigurationAware ) { + // would be nice to make the JavaTypeDescriptor for an entity, e.g., aware of the the TypeConfiguration + ( (TypeConfigurationAware) descriptor ).setTypeConfiguration( typeConfiguration ); + } + } + + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // descriptor access + public JavaTypeDescriptor getDescriptor(Class javaType) { return RegistryHelper.INSTANCE.resolveDescriptor( descriptorsByClass, @@ -58,5 +97,102 @@ public class JavaTypeDescriptorRegistry implements Serializable { old ); } + performInjections( descriptor ); + } + + public JavaTypeDescriptor resolveDescriptor(Class javaType, Supplier> creator) { + //noinspection unchecked + return descriptorsByClass.computeIfAbsent( + javaType, + jt -> { + final JavaTypeDescriptor jtd = creator.get(); + performInjections( jtd ); + return jtd; + } + ); + } + + @SuppressWarnings("unchecked") + public JavaTypeDescriptor resolveDescriptor(Class javaType) { + return resolveDescriptor( + javaType, + () -> { + // the fallback will always be a basic type + final JavaTypeDescriptor fallbackDescriptor; + + if ( javaType.isEnum() ) { + fallbackDescriptor = new EnumJavaDescriptor( javaType ); + } + else if ( Serializable.class.isAssignableFrom( javaType ) ) { + fallbackDescriptor = new OnTheFlySerializableJavaDescriptor( javaType ); + } + else { + fallbackDescriptor = new JavaTypeDescriptorBasicAdaptor( javaType ); + } + + return fallbackDescriptor; + } + ); + } + + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + private class OnTheFlySerializableJavaDescriptor extends AbstractTypeDescriptor { + private final SqlTypeDescriptor sqlTypeDescriptor; + + public OnTheFlySerializableJavaDescriptor(Class type) { + super( type ); + + // todo (6.0) : would be nice to expose for config by user + // todo (6.0) : ^^ might also be nice to allow them to plug in a "JavaTypeDescriptorResolver" + // - that allows them to hook into the #getDescriptor call either as the primary or as a fallback + + + log.debugf( + "Could not find matching JavaTypeDescriptor for requested Java class [%s]; using fallback via its Serializable interface. " + + "This means Hibernate does not know how to perform certain basic operations in relation to this Java type" + + "which can lead to those operations having a large performance impact. Consider registering these " + + "JavaTypeDescriptors with the %s during bootstrap, either directly or through a registered %s " + + "accessing the %s ", + getJavaType().getName(), + JavaTypeDescriptorRegistry.class.getName(), + TypeContributor.class.getName(), + TypeConfiguration.class.getName() + ); + + + sqlTypeDescriptor = VarbinaryTypeDescriptor.INSTANCE; + } + + @Override + public SqlTypeDescriptor getJdbcRecommendedSqlType(SqlTypeDescriptorIndicators context) { + return sqlTypeDescriptor; + } + + @Override + public X unwrap(T value, Class type, SharedSessionContractImplementor session) { + if ( type.equals( byte[].class ) ) { + throw new UnsupportedOperationException( "Cannot unwrap Serializable to format other than byte[]" ); + } + + return (X) SerializationHelper.serialize( value ); + } + + @Override + @SuppressWarnings("unchecked") + public T wrap(X value, SharedSessionContractImplementor session) { + if ( value == null ) { + return null; + } + + if ( value.getClass().equals( byte[].class ) ) { + throw new UnsupportedOperationException( "Cannot unwrap Serializable to format other than byte[]" ); + } + + final byte[] bytes = (byte[]) value; + + return (T) SerializationHelper.deserialize( bytes ); + } } } diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/Primitive.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/Primitive.java new file mode 100644 index 0000000000..c1f292d9c1 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/Primitive.java @@ -0,0 +1,33 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later + * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html + */ +package org.hibernate.type.descriptor.java.spi; + +import java.io.Serializable; + +import org.hibernate.type.descriptor.java.JavaTypeDescriptor; + +/** + * Additional contract for primitive / primitive wrapper Java types. + * + * @author Steve Ebersole + */ +public interface Primitive extends JavaTypeDescriptor { + /** + * Retrieve the primitive counterpart to the wrapper type identified by + * this descriptor + * + * @return The primitive Java type. + */ + Class getPrimitiveClass(); + + /**` + * Get this Java type's default value. + * + * @return The default value. + */ + J getDefaultValue(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/RegistryHelper.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/RegistryHelper.java index da449213eb..1ac634bbcb 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/RegistryHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/RegistryHelper.java @@ -6,13 +6,11 @@ */ package org.hibernate.type.descriptor.java.spi; -import java.io.Serializable; import java.util.Map; import java.util.function.Supplier; import org.hibernate.type.descriptor.java.EnumJavaTypeDescriptor; import org.hibernate.type.descriptor.java.JavaTypeDescriptor; -import org.hibernate.type.descriptor.java.SerializableTypeDescriptor; import org.jboss.logging.Logger; diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/spi/JdbcRecommendedSqlTypeMappingContext.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/sql/SqlTypeDescriptorIndicators.java similarity index 94% rename from hibernate-core/src/main/java/org/hibernate/type/descriptor/spi/JdbcRecommendedSqlTypeMappingContext.java rename to hibernate-core/src/main/java/org/hibernate/type/descriptor/sql/SqlTypeDescriptorIndicators.java index 79803b64f6..33b9411c06 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/spi/JdbcRecommendedSqlTypeMappingContext.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/sql/SqlTypeDescriptorIndicators.java @@ -4,7 +4,7 @@ * License: GNU Lesser General Public License (LGPL), version 2.1 or later * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html */ -package org.hibernate.type.descriptor.spi; +package org.hibernate.type.descriptor.sql; import java.sql.Types; import javax.persistence.EnumType; @@ -19,7 +19,7 @@ import org.hibernate.type.spi.TypeConfiguration; * * @author Steve Ebersole */ -public interface JdbcRecommendedSqlTypeMappingContext { +public interface SqlTypeDescriptorIndicators { /** * Was nationalized character datatype requested for the given Java type? * diff --git a/hibernate-core/src/test/java/org/hibernate/test/converter/custom/MyCustomJavaTypeDescriptor.java b/hibernate-core/src/test/java/org/hibernate/test/converter/custom/MyCustomJavaTypeDescriptor.java index 228f702828..7bbf57a1e0 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/converter/custom/MyCustomJavaTypeDescriptor.java +++ b/hibernate-core/src/test/java/org/hibernate/test/converter/custom/MyCustomJavaTypeDescriptor.java @@ -9,10 +9,9 @@ package org.hibernate.test.converter.custom; import org.hibernate.internal.util.StringHelper; import org.hibernate.type.descriptor.WrapperOptions; import org.hibernate.type.descriptor.java.BasicJavaDescriptor; -import org.hibernate.type.descriptor.java.JavaTypeDescriptor; import org.hibernate.type.descriptor.java.MutabilityPlan; import org.hibernate.type.descriptor.java.MutableMutabilityPlan; -import org.hibernate.type.descriptor.spi.JdbcRecommendedSqlTypeMappingContext; +import org.hibernate.type.descriptor.sql.SqlTypeDescriptorIndicators; import org.hibernate.type.descriptor.sql.SqlTypeDescriptor; /** @@ -40,7 +39,7 @@ public class MyCustomJavaTypeDescriptor implements BasicJavaDescriptor