You are viewing a plain text version of this content. The canonical link for it is here.
Posted to ojb-dev@db.apache.org by ma...@apache.org on 2003/07/08 20:16:28 UTC
cvs commit: db-ojb/src/java/org/apache/ojb/otm/copy MetadataObjectCopyStrategy.java
mattbaird 2003/07/08 11:16:28
Modified: src/java/org/apache/ojb/otm/copy
MetadataObjectCopyStrategy.java
Log:
Finish the MetadataObjectCopyStrategy.
Revision Changes Path
1.2 +78 -11 db-ojb/src/java/org/apache/ojb/otm/copy/MetadataObjectCopyStrategy.java
Index: MetadataObjectCopyStrategy.java
===================================================================
RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/otm/copy/MetadataObjectCopyStrategy.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- MetadataObjectCopyStrategy.java 7 Jul 2003 22:54:14 -0000 1.1
+++ MetadataObjectCopyStrategy.java 8 Jul 2003 18:16:28 -0000 1.2
@@ -56,10 +56,22 @@
import org.apache.ojb.broker.metadata.*;
import org.apache.ojb.broker.metadata.fieldaccess.PersistentField;
+import org.apache.ojb.broker.accesslayer.CollectionProxy;
+import java.util.Map;
import java.util.Collection;
import java.util.Iterator;
+//#ifdef JDK14
+import java.util.IdentityHashMap;
+import java.lang.reflect.Proxy;
+//#else
+/*
+import org.apache.ojb.otm.util.IdentityHashMap;
+import com.develop.java.lang.reflect.Proxy;
+*/
+//#endif
+
/**
* recursively copies an object based on the ClassDescriptor
* User: matthew.baird
@@ -70,31 +82,41 @@
{
/**
* TODO: handle proxies appropriately
- * TODO: handle infinite recursion due to looping object model.
- * TODO: handle collections appropriately
+ * Uses an IdentityMap to make sure we don't recurse infinitely on the same object in a cyclic object model.
+ * Proxies
* @param obj
* @param repo
* @return
*/
public Object copy(final Object obj, final DescriptorRepository repo)
{
+ return clone(obj, new IdentityHashMap(), repo);
+ }
+
+ private static Object clone(final Object toCopy, final Map objMap, final DescriptorRepository repo)
+ {
+ /**
+ * first, check to make sure we aren't recursing to some object that we've already copied.
+ * if the toCopy is in the objMap, just return it.
+ */
+ if (objMap.containsKey(toCopy)) return objMap.get(toCopy);
/**
* if null, return null, duh
*/
- if (obj == null)
+ if (toCopy == null)
return null;
/**
* if no classdescriptor exists for this object, just return this object, we
* can't copy it.
*/
- final ClassDescriptor cld = repo.getDescriptorFor(obj.getClass());
+ final ClassDescriptor cld = repo.getDescriptorFor(toCopy.getClass());
if (cld == null)
- return obj;
+ return toCopy;
Object retval;
try
{
- retval = obj.getClass().newInstance();
+ retval = toCopy.getClass().newInstance();
}
catch (InstantiationException e)
{
@@ -106,6 +128,7 @@
}
/**
* first copy all the fields
+ * fields are not mapped objects (ie ObjectReferenceDescriptors)
*/
final FieldDescriptor[] fieldDescs = cld.getFieldDescriptions();
for (int i = 0; i < fieldDescs.length; i++)
@@ -117,7 +140,7 @@
* value on the copy as the field descriptor used to get the value from the
* object to be copied.
*/
- f.set(retval, f.get(obj));
+ f.set(retval, f.get(toCopy));
}
/**
@@ -131,8 +154,22 @@
final PersistentField f = rd.getPersistentField();
/**
* recursively copy the referenced objects
+ * register in the objMap first
+ */
+ Object object = f.get(toCopy);
+ /**
+ * if this is a proxy, just copy the proxy, don't materialize it, and stop recursing
*/
- f.set(retval, copy(f.get(obj), repo));
+ if (object instanceof Proxy)
+ {
+ f.set(retval, object);
+ }
+ else
+ {
+ Object clone = clone(object, objMap, repo);
+ objMap.put(object, clone);
+ f.set(retval, clone);
+ }
}
/**
* then copy all the 1:M and M:N references
@@ -143,16 +180,42 @@
{
final CollectionDescriptor cd = (CollectionDescriptor) it.next();
final PersistentField f = cd.getPersistentField();
- final Object collection = f.get(obj);
- if (collection instanceof Collection)
+ final Object collection = f.get(toCopy);
+ /**
+ * handle collection proxies where the entire Collection is a big proxy
+ * (vs all the elements in the collection are proxies
+ */
+ if (collection == null)
+ {
+ f.set(retval, null);
+ }
+ else if (collection instanceof CollectionProxy)
+ {
+ f.set(retval, collection);
+ }
+ else if (collection instanceof Collection)
{
try
{
final Collection newCollection = (Collection) collection.getClass().newInstance();
final Iterator tempIter = ((Collection) collection).iterator();
+ Object obj = null;
while (tempIter.hasNext())
{
- newCollection.add(copy(tempIter.next(), repo));
+ obj = tempIter.next();
+ /**
+ * if this is a proxy, just copy the proxy, don't materialize it, and stop recursing
+ */
+ if (obj instanceof Proxy)
+ {
+ newCollection.add(obj);
+ }
+ else
+ {
+ Object clone = clone(obj, objMap, repo);
+ objMap.put(obj, clone);
+ newCollection.add(clone);
+ }
}
f.set(retval, newCollection);
}
@@ -164,6 +227,10 @@
{
throw new ObjectCopyException("IllegalAccessException", e);
}
+ }
+ else
+ {
+ throw new java.lang.UnsupportedOperationException("MetadataObjectCopyStrategy cannot handle Collection of type: " + collection.getClass().getName());
}
}
return retval;
---------------------------------------------------------------------
To unsubscribe, e-mail: ojb-dev-unsubscribe@db.apache.org
For additional commands, e-mail: ojb-dev-help@db.apache.org