diff --git a/hibernate-core/hibernate-core.gradle b/hibernate-core/hibernate-core.gradle index 87d9888069..b07d697927 100644 --- a/hibernate-core/hibernate-core.gradle +++ b/hibernate-core/hibernate-core.gradle @@ -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() diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/AccessType.java b/hibernate-core/src/main/java/org/hibernate/cfg/AccessType.java index f65b81e5e4..8e9c1d7ea4 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/AccessType.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/AccessType.java @@ -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 */ diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/AnnotationBinder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/AnnotationBinder.java index 28017a5ad2..d2db21ea5a 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/AnnotationBinder.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/AnnotationBinder.java @@ -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 hierarchies = builder.createEntityHierarchies( annotationIndex ); + ConfiguredClassHierarchyBuilder builder = new ConfiguredClassHierarchyBuilder(); + Set hierarchies = builder.createEntityHierarchies( annotationIndex ); // now we process each hierarchy one at the time - for ( EntityHierarchy hierarchy : hierarchies ) { - Iterator iter = hierarchy.iterator(); + for ( ConfiguredClassHierarchy hierarchy : hierarchies ) { + Iterator 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 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() - ); - } - } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/ConfiguredClass.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/ConfiguredClass.java new file mode 100644 index 0000000000..0dbdab27c3 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/ConfiguredClass.java @@ -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(); + } +} + + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/EntityHierarchy.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/ConfiguredClassHierarchy.java similarity index 53% rename from hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/EntityHierarchy.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/ConfiguredClassHierarchy.java index ef928c27ba..6ed1302953 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/EntityHierarchy.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/ConfiguredClassHierarchy.java @@ -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 { - @Override - public Iterator iterator() { +public class ConfiguredClassHierarchy implements Iterable { + private final AccessType defaultAccessType; + private final List configuredClasses; + + ConfiguredClassHierarchy(List classes) { + configuredClasses = new ArrayList(); + for ( ClassInfo info : classes ) { + configuredClasses.add( new ConfiguredClass( info, this ) ); + } + defaultAccessType = determineDefaultAccessType(); + } + + private AccessType determineDefaultAccessType() { return null; } + + @Override + public Iterator 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(); + } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/ConfiguredClassHierarchyBuilder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/ConfiguredClassHierarchyBuilder.java new file mode 100644 index 0000000000..7e336b9711 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/ConfiguredClassHierarchyBuilder.java @@ -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 createEntityHierarchies(Index index) { + Map> processedClassInfos = new HashMap>(); + + for ( ClassInfo info : index.getKnownClasses() ) { + if ( processedClassInfos.containsKey( info ) ) { + continue; + } + List configuredClassList = new ArrayList(); + 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 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 hierarchies = new HashSet(); + List> processedList = new ArrayList>(); + for ( List classInfoList : processedClassInfos.values() ) { + if ( !processedList.contains( classInfoList ) ) { + hierarchies.add( new ConfiguredClassHierarchy( classInfoList ) ); + processedList.add( classInfoList ); + } + } + + return hierarchies; + } + + private boolean existsHierarchyWithClassInfoAsLeaf(Map> processedClassInfos, ClassInfo tmpClassInfo) { + if ( !processedClassInfos.containsKey( tmpClassInfo ) ) { + return false; + } + + List 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; + } +} + + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/Entity.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/Entity.java deleted file mode 100644 index b35ca50387..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/Entity.java +++ /dev/null @@ -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; - } -} - - diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/EntityHierarchyBuilder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/EntityHierarchyBuilder.java deleted file mode 100644 index feffb255dd..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/EntityHierarchyBuilder.java +++ /dev/null @@ -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 createEntityHierarchies(Index index) { - List hierarchies = new ArrayList(); - - - return hierarchies; - } -} - - diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/JandexHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/JandexHelper.java new file mode 100644 index 0000000000..81cbcd72e2 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/JandexHelper.java @@ -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 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() + ); + } + } +} + + diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/OrmXmlParser.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/OrmXmlParser.java index b6cf51254c..caba83f7fa 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/OrmXmlParser.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/OrmXmlParser.java @@ -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 mappingStreams = new HashSet(); 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 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 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; } diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/BasicAnnotationBindingTests.java b/hibernate-core/src/test/java/org/hibernate/metamodel/binding/BasicAnnotationBindingTests.java index 4266a49513..5a1c8f95de 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/binding/BasicAnnotationBindingTests.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/binding/BasicAnnotationBindingTests.java @@ -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(); diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/ConfiguredClassHierarchyBuilderTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/ConfiguredClassHierarchyBuilderTest.java new file mode 100644 index 0000000000..3f3bdb78b8 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/ConfiguredClassHierarchyBuilderTest.java @@ -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 hierarchies = builder.createEntityHierarchies( index ); + assertEquals( "There should be only one hierarchy", 1, hierarchies.size() ); + + Iterator 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 hierarchies = builder.createEntityHierarchies( index ); + assertEquals( "There should be only one hierarchy", 1, hierarchies.size() ); + + Iterator 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 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 hierarchies = builder.createEntityHierarchies( index ); + assertEquals( "There should be only one hierarchy", 1, hierarchies.size() ); + + Iterator 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 { + } +} + + diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/OrmXmlParserTests.java b/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/OrmXmlParserTests.java index 03ca1d6f37..ace3da43b4 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/OrmXmlParserTests.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/OrmXmlParserTests.java @@ -17,7 +17,14 @@ public class OrmXmlParserTests extends BaseUnitTestCase { Set xmlFiles = new HashSet(); xmlFiles.add( "org/hibernate/metamodel/source/annotations/orm.xml" ); parser.parseAndUpdateIndex( xmlFiles, null ); + } + @Test + public void testOrmXmlWithOldSchema() { + OrmXmlParser parser = new OrmXmlParser(); + Set xmlFiles = new HashSet(); + xmlFiles.add( "org/hibernate/metamodel/source/annotations/orm2.xml" ); + parser.parseAndUpdateIndex( xmlFiles, null ); } } diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/Star.java b/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/Star.java new file mode 100644 index 0000000000..6592f0dea1 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/Star.java @@ -0,0 +1,13 @@ +package org.hibernate.metamodel.source.annotations; + +import javax.persistence.Entity; + +/** + * @author Hardy Ferentschik + */ +@Entity +public class Star { + private int id; +} + + diff --git a/hibernate-core/src/test/resources/org/hibernate/metamodel/source/annotations/orm2.xml b/hibernate-core/src/test/resources/org/hibernate/metamodel/source/annotations/orm2.xml new file mode 100644 index 0000000000..82bb60b48e --- /dev/null +++ b/hibernate-core/src/test/resources/org/hibernate/metamodel/source/annotations/orm2.xml @@ -0,0 +1,17 @@ + + + + + org.hibernate.metamodel.source.annotations + + + + + + + + \ No newline at end of file