Here's a class that converts Hibernate proxies to normal classes. This is useful with GWT for example, when sending objects loaded from database to the GWT client. Please review it.
package ru.minogin.core.server.hibernate;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import org.apache.log4j.Logger;
import org.hibernate.collection.PersistentBag;
import org.hibernate.collection.PersistentList;
import org.hibernate.collection.PersistentMap;
import org.hibernate.collection.PersistentSet;
import org.hibernate.collection.PersistentSortedSet;
import org.hibernate.proxy.HibernateProxy;
import org.hibernate.proxy.LazyInitializer;
import ru.minogin.core.client.bean.Bean;
import ru.minogin.core.server.reflection.ReflectionUtils;
/**
* Thread-safety: this class in not thread-safe.
*
* @author Andrey Minogin
* @version 1.0, 02/28/11
*
*/
public class Dehibernator {
private static final Logger logger = Logger.getLogger(Dehibernator.class);
private IdentityHashMap<Object, Object> processed;
@SuppressWarnings("unchecked")
public <T> T clean(T object) {
processed = new IdentityHashMap<Object, Object>();
logger.debug("Cleaning: " + (object != null ? object.getClass() : null));
return (T) doClean(object);
}
@SuppressWarnings("unchecked")
private Object doClean(Object dirty) {
logger.debug("Do clean: " + (dirty != null ? dirty.getClass() : null));
if (dirty == null)
return null;
if (processed.containsKey(dirty)) {
logger.debug("Object already cleaned, skipping.");
return processed.get(dirty);
}
if (isPrimitive(dirty)) {
logger.debug("Object is primitive, skipping.");
return dirty;
}
if (dirty instanceof PersistentList) {
logger.debug("Object is a PersistentList");
PersistentList dirtyList = (PersistentList) dirty;
List<Object> cleanList = new ArrayList<Object>();
processed.put(dirtyList, cleanList);
if (dirtyList.wasInitialized()) {
for (Object value : dirtyList) {
cleanList.add(doClean(value));
}
}
return cleanList;
}
if (dirty instanceof PersistentBag) {
logger.debug("Object is a PersistentBag");
PersistentBag dirtyList = (PersistentBag) dirty;
List<Object> cleanList = new ArrayList<Object>();
processed.put(dirtyList, cleanList);
if (dirtyList.wasInitialized()) {
for (Object value : dirtyList) {
cleanList.add(doClean(value));
}
}
return cleanList;
}
if (dirty instanceof PersistentSortedSet) {
logger.debug("Object is a PersistentSortedSet");
PersistentSortedSet dirtySet = (PersistentSortedSet) dirty;
Set<Object> cleanSet = new TreeSet<Object>();
processed.put(dirtySet, cleanSet);
if (dirtySet.wasInitialized()) {
for (Object value : dirtySet) {
cleanSet.add(doClean(value));
}
}
return cleanSet;
}
if (dirty instanceof PersistentSet) {
logger.debug("Object is a PersistentSet");
PersistentSet dirtySet = (PersistentSet) dirty;
Set<Object> cleanSet = new HashSet<Object>();
processed.put(dirtySet, cleanSet);
if (dirtySet.wasInitialized()) {
for (Object value : dirtySet) {
cleanSet.add(doClean(value));
}
}
return cleanSet;
}
if (dirty instanceof PersistentMap) {
logger.debug("Object is a PersistentMap");
PersistentMap dirtyMap = (PersistentMap) dirty;
Map<Object, Object> cleanMap = new LinkedHashMap<Object, Object>();
processed.put(dirtyMap, cleanMap);
if (dirtyMap.wasInitialized()) {
for (Object key : dirtyMap.keySet()) {
Object value = dirtyMap.get(key);
cleanMap.put(doClean(key), doClean(value));
}
}
return cleanMap;
}
if (dirty instanceof List) {
logger.debug("Object is a List");
List<Object> dirtyList = (List<Object>) dirty;
List<Object> cleanList = new ArrayList<Object>();
processed.put(dirtyList, cleanList);
for (Object value : dirtyList) {
cleanList.add(doClean(value));
}
return cleanList;
}
if (dirty instanceof LinkedHashMap) {
logger.debug("Object is a LinkedHashMap");
Map<Object, Object> dirtyMap = (Map<Object, Object>) dirty;
Map<Object, Object> cleanMap = new LinkedHashMap<Object, Object>();
processed.put(dirtyMap, cleanMap);
for (Object key : dirtyMap.keySet()) {
Object value = dirtyMap.get(key);
cleanMap.put(doClean(key), doClean(value));
}
return cleanMap;
}
if (dirty instanceof HashMap) {
logger.debug("Object is a HashMap");
Map<Object, Object> dirtyMap = (Map<Object, Object>) dirty;
Map<Object, Object> cleanMap = new HashMap<Object, Object>();
processed.put(dirtyMap, cleanMap);
for (Object key : dirtyMap.keySet()) {
Object value = dirtyMap.get(key);
cleanMap.put(doClean(key), doClean(value));
}
return cleanMap;
}
if (dirty instanceof LinkedHashSet<?>) {
logger.debug("Object is a LinkedHashSet");
Set<Object> dirtySet = (LinkedHashSet<Object>) dirty;
Set<Object> cleanSet = new LinkedHashSet<Object>();
processed.put(dirtySet, cleanSet);
for (Object value : dirtySet) {
cleanSet.add(doClean(value));
}
return cleanSet;
}
if (dirty instanceof HashSet<?>) {
logger.debug("Object is a HashSet");
Set<Object> dirtySet = (HashSet<Object>) dirty;
Set<Object> cleanSet = new HashSet<Object>();
processed.put(dirtySet, cleanSet);
for (Object value : dirtySet) {
cleanSet.add(doClean(value));
}
return cleanSet;
}
if (dirty instanceof TreeSet<?>) {
logger.debug("Object is a TreeSet");
Set<Object> dirtySet = (TreeSet<Object>) dirty;
Set<Object> cleanSet = new TreeSet<Object>();
processed.put(dirtySet, cleanSet);
for (Object value : dirtySet) {
cleanSet.add(doClean(value));
}
return cleanSet;
}
if (dirty instanceof HibernateProxy) {
logger.debug("Object is a HibernateProxy");
HibernateProxy proxy = (HibernateProxy) dirty;
LazyInitializer lazyInitializer = proxy.getHibernateLazyInitializer();
if (lazyInitializer.isUninitialized()) {
logger.debug("It is uninitialized, skipping");
processed.put(dirty, null);
return null;
}
else {
logger.debug("It is initialized, getting implementati");
dirty = lazyInitializer.getImplementation();
}
}
if (dirty instanceof Bean) {
logger.debug("Object is a Bean");
Bean bean = (Bean) dirty;
processed.put(bean, bean);
for (String property : bean.getPropertyNames()) {
bean.set(property, doClean(bean.get(property)));
}
return bean;
}
processed.put(dirty, dirty);
for (String property : ReflectionUtils.getProperties(dirty)) {
logger.debug("Processing property " + property);
Object value = ReflectionUtils.get(dirty, property);
ReflectionUtils.setIfPossible(dirty, property, doClean(value));
}
return dirty;
}
private boolean isPrimitive(Object object) {
if (object instanceof String)
return true;
if (object instanceof Date)
return true;
if (object instanceof Enum)
return true;
Class<? extends Object> xClass = object.getClass();
if (xClass.isPrimitive())
return true;
return false;
}
}