HHH-6109 Starting work for annotation binding against the new metamodel. Enabling JAXB for parsing of orm.xml
This commit is contained in:
parent
72a2862ea9
commit
42502e696b
10
build.gradle
10
build.gradle
|
@ -46,6 +46,7 @@ libraries = [
|
|||
// Annotations
|
||||
commons_annotations:
|
||||
'org.hibernate:hibernate-commons-annotations:3.2.0.Final',
|
||||
jandex: 'org.jboss:jandex:1.0.0.Beta6',
|
||||
|
||||
// Jakarta commons-collections todo : get rid of commons-collections dependency
|
||||
commons_collections:
|
||||
|
@ -53,6 +54,7 @@ libraries = [
|
|||
|
||||
// Dom4J
|
||||
dom4j: 'dom4j:dom4j:1.6.1@jar',
|
||||
jaxb: 'com.sun.xml.bind:jaxb-xjc:2.1.6',
|
||||
|
||||
// h2
|
||||
h2: 'com.h2database:h2:1.2.145',
|
||||
|
@ -114,11 +116,14 @@ subprojects { subProject ->
|
|||
deployerJars {
|
||||
description = 'Jars needed for doing deployment to JBoss Nexus repo'
|
||||
}
|
||||
jaxb {
|
||||
description = 'Dependencies for running ant xjc (jaxb class generation)'
|
||||
}
|
||||
}
|
||||
|
||||
// appropriately inject the common dependencies into each sub-project
|
||||
dependencies {
|
||||
compile( libraries.logging )
|
||||
compile( libraries.logging )
|
||||
testCompile( libraries.junit )
|
||||
testRuntime( libraries.slf4j_api )
|
||||
testRuntime( libraries.slf4j_log4j12 )
|
||||
|
@ -127,8 +132,9 @@ subprojects { subProject ->
|
|||
testRuntime( libraries.jcl )
|
||||
testRuntime( libraries.javassist )
|
||||
testRuntime( libraries.h2 )
|
||||
jbossLoggingTool( libraries.logging_tools )
|
||||
jbossLoggingTool( libraries.logging_tools )
|
||||
hibernateJpaModelGenTool( libraries.jpa_modelgen )
|
||||
jaxb( libraries.jaxb )
|
||||
deployerJars "org.apache.maven.wagon:wagon-http:1.0-beta-6"
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ dependencies {
|
|||
transitive = false
|
||||
}
|
||||
compile( libraries.commons_annotations )
|
||||
compile( libraries.jandex )
|
||||
compile( libraries.jpa )
|
||||
compile( libraries.javassist )
|
||||
antlr( libraries.antlr )
|
||||
|
@ -43,3 +44,16 @@ ideaModule {
|
|||
}
|
||||
|
||||
|
||||
task jaxb << {
|
||||
jaxbTargetDir = file( "${buildDir}/generated-src/jaxb" )
|
||||
jaxbTargetDir.mkdirs()
|
||||
|
||||
ant.taskdef(name: 'xjc', classname: 'com.sun.tools.xjc.XJCTask', classpath: configurations.jaxb.asPath)
|
||||
ant.jaxbTargetDir = jaxbTargetDir
|
||||
ant.xjc(destdir: '${jaxbTargetDir}', package: 'org.hibernate.metamodel.source.xml') {
|
||||
schema(dir: 'src/main/resources/org/hibernate/ejb', includes: 'orm_2_0.xsd')
|
||||
}
|
||||
}
|
||||
compileJava.dependsOn jaxb
|
||||
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ import org.hibernate.internal.CoreMessageLogger;
|
|||
import org.jboss.logging.Logger;
|
||||
|
||||
/**
|
||||
* TODO : javadoc
|
||||
* Binds the entity identifier.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
|
@ -42,7 +42,8 @@ public class EntityIdentifier {
|
|||
|
||||
/**
|
||||
* Create an identifier
|
||||
* @param entityBinding
|
||||
*
|
||||
* @param entityBinding the entity binding for which this instance is the id
|
||||
*/
|
||||
public EntityIdentifier(EntityBinding entityBinding) {
|
||||
this.entityBinding = entityBinding;
|
||||
|
@ -54,7 +55,8 @@ public class EntityIdentifier {
|
|||
|
||||
public void setValueBinding(AttributeBinding attributeBinding) {
|
||||
if ( this.attributeBinding != null ) {
|
||||
// todo : error? or just log? for now just log
|
||||
// todo : error? or just log? For now throw exception and see what happens. Easier to see whether this
|
||||
// method gets called multiple times
|
||||
LOG.entityIdentifierValueBindingExists( entityBinding.getEntity().getName() );
|
||||
}
|
||||
this.attributeBinding = attributeBinding;
|
||||
|
|
|
@ -29,23 +29,21 @@ import java.io.Serializable;
|
|||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.hibernate.DuplicateMappingException;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.annotations.common.reflection.MetadataProvider;
|
||||
import org.hibernate.annotations.common.reflection.MetadataProviderInjector;
|
||||
import org.hibernate.annotations.common.reflection.ReflectionManager;
|
||||
import org.hibernate.annotations.common.reflection.java.JavaReflectionManager;
|
||||
import org.hibernate.cfg.EJB3NamingStrategy;
|
||||
import org.hibernate.cfg.NamingStrategy;
|
||||
import org.hibernate.cfg.annotations.reflection.JPAMetadataProvider;
|
||||
import org.hibernate.mapping.FetchProfile;
|
||||
import org.hibernate.mapping.MetadataSource;
|
||||
import org.hibernate.metamodel.binding.EntityBinding;
|
||||
import org.hibernate.metamodel.binding.PluralAttributeBinding;
|
||||
import org.hibernate.metamodel.relational.Database;
|
||||
import org.hibernate.metamodel.source.annotations.AnnotationBinder;
|
||||
import org.hibernate.metamodel.source.hbm.HibernateXmlBinder;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
/**
|
||||
* TODO : javadoc
|
||||
|
@ -53,19 +51,36 @@ import org.jboss.logging.Logger;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public class Metadata implements Serializable {
|
||||
private static final Logger log = LoggerFactory.getLogger( Metadata.class );
|
||||
|
||||
private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, Metadata.class.getName());
|
||||
private static final HibernateLogger LOG = Logger.getMessageLogger(HibernateLogger.class, Metadata.class.getName());
|
||||
private final AnnotationBinder annotationBinder;
|
||||
private final HibernateXmlBinder hibernateXmlBinder;
|
||||
private final ExtendsQueue extendsQueue;
|
||||
private final MetadataSourceQueue metadataSourceQueue;
|
||||
private final Database database = new Database();
|
||||
|
||||
private final HibernateXmlBinder hibernateXmlBinder = new HibernateXmlBinder( this );
|
||||
private final ExtendsQueue extendsQueue = new ExtendsQueue( this );
|
||||
private final MetadataSourceQueue metadataSourceQueue = new MetadataSourceQueue( this );
|
||||
private NamingStrategy namingStrategy = EJB3NamingStrategy.INSTANCE;
|
||||
private Map<String, EntityBinding> entityBindingMap = new HashMap<String, EntityBinding>();
|
||||
private Map<String, PluralAttributeBinding> collectionBindingMap = new HashMap<String, PluralAttributeBinding>();
|
||||
private Map<String, FetchProfile> fetchProfiles = new HashMap<String, FetchProfile>();
|
||||
private Map<String, String> imports;
|
||||
|
||||
private transient ReflectionManager reflectionManager = createReflectionManager();
|
||||
public Metadata() {
|
||||
annotationBinder = new AnnotationBinder( this );
|
||||
hibernateXmlBinder = new HibernateXmlBinder( this );
|
||||
extendsQueue = new ExtendsQueue( this );
|
||||
metadataSourceQueue = new MetadataSourceQueue( this );
|
||||
}
|
||||
|
||||
public HibernateXmlBinder getHibernateXmlBinder() {
|
||||
return hibernateXmlBinder;
|
||||
}
|
||||
|
||||
public AnnotationBinder getAnnotationBinder() {
|
||||
return annotationBinder;
|
||||
}
|
||||
|
||||
public ExtendsQueue getExtendsQueue() {
|
||||
return extendsQueue;
|
||||
}
|
||||
|
@ -74,32 +89,10 @@ public class Metadata implements Serializable {
|
|||
return metadataSourceQueue;
|
||||
}
|
||||
|
||||
public ReflectionManager getReflectionManager() {
|
||||
return reflectionManager;
|
||||
}
|
||||
|
||||
public void setReflectionManager(ReflectionManager reflectionManager) {
|
||||
this.reflectionManager = reflectionManager;
|
||||
}
|
||||
|
||||
private ReflectionManager createReflectionManager() {
|
||||
return createReflectionManager( new JPAMetadataProvider() );
|
||||
}
|
||||
|
||||
private ReflectionManager createReflectionManager(MetadataProvider metadataProvider) {
|
||||
ReflectionManager reflectionManager = new JavaReflectionManager();
|
||||
( (MetadataProviderInjector) reflectionManager ).setMetadataProvider( metadataProvider );
|
||||
return reflectionManager;
|
||||
}
|
||||
|
||||
private final Database database = new Database();
|
||||
|
||||
public Database getDatabase() {
|
||||
return database;
|
||||
}
|
||||
|
||||
private NamingStrategy namingStrategy = EJB3NamingStrategy.INSTANCE;
|
||||
|
||||
public NamingStrategy getNamingStrategy() {
|
||||
return namingStrategy;
|
||||
}
|
||||
|
@ -108,8 +101,6 @@ public class Metadata implements Serializable {
|
|||
this.namingStrategy = namingStrategy;
|
||||
}
|
||||
|
||||
private Map<String,EntityBinding> entityBindingMap = new HashMap<String, EntityBinding>();
|
||||
|
||||
public EntityBinding getEntityBinding(String entityName) {
|
||||
return entityBindingMap.get( entityName );
|
||||
}
|
||||
|
@ -126,8 +117,6 @@ public class Metadata implements Serializable {
|
|||
entityBindingMap.put( entityName, entityBinding );
|
||||
}
|
||||
|
||||
private Map<String,PluralAttributeBinding> collectionBindingMap = new HashMap<String, PluralAttributeBinding>();
|
||||
|
||||
public PluralAttributeBinding getCollection(String collectionRole) {
|
||||
return collectionBindingMap.get( collectionRole );
|
||||
}
|
||||
|
@ -146,21 +135,17 @@ public class Metadata implements Serializable {
|
|||
collectionBindingMap.put( collectionRole, pluralAttributeBinding );
|
||||
}
|
||||
|
||||
private Map<String,String> imports;
|
||||
|
||||
public void addImport(String importName, String entityName) {
|
||||
if ( imports == null ) {
|
||||
imports = new HashMap<String, String>();
|
||||
}
|
||||
LOG.tracef( "Import: %s -> %s", importName, entityName );
|
||||
log.trace( "Import: " + importName + " -> " + entityName );
|
||||
String old = imports.put( importName, entityName );
|
||||
if ( old != null ) {
|
||||
LOG.debugf( "import name [%s] overrode previous [%s]", importName, old );
|
||||
log.debug( "import name [{}] overrode previous [{}]", importName, old );
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String,FetchProfile> fetchProfiles = new HashMap<String, FetchProfile>();
|
||||
|
||||
public Iterable<FetchProfile> getFetchProfiles() {
|
||||
return fetchProfiles.values();
|
||||
}
|
||||
|
@ -175,16 +160,10 @@ public class Metadata implements Serializable {
|
|||
}
|
||||
|
||||
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
|
||||
//we need reflectionManager before reading the other components (MetadataSourceQueue in particular)
|
||||
final MetadataProvider metadataProvider = (MetadataProvider) ois.readObject();
|
||||
this.reflectionManager = createReflectionManager( metadataProvider );
|
||||
ois.defaultReadObject();
|
||||
}
|
||||
|
||||
private void writeObject(java.io.ObjectOutputStream out) throws IOException {
|
||||
//We write MetadataProvider first as we need reflectionManager before reading the other components
|
||||
final MetadataProvider metadataProvider = ( ( MetadataProviderInjector ) reflectionManager ).getMetadataProvider();
|
||||
out.writeObject( metadataProvider );
|
||||
out.defaultWriteObject();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,20 +34,20 @@ import java.util.LinkedHashMap;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import javax.persistence.Entity;
|
||||
|
||||
import org.dom4j.Attribute;
|
||||
import org.dom4j.Document;
|
||||
import org.dom4j.Element;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.InvalidMappingException;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.annotations.common.reflection.XClass;
|
||||
import org.hibernate.cfg.MetadataSourceType;
|
||||
import org.hibernate.internal.util.collections.JoinedIterator;
|
||||
import org.hibernate.internal.util.xml.XmlDocument;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
|
||||
/**
|
||||
* TODO : javadoc
|
||||
|
@ -55,19 +55,14 @@ import org.jboss.logging.Logger;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public class MetadataSourceQueue implements Serializable {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger( MetadataSourceQueue.class );
|
||||
private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, MetadataSourceQueue.class.getName());
|
||||
|
||||
private final Metadata metadata;
|
||||
|
||||
private LinkedHashMap<XmlDocument, Set<String>> hbmMetadataToEntityNamesMap
|
||||
= new LinkedHashMap<XmlDocument, Set<String>>();
|
||||
private Map<String, XmlDocument> hbmMetadataByEntityNameXRef = new HashMap<String, XmlDocument>();
|
||||
|
||||
//XClass are not serializable by default
|
||||
private transient List<XClass> annotatedClasses = new ArrayList<XClass>();
|
||||
//only used during the secondPhaseCompile pass, hence does not need to be serialized
|
||||
private transient Map<String, XClass> annotatedClassesByEntityNameMap = new HashMap<String, XClass>();
|
||||
private transient List<Class> annotatedClasses = new ArrayList<Class>();
|
||||
|
||||
public MetadataSourceQueue(Metadata metadata) {
|
||||
this.metadata = metadata;
|
||||
|
@ -75,24 +70,10 @@ public class MetadataSourceQueue implements Serializable {
|
|||
|
||||
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
|
||||
ois.defaultReadObject();
|
||||
annotatedClassesByEntityNameMap = new HashMap<String, XClass>();
|
||||
|
||||
//build back annotatedClasses
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Class> serializableAnnotatedClasses = (List<Class>) ois.readObject();
|
||||
annotatedClasses = new ArrayList<XClass>( serializableAnnotatedClasses.size() );
|
||||
for ( Class clazz : serializableAnnotatedClasses ) {
|
||||
annotatedClasses.add( metadata.getReflectionManager().toXClass( clazz ) );
|
||||
}
|
||||
}
|
||||
|
||||
private void writeObject(java.io.ObjectOutputStream out) throws IOException {
|
||||
out.defaultWriteObject();
|
||||
List<Class> serializableAnnotatedClasses = new ArrayList<Class>( annotatedClasses.size() );
|
||||
for ( XClass xClass : annotatedClasses ) {
|
||||
serializableAnnotatedClasses.add( metadata.getReflectionManager().toClass( xClass ) );
|
||||
}
|
||||
out.writeObject( serializableAnnotatedClasses );
|
||||
}
|
||||
|
||||
public void add(XmlDocument metadataXml) {
|
||||
|
@ -143,28 +124,11 @@ public class MetadataSourceQueue implements Serializable {
|
|||
return unqualifiedName;
|
||||
}
|
||||
|
||||
public void add(XClass annotatedClass) {
|
||||
public void add(Class annotatedClass) {
|
||||
annotatedClasses.add( annotatedClass );
|
||||
}
|
||||
|
||||
protected void syncAnnotatedClasses() {
|
||||
final Iterator<XClass> itr = annotatedClasses.iterator();
|
||||
while ( itr.hasNext() ) {
|
||||
final XClass annotatedClass = itr.next();
|
||||
if ( annotatedClass.isAnnotationPresent( Entity.class ) ) {
|
||||
annotatedClassesByEntityNameMap.put( annotatedClass.getName(), annotatedClass );
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( !annotatedClass.isAnnotationPresent( javax.persistence.MappedSuperclass.class ) ) {
|
||||
itr.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void processMetadata(List<MetadataSourceType> order) {
|
||||
syncAnnotatedClasses();
|
||||
|
||||
for ( MetadataSourceType type : order ) {
|
||||
if ( MetadataSourceType.HBM.equals( type ) ) {
|
||||
processHbmXmlQueue();
|
||||
|
@ -176,7 +140,7 @@ public class MetadataSourceQueue implements Serializable {
|
|||
}
|
||||
|
||||
private void processHbmXmlQueue() {
|
||||
LOG.debug( "Processing hbm.xml files" );
|
||||
log.debug( "Processing hbm.xml files" );
|
||||
for ( Map.Entry<XmlDocument, Set<String>> entry : hbmMetadataToEntityNamesMap.entrySet() ) {
|
||||
// Unfortunately we have to create a Mappings instance for each iteration here
|
||||
processHbmXml( entry.getKey(), entry.getValue() );
|
||||
|
@ -196,83 +160,14 @@ public class MetadataSourceQueue implements Serializable {
|
|||
me
|
||||
);
|
||||
}
|
||||
|
||||
for ( String entityName : entityNames ) {
|
||||
if ( annotatedClassesByEntityNameMap.containsKey( entityName ) ) {
|
||||
annotatedClasses.remove( annotatedClassesByEntityNameMap.get( entityName ) );
|
||||
annotatedClassesByEntityNameMap.remove( entityName );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void processAnnotatedClassesQueue() {
|
||||
LOG.debug( "Process annotated classes" );
|
||||
//bind classes in the correct order calculating some inheritance state
|
||||
List<XClass> orderedClasses = orderAndFillHierarchy( annotatedClasses );
|
||||
// Map<XClass, InheritanceState> inheritanceStatePerClass = AnnotationBinder.buildInheritanceStates(
|
||||
// orderedClasses, mappings
|
||||
// );
|
||||
|
||||
|
||||
for ( XClass clazz : orderedClasses ) {
|
||||
// todo : replace this with similar non-static code.
|
||||
// AnnotationBinder.bindClass( clazz, inheritanceStatePerClass, mappings );
|
||||
|
||||
final String entityName = clazz.getName();
|
||||
if ( hbmMetadataByEntityNameXRef.containsKey( entityName ) ) {
|
||||
hbmMetadataToEntityNamesMap.remove( hbmMetadataByEntityNameXRef.get( entityName ) );
|
||||
hbmMetadataByEntityNameXRef.remove( entityName );
|
||||
}
|
||||
}
|
||||
log.debug( "Process annotated classes" );
|
||||
annotatedClasses.clear();
|
||||
annotatedClassesByEntityNameMap.clear();
|
||||
}
|
||||
|
||||
private List<XClass> orderAndFillHierarchy(List<XClass> original) {
|
||||
List<XClass> copy = new ArrayList<XClass>( original );
|
||||
insertMappedSuperclasses( original, copy );
|
||||
|
||||
// order the hierarchy
|
||||
List<XClass> workingCopy = new ArrayList<XClass>( copy );
|
||||
List<XClass> newList = new ArrayList<XClass>( copy.size() );
|
||||
while ( workingCopy.size() > 0 ) {
|
||||
XClass clazz = workingCopy.get( 0 );
|
||||
orderHierarchy( workingCopy, newList, copy, clazz );
|
||||
}
|
||||
return newList;
|
||||
}
|
||||
|
||||
private void insertMappedSuperclasses(List<XClass> original, List<XClass> copy) {
|
||||
for ( XClass clazz : original ) {
|
||||
XClass superClass = clazz.getSuperclass();
|
||||
while ( superClass != null
|
||||
&& !metadata.getReflectionManager().equals( superClass, Object.class )
|
||||
&& !copy.contains( superClass ) ) {
|
||||
if ( superClass.isAnnotationPresent( Entity.class )
|
||||
|| superClass.isAnnotationPresent( javax.persistence.MappedSuperclass.class ) ) {
|
||||
copy.add( superClass );
|
||||
}
|
||||
superClass = superClass.getSuperclass();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void orderHierarchy(List<XClass> copy, List<XClass> newList, List<XClass> original, XClass clazz) {
|
||||
if ( clazz == null || metadata.getReflectionManager().equals( clazz, Object.class ) ) {
|
||||
return;
|
||||
}
|
||||
//process superclass first
|
||||
orderHierarchy( copy, newList, original, clazz.getSuperclass() );
|
||||
if ( original.contains( clazz ) ) {
|
||||
if ( !newList.contains( clazz ) ) {
|
||||
newList.add( clazz );
|
||||
}
|
||||
copy.remove( clazz );
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return hbmMetadataToEntityNamesMap.isEmpty() && annotatedClasses.isEmpty();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,336 @@
|
|||
/*
|
||||
* 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.Iterator;
|
||||
import java.util.List;
|
||||
import javax.persistence.MappedSuperclass;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* Main class responsible to creating and binding the Hibernate meta-model from annotations.
|
||||
* This binder only has to deal with annotation index. XML configuration is already processed and pseudo annotations
|
||||
* are added to the annotation index.
|
||||
*
|
||||
* @author Hardy Ferentschik
|
||||
* @todo On top of the index we probably needs to pass some sort of XMLContext for global configuration data
|
||||
* @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;
|
||||
|
||||
public AnnotationBinder(Metadata metadata) {
|
||||
this.metadata = metadata;
|
||||
}
|
||||
|
||||
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 );
|
||||
|
||||
// now we process each hierarchy one at the time
|
||||
for ( EntityHierarchy hierarchy : hierarchies ) {
|
||||
Iterator<Entity> iter = hierarchy.iterator();
|
||||
while ( iter.hasNext() ) {
|
||||
Entity entity = iter.next();
|
||||
bindEntity( entity );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void bindEntity(Entity 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()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// //TODO: be more strict with secondarytable allowance (not for ids, not for secondary table join columns etc)
|
||||
// InheritanceState inheritanceState = inheritanceStatePerClass.get( clazzToProcess );
|
||||
// AnnotatedClassType classType = mappings.getClassType( clazzToProcess );
|
||||
//
|
||||
// //Queries declared in MappedSuperclass should be usable in Subclasses
|
||||
// if ( AnnotatedClassType.EMBEDDABLE_SUPERCLASS.equals( classType ) ) {
|
||||
// bindQueries( clazzToProcess, mappings );
|
||||
// bindTypeDefs( clazzToProcess, mappings );
|
||||
// bindFilterDefs( clazzToProcess, mappings );
|
||||
// }
|
||||
//
|
||||
// if ( !isEntityClassType( clazzToProcess, classType ) ) {
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
log.info( "Binding entity from annotated class: {}", classInfo.name() );
|
||||
//
|
||||
// PersistentClass superEntity = getSuperEntity(
|
||||
// clazzToProcess, inheritanceStatePerClass, mappings, inheritanceState
|
||||
// );
|
||||
//
|
||||
// PersistentClass persistentClass = makePersistentClass( inheritanceState, superEntity );
|
||||
|
||||
|
||||
EntityBinder entityBinder = new EntityBinder(
|
||||
metadata, classInfo, jpaEntityAnnotation, hibernateEntityAnnotation
|
||||
);
|
||||
// entityBinder.setInheritanceState( inheritanceState );
|
||||
//
|
||||
// bindQueries( clazzToProcess, mappings );
|
||||
// bindFilterDefs( clazzToProcess, mappings );
|
||||
// bindTypeDefs( clazzToProcess, mappings );
|
||||
// bindFetchProfiles( clazzToProcess, mappings );
|
||||
// BinderHelper.bindAnyMetaDefs( clazzToProcess, mappings );
|
||||
//
|
||||
// String schema = "";
|
||||
// String table = ""; //might be no @Table annotation on the annotated class
|
||||
// String catalog = "";
|
||||
// List<UniqueConstraintHolder> uniqueConstraints = new ArrayList<UniqueConstraintHolder>();
|
||||
// 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() );
|
||||
// }
|
||||
//
|
||||
// Ejb3JoinColumn[] inheritanceJoinedColumns = makeInheritanceJoinColumns(
|
||||
// clazzToProcess, mappings, inheritanceState, superEntity
|
||||
// );
|
||||
// Ejb3DiscriminatorColumn discriminatorColumn = null;
|
||||
// if ( InheritanceType.SINGLE_TABLE.equals( inheritanceState.getType() ) ) {
|
||||
// discriminatorColumn = processDiscriminatorProperties(
|
||||
// clazzToProcess, mappings, inheritanceState, entityBinder
|
||||
// );
|
||||
// }
|
||||
//
|
||||
// entityBinder.setProxy( clazzToProcess.getAnnotation( Proxy.class ) );
|
||||
// entityBinder.setBatchSize( clazzToProcess.getAnnotation( BatchSize.class ) );
|
||||
// entityBinder.setWhere( clazzToProcess.getAnnotation( Where.class ) );
|
||||
// entityBinder.setCache( determineCacheSettings( clazzToProcess, mappings ) );
|
||||
//
|
||||
// //Filters are not allowed on subclasses
|
||||
// if ( !inheritanceState.hasParents() ) {
|
||||
// bindFilters( clazzToProcess, entityBinder, mappings );
|
||||
// }
|
||||
//
|
||||
// entityBinder.bindEntity();
|
||||
//
|
||||
// if ( inheritanceState.hasTable() ) {
|
||||
// Check checkAnn = clazzToProcess.getAnnotation( Check.class );
|
||||
// String constraints = checkAnn == null ?
|
||||
// null :
|
||||
// checkAnn.constraints();
|
||||
// entityBinder.bindTable(
|
||||
// schema, catalog, table, uniqueConstraints,
|
||||
// constraints, inheritanceState.hasDenormalizedTable() ?
|
||||
// superEntity.getTable() :
|
||||
// null
|
||||
// );
|
||||
// }
|
||||
// else {
|
||||
// if ( clazzToProcess.isAnnotationPresent( Table.class ) ) {
|
||||
// log.warn(
|
||||
// "Illegal use of @Table in a subclass of a SINGLE_TABLE hierarchy: " + clazzToProcess
|
||||
// .getName()
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// PropertyHolder propertyHolder = PropertyHolderBuilder.buildPropertyHolder(
|
||||
// clazzToProcess,
|
||||
// persistentClass,
|
||||
// entityBinder, mappings, inheritanceStatePerClass
|
||||
// );
|
||||
//
|
||||
// javax.persistence.SecondaryTable secTabAnn = clazzToProcess.getAnnotation(
|
||||
// javax.persistence.SecondaryTable.class
|
||||
// );
|
||||
// javax.persistence.SecondaryTables secTabsAnn = clazzToProcess.getAnnotation(
|
||||
// javax.persistence.SecondaryTables.class
|
||||
// );
|
||||
// entityBinder.firstLevelSecondaryTablesBinding( secTabAnn, secTabsAnn );
|
||||
//
|
||||
// OnDelete onDeleteAnn = clazzToProcess.getAnnotation( OnDelete.class );
|
||||
// boolean onDeleteAppropriate = false;
|
||||
// if ( InheritanceType.JOINED.equals( inheritanceState.getType() ) && inheritanceState.hasParents() ) {
|
||||
// onDeleteAppropriate = true;
|
||||
// final JoinedSubclass jsc = ( JoinedSubclass ) persistentClass;
|
||||
// if ( persistentClass.getEntityPersisterClass() == null ) {
|
||||
// persistentClass.getRootClass().setEntityPersisterClass( JoinedSubclassEntityPersister.class );
|
||||
// }
|
||||
// SimpleValue key = new DependantValue( mappings, jsc.getTable(), jsc.getIdentifier() );
|
||||
// jsc.setKey( key );
|
||||
// ForeignKey fk = clazzToProcess.getAnnotation( ForeignKey.class );
|
||||
// if ( fk != null && !BinderHelper.isEmptyAnnotationValue( fk.name() ) ) {
|
||||
// key.setForeignKeyName( fk.name() );
|
||||
// }
|
||||
// if ( onDeleteAnn != null ) {
|
||||
// key.setCascadeDeleteEnabled( OnDeleteAction.CASCADE.equals( onDeleteAnn.action() ) );
|
||||
// }
|
||||
// else {
|
||||
// key.setCascadeDeleteEnabled( false );
|
||||
// }
|
||||
// //we are never in a second pass at that stage, so queue it
|
||||
// SecondPass sp = new JoinedSubclassFkSecondPass( jsc, inheritanceJoinedColumns, key, mappings );
|
||||
// mappings.addSecondPass( sp );
|
||||
// mappings.addSecondPass( new CreateKeySecondPass( jsc ) );
|
||||
//
|
||||
// }
|
||||
// else if ( InheritanceType.SINGLE_TABLE.equals( inheritanceState.getType() ) ) {
|
||||
// if ( inheritanceState.hasParents() ) {
|
||||
// if ( persistentClass.getEntityPersisterClass() == null ) {
|
||||
// persistentClass.getRootClass().setEntityPersisterClass( SingleTableEntityPersister.class );
|
||||
// }
|
||||
// }
|
||||
// else {
|
||||
// if ( inheritanceState.hasSiblings() || !discriminatorColumn.isImplicit() ) {
|
||||
// //need a discriminator column
|
||||
// bindDiscriminatorToPersistentClass(
|
||||
// (RootClass) persistentClass,
|
||||
// discriminatorColumn,
|
||||
// entityBinder.getSecondaryTables(),
|
||||
// propertyHolder,
|
||||
// mappings
|
||||
// );
|
||||
// entityBinder.bindDiscriminatorValue();//bind it again since the type might have changed
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// else if ( InheritanceType.TABLE_PER_CLASS.equals( inheritanceState.getType() ) ) {
|
||||
// if ( inheritanceState.hasParents() ) {
|
||||
// if ( persistentClass.getEntityPersisterClass() == null ) {
|
||||
// persistentClass.getRootClass().setEntityPersisterClass( UnionSubclassEntityPersister.class );
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// if ( onDeleteAnn != null && !onDeleteAppropriate ) {
|
||||
// log.warn(
|
||||
// "Inapropriate use of @OnDelete on entity, annotation ignored: {}", propertyHolder.getEntityName()
|
||||
// );
|
||||
// }
|
||||
//
|
||||
// // try to find class level generators
|
||||
// HashMap<String, IdGenerator> classGenerators = buildLocalGenerators( clazzToProcess, mappings );
|
||||
//
|
||||
// // check properties
|
||||
// final InheritanceState.ElementsToProcess elementsToProcess = inheritanceState.getElementsToProcess();
|
||||
// inheritanceState.postProcess( persistentClass, entityBinder );
|
||||
//
|
||||
// final boolean subclassAndSingleTableStrategy = inheritanceState.getType() == InheritanceType.SINGLE_TABLE
|
||||
// && inheritanceState.hasParents();
|
||||
// Set<String> idPropertiesIfIdClass = new HashSet<String>();
|
||||
// boolean isIdClass = mapAsIdClass(
|
||||
// inheritanceStatePerClass,
|
||||
// inheritanceState,
|
||||
// persistentClass,
|
||||
// entityBinder,
|
||||
// propertyHolder,
|
||||
// elementsToProcess,
|
||||
// idPropertiesIfIdClass,
|
||||
// mappings
|
||||
// );
|
||||
//
|
||||
// if ( !isIdClass ) {
|
||||
// entityBinder.setWrapIdsInEmbeddedComponents( elementsToProcess.getIdPropertyCount() > 1 );
|
||||
// }
|
||||
//
|
||||
// processIdPropertiesIfNotAlready(
|
||||
// inheritanceStatePerClass,
|
||||
// mappings,
|
||||
// persistentClass,
|
||||
// entityBinder,
|
||||
// propertyHolder,
|
||||
// classGenerators,
|
||||
// elementsToProcess,
|
||||
// subclassAndSingleTableStrategy,
|
||||
// idPropertiesIfIdClass
|
||||
// );
|
||||
//
|
||||
// if ( !inheritanceState.hasParents() ) {
|
||||
// final RootClass rootClass = ( RootClass ) persistentClass;
|
||||
// mappings.addSecondPass( new CreateKeySecondPass( rootClass ) );
|
||||
// }
|
||||
// else {
|
||||
// superEntity.addSubclass( (Subclass) persistentClass );
|
||||
// }
|
||||
//
|
||||
// mappings.addClass( persistentClass );
|
||||
//
|
||||
// //Process secondary tables and complementary definitions (ie o.h.a.Table)
|
||||
// mappings.addSecondPass( new SecondaryTableSecondPass( entityBinder, propertyHolder, clazzToProcess ) );
|
||||
//
|
||||
// //add process complementary Table definition (index & all)
|
||||
// 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()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* 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.AnnotationInstance;
|
||||
import org.jboss.jandex.ClassInfo;
|
||||
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.metamodel.binding.EntityBinding;
|
||||
import org.hibernate.metamodel.domain.Entity;
|
||||
import org.hibernate.metamodel.source.Metadata;
|
||||
|
||||
/**
|
||||
* @author Hardy Ferentschik
|
||||
*/
|
||||
public class EntityBinder {
|
||||
private final ClassInfo classToBind;
|
||||
|
||||
public EntityBinder(Metadata metadata, ClassInfo classInfo, AnnotationInstance jpaEntityAnnotation, AnnotationInstance hibernateEntityAnnotation) {
|
||||
this.classToBind = classInfo;
|
||||
EntityBinding entityBinding = new EntityBinding();
|
||||
bindJpaAnnotation( jpaEntityAnnotation, entityBinding );
|
||||
bindHibernateAnnotation( hibernateEntityAnnotation, entityBinding );
|
||||
metadata.addEntity( entityBinding );
|
||||
}
|
||||
|
||||
private void bindHibernateAnnotation(AnnotationInstance annotation, EntityBinding entityBinding) {
|
||||
// if ( hibAnn != null ) {
|
||||
// dynamicInsert = hibAnn.dynamicInsert();
|
||||
// dynamicUpdate = hibAnn.dynamicUpdate();
|
||||
// optimisticLockType = hibAnn.optimisticLock();
|
||||
// selectBeforeUpdate = hibAnn.selectBeforeUpdate();
|
||||
// polymorphismType = hibAnn.polymorphism();
|
||||
// explicitHibernateEntityAnnotation = true;
|
||||
// //persister handled in bind
|
||||
// }
|
||||
// else {
|
||||
// //default values when the annotation is not there
|
||||
// dynamicInsert = false;
|
||||
// dynamicUpdate = false;
|
||||
// optimisticLockType = OptimisticLockType.VERSION;
|
||||
// polymorphismType = PolymorphismType.IMPLICIT;
|
||||
// selectBeforeUpdate = false;
|
||||
// }
|
||||
}
|
||||
|
||||
private void bindJpaAnnotation(AnnotationInstance annotation, EntityBinding entityBinding) {
|
||||
if ( annotation == null ) {
|
||||
throw new AssertionFailure( "@Entity cannot be not null when binding an entity" );
|
||||
}
|
||||
String name;
|
||||
if ( annotation.value( "name" ) == null ) {
|
||||
name = StringHelper.unqualify( classToBind.name().toString() );
|
||||
}
|
||||
else {
|
||||
name = annotation.value( "name" ).asString();
|
||||
}
|
||||
entityBinding.setEntity( new Entity( name, null ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* 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.Iterator;
|
||||
|
||||
/**
|
||||
* @author Hardy Ferentschik
|
||||
*/
|
||||
public class EntityHierarchy implements Iterable<Entity> {
|
||||
@Override
|
||||
public Iterator<Entity> iterator() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
package org.hibernate.metamodel.source.annotations;
|
||||
|
||||
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;
|
||||
import javax.xml.bind.Unmarshaller;
|
||||
import javax.xml.transform.stream.StreamSource;
|
||||
import javax.xml.validation.Schema;
|
||||
import javax.xml.validation.SchemaFactory;
|
||||
|
||||
import org.jboss.jandex.Index;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import org.hibernate.metamodel.source.xml.EntityMappings;
|
||||
|
||||
/**
|
||||
* @author Hardy Ferentschik
|
||||
* @todo Need some create some XMLContext as well which can be populated w/ information which can not be expressed via annotations
|
||||
*/
|
||||
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";
|
||||
|
||||
/**
|
||||
* Parses the given xml configuration files and returns a updated annotation index
|
||||
*
|
||||
* @param mappingFileNames the file names of the xml files to parse
|
||||
* @param annotationIndex the annotation index based on scanned annotations
|
||||
*
|
||||
* @return a new updated annotation index, enhancing and modifying the existing ones according to the jpa xml rules
|
||||
*/
|
||||
public Index parseAndUpdateIndex(Set<String> mappingFileNames, Index annotationIndex) {
|
||||
|
||||
Set<InputStream> mappingStreams = new HashSet<InputStream>();
|
||||
for ( String fileName : mappingFileNames ) {
|
||||
mappingStreams.add( getInputStreamForPath( fileName ) );
|
||||
}
|
||||
|
||||
for ( InputStream in : mappingStreams ) {
|
||||
EntityMappings entityMappings = getEntityMappings( in );
|
||||
// ...
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private InputStream getInputStreamForPath(String path) {
|
||||
// try the context class loader first
|
||||
InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream( path );
|
||||
|
||||
// try the current class loader
|
||||
if ( inputStream == null ) {
|
||||
inputStream = OrmXmlParser.class.getResourceAsStream( path );
|
||||
}
|
||||
return inputStream;
|
||||
}
|
||||
|
||||
private EntityMappings getEntityMappings(InputStream in) {
|
||||
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 );
|
||||
}
|
||||
return entityMappings;
|
||||
}
|
||||
|
||||
private Schema getMappingSchema() {
|
||||
ClassLoader loader = OrmXmlParser.class.getClassLoader();
|
||||
URL schemaUrl = loader.getResource( ORM_MAPPING_XSD );
|
||||
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() );
|
||||
}
|
||||
return schema;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -568,22 +568,6 @@ abstract class AbstractEntityBinder {
|
|||
// return prop;
|
||||
// }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
protected Value processValues(Element identifierElement, TableSpecification baseTable, String propertyPath) {
|
||||
// first boolean (false here) indicates that by default columns are nullable
|
||||
// second boolean (true here) indicates that by default column names should be guessed
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2010, 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.binding;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.hibernate.metamodel.relational.Column;
|
||||
import org.hibernate.testing.junit4.BaseUnitTestCase;
|
||||
|
||||
import static junit.framework.Assert.assertNotNull;
|
||||
import static junit.framework.Assert.assertNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* Basic tests of {@code hbm.xml} and annotation binding code
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public abstract class AbstractBasicBindingTests extends BaseUnitTestCase {
|
||||
|
||||
@Test
|
||||
public void testSimpleEntityMapping() {
|
||||
EntityBinding entityBinding = buildSimpleEntityBinding();
|
||||
assertNotNull( entityBinding );
|
||||
assertNotNull( entityBinding.getEntityIdentifier() );
|
||||
assertNotNull( entityBinding.getEntityIdentifier().getValueBinding() );
|
||||
assertNull( entityBinding.getVersioningValueBinding() );
|
||||
|
||||
AttributeBinding idAttributeBinding = entityBinding.getAttributeBinding( "id" );
|
||||
assertNotNull( idAttributeBinding );
|
||||
assertSame( idAttributeBinding, entityBinding.getEntityIdentifier().getValueBinding() );
|
||||
assertNotNull( idAttributeBinding.getAttribute() );
|
||||
assertNotNull( idAttributeBinding.getValue() );
|
||||
assertTrue( idAttributeBinding.getValue() instanceof Column );
|
||||
|
||||
AttributeBinding nameBinding = entityBinding.getAttributeBinding( "name" );
|
||||
assertNotNull( nameBinding );
|
||||
assertNotNull( nameBinding.getAttribute() );
|
||||
assertNotNull( nameBinding.getValue() );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimpleVersionedEntityMapping() {
|
||||
EntityBinding entityBinding = buildSimpleVersionedEntityBinding();
|
||||
assertNotNull( entityBinding );
|
||||
assertNotNull( entityBinding.getEntityIdentifier() );
|
||||
assertNotNull( entityBinding.getEntityIdentifier().getValueBinding() );
|
||||
assertNotNull( entityBinding.getVersioningValueBinding() );
|
||||
assertNotNull( entityBinding.getVersioningValueBinding().getAttribute() );
|
||||
|
||||
AttributeBinding idAttributeBinding = entityBinding.getAttributeBinding( "id" );
|
||||
assertNotNull( idAttributeBinding );
|
||||
assertSame( idAttributeBinding, entityBinding.getEntityIdentifier().getValueBinding() );
|
||||
assertNotNull( idAttributeBinding.getAttribute() );
|
||||
assertNotNull( idAttributeBinding.getValue() );
|
||||
assertTrue( idAttributeBinding.getValue() instanceof Column );
|
||||
|
||||
AttributeBinding nameBinding = entityBinding.getAttributeBinding( "name" );
|
||||
assertNotNull( nameBinding );
|
||||
assertNotNull( nameBinding.getAttribute() );
|
||||
assertNotNull( nameBinding.getValue() );
|
||||
}
|
||||
|
||||
public abstract EntityBinding buildSimpleVersionedEntityBinding();
|
||||
|
||||
public abstract EntityBinding buildSimpleEntityBinding();
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2010, 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.binding;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.jboss.jandex.Index;
|
||||
import org.jboss.jandex.Indexer;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.hibernate.metamodel.source.Metadata;
|
||||
import org.hibernate.testing.FailureExpected;
|
||||
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
/**
|
||||
* Basic tests of annotation based binding code
|
||||
*
|
||||
* @author Hardy Ferentschik
|
||||
*/
|
||||
public class BasicAnnotationBindingTests extends AbstractBasicBindingTests {
|
||||
|
||||
//@FailureExpected(jiraKey = "HHH-5672", message = "Work in progress")
|
||||
@Test
|
||||
public void testSimpleEntityMapping() {
|
||||
super.testSimpleEntityMapping();
|
||||
}
|
||||
|
||||
@FailureExpected(jiraKey = "HHH-5672", message = "Work in progress")
|
||||
@Test
|
||||
public void testSimpleVersionedEntityMapping() {
|
||||
super.testSimpleVersionedEntityMapping();
|
||||
}
|
||||
|
||||
public EntityBinding buildSimpleEntityBinding() {
|
||||
Index index = indexForClass( SimpleEntity.class );
|
||||
Metadata metadata = new Metadata();
|
||||
metadata.getAnnotationBinder().bindMappedClasses( index );
|
||||
|
||||
return metadata.getEntityBinding( SimpleEntity.class.getSimpleName() );
|
||||
}
|
||||
|
||||
public EntityBinding buildSimpleVersionedEntityBinding() {
|
||||
Index index = indexForClass( SimpleEntity.class );
|
||||
Metadata metadata = new Metadata();
|
||||
metadata.getAnnotationBinder().bindMappedClasses( index );
|
||||
|
||||
return metadata.getEntityBinding( SimpleVersionedEntity.class.getSimpleName() );
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
|
@ -30,75 +30,32 @@ import org.hibernate.internal.util.xml.MappingReader;
|
|||
import org.hibernate.internal.util.xml.Origin;
|
||||
import org.hibernate.internal.util.xml.XMLHelper;
|
||||
import org.hibernate.internal.util.xml.XmlDocument;
|
||||
import org.hibernate.metamodel.relational.Column;
|
||||
import org.hibernate.metamodel.source.Metadata;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.hibernate.testing.junit4.BaseUnitTestCase;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* Basic tests of {@code hbm.xml} beinding code
|
||||
* Basic tests of {@code hbm.xml} binding code
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class BasicHbmBindingTests extends BaseUnitTestCase {
|
||||
@Test
|
||||
public void testSuperSimpleMapping() {
|
||||
public class BasicHbmBindingTests extends AbstractBasicBindingTests {
|
||||
|
||||
public EntityBinding buildSimpleEntityBinding() {
|
||||
Metadata metadata = new Metadata();
|
||||
|
||||
{
|
||||
XmlDocument xmlDocument = readResource( "/org/hibernate/metamodel/binding/SimpleEntity.hbm.xml" );
|
||||
metadata.getHibernateXmlBinder().bindRoot( xmlDocument );
|
||||
EntityBinding entityBinding = metadata.getEntityBinding( SimpleEntity.class.getName() );
|
||||
assertNotNull( entityBinding );
|
||||
assertNotNull( entityBinding.getEntityIdentifier() );
|
||||
assertNotNull( entityBinding.getEntityIdentifier().getValueBinding() );
|
||||
assertNull( entityBinding.getVersioningValueBinding() );
|
||||
XmlDocument xmlDocument = readResource( "/org/hibernate/metamodel/binding/SimpleEntity.hbm.xml" );
|
||||
metadata.getHibernateXmlBinder().bindRoot( xmlDocument );
|
||||
return metadata.getEntityBinding( SimpleEntity.class.getName() );
|
||||
}
|
||||
|
||||
AttributeBinding idAttributeBinding = entityBinding.getAttributeBinding( "id" );
|
||||
assertNotNull( idAttributeBinding );
|
||||
assertSame( idAttributeBinding, entityBinding.getEntityIdentifier().getValueBinding() );
|
||||
assertNotNull( idAttributeBinding.getAttribute() );
|
||||
assertNotNull( idAttributeBinding.getValue() );
|
||||
assertTrue( idAttributeBinding.getValue() instanceof Column );
|
||||
public EntityBinding buildSimpleVersionedEntityBinding() {
|
||||
Metadata metadata = new Metadata();
|
||||
|
||||
AttributeBinding nameBinding = entityBinding.getAttributeBinding( "name" );
|
||||
assertNotNull( nameBinding );
|
||||
assertNotNull( nameBinding.getAttribute() );
|
||||
assertNotNull( nameBinding.getValue() );
|
||||
}
|
||||
{
|
||||
XmlDocument xmlDocument = readResource( "/org/hibernate/metamodel/binding/SimpleVersionedEntity.hbm.xml" );
|
||||
metadata.getHibernateXmlBinder().bindRoot( xmlDocument );
|
||||
EntityBinding entityBinding = metadata.getEntityBinding( SimpleVersionedEntity.class.getName() );
|
||||
assertNotNull( entityBinding );
|
||||
assertNotNull( entityBinding.getEntityIdentifier() );
|
||||
assertNotNull( entityBinding.getEntityIdentifier().getValueBinding() );
|
||||
assertNotNull( entityBinding.getVersioningValueBinding() );
|
||||
assertNotNull( entityBinding.getVersioningValueBinding().getAttribute() );
|
||||
|
||||
AttributeBinding idAttributeBinding = entityBinding.getAttributeBinding( "id" );
|
||||
assertNotNull( idAttributeBinding );
|
||||
assertSame( idAttributeBinding, entityBinding.getEntityIdentifier().getValueBinding() );
|
||||
assertNotNull( idAttributeBinding.getAttribute() );
|
||||
assertNotNull( idAttributeBinding.getValue() );
|
||||
assertTrue( idAttributeBinding.getValue() instanceof Column );
|
||||
|
||||
AttributeBinding nameBinding = entityBinding.getAttributeBinding( "name" );
|
||||
assertNotNull( nameBinding );
|
||||
assertNotNull( nameBinding.getAttribute() );
|
||||
assertNotNull( nameBinding.getValue() );
|
||||
}
|
||||
XmlDocument xmlDocument = readResource( "/org/hibernate/metamodel/binding/SimpleVersionedEntity.hbm.xml" );
|
||||
metadata.getHibernateXmlBinder().bindRoot( xmlDocument );
|
||||
return metadata.getEntityBinding( SimpleVersionedEntity.class.getName() );
|
||||
}
|
||||
|
||||
private XmlDocument readResource(final String name) {
|
||||
final String path = "/org/hibernate/test/id/Car.hbm.xml";
|
||||
Origin origin = new Origin() {
|
||||
@Override
|
||||
public String getType() {
|
||||
|
|
|
@ -23,10 +23,15 @@
|
|||
*/
|
||||
package org.hibernate.metamodel.binding;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@Entity
|
||||
public class SimpleEntity {
|
||||
@Id
|
||||
private Long id;
|
||||
private String name;
|
||||
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2010, 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.binding;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@Entity
|
||||
public class SimpleEntitySubClass extends SimpleEntity {
|
||||
|
||||
public SimpleEntitySubClass() {
|
||||
}
|
||||
}
|
|
@ -25,6 +25,8 @@ package org.hibernate.metamodel.binding;
|
|||
|
||||
import java.sql.Types;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.hibernate.metamodel.domain.Entity;
|
||||
import org.hibernate.metamodel.domain.SingularAttribute;
|
||||
import org.hibernate.metamodel.relational.Column;
|
||||
|
@ -32,9 +34,6 @@ import org.hibernate.metamodel.relational.Datatype;
|
|||
import org.hibernate.metamodel.relational.Schema;
|
||||
import org.hibernate.metamodel.relational.Size;
|
||||
import org.hibernate.metamodel.relational.Table;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.hibernate.testing.junit4.BaseUnitTestCase;
|
||||
|
||||
import static org.junit.Assert.assertSame;
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
package org.hibernate.metamodel.binding;
|
||||
|
||||
/**
|
||||
* TODO : javadoc
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class SimpleVersionedEntity {
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
@GenericGenerator(name = "myGenerator", strategy = "sequence")
|
||||
package org.hibernate.metamodel.binding;
|
||||
|
||||
import org.hibernate.annotations.GenericGenerator;
|
|
@ -0,0 +1,24 @@
|
|||
package org.hibernate.metamodel.source.annotations;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.hibernate.testing.junit4.BaseUnitTestCase;
|
||||
|
||||
/**
|
||||
* @author Hardy Ferentschik
|
||||
*/
|
||||
public class OrmXmlParserTests extends BaseUnitTestCase {
|
||||
@Test
|
||||
public void testSingleOrmXml() {
|
||||
OrmXmlParser parser = new OrmXmlParser();
|
||||
Set<String> xmlFiles = new HashSet<String>();
|
||||
xmlFiles.add( "org/hibernate/metamodel/source/annotations/orm.xml" );
|
||||
parser.parseAndUpdateIndex( xmlFiles, null );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
<?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"
|
||||
version="2.0">
|
||||
<package>org.hibernate.test.annotations.onetoone</package>
|
||||
<entity class="Father">
|
||||
<attributes>
|
||||
<id name="id">
|
||||
<generated-value strategy="AUTO"/>
|
||||
</id>
|
||||
<basic name="name"/>
|
||||
</attributes>
|
||||
</entity>
|
||||
<entity class="Son">
|
||||
<attributes>
|
||||
<id name="id">
|
||||
<generated-value strategy="AUTO"/>
|
||||
</id>
|
||||
<basic name="name"/>
|
||||
<one-to-one name="father">
|
||||
<join-table name="father_son">
|
||||
<join-column name="foo"/>
|
||||
<inverse-join-column name="bar"/>
|
||||
</join-table>
|
||||
</one-to-one>
|
||||
</attributes>
|
||||
</entity>
|
||||
</entity-mappings>
|
Loading…
Reference in New Issue