Java Mailing List Archive

http://www.gg3721.com/

Home » Hibernate Commits List »

[hibernate-commits] Hibernate SVN: r15269 - in
 core/branches/Branch_3_2: src/org/hibernate/impl and 5 other
 directories.

hibernate-commits

2008-10-08


Author LoginPost Reply
Author: steve.ebersole@(protected)
Date: 2008-10-08 00:20:21 -0400 (Wed, 08 Oct 2008)
New Revision: 15269

Added:
 core/branches/Branch_3_2/src/org/hibernate/EntityNameResolver.java
 core/branches/Branch_3_2/test/org/hibernate/test/dynamicentity/tuplizer2/
 core/branches/Branch_3_2/test/org/hibernate/test/dynamicentity/tuplizer2/Customer.hbm.xml
 core/branches/Branch_3_2/test/org/hibernate/test/dynamicentity/tuplizer2/ImprovedTuplizerDynamicEntityTest.java
 core/branches/Branch_3_2/test/org/hibernate/test/dynamicentity/tuplizer2/MyEntityInstantiator.java
 core/branches/Branch_3_2/test/org/hibernate/test/dynamicentity/tuplizer2/MyEntityTuplizer.java
Modified:
 core/branches/Branch_3_2/src/org/hibernate/impl/SessionFactoryImpl.java
 core/branches/Branch_3_2/src/org/hibernate/impl/SessionImpl.java
 core/branches/Branch_3_2/src/org/hibernate/persister/entity/AbstractEntityPersister.java
 core/branches/Branch_3_2/src/org/hibernate/persister/entity/EntityPersister.java
 core/branches/Branch_3_2/src/org/hibernate/tuple/EntityModeToTuplizerMapping.java
 core/branches/Branch_3_2/src/org/hibernate/tuple/entity/AbstractEntityTuplizer.java
 core/branches/Branch_3_2/src/org/hibernate/tuple/entity/Dom4jEntityTuplizer.java
 core/branches/Branch_3_2/src/org/hibernate/tuple/entity/DynamicMapEntityTuplizer.java
 core/branches/Branch_3_2/src/org/hibernate/tuple/entity/EntityMetamodel.java
 core/branches/Branch_3_2/src/org/hibernate/tuple/entity/EntityTuplizer.java
 core/branches/Branch_3_2/src/org/hibernate/tuple/entity/PojoEntityTuplizer.java
Log:
HHH-3515 : EntityNameResolver

