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 java.lang.reflect.Field;
19 import java.lang.reflect.InvocationTargetException;
20 import java.util.ArrayList;
21 import java.util.Collection;
22 import java.util.Collections;
23 import java.util.Date;
24 import java.util.HashMap;
25 import java.util.Iterator;
26 import java.util.List;
27 import java.util.Map;
28 import java.util.TreeMap;
29 import java.util.UUID;
30 import java.util.concurrent.ConcurrentHashMap;
31 import java.util.concurrent.ConcurrentMap;
32 import java.util.regex.Matcher;
33 import java.util.regex.Pattern;
34
35 import org.apache.commons.lang.StringUtils;
36 import org.apache.commons.lang.reflect.FieldUtils;
37 import org.eclipse.persistence.indirection.ValueHolder;
38 import org.kuali.rice.core.api.config.property.ConfigurationService;
39 import org.kuali.rice.core.api.criteria.QueryByCriteria;
40 import org.kuali.rice.core.api.datetime.DateTimeService;
41 import org.kuali.rice.core.api.exception.RiceRuntimeException;
42 import org.kuali.rice.core.api.mo.common.GloballyUnique;
43 import org.kuali.rice.core.api.mo.common.Versioned;
44 import org.kuali.rice.core.api.search.SearchOperator;
45 import org.kuali.rice.core.api.uif.RemotableQuickFinder;
46 import org.kuali.rice.core.api.util.RiceKeyConstants;
47 import org.kuali.rice.core.framework.persistence.ojb.conversion.OjbCharBooleanConversion;
48 import org.kuali.rice.core.framework.persistence.platform.DatabasePlatform;
49 import org.kuali.rice.krad.bo.BusinessObject;
50 import org.kuali.rice.krad.bo.InactivatableFromTo;
51 import org.kuali.rice.krad.bo.PersistableBusinessObject;
52 import org.kuali.rice.krad.bo.PersistableBusinessObjectBaseAdapter;
53 import org.kuali.rice.krad.bo.PersistableBusinessObjectExtension;
54 import org.kuali.rice.krad.dao.DocumentDao;
55 import org.kuali.rice.krad.dao.LookupDao;
56 import org.kuali.rice.krad.dao.MaintenanceDocumentDao;
57 import org.kuali.rice.krad.data.DataObjectService;
58 import org.kuali.rice.krad.datadictionary.DataDictionaryEntry;
59 import org.kuali.rice.krad.datadictionary.DataObjectEntry;
60 import org.kuali.rice.krad.datadictionary.PrimitiveAttributeDefinition;
61 import org.kuali.rice.krad.datadictionary.RelationshipDefinition;
62 import org.kuali.rice.krad.datadictionary.SupportAttributeDefinition;
63 import org.kuali.rice.krad.document.Document;
64 import org.kuali.rice.krad.exception.ValidationException;
65 import org.kuali.rice.krad.lookup.LookupUtils;
66 import org.kuali.rice.krad.service.BusinessObjectService;
67 import org.kuali.rice.krad.service.DataDictionaryService;
68 import org.kuali.rice.krad.service.DataObjectMetaDataService;
69 import org.kuali.rice.krad.service.KRADServiceLocator;
70 import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
71 import org.kuali.rice.krad.service.KualiModuleService;
72 import org.kuali.rice.krad.service.LegacyDataAdapter;
73 import org.kuali.rice.krad.service.ModuleService;
74 import org.kuali.rice.krad.service.PersistenceService;
75 import org.kuali.rice.krad.service.PersistenceStructureService;
76 import org.kuali.rice.krad.uif.UifPropertyPaths;
77 import org.kuali.rice.krad.uif.service.ViewDictionaryService;
78 import org.kuali.rice.krad.uif.util.ObjectPropertyUtils;
79 import org.kuali.rice.krad.util.ForeignKeyFieldsPopulationState;
80 import org.kuali.rice.krad.util.GlobalVariables;
81 import org.kuali.rice.krad.util.KRADConstants;
82 import org.kuali.rice.krad.util.KRADPropertyConstants;
83 import org.kuali.rice.krad.util.KRADUtils;
84 import org.kuali.rice.krad.util.LegacyUtils;
85 import org.kuali.rice.krad.util.ObjectUtils;
86 import org.springframework.beans.PropertyAccessorUtils;
87 import org.springframework.beans.factory.annotation.Required;
88
89
90
91
92 @Deprecated
93 public class KNSLegacyDataAdapterImpl implements LegacyDataAdapter {
94 private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(
95 KNSLegacyDataAdapterImpl.class);
96
97 private static final Pattern VALUE_HOLDER_FIELD_PATTERN = Pattern.compile("^_persistence_(.*)_vh$");
98
99 private final ConcurrentMap<Class<?>, List<ValueHolderFieldPair>> valueHolderFieldCache =
100 new ConcurrentHashMap<Class<?>, List<ValueHolderFieldPair>>(8, 0.9f, 1);
101
102 private BusinessObjectService businessObjectService;
103 private PersistenceService persistenceService;
104 private LookupDao lookupDao;
105 private LookupCriteriaGenerator lookupCriteriaGenerator;
106 private DateTimeService dateTimeService;
107 private DatabasePlatform databasePlatform;
108
109 private DocumentDao documentDao;
110 private MaintenanceDocumentDao maintenanceDocumentDaoOjb;
111
112 private PersistenceStructureService persistenceStructureService;
113 private DataObjectMetaDataService dataObjectMetaDataService;
114 private ConfigurationService kualiConfigurationService;
115 private KualiModuleService kualiModuleService;
116 private DataDictionaryService dataDictionaryService;
117 private DataObjectService dataObjectService;
118 private ViewDictionaryService viewDictionaryService;
119
120 @Override
121 public <T> T save(T dataObject) {
122 if (dataObject instanceof Collection) {
123 Collection<Object> newList = new ArrayList<Object>(((Collection) dataObject).size());
124 for (Object obj : (Collection<?>) dataObject) {
125 newList.add(save(obj));
126 }
127 return (T) newList;
128 } else {
129 return (T) businessObjectService.save((PersistableBusinessObject) dataObject);
130 }
131 }
132
133 @Override
134 public <T> T linkAndSave(T dataObject) {
135 return (T) businessObjectService.linkAndSave((PersistableBusinessObject) dataObject);
136 }
137
138 @Override
139 public <T> T saveDocument(T document) {
140 return (T) documentDao.save((Document) document);
141 }
142
143 @Override
144 public <T> T findByPrimaryKey(Class<T> clazz, Map<String, ?> primaryKeys) {
145 return (T) businessObjectService.findByPrimaryKey((Class<BusinessObject>) clazz, primaryKeys);
146 }
147
148 @Override
149 public <T> T findBySinglePrimaryKey(Class<T> clazz, Object primaryKey) {
150 return (T) businessObjectService.findBySinglePrimaryKey((Class<BusinessObject>) clazz, primaryKey);
151 }
152
153 @Override
154 public void delete(Object dataObject) {
155 if (dataObject instanceof Collection) {
156 for (Object dobj : (Collection) dataObject) {
157 delete(dobj);
158 }
159 } else {
160 businessObjectService.delete(dataObject);
161 }
162 }
163
164 @Override
165 public void deleteMatching(Class<?> type, Map<String, ?> fieldValues) {
166 businessObjectService.deleteMatching(type, fieldValues);
167 }
168
169 @Override
170 public <T> T retrieve(T dataObject) {
171 return (T) businessObjectService.retrieve(dataObject);
172 }
173
174 @Override
175 public <T> Collection<T> findAll(Class<T> clazz) {
176
177 return findMatching(clazz, Collections.<String, Object>emptyMap());
178 }
179
180 @Override
181 public <T> Collection<T> findMatching(Class<T> clazz, Map<String, ?> fieldValues) {
182 return (Collection<T>) businessObjectService.findMatching((Class<BusinessObject>) clazz, fieldValues);
183 }
184
185 @Override
186 public <T> Collection<T> findMatchingOrderBy(Class<T> clazz, Map<String, ?> fieldValues, String sortField,
187 boolean sortAscending) {
188 return (Collection<T>) businessObjectService.findMatchingOrderBy((Class<BusinessObject>) clazz, fieldValues,
189 sortField, sortAscending);
190 }
191
192 @Override
193 public Map<String, ?> getPrimaryKeyFieldValues(Object dataObject) {
194 return persistenceService.getPrimaryKeyFieldValues(dataObject);
195 }
196
197 @Override
198 public void retrieveNonKeyFields(Object persistableObject) {
199 persistenceService.retrieveNonKeyFields(persistableObject);
200 synchronizeEclipseLinkWeavings(persistableObject);
201 }
202
203 @Override
204 public void retrieveReferenceObject(Object persistableObject, String referenceObjectName) {
205 persistenceService.retrieveReferenceObject(persistableObject, referenceObjectName);
206 synchronizeEclipseLinkWeavings(persistableObject, referenceObjectName);
207 }
208
209
210
211
212 protected void synchronizeEclipseLinkWeavings(Object persistableObject, String propertyName) {
213 if (LegacyUtils.isKradDataManaged(persistableObject.getClass())) {
214 List<ValueHolderFieldPair> fieldPairs = loadValueHolderFieldPairs(persistableObject.getClass());
215 for (ValueHolderFieldPair fieldPair : fieldPairs) {
216 if (fieldPair.field.getName().equals(propertyName)) {
217 fieldPair.synchronizeValueHolder(persistableObject);
218 }
219 }
220 }
221 }
222
223
224
225
226 protected void synchronizeEclipseLinkWeavings(Object persistableObject) {
227 if (LegacyUtils.isKradDataManaged(persistableObject.getClass())) {
228 List<ValueHolderFieldPair> fieldPairs = loadValueHolderFieldPairs(persistableObject.getClass());
229 for (ValueHolderFieldPair fieldPair : fieldPairs) {
230 fieldPair.synchronizeValueHolder(persistableObject);
231 }
232 }
233 }
234
235
236
237
238 private List<ValueHolderFieldPair> loadValueHolderFieldPairs(Class<?> type) {
239 if (valueHolderFieldCache.get(type) == null) {
240 List<ValueHolderFieldPair> pairs = new ArrayList<ValueHolderFieldPair>();
241 searchValueHolderFieldPairs(type, pairs);
242 valueHolderFieldCache.putIfAbsent(type, pairs);
243 }
244 return valueHolderFieldCache.get(type);
245 }
246
247
248
249
250 private void searchValueHolderFieldPairs(Class<?> type, List<ValueHolderFieldPair> pairs) {
251 if (type.equals(Object.class)) {
252 return;
253 }
254 for (Field valueHolderField : type.getDeclaredFields()) {
255 Matcher matcher = VALUE_HOLDER_FIELD_PATTERN.matcher(valueHolderField.getName());
256 if (matcher.matches()) {
257 valueHolderField.setAccessible(true);
258 String fieldName = matcher.group(1);
259 Field valueField = FieldUtils.getDeclaredField(type, fieldName, true);
260 if (valueField != null) {
261 pairs.add(new ValueHolderFieldPair(valueField, valueHolderField));
262 }
263 }
264 }
265 searchValueHolderFieldPairs(type.getSuperclass(), pairs);
266 }
267
268 @Override
269 public void refreshAllNonUpdatingReferences(Object persistableObject) {
270 persistenceService.refreshAllNonUpdatingReferences((PersistableBusinessObject) persistableObject);
271 synchronizeEclipseLinkWeavings(persistableObject);
272 }
273
274 @Override
275 public boolean isProxied(Object object) {
276 if (object == null || (!(object instanceof BusinessObject) && !(object instanceof PersistableBusinessObjectBaseAdapter))) {
277 return false;
278 }
279 return persistenceService.isProxied(object);
280 }
281
282 @Override
283 public Object resolveProxy(Object o) {
284 return persistenceService.resolveProxy(o);
285 }
286
287
288
289 @Override
290 public <T> Collection<T> findCollectionBySearchHelper(Class<T> dataObjectClass, Map<String, String> formProperties,
291 boolean unbounded, boolean allPrimaryKeyValuesPresentAndNotWildcard, Integer searchResultsLimit) {
292 return lookupDao.findCollectionBySearchHelper(dataObjectClass, formProperties, unbounded,
293 allPrimaryKeyValuesPresentAndNotWildcard, searchResultsLimit);
294 }
295
296
297 @Override
298 public <T> Collection<T> findCollectionBySearchHelper(Class<T> dataObjectClass, Map<String, String> formProperties,
299 List<String> wildcardAsLiteralPropertyNames, boolean unbounded,
300 boolean allPrimaryKeyValuesPresentAndNotWildcard, Integer searchResultsLimit) {
301 return lookupDao.findCollectionBySearchHelper(dataObjectClass, formProperties, unbounded,
302 allPrimaryKeyValuesPresentAndNotWildcard, searchResultsLimit);
303 }
304
305
306
307
308
309
310
311
312
313
314 protected <T> Collection<T> performDataObjectServiceLookup(Class<T> dataObjectClass,
315 Map<String, String> formProperties, boolean unbounded, boolean allPrimaryKeyValuesPresentAndNotWildcard,
316 Integer searchResultsLimit) {
317 if (!unbounded && searchResultsLimit == null) {
318
319
320 searchResultsLimit = org.kuali.rice.kns.lookup.LookupUtils.getSearchResultsLimit(dataObjectClass);
321 }
322 QueryByCriteria.Builder query = lookupCriteriaGenerator.generateCriteria(dataObjectClass, formProperties,
323 allPrimaryKeyValuesPresentAndNotWildcard);
324 if (!unbounded && searchResultsLimit != null) {
325 query.setMaxResults(searchResultsLimit);
326 }
327
328 Collection<T> results = dataObjectService.findMatching(dataObjectClass, query.build()).getResults();
329 return filterCurrentDataObjects(dataObjectClass, results, formProperties);
330 }
331
332 protected <T> Collection<T> filterCurrentDataObjects(Class<T> dataObjectClass, Collection<T> unfiltered,
333 Map<String, String> formProps) {
334 if (InactivatableFromTo.class.isAssignableFrom(dataObjectClass)) {
335 Boolean currentSpecifier = lookupCriteriaCurrentSpecifier(formProps);
336 if (currentSpecifier != null) {
337 List<InactivatableFromTo> onlyCurrent =
338 KRADServiceLocator.getInactivateableFromToService().filterOutNonCurrent(new ArrayList(
339 unfiltered), new Date(LookupUtils.getActiveDateTimestampForCriteria(formProps)
340 .getTime()));
341 if (currentSpecifier) {
342 return (Collection<T>) onlyCurrent;
343 } else {
344 unfiltered.removeAll(onlyCurrent);
345 return unfiltered;
346 }
347 }
348 }
349 return unfiltered;
350 }
351
352 protected Boolean lookupCriteriaCurrentSpecifier(Map<String, String> formProps) {
353 String value = formProps.get(KRADPropertyConstants.CURRENT);
354 if (StringUtils.isNotBlank(value)) {
355
356 String currentBooleanStr = (String) new OjbCharBooleanConversion().javaToSql(value);
357 if (OjbCharBooleanConversion.DATABASE_BOOLEAN_TRUE_STRING_REPRESENTATION.equals(currentBooleanStr)) {
358 return Boolean.TRUE;
359 } else if (OjbCharBooleanConversion.DATABASE_BOOLEAN_FALSE_STRING_REPRESENTATION.equals(
360 currentBooleanStr)) {
361 return Boolean.FALSE;
362 }
363 }
364 return null;
365 }
366
367 @Override
368 public <T> T findObjectBySearch(Class<T> type, Map<String, String> formProps) {
369 return lookupDao.findObjectByMap(type, formProps);
370 }
371
372
373
374
375
376
377
378
379 @Override
380 public boolean allPrimaryKeyValuesPresentAndNotWildcard(Class<?> boClass, Map<String, String> formProps) {
381 List<String> pkFields = listPrimaryKeyFieldNames(boClass);
382 Iterator<String> pkIter = pkFields.iterator();
383 boolean returnVal = true;
384 while (returnVal && pkIter.hasNext()) {
385 String pkName = pkIter.next();
386 String pkValue = formProps.get(pkName);
387
388 if (StringUtils.isBlank(pkValue)) {
389 returnVal = false;
390 } else {
391 for (SearchOperator op : SearchOperator.QUERY_CHARACTERS) {
392 if (pkValue.contains(op.op())) {
393 returnVal = false;
394 break;
395 }
396 }
397 }
398 }
399 return returnVal;
400 }
401
402 @SuppressWarnings("unchecked")
403 @Override
404 public List<String> listPrimaryKeyFieldNames(Class<?> type) {
405 List<String> keys = new ArrayList<String>();
406 if ( type == null ) {
407 return keys;
408 }
409 if (isPersistable(type)) {
410 keys = persistenceStructureService.listPrimaryKeyFieldNames(type);
411 } else {
412 ModuleService responsibleModuleService = kualiModuleService.getResponsibleModuleService(type);
413 if (responsibleModuleService != null && responsibleModuleService.isExternalizable(type)) {
414 keys = responsibleModuleService.listPrimaryKeyFieldNames(type);
415 } else {
416
417 DataObjectEntry dataObjectEntry = dataDictionaryService.getDataDictionary().getDataObjectEntry(type.getName());
418 if ( dataObjectEntry != null ) {
419 List<String> pks = dataObjectEntry.getPrimaryKeys();
420 if (pks != null ) {
421 keys = pks;
422 }
423 } else {
424 LOG.warn( "Unable to retrieve data object entry for non-persistable KNS-managed class: " + type.getName() );
425 }
426 }
427 }
428 return keys;
429 }
430
431
432
433
434
435
436
437
438
439
440
441
442
443 protected List<String> listPrimaryKeyFieldNamesConsultingAllServices(Class<?> type) {
444 return dataObjectMetaDataService.listPrimaryKeyFieldNames(type);
445 }
446
447 @Override
448 public Class<?> determineCollectionObjectType(Class<?> containingType, String collectionPropertyName) {
449 final Class<?> collectionObjectType;
450 if (isPersistable(containingType)) {
451 Map<String, Class> collectionClasses = new HashMap<String, Class>();
452 collectionClasses = persistenceStructureService.listCollectionObjectTypes(containingType);
453 collectionObjectType = collectionClasses.get(collectionPropertyName);
454 } else {
455 throw new RuntimeException(
456 "Can't determine the Class of Collection elements because persistenceStructureService.isPersistable("
457 + containingType.getName()
458 + ") returns false.");
459 }
460 return collectionObjectType;
461
462 }
463
464 @Override
465 public boolean hasReference(Class<?> boClass, String referenceName) {
466 return persistenceStructureService.hasReference(boClass, referenceName);
467 }
468
469 @Override
470 public boolean hasCollection(Class<?> boClass, String collectionName) {
471 return persistenceStructureService.hasCollection(boClass, collectionName);
472 }
473
474 @Override
475 public boolean isExtensionAttribute(Class<?> boClass, String attributePropertyName, Class<?> propertyType) {
476 return propertyType.equals(PersistableBusinessObjectExtension.class);
477 }
478
479 @Override
480 public Class<?> getExtensionAttributeClass(Class<?> boClass, String attributePropertyName) {
481 return persistenceStructureService.getBusinessObjectAttributeClass((Class<? extends PersistableBusinessObject>)boClass, attributePropertyName);
482 }
483
484
485 @Override
486 public Map<String, ?> getPrimaryKeyFieldValuesDOMDS(Object dataObject) {
487 return dataObjectMetaDataService.getPrimaryKeyFieldValues(dataObject);
488 }
489
490 @Override
491 public boolean equalsByPrimaryKeys(Object do1, Object do2) {
492 return dataObjectMetaDataService.equalsByPrimaryKeys(do1, do2);
493 }
494
495 @Override
496 public void materializeAllSubObjects(Object object) {
497 ObjectUtils.materializeAllSubObjects((PersistableBusinessObject) object);
498 }
499
500 @Override
501 public Class<?> getPropertyType(Object object, String propertyName) {
502 return ObjectUtils.getPropertyType(object, propertyName, persistenceStructureService);
503 }
504
505 @Override
506 public Object getExtension(
507 Class<?> businessObjectClass) throws InstantiationException, IllegalAccessException {
508 Class<? extends PersistableBusinessObjectExtension> extensionClass =
509 persistenceStructureService.getBusinessObjectAttributeClass((Class<? extends PersistableBusinessObject>) businessObjectClass, "extension");
510 if (extensionClass != null) {
511 return extensionClass.newInstance();
512 }
513 return null;
514 }
515
516 @Override
517 public void refreshReferenceObject(Object businessObject, String referenceObjectName) {
518 if (StringUtils.isNotBlank(referenceObjectName) && !StringUtils.equals(referenceObjectName, "extension")) {
519 if (persistenceStructureService.hasReference(businessObject.getClass(), referenceObjectName)
520 || persistenceStructureService.hasCollection(businessObject.getClass(), referenceObjectName)) {
521 retrieveReferenceObject(businessObject, referenceObjectName);
522 }
523 }
524 }
525
526 @Override
527 public boolean isLockable(Object object) {
528 return isPersistable(object.getClass());
529 }
530
531 @Override
532 public void verifyVersionNumber(Object dataObject) {
533 if (isPersistable(dataObject.getClass())) {
534 Object pbObject = businessObjectService.retrieve(dataObject);
535 if ( dataObject instanceof Versioned ) {
536 Long pbObjectVerNbr = KRADUtils.isNull(pbObject) ? null : ((Versioned) pbObject).getVersionNumber();
537 Long newObjectVerNbr = ((Versioned) dataObject).getVersionNumber();
538 if (pbObjectVerNbr != null && !(pbObjectVerNbr.equals(newObjectVerNbr))) {
539 GlobalVariables.getMessageMap().putError(KRADConstants.GLOBAL_ERRORS,
540 RiceKeyConstants.ERROR_VERSION_MISMATCH);
541 throw new ValidationException(
542 "Version mismatch between the local business object and the database business object");
543 }
544 }
545 }
546 }
547
548 @Override
549 public RemotableQuickFinder.Builder createQuickFinder(Class<?> containingClass, String attributeName) {
550 return createQuickFinderLegacy(containingClass, attributeName);
551 }
552
553
554
555
556 protected RemotableQuickFinder.Builder createQuickFinderLegacy(Class<?> containingClass, String attributeName) {
557 Object sampleComponent;
558 try {
559 sampleComponent = containingClass.newInstance();
560 } catch (InstantiationException e) {
561 throw new RiceRuntimeException(e);
562 } catch (IllegalAccessException e) {
563 throw new RiceRuntimeException(e);
564 }
565
566 String lookupClassName = null;
567 Map<String, String> fieldConversions = new HashMap<String, String>();
568 Map<String, String> lookupParameters = new HashMap<String, String>();
569
570 org.kuali.rice.krad.bo.DataObjectRelationship relationship =
571 getDataObjectRelationship(sampleComponent, containingClass, attributeName, "",
572 true, true, false);
573 if (relationship != null) {
574 lookupClassName = relationship.getRelatedClass().getName();
575
576 for (Map.Entry<String, String> entry : relationship.getParentToChildReferences().entrySet()) {
577 String fromField = entry.getValue();
578 String toField = entry.getKey();
579 fieldConversions.put(fromField, toField);
580 }
581
582 for (Map.Entry<String, String> entry : relationship.getParentToChildReferences().entrySet()) {
583 String fromField = entry.getKey();
584 String toField = entry.getValue();
585
586 if (relationship.getUserVisibleIdentifierKey() == null || relationship.getUserVisibleIdentifierKey()
587 .equals(fromField)) {
588 lookupParameters.put(fromField, toField);
589 }
590 }
591 } else {
592
593 String titleAttribute = dataObjectMetaDataService.getTitleAttribute(containingClass);
594 if (StringUtils.equals(titleAttribute, attributeName)) {
595 lookupClassName = containingClass.getName();
596
597 List<String> pkAttributes = dataObjectMetaDataService.listPrimaryKeyFieldNames(containingClass);
598 for (String pkAttribute : pkAttributes) {
599 fieldConversions.put(pkAttribute, pkAttribute);
600 if (!StringUtils.equals(pkAttribute, attributeName)) {
601 lookupParameters.put(pkAttribute, pkAttribute);
602 }
603 }
604 }
605 }
606
607 if (StringUtils.isNotBlank(lookupClassName)) {
608 String baseUrl = kualiConfigurationService.getPropertyValueAsString(KRADConstants.KRAD_LOOKUP_URL_KEY);
609 RemotableQuickFinder.Builder builder = RemotableQuickFinder.Builder.create(baseUrl, lookupClassName);
610 builder.setLookupParameters(lookupParameters);
611 builder.setFieldConversions(fieldConversions);
612
613 return builder;
614 }
615
616 return null;
617 }
618
619
620 @Override
621 public boolean isReferenceUpdatable(Class<?> type, String referenceName) {
622 return persistenceStructureService.isReferenceUpdatable(type, referenceName);
623 }
624
625 @SuppressWarnings("rawtypes")
626 @Override
627 public Map<String, Class> listReferenceObjectFields(Class<?> type) {
628 return persistenceStructureService.listReferenceObjectFields(type);
629 }
630
631 @Override
632 public boolean isCollectionUpdatable(Class<?> type, String collectionName) {
633 return persistenceStructureService.isCollectionUpdatable(type, collectionName);
634 }
635
636 @Override
637 public Map<String, Class> listCollectionObjectTypes(Class<?> type) {
638 return persistenceStructureService.listCollectionObjectTypes(type);
639 }
640
641 @Override
642 public BusinessObject getReferenceIfExists(Object bo, String referenceName) {
643 if (!(bo instanceof BusinessObject)) {
644 throw new UnsupportedOperationException("getReferenceIfExists only supports BusinessObject in KNS");
645 }
646
647 return businessObjectService.getReferenceIfExists((BusinessObject) bo, referenceName);
648 }
649
650 @Override
651 public boolean allForeignKeyValuesPopulatedForReference(Object bo, String referenceName) {
652 if (!(bo instanceof PersistableBusinessObject)) {
653 throw new UnsupportedOperationException(
654 "getReferenceIfExists only supports PersistableBusinessObject in KNS");
655 }
656
657 return persistenceService.allForeignKeyValuesPopulatedForReference((PersistableBusinessObject) bo,
658 referenceName);
659 }
660
661
662
663
664
665
666
667
668 @Override
669 public RelationshipDefinition getDictionaryRelationship(Class<?> c, String attributeName) {
670 DataDictionaryEntry entryBase =
671 KRADServiceLocatorWeb.getDataDictionaryService().getDataDictionary().getDictionaryObjectEntry(
672 c.getName());
673 if (entryBase == null) {
674 return null;
675 }
676
677 RelationshipDefinition relationship = null;
678
679 List<RelationshipDefinition> ddRelationships = entryBase.getRelationships();
680
681 int minKeys = Integer.MAX_VALUE;
682 for (RelationshipDefinition def : ddRelationships) {
683
684 if (def.getPrimitiveAttributes().size() == 1) {
685 for (PrimitiveAttributeDefinition primitive : def.getPrimitiveAttributes()) {
686 if (primitive.getSourceName().equals(attributeName) || def.getObjectAttributeName().equals(
687 attributeName)) {
688 relationship = def;
689 minKeys = 1;
690 break;
691 }
692 }
693 } else if (def.getPrimitiveAttributes().size() < minKeys) {
694 for (PrimitiveAttributeDefinition primitive : def.getPrimitiveAttributes()) {
695 if (primitive.getSourceName().equals(attributeName) || def.getObjectAttributeName().equals(
696 attributeName)) {
697 relationship = def;
698 minKeys = def.getPrimitiveAttributes().size();
699 break;
700 }
701 }
702 }
703 }
704
705
706 if (relationship == null) {
707 for (RelationshipDefinition def : ddRelationships) {
708 if (def.hasIdentifier()) {
709 if (def.getIdentifier().getSourceName().equals(attributeName)) {
710 relationship = def;
711 }
712 }
713 }
714 }
715
716 return relationship;
717 }
718
719
720
721
722 @Override
723 public String getTitleAttribute(Class<?> dataObjectClass) {
724 String titleAttribute = null;
725 DataObjectEntry entry = getDataObjectEntry(dataObjectClass);
726 if (entry != null) {
727 titleAttribute = entry.getTitleAttribute();
728 }
729 return titleAttribute;
730 }
731
732
733
734
735
736
737
738 protected DataObjectEntry getDataObjectEntry(Class<?> dataObjectClass) {
739 if (dataObjectClass == null) {
740 throw new IllegalArgumentException("invalid (null) dataObjectClass");
741 }
742
743 DataObjectEntry entry = dataDictionaryService.getDataDictionary().getDataObjectEntry(dataObjectClass.getName());
744
745 return entry;
746 }
747
748
749
750
751 @Override
752 public boolean areNotesSupported(Class<?> dataObjectClass) {
753 boolean hasNotesSupport = false;
754
755 DataObjectEntry entry = getDataObjectEntry(dataObjectClass);
756 if (entry != null) {
757 hasNotesSupport = entry.isBoNotesEnabled();
758 }
759
760 return hasNotesSupport;
761 }
762
763
764
765
766
767
768
769
770 public Map<String, ?> getPrimaryKeyFieldValues(Object dataObject, boolean sortFieldNames) {
771 Map<String, Object> keyFieldValues = (Map<String, Object>) getPrimaryKeyFieldValues(dataObject);
772 if (sortFieldNames) {
773 Map<String, Object> sortedKeyFieldValues = new TreeMap<String, Object>();
774 sortedKeyFieldValues.putAll(keyFieldValues);
775 return sortedKeyFieldValues;
776 }
777 return keyFieldValues;
778 }
779
780
781
782
783 @Override
784 public String getDataObjectIdentifierString(Object dataObject) {
785 String identifierString = "";
786
787 if (dataObject == null) {
788 identifierString = "Null";
789 return identifierString;
790 }
791
792 Class<?> dataObjectClass = dataObject.getClass();
793
794 if ((PersistableBusinessObject.class.isAssignableFrom(
795 dataObjectClass)) || (!LegacyUtils.useLegacyForObject(dataObject) && GloballyUnique.class
796 .isAssignableFrom(dataObjectClass))) {
797 String objectId = ObjectPropertyUtils.getPropertyValue(dataObject, UifPropertyPaths.OBJECT_ID);
798 if (StringUtils.isBlank(objectId)) {
799 objectId = UUID.randomUUID().toString();
800 ObjectPropertyUtils.setPropertyValue(dataObject, UifPropertyPaths.OBJECT_ID, objectId);
801 }
802 }
803 return identifierString;
804 }
805
806 @Override
807 public Class<?> getInquiryObjectClassIfNotTitle(Object dataObject, String propertyName) {
808 Class<?> objectClass = ObjectUtils.materializeClassForProxiedObject(dataObject);
809 org.kuali.rice.krad.bo.DataObjectRelationship relationship =
810 dataObjectMetaDataService.getDataObjectRelationship(dataObject, objectClass, propertyName, "", true,
811 false, true);
812 if (relationship != null) {
813 return relationship.getRelatedClass();
814 }
815 return null;
816 }
817
818 @Override
819 public Map<String, String> getInquiryParameters(Object dataObject, List<String> keys, String propertyName) {
820 Map<String, String> inquiryParameters = new HashMap<String, String>();
821 Class<?> objectClass = ObjectUtils.materializeClassForProxiedObject(dataObject);
822 org.kuali.rice.krad.bo.DataObjectRelationship relationship =
823 dataObjectMetaDataService.getDataObjectRelationship(dataObject, objectClass, propertyName, "", true,
824 false, true);
825 for (String keyName : keys) {
826 String keyConversion = keyName;
827 if (relationship != null) {
828 keyConversion = relationship.getParentAttributeForChildAttribute(keyName);
829 } else if (PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName)) {
830 String nestedAttributePrefix = KRADUtils.getNestedAttributePrefix(propertyName);
831 keyConversion = nestedAttributePrefix + "." + keyName;
832 }
833 inquiryParameters.put(keyConversion, keyName);
834 }
835 return inquiryParameters;
836 }
837
838 @Override
839 public boolean hasLocalLookup(Class<?> dataObjectClass) {
840 return dataObjectMetaDataService.hasLocalLookup(dataObjectClass);
841 }
842
843 @Override
844 public boolean hasLocalInquiry(Class<?> dataObjectClass) {
845 return dataObjectMetaDataService.hasLocalInquiry(dataObjectClass);
846 }
847
848 @Override
849 public org.kuali.rice.krad.bo.DataObjectRelationship getDataObjectRelationship(Object dataObject,
850 Class<?> dataObjectClass, String attributeName, String attributePrefix, boolean keysOnly,
851 boolean supportsLookup, boolean supportsInquiry) {
852 RelationshipDefinition ddReference = getDictionaryRelationship(dataObjectClass, attributeName);
853 return dataObjectMetaDataService.getDataObjectRelationship(dataObject, dataObjectClass, attributeName,
854 attributePrefix, keysOnly, supportsLookup, supportsInquiry);
855
856 }
857
858
859
860 protected org.kuali.rice.krad.bo.DataObjectRelationship populateRelationshipFromDictionaryReference(Class<?> dataObjectClass,
861 RelationshipDefinition ddReference, String attributePrefix, boolean keysOnly) {
862 org.kuali.rice.krad.bo.DataObjectRelationship relationship = new org.kuali.rice.krad.bo.DataObjectRelationship(dataObjectClass,
863 ddReference.getObjectAttributeName(), ddReference.getTargetClass());
864
865 for (PrimitiveAttributeDefinition def : ddReference.getPrimitiveAttributes()) {
866 if (StringUtils.isNotBlank(attributePrefix)) {
867 relationship.getParentToChildReferences().put(attributePrefix + "." + def.getSourceName(),
868 def.getTargetName());
869 } else {
870 relationship.getParentToChildReferences().put(def.getSourceName(), def.getTargetName());
871 }
872 }
873
874 if (!keysOnly) {
875 for (SupportAttributeDefinition def : ddReference.getSupportAttributes()) {
876 if (StringUtils.isNotBlank(attributePrefix)) {
877 relationship.getParentToChildReferences().put(attributePrefix + "." + def.getSourceName(),
878 def.getTargetName());
879 if (def.isIdentifier()) {
880 relationship.setUserVisibleIdentifierKey(attributePrefix + "." + def.getSourceName());
881 }
882 } else {
883 relationship.getParentToChildReferences().put(def.getSourceName(), def.getTargetName());
884 if (def.isIdentifier()) {
885 relationship.setUserVisibleIdentifierKey(def.getSourceName());
886 }
887 }
888 }
889 }
890
891 return relationship;
892 }
893
894 @Override
895 public boolean isPersistable(Class<?> dataObjectClass) {
896 return persistenceStructureService.isPersistable(dataObjectClass);
897 }
898
899 @Override
900 public void setObjectPropertyDeep(Object bo, String propertyName, Class type,
901 Object propertyValue) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
902 ObjectUtils.setObjectPropertyDeep(bo,propertyName,type,propertyValue);
903 }
904
905 protected org.kuali.rice.krad.bo.DataObjectRelationship getRelationshipMetadata(Class<?> dataObjectClass,
906 String attributeName, String attributePrefix) {
907
908 RelationshipDefinition relationshipDefinition = getDictionaryRelationship(dataObjectClass, attributeName);
909 if (relationshipDefinition == null) {
910 return null;
911 }
912
913 org.kuali.rice.krad.bo.DataObjectRelationship dataObjectRelationship =
914 new org.kuali.rice.krad.bo.DataObjectRelationship(relationshipDefinition.getSourceClass(),
915 relationshipDefinition.getObjectAttributeName(), relationshipDefinition.getTargetClass());
916
917 if (!StringUtils.isEmpty(attributePrefix)) {
918 attributePrefix += ".";
919 }
920
921 List<PrimitiveAttributeDefinition> primitives = relationshipDefinition.getPrimitiveAttributes();
922 for (PrimitiveAttributeDefinition primitiveAttributeDefinition : primitives) {
923 dataObjectRelationship.getParentToChildReferences().put(
924 attributePrefix + primitiveAttributeDefinition.getSourceName(),
925 primitiveAttributeDefinition.getTargetName());
926 }
927
928 return dataObjectRelationship;
929 }
930
931 protected boolean classHasSupportedFeatures(Class relationshipClass, boolean supportsLookup,
932 boolean supportsInquiry) {
933 boolean hasSupportedFeatures = true;
934 if (supportsLookup && !getViewDictionaryService().isLookupable(relationshipClass)) {
935 hasSupportedFeatures = false;
936 }
937 if (supportsInquiry && !getViewDictionaryService().isInquirable(relationshipClass)) {
938 hasSupportedFeatures = false;
939 }
940
941 return hasSupportedFeatures;
942 }
943
944 @Override
945 public boolean isNull(Object object){
946 return ObjectUtils.isNull(object);
947 }
948
949 @Override
950 public void setObjectProperty(Object bo, String propertyName, Class propertyType,
951 Object propertyValue) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException{
952 ObjectUtils.setObjectProperty(bo,propertyName,propertyType,propertyValue);
953 }
954
955 @Override
956 public Class materializeClassForProxiedObject(Object object){
957 return ObjectUtils.materializeClassForProxiedObject(object);
958 }
959
960 @Override
961 public Object getNestedValue(Object bo, String fieldName){
962 return ObjectUtils.getNestedValue(bo,fieldName);
963 }
964
965 @Override
966 public Object createNewObjectFromClass(Class clazz){
967 return ObjectUtils.createNewObjectFromClass(clazz);
968 }
969
970 @Override
971 public ForeignKeyFieldsPopulationState getForeignKeyFieldsPopulationState(Object dataObject, String referenceName) {
972 return persistenceStructureService.getForeignKeyFieldsPopulationState(
973 (PersistableBusinessObject) dataObject, referenceName);
974 }
975
976 @Override
977 public Map<String, String> getForeignKeysForReference(Class<?> clazz, String attributeName) {
978 return persistenceStructureService.getForeignKeysForReference(clazz, attributeName);
979 }
980
981 @Override
982 public boolean hasPrimaryKeyFieldValues(Object dataObject) {
983 return persistenceStructureService.hasPrimaryKeyFieldValues(dataObject);
984 }
985
986 @Override
987 public <T extends Document> T findByDocumentHeaderId(Class<T> documentClass, String id) {
988 return documentDao.findByDocumentHeaderId(documentClass, id);
989 }
990
991 @Override
992 public <T extends Document> List<T> findByDocumentHeaderIds(Class<T> documentClass, List<String> ids) {
993 return documentDao.findByDocumentHeaderIds(documentClass, ids);
994 }
995
996
997 @Required
998 public void setBusinessObjectService(BusinessObjectService businessObjectService) {
999 this.businessObjectService = businessObjectService;
1000 }
1001
1002 @Required
1003 public void setPersistenceService(PersistenceService persistenceService) {
1004 this.persistenceService = persistenceService;
1005 }
1006
1007 @Required
1008 public void setLookupDao(LookupDao lookupDao) {
1009 this.lookupDao = lookupDao;
1010 }
1011
1012 @Required
1013 public void setLookupCriteriaGenerator(LookupCriteriaGenerator lookupCriteriaGenerator) {
1014 this.lookupCriteriaGenerator = lookupCriteriaGenerator;
1015 }
1016
1017 @Required
1018 public void setDateTimeService(DateTimeService dts) {
1019 this.dateTimeService = dts;
1020 }
1021
1022 @Required
1023 public void setDatabasePlatform(DatabasePlatform databasePlatform) {
1024 this.databasePlatform = databasePlatform;
1025 }
1026
1027 @Required
1028 public void setMaintenanceDocumentDaoOjb(MaintenanceDocumentDao maintenanceDocumentDaoOjb) {
1029 this.maintenanceDocumentDaoOjb = maintenanceDocumentDaoOjb;
1030 }
1031
1032
1033
1034
1035
1036
1037 @Required
1038 public void setPersistenceStructureService(PersistenceStructureService persistenceStructureService) {
1039 this.persistenceStructureService = persistenceStructureService;
1040 }
1041
1042 @Required
1043 public void setDataObjectMetaDataService(DataObjectMetaDataService dataObjectMetaDataService) {
1044 this.dataObjectMetaDataService = dataObjectMetaDataService;
1045 }
1046
1047 @Required
1048 public void setKualiConfigurationService(ConfigurationService kualiConfigurationService) {
1049 this.kualiConfigurationService = kualiConfigurationService;
1050 }
1051
1052 @Required
1053 public void setKualiModuleService(KualiModuleService kualiModuleService) {
1054 this.kualiModuleService = kualiModuleService;
1055 }
1056
1057 @Required
1058 public void setDataDictionaryService(DataDictionaryService dataDictionaryService) {
1059 this.dataDictionaryService = dataDictionaryService;
1060 }
1061
1062 @Required
1063 public void setDocumentDao(DocumentDao documentDao) {
1064 this.documentDao = documentDao;
1065 }
1066
1067 public DataObjectService getDataObjectService() {
1068 return dataObjectService;
1069 }
1070
1071 public void setDataObjectService(DataObjectService dataObjectService) {
1072 this.dataObjectService = dataObjectService;
1073 }
1074
1075 public ViewDictionaryService getViewDictionaryService() {
1076 return viewDictionaryService;
1077 }
1078
1079 public void setViewDictionaryService(ViewDictionaryService viewDictionaryService) {
1080 this.viewDictionaryService = viewDictionaryService;
1081 }
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096 private static final class ValueHolderFieldPair {
1097
1098 final Field field;
1099 final Field valueHolderField;
1100
1101 ValueHolderFieldPair(Field field, Field valueHolderField) {
1102 this.field = field;
1103 this.valueHolderField = valueHolderField;
1104 }
1105
1106 void synchronizeValueHolder(Object object) {
1107 try {
1108 ValueHolder valueHolder = (ValueHolder)valueHolderField.get(object);
1109 if(valueHolder != null){
1110 Object value = field.get(object);
1111 valueHolder.setValue(value);
1112 }
1113 } catch (IllegalAccessException e) {
1114 throw new RuntimeException(e);
1115 }
1116 }
1117
1118 }
1119
1120 }