KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > dozer > util > mapping > propertydescriptor > BruteForcePropertyDescriptor


1 /*
2  * Copyright 2005-2007 the original author or authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package net.sf.dozer.util.mapping.propertydescriptor;
17
18 import java.beans.PropertyDescriptor JavaDoc;
19 import java.lang.reflect.Array JavaDoc;
20 import java.lang.reflect.InvocationTargetException JavaDoc;
21 import java.lang.reflect.Method JavaDoc;
22 import java.util.ArrayList JavaDoc;
23 import java.util.Collection JavaDoc;
24 import java.util.HashSet JavaDoc;
25 import java.util.Iterator JavaDoc;
26 import java.util.Set JavaDoc;
27
28 import net.sf.dozer.util.mapping.DozerBeanMapper;
29 import net.sf.dozer.util.mapping.MappingException;
30 import net.sf.dozer.util.mapping.fieldmap.ClassMap;
31 import net.sf.dozer.util.mapping.fieldmap.Field;
32 import net.sf.dozer.util.mapping.fieldmap.Hint;
33 import net.sf.dozer.util.mapping.util.CollectionUtils;
34 import net.sf.dozer.util.mapping.util.DestBeanCreator;
35 import net.sf.dozer.util.mapping.util.MapperConstants;
36 import net.sf.dozer.util.mapping.util.MappingUtils;
37 import net.sf.dozer.util.mapping.util.ReflectionUtils;
38
39 import org.apache.commons.logging.Log;
40 import org.apache.commons.logging.LogFactory;
41
42 /**
43  * @author garsombke.franz
44  */

