HHH-6159 - Create EntityManagerFactoryBuilder : integrate EntityManagerFactoryBuilder with metamodel codebase
This commit is contained in:
parent
72af04524a
commit
61c04a0b30
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2012, 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.boot.spi;
|
||||
|
||||
/**
|
||||
* Models the definition of caching settings for a particular region. Generally as found in either:<ul>
|
||||
* <li>{@code cfg.xml}</li>
|
||||
* <li>{@code hbm.xml}</li>
|
||||
* <li>annotation</li>
|
||||
* </ul>
|
||||
* Though certainly other custom sources are acceptable too.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class CacheRegionDefinition {
|
||||
public static enum CacheRegionType {
|
||||
ENTITY,
|
||||
COLLECTION,
|
||||
QUERY
|
||||
}
|
||||
|
||||
private final CacheRegionType regionType;
|
||||
private final String role;
|
||||
private final String usage;
|
||||
private final String region;
|
||||
private final boolean cacheLazy;
|
||||
|
||||
public CacheRegionDefinition(
|
||||
CacheRegionType cacheType,
|
||||
String role,
|
||||
String usage,
|
||||
String region,
|
||||
boolean cacheLazy) {
|
||||
this.regionType = cacheType;
|
||||
this.role = role;
|
||||
this.usage = usage;
|
||||
this.region = region;
|
||||
this.cacheLazy = cacheLazy;
|
||||
}
|
||||
|
||||
public CacheRegionType getRegionType() {
|
||||
return regionType;
|
||||
}
|
||||
|
||||
public String getRole() {
|
||||
return role;
|
||||
}
|
||||
|
||||
public String getUsage() {
|
||||
return usage;
|
||||
}
|
||||
|
||||
public String getRegion() {
|
||||
return region;
|
||||
}
|
||||
|
||||
public boolean isCacheLazy() {
|
||||
return cacheLazy;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2012, 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.boot.spi;
|
||||
|
||||
/**
|
||||
* Models the definition of JACC-based security settings. Generally as found in {@code cfg.xml}, though certainly
|
||||
* other custom sources are acceptable too.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class JaccDefinition {
|
||||
private final String contextId;
|
||||
private final String role;
|
||||
private final String clazz;
|
||||
private final String actions;
|
||||
|
||||
public JaccDefinition(String contextId, String role, String clazz, String actions) {
|
||||
this.contextId = contextId;
|
||||
this.role = role;
|
||||
this.clazz = clazz;
|
||||
this.actions = actions;
|
||||
}
|
||||
|
||||
public String getContextId() {
|
||||
return contextId;
|
||||
}
|
||||
|
||||
public String getRole() {
|
||||
return role;
|
||||
}
|
||||
|
||||
public String getClazz() {
|
||||
return clazz;
|
||||
}
|
||||
|
||||
public String getActions() {
|
||||
return actions;
|
||||
}
|
||||
}
|
|
@ -602,4 +602,35 @@ public interface AvailableSettings {
|
|||
* </ul>
|
||||
*/
|
||||
public static final String INTERCEPTOR = "hibernate.sessionFactory.interceptor";
|
||||
|
||||
/**
|
||||
* Setting which defines the order (and therefore precedence) in whcih Hibernate will process mapping information.
|
||||
* Valid values include: <ul>
|
||||
* <li>{@code hbm}</li>
|
||||
* <li>{@code class}</li>
|
||||
* <li>both {@code hbm} and {@code class} separated by comma</li>
|
||||
* </ul>
|
||||
*
|
||||
* Starting in 5.0 it is also valid to pass a value of {@link org.hibernate.metamodel.MetadataSourceProcessingOrder}
|
||||
* which is an enum specifying which should be processed first.
|
||||
*/
|
||||
public static final String METADATA_PROCESSING_ORDER = "hibernate.mapping.precedence";
|
||||
|
||||
/**
|
||||
* Setting that controls whether we seek out JPA "static metamodel" classes and populate them. Accepts
|
||||
* 3 values:<ul>
|
||||
* <li>
|
||||
* <b>enabled</b> - Do the population
|
||||
* </li>
|
||||
* <li>
|
||||
* <b>disabled</b> - Do not do the population
|
||||
* </li>
|
||||
* <li>
|
||||
* <b>ignoreUnsupported</b> - Do the population, but ignore any non-JPA features that would otherwise
|
||||
* result in the population failing.
|
||||
* </li>
|
||||
* </ul>
|
||||
*/
|
||||
public static final String JPA_METAMODEL_POPULATION = "hibernate.ejb.metamodel.population";
|
||||
|
||||
}
|
||||
|
|
|
@ -182,7 +182,7 @@ public class Configuration implements Serializable {
|
|||
|
||||
public static final String USE_NEW_ID_GENERATOR_MAPPINGS = AvailableSettings.USE_NEW_ID_GENERATOR_MAPPINGS;
|
||||
|
||||
public static final String ARTEFACT_PROCESSING_ORDER = "hibernate.mapping.precedence";
|
||||
public static final String ARTEFACT_PROCESSING_ORDER = AvailableSettings.METADATA_PROCESSING_ORDER;
|
||||
|
||||
/**
|
||||
* Class name of the class needed to enable Search.
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.cfg;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
|
||||
/**
|
||||
|
@ -51,7 +52,7 @@ public enum MetadataSourceType {
|
|||
return name;
|
||||
}
|
||||
|
||||
static MetadataSourceType parsePrecedence(String value) {
|
||||
public static MetadataSourceType parsePrecedence(String value) {
|
||||
if ( HBM.name.equalsIgnoreCase( value ) ) {
|
||||
return HBM;
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
*/
|
||||
package org.hibernate.engine.spi;
|
||||
|
||||
import javax.persistence.metamodel.Metamodel;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
|
@ -287,4 +288,11 @@ public interface SessionFactoryImplementor extends Mapping, SessionFactory {
|
|||
@Deprecated
|
||||
@SuppressWarnings("JavaDoc")
|
||||
public CurrentTenantIdentifierResolver getCurrentTenantIdentifierResolver();
|
||||
|
||||
/**
|
||||
* Obtain the JPA Metamodel instance.
|
||||
*
|
||||
* @since 5.0
|
||||
*/
|
||||
public Metamodel getJpaMetamodel();
|
||||
}
|
||||
|
|
|
@ -1574,4 +1574,19 @@ public interface CoreMessageLogger extends BasicLogger {
|
|||
@LogMessage(level = INFO)
|
||||
@Message(value = "NaturalId queries executed to database: %s", id = 442)
|
||||
void naturalIdQueriesExecuted(long naturalIdQueriesExecutionCount);
|
||||
|
||||
|
||||
// moved from hibernate-entitymanager ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@LogMessage( level = ERROR )
|
||||
@Message( value = "Illegal argument on static metamodel field injection : %s#%s; expected type : %s; encountered type : %s", id = 15007 )
|
||||
void illegalArgumentOnStaticMetamodelFieldInjection( String metamodelClassName,
|
||||
String attributeName,
|
||||
String attributeJavaType,
|
||||
String metamodelFieldJavaType );
|
||||
|
||||
@LogMessage( level = ERROR )
|
||||
@Message( value = "Unable to locate static metamodel field : %s#%s", id = 15011 )
|
||||
void unableToLocateStaticMetamodelField( String metamodelClassName,
|
||||
String attributeName );
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ package org.hibernate.internal;
|
|||
|
||||
import javax.naming.Reference;
|
||||
import javax.naming.StringRefAddr;
|
||||
import javax.persistence.metamodel.Metamodel;
|
||||
import java.io.IOException;
|
||||
import java.io.InvalidObjectException;
|
||||
import java.io.ObjectInputStream;
|
||||
|
@ -111,9 +112,9 @@ import org.hibernate.id.UUIDGenerator;
|
|||
import org.hibernate.id.factory.IdentifierGeneratorFactory;
|
||||
import org.hibernate.integrator.spi.Integrator;
|
||||
import org.hibernate.integrator.spi.IntegratorService;
|
||||
import org.hibernate.internal.util.ReflectHelper;
|
||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||
import org.hibernate.internal.util.config.StrategyInstanceResolver;
|
||||
import org.hibernate.jpa.metamodel.internal.JpaMetaModelPopulationSetting;
|
||||
import org.hibernate.jpa.metamodel.internal.builder.MetamodelBuilder;
|
||||
import org.hibernate.mapping.Collection;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.mapping.RootClass;
|
||||
|
@ -211,6 +212,7 @@ public final class SessionFactoryImpl
|
|||
private final transient TypeHelper typeHelper;
|
||||
private final transient TransactionEnvironment transactionEnvironment;
|
||||
private final transient SessionFactoryOptions sessionFactoryOptions;
|
||||
private final transient Metamodel jpaMetamodel;
|
||||
|
||||
@SuppressWarnings( {"unchecked", "ThrowableResultOfMethodCallIgnored"})
|
||||
public SessionFactoryImpl(
|
||||
|
@ -600,6 +602,23 @@ public final class SessionFactoryImpl
|
|||
|
||||
this.transactionEnvironment = new TransactionEnvironmentImpl( this );
|
||||
this.observer.sessionFactoryCreated( this );
|
||||
|
||||
final JpaMetaModelPopulationSetting jpaMetaModelPopulationSetting = determineJpaMetaModelPopulationSetting( cfg );
|
||||
if ( jpaMetaModelPopulationSetting != JpaMetaModelPopulationSetting.DISABLED ) {
|
||||
this.jpaMetamodel = org.hibernate.jpa.metamodel.internal.legacy.MetamodelImpl.buildMetamodel(
|
||||
cfg.getClassMappings(),
|
||||
this,
|
||||
jpaMetaModelPopulationSetting == JpaMetaModelPopulationSetting.IGNORE_UNSUPPORTED
|
||||
);
|
||||
}
|
||||
else {
|
||||
jpaMetamodel = null;
|
||||
}
|
||||
}
|
||||
|
||||
protected JpaMetaModelPopulationSetting determineJpaMetaModelPopulationSetting(Configuration cfg) {
|
||||
final String setting = cfg.getProperties().getProperty( AvailableSettings.JPA_METAMODEL_POPULATION );
|
||||
return JpaMetaModelPopulationSetting.parse( setting );
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
|
@ -738,6 +757,8 @@ public final class SessionFactoryImpl
|
|||
// Prepare persisters and link them up with their cache
|
||||
// region/access-strategy
|
||||
|
||||
final MetamodelBuilder jpaMetamodelBuilder = new MetamodelBuilder( this );
|
||||
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
if ( settings.getCacheRegionPrefix() != null) {
|
||||
stringBuilder
|
||||
|
@ -816,6 +837,7 @@ public final class SessionFactoryImpl
|
|||
);
|
||||
entityPersisters.put( model.getEntity().getName(), cp );
|
||||
classMeta.put( model.getEntity().getName(), cp.getClassMetadata() );
|
||||
jpaMetamodelBuilder.add( model );
|
||||
}
|
||||
this.classMetadata = Collections.unmodifiableMap(classMeta);
|
||||
|
||||
|
@ -996,6 +1018,8 @@ public final class SessionFactoryImpl
|
|||
|
||||
this.transactionEnvironment = new TransactionEnvironmentImpl( this );
|
||||
this.observer.sessionFactoryCreated( this );
|
||||
|
||||
this.jpaMetamodel = jpaMetamodelBuilder.buildMetamodel();
|
||||
}
|
||||
|
||||
@SuppressWarnings( {"unchecked"} )
|
||||
|
@ -1779,6 +1803,11 @@ public final class SessionFactoryImpl
|
|||
return sessionFactoryOptions.getCurrentTenantIdentifierResolver();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Metamodel getJpaMetamodel() {
|
||||
return jpaMetamodel;
|
||||
}
|
||||
|
||||
|
||||
// Serialization handling ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
|
|
@ -57,14 +57,13 @@ public final class ConfigurationHelper {
|
|||
* @return The value, or null if not found
|
||||
*/
|
||||
public static String getString(String name, Map values) {
|
||||
Object value = values.get( name );
|
||||
if ( value == null ) {
|
||||
return null;
|
||||
}
|
||||
if ( String.class.isInstance( value ) ) {
|
||||
return (String) value;
|
||||
}
|
||||
return value.toString();
|
||||
return asString( values.get( name ) );
|
||||
}
|
||||
|
||||
public static String asString(Object value) {
|
||||
return value == null
|
||||
? null
|
||||
: value.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -118,6 +117,18 @@ public final class ConfigurationHelper {
|
|||
);
|
||||
}
|
||||
|
||||
public static Boolean asBoolean(Object value) {
|
||||
if ( value == null ) {
|
||||
return null;
|
||||
}
|
||||
if ( Boolean.class.isInstance( value ) ) {
|
||||
return ( (Boolean) value );
|
||||
}
|
||||
else {
|
||||
return Boolean.valueOf( value.toString() );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the config value as an int
|
||||
*
|
||||
|
|
|
@ -0,0 +1,131 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
|
||||
* third-party contributors as indicated by either @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.jpa.metamodel.internal;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Member;
|
||||
import java.lang.reflect.Method;
|
||||
import javax.persistence.metamodel.Attribute;
|
||||
import javax.persistence.metamodel.ManagedType;
|
||||
|
||||
import org.hibernate.internal.util.ReflectHelper;
|
||||
|
||||
/**
|
||||
* Models the commonality of the JPA {@link Attribute} hierarchy.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public abstract class AbstractAttribute<X, Y> implements Attribute<X, Y>, Serializable {
|
||||
private final String name;
|
||||
private final Class<Y> javaType;
|
||||
private final AbstractManagedType<X> declaringType;
|
||||
private transient Member member;
|
||||
private final PersistentAttributeType persistentAttributeType;
|
||||
|
||||
public AbstractAttribute(
|
||||
String name,
|
||||
Class<Y> javaType,
|
||||
AbstractManagedType<X> declaringType,
|
||||
Member member,
|
||||
PersistentAttributeType persistentAttributeType) {
|
||||
this.name = name;
|
||||
this.javaType = javaType;
|
||||
this.declaringType = declaringType;
|
||||
this.member = member;
|
||||
this.persistentAttributeType = persistentAttributeType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ManagedType<X> getDeclaringType() {
|
||||
return declaringType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<Y> getJavaType() {
|
||||
return javaType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Member getJavaMember() {
|
||||
return member;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PersistentAttributeType getPersistentAttributeType() {
|
||||
return persistentAttributeType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used by JDK serialization...
|
||||
*
|
||||
* @param oos The output stream to which we are being written...
|
||||
* @throws IOException Indicates a general IO stream exception
|
||||
*/
|
||||
protected void writeObject(ObjectOutputStream oos) throws IOException {
|
||||
oos.defaultWriteObject();
|
||||
oos.writeObject( getJavaMember().getDeclaringClass().getName() );
|
||||
oos.writeObject( getJavaMember().getName() );
|
||||
// should only ever be a field or the getter-method...
|
||||
oos.writeObject( Method.class.isInstance( getJavaMember() ) ? "method" : "field" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Used by JDK serialization...
|
||||
*
|
||||
* @param ois The input stream from which we are being read...
|
||||
* @throws java.io.IOException Indicates a general IO stream exception
|
||||
* @throws ClassNotFoundException Indicates a class resolution issue
|
||||
*/
|
||||
protected void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
|
||||
ois.defaultReadObject();
|
||||
final String memberDeclaringClassName = ( String ) ois.readObject();
|
||||
final String memberName = ( String ) ois.readObject();
|
||||
final String memberType = ( String ) ois.readObject();
|
||||
|
||||
final Class memberDeclaringClass = Class.forName(
|
||||
memberDeclaringClassName,
|
||||
false,
|
||||
declaringType.getJavaType().getClassLoader()
|
||||
);
|
||||
try {
|
||||
this.member = "method".equals( memberType )
|
||||
? memberDeclaringClass.getMethod( memberName, ReflectHelper.NO_PARAM_SIGNATURE )
|
||||
: memberDeclaringClass.getField( memberName );
|
||||
}
|
||||
catch ( Exception e ) {
|
||||
throw new IllegalStateException(
|
||||
"Unable to locate member [" + memberDeclaringClassName + "#"
|
||||
+ memberName + "]"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,317 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
|
||||
* third-party contributors as indicated by either @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.jpa.metamodel.internal;
|
||||
import java.io.Serializable;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import javax.persistence.metamodel.Attribute;
|
||||
import javax.persistence.metamodel.IdentifiableType;
|
||||
import javax.persistence.metamodel.SingularAttribute;
|
||||
import javax.persistence.metamodel.Type;
|
||||
|
||||
/**
|
||||
* Defines commonality for the JPA {@link IdentifiableType} types. JPA defines
|
||||
* identifiable types as entities or mapped-superclasses. Basically things to which an
|
||||
* identifier can be attached.
|
||||
* <p/>
|
||||
* NOTE : Currently we only really have support for direct entities in the Hibernate metamodel
|
||||
* as the information for them is consumed into the closest actual entity subclass(es) in the
|
||||
* internal Hibernate mapping-metamodel.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public abstract class AbstractIdentifiableType<X>
|
||||
extends AbstractManagedType<X>
|
||||
implements IdentifiableType<X>, Serializable {
|
||||
|
||||
private final boolean hasIdentifierProperty;
|
||||
private final boolean isVersioned;
|
||||
|
||||
private SingularAttributeImpl<X, ?> id;
|
||||
private SingularAttributeImpl<X, ?> version;
|
||||
private Set<SingularAttribute<? super X,?>> idClassAttributes;
|
||||
|
||||
public AbstractIdentifiableType(
|
||||
Class<X> javaType,
|
||||
AbstractIdentifiableType<? super X> superType,
|
||||
boolean hasIdentifierProperty,
|
||||
boolean versioned) {
|
||||
super( javaType, superType );
|
||||
this.hasIdentifierProperty = hasIdentifierProperty;
|
||||
isVersioned = versioned;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public AbstractIdentifiableType<? super X> getSupertype() {
|
||||
return ( AbstractIdentifiableType<? super X> ) super.getSupertype();
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if a non-null super type is required to provide the
|
||||
* identifier attribute(s) if this object does not have a declared
|
||||
* identifier.
|
||||
* .
|
||||
* @return true, if a non-null super type is required to provide
|
||||
* the identifier attribute(s) if this object does not have a
|
||||
* declared identifier; false, otherwise.
|
||||
*/
|
||||
protected abstract boolean requiresSupertypeForNonDeclaredIdentifier();
|
||||
|
||||
protected AbstractIdentifiableType<? super X> requireSupertype() {
|
||||
if ( getSupertype() == null ) {
|
||||
throw new IllegalStateException( "No supertype found" );
|
||||
}
|
||||
return getSupertype();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public boolean hasSingleIdAttribute() {
|
||||
return hasIdentifierProperty;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public <Y> SingularAttribute<? super X, Y> getId(Class<Y> javaType) {
|
||||
final SingularAttribute<? super X, Y> id_;
|
||||
if ( id != null ) {
|
||||
checkSimpleId();
|
||||
id_ = ( SingularAttribute<? super X, Y> ) id;
|
||||
if ( javaType != id.getJavaType() ) {
|
||||
throw new IllegalArgumentException( "Id attribute was not of specified type : " + javaType.getName() );
|
||||
}
|
||||
}
|
||||
else {
|
||||
//yuk yuk bad me
|
||||
if ( ! requiresSupertypeForNonDeclaredIdentifier()) {
|
||||
final AbstractIdentifiableType<? super X> supertype = getSupertype();
|
||||
if (supertype != null) {
|
||||
id_ = supertype.getId( javaType );
|
||||
}
|
||||
else {
|
||||
id_ = null;
|
||||
}
|
||||
}
|
||||
else {
|
||||
id_ = requireSupertype().getId( javaType );
|
||||
}
|
||||
}
|
||||
return id_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Centralized check to ensure the id for this hierarchy is a simple one (i.e., does not use
|
||||
* an id-class).
|
||||
*
|
||||
* @see #checkIdClass()
|
||||
*/
|
||||
protected void checkSimpleId() {
|
||||
if ( ! hasIdentifierProperty ) {
|
||||
throw new IllegalStateException( "This class uses an @IdClass" );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public <Y> SingularAttribute<X, Y> getDeclaredId(Class<Y> javaType) {
|
||||
checkDeclaredId();
|
||||
checkSimpleId();
|
||||
if ( javaType != id.getJavaType() ) {
|
||||
throw new IllegalArgumentException( "Id attribute was not of specified type : " + javaType.getName() );
|
||||
}
|
||||
return (SingularAttribute<X, Y>) id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Centralized check to ensure the id is actually declared on the class mapped here, as opposed to a
|
||||
* super class.
|
||||
*/
|
||||
protected void checkDeclaredId() {
|
||||
if ( id == null ) {
|
||||
throw new IllegalArgumentException( "The id attribute is not declared on this type" );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Type<?> getIdType() {
|
||||
if ( id != null ) {
|
||||
checkSimpleId();
|
||||
return id.getType();
|
||||
}
|
||||
else {
|
||||
return requireSupertype().getIdType();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasIdClassAttributesDefined() {
|
||||
return idClassAttributes != null ||
|
||||
( getSupertype() != null && getSupertype().hasIdClassAttributesDefined() );
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Set<SingularAttribute<? super X, ?>> getIdClassAttributes() {
|
||||
if ( idClassAttributes != null ) {
|
||||
checkIdClass();
|
||||
}
|
||||
else {
|
||||
// Java does not allow casting requireSupertype().getIdClassAttributes()
|
||||
// to Set<SingularAttribute<? super X, ?>> because the
|
||||
// superclass X is a different Java type from this X
|
||||
// (i.e, getSupertype().getJavaType() != getJavaType()).
|
||||
// It will, however, allow a Set<SingularAttribute<? super X, ?>>
|
||||
// to be initialized with requireSupertype().getIdClassAttributes(),
|
||||
// since getSupertype().getJavaType() is a superclass of getJavaType()
|
||||
if ( requiresSupertypeForNonDeclaredIdentifier() ) {
|
||||
idClassAttributes = new HashSet<SingularAttribute<? super X, ?>>( requireSupertype().getIdClassAttributes() );
|
||||
}
|
||||
else if ( getSupertype() != null && hasIdClassAttributesDefined() ) {
|
||||
idClassAttributes = new HashSet<SingularAttribute<? super X, ?>>( getSupertype().getIdClassAttributes() );
|
||||
}
|
||||
}
|
||||
return idClassAttributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Centralized check to ensure the id for this hierarchy uses an id-class.
|
||||
*
|
||||
* @see #checkSimpleId()
|
||||
*/
|
||||
private void checkIdClass() {
|
||||
if ( hasIdentifierProperty ) {
|
||||
throw new IllegalArgumentException( "This class does not use @IdClass" );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public boolean hasVersionAttribute() {
|
||||
return isVersioned;
|
||||
}
|
||||
|
||||
public boolean hasDeclaredVersionAttribute() {
|
||||
return isVersioned && version != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public <Y> SingularAttribute<? super X, Y> getVersion(Class<Y> javaType) {
|
||||
if ( ! hasVersionAttribute() ) {
|
||||
return null;
|
||||
}
|
||||
final SingularAttribute<? super X, Y> version_;
|
||||
if ( version != null ) {
|
||||
version_ = ( SingularAttribute<? super X, Y> ) version;
|
||||
if ( javaType != version.getJavaType() ) {
|
||||
throw new IllegalArgumentException( "Version attribute was not of specified type : " + javaType.getName() );
|
||||
}
|
||||
}
|
||||
else {
|
||||
version_ = requireSupertype().getVersion( javaType );
|
||||
}
|
||||
return version_;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public <Y> SingularAttribute<X, Y> getDeclaredVersion(Class<Y> javaType) {
|
||||
checkDeclaredVersion();
|
||||
if ( javaType != version.getJavaType() ) {
|
||||
throw new IllegalArgumentException( "Version attribute was not of specified type : " + javaType.getName() );
|
||||
}
|
||||
return ( SingularAttribute<X, Y> ) version;
|
||||
}
|
||||
|
||||
/**
|
||||
* For used to retrieve the declared version when populating the static metamodel.
|
||||
*
|
||||
* @return The declared
|
||||
*/
|
||||
public SingularAttribute<X, ?> getDeclaredVersion() {
|
||||
checkDeclaredVersion();
|
||||
return version;
|
||||
}
|
||||
|
||||
/**
|
||||
* Centralized check to ensure the version (if one) is actually declared on the class mapped here, as opposed to a
|
||||
* super class.
|
||||
*/
|
||||
protected void checkDeclaredVersion() {
|
||||
if ( version == null || ( getSupertype() != null && getSupertype().hasVersionAttribute() )) {
|
||||
throw new IllegalArgumentException( "The version attribute is not declared on this type" );
|
||||
}
|
||||
}
|
||||
|
||||
public Builder<X> getBuilder() {
|
||||
final AbstractManagedType.Builder<X> managedBuilder = super.getBuilder();
|
||||
return new Builder<X>() {
|
||||
public void applyIdAttribute(SingularAttributeImpl<X, ?> idAttribute) {
|
||||
AbstractIdentifiableType.this.id = idAttribute;
|
||||
managedBuilder.addAttribute( idAttribute );
|
||||
}
|
||||
|
||||
public void applyIdClassAttributes(Set<SingularAttribute<? super X,?>> idClassAttributes) {
|
||||
for ( SingularAttribute<? super X,?> idClassAttribute : idClassAttributes ) {
|
||||
if ( AbstractIdentifiableType.this == idClassAttribute.getDeclaringType() ) {
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
SingularAttribute<X,?> declaredAttribute = ( SingularAttribute<X,?> ) idClassAttribute;
|
||||
addAttribute( declaredAttribute );
|
||||
}
|
||||
}
|
||||
AbstractIdentifiableType.this.idClassAttributes = idClassAttributes;
|
||||
}
|
||||
|
||||
public void applyVersionAttribute(SingularAttributeImpl<X, ?> versionAttribute) {
|
||||
AbstractIdentifiableType.this.version = versionAttribute;
|
||||
managedBuilder.addAttribute( versionAttribute );
|
||||
}
|
||||
|
||||
public void addAttribute(Attribute<X, ?> attribute) {
|
||||
managedBuilder.addAttribute( attribute );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static interface Builder<X> extends AbstractManagedType.Builder<X> {
|
||||
public void applyIdAttribute(SingularAttributeImpl<X,?> idAttribute);
|
||||
public void applyIdClassAttributes(Set<SingularAttribute<? super X,?>> idClassAttributes);
|
||||
public void applyVersionAttribute(SingularAttributeImpl<X,?> versionAttribute);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,479 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
|
||||
* third-party contributors as indicated by either @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.jpa.metamodel.internal;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import javax.persistence.metamodel.Attribute;
|
||||
import javax.persistence.metamodel.Bindable;
|
||||
import javax.persistence.metamodel.CollectionAttribute;
|
||||
import javax.persistence.metamodel.ListAttribute;
|
||||
import javax.persistence.metamodel.ManagedType;
|
||||
import javax.persistence.metamodel.MapAttribute;
|
||||
import javax.persistence.metamodel.PluralAttribute;
|
||||
import javax.persistence.metamodel.SetAttribute;
|
||||
import javax.persistence.metamodel.SingularAttribute;
|
||||
|
||||
import org.hibernate.annotations.common.AssertionFailure;
|
||||
|
||||
/**
|
||||
* Defines commonality for the JPA {@link ManagedType} hierarchy of interfaces.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public abstract class AbstractManagedType<X>
|
||||
extends AbstractType<X>
|
||||
implements ManagedType<X>, Serializable {
|
||||
|
||||
private final AbstractManagedType<? super X> superType;
|
||||
|
||||
private final Map<String,Attribute<X, ?>> declaredAttributes
|
||||
= new HashMap<String, Attribute<X,?>>();
|
||||
private final Map<String, SingularAttribute<X, ?>> declaredSingularAttributes
|
||||
= new HashMap<String, SingularAttribute<X,?>>();
|
||||
private final Map<String, PluralAttribute<X, ?, ?>> declaredPluralAttributes
|
||||
= new HashMap<String, PluralAttribute<X,?,?>>();
|
||||
|
||||
protected AbstractManagedType(Class<X> javaType, AbstractManagedType<? super X> superType) {
|
||||
super( javaType );
|
||||
this.superType = superType;
|
||||
}
|
||||
|
||||
public AbstractManagedType<? super X> getSupertype() {
|
||||
return superType;
|
||||
}
|
||||
|
||||
private boolean locked = false;
|
||||
|
||||
public Builder<X> getBuilder() {
|
||||
if ( locked ) {
|
||||
throw new IllegalStateException( "Type has been locked" );
|
||||
}
|
||||
return new Builder<X>() {
|
||||
public void addAttribute(Attribute<X,?> attribute) {
|
||||
declaredAttributes.put( attribute.getName(), attribute );
|
||||
final Bindable.BindableType bindableType = ( ( Bindable ) attribute ).getBindableType();
|
||||
switch ( bindableType ) {
|
||||
case SINGULAR_ATTRIBUTE : {
|
||||
declaredSingularAttributes.put( attribute.getName(), (SingularAttribute<X,?>) attribute );
|
||||
break;
|
||||
}
|
||||
case PLURAL_ATTRIBUTE : {
|
||||
declaredPluralAttributes.put(attribute.getName(), (PluralAttribute<X,?,?>) attribute );
|
||||
break;
|
||||
}
|
||||
default : {
|
||||
throw new AssertionFailure( "unknown bindable type: " + bindableType );
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public void lock() {
|
||||
locked = true;
|
||||
}
|
||||
|
||||
public static interface Builder<X> {
|
||||
public void addAttribute(Attribute<X,?> attribute);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public Set<Attribute<? super X, ?>> getAttributes() {
|
||||
HashSet attributes = new HashSet<Attribute<X, ?>>( declaredAttributes.values() );
|
||||
if ( getSupertype() != null ) {
|
||||
attributes.addAll( getSupertype().getAttributes() );
|
||||
}
|
||||
return attributes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Attribute<X, ?>> getDeclaredAttributes() {
|
||||
return new HashSet<Attribute<X, ?>>( declaredAttributes.values() );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public Attribute<? super X, ?> getAttribute(String name) {
|
||||
Attribute<? super X, ?> attribute = declaredAttributes.get( name );
|
||||
if ( attribute == null && getSupertype() != null ) {
|
||||
attribute = getSupertype().getAttribute( name );
|
||||
}
|
||||
return attribute;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Attribute<X, ?> getDeclaredAttribute(String name) {
|
||||
final Attribute<X, ?> attr = declaredSingularAttributes.get( name );
|
||||
checkNotNull( "Attribute ", attr, name );
|
||||
return attr;
|
||||
}
|
||||
|
||||
private void checkNotNull(String attributeType, Attribute<?,?> attribute, String name) {
|
||||
if ( attribute == null ) {
|
||||
throw new IllegalArgumentException( attributeType + " named " + name + " is not present" );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public Set<SingularAttribute<? super X, ?>> getSingularAttributes() {
|
||||
HashSet attributes = new HashSet<SingularAttribute<X, ?>>( declaredSingularAttributes.values() );
|
||||
if ( getSupertype() != null ) {
|
||||
attributes.addAll( getSupertype().getSingularAttributes() );
|
||||
}
|
||||
return attributes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<SingularAttribute<X, ?>> getDeclaredSingularAttributes() {
|
||||
return new HashSet<SingularAttribute<X, ?>>( declaredSingularAttributes.values() );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public SingularAttribute<? super X, ?> getSingularAttribute(String name) {
|
||||
SingularAttribute<? super X, ?> attribute = declaredSingularAttributes.get( name );
|
||||
if ( attribute == null && getSupertype() != null ) {
|
||||
attribute = getSupertype().getSingularAttribute( name );
|
||||
}
|
||||
return attribute;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SingularAttribute<X, ?> getDeclaredSingularAttribute(String name) {
|
||||
final SingularAttribute<X, ?> attr = declaredSingularAttributes.get( name );
|
||||
checkNotNull( "SingularAttribute ", attr, name );
|
||||
return attr;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public <Y> SingularAttribute<? super X, Y> getSingularAttribute(String name, Class<Y> type) {
|
||||
SingularAttribute<? super X, ?> attribute = declaredSingularAttributes.get( name );
|
||||
if ( attribute == null && getSupertype() != null ) {
|
||||
attribute = getSupertype().getSingularAttribute( name );
|
||||
}
|
||||
checkTypeForSingleAttribute( "SingularAttribute ", attribute, name, type );
|
||||
return ( SingularAttribute<? super X, Y> ) attribute;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings( "unchecked")
|
||||
public <Y> SingularAttribute<X, Y> getDeclaredSingularAttribute(String name, Class<Y> javaType) {
|
||||
final SingularAttribute<X, ?> attr = declaredSingularAttributes.get( name );
|
||||
checkTypeForSingleAttribute( "SingularAttribute ", attr, name, javaType );
|
||||
return ( SingularAttribute<X, Y> ) attr;
|
||||
}
|
||||
|
||||
private <Y> void checkTypeForSingleAttribute(
|
||||
String attributeType,
|
||||
SingularAttribute<?,?> attribute,
|
||||
String name,
|
||||
Class<Y> javaType) {
|
||||
if ( attribute == null || ( javaType != null && !attribute.getBindableJavaType().equals( javaType ) ) ) {
|
||||
if ( isPrimitiveVariant( attribute, javaType ) ) {
|
||||
return;
|
||||
}
|
||||
throw new IllegalArgumentException(
|
||||
attributeType + " named " + name
|
||||
+ ( javaType != null ? " and of type " + javaType.getName() : "" )
|
||||
+ " is not present"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "SimplifiableIfStatement" })
|
||||
protected <Y> boolean isPrimitiveVariant(SingularAttribute<?,?> attribute, Class<Y> javaType) {
|
||||
if ( attribute == null ) {
|
||||
return false;
|
||||
}
|
||||
Class declaredType = attribute.getBindableJavaType();
|
||||
|
||||
if ( declaredType.isPrimitive() ) {
|
||||
return ( Boolean.class.equals( javaType ) && Boolean.TYPE.equals( declaredType ) )
|
||||
|| ( Character.class.equals( javaType ) && Character.TYPE.equals( declaredType ) )
|
||||
|| ( Byte.class.equals( javaType ) && Byte.TYPE.equals( declaredType ) )
|
||||
|| ( Short.class.equals( javaType ) && Short.TYPE.equals( declaredType ) )
|
||||
|| ( Integer.class.equals( javaType ) && Integer.TYPE.equals( declaredType ) )
|
||||
|| ( Long.class.equals( javaType ) && Long.TYPE.equals( declaredType ) )
|
||||
|| ( Float.class.equals( javaType ) && Float.TYPE.equals( declaredType ) )
|
||||
|| ( Double.class.equals( javaType ) && Double.TYPE.equals( declaredType ) );
|
||||
}
|
||||
|
||||
if ( javaType.isPrimitive() ) {
|
||||
return ( Boolean.class.equals( declaredType ) && Boolean.TYPE.equals( javaType ) )
|
||||
|| ( Character.class.equals( declaredType ) && Character.TYPE.equals( javaType ) )
|
||||
|| ( Byte.class.equals( declaredType ) && Byte.TYPE.equals( javaType ) )
|
||||
|| ( Short.class.equals( declaredType ) && Short.TYPE.equals( javaType ) )
|
||||
|| ( Integer.class.equals( declaredType ) && Integer.TYPE.equals( javaType ) )
|
||||
|| ( Long.class.equals( declaredType ) && Long.TYPE.equals( javaType ) )
|
||||
|| ( Float.class.equals( declaredType ) && Float.TYPE.equals( javaType ) )
|
||||
|| ( Double.class.equals( declaredType ) && Double.TYPE.equals( javaType ) );
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public Set<PluralAttribute<? super X, ?, ?>> getPluralAttributes() {
|
||||
HashSet attributes = new HashSet<PluralAttribute<? super X, ?, ?>>( declaredPluralAttributes.values() );
|
||||
if ( getSupertype() != null ) {
|
||||
attributes.addAll( getSupertype().getPluralAttributes() );
|
||||
}
|
||||
return attributes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<PluralAttribute<X, ?, ?>> getDeclaredPluralAttributes() {
|
||||
return new HashSet<PluralAttribute<X,?,?>>( declaredPluralAttributes.values() );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public CollectionAttribute<? super X, ?> getCollection(String name) {
|
||||
PluralAttribute<? super X, ?, ?> attribute = getPluralAttribute( name );
|
||||
if ( attribute == null && getSupertype() != null ) {
|
||||
attribute = getSupertype().getPluralAttribute( name );
|
||||
}
|
||||
basicCollectionCheck( attribute, name );
|
||||
return ( CollectionAttribute<X, ?> ) attribute;
|
||||
}
|
||||
|
||||
private PluralAttribute<? super X, ?, ?> getPluralAttribute(String name) {
|
||||
return declaredPluralAttributes.get( name );
|
||||
}
|
||||
|
||||
private void basicCollectionCheck(PluralAttribute<? super X, ?, ?> attribute, String name) {
|
||||
checkNotNull( "CollectionAttribute", attribute, name );
|
||||
if ( ! CollectionAttribute.class.isAssignableFrom( attribute.getClass() ) ) {
|
||||
throw new IllegalArgumentException( name + " is not a CollectionAttribute: " + attribute.getClass() );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings( "unchecked")
|
||||
public CollectionAttribute<X, ?> getDeclaredCollection(String name) {
|
||||
final PluralAttribute<X,?,?> attribute = declaredPluralAttributes.get( name );
|
||||
basicCollectionCheck( attribute, name );
|
||||
return ( CollectionAttribute<X, ?> ) attribute;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public SetAttribute<? super X, ?> getSet(String name) {
|
||||
PluralAttribute<? super X, ?, ?> attribute = getPluralAttribute( name );
|
||||
if ( attribute == null && getSupertype() != null ) {
|
||||
attribute = getSupertype().getPluralAttribute( name );
|
||||
}
|
||||
basicSetCheck( attribute, name );
|
||||
return (SetAttribute<? super X, ?>) attribute;
|
||||
}
|
||||
|
||||
private void basicSetCheck(PluralAttribute<? super X, ?, ?> attribute, String name) {
|
||||
checkNotNull( "SetAttribute", attribute, name );
|
||||
if ( ! SetAttribute.class.isAssignableFrom( attribute.getClass() ) ) {
|
||||
throw new IllegalArgumentException( name + " is not a SetAttribute: " + attribute.getClass() );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings( "unchecked")
|
||||
public SetAttribute<X, ?> getDeclaredSet(String name) {
|
||||
final PluralAttribute<X,?,?> attribute = declaredPluralAttributes.get( name );
|
||||
basicSetCheck( attribute, name );
|
||||
return ( SetAttribute<X, ?> ) attribute;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public ListAttribute<? super X, ?> getList(String name) {
|
||||
PluralAttribute<? super X, ?, ?> attribute = getPluralAttribute( name );
|
||||
if ( attribute == null && getSupertype() != null ) {
|
||||
attribute = getSupertype().getPluralAttribute( name );
|
||||
}
|
||||
basicListCheck( attribute, name );
|
||||
return (ListAttribute<? super X, ?>) attribute;
|
||||
}
|
||||
|
||||
private void basicListCheck(PluralAttribute<? super X, ?, ?> attribute, String name) {
|
||||
checkNotNull( "ListAttribute", attribute, name );
|
||||
if ( ! ListAttribute.class.isAssignableFrom( attribute.getClass() ) ) {
|
||||
throw new IllegalArgumentException( name + " is not a ListAttribute: " + attribute.getClass() );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListAttribute<X, ?> getDeclaredList(String name) {
|
||||
final PluralAttribute<X,?,?> attribute = declaredPluralAttributes.get( name );
|
||||
basicListCheck( attribute, name );
|
||||
return ( ListAttribute<X, ?> ) attribute;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public MapAttribute<? super X, ?, ?> getMap(String name) {
|
||||
PluralAttribute<? super X, ?, ?> attribute = getPluralAttribute( name );
|
||||
if ( attribute == null && getSupertype() != null ) {
|
||||
attribute = getSupertype().getPluralAttribute( name );
|
||||
}
|
||||
basicMapCheck( attribute, name );
|
||||
return (MapAttribute<? super X, ?, ?>) attribute;
|
||||
}
|
||||
|
||||
private void basicMapCheck(PluralAttribute<? super X, ?, ?> attribute, String name) {
|
||||
checkNotNull( "MapAttribute", attribute, name );
|
||||
if ( ! MapAttribute.class.isAssignableFrom( attribute.getClass() ) ) {
|
||||
throw new IllegalArgumentException( name + " is not a MapAttribute: " + attribute.getClass() );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public MapAttribute<X, ?, ?> getDeclaredMap(String name) {
|
||||
final PluralAttribute<X,?,?> attribute = declaredPluralAttributes.get( name );
|
||||
basicMapCheck( attribute, name );
|
||||
return ( MapAttribute<X,?,?> ) attribute;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public <E> CollectionAttribute<? super X, E> getCollection(String name, Class<E> elementType) {
|
||||
PluralAttribute<? super X, ?, ?> attribute = declaredPluralAttributes.get( name );
|
||||
if ( attribute == null && getSupertype() != null ) {
|
||||
attribute = getSupertype().getPluralAttribute( name );
|
||||
}
|
||||
checkCollectionElementType( attribute, name, elementType );
|
||||
return ( CollectionAttribute<? super X, E> ) attribute;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <E> CollectionAttribute<X, E> getDeclaredCollection(String name, Class<E> elementType) {
|
||||
final PluralAttribute<X,?,?> attribute = declaredPluralAttributes.get( name );
|
||||
checkCollectionElementType( attribute, name, elementType );
|
||||
return ( CollectionAttribute<X, E> ) attribute;
|
||||
}
|
||||
|
||||
private <E> void checkCollectionElementType(PluralAttribute<?,?,?> attribute, String name, Class<E> elementType) {
|
||||
checkTypeForPluralAttributes( "CollectionAttribute", attribute, name, elementType, PluralAttribute.CollectionType.COLLECTION );
|
||||
}
|
||||
|
||||
private <E> void checkTypeForPluralAttributes(
|
||||
String attributeType,
|
||||
PluralAttribute<?,?,?> attribute,
|
||||
String name,
|
||||
Class<E> elementType,
|
||||
PluralAttribute.CollectionType collectionType) {
|
||||
if ( attribute == null
|
||||
|| ( elementType != null && !attribute.getBindableJavaType().equals( elementType ) )
|
||||
|| attribute.getCollectionType() != collectionType ) {
|
||||
throw new IllegalArgumentException(
|
||||
attributeType + " named " + name
|
||||
+ ( elementType != null ? " and of element type " + elementType : "" )
|
||||
+ " is not present"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public <E> SetAttribute<? super X, E> getSet(String name, Class<E> elementType) {
|
||||
PluralAttribute<? super X, ?, ?> attribute = declaredPluralAttributes.get( name );
|
||||
if ( attribute == null && getSupertype() != null ) {
|
||||
attribute = getSupertype().getPluralAttribute( name );
|
||||
}
|
||||
checkSetElementType( attribute, name, elementType );
|
||||
return ( SetAttribute<? super X, E> ) attribute;
|
||||
}
|
||||
|
||||
private <E> void checkSetElementType(PluralAttribute<? super X, ?, ?> attribute, String name, Class<E> elementType) {
|
||||
checkTypeForPluralAttributes( "SetAttribute", attribute, name, elementType, PluralAttribute.CollectionType.SET );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <E> SetAttribute<X, E> getDeclaredSet(String name, Class<E> elementType) {
|
||||
final PluralAttribute<X,?,?> attribute = declaredPluralAttributes.get( name );
|
||||
checkSetElementType( attribute, name, elementType );
|
||||
return ( SetAttribute<X, E> ) attribute;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public <E> ListAttribute<? super X, E> getList(String name, Class<E> elementType) {
|
||||
PluralAttribute<? super X, ?, ?> attribute = declaredPluralAttributes.get( name );
|
||||
if ( attribute == null && getSupertype() != null ) {
|
||||
attribute = getSupertype().getPluralAttribute( name );
|
||||
}
|
||||
checkListElementType( attribute, name, elementType );
|
||||
return ( ListAttribute<? super X, E> ) attribute;
|
||||
}
|
||||
|
||||
private <E> void checkListElementType(PluralAttribute<? super X, ?, ?> attribute, String name, Class<E> elementType) {
|
||||
checkTypeForPluralAttributes( "ListAttribute", attribute, name, elementType, PluralAttribute.CollectionType.LIST );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <E> ListAttribute<X, E> getDeclaredList(String name, Class<E> elementType) {
|
||||
final PluralAttribute<X,?,?> attribute = declaredPluralAttributes.get( name );
|
||||
checkListElementType( attribute, name, elementType );
|
||||
return ( ListAttribute<X, E> ) attribute;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public <K, V> MapAttribute<? super X, K, V> getMap(String name, Class<K> keyType, Class<V> valueType) {
|
||||
PluralAttribute<? super X, ?, ?> attribute = getPluralAttribute( name );
|
||||
if ( attribute == null && getSupertype() != null ) {
|
||||
attribute = getSupertype().getPluralAttribute( name );
|
||||
}
|
||||
checkMapValueType( attribute, name, valueType );
|
||||
final MapAttribute<? super X, K, V> mapAttribute = ( MapAttribute<? super X, K, V> ) attribute;
|
||||
checkMapKeyType( mapAttribute, name, keyType );
|
||||
return mapAttribute;
|
||||
}
|
||||
|
||||
private <V> void checkMapValueType(PluralAttribute<? super X, ?, ?> attribute, String name, Class<V> valueType) {
|
||||
checkTypeForPluralAttributes( "MapAttribute", attribute, name, valueType, PluralAttribute.CollectionType.MAP);
|
||||
}
|
||||
|
||||
private <K,V> void checkMapKeyType(MapAttribute<? super X, K, V> mapAttribute, String name, Class<K> keyType) {
|
||||
if ( mapAttribute.getKeyJavaType() != keyType ) {
|
||||
throw new IllegalArgumentException( "MapAttribute named " + name + " does not support a key of type " + keyType );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <K, V> MapAttribute<X, K, V> getDeclaredMap(String name, Class<K> keyType, Class<V> valueType) {
|
||||
final PluralAttribute<X,?,?> attribute = declaredPluralAttributes.get( name );
|
||||
checkMapValueType( attribute, name, valueType );
|
||||
final MapAttribute<X, K, V> mapAttribute = ( MapAttribute<X, K, V> ) attribute;
|
||||
checkMapKeyType( mapAttribute, name, keyType );
|
||||
return mapAttribute;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
|
||||
* third-party contributors as indicated by either @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.jpa.metamodel.internal;
|
||||
import java.io.Serializable;
|
||||
import javax.persistence.metamodel.Type;
|
||||
|
||||
/**
|
||||
* Defines commonality for the JPA {@link Type} hierarchy of interfaces.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public abstract class AbstractType<X> implements Type<X>, Serializable {
|
||||
private final Class<X> javaType;
|
||||
|
||||
public AbstractType(Class<X> javaType) {
|
||||
this.javaType = javaType;
|
||||
}
|
||||
|
||||
public Class<X> getJavaType() {
|
||||
return javaType;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright (c) 2009, Red Hat Middleware LLC 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 Middleware LLC.
|
||||
*
|
||||
* 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.jpa.metamodel.internal;
|
||||
import java.io.Serializable;
|
||||
import javax.persistence.metamodel.BasicType;
|
||||
|
||||
/**
|
||||
* @author Emmanuel Bernard
|
||||
*/
|
||||
public class BasicTypeImpl<X> implements BasicType<X>, Serializable {
|
||||
private final Class<X> clazz;
|
||||
private PersistenceType persistenceType;
|
||||
|
||||
@Override
|
||||
public PersistenceType getPersistenceType() {
|
||||
return persistenceType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<X> getJavaType() {
|
||||
return clazz;
|
||||
}
|
||||
|
||||
public BasicTypeImpl(Class<X> clazz, PersistenceType persistenceType) {
|
||||
this.clazz = clazz;
|
||||
this.persistenceType = persistenceType;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Copyright (c) 2009, Red Hat Middleware LLC 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 Middleware LLC.
|
||||
*
|
||||
* 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.jpa.metamodel.internal;
|
||||
|
||||
import java.io.Serializable;
|
||||
import javax.persistence.metamodel.EmbeddableType;
|
||||
|
||||
import org.hibernate.type.ComponentType;
|
||||
|
||||
/**
|
||||
* @author Emmanuel Bernard
|
||||
*/
|
||||
public class EmbeddableTypeImpl<X>
|
||||
extends AbstractManagedType<X>
|
||||
implements EmbeddableType<X>, Serializable {
|
||||
|
||||
private final AbstractManagedType parent;
|
||||
private final ComponentType hibernateType;
|
||||
|
||||
public EmbeddableTypeImpl(Class<X> javaType, AbstractManagedType parent, ComponentType hibernateType) {
|
||||
super( javaType, null );
|
||||
this.parent = parent;
|
||||
this.hibernateType = hibernateType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PersistenceType getPersistenceType() {
|
||||
return PersistenceType.EMBEDDABLE;
|
||||
}
|
||||
|
||||
public AbstractManagedType getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
public ComponentType getHibernateType() {
|
||||
return hibernateType;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* Copyright (c) 2009, Red Hat Middleware LLC 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 Middleware LLC.
|
||||
*
|
||||
* 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.jpa.metamodel.internal;
|
||||
import java.io.Serializable;
|
||||
import javax.persistence.metamodel.EntityType;
|
||||
|
||||
/**
|
||||
* Defines the Hibernate implementation of the JPA {@link EntityType} contract.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
* @author Emmanuel Bernard
|
||||
*/
|
||||
public class EntityTypeImpl<X>
|
||||
extends AbstractIdentifiableType<X>
|
||||
implements EntityType<X>, Serializable {
|
||||
private final String jpaEntityName;
|
||||
|
||||
public EntityTypeImpl(
|
||||
Class<X> javaType,
|
||||
AbstractIdentifiableType<? super X> superType,
|
||||
String jpaEntityName,
|
||||
boolean hasIdentifierProperty,
|
||||
boolean isVersioned) {
|
||||
super( javaType, superType, hasIdentifierProperty, isVersioned );
|
||||
this.jpaEntityName = jpaEntityName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return jpaEntityName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BindableType getBindableType() {
|
||||
return BindableType.ENTITY_TYPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<X> getBindableJavaType() {
|
||||
return getJavaType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PersistenceType getPersistenceType() {
|
||||
return PersistenceType.ENTITY;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean requiresSupertypeForNonDeclaredIdentifier() {
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2012, 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.jpa.metamodel.internal;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public enum JpaMetaModelPopulationSetting {
|
||||
ENABLED,
|
||||
DISABLED,
|
||||
IGNORE_UNSUPPORTED;
|
||||
|
||||
public static JpaMetaModelPopulationSetting parse(String setting) {
|
||||
if ( "enabled".equalsIgnoreCase( setting ) ) {
|
||||
return ENABLED;
|
||||
}
|
||||
else if ( "disabled".equalsIgnoreCase( setting ) ) {
|
||||
return DISABLED;
|
||||
}
|
||||
else {
|
||||
return IGNORE_UNSUPPORTED;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2012, 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.jpa.metamodel.internal;
|
||||
|
||||
import javax.persistence.metamodel.MappedSuperclassType;
|
||||
|
||||
/**
|
||||
* @author Emmanuel Bernard
|
||||
*/
|
||||
public class MappedSuperclassTypeImpl<X> extends AbstractIdentifiableType<X> implements MappedSuperclassType<X> {
|
||||
public MappedSuperclassTypeImpl(
|
||||
Class<X> javaType,
|
||||
AbstractIdentifiableType<? super X> superType,
|
||||
boolean hasIdentifierProperty,
|
||||
boolean versioned) {
|
||||
super( javaType, superType, hasIdentifierProperty, versioned );
|
||||
}
|
||||
|
||||
public PersistenceType getPersistenceType() {
|
||||
return PersistenceType.MAPPED_SUPERCLASS;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean requiresSupertypeForNonDeclaredIdentifier() {
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2012, 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.jpa.metamodel.internal;
|
||||
|
||||
import javax.persistence.metamodel.EmbeddableType;
|
||||
import javax.persistence.metamodel.EntityType;
|
||||
import javax.persistence.metamodel.ManagedType;
|
||||
import javax.persistence.metamodel.Metamodel;
|
||||
import java.io.Serializable;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||
|
||||
/**
|
||||
* Hibernate implementation of the JPA {@link javax.persistence.metamodel.Metamodel} contract.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
* @author Emmanuel Bernard
|
||||
*/
|
||||
public class MetamodelImpl implements Metamodel, Serializable {
|
||||
private final Map<Class<?>, EntityTypeImpl<?>> entityTypeMap;
|
||||
private final Map<Class<?>, MappedSuperclassTypeImpl<?>> mappedSuperclassTypeMap;
|
||||
private final Map<Class<?>, EmbeddableTypeImpl<?>> embeddableTypeMap;
|
||||
|
||||
/**
|
||||
* Instantiate the metamodel.
|
||||
*
|
||||
* @param entityTypeMap The entity mappings.
|
||||
* @param mappedSuperclassTypeMap The {@link javax.persistence.MappedSuperclass} mappings
|
||||
* @param embeddableTypeMap The embeddable (component) mappings.
|
||||
*/
|
||||
public MetamodelImpl(
|
||||
Map<Class<?>, EntityTypeImpl<?>> entityTypeMap,
|
||||
Map<Class<?>, MappedSuperclassTypeImpl<?>> mappedSuperclassTypeMap,
|
||||
Map<Class<?>, EmbeddableTypeImpl<?>> embeddableTypeMap) {
|
||||
this.entityTypeMap = entityTypeMap;
|
||||
this.mappedSuperclassTypeMap = mappedSuperclassTypeMap;
|
||||
this.embeddableTypeMap = embeddableTypeMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public <X> EntityType<X> entity(Class<X> cls) {
|
||||
final EntityType<?> entityType = entityTypeMap.get( cls );
|
||||
if ( entityType == null ) {
|
||||
throw new IllegalArgumentException( "Not an entity: " + cls );
|
||||
}
|
||||
return (EntityType<X>) entityType;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public <X> ManagedType<X> managedType(Class<X> cls) {
|
||||
ManagedType<?> type = entityTypeMap.get( cls );
|
||||
if ( type == null ) {
|
||||
type = mappedSuperclassTypeMap.get( cls );
|
||||
}
|
||||
if ( type == null ) {
|
||||
type = embeddableTypeMap.get( cls );
|
||||
}
|
||||
if ( type == null ) {
|
||||
throw new IllegalArgumentException( "Not an managed type: " + cls );
|
||||
}
|
||||
return (ManagedType<X>) type;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public <X> EmbeddableType<X> embeddable(Class<X> cls) {
|
||||
final EmbeddableType<?> embeddableType = embeddableTypeMap.get( cls );
|
||||
if ( embeddableType == null ) {
|
||||
throw new IllegalArgumentException( "Not an embeddable: " + cls );
|
||||
}
|
||||
return (EmbeddableType<X>) embeddableType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<ManagedType<?>> getManagedTypes() {
|
||||
final int setSize = CollectionHelper.determineProperSizing(
|
||||
entityTypeMap.size() + mappedSuperclassTypeMap.size() + embeddableTypeMap.size()
|
||||
);
|
||||
final Set<ManagedType<?>> managedTypes = new HashSet<ManagedType<?>>( setSize );
|
||||
managedTypes.addAll( entityTypeMap.values() );
|
||||
managedTypes.addAll( mappedSuperclassTypeMap.values() );
|
||||
managedTypes.addAll( embeddableTypeMap.values() );
|
||||
return managedTypes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<EntityType<?>> getEntities() {
|
||||
return new HashSet<EntityType<?>>( entityTypeMap.values() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<EmbeddableType<?>> getEmbeddables() {
|
||||
return new HashSet<EmbeddableType<?>>( embeddableTypeMap.values() );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,223 @@
|
|||
/*
|
||||
* Copyright (c) 2009, Red Hat Middleware LLC 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 Middleware LLC.
|
||||
*
|
||||
* 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.jpa.metamodel.internal;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Member;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import javax.persistence.metamodel.CollectionAttribute;
|
||||
import javax.persistence.metamodel.ListAttribute;
|
||||
import javax.persistence.metamodel.MapAttribute;
|
||||
import javax.persistence.metamodel.PluralAttribute;
|
||||
import javax.persistence.metamodel.SetAttribute;
|
||||
import javax.persistence.metamodel.Type;
|
||||
|
||||
import org.hibernate.metamodel.spi.binding.PluralAttributeBinding;
|
||||
|
||||
/**
|
||||
* @author Emmanuel Bernard
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public abstract class PluralAttributeImpl<X, C, E>
|
||||
extends AbstractAttribute<X,C>
|
||||
implements PluralAttribute<X, C, E>, Serializable {
|
||||
|
||||
private final Type<E> elementType;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private PluralAttributeImpl(Builder builder) {
|
||||
super(
|
||||
builder.attributeBinding.getAttribute().getName(),
|
||||
builder.collectionClass,
|
||||
builder.owner,
|
||||
builder.member,
|
||||
builder.persistentAttributeType
|
||||
);
|
||||
this.elementType = builder.elementType;
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private final Class collectionClass;
|
||||
private AbstractManagedType owner;
|
||||
private PluralAttributeBinding attributeBinding;
|
||||
private Member member;
|
||||
private Type keyType;
|
||||
private Type elementType;
|
||||
private PersistentAttributeType persistentAttributeType;
|
||||
|
||||
public Builder(Class collectionClass) {
|
||||
this.collectionClass = collectionClass;
|
||||
}
|
||||
|
||||
public Builder owner(AbstractManagedType owner) {
|
||||
this.owner = owner;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder member(Member member) {
|
||||
this.member = member;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder binding(PluralAttributeBinding attributeBinding) {
|
||||
this.attributeBinding = attributeBinding;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder elementType(Type elementType) {
|
||||
this.elementType = elementType;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder keyType(Type keyType) {
|
||||
this.keyType = keyType;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder persistentAttributeType(PersistentAttributeType attrType) {
|
||||
this.persistentAttributeType = attrType;
|
||||
return this;
|
||||
}
|
||||
|
||||
@SuppressWarnings( "unchecked" )
|
||||
public <X,C,E,K> PluralAttributeImpl<X,C,E> build() {
|
||||
//apply strict spec rules first
|
||||
if ( Map.class.equals( collectionClass ) ) {
|
||||
return ( PluralAttributeImpl<X, C, E> ) new MapAttributeImpl<X,K,E>( this );
|
||||
}
|
||||
else if ( Set.class.equals( collectionClass ) ) {
|
||||
return ( PluralAttributeImpl<X, C, E> ) new SetAttributeImpl<X,E>( this );
|
||||
}
|
||||
else if ( List.class.equals( collectionClass ) ) {
|
||||
return ( PluralAttributeImpl<X, C, E> ) new ListAttributeImpl<X,E>( this );
|
||||
}
|
||||
else if ( Collection.class.equals( collectionClass ) ) {
|
||||
return ( PluralAttributeImpl<X, C, E> ) new CollectionAttributeImpl<X, E>( this );
|
||||
}
|
||||
|
||||
//apply loose rules
|
||||
if ( Map.class.isAssignableFrom( collectionClass ) ) {
|
||||
return ( PluralAttributeImpl<X, C, E> ) new MapAttributeImpl<X,K,E>( this );
|
||||
}
|
||||
else if ( Set.class.isAssignableFrom( collectionClass ) ) {
|
||||
return ( PluralAttributeImpl<X, C, E> ) new SetAttributeImpl<X,E>( this );
|
||||
}
|
||||
else if ( List.class.isAssignableFrom( collectionClass ) ) {
|
||||
return ( PluralAttributeImpl<X, C, E> ) new ListAttributeImpl<X,E>( this );
|
||||
}
|
||||
else if ( Collection.class.isAssignableFrom( collectionClass ) ) {
|
||||
return ( PluralAttributeImpl<X, C, E> ) new CollectionAttributeImpl<X, E>( this );
|
||||
}
|
||||
throw new UnsupportedOperationException( "Unknown collection: " + collectionClass );
|
||||
}
|
||||
}
|
||||
|
||||
public static Builder builder(Class collectionClass) {
|
||||
return new Builder( collectionClass );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type<E> getElementType() {
|
||||
return elementType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAssociation() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCollection() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BindableType getBindableType() {
|
||||
return BindableType.PLURAL_ATTRIBUTE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<E> getBindableJavaType() {
|
||||
return elementType.getJavaType();
|
||||
}
|
||||
|
||||
static class SetAttributeImpl<X,E> extends PluralAttributeImpl<X,Set<E>,E> implements SetAttribute<X,E> {
|
||||
SetAttributeImpl(Builder xceBuilder) {
|
||||
super( xceBuilder );
|
||||
}
|
||||
|
||||
@Override
|
||||
public CollectionType getCollectionType() {
|
||||
return CollectionType.SET;
|
||||
}
|
||||
}
|
||||
|
||||
static class CollectionAttributeImpl<X,E> extends PluralAttributeImpl<X,Collection<E>,E> implements CollectionAttribute<X,E> {
|
||||
CollectionAttributeImpl(Builder xceBuilder) {
|
||||
super( xceBuilder );
|
||||
}
|
||||
|
||||
@Override
|
||||
public CollectionType getCollectionType() {
|
||||
return CollectionType.COLLECTION;
|
||||
}
|
||||
}
|
||||
|
||||
static class ListAttributeImpl<X,E> extends PluralAttributeImpl<X,List<E>,E> implements ListAttribute<X,E> {
|
||||
ListAttributeImpl(Builder xceBuilder) {
|
||||
super( xceBuilder );
|
||||
}
|
||||
|
||||
@Override
|
||||
public CollectionType getCollectionType() {
|
||||
return CollectionType.LIST;
|
||||
}
|
||||
}
|
||||
|
||||
static class MapAttributeImpl<X,K,V> extends PluralAttributeImpl<X,Map<K,V>,V> implements MapAttribute<X,K,V> {
|
||||
private final Type<K> keyType;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
MapAttributeImpl(Builder xceBuilder) {
|
||||
super( xceBuilder );
|
||||
this.keyType = xceBuilder.keyType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CollectionType getCollectionType() {
|
||||
return CollectionType.MAP;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<K> getKeyJavaType() {
|
||||
return keyType.getJavaType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type<K> getKeyType() {
|
||||
return keyType;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,128 @@
|
|||
/*
|
||||
* Copyright (c) 2009, Red Hat Middleware LLC 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 Middleware LLC.
|
||||
*
|
||||
* 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.jpa.metamodel.internal;
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Member;
|
||||
import javax.persistence.metamodel.SingularAttribute;
|
||||
import javax.persistence.metamodel.Type;
|
||||
|
||||
/**
|
||||
* @author Emmanuel Bernard
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class SingularAttributeImpl<X, Y>
|
||||
extends AbstractAttribute<X,Y>
|
||||
implements SingularAttribute<X, Y>, Serializable {
|
||||
private final boolean isIdentifier;
|
||||
private final boolean isVersion;
|
||||
private final boolean isOptional;
|
||||
private final Type<Y> attributeType;
|
||||
|
||||
public SingularAttributeImpl(
|
||||
String name,
|
||||
Class<Y> javaType,
|
||||
AbstractManagedType<X> declaringType,
|
||||
Member member,
|
||||
boolean isIdentifier,
|
||||
boolean isVersion,
|
||||
boolean isOptional,
|
||||
Type<Y> attributeType,
|
||||
PersistentAttributeType persistentAttributeType) {
|
||||
super( name, javaType, declaringType, member, persistentAttributeType );
|
||||
this.isIdentifier = isIdentifier;
|
||||
this.isVersion = isVersion;
|
||||
this.isOptional = isOptional;
|
||||
this.attributeType = attributeType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclass used to simply instantiation of singular attributes representing an entity's
|
||||
* identifier.
|
||||
*/
|
||||
public static class Identifier<X,Y> extends SingularAttributeImpl<X,Y> {
|
||||
public Identifier(
|
||||
String name,
|
||||
Class<Y> javaType,
|
||||
AbstractManagedType<X> declaringType,
|
||||
Member member,
|
||||
Type<Y> attributeType,
|
||||
PersistentAttributeType persistentAttributeType) {
|
||||
super( name, javaType, declaringType, member, true, false, false, attributeType, persistentAttributeType );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclass used to simply instantiation of singular attributes representing an entity's
|
||||
* version.
|
||||
*/
|
||||
public static class Version<X,Y> extends SingularAttributeImpl<X,Y> {
|
||||
public Version(
|
||||
String name,
|
||||
Class<Y> javaType,
|
||||
AbstractManagedType<X> declaringType,
|
||||
Member member,
|
||||
Type<Y> attributeType,
|
||||
PersistentAttributeType persistentAttributeType) {
|
||||
super( name, javaType, declaringType, member, false, true, false, attributeType, persistentAttributeType );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isId() {
|
||||
return isIdentifier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVersion() {
|
||||
return isVersion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOptional() {
|
||||
return isOptional;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type<Y> getType() {
|
||||
return attributeType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAssociation() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCollection() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BindableType getBindableType() {
|
||||
return BindableType.SINGULAR_ATTRIBUTE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<Y> getBindableJavaType() {
|
||||
return attributeType.getJavaType();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2012, 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.jpa.metamodel.internal;
|
||||
|
||||
/**
|
||||
* Represents Hibernate mapping features that are not supported in JPA metamodel. Used to allow control over how
|
||||
* such features are handled in regards to building the JPA {@link javax.persistence.metamodel.Metamodel} instance.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public enum UnsupportedFeature {
|
||||
ANY( "ANY mappings not supported in JPA metamodel" );
|
||||
|
||||
private final String message;
|
||||
|
||||
UnsupportedFeature(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,536 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
|
||||
* third-party contributors as indicated by either @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.jpa.metamodel.internal.builder;
|
||||
|
||||
import javax.persistence.OneToOne;
|
||||
import javax.persistence.metamodel.Attribute;
|
||||
import javax.persistence.metamodel.IdentifiableType;
|
||||
import javax.persistence.metamodel.PluralAttribute;
|
||||
import javax.persistence.metamodel.Type;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Member;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.annotations.common.AssertionFailure;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.jpa.metamodel.internal.AbstractIdentifiableType;
|
||||
import org.hibernate.jpa.metamodel.internal.AbstractManagedType;
|
||||
import org.hibernate.jpa.metamodel.internal.BasicTypeImpl;
|
||||
import org.hibernate.jpa.metamodel.internal.EmbeddableTypeImpl;
|
||||
import org.hibernate.jpa.metamodel.internal.MappedSuperclassTypeImpl;
|
||||
import org.hibernate.jpa.metamodel.internal.PluralAttributeImpl;
|
||||
import org.hibernate.jpa.metamodel.internal.SingularAttributeImpl;
|
||||
import org.hibernate.jpa.metamodel.internal.UnsupportedFeature;
|
||||
import org.hibernate.metamodel.spi.binding.AttributeBinding;
|
||||
import org.hibernate.metamodel.spi.binding.CompositeAttributeBinding;
|
||||
import org.hibernate.metamodel.spi.binding.IndexedPluralAttributeBinding;
|
||||
import org.hibernate.metamodel.spi.binding.PluralAttributeBinding;
|
||||
import org.hibernate.metamodel.spi.binding.PluralAttributeElementBinding;
|
||||
import org.hibernate.metamodel.spi.binding.PluralAttributeElementNature;
|
||||
import org.hibernate.metamodel.spi.binding.PluralAttributeIndexNature;
|
||||
import org.hibernate.metamodel.spi.binding.SingularAttributeBinding;
|
||||
import org.hibernate.metamodel.spi.domain.PluralAttributeNature;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.tuple.entity.EntityMetamodel;
|
||||
import org.hibernate.type.ComponentType;
|
||||
import org.hibernate.type.EmbeddedComponentType;
|
||||
import org.hibernate.type.EntityType;
|
||||
|
||||
import static javax.persistence.metamodel.Attribute.PersistentAttributeType;
|
||||
|
||||
/**
|
||||
* A factory for building {@link Attribute} instances. Exposes 3 main services:<ol>
|
||||
* <li>{@link #buildAttribute} for building normal attributes</li>
|
||||
* <li>{@link #buildIdAttribute} for building identifier attributes</li>
|
||||
* <li>{@link #buildVersionAttribute} for building version attributes}</li>
|
||||
* <ol>
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
* @author Emmanuel Bernard
|
||||
*/
|
||||
public class AttributeBuilder {
|
||||
private static final Logger LOG = Logger.getLogger( AttributeBuilder.class.getName() );
|
||||
|
||||
/**
|
||||
* The context for attribute building
|
||||
*/
|
||||
public static interface Context {
|
||||
public Type locateEntityTypeByName(String entityName);
|
||||
|
||||
public void registerEmbeddedableType(EmbeddableTypeImpl embeddableType);
|
||||
|
||||
public SessionFactoryImplementor getSessionFactory();
|
||||
|
||||
public EntityPersister getSubClassEntityPersister(MappedSuperclassTypeImpl mappedSuperclass);
|
||||
|
||||
public void handleUnsupportedFeature(UnsupportedFeature feature);
|
||||
}
|
||||
|
||||
private final Context context;
|
||||
|
||||
public AttributeBuilder(Context context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a normal attribute.
|
||||
*
|
||||
* @param ownerType The descriptor of the attribute owner (aka declarer).
|
||||
* @param attributeBinding The Hibernate attribute binding descriptor
|
||||
* @return The built attribute descriptor or null if the attribute is not part of the JPA 2 model (eg backrefs)
|
||||
*/
|
||||
public Attribute buildAttribute(AbstractManagedType ownerType, AttributeBinding attributeBinding) {
|
||||
if ( attributeBinding.getAttribute().isSynthetic() ) {
|
||||
// hide synthetic/virtual properties (fabricated by Hibernate) from the JPA metamodel.
|
||||
LOG.tracef(
|
||||
"Skipping synthetic property %s(%s)",
|
||||
ownerType.getJavaType().getName(),
|
||||
attributeBinding.getAttribute().getName()
|
||||
);
|
||||
return null;
|
||||
}
|
||||
LOG.trace("Building attribute [" + ownerType.getJavaType().getName() + "." + attributeBinding.getAttribute().getName() + "]");
|
||||
final AttributeMetadata attributeMetadata = determineAttributeMetadata(
|
||||
ownerType,
|
||||
attributeBinding,
|
||||
NORMAL_MEMBER_RESOLVER
|
||||
);
|
||||
if ( attributeMetadata == null ) {
|
||||
return null;
|
||||
}
|
||||
if ( attributeMetadata.isPlural() ) {
|
||||
return buildPluralAttribute( (PluralAttributeMetadata) attributeMetadata );
|
||||
}
|
||||
final SingularAttributeMetadata singularAttributeMetadata = (SingularAttributeMetadata)attributeMetadata;
|
||||
final Type metaModelType = getMetaModelType( singularAttributeMetadata.getAttributeTypeDescriptor() );
|
||||
//noinspection unchecked
|
||||
return new SingularAttributeImpl(
|
||||
attributeMetadata.getName(),
|
||||
attributeMetadata.getJavaType(),
|
||||
ownerType,
|
||||
attributeMetadata.getMember(),
|
||||
false,
|
||||
false,
|
||||
true, // todo : need to handle this somehow : property.isOptional(),
|
||||
metaModelType,
|
||||
attributeMetadata.getPersistentAttributeType()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the identifier attribute descriptor
|
||||
*
|
||||
* @param ownerType The descriptor of the attribute owner (aka declarer).
|
||||
* @param attributeBinding The Hibernate attribute binding descriptor
|
||||
*
|
||||
* @return The built attribute descriptor
|
||||
*/
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public SingularAttributeImpl buildIdAttribute(AbstractIdentifiableType ownerType, AttributeBinding attributeBinding) {
|
||||
LOG.trace(
|
||||
"Building identifier attribute [" + ownerType.getJavaType().getName() + "#"
|
||||
+ attributeBinding.getAttribute().getName() + "]"
|
||||
);
|
||||
final SingularAttributeMetadata attributeMetadata = (SingularAttributeMetadata) determineAttributeMetadata(
|
||||
ownerType,
|
||||
attributeBinding,
|
||||
IDENTIFIER_MEMBER_RESOLVER
|
||||
);
|
||||
final Type metaModelType = getMetaModelType( attributeMetadata.getAttributeTypeDescriptor() );
|
||||
return new SingularAttributeImpl.Identifier(
|
||||
attributeBinding.getAttribute().getName(),
|
||||
attributeMetadata.getJavaType(),
|
||||
ownerType,
|
||||
attributeMetadata.getMember(),
|
||||
metaModelType,
|
||||
attributeMetadata.getPersistentAttributeType()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the version attribute descriptor
|
||||
*
|
||||
* @param ownerType The descriptor of the attribute owner (aka declarer).
|
||||
* @param attributeBinding The Hibernate attribute binding descriptor
|
||||
*
|
||||
* @return The built attribute descriptor
|
||||
*/
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public <X, Y> SingularAttributeImpl<X, Y> buildVersionAttribute(AbstractIdentifiableType<X> ownerType, AttributeBinding attributeBinding) {
|
||||
LOG.trace("Building version attribute [ownerType.getJavaType().getName()" + "." + "property.getName()]");
|
||||
final SingularAttributeMetadata<X,Y> attributeMetadata = (SingularAttributeMetadata<X, Y>) determineAttributeMetadata(
|
||||
ownerType,
|
||||
attributeBinding,
|
||||
VERSION_MEMBER_RESOLVER
|
||||
);
|
||||
final Type<Y> metaModelType = getMetaModelType( attributeMetadata.getAttributeTypeDescriptor() );
|
||||
return new SingularAttributeImpl.Version(
|
||||
attributeBinding.getAttribute().getName(),
|
||||
attributeMetadata.getJavaType(),
|
||||
ownerType,
|
||||
attributeMetadata.getMember(),
|
||||
metaModelType,
|
||||
attributeMetadata.getPersistentAttributeType()
|
||||
);
|
||||
}
|
||||
|
||||
@SuppressWarnings( "unchecked" )
|
||||
private PluralAttribute buildPluralAttribute(PluralAttributeMetadata attributeMetadata) {
|
||||
final Type elementType = getMetaModelType( attributeMetadata.getElementAttributeTypeDescriptor() );
|
||||
if ( java.util.Map.class.isAssignableFrom( attributeMetadata.getJavaType() ) ) {
|
||||
final Type keyType = getMetaModelType( attributeMetadata.getMapKeyAttributeTypeDescriptor() );
|
||||
return PluralAttributeImpl.builder( attributeMetadata.getJavaType() )
|
||||
.owner( attributeMetadata.getOwnerType() )
|
||||
.elementType( elementType )
|
||||
.keyType( keyType )
|
||||
.member( attributeMetadata.getMember() )
|
||||
.binding( (PluralAttributeBinding) attributeMetadata.getAttributeBinding() )
|
||||
.persistentAttributeType( attributeMetadata.getPersistentAttributeType() )
|
||||
.build();
|
||||
}
|
||||
return PluralAttributeImpl.builder( attributeMetadata.getJavaType() )
|
||||
.owner( attributeMetadata.getOwnerType() )
|
||||
.elementType( elementType )
|
||||
.member( attributeMetadata.getMember() )
|
||||
.binding( (PluralAttributeBinding) attributeMetadata.getAttributeBinding() )
|
||||
.persistentAttributeType( attributeMetadata.getPersistentAttributeType() )
|
||||
.build();
|
||||
}
|
||||
|
||||
@SuppressWarnings( "unchecked" )
|
||||
private <Y> Type<Y> getMetaModelType(AttributeTypeDescriptor attributeTypeDescriptor) {
|
||||
switch ( attributeTypeDescriptor.getValueClassification() ) {
|
||||
case BASIC: {
|
||||
return new BasicTypeImpl<Y>(
|
||||
attributeTypeDescriptor.getBindableType(),
|
||||
Type.PersistenceType.BASIC
|
||||
);
|
||||
}
|
||||
case ENTITY: {
|
||||
final org.hibernate.type.EntityType type = (EntityType) attributeTypeDescriptor.getHibernateType();
|
||||
return (Type<Y>) context.locateEntityTypeByName( type.getAssociatedEntityName() );
|
||||
}
|
||||
case EMBEDDABLE: {
|
||||
final EmbeddableTypeImpl<Y> embeddableType = new EmbeddableTypeImpl<Y>(
|
||||
attributeTypeDescriptor.getBindableType(),
|
||||
attributeTypeDescriptor.getAttributeMetadata().getOwnerType(),
|
||||
(ComponentType) attributeTypeDescriptor.getHibernateType()
|
||||
);
|
||||
context.registerEmbeddedableType( embeddableType );
|
||||
|
||||
CompositeAttributeBinding compositeAttributeBinding =
|
||||
(CompositeAttributeBinding) attributeTypeDescriptor.getHibernateMetamodelType();
|
||||
for ( AttributeBinding subAttributeBinding : compositeAttributeBinding.attributeBindings() ) {
|
||||
final Attribute<Y, Object> attribute = buildAttribute( embeddableType, subAttributeBinding );
|
||||
if ( attribute != null ) {
|
||||
embeddableType.getBuilder().addAttribute( attribute );
|
||||
}
|
||||
}
|
||||
embeddableType.lock();
|
||||
return embeddableType;
|
||||
}
|
||||
default: {
|
||||
throw new AssertionFailure( "Unknown type : " + attributeTypeDescriptor.getValueClassification() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private EntityMetamodel getDeclarerEntityMetamodel(IdentifiableType<?> ownerType) {
|
||||
final Type.PersistenceType persistenceType = ownerType.getPersistenceType();
|
||||
if ( persistenceType == Type.PersistenceType.ENTITY) {
|
||||
return context.getSessionFactory()
|
||||
.getEntityPersister( ownerType.getJavaType().getName() )
|
||||
.getEntityMetamodel();
|
||||
}
|
||||
else if ( persistenceType == Type.PersistenceType.MAPPED_SUPERCLASS) {
|
||||
return context.getSubClassEntityPersister( (MappedSuperclassTypeImpl) ownerType ).getEntityMetamodel();
|
||||
}
|
||||
else {
|
||||
throw new AssertionFailure( "Cannot get the metamodel for PersistenceType: " + persistenceType );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Here is most of the nuts and bolts of this factory, where we interpret the known JPA metadata
|
||||
* against the known Hibernate metadata and build a descriptor for the attribute.
|
||||
*
|
||||
* @param jpaOwner The JPA representation of the attribute owner
|
||||
* @param attributeBinding Hibernate metamodel representation of the attribute binding
|
||||
* @param memberResolver Strategy for how to resolve the member defining the attribute.
|
||||
*
|
||||
* @return The attribute description
|
||||
*/
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
private AttributeMetadata determineAttributeMetadata(
|
||||
AbstractManagedType jpaOwner,
|
||||
AttributeBinding attributeBinding,
|
||||
MemberResolver memberResolver) {
|
||||
LOG.trace("Starting attribute metadata determination [" + attributeBinding.getAttribute().getName() + "]");
|
||||
final Member member = memberResolver.resolveMember( jpaOwner, attributeBinding );
|
||||
LOG.trace(" Determined member [" + member + "]");
|
||||
|
||||
final org.hibernate.type.Type type = attributeBinding.getHibernateTypeDescriptor().getResolvedTypeMapping();
|
||||
LOG.trace(" Determined type [name=" + type.getName() + ", class=" + type.getClass().getName() + "]");
|
||||
|
||||
if ( type.isAnyType() ) {
|
||||
// ANY mappings are currently not supported in the JPA metamodel; see HHH-6589
|
||||
context.handleUnsupportedFeature( UnsupportedFeature.ANY );
|
||||
return null;
|
||||
}
|
||||
|
||||
if ( SingularAttributeBinding.class.isInstance( attributeBinding ) ) {
|
||||
final SingularAttributeBinding singularAttributeBinding = (SingularAttributeBinding) attributeBinding;
|
||||
|
||||
final PersistentAttributeType jpaAttributeType;
|
||||
if ( singularAttributeBinding.getAttribute().getSingularAttributeType().isComponent() ) {
|
||||
jpaAttributeType = PersistentAttributeType.EMBEDDED;
|
||||
}
|
||||
else if ( singularAttributeBinding.getAttribute().getSingularAttributeType().isAssociation() ) {
|
||||
jpaAttributeType = determineSingularAssociationAttributeType( member );
|
||||
}
|
||||
else {
|
||||
jpaAttributeType = PersistentAttributeType.BASIC;
|
||||
}
|
||||
return new SingularAttributeMetadataImpl( attributeBinding, jpaOwner, member, jpaAttributeType );
|
||||
}
|
||||
else {
|
||||
final PluralAttributeBinding pluralAttributeBinding = (PluralAttributeBinding) attributeBinding;
|
||||
|
||||
// First, determine the type of the elements and use that to help determine the
|
||||
// collection type)
|
||||
final PluralAttributeElementBinding elementBinding = pluralAttributeBinding.getPluralAttributeElementBinding();
|
||||
final PluralAttributeElementNature elementNature = elementBinding.getPluralAttributeElementNature();
|
||||
final PersistentAttributeType persistentAttributeType;
|
||||
final PersistentAttributeType elementPersistentAttributeType;
|
||||
PersistentAttributeType keyPersistentAttributeType = null;
|
||||
|
||||
if ( elementNature == PluralAttributeElementNature.MANY_TO_ANY ) {
|
||||
// ANY mappings are currently not supported in the JPA metamodel; see HHH-6589
|
||||
context.handleUnsupportedFeature( UnsupportedFeature.ANY );
|
||||
return null;
|
||||
}
|
||||
else if ( elementNature == PluralAttributeElementNature.BASIC ) {
|
||||
elementPersistentAttributeType = PersistentAttributeType.BASIC;
|
||||
persistentAttributeType = PersistentAttributeType.ELEMENT_COLLECTION;
|
||||
}
|
||||
else if ( elementNature == PluralAttributeElementNature.COMPOSITE ) {
|
||||
elementPersistentAttributeType = PersistentAttributeType.EMBEDDED;
|
||||
persistentAttributeType = PersistentAttributeType.ELEMENT_COLLECTION;
|
||||
}
|
||||
else {
|
||||
elementPersistentAttributeType = elementNature == PluralAttributeElementNature.MANY_TO_MANY
|
||||
? PersistentAttributeType.MANY_TO_MANY
|
||||
: PersistentAttributeType.ONE_TO_MANY;
|
||||
persistentAttributeType = elementPersistentAttributeType;
|
||||
}
|
||||
|
||||
// For maps, also check the key binding
|
||||
if ( pluralAttributeBinding.getAttribute().getNature() == PluralAttributeNature.MAP ) {
|
||||
final IndexedPluralAttributeBinding indexedPluralAttributeBinding
|
||||
= (IndexedPluralAttributeBinding) pluralAttributeBinding;
|
||||
final PluralAttributeIndexNature indexNature
|
||||
= indexedPluralAttributeBinding.getPluralAttributeIndexBinding().getPluralAttributeIndexNature();
|
||||
|
||||
if ( indexNature == PluralAttributeIndexNature.MANY_TO_ANY ) {
|
||||
context.handleUnsupportedFeature( UnsupportedFeature.ANY );
|
||||
return null;
|
||||
}
|
||||
else if ( indexNature == PluralAttributeIndexNature.MANY_TO_MANY ) {
|
||||
keyPersistentAttributeType = Attribute.PersistentAttributeType.MANY_TO_ONE;
|
||||
}
|
||||
else if ( indexNature == PluralAttributeIndexNature.COMPOSITE ) {
|
||||
keyPersistentAttributeType = Attribute.PersistentAttributeType.EMBEDDED;
|
||||
}
|
||||
else {
|
||||
keyPersistentAttributeType = Attribute.PersistentAttributeType.BASIC;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// for the sake of symmetry...
|
||||
if ( pluralAttributeBinding.getPluralAttributeKeyBinding() != null ) {
|
||||
throw new HibernateException(
|
||||
String.format(
|
||||
"Encountered non-Map attribute binding with associated map-key binding : %s#%s",
|
||||
jpaOwner.getJavaType().getName(),
|
||||
pluralAttributeBinding.getAttribute().getName()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return new PluralAttributeMetadataImpl(
|
||||
pluralAttributeBinding,
|
||||
jpaOwner,
|
||||
member,
|
||||
persistentAttributeType,
|
||||
elementPersistentAttributeType,
|
||||
keyPersistentAttributeType
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public static PersistentAttributeType determineSingularAssociationAttributeType(Member member) {
|
||||
if ( Field.class.isInstance( member ) ) {
|
||||
return ( (Field) member ).getAnnotation( OneToOne.class ) != null
|
||||
? PersistentAttributeType.ONE_TO_ONE
|
||||
: PersistentAttributeType.MANY_TO_ONE;
|
||||
}
|
||||
else {
|
||||
return ( (Method) member ).getAnnotation( OneToOne.class ) != null
|
||||
? PersistentAttributeType.ONE_TO_ONE
|
||||
: PersistentAttributeType.MANY_TO_ONE;
|
||||
}
|
||||
}
|
||||
|
||||
public static ParameterizedType getSignatureType(Member member) {
|
||||
final java.lang.reflect.Type type = Field.class.isInstance( member )
|
||||
? ( ( Field ) member ).getGenericType()
|
||||
: ( ( Method ) member ).getGenericReturnType();
|
||||
//this is a raw type
|
||||
if ( type instanceof Class ) return null;
|
||||
return (ParameterizedType) type;
|
||||
}
|
||||
|
||||
public static PluralAttribute.CollectionType determineCollectionType(Class javaType) {
|
||||
if ( java.util.List.class.isAssignableFrom( javaType ) ) {
|
||||
return PluralAttribute.CollectionType.LIST;
|
||||
}
|
||||
else if ( java.util.Set.class.isAssignableFrom( javaType ) ) {
|
||||
return PluralAttribute.CollectionType.SET;
|
||||
}
|
||||
else if ( java.util.Map.class.isAssignableFrom( javaType ) ) {
|
||||
return PluralAttribute.CollectionType.MAP;
|
||||
}
|
||||
else if ( java.util.Collection.class.isAssignableFrom( javaType ) ) {
|
||||
return PluralAttribute.CollectionType.COLLECTION;
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException( "Expecting collection type [" + javaType.getName() + "]" );
|
||||
}
|
||||
}
|
||||
|
||||
// public static boolean isManyToMany(Member member) {
|
||||
// return Field.class.isInstance( member )
|
||||
// ? ( (Field) member ).getAnnotation( ManyToMany.class ) != null
|
||||
// : ( (Method) member ).getAnnotation( ManyToMany.class ) != null;
|
||||
// }
|
||||
|
||||
private final MemberResolver EMBEDDED_MEMBER_RESOLVER = new MemberResolver() {
|
||||
@Override
|
||||
public Member resolveMember(AbstractManagedType owner, AttributeBinding attributeBinding) {
|
||||
final EmbeddableTypeImpl embeddableType = ( EmbeddableTypeImpl<?> ) owner;
|
||||
final String attributeName = attributeBinding.getAttribute().getName();
|
||||
return embeddableType.getHibernateType()
|
||||
.getComponentTuplizer()
|
||||
.getGetter( embeddableType.getHibernateType().getPropertyIndex( attributeName ) )
|
||||
.getMember();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
private final MemberResolver VIRTUAL_IDENTIFIER_MEMBER_RESOLVER = new MemberResolver() {
|
||||
@Override
|
||||
public Member resolveMember(AbstractManagedType owner, AttributeBinding attributeBinding) {
|
||||
final IdentifiableType identifiableType = (IdentifiableType) owner;
|
||||
final EntityMetamodel entityMetamodel = getDeclarerEntityMetamodel( identifiableType );
|
||||
if ( ! entityMetamodel.getIdentifierProperty().isVirtual() ) {
|
||||
throw new IllegalArgumentException( "expecting IdClass mapping" );
|
||||
}
|
||||
org.hibernate.type.Type type = entityMetamodel.getIdentifierProperty().getType();
|
||||
if ( ! EmbeddedComponentType.class.isInstance( type ) ) {
|
||||
throw new IllegalArgumentException( "expecting IdClass mapping" );
|
||||
}
|
||||
|
||||
final EmbeddedComponentType componentType = (EmbeddedComponentType) type;
|
||||
final String attributeName = attributeBinding.getAttribute().getName();
|
||||
return componentType.getComponentTuplizer()
|
||||
.getGetter( componentType.getPropertyIndex( attributeName ) )
|
||||
.getMember();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* A {@link Member} resolver for normal attributes.
|
||||
*/
|
||||
private final MemberResolver NORMAL_MEMBER_RESOLVER = new MemberResolver() {
|
||||
@Override
|
||||
public Member resolveMember(AbstractManagedType owner, AttributeBinding attributeBinding) {
|
||||
final Type.PersistenceType persistenceType = owner.getPersistenceType();
|
||||
if ( Type.PersistenceType.EMBEDDABLE == persistenceType ) {
|
||||
return EMBEDDED_MEMBER_RESOLVER.resolveMember( owner, attributeBinding );
|
||||
}
|
||||
else if ( Type.PersistenceType.ENTITY == persistenceType
|
||||
|| Type.PersistenceType.MAPPED_SUPERCLASS == persistenceType ) {
|
||||
final IdentifiableType identifiableType = (IdentifiableType) owner;
|
||||
final EntityMetamodel entityMetamodel = getDeclarerEntityMetamodel( identifiableType );
|
||||
final String propertyName = attributeBinding.getAttribute().getName();
|
||||
final Integer index = entityMetamodel.getPropertyIndexOrNull( propertyName );
|
||||
if ( index == null ) {
|
||||
// just like in #determineIdentifierJavaMember , this *should* indicate we have an IdClass mapping
|
||||
return VIRTUAL_IDENTIFIER_MEMBER_RESOLVER.resolveMember( owner, attributeBinding );
|
||||
}
|
||||
else {
|
||||
return entityMetamodel.getTuplizer()
|
||||
.getGetter( index )
|
||||
.getMember();
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException( "Unexpected owner type : " + persistenceType );
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private final MemberResolver IDENTIFIER_MEMBER_RESOLVER = new MemberResolver() {
|
||||
@Override
|
||||
public Member resolveMember(AbstractManagedType owner, AttributeBinding attributeBinding) {
|
||||
final IdentifiableType identifiableType = (IdentifiableType) owner;
|
||||
final EntityMetamodel entityMetamodel = getDeclarerEntityMetamodel( identifiableType );
|
||||
final String attributeName = attributeBinding.getAttribute().getName();
|
||||
if ( ! attributeName.equals( entityMetamodel.getIdentifierProperty().getName() ) ) {
|
||||
// this *should* indicate processing part of an IdClass...
|
||||
return VIRTUAL_IDENTIFIER_MEMBER_RESOLVER.resolveMember( owner, attributeBinding );
|
||||
}
|
||||
return entityMetamodel.getTuplizer().getIdentifierGetter().getMember();
|
||||
}
|
||||
};
|
||||
|
||||
private final MemberResolver VERSION_MEMBER_RESOLVER = new MemberResolver() {
|
||||
@Override
|
||||
public Member resolveMember(AbstractManagedType owner, AttributeBinding attributeBinding) {
|
||||
final IdentifiableType identifiableType = (IdentifiableType) owner;
|
||||
final EntityMetamodel entityMetamodel = getDeclarerEntityMetamodel( identifiableType );
|
||||
final String versionPropertyName = attributeBinding.getAttribute().getName();
|
||||
if ( ! versionPropertyName.equals( entityMetamodel.getVersionProperty().getName() ) ) {
|
||||
// this should never happen, but to be safe...
|
||||
throw new IllegalArgumentException( "Given property did not match declared version property" );
|
||||
}
|
||||
return entityMetamodel.getTuplizer().getVersionGetter().getMember();
|
||||
}
|
||||
};
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2012, 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.jpa.metamodel.internal.builder;
|
||||
|
||||
import javax.persistence.metamodel.Attribute;
|
||||
import java.lang.reflect.Member;
|
||||
|
||||
import org.hibernate.jpa.metamodel.internal.AbstractManagedType;
|
||||
import org.hibernate.metamodel.spi.binding.AttributeBinding;
|
||||
|
||||
/**
|
||||
* Basic contract for describing an attribute in a format needed while building the JPA metamodel.
|
||||
*
|
||||
* The "description" is described:<ol>
|
||||
* <li>partially in terms of JPA ({@link #getPersistentAttributeType} and {@link #getOwnerType})</li>
|
||||
* <li>partially in terms of Hibernate metamodel ({@link #getAttributeBinding})</li>
|
||||
* <li>and partially just in terms of the java model itself ({@link #getMember} and {@link #getJavaType})</li>
|
||||
* </ol>
|
||||
*
|
||||
* @param <X> The attribute owner type
|
||||
* @param <Y> The attribute type.
|
||||
*/
|
||||
public interface AttributeMetadata<X,Y> {
|
||||
/**
|
||||
* Retrieve the name of the attribute
|
||||
*
|
||||
* @return The attribute name
|
||||
*/
|
||||
public String getName();
|
||||
|
||||
/**
|
||||
* Retrieve the member defining the attribute
|
||||
*
|
||||
* @return The attribute member
|
||||
*/
|
||||
public Member getMember();
|
||||
|
||||
/**
|
||||
* Retrieve the attribute java type.
|
||||
*
|
||||
* @return The java type of the attribute.
|
||||
*/
|
||||
public Class<Y> getJavaType();
|
||||
|
||||
/**
|
||||
* Get the JPA attribute type classification for this attribute.
|
||||
*
|
||||
* @return The JPA attribute type classification
|
||||
*/
|
||||
public Attribute.PersistentAttributeType getPersistentAttributeType();
|
||||
|
||||
/**
|
||||
* Retrieve the attribute owner's metamodel information
|
||||
*
|
||||
* @return The metamodel information for the attribute owner
|
||||
*/
|
||||
public AbstractManagedType<X> getOwnerType();
|
||||
|
||||
/**
|
||||
* Retrieve the Hibernate property mapping related to this attribute.
|
||||
*
|
||||
* @return The Hibernate property mapping
|
||||
*/
|
||||
public AttributeBinding getAttributeBinding();
|
||||
|
||||
/**
|
||||
* Is the attribute plural (a collection)?
|
||||
*
|
||||
* @return True if it is plural, false otherwise.
|
||||
*/
|
||||
public boolean isPlural();
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2012, 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.jpa.metamodel.internal.builder;
|
||||
|
||||
/**
|
||||
* Centralized access to a variety of information about a the type of an attribute being built for the JPA metamodel.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
* @author Emmanuel Bernard
|
||||
*/
|
||||
public interface AttributeTypeDescriptor {
|
||||
/**
|
||||
* Enum of the simplified types a value might be. These relate more to the Hibernate classification
|
||||
* then the JPA classification
|
||||
*/
|
||||
enum ValueClassification {
|
||||
EMBEDDABLE,
|
||||
ENTITY,
|
||||
BASIC
|
||||
}
|
||||
|
||||
public org.hibernate.metamodel.spi.domain.Type getHibernateMetamodelType();
|
||||
|
||||
public org.hibernate.type.Type getHibernateType();
|
||||
|
||||
public Class getBindableType();
|
||||
|
||||
/**
|
||||
* Retrieve the simplified value classification
|
||||
*
|
||||
* @return The value type
|
||||
*/
|
||||
public ValueClassification getValueClassification();
|
||||
|
||||
/**
|
||||
* Retrieve the metadata about the attribute from which this value comes
|
||||
*
|
||||
* @return The "containing" attribute metadata.
|
||||
*/
|
||||
public AttributeMetadata getAttributeMetadata();
|
||||
}
|
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2012, 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.jpa.metamodel.internal.builder;
|
||||
|
||||
import javax.persistence.metamodel.Attribute;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Member;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.hibernate.jpa.metamodel.internal.AbstractManagedType;
|
||||
import org.hibernate.metamodel.spi.binding.AttributeBinding;
|
||||
|
||||
/**
|
||||
* Base implementation of AttributeMetadata
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public abstract class BaseAttributeMetadata<X,Y> implements AttributeMetadata<X,Y> {
|
||||
private final AttributeBinding attributeBinding;
|
||||
private final AbstractManagedType<X> ownerType;
|
||||
private final Member member;
|
||||
private final Class<Y> javaType;
|
||||
private final Attribute.PersistentAttributeType persistentAttributeType;
|
||||
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public BaseAttributeMetadata(
|
||||
AttributeBinding attributeBinding,
|
||||
AbstractManagedType<X> ownerType,
|
||||
Member member,
|
||||
Attribute.PersistentAttributeType persistentAttributeType) {
|
||||
this.attributeBinding = attributeBinding;
|
||||
this.ownerType = ownerType;
|
||||
this.member = member;
|
||||
this.persistentAttributeType = persistentAttributeType;
|
||||
final Class declaredType;
|
||||
// we can support method or field members here. Is there really any other valid type?
|
||||
if ( Field.class.isInstance( member ) ) {
|
||||
declaredType = ( (Field) member ).getType();
|
||||
}
|
||||
else if ( Method.class.isInstance( member ) ) {
|
||||
declaredType = ( (Method) member ).getReturnType();
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException( "Cannot determine java-type from given member [" + member + "]" );
|
||||
}
|
||||
this.javaType = declaredType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return attributeBinding.getAttribute().getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Member getMember() {
|
||||
return member;
|
||||
}
|
||||
|
||||
public String getMemberDescription() {
|
||||
return determineMemberDescription( getMember() );
|
||||
}
|
||||
|
||||
public String determineMemberDescription(Member member) {
|
||||
return member.getDeclaringClass().getName() + '#' + member.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<Y> getJavaType() {
|
||||
return javaType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Attribute.PersistentAttributeType getPersistentAttributeType() {
|
||||
return persistentAttributeType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractManagedType<X> getOwnerType() {
|
||||
return ownerType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPlural() {
|
||||
return ! attributeBinding.getAttribute().isSingular();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AttributeBinding getAttributeBinding() {
|
||||
return attributeBinding;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2012, 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.jpa.metamodel.internal.builder;
|
||||
|
||||
import java.lang.reflect.Member;
|
||||
|
||||
import org.hibernate.jpa.metamodel.internal.AbstractManagedType;
|
||||
import org.hibernate.metamodel.spi.binding.AttributeBinding;
|
||||
|
||||
/**
|
||||
* Contract for how we resolve the {@link java.lang.reflect.Member} for a given attribute context.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
* @author Emmanuel Bernard
|
||||
*/
|
||||
public interface MemberResolver {
|
||||
/**
|
||||
* Resolve the member.
|
||||
*
|
||||
* @param owner The JPA Metamodel representation of the class tha owns the member to be resolved
|
||||
* @param attributeBinding Hibernate metamodel representation of the attribute for which to resolve the member.
|
||||
*
|
||||
* @return The resolved member.
|
||||
*/
|
||||
public Member resolveMember(AbstractManagedType owner, AttributeBinding attributeBinding);
|
||||
}
|
|
@ -0,0 +1,392 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2012, 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.jpa.metamodel.internal.builder;
|
||||
|
||||
import javax.persistence.metamodel.Attribute;
|
||||
import javax.persistence.metamodel.SingularAttribute;
|
||||
import javax.persistence.metamodel.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.cfg.NotYetImplementedException;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.jpa.metamodel.internal.AbstractIdentifiableType;
|
||||
import org.hibernate.jpa.metamodel.internal.EmbeddableTypeImpl;
|
||||
import org.hibernate.jpa.metamodel.internal.EntityTypeImpl;
|
||||
import org.hibernate.jpa.metamodel.internal.MappedSuperclassTypeImpl;
|
||||
import org.hibernate.jpa.metamodel.internal.MetamodelImpl;
|
||||
import org.hibernate.jpa.metamodel.internal.UnsupportedFeature;
|
||||
import org.hibernate.mapping.Component;
|
||||
import org.hibernate.mapping.KeyValue;
|
||||
import org.hibernate.mapping.Property;
|
||||
import org.hibernate.metamodel.spi.binding.AttributeBinding;
|
||||
import org.hibernate.metamodel.spi.binding.BasicAttributeBinding;
|
||||
import org.hibernate.metamodel.spi.binding.CompositeAttributeBinding;
|
||||
import org.hibernate.metamodel.spi.binding.EntityBinding;
|
||||
import org.hibernate.metamodel.spi.binding.HierarchyDetails;
|
||||
import org.hibernate.metamodel.spi.binding.SingularNonAssociationAttributeBinding;
|
||||
import org.hibernate.metamodel.spi.domain.Entity;
|
||||
import org.hibernate.metamodel.spi.domain.Hierarchical;
|
||||
import org.hibernate.metamodel.spi.domain.Superclass;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
|
||||
/**
|
||||
* Defines the contract for building JPA Metamodel ({@link org.hibernate.jpa.metamodel.internal.MetamodelImpl}).
|
||||
* <p/>
|
||||
* Contract is made up of:<ol>
|
||||
* <li>Instantiating this builder</li>
|
||||
* <li>adding all managed mapping classes to it ({@link #add})</li>
|
||||
* <li>calling {@link #buildMetamodel}</li>
|
||||
* </ol>
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
* @author Emmanuel Bernard
|
||||
*/
|
||||
public class MetamodelBuilder {
|
||||
private static final Logger log = Logger.getLogger( MetamodelBuilder.class );
|
||||
|
||||
private final SessionFactoryImplementor sessionFactory;
|
||||
|
||||
// these maps eventually make up the JPA Metamodel
|
||||
private final Map<Class<?>,EntityTypeImpl<?>> entityTypeMap = new HashMap<Class<?>, EntityTypeImpl<?>>();
|
||||
private final Map<Class<?>, EmbeddableTypeImpl<?>> embeddableTypeMap = new HashMap<Class<?>, EmbeddableTypeImpl<?>>();
|
||||
private final Map<Class<?>, MappedSuperclassTypeImpl<?>> mappedSuperclassTypeMap = new HashMap<Class<?>, MappedSuperclassTypeImpl<?>>();
|
||||
|
||||
// these fields are needed just for the duration of building the metamodel
|
||||
private final AttributeBuilder attributeBuilder;
|
||||
private final Map<String,EntityTypeImpl> entityTypeByNameMap = new HashMap<String, EntityTypeImpl>();
|
||||
private final Map<MappedSuperclassTypeImpl,String> mappedSuperclassEntityNameMap = new HashMap<MappedSuperclassTypeImpl, String>();
|
||||
private List<EntityBinding> entityBindingList = new ArrayList<EntityBinding>();
|
||||
private Set<Hierarchical> alreadyProcessed = new HashSet<Hierarchical>();
|
||||
|
||||
|
||||
public MetamodelBuilder(SessionFactoryImplementor sessionFactory) {
|
||||
this.sessionFactory = sessionFactory;
|
||||
this.attributeBuilder = new AttributeBuilder( new AttributeBuilderContext() );
|
||||
}
|
||||
|
||||
public void add(EntityBinding entityBinding) {
|
||||
locateOrBuildEntityType( entityBinding );
|
||||
entityBindingList.add( entityBinding );
|
||||
}
|
||||
|
||||
private EntityTypeImpl locateOrBuildEntityType(EntityBinding binding) {
|
||||
EntityTypeImpl entityType = entityTypeMap.get( binding.getClassReference() );
|
||||
if ( entityType == null ) {
|
||||
entityType = buildEntityType( binding );
|
||||
}
|
||||
return entityType;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private EntityTypeImpl buildEntityType(EntityBinding entityBinding) {
|
||||
final Class javaType = entityBinding.getClassReference();
|
||||
final AbstractIdentifiableType superType = locateOrBuildSuperType( entityBinding.getEntity().getSuperType(), entityBinding );
|
||||
|
||||
EntityTypeImpl entityType = new EntityTypeImpl(
|
||||
javaType,
|
||||
superType,
|
||||
entityBinding.getJpaEntityName(),
|
||||
entityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding() != null,
|
||||
entityBinding.isVersioned()
|
||||
);
|
||||
|
||||
entityTypeMap.put( javaType, entityType );
|
||||
return entityType;
|
||||
}
|
||||
|
||||
/**
|
||||
* IMPORTANT!!! This method is called in 2 somewhat different cases:<ol>
|
||||
* <li>resolving super class for @Entity</li>
|
||||
* <li>resolving super class for @MappedSuperclass</li>
|
||||
* </ol>
|
||||
* Make sure changes fit both uses
|
||||
*
|
||||
* @param superDescriptor Hibernate metamodel descriptor of the super class
|
||||
* @param entityBinding The Hibernate metamodel entity binding; could be describing different class between the
|
||||
* 2 use cases described above.
|
||||
*
|
||||
* @return The super type.
|
||||
*/
|
||||
private AbstractIdentifiableType locateOrBuildSuperType(Hierarchical superDescriptor, EntityBinding entityBinding) {
|
||||
if ( superDescriptor == null ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// the super type here could be either a "mapped superclass" or an entity
|
||||
if ( Entity.class.isInstance( superDescriptor ) ) {
|
||||
// make sure super entity binding points to same...
|
||||
final EntityBinding superBinding = entityBinding.getSuperEntityBinding();
|
||||
if ( superBinding == null ) {
|
||||
throw new IllegalStateException( "EntityBinding with super class of Entity type did not specify super entity binding" );
|
||||
}
|
||||
if ( superBinding.getEntity() != superDescriptor ) {
|
||||
throw new IllegalStateException( "Super entity binding and descriptor referenced different descriptors" );
|
||||
}
|
||||
return locateOrBuildEntityType( superBinding );
|
||||
}
|
||||
else if ( Superclass.class.isInstance( superDescriptor ) ) {
|
||||
return locateOrBuildMappedSuperclassType( (Superclass) superDescriptor, entityBinding );
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException(
|
||||
"Unexpected type for entity super descriptor; expecting Entity or Superclass, found ["
|
||||
+ superDescriptor.getClassName() + "]"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private MappedSuperclassTypeImpl locateOrBuildMappedSuperclassType(Superclass superDescriptor, EntityBinding entityBinding) {
|
||||
MappedSuperclassTypeImpl mappedSuperclassType = mappedSuperclassTypeMap.get( superDescriptor.getClassReference() );
|
||||
if ( mappedSuperclassType == null ) {
|
||||
mappedSuperclassType = buildMappedSuperclassType( superDescriptor, entityBinding );
|
||||
}
|
||||
return mappedSuperclassType;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private MappedSuperclassTypeImpl buildMappedSuperclassType(Superclass superDescriptor, EntityBinding entityBinding) {
|
||||
final Class javaType = superDescriptor.getClassReference();
|
||||
final AbstractIdentifiableType superSuperType = locateOrBuildSuperType( superDescriptor, entityBinding );
|
||||
|
||||
MappedSuperclassTypeImpl mappedSuperclassType = new MappedSuperclassTypeImpl(
|
||||
javaType,
|
||||
superSuperType,
|
||||
entityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding() != null,
|
||||
entityBinding.isVersioned()
|
||||
);
|
||||
|
||||
mappedSuperclassTypeMap.put( javaType, mappedSuperclassType );
|
||||
mappedSuperclassEntityNameMap.put( mappedSuperclassType, entityBinding.getEntity().getName() );
|
||||
return mappedSuperclassType;
|
||||
}
|
||||
|
||||
public MetamodelImpl buildMetamodel() {
|
||||
log.trace( "Building JPA Metamodel instance..." );
|
||||
// we need to process types from superclasses to subclasses
|
||||
for ( EntityBinding entityBinding : entityBindingList ) {
|
||||
processHierarchy( entityBinding );
|
||||
}
|
||||
|
||||
for ( EmbeddableTypeImpl embeddable : embeddableTypeMap.values() ) {
|
||||
populateStaticMetamodel( embeddable );
|
||||
}
|
||||
|
||||
|
||||
return new MetamodelImpl(
|
||||
entityTypeMap,
|
||||
mappedSuperclassTypeMap,
|
||||
embeddableTypeMap
|
||||
);
|
||||
}
|
||||
|
||||
private void processHierarchy(EntityBinding entityBinding) {
|
||||
log.trace( " Starting binding [" + entityBinding.getEntity().getName() + "]" );
|
||||
processType( entityBinding.getEntity(), entityBinding );
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a depth-first traversal of the super types...
|
||||
*
|
||||
* @param descriptor The type descriptor to process
|
||||
* @param entityBinding
|
||||
*/
|
||||
private void processType(Hierarchical descriptor, EntityBinding entityBinding) {
|
||||
if ( descriptor == null ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( alreadyProcessed.contains( descriptor ) ) {
|
||||
return;
|
||||
}
|
||||
alreadyProcessed.add( descriptor );
|
||||
|
||||
// perform a depth-first traversal of the super types...
|
||||
processSuperType( descriptor, entityBinding );
|
||||
|
||||
final AbstractIdentifiableType jpaDescriptor = Entity.class.isInstance( descriptor )
|
||||
? entityTypeMap.get( descriptor.getClassReference() )
|
||||
: mappedSuperclassTypeMap.get( descriptor.getClassReference() );
|
||||
|
||||
applyIdMetadata( descriptor, entityBinding.getHierarchyDetails(), jpaDescriptor );
|
||||
applyVersionAttribute( descriptor, entityBinding.getHierarchyDetails(), jpaDescriptor );
|
||||
|
||||
for ( AttributeBinding attributeBinding : entityBinding.attributeBindings() ) {
|
||||
if ( entityBinding.getHierarchyDetails().getEntityIdentifier().isIdentifierAttributeBinding( attributeBinding ) ) {
|
||||
continue;
|
||||
}
|
||||
if ( attributeBinding == entityBinding.getHierarchyDetails().getEntityVersion().getVersioningAttributeBinding() ) {
|
||||
// skip the version property, it was already handled previously.
|
||||
continue;
|
||||
}
|
||||
final Attribute attribute = attributeBuilder.buildAttribute( jpaDescriptor, attributeBinding );
|
||||
if ( attribute != null ) {
|
||||
//noinspection unchecked
|
||||
jpaDescriptor.getBuilder().addAttribute( attribute );
|
||||
}
|
||||
}
|
||||
jpaDescriptor.lock();
|
||||
populateStaticMetamodel( jpaDescriptor );
|
||||
}
|
||||
|
||||
private void processSuperType(Hierarchical descriptor, EntityBinding entityBinding) {
|
||||
final Hierarchical superDescriptor = descriptor.getSuperType();
|
||||
final EntityBinding superEntityBinding = Entity.class.isInstance( superDescriptor )
|
||||
? entityBinding.getSuperEntityBinding()
|
||||
: entityBinding;
|
||||
processType( superDescriptor, superEntityBinding );
|
||||
}
|
||||
|
||||
private void applyIdMetadata(
|
||||
Hierarchical descriptor,
|
||||
HierarchyDetails hierarchyDetails,
|
||||
AbstractIdentifiableType jpaDescriptor) {
|
||||
switch ( hierarchyDetails.getEntityIdentifier().getNature() ) {
|
||||
case SIMPLE: {
|
||||
SingularNonAssociationAttributeBinding idAttributeBinding = hierarchyDetails.getEntityIdentifier().getAttributeBinding();
|
||||
if ( idAttributeBinding != null ) {
|
||||
if ( idAttributeBinding.getAttribute().getAttributeContainer().equals( descriptor ) ) {
|
||||
//noinspection unchecked
|
||||
jpaDescriptor.getBuilder().applyIdAttribute(
|
||||
attributeBuilder.buildIdAttribute( jpaDescriptor, idAttributeBinding )
|
||||
);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case AGGREGATED_COMPOSITE: {
|
||||
SingularNonAssociationAttributeBinding idAttributeBinding = hierarchyDetails.getEntityIdentifier().getAttributeBinding();
|
||||
if ( idAttributeBinding != null ) {
|
||||
if ( idAttributeBinding.getAttribute().getAttributeContainer().equals( descriptor ) ) {
|
||||
//noinspection unchecked
|
||||
jpaDescriptor.getBuilder().applyIdAttribute(
|
||||
attributeBuilder.buildIdAttribute( jpaDescriptor, idAttributeBinding )
|
||||
);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
// nature == (non-aggregated) COMPOSITE
|
||||
CompositeAttributeBinding idAttributeBinding = (CompositeAttributeBinding) hierarchyDetails.getEntityIdentifier().getAttributeBinding();
|
||||
if ( idAttributeBinding != null ) {
|
||||
if ( idAttributeBinding.getAttribute().getAttributeContainer().equals( descriptor ) ) {
|
||||
Set<SingularAttribute> idClassAttributes = new HashSet<SingularAttribute>();
|
||||
for ( AttributeBinding idClassAttributeBinding : idAttributeBinding.attributeBindings() ) {
|
||||
idClassAttributes.add( attributeBuilder.buildIdAttribute( jpaDescriptor, idClassAttributeBinding ) );
|
||||
}
|
||||
//noinspection unchecked
|
||||
jpaDescriptor.getBuilder().applyIdClassAttributes( idClassAttributes );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void applyVersionAttribute(
|
||||
Hierarchical descriptor,
|
||||
HierarchyDetails hierarchyDetails,
|
||||
AbstractIdentifiableType jpaDescriptor) {
|
||||
final BasicAttributeBinding versionBinding = hierarchyDetails.getEntityVersion().getVersioningAttributeBinding();
|
||||
if ( versionBinding != null ) {
|
||||
if ( versionBinding.getAttribute().getAttributeContainer().equals( descriptor ) ) {
|
||||
//noinspection unchecked
|
||||
jpaDescriptor.getBuilder().applyVersionAttribute(
|
||||
attributeBuilder.buildVersionAttribute( jpaDescriptor, versionBinding )
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void populateStaticMetamodel(AbstractIdentifiableType jpaDescriptor) {
|
||||
// todo : implement !
|
||||
}
|
||||
|
||||
private void populateStaticMetamodel(EmbeddableTypeImpl embeddable) {
|
||||
// todo : implement !
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Implementation of AttributeBuilder.Context
|
||||
*/
|
||||
class AttributeBuilderContext implements AttributeBuilder.Context {
|
||||
public Type locateEntityTypeByName(String entityName) {
|
||||
return entityTypeByNameMap.get( entityName );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerEmbeddedableType(EmbeddableTypeImpl embeddableType) {
|
||||
embeddableTypeMap.put( embeddableType.getJavaType(), embeddableType );
|
||||
}
|
||||
|
||||
public SessionFactoryImplementor getSessionFactory() {
|
||||
return sessionFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityPersister getSubClassEntityPersister(MappedSuperclassTypeImpl mappedSuperclass) {
|
||||
final String entityName = mappedSuperclassEntityNameMap.get( mappedSuperclass );
|
||||
if ( entityName == null ) {
|
||||
throw new HibernateException(
|
||||
String.format(
|
||||
"Could not resolve @MappedSuperclass [%s] to entity name",
|
||||
mappedSuperclass.getJavaType().getName()
|
||||
)
|
||||
);
|
||||
}
|
||||
final EntityPersister entityPersister = sessionFactory.getEntityPersister( entityName );
|
||||
if ( entityPersister == null ) {
|
||||
throw new HibernateException(
|
||||
String.format(
|
||||
"Unable to resolve entity name [%s] to EntityPersister for @MappedSuperclass [%s]",
|
||||
entityName,
|
||||
mappedSuperclass.getJavaType().getName()
|
||||
)
|
||||
);
|
||||
}
|
||||
return entityPersister;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleUnsupportedFeature(UnsupportedFeature feature) {
|
||||
boolean ignoreUnsupported = true;
|
||||
if ( ignoreUnsupported ) {
|
||||
log.debug( "Ignoring mapping construct not supported as part of JPA metamodel [" + feature.getMessage() + "]" );
|
||||
}
|
||||
else {
|
||||
throw new UnsupportedOperationException( feature.getMessage() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2012, 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.jpa.metamodel.internal.builder;
|
||||
|
||||
import javax.persistence.metamodel.PluralAttribute;
|
||||
|
||||
/**
|
||||
* Attribute metadata contract for a plural attribute.
|
||||
* @param <X> The owner type
|
||||
* @param <Y> The attribute type (the collection type)
|
||||
* @param <E> The collection element type
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
* @author Emmanuel Bernard
|
||||
*/
|
||||
interface PluralAttributeMetadata<X,Y,E> extends AttributeMetadata<X,Y> {
|
||||
/**
|
||||
* Retrieve the JPA collection type classification for this attribute
|
||||
*
|
||||
* @return The JPA collection type classification
|
||||
*/
|
||||
public PluralAttribute.CollectionType getAttributeCollectionType();
|
||||
|
||||
/**
|
||||
* Retrieve the value context for the collection's elements.
|
||||
*
|
||||
* @return The value context for the collection's elements.
|
||||
*/
|
||||
public AttributeTypeDescriptor getElementAttributeTypeDescriptor();
|
||||
|
||||
/**
|
||||
* Retrieve the value context for the collection's keys (if a map, null otherwise).
|
||||
*
|
||||
* @return The value context for the collection's keys (if a map, null otherwise).
|
||||
*/
|
||||
public AttributeTypeDescriptor getMapKeyAttributeTypeDescriptor();
|
||||
}
|
|
@ -0,0 +1,195 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2012, 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.jpa.metamodel.internal.builder;
|
||||
|
||||
import javax.persistence.metamodel.Attribute;
|
||||
import javax.persistence.metamodel.PluralAttribute;
|
||||
import java.lang.reflect.Member;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.TypeVariable;
|
||||
|
||||
import org.hibernate.annotations.common.AssertionFailure;
|
||||
import org.hibernate.jpa.metamodel.internal.AbstractManagedType;
|
||||
import org.hibernate.metamodel.spi.binding.IndexedPluralAttributeBinding;
|
||||
import org.hibernate.metamodel.spi.binding.PluralAttributeBinding;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class PluralAttributeMetadataImpl<X,Y,E>
|
||||
extends BaseAttributeMetadata<X,Y>
|
||||
implements PluralAttributeMetadata<X,Y,E> {
|
||||
private final PluralAttribute.CollectionType attributeCollectionType;
|
||||
private final Attribute.PersistentAttributeType elementPersistentAttributeType;
|
||||
private final Attribute.PersistentAttributeType keyPersistentAttributeType;
|
||||
private final Class elementJavaType;
|
||||
private final Class keyJavaType;
|
||||
private final AttributeTypeDescriptor elementAttributeTypeDescriptor;
|
||||
private final AttributeTypeDescriptor keyAttributeTypeDescriptor;
|
||||
|
||||
PluralAttributeMetadataImpl(
|
||||
PluralAttributeBinding attributeBinding,
|
||||
AbstractManagedType<X> ownerType,
|
||||
Member member,
|
||||
Attribute.PersistentAttributeType persistentAttributeType,
|
||||
Attribute.PersistentAttributeType elementPersistentAttributeType,
|
||||
Attribute.PersistentAttributeType keyPersistentAttributeType) {
|
||||
super( attributeBinding, ownerType, member, persistentAttributeType );
|
||||
this.attributeCollectionType = AttributeBuilder.determineCollectionType( getJavaType() );
|
||||
this.elementPersistentAttributeType = elementPersistentAttributeType;
|
||||
this.keyPersistentAttributeType = keyPersistentAttributeType;
|
||||
|
||||
ParameterizedType signatureType = AttributeBuilder.getSignatureType( member );
|
||||
if ( keyPersistentAttributeType == null ) {
|
||||
elementJavaType = signatureType != null ?
|
||||
getClassFromGenericArgument( signatureType.getActualTypeArguments()[0] ) :
|
||||
Object.class; //FIXME and honor targetEntity?
|
||||
keyJavaType = null;
|
||||
}
|
||||
else {
|
||||
keyJavaType = signatureType != null ?
|
||||
getClassFromGenericArgument( signatureType.getActualTypeArguments()[0] ) :
|
||||
Object.class; //FIXME and honor targetEntity?
|
||||
elementJavaType = signatureType != null ?
|
||||
getClassFromGenericArgument( signatureType.getActualTypeArguments()[1] ) :
|
||||
Object.class; //FIXME and honor targetEntity?
|
||||
}
|
||||
|
||||
this.elementAttributeTypeDescriptor = new AttributeTypeDescriptor() {
|
||||
@Override
|
||||
public org.hibernate.metamodel.spi.domain.Type getHibernateMetamodelType() {
|
||||
return getAttributeBinding().getAttribute().getElementType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public org.hibernate.type.Type getHibernateType() {
|
||||
return getAttributeBinding().getPluralAttributeElementBinding()
|
||||
.getHibernateTypeDescriptor()
|
||||
.getResolvedTypeMapping();
|
||||
}
|
||||
|
||||
public Class getBindableType() {
|
||||
return elementJavaType;
|
||||
}
|
||||
|
||||
public ValueClassification getValueClassification() {
|
||||
switch ( PluralAttributeMetadataImpl.this.elementPersistentAttributeType ) {
|
||||
case EMBEDDED: {
|
||||
return ValueClassification.EMBEDDABLE;
|
||||
}
|
||||
case BASIC: {
|
||||
return ValueClassification.BASIC;
|
||||
}
|
||||
default: {
|
||||
return ValueClassification.ENTITY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public AttributeMetadata getAttributeMetadata() {
|
||||
return PluralAttributeMetadataImpl.this;
|
||||
}
|
||||
};
|
||||
|
||||
// interpret the key, if one
|
||||
if ( keyPersistentAttributeType != null ) {
|
||||
this.keyAttributeTypeDescriptor = new AttributeTypeDescriptor() {
|
||||
@Override
|
||||
public org.hibernate.metamodel.spi.domain.Type getHibernateMetamodelType() {
|
||||
return ( (IndexedPluralAttributeBinding) getAttributeBinding() ).getPluralAttributeIndexBinding()
|
||||
.getPluralAttributeIndexType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public org.hibernate.type.Type getHibernateType() {
|
||||
return getAttributeBinding().getPluralAttributeKeyBinding()
|
||||
.getHibernateTypeDescriptor()
|
||||
.getResolvedTypeMapping();
|
||||
}
|
||||
|
||||
public Class getBindableType() {
|
||||
return keyJavaType;
|
||||
}
|
||||
|
||||
public ValueClassification getValueClassification() {
|
||||
switch ( PluralAttributeMetadataImpl.this.keyPersistentAttributeType ) {
|
||||
case EMBEDDED: {
|
||||
return ValueClassification.EMBEDDABLE;
|
||||
}
|
||||
case BASIC: {
|
||||
return ValueClassification.BASIC;
|
||||
}
|
||||
default: {
|
||||
return ValueClassification.ENTITY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public AttributeMetadata getAttributeMetadata() {
|
||||
return PluralAttributeMetadataImpl.this;
|
||||
}
|
||||
};
|
||||
}
|
||||
else {
|
||||
keyAttributeTypeDescriptor = null;
|
||||
}
|
||||
}
|
||||
|
||||
private Class<?> getClassFromGenericArgument(java.lang.reflect.Type type) {
|
||||
if ( type instanceof Class ) {
|
||||
return (Class) type;
|
||||
}
|
||||
else if ( type instanceof TypeVariable ) {
|
||||
final java.lang.reflect.Type upperBound = ( ( TypeVariable ) type ).getBounds()[0];
|
||||
return getClassFromGenericArgument( upperBound );
|
||||
}
|
||||
else if ( type instanceof ParameterizedType ) {
|
||||
final java.lang.reflect.Type rawType = ( (ParameterizedType) type ).getRawType();
|
||||
return getClassFromGenericArgument( rawType );
|
||||
}
|
||||
else {
|
||||
throw new AssertionFailure(
|
||||
"Fail to process type argument in a generic declaration. Member : " + getMemberDescription()
|
||||
+ " Type: " + type.getClass()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PluralAttributeBinding getAttributeBinding() {
|
||||
return (PluralAttributeBinding) super.getAttributeBinding();
|
||||
}
|
||||
|
||||
public AttributeTypeDescriptor getElementAttributeTypeDescriptor() {
|
||||
return elementAttributeTypeDescriptor;
|
||||
}
|
||||
|
||||
public PluralAttribute.CollectionType getAttributeCollectionType() {
|
||||
return attributeCollectionType;
|
||||
}
|
||||
|
||||
public AttributeTypeDescriptor getMapKeyAttributeTypeDescriptor() {
|
||||
return keyAttributeTypeDescriptor;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2012, 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.jpa.metamodel.internal.builder;
|
||||
|
||||
/**
|
||||
* Attribute metadata contract for a non-plural attribute.
|
||||
* @param <X> The owner type
|
||||
* @param <Y> The attribute type
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
* @author Emmanuel Bernard
|
||||
*/
|
||||
public interface SingularAttributeMetadata<X,Y> extends AttributeMetadata<X,Y> {
|
||||
/**
|
||||
* Retrieve the value context for this attribute
|
||||
*
|
||||
* @return The attributes value context
|
||||
*/
|
||||
public AttributeTypeDescriptor getAttributeTypeDescriptor();
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2012, 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.jpa.metamodel.internal.builder;
|
||||
|
||||
import javax.persistence.metamodel.Attribute;
|
||||
import java.lang.reflect.Member;
|
||||
|
||||
import org.hibernate.jpa.metamodel.internal.AbstractManagedType;
|
||||
import org.hibernate.metamodel.spi.binding.AttributeBinding;
|
||||
import org.hibernate.metamodel.spi.domain.SingularAttribute;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class SingularAttributeMetadataImpl<X,Y>
|
||||
extends BaseAttributeMetadata<X,Y>
|
||||
implements SingularAttributeMetadata<X,Y> {
|
||||
private final AttributeTypeDescriptor attributeTypeDescriptor;
|
||||
|
||||
public SingularAttributeMetadataImpl(
|
||||
AttributeBinding attributeBinding,
|
||||
AbstractManagedType<X> ownerType,
|
||||
Member member,
|
||||
Attribute.PersistentAttributeType persistentAttributeType) {
|
||||
super( attributeBinding, ownerType, member, persistentAttributeType );
|
||||
attributeTypeDescriptor = new AttributeTypeDescriptor() {
|
||||
@Override
|
||||
public org.hibernate.metamodel.spi.domain.Type getHibernateMetamodelType() {
|
||||
return ( (SingularAttribute) getAttributeMetadata().getAttributeBinding().getAttribute() ).getSingularAttributeType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public org.hibernate.type.Type getHibernateType() {
|
||||
return getAttributeMetadata().getAttributeBinding().getHibernateTypeDescriptor().getResolvedTypeMapping();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class getBindableType() {
|
||||
return getAttributeMetadata().getJavaType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueClassification getValueClassification() {
|
||||
switch ( getPersistentAttributeType() ) {
|
||||
case EMBEDDED: {
|
||||
return ValueClassification.EMBEDDABLE;
|
||||
}
|
||||
case BASIC: {
|
||||
return ValueClassification.BASIC;
|
||||
}
|
||||
default: {
|
||||
return ValueClassification.ENTITY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public AttributeMetadata getAttributeMetadata() {
|
||||
return SingularAttributeMetadataImpl.this;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public AttributeTypeDescriptor getAttributeTypeDescriptor() {
|
||||
return attributeTypeDescriptor;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,142 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2012, 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.jpa.metamodel.internal.legacy;
|
||||
|
||||
import javax.persistence.metamodel.Attribute;
|
||||
import javax.persistence.metamodel.ManagedType;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Member;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.hibernate.internal.util.ReflectHelper;
|
||||
|
||||
/**
|
||||
* Models the commonality of the JPA {@link javax.persistence.metamodel.Attribute} hierarchy.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public abstract class AbstractAttribute<X, Y>
|
||||
implements Attribute<X, Y>, AttributeImplementor<X,Y>, Serializable {
|
||||
private final String name;
|
||||
private final Class<Y> javaType;
|
||||
private final AbstractManagedType<X> declaringType;
|
||||
private transient Member member;
|
||||
private final PersistentAttributeType persistentAttributeType;
|
||||
|
||||
public AbstractAttribute(
|
||||
String name,
|
||||
Class<Y> javaType,
|
||||
AbstractManagedType<X> declaringType,
|
||||
Member member,
|
||||
PersistentAttributeType persistentAttributeType) {
|
||||
this.name = name;
|
||||
this.javaType = javaType;
|
||||
this.declaringType = declaringType;
|
||||
this.member = member;
|
||||
this.persistentAttributeType = persistentAttributeType;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public ManagedType<X> getDeclaringType() {
|
||||
return declaringType;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Class<Y> getJavaType() {
|
||||
return javaType;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Member getJavaMember() {
|
||||
return member;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public PersistentAttributeType getPersistentAttributeType() {
|
||||
return persistentAttributeType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used by JDK serialization...
|
||||
*
|
||||
* @param ois The input stream from which we are being read...
|
||||
* @throws java.io.IOException Indicates a general IO stream exception
|
||||
* @throws ClassNotFoundException Indicates a class resolution issue
|
||||
*/
|
||||
protected void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
|
||||
ois.defaultReadObject();
|
||||
final String memberDeclaringClassName = ( String ) ois.readObject();
|
||||
final String memberName = ( String ) ois.readObject();
|
||||
final String memberType = ( String ) ois.readObject();
|
||||
|
||||
final Class memberDeclaringClass = Class.forName(
|
||||
memberDeclaringClassName,
|
||||
false,
|
||||
declaringType.getJavaType().getClassLoader()
|
||||
);
|
||||
try {
|
||||
this.member = "method".equals( memberType )
|
||||
? memberDeclaringClass.getMethod( memberName, ReflectHelper.NO_PARAM_SIGNATURE )
|
||||
: memberDeclaringClass.getField( memberName );
|
||||
}
|
||||
catch ( Exception e ) {
|
||||
throw new IllegalStateException(
|
||||
"Unable to locate member [" + memberDeclaringClassName + "#"
|
||||
+ memberName + "]"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used by JDK serialization...
|
||||
*
|
||||
* @param oos The output stream to which we are being written...
|
||||
* @throws java.io.IOException Indicates a general IO stream exception
|
||||
*/
|
||||
protected void writeObject(ObjectOutputStream oos) throws IOException {
|
||||
oos.defaultWriteObject();
|
||||
oos.writeObject( getJavaMember().getDeclaringClass().getName() );
|
||||
oos.writeObject( getJavaMember().getName() );
|
||||
// should only ever be a field or the getter-method...
|
||||
oos.writeObject( Method.class.isInstance( getJavaMember() ) ? "method" : "field" );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,318 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2012, 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.jpa.metamodel.internal.legacy;
|
||||
|
||||
import javax.persistence.metamodel.Attribute;
|
||||
import javax.persistence.metamodel.IdentifiableType;
|
||||
import javax.persistence.metamodel.SingularAttribute;
|
||||
import javax.persistence.metamodel.Type;
|
||||
import java.io.Serializable;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Defines commonality for the JPA {@link javax.persistence.metamodel.IdentifiableType} types. JPA defines
|
||||
* identifiable types as entities or mapped-superclasses. Basically things to which an
|
||||
* identifier can be attached.
|
||||
* <p/>
|
||||
* NOTE : Currently we only really have support for direct entities in the Hibernate metamodel
|
||||
* as the information for them is consumed into the closest actual entity subclass(es) in the
|
||||
* internal Hibernate mapping-metamodel.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public abstract class AbstractIdentifiableType<X>
|
||||
extends AbstractManagedType<X>
|
||||
implements IdentifiableType<X>, Serializable {
|
||||
|
||||
private final boolean hasIdentifierProperty;
|
||||
private final boolean isVersioned;
|
||||
|
||||
private SingularAttributeImpl<X, ?> id;
|
||||
private SingularAttributeImpl<X, ?> version;
|
||||
private Set<SingularAttribute<? super X,?>> idClassAttributes;
|
||||
|
||||
public AbstractIdentifiableType(
|
||||
Class<X> javaType,
|
||||
AbstractIdentifiableType<? super X> superType,
|
||||
boolean hasIdentifierProperty,
|
||||
boolean versioned) {
|
||||
super( javaType, superType );
|
||||
this.hasIdentifierProperty = hasIdentifierProperty;
|
||||
isVersioned = versioned;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public AbstractIdentifiableType<? super X> getSupertype() {
|
||||
return ( AbstractIdentifiableType<? super X> ) super.getSupertype();
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if a non-null super type is required to provide the
|
||||
* identifier attribute(s) if this object does not have a declared
|
||||
* identifier.
|
||||
* .
|
||||
* @return true, if a non-null super type is required to provide
|
||||
* the identifier attribute(s) if this object does not have a
|
||||
* declared identifier; false, otherwise.
|
||||
*/
|
||||
protected abstract boolean requiresSupertypeForNonDeclaredIdentifier();
|
||||
|
||||
protected AbstractIdentifiableType<? super X> requireSupertype() {
|
||||
if ( getSupertype() == null ) {
|
||||
throw new IllegalStateException( "No supertype found" );
|
||||
}
|
||||
return getSupertype();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public boolean hasSingleIdAttribute() {
|
||||
return hasIdentifierProperty;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public <Y> SingularAttribute<? super X, Y> getId(Class<Y> javaType) {
|
||||
final SingularAttribute<? super X, Y> id_;
|
||||
if ( id != null ) {
|
||||
checkSimpleId();
|
||||
id_ = ( SingularAttribute<? super X, Y> ) id;
|
||||
if ( javaType != id.getJavaType() ) {
|
||||
throw new IllegalArgumentException( "Id attribute was not of specified type : " + javaType.getName() );
|
||||
}
|
||||
}
|
||||
else {
|
||||
//yuk yuk bad me
|
||||
if ( ! requiresSupertypeForNonDeclaredIdentifier()) {
|
||||
final AbstractIdentifiableType<? super X> supertype = getSupertype();
|
||||
if (supertype != null) {
|
||||
id_ = supertype.getId( javaType );
|
||||
}
|
||||
else {
|
||||
id_ = null;
|
||||
}
|
||||
}
|
||||
else {
|
||||
id_ = requireSupertype().getId( javaType );
|
||||
}
|
||||
}
|
||||
return id_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Centralized check to ensure the id for this hierarchy is a simple one (i.e., does not use
|
||||
* an id-class).
|
||||
*
|
||||
* @see #checkIdClass()
|
||||
*/
|
||||
protected void checkSimpleId() {
|
||||
if ( ! hasIdentifierProperty ) {
|
||||
throw new IllegalStateException( "This class uses an @IdClass" );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public <Y> SingularAttribute<X, Y> getDeclaredId(Class<Y> javaType) {
|
||||
checkDeclaredId();
|
||||
checkSimpleId();
|
||||
if ( javaType != id.getJavaType() ) {
|
||||
throw new IllegalArgumentException( "Id attribute was not of specified type : " + javaType.getName() );
|
||||
}
|
||||
return (SingularAttribute<X, Y>) id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Centralized check to ensure the id is actually declared on the class mapped here, as opposed to a
|
||||
* super class.
|
||||
*/
|
||||
protected void checkDeclaredId() {
|
||||
if ( id == null ) {
|
||||
throw new IllegalArgumentException( "The id attribute is not declared on this type" );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Type<?> getIdType() {
|
||||
if ( id != null ) {
|
||||
checkSimpleId();
|
||||
return id.getType();
|
||||
}
|
||||
else {
|
||||
return requireSupertype().getIdType();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasIdClassAttributesDefined() {
|
||||
return idClassAttributes != null ||
|
||||
( getSupertype() != null && getSupertype().hasIdClassAttributesDefined() );
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Set<SingularAttribute<? super X, ?>> getIdClassAttributes() {
|
||||
if ( idClassAttributes != null ) {
|
||||
checkIdClass();
|
||||
}
|
||||
else {
|
||||
// Java does not allow casting requireSupertype().getIdClassAttributes()
|
||||
// to Set<SingularAttribute<? super X, ?>> because the
|
||||
// superclass X is a different Java type from this X
|
||||
// (i.e, getSupertype().getJavaType() != getJavaType()).
|
||||
// It will, however, allow a Set<SingularAttribute<? super X, ?>>
|
||||
// to be initialized with requireSupertype().getIdClassAttributes(),
|
||||
// since getSupertype().getJavaType() is a superclass of getJavaType()
|
||||
if ( requiresSupertypeForNonDeclaredIdentifier() ) {
|
||||
idClassAttributes = new HashSet<SingularAttribute<? super X, ?>>( requireSupertype().getIdClassAttributes() );
|
||||
}
|
||||
else if ( getSupertype() != null && hasIdClassAttributesDefined() ) {
|
||||
idClassAttributes = new HashSet<SingularAttribute<? super X, ?>>( getSupertype().getIdClassAttributes() );
|
||||
}
|
||||
}
|
||||
return idClassAttributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Centralized check to ensure the id for this hierarchy uses an id-class.
|
||||
*
|
||||
* @see #checkSimpleId()
|
||||
*/
|
||||
private void checkIdClass() {
|
||||
if ( hasIdentifierProperty ) {
|
||||
throw new IllegalArgumentException( "This class does not use @IdClass" );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public boolean hasVersionAttribute() {
|
||||
return isVersioned;
|
||||
}
|
||||
|
||||
public boolean hasDeclaredVersionAttribute() {
|
||||
return isVersioned && version != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public <Y> SingularAttribute<? super X, Y> getVersion(Class<Y> javaType) {
|
||||
if ( ! hasVersionAttribute() ) {
|
||||
return null;
|
||||
}
|
||||
final SingularAttribute<? super X, Y> version_;
|
||||
if ( version != null ) {
|
||||
version_ = ( SingularAttribute<? super X, Y> ) version;
|
||||
if ( javaType != version.getJavaType() ) {
|
||||
throw new IllegalArgumentException( "Version attribute was not of specified type : " + javaType.getName() );
|
||||
}
|
||||
}
|
||||
else {
|
||||
version_ = requireSupertype().getVersion( javaType );
|
||||
}
|
||||
return version_;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public <Y> SingularAttribute<X, Y> getDeclaredVersion(Class<Y> javaType) {
|
||||
checkDeclaredVersion();
|
||||
if ( javaType != version.getJavaType() ) {
|
||||
throw new IllegalArgumentException( "Version attribute was not of specified type : " + javaType.getName() );
|
||||
}
|
||||
return ( SingularAttribute<X, Y> ) version;
|
||||
}
|
||||
|
||||
/**
|
||||
* For used to retrieve the declared version when populating the static metamodel.
|
||||
*
|
||||
* @return The declared
|
||||
*/
|
||||
public SingularAttribute<X, ?> getDeclaredVersion() {
|
||||
checkDeclaredVersion();
|
||||
return version;
|
||||
}
|
||||
|
||||
/**
|
||||
* Centralized check to ensure the version (if one) is actually declared on the class mapped here, as opposed to a
|
||||
* super class.
|
||||
*/
|
||||
protected void checkDeclaredVersion() {
|
||||
if ( version == null || ( getSupertype() != null && getSupertype().hasVersionAttribute() )) {
|
||||
throw new IllegalArgumentException( "The version attribute is not declared on this type" );
|
||||
}
|
||||
}
|
||||
|
||||
public Builder<X> getBuilder() {
|
||||
final AbstractManagedType.Builder<X> managedBuilder = super.getBuilder();
|
||||
return new Builder<X>() {
|
||||
public void applyIdAttribute(SingularAttributeImpl<X, ?> idAttribute) {
|
||||
AbstractIdentifiableType.this.id = idAttribute;
|
||||
managedBuilder.addAttribute( idAttribute );
|
||||
}
|
||||
|
||||
public void applyIdClassAttributes(Set<SingularAttribute<? super X,?>> idClassAttributes) {
|
||||
for ( SingularAttribute<? super X,?> idClassAttribute : idClassAttributes ) {
|
||||
if ( AbstractIdentifiableType.this == idClassAttribute.getDeclaringType() ) {
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
SingularAttribute<X,?> declaredAttribute = ( SingularAttribute<X,?> ) idClassAttribute;
|
||||
addAttribute( declaredAttribute );
|
||||
}
|
||||
}
|
||||
AbstractIdentifiableType.this.idClassAttributes = idClassAttributes;
|
||||
}
|
||||
|
||||
public void applyVersionAttribute(SingularAttributeImpl<X, ?> versionAttribute) {
|
||||
AbstractIdentifiableType.this.version = versionAttribute;
|
||||
managedBuilder.addAttribute( versionAttribute );
|
||||
}
|
||||
|
||||
public void addAttribute(Attribute<X, ?> attribute) {
|
||||
managedBuilder.addAttribute( attribute );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static interface Builder<X> extends AbstractManagedType.Builder<X> {
|
||||
public void applyIdAttribute(SingularAttributeImpl<X, ?> idAttribute);
|
||||
public void applyIdClassAttributes(Set<SingularAttribute<? super X, ?>> idClassAttributes);
|
||||
public void applyVersionAttribute(SingularAttributeImpl<X, ?> versionAttribute);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,529 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
|
||||
* third-party contributors as indicated by either @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.jpa.metamodel.internal.legacy;
|
||||
|
||||
import javax.persistence.metamodel.Attribute;
|
||||
import javax.persistence.metamodel.Bindable;
|
||||
import javax.persistence.metamodel.CollectionAttribute;
|
||||
import javax.persistence.metamodel.ListAttribute;
|
||||
import javax.persistence.metamodel.ManagedType;
|
||||
import javax.persistence.metamodel.MapAttribute;
|
||||
import javax.persistence.metamodel.PluralAttribute;
|
||||
import javax.persistence.metamodel.SetAttribute;
|
||||
import javax.persistence.metamodel.SingularAttribute;
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.hibernate.annotations.common.AssertionFailure;
|
||||
|
||||
/**
|
||||
* Defines commonality for the JPA {@link javax.persistence.metamodel.ManagedType} hierarchy of interfaces.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public abstract class AbstractManagedType<X>
|
||||
extends AbstractType<X>
|
||||
implements ManagedType<X>, Serializable {
|
||||
|
||||
private final AbstractManagedType<? super X> superType;
|
||||
|
||||
private final Map<String,Attribute<X, ?>> declaredAttributes
|
||||
= new HashMap<String, Attribute<X,?>>();
|
||||
private final Map<String, SingularAttribute<X, ?>> declaredSingularAttributes
|
||||
= new HashMap<String, SingularAttribute<X,?>>();
|
||||
private final Map<String, PluralAttribute<X, ?, ?>> declaredPluralAttributes
|
||||
= new HashMap<String, PluralAttribute<X,?,?>>();
|
||||
|
||||
protected AbstractManagedType(Class<X> javaType, AbstractManagedType<? super X> superType) {
|
||||
super( javaType );
|
||||
this.superType = superType;
|
||||
}
|
||||
|
||||
protected AbstractManagedType<? super X> getSupertype() {
|
||||
return superType;
|
||||
}
|
||||
|
||||
private boolean locked = false;
|
||||
|
||||
public Builder<X> getBuilder() {
|
||||
if ( locked ) {
|
||||
throw new IllegalStateException( "Type has been locked" );
|
||||
}
|
||||
return new Builder<X>() {
|
||||
public void addAttribute(Attribute<X,?> attribute) {
|
||||
declaredAttributes.put( attribute.getName(), attribute );
|
||||
final Bindable.BindableType bindableType = ( ( Bindable ) attribute ).getBindableType();
|
||||
switch ( bindableType ) {
|
||||
case SINGULAR_ATTRIBUTE : {
|
||||
declaredSingularAttributes.put( attribute.getName(), (SingularAttribute<X,?>) attribute );
|
||||
break;
|
||||
}
|
||||
case PLURAL_ATTRIBUTE : {
|
||||
declaredPluralAttributes.put(attribute.getName(), (PluralAttribute<X,?,?>) attribute );
|
||||
break;
|
||||
}
|
||||
default : {
|
||||
throw new AssertionFailure( "unknown bindable type: " + bindableType );
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public void lock() {
|
||||
locked = true;
|
||||
}
|
||||
|
||||
public static interface Builder<X> {
|
||||
public void addAttribute(Attribute<X, ?> attribute);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public Set<Attribute<? super X, ?>> getAttributes() {
|
||||
HashSet attributes = new HashSet<Attribute<X, ?>>( declaredAttributes.values() );
|
||||
if ( getSupertype() != null ) {
|
||||
attributes.addAll( getSupertype().getAttributes() );
|
||||
}
|
||||
return attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Set<Attribute<X, ?>> getDeclaredAttributes() {
|
||||
return new HashSet<Attribute<X, ?>>( declaredAttributes.values() );
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public Attribute<? super X, ?> getAttribute(String name) {
|
||||
Attribute<? super X, ?> attribute = declaredAttributes.get( name );
|
||||
if ( attribute == null && getSupertype() != null ) {
|
||||
attribute = getSupertype().getAttribute( name );
|
||||
}
|
||||
return attribute;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Attribute<X, ?> getDeclaredAttribute(String name) {
|
||||
final Attribute<X, ?> attr = declaredSingularAttributes.get( name );
|
||||
checkNotNull( "Attribute ", attr, name );
|
||||
return attr;
|
||||
}
|
||||
|
||||
private void checkNotNull(String attributeType, Attribute<?,?> attribute, String name) {
|
||||
if ( attribute == null ) {
|
||||
throw new IllegalArgumentException( attributeType + " named " + name + " is not present" );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public Set<SingularAttribute<? super X, ?>> getSingularAttributes() {
|
||||
HashSet attributes = new HashSet<SingularAttribute<X, ?>>( declaredSingularAttributes.values() );
|
||||
if ( getSupertype() != null ) {
|
||||
attributes.addAll( getSupertype().getSingularAttributes() );
|
||||
}
|
||||
return attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Set<SingularAttribute<X, ?>> getDeclaredSingularAttributes() {
|
||||
return new HashSet<SingularAttribute<X, ?>>( declaredSingularAttributes.values() );
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public SingularAttribute<? super X, ?> getSingularAttribute(String name) {
|
||||
SingularAttribute<? super X, ?> attribute = declaredSingularAttributes.get( name );
|
||||
if ( attribute == null && getSupertype() != null ) {
|
||||
attribute = getSupertype().getSingularAttribute( name );
|
||||
}
|
||||
return attribute;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public SingularAttribute<X, ?> getDeclaredSingularAttribute(String name) {
|
||||
final SingularAttribute<X, ?> attr = declaredSingularAttributes.get( name );
|
||||
checkNotNull( "SingularAttribute ", attr, name );
|
||||
return attr;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public <Y> SingularAttribute<? super X, Y> getSingularAttribute(String name, Class<Y> type) {
|
||||
SingularAttribute<? super X, ?> attribute = declaredSingularAttributes.get( name );
|
||||
if ( attribute == null && getSupertype() != null ) {
|
||||
attribute = getSupertype().getSingularAttribute( name );
|
||||
}
|
||||
checkTypeForSingleAttribute( "SingularAttribute ", attribute, name, type );
|
||||
return ( SingularAttribute<? super X, Y> ) attribute;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@SuppressWarnings( "unchecked")
|
||||
public <Y> SingularAttribute<X, Y> getDeclaredSingularAttribute(String name, Class<Y> javaType) {
|
||||
final SingularAttribute<X, ?> attr = declaredSingularAttributes.get( name );
|
||||
checkTypeForSingleAttribute( "SingularAttribute ", attr, name, javaType );
|
||||
return ( SingularAttribute<X, Y> ) attr;
|
||||
}
|
||||
|
||||
private <Y> void checkTypeForSingleAttribute(
|
||||
String attributeType,
|
||||
SingularAttribute<?,?> attribute,
|
||||
String name,
|
||||
Class<Y> javaType) {
|
||||
if ( attribute == null || ( javaType != null && !attribute.getBindableJavaType().equals( javaType ) ) ) {
|
||||
if ( isPrimitiveVariant( attribute, javaType ) ) {
|
||||
return;
|
||||
}
|
||||
throw new IllegalArgumentException(
|
||||
attributeType + " named " + name
|
||||
+ ( javaType != null ? " and of type " + javaType.getName() : "" )
|
||||
+ " is not present"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "SimplifiableIfStatement" })
|
||||
protected <Y> boolean isPrimitiveVariant(SingularAttribute<?,?> attribute, Class<Y> javaType) {
|
||||
if ( attribute == null ) {
|
||||
return false;
|
||||
}
|
||||
Class declaredType = attribute.getBindableJavaType();
|
||||
|
||||
if ( declaredType.isPrimitive() ) {
|
||||
return ( Boolean.class.equals( javaType ) && Boolean.TYPE.equals( declaredType ) )
|
||||
|| ( Character.class.equals( javaType ) && Character.TYPE.equals( declaredType ) )
|
||||
|| ( Byte.class.equals( javaType ) && Byte.TYPE.equals( declaredType ) )
|
||||
|| ( Short.class.equals( javaType ) && Short.TYPE.equals( declaredType ) )
|
||||
|| ( Integer.class.equals( javaType ) && Integer.TYPE.equals( declaredType ) )
|
||||
|| ( Long.class.equals( javaType ) && Long.TYPE.equals( declaredType ) )
|
||||
|| ( Float.class.equals( javaType ) && Float.TYPE.equals( declaredType ) )
|
||||
|| ( Double.class.equals( javaType ) && Double.TYPE.equals( declaredType ) );
|
||||
}
|
||||
|
||||
if ( javaType.isPrimitive() ) {
|
||||
return ( Boolean.class.equals( declaredType ) && Boolean.TYPE.equals( javaType ) )
|
||||
|| ( Character.class.equals( declaredType ) && Character.TYPE.equals( javaType ) )
|
||||
|| ( Byte.class.equals( declaredType ) && Byte.TYPE.equals( javaType ) )
|
||||
|| ( Short.class.equals( declaredType ) && Short.TYPE.equals( javaType ) )
|
||||
|| ( Integer.class.equals( declaredType ) && Integer.TYPE.equals( javaType ) )
|
||||
|| ( Long.class.equals( declaredType ) && Long.TYPE.equals( javaType ) )
|
||||
|| ( Float.class.equals( declaredType ) && Float.TYPE.equals( javaType ) )
|
||||
|| ( Double.class.equals( declaredType ) && Double.TYPE.equals( javaType ) );
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public Set<PluralAttribute<? super X, ?, ?>> getPluralAttributes() {
|
||||
HashSet attributes = new HashSet<PluralAttribute<? super X, ?, ?>>( declaredPluralAttributes.values() );
|
||||
if ( getSupertype() != null ) {
|
||||
attributes.addAll( getSupertype().getPluralAttributes() );
|
||||
}
|
||||
return attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Set<PluralAttribute<X, ?, ?>> getDeclaredPluralAttributes() {
|
||||
return new HashSet<PluralAttribute<X,?,?>>( declaredPluralAttributes.values() );
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public CollectionAttribute<? super X, ?> getCollection(String name) {
|
||||
PluralAttribute<? super X, ?, ?> attribute = getPluralAttribute( name );
|
||||
if ( attribute == null && getSupertype() != null ) {
|
||||
attribute = getSupertype().getPluralAttribute( name );
|
||||
}
|
||||
basicCollectionCheck( attribute, name );
|
||||
return ( CollectionAttribute<X, ?> ) attribute;
|
||||
}
|
||||
|
||||
private PluralAttribute<? super X, ?, ?> getPluralAttribute(String name) {
|
||||
return declaredPluralAttributes.get( name );
|
||||
}
|
||||
|
||||
private void basicCollectionCheck(PluralAttribute<? super X, ?, ?> attribute, String name) {
|
||||
checkNotNull( "CollectionAttribute", attribute, name );
|
||||
if ( ! CollectionAttribute.class.isAssignableFrom( attribute.getClass() ) ) {
|
||||
throw new IllegalArgumentException( name + " is not a CollectionAttribute: " + attribute.getClass() );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@SuppressWarnings( "unchecked")
|
||||
public CollectionAttribute<X, ?> getDeclaredCollection(String name) {
|
||||
final PluralAttribute<X,?,?> attribute = declaredPluralAttributes.get( name );
|
||||
basicCollectionCheck( attribute, name );
|
||||
return ( CollectionAttribute<X, ?> ) attribute;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public SetAttribute<? super X, ?> getSet(String name) {
|
||||
PluralAttribute<? super X, ?, ?> attribute = getPluralAttribute( name );
|
||||
if ( attribute == null && getSupertype() != null ) {
|
||||
attribute = getSupertype().getPluralAttribute( name );
|
||||
}
|
||||
basicSetCheck( attribute, name );
|
||||
return (SetAttribute<? super X, ?>) attribute;
|
||||
}
|
||||
|
||||
private void basicSetCheck(PluralAttribute<? super X, ?, ?> attribute, String name) {
|
||||
checkNotNull( "SetAttribute", attribute, name );
|
||||
if ( ! SetAttribute.class.isAssignableFrom( attribute.getClass() ) ) {
|
||||
throw new IllegalArgumentException( name + " is not a SetAttribute: " + attribute.getClass() );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@SuppressWarnings( "unchecked")
|
||||
public SetAttribute<X, ?> getDeclaredSet(String name) {
|
||||
final PluralAttribute<X,?,?> attribute = declaredPluralAttributes.get( name );
|
||||
basicSetCheck( attribute, name );
|
||||
return ( SetAttribute<X, ?> ) attribute;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public ListAttribute<? super X, ?> getList(String name) {
|
||||
PluralAttribute<? super X, ?, ?> attribute = getPluralAttribute( name );
|
||||
if ( attribute == null && getSupertype() != null ) {
|
||||
attribute = getSupertype().getPluralAttribute( name );
|
||||
}
|
||||
basicListCheck( attribute, name );
|
||||
return (ListAttribute<? super X, ?>) attribute;
|
||||
}
|
||||
|
||||
private void basicListCheck(PluralAttribute<? super X, ?, ?> attribute, String name) {
|
||||
checkNotNull( "ListAttribute", attribute, name );
|
||||
if ( ! ListAttribute.class.isAssignableFrom( attribute.getClass() ) ) {
|
||||
throw new IllegalArgumentException( name + " is not a ListAttribute: " + attribute.getClass() );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public ListAttribute<X, ?> getDeclaredList(String name) {
|
||||
final PluralAttribute<X,?,?> attribute = declaredPluralAttributes.get( name );
|
||||
basicListCheck( attribute, name );
|
||||
return ( ListAttribute<X, ?> ) attribute;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public MapAttribute<? super X, ?, ?> getMap(String name) {
|
||||
PluralAttribute<? super X, ?, ?> attribute = getPluralAttribute( name );
|
||||
if ( attribute == null && getSupertype() != null ) {
|
||||
attribute = getSupertype().getPluralAttribute( name );
|
||||
}
|
||||
basicMapCheck( attribute, name );
|
||||
return (MapAttribute<? super X, ?, ?>) attribute;
|
||||
}
|
||||
|
||||
private void basicMapCheck(PluralAttribute<? super X, ?, ?> attribute, String name) {
|
||||
checkNotNull( "MapAttribute", attribute, name );
|
||||
if ( ! MapAttribute.class.isAssignableFrom( attribute.getClass() ) ) {
|
||||
throw new IllegalArgumentException( name + " is not a MapAttribute: " + attribute.getClass() );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public MapAttribute<X, ?, ?> getDeclaredMap(String name) {
|
||||
final PluralAttribute<X,?,?> attribute = declaredPluralAttributes.get( name );
|
||||
basicMapCheck( attribute, name );
|
||||
return ( MapAttribute<X,?,?> ) attribute;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public <E> CollectionAttribute<? super X, E> getCollection(String name, Class<E> elementType) {
|
||||
PluralAttribute<? super X, ?, ?> attribute = declaredPluralAttributes.get( name );
|
||||
if ( attribute == null && getSupertype() != null ) {
|
||||
attribute = getSupertype().getPluralAttribute( name );
|
||||
}
|
||||
checkCollectionElementType( attribute, name, elementType );
|
||||
return ( CollectionAttribute<? super X, E> ) attribute;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public <E> CollectionAttribute<X, E> getDeclaredCollection(String name, Class<E> elementType) {
|
||||
final PluralAttribute<X,?,?> attribute = declaredPluralAttributes.get( name );
|
||||
checkCollectionElementType( attribute, name, elementType );
|
||||
return ( CollectionAttribute<X, E> ) attribute;
|
||||
}
|
||||
|
||||
private <E> void checkCollectionElementType(PluralAttribute<?,?,?> attribute, String name, Class<E> elementType) {
|
||||
checkTypeForPluralAttributes( "CollectionAttribute", attribute, name, elementType, PluralAttribute.CollectionType.COLLECTION );
|
||||
}
|
||||
|
||||
private <E> void checkTypeForPluralAttributes(
|
||||
String attributeType,
|
||||
PluralAttribute<?,?,?> attribute,
|
||||
String name,
|
||||
Class<E> elementType,
|
||||
PluralAttribute.CollectionType collectionType) {
|
||||
if ( attribute == null
|
||||
|| ( elementType != null && !attribute.getBindableJavaType().equals( elementType ) )
|
||||
|| attribute.getCollectionType() != collectionType ) {
|
||||
throw new IllegalArgumentException(
|
||||
attributeType + " named " + name
|
||||
+ ( elementType != null ? " and of element type " + elementType : "" )
|
||||
+ " is not present"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public <E> SetAttribute<? super X, E> getSet(String name, Class<E> elementType) {
|
||||
PluralAttribute<? super X, ?, ?> attribute = declaredPluralAttributes.get( name );
|
||||
if ( attribute == null && getSupertype() != null ) {
|
||||
attribute = getSupertype().getPluralAttribute( name );
|
||||
}
|
||||
checkSetElementType( attribute, name, elementType );
|
||||
return ( SetAttribute<? super X, E> ) attribute;
|
||||
}
|
||||
|
||||
private <E> void checkSetElementType(PluralAttribute<? super X, ?, ?> attribute, String name, Class<E> elementType) {
|
||||
checkTypeForPluralAttributes( "SetAttribute", attribute, name, elementType, PluralAttribute.CollectionType.SET );
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public <E> SetAttribute<X, E> getDeclaredSet(String name, Class<E> elementType) {
|
||||
final PluralAttribute<X,?,?> attribute = declaredPluralAttributes.get( name );
|
||||
checkSetElementType( attribute, name, elementType );
|
||||
return ( SetAttribute<X, E> ) attribute;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public <E> ListAttribute<? super X, E> getList(String name, Class<E> elementType) {
|
||||
PluralAttribute<? super X, ?, ?> attribute = declaredPluralAttributes.get( name );
|
||||
if ( attribute == null && getSupertype() != null ) {
|
||||
attribute = getSupertype().getPluralAttribute( name );
|
||||
}
|
||||
checkListElementType( attribute, name, elementType );
|
||||
return ( ListAttribute<? super X, E> ) attribute;
|
||||
}
|
||||
|
||||
private <E> void checkListElementType(PluralAttribute<? super X, ?, ?> attribute, String name, Class<E> elementType) {
|
||||
checkTypeForPluralAttributes( "ListAttribute", attribute, name, elementType, PluralAttribute.CollectionType.LIST );
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public <E> ListAttribute<X, E> getDeclaredList(String name, Class<E> elementType) {
|
||||
final PluralAttribute<X,?,?> attribute = declaredPluralAttributes.get( name );
|
||||
checkListElementType( attribute, name, elementType );
|
||||
return ( ListAttribute<X, E> ) attribute;
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public <K, V> MapAttribute<? super X, K, V> getMap(String name, Class<K> keyType, Class<V> valueType) {
|
||||
PluralAttribute<? super X, ?, ?> attribute = getPluralAttribute( name );
|
||||
if ( attribute == null && getSupertype() != null ) {
|
||||
attribute = getSupertype().getPluralAttribute( name );
|
||||
}
|
||||
checkMapValueType( attribute, name, valueType );
|
||||
final MapAttribute<? super X, K, V> mapAttribute = ( MapAttribute<? super X, K, V> ) attribute;
|
||||
checkMapKeyType( mapAttribute, name, keyType );
|
||||
return mapAttribute;
|
||||
}
|
||||
|
||||
private <V> void checkMapValueType(PluralAttribute<? super X, ?, ?> attribute, String name, Class<V> valueType) {
|
||||
checkTypeForPluralAttributes( "MapAttribute", attribute, name, valueType, PluralAttribute.CollectionType.MAP);
|
||||
}
|
||||
|
||||
private <K,V> void checkMapKeyType(MapAttribute<? super X, K, V> mapAttribute, String name, Class<K> keyType) {
|
||||
if ( mapAttribute.getKeyJavaType() != keyType ) {
|
||||
throw new IllegalArgumentException( "MapAttribute named " + name + " does not support a key of type " + keyType );
|
||||
}
|
||||
}
|
||||
|
||||
public <K, V> MapAttribute<X, K, V> getDeclaredMap(String name, Class<K> keyType, Class<V> valueType) {
|
||||
final PluralAttribute<X,?,?> attribute = declaredPluralAttributes.get( name );
|
||||
checkMapValueType( attribute, name, valueType );
|
||||
final MapAttribute<X, K, V> mapAttribute = ( MapAttribute<X, K, V> ) attribute;
|
||||
checkMapKeyType( mapAttribute, name, keyType );
|
||||
return mapAttribute;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
|
||||
* third-party contributors as indicated by either @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.jpa.metamodel.internal.legacy;
|
||||
|
||||
import javax.persistence.metamodel.Type;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Defines commonality for the JPA {@link javax.persistence.metamodel.Type} hierarchy of interfaces.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public abstract class AbstractType<X> implements Type<X>, Serializable {
|
||||
private final Class<X> javaType;
|
||||
|
||||
public AbstractType(Class<X> javaType) {
|
||||
this.javaType = javaType;
|
||||
}
|
||||
|
||||
public Class<X> getJavaType() {
|
||||
return javaType;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,979 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2012, 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.jpa.metamodel.internal.legacy;
|
||||
|
||||
import javax.persistence.ManyToMany;
|
||||
import javax.persistence.OneToOne;
|
||||
import javax.persistence.metamodel.Attribute;
|
||||
import javax.persistence.metamodel.IdentifiableType;
|
||||
import javax.persistence.metamodel.PluralAttribute;
|
||||
import javax.persistence.metamodel.Type;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Member;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.TypeVariable;
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.annotations.common.AssertionFailure;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.mapping.Collection;
|
||||
import org.hibernate.mapping.Component;
|
||||
import org.hibernate.mapping.Map;
|
||||
import org.hibernate.mapping.OneToMany;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.mapping.Property;
|
||||
import org.hibernate.mapping.Value;
|
||||
import org.hibernate.tuple.entity.EntityMetamodel;
|
||||
import org.hibernate.type.ComponentType;
|
||||
import org.hibernate.type.EmbeddedComponentType;
|
||||
import org.hibernate.type.EntityType;
|
||||
|
||||
/**
|
||||
* A factory for building {@link javax.persistence.metamodel.Attribute} instances. Exposes 3 main services for building<ol>
|
||||
* <li>{@link #buildAttribute normal attributes}</li>
|
||||
* <li>{@link #buildIdAttribute id attributes}</li>
|
||||
* <li>{@link #buildVersionAttribute version attributes}</li>
|
||||
* <ol>
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
* @author Emmanuel Bernard
|
||||
*/
|
||||
public class AttributeFactory {
|
||||
|
||||
private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class,
|
||||
AttributeFactory.class.getName());
|
||||
|
||||
private final MetadataContext context;
|
||||
|
||||
public AttributeFactory(MetadataContext context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a normal attribute.
|
||||
*
|
||||
* @param ownerType The descriptor of the attribute owner (aka declarer).
|
||||
* @param property The Hibernate property descriptor for the attribute
|
||||
* @param <X> The type of the owner
|
||||
* @param <Y> The attribute type
|
||||
* @return The built attribute descriptor or null if the attribute is not part of the JPA 2 model (eg backrefs)
|
||||
*/
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public <X, Y> AttributeImplementor<X, Y> buildAttribute(AbstractManagedType<X> ownerType, Property property) {
|
||||
if ( property.isSynthetic() ) {
|
||||
// hide synthetic/virtual properties (fabricated by Hibernate) from the JPA metamodel.
|
||||
LOG.tracef(
|
||||
"Skipping synthetic property %s(%s)",
|
||||
ownerType.getJavaType().getName(),
|
||||
property.getName()
|
||||
);
|
||||
return null;
|
||||
}
|
||||
LOG.trace("Building attribute [" + ownerType.getJavaType().getName() + "." + property.getName() + "]");
|
||||
final AttributeContext<X> attributeContext = wrap( ownerType, property );
|
||||
final AttributeMetadata<X,Y> attributeMetadata =
|
||||
determineAttributeMetadata( attributeContext, NORMAL_MEMBER_RESOLVER );
|
||||
if (attributeMetadata == null) {
|
||||
return null;
|
||||
}
|
||||
if (attributeMetadata.isPlural()) {
|
||||
return buildPluralAttribute((PluralAttributeMetadata)attributeMetadata);
|
||||
}
|
||||
final SingularAttributeMetadata<X, Y> singularAttributeMetadata = (SingularAttributeMetadata<X, Y>)attributeMetadata;
|
||||
final Type<Y> metaModelType = getMetaModelType(singularAttributeMetadata.getValueContext());
|
||||
return new SingularAttributeImpl<X, Y>(
|
||||
attributeMetadata.getName(),
|
||||
attributeMetadata.getJavaType(),
|
||||
ownerType,
|
||||
attributeMetadata.getMember(),
|
||||
false,
|
||||
false,
|
||||
property.isOptional(),
|
||||
metaModelType,
|
||||
attributeMetadata.getPersistentAttributeType()
|
||||
);
|
||||
}
|
||||
|
||||
private <X> AttributeContext<X> wrap(final AbstractManagedType<X> ownerType, final Property property) {
|
||||
return new AttributeContext<X>() {
|
||||
public AbstractManagedType<X> getOwnerType() {
|
||||
return ownerType;
|
||||
}
|
||||
|
||||
public Property getPropertyMapping() {
|
||||
return property;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the identifier attribute descriptor
|
||||
*
|
||||
* @param ownerType The descriptor of the attribute owner (aka declarer).
|
||||
* @param property The Hibernate property descriptor for the identifier attribute
|
||||
* @param <X> The type of the owner
|
||||
* @param <Y> The attribute type
|
||||
* @return The built attribute descriptor
|
||||
*/
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public <X, Y> SingularAttributeImpl<X, Y> buildIdAttribute(AbstractIdentifiableType<X> ownerType, Property property) {
|
||||
LOG.trace("Building identifier attribute [" + ownerType.getJavaType().getName() + "." + property.getName() + "]");
|
||||
final AttributeContext<X> attributeContext = wrap( ownerType, property );
|
||||
final SingularAttributeMetadata<X,Y> attributeMetadata =
|
||||
(SingularAttributeMetadata<X, Y>) determineAttributeMetadata( attributeContext, IDENTIFIER_MEMBER_RESOLVER );
|
||||
final Type<Y> metaModelType = getMetaModelType( attributeMetadata.getValueContext() );
|
||||
return new SingularAttributeImpl.Identifier(
|
||||
property.getName(),
|
||||
attributeMetadata.getJavaType(),
|
||||
ownerType,
|
||||
attributeMetadata.getMember(),
|
||||
metaModelType,
|
||||
attributeMetadata.getPersistentAttributeType()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the version attribute descriptor
|
||||
*
|
||||
* @param ownerType The descriptor of the attribute owner (aka declarer).
|
||||
* @param property The Hibernate property descriptor for the version attribute
|
||||
* @param <X> The type of the owner
|
||||
* @param <Y> The attribute type
|
||||
* @return The built attribute descriptor
|
||||
*/
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public <X, Y> SingularAttributeImpl<X, Y> buildVersionAttribute(AbstractIdentifiableType<X> ownerType, Property property) {
|
||||
LOG.trace("Building version attribute [ownerType.getJavaType().getName()" + "." + "property.getName()]");
|
||||
final AttributeContext<X> attributeContext = wrap( ownerType, property );
|
||||
final SingularAttributeMetadata<X,Y> attributeMetadata =
|
||||
(SingularAttributeMetadata<X, Y>) determineAttributeMetadata( attributeContext, VERSION_MEMBER_RESOLVER );
|
||||
final Type<Y> metaModelType = getMetaModelType( attributeMetadata.getValueContext() );
|
||||
return new SingularAttributeImpl.Version(
|
||||
property.getName(),
|
||||
attributeMetadata.getJavaType(),
|
||||
ownerType,
|
||||
attributeMetadata.getMember(),
|
||||
metaModelType,
|
||||
attributeMetadata.getPersistentAttributeType()
|
||||
);
|
||||
}
|
||||
|
||||
@SuppressWarnings( "unchecked" )
|
||||
private <X, Y, E, K> AttributeImplementor<X, Y> buildPluralAttribute(PluralAttributeMetadata<X,Y,E> attributeMetadata) {
|
||||
final Type<E> elementType = getMetaModelType( attributeMetadata.getElementValueContext() );
|
||||
if ( java.util.Map.class.isAssignableFrom( attributeMetadata.getJavaType() ) ) {
|
||||
final Type<K> keyType = getMetaModelType( attributeMetadata.getMapKeyValueContext() );
|
||||
return PluralAttributeImpl.create( attributeMetadata.getOwnerType(), elementType, attributeMetadata.getJavaType(), keyType )
|
||||
.member( attributeMetadata.getMember() )
|
||||
.property( attributeMetadata.getPropertyMapping() )
|
||||
.persistentAttributeType( attributeMetadata.getPersistentAttributeType() )
|
||||
.build();
|
||||
}
|
||||
return PluralAttributeImpl.create(attributeMetadata.getOwnerType(), elementType, attributeMetadata.getJavaType(), null).member(attributeMetadata.getMember()).property(attributeMetadata.getPropertyMapping()).persistentAttributeType(attributeMetadata.getPersistentAttributeType()).build();
|
||||
}
|
||||
|
||||
@SuppressWarnings( "unchecked" )
|
||||
private <Y> Type<Y> getMetaModelType(ValueContext typeContext) {
|
||||
switch ( typeContext.getValueClassification() ) {
|
||||
case BASIC: {
|
||||
return new BasicTypeImpl<Y>(
|
||||
typeContext.getBindableType(),
|
||||
Type.PersistenceType.BASIC
|
||||
);
|
||||
}
|
||||
case ENTITY: {
|
||||
final EntityType type = (EntityType) typeContext.getValue().getType();
|
||||
return (Type<Y>) context.locateEntityType( type.getAssociatedEntityName() );
|
||||
}
|
||||
case EMBEDDABLE: {
|
||||
final Component component = (Component) typeContext.getValue();
|
||||
final EmbeddableTypeImpl<Y> embeddableType = new EmbeddableTypeImpl<Y>(
|
||||
typeContext.getBindableType(),
|
||||
typeContext.getAttributeMetadata().getOwnerType(),
|
||||
(ComponentType) typeContext.getValue().getType()
|
||||
);
|
||||
context.registerEmbeddedableType( embeddableType );
|
||||
final Iterator<Property> subProperties = component.getPropertyIterator();
|
||||
while ( subProperties.hasNext() ) {
|
||||
final Property property = subProperties.next();
|
||||
final AttributeImplementor<Y, Object> attribute = buildAttribute( embeddableType, property );
|
||||
if ( attribute != null ) {
|
||||
embeddableType.getBuilder().addAttribute( attribute );
|
||||
}
|
||||
}
|
||||
embeddableType.lock();
|
||||
return embeddableType;
|
||||
}
|
||||
default: {
|
||||
throw new AssertionFailure( "Unknown type : " + typeContext.getValueClassification() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private EntityMetamodel getDeclarerEntityMetamodel(IdentifiableType<?> ownerType) {
|
||||
final Type.PersistenceType persistenceType = ownerType.getPersistenceType();
|
||||
if ( persistenceType == Type.PersistenceType.ENTITY) {
|
||||
return context.getSessionFactory()
|
||||
.getEntityPersister( ownerType.getJavaType().getName() )
|
||||
.getEntityMetamodel();
|
||||
}
|
||||
else if ( persistenceType == Type.PersistenceType.MAPPED_SUPERCLASS) {
|
||||
PersistentClass persistentClass =
|
||||
context.getPersistentClassHostingProperties( (MappedSuperclassTypeImpl<?>) ownerType );
|
||||
return context.getSessionFactory()
|
||||
.getEntityPersister( persistentClass.getClassName() )
|
||||
.getEntityMetamodel();
|
||||
}
|
||||
else {
|
||||
throw new AssertionFailure( "Cannot get the metamodel for PersistenceType: " + persistenceType );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A contract for defining the meta information about a {@link org.hibernate.mapping.Value}
|
||||
*/
|
||||
private interface ValueContext {
|
||||
/**
|
||||
* Enum of the simplified types a value might be. These relate more to the Hibernate classification
|
||||
* then the JPA classification
|
||||
*/
|
||||
enum ValueClassification {
|
||||
EMBEDDABLE,
|
||||
ENTITY,
|
||||
BASIC
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the value itself
|
||||
*
|
||||
* @return The value
|
||||
*/
|
||||
public Value getValue();
|
||||
|
||||
public Class getBindableType();
|
||||
|
||||
/**
|
||||
* Retrieve the simplified value classification
|
||||
*
|
||||
* @return The value type
|
||||
*/
|
||||
public ValueClassification getValueClassification();
|
||||
|
||||
/**
|
||||
* Retrieve the metadata about the attribute from which this value comes
|
||||
*
|
||||
* @return The "containing" attribute metadata.
|
||||
*/
|
||||
public AttributeMetadata getAttributeMetadata();
|
||||
}
|
||||
|
||||
/**
|
||||
* Basic contract for describing an attribute. The "description" is partially in terms
|
||||
* of JPA ({@link #getPersistentAttributeType} and {@link #getOwnerType}), partially in
|
||||
* terms of Hibernate ({@link #getPropertyMapping}) and partially just in terms of the java
|
||||
* model itself ({@link #getName}, {@link #getMember} and {@link #getJavaType}).
|
||||
*
|
||||
* @param <X> The attribute owner type
|
||||
* @param <Y> The attribute type.
|
||||
*/
|
||||
private interface AttributeMetadata<X,Y> {
|
||||
/**
|
||||
* Retrieve the name of the attribute
|
||||
*
|
||||
* @return The attribute name
|
||||
*/
|
||||
public String getName();
|
||||
|
||||
/**
|
||||
* Retrieve the member defining the attribute
|
||||
*
|
||||
* @return The attribute member
|
||||
*/
|
||||
public Member getMember();
|
||||
|
||||
/**
|
||||
* Retrieve the attribute java type.
|
||||
*
|
||||
* @return The java type of the attribute.
|
||||
*/
|
||||
public Class<Y> getJavaType();
|
||||
|
||||
/**
|
||||
* Get the JPA attribute type classification for this attribute.
|
||||
*
|
||||
* @return The JPA attribute type classification
|
||||
*/
|
||||
public Attribute.PersistentAttributeType getPersistentAttributeType();
|
||||
|
||||
/**
|
||||
* Retrieve the attribute owner's metamodel information
|
||||
*
|
||||
* @return The metamodel information for the attribute owner
|
||||
*/
|
||||
public AbstractManagedType<X> getOwnerType();
|
||||
|
||||
/**
|
||||
* Retrieve the Hibernate property mapping related to this attribute.
|
||||
*
|
||||
* @return The Hibernate property mapping
|
||||
*/
|
||||
public Property getPropertyMapping();
|
||||
|
||||
/**
|
||||
* Is the attribute plural (a collection)?
|
||||
*
|
||||
* @return True if it is plural, false otherwise.
|
||||
*/
|
||||
public boolean isPlural();
|
||||
}
|
||||
|
||||
/**
|
||||
* Attribute metadata contract for a non-plural attribute.
|
||||
* @param <X> The owner type
|
||||
* @param <Y> The attribute type
|
||||
*/
|
||||
private interface SingularAttributeMetadata<X,Y> extends AttributeMetadata<X,Y> {
|
||||
/**
|
||||
* Retrieve the value context for this attribute
|
||||
*
|
||||
* @return The attributes value context
|
||||
*/
|
||||
public ValueContext getValueContext();
|
||||
}
|
||||
|
||||
/**
|
||||
* Attribute metadata contract for a plural attribute.
|
||||
* @param <X> The owner type
|
||||
* @param <Y> The attribute type (the collection type)
|
||||
* @param <E> The collection element type
|
||||
*/
|
||||
private interface PluralAttributeMetadata<X,Y,E> extends AttributeMetadata<X,Y> {
|
||||
/**
|
||||
* Retrieve the JPA collection type classification for this attribute
|
||||
*
|
||||
* @return The JPA collection type classification
|
||||
*/
|
||||
public PluralAttribute.CollectionType getAttributeCollectionType();
|
||||
|
||||
/**
|
||||
* Retrieve the value context for the collection's elements.
|
||||
*
|
||||
* @return The value context for the collection's elements.
|
||||
*/
|
||||
public ValueContext getElementValueContext();
|
||||
|
||||
/**
|
||||
* Retrieve the value context for the collection's keys (if a map, null otherwise).
|
||||
*
|
||||
* @return The value context for the collection's keys (if a map, null otherwise).
|
||||
*/
|
||||
public ValueContext getMapKeyValueContext();
|
||||
}
|
||||
|
||||
/**
|
||||
* Bundle's a Hibernate property mapping together with the JPA metamodel information
|
||||
* of the attribute owner.
|
||||
*
|
||||
* @param <X> The owner type.
|
||||
*/
|
||||
private interface AttributeContext<X> {
|
||||
/**
|
||||
* Retrieve the attribute owner.
|
||||
*
|
||||
* @return The owner.
|
||||
*/
|
||||
public AbstractManagedType<X> getOwnerType();
|
||||
|
||||
/**
|
||||
* Retrieve the Hibernate property mapping.
|
||||
*
|
||||
* @return The Hibvernate property mapping.
|
||||
*/
|
||||
public Property getPropertyMapping();
|
||||
}
|
||||
|
||||
/**
|
||||
* Contract for how we resolve the {@link java.lang.reflect.Member} for a give attribute context.
|
||||
*/
|
||||
private interface MemberResolver {
|
||||
public Member resolveMember(AttributeContext attributeContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* Here is most of the nuts and bolts of this factory, where we interpret the known JPA metadata
|
||||
* against the known Hibernate metadata and build a descriptor for the attribute.
|
||||
*
|
||||
* @param attributeContext The attribute to be described
|
||||
* @param memberResolver Strategy for how to resolve the member defining the attribute.
|
||||
* @param <X> The owner type
|
||||
* @param <Y> The attribute type
|
||||
*
|
||||
* @return The attribute description
|
||||
*/
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
private <X,Y> AttributeMetadata<X,Y> determineAttributeMetadata(
|
||||
AttributeContext<X> attributeContext,
|
||||
MemberResolver memberResolver) {
|
||||
LOG.trace("Starting attribute metadata determination [" + attributeContext.getPropertyMapping().getName() + "]");
|
||||
final Member member = memberResolver.resolveMember( attributeContext );
|
||||
LOG.trace(" Determined member [" + member + "]");
|
||||
|
||||
final Value value = attributeContext.getPropertyMapping().getValue();
|
||||
final org.hibernate.type.Type type = value.getType();
|
||||
LOG.trace(" Determined type [name=" + type.getName() + ", class=" + type.getClass().getName() + "]");
|
||||
|
||||
if ( type.isAnyType() ) {
|
||||
// ANY mappings are currently not supported in the JPA metamodel; see HHH-6589
|
||||
if ( context.isIgnoreUnsupported() ) {
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
throw new UnsupportedOperationException( "ANY not supported" );
|
||||
}
|
||||
}
|
||||
else if ( type.isAssociationType() ) {
|
||||
// collection or entity
|
||||
if ( type.isEntityType() ) {
|
||||
// entity
|
||||
return new SingularAttributeMetadataImpl<X,Y>(
|
||||
attributeContext.getPropertyMapping(),
|
||||
attributeContext.getOwnerType(),
|
||||
member,
|
||||
determineSingularAssociationAttributeType( member )
|
||||
);
|
||||
}
|
||||
// collection
|
||||
if (value instanceof Collection) {
|
||||
final Collection collValue = (Collection)value;
|
||||
final Value elementValue = collValue.getElement();
|
||||
final org.hibernate.type.Type elementType = elementValue.getType();
|
||||
|
||||
// First, determine the type of the elements and use that to help determine the
|
||||
// collection type)
|
||||
final Attribute.PersistentAttributeType elementPersistentAttributeType;
|
||||
final Attribute.PersistentAttributeType persistentAttributeType;
|
||||
if (elementType.isAnyType()) {
|
||||
throw new UnsupportedOperationException("collection of any not supported yet");
|
||||
}
|
||||
final boolean isManyToMany = isManyToMany(member);
|
||||
if (elementValue instanceof Component) {
|
||||
elementPersistentAttributeType = Attribute.PersistentAttributeType.EMBEDDED;
|
||||
persistentAttributeType = Attribute.PersistentAttributeType.ELEMENT_COLLECTION;
|
||||
} else if (elementType.isAssociationType()) {
|
||||
elementPersistentAttributeType = isManyToMany ? Attribute.PersistentAttributeType.MANY_TO_MANY : Attribute.PersistentAttributeType.ONE_TO_MANY;
|
||||
persistentAttributeType = elementPersistentAttributeType;
|
||||
} else {
|
||||
elementPersistentAttributeType = Attribute.PersistentAttributeType.BASIC;
|
||||
persistentAttributeType = Attribute.PersistentAttributeType.ELEMENT_COLLECTION;
|
||||
}
|
||||
|
||||
final Attribute.PersistentAttributeType keyPersistentAttributeType;
|
||||
|
||||
// Finally, we determine the type of the map key (if needed)
|
||||
if (value instanceof Map) {
|
||||
final Value keyValue = ((Map)value).getIndex();
|
||||
final org.hibernate.type.Type keyType = keyValue.getType();
|
||||
|
||||
if (keyType.isAnyType()) throw new UnsupportedOperationException("collection of any not supported yet");
|
||||
if (keyValue instanceof Component) keyPersistentAttributeType = Attribute.PersistentAttributeType.EMBEDDED;
|
||||
else if (keyType.isAssociationType()) keyPersistentAttributeType = Attribute.PersistentAttributeType.MANY_TO_ONE;
|
||||
else keyPersistentAttributeType = Attribute.PersistentAttributeType.BASIC;
|
||||
} else keyPersistentAttributeType = null;
|
||||
return new PluralAttributeMetadataImpl(attributeContext.getPropertyMapping(), attributeContext.getOwnerType(),
|
||||
member, persistentAttributeType, elementPersistentAttributeType,
|
||||
keyPersistentAttributeType);
|
||||
} else if (value instanceof OneToMany) {
|
||||
// TODO : is this even possible??? Really OneToMany should be describing the
|
||||
// element value within a o.h.mapping.Collection (see logic branch above)
|
||||
throw new IllegalArgumentException("HUH???");
|
||||
// final boolean isManyToMany = isManyToMany( member );
|
||||
// //one to many with FK => entity
|
||||
// return new PluralAttributeMetadataImpl(
|
||||
// attributeContext.getPropertyMapping(),
|
||||
// attributeContext.getOwnerType(),
|
||||
// member,
|
||||
// isManyToMany
|
||||
// ? Attribute.PersistentAttributeType.MANY_TO_MANY
|
||||
// : Attribute.PersistentAttributeType.ONE_TO_MANY
|
||||
// value,
|
||||
// AttributeContext.TypeStatus.ENTITY,
|
||||
// Attribute.PersistentAttributeType.ONE_TO_MANY,
|
||||
// null, null, null
|
||||
// );
|
||||
}
|
||||
}
|
||||
else if ( attributeContext.getPropertyMapping().isComposite() ) {
|
||||
// component
|
||||
return new SingularAttributeMetadataImpl<X,Y>(
|
||||
attributeContext.getPropertyMapping(),
|
||||
attributeContext.getOwnerType(),
|
||||
member,
|
||||
Attribute.PersistentAttributeType.EMBEDDED
|
||||
);
|
||||
}
|
||||
else {
|
||||
// basic type
|
||||
return new SingularAttributeMetadataImpl<X,Y>(
|
||||
attributeContext.getPropertyMapping(),
|
||||
attributeContext.getOwnerType(),
|
||||
member,
|
||||
Attribute.PersistentAttributeType.BASIC
|
||||
);
|
||||
}
|
||||
throw new UnsupportedOperationException( "oops, we are missing something: " + attributeContext.getPropertyMapping() );
|
||||
}
|
||||
|
||||
public static Attribute.PersistentAttributeType determineSingularAssociationAttributeType(Member member) {
|
||||
if ( Field.class.isInstance( member ) ) {
|
||||
return ( (Field) member ).getAnnotation( OneToOne.class ) != null
|
||||
? Attribute.PersistentAttributeType.ONE_TO_ONE
|
||||
: Attribute.PersistentAttributeType.MANY_TO_ONE;
|
||||
}
|
||||
else {
|
||||
return ( (Method) member ).getAnnotation( OneToOne.class ) != null
|
||||
? Attribute.PersistentAttributeType.ONE_TO_ONE
|
||||
: Attribute.PersistentAttributeType.MANY_TO_ONE;
|
||||
}
|
||||
}
|
||||
|
||||
private abstract class BaseAttributeMetadata<X,Y> implements AttributeMetadata<X,Y> {
|
||||
private final Property propertyMapping;
|
||||
private final AbstractManagedType<X> ownerType;
|
||||
private final Member member;
|
||||
private final Class<Y> javaType;
|
||||
private final Attribute.PersistentAttributeType persistentAttributeType;
|
||||
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
protected BaseAttributeMetadata(
|
||||
Property propertyMapping,
|
||||
AbstractManagedType<X> ownerType,
|
||||
Member member,
|
||||
Attribute.PersistentAttributeType persistentAttributeType) {
|
||||
this.propertyMapping = propertyMapping;
|
||||
this.ownerType = ownerType;
|
||||
this.member = member;
|
||||
this.persistentAttributeType = persistentAttributeType;
|
||||
final Class declaredType;
|
||||
// we can support method or field members here. Is there really any other valid type?
|
||||
if ( Field.class.isInstance( member ) ) {
|
||||
declaredType = ( (Field) member ).getType();
|
||||
}
|
||||
else if ( Method.class.isInstance( member ) ) {
|
||||
declaredType = ( (Method) member ).getReturnType();
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException( "Cannot determine java-type from given member [" + member + "]" );
|
||||
}
|
||||
this.javaType = accountForPrimitiveTypes( declaredType );
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return propertyMapping.getName();
|
||||
}
|
||||
|
||||
public Member getMember() {
|
||||
return member;
|
||||
}
|
||||
|
||||
public String getMemberDescription() {
|
||||
return determineMemberDescription( getMember() );
|
||||
}
|
||||
|
||||
public String determineMemberDescription(Member member) {
|
||||
return member.getDeclaringClass().getName() + '#' + member.getName();
|
||||
}
|
||||
|
||||
public Class<Y> getJavaType() {
|
||||
return javaType;
|
||||
}
|
||||
|
||||
public Attribute.PersistentAttributeType getPersistentAttributeType() {
|
||||
return persistentAttributeType;
|
||||
}
|
||||
|
||||
public AbstractManagedType<X> getOwnerType() {
|
||||
return ownerType;
|
||||
}
|
||||
|
||||
public boolean isPlural() {
|
||||
return propertyMapping.getType().isCollectionType();
|
||||
}
|
||||
|
||||
public Property getPropertyMapping() {
|
||||
return propertyMapping;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
protected <Y> Class<Y> accountForPrimitiveTypes(Class<Y> declaredType) {
|
||||
// if ( !declaredType.isPrimitive() ) {
|
||||
// return declaredType;
|
||||
// }
|
||||
//
|
||||
// if ( Boolean.TYPE.equals( declaredType ) ) {
|
||||
// return (Class<Y>) Boolean.class;
|
||||
// }
|
||||
// if ( Character.TYPE.equals( declaredType ) ) {
|
||||
// return (Class<Y>) Character.class;
|
||||
// }
|
||||
// if( Byte.TYPE.equals( declaredType ) ) {
|
||||
// return (Class<Y>) Byte.class;
|
||||
// }
|
||||
// if ( Short.TYPE.equals( declaredType ) ) {
|
||||
// return (Class<Y>) Short.class;
|
||||
// }
|
||||
// if ( Integer.TYPE.equals( declaredType ) ) {
|
||||
// return (Class<Y>) Integer.class;
|
||||
// }
|
||||
// if ( Long.TYPE.equals( declaredType ) ) {
|
||||
// return (Class<Y>) Long.class;
|
||||
// }
|
||||
// if ( Float.TYPE.equals( declaredType ) ) {
|
||||
// return (Class<Y>) Float.class;
|
||||
// }
|
||||
// if ( Double.TYPE.equals( declaredType ) ) {
|
||||
// return (Class<Y>) Double.class;
|
||||
// }
|
||||
//
|
||||
// throw new IllegalArgumentException( "Unexpected type [" + declaredType + "]" );
|
||||
// if the field is defined as int, return int not Integer...
|
||||
return declaredType;
|
||||
}
|
||||
|
||||
private class SingularAttributeMetadataImpl<X,Y>
|
||||
extends BaseAttributeMetadata<X,Y>
|
||||
implements SingularAttributeMetadata<X,Y> {
|
||||
private final ValueContext valueContext;
|
||||
|
||||
private SingularAttributeMetadataImpl(
|
||||
Property propertyMapping,
|
||||
AbstractManagedType<X> ownerType,
|
||||
Member member,
|
||||
Attribute.PersistentAttributeType persistentAttributeType) {
|
||||
super( propertyMapping, ownerType, member, persistentAttributeType );
|
||||
valueContext = new ValueContext() {
|
||||
public Value getValue() {
|
||||
return getPropertyMapping().getValue();
|
||||
}
|
||||
|
||||
public Class getBindableType() {
|
||||
return getAttributeMetadata().getJavaType();
|
||||
}
|
||||
|
||||
public ValueClassification getValueClassification() {
|
||||
switch ( getPersistentAttributeType() ) {
|
||||
case EMBEDDED: {
|
||||
return ValueClassification.EMBEDDABLE;
|
||||
}
|
||||
case BASIC: {
|
||||
return ValueClassification.BASIC;
|
||||
}
|
||||
default: {
|
||||
return ValueClassification.ENTITY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public AttributeMetadata getAttributeMetadata() {
|
||||
return SingularAttributeMetadataImpl.this;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public ValueContext getValueContext() {
|
||||
return valueContext;
|
||||
}
|
||||
}
|
||||
|
||||
private class PluralAttributeMetadataImpl<X,Y,E>
|
||||
extends BaseAttributeMetadata<X,Y>
|
||||
implements PluralAttributeMetadata<X,Y,E> {
|
||||
private final PluralAttribute.CollectionType attributeCollectionType;
|
||||
private final Attribute.PersistentAttributeType elementPersistentAttributeType;
|
||||
private final Attribute.PersistentAttributeType keyPersistentAttributeType;
|
||||
private final Class elementJavaType;
|
||||
private final Class keyJavaType;
|
||||
private final ValueContext elementValueContext;
|
||||
private final ValueContext keyValueContext;
|
||||
|
||||
private PluralAttributeMetadataImpl(
|
||||
Property propertyMapping,
|
||||
AbstractManagedType<X> ownerType,
|
||||
Member member,
|
||||
Attribute.PersistentAttributeType persistentAttributeType,
|
||||
Attribute.PersistentAttributeType elementPersistentAttributeType,
|
||||
Attribute.PersistentAttributeType keyPersistentAttributeType) {
|
||||
super( propertyMapping, ownerType, member, persistentAttributeType );
|
||||
this.attributeCollectionType = determineCollectionType( getJavaType() );
|
||||
this.elementPersistentAttributeType = elementPersistentAttributeType;
|
||||
this.keyPersistentAttributeType = keyPersistentAttributeType;
|
||||
|
||||
ParameterizedType signatureType = getSignatureType( member );
|
||||
if ( keyPersistentAttributeType == null ) {
|
||||
elementJavaType = signatureType != null ?
|
||||
getClassFromGenericArgument( signatureType.getActualTypeArguments()[0] ) :
|
||||
Object.class; //FIXME and honor targetEntity?
|
||||
keyJavaType = null;
|
||||
}
|
||||
else {
|
||||
keyJavaType = signatureType != null ?
|
||||
getClassFromGenericArgument( signatureType.getActualTypeArguments()[0] ) :
|
||||
Object.class; //FIXME and honor targetEntity?
|
||||
elementJavaType = signatureType != null ?
|
||||
getClassFromGenericArgument( signatureType.getActualTypeArguments()[1] ) :
|
||||
Object.class; //FIXME and honor targetEntity?
|
||||
}
|
||||
|
||||
this.elementValueContext = new ValueContext() {
|
||||
public Value getValue() {
|
||||
return ( (Collection) getPropertyMapping().getValue() ).getElement();
|
||||
}
|
||||
|
||||
public Class getBindableType() {
|
||||
return elementJavaType;
|
||||
}
|
||||
|
||||
public ValueClassification getValueClassification() {
|
||||
switch ( PluralAttributeMetadataImpl.this.elementPersistentAttributeType ) {
|
||||
case EMBEDDED: {
|
||||
return ValueClassification.EMBEDDABLE;
|
||||
}
|
||||
case BASIC: {
|
||||
return ValueClassification.BASIC;
|
||||
}
|
||||
default: {
|
||||
return ValueClassification.ENTITY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public AttributeMetadata getAttributeMetadata() {
|
||||
return PluralAttributeMetadataImpl.this;
|
||||
}
|
||||
};
|
||||
|
||||
// interpret the key, if one
|
||||
if ( keyPersistentAttributeType != null ) {
|
||||
this.keyValueContext = new ValueContext() {
|
||||
public Value getValue() {
|
||||
return ( (Map) getPropertyMapping().getValue() ).getIndex();
|
||||
}
|
||||
|
||||
public Class getBindableType() {
|
||||
return keyJavaType;
|
||||
}
|
||||
|
||||
public ValueClassification getValueClassification() {
|
||||
switch ( PluralAttributeMetadataImpl.this.keyPersistentAttributeType ) {
|
||||
case EMBEDDED: {
|
||||
return ValueClassification.EMBEDDABLE;
|
||||
}
|
||||
case BASIC: {
|
||||
return ValueClassification.BASIC;
|
||||
}
|
||||
default: {
|
||||
return ValueClassification.ENTITY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public AttributeMetadata getAttributeMetadata() {
|
||||
return PluralAttributeMetadataImpl.this;
|
||||
}
|
||||
};
|
||||
}
|
||||
else {
|
||||
keyValueContext = null;
|
||||
}
|
||||
}
|
||||
|
||||
private Class<?> getClassFromGenericArgument(java.lang.reflect.Type type) {
|
||||
if ( type instanceof Class ) {
|
||||
return (Class) type;
|
||||
}
|
||||
else if ( type instanceof TypeVariable ) {
|
||||
final java.lang.reflect.Type upperBound = ( ( TypeVariable ) type ).getBounds()[0];
|
||||
return getClassFromGenericArgument( upperBound );
|
||||
}
|
||||
else if ( type instanceof ParameterizedType ) {
|
||||
final java.lang.reflect.Type rawType = ( (ParameterizedType) type ).getRawType();
|
||||
return getClassFromGenericArgument( rawType );
|
||||
}
|
||||
else {
|
||||
throw new AssertionFailure(
|
||||
"Fail to process type argument in a generic declaration. Member : " + getMemberDescription()
|
||||
+ " Type: " + type.getClass()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public ValueContext getElementValueContext() {
|
||||
return elementValueContext;
|
||||
}
|
||||
|
||||
public PluralAttribute.CollectionType getAttributeCollectionType() {
|
||||
return attributeCollectionType;
|
||||
}
|
||||
|
||||
public ValueContext getMapKeyValueContext() {
|
||||
return keyValueContext;
|
||||
}
|
||||
}
|
||||
|
||||
public static ParameterizedType getSignatureType(Member member) {
|
||||
final java.lang.reflect.Type type = Field.class.isInstance( member )
|
||||
? ( ( Field ) member ).getGenericType()
|
||||
: ( ( Method ) member ).getGenericReturnType();
|
||||
//this is a raw type
|
||||
if ( type instanceof Class ) return null;
|
||||
return (ParameterizedType) type;
|
||||
}
|
||||
|
||||
public static PluralAttribute.CollectionType determineCollectionType(Class javaType) {
|
||||
if ( java.util.List.class.isAssignableFrom( javaType ) ) {
|
||||
return PluralAttribute.CollectionType.LIST;
|
||||
}
|
||||
else if ( java.util.Set.class.isAssignableFrom( javaType ) ) {
|
||||
return PluralAttribute.CollectionType.SET;
|
||||
}
|
||||
else if ( java.util.Map.class.isAssignableFrom( javaType ) ) {
|
||||
return PluralAttribute.CollectionType.MAP;
|
||||
}
|
||||
else if ( java.util.Collection.class.isAssignableFrom( javaType ) ) {
|
||||
return PluralAttribute.CollectionType.COLLECTION;
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException( "Expecting collection type [" + javaType.getName() + "]" );
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isManyToMany(Member member) {
|
||||
return Field.class.isInstance( member )
|
||||
? ( (Field) member ).getAnnotation( ManyToMany.class ) != null
|
||||
: ( (Method) member ).getAnnotation( ManyToMany.class ) != null;
|
||||
}
|
||||
|
||||
private final MemberResolver EMBEDDED_MEMBER_RESOLVER = new MemberResolver() {
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Member resolveMember(AttributeContext attributeContext) {
|
||||
final EmbeddableTypeImpl embeddableType = ( EmbeddableTypeImpl<?> ) attributeContext.getOwnerType();
|
||||
final String attributeName = attributeContext.getPropertyMapping().getName();
|
||||
return embeddableType.getHibernateType()
|
||||
.getComponentTuplizer()
|
||||
.getGetter( embeddableType.getHibernateType().getPropertyIndex( attributeName ) )
|
||||
.getMember();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
private final MemberResolver VIRTUAL_IDENTIFIER_MEMBER_RESOLVER = new MemberResolver() {
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Member resolveMember(AttributeContext attributeContext) {
|
||||
final IdentifiableType identifiableType = (IdentifiableType) attributeContext.getOwnerType();
|
||||
final EntityMetamodel entityMetamodel = getDeclarerEntityMetamodel( identifiableType );
|
||||
if ( ! entityMetamodel.getIdentifierProperty().isVirtual() ) {
|
||||
throw new IllegalArgumentException( "expecting IdClass mapping" );
|
||||
}
|
||||
org.hibernate.type.Type type = entityMetamodel.getIdentifierProperty().getType();
|
||||
if ( ! EmbeddedComponentType.class.isInstance( type ) ) {
|
||||
throw new IllegalArgumentException( "expecting IdClass mapping" );
|
||||
}
|
||||
|
||||
final EmbeddedComponentType componentType = (EmbeddedComponentType) type;
|
||||
final String attributeName = attributeContext.getPropertyMapping().getName();
|
||||
return componentType.getComponentTuplizer()
|
||||
.getGetter( componentType.getPropertyIndex( attributeName ) )
|
||||
.getMember();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* A {@link java.lang.reflect.Member} resolver for normal attributes.
|
||||
*/
|
||||
private final MemberResolver NORMAL_MEMBER_RESOLVER = new MemberResolver() {
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Member resolveMember(AttributeContext attributeContext) {
|
||||
final AbstractManagedType ownerType = attributeContext.getOwnerType();
|
||||
final Property property = attributeContext.getPropertyMapping();
|
||||
final Type.PersistenceType persistenceType = ownerType.getPersistenceType();
|
||||
if ( Type.PersistenceType.EMBEDDABLE == persistenceType ) {
|
||||
return EMBEDDED_MEMBER_RESOLVER.resolveMember( attributeContext );
|
||||
}
|
||||
else if ( Type.PersistenceType.ENTITY == persistenceType
|
||||
|| Type.PersistenceType.MAPPED_SUPERCLASS == persistenceType ) {
|
||||
final IdentifiableType identifiableType = (IdentifiableType) ownerType;
|
||||
final EntityMetamodel entityMetamodel = getDeclarerEntityMetamodel( identifiableType );
|
||||
final String propertyName = property.getName();
|
||||
final Integer index = entityMetamodel.getPropertyIndexOrNull( propertyName );
|
||||
if ( index == null ) {
|
||||
// just like in #determineIdentifierJavaMember , this *should* indicate we have an IdClass mapping
|
||||
return VIRTUAL_IDENTIFIER_MEMBER_RESOLVER.resolveMember( attributeContext );
|
||||
}
|
||||
else {
|
||||
return entityMetamodel.getTuplizer()
|
||||
.getGetter( index )
|
||||
.getMember();
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException( "Unexpected owner type : " + persistenceType );
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private final MemberResolver IDENTIFIER_MEMBER_RESOLVER = new MemberResolver() {
|
||||
public Member resolveMember(AttributeContext attributeContext) {
|
||||
final IdentifiableType identifiableType = (IdentifiableType) attributeContext.getOwnerType();
|
||||
final EntityMetamodel entityMetamodel = getDeclarerEntityMetamodel( identifiableType );
|
||||
if ( ! attributeContext.getPropertyMapping().getName()
|
||||
.equals( entityMetamodel.getIdentifierProperty().getName() ) ) {
|
||||
// this *should* indicate processing part of an IdClass...
|
||||
return VIRTUAL_IDENTIFIER_MEMBER_RESOLVER.resolveMember( attributeContext );
|
||||
}
|
||||
return entityMetamodel.getTuplizer().getIdentifierGetter().getMember();
|
||||
}
|
||||
};
|
||||
|
||||
private final MemberResolver VERSION_MEMBER_RESOLVER = new MemberResolver() {
|
||||
public Member resolveMember(AttributeContext attributeContext) {
|
||||
final IdentifiableType identifiableType = (IdentifiableType) attributeContext.getOwnerType();
|
||||
final EntityMetamodel entityMetamodel = getDeclarerEntityMetamodel( identifiableType );
|
||||
final String versionPropertyName = attributeContext.getPropertyMapping().getName();
|
||||
if ( ! versionPropertyName.equals( entityMetamodel.getVersionProperty().getName() ) ) {
|
||||
// this should never happen, but to be safe...
|
||||
throw new IllegalArgumentException( "Given property did not match declared version property" );
|
||||
}
|
||||
return entityMetamodel.getTuplizer().getVersionGetter().getMember();
|
||||
}
|
||||
};
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
|
||||
* third-party contributors as indicated by either @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.jpa.metamodel.internal.legacy;
|
||||
import javax.persistence.metamodel.Attribute;
|
||||
|
||||
/**
|
||||
* TODO : javadoc
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface AttributeImplementor<X, Y> extends Attribute<X, Y> {
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright (c) 2009, Red Hat Middleware LLC 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 Middleware LLC.
|
||||
*
|
||||
* 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.jpa.metamodel.internal.legacy;
|
||||
|
||||
import javax.persistence.metamodel.BasicType;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author Emmanuel Bernard
|
||||
*/
|
||||
public class BasicTypeImpl<X> implements BasicType<X>, Serializable {
|
||||
private final Class<X> clazz;
|
||||
private PersistenceType persistenceType;
|
||||
|
||||
public PersistenceType getPersistenceType() {
|
||||
return persistenceType;
|
||||
}
|
||||
|
||||
public Class<X> getJavaType() {
|
||||
return clazz;
|
||||
}
|
||||
|
||||
public BasicTypeImpl(Class<X> clazz, PersistenceType persistenceType) {
|
||||
this.clazz = clazz;
|
||||
this.persistenceType = persistenceType;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright (c) 2009, Red Hat Middleware LLC 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 Middleware LLC.
|
||||
*
|
||||
* 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.jpa.metamodel.internal.legacy;
|
||||
|
||||
import javax.persistence.metamodel.EmbeddableType;
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.hibernate.type.ComponentType;
|
||||
|
||||
/**
|
||||
* @author Emmanuel Bernard
|
||||
*/
|
||||
public class EmbeddableTypeImpl<X>
|
||||
extends AbstractManagedType<X>
|
||||
implements EmbeddableType<X>, Serializable {
|
||||
|
||||
private final AbstractManagedType parent;
|
||||
private final ComponentType hibernateType;
|
||||
|
||||
public EmbeddableTypeImpl(Class<X> javaType, AbstractManagedType parent, ComponentType hibernateType) {
|
||||
super( javaType, null );
|
||||
this.parent = parent;
|
||||
this.hibernateType = hibernateType;
|
||||
}
|
||||
|
||||
public PersistenceType getPersistenceType() {
|
||||
return PersistenceType.EMBEDDABLE;
|
||||
}
|
||||
|
||||
public AbstractManagedType getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
public ComponentType getHibernateType() {
|
||||
return hibernateType;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Copyright (c) 2009, Red Hat Middleware LLC 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 Middleware LLC.
|
||||
*
|
||||
* 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.jpa.metamodel.internal.legacy;
|
||||
|
||||
import javax.persistence.metamodel.EntityType;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Defines the Hibernate implementation of the JPA {@link javax.persistence.metamodel.EntityType} contract.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
* @author Emmanuel Bernard
|
||||
*/
|
||||
public class EntityTypeImpl<X>
|
||||
extends AbstractIdentifiableType<X>
|
||||
implements EntityType<X>, Serializable {
|
||||
private final String jpaEntityName;
|
||||
|
||||
public EntityTypeImpl(
|
||||
Class<X> javaType,
|
||||
AbstractIdentifiableType<? super X> superType,
|
||||
String jpaEntityName,
|
||||
boolean hasIdentifierProperty,
|
||||
boolean isVersioned) {
|
||||
super( javaType, superType, hasIdentifierProperty, isVersioned );
|
||||
this.jpaEntityName = jpaEntityName;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return jpaEntityName;
|
||||
}
|
||||
|
||||
public BindableType getBindableType() {
|
||||
return BindableType.ENTITY_TYPE;
|
||||
}
|
||||
|
||||
public Class<X> getBindableJavaType() {
|
||||
return getJavaType();
|
||||
}
|
||||
|
||||
public PersistenceType getPersistenceType() {
|
||||
return PersistenceType.ENTITY;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean requiresSupertypeForNonDeclaredIdentifier() {
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package org.hibernate.jpa.metamodel.internal.legacy;
|
||||
import javax.persistence.metamodel.MappedSuperclassType;
|
||||
|
||||
/**
|
||||
* @author Emmanuel Bernard
|
||||
*/
|
||||
public class MappedSuperclassTypeImpl<X> extends AbstractIdentifiableType<X> implements MappedSuperclassType<X> {
|
||||
public MappedSuperclassTypeImpl(
|
||||
Class<X> javaType,
|
||||
AbstractIdentifiableType<? super X> superType,
|
||||
boolean hasIdentifierProperty,
|
||||
boolean versioned) {
|
||||
super( javaType, superType, hasIdentifierProperty, versioned );
|
||||
}
|
||||
|
||||
public PersistenceType getPersistenceType() {
|
||||
return PersistenceType.MAPPED_SUPERCLASS;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean requiresSupertypeForNonDeclaredIdentifier() {
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,485 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2012, 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.jpa.metamodel.internal.legacy;
|
||||
|
||||
import javax.persistence.metamodel.Attribute;
|
||||
import javax.persistence.metamodel.IdentifiableType;
|
||||
import javax.persistence.metamodel.MappedSuperclassType;
|
||||
import javax.persistence.metamodel.SingularAttribute;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.annotations.common.AssertionFailure;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||
import org.hibernate.mapping.Component;
|
||||
import org.hibernate.mapping.KeyValue;
|
||||
import org.hibernate.mapping.MappedSuperclass;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.mapping.Property;
|
||||
|
||||
/**
|
||||
* Defines a context for storing information during the building of the {@link MetamodelImpl}.
|
||||
* <p/>
|
||||
* This contextual information includes data needing to be processed in a second pass as well as
|
||||
* cross-references into the built metamodel classes.
|
||||
* <p/>
|
||||
* At the end of the day, clients are interested in the {@link #getEntityTypeMap} and {@link #getEmbeddableTypeMap}
|
||||
* results, which represent all the registered {@linkplain #registerEntityType entities} and
|
||||
* {@linkplain #registerEmbeddedableType embeddables} respectively.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
* @author Emmanuel Bernard
|
||||
*/
|
||||
class MetadataContext {
|
||||
|
||||
private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class,
|
||||
MetadataContext.class.getName());
|
||||
|
||||
private final SessionFactoryImplementor sessionFactory;
|
||||
private final boolean ignoreUnsupported;
|
||||
private final AttributeFactory attributeFactory = new AttributeFactory( this );
|
||||
|
||||
private Map<Class<?>,EntityTypeImpl<?>> entityTypes
|
||||
= new HashMap<Class<?>, EntityTypeImpl<?>>();
|
||||
private Map<String,EntityTypeImpl<?>> entityTypesByEntityName
|
||||
= new HashMap<String, EntityTypeImpl<?>>();
|
||||
private Map<PersistentClass,EntityTypeImpl<?>> entityTypesByPersistentClass
|
||||
= new HashMap<PersistentClass,EntityTypeImpl<?>>();
|
||||
private Map<Class<?>, EmbeddableTypeImpl<?>> embeddables
|
||||
= new HashMap<Class<?>, EmbeddableTypeImpl<?>>();
|
||||
private Map<MappedSuperclass, MappedSuperclassTypeImpl<?>> mappedSuperclassByMappedSuperclassMapping
|
||||
= new HashMap<MappedSuperclass,MappedSuperclassTypeImpl<?>>();
|
||||
//this list contains MappedSuperclass and EntityTypes ordered by superclass first
|
||||
private List<Object> orderedMappings = new ArrayList<Object>();
|
||||
/**
|
||||
* Stack of PersistentClass being process. Last in the list is the highest in the stack.
|
||||
*
|
||||
*/
|
||||
private List<PersistentClass> stackOfPersistentClassesBeingProcessed
|
||||
= new ArrayList<PersistentClass>();
|
||||
private Map<MappedSuperclassTypeImpl<?>, PersistentClass> mappedSuperClassTypeToPersistentClass
|
||||
= new HashMap<MappedSuperclassTypeImpl<?>, PersistentClass>();
|
||||
|
||||
public MetadataContext(SessionFactoryImplementor sessionFactory, boolean ignoreUnsupported) {
|
||||
this.sessionFactory = sessionFactory;
|
||||
this.ignoreUnsupported = ignoreUnsupported;
|
||||
}
|
||||
|
||||
/*package*/ SessionFactoryImplementor getSessionFactory() {
|
||||
return sessionFactory;
|
||||
}
|
||||
|
||||
/*package*/ boolean isIgnoreUnsupported() {
|
||||
return ignoreUnsupported;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the {@linkplain Class java type} to {@link EntityTypeImpl} map.
|
||||
*
|
||||
* @return The {@linkplain Class java type} to {@link EntityTypeImpl} map.
|
||||
*/
|
||||
public Map<Class<?>, EntityTypeImpl<?>> getEntityTypeMap() {
|
||||
return Collections.unmodifiableMap( entityTypes );
|
||||
}
|
||||
|
||||
public Map<Class<?>, EmbeddableTypeImpl<?>> getEmbeddableTypeMap() {
|
||||
return Collections.unmodifiableMap( embeddables );
|
||||
}
|
||||
|
||||
public Map<Class<?>,MappedSuperclassType<?>> getMappedSuperclassTypeMap() {
|
||||
// we need to actually build this map...
|
||||
final Map<Class<?>,MappedSuperclassType<?>> mappedSuperClassTypeMap = CollectionHelper.mapOfSize(
|
||||
mappedSuperclassByMappedSuperclassMapping.size()
|
||||
);
|
||||
|
||||
for ( MappedSuperclassTypeImpl mappedSuperclassType : mappedSuperclassByMappedSuperclassMapping.values() ) {
|
||||
mappedSuperClassTypeMap.put(
|
||||
mappedSuperclassType.getJavaType(),
|
||||
mappedSuperclassType
|
||||
);
|
||||
}
|
||||
|
||||
return mappedSuperClassTypeMap;
|
||||
}
|
||||
|
||||
/*package*/ void registerEntityType(PersistentClass persistentClass, EntityTypeImpl<?> entityType) {
|
||||
entityTypes.put( entityType.getBindableJavaType(), entityType );
|
||||
entityTypesByEntityName.put( persistentClass.getEntityName(), entityType );
|
||||
entityTypesByPersistentClass.put( persistentClass, entityType );
|
||||
orderedMappings.add( persistentClass );
|
||||
}
|
||||
|
||||
/*package*/ void registerEmbeddedableType(EmbeddableTypeImpl<?> embeddableType) {
|
||||
embeddables.put( embeddableType.getJavaType(), embeddableType );
|
||||
}
|
||||
|
||||
/*package*/ void registerMappedSuperclassType(MappedSuperclass mappedSuperclass,
|
||||
MappedSuperclassTypeImpl<?> mappedSuperclassType) {
|
||||
mappedSuperclassByMappedSuperclassMapping.put( mappedSuperclass, mappedSuperclassType );
|
||||
orderedMappings.add( mappedSuperclass );
|
||||
mappedSuperClassTypeToPersistentClass.put( mappedSuperclassType, getEntityWorkedOn() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a Hibernate {@link org.hibernate.mapping.PersistentClass}, locate the corresponding JPA {@link org.hibernate.type.EntityType}
|
||||
* implementation. May retur null if the given {@link org.hibernate.mapping.PersistentClass} has not yet been processed.
|
||||
*
|
||||
* @param persistentClass The Hibernate (config time) metamodel instance representing an entity.
|
||||
* @return Tne corresponding JPA {@link org.hibernate.type.EntityType}, or null if not yet processed.
|
||||
*/
|
||||
public EntityTypeImpl<?> locateEntityType(PersistentClass persistentClass) {
|
||||
return entityTypesByPersistentClass.get( persistentClass );
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a Java {@link Class}, locate the corresponding JPA {@link org.hibernate.type.EntityType}. May
|
||||
* return null which could means that no such mapping exists at least at this time.
|
||||
*
|
||||
* @param javaType The java class.
|
||||
* @return The corresponding JPA {@link org.hibernate.type.EntityType}, or null.
|
||||
*/
|
||||
public EntityTypeImpl<?> locateEntityType(Class<?> javaType) {
|
||||
return entityTypes.get( javaType );
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an entity-name, locate the corresponding JPA {@link org.hibernate.type.EntityType}. May
|
||||
* return null which could means that no such mapping exists at least at this time.
|
||||
*
|
||||
* @param entityName The entity-name.
|
||||
* @return The corresponding JPA {@link org.hibernate.type.EntityType}, or null.
|
||||
*/
|
||||
public EntityTypeImpl<?> locateEntityType(String entityName) {
|
||||
return entityTypesByEntityName.get( entityName );
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public void wrapUp() {
|
||||
LOG.trace("Wrapping up metadata context...");
|
||||
//we need to process types from superclasses to subclasses
|
||||
for (Object mapping : orderedMappings) {
|
||||
if ( PersistentClass.class.isAssignableFrom( mapping.getClass() ) ) {
|
||||
@SuppressWarnings( "unchecked" )
|
||||
final PersistentClass safeMapping = (PersistentClass) mapping;
|
||||
LOG.trace("Starting entity [" + safeMapping.getEntityName() + "]");
|
||||
try {
|
||||
final EntityTypeImpl<?> jpa2Mapping = entityTypesByPersistentClass.get( safeMapping );
|
||||
applyIdMetadata( safeMapping, jpa2Mapping );
|
||||
applyVersionAttribute( safeMapping, jpa2Mapping );
|
||||
Iterator<Property> properties = safeMapping.getDeclaredPropertyIterator();
|
||||
while ( properties.hasNext() ) {
|
||||
final Property property = properties.next();
|
||||
if ( property.getValue() == safeMapping.getIdentifierMapper() ) {
|
||||
// property represents special handling for id-class mappings but we have already
|
||||
// accounted for the embedded property mappings in #applyIdMetadata &&
|
||||
// #buildIdClassAttributes
|
||||
continue;
|
||||
}
|
||||
if ( safeMapping.isVersioned() && property == safeMapping.getVersion() ) {
|
||||
// skip the version property, it was already handled previously.
|
||||
continue;
|
||||
}
|
||||
final Attribute attribute = attributeFactory.buildAttribute( jpa2Mapping, property );
|
||||
if ( attribute != null ) {
|
||||
jpa2Mapping.getBuilder().addAttribute( attribute );
|
||||
}
|
||||
}
|
||||
jpa2Mapping.lock();
|
||||
populateStaticMetamodel( jpa2Mapping );
|
||||
}
|
||||
finally {
|
||||
LOG.trace("Completed entity [" + safeMapping.getEntityName() + "]");
|
||||
}
|
||||
}
|
||||
else if ( MappedSuperclass.class.isAssignableFrom( mapping.getClass() ) ) {
|
||||
@SuppressWarnings( "unchecked" )
|
||||
final MappedSuperclass safeMapping = (MappedSuperclass) mapping;
|
||||
LOG.trace("Starting mapped superclass [" + safeMapping.getMappedClass().getName() + "]");
|
||||
try {
|
||||
final MappedSuperclassTypeImpl<?> jpa2Mapping = mappedSuperclassByMappedSuperclassMapping.get(
|
||||
safeMapping
|
||||
);
|
||||
applyIdMetadata( safeMapping, jpa2Mapping );
|
||||
applyVersionAttribute( safeMapping, jpa2Mapping );
|
||||
Iterator<Property> properties = safeMapping.getDeclaredPropertyIterator();
|
||||
while ( properties.hasNext() ) {
|
||||
final Property property = properties.next();
|
||||
if ( safeMapping.isVersioned() && property == safeMapping.getVersion() ) {
|
||||
// skip the version property, it was already handled previously.
|
||||
continue;
|
||||
}
|
||||
final Attribute attribute = attributeFactory.buildAttribute( jpa2Mapping, property );
|
||||
if ( attribute != null ) {
|
||||
jpa2Mapping.getBuilder().addAttribute( attribute );
|
||||
}
|
||||
}
|
||||
jpa2Mapping.lock();
|
||||
populateStaticMetamodel( jpa2Mapping );
|
||||
}
|
||||
finally {
|
||||
LOG.trace("Completed mapped superclass [" + safeMapping.getMappedClass().getName() + "]");
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new AssertionFailure( "Unexpected mapping type: " + mapping.getClass() );
|
||||
}
|
||||
}
|
||||
|
||||
for ( EmbeddableTypeImpl embeddable : embeddables.values() ) {
|
||||
populateStaticMetamodel( embeddable );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private <X> void applyIdMetadata(PersistentClass persistentClass, EntityTypeImpl<X> jpaEntityType) {
|
||||
if ( persistentClass.hasIdentifierProperty() ) {
|
||||
final Property declaredIdentifierProperty = persistentClass.getDeclaredIdentifierProperty();
|
||||
if (declaredIdentifierProperty != null) {
|
||||
jpaEntityType.getBuilder().applyIdAttribute(
|
||||
attributeFactory.buildIdAttribute( jpaEntityType, declaredIdentifierProperty )
|
||||
);
|
||||
}
|
||||
}
|
||||
else if ( persistentClass.hasIdentifierMapper() ) {
|
||||
@SuppressWarnings( "unchecked")
|
||||
Iterator<Property> propertyIterator = persistentClass.getIdentifierMapper().getPropertyIterator();
|
||||
Set<SingularAttribute<? super X, ?>> attributes = buildIdClassAttributes( jpaEntityType, propertyIterator );
|
||||
jpaEntityType.getBuilder().applyIdClassAttributes( attributes );
|
||||
}
|
||||
else {
|
||||
final KeyValue value = persistentClass.getIdentifier();
|
||||
if (value instanceof Component ) {
|
||||
final Component component = ( Component ) value;
|
||||
if ( component.getPropertySpan() > 1 ) {
|
||||
//FIXME we are an Hibernate embedded id (ie not type)
|
||||
}
|
||||
else {
|
||||
//FIXME take care of declared vs non declared property
|
||||
jpaEntityType.getBuilder().applyIdAttribute(
|
||||
attributeFactory.buildIdAttribute(
|
||||
jpaEntityType,
|
||||
(Property) component.getPropertyIterator().next() )
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private <X> void applyIdMetadata(MappedSuperclass mappingType, MappedSuperclassTypeImpl<X> jpaMappingType) {
|
||||
if ( mappingType.hasIdentifierProperty() ) {
|
||||
final Property declaredIdentifierProperty = mappingType.getDeclaredIdentifierProperty();
|
||||
if (declaredIdentifierProperty != null) {
|
||||
jpaMappingType.getBuilder().applyIdAttribute(
|
||||
attributeFactory.buildIdAttribute( jpaMappingType, declaredIdentifierProperty )
|
||||
);
|
||||
}
|
||||
}
|
||||
//an MappedSuperclass can have no identifier if the id is set below in the hierarchy
|
||||
else if ( mappingType.getIdentifierMapper() != null ){
|
||||
@SuppressWarnings( "unchecked")
|
||||
Iterator<Property> propertyIterator = mappingType.getIdentifierMapper().getPropertyIterator();
|
||||
Set<SingularAttribute<? super X, ?>> attributes = buildIdClassAttributes( jpaMappingType, propertyIterator );
|
||||
jpaMappingType.getBuilder().applyIdClassAttributes( attributes );
|
||||
}
|
||||
}
|
||||
|
||||
private <X> void applyVersionAttribute(PersistentClass persistentClass, EntityTypeImpl<X> jpaEntityType) {
|
||||
final Property declaredVersion = persistentClass.getDeclaredVersion();
|
||||
if (declaredVersion != null) {
|
||||
jpaEntityType.getBuilder().applyVersionAttribute(
|
||||
attributeFactory.buildVersionAttribute( jpaEntityType, declaredVersion )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private <X> void applyVersionAttribute(MappedSuperclass mappingType, MappedSuperclassTypeImpl<X> jpaMappingType) {
|
||||
final Property declaredVersion = mappingType.getDeclaredVersion();
|
||||
if ( declaredVersion != null ) {
|
||||
jpaMappingType.getBuilder().applyVersionAttribute(
|
||||
attributeFactory.buildVersionAttribute( jpaMappingType, declaredVersion )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private <X> Set<SingularAttribute<? super X, ?>> buildIdClassAttributes(
|
||||
AbstractIdentifiableType<X> ownerType,
|
||||
Iterator<Property> propertyIterator) {
|
||||
LOG.trace("Building old-school composite identifier [" + ownerType.getJavaType().getName() + "]");
|
||||
Set<SingularAttribute<? super X, ?>> attributes = new HashSet<SingularAttribute<? super X, ?>>();
|
||||
while ( propertyIterator.hasNext() ) {
|
||||
attributes.add( attributeFactory.buildIdAttribute( ownerType, propertyIterator.next() ) );
|
||||
}
|
||||
return attributes;
|
||||
}
|
||||
|
||||
private <X> void populateStaticMetamodel(AbstractManagedType<X> managedType) {
|
||||
final Class<X> managedTypeClass = managedType.getJavaType();
|
||||
final String metamodelClassName = managedTypeClass.getName() + "_";
|
||||
try {
|
||||
final Class metamodelClass = Class.forName( metamodelClassName, true, managedTypeClass.getClassLoader() );
|
||||
// we found the class; so populate it...
|
||||
registerAttributes( metamodelClass, managedType );
|
||||
}
|
||||
catch ( ClassNotFoundException ignore ) {
|
||||
// nothing to do...
|
||||
}
|
||||
|
||||
// todo : this does not account for @MappeSuperclass, mainly because this is not being tracked in our
|
||||
// internal metamodel as populated from the annotatios properly
|
||||
AbstractManagedType<? super X> superType = managedType.getSupertype();
|
||||
if ( superType != null ) {
|
||||
populateStaticMetamodel( superType );
|
||||
}
|
||||
}
|
||||
|
||||
private final Set<Class> processedMetamodelClasses = new HashSet<Class>();
|
||||
|
||||
private <X> void registerAttributes(Class metamodelClass, AbstractManagedType<X> managedType) {
|
||||
if ( ! processedMetamodelClasses.add( metamodelClass ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// push the attributes on to the metamodel class...
|
||||
for ( Attribute<X, ?> attribute : managedType.getDeclaredAttributes() ) {
|
||||
registerAttribute( metamodelClass, attribute );
|
||||
}
|
||||
|
||||
if ( IdentifiableType.class.isInstance( managedType ) ) {
|
||||
final AbstractIdentifiableType<X> entityType = ( AbstractIdentifiableType<X> ) managedType;
|
||||
|
||||
// handle version
|
||||
if ( entityType.hasDeclaredVersionAttribute() ) {
|
||||
registerAttribute( metamodelClass, entityType.getDeclaredVersion() );
|
||||
}
|
||||
|
||||
// handle id-class mappings specially
|
||||
if ( ! entityType.hasSingleIdAttribute() ) {
|
||||
final Set<SingularAttribute<? super X, ?>> attributes = entityType.getIdClassAttributes();
|
||||
if ( attributes != null ) {
|
||||
for ( SingularAttribute<? super X, ?> attribute : attributes ) {
|
||||
registerAttribute( metamodelClass, attribute );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private <X> void registerAttribute(Class metamodelClass, Attribute<X, ?> attribute) {
|
||||
final String name = attribute.getName();
|
||||
try {
|
||||
// there is a shortcoming in the existing Hibernate code in terms of the way MappedSuperclass
|
||||
// support was bolted on which comes to bear right here when the attribute is an embeddable type
|
||||
// defined on a MappedSuperclass. We do not have the correct information to determine the
|
||||
// appropriate attribute declarer in such cases and so the incoming metamodelClass most likely
|
||||
// does not represent the declarer in such cases.
|
||||
//
|
||||
// As a result, in the case of embeddable classes we simply use getField rather than get
|
||||
// getDeclaredField
|
||||
final Field field = attribute.getPersistentAttributeType() == Attribute.PersistentAttributeType.EMBEDDED
|
||||
? metamodelClass.getField( name )
|
||||
: metamodelClass.getDeclaredField( name );
|
||||
try {
|
||||
if ( ! field.isAccessible() ) {
|
||||
// should be public anyway, but to be sure...
|
||||
field.setAccessible( true );
|
||||
}
|
||||
field.set( null, attribute );
|
||||
}
|
||||
catch ( IllegalAccessException e ) {
|
||||
// todo : exception type?
|
||||
throw new AssertionFailure(
|
||||
"Unable to inject static metamodel attribute : " + metamodelClass.getName() + '#' + name,
|
||||
e
|
||||
);
|
||||
}
|
||||
catch ( IllegalArgumentException e ) {
|
||||
// most likely a mismatch in the type we are injecting and the defined field; this represents a
|
||||
// mismatch in how the annotation processor interpretted the attribute and how our metamodel
|
||||
// and/or annotation binder did.
|
||||
|
||||
// This is particularly the case as arrays are nto handled propery by the StaticMetamodel generator
|
||||
|
||||
// throw new AssertionFailure(
|
||||
// "Illegal argument on static metamodel field injection : " + metamodelClass.getName() + '#' + name
|
||||
// + "; expected type : " + attribute.getClass().getName()
|
||||
// + "; encountered type : " + field.getType().getName()
|
||||
// );
|
||||
LOG.illegalArgumentOnStaticMetamodelFieldInjection(metamodelClass.getName(),
|
||||
name,
|
||||
attribute.getClass().getName(),
|
||||
field.getType().getName());
|
||||
}
|
||||
}
|
||||
catch ( NoSuchFieldException e ) {
|
||||
LOG.unableToLocateStaticMetamodelField(metamodelClass.getName(), name);
|
||||
// throw new AssertionFailure(
|
||||
// "Unable to locate static metamodel field : " + metamodelClass.getName() + '#' + name
|
||||
// );
|
||||
}
|
||||
}
|
||||
|
||||
public MappedSuperclassTypeImpl<?> locateMappedSuperclassType(MappedSuperclass mappedSuperclass) {
|
||||
return mappedSuperclassByMappedSuperclassMapping.get(mappedSuperclass);
|
||||
}
|
||||
|
||||
public void pushEntityWorkedOn(PersistentClass persistentClass) {
|
||||
stackOfPersistentClassesBeingProcessed.add(persistentClass);
|
||||
}
|
||||
|
||||
public void popEntityWorkedOn(PersistentClass persistentClass) {
|
||||
final PersistentClass stackTop = stackOfPersistentClassesBeingProcessed.remove(
|
||||
stackOfPersistentClassesBeingProcessed.size() - 1
|
||||
);
|
||||
if (stackTop != persistentClass) {
|
||||
throw new AssertionFailure( "Inconsistent popping: "
|
||||
+ persistentClass.getEntityName() + " instead of " + stackTop.getEntityName() );
|
||||
}
|
||||
}
|
||||
|
||||
private PersistentClass getEntityWorkedOn() {
|
||||
return stackOfPersistentClassesBeingProcessed.get(
|
||||
stackOfPersistentClassesBeingProcessed.size() - 1
|
||||
);
|
||||
}
|
||||
|
||||
public PersistentClass getPersistentClassHostingProperties(MappedSuperclassTypeImpl<?> mappedSuperclassType) {
|
||||
final PersistentClass persistentClass = mappedSuperClassTypeToPersistentClass.get( mappedSuperclassType );
|
||||
if (persistentClass == null) {
|
||||
throw new AssertionFailure( "Could not find PersistentClass for MappedSuperclassType: "
|
||||
+ mappedSuperclassType.getJavaType() );
|
||||
}
|
||||
return persistentClass;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,238 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2012, 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.jpa.metamodel.internal.legacy;
|
||||
|
||||
import javax.persistence.metamodel.EmbeddableType;
|
||||
import javax.persistence.metamodel.EntityType;
|
||||
import javax.persistence.metamodel.ManagedType;
|
||||
import javax.persistence.metamodel.MappedSuperclassType;
|
||||
import javax.persistence.metamodel.Metamodel;
|
||||
import java.io.Serializable;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||
import org.hibernate.mapping.MappedSuperclass;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
|
||||
/**
|
||||
* Hibernate implementation of the JPA {@link javax.persistence.metamodel.Metamodel} contract.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
* @author Emmanuel Bernard
|
||||
*/
|
||||
public class MetamodelImpl implements Metamodel, Serializable {
|
||||
private final Map<Class<?>,EntityTypeImpl<?>> entities;
|
||||
private final Map<Class<?>, EmbeddableTypeImpl<?>> embeddables;
|
||||
private final Map<Class<?>, MappedSuperclassType<?>> mappedSuperclassTypeMap;
|
||||
|
||||
/**
|
||||
* Build the metamodel using the information from the collection of Hibernate
|
||||
* {@link org.hibernate.mapping.PersistentClass} models as well as the Hibernate {@link org.hibernate.SessionFactory}.
|
||||
*
|
||||
* @param persistentClasses Iterator over the Hibernate (config-time) metamodel
|
||||
* @param sessionFactory The Hibernate session factory.
|
||||
* @return The built metamodel
|
||||
*
|
||||
* @deprecated use {@link #buildMetamodel(java.util.Iterator,org.hibernate.engine.spi.SessionFactoryImplementor,boolean)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public static MetamodelImpl buildMetamodel(
|
||||
Iterator<PersistentClass> persistentClasses,
|
||||
SessionFactoryImplementor sessionFactory) {
|
||||
return buildMetamodel(persistentClasses, sessionFactory, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the metamodel using the information from the collection of Hibernate
|
||||
* {@link org.hibernate.mapping.PersistentClass} models as well as the Hibernate {@link org.hibernate.SessionFactory}.
|
||||
*
|
||||
* @param persistentClasses Iterator over the Hibernate (config-time) metamodel
|
||||
* @param sessionFactory The Hibernate session factory.
|
||||
* @param ignoreUnsupported ignore unsupported/unknown annotations (like @Any)
|
||||
* @return The built metamodel
|
||||
*/
|
||||
public static MetamodelImpl buildMetamodel(
|
||||
Iterator<PersistentClass> persistentClasses,
|
||||
SessionFactoryImplementor sessionFactory,
|
||||
boolean ignoreUnsupported) {
|
||||
MetadataContext context = new MetadataContext( sessionFactory, ignoreUnsupported );
|
||||
while ( persistentClasses.hasNext() ) {
|
||||
PersistentClass pc = persistentClasses.next();
|
||||
if ( pc.getMappedClass() != null ) {
|
||||
locateOrBuildEntityType( pc, context );
|
||||
}
|
||||
}
|
||||
context.wrapUp();
|
||||
return new MetamodelImpl( context.getEntityTypeMap(), context.getEmbeddableTypeMap(), context.getMappedSuperclassTypeMap() );
|
||||
}
|
||||
|
||||
private static EntityTypeImpl<?> locateOrBuildEntityType(PersistentClass persistentClass, MetadataContext context) {
|
||||
EntityTypeImpl<?> entityType = context.locateEntityType( persistentClass );
|
||||
if ( entityType == null ) {
|
||||
entityType = buildEntityType( persistentClass, context );
|
||||
}
|
||||
return entityType;
|
||||
}
|
||||
|
||||
//TODO remove / reduce @SW scope
|
||||
@SuppressWarnings( "unchecked" )
|
||||
private static EntityTypeImpl<?> buildEntityType(PersistentClass persistentClass, MetadataContext context) {
|
||||
final Class javaType = persistentClass.getMappedClass();
|
||||
context.pushEntityWorkedOn(persistentClass);
|
||||
final MappedSuperclass superMappedSuperclass = persistentClass.getSuperMappedSuperclass();
|
||||
AbstractIdentifiableType<?> superType = superMappedSuperclass == null
|
||||
? null
|
||||
: locateOrBuildMappedsuperclassType( superMappedSuperclass, context );
|
||||
//no mappedSuperclass, check for a super entity
|
||||
if (superType == null) {
|
||||
final PersistentClass superPersistentClass = persistentClass.getSuperclass();
|
||||
superType = superPersistentClass == null
|
||||
? null
|
||||
: locateOrBuildEntityType( superPersistentClass, context );
|
||||
}
|
||||
EntityTypeImpl entityType = new EntityTypeImpl(
|
||||
javaType,
|
||||
superType,
|
||||
persistentClass.getJpaEntityName(),
|
||||
persistentClass.hasIdentifierProperty(),
|
||||
persistentClass.isVersioned()
|
||||
);
|
||||
context.registerEntityType( persistentClass, entityType );
|
||||
context.popEntityWorkedOn(persistentClass);
|
||||
return entityType;
|
||||
}
|
||||
|
||||
private static MappedSuperclassTypeImpl<?> locateOrBuildMappedsuperclassType(
|
||||
MappedSuperclass mappedSuperclass, MetadataContext context) {
|
||||
MappedSuperclassTypeImpl<?> mappedSuperclassType = context.locateMappedSuperclassType( mappedSuperclass );
|
||||
if ( mappedSuperclassType == null ) {
|
||||
mappedSuperclassType = buildMappedSuperclassType(mappedSuperclass, context);
|
||||
}
|
||||
return mappedSuperclassType;
|
||||
}
|
||||
|
||||
//TODO remove / reduce @SW scope
|
||||
@SuppressWarnings( "unchecked" )
|
||||
private static MappedSuperclassTypeImpl<?> buildMappedSuperclassType(MappedSuperclass mappedSuperclass,
|
||||
MetadataContext context) {
|
||||
final MappedSuperclass superMappedSuperclass = mappedSuperclass.getSuperMappedSuperclass();
|
||||
AbstractIdentifiableType<?> superType = superMappedSuperclass == null
|
||||
? null
|
||||
: locateOrBuildMappedsuperclassType( superMappedSuperclass, context );
|
||||
//no mappedSuperclass, check for a super entity
|
||||
if (superType == null) {
|
||||
final PersistentClass superPersistentClass = mappedSuperclass.getSuperPersistentClass();
|
||||
superType = superPersistentClass == null
|
||||
? null
|
||||
: locateOrBuildEntityType( superPersistentClass, context );
|
||||
}
|
||||
final Class javaType = mappedSuperclass.getMappedClass();
|
||||
MappedSuperclassTypeImpl mappedSuperclassType = new MappedSuperclassTypeImpl(
|
||||
javaType,
|
||||
superType,
|
||||
mappedSuperclass.hasIdentifierProperty(),
|
||||
mappedSuperclass.isVersioned()
|
||||
);
|
||||
context.registerMappedSuperclassType( mappedSuperclass, mappedSuperclassType );
|
||||
return mappedSuperclassType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiate the metamodel.
|
||||
*
|
||||
* @param entities The entity mappings.
|
||||
* @param embeddables The embeddable (component) mappings.
|
||||
* @param mappedSuperclassTypeMap The {@link javax.persistence.MappedSuperclass} mappings
|
||||
*/
|
||||
private MetamodelImpl(
|
||||
Map<Class<?>, EntityTypeImpl<?>> entities,
|
||||
Map<Class<?>, EmbeddableTypeImpl<?>> embeddables,
|
||||
Map<Class<?>, MappedSuperclassType<?>> mappedSuperclassTypeMap) {
|
||||
this.entities = entities;
|
||||
this.embeddables = embeddables;
|
||||
this.mappedSuperclassTypeMap = mappedSuperclassTypeMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public <X> EntityType<X> entity(Class<X> cls) {
|
||||
final EntityType<?> entityType = entities.get( cls );
|
||||
if ( entityType == null ) {
|
||||
throw new IllegalArgumentException( "Not an entity: " + cls );
|
||||
}
|
||||
return (EntityType<X>) entityType;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public <X> ManagedType<X> managedType(Class<X> cls) {
|
||||
ManagedType<?> type = entities.get( cls );
|
||||
if ( type == null ) {
|
||||
type = mappedSuperclassTypeMap.get( cls );
|
||||
}
|
||||
if ( type == null ) {
|
||||
type = embeddables.get( cls );
|
||||
}
|
||||
if ( type == null ) {
|
||||
throw new IllegalArgumentException( "Not an managed type: " + cls );
|
||||
}
|
||||
return (ManagedType<X>) type;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public <X> EmbeddableType<X> embeddable(Class<X> cls) {
|
||||
final EmbeddableType<?> embeddableType = embeddables.get( cls );
|
||||
if ( embeddableType == null ) {
|
||||
throw new IllegalArgumentException( "Not an embeddable: " + cls );
|
||||
}
|
||||
return (EmbeddableType<X>) embeddableType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<ManagedType<?>> getManagedTypes() {
|
||||
final int setSize = CollectionHelper.determineProperSizing(
|
||||
entities.size() + mappedSuperclassTypeMap.size() + embeddables.size()
|
||||
);
|
||||
final Set<ManagedType<?>> managedTypes = new HashSet<ManagedType<?>>( setSize );
|
||||
managedTypes.addAll( entities.values() );
|
||||
managedTypes.addAll( mappedSuperclassTypeMap.values() );
|
||||
managedTypes.addAll( embeddables.values() );
|
||||
return managedTypes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<EntityType<?>> getEntities() {
|
||||
return new HashSet<EntityType<?>>( entities.values() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<EmbeddableType<?>> getEmbeddables() {
|
||||
return new HashSet<EmbeddableType<?>>( embeddables.values() );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,260 @@
|
|||
/*
|
||||
* Copyright (c) 2009, Red Hat Middleware LLC 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 Middleware LLC.
|
||||
*
|
||||
* 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.jpa.metamodel.internal.legacy;
|
||||
|
||||
import javax.persistence.metamodel.CollectionAttribute;
|
||||
import javax.persistence.metamodel.ListAttribute;
|
||||
import javax.persistence.metamodel.MapAttribute;
|
||||
import javax.persistence.metamodel.PluralAttribute;
|
||||
import javax.persistence.metamodel.SetAttribute;
|
||||
import javax.persistence.metamodel.Type;
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Member;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.hibernate.mapping.Property;
|
||||
|
||||
/**
|
||||
* @author Emmanuel Bernard
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public abstract class PluralAttributeImpl<X, C, E>
|
||||
extends AbstractAttribute<X,C>
|
||||
implements PluralAttribute<X, C, E>, Serializable {
|
||||
|
||||
private final Type<E> elementType;
|
||||
|
||||
private PluralAttributeImpl(Builder<X,C,E,?> builder) {
|
||||
super(
|
||||
builder.property.getName(),
|
||||
builder.collectionClass,
|
||||
builder.type,
|
||||
builder.member,
|
||||
builder.persistentAttributeType
|
||||
);
|
||||
this.elementType = builder.attributeType;
|
||||
}
|
||||
|
||||
public static class Builder<X, C, E, K> {
|
||||
private final Type<E> attributeType;
|
||||
private final AbstractManagedType<X> type;
|
||||
private Member member;
|
||||
private PersistentAttributeType persistentAttributeType;
|
||||
private Property property;
|
||||
private Class<C> collectionClass;
|
||||
private Type<K> keyType;
|
||||
|
||||
|
||||
private Builder(AbstractManagedType<X> ownerType, Type<E> attrType, Class<C> collectionClass, Type<K> keyType) {
|
||||
this.type = ownerType;
|
||||
this.attributeType = attrType;
|
||||
this.collectionClass = collectionClass;
|
||||
this.keyType = keyType;
|
||||
}
|
||||
|
||||
public Builder<X,C,E,K> member(Member member) {
|
||||
this.member = member;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<X,C,E,K> property(Property property) {
|
||||
this.property = property;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<X,C,E,K> persistentAttributeType(PersistentAttributeType attrType) {
|
||||
this.persistentAttributeType = attrType;
|
||||
return this;
|
||||
}
|
||||
|
||||
@SuppressWarnings( "unchecked" )
|
||||
public <K> PluralAttributeImpl<X,C,E> build() {
|
||||
//apply strict spec rules first
|
||||
if ( Map.class.equals( collectionClass ) ) {
|
||||
final Builder<X,Map<K,E>,E,K> builder = (Builder<X,Map<K,E>,E,K>) this;
|
||||
return ( PluralAttributeImpl<X, C, E> ) new MapAttributeImpl<X,K,E>(
|
||||
builder
|
||||
);
|
||||
}
|
||||
else if ( Set.class.equals( collectionClass ) ) {
|
||||
final Builder<X,Set<E>, E,?> builder = (Builder<X, Set<E>, E,?>) this;
|
||||
return ( PluralAttributeImpl<X, C, E> ) new SetAttributeImpl<X,E>(
|
||||
builder
|
||||
);
|
||||
}
|
||||
else if ( List.class.equals( collectionClass ) ) {
|
||||
final Builder<X, List<E>, E,?> builder = (Builder<X, List<E>, E,?>) this;
|
||||
return ( PluralAttributeImpl<X, C, E> ) new ListAttributeImpl<X,E>(
|
||||
builder
|
||||
);
|
||||
}
|
||||
else if ( Collection.class.equals( collectionClass ) ) {
|
||||
final Builder<X, Collection<E>,E,?> builder = (Builder<X, Collection<E>, E,?>) this;
|
||||
return ( PluralAttributeImpl<X, C, E> ) new CollectionAttributeImpl<X, E>(
|
||||
builder
|
||||
);
|
||||
}
|
||||
|
||||
//apply loose rules
|
||||
if ( Map.class.isAssignableFrom( collectionClass ) ) {
|
||||
final Builder<X,Map<K,E>,E,K> builder = (Builder<X,Map<K,E>,E,K>) this;
|
||||
return ( PluralAttributeImpl<X, C, E> ) new MapAttributeImpl<X,K,E>(
|
||||
builder
|
||||
);
|
||||
}
|
||||
else if ( Set.class.isAssignableFrom( collectionClass ) ) {
|
||||
final Builder<X,Set<E>, E,?> builder = (Builder<X, Set<E>, E,?>) this;
|
||||
return ( PluralAttributeImpl<X, C, E> ) new SetAttributeImpl<X,E>(
|
||||
builder
|
||||
);
|
||||
}
|
||||
else if ( List.class.isAssignableFrom( collectionClass ) ) {
|
||||
final Builder<X, List<E>, E,?> builder = (Builder<X, List<E>, E,?>) this;
|
||||
return ( PluralAttributeImpl<X, C, E> ) new ListAttributeImpl<X,E>(
|
||||
builder
|
||||
);
|
||||
}
|
||||
else if ( Collection.class.isAssignableFrom( collectionClass ) ) {
|
||||
final Builder<X, Collection<E>,E,?> builder = (Builder<X, Collection<E>, E,?>) this;
|
||||
return ( PluralAttributeImpl<X, C, E> ) new CollectionAttributeImpl<X, E>(
|
||||
builder
|
||||
);
|
||||
}
|
||||
throw new UnsupportedOperationException( "Unkown collection: " + collectionClass );
|
||||
}
|
||||
}
|
||||
|
||||
public static <X,C,E,K> Builder<X,C,E,K> create(
|
||||
AbstractManagedType<X> ownerType,
|
||||
Type<E> attrType,
|
||||
Class<C> collectionClass,
|
||||
Type<K> keyType) {
|
||||
return new Builder<X,C,E,K>(ownerType, attrType, collectionClass, keyType);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Type<E> getElementType() {
|
||||
return elementType;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public boolean isAssociation() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public boolean isCollection() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public BindableType getBindableType() {
|
||||
return BindableType.PLURAL_ATTRIBUTE;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Class<E> getBindableJavaType() {
|
||||
return elementType.getJavaType();
|
||||
}
|
||||
|
||||
static class SetAttributeImpl<X,E> extends PluralAttributeImpl<X,Set<E>,E> implements SetAttribute<X,E> {
|
||||
SetAttributeImpl(Builder<X,Set<E>,E,?> xceBuilder) {
|
||||
super( xceBuilder );
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public CollectionType getCollectionType() {
|
||||
return CollectionType.SET;
|
||||
}
|
||||
}
|
||||
|
||||
static class CollectionAttributeImpl<X,E> extends PluralAttributeImpl<X,Collection<E>,E> implements CollectionAttribute<X,E> {
|
||||
CollectionAttributeImpl(Builder<X, Collection<E>,E,?> xceBuilder) {
|
||||
super( xceBuilder );
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public CollectionType getCollectionType() {
|
||||
return CollectionType.COLLECTION;
|
||||
}
|
||||
}
|
||||
|
||||
static class ListAttributeImpl<X,E> extends PluralAttributeImpl<X,List<E>,E> implements ListAttribute<X,E> {
|
||||
ListAttributeImpl(Builder<X,List<E>,E,?> xceBuilder) {
|
||||
super( xceBuilder );
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public CollectionType getCollectionType() {
|
||||
return CollectionType.LIST;
|
||||
}
|
||||
}
|
||||
|
||||
static class MapAttributeImpl<X,K,V> extends PluralAttributeImpl<X,Map<K,V>,V> implements MapAttribute<X,K,V> {
|
||||
private final Type<K> keyType;
|
||||
|
||||
MapAttributeImpl(Builder<X,Map<K,V>,V,K> xceBuilder) {
|
||||
super( xceBuilder );
|
||||
this.keyType = xceBuilder.keyType;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public CollectionType getCollectionType() {
|
||||
return CollectionType.MAP;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Class<K> getKeyJavaType() {
|
||||
return keyType.getJavaType();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Type<K> getKeyType() {
|
||||
return keyType;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,145 @@
|
|||
/*
|
||||
* Copyright (c) 2009, Red Hat Middleware LLC 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 Middleware LLC.
|
||||
*
|
||||
* 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.jpa.metamodel.internal.legacy;
|
||||
|
||||
import javax.persistence.metamodel.SingularAttribute;
|
||||
import javax.persistence.metamodel.Type;
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Member;
|
||||
|
||||
/**
|
||||
* @author Emmanuel Bernard
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class SingularAttributeImpl<X, Y>
|
||||
extends AbstractAttribute<X,Y>
|
||||
implements SingularAttribute<X, Y>, Serializable {
|
||||
private final boolean isIdentifier;
|
||||
private final boolean isVersion;
|
||||
private final boolean isOptional;
|
||||
private final Type<Y> attributeType;
|
||||
|
||||
public SingularAttributeImpl(
|
||||
String name,
|
||||
Class<Y> javaType,
|
||||
AbstractManagedType<X> declaringType,
|
||||
Member member,
|
||||
boolean isIdentifier,
|
||||
boolean isVersion,
|
||||
boolean isOptional,
|
||||
Type<Y> attributeType,
|
||||
PersistentAttributeType persistentAttributeType) {
|
||||
super( name, javaType, declaringType, member, persistentAttributeType );
|
||||
this.isIdentifier = isIdentifier;
|
||||
this.isVersion = isVersion;
|
||||
this.isOptional = isOptional;
|
||||
this.attributeType = attributeType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclass used to simply instantiation of singular attributes representing an entity's
|
||||
* identifier.
|
||||
*/
|
||||
public static class Identifier<X,Y> extends SingularAttributeImpl<X,Y> {
|
||||
public Identifier(
|
||||
String name,
|
||||
Class<Y> javaType,
|
||||
AbstractManagedType<X> declaringType,
|
||||
Member member,
|
||||
Type<Y> attributeType,
|
||||
PersistentAttributeType persistentAttributeType) {
|
||||
super( name, javaType, declaringType, member, true, false, false, attributeType, persistentAttributeType );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclass used to simply instantiation of singular attributes representing an entity's
|
||||
* version.
|
||||
*/
|
||||
public static class Version<X,Y> extends SingularAttributeImpl<X,Y> {
|
||||
public Version(
|
||||
String name,
|
||||
Class<Y> javaType,
|
||||
AbstractManagedType<X> declaringType,
|
||||
Member member,
|
||||
Type<Y> attributeType,
|
||||
PersistentAttributeType persistentAttributeType) {
|
||||
super( name, javaType, declaringType, member, false, true, false, attributeType, persistentAttributeType );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public boolean isId() {
|
||||
return isIdentifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public boolean isVersion() {
|
||||
return isVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public boolean isOptional() {
|
||||
return isOptional;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Type<Y> getType() {
|
||||
return attributeType;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public boolean isAssociation() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public boolean isCollection() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public BindableType getBindableType() {
|
||||
return BindableType.SINGULAR_ATTRIBUTE;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Class<Y> getBindableJavaType() {
|
||||
return attributeType.getJavaType();
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
package org.hibernate.jpa.metamodel;
|
|
@ -0,0 +1 @@
|
|||
package org.hibernate.jpa;
|
|
@ -39,6 +39,7 @@ import java.util.zip.ZipEntry;
|
|||
import org.jboss.logging.Logger;
|
||||
import org.w3c.dom.Document;
|
||||
|
||||
import org.hibernate.boot.spi.CacheRegionDefinition;
|
||||
import org.hibernate.internal.jaxb.JaxbRoot;
|
||||
import org.hibernate.internal.jaxb.Origin;
|
||||
import org.hibernate.internal.jaxb.SourceType;
|
||||
|
@ -60,8 +61,11 @@ public class MetadataSources {
|
|||
|
||||
private List<JaxbRoot> jaxbRootList = new ArrayList<JaxbRoot>();
|
||||
private LinkedHashSet<Class<?>> annotatedClasses = new LinkedHashSet<Class<?>>();
|
||||
private LinkedHashSet<String> annotatedClassNames = new LinkedHashSet<String>();
|
||||
private LinkedHashSet<String> annotatedPackages = new LinkedHashSet<String>();
|
||||
|
||||
private final List<CacheRegionDefinition> externalCacheRegionDefinitions = new ArrayList<CacheRegionDefinition>();
|
||||
|
||||
private final JaxbHelper jaxbHelper;
|
||||
|
||||
private final ServiceRegistry serviceRegistry;
|
||||
|
@ -92,6 +96,14 @@ public class MetadataSources {
|
|||
return annotatedClasses;
|
||||
}
|
||||
|
||||
public Iterable<String> getAnnotatedClassNames() {
|
||||
return annotatedClassNames;
|
||||
}
|
||||
|
||||
public List<CacheRegionDefinition> getExternalCacheRegionDefinitions() {
|
||||
return externalCacheRegionDefinitions;
|
||||
}
|
||||
|
||||
public ServiceRegistry getServiceRegistry() {
|
||||
return serviceRegistry;
|
||||
}
|
||||
|
@ -128,6 +140,18 @@ public class MetadataSources {
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read metadata from the annotations attached to the given class.
|
||||
*
|
||||
* @param annotatedClassName The name of a class containing annotations
|
||||
*
|
||||
* @return this (for method chaining)
|
||||
*/
|
||||
public MetadataSources addAnnotatedClassName(String annotatedClassName) {
|
||||
annotatedClassNames.add( annotatedClassName );
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read package-level metadata.
|
||||
*
|
||||
|
@ -383,4 +407,9 @@ public class MetadataSources {
|
|||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public MetadataSources addCacheRegionDefinitions(List<CacheRegionDefinition> cacheRegionDefinitions) {
|
||||
externalCacheRegionDefinitions.addAll( cacheRegionDefinitions );
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -79,6 +79,7 @@ import org.hibernate.metamodel.spi.binding.OneToManyPluralAttributeElementBindin
|
|||
import org.hibernate.metamodel.spi.binding.PluralAttributeBinding;
|
||||
import org.hibernate.metamodel.spi.binding.PluralAttributeElementNature;
|
||||
import org.hibernate.metamodel.spi.binding.PluralAttributeIndexBinding;
|
||||
import org.hibernate.metamodel.spi.binding.PluralAttributeIndexNature;
|
||||
import org.hibernate.metamodel.spi.binding.PluralAttributeKeyBinding;
|
||||
import org.hibernate.metamodel.spi.binding.RelationalValueBinding;
|
||||
import org.hibernate.metamodel.spi.binding.SecondaryTable;
|
||||
|
@ -183,6 +184,8 @@ public class Binder {
|
|||
|
||||
private final HibernateTypeHelper typeHelper; // todo: refactor helper and remove redundant methods in this class
|
||||
|
||||
// todo : apply org.hibernate.metamodel.MetadataSources.getExternalCacheRegionDefinitions()
|
||||
|
||||
public Binder( final MetadataImplementor metadata, final IdentifierGeneratorFactory identifierGeneratorFactory ) {
|
||||
this.metadata = metadata;
|
||||
this.identifierGeneratorFactory = identifierGeneratorFactory;
|
||||
|
@ -648,6 +651,7 @@ public class Binder {
|
|||
return attributeBindingContainer.makeMapAttributeBinding(
|
||||
attribute,
|
||||
pluralAttributeElementNature( attributeSource ),
|
||||
pluralAttributeIndexNature( attributeSource ),
|
||||
determinePluralAttributeKeyReferencedBinding( attributeBindingContainer, attributeSource ),
|
||||
propertyAccessorName( attributeSource ),
|
||||
attributeSource.isIncludedInOptimisticLocking(),
|
||||
|
@ -2022,10 +2026,19 @@ public class Binder {
|
|||
}
|
||||
}
|
||||
|
||||
private PluralAttributeElementNature pluralAttributeElementNature( final PluralAttributeSource attributeSource ) {
|
||||
private PluralAttributeElementNature pluralAttributeElementNature(PluralAttributeSource attributeSource) {
|
||||
return PluralAttributeElementNature.valueOf( attributeSource.getElementSource().getNature().name() );
|
||||
}
|
||||
|
||||
private PluralAttributeIndexNature pluralAttributeIndexNature(PluralAttributeSource attributeSource) {
|
||||
if ( ! IndexedPluralAttributeSource.class.isInstance( attributeSource ) ) {
|
||||
return null;
|
||||
}
|
||||
return PluralAttributeIndexNature.valueOf(
|
||||
( (IndexedPluralAttributeSource) attributeSource ).getIndexSource().getNature().name()
|
||||
);
|
||||
}
|
||||
|
||||
private SingularAttributeBinding determinePluralAttributeKeyReferencedBinding(
|
||||
final AttributeBindingContainer attributeBindingContainer,
|
||||
final PluralAttributeSource attributeSource ) {
|
||||
|
|
|
@ -72,12 +72,19 @@ public class AnnotationMetadataSourceProcessorImpl implements MetadataSourceProc
|
|||
public AnnotationMetadataSourceProcessorImpl(MetadataImpl metadata, MetadataSources metadataSources) {
|
||||
this.metadata = metadata;
|
||||
|
||||
// todo : use the Jandex from JBoss/JPA if available...
|
||||
// todo : cache the built index if no inputs have changed (look at gradle-style hashing for up-to-date checking)
|
||||
|
||||
// create a jandex index from the annotated classes
|
||||
Indexer indexer = new Indexer();
|
||||
for ( Class<?> clazz : metadataSources.getAnnotatedClasses() ) {
|
||||
indexClass( indexer, clazz.getName().replace( '.', '/' ) + ".class" );
|
||||
}
|
||||
|
||||
for ( String className : metadataSources.getAnnotatedClassNames() ) {
|
||||
indexClass( indexer, className.replace( '.', '/' ) + ".class" );
|
||||
}
|
||||
|
||||
// add package-info from the configured packages
|
||||
for ( String packageName : metadataSources.getAnnotatedPackages() ) {
|
||||
indexClass( indexer, packageName.replace( '.', '/' ) + "/package-info.class" );
|
||||
|
|
|
@ -31,6 +31,7 @@ import org.hibernate.internal.jaxb.mapping.hbm.JaxbColumnElement;
|
|||
import org.hibernate.internal.jaxb.mapping.hbm.JaxbIndexElement;
|
||||
import org.hibernate.internal.jaxb.mapping.hbm.JaxbListIndexElement;
|
||||
import org.hibernate.metamodel.spi.source.ExplicitHibernateTypeSource;
|
||||
import org.hibernate.metamodel.spi.source.PluralAttributeIndexNature;
|
||||
import org.hibernate.metamodel.spi.source.PluralAttributeIndexSource;
|
||||
import org.hibernate.metamodel.spi.source.RelationalValueSource;
|
||||
|
||||
|
@ -38,7 +39,6 @@ import org.hibernate.metamodel.spi.source.RelationalValueSource;
|
|||
*
|
||||
*/
|
||||
public class ListAttributeIndexSource extends AbstractHbmSourceNode implements PluralAttributeIndexSource {
|
||||
|
||||
private final List< RelationalValueSource > valueSources;
|
||||
private final ExplicitHibernateTypeSource typeSource;
|
||||
private final int base;
|
||||
|
@ -123,31 +123,16 @@ public class ListAttributeIndexSource extends AbstractHbmSourceNode implements P
|
|||
base = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @see org.hibernate.metamodel.spi.source.ColumnBindingDefaults#areValuesIncludedInInsertByDefault()
|
||||
*/
|
||||
@Override
|
||||
public boolean areValuesIncludedInInsertByDefault() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @see org.hibernate.metamodel.spi.source.ColumnBindingDefaults#areValuesIncludedInUpdateByDefault()
|
||||
*/
|
||||
@Override
|
||||
public boolean areValuesIncludedInUpdateByDefault() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @see org.hibernate.metamodel.spi.source.ColumnBindingDefaults#areValuesNullableByDefault()
|
||||
*/
|
||||
@Override
|
||||
public boolean areValuesNullableByDefault() {
|
||||
return false;
|
||||
|
@ -157,21 +142,16 @@ public class ListAttributeIndexSource extends AbstractHbmSourceNode implements P
|
|||
return base;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @see org.hibernate.metamodel.spi.source.PluralAttributeIndexSource#explicitHibernateTypeSource()
|
||||
*/
|
||||
@Override
|
||||
public PluralAttributeIndexNature getNature() {
|
||||
return PluralAttributeIndexNature.BASIC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExplicitHibernateTypeSource explicitHibernateTypeSource() {
|
||||
return typeSource;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @see org.hibernate.metamodel.spi.source.RelationalValueSourceContainer#relationalValueSources()
|
||||
*/
|
||||
@Override
|
||||
public List< RelationalValueSource > relationalValueSources() {
|
||||
return valueSources;
|
||||
|
|
|
@ -30,6 +30,7 @@ import org.hibernate.internal.jaxb.mapping.hbm.JaxbColumnElement;
|
|||
import org.hibernate.internal.jaxb.mapping.hbm.JaxbIndexElement;
|
||||
import org.hibernate.internal.jaxb.mapping.hbm.JaxbMapKeyElement;
|
||||
import org.hibernate.metamodel.spi.source.ExplicitHibernateTypeSource;
|
||||
import org.hibernate.metamodel.spi.source.PluralAttributeIndexNature;
|
||||
import org.hibernate.metamodel.spi.source.PluralAttributeIndexSource;
|
||||
import org.hibernate.metamodel.spi.source.RelationalValueSource;
|
||||
|
||||
|
@ -37,49 +38,48 @@ import org.hibernate.metamodel.spi.source.RelationalValueSource;
|
|||
*
|
||||
*/
|
||||
public class MapAttributeIndexSource extends AbstractHbmSourceNode implements PluralAttributeIndexSource {
|
||||
|
||||
private final List< RelationalValueSource > valueSources;
|
||||
private final PluralAttributeIndexNature nature;
|
||||
private final List<RelationalValueSource> valueSources;
|
||||
private final ExplicitHibernateTypeSource typeSource;
|
||||
|
||||
/**
|
||||
* @param sourceMappingDocument
|
||||
*/
|
||||
public MapAttributeIndexSource( MappingDocument sourceMappingDocument, final JaxbMapKeyElement mapKey ) {
|
||||
public MapAttributeIndexSource(MappingDocument sourceMappingDocument, final JaxbMapKeyElement mapKey) {
|
||||
super( sourceMappingDocument );
|
||||
valueSources = Helper.buildValueSources( sourceMappingDocument(), new Helper.ValueSourcesAdapter() {
|
||||
valueSources = Helper.buildValueSources(
|
||||
sourceMappingDocument(),
|
||||
new Helper.ValueSourcesAdapter() {
|
||||
|
||||
@Override
|
||||
public String getColumnAttribute() {
|
||||
return mapKey.getColumnAttribute();
|
||||
}
|
||||
@Override
|
||||
public String getColumnAttribute() {
|
||||
return mapKey.getColumnAttribute();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<JaxbColumnElement> getColumn() {
|
||||
return mapKey.getColumn();
|
||||
}
|
||||
@Override
|
||||
public List<JaxbColumnElement> getColumn() {
|
||||
return mapKey.getColumn();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getFormula() {
|
||||
return mapKey.getFormula();
|
||||
}
|
||||
@Override
|
||||
public List<String> getFormula() {
|
||||
return mapKey.getFormula();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFormulaAttribute() {
|
||||
return mapKey.getFormulaAttribute();
|
||||
}
|
||||
@Override
|
||||
public String getFormulaAttribute() {
|
||||
return mapKey.getFormulaAttribute();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIncludedInInsertByDefault() {
|
||||
return areValuesIncludedInInsertByDefault();
|
||||
}
|
||||
@Override
|
||||
public boolean isIncludedInInsertByDefault() {
|
||||
return areValuesIncludedInInsertByDefault();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIncludedInUpdateByDefault() {
|
||||
return areValuesIncludedInUpdateByDefault();
|
||||
}
|
||||
} );
|
||||
@Override
|
||||
public boolean isIncludedInUpdateByDefault() {
|
||||
return areValuesIncludedInUpdateByDefault();
|
||||
}
|
||||
}
|
||||
);
|
||||
this.typeSource = new ExplicitHibernateTypeSource() {
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
if ( mapKey.getTypeAttribute() != null ) {
|
||||
|
@ -92,99 +92,84 @@ public class MapAttributeIndexSource extends AbstractHbmSourceNode implements Pl
|
|||
}
|
||||
|
||||
@Override
|
||||
public Map< String, String > getParameters() {
|
||||
public Map<String, String> getParameters() {
|
||||
return mapKey.getType() != null
|
||||
? Helper.extractParameters( mapKey.getType().getParam() )
|
||||
: java.util.Collections.< String, String >emptyMap();
|
||||
: java.util.Collections.<String, String>emptyMap();
|
||||
}
|
||||
};
|
||||
this.nature = PluralAttributeIndexNature.BASIC;
|
||||
}
|
||||
|
||||
public MapAttributeIndexSource( MappingDocument sourceMappingDocument, final JaxbIndexElement indexElement ) {
|
||||
public MapAttributeIndexSource(MappingDocument sourceMappingDocument, final JaxbIndexElement indexElement) {
|
||||
super( sourceMappingDocument );
|
||||
valueSources = Helper.buildValueSources( sourceMappingDocument, new Helper.ValueSourcesAdapter() {
|
||||
valueSources = Helper.buildValueSources(
|
||||
sourceMappingDocument,
|
||||
new Helper.ValueSourcesAdapter() {
|
||||
|
||||
@Override
|
||||
public String getColumnAttribute() {
|
||||
return indexElement.getColumnAttribute();
|
||||
}
|
||||
@Override
|
||||
public String getColumnAttribute() {
|
||||
return indexElement.getColumnAttribute();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<JaxbColumnElement> getColumn() {
|
||||
return indexElement.getColumn();
|
||||
}
|
||||
@Override
|
||||
public List<JaxbColumnElement> getColumn() {
|
||||
return indexElement.getColumn();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIncludedInInsertByDefault() {
|
||||
return areValuesIncludedInInsertByDefault();
|
||||
}
|
||||
@Override
|
||||
public boolean isIncludedInInsertByDefault() {
|
||||
return areValuesIncludedInInsertByDefault();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIncludedInUpdateByDefault() {
|
||||
return areValuesIncludedInUpdateByDefault();
|
||||
}
|
||||
} );
|
||||
@Override
|
||||
public boolean isIncludedInUpdateByDefault() {
|
||||
return areValuesIncludedInUpdateByDefault();
|
||||
}
|
||||
}
|
||||
);
|
||||
typeSource = new ExplicitHibernateTypeSource() {
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return indexElement.getType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map< String, String > getParameters() {
|
||||
return java.util.Collections.< String, String >emptyMap();
|
||||
public Map<String, String> getParameters() {
|
||||
return java.util.Collections.<String, String>emptyMap();
|
||||
}
|
||||
};
|
||||
|
||||
this.nature = PluralAttributeIndexNature.BASIC;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @see org.hibernate.metamodel.spi.source.ColumnBindingDefaults#areValuesIncludedInInsertByDefault()
|
||||
*/
|
||||
@Override
|
||||
public boolean areValuesIncludedInInsertByDefault() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @see org.hibernate.metamodel.spi.source.ColumnBindingDefaults#areValuesIncludedInUpdateByDefault()
|
||||
*/
|
||||
@Override
|
||||
public boolean areValuesIncludedInUpdateByDefault() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @see org.hibernate.metamodel.spi.source.ColumnBindingDefaults#areValuesNullableByDefault()
|
||||
*/
|
||||
@Override
|
||||
public boolean areValuesNullableByDefault() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @see org.hibernate.metamodel.spi.source.PluralAttributeIndexSource#explicitHibernateTypeSource()
|
||||
*/
|
||||
@Override
|
||||
public PluralAttributeIndexNature getNature() {
|
||||
return nature;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExplicitHibernateTypeSource explicitHibernateTypeSource() {
|
||||
return typeSource;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @see org.hibernate.metamodel.spi.source.RelationalValueSourceContainer#relationalValueSources()
|
||||
*/
|
||||
@Override
|
||||
public List< RelationalValueSource > relationalValueSources() {
|
||||
public List<RelationalValueSource> relationalValueSources() {
|
||||
return valueSources;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,7 +51,8 @@ public class MapAttributeSource extends AbstractPluralAttributeSourceImpl implem
|
|||
JaxbMapKeyElement mapKey = mapElement.getMapKey();
|
||||
if ( mapKey != null ) {
|
||||
this.indexSource = new MapAttributeIndexSource( sourceMappingDocument, mapKey );
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
JaxbIndexElement indexElement = mapElement.getIndex();
|
||||
if ( indexElement != null ) {
|
||||
this.indexSource = new MapAttributeIndexSource( sourceMappingDocument, indexElement );
|
||||
|
|
|
@ -25,7 +25,6 @@ package org.hibernate.metamodel.spi.binding;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.AssertionFailure;
|
||||
|
|
|
@ -195,7 +195,8 @@ public interface AttributeBindingContainer {
|
|||
*
|
||||
*
|
||||
* @param attribute The attribute for which to make a binding.
|
||||
* @param nature The nature of the collection elements.
|
||||
* @param elementNature The nature of the collection elements.
|
||||
* @param indexNature The nature of the collection indexes.
|
||||
* @param referencedAttributeBinding
|
||||
* @param propertyAccessorName
|
||||
* @param includedInOptimisticLocking
|
||||
|
@ -205,7 +206,8 @@ public interface AttributeBindingContainer {
|
|||
*/
|
||||
public MapBinding makeMapAttributeBinding(
|
||||
PluralAttribute attribute,
|
||||
PluralAttributeElementNature nature,
|
||||
PluralAttributeElementNature elementNature,
|
||||
PluralAttributeIndexNature indexNature,
|
||||
SingularAttributeBinding referencedAttributeBinding,
|
||||
String propertyAccessorName,
|
||||
boolean includedInOptimisticLocking,
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
*/
|
||||
package org.hibernate.metamodel.spi.binding;
|
||||
|
||||
import org.hibernate.metamodel.spi.domain.IndexedPluralAttribute;
|
||||
import org.hibernate.metamodel.spi.domain.Type;
|
||||
import org.hibernate.metamodel.spi.relational.Value;
|
||||
|
||||
/**
|
||||
|
@ -30,48 +32,44 @@ import org.hibernate.metamodel.spi.relational.Value;
|
|||
*/
|
||||
public class BasicPluralAttributeIndexBinding implements PluralAttributeIndexBinding {
|
||||
|
||||
private final AbstractPluralAttributeBinding pluralAttributeBinding;
|
||||
private final IndexedPluralAttributeBinding pluralAttributeBinding;
|
||||
private final PluralAttributeIndexNature pluralAttributeIndexNature;
|
||||
private final HibernateTypeDescriptor hibernateTypeDescriptor = new HibernateTypeDescriptor();
|
||||
private Value value;
|
||||
|
||||
/**
|
||||
* @param pluralAttributeBinding
|
||||
*/
|
||||
public BasicPluralAttributeIndexBinding( final AbstractPluralAttributeBinding pluralAttributeBinding ) {
|
||||
public BasicPluralAttributeIndexBinding(
|
||||
IndexedPluralAttributeBinding pluralAttributeBinding,
|
||||
PluralAttributeIndexNature pluralAttributeIndexNature) {
|
||||
this.pluralAttributeBinding = pluralAttributeBinding;
|
||||
this.pluralAttributeIndexNature = pluralAttributeIndexNature;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @see org.hibernate.metamodel.spi.binding.PluralAttributeIndexBinding#getHibernateTypeDescriptor()
|
||||
*/
|
||||
@Override
|
||||
public HibernateTypeDescriptor getHibernateTypeDescriptor() {
|
||||
return hibernateTypeDescriptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @see org.hibernate.metamodel.spi.binding.PluralAttributeIndexBinding#getIndexRelationalValue()
|
||||
*/
|
||||
@Override
|
||||
public Value getIndexRelationalValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @see org.hibernate.metamodel.spi.binding.PluralAttributeIndexBinding#getPluralAttributeBinding()
|
||||
*/
|
||||
@Override
|
||||
public PluralAttributeBinding getPluralAttributeBinding() {
|
||||
public IndexedPluralAttributeBinding getPluralAttributeBinding() {
|
||||
return pluralAttributeBinding;
|
||||
}
|
||||
|
||||
public void setIndexRelationalValue( Value value ) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getPluralAttributeIndexType() {
|
||||
return ( (IndexedPluralAttribute) getPluralAttributeBinding().getAttribute() ).getIndexType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PluralAttributeIndexNature getPluralAttributeIndexNature() {
|
||||
return pluralAttributeIndexNature;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -348,7 +348,8 @@ public class CompositeAttributeBinding
|
|||
@Override
|
||||
public MapBinding makeMapAttributeBinding(
|
||||
PluralAttribute attribute,
|
||||
PluralAttributeElementNature nature,
|
||||
PluralAttributeElementNature elementNature,
|
||||
PluralAttributeIndexNature indexNature,
|
||||
SingularAttributeBinding referencedAttributeBinding,
|
||||
String propertyAccessorName,
|
||||
boolean includedInOptimisticLocking,
|
||||
|
@ -357,7 +358,8 @@ public class CompositeAttributeBinding
|
|||
final MapBinding binding = new MapBinding(
|
||||
this,
|
||||
attribute,
|
||||
nature,
|
||||
elementNature,
|
||||
indexNature,
|
||||
referencedAttributeBinding,
|
||||
propertyAccessorName,
|
||||
includedInOptimisticLocking,
|
||||
|
|
|
@ -643,7 +643,8 @@ public class EntityBinding implements AttributeBindingContainer {
|
|||
@Override
|
||||
public MapBinding makeMapAttributeBinding(
|
||||
PluralAttribute attribute,
|
||||
PluralAttributeElementNature nature,
|
||||
PluralAttributeElementNature elementNature,
|
||||
PluralAttributeIndexNature indexNature,
|
||||
SingularAttributeBinding referencedAttributeBinding,
|
||||
String propertyAccessorName,
|
||||
boolean includedInOptimisticLocking,
|
||||
|
@ -652,7 +653,8 @@ public class EntityBinding implements AttributeBindingContainer {
|
|||
final MapBinding binding = new MapBinding(
|
||||
this,
|
||||
attribute,
|
||||
nature,
|
||||
elementNature,
|
||||
indexNature,
|
||||
referencedAttributeBinding,
|
||||
propertyAccessorName,
|
||||
includedInOptimisticLocking,
|
||||
|
|
|
@ -51,7 +51,7 @@ public class ListBinding extends AbstractPluralAttributeBinding implements Index
|
|||
propertyAccessorName,
|
||||
includedInOptimisticLocking,
|
||||
metaAttributeContext );
|
||||
pluralAttributeIndexBinding = new BasicPluralAttributeIndexBinding( this );
|
||||
pluralAttributeIndexBinding = new BasicPluralAttributeIndexBinding( this, PluralAttributeIndexNature.BASIC );
|
||||
this.base = base;
|
||||
}
|
||||
|
||||
|
|
|
@ -37,6 +37,7 @@ public class MapBinding extends AbstractPluralAttributeBinding implements Indexe
|
|||
AttributeBindingContainer container,
|
||||
PluralAttribute attribute,
|
||||
PluralAttributeElementNature pluralAttributeElementNature,
|
||||
PluralAttributeIndexNature pluralAttributeIndexNature,
|
||||
SingularAttributeBinding referencedAttributeBinding,
|
||||
String propertyAccessorName,
|
||||
boolean includedInOptimisticLocking,
|
||||
|
@ -48,8 +49,9 @@ public class MapBinding extends AbstractPluralAttributeBinding implements Indexe
|
|||
referencedAttributeBinding,
|
||||
propertyAccessorName,
|
||||
includedInOptimisticLocking,
|
||||
metaAttributeContext );
|
||||
pluralAttributeIndexBinding = new BasicPluralAttributeIndexBinding( this );
|
||||
metaAttributeContext
|
||||
);
|
||||
pluralAttributeIndexBinding = new BasicPluralAttributeIndexBinding( this, pluralAttributeIndexNature );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -28,7 +28,6 @@ import java.util.List;
|
|||
|
||||
import org.hibernate.internal.FilterConfiguration;
|
||||
import org.hibernate.metamodel.spi.domain.PluralAttribute;
|
||||
import org.hibernate.metamodel.spi.relational.TableSpecification;
|
||||
import org.hibernate.persister.collection.CollectionPersister;
|
||||
|
||||
/**
|
||||
|
|
|
@ -23,16 +23,20 @@
|
|||
*/
|
||||
package org.hibernate.metamodel.spi.binding;
|
||||
|
||||
import org.hibernate.metamodel.spi.domain.Type;
|
||||
import org.hibernate.metamodel.spi.relational.Value;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface PluralAttributeIndexBinding {
|
||||
IndexedPluralAttributeBinding getPluralAttributeBinding();
|
||||
|
||||
PluralAttributeBinding getPluralAttributeBinding();
|
||||
PluralAttributeIndexNature getPluralAttributeIndexNature();
|
||||
|
||||
Value getIndexRelationalValue();
|
||||
|
||||
HibernateTypeDescriptor getHibernateTypeDescriptor();
|
||||
|
||||
Type getPluralAttributeIndexType();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2012, 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.spi.binding;
|
||||
|
||||
/**
|
||||
* Describes the nature of plural attribute indexes in terms of relational implications.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public enum PluralAttributeIndexNature {
|
||||
/**
|
||||
* The collection indexes are basic, simple values. This is the only valid nature for lists
|
||||
*/
|
||||
BASIC,
|
||||
/**
|
||||
* The map key is a composite
|
||||
*/
|
||||
COMPOSITE,
|
||||
/**
|
||||
* The map key is an association identified by a column(s) on the collection table.
|
||||
*/
|
||||
MANY_TO_MANY,
|
||||
/**
|
||||
* The map key is represented by a Hibernate ANY mapping
|
||||
*/
|
||||
MANY_TO_ANY
|
||||
}
|
|
@ -24,6 +24,7 @@
|
|||
package org.hibernate.metamodel.spi.binding;
|
||||
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.metamodel.spi.domain.Type;
|
||||
import org.hibernate.metamodel.spi.relational.Column;
|
||||
import org.hibernate.metamodel.spi.relational.ForeignKey;
|
||||
import org.hibernate.metamodel.spi.relational.TableSpecification;
|
||||
|
@ -67,6 +68,7 @@ public class PluralAttributeKeyBinding {
|
|||
public SingularAttributeBinding getReferencedAttributeBinding() {
|
||||
return referencedAttributeBinding;
|
||||
}
|
||||
|
||||
/**
|
||||
* The foreign key that defines the scope of this relationship.
|
||||
*
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2012, 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.spi.source;
|
||||
|
||||
/**
|
||||
* Describes the nature of the collection indexes as declared by the sources.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*
|
||||
* @see {@link org.hibernate.metamodel.spi.binding.PluralAttributeIndexNature}
|
||||
*/
|
||||
public enum PluralAttributeIndexNature {
|
||||
BASIC,
|
||||
COMPOSITE,
|
||||
MANY_TO_MANY,
|
||||
MANY_TO_ANY
|
||||
}
|
|
@ -27,6 +27,6 @@ package org.hibernate.metamodel.spi.source;
|
|||
*
|
||||
*/
|
||||
public interface PluralAttributeIndexSource extends RelationalValueSourceContainer {
|
||||
|
||||
PluralAttributeIndexNature getNature();
|
||||
ExplicitHibernateTypeSource explicitHibernateTypeSource();
|
||||
}
|
||||
|
|
|
@ -76,6 +76,15 @@ public class ServiceRegistryBuilder {
|
|||
this.configLoader = new ConfigLoader( bootstrapServiceRegistry );
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows access to the underlying boot-strap registry.
|
||||
*
|
||||
* @return The boot-strap registry
|
||||
*/
|
||||
public BootstrapServiceRegistry getBootstrapServiceRegistry() {
|
||||
return bootstrapServiceRegistry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used from the {@link #initiators} variable initializer
|
||||
*
|
||||
|
|
|
@ -31,7 +31,7 @@ package org.hibernate.jpa;
|
|||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface AvailableSettings {
|
||||
public interface AvailableSettings extends org.hibernate.cfg.AvailableSettings {
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// JPA defined settings
|
||||
|
@ -192,6 +192,17 @@ public interface AvailableSettings {
|
|||
// Hibernate specific settings
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
/**
|
||||
* Names a {@link org.hibernate.jpa.boot.spi.IntegratorProvider} to supply custom Integrator instances to
|
||||
* the underlying SessionFactory when built.
|
||||
*/
|
||||
public static final String INTEGRATOR_PROVIDER = "hibernate.integrator_provider";
|
||||
|
||||
/**
|
||||
* Names a Jandex {@link org.jboss.jandex.Index} instance to use, as opposed to Hibernate using its own.
|
||||
*/
|
||||
public static final String JANDEX_INDEX = "hibernate.jandex_index";
|
||||
|
||||
/**
|
||||
* Query hint (aka {@link javax.persistence.Query#setHint}) for applying
|
||||
* an alias specific lock mode (aka {@link org.hibernate.Query#setLockMode}).
|
||||
|
@ -292,7 +303,7 @@ public interface AvailableSettings {
|
|||
public static final String FLUSH_MODE = "org.hibernate.flushMode";
|
||||
|
||||
/**
|
||||
* Pass an implementation of {@link org.hibernate.ejb.packaging.Scanner}:
|
||||
* Pass an implementation of {@link org.hibernate.jpa.packaging.spi.Scanner}:
|
||||
* - preferably an actual instance
|
||||
* - or a class name with a no-arg constructor
|
||||
*/
|
||||
|
@ -315,30 +326,6 @@ public interface AvailableSettings {
|
|||
*/
|
||||
public static final String ENTITY_MANAGER_FACTORY_NAME = "hibernate.ejb.entitymanager_factory_name";
|
||||
|
||||
/**
|
||||
* @deprecated use {@link #JPA_METAMODEL_POPULATION} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public static final String JPA_METAMODEL_GENERATION = "hibernate.ejb.metamodel.generation";
|
||||
|
||||
/**
|
||||
* Setting that controls whether we seek out JPA "static metamodel" classes and populate them. Accepts
|
||||
* 3 values:<ul>
|
||||
* <li>
|
||||
* <b>enabled</b> - Do the population
|
||||
* </li>
|
||||
* <li>
|
||||
* <b>disabled</b> - Do not do the population
|
||||
* </li>
|
||||
* <li>
|
||||
* <b>ignoreUnsupported</b> - Do the population, but ignore any non-JPA features that would otherwise
|
||||
* result in the population failing.
|
||||
* </li>
|
||||
* </ul>
|
||||
*
|
||||
*/
|
||||
public static final String JPA_METAMODEL_POPULATION = "hibernate.ejb.metamodel.population";
|
||||
|
||||
|
||||
/**
|
||||
* List of classes names
|
||||
|
|
|
@ -42,9 +42,7 @@ import java.net.URL;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
@ -66,25 +64,24 @@ import org.hibernate.MappingException;
|
|||
import org.hibernate.MappingNotFoundException;
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.hibernate.SessionFactoryObserver;
|
||||
import org.hibernate.boot.spi.CacheRegionDefinition;
|
||||
import org.hibernate.boot.spi.JaccDefinition;
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.cfg.NamingStrategy;
|
||||
import org.hibernate.cfg.beanvalidation.BeanValidationIntegrator;
|
||||
import org.hibernate.id.factory.spi.MutableIdentifierGeneratorFactory;
|
||||
import org.hibernate.jpa.AvailableSettings;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.transaction.internal.jdbc.JdbcTransactionFactory;
|
||||
import org.hibernate.engine.transaction.internal.jta.CMTTransactionFactory;
|
||||
import org.hibernate.integrator.spi.Integrator;
|
||||
import org.hibernate.internal.jaxb.cfg.JaxbHibernateConfiguration;
|
||||
import org.hibernate.id.factory.spi.MutableIdentifierGeneratorFactory;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.internal.util.ValueHolder;
|
||||
import org.hibernate.jpa.AvailableSettings;
|
||||
import org.hibernate.jpa.boot.spi.EntityManagerFactoryBuilder;
|
||||
import org.hibernate.jpa.boot.spi.IntegratorProvider;
|
||||
import org.hibernate.jpa.boot.spi.JpaUnifiedSettingsBuilder;
|
||||
import org.hibernate.jpa.boot.spi.PersistenceUnitDescriptor;
|
||||
import org.hibernate.jpa.internal.EntityManagerFactoryImpl;
|
||||
import org.hibernate.jpa.internal.EntityManagerMessageLogger;
|
||||
import org.hibernate.jpa.internal.event.JpaIntegrator;
|
||||
import org.hibernate.jpa.internal.util.LogHelper;
|
||||
import org.hibernate.jpa.internal.util.PersistenceUnitTransactionTypeHelper;
|
||||
import org.hibernate.jpa.packaging.internal.NativeScanner;
|
||||
|
@ -96,13 +93,14 @@ import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper;
|
|||
import org.hibernate.proxy.EntityNotFoundDelegate;
|
||||
import org.hibernate.secure.internal.JACCConfiguration;
|
||||
import org.hibernate.service.BootstrapServiceRegistry;
|
||||
import org.hibernate.service.BootstrapServiceRegistryBuilder;
|
||||
import org.hibernate.service.ConfigLoader;
|
||||
import org.hibernate.service.ServiceRegistry;
|
||||
import org.hibernate.service.ServiceRegistryBuilder;
|
||||
import org.hibernate.service.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.service.spi.ServiceRegistryImplementor;
|
||||
|
||||
import static org.hibernate.internal.jaxb.cfg.JaxbHibernateConfiguration.JaxbSessionFactory.JaxbMapping;
|
||||
import static org.hibernate.jpa.boot.spi.JpaBootstrapServiceRegistryBuilder.buildBootstrapServiceRegistry;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
|
@ -137,7 +135,7 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
|
|||
private final List<JaccDefinition> jaccDefinitions = new ArrayList<JaccDefinition>();
|
||||
private final List<CacheRegionDefinition> cacheRegionDefinitions = new ArrayList<CacheRegionDefinition>();
|
||||
// todo : would much prefer this as a local variable...
|
||||
private final List<JaxbHibernateConfiguration.JaxbSessionFactory.JaxbMapping> cfgXmlNamedMappings = new ArrayList<JaxbHibernateConfiguration.JaxbSessionFactory.JaxbMapping>();
|
||||
private final List<JaxbMapping> cfgXmlNamedMappings = new ArrayList<JaxbMapping>();
|
||||
private Interceptor sessionFactoryInterceptor;
|
||||
private NamingStrategy namingStrategy;
|
||||
private SessionFactoryObserver suppliedSessionFactoryObserver;
|
||||
|
@ -164,7 +162,7 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
|
|||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// First we build the boot-strap service registry, which mainly handles class loader interactions
|
||||
final BootstrapServiceRegistry bootstrapServiceRegistry = buildBootstrapServiceRegistry( integrationSettings );
|
||||
final BootstrapServiceRegistry bootstrapServiceRegistry = buildBootstrapServiceRegistry( persistenceUnit, integrationSettings );
|
||||
// And the main service registry. This is needed to start adding configuration values, etc
|
||||
this.serviceRegistryBuilder = new ServiceRegistryBuilder( bootstrapServiceRegistry );
|
||||
|
||||
|
@ -195,6 +193,25 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
|
|||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Map mergePropertySources(
|
||||
PersistenceUnitDescriptor persistenceUnit,
|
||||
Map integrationSettings,
|
||||
final BootstrapServiceRegistry bootstrapServiceRegistry) {
|
||||
|
||||
JpaUnifiedSettingsBuilder.Result mergedResult = JpaUnifiedSettingsBuilder.mergePropertySources(
|
||||
persistenceUnit,
|
||||
integrationSettings,
|
||||
bootstrapServiceRegistry
|
||||
);
|
||||
|
||||
cfgXmlNamedMappings.addAll( mergedResult.getCfgXmlMappingArtifacts().getMappings() );
|
||||
cacheRegionDefinitions.addAll( mergedResult.getCfgXmlMappingArtifacts().getCacheRegionDefinitions() );
|
||||
jaccDefinitions.addAll( mergedResult.getCfgXmlMappingArtifacts().getJaccDefinitions() );
|
||||
|
||||
return mergedResult.getSettings();
|
||||
}
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// temporary!
|
||||
public Map<?, ?> getConfigurationValues() {
|
||||
|
@ -306,7 +323,9 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
|
|||
}
|
||||
|
||||
private void indexResource(String resourceName, Indexer indexer, BootstrapServiceRegistry bootstrapServiceRegistry) {
|
||||
InputStream stream = bootstrapServiceRegistry.getService( ClassLoaderService.class ).locateResourceStream( resourceName );
|
||||
InputStream stream = bootstrapServiceRegistry.getService( ClassLoaderService.class ).locateResourceStream(
|
||||
resourceName
|
||||
);
|
||||
try {
|
||||
indexer.index( stream );
|
||||
}
|
||||
|
@ -315,174 +334,6 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the {@link BootstrapServiceRegistry} used to eventually build the {@link ServiceRegistryBuilder}; mainly
|
||||
* used here during instantiation to define class-loading behavior.
|
||||
*
|
||||
* @param integrationSettings Any integration settings passed by the EE container or SE application
|
||||
*
|
||||
* @return The built BootstrapServiceRegistry
|
||||
*/
|
||||
private BootstrapServiceRegistry buildBootstrapServiceRegistry(Map integrationSettings) {
|
||||
final BootstrapServiceRegistryBuilder bootstrapServiceRegistryBuilder = new BootstrapServiceRegistryBuilder();
|
||||
bootstrapServiceRegistryBuilder.with( new JpaIntegrator() );
|
||||
|
||||
final IntegratorProvider integratorProvider = (IntegratorProvider) integrationSettings.get( INTEGRATOR_PROVIDER );
|
||||
if ( integratorProvider != null ) {
|
||||
integrationSettings.remove( INTEGRATOR_PROVIDER );
|
||||
for ( Integrator integrator : integratorProvider.getIntegrators() ) {
|
||||
bootstrapServiceRegistryBuilder.with( integrator );
|
||||
}
|
||||
}
|
||||
|
||||
ClassLoader classLoader = (ClassLoader) integrationSettings.get( org.hibernate.cfg.AvailableSettings.APP_CLASSLOADER );
|
||||
if ( classLoader != null ) {
|
||||
integrationSettings.remove( org.hibernate.cfg.AvailableSettings.APP_CLASSLOADER );
|
||||
}
|
||||
else {
|
||||
classLoader = persistenceUnit.getClassLoader();
|
||||
}
|
||||
bootstrapServiceRegistryBuilder.withApplicationClassLoader( classLoader );
|
||||
|
||||
return bootstrapServiceRegistryBuilder.build();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Map mergePropertySources(
|
||||
PersistenceUnitDescriptor persistenceUnit,
|
||||
Map integrationSettings,
|
||||
final BootstrapServiceRegistry bootstrapServiceRegistry) {
|
||||
final Map merged = new HashMap();
|
||||
// first, apply persistence.xml-defined settings
|
||||
if ( persistenceUnit.getProperties() != null ) {
|
||||
merged.putAll( persistenceUnit.getProperties() );
|
||||
}
|
||||
|
||||
merged.put( AvailableSettings.PERSISTENCE_UNIT_NAME, persistenceUnit.getName() );
|
||||
|
||||
// see if the persistence.xml settings named a Hibernate config file....
|
||||
final ValueHolder<ConfigLoader> configLoaderHolder = new ValueHolder<ConfigLoader>(
|
||||
new ValueHolder.DeferredInitializer<ConfigLoader>() {
|
||||
@Override
|
||||
public ConfigLoader initialize() {
|
||||
return new ConfigLoader( bootstrapServiceRegistry );
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
{
|
||||
final String cfgXmlResourceName = (String) merged.remove( AvailableSettings.CFG_FILE );
|
||||
if ( StringHelper.isNotEmpty( cfgXmlResourceName ) ) {
|
||||
// it does, so load those properties
|
||||
JaxbHibernateConfiguration configurationElement = configLoaderHolder.getValue()
|
||||
.loadConfigXmlResource( cfgXmlResourceName );
|
||||
processHibernateConfigurationElement( configurationElement, merged );
|
||||
}
|
||||
}
|
||||
|
||||
// see if integration settings named a Hibernate config file....
|
||||
{
|
||||
final String cfgXmlResourceName = (String) integrationSettings.get( AvailableSettings.CFG_FILE );
|
||||
if ( StringHelper.isNotEmpty( cfgXmlResourceName ) ) {
|
||||
integrationSettings.remove( AvailableSettings.CFG_FILE );
|
||||
// it does, so load those properties
|
||||
JaxbHibernateConfiguration configurationElement = configLoaderHolder.getValue().loadConfigXmlResource(
|
||||
cfgXmlResourceName
|
||||
);
|
||||
processHibernateConfigurationElement( configurationElement, merged );
|
||||
}
|
||||
}
|
||||
|
||||
// finally, apply integration-supplied settings (per JPA spec, integration settings should override other sources)
|
||||
merged.putAll( integrationSettings );
|
||||
|
||||
if ( ! merged.containsKey( AvailableSettings.VALIDATION_MODE ) ) {
|
||||
if ( persistenceUnit.getValidationMode() != null ) {
|
||||
merged.put( AvailableSettings.VALIDATION_MODE, persistenceUnit.getValidationMode() );
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! merged.containsKey( AvailableSettings.SHARED_CACHE_MODE ) ) {
|
||||
if ( persistenceUnit.getSharedCacheMode() != null ) {
|
||||
merged.put( AvailableSettings.SHARED_CACHE_MODE, persistenceUnit.getSharedCacheMode() );
|
||||
}
|
||||
}
|
||||
|
||||
// was getting NPE exceptions from the underlying map when just using #putAll, so going this safer route...
|
||||
Iterator itr = merged.entrySet().iterator();
|
||||
while ( itr.hasNext() ) {
|
||||
final Map.Entry entry = (Map.Entry) itr.next();
|
||||
if ( entry.getValue() == null ) {
|
||||
itr.remove();
|
||||
}
|
||||
}
|
||||
|
||||
return merged;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void processHibernateConfigurationElement(
|
||||
JaxbHibernateConfiguration configurationElement,
|
||||
Map mergeMap) {
|
||||
if ( ! mergeMap.containsKey( org.hibernate.cfg.AvailableSettings.SESSION_FACTORY_NAME ) ) {
|
||||
String cfgName = configurationElement.getSessionFactory().getName();
|
||||
if ( cfgName != null ) {
|
||||
mergeMap.put( org.hibernate.cfg.AvailableSettings.SESSION_FACTORY_NAME, cfgName );
|
||||
}
|
||||
}
|
||||
|
||||
for ( JaxbHibernateConfiguration.JaxbSessionFactory.JaxbProperty jaxbProperty : configurationElement.getSessionFactory().getProperty() ) {
|
||||
mergeMap.put( jaxbProperty.getName(), jaxbProperty.getValue() );
|
||||
}
|
||||
|
||||
for ( JaxbHibernateConfiguration.JaxbSessionFactory.JaxbMapping jaxbMapping : configurationElement.getSessionFactory().getMapping() ) {
|
||||
cfgXmlNamedMappings.add( jaxbMapping );
|
||||
}
|
||||
|
||||
for ( Object cacheDeclaration : configurationElement.getSessionFactory().getClassCacheOrCollectionCache() ) {
|
||||
if ( JaxbHibernateConfiguration.JaxbSessionFactory.JaxbClassCache.class.isInstance( cacheDeclaration ) ) {
|
||||
final JaxbHibernateConfiguration.JaxbSessionFactory.JaxbClassCache jaxbClassCache
|
||||
= (JaxbHibernateConfiguration.JaxbSessionFactory.JaxbClassCache) cacheDeclaration;
|
||||
cacheRegionDefinitions.add(
|
||||
new CacheRegionDefinition(
|
||||
CacheRegionDefinition.CacheType.ENTITY,
|
||||
jaxbClassCache.getClazz(),
|
||||
jaxbClassCache.getUsage().value(),
|
||||
jaxbClassCache.getRegion(),
|
||||
"all".equals( jaxbClassCache.getInclude() )
|
||||
)
|
||||
);
|
||||
}
|
||||
else {
|
||||
final JaxbHibernateConfiguration.JaxbSessionFactory.JaxbCollectionCache jaxbCollectionCache
|
||||
= (JaxbHibernateConfiguration.JaxbSessionFactory.JaxbCollectionCache) cacheDeclaration;
|
||||
cacheRegionDefinitions.add(
|
||||
new CacheRegionDefinition(
|
||||
CacheRegionDefinition.CacheType.COLLECTION,
|
||||
jaxbCollectionCache.getCollection(),
|
||||
jaxbCollectionCache.getUsage().value(),
|
||||
jaxbCollectionCache.getRegion(),
|
||||
false
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if ( configurationElement.getSecurity() != null ) {
|
||||
final String contextId = configurationElement.getSecurity().getContext();
|
||||
for ( JaxbHibernateConfiguration.JaxbSecurity.JaxbGrant grant : configurationElement.getSecurity().getGrant() ) {
|
||||
jaccDefinitions.add(
|
||||
new JaccDefinition(
|
||||
contextId,
|
||||
grant.getRole(),
|
||||
grant.getEntityName(),
|
||||
grant.getActions()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void processProperties(BootstrapServiceRegistry bootstrapServiceRegistry) {
|
||||
applyJdbcConnectionProperties();
|
||||
applyTransactionProperties();
|
||||
|
@ -535,14 +386,14 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
|
|||
addCacheRegionDefinition(
|
||||
keyString.substring( AvailableSettings.CLASS_CACHE_PREFIX.length() + 1 ),
|
||||
(String) entry.getValue(),
|
||||
CacheRegionDefinition.CacheType.ENTITY
|
||||
CacheRegionDefinition.CacheRegionType.ENTITY
|
||||
);
|
||||
}
|
||||
else if ( keyString.startsWith( AvailableSettings.COLLECTION_CACHE_PREFIX ) ) {
|
||||
addCacheRegionDefinition(
|
||||
keyString.substring( AvailableSettings.COLLECTION_CACHE_PREFIX.length() + 1 ),
|
||||
(String) entry.getValue(),
|
||||
CacheRegionDefinition.CacheType.COLLECTION
|
||||
CacheRegionDefinition.CacheRegionType.COLLECTION
|
||||
);
|
||||
}
|
||||
else if ( keyString.startsWith( AvailableSettings.JACC_PREFIX )
|
||||
|
@ -665,11 +516,11 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
|
|||
}
|
||||
}
|
||||
|
||||
private void addCacheRegionDefinition(String role, String value, CacheRegionDefinition.CacheType cacheType) {
|
||||
private void addCacheRegionDefinition(String role, String value, CacheRegionDefinition.CacheRegionType cacheType) {
|
||||
final StringTokenizer params = new StringTokenizer( value, ";, " );
|
||||
if ( !params.hasMoreTokens() ) {
|
||||
StringBuilder error = new StringBuilder( "Illegal usage of " );
|
||||
if ( cacheType == CacheRegionDefinition.CacheType.ENTITY ) {
|
||||
if ( cacheType == CacheRegionDefinition.CacheRegionType.ENTITY ) {
|
||||
error.append( AvailableSettings.CLASS_CACHE_PREFIX )
|
||||
.append( ": " )
|
||||
.append( AvailableSettings.CLASS_CACHE_PREFIX );
|
||||
|
@ -693,7 +544,7 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
|
|||
region = params.nextToken();
|
||||
}
|
||||
boolean lazyProperty = true;
|
||||
if ( cacheType == CacheRegionDefinition.CacheType.ENTITY ) {
|
||||
if ( cacheType == CacheRegionDefinition.CacheRegionType.ENTITY ) {
|
||||
if ( params.hasMoreTokens() ) {
|
||||
lazyProperty = "all".equalsIgnoreCase( params.nextToken() );
|
||||
}
|
||||
|
@ -973,26 +824,30 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
|
|||
|
||||
if ( jaccDefinitions != null ) {
|
||||
for ( JaccDefinition jaccDefinition : jaccDefinitions ) {
|
||||
JACCConfiguration jaccCfg = new JACCConfiguration( jaccDefinition.contextId );
|
||||
jaccCfg.addPermission( jaccDefinition.role, jaccDefinition.clazz, jaccDefinition.actions );
|
||||
JACCConfiguration jaccCfg = new JACCConfiguration( jaccDefinition.getContextId() );
|
||||
jaccCfg.addPermission(
|
||||
jaccDefinition.getRole(),
|
||||
jaccDefinition.getClazz(),
|
||||
jaccDefinition.getActions()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if ( cacheRegionDefinitions != null ) {
|
||||
for ( CacheRegionDefinition cacheRegionDefinition : cacheRegionDefinitions ) {
|
||||
if ( cacheRegionDefinition.cacheType == CacheRegionDefinition.CacheType.ENTITY ) {
|
||||
if ( cacheRegionDefinition.getRegionType() == CacheRegionDefinition.CacheRegionType.ENTITY ) {
|
||||
cfg.setCacheConcurrencyStrategy(
|
||||
cacheRegionDefinition.role,
|
||||
cacheRegionDefinition.usage,
|
||||
cacheRegionDefinition.region,
|
||||
cacheRegionDefinition.cacheLazy
|
||||
cacheRegionDefinition.getRole(),
|
||||
cacheRegionDefinition.getUsage(),
|
||||
cacheRegionDefinition.getRegion(),
|
||||
cacheRegionDefinition.isCacheLazy()
|
||||
);
|
||||
}
|
||||
else {
|
||||
cfg.setCollectionCacheConcurrencyStrategy(
|
||||
cacheRegionDefinition.role,
|
||||
cacheRegionDefinition.usage,
|
||||
cacheRegionDefinition.region
|
||||
cacheRegionDefinition.getRole(),
|
||||
cacheRegionDefinition.getUsage(),
|
||||
cacheRegionDefinition.getRegion()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1001,7 +856,7 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
|
|||
|
||||
// todo : need to have this use the metamodel codebase eventually...
|
||||
|
||||
for ( JaxbHibernateConfiguration.JaxbSessionFactory.JaxbMapping jaxbMapping : cfgXmlNamedMappings ) {
|
||||
for ( JaxbMapping jaxbMapping : cfgXmlNamedMappings ) {
|
||||
if ( jaxbMapping.getClazz() != null ) {
|
||||
cfg.addAnnotatedClass(
|
||||
serviceRegistry.getService( ClassLoaderService.class ).classForName( jaxbMapping.getClazz() )
|
||||
|
@ -1125,42 +980,6 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
|
|||
return "[PersistenceUnit: " + persistenceUnit.getName() + "] ";
|
||||
}
|
||||
|
||||
public static class CacheRegionDefinition {
|
||||
public static enum CacheType { ENTITY, COLLECTION }
|
||||
|
||||
public final CacheType cacheType;
|
||||
public final String role;
|
||||
public final String usage;
|
||||
public final String region;
|
||||
public final boolean cacheLazy;
|
||||
|
||||
public CacheRegionDefinition(
|
||||
CacheType cacheType,
|
||||
String role,
|
||||
String usage,
|
||||
String region, boolean cacheLazy) {
|
||||
this.cacheType = cacheType;
|
||||
this.role = role;
|
||||
this.usage = usage;
|
||||
this.region = region;
|
||||
this.cacheLazy = cacheLazy;
|
||||
}
|
||||
}
|
||||
|
||||
public static class JaccDefinition {
|
||||
public final String contextId;
|
||||
public final String role;
|
||||
public final String clazz;
|
||||
public final String actions;
|
||||
|
||||
public JaccDefinition(String contextId, String role, String clazz, String actions) {
|
||||
this.contextId = contextId;
|
||||
this.role = role;
|
||||
this.clazz = clazz;
|
||||
this.actions = actions;
|
||||
}
|
||||
}
|
||||
|
||||
public static class ScanningContext {
|
||||
private URL url;
|
||||
private boolean detectClasses;
|
||||
|
|
|
@ -0,0 +1,661 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2012, 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.jpa.boot.internal;
|
||||
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
import javax.persistence.EntityNotFoundException;
|
||||
import javax.persistence.PersistenceException;
|
||||
import javax.persistence.SharedCacheMode;
|
||||
import javax.persistence.spi.PersistenceUnitTransactionType;
|
||||
import java.io.File;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.CustomEntityDirtinessStrategy;
|
||||
import org.hibernate.EntityNameResolver;
|
||||
import org.hibernate.Interceptor;
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.hibernate.SessionFactoryObserver;
|
||||
import org.hibernate.boot.spi.CacheRegionDefinition;
|
||||
import org.hibernate.boot.spi.JaccDefinition;
|
||||
import org.hibernate.cache.spi.access.AccessType;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.cfg.MetadataSourceType;
|
||||
import org.hibernate.cfg.NamingStrategy;
|
||||
import org.hibernate.cfg.beanvalidation.BeanValidationIntegrator;
|
||||
import org.hibernate.context.spi.CurrentTenantIdentifierResolver;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.transaction.internal.jdbc.JdbcTransactionFactory;
|
||||
import org.hibernate.engine.transaction.internal.jta.CMTTransactionFactory;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.internal.util.config.ConfigurationHelper;
|
||||
import org.hibernate.jpa.AvailableSettings;
|
||||
import org.hibernate.jpa.boot.spi.EntityManagerFactoryBuilder;
|
||||
import org.hibernate.jpa.boot.spi.JpaUnifiedSettingsBuilder;
|
||||
import org.hibernate.jpa.boot.spi.PersistenceUnitDescriptor;
|
||||
import org.hibernate.jpa.boot.spi.Settings;
|
||||
import org.hibernate.jpa.internal.EntityManagerFactoryImpl;
|
||||
import org.hibernate.jpa.internal.EntityManagerMessageLogger;
|
||||
import org.hibernate.jpa.internal.util.LogHelper;
|
||||
import org.hibernate.jpa.internal.util.PersistenceUnitTransactionTypeHelper;
|
||||
import org.hibernate.jpa.internal.util.SharedCacheModeHelper;
|
||||
import org.hibernate.metamodel.Metadata;
|
||||
import org.hibernate.metamodel.MetadataBuilder;
|
||||
import org.hibernate.metamodel.MetadataSourceProcessingOrder;
|
||||
import org.hibernate.metamodel.MetadataSources;
|
||||
import org.hibernate.metamodel.SessionFactoryBuilder;
|
||||
import org.hibernate.proxy.EntityNotFoundDelegate;
|
||||
import org.hibernate.service.BootstrapServiceRegistry;
|
||||
import org.hibernate.service.ServiceRegistry;
|
||||
import org.hibernate.service.ServiceRegistryBuilder;
|
||||
import org.hibernate.service.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.service.spi.ServiceRegistryImplementor;
|
||||
|
||||
import static org.hibernate.internal.jaxb.cfg.JaxbHibernateConfiguration.JaxbSessionFactory.JaxbMapping;
|
||||
import static org.hibernate.jpa.boot.spi.JpaBootstrapServiceRegistryBuilder.buildBootstrapServiceRegistry;
|
||||
import static org.hibernate.jpa.boot.spi.JpaUnifiedSettingsBuilder.CfgXmlMappingArtifacts;
|
||||
|
||||
/**
|
||||
* This will eventually replace {@link EntityManagerFactoryBuilderImpl}
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*
|
||||
* @deprecated This class will go away before 5.0 even goes alpha and its functionality will replace that in
|
||||
* {@link EntityManagerFactoryBuilderImpl}.
|
||||
*/
|
||||
@Deprecated
|
||||
public class EntityManagerFactoryBuilderUsingMetamodelImpl implements EntityManagerFactoryBuilder {
|
||||
private static final EntityManagerMessageLogger LOG = Logger.getMessageLogger(
|
||||
EntityManagerMessageLogger.class,
|
||||
EntityManagerFactoryBuilderImpl.class.getName()
|
||||
);
|
||||
|
||||
private final PersistenceUnitDescriptor persistenceUnit;
|
||||
private final Map<?,?> configurationValues;
|
||||
|
||||
private final BootstrapServiceRegistry bootstrapServiceRegistry;
|
||||
private final MetadataSources metadataSources;
|
||||
|
||||
private final List<JaccDefinition> jaccDefinitions = new ArrayList<JaccDefinition>(); // todo : see HHH-7462
|
||||
private final List<CacheRegionDefinition> cacheRegionDefinitions = new ArrayList<CacheRegionDefinition>();
|
||||
|
||||
public EntityManagerFactoryBuilderUsingMetamodelImpl(
|
||||
PersistenceUnitDescriptor persistenceUnit,
|
||||
Map integrationSettings) {
|
||||
LogHelper.logPersistenceUnitInformation( persistenceUnit );
|
||||
|
||||
this.persistenceUnit = persistenceUnit;
|
||||
if ( integrationSettings == null ) {
|
||||
integrationSettings = Collections.emptyMap();
|
||||
}
|
||||
|
||||
// build the boot-strap service registry, which mainly handles class loader interactions
|
||||
this.bootstrapServiceRegistry = buildBootstrapServiceRegistry(
|
||||
persistenceUnit,
|
||||
integrationSettings
|
||||
);
|
||||
|
||||
final JpaUnifiedSettingsBuilder.Result mergedResult = JpaUnifiedSettingsBuilder.mergePropertySources(
|
||||
persistenceUnit,
|
||||
integrationSettings,
|
||||
bootstrapServiceRegistry
|
||||
);
|
||||
|
||||
final CfgXmlMappingArtifacts cfgXmlMappingArtifacts = mergedResult.getCfgXmlMappingArtifacts();
|
||||
this.configurationValues = mergedResult.getSettings();
|
||||
|
||||
// todo : add scanning...
|
||||
|
||||
this.metadataSources = new MetadataSources( bootstrapServiceRegistry );
|
||||
for ( JaxbMapping jaxbMapping : cfgXmlMappingArtifacts.getMappings() ) {
|
||||
if ( jaxbMapping.getClazz() != null ) {
|
||||
metadataSources.addAnnotatedClassName( jaxbMapping.getClazz() );
|
||||
}
|
||||
else if ( jaxbMapping.getResource() != null ) {
|
||||
metadataSources.addResource( jaxbMapping.getResource() );
|
||||
}
|
||||
else if ( jaxbMapping.getJar() != null ) {
|
||||
metadataSources.addJar( new File( jaxbMapping.getJar() ) );
|
||||
}
|
||||
else if ( jaxbMapping.getPackage() != null ) {
|
||||
metadataSources.addPackage( jaxbMapping.getPackage() );
|
||||
}
|
||||
}
|
||||
|
||||
// todo : add results of scanning to the MetadataSources
|
||||
|
||||
metadataSources.addCacheRegionDefinitions( cacheRegionDefinitions );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
// currently nothing to do...
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityManagerFactory buildEntityManagerFactory() {
|
||||
final ServiceRegistryBuilder serviceRegistryBuilder = new ServiceRegistryBuilder( bootstrapServiceRegistry );
|
||||
final SpecialProperties specialProperties = processProperties( serviceRegistryBuilder );
|
||||
|
||||
final MetadataBuilder metadataBuilder = metadataSources.getMetadataBuilder();
|
||||
prepareMetadataBuilder( metadataBuilder, specialProperties );
|
||||
final Metadata metadata = metadataBuilder.buildMetadata();
|
||||
|
||||
final SessionFactoryBuilder sessionFactoryBuilder = metadata.getSessionFactoryBuilder();
|
||||
prepareSessionFactoryBuilder( sessionFactoryBuilder, specialProperties );
|
||||
sessionFactoryBuilder.add( new ServiceRegistryCloser() );
|
||||
SessionFactoryImplementor sessionFactory = (SessionFactoryImplementor) sessionFactoryBuilder.buildSessionFactory();
|
||||
|
||||
final Settings emfCreationSettings = prepareEntitytManagerFactoryCreationSettings( specialProperties );
|
||||
|
||||
// IMPL NOTE : the last param (passed as null) is the Configuration which we pass in at the moment solely to
|
||||
// get access to the mapping information in order to build the JPA javax.persistence.metamodel.Metamodel
|
||||
// We need to change that to leverage the new Hibernate Metadata metamodel package anyway..
|
||||
|
||||
return new EntityManagerFactoryImpl(
|
||||
persistenceUnit.getName(),
|
||||
sessionFactory,
|
||||
(SettingsImpl) emfCreationSettings,
|
||||
configurationValues,
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
private SpecialProperties processProperties(ServiceRegistryBuilder serviceRegistryBuilder) {
|
||||
final SpecialProperties specialProperties = new SpecialProperties();
|
||||
|
||||
applyJdbcConnectionProperties( serviceRegistryBuilder );
|
||||
applyTransactionProperties( serviceRegistryBuilder, specialProperties );
|
||||
|
||||
final Object validationFactory = configurationValues.get( AvailableSettings.VALIDATION_FACTORY );
|
||||
if ( validationFactory != null ) {
|
||||
BeanValidationIntegrator.validateFactory( validationFactory );
|
||||
}
|
||||
|
||||
// flush before completion validation
|
||||
if ( "true".equals( configurationValues.get( Environment.FLUSH_BEFORE_COMPLETION ) ) ) {
|
||||
serviceRegistryBuilder.applySetting( Environment.FLUSH_BEFORE_COMPLETION, "false" );
|
||||
LOG.definingFlushBeforeCompletionIgnoredInHem( Environment.FLUSH_BEFORE_COMPLETION );
|
||||
}
|
||||
|
||||
for ( Map.Entry entry : configurationValues.entrySet() ) {
|
||||
if ( entry.getKey() instanceof String ) {
|
||||
final String keyString = (String) entry.getKey();
|
||||
|
||||
//noinspection deprecation
|
||||
if ( AvailableSettings.INTERCEPTOR.equals( keyString )
|
||||
|| org.hibernate.cfg.AvailableSettings.INTERCEPTOR.equals( keyString ) ) {
|
||||
specialProperties.sessionFactoryInterceptor = instantiateCustomClassFromConfiguration(
|
||||
entry.getValue(),
|
||||
Interceptor.class,
|
||||
bootstrapServiceRegistry
|
||||
);
|
||||
}
|
||||
else if ( AvailableSettings.SESSION_INTERCEPTOR.equals( keyString ) ) {
|
||||
specialProperties.sessionInterceptorClass = loadSessionInterceptorClass(
|
||||
entry.getValue(),
|
||||
bootstrapServiceRegistry
|
||||
);
|
||||
}
|
||||
else if ( AvailableSettings.NAMING_STRATEGY.equals( keyString ) ) {
|
||||
specialProperties.namingStrategy = instantiateCustomClassFromConfiguration(
|
||||
entry.getValue(),
|
||||
NamingStrategy.class,
|
||||
bootstrapServiceRegistry
|
||||
);
|
||||
}
|
||||
else if ( AvailableSettings.SESSION_FACTORY_OBSERVER.equals( keyString ) ) {
|
||||
specialProperties.sessionFactoryObserver = instantiateCustomClassFromConfiguration(
|
||||
entry.getValue(),
|
||||
SessionFactoryObserver.class,
|
||||
bootstrapServiceRegistry
|
||||
);
|
||||
}
|
||||
else if ( org.hibernate.cfg.AvailableSettings.CUSTOM_ENTITY_DIRTINESS_STRATEGY.equals( keyString ) ) {
|
||||
specialProperties.customEntityDirtinessStrategy = instantiateCustomClassFromConfiguration(
|
||||
entry.getValue(),
|
||||
CustomEntityDirtinessStrategy.class,
|
||||
bootstrapServiceRegistry
|
||||
);
|
||||
}
|
||||
else if ( org.hibernate.cfg.AvailableSettings.MULTI_TENANT_IDENTIFIER_RESOLVER.equals( keyString ) ) {
|
||||
specialProperties.currentTenantIdentifierResolver = instantiateCustomClassFromConfiguration(
|
||||
entry.getValue(),
|
||||
CurrentTenantIdentifierResolver.class,
|
||||
bootstrapServiceRegistry
|
||||
);
|
||||
}
|
||||
else if ( AvailableSettings.DISCARD_PC_ON_CLOSE.equals( keyString ) ) {
|
||||
specialProperties.releaseResourcesOnClose = ( "true".equals( entry.getValue() ) );
|
||||
}
|
||||
else if ( AvailableSettings.SHARED_CACHE_MODE.equals( keyString ) ) {
|
||||
specialProperties.sharedCacheMode = SharedCacheModeHelper.asSharedCacheMode( entry.getValue() );
|
||||
}
|
||||
else if ( org.hibernate.cfg.AvailableSettings.METADATA_PROCESSING_ORDER.equals( keyString ) ) {
|
||||
specialProperties.sourceProcessingOrder = interpretSourceProcessingOrder( entry.getValue() );
|
||||
}
|
||||
else if ( org.hibernate.cfg.AvailableSettings.DEFAULT_CACHE_CONCURRENCY_STRATEGY.equals( keyString ) ) {
|
||||
specialProperties.defaultCacheAccessType = interpretCacheAccessStrategy( entry.getValue() );
|
||||
}
|
||||
else if ( org.hibernate.cfg.AvailableSettings.USE_NEW_ID_GENERATOR_MAPPINGS.equals( keyString ) ) {
|
||||
specialProperties.useEnhancedGenerators = ConfigurationHelper.asBoolean( entry.getValue() );
|
||||
}
|
||||
else if ( keyString.startsWith( AvailableSettings.CLASS_CACHE_PREFIX ) ) {
|
||||
addCacheRegionDefinition(
|
||||
keyString.substring( AvailableSettings.CLASS_CACHE_PREFIX.length() + 1 ),
|
||||
(String) entry.getValue(),
|
||||
CacheRegionDefinition.CacheRegionType.ENTITY
|
||||
);
|
||||
}
|
||||
else if ( keyString.startsWith( AvailableSettings.COLLECTION_CACHE_PREFIX ) ) {
|
||||
addCacheRegionDefinition(
|
||||
keyString.substring( AvailableSettings.COLLECTION_CACHE_PREFIX.length() + 1 ),
|
||||
(String) entry.getValue(),
|
||||
CacheRegionDefinition.CacheRegionType.COLLECTION
|
||||
);
|
||||
}
|
||||
else if ( keyString.startsWith( AvailableSettings.JACC_PREFIX )
|
||||
&& ! ( keyString.equals( AvailableSettings.JACC_CONTEXT_ID )
|
||||
|| keyString.equals( AvailableSettings.JACC_ENABLED ) ) ) {
|
||||
addJaccDefinition( (String) entry.getKey(), entry.getValue() );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return specialProperties;
|
||||
}
|
||||
|
||||
private void applyJdbcConnectionProperties(ServiceRegistryBuilder serviceRegistryBuilder) {
|
||||
if ( persistenceUnit.getJtaDataSource() != null ) {
|
||||
serviceRegistryBuilder.applySetting( Environment.DATASOURCE, persistenceUnit.getJtaDataSource() );
|
||||
}
|
||||
else if ( persistenceUnit.getNonJtaDataSource() != null ) {
|
||||
serviceRegistryBuilder.applySetting( Environment.DATASOURCE, persistenceUnit.getNonJtaDataSource() );
|
||||
}
|
||||
else {
|
||||
final String driver = (String) configurationValues.get( AvailableSettings.JDBC_DRIVER );
|
||||
if ( StringHelper.isNotEmpty( driver ) ) {
|
||||
serviceRegistryBuilder.applySetting( org.hibernate.cfg.AvailableSettings.DRIVER, driver );
|
||||
}
|
||||
final String url = (String) configurationValues.get( AvailableSettings.JDBC_URL );
|
||||
if ( StringHelper.isNotEmpty( url ) ) {
|
||||
serviceRegistryBuilder.applySetting( org.hibernate.cfg.AvailableSettings.URL, url );
|
||||
}
|
||||
final String user = (String) configurationValues.get( AvailableSettings.JDBC_USER );
|
||||
if ( StringHelper.isNotEmpty( user ) ) {
|
||||
serviceRegistryBuilder.applySetting( org.hibernate.cfg.AvailableSettings.USER, user );
|
||||
}
|
||||
final String pass = (String) configurationValues.get( AvailableSettings.JDBC_PASSWORD );
|
||||
if ( StringHelper.isNotEmpty( pass ) ) {
|
||||
serviceRegistryBuilder.applySetting( org.hibernate.cfg.AvailableSettings.PASS, pass );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void applyTransactionProperties(ServiceRegistryBuilder serviceRegistryBuilder, SpecialProperties specialProperties) {
|
||||
PersistenceUnitTransactionType txnType = PersistenceUnitTransactionTypeHelper.interpretTransactionType(
|
||||
configurationValues.get( AvailableSettings.TRANSACTION_TYPE )
|
||||
);
|
||||
if ( txnType == null ) {
|
||||
txnType = persistenceUnit.getTransactionType();
|
||||
}
|
||||
if ( txnType == null ) {
|
||||
// is it more appropriate to have this be based on bootstrap entry point (EE vs SE)?
|
||||
txnType = PersistenceUnitTransactionType.RESOURCE_LOCAL;
|
||||
}
|
||||
specialProperties.jpaTransactionType = txnType;
|
||||
boolean hasTxStrategy = configurationValues.containsKey( Environment.TRANSACTION_STRATEGY );
|
||||
if ( hasTxStrategy ) {
|
||||
LOG.overridingTransactionStrategyDangerous( Environment.TRANSACTION_STRATEGY );
|
||||
}
|
||||
else {
|
||||
if ( txnType == PersistenceUnitTransactionType.JTA ) {
|
||||
serviceRegistryBuilder.applySetting( Environment.TRANSACTION_STRATEGY, CMTTransactionFactory.class );
|
||||
}
|
||||
else if ( txnType == PersistenceUnitTransactionType.RESOURCE_LOCAL ) {
|
||||
serviceRegistryBuilder.applySetting( Environment.TRANSACTION_STRATEGY, JdbcTransactionFactory.class );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> T instantiateCustomClassFromConfiguration(
|
||||
Object value,
|
||||
Class<T> type,
|
||||
ServiceRegistry bootstrapServiceRegistry) {
|
||||
if ( value == null ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ( type.isInstance( value ) ) {
|
||||
return (T) value;
|
||||
}
|
||||
|
||||
final Class<? extends T> implementationClass;
|
||||
|
||||
if ( Class.class.isInstance( value ) ) {
|
||||
try {
|
||||
implementationClass = (Class<? extends T>) value;
|
||||
}
|
||||
catch (ClassCastException e) {
|
||||
throw persistenceException(
|
||||
String.format(
|
||||
"Specified implementation class [%s] was not of expected type [%s]",
|
||||
((Class) value).getName(),
|
||||
type.getName()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
else {
|
||||
final String implementationClassName = value.toString();
|
||||
try {
|
||||
implementationClass = bootstrapServiceRegistry.getService( ClassLoaderService.class )
|
||||
.classForName( implementationClassName );
|
||||
}
|
||||
catch (ClassCastException e) {
|
||||
throw persistenceException(
|
||||
String.format(
|
||||
"Specified implementation class [%s] was not of expected type [%s]",
|
||||
implementationClassName,
|
||||
type.getName()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
return implementationClass.newInstance();
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw persistenceException(
|
||||
String.format(
|
||||
"Unable to instantiate specified implementation class [%s]",
|
||||
implementationClass.getName()
|
||||
),
|
||||
e
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Class<? extends Interceptor> loadSessionInterceptorClass(
|
||||
Object value,
|
||||
BootstrapServiceRegistry bootstrapServiceRegistry) {
|
||||
if ( value == null ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Class theClass;
|
||||
if ( Class.class.isInstance( value ) ) {
|
||||
theClass = (Class) value;
|
||||
}
|
||||
else {
|
||||
theClass = bootstrapServiceRegistry.getService( ClassLoaderService.class ).classForName( value.toString() );
|
||||
}
|
||||
|
||||
try {
|
||||
return (Class<? extends Interceptor>) theClass;
|
||||
}
|
||||
catch (ClassCastException e) {
|
||||
throw persistenceException(
|
||||
String.format(
|
||||
"Specified Interceptor implementation class [%s] was not castable to Interceptor",
|
||||
theClass.getName()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private MetadataSourceProcessingOrder interpretSourceProcessingOrder(Object value) {
|
||||
if ( value == null ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ( MetadataSourceProcessingOrder.class.isInstance( value ) ) {
|
||||
return (MetadataSourceProcessingOrder) value;
|
||||
}
|
||||
else {
|
||||
final String s = value.toString();
|
||||
final StringTokenizer tokenizer = new StringTokenizer( s, ",; ", false );
|
||||
final MetadataSourceType metadataSourceType = MetadataSourceType.parsePrecedence( tokenizer.nextToken() );
|
||||
return metadataSourceType == MetadataSourceType.CLASS
|
||||
? MetadataSourceProcessingOrder.ANNOTATIONS_FIRST
|
||||
: MetadataSourceProcessingOrder.HBM_FIRST;
|
||||
}
|
||||
}
|
||||
|
||||
private AccessType interpretCacheAccessStrategy(Object value) {
|
||||
if ( value == null ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ( AccessType.class.isInstance( value ) ) {
|
||||
return (AccessType) value;
|
||||
}
|
||||
else {
|
||||
return AccessType.fromExternalName( value.toString() );
|
||||
}
|
||||
}
|
||||
|
||||
private String jaccContextId;
|
||||
|
||||
private void addJaccDefinition(String key, Object value) {
|
||||
if ( jaccContextId == null ) {
|
||||
jaccContextId = (String) configurationValues.get( AvailableSettings.JACC_CONTEXT_ID );
|
||||
if ( jaccContextId == null ) {
|
||||
throw persistenceException(
|
||||
"Entities have been configured for JACC, but "
|
||||
+ AvailableSettings.JACC_CONTEXT_ID + " has not been set"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
final int roleStart = AvailableSettings.JACC_PREFIX.length() + 1;
|
||||
final String role = key.substring( roleStart, key.indexOf( '.', roleStart ) );
|
||||
final int classStart = roleStart + role.length() + 1;
|
||||
final String clazz = key.substring( classStart, key.length() );
|
||||
|
||||
final JaccDefinition def = new JaccDefinition( jaccContextId, role, clazz, (String) value );
|
||||
|
||||
jaccDefinitions.add( def );
|
||||
|
||||
}
|
||||
catch ( IndexOutOfBoundsException e ) {
|
||||
throw persistenceException( "Illegal usage of " + AvailableSettings.JACC_PREFIX + ": " + key );
|
||||
}
|
||||
}
|
||||
|
||||
private void addCacheRegionDefinition(String role, String value, CacheRegionDefinition.CacheRegionType cacheType) {
|
||||
final StringTokenizer params = new StringTokenizer( value, ";, " );
|
||||
if ( !params.hasMoreTokens() ) {
|
||||
StringBuilder error = new StringBuilder( "Illegal usage of " );
|
||||
if ( cacheType == CacheRegionDefinition.CacheRegionType.ENTITY ) {
|
||||
error.append( AvailableSettings.CLASS_CACHE_PREFIX )
|
||||
.append( ": " )
|
||||
.append( AvailableSettings.CLASS_CACHE_PREFIX );
|
||||
}
|
||||
else {
|
||||
error.append( AvailableSettings.COLLECTION_CACHE_PREFIX )
|
||||
.append( ": " )
|
||||
.append( AvailableSettings.COLLECTION_CACHE_PREFIX );
|
||||
}
|
||||
error.append( '.' )
|
||||
.append( role )
|
||||
.append( ' ' )
|
||||
.append( value )
|
||||
.append( ". Was expecting configuration, but found none" );
|
||||
throw persistenceException( error.toString() );
|
||||
}
|
||||
|
||||
String usage = params.nextToken();
|
||||
String region = null;
|
||||
if ( params.hasMoreTokens() ) {
|
||||
region = params.nextToken();
|
||||
}
|
||||
boolean lazyProperty = true;
|
||||
if ( cacheType == CacheRegionDefinition.CacheRegionType.ENTITY ) {
|
||||
if ( params.hasMoreTokens() ) {
|
||||
lazyProperty = "all".equalsIgnoreCase( params.nextToken() );
|
||||
}
|
||||
}
|
||||
else {
|
||||
lazyProperty = false;
|
||||
}
|
||||
|
||||
final CacheRegionDefinition def = new CacheRegionDefinition( cacheType, role, usage, region, lazyProperty );
|
||||
cacheRegionDefinitions.add( def );
|
||||
}
|
||||
|
||||
@SuppressWarnings("UnnecessaryUnboxing")
|
||||
private void prepareMetadataBuilder(
|
||||
MetadataBuilder metadataBuilder,
|
||||
SpecialProperties specialProperties) {
|
||||
if ( specialProperties.namingStrategy != null ) {
|
||||
metadataBuilder.with( specialProperties.namingStrategy );
|
||||
}
|
||||
|
||||
if ( specialProperties.sourceProcessingOrder != null ) {
|
||||
metadataBuilder.with( specialProperties.sourceProcessingOrder );
|
||||
}
|
||||
|
||||
if ( specialProperties.useEnhancedGenerators != null ) {
|
||||
metadataBuilder.withNewIdentifierGeneratorsEnabled( specialProperties.useEnhancedGenerators.booleanValue() );
|
||||
}
|
||||
|
||||
if ( specialProperties.sharedCacheMode != null ) {
|
||||
metadataBuilder.with( specialProperties.sharedCacheMode );
|
||||
}
|
||||
|
||||
if ( specialProperties.defaultCacheAccessType != null ) {
|
||||
metadataBuilder.with( specialProperties.defaultCacheAccessType );
|
||||
}
|
||||
}
|
||||
|
||||
private void prepareSessionFactoryBuilder(SessionFactoryBuilder builder, SpecialProperties specialProperties) {
|
||||
if ( specialProperties.sessionFactoryInterceptor != null ) {
|
||||
builder.with( specialProperties.sessionFactoryInterceptor );
|
||||
}
|
||||
if ( specialProperties.entityNameResolver != null ) {
|
||||
builder.add( specialProperties.entityNameResolver );
|
||||
}
|
||||
if ( specialProperties.entityNotFoundDelegate != null ) {
|
||||
builder.with( specialProperties.entityNotFoundDelegate );
|
||||
}
|
||||
if ( specialProperties.sessionFactoryObserver != null ) {
|
||||
builder.add( specialProperties.sessionFactoryObserver );
|
||||
}
|
||||
if ( specialProperties.customEntityDirtinessStrategy != null ) {
|
||||
builder.with( specialProperties.customEntityDirtinessStrategy );
|
||||
}
|
||||
if ( specialProperties.currentTenantIdentifierResolver != null ) {
|
||||
builder.with( specialProperties.currentTenantIdentifierResolver );
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("UnnecessaryUnboxing")
|
||||
private Settings prepareEntitytManagerFactoryCreationSettings(SpecialProperties specialProperties) {
|
||||
final SettingsImpl settings = new SettingsImpl();
|
||||
if ( specialProperties.releaseResourcesOnClose != null ) {
|
||||
settings.setReleaseResourcesOnCloseEnabled( specialProperties.releaseResourcesOnClose.booleanValue() );
|
||||
}
|
||||
if ( specialProperties.sessionInterceptorClass != null ) {
|
||||
settings.setSessionInterceptorClass( specialProperties.sessionInterceptorClass );
|
||||
}
|
||||
if ( specialProperties.jpaTransactionType != null ) {
|
||||
settings.setTransactionType( specialProperties.jpaTransactionType );
|
||||
}
|
||||
return settings;
|
||||
}
|
||||
|
||||
|
||||
private PersistenceException persistenceException(String message) {
|
||||
return persistenceException( message, null );
|
||||
}
|
||||
|
||||
private PersistenceException persistenceException(String message, Exception cause) {
|
||||
return new PersistenceException(
|
||||
getExceptionHeader() + message,
|
||||
cause
|
||||
);
|
||||
}
|
||||
|
||||
private String getExceptionHeader() {
|
||||
return "[PersistenceUnit: " + persistenceUnit.getName() + "] ";
|
||||
}
|
||||
|
||||
/**
|
||||
* Aggregated return structure
|
||||
*/
|
||||
private static class SpecialProperties {
|
||||
// affecting MetadataBuilder...
|
||||
private NamingStrategy namingStrategy;
|
||||
private MetadataSourceProcessingOrder sourceProcessingOrder;
|
||||
private SharedCacheMode sharedCacheMode;
|
||||
private AccessType defaultCacheAccessType;
|
||||
private Boolean useEnhancedGenerators;
|
||||
|
||||
// affecting SessionFactoryBuilder...
|
||||
private Interceptor sessionFactoryInterceptor;
|
||||
private SessionFactoryObserver sessionFactoryObserver;
|
||||
private EntityNameResolver entityNameResolver;
|
||||
private EntityNotFoundDelegate entityNotFoundDelegate = new JpaEntityNotFoundDelegate();
|
||||
private CustomEntityDirtinessStrategy customEntityDirtinessStrategy;
|
||||
private CurrentTenantIdentifierResolver currentTenantIdentifierResolver;
|
||||
|
||||
// affecting EntityManagerFactory building
|
||||
private Boolean releaseResourcesOnClose;
|
||||
private Class<? extends Interceptor> sessionInterceptorClass;
|
||||
private PersistenceUnitTransactionType jpaTransactionType;
|
||||
}
|
||||
|
||||
private static class JpaEntityNotFoundDelegate implements EntityNotFoundDelegate, Serializable {
|
||||
public void handleEntityNotFound(String entityName, Serializable id) {
|
||||
throw new EntityNotFoundException( "Unable to find " + entityName + " with id " + id );
|
||||
}
|
||||
}
|
||||
|
||||
private static class ServiceRegistryCloser implements SessionFactoryObserver {
|
||||
@Override
|
||||
public void sessionFactoryCreated(SessionFactory sessionFactory) {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sessionFactoryClosed(SessionFactory sessionFactory) {
|
||||
SessionFactoryImplementor sfi = ( (SessionFactoryImplementor) sessionFactory );
|
||||
sfi.getServiceRegistry().destroy();
|
||||
ServiceRegistry basicRegistry = sfi.getServiceRegistry().getParentServiceRegistry();
|
||||
( (ServiceRegistryImplementor) basicRegistry ).destroy();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -27,6 +27,7 @@ import javax.persistence.spi.PersistenceUnitInfo;
|
|||
import java.util.Map;
|
||||
|
||||
import org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl;
|
||||
import org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderUsingMetamodelImpl;
|
||||
import org.hibernate.jpa.boot.internal.PersistenceUnitInfoDescriptor;
|
||||
|
||||
/**
|
||||
|
@ -35,15 +36,57 @@ import org.hibernate.jpa.boot.internal.PersistenceUnitInfoDescriptor;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public final class Bootstrap {
|
||||
/**
|
||||
* Builds and returns an EntityManagerFactoryBuilder that can be used to then create an
|
||||
* {@link javax.persistence.EntityManagerFactory}. Essentially this represents phase 1 of a 2 phase
|
||||
* {@link javax.persistence.EntityManagerFactory} building process.
|
||||
*
|
||||
* @param persistenceUnitDescriptor The persistence-unit description. Note that this is the Hibernate abstraction
|
||||
* hiding where this info comes from.
|
||||
* @param integration The map of integration settings. Generally speaking, integration settings take precedence
|
||||
* over persistence-unit settings.
|
||||
*
|
||||
* @return The {@link javax.persistence.EntityManagerFactory} builder.
|
||||
*/
|
||||
public static EntityManagerFactoryBuilder getEntityManagerFactoryBuilder(
|
||||
PersistenceUnitDescriptor persistenceUnitDescriptor,
|
||||
Map integration) {
|
||||
return new EntityManagerFactoryBuilderImpl( persistenceUnitDescriptor, integration );
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds and returns an EntityManagerFactoryBuilder that can be used to then create an
|
||||
* {@link javax.persistence.EntityManagerFactory}. Essentially this represents phase 1 of a 2 phase
|
||||
* {@link javax.persistence.EntityManagerFactory} building process.
|
||||
*
|
||||
* This form accepts the JPA container bootstrap persistence-unit descriptor representation
|
||||
* ({@link PersistenceUnitInfo}) and wraps it in our {@link PersistenceUnitDescriptor} abstraction. It then
|
||||
* just delegates the call to {@link #getEntityManagerFactoryBuilder(PersistenceUnitDescriptor, Map)}
|
||||
*
|
||||
* @param persistenceUnitInfo The persistence-unit description as defined by the JPA PersistenceUnitInfo contract
|
||||
* @param integration The map of integration settings. Generally speaking, integration settings take precedence
|
||||
* over persistence-unit settings.
|
||||
*
|
||||
* @return The {@link javax.persistence.EntityManagerFactory} builder.
|
||||
*/
|
||||
public static EntityManagerFactoryBuilder getEntityManagerFactoryBuilder(
|
||||
PersistenceUnitInfo persistenceUnitInfo,
|
||||
Map integration) {
|
||||
return getEntityManagerFactoryBuilder( new PersistenceUnitInfoDescriptor( persistenceUnitInfo ), integration );
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifically builds and returns a EntityManagerFactoryBuilder that leverages the new metamodel codebase.
|
||||
* Eventually this will be the normal operation of {@link #getEntityManagerFactoryBuilder(PersistenceUnitDescriptor, Map)},
|
||||
* but for now due to the incompleteness of the metamodel codebase, this is not integrated as the main way to
|
||||
* build the EntityManagerFactoryBuilder. This allows tests in the nor-core modules to keep running.
|
||||
*
|
||||
* @deprecated This is a temporary method until metamodel codebase is more complete
|
||||
*/
|
||||
@Deprecated
|
||||
public static EntityManagerFactoryBuilder getEntityManagerFactoryBuilderUsingMetamodel(
|
||||
PersistenceUnitDescriptor persistenceUnitDescriptor,
|
||||
Map integration) {
|
||||
return new EntityManagerFactoryBuilderUsingMetamodelImpl( persistenceUnitDescriptor, integration );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2012, 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.jpa.boot.spi;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.integrator.spi.Integrator;
|
||||
import org.hibernate.jpa.internal.event.JpaIntegrator;
|
||||
import org.hibernate.service.BootstrapServiceRegistry;
|
||||
import org.hibernate.service.BootstrapServiceRegistryBuilder;
|
||||
|
||||
import static org.hibernate.cfg.AvailableSettings.APP_CLASSLOADER;
|
||||
import static org.hibernate.jpa.AvailableSettings.INTEGRATOR_PROVIDER;
|
||||
|
||||
/**
|
||||
* Helper class for building a BootstrapServiceRegistry for JPA use. Extracted to separate class so others can
|
||||
* leverage.
|
||||
*/
|
||||
public class JpaBootstrapServiceRegistryBuilder {
|
||||
/**
|
||||
* Builds the {@link org.hibernate.service.BootstrapServiceRegistry} used by used as part of JPA boot-strapping.
|
||||
*
|
||||
* Mainly accounts for class-loading behavior and reading a (potentially) explicitly defined
|
||||
* {@link IntegratorProvider}
|
||||
*
|
||||
* @param integrationSettings Any integration settings passed by the EE container or SE application
|
||||
*
|
||||
* @return The built BootstrapServiceRegistry
|
||||
*/
|
||||
public static BootstrapServiceRegistry buildBootstrapServiceRegistry(
|
||||
PersistenceUnitDescriptor persistenceUnit,
|
||||
Map integrationSettings) {
|
||||
final BootstrapServiceRegistryBuilder bootstrapServiceRegistryBuilder = new BootstrapServiceRegistryBuilder();
|
||||
bootstrapServiceRegistryBuilder.with( new JpaIntegrator() );
|
||||
|
||||
final IntegratorProvider integratorProvider = (IntegratorProvider) integrationSettings.get( INTEGRATOR_PROVIDER );
|
||||
if ( integratorProvider != null ) {
|
||||
integrationSettings.remove( INTEGRATOR_PROVIDER );
|
||||
for ( Integrator integrator : integratorProvider.getIntegrators() ) {
|
||||
bootstrapServiceRegistryBuilder.with( integrator );
|
||||
}
|
||||
}
|
||||
|
||||
ClassLoader classLoader = (ClassLoader) integrationSettings.get( APP_CLASSLOADER );
|
||||
if ( classLoader != null ) {
|
||||
integrationSettings.remove( APP_CLASSLOADER );
|
||||
}
|
||||
else {
|
||||
classLoader = persistenceUnit.getClassLoader();
|
||||
}
|
||||
bootstrapServiceRegistryBuilder.withApplicationClassLoader( classLoader );
|
||||
|
||||
return bootstrapServiceRegistryBuilder.build();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,251 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2012, 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.jpa.boot.spi;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.hibernate.boot.spi.CacheRegionDefinition;
|
||||
import org.hibernate.boot.spi.JaccDefinition;
|
||||
import org.hibernate.internal.jaxb.cfg.JaxbHibernateConfiguration;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.internal.util.ValueHolder;
|
||||
import org.hibernate.jpa.AvailableSettings;
|
||||
import org.hibernate.service.BootstrapServiceRegistry;
|
||||
import org.hibernate.service.ConfigLoader;
|
||||
|
||||
import static org.hibernate.internal.jaxb.cfg.JaxbHibernateConfiguration.JaxbSessionFactory.JaxbMapping;
|
||||
|
||||
/**
|
||||
* Helper class for handling building a unified map of "JPA settings". Extracted to separate class so others can
|
||||
* leverage.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class JpaUnifiedSettingsBuilder {
|
||||
/**
|
||||
* JPA settings can name one or more {@code cfg.xml} file to read for setting information. {@code cfg.xml}
|
||||
* files, however, can name things other than just settings (properties). If can name metadata mappings,
|
||||
* cache configurations, etc. This interface collects those "other" artifacts for use by the caller of this
|
||||
* helper so that the {@code cfg.xml} does not need to be parsed a second time to get that information later.
|
||||
*/
|
||||
public static interface CfgXmlMappingArtifacts {
|
||||
public List<JaxbMapping> getMappings();
|
||||
public List<CacheRegionDefinition> getCacheRegionDefinitions();
|
||||
public List<JaccDefinition> getJaccDefinitions();
|
||||
}
|
||||
|
||||
/**
|
||||
* Aggregated result of processing all pertinent JPA setting sources.
|
||||
*/
|
||||
public static interface Result {
|
||||
public Map<?, ?> getSettings();
|
||||
public CfgXmlMappingArtifacts getCfgXmlMappingArtifacts();
|
||||
}
|
||||
|
||||
public static Result mergePropertySources(
|
||||
PersistenceUnitDescriptor persistenceUnit,
|
||||
Map integrationSettings,
|
||||
final BootstrapServiceRegistry bootstrapServiceRegistry) {
|
||||
ResultImpl result = new ResultImpl();
|
||||
result.consume( persistenceUnit, integrationSettings, bootstrapServiceRegistry );
|
||||
return result;
|
||||
}
|
||||
|
||||
private static class CfgXmlMappingArtifactsImpl implements CfgXmlMappingArtifacts {
|
||||
private final List<JaxbMapping> mappings = new ArrayList<JaxbMapping>();
|
||||
private final List<CacheRegionDefinition> cacheRegionDefinitions = new ArrayList<CacheRegionDefinition>();
|
||||
private final List<JaccDefinition> jaccDefinitions = new ArrayList<JaccDefinition>();
|
||||
|
||||
@Override
|
||||
public List<JaxbMapping> getMappings() {
|
||||
return mappings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CacheRegionDefinition> getCacheRegionDefinitions() {
|
||||
return cacheRegionDefinitions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<JaccDefinition> getJaccDefinitions() {
|
||||
return jaccDefinitions;
|
||||
}
|
||||
}
|
||||
|
||||
private static class ResultImpl implements Result {
|
||||
private final Map<?,?> settings = new ConcurrentHashMap();
|
||||
private final CfgXmlMappingArtifactsImpl cfgXmlMappingArtifacts = new CfgXmlMappingArtifactsImpl();
|
||||
|
||||
@Override
|
||||
public Map<?, ?> getSettings() {
|
||||
return settings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CfgXmlMappingArtifacts getCfgXmlMappingArtifacts() {
|
||||
return cfgXmlMappingArtifacts;
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void consume(
|
||||
PersistenceUnitDescriptor persistenceUnit,
|
||||
Map integrationSettings,
|
||||
final BootstrapServiceRegistry bootstrapServiceRegistry) {
|
||||
final Map merged = new HashMap();
|
||||
// first, apply persistence.xml-defined settings
|
||||
if ( persistenceUnit.getProperties() != null ) {
|
||||
merged.putAll( persistenceUnit.getProperties() );
|
||||
}
|
||||
|
||||
merged.put( AvailableSettings.PERSISTENCE_UNIT_NAME, persistenceUnit.getName() );
|
||||
|
||||
// see if the persistence.xml settings named a Hibernate config file....
|
||||
final ValueHolder<ConfigLoader> configLoaderHolder = new ValueHolder<ConfigLoader>(
|
||||
new ValueHolder.DeferredInitializer<ConfigLoader>() {
|
||||
@Override
|
||||
public ConfigLoader initialize() {
|
||||
return new ConfigLoader( bootstrapServiceRegistry );
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
{
|
||||
final String cfgXmlResourceName = (String) merged.remove( AvailableSettings.CFG_FILE );
|
||||
if ( StringHelper.isNotEmpty( cfgXmlResourceName ) ) {
|
||||
// it does, so load those properties
|
||||
JaxbHibernateConfiguration configurationElement = configLoaderHolder.getValue()
|
||||
.loadConfigXmlResource( cfgXmlResourceName );
|
||||
processHibernateConfigurationElement( configurationElement, merged );
|
||||
}
|
||||
}
|
||||
|
||||
// see if integration settings named a Hibernate config file....
|
||||
{
|
||||
final String cfgXmlResourceName = (String) integrationSettings.get( AvailableSettings.CFG_FILE );
|
||||
if ( StringHelper.isNotEmpty( cfgXmlResourceName ) ) {
|
||||
integrationSettings.remove( AvailableSettings.CFG_FILE );
|
||||
// it does, so load those properties
|
||||
JaxbHibernateConfiguration configurationElement = configLoaderHolder.getValue().loadConfigXmlResource(
|
||||
cfgXmlResourceName
|
||||
);
|
||||
processHibernateConfigurationElement( configurationElement, merged );
|
||||
}
|
||||
}
|
||||
|
||||
// finally, apply integration-supplied settings (per JPA spec, integration settings should override other sources)
|
||||
merged.putAll( integrationSettings );
|
||||
|
||||
if ( ! merged.containsKey( AvailableSettings.VALIDATION_MODE ) ) {
|
||||
if ( persistenceUnit.getValidationMode() != null ) {
|
||||
merged.put( AvailableSettings.VALIDATION_MODE, persistenceUnit.getValidationMode() );
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! merged.containsKey( AvailableSettings.SHARED_CACHE_MODE ) ) {
|
||||
if ( persistenceUnit.getSharedCacheMode() != null ) {
|
||||
merged.put( AvailableSettings.SHARED_CACHE_MODE, persistenceUnit.getSharedCacheMode() );
|
||||
}
|
||||
}
|
||||
|
||||
// was getting NPE exceptions from the underlying map when just using #putAll, so going this safer route...
|
||||
Iterator itr = merged.entrySet().iterator();
|
||||
while ( itr.hasNext() ) {
|
||||
final Map.Entry entry = (Map.Entry) itr.next();
|
||||
if ( entry.getValue() == null ) {
|
||||
itr.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void processHibernateConfigurationElement(
|
||||
JaxbHibernateConfiguration configurationElement,
|
||||
Map mergeMap) {
|
||||
if ( ! mergeMap.containsKey( org.hibernate.cfg.AvailableSettings.SESSION_FACTORY_NAME ) ) {
|
||||
String cfgName = configurationElement.getSessionFactory().getName();
|
||||
if ( cfgName != null ) {
|
||||
mergeMap.put( org.hibernate.cfg.AvailableSettings.SESSION_FACTORY_NAME, cfgName );
|
||||
}
|
||||
}
|
||||
|
||||
for ( JaxbHibernateConfiguration.JaxbSessionFactory.JaxbProperty jaxbProperty : configurationElement.getSessionFactory().getProperty() ) {
|
||||
mergeMap.put( jaxbProperty.getName(), jaxbProperty.getValue() );
|
||||
}
|
||||
|
||||
for ( JaxbMapping jaxbMapping : configurationElement.getSessionFactory().getMapping() ) {
|
||||
cfgXmlMappingArtifacts.mappings.add( jaxbMapping );
|
||||
}
|
||||
|
||||
for ( Object cacheDeclaration : configurationElement.getSessionFactory().getClassCacheOrCollectionCache() ) {
|
||||
if ( JaxbHibernateConfiguration.JaxbSessionFactory.JaxbClassCache.class.isInstance( cacheDeclaration ) ) {
|
||||
final JaxbHibernateConfiguration.JaxbSessionFactory.JaxbClassCache jaxbClassCache
|
||||
= (JaxbHibernateConfiguration.JaxbSessionFactory.JaxbClassCache) cacheDeclaration;
|
||||
cfgXmlMappingArtifacts.cacheRegionDefinitions.add(
|
||||
new CacheRegionDefinition(
|
||||
CacheRegionDefinition.CacheRegionType.ENTITY,
|
||||
jaxbClassCache.getClazz(),
|
||||
jaxbClassCache.getUsage().value(),
|
||||
jaxbClassCache.getRegion(),
|
||||
"all".equals( jaxbClassCache.getInclude() )
|
||||
)
|
||||
);
|
||||
}
|
||||
else {
|
||||
final JaxbHibernateConfiguration.JaxbSessionFactory.JaxbCollectionCache jaxbCollectionCache
|
||||
= (JaxbHibernateConfiguration.JaxbSessionFactory.JaxbCollectionCache) cacheDeclaration;
|
||||
cfgXmlMappingArtifacts.cacheRegionDefinitions.add(
|
||||
new CacheRegionDefinition(
|
||||
CacheRegionDefinition.CacheRegionType.COLLECTION,
|
||||
jaxbCollectionCache.getCollection(),
|
||||
jaxbCollectionCache.getUsage().value(),
|
||||
jaxbCollectionCache.getRegion(),
|
||||
false
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if ( configurationElement.getSecurity() != null ) {
|
||||
final String contextId = configurationElement.getSecurity().getContext();
|
||||
for ( JaxbHibernateConfiguration.JaxbSecurity.JaxbGrant grant : configurationElement.getSecurity().getGrant() ) {
|
||||
cfgXmlMappingArtifacts.jaccDefinitions.add(
|
||||
new JaccDefinition(
|
||||
contextId,
|
||||
grant.getRole(),
|
||||
grant.getEntityName(),
|
||||
grant.getActions()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -64,7 +64,8 @@ import org.hibernate.jpa.AvailableSettings;
|
|||
import org.hibernate.jpa.HibernateQuery;
|
||||
import org.hibernate.jpa.boot.internal.SettingsImpl;
|
||||
import org.hibernate.jpa.criteria.CriteriaBuilderImpl;
|
||||
import org.hibernate.jpa.internal.metamodel.MetamodelImpl;
|
||||
import org.hibernate.jpa.metamodel.internal.JpaMetaModelPopulationSetting;
|
||||
import org.hibernate.jpa.metamodel.internal.legacy.MetamodelImpl;
|
||||
import org.hibernate.jpa.internal.util.PersistenceUtilHelper;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.metadata.ClassMetadata;
|
||||
|
@ -122,19 +123,7 @@ public class EntityManagerFactoryImpl implements HibernateEntityManagerFactory {
|
|||
this.transactionType = settings.getTransactionType();
|
||||
this.discardOnClose = settings.isReleaseResourcesOnCloseEnabled();
|
||||
this.sessionInterceptorClass = settings.getSessionInterceptorClass();
|
||||
|
||||
final Iterator<PersistentClass> classes = cfg.getClassMappings();
|
||||
final JpaMetaModelPopulationSetting jpaMetaModelPopulationSetting = determineJpaMetaModelPopulationSetting( cfg );
|
||||
if ( JpaMetaModelPopulationSetting.DISABLED == jpaMetaModelPopulationSetting ) {
|
||||
this.metamodel = null;
|
||||
}
|
||||
else {
|
||||
this.metamodel = MetamodelImpl.buildMetamodel(
|
||||
classes,
|
||||
sessionFactory,
|
||||
JpaMetaModelPopulationSetting.IGNORE_UNSUPPORTED == jpaMetaModelPopulationSetting
|
||||
);
|
||||
}
|
||||
this.metamodel = sessionFactory.getJpaMetamodel();
|
||||
this.criteriaBuilder = new CriteriaBuilderImpl( this );
|
||||
this.util = new HibernatePersistenceUnitUtil( this );
|
||||
|
||||
|
@ -154,43 +143,6 @@ public class EntityManagerFactoryImpl implements HibernateEntityManagerFactory {
|
|||
EntityManagerFactoryRegistry.INSTANCE.addEntityManagerFactory(entityManagerFactoryName, this);
|
||||
}
|
||||
|
||||
private enum JpaMetaModelPopulationSetting {
|
||||
ENABLED,
|
||||
DISABLED,
|
||||
IGNORE_UNSUPPORTED;
|
||||
|
||||
private static JpaMetaModelPopulationSetting parse(String setting) {
|
||||
if ( "enabled".equalsIgnoreCase( setting ) ) {
|
||||
return ENABLED;
|
||||
}
|
||||
else if ( "disabled".equalsIgnoreCase( setting ) ) {
|
||||
return DISABLED;
|
||||
}
|
||||
else {
|
||||
return IGNORE_UNSUPPORTED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected JpaMetaModelPopulationSetting determineJpaMetaModelPopulationSetting(Configuration cfg) {
|
||||
String setting = ConfigurationHelper.getString(
|
||||
AvailableSettings.JPA_METAMODEL_POPULATION,
|
||||
cfg.getProperties(),
|
||||
null
|
||||
);
|
||||
if ( setting == null ) {
|
||||
setting = ConfigurationHelper.getString( AvailableSettings.JPA_METAMODEL_GENERATION, cfg.getProperties(), null );
|
||||
if ( setting != null ) {
|
||||
log.infof(
|
||||
"Encountered deprecated setting [%s], use [%s] instead",
|
||||
AvailableSettings.JPA_METAMODEL_GENERATION,
|
||||
AvailableSettings.JPA_METAMODEL_POPULATION
|
||||
);
|
||||
}
|
||||
}
|
||||
return JpaMetaModelPopulationSetting.parse( setting );
|
||||
}
|
||||
|
||||
private static void addAll(HashMap<String, Object> destination, Map<?,?> source) {
|
||||
for ( Map.Entry entry : source.entrySet() ) {
|
||||
if ( String.class.isInstance( entry.getKey() ) ) {
|
||||
|
|
|
@ -70,12 +70,19 @@ public interface EntityManagerMessageLogger extends CoreMessageLogger {
|
|||
@Message( value = "Exploded jar file not a directory (ignored): %s", id = 15006 )
|
||||
void explodedJarNotDirectory( URL jarUrl );
|
||||
|
||||
@LogMessage( level = ERROR )
|
||||
@Message( value = "Illegal argument on static metamodel field injection : %s#%s; expected type : %s; encountered type : %s", id = 15007 )
|
||||
void illegalArgumentOnStaticMetamodelFieldInjection( String name,
|
||||
String name2,
|
||||
String name3,
|
||||
String name4 );
|
||||
/**
|
||||
* Simply deprecated for now to show the fact that id 15007 is still in use...
|
||||
*
|
||||
* @deprecated Moved to hibernate-core in conjunction with moving JPA metamodel generation to SessionFactory
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
@LogMessage( level = ERROR )
|
||||
@Message( value = "Illegal argument on static metamodel field injection : %s#%s; expected type : %s; encountered type : %s", id = 15007 )
|
||||
void illegalArgumentOnStaticMetamodelFieldInjection( String metamodelClassName,
|
||||
String attributeName,
|
||||
String attributeJavaType,
|
||||
String metamodelFieldJavaType );
|
||||
|
||||
@LogMessage( level = ERROR )
|
||||
@Message( value = "Malformed URL: %s", id = 15008 )
|
||||
|
@ -92,10 +99,17 @@ public interface EntityManagerMessageLogger extends CoreMessageLogger {
|
|||
void unableToFindFile( URL jarUrl,
|
||||
@Cause Exception e );
|
||||
|
||||
@LogMessage( level = ERROR )
|
||||
@Message( value = "Unable to locate static metamodel field : %s#%s", id = 15011 )
|
||||
void unableToLocateStaticMetamodelField( String name,
|
||||
String name2 );
|
||||
/**
|
||||
* Simply deprecated for now to show the fact that id 15011 is still in use...
|
||||
*
|
||||
* @deprecated Moved to hibernate-core in conjunction with moving JPA metamodel generation to SessionFactory
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
@LogMessage( level = ERROR )
|
||||
@Message( value = "Unable to locate static metamodel field : %s#%s", id = 15011 )
|
||||
void unableToLocateStaticMetamodelField( String metamodelClassName,
|
||||
String attributeName );
|
||||
|
||||
@LogMessage( level = INFO )
|
||||
@Message( value = "Using provided datasource", id = 15012 )
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2012, 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.jpa.internal.util;
|
||||
|
||||
import javax.persistence.SharedCacheMode;
|
||||
|
||||
/**
|
||||
* Helper for dealing with SharedCacheMode references as either {@link SharedCacheMode} or String.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class SharedCacheModeHelper {
|
||||
public static SharedCacheMode asSharedCacheMode(Object value) {
|
||||
if ( value == null ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ( SharedCacheMode.class.isInstance( value ) ) {
|
||||
return (SharedCacheMode) value;
|
||||
}
|
||||
else {
|
||||
return SharedCacheMode.valueOf( value.toString() );
|
||||
}
|
||||
}
|
||||
}
|
|
@ -44,7 +44,7 @@ import org.hibernate.jpa.test.metamodel.Customer;
|
|||
import org.hibernate.jpa.test.metamodel.Customer_;
|
||||
import org.hibernate.jpa.test.metamodel.Info;
|
||||
import org.hibernate.jpa.test.metamodel.LineItem;
|
||||
import org.hibernate.jpa.internal.metamodel.MetamodelImpl;
|
||||
import org.hibernate.jpa.metamodel.internal.legacy.MetamodelImpl;
|
||||
import org.hibernate.jpa.test.metamodel.Order;
|
||||
import org.hibernate.jpa.test.metamodel.Phone;
|
||||
import org.hibernate.jpa.test.metamodel.Product;
|
||||
|
|
|
@ -41,7 +41,7 @@ import javax.persistence.metamodel.Type;
|
|||
import org.junit.Test;
|
||||
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import org.hibernate.jpa.internal.metamodel.MetamodelImpl;
|
||||
import org.hibernate.jpa.metamodel.internal.legacy.MetamodelImpl;
|
||||
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
|
||||
|
|
Loading…
Reference in New Issue