Skip to content

Commit

Permalink
#22 - Create AnnotationUsage for discriminator-value, discriminator-c…
Browse files Browse the repository at this point in the history
…olumn and discriminator-formula in XML
  • Loading branch information
dreab8 authored and sebersole committed Dec 4, 2023
1 parent 0adde07 commit f853b68
Show file tree
Hide file tree
Showing 4 changed files with 266 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -1496,4 +1501,81 @@ private static List<MutableAnnotationUsage<NamedAttributeNode>> makeNamedAttribu
}
return namedAttributeNodeAnnotations;
}

static void applyDiscriminatorValue(
String discriminatorValue,
MutableClassDetails target,
XmlDocumentContext xmlDocumentContext) {
if ( discriminatorValue != null ) {
final MutableAnnotationUsage<DiscriminatorValue> 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<DiscriminatorColumn> discriminatorColumnAnn = XmlProcessingHelper
.getOrMakeAnnotation( DiscriminatorColumn.class, target, xmlDocumentContext );
final AnnotationDescriptor<DiscriminatorColumn> 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<DiscriminatorFormula> discriminatorFormulaAnn = XmlProcessingHelper
.getOrMakeAnnotation( DiscriminatorFormula.class, target, xmlDocumentContext );
discriminatorFormulaAnn.setAttributeValue( "value", discriminatorFormula );

// todo add to mapping-3.2.0.xsd discriminatorType of @DiscriminatorFormula
}
}
}
Original file line number Diff line number Diff line change
@@ -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<EntityHierarchy> 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<DiscriminatorValue> rootDiscriminatorValueAnnotationUsage = root.getClassDetails()
.getAnnotationUsage( DiscriminatorValue.class );
assertThat( rootDiscriminatorValueAnnotationUsage ).isNull();

final AnnotationUsage<DiscriminatorColumn> 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<IdentifiableTypeMetadata> subTypes = root.getSubTypes();
assertThat( subTypes ).hasSize( 1 );

final IdentifiableTypeMetadata subType = subTypes.iterator().next();
final AnnotationUsage<DiscriminatorValue> subTypeDiscriminatorValueAnnotationUsage = subType.getClassDetails()
.getAnnotationUsage( DiscriminatorValue.class );
assertThat( subTypeDiscriminatorValueAnnotationUsage ).isNotNull();
String discriminatorValue = subTypeDiscriminatorValueAnnotationUsage.getString( "value" );
assertThat( discriminatorValue ).isEqualTo( "R" );

final AnnotationUsage<DiscriminatorFormula> discriminatorFortmulaAnnotationUsage = root.getClassDetails()
.getAnnotationUsage( DiscriminatorFormula.class );
assertThat( discriminatorFortmulaAnnotationUsage ).isNull();
}
else if ( entityName.equals( "org.hibernate.models.orm.xml.complete.SimplePerson" ) ) {
final AnnotationUsage<DiscriminatorValue> rootDiscriminatorValueAnnotationUsage = root.getClassDetails()
.getAnnotationUsage( DiscriminatorValue.class );
assertThat( rootDiscriminatorValueAnnotationUsage ).isNull();

final AnnotationUsage<DiscriminatorColumn> 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<DiscriminatorFormula> discriminatorFortmulaAnnotationUsage = root.getClassDetails()
.getAnnotationUsage( DiscriminatorFormula.class );
assertThat( discriminatorFortmulaAnnotationUsage ).isNull();
}
else {
assertThat( entityName ).isEqualTo( "org.hibernate.models.orm.xml.SimpleEntity" );

final AnnotationUsage<DiscriminatorValue> rootDiscriminatorValueAnnotationUsage = root.getClassDetails()
.getAnnotationUsage( DiscriminatorValue.class );
assertThat( rootDiscriminatorValueAnnotationUsage ).isNull();

final AnnotationUsage<DiscriminatorColumn> discriminatorColumnAnnotationUsage = root.getClassDetails()
.getAnnotationUsage( DiscriminatorColumn.class );
assertThat( discriminatorColumnAnnotationUsage ).isNull();

final AnnotationUsage<DiscriminatorFormula> 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" );
}
}

}
}
}
43 changes: 43 additions & 0 deletions src/test/resources/mappings/complete/discriminator-value.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<!--
~ Hibernate, Relational Persistence for Idiomatic Java
~
~ SPDX-License-Identifier: Apache-2.0
~ Copyright: Red Hat Inc. and Hibernate Authors
-->
<entity-mappings xmlns="http://www.hibernate.org/xsd/orm/mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
version="3.2">
<package>org.hibernate.models.orm.xml.complete</package>

<entity class="Root" metadata-complete="true" access="FIELD">
<inheritance strategy="JOINED"/>
<discriminator-column name="TYPE_COLUMN" discriminator-type="INTEGER"/>
<attributes>
<id name="id">
<column name="pk"/>
</id>
<basic name="name"/>
</attributes>
</entity>
<entity class="Sub" metadata-complete="true" access="FIELD">
<extends>Root</extends>
<discriminator-value>R</discriminator-value>
<attributes>
<basic name="subName"/>
</attributes>
</entity>

<entity class="SimplePerson" metadata-complete="true" access="FIELD">
<discriminator-column/>
<attributes>
<id name="id"/>
</attributes>
</entity>

<entity class="org.hibernate.models.orm.xml.SimpleEntity" metadata-complete="true" access="FIELD">
<discriminator-formula>CASE WHEN VALUE1 IS NOT NULL THEN 1 WHEN VALUE2 IS NOT NULL THEN 2 END</discriminator-formula>
<attributes>
<id name="id"/>
</attributes>
</entity>
</entity-mappings>

0 comments on commit f853b68

Please sign in to comment.