Skip to content

Commit

Permalink
sebersole#26 Create AnnotationUsage for tenant-id in XML
Browse files Browse the repository at this point in the history
  • Loading branch information
dreab8 committed Nov 2, 2023
1 parent 570cb49 commit 5e3d32b
Show file tree
Hide file tree
Showing 9 changed files with 246 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,13 @@
import org.hibernate.boot.internal.Target;
import org.hibernate.boot.jaxb.mapping.spi.JaxbAnyMappingImpl;
import org.hibernate.boot.jaxb.mapping.spi.JaxbAttributesContainer;
import org.hibernate.boot.jaxb.mapping.spi.JaxbAttributesContainerImpl;
import org.hibernate.boot.jaxb.mapping.spi.JaxbBaseAttributesContainer;
import org.hibernate.boot.jaxb.mapping.spi.JaxbBasicImpl;
import org.hibernate.boot.jaxb.mapping.spi.JaxbCollectionIdImpl;
import org.hibernate.boot.jaxb.mapping.spi.JaxbColumnImpl;
import org.hibernate.boot.jaxb.mapping.spi.JaxbElementCollectionImpl;
import org.hibernate.boot.jaxb.mapping.spi.JaxbEmbeddableAttributesContainerImpl;
import org.hibernate.boot.jaxb.mapping.spi.JaxbEmbeddedIdImpl;
import org.hibernate.boot.jaxb.mapping.spi.JaxbEmbeddedImpl;
import org.hibernate.boot.jaxb.mapping.spi.JaxbGeneratedValueImpl;
Expand All @@ -37,6 +39,7 @@
import org.hibernate.boot.jaxb.mapping.spi.JaxbOneToOneImpl;
import org.hibernate.boot.jaxb.mapping.spi.JaxbPersistentAttribute;
import org.hibernate.boot.jaxb.mapping.spi.JaxbPluralAnyMappingImpl;
import org.hibernate.boot.jaxb.mapping.spi.JaxbTenantIdImpl;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.models.source.internal.MutableAnnotationUsage;
import org.hibernate.models.source.internal.MutableClassDetails;
Expand All @@ -46,6 +49,7 @@
import org.hibernate.models.source.spi.SourceModelBuildingContext;

import jakarta.persistence.AccessType;
import jakarta.persistence.Basic;
import jakarta.persistence.Column;
import jakarta.persistence.ElementCollection;
import jakarta.persistence.Embedded;
Expand All @@ -54,6 +58,7 @@
import jakarta.persistence.OrderBy;
import jakarta.persistence.OrderColumn;
import jakarta.persistence.Temporal;
import jakarta.persistence.TemporalType;

import static org.hibernate.internal.util.NullnessHelper.coalesce;
import static org.hibernate.models.orm.categorize.xml.internal.XmlProcessingHelper.getOrMakeAnnotation;
Expand Down Expand Up @@ -153,14 +158,50 @@ public interface MemberAdjuster {
}

public static void processAttributes(
JaxbAttributesContainer attributesContainer,
JaxbAttributesContainerImpl attributesContainer,
MutableClassDetails mutableClassDetails,
AccessType classAccessType,
SourceModelBuildingContext sourceModelBuildingContext) {
processAttributes( attributesContainer, mutableClassDetails, classAccessType, null, sourceModelBuildingContext );
}

public static void processAttributes(
JaxbAttributesContainerImpl attributesContainer,
MutableClassDetails mutableClassDetails,
AccessType classAccessType,
MemberAdjuster memberAdjuster,
SourceModelBuildingContext sourceModelBuildingContext) {
processBasicAttributes(
attributesContainer,
mutableClassDetails,
classAccessType,
memberAdjuster,
sourceModelBuildingContext
);
processTenantId(
attributesContainer.getTenantId(),
mutableClassDetails,
classAccessType,
sourceModelBuildingContext
);
}

