HHH-6291 - Basic MetadataImpl redesign
This commit is contained in:
parent
b8b003efa3
commit
baeb6dc400
|
@ -37,6 +37,7 @@ import org.hibernate.internal.util.ReflectHelper;
|
||||||
import org.hibernate.metamodel.domain.Entity;
|
import org.hibernate.metamodel.domain.Entity;
|
||||||
import org.hibernate.metamodel.relational.Column;
|
import org.hibernate.metamodel.relational.Column;
|
||||||
import org.hibernate.metamodel.relational.TableSpecification;
|
import org.hibernate.metamodel.relational.TableSpecification;
|
||||||
|
import org.hibernate.metamodel.source.hbm.HbmBindingContext;
|
||||||
import org.hibernate.metamodel.source.hbm.HbmHelper;
|
import org.hibernate.metamodel.source.hbm.HbmHelper;
|
||||||
import org.hibernate.metamodel.source.hbm.util.MappingHelper;
|
import org.hibernate.metamodel.source.hbm.util.MappingHelper;
|
||||||
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLHibernateMapping.XMLClass;
|
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLHibernateMapping.XMLClass;
|
||||||
|
@ -44,7 +45,6 @@ import org.hibernate.metamodel.source.hbm.xml.mapping.XMLSqlDeleteElement;
|
||||||
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLSqlInsertElement;
|
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLSqlInsertElement;
|
||||||
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLSqlUpdateElement;
|
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLSqlUpdateElement;
|
||||||
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLSynchronizeElement;
|
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLSynchronizeElement;
|
||||||
import org.hibernate.metamodel.source.spi.BindingContext;
|
|
||||||
import org.hibernate.metamodel.source.spi.MetaAttributeContext;
|
import org.hibernate.metamodel.source.spi.MetaAttributeContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -101,7 +101,7 @@ public class EntityBinding {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: change to intialize from Doimain
|
// TODO: change to intialize from Doimain
|
||||||
public void fromHbmXml(BindingContext bindingContext, XMLClass entityClazz, Entity entity) {
|
public void fromHbmXml(HbmBindingContext bindingContext, XMLClass entityClazz, Entity entity) {
|
||||||
this.entity = entity;
|
this.entity = entity;
|
||||||
metaAttributeContext = HbmHelper.extractMetaAttributeContext( entityClazz.getMeta(), true, bindingContext.getMetaAttributeContext() );
|
metaAttributeContext = HbmHelper.extractMetaAttributeContext( entityClazz.getMeta(), true, bindingContext.getMetaAttributeContext() );
|
||||||
|
|
||||||
|
|
|
@ -23,11 +23,18 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.metamodel.source.annotations;
|
package org.hibernate.metamodel.source.annotations;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.internal.CoreMessageLogger;
|
import org.hibernate.internal.CoreMessageLogger;
|
||||||
import org.jboss.jandex.Index;
|
import org.jboss.jandex.Index;
|
||||||
|
|
||||||
|
import org.hibernate.metamodel.MetadataSources;
|
||||||
|
import org.hibernate.metamodel.source.annotation.xml.XMLEntityMappings;
|
||||||
import org.hibernate.metamodel.source.annotations.entity.ConfiguredClass;
|
import org.hibernate.metamodel.source.annotations.entity.ConfiguredClass;
|
||||||
import org.hibernate.metamodel.source.annotations.entity.ConfiguredClassHierarchy;
|
import org.hibernate.metamodel.source.annotations.entity.ConfiguredClassHierarchy;
|
||||||
import org.hibernate.metamodel.source.annotations.entity.EntityBinder;
|
import org.hibernate.metamodel.source.annotations.entity.EntityBinder;
|
||||||
|
@ -38,7 +45,14 @@ import org.hibernate.metamodel.source.annotations.global.TypeDefBinder;
|
||||||
import org.hibernate.metamodel.source.annotations.global.FetchProfileBinder;
|
import org.hibernate.metamodel.source.annotations.global.FetchProfileBinder;
|
||||||
import org.hibernate.metamodel.source.annotations.global.TableBinder;
|
import org.hibernate.metamodel.source.annotations.global.TableBinder;
|
||||||
import org.hibernate.metamodel.source.annotations.util.ConfiguredClassHierarchyBuilder;
|
import org.hibernate.metamodel.source.annotations.util.ConfiguredClassHierarchyBuilder;
|
||||||
|
import org.hibernate.metamodel.source.annotations.xml.OrmXmlParser;
|
||||||
|
import org.hibernate.metamodel.source.internal.JaxbRoot;
|
||||||
import org.hibernate.metamodel.source.internal.MetadataImpl;
|
import org.hibernate.metamodel.source.internal.MetadataImpl;
|
||||||
|
import org.hibernate.metamodel.source.spi.Binder;
|
||||||
|
import org.hibernate.metamodel.source.spi.MetadataImplementor;
|
||||||
|
import org.hibernate.service.classloading.spi.ClassLoaderService;
|
||||||
|
|
||||||
|
import org.jboss.jandex.Indexer;
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -48,35 +62,77 @@ import org.jboss.logging.Logger;
|
||||||
*
|
*
|
||||||
* @author Hardy Ferentschik
|
* @author Hardy Ferentschik
|
||||||
*/
|
*/
|
||||||
public class AnnotationBinder {
|
public class AnnotationBinder implements Binder {
|
||||||
|
|
||||||
private static final CoreMessageLogger LOG = Logger.getMessageLogger( CoreMessageLogger.class, AnnotationBinder.class.getName() );
|
private static final CoreMessageLogger LOG = Logger.getMessageLogger( CoreMessageLogger.class, AnnotationBinder.class.getName() );
|
||||||
private final MetadataImpl metadata;
|
|
||||||
private final Index index;
|
|
||||||
|
|
||||||
public AnnotationBinder(MetadataImpl metadata, Index index) {
|
private final MetadataImplementor metadata;
|
||||||
|
|
||||||
|
private Index index;
|
||||||
|
private ClassLoaderService classLoaderService;
|
||||||
|
|
||||||
|
public AnnotationBinder(MetadataImpl metadata) {
|
||||||
this.metadata = metadata;
|
this.metadata = metadata;
|
||||||
this.index = index;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void bind() {
|
@Override
|
||||||
preEntityBindings();
|
@SuppressWarnings( {"unchecked"})
|
||||||
bindMappedClasses();
|
public void prepare(MetadataSources sources) {
|
||||||
postEntityBindings();
|
// create a jandex index from the annotated classes
|
||||||
|
Indexer indexer = new Indexer();
|
||||||
|
for ( Class<?> clazz : sources.getAnnotatedClasses() ) {
|
||||||
|
indexClass( indexer, clazz.getName().replace( '.', '/' ) + ".class" );
|
||||||
|
}
|
||||||
|
|
||||||
|
// add package-info from the configured packages
|
||||||
|
for ( String packageName : sources.getAnnotatedPackages() ) {
|
||||||
|
indexClass( indexer, packageName.replace( '.', '/' ) + "/package-info.class" );
|
||||||
|
}
|
||||||
|
|
||||||
|
index = indexer.complete();
|
||||||
|
|
||||||
|
List<JaxbRoot<XMLEntityMappings>> mappings = new ArrayList<JaxbRoot<XMLEntityMappings>>();
|
||||||
|
for ( JaxbRoot<?> root : sources.getJaxbRootList() ) {
|
||||||
|
if ( root.getRoot() instanceof XMLEntityMappings ) {
|
||||||
|
mappings.add( (JaxbRoot<XMLEntityMappings>) root );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( !mappings.isEmpty() ) {
|
||||||
|
// process the xml configuration
|
||||||
|
final OrmXmlParser ormParser = new OrmXmlParser( metadata );
|
||||||
|
index = ormParser.parseAndUpdateIndex( mappings, index );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private void indexClass(Indexer indexer, String className) {
|
||||||
* Binds global configuration data prior to entity binding. This includes generators and type definitions.
|
InputStream stream = classLoaderService().locateResourceStream( className );
|
||||||
*/
|
try {
|
||||||
private void preEntityBindings() {
|
indexer.index( stream );
|
||||||
TypeDefBinder.bind(metadata, index);
|
}
|
||||||
IdGeneratorBinder.bind(metadata, index);
|
catch ( IOException e ) {
|
||||||
|
throw new HibernateException( "Unable to open input stream for class " + className, e );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private ClassLoaderService classLoaderService(){
|
||||||
* Does the actual entity binding (see {@link org.hibernate.metamodel.binding.EntityBinding}.
|
if ( classLoaderService == null ) {
|
||||||
*/
|
classLoaderService = metadata.getServiceRegistry().getService( ClassLoaderService.class );
|
||||||
private void bindMappedClasses() {
|
}
|
||||||
|
return classLoaderService;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void bindIndependentMetadata(MetadataSources sources) {
|
||||||
|
TypeDefBinder.bind( metadata, index );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void bindTypeDependentMetadata(MetadataSources sources) {
|
||||||
|
IdGeneratorBinder.bind( metadata, index );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void bindMappingMetadata(MetadataSources sources, List<String> processedEntityNames) {
|
||||||
// need to order our annotated entities into an order we can process
|
// need to order our annotated entities into an order we can process
|
||||||
Set<ConfiguredClassHierarchy> hierarchies = ConfiguredClassHierarchyBuilder.createEntityHierarchies(
|
Set<ConfiguredClassHierarchy> hierarchies = ConfiguredClassHierarchyBuilder.createEntityHierarchies(
|
||||||
index, metadata.getServiceRegistry()
|
index, metadata.getServiceRegistry()
|
||||||
|
@ -92,15 +148,12 @@ public class AnnotationBinder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Binds global configuration data post entity binding. This includes mappings which live outside of the configuration for a single
|
public void bindMappingDependentMetadata(MetadataSources sources) {
|
||||||
* entity or entity hierarchy, for example sequence generators, fetch profiles, etc
|
|
||||||
*/
|
|
||||||
private void postEntityBindings() {
|
|
||||||
TableBinder.bind( metadata, index );
|
TableBinder.bind( metadata, index );
|
||||||
FetchProfileBinder.bind( metadata, index );
|
FetchProfileBinder.bind( metadata, index );
|
||||||
QueryBinder.bind(metadata, index);
|
QueryBinder.bind( metadata, index );
|
||||||
FilterDefBinder.bind(metadata, index);
|
FilterDefBinder.bind( metadata, index );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,121 +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 java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.jboss.jandex.Index;
|
|
||||||
import org.jboss.jandex.Indexer;
|
|
||||||
|
|
||||||
import org.hibernate.HibernateException;
|
|
||||||
import org.hibernate.metamodel.MetadataSources;
|
|
||||||
import org.hibernate.metamodel.source.annotation.xml.XMLEntityMappings;
|
|
||||||
import org.hibernate.metamodel.source.annotations.xml.OrmXmlParser;
|
|
||||||
import org.hibernate.metamodel.source.internal.JaxbRoot;
|
|
||||||
import org.hibernate.metamodel.source.spi.Binder;
|
|
||||||
import org.hibernate.metamodel.source.spi.MetadataImplementor;
|
|
||||||
import org.hibernate.service.classloading.spi.ClassLoaderService;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Steve Ebersole
|
|
||||||
*/
|
|
||||||
public class JpaBinder implements Binder {
|
|
||||||
private final MetadataImplementor metadata;
|
|
||||||
|
|
||||||
private Index index;
|
|
||||||
private ClassLoaderService classLoaderService;
|
|
||||||
|
|
||||||
public JpaBinder(MetadataImplementor metadata) {
|
|
||||||
this.metadata = metadata;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@SuppressWarnings( {"unchecked"})
|
|
||||||
public void prepare(MetadataSources sources) {
|
|
||||||
// create a jandex index from the annotated classes
|
|
||||||
Indexer indexer = new Indexer();
|
|
||||||
for ( Class<?> clazz : sources.getAnnotatedClasses() ) {
|
|
||||||
indexClass( indexer, clazz.getName().replace( '.', '/' ) + ".class" );
|
|
||||||
}
|
|
||||||
|
|
||||||
// add package-info from the configured packages
|
|
||||||
for ( String packageName : sources.getAnnotatedPackages() ) {
|
|
||||||
indexClass( indexer, packageName.replace( '.', '/' ) + "/package-info.class" );
|
|
||||||
}
|
|
||||||
|
|
||||||
index = indexer.complete();
|
|
||||||
|
|
||||||
List<JaxbRoot<XMLEntityMappings>> mappings = new ArrayList<JaxbRoot<XMLEntityMappings>>();
|
|
||||||
for ( JaxbRoot<?> root : sources.getJaxbRootList() ) {
|
|
||||||
if ( root.getRoot() instanceof XMLEntityMappings ) {
|
|
||||||
mappings.add( (JaxbRoot<XMLEntityMappings>) root );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( !mappings.isEmpty() ) {
|
|
||||||
// process the xml configuration
|
|
||||||
final OrmXmlParser ormParser = new OrmXmlParser( metadata );
|
|
||||||
index = ormParser.parseAndUpdateIndex( mappings, index );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void indexClass(Indexer indexer, String className) {
|
|
||||||
InputStream stream = classLoaderService().locateResourceStream( className );
|
|
||||||
try {
|
|
||||||
indexer.index( stream );
|
|
||||||
}
|
|
||||||
catch ( IOException e ) {
|
|
||||||
throw new HibernateException( "Unable to open input stream for class " + className, e );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private ClassLoaderService classLoaderService(){
|
|
||||||
if ( classLoaderService == null ) {
|
|
||||||
classLoaderService = metadata.getServiceRegistry().getService( ClassLoaderService.class );
|
|
||||||
}
|
|
||||||
return classLoaderService;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void bindIndependentMetadata(MetadataSources sources) {
|
|
||||||
// todo : implement method body
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void bindTypeDependentMetadata(MetadataSources sources) {
|
|
||||||
// todo : implement method body
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void bindMappingMetadata(MetadataSources sources, List<String> processedEntityNames) {
|
|
||||||
// todo : implement method body
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void bindMappingDependentMetadata(MetadataSources sources) {
|
|
||||||
// todo : implement method body
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -36,7 +36,7 @@ import org.hibernate.metamodel.binding.FetchProfile;
|
||||||
import org.hibernate.metamodel.binding.FetchProfile.Fetch;
|
import org.hibernate.metamodel.binding.FetchProfile.Fetch;
|
||||||
import org.hibernate.metamodel.source.annotations.HibernateDotNames;
|
import org.hibernate.metamodel.source.annotations.HibernateDotNames;
|
||||||
import org.hibernate.metamodel.source.annotations.util.JandexHelper;
|
import org.hibernate.metamodel.source.annotations.util.JandexHelper;
|
||||||
import org.hibernate.metamodel.source.internal.MetadataImpl;
|
import org.hibernate.metamodel.source.spi.MetadataImplementor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Binds fetch profiles found in annotations.
|
* Binds fetch profiles found in annotations.
|
||||||
|
@ -52,8 +52,7 @@ public class FetchProfileBinder {
|
||||||
* @param jandex the jandex index
|
* @param jandex the jandex index
|
||||||
*/
|
*/
|
||||||
// TODO verify that association exists. See former VerifyFetchProfileReferenceSecondPass
|
// TODO verify that association exists. See former VerifyFetchProfileReferenceSecondPass
|
||||||
public static void bind(MetadataImpl metadata,
|
public static void bind(MetadataImplementor metadata, Index jandex) {
|
||||||
Index jandex) {
|
|
||||||
for ( AnnotationInstance fetchProfile : jandex.getAnnotations( HibernateDotNames.FETCH_PROFILE ) ) {
|
for ( AnnotationInstance fetchProfile : jandex.getAnnotations( HibernateDotNames.FETCH_PROFILE ) ) {
|
||||||
bind( metadata, fetchProfile );
|
bind( metadata, fetchProfile );
|
||||||
}
|
}
|
||||||
|
@ -64,8 +63,7 @@ public class FetchProfileBinder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void bind(MetadataImpl metadata,
|
private static void bind(MetadataImplementor metadata, AnnotationInstance fetchProfile) {
|
||||||
AnnotationInstance fetchProfile) {
|
|
||||||
String name = JandexHelper.getValueAsString( fetchProfile, "name" );
|
String name = JandexHelper.getValueAsString( fetchProfile, "name" );
|
||||||
Set<Fetch> fetches = new HashSet<Fetch>();
|
Set<Fetch> fetches = new HashSet<Fetch>();
|
||||||
for ( AnnotationInstance override : JandexHelper.getValueAsArray( fetchProfile, "fetchOverrides" ) ) {
|
for ( AnnotationInstance override : JandexHelper.getValueAsArray( fetchProfile, "fetchOverrides" ) ) {
|
||||||
|
@ -76,9 +74,9 @@ public class FetchProfileBinder {
|
||||||
fetches.add(
|
fetches.add(
|
||||||
new Fetch(
|
new Fetch(
|
||||||
JandexHelper.getValueAsString( override, "entity" ), JandexHelper.getValueAsString(
|
JandexHelper.getValueAsString( override, "entity" ), JandexHelper.getValueAsString(
|
||||||
override,
|
override,
|
||||||
"association"
|
"association"
|
||||||
),
|
),
|
||||||
fetchMode.toString().toLowerCase()
|
fetchMode.toString().toLowerCase()
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
|
@ -36,7 +36,7 @@ import org.hibernate.engine.spi.FilterDefinition;
|
||||||
import org.hibernate.internal.CoreMessageLogger;
|
import org.hibernate.internal.CoreMessageLogger;
|
||||||
import org.hibernate.metamodel.source.annotations.HibernateDotNames;
|
import org.hibernate.metamodel.source.annotations.HibernateDotNames;
|
||||||
import org.hibernate.metamodel.source.annotations.util.JandexHelper;
|
import org.hibernate.metamodel.source.annotations.util.JandexHelper;
|
||||||
import org.hibernate.metamodel.source.internal.MetadataImpl;
|
import org.hibernate.metamodel.source.spi.MetadataImplementor;
|
||||||
import org.hibernate.type.Type;
|
import org.hibernate.type.Type;
|
||||||
|
|
||||||
public class FilterDefBinder {
|
public class FilterDefBinder {
|
||||||
|
@ -52,8 +52,7 @@ public class FilterDefBinder {
|
||||||
* @param metadata the global metadata
|
* @param metadata the global metadata
|
||||||
* @param jandex the jandex index
|
* @param jandex the jandex index
|
||||||
*/
|
*/
|
||||||
public static void bind(MetadataImpl metadata,
|
public static void bind(MetadataImplementor metadata, Index jandex) {
|
||||||
Index jandex) {
|
|
||||||
for ( AnnotationInstance filterDef : jandex.getAnnotations( HibernateDotNames.FILTER_DEF ) ) {
|
for ( AnnotationInstance filterDef : jandex.getAnnotations( HibernateDotNames.FILTER_DEF ) ) {
|
||||||
bind( metadata, filterDef );
|
bind( metadata, filterDef );
|
||||||
}
|
}
|
||||||
|
@ -64,8 +63,7 @@ public class FilterDefBinder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void bind(MetadataImpl metadata,
|
private static void bind(MetadataImplementor metadata, AnnotationInstance filterDef) {
|
||||||
AnnotationInstance filterDef) {
|
|
||||||
String name = JandexHelper.getValueAsString( filterDef, "name" );
|
String name = JandexHelper.getValueAsString( filterDef, "name" );
|
||||||
Map<String, Type> prms = new HashMap<String, Type>();
|
Map<String, Type> prms = new HashMap<String, Type>();
|
||||||
for ( AnnotationInstance prm : JandexHelper.getValueAsArray( filterDef, "parameters" ) ) {
|
for ( AnnotationInstance prm : JandexHelper.getValueAsArray( filterDef, "parameters" ) ) {
|
||||||
|
|
|
@ -23,10 +23,10 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.metamodel.source.annotations.global;
|
package org.hibernate.metamodel.source.annotations.global;
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import javax.persistence.GenerationType;
|
import javax.persistence.GenerationType;
|
||||||
import javax.persistence.SequenceGenerator;
|
import javax.persistence.SequenceGenerator;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import org.jboss.jandex.AnnotationInstance;
|
import org.jboss.jandex.AnnotationInstance;
|
||||||
import org.jboss.jandex.Index;
|
import org.jboss.jandex.Index;
|
||||||
|
@ -48,7 +48,7 @@ import org.hibernate.metamodel.binding.IdGenerator;
|
||||||
import org.hibernate.metamodel.source.annotations.HibernateDotNames;
|
import org.hibernate.metamodel.source.annotations.HibernateDotNames;
|
||||||
import org.hibernate.metamodel.source.annotations.JPADotNames;
|
import org.hibernate.metamodel.source.annotations.JPADotNames;
|
||||||
import org.hibernate.metamodel.source.annotations.util.JandexHelper;
|
import org.hibernate.metamodel.source.annotations.util.JandexHelper;
|
||||||
import org.hibernate.metamodel.source.internal.MetadataImpl;
|
import org.hibernate.metamodel.source.spi.MetadataImplementor;
|
||||||
|
|
||||||
public class IdGeneratorBinder {
|
public class IdGeneratorBinder {
|
||||||
|
|
||||||
|
@ -57,6 +57,9 @@ public class IdGeneratorBinder {
|
||||||
IdGeneratorBinder.class.getName()
|
IdGeneratorBinder.class.getName()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
private IdGeneratorBinder() {
|
||||||
|
}
|
||||||
|
|
||||||
private static void addStringParameter(AnnotationInstance annotation,
|
private static void addStringParameter(AnnotationInstance annotation,
|
||||||
String element,
|
String element,
|
||||||
Map<String, String> parameters,
|
Map<String, String> parameters,
|
||||||
|
@ -74,8 +77,7 @@ public class IdGeneratorBinder {
|
||||||
* @param metadata the global metadata
|
* @param metadata the global metadata
|
||||||
* @param jandex the jandex index
|
* @param jandex the jandex index
|
||||||
*/
|
*/
|
||||||
public static void bind(MetadataImpl metadata,
|
public static void bind(MetadataImplementor metadata, Index jandex) {
|
||||||
Index jandex) {
|
|
||||||
for ( AnnotationInstance generator : jandex.getAnnotations( JPADotNames.SEQUENCE_GENERATOR ) ) {
|
for ( AnnotationInstance generator : jandex.getAnnotations( JPADotNames.SEQUENCE_GENERATOR ) ) {
|
||||||
bindSequenceGenerator( metadata, generator );
|
bindSequenceGenerator( metadata, generator );
|
||||||
}
|
}
|
||||||
|
@ -92,8 +94,7 @@ public class IdGeneratorBinder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void bindGenericGenerator(MetadataImpl metadata,
|
private static void bindGenericGenerator(MetadataImplementor metadata, AnnotationInstance generator) {
|
||||||
AnnotationInstance generator) {
|
|
||||||
String name = JandexHelper.getValueAsString( generator, "name" );
|
String name = JandexHelper.getValueAsString( generator, "name" );
|
||||||
Map<String, String> prms = new HashMap<String, String>();
|
Map<String, String> prms = new HashMap<String, String>();
|
||||||
for ( AnnotationInstance prm : JandexHelper.getValueAsArray( generator, "parameters" ) ) {
|
for ( AnnotationInstance prm : JandexHelper.getValueAsArray( generator, "parameters" ) ) {
|
||||||
|
@ -109,8 +110,7 @@ public class IdGeneratorBinder {
|
||||||
LOG.tracef( "Add generic generator with name: %s", name );
|
LOG.tracef( "Add generic generator with name: %s", name );
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void bindSequenceGenerator(MetadataImpl metadata,
|
private static void bindSequenceGenerator(MetadataImplementor metadata, AnnotationInstance generator) {
|
||||||
AnnotationInstance generator) {
|
|
||||||
String name = JandexHelper.getValueAsString( generator, "name" );
|
String name = JandexHelper.getValueAsString( generator, "name" );
|
||||||
String strategy;
|
String strategy;
|
||||||
Map<String, String> prms = new HashMap<String, String>();
|
Map<String, String> prms = new HashMap<String, String>();
|
||||||
|
@ -142,8 +142,7 @@ public class IdGeneratorBinder {
|
||||||
LOG.tracef( "Add sequence generator with name: %s", name );
|
LOG.tracef( "Add sequence generator with name: %s", name );
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void bindTableGenerator(MetadataImpl metadata,
|
private static void bindTableGenerator(MetadataImplementor metadata, AnnotationInstance generator) {
|
||||||
AnnotationInstance generator) {
|
|
||||||
String name = JandexHelper.getValueAsString( generator, "name" );
|
String name = JandexHelper.getValueAsString( generator, "name" );
|
||||||
String strategy;
|
String strategy;
|
||||||
Map<String, String> prms = new HashMap<String, String>();
|
Map<String, String> prms = new HashMap<String, String>();
|
||||||
|
@ -183,9 +182,6 @@ public class IdGeneratorBinder {
|
||||||
LOG.tracef( "Add table generator with name: %s", name );
|
LOG.tracef( "Add table generator with name: %s", name );
|
||||||
}
|
}
|
||||||
|
|
||||||
private IdGeneratorBinder() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String generatorType(GenerationType generatorEnum, boolean useNewGeneratorMappings) {
|
public static String generatorType(GenerationType generatorEnum, boolean useNewGeneratorMappings) {
|
||||||
switch ( generatorEnum ) {
|
switch ( generatorEnum ) {
|
||||||
case IDENTITY:
|
case IDENTITY:
|
||||||
|
|
|
@ -23,11 +23,11 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.metamodel.source.annotations.global;
|
package org.hibernate.metamodel.source.annotations.global;
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import javax.persistence.NamedNativeQueries;
|
import javax.persistence.NamedNativeQueries;
|
||||||
import javax.persistence.NamedNativeQuery;
|
import javax.persistence.NamedNativeQuery;
|
||||||
import javax.persistence.NamedQueries;
|
import javax.persistence.NamedQueries;
|
||||||
import javax.persistence.NamedQuery;
|
import javax.persistence.NamedQuery;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
import org.jboss.jandex.AnnotationInstance;
|
import org.jboss.jandex.AnnotationInstance;
|
||||||
import org.jboss.jandex.Index;
|
import org.jboss.jandex.Index;
|
||||||
|
@ -47,7 +47,7 @@ import org.hibernate.internal.util.StringHelper;
|
||||||
import org.hibernate.metamodel.source.annotations.HibernateDotNames;
|
import org.hibernate.metamodel.source.annotations.HibernateDotNames;
|
||||||
import org.hibernate.metamodel.source.annotations.JPADotNames;
|
import org.hibernate.metamodel.source.annotations.JPADotNames;
|
||||||
import org.hibernate.metamodel.source.annotations.util.JandexHelper;
|
import org.hibernate.metamodel.source.annotations.util.JandexHelper;
|
||||||
import org.hibernate.metamodel.source.internal.MetadataImpl;
|
import org.hibernate.metamodel.source.spi.MetadataImplementor;
|
||||||
|
|
||||||
public class QueryBinder {
|
public class QueryBinder {
|
||||||
|
|
||||||
|
@ -65,8 +65,7 @@ public class QueryBinder {
|
||||||
* @param metadata the global metadata
|
* @param metadata the global metadata
|
||||||
* @param jandex the jandex index
|
* @param jandex the jandex index
|
||||||
*/
|
*/
|
||||||
public static void bind(MetadataImpl metadata,
|
public static void bind(MetadataImplementor metadata, Index jandex) {
|
||||||
Index jandex) {
|
|
||||||
for ( AnnotationInstance query : jandex.getAnnotations( JPADotNames.NAMED_QUERY ) ) {
|
for ( AnnotationInstance query : jandex.getAnnotations( JPADotNames.NAMED_QUERY ) ) {
|
||||||
bindNamedQuery( metadata, query );
|
bindNamedQuery( metadata, query );
|
||||||
}
|
}
|
||||||
|
@ -101,8 +100,7 @@ public class QueryBinder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void bindNamedQuery(MetadataImpl metadata,
|
private static void bindNamedQuery(MetadataImplementor metadata, AnnotationInstance annotation) {
|
||||||
AnnotationInstance annotation) {
|
|
||||||
String name = JandexHelper.getValueAsString( annotation, "name" );
|
String name = JandexHelper.getValueAsString( annotation, "name" );
|
||||||
if ( StringHelper.isEmpty( name ) ) {
|
if ( StringHelper.isEmpty( name ) ) {
|
||||||
throw new AnnotationException( "A named query must have a name when used in class or package level" );
|
throw new AnnotationException( "A named query must have a name when used in class or package level" );
|
||||||
|
@ -137,8 +135,7 @@ public class QueryBinder {
|
||||||
LOG.debugf( "Binding named query: %s => %s", name, query );
|
LOG.debugf( "Binding named query: %s => %s", name, query );
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void bindNamedNativeQuery(MetadataImpl metadata,
|
private static void bindNamedNativeQuery(MetadataImplementor metadata, AnnotationInstance annotation) {
|
||||||
AnnotationInstance annotation) {
|
|
||||||
String name = JandexHelper.getValueAsString( annotation, "name" );
|
String name = JandexHelper.getValueAsString( annotation, "name" );
|
||||||
if ( StringHelper.isEmpty( name ) ) {
|
if ( StringHelper.isEmpty( name ) ) {
|
||||||
throw new AnnotationException( "A named native query must have a name when used in class or package level" );
|
throw new AnnotationException( "A named native query must have a name when used in class or package level" );
|
||||||
|
|
|
@ -37,7 +37,7 @@ import org.hibernate.metamodel.relational.SimpleValue;
|
||||||
import org.hibernate.metamodel.relational.Table;
|
import org.hibernate.metamodel.relational.Table;
|
||||||
import org.hibernate.metamodel.source.annotations.HibernateDotNames;
|
import org.hibernate.metamodel.source.annotations.HibernateDotNames;
|
||||||
import org.hibernate.metamodel.source.annotations.util.JandexHelper;
|
import org.hibernate.metamodel.source.annotations.util.JandexHelper;
|
||||||
import org.hibernate.metamodel.source.internal.MetadataImpl;
|
import org.hibernate.metamodel.source.spi.MetadataImplementor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Binds table related information. This binder is called after the entities are bound.
|
* Binds table related information. This binder is called after the entities are bound.
|
||||||
|
@ -58,8 +58,7 @@ public class TableBinder {
|
||||||
* @param metadata the global metadata
|
* @param metadata the global metadata
|
||||||
* @param jandex the annotation index repository
|
* @param jandex the annotation index repository
|
||||||
*/
|
*/
|
||||||
public static void bind(MetadataImpl metadata,
|
public static void bind(MetadataImplementor metadata, Index jandex) {
|
||||||
Index jandex) {
|
|
||||||
for ( AnnotationInstance tableAnnotation : jandex.getAnnotations( HibernateDotNames.TABLE ) ) {
|
for ( AnnotationInstance tableAnnotation : jandex.getAnnotations( HibernateDotNames.TABLE ) ) {
|
||||||
bind( metadata, tableAnnotation );
|
bind( metadata, tableAnnotation );
|
||||||
}
|
}
|
||||||
|
@ -70,8 +69,7 @@ public class TableBinder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void bind(MetadataImpl metadata,
|
private static void bind(MetadataImplementor metadata, AnnotationInstance tableAnnotation) {
|
||||||
AnnotationInstance tableAnnotation) {
|
|
||||||
String tableName = JandexHelper.getValueAsString( tableAnnotation, "appliesTo" );
|
String tableName = JandexHelper.getValueAsString( tableAnnotation, "appliesTo" );
|
||||||
ObjectName objectName = new ObjectName( tableName );
|
ObjectName objectName = new ObjectName( tableName );
|
||||||
Schema schema = metadata.getDatabase().getSchema( objectName.getSchema(), objectName.getCatalog() );
|
Schema schema = metadata.getDatabase().getSchema( objectName.getSchema(), objectName.getCatalog() );
|
||||||
|
@ -81,8 +79,7 @@ public class TableBinder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void bindHibernateTableAnnotation(Table table,
|
private static void bindHibernateTableAnnotation(Table table, AnnotationInstance tableAnnotation) {
|
||||||
AnnotationInstance tableAnnotation) {
|
|
||||||
for ( AnnotationInstance indexAnnotation : JandexHelper.getValueAsArray( tableAnnotation, "indexes" ) ) {
|
for ( AnnotationInstance indexAnnotation : JandexHelper.getValueAsArray( tableAnnotation, "indexes" ) ) {
|
||||||
bindIndexAnnotation( table, indexAnnotation );
|
bindIndexAnnotation( table, indexAnnotation );
|
||||||
}
|
}
|
||||||
|
@ -92,8 +89,7 @@ public class TableBinder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void bindIndexAnnotation(Table table,
|
private static void bindIndexAnnotation(Table table, AnnotationInstance indexAnnotation) {
|
||||||
AnnotationInstance indexAnnotation) {
|
|
||||||
String indexName = JandexHelper.getValueAsString( indexAnnotation, "appliesTo" );
|
String indexName = JandexHelper.getValueAsString( indexAnnotation, "appliesTo" );
|
||||||
String[] columnNames = (String[]) JandexHelper.getValue( indexAnnotation, "columnNames" );
|
String[] columnNames = (String[]) JandexHelper.getValue( indexAnnotation, "columnNames" );
|
||||||
if ( columnNames == null ) {
|
if ( columnNames == null ) {
|
||||||
|
@ -110,8 +106,7 @@ public class TableBinder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Column findColumn(Table table,
|
private static Column findColumn(Table table, String columnName) {
|
||||||
String columnName) {
|
|
||||||
Column column = null;
|
Column column = null;
|
||||||
for ( SimpleValue value : table.values() ) {
|
for ( SimpleValue value : table.values() ) {
|
||||||
if ( value instanceof Column && ( (Column) value ).getName().equals( columnName ) ) {
|
if ( value instanceof Column && ( (Column) value ).getName().equals( columnName ) ) {
|
||||||
|
|
|
@ -37,7 +37,7 @@ import org.hibernate.internal.util.StringHelper;
|
||||||
import org.hibernate.metamodel.binding.TypeDef;
|
import org.hibernate.metamodel.binding.TypeDef;
|
||||||
import org.hibernate.metamodel.source.annotations.HibernateDotNames;
|
import org.hibernate.metamodel.source.annotations.HibernateDotNames;
|
||||||
import org.hibernate.metamodel.source.annotations.util.JandexHelper;
|
import org.hibernate.metamodel.source.annotations.util.JandexHelper;
|
||||||
import org.hibernate.metamodel.source.internal.MetadataImpl;
|
import org.hibernate.metamodel.source.spi.MetadataImplementor;
|
||||||
|
|
||||||
public class TypeDefBinder {
|
public class TypeDefBinder {
|
||||||
|
|
||||||
|
@ -52,8 +52,7 @@ public class TypeDefBinder {
|
||||||
* @param metadata the global metadata
|
* @param metadata the global metadata
|
||||||
* @param jandex the jandex jandex
|
* @param jandex the jandex jandex
|
||||||
*/
|
*/
|
||||||
public static void bind(MetadataImpl metadata,
|
public static void bind(MetadataImplementor metadata, Index jandex) {
|
||||||
Index jandex) {
|
|
||||||
for ( AnnotationInstance typeDef : jandex.getAnnotations( HibernateDotNames.TYPE_DEF ) ) {
|
for ( AnnotationInstance typeDef : jandex.getAnnotations( HibernateDotNames.TYPE_DEF ) ) {
|
||||||
bind( metadata, typeDef );
|
bind( metadata, typeDef );
|
||||||
}
|
}
|
||||||
|
@ -64,8 +63,7 @@ public class TypeDefBinder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void bind(MetadataImpl metadata,
|
private static void bind(MetadataImplementor metadata, AnnotationInstance typeDef) {
|
||||||
AnnotationInstance typeDef) {
|
|
||||||
String name = JandexHelper.getValueAsString( typeDef, "name" );
|
String name = JandexHelper.getValueAsString( typeDef, "name" );
|
||||||
String defaultForType = JandexHelper.getValueAsString( typeDef, "defaultForType" );
|
String defaultForType = JandexHelper.getValueAsString( typeDef, "defaultForType" );
|
||||||
String typeClass = JandexHelper.getValueAsString( typeDef, "typeClass" );
|
String typeClass = JandexHelper.getValueAsString( typeDef, "typeClass" );
|
||||||
|
@ -89,10 +87,11 @@ public class TypeDefBinder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void bind(String name,
|
private static void bind(
|
||||||
String typeClass,
|
String name,
|
||||||
Map<String, String> prms,
|
String typeClass,
|
||||||
MetadataImpl metadata) {
|
Map<String, String> prms,
|
||||||
|
MetadataImplementor metadata) {
|
||||||
LOG.debugf( "Binding type definition: %s", name );
|
LOG.debugf( "Binding type definition: %s", name );
|
||||||
metadata.addTypeDefinition( new TypeDef( name, typeClass, prms ) );
|
metadata.addTypeDefinition( new TypeDef( name, typeClass, prms ) );
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,6 +76,7 @@ import org.hibernate.metamodel.binding.state.PluralAttributeBindingState;
|
||||||
import org.hibernate.metamodel.binding.state.SimpleAttributeBindingState;
|
import org.hibernate.metamodel.binding.state.SimpleAttributeBindingState;
|
||||||
import org.hibernate.metamodel.relational.state.TupleRelationalState;
|
import org.hibernate.metamodel.relational.state.TupleRelationalState;
|
||||||
import org.hibernate.metamodel.relational.state.ValueRelationalState;
|
import org.hibernate.metamodel.relational.state.ValueRelationalState;
|
||||||
|
import org.hibernate.metamodel.source.spi.BindingContext;
|
||||||
import org.hibernate.metamodel.source.spi.MetadataImplementor;
|
import org.hibernate.metamodel.source.spi.MetadataImplementor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -84,28 +85,27 @@ import org.hibernate.metamodel.source.spi.MetadataImplementor;
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
abstract class AbstractEntityBinder {
|
abstract class AbstractEntityBinder {
|
||||||
private final HbmBinder hibernateMappingBinder;
|
private final HbmBindingContext bindingContext;
|
||||||
private final Schema.Name schemaName;
|
private final Schema.Name schemaName;
|
||||||
|
|
||||||
AbstractEntityBinder(HbmBinder hibernateMappingBinder,
|
AbstractEntityBinder(HbmBindingContext bindingContext, XMLHibernateMapping.XMLClass entityClazz) {
|
||||||
XMLHibernateMapping.XMLClass entityClazz) {
|
this.bindingContext = bindingContext;
|
||||||
this.hibernateMappingBinder = hibernateMappingBinder;
|
|
||||||
this.schemaName = new Schema.Name(
|
this.schemaName = new Schema.Name(
|
||||||
( entityClazz.getSchema() == null ?
|
entityClazz.getSchema() == null
|
||||||
hibernateMappingBinder.getMappingDefaults().getDefaultSchemaName() :
|
? bindingContext.getMappingDefaults().getDefaultSchemaName()
|
||||||
entityClazz.getSchema() ),
|
: entityClazz.getSchema(),
|
||||||
( entityClazz.getCatalog() == null ?
|
entityClazz.getCatalog() == null
|
||||||
hibernateMappingBinder.getMappingDefaults().getDefaultCatalogName() :
|
? bindingContext.getMappingDefaults().getDefaultCatalogName() :
|
||||||
entityClazz.getCatalog() )
|
entityClazz.getCatalog()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public HbmBinder getHibernateMappingBinder() {
|
public HbmBindingContext getBindingContext() {
|
||||||
return hibernateMappingBinder;
|
return bindingContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected MetadataImplementor getMetadata() {
|
protected MetadataImplementor getMetadata() {
|
||||||
return hibernateMappingBinder.getMetadata();
|
return bindingContext.getMetadataImplementor();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Schema.Name getSchemaName() {
|
protected Schema.Name getSchemaName() {
|
||||||
|
@ -116,13 +116,14 @@ abstract class AbstractEntityBinder {
|
||||||
return getMetadata().getOptions().getNamingStrategy();
|
return getMetadata().getOptions().getNamingStrategy();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void basicEntityBinding(XMLHibernateMapping.XMLClass entityClazz,
|
protected void basicEntityBinding(
|
||||||
EntityBinding entityBinding,
|
XMLHibernateMapping.XMLClass entityClazz,
|
||||||
Hierarchical superType) {
|
EntityBinding entityBinding,
|
||||||
|
Hierarchical superType) {
|
||||||
entityBinding.fromHbmXml(
|
entityBinding.fromHbmXml(
|
||||||
hibernateMappingBinder,
|
bindingContext,
|
||||||
entityClazz,
|
entityClazz,
|
||||||
new Entity( hibernateMappingBinder.extractEntityName( entityClazz ), superType )
|
new Entity( bindingContext.extractEntityName( entityClazz ), superType )
|
||||||
);
|
);
|
||||||
// TODO: move this stuff out
|
// TODO: move this stuff out
|
||||||
// transfer an explicitly defined lazy attribute
|
// transfer an explicitly defined lazy attribute
|
||||||
|
@ -133,11 +134,11 @@ abstract class AbstractEntityBinder {
|
||||||
final String entityName = entityBinding.getEntity().getName();
|
final String entityName = entityBinding.getEntity().getName();
|
||||||
|
|
||||||
if ( entityClazz.getFetchProfile() != null ) {
|
if ( entityClazz.getFetchProfile() != null ) {
|
||||||
hibernateMappingBinder.bindFetchProfiles( entityClazz.getFetchProfile(), entityName );
|
bindingContext.bindFetchProfiles( entityClazz.getFetchProfile(), entityName );
|
||||||
}
|
}
|
||||||
|
|
||||||
getMetadata().addImport( entityName, entityName );
|
getMetadata().addImport( entityName, entityName );
|
||||||
if ( hibernateMappingBinder.isAutoImport() ) {
|
if ( bindingContext.isAutoImport() ) {
|
||||||
if ( entityName.indexOf( '.' ) > 0 ) {
|
if ( entityName.indexOf( '.' ) > 0 ) {
|
||||||
getMetadata().addImport( StringHelper.unqualify( entityName ), entityName );
|
getMetadata().addImport( StringHelper.unqualify( entityName ), entityName );
|
||||||
}
|
}
|
||||||
|
@ -145,12 +146,12 @@ abstract class AbstractEntityBinder {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String getDefaultAccess() {
|
protected String getDefaultAccess() {
|
||||||
return hibernateMappingBinder.getMappingDefaults().getDefaultAccess();
|
return bindingContext.getMappingDefaults().getDefaultAccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void bindPojoRepresentation(XMLHibernateMapping.XMLClass entityClazz,
|
private void bindPojoRepresentation(XMLHibernateMapping.XMLClass entityClazz,
|
||||||
EntityBinding entityBinding) {
|
EntityBinding entityBinding) {
|
||||||
String className = hibernateMappingBinder.getClassName( entityClazz.getName() );
|
String className = bindingContext.getClassName( entityClazz.getName() );
|
||||||
String proxyName = entityBinding.getProxyInterfaceName();
|
String proxyName = entityBinding.getProxyInterfaceName();
|
||||||
|
|
||||||
entityBinding.getEntity().getPojoEntitySpecifics().setClassName( className );
|
entityBinding.getEntity().getPojoEntitySpecifics().setClassName( className );
|
||||||
|
@ -291,7 +292,7 @@ abstract class AbstractEntityBinder {
|
||||||
if ( XMLBagElement.class.isInstance( attribute ) ) {
|
if ( XMLBagElement.class.isInstance( attribute ) ) {
|
||||||
XMLBagElement collection = XMLBagElement.class.cast( attribute );
|
XMLBagElement collection = XMLBagElement.class.cast( attribute );
|
||||||
BagBinding collectionBinding = makeBagAttributeBinding( collection, entityBinding );
|
BagBinding collectionBinding = makeBagAttributeBinding( collection, entityBinding );
|
||||||
hibernateMappingBinder.getMetadata().addCollection( collectionBinding );
|
bindingContext.getMetadataImplementor().addCollection( collectionBinding );
|
||||||
attributeBinding = collectionBinding;
|
attributeBinding = collectionBinding;
|
||||||
}
|
}
|
||||||
else if ( XMLIdbagElement.class.isInstance( attribute ) ) {
|
else if ( XMLIdbagElement.class.isInstance( attribute ) ) {
|
||||||
|
@ -444,7 +445,7 @@ PrimitiveArray
|
||||||
EntityBinding entityBinding) {
|
EntityBinding entityBinding) {
|
||||||
SimpleAttributeBindingState bindingState = new HbmSimpleAttributeBindingState(
|
SimpleAttributeBindingState bindingState = new HbmSimpleAttributeBindingState(
|
||||||
entityBinding.getEntity().getPojoEntitySpecifics().getClassName(),
|
entityBinding.getEntity().getPojoEntitySpecifics().getClassName(),
|
||||||
hibernateMappingBinder,
|
bindingContext,
|
||||||
entityBinding.getMetaAttributeContext(),
|
entityBinding.getMetaAttributeContext(),
|
||||||
property
|
property
|
||||||
);
|
);
|
||||||
|
@ -453,7 +454,7 @@ PrimitiveArray
|
||||||
ValueRelationalState relationalState =
|
ValueRelationalState relationalState =
|
||||||
convertToSimpleValueRelationalStateIfPossible(
|
convertToSimpleValueRelationalStateIfPossible(
|
||||||
new HbmSimpleValueRelationalStateContainer(
|
new HbmSimpleValueRelationalStateContainer(
|
||||||
hibernateMappingBinder,
|
bindingContext,
|
||||||
true,
|
true,
|
||||||
property
|
property
|
||||||
)
|
)
|
||||||
|
@ -483,7 +484,7 @@ PrimitiveArray
|
||||||
PluralAttributeBindingState bindingState =
|
PluralAttributeBindingState bindingState =
|
||||||
new HbmPluralAttributeBindingState(
|
new HbmPluralAttributeBindingState(
|
||||||
entityBinding.getEntity().getPojoEntitySpecifics().getClassName(),
|
entityBinding.getEntity().getPojoEntitySpecifics().getClassName(),
|
||||||
hibernateMappingBinder,
|
bindingContext,
|
||||||
entityBinding.getMetaAttributeContext(),
|
entityBinding.getMetaAttributeContext(),
|
||||||
collection
|
collection
|
||||||
);
|
);
|
||||||
|
@ -523,7 +524,7 @@ PrimitiveArray
|
||||||
ManyToOneAttributeBindingState bindingState =
|
ManyToOneAttributeBindingState bindingState =
|
||||||
new HbmManyToOneAttributeBindingState(
|
new HbmManyToOneAttributeBindingState(
|
||||||
entityBinding.getEntity().getPojoEntitySpecifics().getClassName(),
|
entityBinding.getEntity().getPojoEntitySpecifics().getClassName(),
|
||||||
hibernateMappingBinder,
|
bindingContext,
|
||||||
entityBinding.getMetaAttributeContext(),
|
entityBinding.getMetaAttributeContext(),
|
||||||
manyToOne
|
manyToOne
|
||||||
);
|
);
|
||||||
|
@ -531,7 +532,7 @@ PrimitiveArray
|
||||||
// boolean (true here) indicates that by default column names should be guessed
|
// boolean (true here) indicates that by default column names should be guessed
|
||||||
ManyToOneRelationalState relationalState =
|
ManyToOneRelationalState relationalState =
|
||||||
new HbmManyToOneRelationalStateContainer(
|
new HbmManyToOneRelationalStateContainer(
|
||||||
hibernateMappingBinder,
|
bindingContext,
|
||||||
true,
|
true,
|
||||||
manyToOne
|
manyToOne
|
||||||
);
|
);
|
||||||
|
|
|
@ -23,362 +23,62 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.metamodel.source.hbm;
|
package org.hibernate.metamodel.source.hbm;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.ArrayList;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.hibernate.cfg.NamingStrategy;
|
import org.hibernate.metamodel.MetadataSources;
|
||||||
import org.hibernate.engine.spi.FilterDefinition;
|
|
||||||
import org.hibernate.internal.util.StringHelper;
|
|
||||||
import org.hibernate.metamodel.binding.FetchProfile;
|
|
||||||
import org.hibernate.metamodel.binding.FetchProfile.Fetch;
|
|
||||||
import org.hibernate.metamodel.binding.TypeDef;
|
|
||||||
import org.hibernate.metamodel.relational.AuxiliaryDatabaseObject;
|
|
||||||
import org.hibernate.metamodel.relational.BasicAuxiliaryDatabaseObjectImpl;
|
|
||||||
import org.hibernate.metamodel.source.MappingException;
|
|
||||||
import org.hibernate.metamodel.source.Origin;
|
|
||||||
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLFetchProfileElement;
|
|
||||||
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLFetchProfileElement.XMLFetch;
|
|
||||||
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLHibernateMapping;
|
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLHibernateMapping;
|
||||||
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLHibernateMapping.XMLClass;
|
|
||||||
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLHibernateMapping.XMLImport;
|
|
||||||
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLJoinedSubclassElement;
|
|
||||||
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLParamElement;
|
|
||||||
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLQueryElement;
|
|
||||||
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLSqlQueryElement;
|
|
||||||
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLSubclassElement;
|
|
||||||
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLUnionSubclassElement;
|
|
||||||
import org.hibernate.metamodel.source.internal.JaxbRoot;
|
import org.hibernate.metamodel.source.internal.JaxbRoot;
|
||||||
import org.hibernate.metamodel.source.internal.OverriddenMappingDefaults;
|
import org.hibernate.metamodel.source.spi.Binder;
|
||||||
import org.hibernate.metamodel.source.spi.BindingContext;
|
|
||||||
import org.hibernate.metamodel.source.spi.MappingDefaults;
|
|
||||||
import org.hibernate.metamodel.source.spi.MetaAttributeContext;
|
|
||||||
import org.hibernate.metamodel.source.spi.MetadataImplementor;
|
import org.hibernate.metamodel.source.spi.MetadataImplementor;
|
||||||
import org.hibernate.service.ServiceRegistry;
|
|
||||||
import org.hibernate.service.classloading.spi.ClassLoaderService;
|
|
||||||
import org.hibernate.service.classloading.spi.ClassLoadingException;
|
|
||||||
import org.hibernate.type.Type;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Responsible for performing binding of hbm xml.
|
* Responsible for performing binding of hbm xml.
|
||||||
*/
|
*/
|
||||||
public class HbmBinder implements BindingContext {
|
public class HbmBinder implements Binder {
|
||||||
|
|
||||||
private final JaxbRoot<XMLHibernateMapping> jaxbRoot;
|
|
||||||
private final XMLHibernateMapping hibernateMapping;
|
|
||||||
|
|
||||||
private final MappingDefaults mappingDefaults;
|
|
||||||
private final MetaAttributeContext metaAttributeContext;
|
|
||||||
|
|
||||||
private final boolean autoImport;
|
|
||||||
|
|
||||||
private final MetadataImplementor metadata;
|
private final MetadataImplementor metadata;
|
||||||
|
private List<HibernateMappingProcessor> processors;
|
||||||
|
|
||||||
public HbmBinder(MetadataImplementor metadata, JaxbRoot<XMLHibernateMapping> jaxbRoot) {
|
public HbmBinder(MetadataImplementor metadata) {
|
||||||
this.jaxbRoot = jaxbRoot;
|
|
||||||
this.hibernateMapping = jaxbRoot.getRoot();
|
|
||||||
|
|
||||||
this.metadata = metadata;
|
this.metadata = metadata;
|
||||||
|
|
||||||
this.mappingDefaults = new OverriddenMappingDefaults(
|
|
||||||
metadata.getMappingDefaults(),
|
|
||||||
hibernateMapping.getPackage(),
|
|
||||||
hibernateMapping.getSchema(),
|
|
||||||
hibernateMapping.getCatalog(),
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
hibernateMapping.getDefaultCascade(),
|
|
||||||
hibernateMapping.getDefaultAccess(),
|
|
||||||
hibernateMapping.isDefaultLazy()
|
|
||||||
);
|
|
||||||
|
|
||||||
autoImport = hibernateMapping.isAutoImport();
|
|
||||||
|
|
||||||
metaAttributeContext = extractMetaAttributes();
|
|
||||||
}
|
|
||||||
|
|
||||||
private MetaAttributeContext extractMetaAttributes() {
|
|
||||||
return hibernateMapping.getMeta() == null
|
|
||||||
? new MetaAttributeContext( metadata.getMetaAttributeContext() )
|
|
||||||
: HbmHelper.extractMetaAttributeContext( hibernateMapping.getMeta(), true, metadata.getMetaAttributeContext() );
|
|
||||||
}
|
|
||||||
|
|
||||||
public MetadataImplementor getMetadata() {
|
|
||||||
return metadata;
|
|
||||||
}
|
|
||||||
|
|
||||||
Origin getOrigin() {
|
|
||||||
return jaxbRoot.getOrigin();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ServiceRegistry getServiceRegistry() {
|
@SuppressWarnings( {"unchecked"})
|
||||||
return metadata.getServiceRegistry();
|
public void prepare(MetadataSources sources) {
|
||||||
|
this.processors = new ArrayList<HibernateMappingProcessor>();
|
||||||
|
for ( JaxbRoot jaxbRoot : sources.getJaxbRootList() ) {
|
||||||
|
if ( jaxbRoot.getRoot() instanceof XMLHibernateMapping ) {
|
||||||
|
processors.add( new HibernateMappingProcessor( metadata, (JaxbRoot<XMLHibernateMapping>) jaxbRoot ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NamingStrategy getNamingStrategy() {
|
public void bindIndependentMetadata(MetadataSources sources) {
|
||||||
return metadata.getOptions().getNamingStrategy();
|
for ( HibernateMappingProcessor processor : processors ) {
|
||||||
|
processor.bindIndependentMetadata();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MappingDefaults getMappingDefaults() {
|
public void bindTypeDependentMetadata(MetadataSources sources) {
|
||||||
return mappingDefaults;
|
for ( HibernateMappingProcessor processor : processors ) {
|
||||||
|
processor.bindTypeDependentMetadata();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MetaAttributeContext getMetaAttributeContext() {
|
public void bindMappingMetadata(MetadataSources sources, List<String> processedEntityNames) {
|
||||||
return metaAttributeContext;
|
for ( HibernateMappingProcessor processor : processors ) {
|
||||||
|
processor.bindMappingMetadata( processedEntityNames );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MetadataImplementor getMetadataImplementor() {
|
public void bindMappingDependentMetadata(MetadataSources sources) {
|
||||||
return metadata;
|
for ( HibernateMappingProcessor processor : processors ) {
|
||||||
}
|
processor.bindMappingDependentMetadata();
|
||||||
|
|
||||||
boolean isAutoImport() {
|
|
||||||
return autoImport;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void processHibernateMapping() {
|
|
||||||
// no pre-requisites
|
|
||||||
bindDatabaseObjectDefinitions();
|
|
||||||
|
|
||||||
// no pre-requisites
|
|
||||||
bindTypeDefinitions();
|
|
||||||
|
|
||||||
// potentially depends on type definitions
|
|
||||||
bindFilterDefinitions();
|
|
||||||
|
|
||||||
// potentially depends on type definitions
|
|
||||||
bindIdentifierGenerators();
|
|
||||||
|
|
||||||
// potentially depends on type definitions and identifier generators
|
|
||||||
bindMappings();
|
|
||||||
|
|
||||||
// depends on mappings
|
|
||||||
bindFetchProfiles();
|
|
||||||
|
|
||||||
// depends on mappings
|
|
||||||
bindImports();
|
|
||||||
|
|
||||||
// depends on mappings and potentially on type definitions
|
|
||||||
bindResultSetMappings();
|
|
||||||
|
|
||||||
// depends on mappings and potentially on type definitions and result set mappings
|
|
||||||
bindNamedQueries();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void bindDatabaseObjectDefinitions() {
|
|
||||||
if ( hibernateMapping.getDatabaseObject() == null ) {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
for ( XMLHibernateMapping.XMLDatabaseObject databaseObjectElement : hibernateMapping.getDatabaseObject() ) {
|
|
||||||
final AuxiliaryDatabaseObject auxiliaryDatabaseObject;
|
|
||||||
if ( databaseObjectElement.getDefinition() != null ) {
|
|
||||||
final String className = databaseObjectElement.getDefinition().getClazz();
|
|
||||||
try {
|
|
||||||
auxiliaryDatabaseObject = (AuxiliaryDatabaseObject) classLoaderService().classForName( className ).newInstance();
|
|
||||||
}
|
|
||||||
catch (ClassLoadingException e) {
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
catch (Exception e) {
|
|
||||||
throw new MappingException(
|
|
||||||
"could not instantiate custom database object class [" + className + "]",
|
|
||||||
jaxbRoot.getOrigin()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Set<String> dialectScopes = new HashSet<String>();
|
|
||||||
if ( databaseObjectElement.getDialectScope() != null ) {
|
|
||||||
for ( XMLHibernateMapping.XMLDatabaseObject.XMLDialectScope dialectScope : databaseObjectElement.getDialectScope() ) {
|
|
||||||
dialectScopes.add( dialectScope.getName() );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
auxiliaryDatabaseObject = new BasicAuxiliaryDatabaseObjectImpl(
|
|
||||||
databaseObjectElement.getCreate(),
|
|
||||||
databaseObjectElement.getDrop(),
|
|
||||||
dialectScopes
|
|
||||||
);
|
|
||||||
}
|
|
||||||
metadata.addAuxiliaryDatabaseObject( auxiliaryDatabaseObject );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void bindTypeDefinitions() {
|
|
||||||
if ( hibernateMapping.getTypedef() == null ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for ( XMLHibernateMapping.XMLTypedef typedef : hibernateMapping.getTypedef() ) {
|
|
||||||
final Map<String, String> parameters = new HashMap<String, String>();
|
|
||||||
for ( XMLParamElement paramElement : typedef.getParam() ) {
|
|
||||||
parameters.put( paramElement.getName(), paramElement.getValue() );
|
|
||||||
}
|
|
||||||
metadata.addTypeDefinition( new TypeDef( typedef.getName(), typedef.getClazz(), parameters ) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void bindFilterDefinitions() {
|
|
||||||
if(hibernateMapping.getFilterDef() == null){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for ( XMLHibernateMapping.XMLFilterDef filterDefinition : hibernateMapping.getFilterDef() ) {
|
|
||||||
final String name = filterDefinition.getName();
|
|
||||||
final Map<String,Type> parameters = new HashMap<String, Type>();
|
|
||||||
String condition = null;
|
|
||||||
for ( Object o : filterDefinition.getContent() ) {
|
|
||||||
if ( o instanceof String ) {
|
|
||||||
// represents the condition
|
|
||||||
if ( condition != null ) {
|
|
||||||
// log?
|
|
||||||
}
|
|
||||||
condition = (String) o;
|
|
||||||
}
|
|
||||||
else if ( o instanceof XMLHibernateMapping.XMLFilterDef.XMLFilterParam ) {
|
|
||||||
final XMLHibernateMapping.XMLFilterDef.XMLFilterParam paramElement = (XMLHibernateMapping.XMLFilterDef.XMLFilterParam) o;
|
|
||||||
// todo : should really delay this resolution until later to allow typedef names
|
|
||||||
parameters.put(
|
|
||||||
paramElement.getName(),
|
|
||||||
metadata.getTypeResolver().heuristicType( paramElement.getType() )
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw new MappingException( "Unrecognized nested filter content", jaxbRoot.getOrigin() );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( condition == null ) {
|
|
||||||
condition = filterDefinition.getCondition();
|
|
||||||
}
|
|
||||||
metadata.addFilterDefinition( new FilterDefinition( name, condition, parameters ) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void bindIdentifierGenerators() {
|
|
||||||
if ( hibernateMapping.getIdentifierGenerator() == null ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for ( XMLHibernateMapping.XMLIdentifierGenerator identifierGeneratorElement : hibernateMapping.getIdentifierGenerator() ) {
|
|
||||||
metadata.registerIdentifierGenerator(
|
|
||||||
identifierGeneratorElement.getName(),
|
|
||||||
identifierGeneratorElement.getClazz()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void bindMappings() {
|
|
||||||
if ( hibernateMapping.getClazzOrSubclassOrJoinedSubclass() == null ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for ( Object clazzOrSubclass : hibernateMapping.getClazzOrSubclassOrJoinedSubclass() ) {
|
|
||||||
if ( XMLClass.class.isInstance( clazzOrSubclass ) ) {
|
|
||||||
XMLClass clazz =
|
|
||||||
XMLClass.class.cast( clazzOrSubclass );
|
|
||||||
new RootEntityBinder( this, clazz ).process( clazz );
|
|
||||||
}
|
|
||||||
else if ( XMLSubclassElement.class.isInstance( clazzOrSubclass ) ) {
|
|
||||||
// PersistentClass superModel = getSuperclass( mappings, element );
|
|
||||||
// handleSubclass( superModel, mappings, element, inheritedMetas );
|
|
||||||
}
|
|
||||||
else if ( XMLJoinedSubclassElement.class.isInstance( clazzOrSubclass ) ) {
|
|
||||||
// PersistentClass superModel = getSuperclass( mappings, element );
|
|
||||||
// handleJoinedSubclass( superModel, mappings, element, inheritedMetas );
|
|
||||||
}
|
|
||||||
else if ( XMLUnionSubclassElement.class.isInstance( clazzOrSubclass ) ) {
|
|
||||||
// PersistentClass superModel = getSuperclass( mappings, element );
|
|
||||||
// handleUnionSubclass( superModel, mappings, element, inheritedMetas );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw new org.hibernate.metamodel.source.MappingException(
|
|
||||||
"unknown type of class or subclass: " +
|
|
||||||
clazzOrSubclass.getClass().getName(), jaxbRoot.getOrigin()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void bindFetchProfiles(){
|
|
||||||
if(hibernateMapping.getFetchProfile() == null){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
bindFetchProfiles( hibernateMapping.getFetchProfile(),null );
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void bindFetchProfiles(List<XMLFetchProfileElement> fetchProfiles, String containingEntityName) {
|
|
||||||
for ( XMLFetchProfileElement fetchProfile : fetchProfiles ) {
|
|
||||||
String profileName = fetchProfile.getName();
|
|
||||||
Set<Fetch> fetches = new HashSet<Fetch>();
|
|
||||||
for ( XMLFetch fetch : fetchProfile.getFetch() ) {
|
|
||||||
String entityName = fetch.getEntity() == null ? containingEntityName : fetch.getEntity();
|
|
||||||
if ( entityName == null ) {
|
|
||||||
throw new MappingException(
|
|
||||||
"could not determine entity for fetch-profile fetch [" + profileName + "]:[" +
|
|
||||||
fetch.getAssociation() + "]",
|
|
||||||
jaxbRoot.getOrigin()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
fetches.add( new Fetch( entityName, fetch.getAssociation(), fetch.getStyle() ) );
|
|
||||||
}
|
|
||||||
metadata.addFetchProfile( new FetchProfile( profileName, fetches ) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void bindImports() {
|
|
||||||
if ( hibernateMapping.getImport() == null ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for ( XMLImport importValue : hibernateMapping.getImport() ) {
|
|
||||||
String className = getClassName( importValue.getClazz() );
|
|
||||||
String rename = importValue.getRename();
|
|
||||||
rename = ( rename == null ) ? StringHelper.unqualify( className ) : rename;
|
|
||||||
metadata.addImport( className, rename );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void bindResultSetMappings() {
|
|
||||||
if ( hibernateMapping.getResultset() == null ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// bindResultSetMappingDefinitions( element, null, mappings );
|
|
||||||
}
|
|
||||||
|
|
||||||
private void bindNamedQueries() {
|
|
||||||
if ( hibernateMapping.getQueryOrSqlQuery() == null ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for ( Object queryOrSqlQuery : hibernateMapping.getQueryOrSqlQuery() ) {
|
|
||||||
if ( XMLQueryElement.class.isInstance( queryOrSqlQuery ) ) {
|
|
||||||
// bindNamedQuery( element, null, mappings );
|
|
||||||
}
|
|
||||||
else if ( XMLSqlQueryElement.class.isInstance( queryOrSqlQuery ) ) {
|
|
||||||
// bindNamedSQLQuery( element, null, mappings );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw new MappingException(
|
|
||||||
"unknown type of query: " +
|
|
||||||
queryOrSqlQuery.getClass().getName(), jaxbRoot.getOrigin()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private ClassLoaderService classLoaderService;
|
|
||||||
|
|
||||||
private ClassLoaderService classLoaderService() {
|
|
||||||
if ( classLoaderService == null ) {
|
|
||||||
classLoaderService = metadata.getServiceRegistry().getService( ClassLoaderService.class );
|
|
||||||
}
|
|
||||||
return classLoaderService;
|
|
||||||
}
|
|
||||||
|
|
||||||
String extractEntityName(XMLClass entityClazz) {
|
|
||||||
return HbmHelper.extractEntityName( entityClazz, mappingDefaults.getPackageName() );
|
|
||||||
}
|
|
||||||
|
|
||||||
String getClassName(String unqualifiedName) {
|
|
||||||
return HbmHelper.getClassName( unqualifiedName, mappingDefaults.getPackageName() );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,42 +25,23 @@ package org.hibernate.metamodel.source.hbm;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.hibernate.metamodel.MetadataSources;
|
import org.hibernate.internal.util.xml.XmlDocument;
|
||||||
import org.hibernate.metamodel.source.spi.Binder;
|
import org.hibernate.metamodel.source.Origin;
|
||||||
import org.hibernate.metamodel.source.spi.MetadataImplementor;
|
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLFetchProfileElement;
|
||||||
|
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLHibernateMapping;
|
||||||
|
import org.hibernate.metamodel.source.spi.BindingContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class HibernateMappingBinder implements Binder {
|
public interface HbmBindingContext extends BindingContext {
|
||||||
private final MetadataImplementor metadata;
|
public boolean isAutoImport();
|
||||||
|
|
||||||
public HibernateMappingBinder(MetadataImplementor metadata) {
|
public String extractEntityName(XMLHibernateMapping.XMLClass entityClazz);
|
||||||
this.metadata = metadata;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
public String getClassName(String unqualifiedName);
|
||||||
public void prepare(MetadataSources sources) {
|
|
||||||
// nothing to do here.
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
public void bindFetchProfiles(List<XMLFetchProfileElement> fetchProfiles, String containingEntityName);
|
||||||
public void bindIndependentMetadata(MetadataSources sources) {
|
|
||||||
// todo : implement method body
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
public Origin getOrigin();
|
||||||
public void bindTypeDependentMetadata(MetadataSources sources) {
|
|
||||||
// todo : implement method body
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void bindMappingMetadata(MetadataSources sources, List<String> processedEntityNames) {
|
|
||||||
// todo : implement method body
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void bindMappingDependentMetadata(MetadataSources sources) {
|
|
||||||
// todo : implement method body
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -0,0 +1,369 @@
|
||||||
|
/*
|
||||||
|
* 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.hbm;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.hibernate.cfg.NamingStrategy;
|
||||||
|
import org.hibernate.engine.spi.FilterDefinition;
|
||||||
|
import org.hibernate.internal.util.StringHelper;
|
||||||
|
import org.hibernate.metamodel.binding.FetchProfile;
|
||||||
|
import org.hibernate.metamodel.binding.TypeDef;
|
||||||
|
import org.hibernate.metamodel.relational.AuxiliaryDatabaseObject;
|
||||||
|
import org.hibernate.metamodel.relational.BasicAuxiliaryDatabaseObjectImpl;
|
||||||
|
import org.hibernate.metamodel.source.MappingException;
|
||||||
|
import org.hibernate.metamodel.source.Origin;
|
||||||
|
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLFetchProfileElement;
|
||||||
|
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLHibernateMapping;
|
||||||
|
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLJoinedSubclassElement;
|
||||||
|
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLParamElement;
|
||||||
|
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLQueryElement;
|
||||||
|
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLSqlQueryElement;
|
||||||
|
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLSubclassElement;
|
||||||
|
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLUnionSubclassElement;
|
||||||
|
import org.hibernate.metamodel.source.internal.JaxbRoot;
|
||||||
|
import org.hibernate.metamodel.source.internal.OverriddenMappingDefaults;
|
||||||
|
import org.hibernate.metamodel.source.spi.MappingDefaults;
|
||||||
|
import org.hibernate.metamodel.source.spi.MetaAttributeContext;
|
||||||
|
import org.hibernate.metamodel.source.spi.MetadataImplementor;
|
||||||
|
import org.hibernate.service.ServiceRegistry;
|
||||||
|
import org.hibernate.service.classloading.spi.ClassLoaderService;
|
||||||
|
import org.hibernate.service.classloading.spi.ClassLoadingException;
|
||||||
|
import org.hibernate.type.Type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Responsible for processing a {@code <hibernate-mapping/>} element. Allows processing to be coordinated across
|
||||||
|
* all hbm files in an ordered fashion. The order is essentially the same as defined in
|
||||||
|
* {@link org.hibernate.metamodel.source.spi.Binder}
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class HibernateMappingProcessor implements HbmBindingContext {
|
||||||
|
private final MetadataImplementor metadata;
|
||||||
|
private final JaxbRoot<XMLHibernateMapping> jaxbRoot;
|
||||||
|
|
||||||
|
private final XMLHibernateMapping hibernateMapping;
|
||||||
|
|
||||||
|
private final MappingDefaults mappingDefaults;
|
||||||
|
private final MetaAttributeContext metaAttributeContext;
|
||||||
|
|
||||||
|
private final boolean autoImport;
|
||||||
|
|
||||||
|
public HibernateMappingProcessor(MetadataImplementor metadata, JaxbRoot<XMLHibernateMapping> jaxbRoot) {
|
||||||
|
this.metadata = metadata;
|
||||||
|
this.jaxbRoot = jaxbRoot;
|
||||||
|
|
||||||
|
this.hibernateMapping = jaxbRoot.getRoot();
|
||||||
|
this.mappingDefaults = new OverriddenMappingDefaults(
|
||||||
|
metadata.getMappingDefaults(),
|
||||||
|
hibernateMapping.getPackage(),
|
||||||
|
hibernateMapping.getSchema(),
|
||||||
|
hibernateMapping.getCatalog(),
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
hibernateMapping.getDefaultCascade(),
|
||||||
|
hibernateMapping.getDefaultAccess(),
|
||||||
|
hibernateMapping.isDefaultLazy()
|
||||||
|
);
|
||||||
|
|
||||||
|
autoImport = hibernateMapping.isAutoImport();
|
||||||
|
|
||||||
|
metaAttributeContext = extractMetaAttributes();
|
||||||
|
}
|
||||||
|
|
||||||
|
private MetaAttributeContext extractMetaAttributes() {
|
||||||
|
return hibernateMapping.getMeta() == null
|
||||||
|
? new MetaAttributeContext( metadata.getMetaAttributeContext() )
|
||||||
|
: HbmHelper.extractMetaAttributeContext( hibernateMapping.getMeta(), true, metadata.getMetaAttributeContext() );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAutoImport() {
|
||||||
|
return autoImport;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Origin getOrigin() {
|
||||||
|
return jaxbRoot.getOrigin();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ServiceRegistry getServiceRegistry() {
|
||||||
|
return metadata.getServiceRegistry();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NamingStrategy getNamingStrategy() {
|
||||||
|
return metadata.getOptions().getNamingStrategy();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MappingDefaults getMappingDefaults() {
|
||||||
|
return mappingDefaults;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MetaAttributeContext getMetaAttributeContext() {
|
||||||
|
return metaAttributeContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MetadataImplementor getMetadataImplementor() {
|
||||||
|
return metadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void bindIndependentMetadata() {
|
||||||
|
bindDatabaseObjectDefinitions();
|
||||||
|
bindTypeDefinitions();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void bindDatabaseObjectDefinitions() {
|
||||||
|
if ( hibernateMapping.getDatabaseObject() == null ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for ( XMLHibernateMapping.XMLDatabaseObject databaseObjectElement : hibernateMapping.getDatabaseObject() ) {
|
||||||
|
final AuxiliaryDatabaseObject auxiliaryDatabaseObject;
|
||||||
|
if ( databaseObjectElement.getDefinition() != null ) {
|
||||||
|
final String className = databaseObjectElement.getDefinition().getClazz();
|
||||||
|
try {
|
||||||
|
auxiliaryDatabaseObject = (AuxiliaryDatabaseObject) classLoaderService().classForName( className ).newInstance();
|
||||||
|
}
|
||||||
|
catch (ClassLoadingException e) {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
throw new MappingException(
|
||||||
|
"could not instantiate custom database object class [" + className + "]",
|
||||||
|
jaxbRoot.getOrigin()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Set<String> dialectScopes = new HashSet<String>();
|
||||||
|
if ( databaseObjectElement.getDialectScope() != null ) {
|
||||||
|
for ( XMLHibernateMapping.XMLDatabaseObject.XMLDialectScope dialectScope : databaseObjectElement.getDialectScope() ) {
|
||||||
|
dialectScopes.add( dialectScope.getName() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
auxiliaryDatabaseObject = new BasicAuxiliaryDatabaseObjectImpl(
|
||||||
|
databaseObjectElement.getCreate(),
|
||||||
|
databaseObjectElement.getDrop(),
|
||||||
|
dialectScopes
|
||||||
|
);
|
||||||
|
}
|
||||||
|
metadata.addAuxiliaryDatabaseObject( auxiliaryDatabaseObject );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void bindTypeDefinitions() {
|
||||||
|
if ( hibernateMapping.getTypedef() == null ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for ( XMLHibernateMapping.XMLTypedef typedef : hibernateMapping.getTypedef() ) {
|
||||||
|
final Map<String, String> parameters = new HashMap<String, String>();
|
||||||
|
for ( XMLParamElement paramElement : typedef.getParam() ) {
|
||||||
|
parameters.put( paramElement.getName(), paramElement.getValue() );
|
||||||
|
}
|
||||||
|
metadata.addTypeDefinition( new TypeDef( typedef.getName(), typedef.getClazz(), parameters ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void bindTypeDependentMetadata() {
|
||||||
|
bindFilterDefinitions();
|
||||||
|
bindIdentifierGenerators();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void bindFilterDefinitions() {
|
||||||
|
if(hibernateMapping.getFilterDef() == null){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for ( XMLHibernateMapping.XMLFilterDef filterDefinition : hibernateMapping.getFilterDef() ) {
|
||||||
|
final String name = filterDefinition.getName();
|
||||||
|
final Map<String,Type> parameters = new HashMap<String, Type>();
|
||||||
|
String condition = null;
|
||||||
|
for ( Object o : filterDefinition.getContent() ) {
|
||||||
|
if ( o instanceof String ) {
|
||||||
|
// represents the condition
|
||||||
|
if ( condition != null ) {
|
||||||
|
// log?
|
||||||
|
}
|
||||||
|
condition = (String) o;
|
||||||
|
}
|
||||||
|
else if ( o instanceof XMLHibernateMapping.XMLFilterDef.XMLFilterParam ) {
|
||||||
|
final XMLHibernateMapping.XMLFilterDef.XMLFilterParam paramElement = (XMLHibernateMapping.XMLFilterDef.XMLFilterParam) o;
|
||||||
|
// todo : should really delay this resolution until later to allow typedef names
|
||||||
|
parameters.put(
|
||||||
|
paramElement.getName(),
|
||||||
|
metadata.getTypeResolver().heuristicType( paramElement.getType() )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new MappingException( "Unrecognized nested filter content", jaxbRoot.getOrigin() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( condition == null ) {
|
||||||
|
condition = filterDefinition.getCondition();
|
||||||
|
}
|
||||||
|
metadata.addFilterDefinition( new FilterDefinition( name, condition, parameters ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void bindIdentifierGenerators() {
|
||||||
|
if ( hibernateMapping.getIdentifierGenerator() == null ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for ( XMLHibernateMapping.XMLIdentifierGenerator identifierGeneratorElement : hibernateMapping.getIdentifierGenerator() ) {
|
||||||
|
metadata.registerIdentifierGenerator(
|
||||||
|
identifierGeneratorElement.getName(),
|
||||||
|
identifierGeneratorElement.getClazz()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void bindMappingMetadata(List<String> processedEntityNames) {
|
||||||
|
if ( hibernateMapping.getClazzOrSubclassOrJoinedSubclass() == null ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for ( Object clazzOrSubclass : hibernateMapping.getClazzOrSubclassOrJoinedSubclass() ) {
|
||||||
|
if ( XMLHibernateMapping.XMLClass.class.isInstance( clazzOrSubclass ) ) {
|
||||||
|
XMLHibernateMapping.XMLClass clazz =
|
||||||
|
XMLHibernateMapping.XMLClass.class.cast( clazzOrSubclass );
|
||||||
|
new RootEntityBinder( this, clazz ).process( clazz );
|
||||||
|
}
|
||||||
|
else if ( XMLSubclassElement.class.isInstance( clazzOrSubclass ) ) {
|
||||||
|
// PersistentClass superModel = getSuperclass( mappings, element );
|
||||||
|
// handleSubclass( superModel, mappings, element, inheritedMetas );
|
||||||
|
}
|
||||||
|
else if ( XMLJoinedSubclassElement.class.isInstance( clazzOrSubclass ) ) {
|
||||||
|
// PersistentClass superModel = getSuperclass( mappings, element );
|
||||||
|
// handleJoinedSubclass( superModel, mappings, element, inheritedMetas );
|
||||||
|
}
|
||||||
|
else if ( XMLUnionSubclassElement.class.isInstance( clazzOrSubclass ) ) {
|
||||||
|
// PersistentClass superModel = getSuperclass( mappings, element );
|
||||||
|
// handleUnionSubclass( superModel, mappings, element, inheritedMetas );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new org.hibernate.metamodel.source.MappingException(
|
||||||
|
"unknown type of class or subclass: " +
|
||||||
|
clazzOrSubclass.getClass().getName(), jaxbRoot.getOrigin()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void bindMappingDependentMetadata() {
|
||||||
|
bindFetchProfiles();
|
||||||
|
bindImports();
|
||||||
|
bindResultSetMappings();
|
||||||
|
bindNamedQueries();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void bindFetchProfiles(){
|
||||||
|
if(hibernateMapping.getFetchProfile() == null){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
bindFetchProfiles( hibernateMapping.getFetchProfile(),null );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void bindFetchProfiles(List<XMLFetchProfileElement> fetchProfiles, String containingEntityName) {
|
||||||
|
for ( XMLFetchProfileElement fetchProfile : fetchProfiles ) {
|
||||||
|
String profileName = fetchProfile.getName();
|
||||||
|
Set<FetchProfile.Fetch> fetches = new HashSet<FetchProfile.Fetch>();
|
||||||
|
for ( XMLFetchProfileElement.XMLFetch fetch : fetchProfile.getFetch() ) {
|
||||||
|
String entityName = fetch.getEntity() == null ? containingEntityName : fetch.getEntity();
|
||||||
|
if ( entityName == null ) {
|
||||||
|
throw new MappingException(
|
||||||
|
"could not determine entity for fetch-profile fetch [" + profileName + "]:[" +
|
||||||
|
fetch.getAssociation() + "]",
|
||||||
|
jaxbRoot.getOrigin()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
fetches.add( new FetchProfile.Fetch( entityName, fetch.getAssociation(), fetch.getStyle() ) );
|
||||||
|
}
|
||||||
|
metadata.addFetchProfile( new FetchProfile( profileName, fetches ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void bindImports() {
|
||||||
|
if ( hibernateMapping.getImport() == null ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for ( XMLHibernateMapping.XMLImport importValue : hibernateMapping.getImport() ) {
|
||||||
|
String className = getClassName( importValue.getClazz() );
|
||||||
|
String rename = importValue.getRename();
|
||||||
|
rename = ( rename == null ) ? StringHelper.unqualify( className ) : rename;
|
||||||
|
metadata.addImport( className, rename );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void bindResultSetMappings() {
|
||||||
|
if ( hibernateMapping.getResultset() == null ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// bindResultSetMappingDefinitions( element, null, mappings );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void bindNamedQueries() {
|
||||||
|
if ( hibernateMapping.getQueryOrSqlQuery() == null ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for ( Object queryOrSqlQuery : hibernateMapping.getQueryOrSqlQuery() ) {
|
||||||
|
if ( XMLQueryElement.class.isInstance( queryOrSqlQuery ) ) {
|
||||||
|
// bindNamedQuery( element, null, mappings );
|
||||||
|
}
|
||||||
|
else if ( XMLSqlQueryElement.class.isInstance( queryOrSqlQuery ) ) {
|
||||||
|
// bindNamedSQLQuery( element, null, mappings );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new MappingException(
|
||||||
|
"unknown type of query: " +
|
||||||
|
queryOrSqlQuery.getClass().getName(), jaxbRoot.getOrigin()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ClassLoaderService classLoaderService;
|
||||||
|
|
||||||
|
private ClassLoaderService classLoaderService() {
|
||||||
|
if ( classLoaderService == null ) {
|
||||||
|
classLoaderService = metadata.getServiceRegistry().getService( ClassLoaderService.class );
|
||||||
|
}
|
||||||
|
return classLoaderService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String extractEntityName(XMLHibernateMapping.XMLClass entityClazz) {
|
||||||
|
return HbmHelper.extractEntityName( entityClazz, mappingDefaults.getPackageName() );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getClassName(String unqualifiedName) {
|
||||||
|
return HbmHelper.getClassName( unqualifiedName, mappingDefaults.getPackageName() );
|
||||||
|
}
|
||||||
|
}
|
|
@ -50,12 +50,12 @@ import org.hibernate.metamodel.binding.state.DiscriminatorBindingState;
|
||||||
*/
|
*/
|
||||||
class RootEntityBinder extends AbstractEntityBinder {
|
class RootEntityBinder extends AbstractEntityBinder {
|
||||||
|
|
||||||
RootEntityBinder(HbmBinder hibernateMappingBinder, XMLClass xmlClazz) {
|
RootEntityBinder(HbmBindingContext bindingContext, XMLClass xmlClazz) {
|
||||||
super( hibernateMappingBinder, xmlClazz );
|
super( bindingContext, xmlClazz );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void process(XMLClass xmlClazz) {
|
public void process(XMLClass xmlClazz) {
|
||||||
String entityName = getHibernateMappingBinder().extractEntityName( xmlClazz );
|
String entityName = getBindingContext().extractEntityName( xmlClazz );
|
||||||
if ( entityName == null ) {
|
if ( entityName == null ) {
|
||||||
throw new MappingException( "Unable to determine entity name" );
|
throw new MappingException( "Unable to determine entity name" );
|
||||||
}
|
}
|
||||||
|
@ -134,20 +134,20 @@ class RootEntityBinder extends AbstractEntityBinder {
|
||||||
|
|
||||||
throw new InvalidMappingException(
|
throw new InvalidMappingException(
|
||||||
"Entity [" + entityBinding.getEntity().getName() + "] did not contain identifier mapping",
|
"Entity [" + entityBinding.getEntity().getName() + "] did not contain identifier mapping",
|
||||||
getHibernateMappingBinder().getOrigin()
|
getBindingContext().getOrigin()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void bindSimpleId(XMLId id, EntityBinding entityBinding) {
|
private void bindSimpleId(XMLId id, EntityBinding entityBinding) {
|
||||||
SimpleAttributeBindingState bindingState = new HbmSimpleAttributeBindingState(
|
SimpleAttributeBindingState bindingState = new HbmSimpleAttributeBindingState(
|
||||||
entityBinding.getEntity().getPojoEntitySpecifics().getClassName(),
|
entityBinding.getEntity().getPojoEntitySpecifics().getClassName(),
|
||||||
getHibernateMappingBinder(),
|
getBindingContext(),
|
||||||
entityBinding.getMetaAttributeContext(),
|
entityBinding.getMetaAttributeContext(),
|
||||||
id
|
id
|
||||||
);
|
);
|
||||||
// boolean (true here) indicates that by default column names should be guessed
|
// boolean (true here) indicates that by default column names should be guessed
|
||||||
HbmSimpleValueRelationalStateContainer relationalStateContainer = new HbmSimpleValueRelationalStateContainer(
|
HbmSimpleValueRelationalStateContainer relationalStateContainer = new HbmSimpleValueRelationalStateContainer(
|
||||||
getHibernateMappingBinder(), true, id
|
getBindingContext(), true, id
|
||||||
);
|
);
|
||||||
if ( relationalStateContainer.getRelationalStates().size() > 1 ) {
|
if ( relationalStateContainer.getRelationalStates().size() > 1 ) {
|
||||||
throw new MappingException( "ID is expected to be a single column, but has more than 1 value" );
|
throw new MappingException( "ID is expected to be a single column, but has more than 1 value" );
|
||||||
|
@ -247,14 +247,14 @@ class RootEntityBinder extends AbstractEntityBinder {
|
||||||
DiscriminatorBindingState bindingState = new HbmDiscriminatorBindingState(
|
DiscriminatorBindingState bindingState = new HbmDiscriminatorBindingState(
|
||||||
entityBinding.getEntity().getPojoEntitySpecifics().getClassName(),
|
entityBinding.getEntity().getPojoEntitySpecifics().getClassName(),
|
||||||
entityBinding.getEntity().getName(),
|
entityBinding.getEntity().getName(),
|
||||||
getHibernateMappingBinder(),
|
getBindingContext(),
|
||||||
xmlEntityClazz
|
xmlEntityClazz
|
||||||
);
|
);
|
||||||
|
|
||||||
// boolean (true here) indicates that by default column names should be guessed
|
// boolean (true here) indicates that by default column names should be guessed
|
||||||
ValueRelationalState relationalState = convertToSimpleValueRelationalStateIfPossible(
|
ValueRelationalState relationalState = convertToSimpleValueRelationalStateIfPossible(
|
||||||
new HbmSimpleValueRelationalStateContainer(
|
new HbmSimpleValueRelationalStateContainer(
|
||||||
getHibernateMappingBinder(),
|
getBindingContext(),
|
||||||
true,
|
true,
|
||||||
xmlEntityClazz.getDiscriminator()
|
xmlEntityClazz.getDiscriminator()
|
||||||
)
|
)
|
||||||
|
@ -288,7 +288,7 @@ class RootEntityBinder extends AbstractEntityBinder {
|
||||||
SimpleAttributeBindingState bindingState =
|
SimpleAttributeBindingState bindingState =
|
||||||
new HbmSimpleAttributeBindingState(
|
new HbmSimpleAttributeBindingState(
|
||||||
entityBinding.getEntity().getPojoEntitySpecifics().getClassName(),
|
entityBinding.getEntity().getPojoEntitySpecifics().getClassName(),
|
||||||
getHibernateMappingBinder(),
|
getBindingContext(),
|
||||||
entityBinding.getMetaAttributeContext(),
|
entityBinding.getMetaAttributeContext(),
|
||||||
version
|
version
|
||||||
);
|
);
|
||||||
|
@ -297,7 +297,7 @@ class RootEntityBinder extends AbstractEntityBinder {
|
||||||
ValueRelationalState relationalState =
|
ValueRelationalState relationalState =
|
||||||
convertToSimpleValueRelationalStateIfPossible(
|
convertToSimpleValueRelationalStateIfPossible(
|
||||||
new HbmSimpleValueRelationalStateContainer(
|
new HbmSimpleValueRelationalStateContainer(
|
||||||
getHibernateMappingBinder(),
|
getBindingContext(),
|
||||||
true,
|
true,
|
||||||
version
|
version
|
||||||
)
|
)
|
||||||
|
@ -315,7 +315,7 @@ class RootEntityBinder extends AbstractEntityBinder {
|
||||||
SimpleAttributeBindingState bindingState =
|
SimpleAttributeBindingState bindingState =
|
||||||
new HbmSimpleAttributeBindingState(
|
new HbmSimpleAttributeBindingState(
|
||||||
entityBinding.getEntity().getPojoEntitySpecifics().getClassName(),
|
entityBinding.getEntity().getPojoEntitySpecifics().getClassName(),
|
||||||
getHibernateMappingBinder(),
|
getBindingContext(),
|
||||||
entityBinding.getMetaAttributeContext(),
|
entityBinding.getMetaAttributeContext(),
|
||||||
timestamp
|
timestamp
|
||||||
);
|
);
|
||||||
|
@ -325,7 +325,7 @@ class RootEntityBinder extends AbstractEntityBinder {
|
||||||
ValueRelationalState relationalState =
|
ValueRelationalState relationalState =
|
||||||
convertToSimpleValueRelationalStateIfPossible(
|
convertToSimpleValueRelationalStateIfPossible(
|
||||||
new HbmSimpleValueRelationalStateContainer(
|
new HbmSimpleValueRelationalStateContainer(
|
||||||
getHibernateMappingBinder(),
|
getBindingContext(),
|
||||||
true,
|
true,
|
||||||
timestamp
|
timestamp
|
||||||
)
|
)
|
||||||
|
|
|
@ -23,8 +23,6 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.metamodel.source.internal;
|
package org.hibernate.metamodel.source.internal;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
@ -32,12 +30,9 @@ import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.jboss.jandex.Index;
|
|
||||||
import org.jboss.jandex.Indexer;
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
|
|
||||||
import org.hibernate.DuplicateMappingException;
|
import org.hibernate.DuplicateMappingException;
|
||||||
import org.hibernate.HibernateException;
|
|
||||||
import org.hibernate.SessionFactory;
|
import org.hibernate.SessionFactory;
|
||||||
import org.hibernate.cfg.NamingStrategy;
|
import org.hibernate.cfg.NamingStrategy;
|
||||||
import org.hibernate.engine.spi.FilterDefinition;
|
import org.hibernate.engine.spi.FilterDefinition;
|
||||||
|
@ -55,13 +50,8 @@ import org.hibernate.metamodel.binding.TypeDef;
|
||||||
import org.hibernate.metamodel.domain.MetaAttribute;
|
import org.hibernate.metamodel.domain.MetaAttribute;
|
||||||
import org.hibernate.metamodel.relational.AuxiliaryDatabaseObject;
|
import org.hibernate.metamodel.relational.AuxiliaryDatabaseObject;
|
||||||
import org.hibernate.metamodel.relational.Database;
|
import org.hibernate.metamodel.relational.Database;
|
||||||
import org.hibernate.metamodel.source.annotation.xml.XMLEntityMappings;
|
|
||||||
import org.hibernate.metamodel.source.annotations.AnnotationBinder;
|
import org.hibernate.metamodel.source.annotations.AnnotationBinder;
|
||||||
import org.hibernate.metamodel.source.annotations.JpaBinder;
|
|
||||||
import org.hibernate.metamodel.source.annotations.xml.OrmXmlParser;
|
|
||||||
import org.hibernate.metamodel.source.hbm.HbmBinder;
|
import org.hibernate.metamodel.source.hbm.HbmBinder;
|
||||||
import org.hibernate.metamodel.source.hbm.HibernateMappingBinder;
|
|
||||||
import org.hibernate.metamodel.source.hbm.xml.mapping.XMLHibernateMapping;
|
|
||||||
import org.hibernate.metamodel.source.spi.Binder;
|
import org.hibernate.metamodel.source.spi.Binder;
|
||||||
import org.hibernate.metamodel.source.spi.MappingDefaults;
|
import org.hibernate.metamodel.source.spi.MappingDefaults;
|
||||||
import org.hibernate.metamodel.source.spi.MetaAttributeContext;
|
import org.hibernate.metamodel.source.spi.MetaAttributeContext;
|
||||||
|
@ -119,33 +109,26 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
|
||||||
final Binder[] binders;
|
final Binder[] binders;
|
||||||
if ( options.getSourceProcessingOrder() == SourceProcessingOrder.HBM_FIRST ) {
|
if ( options.getSourceProcessingOrder() == SourceProcessingOrder.HBM_FIRST ) {
|
||||||
binders = new Binder[] {
|
binders = new Binder[] {
|
||||||
new HibernateMappingBinder( this ),
|
new HbmBinder( this ),
|
||||||
new JpaBinder( this )
|
new AnnotationBinder( this )
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
binders = new Binder[] {
|
binders = new Binder[] {
|
||||||
new JpaBinder( this ),
|
new AnnotationBinder( this ),
|
||||||
new HibernateMappingBinder( this )
|
new HbmBinder( this )
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final ArrayList<String> processedEntityNames = new ArrayList<String>();
|
||||||
|
|
||||||
prepare( binders, metadataSources );
|
prepare( binders, metadataSources );
|
||||||
bindIndependentMetadata( binders, metadataSources );
|
bindIndependentMetadata( binders, metadataSources );
|
||||||
bindTypeDependentMetadata( binders, metadataSources );
|
bindTypeDependentMetadata( binders, metadataSources );
|
||||||
bindMappingMetadata( binders, metadataSources );
|
bindMappingMetadata( binders, metadataSources, processedEntityNames );
|
||||||
bindMappingDependentMetadata( binders, metadataSources );
|
bindMappingDependentMetadata( binders, metadataSources );
|
||||||
|
|
||||||
final ArrayList<String> processedEntityNames = new ArrayList<String>();
|
// todo : remove this by coordinated ordering of entity processing
|
||||||
if ( options.getSourceProcessingOrder() == SourceProcessingOrder.HBM_FIRST ) {
|
|
||||||
applyHibernateMappings( metadataSources, processedEntityNames );
|
|
||||||
applyAnnotationMappings( metadataSources, processedEntityNames );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
applyAnnotationMappings( metadataSources, processedEntityNames );
|
|
||||||
applyHibernateMappings( metadataSources, processedEntityNames );
|
|
||||||
}
|
|
||||||
|
|
||||||
new EntityReferenceResolver( this ).resolve();
|
new EntityReferenceResolver( this ).resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,21 +138,6 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Index prepareIndex(MetadataSources metadataSources) {
|
|
||||||
// create a jandex index from the annotated classes
|
|
||||||
Indexer indexer = new Indexer();
|
|
||||||
for ( Class<?> clazz : metadataSources.getAnnotatedClasses() ) {
|
|
||||||
indexClass( indexer, clazz.getName().replace( '.', '/' ) + ".class" );
|
|
||||||
}
|
|
||||||
|
|
||||||
// add package-info from the configured packages
|
|
||||||
for ( String packageName : metadataSources.getAnnotatedPackages() ) {
|
|
||||||
indexClass( indexer, packageName.replace( '.', '/' ) + "/package-info.class" );
|
|
||||||
}
|
|
||||||
|
|
||||||
return indexer.complete();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void bindIndependentMetadata(Binder[] binders, MetadataSources metadataSources) {
|
private void bindIndependentMetadata(Binder[] binders, MetadataSources metadataSources) {
|
||||||
for ( Binder binder : binders ) {
|
for ( Binder binder : binders ) {
|
||||||
binder.bindIndependentMetadata( metadataSources );
|
binder.bindIndependentMetadata( metadataSources );
|
||||||
|
@ -182,8 +150,7 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void bindMappingMetadata(Binder[] binders, MetadataSources metadataSources) {
|
private void bindMappingMetadata(Binder[] binders, MetadataSources metadataSources, List<String> processedEntityNames) {
|
||||||
final ArrayList<String> processedEntityNames = new ArrayList<String>();
|
|
||||||
for ( Binder binder : binders ) {
|
for ( Binder binder : binders ) {
|
||||||
binder.bindMappingMetadata( metadataSources, processedEntityNames );
|
binder.bindMappingMetadata( metadataSources, processedEntityNames );
|
||||||
}
|
}
|
||||||
|
@ -209,9 +176,11 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
|
||||||
return filterDefs.values();
|
return filterDefs.values();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void addIdGenerator(IdGenerator generator) {
|
public void addIdGenerator(IdGenerator generator) {
|
||||||
idGenerators.put( generator.getName(), generator );
|
idGenerators.put( generator.getName(), generator );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IdGenerator getIdGenerator(String name) {
|
public IdGenerator getIdGenerator(String name) {
|
||||||
if ( name == null ) {
|
if ( name == null ) {
|
||||||
|
@ -229,6 +198,7 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
|
||||||
auxiliaryDatabaseObjects.add( auxiliaryDatabaseObject );
|
auxiliaryDatabaseObjects.add( auxiliaryDatabaseObject );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void addNamedNativeQuery(String name, NamedSQLQueryDefinition def) {
|
public void addNamedNativeQuery(String name, NamedSQLQueryDefinition def) {
|
||||||
namedNativeQueryDefs.put( name, def );
|
namedNativeQueryDefs.put( name, def );
|
||||||
}
|
}
|
||||||
|
@ -240,6 +210,7 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
|
||||||
return namedNativeQueryDefs.get( name );
|
return namedNativeQueryDefs.get( name );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void addNamedQuery(String name, NamedQueryDefinition def) {
|
public void addNamedQuery(String name, NamedQueryDefinition def) {
|
||||||
namedQueryDefs.put( name, def );
|
namedQueryDefs.put( name, def );
|
||||||
}
|
}
|
||||||
|
@ -268,64 +239,6 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
|
||||||
return typeDefs.get( name );
|
return typeDefs.get( name );
|
||||||
}
|
}
|
||||||
|
|
||||||
private void applyHibernateMappings(MetadataSources metadataSources, List<String> processedEntityNames) {
|
|
||||||
|
|
||||||
for ( JaxbRoot jaxbRoot : metadataSources.getJaxbRootList() ) {
|
|
||||||
// filter to just hbm-based roots
|
|
||||||
if ( jaxbRoot.getRoot() instanceof XMLHibernateMapping ) {
|
|
||||||
final HbmBinder mappingBinder = new HbmBinder( this, jaxbRoot );
|
|
||||||
mappingBinder.processHibernateMapping();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void applyAnnotationMappings(MetadataSources metadataSources, List<String> processedEntityNames) {
|
|
||||||
// create a jandex index from the annotated classes
|
|
||||||
Indexer indexer = new Indexer();
|
|
||||||
for ( Class<?> clazz : metadataSources.getAnnotatedClasses() ) {
|
|
||||||
indexClass( indexer, clazz.getName().replace( '.', '/' ) + ".class" );
|
|
||||||
}
|
|
||||||
|
|
||||||
// add package-info from the configured packages
|
|
||||||
for ( String packageName : metadataSources.getAnnotatedPackages() ) {
|
|
||||||
indexClass( indexer, packageName.replace( '.', '/' ) + "/package-info.class" );
|
|
||||||
}
|
|
||||||
Index index = indexer.complete();
|
|
||||||
|
|
||||||
|
|
||||||
List<JaxbRoot<XMLEntityMappings>> mappings = new ArrayList<JaxbRoot<XMLEntityMappings>>();
|
|
||||||
for ( JaxbRoot<?> root : metadataSources.getJaxbRootList() ) {
|
|
||||||
if ( root.getRoot() instanceof XMLEntityMappings ) {
|
|
||||||
mappings.add( (JaxbRoot<XMLEntityMappings>) root );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( !mappings.isEmpty() ) {
|
|
||||||
// process the xml configuration
|
|
||||||
final OrmXmlParser ormParser = new OrmXmlParser( this );
|
|
||||||
index = ormParser.parseAndUpdateIndex( mappings, index );
|
|
||||||
}
|
|
||||||
|
|
||||||
// create the annotation binder and pass it the final annotation index
|
|
||||||
final AnnotationBinder annotationBinder = new AnnotationBinder( this, index );
|
|
||||||
annotationBinder.bind();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a single class to the jandex index
|
|
||||||
*
|
|
||||||
* @param indexer the jandex indexer
|
|
||||||
* @param className the fully qualified name of the class
|
|
||||||
*/
|
|
||||||
private void indexClass(Indexer indexer, String className) {
|
|
||||||
InputStream stream = classLoaderService().locateResourceStream( className );
|
|
||||||
try {
|
|
||||||
indexer.index( stream );
|
|
||||||
}
|
|
||||||
catch ( IOException e ) {
|
|
||||||
throw new HibernateException( "Unable to open input stream for class " + className, e );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private ClassLoaderService classLoaderService(){
|
private ClassLoaderService classLoaderService(){
|
||||||
if(classLoaderService==null){
|
if(classLoaderService==null){
|
||||||
classLoaderService = serviceRegistry.getService( ClassLoaderService.class );
|
classLoaderService = serviceRegistry.getService( ClassLoaderService.class );
|
||||||
|
|
|
@ -24,9 +24,12 @@
|
||||||
package org.hibernate.metamodel.source.spi;
|
package org.hibernate.metamodel.source.spi;
|
||||||
|
|
||||||
import org.hibernate.engine.spi.FilterDefinition;
|
import org.hibernate.engine.spi.FilterDefinition;
|
||||||
|
import org.hibernate.engine.spi.NamedQueryDefinition;
|
||||||
|
import org.hibernate.engine.spi.NamedSQLQueryDefinition;
|
||||||
import org.hibernate.metamodel.Metadata;
|
import org.hibernate.metamodel.Metadata;
|
||||||
import org.hibernate.metamodel.binding.EntityBinding;
|
import org.hibernate.metamodel.binding.EntityBinding;
|
||||||
import org.hibernate.metamodel.binding.FetchProfile;
|
import org.hibernate.metamodel.binding.FetchProfile;
|
||||||
|
import org.hibernate.metamodel.binding.IdGenerator;
|
||||||
import org.hibernate.metamodel.binding.PluralAttributeBinding;
|
import org.hibernate.metamodel.binding.PluralAttributeBinding;
|
||||||
import org.hibernate.metamodel.binding.TypeDef;
|
import org.hibernate.metamodel.binding.TypeDef;
|
||||||
import org.hibernate.metamodel.relational.AuxiliaryDatabaseObject;
|
import org.hibernate.metamodel.relational.AuxiliaryDatabaseObject;
|
||||||
|
@ -56,7 +59,13 @@ public interface MetadataImplementor extends Metadata, BindingContext {
|
||||||
|
|
||||||
public void addFilterDefinition(FilterDefinition filterDefinition);
|
public void addFilterDefinition(FilterDefinition filterDefinition);
|
||||||
|
|
||||||
|
public void addIdGenerator(IdGenerator generator);
|
||||||
|
|
||||||
public void registerIdentifierGenerator(String name, String clazz);
|
public void registerIdentifierGenerator(String name, String clazz);
|
||||||
|
|
||||||
|
public void addNamedNativeQuery(String name, NamedSQLQueryDefinition def);
|
||||||
|
|
||||||
|
public void addNamedQuery(String name, NamedQueryDefinition def);
|
||||||
|
|
||||||
public void addAuxiliaryDatabaseObject(AuxiliaryDatabaseObject auxiliaryDatabaseObject);
|
public void addAuxiliaryDatabaseObject(AuxiliaryDatabaseObject auxiliaryDatabaseObject);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue