Since the challenge still exists, here is an even further improved version.
The behaviour is the same, simply some performance improvements were added.

package org.hibernate.collection;
  | 
  | import java.lang.reflect.InvocationTargetException;
  | import java.util.Collection;
  | import java.util.HashSet;
  | import java.util.Map;
  | 
  | import org.apache.commons.beanutils.PropertyUtils;
  | import org.hibernate.LazyInitializationException;
  | 
  | /**
  |  * Some utility methods to get a complete clean POJO from an entity bean 
with hibernate 
  |  * specific fields stripped out. Note this class is not meant as a way of 
avoid 
  |  * LazyInitializationException's.
  |  * Its purpose to strip out data before sending the object to a remote 
client so that 
  |  * does not have knowledge of hibernate classes. 
  |  * @author ALR 5/9/2006
  |  * @author modified by James Adams 6/9/2006, 7/9/2006
  |  * @author me 7/6/2008
  |  */
  | public final class HibernateCleaner
  | {
  |     /**
  |      * Traverse through the object removing all fields of type 
  |      * org.hibernate.collection.PersistentCollection. by following all bean 
style get* methods.
  |      * <p>
  |      * <b>Note</b> the object cannot be reattached after calling this 
method.
  |      * 
  |      * @param obj the object to clean
  |      */
  |     public static void clean(final Object obj)
  |     {
  |             try
  |             {
  |                     removePersistenceContext(obj, new HashSet<Integer>());
  |             }
  |             catch (final IllegalAccessException e)
  |             {
  |                     throw new RuntimeException(e);
  |             }
  |             catch (final InvocationTargetException e)
  |             {
  |                     throw new RuntimeException(e);
  |             }
  |             catch (final NoSuchMethodException e)
  |             {
  |                     throw new RuntimeException(e);
  |             }
  |     }
  | 
  |     /**
  |      * Checks if the object MIGHT contain PersistentCollection fields by 
checking if its not a
  |      * primitive, or if its in package java.* or javax.*.
  |      * 
  |      * <p>
  |      * <b>NOTE</b> This relies on there not being an entity within those 
packages.
  |      * A more conservative approach is to only check if its a primitive.
  |      * @param obj the object to check
  |      * @author James Adams
  |      */
  |     public static boolean couldObjectContainPersistentCollections(final 
Object obj)
  |     {
  |             if (obj == null) return false;
  | 
  |             final Class clazz = obj.getClass();
  | 
  |             if (clazz.isPrimitive()) return false;
  | 
  |             final String className = clazz.getName();
  | 
  |             //TODO - This is not fool proof and relies on people not using 
package with names below.
  |             //More conservative approach is to remove this
  |             if (className.startsWith("java.") || 
className.startsWith("javax.")) return false;
  | 
  |             return true; //If we got here it might be a hibernate persisted 
object
  |     }
  | 
  |     /**
  |      * Because this class is in package org.hibernate.collection this method
  |      * allows us to access the inner protected fields of the hibernate 
collections
  |      * @param obj
  |      * @return The inner collection object of the PersistentCollection 
parameter
  |      * @author James Adams
  |      */
  |     private static Object getInnerCollection(final PersistentCollection obj)
  |     {
  |             if (obj instanceof PersistentBag)
  |                     return ((PersistentBag) obj).bag;
  |             else if (obj instanceof PersistentList)
  |                     return ((PersistentList) obj).list;
  |             else if (obj instanceof PersistentSet)
  |                     return ((PersistentSet) obj).set;
  |             else if (obj instanceof PersistentMap)
  |                     return ((PersistentMap) obj).map;
  |             else if (obj instanceof PersistentSortedMap)
  |                     return ((PersistentSortedMap) obj).map;
  |             else if (obj instanceof PersistentSortedSet)
  |                     return ((PersistentSortedSet) obj).set;
  |             else
  |                     return null;
  |     }
  | 
  |     /**
  |      * If the specified object's identity hash code is not in the specified
  |      * collection of visited hash codes, removes of all data binding the 
object
  |      * (and its members) to a specific persistence context, leaving intact 
only
  |      * model-centric data
  |      * 
  |      * @param visitedObjectHashCodes
  |      * @param obj
  |      * @author ALR
  |      * @author James Adams, modified 6/9/2006,7/9/2006
  |      * @throws NoSuchMethodException 
  |      * @throws InvocationTargetException 
  |      * @throws IllegalAccessException 
  |      */
  |     private static Object removePersistenceContext(Object obj, //
  |                     final Collection<Integer> visitedObjectHashCodes) //
  |                     throws IllegalAccessException, 
InvocationTargetException, NoSuchMethodException
  |     {
  |             if (obj == null) return null;
  | 
  |             final Integer hashCode = System.identityHashCode(obj);
  | 
  |             if (visitedObjectHashCodes.contains(hashCode)) return obj;
  | 
  |             //Add the object's hash to the Collection of visited hash codes
  |             visitedObjectHashCodes.add(hashCode);
  | 
  |             try
  |             {
  |                     // If runtime type of persistentCollection is 
PersistentCollection we get the
  |                     // inner collection from within the hibernate proxy
  |                     if (obj instanceof PersistentCollection)
  |                     {
  |                             obj = getInnerCollection((PersistentCollection) 
obj);
  |                     }
  |             }
  |             catch (final LazyInitializationException e)
  |             {
  |                     return null;
  |             }
  | 
  |             if (obj == null) return null;
  | 
  |             if (obj instanceof Collection)
  |             {
  |                     for (final Object o : (Collection< ? >) obj)
  |                     {
  |                             //recurse into each element of the collection.  
We don't need to set the value of 
  |                             //the object in the Collection as the reference 
will be adjusted, doing so within
  |                             //this iterable loop would result in a 
ConcurrentModificationException anyway. 
  |                             removePersistenceContext(o, 
visitedObjectHashCodes);
  |                             //TODO - Does Hibernate support Collections of 
primitives? As this will not work 
  |                             // when the Collection is of types that Java 
does not pass by reference;
  |                             // primitives, String, Integer, Float etc.
  |                             // In this case we need to create a new 
Collection and populate it. 
  |                     }
  |             }
  |             else if (!couldObjectContainPersistentCollections(obj))
  |                     return obj;
  |             else
  |             {
  |                     @SuppressWarnings("unchecked")
  |                     final Map<String, Object> allMembers = 
PropertyUtils.describe(obj);
  |                     for (final Map.Entry<String, Object> member : 
allMembers.entrySet())
  |                     {
  |                             final Object propertyValue = member.getValue();
  |                             try
  |                             {
  |                                     final Object cleanedValue = 
removePersistenceContext(propertyValue, // 
  |                                                     visitedObjectHashCodes);
  | 
  |                                     // avoid costly calls via reflection if 
the value has not been modified
  |                                     if (cleanedValue != propertyValue)
  |                                     {
  |                                             PropertyUtils.setProperty(obj, 
member.getKey(), cleanedValue);
  |                                     }
  |                             }
  |                             catch (final LazyInitializationException e)
  |                             {
  |                                     PropertyUtils.setProperty(obj, 
member.getKey(), null);
  |                             }
  |                     }
  |             }
  |             return obj;
  |     }
  | 
  |     private HibernateCleaner()
  |     {
  |     // nothing
  |     }
  | }

View the original post : 
http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4162685#4162685

Reply to the post : 
http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4162685
_______________________________________________
jboss-user mailing list
[email protected]
https://lists.jboss.org/mailman/listinfo/jboss-user

Reply via email to