Added: core/branches/Branch_3_2/src/org/hibernate/EntityNameResolver.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/EntityNameResolver.java                  (rev 0)
+++ core/branches/Branch_3_2/src/org/hibernate/EntityNameResolver.java  2008-10-08 04:20:21 UTC (rev 15269)
@@(protected) @@
+/*
+ * 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_2/src/org/hibernate/impl/SessionFactoryImpl.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/impl/SessionFactoryImpl.java  2008-10-08 04:13:07 UTC (rev 15268)
+++ core/branches/Branch_3_2/src/org/hibernate/impl/SessionFactoryImpl.java  2008-10-08 04:20:21 UTC (rev 15269)
@@(protected) @@
import java.util.Map;
import java.util.Properties;
import java.util.Set;
+import java.util.LinkedHashSet;

import javax.naming.NamingException;
import javax.naming.Reference;
@@(protected) @@
import org.hibernate.QueryException;
import org.hibernate.SessionFactory;
import org.hibernate.StatelessSession;
+import org.hibernate.EntityNameResolver;
+import org.hibernate.tuple.entity.EntityTuplizer;
import org.hibernate.engine.query.sql.NativeSQLQuerySpecification;
import org.hibernate.cache.Cache;
import org.hibernate.cache.CacheConcurrencyStrategy;
@@(protected) @@
import org.hibernate.type.Type;
import org.hibernate.util.CollectionHelper;
import org.hibernate.util.ReflectHelper;
+import org.hibernate.util.EmptyIterator;


/**
@@(protected) @@
 private final transient CurrentSessionContext currentSessionContext;
 private final transient EntityNotFoundDelegate entityNotFoundDelegate;
 private final transient SQLFunctionRegistry sqlFunctionRegistry;
+  private final transient HashMap entityNameResolvers = new HashMap();
 
 private final QueryPlanCache queryPlanCache = new QueryPlanCache( this );

@@(protected) @@
   // 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:
@@(protected) @@
   this.entityNotFoundDelegate = entityNotFoundDelegate;
 }

+  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_2/src/org/hibernate/impl/SessionImpl.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/impl/SessionImpl.java  2008-10-08 04:13:07 UTC (rev 15268)
+++ core/branches/Branch_3_2/src/org/hibernate/impl/SessionImpl.java  2008-10-08 04:20:21 UTC (rev 15269)
@@(protected) @@
import org.hibernate.Transaction;
import org.hibernate.TransientObjectException;
import org.hibernate.UnresolvableObjectException;
+import org.hibernate.EntityNameResolver;
import org.hibernate.engine.query.sql.NativeSQLQuerySpecification;
import org.hibernate.collection.PersistentCollection;
import org.hibernate.engine.ActionQueue;
@@(protected) @@
 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".
  *
@@(protected) @@

 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_2/src/org/hibernate/persister/entity/AbstractEntityPersister.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/persister/entity/AbstractEntityPersister.java  2008-10-08 04:13:07 UTC (rev 15268)
+++ core/branches/Branch_3_2/src/org/hibernate/persister/entity/AbstractEntityPersister.java  2008-10-08 04:20:21 UTC (rev 15269)
@@(protected) @@
 private final boolean isLazyPropertiesCacheable;
 private final CacheEntryStructure cacheEntryStructure;
 private final EntityMetamodel entityMetamodel;
-  private final Map entityNameBySubclass = new HashMap();
 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

 private final String[] rootTableKeyColumnNames;
@@(protected) @@
       (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();
@@(protected) @@
   return entityMetamodel.getEntityType();
 }

-  private String getSubclassEntityName(Class clazz) {
-    return ( String ) entityNameBySubclass.get( clazz );
-  }
-
 public boolean isPolymorphic() {
   return entityMetamodel.isPolymorphic();
 }
@@(protected) @@
   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_2/src/org/hibernate/persister/entity/EntityPersister.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/persister/entity/EntityPersister.java  2008-10-08 04:13:07 UTC (rev 15268)
+++ core/branches/Branch_3_2/src/org/hibernate/persister/entity/EntityPersister.java  2008-10-08 04:20:21 UTC (rev 15269)
@@(protected) @@
 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_2/src/org/hibernate/tuple/EntityModeToTuplizerMapping.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/tuple/EntityModeToTuplizerMapping.java  2008-10-08 04:13:07 UTC (rev 15268)
+++ core/branches/Branch_3_2/src/org/hibernate/tuple/EntityModeToTuplizerMapping.java  2008-10-08 04:20:21 UTC (rev 15269)
@@(protected) @@
 }

 /**
+   * Allow iteration over all defined {@(protected)}.
+   *
+   * @return Iterator over defined tuplizers
+   */
+  public Iterator iterateTuplizers() {
+    return tuplizers.values().iterator();
+  }
+
+  /**
  * Given a supposed instance of an entity/component, guess its entity mode.
  *
  * @param object The supposed instance of the entity/component.

Modified: core/branches/Branch_3_2/src/org/hibernate/tuple/entity/AbstractEntityTuplizer.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/tuple/entity/AbstractEntityTuplizer.java  2008-10-08 04:13:07 UTC (rev 15268)
+++ core/branches/Branch_3_2/src/org/hibernate/tuple/entity/AbstractEntityTuplizer.java  2008-10-08 04:20:21 UTC (rev 15269)
@@(protected) @@


 /**
-   * 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.
@@(protected) @@
  * @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_2/src/org/hibernate/tuple/entity/Dom4jEntityTuplizer.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/tuple/entity/Dom4jEntityTuplizer.java  2008-10-08 04:13:07 UTC (rev 15268)
+++ core/branches/Branch_3_2/src/org/hibernate/tuple/entity/Dom4jEntityTuplizer.java  2008-10-08 04:20:21 UTC (rev 15269)
@@(protected) @@
-// $Id: Dom4jEntityTuplizer.java 9210 2006-02-03 22:15:19Z steveebersole $
+/*
+ * 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.tuple.entity;

import org.hibernate.mapping.PersistentClass;
@@(protected) @@
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;
@@(protected) @@

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

 static final Log log = LogFactory.getLog( 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() );
   }
 }
-  
+
+  /**
+   * {@(protected)}
+   */
 public EntityMode getEntityMode() {
   return EntityMode.DOM4J;
 }
