001 package org.apache.ojb.otm.swizzle;
002
003 /* Copyright 2003-2005 The Apache Software Foundation
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018 import java.lang.reflect.Array;
019 import java.util.Collection;
020 import java.util.Iterator;
021 import java.util.List;
022 import java.util.Set;
023 import org.apache.ojb.broker.Identity;
024 import org.apache.ojb.broker.PersistenceBroker;
025 import org.apache.ojb.broker.cache.ObjectCache;
026 import org.apache.ojb.broker.core.proxy.CollectionProxyDefaultImpl;
027 import org.apache.ojb.broker.core.proxy.ListProxyDefaultImpl;
028 import org.apache.ojb.broker.core.proxy.SetProxyDefaultImpl;
029 import org.apache.ojb.broker.metadata.ClassDescriptor;
030 import org.apache.ojb.broker.metadata.CollectionDescriptor;
031 import org.apache.ojb.broker.metadata.FieldDescriptor;
032 import org.apache.ojb.broker.metadata.ObjectReferenceDescriptor;
033 import org.apache.ojb.broker.metadata.fieldaccess.PersistentField;
034
035 public class CopySwizzling implements Swizzling
036 {
037
038 /**
039 * @see org.apache.ojb.otm.swizzle.Swizzling#swizzle(Object, Object, PersistenceBroker, ObjectCache)
040 */
041 public Object swizzle(Object newObj, Object oldObj, PersistenceBroker pb,
042 ObjectCache cache)
043 {
044 if (newObj == null) // invalidating
045 {
046 return null;
047 }
048
049 if (oldObj == null)
050 {
051 return newObj;
052 }
053
054 if (!newObj.getClass().equals(oldObj.getClass()))
055 {
056 System.err.println("Cannot swizzle objects of different classes: "
057 + newObj.getClass() + " and " + oldObj.getClass());
058 return newObj;
059 }
060
061 ClassDescriptor mif = pb.getClassDescriptor(newObj.getClass());
062 FieldDescriptor[] fieldDescs = mif.getFieldDescriptions();
063
064 for (int i = 0; i < fieldDescs.length; i++)
065 {
066 FieldDescriptor fd = fieldDescs[i];
067 PersistentField f = fd.getPersistentField();
068 f.set(oldObj, f.get(newObj));
069 }
070
071 // N:1 relations
072 Iterator iter = mif.getObjectReferenceDescriptors().iterator();
073 ObjectReferenceDescriptor rds;
074 PersistentField field;
075 Object newRelObj;
076 Identity newRelOid;
077 Object oldRelObj;
078
079 while (iter.hasNext())
080 {
081 rds = (ObjectReferenceDescriptor) iter.next();
082 field = rds.getPersistentField();
083 newRelObj = field.get(newObj);
084 oldRelObj = field.get(oldObj);
085 if ((newRelObj == null) && (oldRelObj != null))
086 {
087 field.set(oldObj, null);
088 }
089 else if (newRelObj != null)
090 {
091 newRelOid = new Identity(newRelObj, pb);
092 if ((oldRelObj == null) ||
093 !newRelOid.equals(new Identity(oldRelObj, pb)))
094 {
095 // seek for existing old object with the new identity
096 oldRelObj = cache.lookup(newRelOid);
097 if (oldRelObj == null)
098 {
099 throw new IllegalStateException("Related object not found in the context: " + newRelOid);
100 }
101 field.set(oldObj, oldRelObj);
102 }
103 }
104 }
105
106 // 1:N relations
107 Iterator collections = mif.getCollectionDescriptors().iterator();
108 CollectionDescriptor collectionDescriptor;
109
110 while (collections.hasNext())
111 {
112 collectionDescriptor = (CollectionDescriptor) collections.next();
113 field = collectionDescriptor.getPersistentField();
114 if (Collection.class.isAssignableFrom(field.getType()))
115 {
116 Collection newCol;
117 Collection oldCol;
118
119 newCol = (Collection) field.get(newObj);
120 if (newCol == null)
121 {
122 field.set(oldObj, null);
123 continue;
124 }
125
126 oldCol = (Collection) field.get(oldObj);
127 if (newCol instanceof CollectionProxyDefaultImpl)
128 {
129 CollectionProxyDefaultImpl cp = (CollectionProxyDefaultImpl) newCol;
130 if (newCol instanceof List)
131 {
132 oldCol = new ListProxyDefaultImpl(pb.getPBKey(), cp.getCollectionClass(), cp.getQuery());
133 }
134 else if (newCol instanceof Set)
135 {
136 oldCol = new SetProxyDefaultImpl(pb.getPBKey(), cp.getCollectionClass(), cp.getQuery());
137 }
138 else
139 {
140 oldCol = new CollectionProxyDefaultImpl(pb.getPBKey(), cp.getCollectionClass(), cp.getQuery());
141 }
142 if (!((CollectionProxyDefaultImpl) newCol).isLoaded())
143 {
144 field.set(oldObj, oldCol);
145 continue;
146 }
147 oldCol.clear();
148 }
149 else
150 {
151 try
152 {
153 oldCol = (Collection) newCol.getClass().newInstance();
154 }
155 catch (Exception ex)
156 {
157 System.err.println("Cannot instantiate collection field which is neither Collection nor array: " + field);
158 ex.printStackTrace();
159 return newObj;
160 }
161 }
162 field.set(oldObj, oldCol);
163 for (Iterator it = newCol.iterator(); it.hasNext(); )
164 {
165 newRelObj = it.next();
166 newRelOid = new Identity(newRelObj, pb);
167 oldRelObj = cache.lookup(newRelOid);
168 if (oldRelObj == null)
169 {
170 oldRelObj = newRelObj;
171 }
172 oldCol.add(oldRelObj);
173 }
174 }
175 else if (field.getType().isArray())
176 {
177 Object newArray = field.get(newObj);
178 int length = Array.getLength(newArray);
179 Object oldArray =
180 Array.newInstance(field.getType().getComponentType(), length);
181
182 for (int i = 0; i < length; i++)
183 {
184 newRelObj = Array.get(newArray, i);
185 newRelOid = new Identity(newRelObj, pb);
186 oldRelObj = cache.lookup(newRelOid);
187 if (oldRelObj == null)
188 {
189 throw new IllegalStateException("Related object not found for swizzle: " + newRelOid);
190 }
191 Array.set(oldArray, i, oldRelObj);
192 }
193 field.set(oldObj, oldArray);
194 }
195 else
196 {
197 throw new IllegalStateException("Cannot swizzle collection field: " + field);
198 }
199 }
200
201 return oldObj;
202 }
203
204 /**
205 * @see org.apache.ojb.otm.swizzle.Swizzling#isSameInstance(Object, Object)
206 */
207 public boolean isSameInstance(Object swizzledObject, Object object)
208 {
209 return (swizzledObject == object);
210 }
211
212 /**
213 * @see org.apache.ojb.otm.swizzle.Swizzling#getRealTarget(Object)
214 */
215 public Object getRealTarget(Object swizzledObject)
216 {
217 return swizzledObject;
218 }
219
220 }