Here is a PersistenceDelegate that converts Hibernate collections classes
into java.util collections classes. This allows them to be passed through
a java.beans.XMLEncoder. When decoded they become java.util classes.
See also HB-931.
To use, add to your Encoder the PersistenceDelegates returned by getDelegates().
This has been tested with JDK 1.4.2.
Note: XMLEncoder/XMLDecoder are not thread safe, and memory leaks
if you fail to close XMLEncoder.
Permission is granted to copy as long as copyright notice is preserved.
-------------------------------------------------------------------------------------
Code:
/*
* Copyright (C) 2004 Awarix, Inc. All rights reserved.
*
* $Id: HibernatePersistenceDelegate.java 1915 2004-11-11 22:50:56Z archie $
*/
package com.awarix.util.hibernate;
import java.beans.DefaultPersistenceDelegate;
import java.beans.Encoder;
import java.beans.Expression;
import java.beans.PersistenceDelegate;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.TreeMap;
import java.util.TreeSet;
import net.sf.hibernate.HibernateException;
import net.sf.hibernate.Session;
import net.sf.hibernate.SessionFactory;
import net.sf.hibernate.Transaction;
/**
* An extension of {@link PersistenceDelegate PersistenceDelegate}
* that handles Hibernate collections classes. These classes cannot normally
* be instantiated by the application, so they don't pass successfully through
* an XML encoded stream. On the other hand, Hibernate will let you replace
* them with the usual collections classes from <code>java.util</code>. So
* that's what we do here.
*/
public class HibernatePersistenceDelegate extends DefaultPersistenceDelegate {
static HibernatePersistenceDelegate INSTANCE
= new HibernatePersistenceDelegate();
static final Map CLASS_MAP;
static {
HashMap map = new HashMap();
map.put(net.sf.hibernate.collection.Bag.class, ArrayList.class);
map.put(net.sf.hibernate.collection.IdentifierBag.class,
ArrayList.class);
map.put(net.sf.hibernate.collection.List.class, ArrayList.class);
map.put(net.sf.hibernate.collection.Map.class, HashMap.class);
map.put(net.sf.hibernate.collection.Set.class, HashSet.class);
map.put(net.sf.hibernate.collection.SortedMap.class, TreeMap.class);
map.put(net.sf.hibernate.collection.SortedSet.class, TreeSet.class);
CLASS_MAP = Collections.synchronizedMap(map);
}
private HibernatePersistenceDelegate() {
}
/**
* Get the set of delegates to install in an
* {@link java.beans.Encoder Encoder}
* to properly handle Hibernate collections types. This method returns
* the set as a mapping from <code>Class</code> ->
* <code>PersistenceDelegate</code>.
*/
public static Map getDelegates() {
HashMap map = new HashMap();
for (Iterator i = CLASS_MAP.keySet().iterator(); i.hasNext(); )
map.put(i.next(), INSTANCE);
return map;
}
/**
* Overridden to handle conversion of Hibernate collection
* classes into <code>java.util</code> collection classes.
*/
protected Expression instantiate(Object oldInstance, Encoder out) {
Class replaceType = (Class)CLASS_MAP.get(oldInstance.getClass());
if (replaceType != null) {
return new Expression(oldInstance,
replaceType, "new", new Object[0]);
}
return super.instantiate(oldInstance, out);
}
/**
* Overridden to handle conversion of Hibernate collection
* classes into <code>java.util</code> collection classes.
*/
protected boolean mutatesTo(Object oldInstance, Object newInstance) {
if (oldInstance != null && newInstance != null
&& CLASS_MAP.get(oldInstance.getClass()) == newInstance.getClass())
return true;
return super.mutatesTo(oldInstance, newInstance);
}
/**
* Overridden to handle conversion of Hibernate collection
* classes into <code>java.util</code> collection classes.
*/
protected void initialize(Class type, Object oldInstance,
Object newInstance, Encoder out) {
Class replaceType = (Class)CLASS_MAP.get(oldInstance.getClass());
if (replaceType != null) {
Object replace = replace(oldInstance);
if (type == oldInstance.getClass())
type = replace.getClass();
super.initialize(type, replace, newInstance, out);
}
super.initialize(type, oldInstance, newInstance, out);
}
Object replace(Object obj) {
if (obj instanceof net.sf.hibernate.collection.Set)
return new HashSet((Set)obj);
else if (obj instanceof net.sf.hibernate.collection.Map)
return new HashMap((Map)obj);
else if (obj instanceof net.sf.hibernate.collection.SortedSet)
return new TreeSet((SortedSet)obj);
else if (obj instanceof net.sf.hibernate.collection.SortedMap)
return new TreeMap((SortedMap)obj);
else if (obj instanceof net.sf.hibernate.collection.List
|| obj instanceof net.sf.hibernate.collection.Bag
|| obj instanceof net.sf.hibernate.collection.IdentifierBag)
return new ArrayList((Collection)obj);
throw new RuntimeException("unexpected");
}
}