public static void processAttributes(
JaxbEmbeddableAttributesContainerImpl attributesContainer,
MutableClassDetails mutableClassDetails,
AccessType classAccessType,
MemberAdjuster memberAdjuster,
SourceModelBuildingContext sourceModelBuildingContext) {
processBasicAttributes(
attributesContainer,
mutableClassDetails,
classAccessType,
memberAdjuster,
sourceModelBuildingContext
);
}

static void processBasicAttributes(
JaxbAttributesContainer attributesContainer,
MutableClassDetails mutableClassDetails,
AccessType classAccessType,
Expand Down Expand Up @@ -233,6 +274,7 @@ public static void processAttributes(
memberAdjuster.adjust( memberDetails, jaxbPluralAnyMapping, sourceModelBuildingContext );
}
}

}

public static void processCommonAttributeAnnotations(
Expand Down Expand Up @@ -550,13 +592,7 @@ public static MutableMemberDetails processElementCollectionAttribute(
getOrMakeAnnotation( Nationalized.class, memberDetails );
}

if ( jaxbElementCollection.getTemporal() != null ) {
final MutableAnnotationUsage<Temporal> temporalAnn = getOrMakeAnnotation(
Temporal.class,
memberDetails
);
temporalAnn.setAttributeValue( "value", jaxbElementCollection.getTemporal() );
}
XmlAnnotationHelper.applyTemporal( jaxbElementCollection.getTemporal(), memberDetails );

XmlAnnotationHelper.applyBasicTypeComposition( jaxbElementCollection, memberDetails, sourceModelBuildingContext );
if ( StringHelper.isNotEmpty( jaxbElementCollection.getTargetClass() ) ) {
Expand Down Expand Up @@ -617,4 +653,16 @@ public static MutableMemberDetails processPluralAnyMappingAttributes(
SourceModelBuildingContext sourceModelBuildingContext) {
throw new UnsupportedOperationException( "Support for many-to-any attributes not yet implemented" );
}

public static void processTenantId(
JaxbTenantIdImpl jaxbTenantId,
MutableClassDetails declarer,
AccessType accessType,
SourceModelBuildingContext sourceModelBuildingContext) {
if ( jaxbTenantId != null ) {
XmlAnnotationHelper.applyTenantId( jaxbTenantId, declarer, sourceModelBuildingContext );

processBasicAttribute( jaxbTenantId, declarer, accessType, sourceModelBuildingContext );
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import org.hibernate.boot.jaxb.mapping.spi.JaxbOneToOneImpl;
import org.hibernate.boot.jaxb.mapping.spi.JaxbPersistentAttribute;
import org.hibernate.boot.jaxb.mapping.spi.JaxbPluralAttribute;
import org.hibernate.boot.jaxb.mapping.spi.JaxbTenantIdImpl;
import org.hibernate.models.ModelsException;
import org.hibernate.models.internal.CollectionHelper;
import org.hibernate.models.internal.StringHelper;
Expand All @@ -56,8 +57,6 @@

import static org.hibernate.internal.util.NullnessHelper.coalesce;
import static org.hibernate.internal.util.NullnessHelper.nullif;
import static org.hibernate.models.orm.categorize.xml.internal.AttributeProcessor.processAttributes;
import static org.hibernate.models.orm.categorize.xml.internal.AttributeProcessor.processNaturalId;

/**
* Helper for handling managed types defined in mapping XML, in either
Expand Down Expand Up @@ -171,6 +170,17 @@ private static void prepareDynamicClass(
classDetails.addField( member );
}

// <tenant-id/>
final JaxbTenantIdImpl tenantId = attributes.getTenantId();
if ( tenantId != null ) {
final MapModeFieldDetails member = new MapModeFieldDetails(
tenantId.getName(),
determineDynamicAttributeJavaType( tenantId, sourceModelBuildingContext ),
sourceModelBuildingContext
);
classDetails.addField( member );
}

// <natural-id/>
if ( attributes.getNaturalId() != null ) {
attributes.getNaturalId().getBasicAttributes().forEach( (jaxbBasic) -> {
Expand Down Expand Up @@ -337,6 +347,11 @@ private static ClassDetails determineDynamicAttributeJavaType(
return XmlAnnotationHelper.resolveJavaType( jaxbBasic.getTarget(), sourceModelBuildingContext );
}

if ( jaxbPersistentAttribute instanceof JaxbTenantIdImpl ) {
final JaxbTenantIdImpl jaxbTenantId = (JaxbTenantIdImpl) jaxbPersistentAttribute;
return XmlAnnotationHelper.resolveJavaType( jaxbTenantId.getTarget(), sourceModelBuildingContext );
}

if ( jaxbPersistentAttribute instanceof JaxbEmbeddedImpl ) {
final JaxbEmbeddedImpl jaxbEmbedded = (JaxbEmbeddedImpl) jaxbPersistentAttribute;
final String target = jaxbEmbedded.getTarget();
Expand Down Expand Up @@ -469,6 +484,13 @@ private static void processEntityMetadata(

XmlAnnotationHelper.applyRowId( jaxbEntity.getRowid(), classDetails, sourceModelBuildingContext );

// AttributeProcessor.processTenantId (
// jaxbEntity.getTenantId(),
// classDetails,
// classAccessType,
// sourceModelBuildingContext
// );

// todo : secondary-tables
}

Expand Down Expand Up @@ -588,8 +610,7 @@ private static void processMappedSuperclassMetadata(
);
classDetails.addAnnotationUsage( XmlAnnotationHelper.createAccessAnnotation( classAccessType, classDetails ) );

final JaxbAttributesContainer attributes = jaxbMappedSuperclass.getAttributes();
AttributeProcessor.processAttributes( attributes, classDetails, classAccessType, sourceModelBuildingContext );
AttributeProcessor.processAttributes( jaxbMappedSuperclass.getAttributes(), classDetails, classAccessType, sourceModelBuildingContext );

processEntityOrMappedSuperclass( jaxbMappedSuperclass, classDetails, sourceModelBuildingContext );
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import org.hibernate.annotations.SQLJoinTableRestriction;
import org.hibernate.annotations.SQLRestriction;
import org.hibernate.annotations.SqlFragmentAlias;
import org.hibernate.annotations.TenantId;
import org.hibernate.annotations.Type;
import org.hibernate.annotations.UuidGenerator;
import org.hibernate.boot.internal.Target;
Expand Down Expand Up @@ -61,6 +62,7 @@
import org.hibernate.boot.jaxb.mapping.spi.JaxbSequenceGeneratorImpl;
import org.hibernate.boot.jaxb.mapping.spi.JaxbTableGeneratorImpl;
import org.hibernate.boot.jaxb.mapping.spi.JaxbTableImpl;
import org.hibernate.boot.jaxb.mapping.spi.JaxbTenantIdImpl;
import org.hibernate.boot.jaxb.mapping.spi.JaxbUserTypeImpl;
import org.hibernate.boot.jaxb.mapping.spi.JaxbUuidGeneratorImpl;
import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle;
Expand Down Expand Up @@ -162,6 +164,19 @@ public static void applyBasic(
}
}

public static void applyBasic(
JaxbTenantIdImpl jaxbTenantId,
MutableMemberDetails memberDetails,
SourceModelBuildingContext sourceModelBuildingContext) {
final MutableAnnotationUsage<Basic> basicAnn = XmlProcessingHelper.getOrMakeAnnotation( Basic.class, memberDetails );
if ( jaxbTenantId.getFetch() != null ) {
basicAnn.setAttributeValue( "fetch", jaxbTenantId.getFetch() );
}
if ( jaxbTenantId.isOptional() != null ) {
basicAnn.setAttributeValue( "optional", jaxbTenantId.isOptional() );
}
}

public static void applyAccess(
AccessType accessType,
MutableMemberDetails memberDetails,
Expand Down Expand Up @@ -1011,10 +1026,34 @@ private static MethodDetails getCallbackMethodDetails(
static void applyRowId(
String rowId,
MutableClassDetails target,
SourceModelBuildingContext buildingContext) {
SourceModelBuildingContext sourceModelBuildingContext) {
if ( rowId != null ) {
final MutableAnnotationUsage<RowId> rowIdAnn = XmlProcessingHelper.getOrMakeAnnotation( RowId.class, target );
applyAttributeIfSpecified( rowIdAnn, "value", rowId );
}
}

static void applyTenantId(
JaxbTenantIdImpl jaxbTenantIdClass,
MutableClassDetails target,
SourceModelBuildingContext sourceModelBuildingContext) {
if ( jaxbTenantIdClass != null ) {
final MutableAnnotationUsage<TenantId> tenantIdAnn = XmlProcessingHelper.getOrMakeAnnotation(
TenantId.class,
target
);
applyAttributeIfSpecified( tenantIdAnn, "name", jaxbTenantIdClass.getName() );
// todo : `bind-as-param` attribute
}
}

static void applyTemporal(TemporalType temporal, MutableMemberDetails memberDetails) {
if ( temporal != null ) {
final MutableAnnotationUsage<Temporal> temporalAnn = getOrMakeAnnotation(
Temporal.class,
memberDetails
);
temporalAnn.setAttributeValue( "value", temporal );
}
}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
/*
* 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 java.util.Set;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/*
* 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 java.util.Set;

import org.hibernate.annotations.TenantId;
import org.hibernate.boot.internal.BootstrapContextImpl;
import org.hibernate.boot.internal.MetadataBuilderImpl;
import org.hibernate.boot.model.process.spi.ManagedResources;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.models.orm.categorize.spi.CategorizedDomainModel;
import org.hibernate.models.orm.categorize.spi.EntityHierarchy;
import org.hibernate.models.orm.categorize.spi.EntityTypeMetadata;
import org.hibernate.models.orm.process.ManagedResourcesImpl;
import org.hibernate.models.source.spi.AnnotationUsage;
import org.hibernate.models.source.spi.FieldDetails;

import org.junit.jupiter.api.Test;

import jakarta.persistence.Basic;
import jakarta.persistence.Column;
import jakarta.persistence.FetchType;

import static org.assertj.core.api.Assertions.assertThat;
import static org.hibernate.models.orm.categorize.spi.ManagedResourcesProcessor.processManagedResources;

public class TenantIdTest {
@Test
void testSimpleDynamicModel() {
final ManagedResources managedResources = new ManagedResourcesImpl.Builder()
.addXmlMappings( "mappings/dynamic/dynamic-tenantid.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( 2 );

entityHierarchies.forEach(
entityHierarchy -> {
final EntityTypeMetadata root = entityHierarchy.getRoot();
final AnnotationUsage<TenantId> tenantIdAnnotationUsage = root.getClassDetails()
.getAnnotationUsage( TenantId.class );
final String entityName = root.getEntityName();
if ( entityName.equals( "EntityWithoutTenantId" ) ) {
assertThat( tenantIdAnnotationUsage ).isNull();
}
else {
assertThat( tenantIdAnnotationUsage ).isNotNull();
assertThat( tenantIdAnnotationUsage.getString( "name" ) ).isEqualTo( "tenantId" );

final FieldDetails fieldDetails = root.getClassDetails().findFieldByName( "tenantId" );

final AnnotationUsage<Basic> basicAnnotationUsage = fieldDetails.getAnnotationUsage( Basic.class );
assertThat( basicAnnotationUsage ).isNotNull();
assertThat( basicAnnotationUsage.<FetchType>getAttributeValue( "fetch" ) )
.isEqualTo( FetchType.EAGER );
assertThat( basicAnnotationUsage.getBoolean( "optional" ) ).isTrue();

final AnnotationUsage<Column> columnAnnotationUsage = fieldDetails.
getAnnotationUsage( Column.class );
assertThat( basicAnnotationUsage ).isNotNull();
assertThat( columnAnnotationUsage.getString( "name" ) ).isEqualTo( "TENANT_ID" );
assertThat( columnAnnotationUsage.getBoolean( "insertable" ) ).isFalse();

}
}
);
}
}
}
Loading

0 comments on commit 5e3d32b

Please sign in to comment.