diff --git a/hibernate-core/src/main/java/org/hibernate/boot/jaxb/hbm/transform/HbmXmlTransformer.java b/hibernate-core/src/main/java/org/hibernate/boot/jaxb/hbm/transform/HbmXmlTransformer.java index 5a5654a40b..6533e062d0 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/jaxb/hbm/transform/HbmXmlTransformer.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/jaxb/hbm/transform/HbmXmlTransformer.java @@ -61,6 +61,7 @@ import org.hibernate.boot.jaxb.hbm.spi.JaxbHbmListType; import org.hibernate.boot.jaxb.hbm.spi.JaxbHbmManyToAnyCollectionElementType; import org.hibernate.boot.jaxb.hbm.spi.JaxbHbmManyToManyCollectionElementType; import org.hibernate.boot.jaxb.hbm.spi.JaxbHbmManyToOneType; +import org.hibernate.boot.jaxb.hbm.spi.JaxbHbmMapKeyBasicType; import org.hibernate.boot.jaxb.hbm.spi.JaxbHbmMapType; import org.hibernate.boot.jaxb.hbm.spi.JaxbHbmNamedNativeQueryType; import org.hibernate.boot.jaxb.hbm.spi.JaxbHbmNamedQueryType; @@ -129,7 +130,6 @@ import org.hibernate.boot.jaxb.mapping.spi.JaxbHbmFilterImpl; import org.hibernate.boot.jaxb.mapping.spi.JaxbHqlImportImpl; import org.hibernate.boot.jaxb.mapping.spi.JaxbIdClassImpl; import org.hibernate.boot.jaxb.mapping.spi.JaxbIdImpl; -import org.hibernate.boot.jaxb.mapping.spi.JaxbInheritanceImpl; import org.hibernate.boot.jaxb.mapping.spi.JaxbJoinColumnImpl; import org.hibernate.boot.jaxb.mapping.spi.JaxbManyToManyImpl; import org.hibernate.boot.jaxb.mapping.spi.JaxbManyToOneImpl; @@ -164,7 +164,6 @@ import org.jboss.logging.Logger; import jakarta.persistence.ConstraintMode; import jakarta.persistence.FetchType; -import jakarta.persistence.InheritanceType; import jakarta.persistence.TemporalType; import jakarta.xml.bind.JAXBContext; import jakarta.xml.bind.JAXBElement; @@ -1834,18 +1833,55 @@ public class HbmXmlTransformer { else if ( source.getMapKey() != null ) { if ( ! StringHelper.isEmpty( source.getMapKey().getFormulaAttribute() ) ) { handleUnsupported( - "Transformation of formulas within map-keys are not supported - `%s`", + "Transformation of formula attribute within map-keys is not supported - `%s`", origin ); return; } - final JaxbMapKeyColumnImpl mapKey = new JaxbMapKeyColumnImpl(); - mapKey.setName( source.getMapKey().getColumnAttribute() ); - target.setMapKeyColumn( mapKey ); + if ( CollectionHelper.isNotEmpty( source.getMapKey().getColumnOrFormula() ) ) { + handleUnsupported( + "Transformation of column/formula elements within map-keys is not supported - `%s`", + origin + ); + return; + } + + if ( StringHelper.isNotEmpty( source.getMapKey().getNode() ) ) { + handleUnsupported( + "Transformation of `node` attribute is not supported - %s", + origin + ); + return; + } + + final String mapKeyType = resolveMapKeyType( source.getMapKey() ); + if ( mapKeyType != null ) { + final JaxbUserTypeImpl jaxbMapKeyType = new JaxbUserTypeImpl(); + target.setMapKeyType( jaxbMapKeyType ); + jaxbMapKeyType.setValue( mapKeyType ); + } + + if ( StringHelper.isNotEmpty( source.getMapKey().getColumnAttribute() ) ) { + final JaxbMapKeyColumnImpl mapKeyColumn = new JaxbMapKeyColumnImpl(); + mapKeyColumn.setName( source.getMapKey().getColumnAttribute() ); + target.setMapKeyColumn( mapKeyColumn ); + } } } + private String resolveMapKeyType(JaxbHbmMapKeyBasicType mapKey) { + if ( StringHelper.isNotEmpty( mapKey.getTypeAttribute() ) ) { + return mapKey.getTypeAttribute(); + } + + if ( mapKey.getType() != null ) { + return StringHelper.nullIfEmpty( mapKey.getType().getName() ); + } + + return null; + } + private Boolean invert(Boolean value) { return invert( value, null ); } @@ -1877,6 +1913,8 @@ public class HbmXmlTransformer { transferCollectionBasicInfo( hbmCollection, target ); transferCollectionTable( hbmCollection, target ); + transferElementTypeInfo( hbmCollection, element, target ); + transferColumnsAndFormulas( new ColumnAndFormulaSource() { @Override @@ -1920,6 +1958,29 @@ public class HbmXmlTransformer { ); } + private void transferElementTypeInfo( + PluralAttributeInfo hbmCollection, + JaxbHbmBasicCollectionElementType element, + JaxbElementCollectionImpl target) { + if ( StringHelper.isNotEmpty( element.getTypeAttribute() ) ) { + final JaxbUserTypeImpl jaxbUserType = new JaxbUserTypeImpl(); + target.setType( jaxbUserType ); + jaxbUserType.setValue( element.getTypeAttribute() ); + } + else if ( element.getType() != null && StringHelper.isNotEmpty( element.getType().getName() ) ) { + final JaxbUserTypeImpl jaxbUserType = new JaxbUserTypeImpl(); + target.setType( jaxbUserType ); + + jaxbUserType.setValue( element.getType().getName() ); + for ( JaxbHbmConfigParameterType hbmParam : element.getType().getConfigParameters() ) { + final JaxbConfigurationParameterImpl param = new JaxbConfigurationParameterImpl(); + param.setName( hbmParam.getName() ); + param.setValue( hbmParam.getValue() ); + jaxbUserType.getParameters().add( param ); + } + } + } + private void transferElementInfo( PluralAttributeInfo hbmCollection, JaxbHbmCompositeCollectionElementType compositeElement, diff --git a/hibernate-core/src/main/java/org/hibernate/boot/jaxb/mapping/spi/JaxbPluralAttribute.java b/hibernate-core/src/main/java/org/hibernate/boot/jaxb/mapping/spi/JaxbPluralAttribute.java index b4be4bd70a..e73bd876c4 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/jaxb/mapping/spi/JaxbPluralAttribute.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/jaxb/mapping/spi/JaxbPluralAttribute.java @@ -66,6 +66,10 @@ public interface JaxbPluralAttribute extends JaxbPersistentAttribute, JaxbLockab void setMapKeyColumn(JaxbMapKeyColumnImpl value); + JaxbUserTypeImpl getMapKeyType(); + + void setMapKeyType(JaxbUserTypeImpl value); + List getMapKeyJoinColumns(); JaxbForeignKeyImpl getMapKeyForeignKey(); diff --git a/hibernate-core/src/main/java/org/hibernate/boot/models/xml/internal/AbstractUserTypeCases.java b/hibernate-core/src/main/java/org/hibernate/boot/models/xml/internal/AbstractUserTypeCases.java new file mode 100644 index 0000000000..ea2529119a --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/boot/models/xml/internal/AbstractUserTypeCases.java @@ -0,0 +1,364 @@ +/* + * 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.boot.models.xml.internal; + +import org.hibernate.boot.jaxb.mapping.spi.JaxbUserTypeImpl; +import org.hibernate.boot.models.xml.spi.XmlDocumentContext; +import org.hibernate.models.spi.MutableMemberDetails; +import org.hibernate.type.descriptor.java.BasicJavaType; +import org.hibernate.type.descriptor.java.BigDecimalJavaType; +import org.hibernate.type.descriptor.java.BigIntegerJavaType; +import org.hibernate.type.descriptor.java.BlobJavaType; +import org.hibernate.type.descriptor.java.BooleanJavaType; +import org.hibernate.type.descriptor.java.ByteJavaType; +import org.hibernate.type.descriptor.java.CalendarJavaType; +import org.hibernate.type.descriptor.java.CharacterJavaType; +import org.hibernate.type.descriptor.java.ClassJavaType; +import org.hibernate.type.descriptor.java.ClobJavaType; +import org.hibernate.type.descriptor.java.CurrencyJavaType; +import org.hibernate.type.descriptor.java.DateJavaType; +import org.hibernate.type.descriptor.java.DoubleJavaType; +import org.hibernate.type.descriptor.java.DurationJavaType; +import org.hibernate.type.descriptor.java.FloatJavaType; +import org.hibernate.type.descriptor.java.InetAddressJavaType; +import org.hibernate.type.descriptor.java.InstantJavaType; +import org.hibernate.type.descriptor.java.IntegerJavaType; +import org.hibernate.type.descriptor.java.LocalDateJavaType; +import org.hibernate.type.descriptor.java.LocalDateTimeJavaType; +import org.hibernate.type.descriptor.java.LocalTimeJavaType; +import org.hibernate.type.descriptor.java.LocaleJavaType; +import org.hibernate.type.descriptor.java.LongJavaType; +import org.hibernate.type.descriptor.java.NClobJavaType; +import org.hibernate.type.descriptor.java.OffsetDateTimeJavaType; +import org.hibernate.type.descriptor.java.OffsetTimeJavaType; +import org.hibernate.type.descriptor.java.ShortJavaType; +import org.hibernate.type.descriptor.java.StringJavaType; +import org.hibernate.type.descriptor.java.TimeZoneJavaType; +import org.hibernate.type.descriptor.java.UUIDJavaType; +import org.hibernate.type.descriptor.java.UrlJavaType; +import org.hibernate.type.descriptor.java.YearJavaType; +import org.hibernate.type.descriptor.java.ZoneIdJavaType; +import org.hibernate.type.descriptor.java.ZoneOffsetJavaType; +import org.hibernate.type.descriptor.java.ZonedDateTimeJavaType; + +import jakarta.persistence.TemporalType; + +/** + * @author Steve Ebersole + */ +public abstract class AbstractUserTypeCases implements UserTypeCases { + protected abstract void applyJavaTypeAnnotation( + MutableMemberDetails memberDetails, + Class> descriptor, + XmlDocumentContext xmlDocumentContext); + + protected abstract void applyTemporalPrecision( + MutableMemberDetails memberDetails, + @SuppressWarnings("deprecation") TemporalType temporalType, + XmlDocumentContext xmlDocumentContext); + + @Override + public void handleNone( + JaxbUserTypeImpl jaxbType, + MutableMemberDetails memberDetails, + XmlDocumentContext xmlDocumentContext) { + } + + @Override + public void handleCharacter( + JaxbUserTypeImpl jaxbType, + MutableMemberDetails memberDetails, + XmlDocumentContext xmlDocumentContext) { + applyJavaTypeAnnotation( memberDetails, CharacterJavaType.class, xmlDocumentContext ); + } + + @Override + public void handleString( + JaxbUserTypeImpl jaxbType, + MutableMemberDetails memberDetails, + XmlDocumentContext xmlDocumentContext) { + applyJavaTypeAnnotation( memberDetails, StringJavaType.class, xmlDocumentContext ); + } + + @Override + public void handleByte( + JaxbUserTypeImpl jaxbType, + MutableMemberDetails memberDetails, + XmlDocumentContext xmlDocumentContext) { + applyJavaTypeAnnotation( memberDetails, ByteJavaType.class, xmlDocumentContext ); + } + + @Override + public void handleBoolean( + JaxbUserTypeImpl jaxbType, + MutableMemberDetails memberDetails, + XmlDocumentContext xmlDocumentContext) { + applyJavaTypeAnnotation( memberDetails, BooleanJavaType.class, xmlDocumentContext ); + } + + @Override + public void handleShort( + JaxbUserTypeImpl jaxbType, + MutableMemberDetails memberDetails, + XmlDocumentContext xmlDocumentContext) { + applyJavaTypeAnnotation( memberDetails, ShortJavaType.class, xmlDocumentContext ); + } + + @Override + public void handleInteger( + JaxbUserTypeImpl jaxbType, + MutableMemberDetails memberDetails, + XmlDocumentContext xmlDocumentContext) { + applyJavaTypeAnnotation( memberDetails, IntegerJavaType.class, xmlDocumentContext ); + } + + @Override + public void handleLong( + JaxbUserTypeImpl jaxbType, + MutableMemberDetails memberDetails, + XmlDocumentContext xmlDocumentContext) { + applyJavaTypeAnnotation( memberDetails, LongJavaType.class, xmlDocumentContext ); + } + + @Override + public void handleDouble( + JaxbUserTypeImpl jaxbType, + MutableMemberDetails memberDetails, + XmlDocumentContext xmlDocumentContext) { + applyJavaTypeAnnotation( memberDetails, DoubleJavaType.class, xmlDocumentContext ); + } + + @Override + public void handleFloat( + JaxbUserTypeImpl jaxbType, + MutableMemberDetails memberDetails, + XmlDocumentContext xmlDocumentContext) { + applyJavaTypeAnnotation( memberDetails, FloatJavaType.class, xmlDocumentContext ); + } + + @Override + public void handleBigInteger( + JaxbUserTypeImpl jaxbType, + MutableMemberDetails memberDetails, + XmlDocumentContext xmlDocumentContext) { + applyJavaTypeAnnotation( memberDetails, BigIntegerJavaType.class, xmlDocumentContext ); + } + + @Override + public void handleBigDecimal( + JaxbUserTypeImpl jaxbType, + MutableMemberDetails memberDetails, + XmlDocumentContext xmlDocumentContext) { + applyJavaTypeAnnotation( memberDetails, BigDecimalJavaType.class, xmlDocumentContext ); + } + + @Override + public void handleUuid( + JaxbUserTypeImpl jaxbType, + MutableMemberDetails memberDetails, + XmlDocumentContext xmlDocumentContext) { + applyJavaTypeAnnotation( memberDetails, UUIDJavaType.class, xmlDocumentContext ); + } + + @Override + public void handleUrl( + JaxbUserTypeImpl jaxbType, + MutableMemberDetails memberDetails, + XmlDocumentContext xmlDocumentContext) { + applyJavaTypeAnnotation( memberDetails, UrlJavaType.class, xmlDocumentContext ); + } + + @Override + public void handleInetAddress( + JaxbUserTypeImpl jaxbType, + MutableMemberDetails memberDetails, + XmlDocumentContext xmlDocumentContext) { + applyJavaTypeAnnotation( memberDetails, InetAddressJavaType.class, xmlDocumentContext ); + } + + @Override + public void handleCurrency( + JaxbUserTypeImpl jaxbType, + MutableMemberDetails memberDetails, + XmlDocumentContext xmlDocumentContext) { + applyJavaTypeAnnotation( memberDetails, CurrencyJavaType.class, xmlDocumentContext ); + } + + @Override + public void handleLocale( + JaxbUserTypeImpl jaxbType, + MutableMemberDetails memberDetails, + XmlDocumentContext xmlDocumentContext) { + applyJavaTypeAnnotation( memberDetails, LocaleJavaType.class, xmlDocumentContext ); + } + + @Override + public void handleClass( + JaxbUserTypeImpl jaxbType, + MutableMemberDetails memberDetails, + XmlDocumentContext xmlDocumentContext) { + applyJavaTypeAnnotation( memberDetails, ClassJavaType.class, xmlDocumentContext ); + } + + @Override + public void handleBlob( + JaxbUserTypeImpl jaxbType, + MutableMemberDetails memberDetails, + XmlDocumentContext xmlDocumentContext) { + applyJavaTypeAnnotation( memberDetails, BlobJavaType.class, xmlDocumentContext ); + } + + @Override + public void handleClob( + JaxbUserTypeImpl jaxbType, + MutableMemberDetails memberDetails, + XmlDocumentContext xmlDocumentContext) { + applyJavaTypeAnnotation( memberDetails, ClobJavaType.class, xmlDocumentContext ); + } + + @Override + public void handleNClob( + JaxbUserTypeImpl jaxbType, + MutableMemberDetails memberDetails, + XmlDocumentContext xmlDocumentContext) { + applyJavaTypeAnnotation( memberDetails, NClobJavaType.class, xmlDocumentContext ); + } + + @Override + public void handleInstant( + JaxbUserTypeImpl jaxbType, + MutableMemberDetails memberDetails, + XmlDocumentContext xmlDocumentContext) { + applyJavaTypeAnnotation( memberDetails, InstantJavaType.class, xmlDocumentContext ); + } + + @Override + public void handleDuration( + JaxbUserTypeImpl jaxbType, + MutableMemberDetails memberDetails, + XmlDocumentContext xmlDocumentContext) { + applyJavaTypeAnnotation( memberDetails, DurationJavaType.class, xmlDocumentContext ); + } + + @Override + public void handleYear( + JaxbUserTypeImpl jaxbType, + MutableMemberDetails memberDetails, + XmlDocumentContext xmlDocumentContext) { + applyJavaTypeAnnotation( memberDetails, YearJavaType.class, xmlDocumentContext ); + } + + @Override + public void handleLocalDateTime( + JaxbUserTypeImpl jaxbType, + MutableMemberDetails memberDetails, + XmlDocumentContext xmlDocumentContext) { + applyJavaTypeAnnotation( memberDetails, LocalDateTimeJavaType.class, xmlDocumentContext ); + } + + @Override + public void handleLocalDate( + JaxbUserTypeImpl jaxbType, + MutableMemberDetails memberDetails, + XmlDocumentContext xmlDocumentContext) { + applyJavaTypeAnnotation( memberDetails, LocalDateJavaType.class, xmlDocumentContext ); + } + + @Override + public void handleLocalTime( + JaxbUserTypeImpl jaxbType, + MutableMemberDetails memberDetails, + XmlDocumentContext xmlDocumentContext) { + applyJavaTypeAnnotation( memberDetails, LocalTimeJavaType.class, xmlDocumentContext ); + } + + @Override + public void handleZonedDateTime( + JaxbUserTypeImpl jaxbType, + MutableMemberDetails memberDetails, + XmlDocumentContext xmlDocumentContext) { + applyJavaTypeAnnotation( memberDetails, ZonedDateTimeJavaType.class, xmlDocumentContext ); + } + + @Override + public void handleOffsetDateTime( + JaxbUserTypeImpl jaxbType, + MutableMemberDetails memberDetails, + XmlDocumentContext xmlDocumentContext) { + applyJavaTypeAnnotation( memberDetails, OffsetDateTimeJavaType.class, xmlDocumentContext ); + } + + @Override + public void handleOffsetTime( + JaxbUserTypeImpl jaxbType, + MutableMemberDetails memberDetails, + XmlDocumentContext xmlDocumentContext) { + applyJavaTypeAnnotation( memberDetails, OffsetTimeJavaType.class, xmlDocumentContext ); + } + + @Override + public void handleZoneId( + JaxbUserTypeImpl jaxbType, + MutableMemberDetails memberDetails, + XmlDocumentContext xmlDocumentContext) { + applyJavaTypeAnnotation( memberDetails, ZoneIdJavaType.class, xmlDocumentContext ); + } + + @Override + public void handleZoneOffset( + JaxbUserTypeImpl jaxbType, + MutableMemberDetails memberDetails, + XmlDocumentContext xmlDocumentContext) { + applyJavaTypeAnnotation( memberDetails, ZoneOffsetJavaType.class, xmlDocumentContext ); + } + + @Override + public void handleTimestamp( + JaxbUserTypeImpl jaxbType, + MutableMemberDetails memberDetails, + XmlDocumentContext xmlDocumentContext) { + applyJavaTypeAnnotation( memberDetails, DateJavaType.class, xmlDocumentContext ); + //noinspection deprecation + applyTemporalPrecision( memberDetails, TemporalType.TIMESTAMP, xmlDocumentContext ); + } + + @Override + public void handleDate( + JaxbUserTypeImpl jaxbType, + MutableMemberDetails memberDetails, + XmlDocumentContext xmlDocumentContext) { + applyJavaTypeAnnotation( memberDetails, DateJavaType.class, xmlDocumentContext ); + //noinspection deprecation + applyTemporalPrecision( memberDetails, TemporalType.DATE, xmlDocumentContext ); + } + + @Override + public void handleTime( + JaxbUserTypeImpl jaxbType, + MutableMemberDetails memberDetails, + XmlDocumentContext xmlDocumentContext) { + applyJavaTypeAnnotation( memberDetails, DateJavaType.class, xmlDocumentContext ); + //noinspection deprecation + applyTemporalPrecision( memberDetails, TemporalType.TIME, xmlDocumentContext ); + } + + @Override + public void handleCalendar( + JaxbUserTypeImpl jaxbType, + MutableMemberDetails memberDetails, + XmlDocumentContext xmlDocumentContext) { + applyJavaTypeAnnotation( memberDetails, CalendarJavaType.class, xmlDocumentContext ); + } + + @Override + public void handleTimeZone( + JaxbUserTypeImpl jaxbType, + MutableMemberDetails memberDetails, + XmlDocumentContext xmlDocumentContext) { + applyJavaTypeAnnotation( memberDetails, TimeZoneJavaType.class, xmlDocumentContext ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/boot/models/xml/internal/UserTypeCases.java b/hibernate-core/src/main/java/org/hibernate/boot/models/xml/internal/UserTypeCases.java new file mode 100644 index 0000000000..7aca3de332 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/boot/models/xml/internal/UserTypeCases.java @@ -0,0 +1,92 @@ +/* + * 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.boot.models.xml.internal; + +import org.hibernate.boot.jaxb.mapping.spi.JaxbUserTypeImpl; +import org.hibernate.boot.models.xml.spi.XmlDocumentContext; +import org.hibernate.models.spi.MutableMemberDetails; + +/** + * @author Steve Ebersole + */ +public interface UserTypeCases { + void handleNone(JaxbUserTypeImpl jaxbType, MutableMemberDetails memberDetails, XmlDocumentContext xmlDocumentContext); + + void handleCharacter(JaxbUserTypeImpl jaxbType, MutableMemberDetails memberDetails, XmlDocumentContext xmlDocumentContext); + + void handleString(JaxbUserTypeImpl jaxbType, MutableMemberDetails memberDetails, XmlDocumentContext xmlDocumentContext); + + void handleByte(JaxbUserTypeImpl jaxbType, MutableMemberDetails memberDetails, XmlDocumentContext xmlDocumentContext); + + void handleBoolean(JaxbUserTypeImpl jaxbType, MutableMemberDetails memberDetails, XmlDocumentContext xmlDocumentContext); + + void handleShort(JaxbUserTypeImpl jaxbType, MutableMemberDetails memberDetails, XmlDocumentContext xmlDocumentContext); + + void handleInteger(JaxbUserTypeImpl jaxbType, MutableMemberDetails memberDetails, XmlDocumentContext xmlDocumentContext); + + void handleLong(JaxbUserTypeImpl jaxbType, MutableMemberDetails memberDetails, XmlDocumentContext xmlDocumentContext); + + void handleDouble(JaxbUserTypeImpl jaxbType, MutableMemberDetails memberDetails, XmlDocumentContext xmlDocumentContext); + + void handleFloat(JaxbUserTypeImpl jaxbType, MutableMemberDetails memberDetails, XmlDocumentContext xmlDocumentContext); + + void handleBigInteger(JaxbUserTypeImpl jaxbType, MutableMemberDetails memberDetails, XmlDocumentContext xmlDocumentContext); + + void handleBigDecimal(JaxbUserTypeImpl jaxbType, MutableMemberDetails memberDetails, XmlDocumentContext xmlDocumentContext); + + void handleUuid(JaxbUserTypeImpl jaxbType, MutableMemberDetails memberDetails, XmlDocumentContext xmlDocumentContext); + + void handleUrl(JaxbUserTypeImpl jaxbType, MutableMemberDetails memberDetails, XmlDocumentContext xmlDocumentContext); + + void handleInetAddress(JaxbUserTypeImpl jaxbType, MutableMemberDetails memberDetails, XmlDocumentContext xmlDocumentContext); + + void handleCurrency(JaxbUserTypeImpl jaxbType, MutableMemberDetails memberDetails, XmlDocumentContext xmlDocumentContext); + + void handleLocale(JaxbUserTypeImpl jaxbType, MutableMemberDetails memberDetails, XmlDocumentContext xmlDocumentContext); + + void handleClass(JaxbUserTypeImpl jaxbType, MutableMemberDetails memberDetails, XmlDocumentContext xmlDocumentContext); + + void handleBlob(JaxbUserTypeImpl jaxbType, MutableMemberDetails memberDetails, XmlDocumentContext xmlDocumentContext); + + void handleClob(JaxbUserTypeImpl jaxbType, MutableMemberDetails memberDetails, XmlDocumentContext xmlDocumentContext); + + void handleNClob(JaxbUserTypeImpl jaxbType, MutableMemberDetails memberDetails, XmlDocumentContext xmlDocumentContext); + + void handleInstant(JaxbUserTypeImpl jaxbType, MutableMemberDetails memberDetails, XmlDocumentContext xmlDocumentContext); + + void handleDuration(JaxbUserTypeImpl jaxbType, MutableMemberDetails memberDetails, XmlDocumentContext xmlDocumentContext); + + void handleYear(JaxbUserTypeImpl jaxbType, MutableMemberDetails memberDetails, XmlDocumentContext xmlDocumentContext); + + void handleLocalDateTime(JaxbUserTypeImpl jaxbType, MutableMemberDetails memberDetails, XmlDocumentContext xmlDocumentContext); + + void handleLocalDate(JaxbUserTypeImpl jaxbType, MutableMemberDetails memberDetails, XmlDocumentContext xmlDocumentContext); + + void handleLocalTime(JaxbUserTypeImpl jaxbType, MutableMemberDetails memberDetails, XmlDocumentContext xmlDocumentContext); + + void handleZonedDateTime(JaxbUserTypeImpl jaxbType, MutableMemberDetails memberDetails, XmlDocumentContext xmlDocumentContext); + + void handleOffsetDateTime(JaxbUserTypeImpl jaxbType, MutableMemberDetails memberDetails, XmlDocumentContext xmlDocumentContext); + + void handleOffsetTime(JaxbUserTypeImpl jaxbType, MutableMemberDetails memberDetails, XmlDocumentContext xmlDocumentContext); + + void handleZoneId(JaxbUserTypeImpl jaxbType, MutableMemberDetails memberDetails, XmlDocumentContext xmlDocumentContext); + + void handleZoneOffset(JaxbUserTypeImpl jaxbType, MutableMemberDetails memberDetails, XmlDocumentContext xmlDocumentContext); + + void handleTimestamp(JaxbUserTypeImpl jaxbType, MutableMemberDetails memberDetails, XmlDocumentContext xmlDocumentContext); + + void handleDate(JaxbUserTypeImpl jaxbType, MutableMemberDetails memberDetails, XmlDocumentContext xmlDocumentContext); + + void handleTime(JaxbUserTypeImpl jaxbType, MutableMemberDetails memberDetails, XmlDocumentContext xmlDocumentContext); + + void handleCalendar(JaxbUserTypeImpl jaxbType, MutableMemberDetails memberDetails, XmlDocumentContext xmlDocumentContext); + + void handleTimeZone(JaxbUserTypeImpl jaxbType, MutableMemberDetails memberDetails, XmlDocumentContext xmlDocumentContext); + + void handleGeneral(JaxbUserTypeImpl jaxbType, MutableMemberDetails memberDetails, XmlDocumentContext xmlDocumentContext); +} diff --git a/hibernate-core/src/main/java/org/hibernate/boot/models/xml/internal/UserTypeCasesMapKey.java b/hibernate-core/src/main/java/org/hibernate/boot/models/xml/internal/UserTypeCasesMapKey.java new file mode 100644 index 0000000000..8d508fa018 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/boot/models/xml/internal/UserTypeCasesMapKey.java @@ -0,0 +1,94 @@ +/* + * 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.boot.models.xml.internal; + +import java.util.Locale; + +import org.hibernate.boot.jaxb.mapping.spi.JaxbUserTypeImpl; +import org.hibernate.boot.models.HibernateAnnotations; +import org.hibernate.boot.models.JpaAnnotations; +import org.hibernate.boot.models.annotations.internal.JavaTypeAnnotation; +import org.hibernate.boot.models.annotations.internal.MapKeyJavaTypeAnnotation; +import org.hibernate.boot.models.annotations.internal.MapKeyTemporalJpaAnnotation; +import org.hibernate.boot.models.annotations.internal.MapKeyTypeAnnotation; +import org.hibernate.boot.models.xml.spi.XmlDocumentContext; +import org.hibernate.models.spi.ClassDetails; +import org.hibernate.models.spi.MutableMemberDetails; +import org.hibernate.type.descriptor.java.BasicJavaType; +import org.hibernate.usertype.UserType; + +import jakarta.persistence.MapKeyTemporal; +import jakarta.persistence.TemporalType; + +/** + * @author Steve Ebersole + */ +public class UserTypeCasesMapKey extends AbstractUserTypeCases { + public static final UserTypeCasesMapKey MAP_KEY_USER_TYPE_CASES = new UserTypeCasesMapKey(); + + public static void applyJavaTypeAnnotationStatic( + MutableMemberDetails memberDetails, + Class> descriptor, + XmlDocumentContext xmlDocumentContext) { + final MapKeyJavaTypeAnnotation javaTypeAnnotation = (MapKeyJavaTypeAnnotation) memberDetails.applyAnnotationUsage( + HibernateAnnotations.MAP_KEY_JAVA_TYPE, + xmlDocumentContext.getModelBuildingContext() + ); + javaTypeAnnotation.value( descriptor ); + } + + @Override + protected void applyJavaTypeAnnotation( + MutableMemberDetails memberDetails, + Class> descriptor, + XmlDocumentContext xmlDocumentContext) { + applyJavaTypeAnnotationStatic( memberDetails, descriptor, xmlDocumentContext ); + } + + @SuppressWarnings("deprecation") + @Override + protected void applyTemporalPrecision( + MutableMemberDetails memberDetails, + TemporalType temporalType, + XmlDocumentContext xmlDocumentContext) { + final MapKeyTemporal directUsage = memberDetails.getDirectAnnotationUsage( MapKeyTemporal.class ); + if ( directUsage != null ) { + // make sure they match + if ( directUsage.value() != temporalType ) { + throw new org.hibernate.MappingException( String.format( + Locale.ROOT, + "Mismatch in expected TemporalType on %s; found %s and %s", + memberDetails, + directUsage.value(), + temporalType + ) ); + } + return; + } + + final MapKeyTemporalJpaAnnotation temporalAnnotation = (MapKeyTemporalJpaAnnotation) memberDetails.applyAnnotationUsage( + JpaAnnotations.MAP_KEY_TEMPORAL, + xmlDocumentContext.getModelBuildingContext() + ); + temporalAnnotation.value( temporalType ); + } + + @Override + public void handleGeneral( + JaxbUserTypeImpl jaxbType, + MutableMemberDetails memberDetails, + XmlDocumentContext xmlDocumentContext) { + final ClassDetails userTypeImpl = XmlAnnotationHelper.resolveJavaType( jaxbType.getValue(), xmlDocumentContext ); + assert userTypeImpl.isImplementor( UserType.class ); + final MapKeyTypeAnnotation typeAnn = (MapKeyTypeAnnotation) memberDetails.applyAnnotationUsage( + HibernateAnnotations.MAP_KEY_TYPE, + xmlDocumentContext.getModelBuildingContext() + ); + typeAnn.value( userTypeImpl.toJavaClass() ); + typeAnn.parameters( XmlAnnotationHelper.collectParameters( jaxbType.getParameters(), xmlDocumentContext ) ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/boot/models/xml/internal/UserTypeCasesStandard.java b/hibernate-core/src/main/java/org/hibernate/boot/models/xml/internal/UserTypeCasesStandard.java new file mode 100644 index 0000000000..3c418d890c --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/boot/models/xml/internal/UserTypeCasesStandard.java @@ -0,0 +1,93 @@ +/* + * 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.boot.models.xml.internal; + +import java.util.Locale; + +import org.hibernate.boot.jaxb.mapping.spi.JaxbUserTypeImpl; +import org.hibernate.boot.models.HibernateAnnotations; +import org.hibernate.boot.models.JpaAnnotations; +import org.hibernate.boot.models.annotations.internal.JavaTypeAnnotation; +import org.hibernate.boot.models.annotations.internal.TemporalJpaAnnotation; +import org.hibernate.boot.models.annotations.internal.TypeAnnotation; +import org.hibernate.boot.models.xml.spi.XmlDocumentContext; +import org.hibernate.models.spi.ClassDetails; +import org.hibernate.models.spi.MutableMemberDetails; +import org.hibernate.type.descriptor.java.BasicJavaType; +import org.hibernate.usertype.UserType; + +import jakarta.persistence.Temporal; +import jakarta.persistence.TemporalType; + +/** + * @author Steve Ebersole + */ +public class UserTypeCasesStandard extends AbstractUserTypeCases { + public static final UserTypeCasesStandard STANDARD_USER_TYPE_CASES = new UserTypeCasesStandard(); + + public static void applyJavaTypeAnnotationStatic( + MutableMemberDetails memberDetails, + Class> descriptor, + XmlDocumentContext xmlDocumentContext) { + final JavaTypeAnnotation javaTypeAnnotation = (JavaTypeAnnotation) memberDetails.applyAnnotationUsage( + HibernateAnnotations.JAVA_TYPE, + xmlDocumentContext.getModelBuildingContext() + ); + javaTypeAnnotation.value( descriptor ); + } + + @Override + protected void applyJavaTypeAnnotation( + MutableMemberDetails memberDetails, + Class> descriptor, + XmlDocumentContext xmlDocumentContext) { + applyJavaTypeAnnotationStatic( memberDetails, descriptor, xmlDocumentContext ); + } + + @SuppressWarnings("deprecation") + @Override + protected void applyTemporalPrecision( + MutableMemberDetails memberDetails, + TemporalType temporalType, + XmlDocumentContext xmlDocumentContext) { + final Temporal directUsage = memberDetails.getDirectAnnotationUsage( Temporal.class ); + if ( directUsage != null ) { + // make sure they match + if ( directUsage.value() != temporalType ) { + throw new org.hibernate.MappingException( String.format( + Locale.ROOT, + "Mismatch in expected TemporalType on %s; found %s and %s", + memberDetails, + directUsage.value(), + temporalType + ) ); + } + return; + } + + final TemporalJpaAnnotation temporalAnnotation = (TemporalJpaAnnotation) memberDetails.applyAnnotationUsage( + JpaAnnotations.TEMPORAL, + xmlDocumentContext.getModelBuildingContext() + ); + temporalAnnotation.value( temporalType ); + } + + @Override + public void handleGeneral( + JaxbUserTypeImpl jaxbType, + MutableMemberDetails memberDetails, + XmlDocumentContext xmlDocumentContext) { + final ClassDetails userTypeImpl = XmlAnnotationHelper.resolveJavaType( jaxbType.getValue(), xmlDocumentContext ); + assert userTypeImpl.isImplementor( UserType.class ); + final TypeAnnotation typeAnn = (TypeAnnotation) memberDetails.applyAnnotationUsage( + HibernateAnnotations.TYPE, + xmlDocumentContext.getModelBuildingContext() + ); + typeAnn.value( userTypeImpl.toJavaClass() ); + typeAnn.parameters( XmlAnnotationHelper.collectParameters( jaxbType.getParameters(), xmlDocumentContext ) ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/boot/models/xml/internal/XmlAnnotationHelper.java b/hibernate-core/src/main/java/org/hibernate/boot/models/xml/internal/XmlAnnotationHelper.java index d4646a9a2b..b5f28dda14 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/models/xml/internal/XmlAnnotationHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/models/xml/internal/XmlAnnotationHelper.java @@ -133,7 +133,6 @@ import org.hibernate.boot.models.annotations.internal.TableGeneratorJpaAnnotatio import org.hibernate.boot.models.annotations.internal.TableJpaAnnotation; import org.hibernate.boot.models.annotations.internal.TargetXmlAnnotation; import org.hibernate.boot.models.annotations.internal.TemporalJpaAnnotation; -import org.hibernate.boot.models.annotations.internal.TypeAnnotation; import org.hibernate.boot.models.annotations.internal.UniqueConstraintJpaAnnotation; import org.hibernate.boot.models.annotations.internal.UuidGeneratorAnnotation; import org.hibernate.boot.models.annotations.spi.CustomSqlDetails; @@ -158,41 +157,6 @@ import org.hibernate.models.spi.MutableClassDetails; import org.hibernate.models.spi.MutableMemberDetails; import org.hibernate.models.spi.SourceModelBuildingContext; import org.hibernate.type.SqlTypes; -import org.hibernate.type.descriptor.java.BasicJavaType; -import org.hibernate.type.descriptor.java.BigDecimalJavaType; -import org.hibernate.type.descriptor.java.BigIntegerJavaType; -import org.hibernate.type.descriptor.java.BlobJavaType; -import org.hibernate.type.descriptor.java.BooleanJavaType; -import org.hibernate.type.descriptor.java.ByteJavaType; -import org.hibernate.type.descriptor.java.CalendarJavaType; -import org.hibernate.type.descriptor.java.CharacterJavaType; -import org.hibernate.type.descriptor.java.ClassJavaType; -import org.hibernate.type.descriptor.java.ClobJavaType; -import org.hibernate.type.descriptor.java.CurrencyJavaType; -import org.hibernate.type.descriptor.java.DateJavaType; -import org.hibernate.type.descriptor.java.DoubleJavaType; -import org.hibernate.type.descriptor.java.DurationJavaType; -import org.hibernate.type.descriptor.java.InetAddressJavaType; -import org.hibernate.type.descriptor.java.InstantJavaType; -import org.hibernate.type.descriptor.java.IntegerJavaType; -import org.hibernate.type.descriptor.java.LocalDateJavaType; -import org.hibernate.type.descriptor.java.LocalDateTimeJavaType; -import org.hibernate.type.descriptor.java.LocalTimeJavaType; -import org.hibernate.type.descriptor.java.LocaleJavaType; -import org.hibernate.type.descriptor.java.LongJavaType; -import org.hibernate.type.descriptor.java.NClobJavaType; -import org.hibernate.type.descriptor.java.OffsetDateTimeJavaType; -import org.hibernate.type.descriptor.java.OffsetTimeJavaType; -import org.hibernate.type.descriptor.java.ShortJavaType; -import org.hibernate.type.descriptor.java.StringJavaType; -import org.hibernate.type.descriptor.java.TimeZoneJavaType; -import org.hibernate.type.descriptor.java.UUIDJavaType; -import org.hibernate.type.descriptor.java.UrlJavaType; -import org.hibernate.type.descriptor.java.YearJavaType; -import org.hibernate.type.descriptor.java.ZoneIdJavaType; -import org.hibernate.type.descriptor.java.ZoneOffsetJavaType; -import org.hibernate.type.descriptor.java.ZonedDateTimeJavaType; -import org.hibernate.usertype.UserType; import jakarta.persistence.AssociationOverride; import jakarta.persistence.AttributeOverride; @@ -203,7 +167,6 @@ import jakarta.persistence.EnumType; import jakarta.persistence.Index; import jakarta.persistence.PrimaryKeyJoinColumn; import jakarta.persistence.SecondaryTable; -import jakarta.persistence.Temporal; import jakarta.persistence.TemporalType; import jakarta.persistence.UniqueConstraint; import org.checkerframework.checker.nullness.qual.Nullable; @@ -226,6 +189,8 @@ import static org.hibernate.boot.models.JpaAnnotations.EXCLUDE_SUPERCLASS_LISTEN import static org.hibernate.boot.models.JpaAnnotations.INDEX; import static org.hibernate.boot.models.JpaAnnotations.SECONDARY_TABLE; import static org.hibernate.boot.models.JpaAnnotations.UNIQUE_CONSTRAINT; +import static org.hibernate.boot.models.xml.internal.UserTypeCasesMapKey.MAP_KEY_USER_TYPE_CASES; +import static org.hibernate.boot.models.xml.internal.UserTypeCasesStandard.STANDARD_USER_TYPE_CASES; /** * Helper for creating annotation from equivalent JAXB @@ -302,303 +267,191 @@ public class XmlAnnotationHelper { JaxbUserTypeImpl jaxbType, MutableMemberDetails memberDetails, XmlDocumentContext xmlDocumentContext) { - if ( jaxbType == null || StringHelper.isEmpty( jaxbType.getValue() ) ) { - return; - } - - final boolean wasSpecialCase = handleSpecialBasicTypeCases( jaxbType, memberDetails, xmlDocumentContext ); - if ( wasSpecialCase ) { - return; - } - - final ClassDetails userTypeImpl = resolveJavaType( jaxbType.getValue(), xmlDocumentContext ); - assert userTypeImpl.isImplementor( UserType.class ); - final TypeAnnotation typeAnn = (TypeAnnotation) memberDetails.applyAnnotationUsage( - HibernateAnnotations.TYPE, - xmlDocumentContext.getModelBuildingContext() - ); - typeAnn.value( userTypeImpl.toJavaClass() ); - typeAnn.parameters( collectParameters( jaxbType.getParameters(), xmlDocumentContext ) ); + applyUserType( jaxbType, memberDetails, STANDARD_USER_TYPE_CASES, xmlDocumentContext ); } - private static boolean handleSpecialBasicTypeCases( + public static void applyMapKeyUserType( JaxbUserTypeImpl jaxbType, MutableMemberDetails memberDetails, XmlDocumentContext xmlDocumentContext) { - if ( jaxbType.getValue().equalsIgnoreCase( "char" ) + applyUserType( jaxbType, memberDetails, MAP_KEY_USER_TYPE_CASES, xmlDocumentContext ); + } + + public static void applyUserType( + JaxbUserTypeImpl jaxbType, + MutableMemberDetails memberDetails, + UserTypeCases cases, + XmlDocumentContext xmlDocumentContext) { + if ( jaxbType == null || StringHelper.isEmpty( jaxbType.getValue() ) ) { + cases.handleNone( jaxbType, memberDetails, xmlDocumentContext ); + } + else if ( jaxbType.getValue().equalsIgnoreCase( "char" ) || jaxbType.getValue().equalsIgnoreCase( "character" ) || Character.class.getName().equalsIgnoreCase( jaxbType.getValue() ) ) { - applyJavaTypeAnnotation( memberDetails, CharacterJavaType.class, xmlDocumentContext ); - return true; + cases.handleCharacter( jaxbType, memberDetails, xmlDocumentContext ); } - - if ( jaxbType.getValue().equalsIgnoreCase( "string" ) + else if ( jaxbType.getValue().equalsIgnoreCase( "string" ) || String.class.getName().equalsIgnoreCase( jaxbType.getValue() ) ) { - applyJavaTypeAnnotation( memberDetails, StringJavaType.class, xmlDocumentContext ); - return true; + cases.handleString( jaxbType, memberDetails, xmlDocumentContext ); } - - if ( jaxbType.getValue().equalsIgnoreCase( "byte" ) + else if ( jaxbType.getValue().equalsIgnoreCase( "byte" ) || Byte.class.getName().equals( jaxbType.getValue() ) ) { - applyJavaTypeAnnotation( memberDetails, ByteJavaType.class, xmlDocumentContext ); - return true; + cases.handleByte( jaxbType, memberDetails, xmlDocumentContext ); } - - if ( jaxbType.getValue().equalsIgnoreCase( "boolean" ) + else if ( jaxbType.getValue().equalsIgnoreCase( "boolean" ) || Boolean.class.getName().equals( jaxbType.getValue() ) ) { - applyJavaTypeAnnotation( memberDetails, BooleanJavaType.class, xmlDocumentContext ); - return true; + cases.handleBoolean( jaxbType, memberDetails, xmlDocumentContext ); } - - if ( jaxbType.getValue().equalsIgnoreCase( "short" ) + else if ( jaxbType.getValue().equalsIgnoreCase( "short" ) || Short.class.getName().equals( jaxbType.getValue() ) ) { - applyJavaTypeAnnotation( memberDetails, ShortJavaType.class, xmlDocumentContext ); - return true; + cases.handleShort( jaxbType, memberDetails, xmlDocumentContext ); } - - if ( jaxbType.getValue().equalsIgnoreCase( "int" ) + else if ( jaxbType.getValue().equalsIgnoreCase( "int" ) || jaxbType.getValue().equalsIgnoreCase( "integer" ) || Integer.class.getName().equals( jaxbType.getValue() ) ) { - applyJavaTypeAnnotation( memberDetails, IntegerJavaType.class, xmlDocumentContext ); - return true; + cases.handleInteger( jaxbType, memberDetails, xmlDocumentContext ); } - - if ( jaxbType.getValue().equalsIgnoreCase( "long" ) + else if ( jaxbType.getValue().equalsIgnoreCase( "long" ) || Long.class.getName().equals( jaxbType.getValue() ) ) { - applyJavaTypeAnnotation( memberDetails, LongJavaType.class, xmlDocumentContext ); - return true; + cases.handleLong( jaxbType, memberDetails, xmlDocumentContext ); } - - if ( jaxbType.getValue().equalsIgnoreCase( "double" ) + else if ( jaxbType.getValue().equalsIgnoreCase( "double" ) || Double.class.getName().equals( jaxbType.getValue() ) ) { - applyJavaTypeAnnotation( memberDetails, DoubleJavaType.class, xmlDocumentContext ); - return true; + cases.handleDouble( jaxbType, memberDetails, xmlDocumentContext ); } - - if ( jaxbType.getValue().equalsIgnoreCase( "float" ) + else if ( jaxbType.getValue().equalsIgnoreCase( "float" ) || Float.class.getName().equals( jaxbType.getValue() ) ) { - applyJavaTypeAnnotation( memberDetails, DoubleJavaType.class, xmlDocumentContext ); - return true; + cases.handleFloat( jaxbType, memberDetails, xmlDocumentContext ); } - - if ( jaxbType.getValue().equalsIgnoreCase( "biginteger" ) + else if ( jaxbType.getValue().equalsIgnoreCase( "biginteger" ) || jaxbType.getValue().equalsIgnoreCase( "big_integer" ) || BigInteger.class.getName().equals( jaxbType.getValue() ) ) { - applyJavaTypeAnnotation( memberDetails, BigIntegerJavaType.class, xmlDocumentContext ); - return true; + cases.handleBigInteger( jaxbType, memberDetails, xmlDocumentContext ); } - - if ( jaxbType.getValue().equalsIgnoreCase( "bigdecimal" ) + else if ( jaxbType.getValue().equalsIgnoreCase( "bigdecimal" ) || jaxbType.getValue().equalsIgnoreCase( "big_decimal" ) || BigDecimal.class.getName().equals( jaxbType.getValue() ) ) { - applyJavaTypeAnnotation( memberDetails, BigDecimalJavaType.class, xmlDocumentContext ); - return true; + cases.handleBigDecimal( jaxbType, memberDetails, xmlDocumentContext ); } - - if ( jaxbType.getValue().equalsIgnoreCase( "uuid" ) + else if ( jaxbType.getValue().equalsIgnoreCase( "uuid" ) || UUID.class.getName().equals( jaxbType.getValue() ) ) { - applyJavaTypeAnnotation( memberDetails, UUIDJavaType.class, xmlDocumentContext ); - return true; + cases.handleUuid( jaxbType, memberDetails, xmlDocumentContext ); } - - if ( jaxbType.getValue().equalsIgnoreCase( "url" ) + else if ( jaxbType.getValue().equalsIgnoreCase( "url" ) || URL.class.getName().equals( jaxbType.getValue() ) ) { - applyJavaTypeAnnotation( memberDetails, UrlJavaType.class, xmlDocumentContext ); - return true; + cases.handleUrl( jaxbType, memberDetails, xmlDocumentContext ); } - - if ( jaxbType.getValue().equalsIgnoreCase( "inet" ) + else if ( jaxbType.getValue().equalsIgnoreCase( "inet" ) || jaxbType.getValue().equalsIgnoreCase( "inetaddress" ) || jaxbType.getValue().equalsIgnoreCase( "inet_address" ) || InetAddress.class.getName().equals( jaxbType.getValue() ) ) { - applyJavaTypeAnnotation( memberDetails, InetAddressJavaType.class, xmlDocumentContext ); - return true; + cases.handleInetAddress( jaxbType, memberDetails, xmlDocumentContext ); } - - if ( jaxbType.getValue().equalsIgnoreCase( "currency" ) + else if ( jaxbType.getValue().equalsIgnoreCase( "currency" ) || Currency.class.getName().equals( jaxbType.getValue() ) ) { - applyJavaTypeAnnotation( memberDetails, CurrencyJavaType.class, xmlDocumentContext ); - return true; + cases.handleCurrency( jaxbType, memberDetails, xmlDocumentContext ); } - - if ( jaxbType.getValue().equalsIgnoreCase( "locale" ) + else if ( jaxbType.getValue().equalsIgnoreCase( "locale" ) || Locale.class.getName().equals( jaxbType.getValue() ) ) { - applyJavaTypeAnnotation( memberDetails, LocaleJavaType.class, xmlDocumentContext ); - return true; + cases.handleLocale( jaxbType, memberDetails, xmlDocumentContext ); } - - if ( jaxbType.getValue().equalsIgnoreCase( "class" ) + else if ( jaxbType.getValue().equalsIgnoreCase( "class" ) || Class.class.getName().equals( jaxbType.getValue() ) ) { - applyJavaTypeAnnotation( memberDetails, ClassJavaType.class, xmlDocumentContext ); - return true; + cases.handleClass( jaxbType, memberDetails, xmlDocumentContext ); } - - if ( jaxbType.getValue().equalsIgnoreCase( "blob" ) + else if ( jaxbType.getValue().equalsIgnoreCase( "blob" ) || Blob.class.getName().equals( jaxbType.getValue() ) ) { - applyJavaTypeAnnotation( memberDetails, BlobJavaType.class, xmlDocumentContext ); - return true; + cases.handleBlob( jaxbType, memberDetails, xmlDocumentContext ); } - - if ( jaxbType.getValue().equalsIgnoreCase( "clob" ) + else if ( jaxbType.getValue().equalsIgnoreCase( "clob" ) || Clob.class.getName().equals( jaxbType.getValue() ) ) { - applyJavaTypeAnnotation( memberDetails, ClobJavaType.class, xmlDocumentContext ); - return true; + cases.handleClob( jaxbType, memberDetails, xmlDocumentContext ); } - - if ( jaxbType.getValue().equalsIgnoreCase( "nclob" ) + else if ( jaxbType.getValue().equalsIgnoreCase( "nclob" ) || NClob.class.getName().equals( jaxbType.getValue() ) ) { - applyJavaTypeAnnotation( memberDetails, NClobJavaType.class, xmlDocumentContext ); - return true; + cases.handleNClob( jaxbType, memberDetails, xmlDocumentContext ); } - - if ( jaxbType.getValue().equalsIgnoreCase( "instant" ) + else if ( jaxbType.getValue().equalsIgnoreCase( "instant" ) || Instant.class.getName().equals( jaxbType.getValue() ) ) { - applyJavaTypeAnnotation( memberDetails, InstantJavaType.class, xmlDocumentContext ); - return true; + cases.handleInstant( jaxbType, memberDetails, xmlDocumentContext ); } - - if ( jaxbType.getValue().equalsIgnoreCase( "duration" ) + else if ( jaxbType.getValue().equalsIgnoreCase( "duration" ) || Duration.class.getName().equals( jaxbType.getValue() ) ) { - applyJavaTypeAnnotation( memberDetails, DurationJavaType.class, xmlDocumentContext ); - return true; + cases.handleDuration( jaxbType, memberDetails, xmlDocumentContext ); } - - if ( jaxbType.getValue().equalsIgnoreCase( "year" ) + else if ( jaxbType.getValue().equalsIgnoreCase( "year" ) || Year.class.getName().equals( jaxbType.getValue() ) ) { - applyJavaTypeAnnotation( memberDetails, YearJavaType.class, xmlDocumentContext ); - return true; + cases.handleYear( jaxbType, memberDetails, xmlDocumentContext ); } - - if ( jaxbType.getValue().equalsIgnoreCase( "localdatetime" ) + else if ( jaxbType.getValue().equalsIgnoreCase( "localdatetime" ) || jaxbType.getValue().equalsIgnoreCase( "local_date_time" ) || LocalDateTime.class.getName().equals( jaxbType.getValue() ) ) { - applyJavaTypeAnnotation( memberDetails, LocalDateTimeJavaType.class, xmlDocumentContext ); - return true; + cases.handleLocalDateTime( jaxbType, memberDetails, xmlDocumentContext ); } - - if ( jaxbType.getValue().equalsIgnoreCase( "localdate" ) + else if ( jaxbType.getValue().equalsIgnoreCase( "localdate" ) || jaxbType.getValue().equalsIgnoreCase( "local_date" ) || LocalDate.class.getName().equals( jaxbType.getValue() ) ) { - applyJavaTypeAnnotation( memberDetails, LocalDateJavaType.class, xmlDocumentContext ); - return true; + cases.handleLocalDate( jaxbType, memberDetails, xmlDocumentContext ); } - - if ( jaxbType.getValue().equalsIgnoreCase( "localtime" ) + else if ( jaxbType.getValue().equalsIgnoreCase( "localtime" ) || jaxbType.getValue().equalsIgnoreCase( "local_time" ) || LocalTime.class.getName().equals( jaxbType.getValue() ) ) { - applyJavaTypeAnnotation( memberDetails, LocalTimeJavaType.class, xmlDocumentContext ); - return true; + cases.handleLocalTime( jaxbType, memberDetails, xmlDocumentContext ); } - - if ( jaxbType.getValue().equalsIgnoreCase( "zoneddatetime" ) + else if ( jaxbType.getValue().equalsIgnoreCase( "zoneddatetime" ) || jaxbType.getValue().equalsIgnoreCase( "zoned_date_time" ) || ZonedDateTime.class.getName().equals( jaxbType.getValue() ) ) { - applyJavaTypeAnnotation( memberDetails, ZonedDateTimeJavaType.class, xmlDocumentContext ); - return true; + cases.handleZonedDateTime( jaxbType, memberDetails, xmlDocumentContext ); } - - if ( jaxbType.getValue().equalsIgnoreCase( "offsetdatetime" ) + else if ( jaxbType.getValue().equalsIgnoreCase( "offsetdatetime" ) || jaxbType.getValue().equalsIgnoreCase( "offset_date_time" ) || OffsetDateTime.class.getName().equals( jaxbType.getValue() ) ) { - applyJavaTypeAnnotation( memberDetails, OffsetDateTimeJavaType.class, xmlDocumentContext ); - return true; + cases.handleOffsetDateTime( jaxbType, memberDetails, xmlDocumentContext ); } - - if ( jaxbType.getValue().equalsIgnoreCase( "offsettime" ) + else if ( jaxbType.getValue().equalsIgnoreCase( "offsettime" ) || jaxbType.getValue().equalsIgnoreCase( "offset_time" ) || OffsetTime.class.getName().equals( jaxbType.getValue() ) ) { - applyJavaTypeAnnotation( memberDetails, OffsetTimeJavaType.class, xmlDocumentContext ); - return true; + cases.handleOffsetTime( jaxbType, memberDetails, xmlDocumentContext ); } - - if ( jaxbType.getValue().equalsIgnoreCase( "zoneid" ) + else if ( jaxbType.getValue().equalsIgnoreCase( "zoneid" ) || jaxbType.getValue().equalsIgnoreCase( "zone_id" ) || ZoneId.class.getName().equals( jaxbType.getValue() ) ) { - applyJavaTypeAnnotation( memberDetails, ZoneIdJavaType.class, xmlDocumentContext ); - return true; + cases.handleZoneId( jaxbType, memberDetails, xmlDocumentContext ); } - - if ( jaxbType.getValue().equalsIgnoreCase( "zoneoffset" ) + else if ( jaxbType.getValue().equalsIgnoreCase( "zoneoffset" ) || jaxbType.getValue().equalsIgnoreCase( "zone_offset" ) || ZoneOffset.class.getName().equals( jaxbType.getValue() ) ) { - applyJavaTypeAnnotation( memberDetails, ZoneOffsetJavaType.class, xmlDocumentContext ); - return true; + cases.handleZoneOffset( jaxbType, memberDetails, xmlDocumentContext ); } - - if ( jaxbType.getValue().equalsIgnoreCase( "timestamp" ) + else if ( jaxbType.getValue().equalsIgnoreCase( "timestamp" ) || jaxbType.getValue().equalsIgnoreCase( "time_stamp" ) || java.util.Date.class.getName().equals( jaxbType.getValue() ) || Timestamp.class.getName().equals( jaxbType.getValue() ) ) { - applyJavaTypeAnnotation( memberDetails, DateJavaType.class, xmlDocumentContext ); - applyTemporalPrecision( memberDetails, TemporalType.TIMESTAMP, xmlDocumentContext ); - return true; + cases.handleTimestamp( jaxbType, memberDetails, xmlDocumentContext ); } - - if ( jaxbType.getValue().equalsIgnoreCase( "date" ) + else if ( jaxbType.getValue().equalsIgnoreCase( "date" ) || java.sql.Date.class.getName().equals( jaxbType.getValue() ) ) { - applyJavaTypeAnnotation( memberDetails, DateJavaType.class, xmlDocumentContext ); - applyTemporalPrecision( memberDetails, TemporalType.DATE, xmlDocumentContext ); - return true; + cases.handleDate( jaxbType, memberDetails, xmlDocumentContext ); } - - if ( jaxbType.getValue().equalsIgnoreCase( "time" ) + else if ( jaxbType.getValue().equalsIgnoreCase( "time" ) || java.sql.Time.class.getName().equals( jaxbType.getValue() ) ) { - applyJavaTypeAnnotation( memberDetails, DateJavaType.class, xmlDocumentContext ); - applyTemporalPrecision( memberDetails, TemporalType.TIME, xmlDocumentContext ); - return true; + cases.handleTime( jaxbType, memberDetails, xmlDocumentContext ); } - - if ( jaxbType.getValue().equalsIgnoreCase( "calendar" ) + else if ( jaxbType.getValue().equalsIgnoreCase( "calendar" ) || jaxbType.getValue().equalsIgnoreCase( "gregoriancalendar" ) || jaxbType.getValue().equalsIgnoreCase( "gregorian_calendar" ) || Calendar.class.getName().equals( jaxbType.getValue() ) || GregorianCalendar.class.getName().equals( jaxbType.getValue() ) ) { - applyJavaTypeAnnotation( memberDetails, CalendarJavaType.class, xmlDocumentContext ); - return true; + cases.handleCalendar( jaxbType, memberDetails, xmlDocumentContext ); } - - if ( jaxbType.getValue().equalsIgnoreCase( "timezone" ) + else if ( jaxbType.getValue().equalsIgnoreCase( "timezone" ) || jaxbType.getValue().equalsIgnoreCase( "time_zone" ) || TimeZone.class.getName().equals( jaxbType.getValue() ) ) { - applyJavaTypeAnnotation( memberDetails, TimeZoneJavaType.class, xmlDocumentContext ); - return true; + cases.handleTimeZone( jaxbType, memberDetails, xmlDocumentContext ); } - - return false; - } - - private static void applyJavaTypeAnnotation( - MutableMemberDetails memberDetails, - Class> descriptor, - XmlDocumentContext xmlDocumentContext) { - final JavaTypeAnnotation javaTypeAnnotation = (JavaTypeAnnotation) memberDetails.applyAnnotationUsage( - HibernateAnnotations.JAVA_TYPE, - xmlDocumentContext.getModelBuildingContext() - ); - javaTypeAnnotation.value( descriptor ); - } - - private static void applyTemporalPrecision(MutableMemberDetails memberDetails, TemporalType temporalType, XmlDocumentContext xmlDocumentContext) { - final Temporal directUsage = memberDetails.getDirectAnnotationUsage( Temporal.class ); - if ( directUsage != null ) { - // make sure they match - if ( directUsage.value() != temporalType ) { - throw new org.hibernate.MappingException( String.format( - Locale.ROOT, - "Mismatch in expected TemporalType on %s; found %s and %s", - memberDetails, - directUsage.value(), - temporalType - ) ); - } - return; + else { + cases.handleGeneral( jaxbType, memberDetails, xmlDocumentContext ); } - - final TemporalJpaAnnotation temporalAnnotation = (TemporalJpaAnnotation) memberDetails.applyAnnotationUsage( - JpaAnnotations.TEMPORAL, - xmlDocumentContext.getModelBuildingContext() - ); - temporalAnnotation.value( temporalType ); } private static final Parameter[] NO_PARAMETERS = new Parameter[0]; diff --git a/hibernate-core/src/main/java/org/hibernate/boot/models/xml/internal/attr/CommonPluralAttributeProcessing.java b/hibernate-core/src/main/java/org/hibernate/boot/models/xml/internal/attr/CommonPluralAttributeProcessing.java index 7cc19f58b0..8bee796ab6 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/models/xml/internal/attr/CommonPluralAttributeProcessing.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/models/xml/internal/attr/CommonPluralAttributeProcessing.java @@ -150,6 +150,10 @@ public class CommonPluralAttributeProcessing { columnAnn.apply( jaxbPluralAttribute.getMapKeyColumn(), xmlDocumentContext ); } + if ( jaxbPluralAttribute.getMapKeyType() != null ) { + XmlAnnotationHelper.applyMapKeyUserType( jaxbPluralAttribute.getMapKeyType(), memberDetails, xmlDocumentContext ); + } + JoinColumnProcessing.applyMapKeyJoinColumns( jaxbPluralAttribute.getMapKeyJoinColumns(), memberDetails, diff --git a/hibernate-core/src/main/resources/org/hibernate/xsd/mapping/mapping-7.0.xsd b/hibernate-core/src/main/resources/org/hibernate/xsd/mapping/mapping-7.0.xsd index 30df69c2f7..023bb49e4f 100644 --- a/hibernate-core/src/main/resources/org/hibernate/xsd/mapping/mapping-7.0.xsd +++ b/hibernate-core/src/main/resources/org/hibernate/xsd/mapping/mapping-7.0.xsd @@ -3290,7 +3290,10 @@ - + + + +