Coverage Report - org.apache.ojb.otm.copy.MetadataObjectCopyStrategy
 
Classes in this File Line Coverage Branch Coverage Complexity
MetadataObjectCopyStrategy
N/A
N/A
13.5
 
 1  
 package org.apache.ojb.otm.copy;
 2  
 
 3  
 /* Copyright 2003-2005 The Apache Software Foundation
 4  
  *
 5  
  * Licensed under the Apache License, Version 2.0 (the "License");
 6  
  * you may not use this file except in compliance with the License.
 7  
  * You may obtain a copy of the License at
 8  
  *
 9  
  *     http://www.apache.org/licenses/LICENSE-2.0
 10  
  *
 11  
  * Unless required by applicable law or agreed to in writing, software
 12  
  * distributed under the License is distributed on an "AS IS" BASIS,
 13  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  
  * See the License for the specific language governing permissions and
 15  
  * limitations under the License.
 16  
  */
 17  
 
 18  
 import org.apache.ojb.broker.PersistenceBroker;
 19  
 import org.apache.ojb.broker.metadata.*;
 20  
 import org.apache.ojb.broker.metadata.fieldaccess.PersistentField;
 21  
 import org.apache.ojb.broker.core.proxy.CollectionProxyDefaultImpl;
 22  
 import org.apache.ojb.broker.core.proxy.ProxyHelper;
 23  
 import org.apache.ojb.broker.util.ConstructorHelper;
 24  
 import org.apache.ojb.broker.util.IdentityMapFactory;
 25  
 
 26  
 import java.lang.reflect.Constructor;
 27  
 import java.util.Map;
 28  
 import java.util.Collection;
 29  
 import java.util.Iterator;
 30  
 
 31  
 /**
 32  
  * recursively copies an object based on the ClassDescriptor
 33  
  * User: matthew.baird
 34  
  * Date: Jul 7, 2003
 35  
  * Time: 1:41:58 PM
 36  
  */
 37  
 public final class MetadataObjectCopyStrategy implements ObjectCopyStrategy
 38  
 {
 39  
     private static final ReflectiveObjectCopyStrategy _reflective = new ReflectiveObjectCopyStrategy();
 40  
     private static final SerializeObjectCopyStrategy _serialize = new SerializeObjectCopyStrategy();
 41  
 
 42  
     /**
 43  
      * Uses an IdentityMap to make sure we don't recurse infinitely on the same object in a cyclic object model.
 44  
      * Proxies
 45  
      * @param obj
 46  
      * @return
 47  
      */
 48  
     public Object copy(final Object obj, final PersistenceBroker broker)
 49  
     {
 50  
         return clone(obj, IdentityMapFactory.getIdentityMap(), broker);
 51  
     }
 52  
 
 53  
     private static Object clone(final Object toCopy, final Map objMap, final PersistenceBroker broker)
 54  
     {
 55  
         /**
 56  
          * first, check to make sure we aren't recursing to some object that we've already copied.
 57  
          * if the toCopy is in the objMap, just return it.
 58  
          */
 59  
         if (objMap.containsKey(toCopy)) return objMap.get(toCopy);
 60  
         /**
 61  
          * if null, return null, duh
 62  
          */
 63  
         if (toCopy == null)
 64  
             return null;
 65  
 
 66  
         /**
 67  
          * if this is a proxy, just copy the proxy, don't materialize it, and stop recursing
 68  
          */
 69  
         if (ProxyHelper.isVirtualOjbProxy(toCopy))
 70  
         {
 71  
             return _reflective.copy(toCopy, null);
 72  
         }
 73  
         else if (ProxyHelper.isNormalOjbProxy(toCopy))
 74  
         {
 75  
             return _serialize.copy(toCopy, null);
 76  
         }
 77  
 
 78  
         /**
 79  
          * if no classdescriptor exists for this object, just return this object, we
 80  
          * can't copy it.
 81  
          */
 82  
         final ClassDescriptor cld = broker.getClassDescriptor(toCopy.getClass());
 83  
         if (cld == null)
 84  
         {
 85  
             return _reflective.copy(toCopy, null);
 86  
         }
 87  
 
 88  
         final Object retval;
 89  
         try
 90  
         {
 91  
             final Constructor con = cld.getZeroArgumentConstructor();
 92  
             retval = ConstructorHelper.instantiate(con);
 93  
             objMap.put(toCopy,retval);
 94  
         }
 95  
         catch (InstantiationException e)
 96  
         {
 97  
             throw new ObjectCopyException("InstantiationException", e);
 98  
         }
 99  
 
 100  
         /**
 101  
          * first copy all the fields
 102  
          * fields are not mapped objects (ie ObjectReferenceDescriptors)
 103  
          */
 104  
         final FieldDescriptor[] fieldDescs = cld.getFieldDescriptions();
 105  
 //        final BrokerHelper brokerHelper = broker.serviceBrokerHelper();
 106  
         for (int i = 0; i < fieldDescs.length; i++)
 107  
         {
 108  
             final FieldDescriptor fd = fieldDescs[i];
 109  
             final PersistentField f = fd.getPersistentField();
 110  
             Object fieldValue = f.get(toCopy);
 111  
 /*
 112  
 arminw:
 113  
 TODO: ensure that the autoincrement values be assigned before the copy was done
 114  
 If possible we should avoid to declare BrokerHelper#getAutoIncrementValue public and
 115  
 if we copy an object user don't expect the change of fields.
 116  
 */
 117  
 //            // If the field is auto increment, assign its value before copying!
 118  
 //            if (fd.isAutoIncrement())
 119  
 //            {
 120  
 //                fieldValue = brokerHelper.getAutoIncrementValue(fd, toCopy, fieldValue);
 121  
 //            }
 122  
 
 123  
             f.set(retval, fieldValue);
 124  
         }
 125  
 
 126  
         /**
 127  
          * then copy all the 1:1 references
 128  
          */
 129  
         final Collection refDescsCol = cld.getObjectReferenceDescriptors();
 130  
         final ObjectReferenceDescriptor[] rds = (ObjectReferenceDescriptor[]) refDescsCol.toArray(new ObjectReferenceDescriptor[refDescsCol.size()]);
 131  
         for (int i = 0; i < rds.length; i++)
 132  
         {
 133  
             final ObjectReferenceDescriptor rd = rds[i];
 134  
             final PersistentField f = rd.getPersistentField();
 135  
             /**
 136  
              * recursively copy the referenced objects
 137  
              * register in the objMap first
 138  
              */
 139  
             final Object object = f.get(toCopy);
 140  
             final Object clone = clone(object, objMap, broker);
 141  
             objMap.put(object, clone);
 142  
             f.set(retval, clone);
 143  
         }
 144  
         /**
 145  
          * then copy all the 1:M and M:N references
 146  
          */
 147  
         final Collection colDescsCol = cld.getCollectionDescriptors();
 148  
         final Iterator it = colDescsCol.iterator();
 149  
         while (it.hasNext())
 150  
         {
 151  
             final CollectionDescriptor cd = (CollectionDescriptor) it.next();
 152  
             final PersistentField f = cd.getPersistentField();
 153  
             final Object collection = f.get(toCopy);
 154  
             /**
 155  
              * handle collection proxies where the entire Collection is a big proxy
 156  
              * (vs all the elements in the collection are proxies
 157  
              */
 158  
             if (collection == null)
 159  
             {
 160  
                 f.set(retval, null);
 161  
             }
 162  
             else if (collection instanceof CollectionProxyDefaultImpl)
 163  
             {
 164  
                 f.set(retval, _reflective.copy(collection, null));
 165  
             }
 166  
             else if (collection instanceof Collection)
 167  
             {
 168  
                 try
 169  
                 {
 170  
                     final Collection newCollection = (Collection) collection.getClass().newInstance();
 171  
                     final Iterator tempIter = ((Collection) collection).iterator();
 172  
                     Object obj;
 173  
                     while (tempIter.hasNext())
 174  
                     {
 175  
                         obj = tempIter.next();
 176  
                         /**
 177  
                         * if this is a proxy, just copy the proxy, don't materialize it, and stop recursing
 178  
                         */
 179  
                         if (ProxyHelper.isNormalOjbProxy(obj))  // tomdz: what about VirtualProxy ?
 180  
                         {
 181  
                             newCollection.add(obj);
 182  
                         }
 183  
                         else
 184  
                         {
 185  
                             final Object clone = clone(obj, objMap, broker);
 186  
                             objMap.put(obj, clone);
 187  
                             newCollection.add(clone);
 188  
                         }
 189  
                     }
 190  
                     f.set(retval, newCollection);
 191  
                 }
 192  
                 catch (InstantiationException e)
 193  
                 {
 194  
                     throw new ObjectCopyException("InstantiationException", e);
 195  
                 }
 196  
                 catch (IllegalAccessException e)
 197  
                 {
 198  
                     throw new ObjectCopyException("IllegalAccessException", e);
 199  
                 }
 200  
             }
 201  
             else
 202  
             {
 203  
                 throw new java.lang.UnsupportedOperationException("MetadataObjectCopyStrategy cannot handle Collection of type: " + collection.getClass().getName());
 204  
             }
 205  
         }
 206  
         return retval;
 207  
     }
 208  
 }