Author: steve.ebersole(a)jboss.com
Date: 2008-10-07 11:56:16 -0400 (Tue, 07 Oct 2008)
New Revision: 15259
Added:
core/branches/Branch_3_3/core/src/main/java/org/hibernate/EntityNameResolver.java
core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/dynamicentity/tuplizer2/
core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/dynamicentity/tuplizer2/Customer.hbm.xml
core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/dynamicentity/tuplizer2/ImprovedTuplizerDynamicEntityTest.java
core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/dynamicentity/tuplizer2/MyEntityInstantiator.java
core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/dynamicentity/tuplizer2/MyEntityTuplizer.java
Modified:
core/branches/Branch_3_3/core/src/main/java/org/hibernate/impl/SessionFactoryImpl.java
core/branches/Branch_3_3/core/src/main/java/org/hibernate/impl/SessionImpl.java
core/branches/Branch_3_3/core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java
core/branches/Branch_3_3/core/src/main/java/org/hibernate/persister/entity/EntityPersister.java
core/branches/Branch_3_3/core/src/main/java/org/hibernate/tuple/entity/AbstractEntityTuplizer.java
core/branches/Branch_3_3/core/src/main/java/org/hibernate/tuple/entity/Dom4jEntityTuplizer.java
core/branches/Branch_3_3/core/src/main/java/org/hibernate/tuple/entity/DynamicMapEntityTuplizer.java
core/branches/Branch_3_3/core/src/main/java/org/hibernate/tuple/entity/EntityMetamodel.java
core/branches/Branch_3_3/core/src/main/java/org/hibernate/tuple/entity/EntityTuplizer.java
core/branches/Branch_3_3/core/src/main/java/org/hibernate/tuple/entity/PojoEntityTuplizer.java
Log:
HHH-3515 : EntityNameResolver
Added: core/branches/Branch_3_3/core/src/main/java/org/hibernate/EntityNameResolver.java
===================================================================
--- core/branches/Branch_3_3/core/src/main/java/org/hibernate/EntityNameResolver.java
(rev 0)
+++
core/branches/Branch_3_3/core/src/main/java/org/hibernate/EntityNameResolver.java 2008-10-07
15:56:16 UTC (rev 15259)
@@ -0,0 +1,42 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, 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;
+
+/**
+ * Contract for resolving an entity-name from a given entity instance.
+ *
+ * @author Steve Ebersole
+ */
+public interface EntityNameResolver {
+ /**
+ * Given an entity instance, determine its entity-name.
+ *
+ * @param entity The entity instance.
+ *
+ * @return The corresponding entity-name, or null if this impl does not know how to
perform resolution
+ * for the given entity instance.
+ */
+ public String resolveEntityName(Object entity);
+}
Modified:
core/branches/Branch_3_3/core/src/main/java/org/hibernate/impl/SessionFactoryImpl.java
===================================================================
---
core/branches/Branch_3_3/core/src/main/java/org/hibernate/impl/SessionFactoryImpl.java 2008-10-07
15:54:42 UTC (rev 15258)
+++
core/branches/Branch_3_3/core/src/main/java/org/hibernate/impl/SessionFactoryImpl.java 2008-10-07
15:56:16 UTC (rev 15259)
@@ -39,6 +39,7 @@
import java.util.Map;
import java.util.Properties;
import java.util.Set;
+import java.util.LinkedHashSet;
import javax.naming.NamingException;
import javax.naming.Reference;
import javax.naming.StringRefAddr;
@@ -58,6 +59,9 @@
import org.hibernate.SessionFactory;
import org.hibernate.StatelessSession;
import org.hibernate.SessionFactoryObserver;
+import org.hibernate.EntityNameResolver;
+import org.hibernate.EntityNameResolver;
+import org.hibernate.tuple.entity.EntityTuplizer;
import org.hibernate.cache.CacheKey;
import org.hibernate.cache.CollectionRegion;
import org.hibernate.cache.EntityRegion;
@@ -113,6 +117,7 @@
import org.hibernate.type.Type;
import org.hibernate.util.CollectionHelper;
import org.hibernate.util.ReflectHelper;
+import org.hibernate.util.EmptyIterator;
/**
@@ -172,6 +177,7 @@
private final transient EntityNotFoundDelegate entityNotFoundDelegate;
private final transient SQLFunctionRegistry sqlFunctionRegistry;
private final transient SessionFactoryObserver observer;
+ private final transient HashMap entityNameResolvers = new HashMap();
private final QueryPlanCache queryPlanCache = new QueryPlanCache( this );
@@ -319,11 +325,15 @@
// after *all* persisters and named queries are registered
Iterator iter = entityPersisters.values().iterator();
while ( iter.hasNext() ) {
- ( (EntityPersister) iter.next() ).postInstantiate();
+ final EntityPersister persister = ( ( EntityPersister ) iter.next() );
+ persister.postInstantiate();
+ registerEntityNameResolvers( persister );
+
}
iter = collectionPersisters.values().iterator();
while ( iter.hasNext() ) {
- ( (CollectionPersister) iter.next() ).postInstantiate();
+ final CollectionPersister persister = ( ( CollectionPersister ) iter.next() );
+ persister.postInstantiate();
}
//JNDI + Serialization:
@@ -415,6 +425,41 @@
this.observer.sessionFactoryCreated( this );
}
+ private void registerEntityNameResolvers(EntityPersister persister) {
+ Iterator itr = persister.getEntityMetamodel().getTuplizerMapping().iterateTuplizers();
+ while ( itr.hasNext() ) {
+ final EntityTuplizer tuplizer = ( EntityTuplizer ) itr.next();
+ registerEntityNameResolvers( tuplizer );
+ }
+ }
+
+ private void registerEntityNameResolvers(EntityTuplizer tuplizer) {
+ EntityNameResolver[] resolvers = tuplizer.getEntityNameResolvers();
+ if ( resolvers == null ) {
+ return;
+ }
+
+ for ( int i = 0; i < resolvers.length; i++ ) {
+ registerEntityNameResolver( resolvers[i], tuplizer.getEntityMode() );
+ }
+ }
+
+ public void registerEntityNameResolver(EntityNameResolver resolver, EntityMode
entityMode) {
+ LinkedHashSet resolversForMode = ( LinkedHashSet ) entityNameResolvers.get( entityMode
);
+ if ( resolversForMode == null ) {
+ resolversForMode = new LinkedHashSet();
+ entityNameResolvers.put( entityMode, resolversForMode );
+ }
+ resolversForMode.add( resolver );
+ }
+
+ public Iterator iterateEntityNameResolvers(EntityMode entityMode) {
+ Set actualEntityNameResolvers = ( Set ) entityNameResolvers.get( entityMode );
+ return actualEntityNameResolvers == null
+ ? EmptyIterator.INSTANCE
+ : actualEntityNameResolvers.iterator();
+ }
+
public QueryPlanCache getQueryPlanCache() {
return queryPlanCache;
}
Modified: core/branches/Branch_3_3/core/src/main/java/org/hibernate/impl/SessionImpl.java
===================================================================
---
core/branches/Branch_3_3/core/src/main/java/org/hibernate/impl/SessionImpl.java 2008-10-07
15:54:42 UTC (rev 15258)
+++
core/branches/Branch_3_3/core/src/main/java/org/hibernate/impl/SessionImpl.java 2008-10-07
15:56:16 UTC (rev 15259)
@@ -66,6 +66,7 @@
import org.hibernate.Transaction;
import org.hibernate.TransientObjectException;
import org.hibernate.UnresolvableObjectException;
+import org.hibernate.EntityNameResolver;
import org.hibernate.collection.PersistentCollection;
import org.hibernate.engine.ActionQueue;
import org.hibernate.engine.CollectionEntry;
@@ -139,7 +140,7 @@
*
* @author Gavin King
*/
-public final class SessionImpl extends AbstractSessionImpl
+public final class SessionImpl extends AbstractSessionImpl
implements EventSource, org.hibernate.classic.Session, JDBCContext.Context {
// todo : need to find a clean way to handle the "event source" role
@@ -175,6 +176,30 @@
private transient Session rootSession;
private transient Map childSessionsByEntityMode;
+ private EntityNameResolver entityNameResolver = new EntityNameResolver() {
+ public String resolveEntityName(Object entity) {
+ String entityName = interceptor.getEntityName( entity );
+ if ( entityName != null ) {
+ return entityName;
+ }
+
+ Iterator itr = factory.iterateEntityNameResolvers( entityMode );
+ while ( itr.hasNext() ) {
+ final EntityNameResolver resolver = ( EntityNameResolver ) itr.next();
+ entityName = resolver.resolveEntityName( entity );
+ if ( entityName != null ) {
+ break;
+ }
+ }
+ if ( entityName != null ) {
+ return entityName;
+ }
+
+ // the old-time stand-by...
+ return entity.getClass().getName();
+ }
+ };
+
/**
* Constructor used in building "child sessions".
*
@@ -1789,23 +1814,7 @@
public String guessEntityName(Object object) throws HibernateException {
errorIfClosed();
- String entity = interceptor.getEntityName( object );
- if ( entity == null ) {
- if ( object instanceof Map ) {
- entity = (String) ( (Map) object ).get( DynamicMapInstantiator.KEY );
- if ( entity == null ) {
- throw new HibernateException( "could not determine type of dynamic entity"
);
- }
- }
- else if ( object instanceof Element ) {
- // TODO : really need to keep a map of nodeName -> entityName, but that would mean
nodeName being distinct
- entity = ( (Element) object ).getName();
- }
- else {
- entity = object.getClass().getName();
- }
- }
- return entity;
+ return entityNameResolver.resolveEntityName( object );
}
public void cancelQuery() throws HibernateException {
Modified:
core/branches/Branch_3_3/core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java
===================================================================
---
core/branches/Branch_3_3/core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java 2008-10-07
15:54:42 UTC (rev 15258)
+++
core/branches/Branch_3_3/core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java 2008-10-07
15:56:16 UTC (rev 15259)
@@ -133,7 +133,6 @@
private final boolean isLazyPropertiesCacheable;
private final CacheEntryStructure cacheEntryStructure;
private final EntityMetamodel entityMetamodel;
- private final Map entityNameBySubclass = new HashMap();
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
private final String[] rootTableKeyColumnNames;
@@ -455,15 +454,6 @@
(CacheEntryStructure) new UnstructuredCacheEntry();
this.entityMetamodel = new EntityMetamodel( persistentClass, factory );
-
- if ( persistentClass.hasPojoRepresentation() ) {
- //TODO: this is currently specific to pojos, but need to be available for all
entity-modes
- Iterator iter = persistentClass.getSubclassIterator();
- while ( iter.hasNext() ) {
- PersistentClass pc = ( PersistentClass ) iter.next();
- entityNameBySubclass.put( pc.getMappedClass(), pc.getEntityName() );
- }
- }
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int batch = persistentClass.getBatchSize();
@@ -3254,10 +3244,6 @@
return entityMetamodel.getEntityType();
}
- private String getSubclassEntityName(Class clazz) {
- return ( String ) entityNameBySubclass.get( clazz );
- }
-
public boolean isPolymorphic() {
return entityMetamodel.isPolymorphic();
}
@@ -3646,29 +3632,17 @@
getTuplizer( entityMode ).resetIdentifier( entity, currentId, currentVersion );
}
- public EntityPersister getSubclassEntityPersister(Object instance,
SessionFactoryImplementor factory, EntityMode entityMode) {
+ public EntityPersister getSubclassEntityPersister(
+ Object instance,
+ SessionFactoryImplementor factory,
+ EntityMode entityMode) {
if ( !hasSubclasses() ) {
return this;
}
else {
- // TODO : really need a way to do something like :
- // getTuplizer(entityMode).determineConcreteSubclassEntityName(instance)
- Class clazz = instance.getClass();
- if ( clazz == getMappedClass( entityMode ) ) {
- return this;
- }
- else {
- String subclassEntityName = getSubclassEntityName( clazz );
- if ( subclassEntityName == null ) {
- throw new HibernateException(
- "instance not of expected entity type: " + clazz.getName() +
- " is not a: " + getEntityName()
- );
- }
- else {
- return factory.getEntityPersister( subclassEntityName );
- }
- }
+ final String concreteEntityName = getTuplizer( entityMode )
+ .determineConcreteSubclassEntityName( instance, factory );
+ return factory.getEntityPersister( concreteEntityName );
}
}
Modified:
core/branches/Branch_3_3/core/src/main/java/org/hibernate/persister/entity/EntityPersister.java
===================================================================
---
core/branches/Branch_3_3/core/src/main/java/org/hibernate/persister/entity/EntityPersister.java 2008-10-07
15:54:42 UTC (rev 15258)
+++
core/branches/Branch_3_3/core/src/main/java/org/hibernate/persister/entity/EntityPersister.java 2008-10-07
15:56:16 UTC (rev 15259)
@@ -668,15 +668,35 @@
public boolean hasUninitializedLazyProperties(Object object, EntityMode entityMode);
/**
- * Set the identifier and version of the given instance back
- * to its "unsaved" value, returning the id
- * @param currentId TODO
- * @param currentVersion TODO
+ * Set the identifier and version of the given instance back to its "unsaved"
value.
+ *
+ * @param entity The entity instance
+ * @param currentId The currently assigned identifier value.
+ * @param currentVersion The currently assigned version value.
+ * @param entityMode The entity mode represented by the entity instance.
*/
public void resetIdentifier(Object entity, Serializable currentId, Object
currentVersion, EntityMode entityMode);
/**
- * Get the persister for an instance of this class or a subclass
+ * A request has already identified the entity-name of this persister as the mapping for
the given instance.
+ * However, we still need to account for possible subclassing and potentially re-route
to the more appropriate
+ * persister.
+ * <p/>
+ * For example, a request names <tt>Animal</tt> as the entity-name which
gets resolved to this persister. But the
+ * actual instance is really an instance of <tt>Cat</tt> which is a subclass
of <tt>Animal</tt>. So, here the
+ * <tt>Animal</tt> persister is being asked to return the persister specific
to <tt>Cat</tt>.
+ * <p/>
+ * It is also possible that the instance is actually an <tt>Animal</tt>
instance in the above example in which
+ * case we would retrn <tt>this</tt> from this method.
+ *
+ * @param instance The entity instance
+ * @param factory Reference to the SessionFactory
+ * @param entityMode The entity mode represented by the entity instance.
+ *
+ * @return The appropriate persister
+ *
+ * @throws HibernateException Indicates that instance was deemed to not be a subclass of
the entity mapped by
+ * this persister.
*/
public EntityPersister getSubclassEntityPersister(Object instance,
SessionFactoryImplementor factory, EntityMode entityMode);
}
Modified:
core/branches/Branch_3_3/core/src/main/java/org/hibernate/tuple/entity/AbstractEntityTuplizer.java
===================================================================
---
core/branches/Branch_3_3/core/src/main/java/org/hibernate/tuple/entity/AbstractEntityTuplizer.java 2008-10-07
15:54:42 UTC (rev 15258)
+++
core/branches/Branch_3_3/core/src/main/java/org/hibernate/tuple/entity/AbstractEntityTuplizer.java 2008-10-07
15:56:16 UTC (rev 15259)
@@ -74,13 +74,6 @@
/**
- * Return the entity-mode handled by this tuplizer instance.
- *
- * @return The entity-mode
- */
- protected abstract EntityMode getEntityMode();
-
- /**
* Build an appropriate Getter for the given property.
*
* @param mappedProperty The property to be accessed via the built Getter.
@@ -326,7 +319,6 @@
* @return The property value extracted.
*/
protected Object getComponentValue(ComponentType type, Object component, String
propertyPath) {
-
int loc = propertyPath.indexOf('.');
String basePropertyName = loc>0 ?
propertyPath.substring(0, loc) : propertyPath;
Modified:
core/branches/Branch_3_3/core/src/main/java/org/hibernate/tuple/entity/Dom4jEntityTuplizer.java
===================================================================
---
core/branches/Branch_3_3/core/src/main/java/org/hibernate/tuple/entity/Dom4jEntityTuplizer.java 2008-10-07
15:54:42 UTC (rev 15258)
+++
core/branches/Branch_3_3/core/src/main/java/org/hibernate/tuple/entity/Dom4jEntityTuplizer.java 2008-10-07
15:56:16 UTC (rev 15259)
@@ -35,6 +35,8 @@
import org.hibernate.property.Setter;
import org.hibernate.EntityMode;
import org.hibernate.HibernateException;
+import org.hibernate.EntityNameResolver;
+import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.tuple.Instantiator;
import org.hibernate.tuple.Dom4jInstantiator;
import org.hibernate.type.AbstractComponentType;
@@ -44,8 +46,9 @@
import java.io.Serializable;
import java.util.HashSet;
-import java.util.Set;
import java.util.Iterator;
+import java.util.Map;
+import java.util.HashMap;
/**
* An {@link EntityTuplizer} specific to the dom4j entity mode.
@@ -57,17 +60,21 @@
static final Logger log = LoggerFactory.getLogger( Dom4jEntityTuplizer.class );
- private Set subclassNodeNames = new HashSet();
+ private Map inheritenceNodeNameMap = new HashMap();
Dom4jEntityTuplizer(EntityMetamodel entityMetamodel, PersistentClass mappedEntity) {
- super(entityMetamodel, mappedEntity);
+ super( entityMetamodel, mappedEntity );
+ inheritenceNodeNameMap.put( mappedEntity.getNodeName(), mappedEntity.getEntityName()
);
Iterator itr = mappedEntity.getSubclassClosureIterator();
while( itr.hasNext() ) {
final PersistentClass mapping = ( PersistentClass ) itr.next();
- subclassNodeNames.add( mapping.getNodeName() );
+ inheritenceNodeNameMap.put( mapping.getNodeName(), mapping.getEntityName() );
}
}
+ /**
+ * {@inheritDoc}
+ */
public EntityMode getEntityMode() {
return EntityMode.DOM4J;
}
@@ -85,18 +92,30 @@
}
}
+ /**
+ * {@inheritDoc}
+ */
protected Getter buildPropertyGetter(Property mappedProperty, PersistentClass
mappedEntity) {
return buildPropertyAccessor(mappedProperty).getGetter( null, mappedProperty.getName()
);
}
+ /**
+ * {@inheritDoc}
+ */
protected Setter buildPropertySetter(Property mappedProperty, PersistentClass
mappedEntity) {
return buildPropertyAccessor(mappedProperty).getSetter( null, mappedProperty.getName()
);
}
+ /**
+ * {@inheritDoc}
+ */
protected Instantiator buildInstantiator(PersistentClass persistentClass) {
return new Dom4jInstantiator( persistentClass );
}
+ /**
+ * {@inheritDoc}
+ */
public Serializable getIdentifier(Object entityOrId) throws HibernateException {
if (entityOrId instanceof Element) {
return super.getIdentifier(entityOrId);
@@ -107,6 +126,9 @@
}
}
+ /**
+ * {@inheritDoc}
+ */
protected ProxyFactory buildProxyFactory(PersistentClass mappingInfo, Getter idGetter,
Setter idSetter) {
HashSet proxyInterfaces = new HashSet();
proxyInterfaces.add( HibernateProxy.class );
@@ -132,15 +154,73 @@
return pf;
}
+ /**
+ * {@inheritDoc}
+ */
public Class getMappedClass() {
return Element.class;
}
+ /**
+ * {@inheritDoc}
+ */
public Class getConcreteProxyClass() {
return Element.class;
}
+ /**
+ * {@inheritDoc}
+ */
public boolean isInstrumented() {
return false;
}
+
+ /**
+ * {@inheritDoc}
+ */
+ public EntityNameResolver[] getEntityNameResolvers() {
+ return new EntityNameResolver[] { new BasicEntityNameResolver( getEntityName(),
inheritenceNodeNameMap ) };
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String determineConcreteSubclassEntityName(Object entityInstance,
SessionFactoryImplementor factory) {
+ return ( String ) inheritenceNodeNameMap.get( extractNodeName( ( Element )
entityInstance ) );
+ }
+
+ public static String extractNodeName(Element element) {
+ return element.getName();
+ }
+
+ public static class BasicEntityNameResolver implements EntityNameResolver {
+ private final String rootEntityName;
+ private final Map nodeNameToEntityNameMap;
+
+ public BasicEntityNameResolver(String rootEntityName, Map nodeNameToEntityNameMap) {
+ this.rootEntityName = rootEntityName;
+ this.nodeNameToEntityNameMap = nodeNameToEntityNameMap;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String resolveEntityName(Object entity) {
+ return ( String ) nodeNameToEntityNameMap.get( extractNodeName( ( Element ) entity )
);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean equals(Object obj) {
+ return rootEntityName.equals( ( ( BasicEntityNameResolver ) obj ).rootEntityName );
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int hashCode() {
+ return rootEntityName.hashCode();
+ }
+ }
}
Modified:
core/branches/Branch_3_3/core/src/main/java/org/hibernate/tuple/entity/DynamicMapEntityTuplizer.java
===================================================================
---
core/branches/Branch_3_3/core/src/main/java/org/hibernate/tuple/entity/DynamicMapEntityTuplizer.java 2008-10-07
15:54:42 UTC (rev 15258)
+++
core/branches/Branch_3_3/core/src/main/java/org/hibernate/tuple/entity/DynamicMapEntityTuplizer.java 2008-10-07
15:56:16 UTC (rev 15259)
@@ -28,6 +28,8 @@
import org.hibernate.EntityMode;
import org.hibernate.HibernateException;
+import org.hibernate.EntityNameResolver;
+import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.tuple.Instantiator;
import org.hibernate.tuple.DynamicMapInstantiator;
import org.hibernate.mapping.PersistentClass;
@@ -112,4 +114,37 @@
public boolean isInstrumented() {
return false;
}
+
+ public EntityNameResolver[] getEntityNameResolvers() {
+ return new EntityNameResolver[] { BasicEntityNameResolver.INSTANCE };
+ }
+
+ public String determineConcreteSubclassEntityName(Object entityInstance,
SessionFactoryImplementor factory) {
+ // TODO : do we need an explicit isInstance check here, or is that asserted prior to
here?
+ return extractEmbeddedEntityName( ( Map ) entityInstance );
+ }
+
+ public static String extractEmbeddedEntityName(Map entity) {
+ return ( String ) entity.get( DynamicMapInstantiator.KEY );
+ }
+
+ public static class BasicEntityNameResolver implements EntityNameResolver {
+ public static final BasicEntityNameResolver INSTANCE = new BasicEntityNameResolver();
+
+ public String resolveEntityName(Object entity) {
+ final String entityName = extractEmbeddedEntityName( ( Map ) entity );
+ if ( entityName == null ) {
+ throw new HibernateException( "Could not determine type of dynamic map
entity" );
+ }
+ return entityName;
+ }
+
+ public boolean equals(Object obj) {
+ return getClass().equals( obj.getClass() );
+ }
+
+ public int hashCode() {
+ return getClass().hashCode();
+ }
+ }
}
Modified:
core/branches/Branch_3_3/core/src/main/java/org/hibernate/tuple/entity/EntityMetamodel.java
===================================================================
---
core/branches/Branch_3_3/core/src/main/java/org/hibernate/tuple/entity/EntityMetamodel.java 2008-10-07
15:54:42 UTC (rev 15258)
+++
core/branches/Branch_3_3/core/src/main/java/org/hibernate/tuple/entity/EntityMetamodel.java 2008-10-07
15:56:16 UTC (rev 15259)
@@ -122,21 +122,10 @@
private final boolean inherited;
private final boolean hasSubclasses;
private final Set subclassEntityNames = new HashSet();
+ private final Map entityNameByInheritenceClassNameMap = new HashMap();
private final EntityEntityModeToTuplizerMapping tuplizerMapping;
- public EntityTuplizer getTuplizer(EntityMode entityMode) {
- return (EntityTuplizer) tuplizerMapping.getTuplizer( entityMode );
- }
-
- public EntityTuplizer getTuplizerOrNull(EntityMode entityMode) {
- return ( EntityTuplizer ) tuplizerMapping.getTuplizerOrNull( entityMode );
- }
-
- public EntityMode guessEntityMode(Object object) {
- return tuplizerMapping.guessEntityMode( object );
- }
-
public EntityMetamodel(PersistentClass persistentClass, SessionFactoryImplementor
sessionFactory) {
this.sessionFactory = sessionFactory;
@@ -322,6 +311,15 @@
}
subclassEntityNames.add( name );
+ if ( persistentClass.hasPojoRepresentation() ) {
+ entityNameByInheritenceClassNameMap.put( persistentClass.getMappedClass(),
persistentClass.getEntityName() );
+ iter = persistentClass.getSubclassIterator();
+ while ( iter.hasNext() ) {
+ final PersistentClass pc = ( PersistentClass ) iter.next();
+ entityNameByInheritenceClassNameMap.put( pc.getMappedClass(), pc.getEntityName() );
+ }
+ }
+
tuplizerMapping = new EntityEntityModeToTuplizerMapping( persistentClass, this );
}
@@ -395,6 +393,22 @@
}
}
+ public EntityEntityModeToTuplizerMapping getTuplizerMapping() {
+ return tuplizerMapping;
+ }
+
+ public EntityTuplizer getTuplizer(EntityMode entityMode) {
+ return (EntityTuplizer) tuplizerMapping.getTuplizer( entityMode );
+ }
+
+ public EntityTuplizer getTuplizerOrNull(EntityMode entityMode) {
+ return ( EntityTuplizer ) tuplizerMapping.getTuplizerOrNull( entityMode );
+ }
+
+ public EntityMode guessEntityMode(Object object) {
+ return tuplizerMapping.guessEntityMode( object );
+ }
+
public int[] getNaturalIdentifierProperties() {
return naturalIdPropertyNumbers;
}
@@ -555,6 +569,16 @@
return isAbstract;
}
+ /**
+ * Return the entity-name mapped to the given class within our inheritence hierarchy, if
any.
+ *
+ * @param inheritenceClass The class for which to resolve the entity-name.
+ * @return The mapped entity-name, or null if no such mapping was found.
+ */
+ public String findEntityNameByEntityClass(Class inheritenceClass) {
+ return ( String ) entityNameByInheritenceClassNameMap.get( inheritenceClass.getName()
);
+ }
+
public String toString() {
return "EntityMetamodel(" + name + ':' +
ArrayHelper.toString(properties) + ')';
}
Modified:
core/branches/Branch_3_3/core/src/main/java/org/hibernate/tuple/entity/EntityTuplizer.java
===================================================================
---
core/branches/Branch_3_3/core/src/main/java/org/hibernate/tuple/entity/EntityTuplizer.java 2008-10-07
15:54:42 UTC (rev 15258)
+++
core/branches/Branch_3_3/core/src/main/java/org/hibernate/tuple/entity/EntityTuplizer.java 2008-10-07
15:56:16 UTC (rev 15259)
@@ -28,8 +28,11 @@
import java.util.Map;
import org.hibernate.HibernateException;
+import org.hibernate.EntityNameResolver;
+import org.hibernate.EntityMode;
import org.hibernate.tuple.Tuplizer;
import org.hibernate.engine.SessionImplementor;
+import org.hibernate.engine.SessionFactoryImplementor;
/**
* Defines further responsibilities reagarding tuplization based on
@@ -42,6 +45,12 @@
* @author Steve Ebersole
*/
public interface EntityTuplizer extends Tuplizer {
+ /**
+ * Return the entity-mode handled by this tuplizer instance.
+ *
+ * @return The entity-mode
+ */
+ public EntityMode getEntityMode();
/**
* Create an entity instance initialized with the given identifier.
@@ -176,11 +185,11 @@
*/
public boolean isValidatableImplementor();
- // TODO: getConcreteProxyClass() is solely used (externally) to perform narrowProxy()
- // would be great to fully encapsulate that narrowProxy() functionality within the
- // Tuplizer, itself, with a Tuplizer.narrowProxy(..., PersistentContext) method
/**
* Returns the java class to which generated proxies will be typed.
+ * <p/>
+ * todo : look at fully encapsulating {@link
org.hibernate.engine.PersistenceContext#narrowProxy} here,
+ * since that is the only external use of this method
*
* @return The java class to which generated proxies will be typed
*/
@@ -198,4 +207,35 @@
* Is it an instrumented POJO?
*/
public boolean isInstrumented();
+
+ /**
+ * Get any {@link EntityNameResolver EntityNameResolvers} associated with this {@link
Tuplizer}.
+ *
+ * @return The associated resolvers. May be null or empty.
+ */
+ public EntityNameResolver[] getEntityNameResolvers();
+
+ /**
+ * Given an entity instance, determine the most appropriate (most targeted) entity-name
which represents it.
+ * This is called in situations where we already know an entity name for the given
entityInstance; we are being
+ * asked to determine if there is a more appropriate entity-name to use, specifically
within an inheritence
+ * hierarchy.
+ * <p/>
+ * For example, consider a case where a user calls <tt>session.update(
"Animal", cat );</tt>. Here, the
+ * user has explicitly provided <tt>Animal</tt> as the entity-name.
However, they have passed in an instance
+ * of <tt>Cat</tt> which is a subclass of <tt>Animal</tt>. In
this case, we would return <tt>Cat</tt> as the
+ * entity-name.
+ * <p/>
+ * <tt>null</tt> may be returned from calls to this method. The meaining of
<tt>null</tt> in that case is assumed
+ * to be that we should use whatever explicit entity-name the user provided
(<tt>Animal</tt> rather than <tt>Cat</tt>
+ * in the example above).
+ *
+ * @param entityInstance The entity instance.
+ * @param factory Reference to the SessionFactory.
+ *
+ * @return The most appropriate entity name to use.
+ *
+ * @throws HibernateException If we are unable to determine an entity-name within the
inheritence hierarchy.
+ */
+ public String determineConcreteSubclassEntityName(Object entityInstance,
SessionFactoryImplementor factory);
}
Modified:
core/branches/Branch_3_3/core/src/main/java/org/hibernate/tuple/entity/PojoEntityTuplizer.java
===================================================================
---
core/branches/Branch_3_3/core/src/main/java/org/hibernate/tuple/entity/PojoEntityTuplizer.java 2008-10-07
15:54:42 UTC (rev 15258)
+++
core/branches/Branch_3_3/core/src/main/java/org/hibernate/tuple/entity/PojoEntityTuplizer.java 2008-10-07
15:56:16 UTC (rev 15259)
@@ -36,6 +36,7 @@
import org.hibernate.EntityMode;
import org.hibernate.HibernateException;
import org.hibernate.MappingException;
+import org.hibernate.EntityNameResolver;
import org.hibernate.tuple.Instantiator;
import org.hibernate.tuple.PojoInstantiator;
import org.hibernate.bytecode.ReflectionOptimizer;
@@ -43,6 +44,7 @@
import org.hibernate.classic.Lifecycle;
import org.hibernate.classic.Validatable;
import org.hibernate.engine.SessionImplementor;
+import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.intercept.FieldInterceptor;
import org.hibernate.intercept.FieldInterceptionHelper;
import org.hibernate.mapping.PersistentClass;
@@ -70,7 +72,7 @@
private final boolean lifecycleImplementor;
private final boolean validatableImplementor;
private final Set lazyPropertyNames = new HashSet();
- private ReflectionOptimizer optimizer;
+ private final ReflectionOptimizer optimizer;
public PojoEntityTuplizer(EntityMetamodel entityMetamodel, PersistentClass mappedEntity)
{
super( entityMetamodel, mappedEntity );
@@ -109,6 +111,9 @@
}
+ /**
+ * {@inheritDoc}
+ */
protected ProxyFactory buildProxyFactory(PersistentClass persistentClass, Getter
idGetter, Setter idSetter) {
// determine the id getter and setter methods from the proxy interface (if any)
// determine all interfaces needed by the resulting proxy
@@ -199,11 +204,14 @@
}
protected ProxyFactory buildProxyFactoryInternal(PersistentClass persistentClass, Getter
idGetter, Setter idSetter) {
- // TODO : YUCK!!! finx after HHH-1907 is complete
+ // TODO : YUCK!!! fix after HHH-1907 is complete
return Environment.getBytecodeProvider().getProxyFactoryFactory().buildProxyFactory();
// return
getFactory().getSettings().getBytecodeProvider().getProxyFactoryFactory().buildProxyFactory();
}
+ /**
+ * {@inheritDoc}
+ */
protected Instantiator buildInstantiator(PersistentClass persistentClass) {
if ( optimizer == null ) {
return new PojoInstantiator( persistentClass, null );
@@ -213,6 +221,9 @@
}
}
+ /**
+ * {@inheritDoc}
+ */
public void setPropertyValues(Object entity, Object[] values) throws HibernateException
{
if ( !getEntityMetamodel().hasLazyProperties() && optimizer != null &&
optimizer.getAccessOptimizer() != null ) {
setPropertyValuesWithOptimizer( entity, values );
@@ -222,6 +233,9 @@
}
}
+ /**
+ * {@inheritDoc}
+ */
public Object[] getPropertyValues(Object entity) throws HibernateException {
if ( shouldGetAllProperties( entity ) && optimizer != null &&
optimizer.getAccessOptimizer() != null ) {
return getPropertyValuesWithOptimizer( entity );
@@ -231,6 +245,9 @@
}
}
+ /**
+ * {@inheritDoc}
+ */
public Object[] getPropertyValuesToInsert(Object entity, Map mergeMap,
SessionImplementor session) throws HibernateException {
if ( shouldGetAllProperties( entity ) && optimizer != null &&
optimizer.getAccessOptimizer() != null ) {
return getPropertyValuesWithOptimizer( entity );
@@ -248,36 +265,60 @@
return optimizer.getAccessOptimizer().getPropertyValues( object );
}
+ /**
+ * {@inheritDoc}
+ */
public EntityMode getEntityMode() {
return EntityMode.POJO;
}
+ /**
+ * {@inheritDoc}
+ */
public Class getMappedClass() {
return mappedClass;
}
+ /**
+ * {@inheritDoc}
+ */
public boolean isLifecycleImplementor() {
return lifecycleImplementor;
}
+ /**
+ * {@inheritDoc}
+ */
public boolean isValidatableImplementor() {
return validatableImplementor;
}
+ /**
+ * {@inheritDoc}
+ */
protected Getter buildPropertyGetter(Property mappedProperty, PersistentClass
mappedEntity) {
return mappedProperty.getGetter( mappedEntity.getMappedClass() );
}
+ /**
+ * {@inheritDoc}
+ */
protected Setter buildPropertySetter(Property mappedProperty, PersistentClass
mappedEntity) {
return mappedProperty.getSetter( mappedEntity.getMappedClass() );
}
+ /**
+ * {@inheritDoc}
+ */
public Class getConcreteProxyClass() {
return proxyInterface;
}
//TODO: need to make the majority of this functionality into a top-level support
class for custom impl support
+ /**
+ * {@inheritDoc}
+ */
public void afterInitialize(Object entity, boolean lazyPropertiesAreUnfetched,
SessionImplementor session) {
if ( isInstrumented() ) {
Set lazyProps = lazyPropertiesAreUnfetched &&
getEntityMetamodel().hasLazyProperties() ?
@@ -288,6 +329,9 @@
}
}
+ /**
+ * {@inheritDoc}
+ */
public boolean hasUninitializedLazyProperties(Object entity) {
if ( getEntityMetamodel().hasLazyProperties() ) {
FieldInterceptor callback = FieldInterceptionHelper.extractFieldInterceptor( entity
);
@@ -298,8 +342,37 @@
}
}
+ /**
+ * {@inheritDoc}
+ */
public boolean isInstrumented() {
return FieldInterceptionHelper.isInstrumented( getMappedClass() );
}
+ /**
+ * {@inheritDoc}
+ */
+ public String determineConcreteSubclassEntityName(Object entityInstance,
SessionFactoryImplementor factory) {
+ final Class concreteEntityClass = entityInstance.getClass();
+ if ( concreteEntityClass == getMappedClass() ) {
+ return getEntityName();
+ }
+ else {
+ String entityName = getEntityMetamodel().findEntityNameByEntityClass(
concreteEntityClass );
+ if ( entityName == null ) {
+ throw new HibernateException(
+ "Unable to resolve entity name from Class [" +
concreteEntityClass.getName() + "]"
+ + " expected instance/subclass of [" + getEntityName() + "]"
+ );
+ }
+ return entityName;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public EntityNameResolver[] getEntityNameResolvers() {
+ return null;
+ }
}
Added:
core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/dynamicentity/tuplizer2/Customer.hbm.xml
===================================================================
---
core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/dynamicentity/tuplizer2/Customer.hbm.xml
(rev 0)
+++
core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/dynamicentity/tuplizer2/Customer.hbm.xml 2008-10-07
15:56:16 UTC (rev 15259)
@@ -0,0 +1,72 @@
+<?xml version="1.0"?>
+<!--
+ ~ Hibernate, Relational Persistence for Idiomatic Java
+ ~
+ ~ Copyright (c) 2008, 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
+ ~
+ -->
+
+<!DOCTYPE hibernate-mapping PUBLIC
+ "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
+ "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
+
+<hibernate-mapping package="org.hibernate.test.dynamicentity">
+
+ <class name="Person" table="t_person"
discriminator-value="person" abstract="false">
+ <tuplizer
class="org.hibernate.test.dynamicentity.tuplizer2.MyEntityTuplizer"
entity-mode="pojo"/>
+ <id name="id">
+ <generator class="native"/>
+ </id>
+ <discriminator force="false"/>
+ <property name="name"/>
+
+ <many-to-one name="address" cascade="all"
column="addr_id"/>
+
+ <set name="family" lazy="true"
cascade="all">
+ <key column="pers_id"/>
+ <one-to-many class="Person"/>
+ </set>
+
+ <subclass name="Customer" discriminator-value="customer"
abstract="false">
+ <tuplizer
class="org.hibernate.test.dynamicentity.tuplizer2.MyEntityTuplizer"
entity-mode="pojo"/>
+ <many-to-one name="company" cascade="none"
column="comp_id"/>
+ </subclass>
+ </class>
+
+ <class name="Company" table="t_company"
abstract="false">
+ <tuplizer
class="org.hibernate.test.dynamicentity.tuplizer2.MyEntityTuplizer"
entity-mode="pojo"/>
+ <id name="id">
+ <generator class="native"/>
+ </id>
+ <property name="name"/>
+ </class>
+
+ <class name="Address" table="t_address"
abstract="false">
+ <tuplizer
class="org.hibernate.test.dynamicentity.tuplizer2.MyEntityTuplizer"
entity-mode="pojo"/>
+ <id name="id">
+ <generator class="native"/>
+ </id>
+ <property name="street"/>
+ <property name="city"/>
+ <property name="postalCode"/>
+ </class>
+
+</hibernate-mapping>
Added:
core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/dynamicentity/tuplizer2/ImprovedTuplizerDynamicEntityTest.java
===================================================================
---
core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/dynamicentity/tuplizer2/ImprovedTuplizerDynamicEntityTest.java
(rev 0)
+++
core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/dynamicentity/tuplizer2/ImprovedTuplizerDynamicEntityTest.java 2008-10-07
15:56:16 UTC (rev 15259)
@@ -0,0 +1,149 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, 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.test.dynamicentity.tuplizer2;
+
+import org.hibernate.test.dynamicentity.Company;
+import org.hibernate.test.dynamicentity.ProxyHelper;
+import org.hibernate.test.dynamicentity.Customer;
+import org.hibernate.test.dynamicentity.Address;
+import org.hibernate.test.dynamicentity.Person;
+import org.hibernate.Session;
+import org.hibernate.Hibernate;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.junit.functional.FunctionalTestCase;
+import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
+
+import junit.framework.TestSuite;
+
+import java.util.HashSet;
+
+/**
+ * Demonstrates use of Tuplizers to allow the use of JDK
+ * {@link java.lang.reflect.Proxy dynamic proxies} as our
+ * domain model.
+ * <p/>
+ * Here we plug a custom Interceptor into the session simply to
+ * allow us to not have to explicitly supply the appropriate entity
+ * name to the Session calls.
+ *
+ * @author Steve Ebersole
+ */
+public class ImprovedTuplizerDynamicEntityTest extends FunctionalTestCase {
+ public ImprovedTuplizerDynamicEntityTest(String x) {
+ super( x );
+ }
+
+ public String[] getMappings() {
+ return new String[] { "dynamicentity/tuplizer2/Customer.hbm.xml" };
+ }
+
+ public void configure(Configuration cfg) {
+ super.configure( cfg );
+ }
+
+ public static TestSuite suite() {
+ return new FunctionalTestClassTestSuite( ImprovedTuplizerDynamicEntityTest.class );
+ }
+
+ public void testIt() {
+ // Test saving these dyna-proxies
+ Session session = openSession();
+ session.beginTransaction();
+ Company company = ProxyHelper.newCompanyProxy();
+ company.setName( "acme" );
+ session.save( company );
+ Customer customer = ProxyHelper.newCustomerProxy();
+ customer.setName( "Steve" );
+ customer.setCompany( company );
+ Address address = ProxyHelper.newAddressProxy();
+ address.setStreet( "somewhere over the rainbow" );
+ address.setCity( "lawerence, kansas" );
+ address.setPostalCode( "toto");
+ customer.setAddress( address );
+ customer.setFamily( new HashSet() );
+ Person son = ProxyHelper.newPersonProxy();
+ son.setName( "son" );
+ customer.getFamily().add( son );
+ Person wife = ProxyHelper.newPersonProxy();
+ wife.setName( "wife" );
+ customer.getFamily().add( wife );
+ session.save( customer );
+ session.getTransaction().commit();
+ session.close();
+
+ assertNotNull( "company id not assigned", company.getId() );
+ assertNotNull( "customer id not assigned", customer.getId() );
+ assertNotNull( "address id not assigned", address.getId() );
+ assertNotNull( "son:Person id not assigned", son.getId() );
+ assertNotNull( "wife:Person id not assigned", wife.getId() );
+
+ // Test loading these dyna-proxies, along with flush processing
+ session = openSession();
+ session.beginTransaction();
+ customer = ( Customer ) session.load( Customer.class, customer.getId() );
+ assertFalse( "should-be-proxy was initialized", Hibernate.isInitialized(
customer ) );
+
+ customer.setName( "other" );
+ session.flush();
+ assertFalse( "should-be-proxy was initialized", Hibernate.isInitialized(
customer.getCompany() ) );
+
+ session.refresh( customer );
+ assertEquals( "name not updated", "other", customer.getName() );
+ assertEquals( "company association not correct", "acme",
customer.getCompany().getName() );
+
+ session.getTransaction().commit();
+ session.close();
+
+ // Test detached entity re-attachment with these dyna-proxies
+ customer.setName( "Steve" );
+ session = openSession();
+ session.beginTransaction();
+ session.update( customer );
+ session.flush();
+ session.refresh( customer );
+ assertEquals( "name not updated", "Steve", customer.getName() );
+ session.getTransaction().commit();
+ session.close();
+
+ // Test querying
+ session = openSession();
+ session.beginTransaction();
+ int count = session.createQuery( "from Customer" ).list().size();
+ assertEquals( "querying dynamic entity", 1, count );
+ session.clear();
+ count = session.createQuery( "from Person" ).list().size();
+ assertEquals( "querying dynamic entity", 3, count );
+ session.getTransaction().commit();
+ session.close();
+
+ // test deleteing
+ session = openSession();
+ session.beginTransaction();
+ session.delete( company );
+ session.delete( customer );
+ session.getTransaction().commit();
+ session.close();
+ }
+}
Added:
core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/dynamicentity/tuplizer2/MyEntityInstantiator.java
===================================================================
---
core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/dynamicentity/tuplizer2/MyEntityInstantiator.java
(rev 0)
+++
core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/dynamicentity/tuplizer2/MyEntityInstantiator.java 2008-10-07
15:56:16 UTC (rev 15259)
@@ -0,0 +1,78 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, 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.test.dynamicentity.tuplizer2;
+
+import org.hibernate.tuple.Instantiator;
+import org.hibernate.test.dynamicentity.Customer;
+import org.hibernate.test.dynamicentity.ProxyHelper;
+import org.hibernate.test.dynamicentity.Company;
+import org.hibernate.test.dynamicentity.Address;
+import org.hibernate.test.dynamicentity.Person;
+import org.hibernate.util.ReflectHelper;
+import org.hibernate.HibernateException;
+
+import java.io.Serializable;
+
+/**
+ * @author Steve Ebersole
+ */
+public class MyEntityInstantiator implements Instantiator {
+ private final String entityName;
+
+ public MyEntityInstantiator(String entityName) {
+ this.entityName = entityName;
+ }
+
+ public Object instantiate(Serializable id) {
+ if ( Person.class.getName().equals( entityName ) ) {
+ return ProxyHelper.newPersonProxy( id );
+ }
+ if ( Customer.class.getName().equals( entityName ) ) {
+ return ProxyHelper.newCustomerProxy( id );
+ }
+ else if ( Company.class.getName().equals( entityName ) ) {
+ return ProxyHelper.newCompanyProxy( id );
+ }
+ else if ( Address.class.getName().equals( entityName ) ) {
+ return ProxyHelper.newAddressProxy( id );
+ }
+ else {
+ throw new IllegalArgumentException( "unknown entity for instantiation [" +
entityName + "]" );
+ }
+ }
+
+ public Object instantiate() {
+ return instantiate( null );
+ }
+
+ public boolean isInstance(Object object) {
+ try {
+ return ReflectHelper.classForName( entityName ).isInstance( object );
+ }
+ catch( Throwable t ) {
+ throw new HibernateException( "could not get handle to entity-name as interface :
" + t );
+ }
+ }
+}
Added:
core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/dynamicentity/tuplizer2/MyEntityTuplizer.java
===================================================================
---
core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/dynamicentity/tuplizer2/MyEntityTuplizer.java
(rev 0)
+++
core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/dynamicentity/tuplizer2/MyEntityTuplizer.java 2008-10-07
15:56:16 UTC (rev 15259)
@@ -0,0 +1,87 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, 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.test.dynamicentity.tuplizer2;
+
+import org.hibernate.tuple.entity.PojoEntityTuplizer;
+import org.hibernate.tuple.entity.EntityMetamodel;
+import org.hibernate.tuple.Instantiator;
+import org.hibernate.mapping.PersistentClass;
+import org.hibernate.proxy.ProxyFactory;
+import org.hibernate.property.Getter;
+import org.hibernate.property.Setter;
+import org.hibernate.test.dynamicentity.tuplizer.MyEntityInstantiator;
+import org.hibernate.test.dynamicentity.ProxyHelper;
+import org.hibernate.engine.SessionFactoryImplementor;
+import org.hibernate.EntityNameResolver;
+
+/**
+ * @author Steve Ebersole
+ */
+public class MyEntityTuplizer extends PojoEntityTuplizer {
+
+ public MyEntityTuplizer(EntityMetamodel entityMetamodel, PersistentClass mappedEntity)
{
+ super( entityMetamodel, mappedEntity );
+ }
+
+ public EntityNameResolver[] getEntityNameResolvers() {
+ return new EntityNameResolver[] { MyEntityNameResolver.INSTANCE };
+ }
+
+ protected Instantiator buildInstantiator(PersistentClass persistentClass) {
+ return new MyEntityInstantiator( persistentClass.getEntityName() );
+ }
+
+ public String determineConcreteSubclassEntityName(Object entityInstance,
SessionFactoryImplementor factory) {
+ String entityName = ProxyHelper.extractEntityName( entityInstance );
+ if ( entityName == null ) {
+ entityName = super.determineConcreteSubclassEntityName( entityInstance, factory );
+ }
+ return entityName;
+ }
+
+ protected ProxyFactory buildProxyFactory(PersistentClass persistentClass, Getter
idGetter, Setter idSetter) {
+ // allows defining a custom proxy factory, which is responsible for
+ // generating lazy proxies for a given entity.
+ //
+ // Here we simply use the default...
+ return super.buildProxyFactory( persistentClass, idGetter, idSetter );
+ }
+
+ public static class MyEntityNameResolver implements EntityNameResolver {
+ public static final MyEntityNameResolver INSTANCE = new MyEntityNameResolver();
+
+ public String resolveEntityName(Object entity) {
+ return ProxyHelper.extractEntityName( entity );
+ }
+
+ public boolean equals(Object obj) {
+ return getClass().equals( obj.getClass() );
+ }
+
+ public int hashCode() {
+ return getClass().hashCode();
+ }
+ }
+}