Coverage Report - org.kuali.student.common.assembly.transform.DefaultDataBeanMapper
 
Classes in this File Line Coverage Branch Coverage Complexity
DefaultDataBeanMapper
76%
119/155
60%
85/140
9.375
 
 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.Set;
 20  
 import java.util.Map.Entry;
 21  
 
 22  
 import org.kuali.student.common.assembly.data.Data;
 23  
 import org.kuali.student.common.assembly.data.Metadata;
 24  
 import org.kuali.student.common.assembly.data.Data.DataType;
 25  
 import org.kuali.student.common.assembly.data.Data.Key;
 26  
 import org.kuali.student.common.assembly.data.Data.Property;
 27  
 import org.kuali.student.common.assembly.data.Data.StringKey;
 28  
 
 29  
 
 30  2
 public class DefaultDataBeanMapper implements DataBeanMapper {
 31  1
         public static DataBeanMapper INSTANCE = new DefaultDataBeanMapper();
 32  
         
 33  
         /* (non-Javadoc)
 34  
          * @see org.kuali.student.core.assembly.data.DataBeanMapper#convertFromBean(java.lang.Object)
 35  
          */
 36  
         public Data convertFromBean(Object value) throws Exception{
 37  2
                  Data result = new Data();
 38  
                 
 39  2
                 if (value != null) {
 40  2
                 BeanInfo info = Introspector.getBeanInfo(value.getClass());
 41  2
                 PropertyDescriptor[] properties = info.getPropertyDescriptors();
 42  
                  
 43  24
                 for (PropertyDescriptor pd : properties) {
 44  22
                     String propKey = pd.getName();
 45  22
                     Object propValue = pd.getReadMethod().invoke(value, (Object[]) null);
 46  
                     
 47  22
                     if ("attributes".equals(propKey)){
 48  1
                             setDataAttributes(result, propValue);
 49  
                     } else {
 50  21
                             setDataValue(result, propKey, propValue);
 51  
                     }
 52  
                 }
 53  
                 }        
 54  
                 
 55  2
                 return result;
 56  
         }
 57  
         
 58  
         /* (non-Javadoc)
 59  
          * @see org.kuali.student.core.assembly.data.DataBeanMapper#convertFromData(org.kuali.student.core.assembly.data.Data, java.lang.Class)
 60  
          */
 61  
         public Object convertFromData(Data data, Class<?> clazz, Metadata metadata) throws Exception{
 62  2
                 Object result = null;
 63  
                 
 64  2
                 result = clazz.newInstance();
 65  2
         BeanInfo info = Introspector.getBeanInfo(result.getClass());
 66  2
         PropertyDescriptor[] properties = info.getPropertyDescriptors();
 67  
 
 68  2
         PropertyDescriptor attrProperty = null;
 69  
         
 70  2
         Set<Key> staticProperties = new HashSet<Key>();
 71  24
                 for (PropertyDescriptor pd : properties) {
 72  22
                         if ("attributes".equals(pd.getName())){
 73  
                                 //Dynamic attributes will be handled later
 74  1
                                 attrProperty = pd;
 75  
                         } else {
 76  21
                     StringKey propKey = new StringKey(pd.getName());
 77  21
                     Object propValue = data.get(propKey);
 78  
         
 79  
                     //Process a nested object structure or list
 80  21
                     if (propValue instanceof Data){
 81  1
                             clazz.getFields();
 82  1
                             if(metadata!=null){
 83  1
                                     if(DataType.LIST.equals(metadata.getDataType())){
 84  0
                                             propValue = convertNestedData((Data)propValue, clazz.getDeclaredField(propKey.toString()),metadata.getProperties().get("*"));
 85  
                                     }else{
 86  1
                                             propValue = convertNestedData((Data)propValue, clazz.getDeclaredField(propKey.toString()),metadata.getProperties().get(propKey.toString()));
 87  
                                     }
 88  
                             }
 89  
                             else{
 90  0
                                     propValue = convertNestedData((Data)propValue, clazz.getDeclaredField(propKey.toString()),null);
 91  
                             }
 92  20
                     }else if(metadata!=null&&propValue==null){
 93  1
                             Metadata fieldMetadata = metadata.getProperties().get(propKey.toString());
 94  1
                             if(fieldMetadata != null && fieldMetadata.getDefaultValue() != null){
 95  0
                                     propValue = fieldMetadata.getDefaultValue().get();        
 96  
                             }
 97  
                     }
 98  
                     
 99  
                             //Set the bean property
 100  21
                             if(pd.getWriteMethod() != null & propValue != null){
 101  18
                                     if(!(propValue instanceof List) && pd.getPropertyType().isAssignableFrom(List.class)){
 102  0
                                             ArrayList<Object> list = new ArrayList<Object>(1);
 103  0
                                             list.add(propValue);
 104  0
                                             pd.getWriteMethod().invoke(result, list);
 105  0
                                     }else{
 106  18
                                             pd.getWriteMethod().invoke(result, new Object[] {propValue});
 107  
                                     }
 108  
                     }
 109  
                     
 110  
                             //Hold onto the property so we know it is not dynamic
 111  21
                             staticProperties.add(propKey);
 112  
                         }
 113  
                 }
 114  
                 
 115  
                 //Any fields not processed above doesn't exist as properties for the bean and 
 116  
                 //will be set as dynamic attributes.
 117  2
                 Set<Key> keySet = data.keySet();
 118  2
                 if (keySet != null && attrProperty != null){
 119  1
                         Map<String,String> attributes = new HashMap<String,String>();
 120  1
             for (Key k : keySet) {
 121  11
                                 String keyString = k.toString();
 122  
                                 //Obtain the dynamic flag from the dictionary
 123  11
                                 if(metadata==null){
 124  11
                                         if (!staticProperties.contains(k) && data.get(k) != null && !keyString.startsWith("_run")){
 125  2
                                                 attributes.put((String)k.get(),data.get(k).toString());
 126  
                                         }
 127  
                                 }
 128  
                                 else {
 129  0
                                     if ((! staticProperties.contains(k)) &&
 130  
                                         (null != data.get(k)) &&
 131  
                                         (! keyString.startsWith("_run")) &&
 132  
                                         (null != metadata.getProperties().get(keyString)) &&
 133  
                                         (metadata.getProperties().get(keyString).isDynamic()))
 134  
                                     {
 135  0
                         attributes.put((String) k.get(), data.get(k).toString());
 136  
                                         }
 137  
                                 }
 138  11
                         }
 139  1
             if (attrProperty.getWriteMethod() != null) {
 140  1
                 attrProperty.getWriteMethod().invoke(result, new Object[] {attributes});
 141  
             }
 142  
                 }
 143  
 
 144  2
                 return result;
 145  
         }
 146  
         
 147  
         
 148  
         /**
 149  
          * Processes a nested data map, it checks to see if the data should be converted to 
 150  
          * a list structure or simply be processed as a nested complex object structure.
 151  
          * 
 152  
          * @param data
 153  
          * @param propField
 154  
          * @return
 155  
          * @throws Exception
 156  
          */
 157  
         protected Object convertNestedData(Data data, Field propField, Metadata metadata) throws Exception{
 158  1
                 Object result = null;
 159  
 
 160  1
                 Class<?> propClass = propField.getType();
 161  1
                 if ("java.util.List".equals(propClass.getName())){
 162  
                         //Get the generic type for the list
 163  1
                         ParameterizedType propType = (ParameterizedType)propField.getGenericType();
 164  1
                         Type itemType = propType.getActualTypeArguments()[0];
 165  
                         
 166  
                         
 167  1
                         List<Object> resultList = new ArrayList<Object>();
 168  1
                         for(Iterator<Property> listIter = data.realPropertyIterator(); listIter.hasNext();){
 169  1
                                 Property listItem = listIter.next();
 170  1
                                 Object listItemValue = listItem.getValue();
 171  1
                                 if (listItemValue instanceof Data ){
 172  1
                                         Data listItemData = (Data)listItemValue;
 173  1
                                         Boolean isDeleted = listItemData.query("_runtimeData/deleted");
 174  1
                                         if (isDeleted == null || !isDeleted){
 175  1
                                                 if(metadata!=null){
 176  0
                                                         listItemValue = convertFromData((Data)listItemValue, (Class<?>)itemType, metadata.getProperties().get("*"));
 177  
                                                 }else{
 178  1
                                                         listItemValue = convertFromData((Data)listItemValue, (Class<?>)itemType, null);
 179  
                                                 }
 180  1
                                                 resultList.add(listItemValue);
 181  
                                         }
 182  1
                                 } else {
 183  0
                                         resultList.add(listItemValue);
 184  
                                 }
 185  1
                         }
 186  
 
 187  1
                         result = resultList;
 188  1
                 } else {
 189  0
                         result = convertFromData(data, propClass,metadata);
 190  
                 }
 191  
                 
 192  1
                 return result;
 193  
         }
 194  
         
 195  
         /**
 196  
          * Used to set a simple property value into the data object. 
 197  
          * @param data
 198  
          * @param propertyKey
 199  
          * @param value
 200  
          * 
 201  
          */
 202  
         protected void setDataValue(Data data, String propertyKey, Object value) throws Exception{
 203  21
                 if (isPropertyValid(value)){
 204  18
                         if (value instanceof Boolean){
 205  0
                                 data.set(propertyKey, (Boolean)value);
 206  18
                         } else if (value instanceof Date){
 207  1
                                 data.set(propertyKey, (Date)value);
 208  17
                         } else if (value instanceof Integer){
 209  0
                                 data.set(propertyKey, (Integer)value);
 210  17
                         } else if (value instanceof Double){
 211  1
                                 data.set(propertyKey, (Double)value);
 212  16
                         } else if (value instanceof Float){
 213  0
                                 data.set(propertyKey, (Float)value);
 214  16
                         } else if (value instanceof Long) {
 215  0
                                 data.set(propertyKey, (Long)value);
 216  16
                         } else if (value instanceof Short){
 217  0
                                 data.set(propertyKey, (Short)value);                        
 218  16
                         } else if (value instanceof String){
 219  15
                                 data.set(propertyKey, (String)value);
 220  1
                         } else if (value instanceof Timestamp){
 221  0
                                 data.set(propertyKey, (Timestamp)value);
 222  1
                         } else if (value instanceof Time){
 223  0
                                 data.set(propertyKey, (Time)value);
 224  1
                         } else if (value instanceof Collection){
 225  1
                                 data.set(propertyKey, getCollectionData(value));
 226  
                         } else {
 227  0
                                 Data dataValue = convertFromBean(value);
 228  0
                                 data.set(propertyKey, dataValue);
 229  
                         }
 230  
                 }
 231  
                 
 232  21
         }
 233  
         
 234  
         /**
 235  
          * This process the attributes map and sets the attribute key/value pairs into the Data map
 236  
          * 
 237  
          * @param data
 238  
          * @param value
 239  
          */
 240  
         protected void setDataAttributes(Data data, Object value) {
 241  
                 @SuppressWarnings("unchecked")
 242  1
                 Map<String, String> attributes = (Map<String, String>)value;
 243  
                 
 244  1
                 for (Entry<String, String> entry:attributes.entrySet()){
 245  2
                         if("false".equals(entry.getValue())||"true".equals(entry.getValue())){
 246  0
                                 data.set(entry.getKey(), Boolean.valueOf(entry.getValue()));
 247  
                         }else{
 248  2
                                 data.set(entry.getKey(), entry.getValue());
 249  
                         }
 250  
                 }
 251  1
         }
 252  
 
 253  
         /**
 254  
          * Used to set a list item value into the data object.
 255  
          * 
 256  
          * @param data
 257  
          * @param value
 258  
          */
 259  
         protected void setDataListValue(Data data, Object value) throws Exception{
 260  1
                 if (isPropertyValid(value)){
 261  1
                         if (value instanceof Boolean){
 262  0
                                 data.add((Boolean)value);
 263  1
                         } else if (value instanceof Date){
 264  0
                                 data.add((Date)value);
 265  1
                         } else if (value instanceof Integer){
 266  0
                                 data.add((Integer)value);
 267  1
                         } else if (value instanceof Double){
 268  0
                                 data.add((Double)value);
 269  1
                         } else if (value instanceof Float){
 270  0
                                 data.add((Float)value);
 271  1
                         } else if (value instanceof Long) {
 272  0
                                 data.add((Long)value);
 273  1
                         } else if (value instanceof Short){
 274  0
                                 data.add((Short)value);                        
 275  1
                         } else if (value instanceof String){
 276  0
                                 data.add((String)value);
 277  1
                         } else if (value instanceof Timestamp){
 278  0
                                 data.add((Timestamp)value);
 279  1
                         } else if (value instanceof Time){
 280  0
                                 data.add((Time)value);
 281  1
                         } else if (value instanceof Collection){
 282  0
                                 data.add(getCollectionData(value));
 283  
                         } else {
 284  1
                                 Data dataValue = convertFromBean(value);
 285  1
                                 data.add(dataValue);                        
 286  
                         }
 287  
                 }
 288  1
         }
 289  
         
 290  
         /**
 291  
          * Returns a data map object representing a collection
 292  
          * 
 293  
          * @param value
 294  
          * @return
 295  
          * @throws Exception
 296  
          */
 297  
         protected Data getCollectionData(Object value) throws Exception{
 298  1
                 Data result = new Data();
 299  
                 
 300  1
                 if (value instanceof List){
 301  1
                         List<?> valueList = (List<?>)value;
 302  2
                         for (int i=0;i<valueList.size();i++){
 303  1
                                 Object itemValue = valueList.get(i); 
 304  1
                                 setDataListValue(result, itemValue);
 305  
                         }
 306  1
                 } else {
 307  0
                         Collection<?> valueCollection = (Collection<?>)value;
 308  0
                         for (Object o:valueCollection){
 309  0
                                 setDataListValue(result, o);
 310  
                         }
 311  
                 }
 312  
                 
 313  1
                 return result;
 314  
         }
 315  
         
 316  
         protected boolean isPropertyValid(Object value){
 317  22
                 boolean isValid = false;
 318  
                 
 319  22
                 if (value != null){
 320  21
                         Class<?> clazz = value.getClass();
 321  21
                         isValid = !(clazz.isArray() || clazz.isAnnotation() || value instanceof Class);
 322  
                 }
 323  
                 
 324  22
                 return isValid;
 325  
         }
 326  
 }