From 025b3cc14180d0459856bc45a6cac7acce3e1265 Mon Sep 17 00:00:00 2001 From: Hardy Ferentschik Date: Fri, 11 Dec 2009 19:14:01 +0000 Subject: [PATCH] HHH-4527 No functional changes yet. Just some cleanup and refactoring (extract method, encapsulate field) git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@18211 1b8cb986-b30d-0410-93ca-fae66ebed9b2 --- .../org/hibernate/annotations/AccessType.java | 9 +- .../org/hibernate/cfg/AnnotationBinder.java | 363 ++++++++++-------- .../cfg/AnnotationConfiguration.java | 47 ++- .../java/org/hibernate/cfg/BinderHelper.java | 2 +- .../hibernate/cfg/ClassPropertyHolder.java | 4 +- .../org/hibernate/cfg/InheritanceState.java | 96 ++++- .../cfg/annotations/EntityBinder.java | 2 +- .../test/annotations/access/AccessTest.java | 22 +- .../test/annotations/access/Furniture.java | 1 - .../test/annotations/embedded/Country.java | 2 - 10 files changed, 315 insertions(+), 233 deletions(-) diff --git a/annotations/src/main/java/org/hibernate/annotations/AccessType.java b/annotations/src/main/java/org/hibernate/annotations/AccessType.java index 8d387b9355..5a2037e318 100644 --- a/annotations/src/main/java/org/hibernate/annotations/AccessType.java +++ b/annotations/src/main/java/org/hibernate/annotations/AccessType.java @@ -23,17 +23,20 @@ */ package org.hibernate.annotations; -import static java.lang.annotation.ElementType.*; import java.lang.annotation.Retention; -import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Target; +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + /** * Property Access type * * @author Emmanuel Bernard */ -@Target({TYPE, METHOD, FIELD}) +@Target({ TYPE, METHOD, FIELD }) @Retention(RUNTIME) public @interface AccessType { String value(); diff --git a/annotations/src/main/java/org/hibernate/cfg/AnnotationBinder.java b/annotations/src/main/java/org/hibernate/cfg/AnnotationBinder.java index 7e87a67ee2..59294c7024 100644 --- a/annotations/src/main/java/org/hibernate/cfg/AnnotationBinder.java +++ b/annotations/src/main/java/org/hibernate/cfg/AnnotationBinder.java @@ -176,6 +176,7 @@ import org.slf4j.LoggerFactory; * package) * * @author Emmanuel Bernard + * @author Hardy Ferentschik */ @SuppressWarnings("unchecked") public final class AnnotationBinder { @@ -247,7 +248,7 @@ public final class AnnotationBinder { } public static void bindPackage(String packageName, ExtendedMappings mappings) { - XPackage pckg = null; + XPackage pckg; try { pckg = mappings.getReflectionManager().packageForName( packageName ); } @@ -438,153 +439,72 @@ public final class AnnotationBinder { bindFilterDefs(clazzToProcess, mappings); } - if ( AnnotatedClassType.EMBEDDABLE_SUPERCLASS.equals( classType ) //will be processed by their subentities - || AnnotatedClassType.NONE.equals( classType ) //to be ignored - || AnnotatedClassType.EMBEDDABLE.equals( classType ) //allow embeddable element declaration - ) { - if ( AnnotatedClassType.NONE.equals( classType ) - && clazzToProcess.isAnnotationPresent( org.hibernate.annotations.Entity.class ) ) { - log.warn( "Class annotated @org.hibernate.annotations.Entity but not javax.persistence.Entity " - + "(most likely a user error): {}", clazzToProcess.getName() ); - } + if( !isEntityClassType( clazzToProcess, classType ) ) { return; } - if ( !classType.equals( AnnotatedClassType.ENTITY ) ) { - //TODO make this test accurate by removing the none elements artifically added - throw new AnnotationException( - "Annotated class should have a @javax.persistence.Entity, @javax.persistence.Embeddable or @javax.persistence.EmbeddedSuperclass annotation: " + clazzToProcess - .getName() - ); - } - XAnnotatedElement annotatedClass = clazzToProcess; + log.info( "Binding entity from annotated class: {}", clazzToProcess.getName() ); - final ReflectionManager reflectionManager = mappings.getReflectionManager(); - InheritanceState superEntityState = - InheritanceState.getSuperEntityInheritanceState( - clazzToProcess, inheritanceStatePerClass, reflectionManager - ); - PersistentClass superEntity = superEntityState != null ? - mappings.getClass( - superEntityState.clazz.getName() - ) : - null; - if ( superEntity == null ) { - //check if superclass is not a potential persistent class - if ( inheritanceState.hasParents ) { - throw new AssertionFailure( - "Subclass has to be binded after it's mother class: " - + superEntityState.clazz.getName() - ); - } - } - bindQueries( annotatedClass, mappings ); - bindFilterDefs( annotatedClass, mappings ); - bindTypeDefs( annotatedClass, mappings ); - BinderHelper.bindAnyMetaDefs( annotatedClass, mappings ); + + PersistentClass superEntity = getSuperEntity(clazzToProcess, inheritanceStatePerClass, mappings, inheritanceState); + + bindQueries( clazzToProcess, mappings ); + bindFilterDefs( clazzToProcess, mappings ); + bindTypeDefs( clazzToProcess, mappings ); + BinderHelper.bindAnyMetaDefs( clazzToProcess, mappings ); String schema = ""; String table = ""; //might be no @Table annotation on the annotated class String catalog = ""; - String discrimValue = null; List uniqueConstraints = new ArrayList(); - Ejb3DiscriminatorColumn discriminatorColumn = null; - Ejb3JoinColumn[] inheritanceJoinedColumns = null; - - if ( annotatedClass.isAnnotationPresent( javax.persistence.Table.class ) ) { - javax.persistence.Table tabAnn = annotatedClass.getAnnotation( javax.persistence.Table.class ); + if ( clazzToProcess.isAnnotationPresent( javax.persistence.Table.class ) ) { + javax.persistence.Table tabAnn = clazzToProcess.getAnnotation( javax.persistence.Table.class ); table = tabAnn.name(); schema = tabAnn.schema(); catalog = tabAnn.catalog(); uniqueConstraints = TableBinder.buildUniqueConstraintHolders( tabAnn.uniqueConstraints() ); } - final boolean hasJoinedColumns = inheritanceState.hasParents - && InheritanceType.JOINED.equals( inheritanceState.type ); - if ( hasJoinedColumns ) { - //@Inheritance(JOINED) subclass need to link back to the super entity - PrimaryKeyJoinColumns jcsAnn = annotatedClass.getAnnotation( PrimaryKeyJoinColumns.class ); - boolean explicitInheritanceJoinedColumns = jcsAnn != null && jcsAnn.value().length != 0; - if ( explicitInheritanceJoinedColumns ) { - int nbrOfInhJoinedColumns = jcsAnn.value().length; - PrimaryKeyJoinColumn jcAnn; - inheritanceJoinedColumns = new Ejb3JoinColumn[nbrOfInhJoinedColumns]; - for (int colIndex = 0; colIndex < nbrOfInhJoinedColumns; colIndex++) { - jcAnn = jcsAnn.value()[colIndex]; - inheritanceJoinedColumns[colIndex] = Ejb3JoinColumn.buildJoinColumn( - jcAnn, null, superEntity.getIdentifier(), - (Map) null, (PropertyHolder) null, mappings - ); - } - } - else { - PrimaryKeyJoinColumn jcAnn = annotatedClass.getAnnotation( PrimaryKeyJoinColumn.class ); - inheritanceJoinedColumns = new Ejb3JoinColumn[1]; - inheritanceJoinedColumns[0] = Ejb3JoinColumn.buildJoinColumn( - jcAnn, null, superEntity.getIdentifier(), - (Map) null, (PropertyHolder) null, mappings - ); - } - log.debug( "Subclass joined column(s) created" ); - } - else { - if ( annotatedClass.isAnnotationPresent( javax.persistence.PrimaryKeyJoinColumns.class ) - || annotatedClass.isAnnotationPresent( javax.persistence.PrimaryKeyJoinColumn.class ) ) { - log.warn( "Root entity should not hold an PrimaryKeyJoinColum(s), will be ignored" ); - } - } - if ( InheritanceType.SINGLE_TABLE.equals( inheritanceState.type ) ) { - javax.persistence.DiscriminatorColumn discAnn = annotatedClass.getAnnotation( + Ejb3JoinColumn[] inheritanceJoinedColumns = makeInheritanceJoinColumns( clazzToProcess, mappings, inheritanceState, superEntity ); + Ejb3DiscriminatorColumn discriminatorColumn = null; + String discrimValue = null; + if ( InheritanceType.SINGLE_TABLE.equals( inheritanceState.getType() ) ) { + javax.persistence.DiscriminatorColumn discAnn = clazzToProcess.getAnnotation( javax.persistence.DiscriminatorColumn.class ); DiscriminatorType discriminatorType = discAnn != null ? discAnn.discriminatorType() : DiscriminatorType.STRING; - org.hibernate.annotations.DiscriminatorFormula discFormulaAnn = annotatedClass.getAnnotation( + org.hibernate.annotations.DiscriminatorFormula discFormulaAnn = clazzToProcess.getAnnotation( org.hibernate.annotations.DiscriminatorFormula.class ); - if ( !inheritanceState.hasParents ) { + if ( !inheritanceState.hasParents() ) { discriminatorColumn = Ejb3DiscriminatorColumn.buildDiscriminatorColumn( discriminatorType, discAnn, discFormulaAnn, mappings ); } - if ( discAnn != null && inheritanceState.hasParents ) { + if ( discAnn != null && inheritanceState.hasParents() ) { log.warn( "Discriminator column has to be defined in the root entity, it will be ignored in subclass: {}", clazzToProcess.getName() ); } - discrimValue = annotatedClass.isAnnotationPresent( DiscriminatorValue.class ) ? - annotatedClass.getAnnotation( DiscriminatorValue.class ).value() : + + discrimValue = clazzToProcess.isAnnotationPresent( DiscriminatorValue.class ) ? + clazzToProcess.getAnnotation( DiscriminatorValue.class ).value() : null; } - //we now know what kind of persistent entity it is - PersistentClass persistentClass; - //create persistent class - if ( !inheritanceState.hasParents ) { - persistentClass = new RootClass(); - } - else if ( InheritanceType.SINGLE_TABLE.equals( inheritanceState.type ) ) { - persistentClass = new SingleTableSubclass( superEntity ); - } - else if ( InheritanceType.JOINED.equals( inheritanceState.type ) ) { - persistentClass = new JoinedSubclass( superEntity ); - } - else if ( InheritanceType.TABLE_PER_CLASS.equals( inheritanceState.type ) ) { - persistentClass = new UnionSubclass( superEntity ); - } - else { - throw new AssertionFailure( "Unknown inheritance type: " + inheritanceState.type ); - } - Proxy proxyAnn = annotatedClass.getAnnotation( Proxy.class ); - BatchSize sizeAnn = annotatedClass.getAnnotation( BatchSize.class ); - Where whereAnn = annotatedClass.getAnnotation( Where.class ); - Entity entityAnn = annotatedClass.getAnnotation( Entity.class ); - org.hibernate.annotations.Entity hibEntityAnn = annotatedClass.getAnnotation( + PersistentClass persistentClass = makePersistentClass( inheritanceState, superEntity ); + + Proxy proxyAnn = clazzToProcess.getAnnotation( Proxy.class ); + BatchSize sizeAnn = clazzToProcess.getAnnotation( BatchSize.class ); + Where whereAnn = clazzToProcess.getAnnotation( Where.class ); + Entity entityAnn = clazzToProcess.getAnnotation( Entity.class ); + org.hibernate.annotations.Entity hibEntityAnn = clazzToProcess.getAnnotation( org.hibernate.annotations.Entity.class ); - org.hibernate.annotations.Cache cacheAnn = annotatedClass.getAnnotation( + org.hibernate.annotations.Cache cacheAnn = clazzToProcess.getAnnotation( org.hibernate.annotations.Cache.class ); EntityBinder entityBinder = new EntityBinder( @@ -598,14 +518,14 @@ public final class AnnotationBinder { entityBinder.setInheritanceState( inheritanceState ); //Filters are not allowed on subclasses - if ( !inheritanceState.hasParents ) { + if ( !inheritanceState.hasParents() ) { bindFilters(clazzToProcess, entityBinder, mappings); } entityBinder.bindEntity(); if ( inheritanceState.hasTable() ) { - Check checkAnn = annotatedClass.getAnnotation( Check.class ); + Check checkAnn = clazzToProcess.getAnnotation( Check.class ); String constraints = checkAnn == null ? null : checkAnn.constraints(); @@ -617,32 +537,29 @@ public final class AnnotationBinder { ); } else { - if ( annotatedClass.isAnnotationPresent( Table.class ) ) { + if ( clazzToProcess.isAnnotationPresent( Table.class ) ) { log.warn( "Illegal use of @Table in a subclass of a SINGLE_TABLE hierarchy: " + clazzToProcess .getName() ); } } -// Map columnOverride = PropertyHolderBuilder.buildHierarchyColumnOverride( -// clazzToProcess, -// persistentClass.getClassName() -// ); + PropertyHolder propertyHolder = PropertyHolderBuilder.buildPropertyHolder( clazzToProcess, persistentClass, entityBinder, mappings, inheritanceStatePerClass ); - javax.persistence.SecondaryTable secTabAnn = annotatedClass.getAnnotation( + javax.persistence.SecondaryTable secTabAnn = clazzToProcess.getAnnotation( javax.persistence.SecondaryTable.class ); - javax.persistence.SecondaryTables secTabsAnn = annotatedClass.getAnnotation( + javax.persistence.SecondaryTables secTabsAnn = clazzToProcess.getAnnotation( javax.persistence.SecondaryTables.class ); entityBinder.firstLevelSecondaryTablesBinding( secTabAnn, secTabsAnn ); - OnDelete onDeleteAnn = annotatedClass.getAnnotation( OnDelete.class ); + OnDelete onDeleteAnn = clazzToProcess.getAnnotation( OnDelete.class ); boolean onDeleteAppropriate = false; - if ( InheritanceType.JOINED.equals( inheritanceState.type ) && inheritanceState.hasParents ) { + if ( InheritanceType.JOINED.equals( inheritanceState.getType() ) && inheritanceState.hasParents() ) { onDeleteAppropriate = true; final JoinedSubclass jsc = (JoinedSubclass) persistentClass; if ( persistentClass.getEntityPersisterClass() == null ) { @@ -650,7 +567,7 @@ public final class AnnotationBinder { } SimpleValue key = new DependantValue( jsc.getTable(), jsc.getIdentifier() ); jsc.setKey( key ); - ForeignKey fk = annotatedClass.getAnnotation( ForeignKey.class ); + ForeignKey fk = clazzToProcess.getAnnotation( ForeignKey.class ); if ( fk != null && !BinderHelper.isDefault( fk.name() ) ) { key.setForeignKeyName( fk.name() ); } @@ -666,14 +583,14 @@ public final class AnnotationBinder { mappings.addSecondPass( new CreateKeySecondPass( jsc ) ); } - else if ( InheritanceType.SINGLE_TABLE.equals( inheritanceState.type ) ) { - if ( inheritanceState.hasParents ) { + else if ( InheritanceType.SINGLE_TABLE.equals( inheritanceState.getType() ) ) { + if ( inheritanceState.hasParents() ) { if ( persistentClass.getEntityPersisterClass() == null ) { persistentClass.getRootClass().setEntityPersisterClass( SingleTableEntityPersister.class ); } } else { - if ( inheritanceState.hasSons || !discriminatorColumn.isImplicit() ) { + if ( inheritanceState.hasSiblings() || !discriminatorColumn.isImplicit() ) { //need a discriminator column bindDiscriminatorToPersistentClass( (RootClass) persistentClass, @@ -685,8 +602,8 @@ public final class AnnotationBinder { } } } - else if ( InheritanceType.TABLE_PER_CLASS.equals( inheritanceState.type ) ) { - if ( inheritanceState.hasParents ) { + else if ( InheritanceType.TABLE_PER_CLASS.equals( inheritanceState.getType() ) ) { + if ( inheritanceState.hasParents() ) { if ( persistentClass.getEntityPersisterClass() == null ) { persistentClass.getRootClass().setEntityPersisterClass( UnionSubclassEntityPersister.class ); } @@ -699,7 +616,7 @@ public final class AnnotationBinder { } //try to find class level generators - HashMap classGenerators = buildLocalGenerators( annotatedClass, mappings ); + HashMap classGenerators = buildLocalGenerators( clazzToProcess, mappings ); // check properties List elements = @@ -709,30 +626,29 @@ public final class AnnotationBinder { if ( elements == null ) { throw new AnnotationException( "No identifier specified for entity: " + propertyHolder.getEntityName() ); } - final boolean subclassAndSingleTableStrategy = inheritanceState.type == InheritanceType.SINGLE_TABLE - && inheritanceState.hasParents; + final boolean subclassAndSingleTableStrategy = inheritanceState.getType() == InheritanceType.SINGLE_TABLE + && inheritanceState.hasParents(); //process idclass if any Set idProperties = new HashSet(); IdClass idClass = null; XClass current = null; - if ( !inheritanceState.hasParents ) { + if ( !inheritanceState.hasParents() ) { //look for idClass - current = inheritanceState.clazz; InheritanceState state = inheritanceState; do { - current = state.clazz; + current = state.getClazz(); if ( current.isAnnotationPresent( IdClass.class ) ) { idClass = current.getAnnotation( IdClass.class ); break; } state = InheritanceState.getSuperclassInheritanceState( - current, inheritanceStatePerClass, reflectionManager + current, inheritanceStatePerClass, mappings.getReflectionManager() ); } while ( state != null ); } if ( idClass != null ) { - XClass compositeClass = reflectionManager.toXClass( idClass.value() ); + XClass compositeClass = mappings.getReflectionManager().toXClass( idClass.value() ); boolean isComponent = true; boolean propertyAnnotated = entityBinder.isPropertyAnnotated( compositeClass ); String propertyAccessor = entityBinder.getPropertyAccessor( compositeClass ); @@ -837,7 +753,7 @@ public final class AnnotationBinder { ); } - if ( !inheritanceState.hasParents ) { + if ( !inheritanceState.hasParents() ) { final RootClass rootClass = (RootClass) persistentClass; mappings.addSecondPass( new CreateKeySecondPass( rootClass ) ); } @@ -848,14 +764,121 @@ public final class AnnotationBinder { mappings.addClass( persistentClass ); //Process secondary tables and complementary definitions (ie o.h.a.Table) - mappings.addSecondPass( new SecondaryTableSecondPass( entityBinder, propertyHolder, annotatedClass ) ); + mappings.addSecondPass( new SecondaryTableSecondPass( entityBinder, propertyHolder, clazzToProcess ) ); //add process complementary Table definition (index & all) - entityBinder.processComplementaryTableDefinitions( annotatedClass.getAnnotation( org.hibernate.annotations.Table.class ) ); - entityBinder.processComplementaryTableDefinitions( annotatedClass.getAnnotation( org.hibernate.annotations.Tables.class ) ); + entityBinder.processComplementaryTableDefinitions( clazzToProcess.getAnnotation( org.hibernate.annotations.Table.class ) ); + entityBinder.processComplementaryTableDefinitions( clazzToProcess.getAnnotation( org.hibernate.annotations.Tables.class ) ); } + private static PersistentClass makePersistentClass(InheritanceState inheritanceState, PersistentClass superEntity) { + //we now know what kind of persistent entity it is + PersistentClass persistentClass; + //create persistent class + if ( !inheritanceState.hasParents() ) { + persistentClass = new RootClass(); + } + else if ( InheritanceType.SINGLE_TABLE.equals( inheritanceState.getType() ) ) { + persistentClass = new SingleTableSubclass( superEntity ); + } + else if ( InheritanceType.JOINED.equals( inheritanceState.getType() ) ) { + persistentClass = new JoinedSubclass( superEntity ); + } + else if ( InheritanceType.TABLE_PER_CLASS.equals( inheritanceState.getType() ) ) { + persistentClass = new UnionSubclass( superEntity ); + } + else { + throw new AssertionFailure( "Unknown inheritance type: " + inheritanceState.getType() ); + } + return persistentClass; + } + + private static Ejb3JoinColumn[] makeInheritanceJoinColumns(XClass clazzToProcess, ExtendedMappings mappings, InheritanceState inheritanceState, PersistentClass superEntity) { + Ejb3JoinColumn[] inheritanceJoinedColumns = null; + final boolean hasJoinedColumns = inheritanceState.hasParents() + && InheritanceType.JOINED.equals( inheritanceState.getType() ); + if ( hasJoinedColumns ) { + //@Inheritance(JOINED) subclass need to link back to the super entity + PrimaryKeyJoinColumns jcsAnn = clazzToProcess.getAnnotation( PrimaryKeyJoinColumns.class ); + boolean explicitInheritanceJoinedColumns = jcsAnn != null && jcsAnn.value().length != 0; + if ( explicitInheritanceJoinedColumns ) { + int nbrOfInhJoinedColumns = jcsAnn.value().length; + PrimaryKeyJoinColumn jcAnn; + inheritanceJoinedColumns = new Ejb3JoinColumn[nbrOfInhJoinedColumns]; + for (int colIndex = 0; colIndex < nbrOfInhJoinedColumns; colIndex++) { + jcAnn = jcsAnn.value()[colIndex]; + inheritanceJoinedColumns[colIndex] = Ejb3JoinColumn.buildJoinColumn( + jcAnn, null, superEntity.getIdentifier(), + ( Map ) null, ( PropertyHolder ) null, mappings + ); + } + } + else { + PrimaryKeyJoinColumn jcAnn = clazzToProcess.getAnnotation( PrimaryKeyJoinColumn.class ); + inheritanceJoinedColumns = new Ejb3JoinColumn[1]; + inheritanceJoinedColumns[0] = Ejb3JoinColumn.buildJoinColumn( + jcAnn, null, superEntity.getIdentifier(), + (Map) null, (PropertyHolder) null, mappings + ); + } + log.debug( "Subclass joined column(s) created" ); + } + else { + if ( clazzToProcess.isAnnotationPresent( PrimaryKeyJoinColumns.class ) + || clazzToProcess.isAnnotationPresent( PrimaryKeyJoinColumn.class ) ) { + log.warn( "Root entity should not hold an PrimaryKeyJoinColum(s), will be ignored" ); + } + } + return inheritanceJoinedColumns; + } + + private static PersistentClass getSuperEntity(XClass clazzToProcess, Map inheritanceStatePerClass, ExtendedMappings mappings, InheritanceState inheritanceState) { + final ReflectionManager reflectionManager = mappings.getReflectionManager(); + InheritanceState superEntityState = + InheritanceState.getInheritanceStateOfSuperEntity( + clazzToProcess, inheritanceStatePerClass, reflectionManager + ); + PersistentClass superEntity = superEntityState != null ? + mappings.getClass( + superEntityState.getClazz().getName() + ) : + null; + if ( superEntity == null ) { + //check if superclass is not a potential persistent class + if ( inheritanceState.hasParents() ) { + throw new AssertionFailure( + "Subclass has to be binded after it's mother class: " + + superEntityState.getClazz().getName() + ); + } + } + return superEntity; + } + + private static boolean isEntityClassType(XClass clazzToProcess, AnnotatedClassType classType) { + if ( AnnotatedClassType.EMBEDDABLE_SUPERCLASS.equals( classType ) //will be processed by their subentities + || AnnotatedClassType.NONE.equals( classType ) //to be ignored + || AnnotatedClassType.EMBEDDABLE.equals( classType ) //allow embeddable element declaration + ) { + if ( AnnotatedClassType.NONE.equals( classType ) + && clazzToProcess.isAnnotationPresent( org.hibernate.annotations.Entity.class ) ) { + log.warn( "Class annotated @org.hibernate.annotations.Entity but not javax.persistence.Entity " + + "(most likely a user error): {}", clazzToProcess.getName() ); + } + return false; + } + + if ( !classType.equals( AnnotatedClassType.ENTITY ) ) { + throw new AnnotationException( + "Annotated class should have a @javax.persistence.Entity, @javax.persistence.Embeddable or @javax.persistence.EmbeddedSuperclass annotation: " + clazzToProcess + .getName() + ); + } + + return true; + } + /** * Get the annotated elements * Guess the annotated element from @Id or @EmbeddedId presence @@ -874,19 +897,19 @@ public final class AnnotationBinder { int deep = classesToProcess.size(); boolean hasIdentifier = false; - assert !inheritanceState.isEmbeddableSuperclass; + assert !inheritanceState.isEmbeddableSuperclass(); Boolean isExplicitPropertyAnnotated = null; String explicitAccessType; - if ( inheritanceState.hasParents ) { + if ( inheritanceState.hasParents() ) { InheritanceState superEntityState = - InheritanceState.getSuperEntityInheritanceState( + InheritanceState.getInheritanceStateOfSuperEntity( clazzToProcess, inheritanceStatePerClass, mappings.getReflectionManager() ); isExplicitPropertyAnnotated = superEntityState != null ? - superEntityState.isPropertyAnnotated : + superEntityState.isPropertyAnnotated() : null; explicitAccessType = superEntityState != null ? - superEntityState.accessType : + superEntityState.getAccessType() : null; } else { @@ -928,7 +951,7 @@ public final class AnnotationBinder { exceptionWhileWalkingElements = e; } - if ( !hasIdentifier && !inheritanceState.hasParents ) { + if ( !hasIdentifier && !inheritanceState.hasParents() ) { if ( isExplicitPropertyAnnotated != null ) { //the original exception is legitimate if ( exceptionWhileWalkingElements != null) throw exceptionWhileWalkingElements; @@ -953,9 +976,9 @@ public final class AnnotationBinder { //TODO set the access type here? entityBinder.setPropertyAnnotated( isPropertyAnnotated ); entityBinder.setPropertyAccessor( accessType ); - inheritanceState.isPropertyAnnotated = isPropertyAnnotated; - inheritanceState.accessType = accessType; - return hasIdentifier || inheritanceState.hasParents ? + inheritanceState.setPropertyAnnotated( isPropertyAnnotated ); + inheritanceState.setAccessType( accessType ); + return hasIdentifier || inheritanceState.hasParents() ? elements : null; } @@ -983,16 +1006,16 @@ public final class AnnotationBinder { currentClassInHierarchy = superClass; } - while ( superclassState != null && superclassState.isEmbeddableSuperclass ); + while ( superclassState != null && superclassState.isEmbeddableSuperclass() ); //add @MappedSuperclass in the metadata // classes from 0 to n-1 are @MappedSuperclass and should be linked org.hibernate.mapping.MappedSuperclass mappedSuperclass = null; final InheritanceState superEntityState = - InheritanceState.getSuperEntityInheritanceState(annotatedClass, inheritanceStatePerClass, reflectionManager); + InheritanceState.getInheritanceStateOfSuperEntity(annotatedClass, inheritanceStatePerClass, reflectionManager); PersistentClass superEntity = superEntityState != null ? - mappings.getClass( superEntityState.clazz.getName() ) : + mappings.getClass( superEntityState.getClazz().getName() ) : null; final int lastMappedSuperclass = classesToProcess.size() - 1; for ( int index = 0 ; index < lastMappedSuperclass ; index++ ) { @@ -1139,7 +1162,7 @@ public final class AnnotationBinder { String localPropertyAccessor = access != null ? access.value() : null; - String accessType = null; + String accessType; if ( "property".equals( localPropertyAccessor ) || "field".equals( localPropertyAccessor ) ) { accessType = localPropertyAccessor; } @@ -1579,8 +1602,6 @@ public final class AnnotationBinder { } Cascade hibernateCascade = property.getAnnotation( Cascade.class ); - NotFound notFound = property.getAnnotation( NotFound.class ); - boolean ignoreNotFound = notFound != null && notFound.action().equals( NotFoundAction.IGNORE ); OnDelete onDeleteAnn = property.getAnnotation( OnDelete.class ); boolean onDeleteCascade = onDeleteAnn != null && OnDeleteAction.CASCADE.equals( onDeleteAnn.action() ); JoinTable assocTable = property.getAnnotation( JoinTable.class ); @@ -1654,7 +1675,7 @@ public final class AnnotationBinder { collectionBinder.setMappings( mappings ); collectionBinder.setPropertyAccessorName( inferredData.getDefaultAccess() ); - Ejb3Column[] elementColumns = null; + Ejb3Column[] elementColumns; PropertyData virtualProperty = new WrappedInferredData( inferredData, "element" ); if ( property.isAnnotationPresent( Column.class ) || property.isAnnotationPresent( Formula.class @@ -1860,7 +1881,7 @@ public final class AnnotationBinder { } else { //define whether the type is a component or not - boolean isComponent = false; + boolean isComponent; Embeddable embeddableAnn = returnedClass.getAnnotation( Embeddable.class ); Embedded embeddedAnn = property.getAnnotation( Embedded.class ); isComponent = embeddedAnn != null || embeddableAnn != null; @@ -2185,9 +2206,7 @@ public final class AnnotationBinder { ); } RootClass rootClass = (RootClass) persistentClass; - String persistentClassName = rootClass == null ? - null : - rootClass.getClassName(); + String persistentClassName = rootClass.getClassName(); SimpleValue id; if ( isComposite ) { id = fillComponent( @@ -2620,6 +2639,14 @@ public final class AnnotationBinder { return mappings.getReflectionManager().equals( clazz, void.class ); } + /** + * For the mapped entities build some temporary data-structure containing information about the + * inheritance status of a class. + * + * @param orderedClasses Order list of all annotated entities and their mapped superclasses + * @param reflectionManager Reference to the reflection manager (commons-annotations) + * @return A map of {@code InheritanceState}s keyed against their {@code XClass}. + */ public static Map buildInheritanceStates( List orderedClasses, ReflectionManager reflectionManager ) { @@ -2635,22 +2662,22 @@ public final class AnnotationBinder { if ( superclassState != null ) { //the classes are ordered thus preventing an NPE //FIXME if an entity has subclasses annotated @MappedSperclass wo sub @Entity this is wrong - superclassState.hasSons = true; - InheritanceState superEntityState = InheritanceState.getSuperEntityInheritanceState( + superclassState.setHasSiblings( true ); + InheritanceState superEntityState = InheritanceState.getInheritanceStateOfSuperEntity( clazz, inheritanceStatePerClass, reflectionManager ); - state.hasParents = superEntityState != null; - final boolean nonDefault = state.type != null && !InheritanceType.SINGLE_TABLE.equals( state.type ); - if ( superclassState.type != null ) { - final boolean mixingStrategy = state.type != null && !state.type.equals( superclassState.type ); + state.setHasParents( superEntityState != null ); + final boolean nonDefault = state.getType() != null && !InheritanceType.SINGLE_TABLE.equals( state.getType() ); + if ( superclassState.getType() != null ) { + final boolean mixingStrategy = state.getType() != null && !state.getType().equals( superclassState.getType() ); if ( nonDefault && mixingStrategy ) { log.warn( "Mixing inheritance strategy in a entity hierarchy is not allowed, ignoring sub strategy in: {}", clazz.getName() ); } - state.type = superclassState.type; + state.setType( superclassState.getType() ); } } inheritanceStatePerClass.put( clazz, state ); diff --git a/annotations/src/main/java/org/hibernate/cfg/AnnotationConfiguration.java b/annotations/src/main/java/org/hibernate/cfg/AnnotationConfiguration.java index 854bff2f14..dc239d91cd 100644 --- a/annotations/src/main/java/org/hibernate/cfg/AnnotationConfiguration.java +++ b/annotations/src/main/java/org/hibernate/cfg/AnnotationConfiguration.java @@ -123,7 +123,6 @@ public class AnnotationConfiguration extends Configuration { private Set defaultNamedGenerators; private Map generatorTables; private Map> uniqueConstraintHoldersByTable; -// private Map> tableUniqueConstraints; private Map mappedByResolver; private Map propertyRefResolver; private Map anyMetaDefs; @@ -146,10 +145,30 @@ public class AnnotationConfiguration extends Configuration { super( sf ); } + /** + * Takes the list of entities annotated with {@code @Entity} or {@code @MappedSuperclass} and returns them in an + * ordered list. + * + * @param original The list of all entities annotated with {@code @Entity} or {@code @MappedSuperclass} + * @return Ordered list of entities including superclasses for entities which have any. Class hierachies are + * listed bottom up (starting from the top level base class). There is no indication in the list when a new class + * (hierarchy) starts. + */ protected List orderAndFillHierarchy(List original) { - //TODO remove embeddable List copy = new ArrayList( original ); - //for each class, copy all the relevant hierarchy + insertMappedSuperclasses( original, copy ); + + // order the hierarchy + List workingCopy = new ArrayList( copy ); + List newList = new ArrayList( copy.size() ); + while ( workingCopy.size() > 0 ) { + XClass clazz = workingCopy.get( 0 ); + orderHierarchy( workingCopy, newList, copy, clazz ); + } + return newList; + } + + private void insertMappedSuperclasses(List original, List copy) { for ( XClass clazz : original ) { XClass superClass = clazz.getSuperclass(); while ( superClass != null && !reflectionManager.equals( superClass, Object.class ) && !copy.contains( @@ -162,13 +181,6 @@ public class AnnotationConfiguration extends Configuration { superClass = superClass.getSuperclass(); } } - List workingCopy = new ArrayList( copy ); - List newList = new ArrayList( copy.size() ); - while ( workingCopy.size() > 0 ) { - XClass clazz = workingCopy.get( 0 ); - orderHierarchy( workingCopy, newList, copy, clazz ); - } - return newList; } private void orderHierarchy(List copy, List newList, List original, XClass clazz) { @@ -598,6 +610,7 @@ public class AnnotationConfiguration extends Configuration { orderedClasses, reflectionManager ); ExtendedMappings mappings = createExtendedMappings(); + for ( XClass clazz : orderedClasses ) { //todo use the same extended mapping AnnotationBinder.bindClass( clazz, inheritanceStatePerClass, mappings ); @@ -1166,20 +1179,6 @@ public class AnnotationConfiguration extends Configuration { } protected class ExtendedMappingsImpl extends MappingsImpl implements ExtendedMappings { -// private final Map namedGenerators; -// private final Map> joins; -// private final Map classTypes; -// private final Map generatorTables; -// private final Map> tableUniqueConstraints; -// private final Map mappedByResolver; -// private final Map propertyRefResolver; -// private final ReflectionManager reflectionManager; -// private final Set defaultNamedQueryNames; -// private final Set defaultNamedNativeQueryNames; -// private final Set defaultSqlResulSetMappingNames; -// private final Set defaultNamedGenerators; -// private final Map anyMetaDefs; - public void addDefaultGenerator(IdGenerator generator) { this.addGenerator( generator ); defaultNamedGenerators.add( generator.getName() ); diff --git a/annotations/src/main/java/org/hibernate/cfg/BinderHelper.java b/annotations/src/main/java/org/hibernate/cfg/BinderHelper.java index 44abc2bdd5..73c322c92c 100644 --- a/annotations/src/main/java/org/hibernate/cfg/BinderHelper.java +++ b/annotations/src/main/java/org/hibernate/cfg/BinderHelper.java @@ -591,7 +591,7 @@ public class BinderHelper { "Declaring class is not found in the inheritance state hierarchy: " + declaringClass ); } - if ( inheritanceState.isEmbeddableSuperclass ) { + if ( inheritanceState.isEmbeddableSuperclass() ) { retrieve = true; } } diff --git a/annotations/src/main/java/org/hibernate/cfg/ClassPropertyHolder.java b/annotations/src/main/java/org/hibernate/cfg/ClassPropertyHolder.java index 2e89fc0e78..8dd224fa41 100644 --- a/annotations/src/main/java/org/hibernate/cfg/ClassPropertyHolder.java +++ b/annotations/src/main/java/org/hibernate/cfg/ClassPropertyHolder.java @@ -113,7 +113,7 @@ public class ClassPropertyHolder extends AbstractPropertyHolder { "Declaring class is not found in the inheritance state hierarchy: " + declaringClass ); } - if ( inheritanceState.isEmbeddableSuperclass ) { + if ( inheritanceState.isEmbeddableSuperclass() ) { persistentClass.addMappedsuperclassProperty(prop); addPropertyToMappedSuperclass( prop, declaringClass ); } @@ -141,7 +141,7 @@ public class ClassPropertyHolder extends AbstractPropertyHolder { "Declaring class is not found in the inheritance state hierarchy: " + declaringClass ); } - if ( inheritanceState.isEmbeddableSuperclass ) { + if ( inheritanceState.isEmbeddableSuperclass() ) { join.addMappedsuperclassProperty(prop); addPropertyToMappedSuperclass( prop, declaringClass ); } diff --git a/annotations/src/main/java/org/hibernate/cfg/InheritanceState.java b/annotations/src/main/java/org/hibernate/cfg/InheritanceState.java index 534041b101..65cbfd03f4 100644 --- a/annotations/src/main/java/org/hibernate/cfg/InheritanceState.java +++ b/annotations/src/main/java/org/hibernate/cfg/InheritanceState.java @@ -33,56 +33,58 @@ import org.hibernate.annotations.common.reflection.XAnnotatedElement; import org.hibernate.annotations.common.reflection.XClass; /** - * Some extra data to the inheritance position of a class + * Some extra data to the inheritance position of a class. * * @author Emmanuel Bernard */ public class InheritanceState { public InheritanceState(XClass clazz) { - this.clazz = clazz; + this.setClazz( clazz ); extractInheritanceType(); } - public XClass clazz; + private XClass clazz; + /** - * has son either mappedsuperclass son or entity son + * Has sibling (either mappedsuperclass entity) */ - public boolean hasSons = false; + private boolean hasSiblings = false; + /** * a mother entity is available */ - public boolean hasParents = false; - public InheritanceType type; - public boolean isEmbeddableSuperclass = false; + private boolean hasParents = false; + private InheritanceType type; + private boolean isEmbeddableSuperclass = false; /** * only defined on embedded superclasses */ - public String accessType = null; - public Boolean isPropertyAnnotated; + private String accessType = null; + private Boolean isPropertyAnnotated; private void extractInheritanceType() { - XAnnotatedElement element = clazz; + XAnnotatedElement element = getClazz(); Inheritance inhAnn = element.getAnnotation( Inheritance.class ); MappedSuperclass mappedSuperClass = element.getAnnotation( MappedSuperclass.class ); if ( mappedSuperClass != null ) { - isEmbeddableSuperclass = true; - type = inhAnn == null ? null : inhAnn.strategy(); + setEmbeddableSuperclass( true ); + setType( inhAnn == null ? null : inhAnn.strategy() ); } else { - type = inhAnn == null ? InheritanceType.SINGLE_TABLE : inhAnn.strategy(); + setType( inhAnn == null ? InheritanceType.SINGLE_TABLE : inhAnn.strategy() ); } } boolean hasTable() { - return !hasParents || !InheritanceType.SINGLE_TABLE.equals( type ); + return !hasParents() || !InheritanceType.SINGLE_TABLE.equals( getType() ); } boolean hasDenormalizedTable() { - return hasParents && InheritanceType.TABLE_PER_CLASS.equals( type ); + return hasParents() && InheritanceType.TABLE_PER_CLASS.equals( getType() ); } - public static InheritanceState getSuperEntityInheritanceState( + public static InheritanceState getInheritanceStateOfSuperEntity( XClass clazz, Map states, ReflectionManager reflectionManager ) { @@ -90,7 +92,9 @@ public class InheritanceState { do { superclass = superclass.getSuperclass(); InheritanceState currentState = states.get( superclass ); - if ( currentState != null && !currentState.isEmbeddableSuperclass ) return currentState; + if ( currentState != null && !currentState.isEmbeddableSuperclass() ) { + return currentState; + } } while ( superclass != null && !reflectionManager.equals( superclass, Object.class ) ); return null; @@ -109,4 +113,60 @@ public class InheritanceState { while ( superclass != null && !reflectionManager.equals( superclass, Object.class ) ); return null; } + + public XClass getClazz() { + return clazz; + } + + public void setClazz(XClass clazz) { + this.clazz = clazz; + } + + public boolean hasSiblings() { + return hasSiblings; + } + + public void setHasSiblings(boolean hasSiblings) { + this.hasSiblings = hasSiblings; + } + + public boolean hasParents() { + return hasParents; + } + + public void setHasParents(boolean hasParents) { + this.hasParents = hasParents; + } + + public InheritanceType getType() { + return type; + } + + public void setType(InheritanceType type) { + this.type = type; + } + + public boolean isEmbeddableSuperclass() { + return isEmbeddableSuperclass; + } + + public void setEmbeddableSuperclass(boolean embeddableSuperclass) { + isEmbeddableSuperclass = embeddableSuperclass; + } + + public String getAccessType() { + return accessType; + } + + public void setAccessType(String accessType) { + this.accessType = accessType; + } + + public Boolean isPropertyAnnotated() { + return isPropertyAnnotated; + } + + public void setPropertyAnnotated(Boolean propertyAnnotated) { + isPropertyAnnotated = propertyAnnotated; + } } diff --git a/annotations/src/main/java/org/hibernate/cfg/annotations/EntityBinder.java b/annotations/src/main/java/org/hibernate/cfg/annotations/EntityBinder.java index 4ecb688cd2..248b10a718 100644 --- a/annotations/src/main/java/org/hibernate/cfg/annotations/EntityBinder.java +++ b/annotations/src/main/java/org/hibernate/cfg/annotations/EntityBinder.java @@ -294,7 +294,7 @@ public class EntityBinder { persistentClass.addTuplizer( mode, tuplizer.impl().getName() ); } - if ( !inheritanceState.hasParents ) { + if ( !inheritanceState.hasParents() ) { for ( Map.Entry filter : filters.entrySet() ) { String filterName = filter.getKey(); String cond = filter.getValue(); diff --git a/annotations/src/test/java/org/hibernate/test/annotations/access/AccessTest.java b/annotations/src/test/java/org/hibernate/test/annotations/access/AccessTest.java index 3de3407e84..c73076b3ef 100644 --- a/annotations/src/test/java/org/hibernate/test/annotations/access/AccessTest.java +++ b/annotations/src/test/java/org/hibernate/test/annotations/access/AccessTest.java @@ -9,7 +9,7 @@ import org.hibernate.test.annotations.TestCase; * @author Emmanuel Bernard */ public class AccessTest extends TestCase { - + public void testSuperclassOverriding() throws Exception { Furniture fur = new Furniture(); fur.setColor( "Black" ); @@ -21,7 +21,7 @@ public class AccessTest extends TestCase { tx.commit(); s.clear(); tx = s.beginTransaction(); - fur = (Furniture) s.get( Furniture.class, fur.getId() ); + fur = ( Furniture ) s.get( Furniture.class, fur.getId() ); assertFalse( fur.isAlive ); assertNotNull( fur.getColor() ); s.delete( fur ); @@ -38,7 +38,7 @@ public class AccessTest extends TestCase { tx.commit(); s.clear(); tx = s.beginTransaction(); - fur = (Furniture) s.get( Furniture.class, fur.getId() ); + fur = ( Furniture ) s.get( Furniture.class, fur.getId() ); assertNotNull( fur.getGod() ); s.delete( fur ); tx.commit(); @@ -54,12 +54,11 @@ public class AccessTest extends TestCase { tx.commit(); s.clear(); tx = s.beginTransaction(); - fur = (Furniture) s.get( Furniture.class, fur.getId() ); + fur = ( Furniture ) s.get( Furniture.class, fur.getId() ); assertEquals( 5, fur.weight ); s.delete( fur ); tx.commit(); s.close(); - } public void testNonOverridenSubclass() throws Exception { @@ -71,12 +70,11 @@ public class AccessTest extends TestCase { tx.commit(); s.clear(); tx = s.beginTransaction(); - chair = (Chair) s.get( Chair.class, chair.getId() ); + chair = ( Chair ) s.get( Chair.class, chair.getId() ); assertNull( chair.getPillow() ); s.delete( chair ); tx.commit(); s.close(); - } public void testOverridenSubclass() throws Exception { @@ -89,13 +87,12 @@ public class AccessTest extends TestCase { tx.commit(); s.clear(); tx = s.beginTransaction(); - bed = (BigBed) s.get( BigBed.class, bed.getId() ); + bed = ( BigBed ) s.get( BigBed.class, bed.getId() ); assertEquals( 5, bed.size ); assertNull( bed.getQuality() ); s.delete( bed ); tx.commit(); s.close(); - } public void testFieldsOverriding() throws Exception { @@ -107,22 +104,21 @@ public class AccessTest extends TestCase { tx.commit(); s.clear(); tx = s.beginTransaction(); - gs = (Gardenshed) s.get( Gardenshed.class, gs.getId() ); + gs = ( Gardenshed ) s.get( Gardenshed.class, gs.getId() ); assertEquals( 4, gs.floors ); assertEquals( 6, gs.getFloors() ); s.delete( gs ); tx.commit(); s.close(); - } protected Class[] getMappings() { - return new Class[]{ + return new Class[] { Bed.class, Chair.class, Furniture.class, BigBed.class, - Gardenshed.class + Gardenshed.class, }; } } diff --git a/annotations/src/test/java/org/hibernate/test/annotations/access/Furniture.java b/annotations/src/test/java/org/hibernate/test/annotations/access/Furniture.java index 9e8377ff06..a977a7ee0e 100644 --- a/annotations/src/test/java/org/hibernate/test/annotations/access/Furniture.java +++ b/annotations/src/test/java/org/hibernate/test/annotations/access/Furniture.java @@ -37,7 +37,6 @@ public class Furniture extends Woody { this.id = id; } - @AccessType("property") public long weight; diff --git a/annotations/src/test/java/org/hibernate/test/annotations/embedded/Country.java b/annotations/src/test/java/org/hibernate/test/annotations/embedded/Country.java index a4569acdfe..4a94c35ce9 100644 --- a/annotations/src/test/java/org/hibernate/test/annotations/embedded/Country.java +++ b/annotations/src/test/java/org/hibernate/test/annotations/embedded/Country.java @@ -13,7 +13,6 @@ import org.hibernate.annotations.AccessType; * @author Emmanuel Bernard */ @Embeddable -//access = AccessType.PROPERTY) @AccessType("property") public class Country implements Serializable { private String iso2; @@ -35,5 +34,4 @@ public class Country implements Serializable { public void setName(String name) { this.name = name; } - }