@@(protected) @@
     return mappedProperty.getPropertyAccessor(null);
   }
   else {
-      return PropertyAccessorFactory.getDom4jPropertyAccessor(
-          mappedProperty.getNodeName(),
+      return PropertyAccessorFactory.getDom4jPropertyAccessor(
+          mappedProperty.getNodeName(),
         mappedProperty.getType(),
         getEntityMetamodel().getSessionFactory()
       );
   }
 }

+  /**
+   * {@(protected)}
+   */
 protected Getter buildPropertyGetter(Property mappedProperty, PersistentClass mappedEntity) {
   return buildPropertyAccessor(mappedProperty).getGetter( null, mappedProperty.getName() );
 }

+  /**
+   * {@(protected)}
+   */
 protected Setter buildPropertySetter(Property mappedProperty, PersistentClass mappedEntity) {
   return buildPropertyAccessor(mappedProperty).getSetter( null, mappedProperty.getName() );
 }

+  /**
+   * {@(protected)}
+   */
 protected Instantiator buildInstantiator(PersistentClass persistentClass) {
   return new Dom4jInstantiator( persistentClass );
 }

+  /**
+   * {@(protected)}
+   */
 public Serializable getIdentifier(Object entityOrId) throws HibernateException {
   if (entityOrId instanceof Element) {
     return super.getIdentifier(entityOrId);
@@(protected) @@
     return (Serializable) entityOrId;
   }
 }
-  
+
+  /**
+   * {@(protected)}
+   */
 protected ProxyFactory buildProxyFactory(PersistentClass mappingInfo, Getter idGetter, Setter idSetter) {
   HashSet proxyInterfaces = new HashSet();
   proxyInterfaces.add( HibernateProxy.class );
@@(protected) @@
   return pf;
 }

+  /**
+   * {@(protected)}
+   */
 public Class getMappedClass() {
   return Element.class;
 }

+  /**
+   * {@(protected)}
+   */
 public Class getConcreteProxyClass() {
   return Element.class;
 }

+  /**
+   * {@(protected)}
+   */
 public boolean isInstrumented() {
   return false;
 }
+
+  /**
+   * {@(protected)}
+   */
+  public EntityNameResolver[] getEntityNameResolvers() {
+    return new EntityNameResolver[] { new BasicEntityNameResolver( getEntityName(), inheritenceNodeNameMap ) };
+  }
+
+  /**
+   * {@(protected)}
+   */
+  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;
+    }
+
+    /**
+     * {@(protected)}
+     */
+    public String resolveEntityName(Object entity) {
+    return ( String ) nodeNameToEntityNameMap.get( extractNodeName( ( Element ) entity ) );
+    }
+
+    /**
+     * {@(protected)}
+     */
+    public boolean equals(Object obj) {
+      return rootEntityName.equals( ( ( BasicEntityNameResolver ) obj ).rootEntityName );
+    }
+
+    /**
+     * {@(protected)}
+     */
+    public int hashCode() {
+      return rootEntityName.hashCode();
+    }
+  }
}

