HHH-6159 - Create EntityManagerFactoryBuilder : integrate EntityManagerFactoryBuilder with metamodel codebase

This commit is contained in:
Steve Ebersole 2012-07-23 23:58:28 -05:00
parent 72af04524a
commit 61c04a0b30
80 changed files with 8431 additions and 479 deletions

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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";
}

View File

@ -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.

View File

@ -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;
}

View File

@ -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();
}

View File

@ -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 );
}

View File

@ -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 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -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
*

View File

@ -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 + "]"
);
}
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}

View File

@ -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() );
}
}

View File

@ -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;
}
}
}

View File

@ -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();
}
}

View File

@ -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;
}
}

View File

@ -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();
}
};
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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;
}
}

View File

@ -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);
}

View File

@ -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() );
}
}
}
}

View File

@ -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();
}

View File

@ -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;
}
}

View File

@ -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();
}

View File

@ -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;
}
}

View File

@ -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" );
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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();
}
};
}

View File

@ -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> {
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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() );
}
}

View File

@ -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;
}
}
}

View File

@ -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();
}
}

View File

@ -0,0 +1 @@
package org.hibernate.jpa.metamodel;

View File

@ -0,0 +1 @@
package org.hibernate.jpa;

View File

@ -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;
}
}

View File

@ -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 ) {

View File

@ -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" );

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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 );

View File

@ -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;

View File

@ -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,

View File

@ -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;
}
}

View File

@ -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,

View File

@ -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,

View File

@ -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;
}

View File

@ -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 );
}
/**

View File

@ -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;
/**

View File

@ -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();
}

View File

@ -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
}

View File

@ -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.
*

View File

@ -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
}

View File

@ -27,6 +27,6 @@ package org.hibernate.metamodel.spi.source;
*
*/
public interface PluralAttributeIndexSource extends RelationalValueSourceContainer {
PluralAttributeIndexNature getNature();
ExplicitHibernateTypeSource explicitHibernateTypeSource();
}

View File

@ -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
*

View File

@ -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

View File

@ -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;

View File

@ -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();
}
}
}

View File

@ -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 );
}
}

View File

@ -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();
}
}

View File

@ -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()
)
);
}
}
}
}
}

View File

@ -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() ) ) {

View File

@ -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 )

View File

@ -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() );
}
}
}

View File

@ -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;

View File

@ -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;