Clover Coverage Report - KS Common 1.2-M4-SNAPSHOT (Aggregated)
Coverage timestamp: Wed Jul 20 2011 12:23:34 EDT
../../../../../../img/srcFileCovDistChart7.png 18% of files have more coverage
169   392   77   16.9
108   282   0.46   10
10     7.7  
1    
 
  DefaultDataBeanMapper       Line # 32 169 0% 77 103 64.1% 0.641115
 
  (1)
 
1    package org.kuali.student.common.assembly.transform;
2   
3    import java.beans.BeanInfo;
4    import java.beans.Introspector;
5    import java.beans.PropertyDescriptor;
6    import java.lang.reflect.Field;
7    import java.lang.reflect.ParameterizedType;
8    import java.lang.reflect.Type;
9    import java.sql.Time;
10    import java.sql.Timestamp;
11    import java.util.ArrayList;
12    import java.util.Collection;
13    import java.util.Date;
14    import java.util.HashMap;
15    import java.util.HashSet;
16    import java.util.Iterator;
17    import java.util.List;
18    import java.util.Map;
19    import java.util.Map.Entry;
20    import java.util.Set;
21   
22    import org.apache.log4j.Logger;
23    import org.kuali.student.common.assembly.data.Data;
24    import org.kuali.student.common.assembly.data.Data.DataType;
25    import org.kuali.student.common.assembly.data.Data.DataValue;
26    import org.kuali.student.common.assembly.data.Data.Key;
27    import org.kuali.student.common.assembly.data.Data.Property;
28    import org.kuali.student.common.assembly.data.Data.StringKey;
29    import org.kuali.student.common.assembly.data.Metadata;
30   
31   
 
