1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.krad.service.impl;
17
18 import org.apache.commons.beanutils.PropertyUtils;
19 import org.apache.commons.lang.StringUtils;
20 import org.apache.log4j.Logger;
21 import org.apache.ojb.broker.metadata.ClassDescriptor;
22 import org.apache.ojb.broker.metadata.ConnectionRepository;
23 import org.apache.ojb.broker.metadata.DescriptorRepository;
24 import org.apache.ojb.broker.metadata.FieldDescriptor;
25 import org.apache.ojb.broker.metadata.MetadataManager;
26 import org.apache.ojb.broker.metadata.ObjectReferenceDescriptor;
27 import org.apache.ojb.broker.metadata.fieldaccess.PersistentField;
28 import org.kuali.rice.core.api.exception.RiceRuntimeException;
29 import org.kuali.rice.core.api.util.ClassLoaderUtils;
30 import org.kuali.rice.krad.bo.PersistableBusinessObject;
31 import org.kuali.rice.krad.dao.PersistenceDao;
32 import org.kuali.rice.krad.exception.IntrospectionException;
33 import org.kuali.rice.krad.exception.ObjectNotABusinessObjectRuntimeException;
34 import org.kuali.rice.krad.exception.ReferenceAttributeDoesntExistException;
35 import org.kuali.rice.krad.exception.ReferenceAttributeNotAnOjbReferenceException;
36 import org.kuali.rice.krad.service.PersistenceService;
37 import org.kuali.rice.krad.util.ObjectUtils;
38 import org.springframework.core.io.DefaultResourceLoader;
39 import org.springframework.transaction.annotation.Transactional;
40
41 import java.beans.PropertyDescriptor;
42 import java.io.IOException;
43 import java.io.InputStream;
44 import java.lang.reflect.InvocationTargetException;
45 import java.util.HashMap;
46 import java.util.HashSet;
47 import java.util.Iterator;
48 import java.util.List;
49 import java.util.Map;
50 import java.util.Set;
51 import java.util.Vector;
52
53
54
55
56
57
58
59 @Transactional
60 public class PersistenceServiceOjbImpl extends PersistenceServiceImplBase implements PersistenceService {
61 private static Logger LOG = Logger.getLogger(PersistenceServiceOjbImpl.class);
62 private static final String CLASSPATH_RESOURCE_PREFIX = "classpath:";
63 private PersistenceDao persistenceDao;
64
65 public void clearCache() {
66 persistenceDao.clearCache();
67 }
68
69 public Object resolveProxy(Object o) {
70 return persistenceDao.resolveProxy(o);
71 }
72
73 public void loadRepositoryDescriptor(String ojbRepositoryFilePath) {
74 if ( LOG.isInfoEnabled() ) {
75 LOG.info("Begin loading OJB Metadata for: " + ojbRepositoryFilePath);
76 }
77 DefaultResourceLoader resourceLoader = new DefaultResourceLoader(ClassLoaderUtils.getDefaultClassLoader());
78 InputStream is = null;
79 try {
80 is = resourceLoader.getResource(CLASSPATH_RESOURCE_PREFIX + ojbRepositoryFilePath).getInputStream();
81 ConnectionRepository cr = MetadataManager.getInstance().readConnectionRepository(is);
82 MetadataManager.getInstance().mergeConnectionRepository(cr);
83
84 is = resourceLoader.getResource(CLASSPATH_RESOURCE_PREFIX + ojbRepositoryFilePath).getInputStream();
85 DescriptorRepository dr = MetadataManager.getInstance().readDescriptorRepository(is);
86 MetadataManager.getInstance().mergeDescriptorRepository(dr);
87
88 if (LOG.isDebugEnabled()) {
89 LOG.debug("--------------------------------------------------------------------------");
90 LOG.debug("Merging repository descriptor: " + ojbRepositoryFilePath);
91 LOG.debug("--------------------------------------------------------------------------");
92 }
93 } catch (IOException ioe) {
94 if (is != null) {
95 try {
96 is.close();
97 } catch (IOException e) {
98 LOG.warn("Failed to close InputStream on OJB repository path " + ojbRepositoryFilePath, e);
99 }
100 }
101 throw new RiceRuntimeException(ioe);
102 } finally {
103 if (is != null) {
104 try {
105 is.close();
106 } catch (IOException e) {
107 LOG.warn("Failed to close InputStream on OJB repository path " + ojbRepositoryFilePath, e);
108 }
109 }
110 }
111 if ( LOG.isInfoEnabled() ) {
112 LOG.info("Finished loading OJB Metadata for: " + ojbRepositoryFilePath);
113 }
114 }
115
116
117
118
119 public void retrieveNonKeyFields(Object persistableObject) {
120 if (persistableObject == null) {
121 throw new IllegalArgumentException("invalid (null) persistableObject");
122 }
123 if ( LOG.isDebugEnabled() ) {
124 LOG.debug("retrieving non-key fields for " + persistableObject);
125 }
126
127 persistenceDao.retrieveAllReferences(persistableObject);
128 }
129
130
131
132
133
134 public void retrieveReferenceObject(Object persistableObject, String referenceObjectName) {
135 if (persistableObject == null) {
136 throw new IllegalArgumentException("invalid (null) persistableObject");
137 }
138 if ( LOG.isDebugEnabled() ) {
139 LOG.debug("retrieving reference object " + referenceObjectName + " for " + persistableObject);
140 }
141 persistenceDao.retrieveReference(persistableObject, referenceObjectName);
142 }
143
144
145
146
147
148 public void retrieveReferenceObjects(Object persistableObject, List referenceObjectNames) {
149 if (persistableObject == null) {
150 throw new IllegalArgumentException("invalid (null) persistableObject");
151 }
152 if (referenceObjectNames == null) {
153 throw new IllegalArgumentException("invalid (null) referenceObjectNames");
154 }
155 if (referenceObjectNames.isEmpty()) {
156 throw new IllegalArgumentException("invalid (empty) referenceObjectNames");
157 }
158
159 int index = 0;
160 for (Iterator i = referenceObjectNames.iterator(); i.hasNext(); index++) {
161 String referenceObjectName = (String) i.next();
162 if (StringUtils.isBlank(referenceObjectName)) {
163 throw new IllegalArgumentException("invalid (blank) name at position " + index);
164 }
165
166 retrieveReferenceObject(persistableObject, referenceObjectName);
167 }
168 }
169
170
171
172
173
174 public void retrieveReferenceObjects(List persistableObjects, List referenceObjectNames) {
175 if (persistableObjects == null) {
176 throw new IllegalArgumentException("invalid (null) persistableObjects");
177 }
178 if (persistableObjects.isEmpty()) {
179 throw new IllegalArgumentException("invalid (empty) persistableObjects");
180 }
181 if (referenceObjectNames == null) {
182 throw new IllegalArgumentException("invalid (null) referenceObjectNames");
183 }
184 if (referenceObjectNames.isEmpty()) {
185 throw new IllegalArgumentException("invalid (empty) referenceObjectNames");
186 }
187
188 for (Iterator i = persistableObjects.iterator(); i.hasNext();) {
189 Object persistableObject = i.next();
190 retrieveReferenceObjects(persistableObject, referenceObjectNames);
191 }
192 }
193
194
195
196
197
198 public String getFlattenedPrimaryKeyFieldValues(Object persistableObject) {
199 if (persistableObject == null) {
200 throw new IllegalArgumentException("invalid (null) persistableObject");
201 }
202 Map primaryKeyValues = getPrimaryKeyFieldValues(persistableObject, true);
203
204 StringBuffer flattened = new StringBuffer(persistableObject.getClass().getName());
205 flattened.append("(");
206 for (Iterator i = primaryKeyValues.entrySet().iterator(); i.hasNext();) {
207 Map.Entry e = (Map.Entry) i.next();
208
209 String fieldName = (String) e.getKey();
210 Object fieldValue = e.getValue();
211
212 flattened.append(fieldName + "=" + fieldValue);
213 if (i.hasNext()) {
214 flattened.append(",");
215 }
216 }
217
218 flattened.append(")");
219
220 return flattened.toString();
221
222 }
223
224 private void linkObjectsWithCircularReferenceCheck(Object persistableObject, Set referenceSet) {
225 if (ObjectUtils.isNull(persistableObject) || referenceSet.contains(persistableObject)) {
226 return;
227 }
228 referenceSet.add(persistableObject);
229 ClassDescriptor classDescriptor = getClassDescriptor(persistableObject.getClass());
230
231 String className = null;
232 String fieldName = null;
233 try {
234
235 Vector objectReferences = classDescriptor.getObjectReferenceDescriptors();
236 for (Iterator iter = objectReferences.iterator(); iter.hasNext();) {
237 ObjectReferenceDescriptor referenceDescriptor = (ObjectReferenceDescriptor) iter.next();
238
239
240 className = persistableObject.getClass().getName();
241 fieldName = referenceDescriptor.getAttributeName();
242 Object referenceObject = PropertyUtils.getProperty(persistableObject, fieldName);
243 if (ObjectUtils.isNull(referenceObject) || referenceSet.contains(referenceObject)) {
244 continue;
245 }
246
247
248 linkObjectsWithCircularReferenceCheck(referenceObject, referenceSet);
249
250
251
252 FieldDescriptor[] refFkNames = referenceDescriptor.getForeignKeyFieldDescriptors(classDescriptor);
253 ClassDescriptor refCld = getClassDescriptor(referenceDescriptor.getItemClass());
254 FieldDescriptor[] refPkNames = refCld.getPkFields();
255
256 Map objFkValues = new HashMap();
257 for (int i = 0; i < refPkNames.length; i++) {
258 objFkValues.put(refFkNames[i].getAttributeName(), ObjectUtils.getPropertyValue(referenceObject, refPkNames[i].getAttributeName()));
259 }
260
261 for (int i = 0; i < refFkNames.length; i++) {
262 FieldDescriptor fkField = refFkNames[i];
263 String fkName = fkField.getAttributeName();
264
265
266
267 Object fkValue = null;
268 if (objFkValues.containsKey(fkName)) {
269 fkValue = objFkValues.get(fkName);
270 }
271
272
273 Object mainFkValue = ObjectUtils.getPropertyValue(persistableObject, fkName);
274 if (ObjectUtils.isNotNull(mainFkValue) && StringUtils.isNotBlank(mainFkValue.toString())) {
275 fkValue = mainFkValue;
276 } else if (ObjectUtils.isNull(fkValue) || StringUtils.isBlank(fkValue.toString())) {
277
278
279 for (Iterator iter2 = objectReferences.iterator(); iter2.hasNext();) {
280 ObjectReferenceDescriptor checkDescriptor = (ObjectReferenceDescriptor) iter2.next();
281
282 fkValue = getReferenceFKValue(persistableObject, checkDescriptor, fkName);
283 if (ObjectUtils.isNotNull(fkValue) && StringUtils.isNotBlank(fkValue.toString())) {
284 break;
285 }
286 }
287 }
288
289
290 if (ObjectUtils.isNotNull(fkValue)) {
291 fieldName = refPkNames[i].getAttributeName();
292 ObjectUtils.setObjectProperty(referenceObject, fieldName, fkValue.getClass(), fkValue);
293
294
295 if (ObjectUtils.isNull(mainFkValue)) {
296 ObjectUtils.setObjectProperty(persistableObject, fkName, fkValue.getClass(), fkValue);
297 }
298 }
299 }
300 }
301 } catch (NoSuchMethodException e) {
302 throw new IntrospectionException("no setter for property '" + className + "." + fieldName + "'", e);
303 } catch (IllegalAccessException e) {
304 throw new IntrospectionException("problem accessing property '" + className + "." + fieldName + "'", e);
305 } catch (InvocationTargetException e) {
306 throw new IntrospectionException("problem invoking getter for property '" + className + "." + fieldName + "'", e);
307 }
308 }
309
310
311
312
313
314
315
316
317
318
319
320
321 public void linkObjects(Object persistableObject) {
322 linkObjectsWithCircularReferenceCheck(persistableObject, new HashSet());
323 }
324
325
326
327
328
329
330 public boolean allForeignKeyValuesPopulatedForReference(PersistableBusinessObject bo, String referenceName) {
331
332 boolean allFkeysHaveValues = true;
333
334
335 if (bo == null) {
336 throw new IllegalArgumentException("The Class passed in for the BusinessObject argument was null.");
337 }
338 if (StringUtils.isBlank(referenceName)) {
339 throw new IllegalArgumentException("The String passed in for the referenceName argument was null or empty.");
340 }
341
342 PropertyDescriptor propertyDescriptor = null;
343
344
345 try {
346 propertyDescriptor = PropertyUtils.getPropertyDescriptor(bo, referenceName);
347 } catch (Exception e) {
348 throw new RuntimeException(e);
349 }
350 if (propertyDescriptor == null) {
351 throw new ReferenceAttributeDoesntExistException("Requested attribute: '" + referenceName + "' does not exist " + "on class: '" + bo.getClass().getName() + "'.");
352 }
353
354
355 Class referenceClass = getBusinessObjectAttributeClass( bo.getClass(), referenceName );
356 if ( referenceClass == null ) {
357 referenceClass = propertyDescriptor.getPropertyType();
358 }
359
360
361
362 if (!PersistableBusinessObject.class.isAssignableFrom(referenceClass)) {
363 throw new ObjectNotABusinessObjectRuntimeException("Attribute requested (" + referenceName + ") is of class: " + "'" + referenceClass.getName() + "' and is not a " + "descendent of BusinessObject. Only descendents of BusinessObject "
364 + "can be used.");
365 }
366
367
368
369
370 ClassDescriptor classDescriptor = getClassDescriptor(bo.getClass());
371 ObjectReferenceDescriptor referenceDescriptor = classDescriptor.getObjectReferenceDescriptorByName(referenceName);
372 if (referenceDescriptor == null) {
373 throw new ReferenceAttributeNotAnOjbReferenceException("Attribute requested (" + referenceName + ") is not listed " + "in OJB as a reference-descriptor for class: '" + bo.getClass().getName() + "'");
374 }
375
376
377
378 Vector fkFields = referenceDescriptor.getForeignKeyFields();
379 Iterator fkIterator = fkFields.iterator();
380
381
382 while (fkIterator.hasNext()) {
383
384
385 String fkFieldName = (String) fkIterator.next();
386
387
388 Object fkFieldValue = null;
389 try {
390 fkFieldValue = PropertyUtils.getSimpleProperty(bo, fkFieldName);
391 }
392
393
394
395 catch (IllegalAccessException e) {
396 return false;
397 } catch (InvocationTargetException e) {
398 return false;
399 } catch (NoSuchMethodException e) {
400 return false;
401 }
402
403
404 if (fkFieldValue == null) {
405 return false;
406 } else if (String.class.isAssignableFrom(fkFieldValue.getClass())) {
407 if (StringUtils.isBlank((String) fkFieldValue)) {
408 return false;
409 }
410 }
411 }
412
413 return allFkeysHaveValues;
414 }
415
416
417
418
419
420 public void refreshAllNonUpdatingReferences(PersistableBusinessObject bo) {
421
422
423 ClassDescriptor classDescriptor = getClassDescriptor(bo.getClass());
424
425
426 Vector references = classDescriptor.getObjectReferenceDescriptors();
427
428
429 for (Iterator iter = references.iterator(); iter.hasNext();) {
430 ObjectReferenceDescriptor reference = (ObjectReferenceDescriptor) iter.next();
431
432
433 if (reference.getCascadingStore() == ObjectReferenceDescriptor.CASCADE_NONE) {
434 PersistentField persistentField = reference.getPersistentField();
435 String referenceName = persistentField.getName();
436 retrieveReferenceObject(bo, referenceName);
437 }
438 }
439 }
440
441 private Object getReferenceFKValue(Object persistableObject, ObjectReferenceDescriptor chkRefCld, String fkName) {
442 ClassDescriptor classDescriptor = getClassDescriptor(persistableObject.getClass());
443 Object referenceObject = ObjectUtils.getPropertyValue(persistableObject, chkRefCld.getAttributeName());
444
445 if (referenceObject == null) {
446 return null;
447 }
448
449 FieldDescriptor[] refFkNames = chkRefCld.getForeignKeyFieldDescriptors(classDescriptor);
450 ClassDescriptor refCld = getClassDescriptor(chkRefCld.getItemClass());
451 FieldDescriptor[] refPkNames = refCld.getPkFields();
452
453
454 Object fkValue = null;
455 for (int i = 0; i < refFkNames.length; i++) {
456 FieldDescriptor fkField = refFkNames[i];
457
458 if (fkField.getAttributeName().equals(fkName)) {
459 fkValue = ObjectUtils.getPropertyValue(referenceObject, refPkNames[i].getAttributeName());
460 break;
461 }
462 }
463
464 return fkValue;
465 }
466
467
468
469
470
471
472 public boolean isProxied(Object object) {
473 return persistenceDao.isProxied(object);
474 }
475
476
477
478
479
480
481
482 public void setPersistenceDao(PersistenceDao persistenceDao) {
483 this.persistenceDao = persistenceDao;
484 }
485 }