Modified: core/branches/Branch_3_2/src/org/hibernate/tuple/entity/DynamicMapEntityTuplizer.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/tuple/entity/DynamicMapEntityTuplizer.java  2008-10-08 04:13:07 UTC (rev 15268)
+++ core/branches/Branch_3_2/src/org/hibernate/tuple/entity/DynamicMapEntityTuplizer.java  2008-10-08 04:20:21 UTC (rev 15269)
@@(protected) @@
-// $Id: DynamicMapEntityTuplizer.java 9210 2006-02-03 22:15:19Z steveebersole $
+/*
+ * 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.tuple.entity;

import java.util.Map;

import org.hibernate.EntityMode;
import org.hibernate.HibernateException;
-import org.hibernate.tuple.entity.AbstractEntityTuplizer;
+import org.hibernate.EntityNameResolver;
+import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.tuple.Instantiator;
import org.hibernate.tuple.DynamicMapInstantiator;
import org.hibernate.mapping.PersistentClass;
@@(protected) @@
 DynamicMapEntityTuplizer(EntityMetamodel entityMetamodel, PersistentClass mappedEntity) {
   super(entityMetamodel, mappedEntity);
 }
-  
+
 public EntityMode getEntityMode() {
   return EntityMode.MAP;
 }
@@(protected) @@
 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_2/src/org/hibernate/tuple/entity/EntityMetamodel.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/tuple/entity/EntityMetamodel.java  2008-10-08 04:13:07 UTC (rev 15268)
+++ core/branches/Branch_3_2/src/org/hibernate/tuple/entity/EntityMetamodel.java  2008-10-08 04:20:21 UTC (rev 15269)
@@(protected) @@
-// $Id: EntityMetamodel.java 9210 2006-02-03 22:15:19Z steveebersole $
+/*
+ * 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.tuple.entity;

import java.io.Serializable;
@@(protected) @@
 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;

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

@@(protected) @@
   }
 }

+  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;
 }
@@(protected) @@
   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_2/src/org/hibernate/tuple/entity/EntityTuplizer.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/tuple/entity/EntityTuplizer.java  2008-10-08 04:13:07 UTC (rev 15268)
+++ core/branches/Branch_3_2/src/org/hibernate/tuple/entity/EntityTuplizer.java  2008-10-08 04:20:21 UTC (rev 15269)
@@(protected) @@
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
@@(protected) @@
* @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.
@@(protected) @@
  */
 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 {@(protected),
+   * since that is the only external use of this method
  *
  * @return The java class to which generated proxies will be typed
  */
@@(protected) @@
  * Is it an instrumented POJO?
  */
 public boolean isInstrumented();
+
+  /**
+   * Get any {@(protected)}.
+   *
+   * @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_2/src/org/hibernate/tuple/entity/PojoEntityTuplizer.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/tuple/entity/PojoEntityTuplizer.java  2008-10-08 04:13:07 UTC (rev 15268)
+++ core/branches/Branch_3_2/src/org/hibernate/tuple/entity/PojoEntityTuplizer.java  2008-10-08 04:20:21 UTC (rev 15269)
@@(protected) @@
-// $Id: PojoEntityTuplizer.java 9210 2006-02-03 22:15:19Z steveebersole $
+/*
+ * 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.tuple.entity;

import java.lang.reflect.Method;
@@(protected) @@
import org.hibernate.EntityMode;
import org.hibernate.HibernateException;
import org.hibernate.MappingException;
-import org.hibernate.tuple.entity.AbstractEntityTuplizer;
-import org.hibernate.tuple.entity.EntityMetamodel;
+import org.hibernate.EntityNameResolver;
import org.hibernate.tuple.Instantiator;
import org.hibernate.tuple.PojoInstantiator;
import org.hibernate.bytecode.ReflectionOptimizer;
@@(protected) @@
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;
@@(protected) @@
 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 );
@@(protected) @@
//          mappedClass, getterNames, setterNames, propTypes
//      );
   }
-  
+
 }

+  /**
+   * {@(protected)}
+   */
 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
   HashSet proxyInterfaces = new HashSet();
   proxyInterfaces.add( HibernateProxy.class );
-    
+
   Class mappedClass = persistentClass.getMappedClass();
   Class proxyInterface = persistentClass.getProxyInterface();

   if ( proxyInterface!=null && !mappedClass.equals( proxyInterface ) ) {
     if ( !proxyInterface.isInterface() ) {
       throw new MappingException(
-             "proxy must be either an interface, or the class itself: " +
+             "proxy must be either an interface, or the class itself: " +
            getEntityName()
         );
     }
@@(protected) @@
     if ( subclassProxy!=null && !subclassClass.equals( subclassProxy ) ) {
       if ( !proxyInterface.isInterface() ) {
         throw new MappingException(
-               "proxy must be either an interface, or the class itself: " +
+               "proxy must be either an interface, or the class itself: " +
              subclass.getEntityName()
         );
       }
@@(protected) @@
     Method method = property.getGetter(clazz).getMethod();
     if ( method != null && Modifier.isFinal( method.getModifiers() ) ) {
       log.error(
-            "Getters of lazy classes cannot be final: " + persistentClass.getEntityName() +
-            "." + property.getName()
+            "Getters of lazy classes cannot be final: " + persistentClass.getEntityName() +
+            "." + property.getName()
         );
     }
     method = property.getSetter(clazz).getMethod();
        if ( method != null && Modifier.isFinal( method.getModifiers() ) ) {
       log.error(
-            "Setters of lazy classes cannot be final: " + persistentClass.getEntityName() +
-            "." + property.getName()
+            "Setters of lazy classes cannot be final: " + persistentClass.getEntityName() +
+            "." + property.getName()
         );
     }
   }
@@(protected) @@
   Method idGetterMethod = idGetter==null ? null : idGetter.getMethod();
   Method idSetterMethod = idSetter==null ? null : idSetter.getMethod();

-    Method proxyGetIdentifierMethod = idGetterMethod==null || proxyInterface==null ?
+    Method proxyGetIdentifierMethod = idGetterMethod==null || proxyInterface==null ?
       null :
        ReflectHelper.getMethod(proxyInterface, idGetterMethod);
-    Method proxySetIdentifierMethod = idSetterMethod==null || proxyInterface==null ?
+    Method proxySetIdentifierMethod = idSetterMethod==null || proxyInterface==null ?
       null :
        ReflectHelper.getMethod(proxyInterface, idSetterMethod);

@@(protected) @@
 }

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

+  /**
+   * {@(protected)}
+   */
 protected Instantiator buildInstantiator(PersistentClass persistentClass) {
   if ( optimizer == null ) {
     return new PojoInstantiator( persistentClass, null );
@@(protected) @@
   }
 }

+  /**
+   * {@(protected)}
+   */
 public void setPropertyValues(Object entity, Object[] values) throws HibernateException {
   if ( !getEntityMetamodel().hasLazyProperties() && optimizer != null && optimizer.getAccessOptimizer() != null ) {
     setPropertyValuesWithOptimizer( entity, values );
@@(protected) @@
   }
 }

+  /**
+   * {@(protected)}
+   */
 public Object[] getPropertyValues(Object entity) throws HibernateException {
   if ( shouldGetAllProperties( entity ) && optimizer != null && optimizer.getAccessOptimizer() != null ) {
     return getPropertyValuesWithOptimizer( entity );
@@(protected) @@
   }
 }

+  /**
+   * {@(protected)}
+   */
 public Object[] getPropertyValuesToInsert(Object entity, Map mergeMap, SessionImplementor session) throws HibernateException {
   if ( shouldGetAllProperties( entity ) && optimizer != null && optimizer.getAccessOptimizer() != null ) {
     return getPropertyValuesWithOptimizer( entity );
@@(protected) @@
   return optimizer.getAccessOptimizer().getPropertyValues( object );
 }

+  /**
+   * {@(protected)}
+   */
 public EntityMode getEntityMode() {
   return EntityMode.POJO;
 }

+  /**
+   * {@(protected)}
+   */
 public Class getMappedClass() {
   return mappedClass;
 }

+  /**
+   * {@(protected)}
+   */
 public boolean isLifecycleImplementor() {
   return lifecycleImplementor;
 }

+  /**
+   * {@(protected)}
+   */
 public boolean isValidatableImplementor() {
   return validatableImplementor;
 }

+  /**
+   * {@(protected)}
+   */
 protected Getter buildPropertyGetter(Property mappedProperty, PersistentClass mappedEntity) {
   return mappedProperty.getGetter( mappedEntity.getMappedClass() );
 }

+  /**
+   * {@(protected)}
+   */
 protected Setter buildPropertySetter(Property mappedProperty, PersistentClass mappedEntity) {
   return mappedProperty.getSetter( mappedEntity.getMappedClass() );
 }

+  /**
+   * {@(protected)}
+   */
 public Class getConcreteProxyClass() {
   return proxyInterface;
 }

  //TODO: need to make the majority of this functionality into a top-level support class for custom impl support

+  /**
+   * {@(protected)}
+   */
 public void afterInitialize(Object entity, boolean lazyPropertiesAreUnfetched, SessionImplementor session) {
   if ( isInstrumented() ) {
     Set lazyProps = lazyPropertiesAreUnfetched && getEntityMetamodel().hasLazyProperties() ?
@@(protected) @@
   }
 }

+  /**
+   * {@(protected)}
+   */
 public boolean hasUninitializedLazyProperties(Object entity) {
   if ( getEntityMetamodel().hasLazyProperties() ) {
     FieldInterceptor callback = FieldInterceptionHelper.extractFieldInterceptor( entity );
@@(protected) @@
   }
 }

+  /**
+   * {@(protected)}
+   */
 public boolean isInstrumented() {
   return FieldInterceptionHelper.isInstrumented( getMappedClass() );
 }

+  /**
+   * {@(protected)}
+   */
+  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;
+    }
+  }
+
+  /**
+   * {@(protected)}
+   */
+  public EntityNameResolver[] getEntityNameResolvers() {
+    return null;
+  }
}

