From f6b0c1452317411d5a1295c661fb75f280bc5040 Mon Sep 17 00:00:00 2001 From: Andrea Boriero Date: Tue, 21 Nov 2023 19:07:08 +0100 Subject: [PATCH] #22 - Create AnnotationUsage for discriminator-value, discriminator-column and discriminator-formula in XML --- .../xml/internal/ManagedTypeProcessor.java | 17 +++ .../xml/internal/XmlAnnotationHelper.java | 82 ++++++++++++ .../xml/complete/DiscriminatorValueTest.java | 124 ++++++++++++++++++ .../mappings/complete/discriminator-value.xml | 43 ++++++ 4 files changed, 266 insertions(+) create mode 100644 src/test/java/org/hibernate/models/orm/xml/complete/DiscriminatorValueTest.java create mode 100644 src/test/resources/mappings/complete/discriminator-value.xml diff --git a/src/main/java/org/hibernate/boot/models/categorize/xml/internal/ManagedTypeProcessor.java b/src/main/java/org/hibernate/boot/models/categorize/xml/internal/ManagedTypeProcessor.java index 60f21ba..ad688c5 100644 --- a/src/main/java/org/hibernate/boot/models/categorize/xml/internal/ManagedTypeProcessor.java +++ b/src/main/java/org/hibernate/boot/models/categorize/xml/internal/ManagedTypeProcessor.java @@ -482,6 +482,23 @@ private static void processEntityMetadata( XmlAnnotationHelper.applyNamedEntityGraph( namedEntityGraph, classDetails, xmlDocumentContext ); } + XmlAnnotationHelper.applyDiscriminatorValue( + jaxbEntity.getDiscriminatorValue(), + classDetails, + xmlDocumentContext + ); + + XmlAnnotationHelper.applyDiscriminatorColumn( + jaxbEntity.getDiscriminatorColumn(), + classDetails, + xmlDocumentContext + ); + + XmlAnnotationHelper.applyDiscriminatorFormula( + jaxbEntity.getDiscriminatorFormula(), + classDetails, + xmlDocumentContext + ); // todo : secondary-tables } diff --git a/src/main/java/org/hibernate/boot/models/categorize/xml/internal/XmlAnnotationHelper.java b/src/main/java/org/hibernate/boot/models/categorize/xml/internal/XmlAnnotationHelper.java index 35084d7..38a064e 100644 --- a/src/main/java/org/hibernate/boot/models/categorize/xml/internal/XmlAnnotationHelper.java +++ b/src/main/java/org/hibernate/boot/models/categorize/xml/internal/XmlAnnotationHelper.java @@ -23,6 +23,7 @@ import org.hibernate.annotations.CascadeType; import org.hibernate.annotations.CollectionId; import org.hibernate.annotations.CollectionType; +import org.hibernate.annotations.DiscriminatorFormula; import org.hibernate.annotations.Filter; import org.hibernate.annotations.FilterJoinTable; import org.hibernate.annotations.JavaType; @@ -53,6 +54,8 @@ import org.hibernate.boot.jaxb.mapping.spi.JaxbConfigurationParameterImpl; import org.hibernate.boot.jaxb.mapping.spi.JaxbConvertImpl; import org.hibernate.boot.jaxb.mapping.spi.JaxbCustomSqlImpl; +import org.hibernate.boot.jaxb.mapping.spi.JaxbDiscriminatorColumnImpl; +import org.hibernate.boot.jaxb.mapping.spi.JaxbDiscriminatorColumnImpl; import org.hibernate.boot.jaxb.mapping.spi.JaxbEmbeddedIdImpl; import org.hibernate.boot.jaxb.mapping.spi.JaxbEntity; import org.hibernate.boot.jaxb.mapping.spi.JaxbEntityListenerImpl; @@ -111,6 +114,8 @@ import jakarta.persistence.CheckConstraint; import jakarta.persistence.Column; import jakarta.persistence.Convert; +import jakarta.persistence.DiscriminatorColumn; +import jakarta.persistence.DiscriminatorValue; import jakarta.persistence.EmbeddedId; import jakarta.persistence.Entity; import jakarta.persistence.EntityListeners; @@ -1496,4 +1501,81 @@ private static List> makeNamedAttribu } return namedAttributeNodeAnnotations; } + + static void applyDiscriminatorValue( + String discriminatorValue, + MutableClassDetails target, + XmlDocumentContext xmlDocumentContext) { + if ( discriminatorValue != null ) { + final MutableAnnotationUsage rowIdAnn = XmlProcessingHelper + .getOrMakeAnnotation( DiscriminatorValue.class, target, xmlDocumentContext ); + applyAttributeIfSpecified( rowIdAnn, "value", discriminatorValue ); + } + } + + static void applyDiscriminatorColumn( + JaxbDiscriminatorColumnImpl discriminatorColumn, + MutableClassDetails target, + XmlDocumentContext xmlDocumentContext){ + if ( discriminatorColumn != null ) { + final MutableAnnotationUsage discriminatorColumnAnn = XmlProcessingHelper + .getOrMakeAnnotation( DiscriminatorColumn.class, target, xmlDocumentContext ); + final AnnotationDescriptor discriminatorColumnDescriptor = xmlDocumentContext + .getModelBuildingContext() + .getAnnotationDescriptorRegistry() + .getDescriptor( DiscriminatorColumn.class ); + applyOr( + discriminatorColumn, + JaxbDiscriminatorColumnImpl::getName, + "name", + discriminatorColumnAnn, + discriminatorColumnDescriptor + ); + + applyOr( + discriminatorColumn, + JaxbDiscriminatorColumnImpl::getDiscriminatorType, + "discriminatorType", + discriminatorColumnAnn, + discriminatorColumnDescriptor + ); + applyOr( + discriminatorColumn, + JaxbDiscriminatorColumnImpl::getColumnDefinition, + "columnDefinition", + discriminatorColumnAnn, + discriminatorColumnDescriptor + ); + applyOr( + discriminatorColumn, + JaxbDiscriminatorColumnImpl::getOptions, + "options", + discriminatorColumnAnn, + discriminatorColumnDescriptor + ); + applyOr( + discriminatorColumn, + JaxbDiscriminatorColumnImpl::getLength, + "length", + discriminatorColumnAnn, + discriminatorColumnDescriptor + ); + + // todo : add force-selection attribute to @DiscriminatorColumn + } + + } + + public static void applyDiscriminatorFormula( + String discriminatorFormula, + MutableClassDetails target, + XmlDocumentContext xmlDocumentContext) { + if ( StringHelper.isNotEmpty( discriminatorFormula ) ) { + final MutableAnnotationUsage discriminatorFormulaAnn = XmlProcessingHelper + .getOrMakeAnnotation( DiscriminatorFormula.class, target, xmlDocumentContext ); + discriminatorFormulaAnn.setAttributeValue( "value", discriminatorFormula ); + + // todo add to mapping-3.2.0.xsd discriminatorType of @DiscriminatorFormula + } + } } diff --git a/src/test/java/org/hibernate/models/orm/xml/complete/DiscriminatorValueTest.java b/src/test/java/org/hibernate/models/orm/xml/complete/DiscriminatorValueTest.java new file mode 100644 index 0000000..668bad0 --- /dev/null +++ b/src/test/java/org/hibernate/models/orm/xml/complete/DiscriminatorValueTest.java @@ -0,0 +1,124 @@ +package org.hibernate.models.orm.xml.complete; + +import java.util.Set; + +import org.hibernate.annotations.DiscriminatorFormula; +import org.hibernate.boot.internal.BootstrapContextImpl; +import org.hibernate.boot.internal.MetadataBuilderImpl; +import org.hibernate.boot.model.process.spi.ManagedResources; +import org.hibernate.boot.models.categorize.spi.CategorizedDomainModel; +import org.hibernate.boot.models.categorize.spi.EntityHierarchy; +import org.hibernate.boot.models.categorize.spi.EntityTypeMetadata; +import org.hibernate.boot.models.categorize.spi.IdentifiableTypeMetadata; +import org.hibernate.boot.registry.StandardServiceRegistry; +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.models.orm.process.ManagedResourcesImpl; +import org.hibernate.models.spi.AnnotationUsage; + +import org.junit.jupiter.api.Test; + +import jakarta.persistence.DiscriminatorColumn; +import jakarta.persistence.DiscriminatorType; +import jakarta.persistence.DiscriminatorValue; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.hibernate.boot.models.categorize.spi.ManagedResourcesProcessor.processManagedResources; + +public class DiscriminatorValueTest { + @Test + void testDiscriminatorValue() { + final ManagedResources managedResources = new ManagedResourcesImpl.Builder() + .addXmlMappings( "mappings/complete/discriminator-value.xml" ) + .build(); + try (StandardServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().build()) { + final BootstrapContextImpl bootstrapContext = new BootstrapContextImpl( + serviceRegistry, + new MetadataBuilderImpl.MetadataBuildingOptionsImpl( serviceRegistry ) + ); + final CategorizedDomainModel categorizedDomainModel = processManagedResources( + managedResources, + bootstrapContext + ); + + final Set entityHierarchies = categorizedDomainModel.getEntityHierarchies(); + assertThat( entityHierarchies ).hasSize( 3 ); + + for ( EntityHierarchy entityHierarchy : entityHierarchies ) { + final EntityTypeMetadata root = entityHierarchy.getRoot(); + + final String entityName = root.getClassDetails().getName(); + if ( entityName.equals( "org.hibernate.models.orm.xml.complete.Root" ) ) { + + final AnnotationUsage rootDiscriminatorValueAnnotationUsage = root.getClassDetails() + .getAnnotationUsage( DiscriminatorValue.class ); + assertThat( rootDiscriminatorValueAnnotationUsage ).isNull(); + + final AnnotationUsage discriminatorColumnAnnotationUsage = root.getClassDetails() + .getAnnotationUsage( DiscriminatorColumn.class ); + + assertThat( discriminatorColumnAnnotationUsage ).isNotNull(); + + final String discriminatorColumName = discriminatorColumnAnnotationUsage.getString( "name" ); + assertThat( discriminatorColumName ).isEqualTo( "TYPE_COLUMN" ); + + final DiscriminatorType discriminatorColumnType = discriminatorColumnAnnotationUsage + .getEnum( "discriminatorType" ); + assertThat( discriminatorColumnType ).isEqualTo( DiscriminatorType.INTEGER ); + + final Iterable subTypes = root.getSubTypes(); + assertThat( subTypes ).hasSize( 1 ); + + final IdentifiableTypeMetadata subType = subTypes.iterator().next(); + final AnnotationUsage subTypeDiscriminatorValueAnnotationUsage = subType.getClassDetails() + .getAnnotationUsage( DiscriminatorValue.class ); + assertThat( subTypeDiscriminatorValueAnnotationUsage ).isNotNull(); + String discriminatorValue = subTypeDiscriminatorValueAnnotationUsage.getString( "value" ); + assertThat( discriminatorValue ).isEqualTo( "R" ); + + final AnnotationUsage discriminatorFortmulaAnnotationUsage = root.getClassDetails() + .getAnnotationUsage( DiscriminatorFormula.class ); + assertThat( discriminatorFortmulaAnnotationUsage ).isNull(); + } + else if ( entityName.equals( "org.hibernate.models.orm.xml.complete.SimplePerson" ) ) { + final AnnotationUsage rootDiscriminatorValueAnnotationUsage = root.getClassDetails() + .getAnnotationUsage( DiscriminatorValue.class ); + assertThat( rootDiscriminatorValueAnnotationUsage ).isNull(); + + final AnnotationUsage discriminatorColumnAnnotationUsage = root.getClassDetails() + .getAnnotationUsage( DiscriminatorColumn.class ); + assertThat( discriminatorColumnAnnotationUsage ).isNotNull(); + + final String discriminatorColumName = discriminatorColumnAnnotationUsage.getString( "name" ); + assertThat( discriminatorColumName ).isEqualTo( "DTYPE" ); + + final DiscriminatorType discriminatorColumnType = discriminatorColumnAnnotationUsage + .getEnum( "discriminatorType" ); + assertThat( discriminatorColumnType ).isEqualTo( DiscriminatorType.STRING ); + + final AnnotationUsage discriminatorFortmulaAnnotationUsage = root.getClassDetails() + .getAnnotationUsage( DiscriminatorFormula.class ); + assertThat( discriminatorFortmulaAnnotationUsage ).isNull(); + } + else { + assertThat( entityName ).isEqualTo( "org.hibernate.models.orm.xml.SimpleEntity" ); + + final AnnotationUsage rootDiscriminatorValueAnnotationUsage = root.getClassDetails() + .getAnnotationUsage( DiscriminatorValue.class ); + assertThat( rootDiscriminatorValueAnnotationUsage ).isNull(); + + final AnnotationUsage discriminatorColumnAnnotationUsage = root.getClassDetails() + .getAnnotationUsage( DiscriminatorColumn.class ); + assertThat( discriminatorColumnAnnotationUsage ).isNull(); + + final AnnotationUsage discriminatorFortmulaAnnotationUsage = root.getClassDetails() + .getAnnotationUsage( DiscriminatorFormula.class ); + assertThat( discriminatorFortmulaAnnotationUsage ).isNotNull(); + + final String formula = discriminatorFortmulaAnnotationUsage.getString( "value" ); + assertThat( formula ).isEqualTo( "CASE WHEN VALUE1 IS NOT NULL THEN 1 WHEN VALUE2 IS NOT NULL THEN 2 END" ); + } + } + + } + } +} diff --git a/src/test/resources/mappings/complete/discriminator-value.xml b/src/test/resources/mappings/complete/discriminator-value.xml new file mode 100644 index 0000000..3d265fe --- /dev/null +++ b/src/test/resources/mappings/complete/discriminator-value.xml @@ -0,0 +1,43 @@ + + + org.hibernate.models.orm.xml.complete + + + + + + + + + + + + + Root + R + + + + + + + + + + + + + + CASE WHEN VALUE1 IS NOT NULL THEN 1 WHEN VALUE2 IS NOT NULL THEN 2 END + + + + +