32    public class DefaultDataBeanMapper implements DataBeanMapper {
33    public static DataBeanMapper INSTANCE = new DefaultDataBeanMapper();
34    final Logger LOG = Logger.getLogger(DefaultDataBeanMapper.class);
35   
36    /* (non-Javadoc)
37    * @see org.kuali.student.core.assembly.data.DataBeanMapper#convertFromBean(java.lang.Object)
38    */
 
39  2 toggle public Data convertFromBean(Object value, Metadata metadata) throws Exception{
40  2 Data result = new Data();
41   
42  2 if (value != null) {
43  2 BeanInfo info = Introspector.getBeanInfo(value.getClass());
44  2 PropertyDescriptor[] properties = info.getPropertyDescriptors();
45   
46  2 for (PropertyDescriptor pd : properties) {
47  22 String propKey = pd.getName();
48  22 Object propValue = pd.getReadMethod().invoke(value, (Object[]) null);
49   
50  22 if ("attributes".equals(propKey)){
51  1 setDataAttributes(result, propValue, metadata);
52    } else {
53  21 setDataValue(result, propKey, propValue, metadata);
54    }
55    }
56    }
57   
58  2 return result;
59    }
60   
61    /* (non-Javadoc)
62    * @see org.kuali.student.core.assembly.data.DataBeanMapper#convertFromData(org.kuali.student.core.assembly.data.Data, java.lang.Class)
63    *
64    * FIXME: Probably a good idea to change "clazz" parameter to be "String objectType" to be consistent with convertFromBean method
65    */
 
66  2 toggle public Object convertFromData(Data data, Class<?> clazz, Metadata metadata) throws Exception{
67  2 Object result = null;
68   
69  2 result = clazz.newInstance();
70  2 BeanInfo info = Introspector.getBeanInfo(result.getClass());
71  2 PropertyDescriptor[] properties = info.getPropertyDescriptors();
72   
73  2 PropertyDescriptor attrProperty = null;
74   
75  2 Set<Key> staticProperties = new HashSet<Key>();
76  2 for (PropertyDescriptor pd : properties) {
77  22 if ("attributes".equals(pd.getName())){
78    //Dynamic attributes will be handled later
79  1 attrProperty = pd;
80    } else {
81  21 StringKey propKey = new StringKey(pd.getName());
82  21 Object propValue = data.get(propKey);
83   
84    //Process a nested object structure or list
85  21 if (propValue instanceof Data){
86  1 clazz.getFields();
87  1 if(metadata!=null){
88  1 if(DataType.LIST.equals(metadata.getDataType())){
89  0 propValue = convertNestedData((Data)propValue, clazz.getDeclaredField(propKey.toString()),metadata.getProperties().get("*"));
90    }else{
91  1 propValue = convertNestedData((Data)propValue, clazz.getDeclaredField(propKey.toString()),metadata.getProperties().get(propKey.toString()));
92    }
93    }
94    else{
95  0 propValue = convertNestedData((Data)propValue, clazz.getDeclaredField(propKey.toString()),null);
96    }
97  20 }else if(metadata!=null&&propValue==null){
98  1 Metadata fieldMetadata = metadata.getProperties().get(propKey.toString());
99  1 if(fieldMetadata != null && fieldMetadata.getDefaultValue() != null){
100  0 propValue = fieldMetadata.getDefaultValue().get();
101    }
102    }
103   
104    //Set the bean property
105  21 if(pd.getWriteMethod() != null & propValue != null){
106  18 if(!(propValue instanceof List) && pd.getPropertyType().isAssignableFrom(List.class)){
107  0 ArrayList<Object> list = new ArrayList<Object>(1);
108  0 list.add(propValue);
109  0 pd.getWriteMethod().invoke(result, list);
110    }else{
111  18 pd.getWriteMethod().invoke(result, new Object[] {propValue});
112    }
113    }
114   
115    //Hold onto the property so we know it is not dynamic
116  21 staticProperties.add(propKey);
117    }
118    }
119   
120    //Any fields not processed above doesn't exist as properties for the bean and
121    //will be set as dynamic attributes.
122  2 Set<Key> keySet = data.keySet();
123  2 if (keySet != null && attrProperty != null){
124  1 Map<String,String> attributes = new HashMap<String,String>();
125  1 for (Key k : keySet) {
126  11 String keyString = k.toString();
127    //Obtain the dynamic flag from the dictionary
128  11 if(metadata==null){
129  11 if (!staticProperties.contains(k) && data.get(k) != null && !keyString.startsWith("_run")){
130  2 attributes.put((String)k.get(),data.get(k).toString());
131    }
132    }
133    else {
134  0 if ((! staticProperties.contains(k)) &&
135    (null != data.get(k)) &&
136    (! keyString.startsWith("_run")) &&
137    (null != metadata.getProperties().get(keyString)) &&
138    (metadata.getProperties().get(keyString).isDynamic()))
139    {
140  0 if (data.get(k) instanceof Data){
141  0 attributes.put((String) k.get(), convertDataValueToStringValue((Data)data.get(k)));
142    } else {
143  0 attributes.put((String) k.get(), data.get(k).toString());
144    }
145    }
146    }
147    }
148  1 if (attrProperty.getWriteMethod() != null) {
149  1 attrProperty.getWriteMethod().invoke(result, new Object[] {attributes});
150    }
151    }
152   
153  2 return result;
154    }
155   
156   
157    /**
158    * Processes a nested data map, it checks to see if the data should be converted to
159    * a list structure or simply be processed as a nested complex object structure.
160    *
161    * @param data
162    * @param propField
163    * @return
164    * @throws Exception
165    */
 
166  1 toggle protected Object convertNestedData(Data data, Field propField, Metadata metadata) throws Exception{
167  1 Object result = null;
168   
169  1 Class<?> propClass = propField.getType();
170  1 if ("java.util.List".equals(propClass.getName())){
171    //Get the generic type for the list
172  1 ParameterizedType propType = (ParameterizedType)propField.getGenericType();
173  1 Type itemType = propType.getActualTypeArguments()[0];
174   
175   
176  1 List<Object> resultList = new ArrayList<Object>();
177  2 for(Iterator<Property> listIter = data.realPropertyIterator(); listIter.hasNext();){
178  1 Property listItem = listIter.next();
179  1 Object listItemValue = listItem.getValue();
180  1 if (listItemValue instanceof Data ){
181  1 Data listItemData = (Data)listItemValue;
182  1 Boolean isDeleted = listItemData.query("_runtimeData/deleted");
183  1 if (isDeleted == null || !isDeleted){
184  1 if(metadata!=null){
185  0 listItemValue = convertFromData((Data)listItemValue, (Class<?>)itemType, metadata.getProperties().get("*"));
186    }else{
187  1 listItemValue = convertFromData((Data)listItemValue, (Class<?>)itemType, null);
188    }
189  1 resultList.add(listItemValue);
190    }
191    } else {
192  0 resultList.add(listItemValue);
193    }
194    }
195   
196  1 result = resultList;
197    } else {
198  0 result = convertFromData(data, propClass,metadata);
199    }
200   
201  1 return result;
202    }
203   
204    /**
205    * Used to set a simple property value into the data object.
206    * @param data
207    * @param propertyKey
208    * @param value
209    *
210    */
 
211  21 toggle protected void setDataValue(Data data, String propertyKey, Object value, Metadata metadata) throws Exception{
212  21 if (isPropertyValid(value)){
213  18 if (value instanceof Boolean){
214  0 data.set(propertyKey, (Boolean)value);
215  18 } else if (value instanceof Date){
216  1 data.set(propertyKey, (Date)value);
217  17 } else if (value instanceof Integer){
218  0 data.set(propertyKey, (Integer)value);
219  17 } else if (value instanceof Double){
220  1 data.set(propertyKey, (Double)value);
221  16 } else if (value instanceof Float){
222  0 data.set(propertyKey, (Float)value);
223  16 } else if (value instanceof Long) {
224  0 data.set(propertyKey, (Long)value);
225  16 } else if (value instanceof Short){
226  0 data.set(propertyKey, (Short)value);
227  16 } else if (value instanceof String){
228  15 data.set(propertyKey, (String)value);
229  1 } else if (value instanceof Timestamp){
230  0 data.set(propertyKey, (Timestamp)value);
231  1 } else if (value instanceof Time){
232  0 data.set(propertyKey, (Time)value);
233  1 } else if (value instanceof Collection){
234    //TODO: Determine correct metadata to pass in getCollectionData() instead of null
235  1 data.set(propertyKey, getCollectionData(value, null));
236    } else {
237    //TODO: Determine correct metadata to pass into convertFromBean() instead of null
238  0 Data dataValue = convertFromBean(value, null);
239  0 data.set(propertyKey, dataValue);
240    }
241    }
242   
243    }
244   
245    /**
246    * This process the attributes map and sets the attribute key/value pairs into the Data map
247    *
248    * @param data
249    * @param value
250    */
 
251  1 toggle protected void setDataAttributes(Data data, Object value, Metadata metadata) {
252  1 @SuppressWarnings("unchecked")
253    Map<String, String> attributes = (Map<String, String>)value;
254   
255  1 for (Entry<String, String> entry:attributes.entrySet()){
256  2 Metadata fieldMetadata = null;
257  2 if (metadata != null) {
258  0 fieldMetadata = metadata.getProperties().get(entry.getKey());
259    } else {
260    //FIXME: Fix this so this warning never happens !!
261  2 LOG.warn("Metadata was null while processing property " + entry.getKey());
262    }
263  2 if (fieldMetadata != null && DataType.LIST.equals(fieldMetadata.getDataType())){
264  0 data.set(entry.getKey(), convertStringToDataValue(entry.getValue()));
265  2 } else if ("false".equals(entry.getValue())||"true".equals(entry.getValue())){
266  0 data.set(entry.getKey(), Boolean.valueOf(entry.getValue()));
267    }else{
268  2 data.set(entry.getKey(), entry.getValue());
269    }
270    }
271    }
272   
273    /**
274    * Converts a list represented by a comma delimited string so to a DataValue
275    *
276    * @param stringValue a comma separated list of values
277    * @return DataValue representation of stringValue
278    */
 
279  0 toggle protected Data convertStringToDataValue(String stringValue) {
280  0 Data data = null;
281   
282  0 if (stringValue != null){
283  0 data = new Data();
284  0 String[] stringValues = stringValue.split(",");
285  0 for (String value:stringValues){
286  0 data.add(value);
287    }
288    }
289   
290  0 return data;
291    }
292   
293    /**
294    * Converts a list represented by DataValue to a list of values as a comma delimited StringValue
295   
296    * @param dataValue DataValue representing a list object
297    * @return the list converted to a comma delimited StringValue
298    */
 
299  0 toggle protected String convertDataValueToStringValue(Data data) {
300  0 StringBuffer sbValue = new StringBuffer();
301   
302  0 Iterator<Property> propertyIterator = data.realPropertyIterator();
303  0 while(propertyIterator.hasNext()){
304  0 Property property = propertyIterator.next();
305  0 String propertyValue = property.getValue();
306  0 sbValue.append(",");
307  0 sbValue.append(propertyValue);
308    }
309   
310  0 if (sbValue.toString().isEmpty()){
311  0 return "";
312    } else {
313  0 return sbValue.toString().substring(1);
314    }
315    }
316   
317    /**
318    * Used to set a list item value into the data object.
319    *
320    * @param data
321    * @param value
322    */
 
323  1 toggle protected void setDataListValue(Data data, Object value, Metadata metadata) throws Exception{
324  1 if (isPropertyValid(value)){
325  1 if (value instanceof Boolean){
326  0 data.add((Boolean)value);
327  1 } else if (value instanceof Date){
328  0 data.add((Date)value);
329  1 } else if (value instanceof Integer){
330  0 data.add((Integer)value);
331  1 } else if (value instanceof Double){
332  0 data.add((Double)value);
333  1 } else if (value instanceof Float){
334  0 data.add((Float)value);
335  1 } else if (value instanceof Long) {
336  0 data.add((Long)value);
337  1 } else if (value instanceof Short){
338  0 data.add((Short)value);
339  1 } else if (value instanceof String){
340  0 data.add((String)value);
341  1 } else if (value instanceof Timestamp){
342  0 data.add((Timestamp)value);
343  1 } else if (value instanceof Time){
344  0 data.add((Time)value);
345  1 } else if (value instanceof Collection){
346    //TODO: Find correct metadata to pass in
347  0 data.add(getCollectionData(value, null));
348    } else {
349    //TODO: Find correct metadata to pass in
350  1 Data dataValue = convertFromBean(value, null);
351  1 data.add(dataValue);
352    }
353    }
354    }
355   
356    /**
357    * Returns a data map object representing a collection
358    *
359    * @param value
360    * @return
361    * @throws Exception
362    */
 
363  1 toggle protected Data getCollectionData(Object value, Metadata metadata) throws Exception{
364  1 Data result = new Data();
365   
366  1 if (value instanceof List){
367  1 List<?> valueList = (List<?>)value;
368  2 for (int i=0;i<valueList.size();i++){
369  1 Object itemValue = valueList.get(i);
370  1 setDataListValue(result, itemValue, metadata);
371    }
372    } else {
373  0 Collection<?> valueCollection = (Collection<?>)value;
374  0 for (Object o:valueCollection){
375  0 setDataListValue(result, o, metadata);
376    }
377    }
378   
379  1 return result;
380    }
381   
 
382  22 toggle protected boolean isPropertyValid(Object value){
383  22 boolean isValid = false;
384   
385  22 if (value != null){
386  21 Class<?> clazz = value.getClass();
387  21 isValid = !(clazz.isArray() || clazz.isAnnotation() || value instanceof Class);
388    }
389   
390  22 return isValid;
391    }
392    }