Added: core/branches/Branch_3_2/test/org/hibernate/test/dynamicentity/tuplizer2/Customer.hbm.xml
===================================================================
--- core/branches/Branch_3_2/test/org/hibernate/test/dynamicentity/tuplizer2/Customer.hbm.xml                  (rev 0)
+++ core/branches/Branch_3_2/test/org/hibernate/test/dynamicentity/tuplizer2/Customer.hbm.xml  2008-10-08 04:20:21 UTC (rev 15269)
@@(protected) @@
+<?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_2/test/org/hibernate/test/dynamicentity/tuplizer2/ImprovedTuplizerDynamicEntityTest.java
===================================================================
--- core/branches/Branch_3_2/test/org/hibernate/test/dynamicentity/tuplizer2/ImprovedTuplizerDynamicEntityTest.java                  (rev 0)
+++ core/branches/Branch_3_2/test/org/hibernate/test/dynamicentity/tuplizer2/ImprovedTuplizerDynamicEntityTest.java  2008-10-08 04:20:21 UTC (rev 15269)
@@(protected) @@
+/*
+ * 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
+ * {@(protected)
+ * 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_2/test/org/hibernate/test/dynamicentity/tuplizer2/MyEntityInstantiator.java
===================================================================
--- core/branches/Branch_3_2/test/org/hibernate/test/dynamicentity/tuplizer2/MyEntityInstantiator.java                  (rev 0)
+++ core/branches/Branch_3_2/test/org/hibernate/test/dynamicentity/tuplizer2/MyEntityInstantiator.java  2008-10-08 04:20:21 UTC (rev 15269)
@@(protected) @@
+/*
+ * 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_2/test/org/hibernate/test/dynamicentity/tuplizer2/MyEntityTuplizer.java
===================================================================
--- core/branches/Branch_3_2/test/org/hibernate/test/dynamicentity/tuplizer2/MyEntityTuplizer.java                  (rev 0)
+++ core/branches/Branch_3_2/test/org/hibernate/test/dynamicentity/tuplizer2/MyEntityTuplizer.java  2008-10-08 04:20:21 UTC (rev 15269)
@@(protected) @@
+/*
+ * 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();
+    }
+  }
+}

_______________________________________________
hibernate-commits mailing list
hibernate-commits@(protected)
https://lists.jboss.org/mailman/listinfo/hibernate-commits
©2008 gg3721.com - Jax Systems, LLC, U.S.A.