package org.aperteworkflow.util;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.collections.CollectionConverter;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.mapper.Mapper;
import org.hibernate.Hibernate;
import org.hibernate.collection.PersistentSet;
import pl.net.bluesoft.rnd.processtool.model.AbstractPersistentEntity;
import pl.net.bluesoft.rnd.processtool.model.PersistentEntity;
import pl.net.bluesoft.util.lang.Lang;
import java.lang.reflect.Field;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* @author tlipski@bluesoft.net.pl
*/
public class HibernateBeanUtil {
private static class MyPersistentSetConverter extends CollectionConverter {
public MyPersistentSetConverter(Mapper mapper) {
super(mapper);
}
@Override
public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) {
PersistentSet ps = (PersistentSet) source;
super.marshal(new HashSet(ps), writer, context);
}
@Override
public boolean canConvert(Class type) {
if (type == null) return false;
return type.isAssignableFrom(PersistentSet.class);
}
}
private final static XStream xs = new XStream();
static {
xs.registerConverter(new MyPersistentSetConverter(xs.getMapper()), XStream.PRIORITY_VERY_HIGH);
}
public static <T> T fetchHibernateData(T o) {
try {
if (o == null) return null;
new LazyLoadExpander().expand(o);
String s = xs.toXML(o);
s = s.replace("class=\"org.hibernate.collection.PersistentSet\"", "class=\"java.util.HashSet\"");
s = s.replaceAll("class=\"(.*?)_\\$\\$_javassist[^\"]*\"", "class=\"$1\"");
T clone = (T)xs.fromXML(s);
return clone;
}
catch (Exception e) {
Logger.getLogger(HibernateBeanUtil.class.toString()).log(Level.SEVERE, e.getMessage(), e);
throw new RuntimeException(e);
}
}
private static class LazyLoadExpander {
private final Set<Object> expanded = new HashSet<Object>();
public <T> void expand(T t) {
if (t == null || expanded.contains(t)) {
return;
}
expanded.add(t);
if (t instanceof AbstractPersistentEntity) {
Hibernate.initialize(t);
for (Field field : Lang.getFieldsFromClassAndAncestors(t.getClass())) {
try {
Object value = Lang.get(t, field.getName());
if (value instanceof AbstractPersistentEntity) {
expand(value);
}
if (value instanceof Collection) {
for (Object obj : (Collection)value) {
expand(obj);
}
}
}
catch (Exception e) {
}
}
}
}
}
}