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