From d4de89bb81dd4221d6459d0ceb4803eceec1ad20 Mon Sep 17 00:00:00 2001 From: Marco Belladelli Date: Wed, 25 Oct 2023 07:07:08 +0200 Subject: [PATCH] #8 - Create AnnotationUsage for id-class --- .../xml/internal/ManagedTypeProcessor.java | 18 ++++++- .../orm/xml/internal/XmlAnnotationHelper.java | 47 ++++++++++++++----- .../xml/complete/SimpleCompleteXmlTests.java | 4 ++ .../orm/xml/dynamic/DynamicModelTests.java | 46 +++++++++++++++++- .../models/orm/xml/dynamic/Employee.java | 18 +++++++ .../models/orm/xml/dynamic/EmployeePK.java | 14 ++++++ .../mappings/complete/simple-complete.xml | 2 +- .../mappings/dynamic/dynamic-id-class.xml | 17 +++++++ 8 files changed, 151 insertions(+), 15 deletions(-) create mode 100644 hibernate-models-orm/src/test/java/org/hibernate/models/orm/xml/dynamic/Employee.java create mode 100644 hibernate-models-orm/src/test/java/org/hibernate/models/orm/xml/dynamic/EmployeePK.java create mode 100644 hibernate-models-orm/src/test/resources/mappings/dynamic/dynamic-id-class.xml diff --git a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/xml/internal/ManagedTypeProcessor.java b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/xml/internal/ManagedTypeProcessor.java index 5da987a..7ddd06f 100644 --- a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/xml/internal/ManagedTypeProcessor.java +++ b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/xml/internal/ManagedTypeProcessor.java @@ -23,6 +23,7 @@ import org.hibernate.boot.jaxb.mapping.spi.JaxbEmbeddedImpl; import org.hibernate.boot.jaxb.mapping.spi.JaxbEntityImpl; import org.hibernate.boot.jaxb.mapping.spi.JaxbEntityMappingsImpl; +import org.hibernate.boot.jaxb.mapping.spi.JaxbEntityOrMappedSuperclass; import org.hibernate.boot.jaxb.mapping.spi.JaxbIdImpl; import org.hibernate.boot.jaxb.mapping.spi.JaxbManagedType; import org.hibernate.boot.jaxb.mapping.spi.JaxbMappedSuperclassImpl; @@ -454,7 +455,8 @@ private static void processEntityMetadata( sourceModelBuildingContext ) ); - // todo : id-class + processCommonEntityOrMappedSuperclass( jaxbEntity, classDetails, sourceModelBuildingContext ); + // todo : callbacks // todo : entity-listeners // todo : secondary-tables @@ -579,7 +581,8 @@ private static void processMappedSuperclassMetadata( final JaxbAttributesContainer attributes = jaxbMappedSuperclass.getAttributes(); processAttributes( attributes, classDetails, classAccessType, sourceModelBuildingContext ); - // todo : id-class + processCommonEntityOrMappedSuperclass( jaxbMappedSuperclass, classDetails, sourceModelBuildingContext ); + // todo : entity-listeners // todo : callbacks } @@ -600,6 +603,17 @@ public static void processOverrideMappedSuperclass( } ); } + private static void processCommonEntityOrMappedSuperclass( + JaxbEntityOrMappedSuperclass jaxbEntity, + MutableClassDetails classDetails, + SourceModelBuildingContext sourceModelBuildingContext) { + XmlAnnotationHelper.applyIdClass( jaxbEntity.getIdClass(), classDetails, sourceModelBuildingContext ); + + // todo : entity-listeners + // todo : exclude default listeners (?) + // todo : exclude superclass listeners (?) + } + public static void processCompleteEmbeddable( JaxbEntityMappingsImpl jaxbRoot, JaxbEmbeddableImpl jaxbEmbeddable, diff --git a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/xml/internal/XmlAnnotationHelper.java b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/xml/internal/XmlAnnotationHelper.java index 94ee385..0ee8377 100644 --- a/hibernate-models-orm/src/main/java/org/hibernate/models/orm/xml/internal/XmlAnnotationHelper.java +++ b/hibernate-models-orm/src/main/java/org/hibernate/models/orm/xml/internal/XmlAnnotationHelper.java @@ -15,9 +15,9 @@ import java.util.UUID; import org.hibernate.annotations.AttributeAccessor; +import org.hibernate.annotations.CollectionType; import org.hibernate.annotations.Filter; import org.hibernate.annotations.FilterJoinTable; -import org.hibernate.annotations.CollectionType; import org.hibernate.annotations.Formula; import org.hibernate.annotations.JavaType; import org.hibernate.annotations.JdbcType; @@ -44,6 +44,7 @@ import org.hibernate.boot.jaxb.mapping.spi.JaxbEntity; import org.hibernate.boot.jaxb.mapping.spi.JaxbGeneratedValueImpl; import org.hibernate.boot.jaxb.mapping.spi.JaxbHbmFilterImpl; +import org.hibernate.boot.jaxb.mapping.spi.JaxbIdClassImpl; import org.hibernate.boot.jaxb.mapping.spi.JaxbIdImpl; import org.hibernate.boot.jaxb.mapping.spi.JaxbLobImpl; import org.hibernate.boot.jaxb.mapping.spi.JaxbNationalizedImpl; @@ -82,6 +83,7 @@ import jakarta.persistence.Enumerated; import jakarta.persistence.GeneratedValue; import jakarta.persistence.Id; +import jakarta.persistence.IdClass; import jakarta.persistence.Inheritance; import jakarta.persistence.Lob; import jakarta.persistence.SequenceGenerator; @@ -800,7 +802,7 @@ static void applyFilter( applyFilter( jaxbFilter, target, Filter.class, sourceModelBuildingContext ); } - static void applyJoinTableFilters( + static void applyJoinTableFilter( JaxbHbmFilterImpl jaxbFilter, MutableAnnotationTarget target, SourceModelBuildingContext sourceModelBuildingContext) { @@ -811,7 +813,7 @@ private static void applyFilter( JaxbHbmFilterImpl jaxbFilter, MutableAnnotationTarget target, Class filterAnnotationClass, - SourceModelBuildingContext sourceModelBuildingContext) { + SourceModelBuildingContext buildingContext) { // Since @Filter and @FilterJoinTable have exactly the same attributes, // we can use the same method with parametrized annotation class final MutableAnnotationUsage filterAnn = getOrMakeNamedAnnotation( @@ -825,15 +827,38 @@ private static void applyFilter( final List aliases = jaxbFilter.getAliases(); if ( !CollectionHelper.isEmpty( aliases ) ) { - final List> sqlFragmentAliases = new ArrayList<>( aliases.size() ); - for ( JaxbHbmFilterImpl.JaxbAliasesImpl alias : aliases ) { - final MutableAnnotationUsage aliasAnn = new DynamicAnnotationUsage<>( SqlFragmentAlias.class ); - aliasAnn.setAttributeValue( "alias", alias.getAlias() ); - aliasAnn.setAttributeValue( "table", alias.getTable() ); - aliasAnn.setAttributeValue( "entity", alias.getEntity() ); - sqlFragmentAliases.add( aliasAnn ); + filterAnn.setAttributeValue( "aliases", getSqlFragmentAliases( aliases, buildingContext ) ); + } + } + + private static List> getSqlFragmentAliases( + List aliases, + SourceModelBuildingContext buildingContext) { + final List> sqlFragmentAliases = new ArrayList<>( aliases.size() ); + for ( JaxbHbmFilterImpl.JaxbAliasesImpl alias : aliases ) { + final MutableAnnotationUsage aliasAnn = new DynamicAnnotationUsage<>( SqlFragmentAlias.class ); + aliasAnn.setAttributeValue( "alias", alias.getAlias() ); + applyAttributeIfSpecified( aliasAnn, "table", alias.getTable() ); + if ( StringHelper.isNotEmpty( alias.getEntity() ) ) { + aliasAnn.setAttributeValue( + "entity", + buildingContext.getClassDetailsRegistry().resolveClassDetails( alias.getEntity() ) + ); } - filterAnn.setAttributeValue( "aliases", sqlFragmentAliases ); + sqlFragmentAliases.add( aliasAnn ); + } + return sqlFragmentAliases; + } + + static void applyIdClass( + JaxbIdClassImpl jaxbIdClass, + MutableClassDetails target, + SourceModelBuildingContext buildingContext) { + if ( jaxbIdClass != null ) { + XmlProcessingHelper.makeAnnotation( IdClass.class, target ).setAttributeValue( + "value", + buildingContext.getClassDetailsRegistry().resolveClassDetails( jaxbIdClass.getClazz() ) + ); } } } diff --git a/hibernate-models-orm/src/test/java/org/hibernate/models/orm/xml/complete/SimpleCompleteXmlTests.java b/hibernate-models-orm/src/test/java/org/hibernate/models/orm/xml/complete/SimpleCompleteXmlTests.java index 98c2300..91b1ed4 100644 --- a/hibernate-models-orm/src/test/java/org/hibernate/models/orm/xml/complete/SimpleCompleteXmlTests.java +++ b/hibernate-models-orm/src/test/java/org/hibernate/models/orm/xml/complete/SimpleCompleteXmlTests.java @@ -21,6 +21,7 @@ import org.hibernate.models.source.SourceModelTestHelper; import org.hibernate.models.source.internal.SourceModelBuildingContextImpl; import org.hibernate.models.source.spi.AnnotationUsage; +import org.hibernate.models.source.spi.ClassDetails; import org.junit.jupiter.api.Test; @@ -103,5 +104,8 @@ private void validateFilterUsage(AnnotationUsage filter) { assertThat( aliases ).hasSize( 1 ); assertThat( aliases.get( 0 ).getAttributeValue( "alias" ) ).isEqualTo( "t" ); assertThat( aliases.get( 0 ).getAttributeValue( "table" ) ).isEqualTo( "SimpleEntity" ); + assertThat( aliases.get( 0 ) + .getAttributeValue( "entity" ) + .getName() ).isEqualTo( SimpleEntity.class.getName() ); } } diff --git a/hibernate-models-orm/src/test/java/org/hibernate/models/orm/xml/dynamic/DynamicModelTests.java b/hibernate-models-orm/src/test/java/org/hibernate/models/orm/xml/dynamic/DynamicModelTests.java index 265045f..5c9b381 100644 --- a/hibernate-models-orm/src/test/java/org/hibernate/models/orm/xml/dynamic/DynamicModelTests.java +++ b/hibernate-models-orm/src/test/java/org/hibernate/models/orm/xml/dynamic/DynamicModelTests.java @@ -16,15 +16,18 @@ import org.hibernate.models.orm.spi.ManagedResources; import org.hibernate.models.orm.spi.ProcessResult; import org.hibernate.models.orm.spi.Processor; -import org.hibernate.models.orm.xml.SimpleEntity; import org.hibernate.models.source.SourceModelTestHelper; import org.hibernate.models.source.internal.SourceModelBuildingContextImpl; +import org.hibernate.models.source.spi.AnnotationUsage; +import org.hibernate.models.source.spi.ClassDetails; import org.hibernate.models.source.spi.FieldDetails; import org.junit.jupiter.api.Test; import org.jboss.jandex.Index; +import jakarta.persistence.IdClass; + import static org.assertj.core.api.Assertions.assertThat; import static org.hibernate.models.internal.SimpleClassLoading.SIMPLE_CLASS_LOADING; @@ -126,4 +129,45 @@ public boolean shouldIgnoreUnlistedClasses() { assertThat( labelsField.getType().getClassName() ).isEqualTo( Set.class.getName() ); } + @Test + void testIdClass() { + final ManagedResources managedResources = new ManagedResourcesImpl.Builder() + .addXmlMappings( "mappings/dynamic/dynamic-id-class.xml" ) + .build(); + final Index jandexIndex = SourceModelTestHelper.buildJandexIndex( + SIMPLE_CLASS_LOADING, + Employee.class, + EmployeePK.class + ); + final SourceModelBuildingContextImpl buildingContext = SourceModelTestHelper.createBuildingContext( + jandexIndex, + SIMPLE_CLASS_LOADING + ); + + final ProcessResult processResult = Processor.process( + managedResources, + null, + new Processor.Options() { + @Override + public boolean areGeneratorsGlobal() { + return false; + } + + @Override + public boolean shouldIgnoreUnlistedClasses() { + return false; + } + }, + buildingContext + ); + + assertThat( processResult.getEntityHierarchies() ).hasSize( 1 ); + final EntityHierarchy hierarchy = processResult.getEntityHierarchies().iterator().next(); + final EntityTypeMetadata rootEntity = hierarchy.getRoot(); + assertThat( rootEntity.getClassDetails().getName() ).isEqualTo( Employee.class.getName() ); + + final AnnotationUsage idClass = rootEntity.getClassDetails().getAnnotationUsage( IdClass.class ); + assertThat( idClass ).isNotNull(); + assertThat( idClass.getAttributeValue( "value" ).getName() ).isEqualTo( EmployeePK.class.getName() ); + } } diff --git a/hibernate-models-orm/src/test/java/org/hibernate/models/orm/xml/dynamic/Employee.java b/hibernate-models-orm/src/test/java/org/hibernate/models/orm/xml/dynamic/Employee.java new file mode 100644 index 0000000..83525a6 --- /dev/null +++ b/hibernate-models-orm/src/test/java/org/hibernate/models/orm/xml/dynamic/Employee.java @@ -0,0 +1,18 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.models.orm.xml.dynamic; + +import jakarta.persistence.Entity; +import jakarta.persistence.Id; + +@Entity +public class Employee { + @Id + private String name; + @Id + private int number; +} diff --git a/hibernate-models-orm/src/test/java/org/hibernate/models/orm/xml/dynamic/EmployeePK.java b/hibernate-models-orm/src/test/java/org/hibernate/models/orm/xml/dynamic/EmployeePK.java new file mode 100644 index 0000000..37f4a91 --- /dev/null +++ b/hibernate-models-orm/src/test/java/org/hibernate/models/orm/xml/dynamic/EmployeePK.java @@ -0,0 +1,14 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright: Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.models.orm.xml.dynamic; + +import jakarta.persistence.Id; + +public class EmployeePK { + private String name; + private int number; +} diff --git a/hibernate-models-orm/src/test/resources/mappings/complete/simple-complete.xml b/hibernate-models-orm/src/test/resources/mappings/complete/simple-complete.xml index b797fcf..bf345fd 100644 --- a/hibernate-models-orm/src/test/resources/mappings/complete/simple-complete.xml +++ b/hibernate-models-orm/src/test/resources/mappings/complete/simple-complete.xml @@ -10,7 +10,7 @@ version="3.1"> - + diff --git a/hibernate-models-orm/src/test/resources/mappings/dynamic/dynamic-id-class.xml b/hibernate-models-orm/src/test/resources/mappings/dynamic/dynamic-id-class.xml new file mode 100644 index 0000000..5bca31c --- /dev/null +++ b/hibernate-models-orm/src/test/resources/mappings/dynamic/dynamic-id-class.xml @@ -0,0 +1,17 @@ + + + + + + + + + + \ No newline at end of file