HHH-6109 Starting the implementation of a replacement for InheritanceState. The determined mapped classes need to be pre-processed

in order to detmerine inheritance features, default access types, etc
This commit is contained in:
Hardy Ferentschik 2011-04-01 18:02:07 +02:00
parent 42502e696b
commit 297c703449
15 changed files with 516 additions and 154 deletions

View File

@ -30,20 +30,22 @@ manifest.mainAttributes(
'Main-Class': 'org.hibernate.Version'
)
sourceSets {
test {
// resources inherently exclude sources
resources {
setSrcDirs( ['src/test/java','src/test/resources'] )
}
}
sourceSets.main {
originalJavaSrcDirs = java.srcDirs
jaxbTargetDir = file( "${buildDir}/generated-src/jaxb" )
java.srcDir jaxbTargetDir
}
// resources inherently exclude sources
sourceSets.test.resources {
setSrcDirs( ['src/test/java','src/test/resources'] )
}
ideaModule {
sourceDirs.add( file( '$buildDir/generated-src/antlr/main' ) )
}
task jaxb << {
jaxbTargetDir = file( "${buildDir}/generated-src/jaxb" )
jaxbTargetDir.mkdirs()

View File

@ -21,14 +21,10 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
// $Id$
package org.hibernate.cfg;
/**
* Enum defining deifferent access strategies for accessing entity values.
* Enum defining different access strategies for accessing entity values.
*
* @author Hardy Ferentschik
*/

View File

@ -24,18 +24,14 @@
package org.hibernate.metamodel.source.annotations;
import java.util.Iterator;
import java.util.List;
import javax.persistence.MappedSuperclass;
import java.util.Set;
import org.jboss.jandex.AnnotationInstance;
import org.jboss.jandex.ClassInfo;
import org.jboss.jandex.DotName;
import org.jboss.jandex.Index;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.hibernate.AnnotationException;
import org.hibernate.AssertionFailure;
import org.hibernate.metamodel.source.Metadata;
/**
@ -48,10 +44,6 @@ import org.hibernate.metamodel.source.Metadata;
* @todo The annotation index should really be passed at construction time
*/
public class AnnotationBinder {
public static final DotName ENTITY = DotName.createSimple( Entity.class.getName() );
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() );
private static final Logger log = LoggerFactory.getLogger( AnnotationBinder.class );
private final Metadata metadata;
@ -61,33 +53,30 @@ public class AnnotationBinder {
public void bindMappedClasses(Index annotationIndex) {
// need to order our annotated entities into an order we can process
EntityHierarchyBuilder builder = new EntityHierarchyBuilder();
List<EntityHierarchy> hierarchies = builder.createEntityHierarchies( annotationIndex );
ConfiguredClassHierarchyBuilder builder = new ConfiguredClassHierarchyBuilder();
Set<ConfiguredClassHierarchy> hierarchies = builder.createEntityHierarchies( annotationIndex );
// now we process each hierarchy one at the time
for ( EntityHierarchy hierarchy : hierarchies ) {
Iterator<Entity> iter = hierarchy.iterator();
for ( ConfiguredClassHierarchy hierarchy : hierarchies ) {
Iterator<ConfiguredClass> iter = hierarchy.iterator();
while ( iter.hasNext() ) {
Entity entity = iter.next();
ConfiguredClass entity = iter.next();
bindEntity( entity );
}
}
}
public void bindEntity(Entity entity) {
public void bindEntity(ConfiguredClass entity) {
ClassInfo classInfo = entity.getClassInfo();
//@Entity and @MappedSuperclass on the same class leads to a NPE down the road
AnnotationInstance jpaEntityAnnotation = getSingleAnnotation( classInfo, ENTITY );
AnnotationInstance mappedSuperClassAnnotation = getSingleAnnotation( classInfo, MAPPED_SUPER_CLASS );
AnnotationInstance hibernateEntityAnnotation = getSingleAnnotation( classInfo, HIBERNATE_ENTITY );
if ( jpaEntityAnnotation != null && mappedSuperClassAnnotation != null ) {
throw new AnnotationException(
"An entity cannot be annotated with both @Entity and @MappedSuperclass: "
+ classInfo.name().toString()
);
}
AnnotationInstance jpaEntityAnnotation = JandexHelper.getSingleAnnotation( classInfo, ConfiguredClass.ENTITY );
AnnotationInstance mappedSuperClassAnnotation = JandexHelper.getSingleAnnotation(
classInfo, ConfiguredClass.MAPPED_SUPER_CLASS
);
AnnotationInstance hibernateEntityAnnotation = JandexHelper.getSingleAnnotation(
classInfo, ConfiguredClass.HIBERNATE_ENTITY
);
// //TODO: be more strict with secondarytable allowance (not for ids, not for secondary table join columns etc)
@ -307,30 +296,6 @@ public class AnnotationBinder {
// entityBinder.processComplementaryTableDefinitions( clazzToProcess.getAnnotation( org.hibernate.annotations.Table.class ) );
// entityBinder.processComplementaryTableDefinitions( clazzToProcess.getAnnotation( org.hibernate.annotations.Tables.class ) );
}
/**
* @param classInfo the class info from which to retrieve the annotation instance
* @param annotationName the annotation to retrieve from the class info
*
* @return the single annotation defined on the class or {@code null} in case the annotation is not specified at all
*
* @throws AssertionFailure in case there is
*/
private AnnotationInstance getSingleAnnotation(ClassInfo classInfo, DotName annotationName)
throws AssertionFailure {
List<AnnotationInstance> annotationList = classInfo.annotations().get( annotationName );
if ( annotationList == null ) {
return null;
}
else if ( annotationList.size() == 1 ) {
return annotationList.get( 0 );
}
else {
throw new AssertionFailure(
"There should be only one annotation of type " + annotationName + " defined on" + classInfo.name()
);
}
}
}

View File

@ -0,0 +1,84 @@
/*
* 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 javax.persistence.Entity;
import javax.persistence.MappedSuperclass;
import org.jboss.jandex.AnnotationInstance;
import org.jboss.jandex.ClassInfo;
import org.jboss.jandex.DotName;
import org.hibernate.AnnotationException;
/**
* Represents an entity, mapped superclass or component configured via annotations/xml.
*
* @author Hardy Ferentschik
*/
public class ConfiguredClass {
public static final DotName ENTITY = DotName.createSimple( Entity.class.getName() );
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() );
private final ClassInfo classInfo;
private final ConfiguredClassHierarchy hierarchy;
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, ENTITY );
AnnotationInstance mappedSuperClassAnnotation = JandexHelper.getSingleAnnotation( classInfo, MAPPED_SUPER_CLASS );
AnnotationInstance hibernateEntityAnnotation = JandexHelper.getSingleAnnotation( classInfo, HIBERNATE_ENTITY );
if ( jpaEntityAnnotation != null && mappedSuperClassAnnotation != null ) {
throw new AnnotationException(
"An entity cannot be annotated with both @Entity and @MappedSuperclass: "
+ classInfo.name().toString()
);
}
}
public ClassInfo getClassInfo() {
return classInfo;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append( "ConfiguredClass" );
sb.append( "{classInfo=" ).append( classInfo );
sb.append( '}' );
return sb.toString();
}
}

View File

@ -23,16 +23,47 @@
*/
package org.hibernate.metamodel.source.annotations;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.jboss.jandex.ClassInfo;
import org.hibernate.cfg.AccessType;
/**
* @author Hardy Ferentschik
*/
public class EntityHierarchy implements Iterable<Entity> {
@Override
public Iterator<Entity> iterator() {
public class ConfiguredClassHierarchy implements Iterable<ConfiguredClass> {
private final AccessType defaultAccessType;
private final List<ConfiguredClass> configuredClasses;
ConfiguredClassHierarchy(List<ClassInfo> classes) {
configuredClasses = new ArrayList<ConfiguredClass>();
for ( ClassInfo info : classes ) {
configuredClasses.add( new ConfiguredClass( info, this ) );
}
defaultAccessType = determineDefaultAccessType();
}
private AccessType determineDefaultAccessType() {
return null;
}
@Override
public Iterator<ConfiguredClass> iterator() {
return configuredClasses.iterator();
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append( "ConfiguredClassHierarchy" );
sb.append( "{defaultAccessType=" ).append( defaultAccessType );
sb.append( ", configuredClasses=" ).append( configuredClasses );
sb.append( '}' );
return sb.toString();
}
}

View File

@ -0,0 +1,112 @@
/*
* 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.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.jboss.jandex.ClassInfo;
import org.jboss.jandex.DotName;
import org.jboss.jandex.Index;
import org.hibernate.internal.util.ReflectHelper;
/**
* Given a annotation index build a list of class hierarchies.
*
* @author Hardy Ferentschik
*/
public class ConfiguredClassHierarchyBuilder {
public Set<ConfiguredClassHierarchy> createEntityHierarchies(Index index) {
Map<ClassInfo, List<ClassInfo>> processedClassInfos = new HashMap<ClassInfo, List<ClassInfo>>();
for ( ClassInfo info : index.getKnownClasses() ) {
if ( processedClassInfos.containsKey( info ) ) {
continue;
}
List<ClassInfo> configuredClassList = new ArrayList<ClassInfo>();
ClassInfo tmpClassInfo = info;
Class<?> clazz = classForName( tmpClassInfo );
while ( clazz != null && !clazz.equals( Object.class ) ) {
tmpClassInfo = index.getClassByName( DotName.createSimple( clazz.getName() ) );
clazz = clazz.getSuperclass();
if ( tmpClassInfo == null ) {
continue;
}
if ( existsHierarchyWithClassInfoAsLeaf( processedClassInfos, tmpClassInfo ) ) {
List<ClassInfo> classInfoList = processedClassInfos.get( tmpClassInfo );
for ( ClassInfo tmpInfo : configuredClassList ) {
classInfoList.add( tmpInfo );
processedClassInfos.put( tmpInfo, classInfoList );
}
break;
}
else {
configuredClassList.add( 0, tmpClassInfo );
processedClassInfos.put( tmpClassInfo, configuredClassList );
}
}
}
Set<ConfiguredClassHierarchy> hierarchies = new HashSet<ConfiguredClassHierarchy>();
List<List<ClassInfo>> processedList = new ArrayList<List<ClassInfo>>();
for ( List<ClassInfo> classInfoList : processedClassInfos.values() ) {
if ( !processedList.contains( classInfoList ) ) {
hierarchies.add( new ConfiguredClassHierarchy( classInfoList ) );
processedList.add( classInfoList );
}
}
return hierarchies;
}
private boolean existsHierarchyWithClassInfoAsLeaf(Map<ClassInfo, List<ClassInfo>> processedClassInfos, ClassInfo tmpClassInfo) {
if ( !processedClassInfos.containsKey( tmpClassInfo ) ) {
return false;
}
List<ClassInfo> classInfoList = processedClassInfos.get( tmpClassInfo );
return classInfoList.get( classInfoList.size() - 1 ).equals( tmpClassInfo );
}
private Class<?> classForName(ClassInfo info) {
Class<?> clazz = null;
try {
clazz = ReflectHelper.classForName( info.toString() );
}
catch ( ClassNotFoundException e ) {
// todo what to do here!?i
}
return clazz;
}
}

View File

@ -1,41 +0,0 @@
/*
* 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 org.jboss.jandex.ClassInfo;
/**
* Represents an entity or mapped superclass which needs to be mapped.
*
* @author Hardy Ferentschik
*/
public class Entity {
private ClassInfo classInfo;
public ClassInfo getClassInfo() {
return classInfo;
}
}

View File

@ -1,22 +0,0 @@
package org.hibernate.metamodel.source.annotations;
import java.util.ArrayList;
import java.util.List;
import org.jboss.jandex.Index;
/**
* Given a annotation index build a list of entity hierarchies.
*
* @author Hardy Ferentschik
*/
public class EntityHierarchyBuilder {
public List<EntityHierarchy> createEntityHierarchies(Index index) {
List<EntityHierarchy> hierarchies = new ArrayList<EntityHierarchy>();
return hierarchies;
}
}

View File

@ -0,0 +1,43 @@
package org.hibernate.metamodel.source.annotations;
import java.util.List;
import org.jboss.jandex.AnnotationInstance;
import org.jboss.jandex.ClassInfo;
import org.jboss.jandex.DotName;
import org.hibernate.AssertionFailure;
/**
* @author Hardy Ferentschik
*/
public class JandexHelper {
private JandexHelper() {
}
/**
* @param classInfo the class info from which to retrieve the annotation instance
* @param annotationName the annotation to retrieve from the class info
*
* @return the single annotation defined on the class or {@code null} in case the annotation is not specified at all
*
* @throws org.hibernate.AssertionFailure in case there is
*/
static public AnnotationInstance getSingleAnnotation(ClassInfo classInfo, DotName annotationName)
throws AssertionFailure {
List<AnnotationInstance> annotationList = classInfo.annotations().get( annotationName );
if ( annotationList == null ) {
return null;
}
else if ( annotationList.size() == 1 ) {
return annotationList.get( 0 );
}
else {
throw new AssertionFailure(
"There should be only one annotation of type " + annotationName + " defined on" + classInfo.name()
);
}
}
}

View File

@ -4,7 +4,6 @@ import java.io.InputStream;
import java.net.URL;
import java.util.HashSet;
import java.util.Set;
import javax.validation.ValidationException;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
@ -18,6 +17,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.SAXException;
import org.hibernate.AnnotationException;
import org.hibernate.metamodel.source.xml.EntityMappings;
/**
@ -26,7 +26,8 @@ import org.hibernate.metamodel.source.xml.EntityMappings;
*/
public class OrmXmlParser {
private static final Logger log = LoggerFactory.getLogger( OrmXmlParser.class );
private static final String ORM_MAPPING_XSD = "org/hibernate/ejb/orm_2_0.xsd";
private static final String ORM1_MAPPING_XSD = "org/hibernate/ejb/orm_1_0.xsd";
private static final String ORM2_MAPPING_XSD = "org/hibernate/ejb/orm_2_0.xsd";
/**
* Parses the given xml configuration files and returns a updated annotation index
@ -40,12 +41,26 @@ public class OrmXmlParser {
Set<InputStream> mappingStreams = new HashSet<InputStream>();
for ( String fileName : mappingFileNames ) {
mappingStreams.add( getInputStreamForPath( fileName ) );
}
for ( InputStream in : mappingStreams ) {
EntityMappings entityMappings = getEntityMappings( in );
// ...
Schema schema = getMappingSchema( ORM2_MAPPING_XSD );
InputStream in = getInputStreamForPath( fileName );
EntityMappings entityMappings;
try {
entityMappings = unmarshallXml( in, schema );
}
catch ( JAXBException orm2Exception ) {
// if we cannot parse against orm_2_0.xsd we try orm_1_0.xsd for backwards compatibility
try {
schema = getMappingSchema( ORM1_MAPPING_XSD );
in = getInputStreamForPath( fileName );
entityMappings = unmarshallXml( in, schema );
}
catch ( JAXBException orm1Exception ) {
throw new AnnotationException( "Unable to parse xml configuration.", orm1Exception );
}
}
// ..
}
return null;
@ -62,35 +77,27 @@ public class OrmXmlParser {
return inputStream;
}
private EntityMappings getEntityMappings(InputStream in) {
private EntityMappings unmarshallXml(InputStream in, Schema schema) throws JAXBException {
EntityMappings entityMappings;
Schema schema = getMappingSchema();
try {
JAXBContext jc = JAXBContext.newInstance( EntityMappings.class );
Unmarshaller unmarshaller = jc.createUnmarshaller();
unmarshaller.setSchema( schema );
StreamSource stream = new StreamSource( in );
JAXBElement<EntityMappings> root = unmarshaller.unmarshal( stream, EntityMappings.class );
entityMappings = root.getValue();
}
catch ( JAXBException e ) {
String msg = "Error parsing mapping file.";
log.error( msg );
throw new ValidationException( msg, e );
}
JAXBContext jc = JAXBContext.newInstance( EntityMappings.class );
Unmarshaller unmarshaller = jc.createUnmarshaller();
unmarshaller.setSchema( schema );
StreamSource stream = new StreamSource( in );
JAXBElement<EntityMappings> root = unmarshaller.unmarshal( stream, EntityMappings.class );
entityMappings = root.getValue();
return entityMappings;
}
private Schema getMappingSchema() {
private Schema getMappingSchema(String schemaVersion) {
ClassLoader loader = OrmXmlParser.class.getClassLoader();
URL schemaUrl = loader.getResource( ORM_MAPPING_XSD );
URL schemaUrl = loader.getResource( schemaVersion );
SchemaFactory sf = SchemaFactory.newInstance( javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI );
Schema schema = null;
try {
schema = sf.newSchema( schemaUrl );
}
catch ( SAXException e ) {
log.debug( "Unable to create schema for {}: {}", ORM_MAPPING_XSD, e.getMessage() );
log.debug( "Unable to create schema for {}: {}", ORM2_MAPPING_XSD, e.getMessage() );
}
return schema;
}

View File

@ -42,7 +42,7 @@ import static org.junit.Assert.fail;
*/
public class BasicAnnotationBindingTests extends AbstractBasicBindingTests {
//@FailureExpected(jiraKey = "HHH-5672", message = "Work in progress")
@FailureExpected(jiraKey = "HHH-5672", message = "Work in progress")
@Test
public void testSimpleEntityMapping() {
super.testSimpleEntityMapping();

View File

@ -0,0 +1,148 @@
package org.hibernate.metamodel.source.annotations;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
import java.util.Set;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
import org.jboss.jandex.ClassInfo;
import org.jboss.jandex.DotName;
import org.jboss.jandex.Index;
import org.jboss.jandex.Indexer;
import org.junit.Test;
import org.hibernate.AnnotationException;
import org.hibernate.testing.junit4.BaseUnitTestCase;
import static junit.framework.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.fail;
/**
* @author Hardy Ferentschik
*/
public class ConfiguredClassHierarchyBuilderTest extends BaseUnitTestCase {
@Test
public void testSingleEntity() {
Index index = indexForClass( Foo.class );
ConfiguredClassHierarchyBuilder builder = new ConfiguredClassHierarchyBuilder();
Set<ConfiguredClassHierarchy> hierarchies = builder.createEntityHierarchies( index );
assertEquals( "There should be only one hierarchy", 1, hierarchies.size() );
Iterator<ConfiguredClass> iter = hierarchies.iterator().next().iterator();
ClassInfo info = iter.next().getClassInfo();
assertEquals( "wrong class", DotName.createSimple( Foo.class.getName() ), info.name() );
assertFalse( iter.hasNext() );
}
@Test
public void testSimpleInheritance() {
Index index = indexForClass( B.class, A.class );
ConfiguredClassHierarchyBuilder builder = new ConfiguredClassHierarchyBuilder();
Set<ConfiguredClassHierarchy> hierarchies = builder.createEntityHierarchies( index );
assertEquals( "There should be only one hierarchy", 1, hierarchies.size() );
Iterator<ConfiguredClass> iter = hierarchies.iterator().next().iterator();
ClassInfo info = iter.next().getClassInfo();
assertEquals( "wrong class", DotName.createSimple( A.class.getName() ), info.name() );
info = iter.next().getClassInfo();
assertEquals( "wrong class", DotName.createSimple( B.class.getName() ), info.name() );
assertFalse( iter.hasNext() );
}
@Test
public void testMultipleHierarchies() {
Index index = indexForClass( B.class, A.class, Foo.class );
ConfiguredClassHierarchyBuilder builder = new ConfiguredClassHierarchyBuilder();
Set<ConfiguredClassHierarchy> hierarchies = builder.createEntityHierarchies( index );
assertEquals( "There should be only one hierarchy", 2, hierarchies.size() );
}
@Test
public void testMappedSuperClass() {
Index index = indexForClass( MappedSubClass.class, MappedSuperClass.class, UnmappedSubClass.class );
ConfiguredClassHierarchyBuilder builder = new ConfiguredClassHierarchyBuilder();
Set<ConfiguredClassHierarchy> hierarchies = builder.createEntityHierarchies( index );
assertEquals( "There should be only one hierarchy", 1, hierarchies.size() );
Iterator<ConfiguredClass> iter = hierarchies.iterator().next().iterator();
ClassInfo info = iter.next().getClassInfo();
assertEquals( "wrong class", DotName.createSimple( MappedSuperClass.class.getName() ), info.name() );
info = iter.next().getClassInfo();
assertEquals( "wrong class", DotName.createSimple( UnmappedSubClass.class.getName() ), info.name() );
assertFalse( iter.hasNext() );
info = iter.next().getClassInfo();
assertEquals( "wrong class", DotName.createSimple( MappedSubClass.class.getName() ), info.name() );
assertFalse( iter.hasNext() );
}
@Test(expected = AnnotationException.class)
public void testEntityAndMappedSuperClassAnnotations() {
Index index = indexForClass( EntityAndMappedSuperClass.class );
ConfiguredClassHierarchyBuilder builder = new ConfiguredClassHierarchyBuilder();
builder.createEntityHierarchies( index );
}
private Index indexForClass(Class<?>... classes) {
Indexer indexer = new Indexer();
for ( Class<?> clazz : classes ) {
InputStream stream = getClass().getClassLoader().getResourceAsStream(
clazz.getName().replace( '.', '/' ) + ".class"
);
try {
indexer.index( stream );
}
catch ( IOException e ) {
fail( "Unable to index" );
}
}
return indexer.complete();
}
@Entity
public class Foo {
@Id
@GeneratedValue
private int id;
}
@Entity
public class A {
@Id
@GeneratedValue
private int id;
}
@Entity
public class B extends A {
private String name;
}
@MappedSuperclass
public class MappedSuperClass {
@Id
@GeneratedValue
private int id;
}
public class UnmappedSubClass extends MappedSuperClass {
private String unmappedProperty;
}
@Entity
public class MappedSubClass extends UnmappedSubClass {
private String mappedProperty;
}
@Entity
@MappedSuperclass
public class EntityAndMappedSuperClass {
}
}

View File

@ -17,7 +17,14 @@ public class OrmXmlParserTests extends BaseUnitTestCase {
Set<String> xmlFiles = new HashSet<String>();
xmlFiles.add( "org/hibernate/metamodel/source/annotations/orm.xml" );
parser.parseAndUpdateIndex( xmlFiles, null );
}
@Test
public void testOrmXmlWithOldSchema() {
OrmXmlParser parser = new OrmXmlParser();
Set<String> xmlFiles = new HashSet<String>();
xmlFiles.add( "org/hibernate/metamodel/source/annotations/orm2.xml" );
parser.parseAndUpdateIndex( xmlFiles, null );
}
}

View File

@ -0,0 +1,13 @@
package org.hibernate.metamodel.source.annotations;
import javax.persistence.Entity;
/**
* @author Hardy Ferentschik
*/
@Entity
public class Star {
private int id;
}

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm orm_1_0.xsd"
version="1.0"
>
<!-- use orm_1_0 on purpose to test backward compatibility -->
<package>org.hibernate.metamodel.source.annotations</package>
<entity class="Star" access="FIELD" metadata-complete="false">
<attributes>
<id name="id">
<column name="STAR_ID"/>
</id>
</attributes>
</entity>
</entity-mappings>