Skip to content

Commit

Permalink
#74 Implement ManyToOneAttributeProcessing
Browse files Browse the repository at this point in the history
  • Loading branch information
sebersole committed Nov 17, 2023
1 parent 4e27501 commit ab17103
Show file tree
Hide file tree
Showing 11 changed files with 516 additions and 23 deletions.
18 changes: 13 additions & 5 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
plugins {
id "java-library"

id "checkstyle"
}

group = "org.hibernate.models"
version = "1.0.0-SNAPSHOT"

apply from: rootProject.file( "gradle/checkstyle.gradle" )

dependencies {
implementation platform( libs.hibernatePlatform )
implementation libs.hibernateCore
Expand All @@ -28,16 +28,17 @@ dependencies {
testImplementation libs.hibernateTesting

testRuntimeOnly testLibs.junit5Engine
testRuntimeOnly testLibs.h2
}

java {
sourceCompatibility = 17
targetCompatibility = 17
}

//test {
// useJUnitPlatform()
//}
test {
useJUnitPlatform()
}

tasks.withType( JavaCompile ).configureEach {
options.encoding = "UTF-8"
Expand All @@ -49,3 +50,10 @@ tasks.register( "compile" ) {compile->
compile.dependsOn tasks.named( sourceSets.main.compileJavaTaskName )
compile.dependsOn tasks.named( sourceSets.test.compileJavaTaskName )
}

checkstyle {
sourceSets = [ project.sourceSets.main ]
showViolations = false
}
// only include explicit sources (and thereby exclude generated sources)
tasks.checkstyleMain.source = 'src/main'
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
import org.hibernate.boot.model.naming.Identifier;
import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.engine.spi.FilterDefinition;
import org.hibernate.internal.util.NamedConsumer;
import org.hibernate.internal.util.KeyedConsumer;
import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.models.ModelsException;
Expand Down Expand Up @@ -121,8 +121,8 @@ public IdentifiableTypeBinder getSuperTypeBinder(ClassDetails type) {
}

@Override
public void forEachType(NamedConsumer<ManagedTypeBinder> consumer) {
typeBinders.forEach( (classDetails, managedTypeBinder) -> consumer.consume( classDetails.getName(), managedTypeBinder ) );
public void forEachType(KeyedConsumer<String,ManagedTypeBinder> consumer) {
typeBinders.forEach( (classDetails, managedTypeBinder) -> consumer.accept( classDetails.getName(), managedTypeBinder ) );
}

@Override
Expand All @@ -131,7 +131,7 @@ public int getTableCount() {
}

@Override
public void forEachTable(NamedConsumer<TableReference> consumer) {
public void forEachTable(KeyedConsumer<String,TableReference> consumer) {
//noinspection unchecked
tableMap.forEach( (BiConsumer<? super String, ? super TableReference>) consumer );
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@

import org.hibernate.boot.model.relational.Database;
import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.internal.util.NamedConsumer;
import org.hibernate.models.orm.bind.internal.binders.TableBinder;
import org.hibernate.internal.util.KeyedConsumer;
import org.hibernate.models.orm.bind.internal.binders.IdentifiableTypeBinder;
import org.hibernate.models.orm.bind.internal.binders.ManagedTypeBinder;
import org.hibernate.models.orm.bind.internal.binders.TableBinder;
import org.hibernate.models.orm.categorize.spi.FilterDefRegistration;
import org.hibernate.models.orm.categorize.spi.ManagedTypeMetadata;
import org.hibernate.models.spi.ClassDetails;
Expand All @@ -32,7 +32,7 @@ default Database getDatabase() {
void apply(FilterDefRegistration registration);

int getTableCount();
void forEachTable(NamedConsumer<TableReference> consumer);
void forEachTable(KeyedConsumer<String,TableReference> consumer);
<T extends TableReference> T getTableByName(String name);
void addTable(TableReference table);
void registerTableSecondPass(TableBinder.TableSecondPass secondPass);
Expand All @@ -46,6 +46,6 @@ default ManagedTypeBinder getTypeBinder(ManagedTypeMetadata type) {

ManagedTypeBinder getTypeBinder(ClassDetails type);
IdentifiableTypeBinder getSuperTypeBinder(ClassDetails type);
void forEachType(NamedConsumer<ManagedTypeBinder> consumer);
void forEachType(KeyedConsumer<String,ManagedTypeBinder> consumer);

}
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,16 @@
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;

import org.hibernate.AnnotationException;
import org.hibernate.annotations.AttributeAccessor;
import org.hibernate.annotations.Check;
import org.hibernate.annotations.CollectionType;
import org.hibernate.annotations.Filter;
import org.hibernate.annotations.FilterJoinTable;
Expand All @@ -41,6 +46,7 @@
import org.hibernate.boot.jaxb.mapping.spi.JaxbBasicImpl;
import org.hibernate.boot.jaxb.mapping.spi.JaxbBasicMapping;
import org.hibernate.boot.jaxb.mapping.spi.JaxbCachingImpl;
import org.hibernate.boot.jaxb.mapping.spi.JaxbCheckConstraintImpl;
import org.hibernate.boot.jaxb.mapping.spi.JaxbCollectionUserTypeImpl;
import org.hibernate.boot.jaxb.mapping.spi.JaxbColumnImpl;
import org.hibernate.boot.jaxb.mapping.spi.JaxbConfigurationParameterImpl;
Expand All @@ -49,10 +55,12 @@
import org.hibernate.boot.jaxb.mapping.spi.JaxbEmbeddedIdImpl;
import org.hibernate.boot.jaxb.mapping.spi.JaxbEntity;
import org.hibernate.boot.jaxb.mapping.spi.JaxbEntityListenerImpl;
import org.hibernate.boot.jaxb.mapping.spi.JaxbForeignKeyImpl;
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.JaxbJoinColumnImpl;
import org.hibernate.boot.jaxb.mapping.spi.JaxbLifecycleCallback;
import org.hibernate.boot.jaxb.mapping.spi.JaxbLifecycleCallbackContainer;
import org.hibernate.boot.jaxb.mapping.spi.JaxbLobImpl;
Expand All @@ -64,6 +72,7 @@
import org.hibernate.boot.jaxb.mapping.spi.JaxbUserTypeImpl;
import org.hibernate.boot.jaxb.mapping.spi.JaxbUuidGeneratorImpl;
import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle;
import org.hibernate.internal.util.KeyedConsumer;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.models.ModelsException;
Expand All @@ -75,6 +84,7 @@
import org.hibernate.models.internal.MutableClassDetails;
import org.hibernate.models.internal.MutableMemberDetails;
import org.hibernate.models.internal.dynamic.DynamicAnnotationUsage;
import org.hibernate.models.spi.AnnotationDescriptor;
import org.hibernate.models.spi.AnnotationTarget;
import org.hibernate.models.spi.AnnotationUsage;
import org.hibernate.models.spi.ClassDetails;
Expand All @@ -88,17 +98,21 @@
import jakarta.persistence.AssociationOverride;
import jakarta.persistence.AttributeOverride;
import jakarta.persistence.Basic;
import jakarta.persistence.CheckConstraint;
import jakarta.persistence.Column;
import jakarta.persistence.Convert;
import jakarta.persistence.EmbeddedId;
import jakarta.persistence.Entity;
import jakarta.persistence.EntityListeners;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.persistence.ForeignKey;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import jakarta.persistence.IdClass;
import jakarta.persistence.Inheritance;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.JoinColumns;
import jakarta.persistence.Lob;
import jakarta.persistence.PostLoad;
import jakarta.persistence.PostPersist;
Expand Down Expand Up @@ -133,7 +147,7 @@ public static void applyEntity(
JaxbEntity jaxbEntity,
MutableClassDetails classDetails,
SourceModelBuildingContext sourceModelBuildingContext) {
final MutableAnnotationUsage<Entity> entityUsage = XmlProcessingHelper.getOrMakeAnnotation( Entity.class, classDetails );
final MutableAnnotationUsage<Entity> entityUsage = getOrMakeAnnotation( Entity.class, classDetails );
if ( StringHelper.isNotEmpty( jaxbEntity.getName() ) ) {
entityUsage.setAttributeValue( "name", jaxbEntity.getName() );
}
Expand All @@ -153,7 +167,7 @@ public static void applyBasic(
JaxbBasicImpl jaxbBasic,
MutableMemberDetails memberDetails,
SourceModelBuildingContext sourceModelBuildingContext) {
final MutableAnnotationUsage<Basic> basicAnn = XmlProcessingHelper.getOrMakeAnnotation( Basic.class, memberDetails );
final MutableAnnotationUsage<Basic> basicAnn = getOrMakeAnnotation( Basic.class, memberDetails );
if ( jaxbBasic.getFetch() != null ) {
basicAnn.setAttributeValue( "fetch", jaxbBasic.getFetch() );
}
Expand Down Expand Up @@ -205,10 +219,106 @@ public static void applyColumn(
createColumnAnnotation( jaxbColumn, memberDetails );
}

public static MutableAnnotationUsage<JoinColumn> applyJoinColumn(
JaxbJoinColumnImpl jaxbJoinColumn,
MutableMemberDetails memberDetails,
SourceModelBuildingContext sourceModelBuildingContext) {
if ( jaxbJoinColumn == null ) {
return null;
}

return createJoinColumnAnnotation( jaxbJoinColumn, memberDetails, sourceModelBuildingContext );
}

public static MutableAnnotationUsage<JoinColumn> createJoinColumnAnnotation(
JaxbJoinColumnImpl jaxbJoinColumn,
MutableMemberDetails memberDetails,
SourceModelBuildingContext sourceModelBuildingContext) {
final MutableAnnotationUsage<JoinColumn> joinColumnAnn = getOrMakeAnnotation( JoinColumn.class, memberDetails );
final AnnotationDescriptor<JoinColumn> joinColumnDescriptor = sourceModelBuildingContext
.getAnnotationDescriptorRegistry()
.getDescriptor( JoinColumn.class );

applyOr( jaxbJoinColumn, JaxbJoinColumnImpl::getName, "name", joinColumnAnn, joinColumnDescriptor );
applyOr( jaxbJoinColumn, JaxbJoinColumnImpl::getTable, "table", joinColumnAnn, joinColumnDescriptor );
applyOr( jaxbJoinColumn, JaxbJoinColumnImpl::getReferencedColumnName, "referencedColumnName", joinColumnAnn, joinColumnDescriptor );
applyOr( jaxbJoinColumn, JaxbJoinColumnImpl::getOptions, "options", joinColumnAnn, joinColumnDescriptor );
applyOr( jaxbJoinColumn, JaxbJoinColumnImpl::getComment, "comment", joinColumnAnn, joinColumnDescriptor );
applyOr( jaxbJoinColumn, JaxbJoinColumnImpl::getColumnDefinition, "columnDefinition", joinColumnAnn, joinColumnDescriptor );

final JaxbForeignKeyImpl jaxbForeignKey = jaxbJoinColumn.getForeignKey();
final MutableAnnotationUsage<ForeignKey> foreignKeyAnn = getOrMakeAnnotation( ForeignKey.class, memberDetails );
final AnnotationDescriptor<ForeignKey> foreignKeyDescriptor = sourceModelBuildingContext
.getAnnotationDescriptorRegistry()
.getDescriptor( ForeignKey.class );
joinColumnAnn.setAttributeValue( "foreignKey", foreignKeyAnn );

applyOr( jaxbForeignKey, JaxbForeignKeyImpl::getName, "name", foreignKeyAnn, foreignKeyDescriptor );
applyOr( jaxbForeignKey, JaxbForeignKeyImpl::getConstraintMode, "value", foreignKeyAnn, foreignKeyDescriptor );
applyOr( jaxbForeignKey, JaxbForeignKeyImpl::getForeignKeyDefinition, "foreignKeyDefinition", foreignKeyAnn, foreignKeyDescriptor );
applyOr( jaxbForeignKey, JaxbForeignKeyImpl::getOptions, "options", foreignKeyAnn, foreignKeyDescriptor );

if ( CollectionHelper.isNotEmpty( jaxbJoinColumn.getCheckConstraint() ) ) {
final List<MutableAnnotationUsage<CheckConstraint>> constraints = new ArrayList<>( jaxbJoinColumn.getCheckConstraint().size() );
joinColumnAnn.setAttributeValue( "check", constraints );
for ( int i = 0; i < jaxbJoinColumn.getCheckConstraint().size(); i++ ) {
final JaxbCheckConstraintImpl jaxbCheckConstraint = jaxbJoinColumn.getCheckConstraint().get( i );
final MutableAnnotationUsage<CheckConstraint> checkConstraintAnn = getOrMakeAnnotation( CheckConstraint.class, memberDetails );
final AnnotationDescriptor<CheckConstraint> checkConstraintDescriptor = sourceModelBuildingContext
.getAnnotationDescriptorRegistry()
.getDescriptor( CheckConstraint.class );
constraints.add( checkConstraintAnn );

applyOr( jaxbCheckConstraint, JaxbCheckConstraintImpl::getName, "name", checkConstraintAnn, checkConstraintDescriptor );
applyOr( jaxbCheckConstraint, JaxbCheckConstraintImpl::getConstraint, "constraint", checkConstraintAnn, checkConstraintDescriptor );
applyOr( jaxbCheckConstraint, JaxbCheckConstraintImpl::getOptions, "options", checkConstraintAnn, checkConstraintDescriptor );
}
}
else {
final MutableAnnotationUsage<CheckConstraint> checkConstraintAnn = getOrMakeAnnotation( CheckConstraint.class, memberDetails );
joinColumnAnn.setAttributeValue( "check", List.of( checkConstraintAnn ) );
}

return joinColumnAnn;
}

public static <T,N> void applyOr(
N jaxbNode,
Function<N,T> jaxbValueAccess,
String name,
KeyedConsumer<String, T> valueConsumer,
Supplier<T> defaultValueProvider) {
if ( jaxbNode != null ) {
final T value = jaxbValueAccess.apply( jaxbNode );
if ( value != null ) {
valueConsumer.accept( name, value );
return;
}
}

valueConsumer.accept( name, defaultValueProvider.get() );
}

public static <T,N,A extends Annotation> void applyOr(
N jaxbNode,
Function<N,T> jaxbValueAccess,
String name,
MutableAnnotationUsage<A> annotationUsage,
AnnotationDescriptor<A> annotationDescriptor) {
//noinspection unchecked
applyOr(
jaxbNode,
jaxbValueAccess,
name,
(key, value) -> annotationUsage.setAttributeValue( name, value ),
() -> (T) annotationDescriptor.getAttribute( name ).getAttributeMethod().getDefaultValue()
);
}

private static MutableAnnotationUsage<Column> createColumnAnnotation(
JaxbColumnImpl jaxbColumn,
MutableAnnotationTarget target) {
final MutableAnnotationUsage<Column> columnAnn = XmlProcessingHelper.getOrMakeAnnotation( Column.class, target );
final MutableAnnotationUsage<Column> columnAnn = getOrMakeAnnotation( Column.class, target );

if ( jaxbColumn != null ) {
if ( StringHelper.isNotEmpty( jaxbColumn.getName() ) ) {
Expand Down Expand Up @@ -250,6 +360,26 @@ private static MutableAnnotationUsage<Column> createColumnAnnotation(
if ( jaxbColumn.getScale() != null ) {
columnAnn.setAttributeValue( "scale", jaxbColumn.getScale() );
}

if ( jaxbColumn.getComment() != null ) {
columnAnn.setAttributeValue( "comment", jaxbColumn.getComment() );
}

if ( jaxbColumn.getOptions() != null ) {
columnAnn.setAttributeValue( "options", jaxbColumn.getOptions() );
}

if ( CollectionHelper.isNotEmpty( jaxbColumn.getCheckConstraints() ) ) {
final List<AnnotationUsage<Check>> checks = new ArrayList<>( jaxbColumn.getCheckConstraints().size() );
for ( int i = 0; i < jaxbColumn.getCheckConstraints().size(); i++ ) {
final JaxbCheckConstraintImpl jaxbCheck = jaxbColumn.getCheckConstraints().get( i );
final MutableAnnotationUsage<Check> checkAnn = getOrMakeAnnotation( Check.class, target );
checkAnn.setAttributeValue( "name", jaxbCheck.getName() );
checkAnn.setAttributeValue( "constraints", jaxbCheck.getConstraint() );
checks.add( checkAnn );
}
columnAnn.setAttributeValue( "check", checks );
}
}

return columnAnn;
Expand Down Expand Up @@ -558,7 +688,7 @@ public static void applyTableOverride(
return;
}

final MutableAnnotationUsage<Table> tableAnn = XmlProcessingHelper.getOrMakeAnnotation( Table.class, target );
final MutableAnnotationUsage<Table> tableAnn = getOrMakeAnnotation( Table.class, target );

applyTableAttributes( tableAnn, jaxbTable, persistenceUnitMetadata );

Expand Down Expand Up @@ -672,7 +802,7 @@ static void applyInheritance(
return;
}

final MutableAnnotationUsage<Inheritance> inheritanceAnn = XmlProcessingHelper.getOrMakeAnnotation(
final MutableAnnotationUsage<Inheritance> inheritanceAnn = getOrMakeAnnotation(
Inheritance.class,
classDetails
);
Expand Down Expand Up @@ -939,7 +1069,7 @@ static void applyEntityListener(
JaxbEntityListenerImpl jaxbEntityListener,
MutableClassDetails classDetails,
SourceModelBuildingContext buildingContext) {
final MutableAnnotationUsage<EntityListeners> entityListeners = XmlProcessingHelper.getOrMakeAnnotation(
final MutableAnnotationUsage<EntityListeners> entityListeners = getOrMakeAnnotation(
EntityListeners.class,
classDetails
);
Expand Down Expand Up @@ -1013,7 +1143,7 @@ static void applyRowId(
MutableClassDetails target,
SourceModelBuildingContext buildingContext) {
if ( rowId != null ) {
final MutableAnnotationUsage<RowId> rowIdAnn = XmlProcessingHelper.getOrMakeAnnotation( RowId.class, target );
final MutableAnnotationUsage<RowId> rowIdAnn = getOrMakeAnnotation( RowId.class, target );
applyAttributeIfSpecified( rowIdAnn, "value", rowId );
}
}
Expand Down
Loading

0 comments on commit ab17103

Please sign in to comment.