KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > ojb > otm > copy > MetadataObjectCopyStrategy


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 JavaDoc;
27 import java.util.Map JavaDoc;
28 import java.util.Collection JavaDoc;
29 import java.util.Iterator JavaDoc;
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 JavaDoc copy(final Object JavaDoc obj, final PersistenceBroker broker)
49     {
50         return clone(obj, IdentityMapFactory.getIdentityMap(), broker);
51     }
52
53     private static Object JavaDoc clone(final Object JavaDoc toCopy, final Map JavaDoc 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 JavaDoc retval;
89         try
90         {
91             final Constructor JavaDoc con = cld.getZeroArgumentConstructor();
92             retval = ConstructorHelper.instantiate(con);
93             objMap.put(toCopy,retval);
94         }
95         catch (InstantiationException JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc object = f.get(toCopy);
140             final Object JavaDoc 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 JavaDoc colDescsCol = cld.getCollectionDescriptors();
148         final Iterator JavaDoc it = colDescsCol.iterator();
149         while (it.hasNext())
150         {
151             final CollectionDescriptor cd = (CollectionDescriptor) it.next();
152             final PersistentField f = cd.getPersistentField();
153             final Object JavaDoc 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 JavaDoc)
167             {
168                 try
169                 {
170                     final Collection JavaDoc newCollection = (Collection JavaDoc) collection.getClass().newInstance();
171                     final Iterator JavaDoc tempIter = ((Collection JavaDoc) collection).iterator();
172                     Object JavaDoc 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 JavaDoc 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 JavaDoc e)
193                 {
194                     throw new ObjectCopyException("InstantiationException", e);
195                 }
196                 catch (IllegalAccessException JavaDoc e)
197                 {
198                     throw new ObjectCopyException("IllegalAccessException", e);
199                 }
200             }
201             else
202             {
203                 throw new java.lang.UnsupportedOperationException JavaDoc("MetadataObjectCopyStrategy cannot handle Collection of type: " + collection.getClass().getName());
204             }
205         }
206         return retval;
207     }
208 }
209
Popular Tags