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