HHH-6114 Determining inheritance strategy and starting to process mapped properties
This commit is contained in:
parent
f27695b680
commit
78ad67cff6
|
@ -23,12 +23,11 @@
|
|||
*/
|
||||
package org.hibernate.metamodel.source.annotations;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.MappedSuperclass;
|
||||
import java.util.List;
|
||||
import javax.persistence.AccessType;
|
||||
|
||||
import org.jboss.jandex.AnnotationInstance;
|
||||
import org.jboss.jandex.ClassInfo;
|
||||
import org.jboss.jandex.DotName;
|
||||
|
||||
import org.hibernate.AnnotationException;
|
||||
|
||||
|
@ -39,19 +38,20 @@ import org.hibernate.AnnotationException;
|
|||
*/
|
||||
public class ConfiguredClass {
|
||||
private final ClassInfo classInfo;
|
||||
private final AccessType classAccessType;
|
||||
private final ConfiguredClassHierarchy hierarchy;
|
||||
private final boolean isMappedSuperClass;
|
||||
private final List<MappedProperty> mappedProperties;
|
||||
|
||||
public ConfiguredClass(ClassInfo info, ConfiguredClassHierarchy hierarchy) {
|
||||
this.classInfo = info;
|
||||
this.hierarchy = hierarchy;
|
||||
init();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
//@Entity and @MappedSuperclass on the same class leads to a NPE down the road
|
||||
AnnotationInstance jpaEntityAnnotation = JandexHelper.getSingleAnnotation( classInfo, JPADotNames.ENTITY );
|
||||
AnnotationInstance mappedSuperClassAnnotation = JandexHelper.getSingleAnnotation( classInfo, JPADotNames.MAPPED_SUPER_CLASS );
|
||||
AnnotationInstance hibernateEntityAnnotation = JandexHelper.getSingleAnnotation( classInfo, JPADotNames.HIBERNATE_ENTITY );
|
||||
AnnotationInstance mappedSuperClassAnnotation = JandexHelper.getSingleAnnotation(
|
||||
classInfo, JPADotNames.MAPPED_SUPER_CLASS
|
||||
);
|
||||
|
||||
if ( jpaEntityAnnotation != null && mappedSuperClassAnnotation != null ) {
|
||||
throw new AnnotationException(
|
||||
|
@ -60,13 +60,19 @@ public class ConfiguredClass {
|
|||
);
|
||||
}
|
||||
|
||||
|
||||
isMappedSuperClass = mappedSuperClassAnnotation != null;
|
||||
classAccessType = determineClassAccessType( hierarchy.getDefaultAccessType() );
|
||||
mappedProperties = collectMappedProperties();
|
||||
}
|
||||
|
||||
public ClassInfo getClassInfo() {
|
||||
return classInfo;
|
||||
}
|
||||
|
||||
public boolean isMappedSuperClass() {
|
||||
return isMappedSuperClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
|
@ -75,6 +81,22 @@ public class ConfiguredClass {
|
|||
sb.append( '}' );
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private AccessType determineClassAccessType(AccessType hierarchyAccessType) {
|
||||
// default to the hierarchy access type to start with
|
||||
AccessType accessType = hierarchyAccessType;
|
||||
|
||||
AnnotationInstance accessAnnotation = JandexHelper.getSingleAnnotation( classInfo, JPADotNames.ACCESS );
|
||||
if ( accessAnnotation != null ) {
|
||||
accessType = Enum.valueOf( AccessType.class, accessAnnotation.value( "value" ).asEnum() );
|
||||
}
|
||||
|
||||
return accessType;
|
||||
}
|
||||
|
||||
private List<MappedProperty> collectMappedProperties() {
|
||||
return null; //To change body of created methods use File | Settings | File Templates.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -66,8 +66,7 @@ public class ConfiguredClassHierarchy implements Iterable<ConfiguredClass> {
|
|||
/**
|
||||
* @return An iterator iterating in top down manner over the configured classes in this hierarchy.
|
||||
*/
|
||||
public Iterator<ConfiguredClass> iterator
|
||||
() {
|
||||
public Iterator<ConfiguredClass> iterator() {
|
||||
return configuredClasses.iterator();
|
||||
}
|
||||
|
||||
|
@ -97,28 +96,7 @@ public class ConfiguredClassHierarchy implements Iterable<ConfiguredClass> {
|
|||
if ( idAnnotations == null || idAnnotations.size() == 0 ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for ( AnnotationInstance annotation : idAnnotations ) {
|
||||
AccessType tmpAccessType;
|
||||
if ( annotation.target() instanceof FieldInfo ) {
|
||||
tmpAccessType = AccessType.FIELD;
|
||||
}
|
||||
else if ( annotation.target() instanceof MethodInfo ) {
|
||||
tmpAccessType = AccessType.PROPERTY;
|
||||
}
|
||||
else {
|
||||
throw new AnnotationException( "Invalid placement of @Id annotation" );
|
||||
}
|
||||
|
||||
if ( accessType == null ) {
|
||||
accessType = tmpAccessType;
|
||||
}
|
||||
else {
|
||||
if ( !accessType.equals( tmpAccessType ) ) {
|
||||
throw new AnnotationException( "Inconsistent placement of @Id annotation within hierarchy " + hierarchyListString() );
|
||||
}
|
||||
}
|
||||
}
|
||||
accessType = processIdAnnotations( idAnnotations );
|
||||
}
|
||||
|
||||
if ( accessType == null ) {
|
||||
|
@ -128,8 +106,71 @@ public class ConfiguredClassHierarchy implements Iterable<ConfiguredClass> {
|
|||
return accessType;
|
||||
}
|
||||
|
||||
private AccessType processIdAnnotations(List<AnnotationInstance> idAnnotations) {
|
||||
AccessType accessType = null;
|
||||
for ( AnnotationInstance annotation : idAnnotations ) {
|
||||
AccessType tmpAccessType;
|
||||
if ( annotation.target() instanceof FieldInfo ) {
|
||||
tmpAccessType = AccessType.FIELD;
|
||||
}
|
||||
else if ( annotation.target() instanceof MethodInfo ) {
|
||||
tmpAccessType = AccessType.PROPERTY;
|
||||
}
|
||||
else {
|
||||
throw new AnnotationException( "Invalid placement of @Id annotation" );
|
||||
}
|
||||
|
||||
if ( accessType == null ) {
|
||||
accessType = tmpAccessType;
|
||||
}
|
||||
else {
|
||||
if ( !accessType.equals( tmpAccessType ) ) {
|
||||
throw new AnnotationException( "Inconsistent placement of @Id annotation within hierarchy " + hierarchyListString() );
|
||||
}
|
||||
}
|
||||
}
|
||||
return accessType;
|
||||
}
|
||||
|
||||
private InheritanceType determineInheritanceType() {
|
||||
return null; //To change body of created methods use File | Settings | File Templates.
|
||||
Iterator<ConfiguredClass> iter = iterator();
|
||||
InheritanceType inheritanceType = null;
|
||||
while ( iter.hasNext() ) {
|
||||
ConfiguredClass configuredClass = iter.next();
|
||||
ClassInfo info = configuredClass.getClassInfo();
|
||||
AnnotationInstance inheritanceAnnotation = JandexHelper.getSingleAnnotation(
|
||||
info, JPADotNames.INHERITANCE
|
||||
);
|
||||
if ( inheritanceAnnotation == null ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
InheritanceType tmpInheritanceType = Enum.valueOf(
|
||||
InheritanceType.class, inheritanceAnnotation.value( "strategy" ).asEnum()
|
||||
);
|
||||
if ( tmpInheritanceType == null ) {
|
||||
// default inheritance type is single table
|
||||
inheritanceType = InheritanceType.SINGLE_TABLE;
|
||||
}
|
||||
|
||||
if ( inheritanceType == null ) {
|
||||
inheritanceType = tmpInheritanceType;
|
||||
}
|
||||
else {
|
||||
if ( !inheritanceType.equals( tmpInheritanceType ) ) {
|
||||
throw new AnnotationException(
|
||||
"Multiple incompatible instances of @Inheritance specified within hierarchy " + hierarchyListString()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( inheritanceType == null ) {
|
||||
// default inheritance type is single table
|
||||
inheritanceType = InheritanceType.SINGLE_TABLE;
|
||||
}
|
||||
|
||||
return inheritanceType;
|
||||
}
|
||||
|
||||
private AccessType throwIdNotFoundAnnotationException() {
|
||||
|
|
|
@ -23,8 +23,10 @@
|
|||
*/
|
||||
package org.hibernate.metamodel.source.annotations;
|
||||
|
||||
import javax.persistence.Access;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Inheritance;
|
||||
import javax.persistence.MappedSuperclass;
|
||||
|
||||
import org.jboss.jandex.DotName;
|
||||
|
@ -39,8 +41,10 @@ public interface JPADotNames {
|
|||
public static final DotName HIBERNATE_ENTITY = DotName.createSimple( org.hibernate.annotations.Entity.class.getName() );
|
||||
public static final DotName MAPPED_SUPER_CLASS = DotName.createSimple( MappedSuperclass.class.getName() );
|
||||
|
||||
public static final DotName ID = DotName.createSimple( Id.class.getName() );
|
||||
public static final DotName INHERITANCE = DotName.createSimple( Inheritance.class.getName() );
|
||||
public static final DotName ACCESS = DotName.createSimple( Access.class.getName() );
|
||||
|
||||
public static final DotName ID = DotName.createSimple( Id.class.getName() );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,3 +1,26 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.metamodel.source.annotations;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -9,6 +32,8 @@ import org.jboss.jandex.DotName;
|
|||
import org.hibernate.AssertionFailure;
|
||||
|
||||
/**
|
||||
* Utility methods for working with the jandex annotation index.
|
||||
*
|
||||
* @author Hardy Ferentschik
|
||||
*/
|
||||
public class JandexHelper {
|
||||
|
@ -34,7 +59,9 @@ public class JandexHelper {
|
|||
}
|
||||
else {
|
||||
throw new AssertionFailure(
|
||||
"There should be only one annotation of type " + annotationName + " defined on" + classInfo.name()
|
||||
"Found more than one instance of the annotation "
|
||||
+ annotationList.get( 0 ).name().toString()
|
||||
+ ". Expected was one."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.metamodel.source.annotations;
|
||||
|
||||
/**
|
||||
* Represent a mapped property (explicitly or implicitly mapped).
|
||||
*
|
||||
* @author Hardy Ferentschik
|
||||
*/
|
||||
public class MappedProperty {
|
||||
}
|
||||
|
||||
|
|
@ -8,6 +8,8 @@ import javax.persistence.AccessType;
|
|||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Inheritance;
|
||||
import javax.persistence.InheritanceType;
|
||||
import javax.persistence.MappedSuperclass;
|
||||
|
||||
import org.jboss.jandex.ClassInfo;
|
||||
|
@ -175,6 +177,72 @@ public class ConfiguredClassHierarchyBuilderTest extends BaseUnitTestCase {
|
|||
assertEquals( "Wrong default access type", AccessType.PROPERTY, hierarchy.getDefaultAccessType() );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefaultInheritanceStrategy() {
|
||||
@Entity
|
||||
class A {
|
||||
@Id
|
||||
String id;
|
||||
}
|
||||
|
||||
@Entity
|
||||
class B extends A {
|
||||
}
|
||||
|
||||
Index index = indexForClass( B.class, A.class );
|
||||
ConfiguredClassHierarchyBuilder builder = new ConfiguredClassHierarchyBuilder();
|
||||
Set<ConfiguredClassHierarchy> hierarchies = builder.createEntityHierarchies( index );
|
||||
assertTrue( hierarchies.size() == 1 );
|
||||
ConfiguredClassHierarchy hierarchy = hierarchies.iterator().next();
|
||||
assertEquals( "Wrong inheritance type", InheritanceType.SINGLE_TABLE, hierarchy.getInheritanceType() );
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testExplicitInheritanceStrategy() {
|
||||
@MappedSuperclass
|
||||
class MappedSuperClass {
|
||||
|
||||
}
|
||||
|
||||
@Entity
|
||||
@Inheritance(strategy = InheritanceType.JOINED)
|
||||
class A extends MappedSuperClass {
|
||||
@Id
|
||||
String id;
|
||||
}
|
||||
|
||||
@Entity
|
||||
class B extends A {
|
||||
}
|
||||
|
||||
Index index = indexForClass( B.class, MappedSuperClass.class, A.class );
|
||||
ConfiguredClassHierarchyBuilder builder = new ConfiguredClassHierarchyBuilder();
|
||||
Set<ConfiguredClassHierarchy> hierarchies = builder.createEntityHierarchies( index );
|
||||
assertTrue( hierarchies.size() == 1 );
|
||||
ConfiguredClassHierarchy hierarchy = hierarchies.iterator().next();
|
||||
assertEquals( "Wrong inheritance type", InheritanceType.JOINED, hierarchy.getInheritanceType() );
|
||||
}
|
||||
|
||||
@Test(expected = AnnotationException.class)
|
||||
public void testMultipleConflictingInheritanceDefinitions() {
|
||||
|
||||
@Entity
|
||||
@Inheritance(strategy = InheritanceType.JOINED)
|
||||
class A {
|
||||
String id;
|
||||
}
|
||||
|
||||
@Entity
|
||||
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
|
||||
class B extends A {
|
||||
}
|
||||
|
||||
Index index = indexForClass( B.class, A.class );
|
||||
ConfiguredClassHierarchyBuilder builder = new ConfiguredClassHierarchyBuilder();
|
||||
builder.createEntityHierarchies( index );
|
||||
}
|
||||
|
||||
private Index indexForClass(Class<?>... classes) {
|
||||
Indexer indexer = new Indexer();
|
||||
for ( Class<?> clazz : classes ) {
|
||||
|
|
Loading…
Reference in New Issue