1   
2   
3   
4   
5   
6   
7   
8   
9   
10  
11  
12  
13  
14  
15  
16  package org.kuali.ole.module.purap.util;
17  
18  import org.kuali.ole.module.purap.PurapConstants;
19  import org.kuali.ole.sys.context.SpringContext;
20  import org.kuali.rice.core.web.format.FormatException;
21  import org.kuali.rice.krad.bo.BusinessObject;
22  import org.kuali.rice.krad.bo.ExternalizableBusinessObject;
23  import org.kuali.rice.krad.service.KualiModuleService;
24  import org.kuali.rice.krad.service.ModuleService;
25  import org.kuali.rice.krad.service.PersistenceService;
26  import org.kuali.rice.krad.util.ExternalizableBusinessObjectUtils;
27  import org.kuali.rice.krad.util.ObjectUtils;
28  
29  import java.lang.reflect.Field;
30  import java.lang.reflect.InvocationTargetException;
31  import java.lang.reflect.Modifier;
32  import java.util.*;
33  
34  
35  
36  
37  
38  
39  public class PurApObjectUtils {
40      private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(PurApObjectUtils.class);
41  
42      
43  
44  
45  
46  
47  
48  
49  
50      public static void populateFromBaseClass(Class base, BusinessObject src, BusinessObject target, Map supplementalUncopyable) {
51          List<String> fieldNames = new ArrayList<String>();
52          Field[] fields = base.getDeclaredFields();
53  
54  
55          for (Field field : fields) {
56              if (!Modifier.isTransient(field.getModifiers())) {
57                  fieldNames.add(field.getName());
58              } else {
59                  if (LOG.isDebugEnabled()) {
60                      LOG.debug("field " + field.getName() + " is transient, skipping ");
61                  }
62              }
63          }
64          int counter = 0;
65          for (String fieldName : fieldNames) {
66              if ((isProcessableField(base, fieldName, PurapConstants.KNOWN_UNCOPYABLE_FIELDS)) && (isProcessableField(base, fieldName, supplementalUncopyable))) {
67                  attemptCopyOfFieldName(base.getName(), fieldName, src, target, supplementalUncopyable);
68                  counter++;
69              }
70          }
71          if (LOG.isDebugEnabled()) {
72              LOG.debug("Population complete for " + counter + " fields out of a total of " + fieldNames.size() + " potential fields in object with base class '" + base + "'");
73          }
74      }
75  
76      
77  
78  
79  
80  
81  
82  
83  
84      protected static boolean isProcessableField(Class baseClass, String fieldName, Map excludedFieldNames) {
85          if (excludedFieldNames.containsKey(fieldName)) {
86              Class potentialClassName = (Class) excludedFieldNames.get(fieldName);
87              if ((ObjectUtils.isNull(potentialClassName)) || (potentialClassName.equals(baseClass))) {
88                  return false;
89              }
90          }
91          return true;
92      }
93  
94      
95  
96  
97  
98  
99  
100 
101 
102 
103     protected static void attemptCopyOfFieldName(String baseClassName, String fieldName, BusinessObject sourceObject, BusinessObject targetObject, Map supplementalUncopyable) {
104         try {
105 
106             Object propertyValue = ObjectUtils.getPropertyValue(sourceObject, fieldName);
107             if ((ObjectUtils.isNotNull(propertyValue)) && (Collection.class.isAssignableFrom(propertyValue.getClass()))) {
108                 if (LOG.isDebugEnabled()) {
109                     LOG.debug("attempting to copy collection field '" + fieldName + "' using base class '" + baseClassName + "' and property value class '" + propertyValue.getClass() + "'");
110                 }
111                 copyCollection(fieldName, targetObject, (Collection) propertyValue, supplementalUncopyable);
112             } else {
113                 String propertyValueClass = (ObjectUtils.isNotNull(propertyValue)) ? propertyValue.getClass().toString() : "(null)";
114                 if (LOG.isDebugEnabled()) {
115                     LOG.debug("attempting to set field '" + fieldName + "' using base class '" + baseClassName + "' and property value class '" + propertyValueClass + "'");
116                 }
117                 ObjectUtils.setObjectProperty(targetObject, fieldName, propertyValue);
118             }
119         } catch (Exception e) {
120             
121             
122             
123             if (LOG.isDebugEnabled()) {
124                 LOG.debug("couldn't set field '" + fieldName + "' using base class '" + baseClassName + "' due to exception with class name '" + e.getClass().getName() + "'", e);
125             }
126         }
127     }
128 
129     
130 
131 
132 
133 
134 
135 
136 
137 
138 
139 
140 
141     protected static <T extends BusinessObject> void copyCollection(String fieldName, BusinessObject targetObject, Collection<T> sourceList, Map supplementalUncopyable) throws FormatException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
142         Collection listToSet = null;
143 
144         
145         if (ObjectUtils.isNotNull(sourceList)) {
146             ObjectUtils.materializeObjects(sourceList);
147         }
148 
149         
150 
151 
152         try {
153             listToSet = sourceList.getClass().newInstance();
154         } catch (Exception e) {
155             if (LOG.isDebugEnabled()) {
156                 LOG.debug("couldn't set class '" + sourceList.getClass() + "' on collection..." + fieldName + " using " + sourceList.getClass());
157             }
158             listToSet = new ArrayList<T>();
159         }
160 
161 
162         for (Iterator iterator = sourceList.iterator(); iterator.hasNext(); ) {
163             BusinessObject sourceCollectionObject = (BusinessObject) iterator.next();
164             if (LOG.isDebugEnabled()) {
165                 LOG.debug("attempting to copy collection member with class '" + sourceCollectionObject.getClass() + "'");
166             }
167             BusinessObject targetCollectionObject = (BusinessObject) createNewObjectFromClass(sourceCollectionObject.getClass());
168             populateFromBaseWithSuper(sourceCollectionObject, targetCollectionObject, supplementalUncopyable, new HashSet<Class>());
169             
170             Map pkMap = SpringContext.getBean(PersistenceService.class).getPrimaryKeyFieldValues(targetCollectionObject);
171             Set<String> pkFields = pkMap.keySet();
172             for (String field : pkFields) {
173                 ObjectUtils.setObjectProperty(targetCollectionObject, field, null);
174             }
175             listToSet.add(targetCollectionObject);
176         }
177         ObjectUtils.setObjectProperty(targetObject, fieldName, listToSet);
178     }
179 
180     
181 
182 
183 
184 
185 
186 
187 
188 
189     protected static Object createNewObjectFromClass(Class clazz) {
190         if (clazz == null) {
191             throw new RuntimeException("BO class was passed in as null");
192         }
193         try {
194             if (clazz.getSuperclass().equals(ExternalizableBusinessObject.class)) {
195                 Class eboInterface = ExternalizableBusinessObjectUtils.determineExternalizableBusinessObjectSubInterface(clazz);
196                 ModuleService moduleService = SpringContext.getBean(KualiModuleService.class).getResponsibleModuleService(eboInterface);
197                 return moduleService.createNewObjectFromExternalizableClass(eboInterface);
198             } else {
199                 return clazz.newInstance();
200             }
201         } catch (Exception e) {
202             throw new RuntimeException("Error occured while trying to create a new instance for class " + clazz);
203         }
204     }
205 
206     
207 
208 
209 
210 
211 
212 
213     public static void populateFromBaseClass(Class base, BusinessObject src, BusinessObject target) {
214         populateFromBaseClass(base, src, target, new HashMap());
215     }
216 
217     
218 
219 
220 
221 
222 
223 
224 
225 
226     public static void populateFromBaseWithSuper(BusinessObject sourceObject, BusinessObject targetObject, Map supplementalUncopyableFieldNames, Set<Class> classesToExclude) {
227         List<Class> classesToCopy = new ArrayList<Class>();
228         Class sourceObjectClass = sourceObject.getClass();
229         classesToCopy.add(sourceObjectClass);
230         while (sourceObjectClass.getSuperclass() != null) {
231             sourceObjectClass = sourceObjectClass.getSuperclass();
232             if (!classesToExclude.contains(sourceObjectClass)) {
233                 classesToCopy.add(sourceObjectClass);
234             }
235         }
236         for (int i = (classesToCopy.size() - 1); i >= 0; i--) {
237             Class temp = classesToCopy.get(i);
238             populateFromBaseClass(temp, sourceObject, targetObject, supplementalUncopyableFieldNames);
239         }
240     }
241 
242     
243 
244     
245 
246 
247 
248 
249 
250 
251     public static BusinessObject retrieveObjectWithIdentitcalKey(Collection controlList, BusinessObject bo) {
252         BusinessObject returnBo = null;
253 
254         for (Iterator i = controlList.iterator(); i.hasNext(); ) {
255             BusinessObject listBo = (BusinessObject) i.next();
256             if (equalByKeys(listBo, bo)) {
257                 returnBo = listBo;
258             }
259         }
260 
261         return returnBo;
262     }
263 
264     
265 
266 
267 
268 
269 
270 
271     public static boolean equalByKeys(BusinessObject bo1, BusinessObject bo2) {
272         boolean equal = true;
273 
274         if (bo1 == null && bo2 == null) {
275             equal = true;
276         } else if (bo1 == null || bo2 == null) {
277             equal = false;
278         } else if (!bo1.getClass().getName().equals(bo2.getClass().getName())) {
279             equal = false;
280         } else {
281             Map bo1Keys = SpringContext.getBean(PersistenceService.class).getPrimaryKeyFieldValues(bo1);
282             Map bo2Keys = SpringContext.getBean(PersistenceService.class).getPrimaryKeyFieldValues(bo2);
283             for (Iterator iter = bo1Keys.keySet().iterator(); iter.hasNext(); ) {
284                 String keyName = (String) iter.next();
285                 if (bo1Keys.get(keyName) != null && bo2Keys.get(keyName) != null) {
286                     if (!bo1Keys.get(keyName).toString().equals(bo2Keys.get(keyName).toString())) {
287                         equal = false;
288                     }
289                 } else {
290                     
291                     
292                     equal = false;
293                 }
294             }
295         }
296 
297 
298         return equal;
299     }
300     
301 }