45 public class BruteForcePropertyDescriptor implements DozerPropertyDescriptorIF {
46
47   //private static final Logger log = Logger.getLogger(BruteForcePropertyDescriptor.class);
48
private static final Log log = LogFactory.getLog(DozerBeanMapper.class);
49   
50
51   private final Field field;
52   private final ReflectionUtils reflectionUtils = new ReflectionUtils();
53   private final CollectionUtils collectionUtils = new CollectionUtils();
54   private final MappingUtils mappingUtils = new MappingUtils();
55   private final DestBeanCreator destBeanCreator = new DestBeanCreator(MappingUtils.storedFactories);//only temp use the public static factories. The factories data needs to be relocated to a better place
56

57
58   public BruteForcePropertyDescriptor(Field field) {
59     this.field = field;
60   }
61
62   public Class JavaDoc getPropertyType(Class JavaDoc clazz) {
63     Class JavaDoc returnType;
64     try {
65       returnType = getReadMethod(clazz).getReturnType();
66     } catch (Exception JavaDoc e) {
67       log.debug("Read method exception:" + e);
68       // let us try the set method - the field might not have a 'get' method
69
returnType = getWriteMethod(clazz).getParameterTypes()[0];
70     }
71     return returnType;
72   }
73
74   public void setPropertyValue(Object JavaDoc bean, Object JavaDoc value, Hint hint, ClassMap classMap) {
75     try {
76       if (field.getName().indexOf(MapperConstants.DEEP_FIELD_DELIMITOR) < 0) {
77         if (getPropertyType(bean.getClass()).isPrimitive() && value == null) {
78           // do nothing
79
} else {
80           //Check if dest value is already set and is equal to src value. If true, no need to rewrite the dest value
81
try {
82             if (getPropertyValue(bean) == value) {
83               return;
84             }
85           } catch (Exception JavaDoc e) {
86             //if we failed to read the value, assume we must write, and continue...
87
}
88           if (!field.isIndexed()) {
89             getWriteMethod(bean.getClass()).invoke(bean, new Object JavaDoc[] { value });
90           } else {
91             writeIndexedValue(null, bean, value);
92           }
93         }
94       } else {
95         writeDeepDestinationValue(bean, value, hint, classMap);
96       }
97     } catch (Exception JavaDoc e) {
98       throw new MappingException(e);
99     }
100   }
101
102   public Object JavaDoc getPropertyValue(Object JavaDoc bean) {
103     Object JavaDoc o = null;
104     try {
105       if (field.getName().indexOf(MapperConstants.DEEP_FIELD_DELIMITOR) < 0) {
106         o = getReadMethod(bean.getClass()).invoke(bean, null);
107         if (field.isIndexed()) {
108           return mappingUtils.getIndexedValue(o, field.getIndex());
109         } else {
110           return o;
111         }
112       } else {
113         return getDeepSrcFieldValue(bean);
114       }
115     } catch (Exception JavaDoc e) {
116       throw new MappingException(e);
117     }
118   }
119
120
121   protected Object JavaDoc getDeepSrcFieldValue(Object JavaDoc srcObj) throws InvocationTargetException JavaDoc, IllegalAccessException JavaDoc {
122     // follow deep field hierarchy. If any values are null along the way, then return null
123
Object JavaDoc parentObj = srcObj;
124     Object JavaDoc hierarchyValue = null;
125     PropertyDescriptor JavaDoc[] hierarchy = getHierarchy(srcObj);
126     int size = hierarchy.length;
127     for (int i = 0; i < size; i++) {
128       PropertyDescriptor JavaDoc pd = hierarchy[i];
129       hierarchyValue = pd.getReadMethod().invoke(parentObj, null);
130       parentObj = hierarchyValue;
131       if (hierarchyValue == null) {
132         break;
133       }
134     }
135     
136     //If field is indexed, get actual value within the collection at the specified index
137
if (field.isIndexed()) {
138       hierarchyValue = mappingUtils.getIndexedValue(hierarchyValue, field.getIndex());
139     }
140     
141     return hierarchyValue;
142   }
143
144   protected Method JavaDoc getReadMethod(Class JavaDoc objectClass, String JavaDoc fieldName) {
145     PropertyDescriptor JavaDoc pd = reflectionUtils.getPropertyDescriptor(objectClass, fieldName);
146     if ((pd == null || pd.getReadMethod() == null)) {
147       throw new MappingException("Unable to determine read method for field: " + fieldName + " class: " + objectClass);
148     }
149     return pd.getReadMethod();
150   }
151
152   protected Method JavaDoc getWriteMethod(Class JavaDoc objectClass, String JavaDoc fieldName) {
153     PropertyDescriptor JavaDoc pd = reflectionUtils.getPropertyDescriptor(objectClass, fieldName);
154     if ((pd == null || pd.getWriteMethod() == null)) {
155       throw new MappingException("Unable to determine write method for field: " + fieldName + " class: " + objectClass);
156     }
157     return pd.getWriteMethod();
158   }
159
160   protected void writeDeepDestinationValue(Object JavaDoc destObj, Object JavaDoc destFieldValue, Hint destHint, ClassMap classMap)
161       throws IllegalAccessException JavaDoc, InvocationTargetException JavaDoc, InstantiationException JavaDoc, ClassNotFoundException JavaDoc,
162       NoSuchMethodException JavaDoc, NoSuchFieldException JavaDoc {
163     // follow deep field hierarchy. If any values are null along the way, then create a new instance
164
PropertyDescriptor JavaDoc[] hierarchy = getHierarchy(destObj);
165     // first, iteratate through hierarchy and instantiate any objects that are null
166
Object JavaDoc parentObj = destObj;
167     int hierarchyLength = hierarchy.length - 1;
168     for (int i = 0; i < hierarchyLength; i++) {
169       PropertyDescriptor JavaDoc pd = hierarchy[i];
170       Object JavaDoc value = pd.getReadMethod().invoke(parentObj, null);
171       Class JavaDoc clazz = null;
172       if (value == null) {
173         clazz = pd.getPropertyType();
174         if (clazz.isInterface()) {
175           // before setting the property on the destination object we should check for a destination hint. need to know
176
// that we are at the end of the line
177
if ((i + 1) == hierarchyLength) {
178             // determine the property type
179
if (destHint != null) {
180               clazz = destHint.getHint();
181             }
182           }
183         }
184         Object JavaDoc o;
185         try {
186           o = clazz.newInstance();
187           pd.getWriteMethod().invoke(parentObj, new Object JavaDoc[] { o });
188         } catch (InstantiationException JavaDoc e) {
189           // lets see if they have a factory we can try. If not...throw the exception:
190
if (classMap.getDestClass().getBeanFactory() != null) {
191             o = destBeanCreator.createFromFactory(null, classMap.getSourceClass().getClassToMap(), classMap
192                 .getDestClass().getBeanFactory(), classMap.getDestClass().getFactoryBeanId(), clazz);
193             pd.getWriteMethod().invoke(parentObj, new Object JavaDoc[] { o });
194           } else {
195             throw e;
196           }
197         }
198         value = pd.getReadMethod().invoke(parentObj, null);
199       }
200       parentObj = value;
201     }
202     // second, set deep field value
203
PropertyDescriptor JavaDoc pd = hierarchy[hierarchy.length - 1];
204     if (pd.getReadMethod().getReturnType().isPrimitive() && destFieldValue == null) {
205     } else {
206       if (!field.isIndexed()) {
207         Method JavaDoc method = pd.getWriteMethod();
208         if(method == null && field.getTheSetMethod() != null) {
209           // lets see if we can find a custom method
210
method = reflectionUtils.findAMethod(parentObj.getClass(), field.getTheSetMethod());
211         }
212         method.invoke(parentObj, new Object JavaDoc[] { destFieldValue });
213       } else {
214         writeIndexedValue(pd, parentObj, destFieldValue);
215       }
216     }
217   }
218
219   protected PropertyDescriptor JavaDoc[] getHierarchy(Object JavaDoc obj) {
220     return reflectionUtils.getDeepFieldHierarchy(obj.getClass(), field.getName());
221   }
222
223   public String JavaDoc getReadMethodName(Class JavaDoc clazz) {
224     Method JavaDoc readMethod;
225     try {
226       readMethod = getReadMethod(clazz);
227     } catch (MappingException e) {
228       log.debug("Can't find read method for class:" + clazz + " and field:" + field.getName());
229       return "NoReadMethodFound";
230     }
231     return readMethod.getName();
232   }
233
234   public String JavaDoc getWriteMethodName(Class JavaDoc clazz) {
235     return getWriteMethod(clazz).getName();
236   }
237
238   public Method JavaDoc getReadMethod(Class JavaDoc bean) {
239     Method JavaDoc readMethod;
240     if (field.getTheGetMethod() == null) {
241       readMethod = getReadMethod(bean, field.getName());
242     } else {
243       try {
244         readMethod = reflectionUtils.findAMethod(bean, field.getTheGetMethod());
245       } catch (Exception JavaDoc e) {
246         throw new MappingException(e);
247       }
248     }
249     return readMethod;
250   }
251
252   public Method JavaDoc getWriteMethod(Class JavaDoc clazz) {
253     Method JavaDoc writeMethod;
254     if (field.getTheSetMethod() == null || field.getName().indexOf(MapperConstants.DEEP_FIELD_DELIMITOR) > 0) {
255       writeMethod = getWriteMethod(clazz, field.getName());
256     } else {
257       try {
258         writeMethod = reflectionUtils.findAMethod(clazz, field.getTheSetMethod());
259       } catch (Exception JavaDoc e) {
260         throw new MappingException(e);
261       }
262     }
263     return writeMethod;
264   }
265
266   protected void writeIndexedValue(PropertyDescriptor JavaDoc pd, Object JavaDoc destObj, Object JavaDoc destFieldValue)
267       throws IllegalAccessException JavaDoc, InvocationTargetException JavaDoc, NoSuchMethodException JavaDoc, ClassNotFoundException JavaDoc,
268       NoSuchFieldException JavaDoc {
269     int index = field.getIndex();
270     Object JavaDoc o = null;
271     if (pd != null) {
272       o = pd.getReadMethod().invoke(destObj, null);
273     } else {
274       o = getReadMethod(destObj.getClass()).invoke(destObj, null);
275     }
276     if (o == null) {
277       Class JavaDoc returnType = null;
278       if (pd != null) {
279         returnType = pd.getReadMethod().getReturnType();
280       } else {
281         returnType = getPropertyType(destObj.getClass());
282       }
283       if (returnType.isArray()) {
284         o = Array.newInstance(returnType.getComponentType(), 0);
285       } else if (collectionUtils.isSet(returnType)) {
286         o = new HashSet JavaDoc();
287       } else { // default
288
o = new ArrayList JavaDoc();
289       }
290     }
291     if (o instanceof Collection JavaDoc) {
292       Collection JavaDoc newCollection;
293       if (o instanceof Set JavaDoc) {
294         newCollection = new HashSet JavaDoc();
295       } else {
296         newCollection = new ArrayList JavaDoc();
297       }
298
299       Collection JavaDoc c = (Collection JavaDoc) o;
300       Iterator JavaDoc i = c.iterator();
301       int x = 0;
302       while (i.hasNext()) {
303         if (x != index) {
304           newCollection.add(i.next());
305         } else {
306           newCollection.add(destFieldValue);
307         }
308         x++;
309       }
310       if (newCollection.size() <= index) {
311         while (newCollection.size() < index) {
312           newCollection.add(null);
313         }
314         newCollection.add(destFieldValue);
315       }
316       if (pd != null) {
317         pd.getWriteMethod().invoke(destObj, new Object JavaDoc[] { newCollection });
318       } else {
319         getWriteMethod(destObj.getClass()).invoke(destObj, new Object JavaDoc[] { newCollection });
320       }
321     } else if (o.getClass().isArray()) {
322       Object JavaDoc[] objs = (Object JavaDoc[]) o;
323       Object JavaDoc[] x = (Object JavaDoc[]) Array.newInstance(objs.getClass().getComponentType(),
324           objs.length > index ? objs.length + 1 : index + 1);
325       for (int i = 0; i < objs.length; i++) {
326         x[i] = objs[i];
327       }
328       x[index] = destFieldValue;
329
330       if (pd == null) {
331         getWriteMethod(destObj.getClass()).invoke(destObj, new Object JavaDoc[] { x });
332       } else {
333         pd.getWriteMethod().invoke(destObj, new Object JavaDoc[] { x });
334       }
335     }
336   }
337
338 }
Popular Tags