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.util.ArrayList;
19 import java.util.HashMap;
20 import java.util.Iterator;
21 import java.util.List;
22 import java.util.Map;
23 import java.util.TreeMap;
24 import java.util.UUID;
25
26 import org.apache.commons.lang.StringUtils;
27 import org.kuali.rice.krad.bo.BusinessObject;
28 import org.kuali.rice.krad.bo.DataObjectRelationship;
29 import org.kuali.rice.krad.bo.PersistableBusinessObject;
30 import org.kuali.rice.krad.datadictionary.BusinessObjectEntry;
31 import org.kuali.rice.krad.datadictionary.DataDictionaryEntry;
32 import org.kuali.rice.krad.datadictionary.DataObjectEntry;
33 import org.kuali.rice.krad.datadictionary.PrimitiveAttributeDefinition;
34 import org.kuali.rice.krad.datadictionary.RelationshipDefinition;
35 import org.kuali.rice.krad.datadictionary.SupportAttributeDefinition;
36 import org.kuali.rice.krad.service.DataDictionaryService;
37 import org.kuali.rice.krad.service.DataObjectMetaDataService;
38 import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
39 import org.kuali.rice.krad.service.KualiModuleService;
40 import org.kuali.rice.krad.service.ModuleService;
41 import org.kuali.rice.krad.service.PersistenceStructureService;
42 import org.kuali.rice.krad.uif.UifPropertyPaths;
43 import org.kuali.rice.krad.uif.service.ViewDictionaryService;
44 import org.kuali.rice.krad.uif.util.ObjectPropertyUtils;
45 import org.kuali.rice.krad.util.KRADUtils;
46 import org.kuali.rice.krad.util.LegacyDataFramework;
47 import org.springframework.beans.PropertyAccessorUtils;
48
49
50
51
52
53
54
55 @Deprecated
56 @LegacyDataFramework
57 public class DataObjectMetaDataServiceImpl implements DataObjectMetaDataService {
58 private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(
59 DataObjectMetaDataServiceImpl.class);
60
61 private DataDictionaryService dataDictionaryService;
62 private KualiModuleService kualiModuleService;
63 private PersistenceStructureService persistenceStructureService;
64 private ViewDictionaryService viewDictionaryService;
65
66 @Override
67 public List<String> listPrimaryKeyFieldNames(Class<?> clazz) {
68 if (persistenceStructureService.isPersistable(clazz)) {
69 return persistenceStructureService.listPrimaryKeyFieldNames(clazz);
70 }
71
72 ModuleService responsibleModuleService = getKualiModuleService().getResponsibleModuleService(clazz);
73 if (responsibleModuleService != null && responsibleModuleService.isExternalizable(clazz)) {
74 return responsibleModuleService.listPrimaryKeyFieldNames(clazz);
75 }
76
77
78 List<String> pks = dataDictionaryService.getDataDictionary().getDataObjectEntry(clazz.getName())
79 .getPrimaryKeys();
80 if (pks != null && !pks.isEmpty()) {
81 return pks;
82 }
83
84 return new ArrayList<String>();
85 }
86
87 @Override
88 public Map<String, ?> getPrimaryKeyFieldValues(Object dataObject) {
89 return getPrimaryKeyFieldValues(dataObject, false);
90 }
91
92 @Override
93 public Map<String, ?> getPrimaryKeyFieldValues(Object dataObject, boolean sortFieldNames) {
94 Map<String, Object> keyValueMap;
95
96 if (sortFieldNames) {
97 keyValueMap = new TreeMap<String, Object>();
98 } else {
99 keyValueMap = new HashMap<String, Object>();
100 }
101
102 List<String> fields = listPrimaryKeyFieldNames(dataObject.getClass());
103 for (String fieldName : fields) {
104 keyValueMap.put(fieldName, ObjectPropertyUtils.getPropertyValue(dataObject, fieldName));
105 }
106
107 return keyValueMap;
108 }
109
110 @Override
111 public boolean equalsByPrimaryKeys(Object do1, Object do2) {
112 boolean equal = true;
113
114 if (do1 == null && do2 == null) {
115 equal = true;
116 } else if (do1 == null || do2 == null) {
117 equal = false;
118 } else if (!do1.getClass().getName().equals(do2.getClass().getName())) {
119 equal = false;
120 } else {
121 Map<String, ?> do1Keys = getPrimaryKeyFieldValues(do1);
122 Map<String, ?> do2Keys = getPrimaryKeyFieldValues(do2);
123 for (Iterator<String> iter = do1Keys.keySet().iterator(); iter.hasNext(); ) {
124 String keyName = iter.next();
125 if (do1Keys.get(keyName) != null && do2Keys.get(keyName) != null) {
126 if (!do1Keys.get(keyName).toString().equals(do2Keys.get(keyName).toString())) {
127 equal = false;
128 }
129 } else {
130 equal = false;
131 }
132 }
133 }
134
135 return equal;
136 }
137
138 @Override
139 public DataObjectRelationship getDataObjectRelationship(Object dataObject, Class<?> dataObjectClass,
140 String attributeName, String attributePrefix, boolean keysOnly, boolean supportsLookup,
141 boolean supportsInquiry) {
142 RelationshipDefinition ddReference = getDictionaryRelationship(dataObjectClass, attributeName);
143
144 return getDataObjectRelationship(ddReference, dataObject, dataObjectClass, attributeName, attributePrefix,
145 keysOnly, supportsLookup, supportsInquiry);
146 }
147
148 protected DataObjectRelationship getDataObjectRelationship(RelationshipDefinition ddReference, Object dataObject,
149 Class<?> dataObjectClass, String attributeName, String attributePrefix, boolean keysOnly,
150 boolean supportsLookup, boolean supportsInquiry) {
151 DataObjectRelationship relationship = null;
152
153
154
155 if (PropertyAccessorUtils.isNestedOrIndexedProperty(attributeName)) {
156 if (ddReference != null) {
157 if (classHasSupportedFeatures(ddReference.getTargetClass(), supportsLookup, supportsInquiry)) {
158 relationship = populateRelationshipFromDictionaryReference(dataObjectClass, ddReference,
159 attributePrefix, keysOnly);
160
161 return relationship;
162 }
163 }
164
165
166 String localPrefix = StringUtils.substringBefore(attributeName, ".");
167 String localAttributeName = StringUtils.substringAfter(attributeName, ".");
168 if (dataObject == null) {
169 try {
170 dataObject = KRADUtils.createNewObjectFromClass(dataObjectClass);
171 } catch (RuntimeException e) {
172
173 return null;
174 }
175 }
176
177 Object nestedObject = ObjectPropertyUtils.getPropertyValue(dataObject, localPrefix);
178 Class<?> nestedClass = null;
179 if (nestedObject == null) {
180 nestedClass = ObjectPropertyUtils.getPropertyType(dataObject, localPrefix);
181 } else {
182 nestedClass = nestedObject.getClass();
183 }
184
185 String fullPrefix = localPrefix;
186 if (StringUtils.isNotBlank(attributePrefix)) {
187 fullPrefix = attributePrefix + "." + localPrefix;
188 }
189
190 relationship = getDataObjectRelationship(nestedObject, nestedClass, localAttributeName, fullPrefix,
191 keysOnly, supportsLookup, supportsInquiry);
192
193 return relationship;
194 }
195
196
197 int maxSize = Integer.MAX_VALUE;
198
199
200 if (getPersistenceStructureService().isPersistable(dataObjectClass)) {
201 Map<String, DataObjectRelationship> rels = getPersistenceStructureService().getRelationshipMetadata(
202 dataObjectClass, attributeName, attributePrefix);
203 if (rels.size() > 0) {
204 for (DataObjectRelationship rel : rels.values()) {
205 if (rel.getParentToChildReferences().size() < maxSize) {
206 if (classHasSupportedFeatures(rel.getRelatedClass(), supportsLookup, supportsInquiry)) {
207 maxSize = rel.getParentToChildReferences().size();
208 relationship = rel;
209 }
210 }
211 }
212 }
213 } else {
214 ModuleService moduleService = getKualiModuleService().getResponsibleModuleService(dataObjectClass);
215 if (moduleService != null && moduleService.isExternalizable(dataObjectClass)) {
216 relationship = getRelationshipMetadata(dataObjectClass, attributeName, attributePrefix);
217 if ((relationship != null) && classHasSupportedFeatures(relationship.getRelatedClass(), supportsLookup,
218 supportsInquiry)) {
219 return relationship;
220 } else {
221 return null;
222 }
223 }
224 }
225
226 if (ddReference != null && ddReference.getPrimitiveAttributes().size() < maxSize) {
227 if (classHasSupportedFeatures(ddReference.getTargetClass(), supportsLookup, supportsInquiry)) {
228 relationship = populateRelationshipFromDictionaryReference(dataObjectClass, ddReference, null,
229 keysOnly);
230 }
231 }
232
233 return relationship;
234 }
235
236 protected boolean classHasSupportedFeatures(Class relationshipClass, boolean supportsLookup,
237 boolean supportsInquiry) {
238 boolean hasSupportedFeatures = true;
239 if (supportsLookup && !getViewDictionaryService().isLookupable(relationshipClass)) {
240 hasSupportedFeatures = false;
241 }
242 if (supportsInquiry && !getViewDictionaryService().isInquirable(relationshipClass)) {
243 hasSupportedFeatures = false;
244 }
245
246 return hasSupportedFeatures;
247 }
248
249
250
251
252
253
254
255
256
257 @Override
258 public RelationshipDefinition getDictionaryRelationship(Class<?> c, String attributeName) {
259 DataDictionaryEntry entryBase = getDataDictionaryService().getDataDictionary().getDictionaryObjectEntry(
260 c.getName());
261 if (entryBase == null) {
262 return null;
263 }
264
265 RelationshipDefinition relationship = null;
266
267 List<RelationshipDefinition> ddRelationships = entryBase.getRelationships();
268
269 int minKeys = Integer.MAX_VALUE;
270 for (RelationshipDefinition def : ddRelationships) {
271
272 if (def.getPrimitiveAttributes().size() == 1) {
273 for (PrimitiveAttributeDefinition primitive : def.getPrimitiveAttributes()) {
274 if (primitive.getSourceName().equals(attributeName) || def.getObjectAttributeName().equals(
275 attributeName)) {
276 relationship = def;
277 minKeys = 1;
278 break;
279 }
280 }
281 } else if (def.getPrimitiveAttributes().size() < minKeys) {
282 for (PrimitiveAttributeDefinition primitive : def.getPrimitiveAttributes()) {
283 if (primitive.getSourceName().equals(attributeName) || def.getObjectAttributeName().equals(
284 attributeName)) {
285 relationship = def;
286 minKeys = def.getPrimitiveAttributes().size();
287 break;
288 }
289 }
290 }
291 }
292
293
294 if (relationship == null) {
295 for (RelationshipDefinition def : ddRelationships) {
296 if (def.hasIdentifier()) {
297 if (def.getIdentifier().getSourceName().equals(attributeName)) {
298 relationship = def;
299 }
300 }
301 }
302 }
303
304 return relationship;
305 }
306
307 protected DataObjectRelationship populateRelationshipFromDictionaryReference(Class<?> dataObjectClass,
308 RelationshipDefinition ddReference, String attributePrefix, boolean keysOnly) {
309 DataObjectRelationship relationship = new DataObjectRelationship(dataObjectClass,
310 ddReference.getObjectAttributeName(), ddReference.getTargetClass());
311
312 for (PrimitiveAttributeDefinition def : ddReference.getPrimitiveAttributes()) {
313 if (StringUtils.isNotBlank(attributePrefix)) {
314 relationship.getParentToChildReferences().put(attributePrefix + "." + def.getSourceName(),
315 def.getTargetName());
316 } else {
317 relationship.getParentToChildReferences().put(def.getSourceName(), def.getTargetName());
318 }
319 }
320
321 if (!keysOnly) {
322 for (SupportAttributeDefinition def : ddReference.getSupportAttributes()) {
323 if (StringUtils.isNotBlank(attributePrefix)) {
324 relationship.getParentToChildReferences().put(attributePrefix + "." + def.getSourceName(),
325 def.getTargetName());
326 if (def.isIdentifier()) {
327 relationship.setUserVisibleIdentifierKey(attributePrefix + "." + def.getSourceName());
328 }
329 } else {
330 relationship.getParentToChildReferences().put(def.getSourceName(), def.getTargetName());
331 if (def.isIdentifier()) {
332 relationship.setUserVisibleIdentifierKey(def.getSourceName());
333 }
334 }
335 }
336 }
337
338 return relationship;
339 }
340
341 protected DataObjectRelationship getRelationshipMetadata(Class<?> dataObjectClass, String attributeName,
342 String attributePrefix) {
343
344 RelationshipDefinition relationshipDefinition = getDictionaryRelationship(dataObjectClass, attributeName);
345 if (relationshipDefinition == null) {
346 return null;
347 }
348
349 DataObjectRelationship dataObjectRelationship = new DataObjectRelationship(
350 relationshipDefinition.getSourceClass(), relationshipDefinition.getObjectAttributeName(),
351 relationshipDefinition.getTargetClass());
352
353 if (!StringUtils.isEmpty(attributePrefix)) {
354 attributePrefix += ".";
355 }
356
357 List<PrimitiveAttributeDefinition> primitives = relationshipDefinition.getPrimitiveAttributes();
358 for (PrimitiveAttributeDefinition primitiveAttributeDefinition : primitives) {
359 dataObjectRelationship.getParentToChildReferences().put(
360 attributePrefix + primitiveAttributeDefinition.getSourceName(),
361 primitiveAttributeDefinition.getTargetName());
362 }
363
364 return dataObjectRelationship;
365 }
366
367
368
369
370 @Override
371 public String getTitleAttribute(Class<?> dataObjectClass) {
372 String titleAttribute = null;
373
374 DataObjectEntry entry = getDataObjectEntry(dataObjectClass);
375 if (entry != null) {
376 titleAttribute = entry.getTitleAttribute();
377 }
378
379 return titleAttribute;
380 }
381
382
383
384
385 @Override
386 public boolean areNotesSupported(Class<?> dataObjectClass) {
387 boolean hasNotesSupport = false;
388
389 DataObjectEntry entry = getDataObjectEntry(dataObjectClass);
390 if (entry != null) {
391 hasNotesSupport = entry.isBoNotesEnabled();
392 }
393
394 return hasNotesSupport;
395 }
396
397
398
399
400 @Override
401 public String getDataObjectIdentifierString(Object dataObject) {
402 String identifierString = "";
403
404 if (dataObject == null) {
405 identifierString = "Null";
406 return identifierString;
407 }
408
409 Class<?> dataObjectClass = dataObject.getClass();
410
411
412 if (PersistableBusinessObject.class.isAssignableFrom(dataObjectClass)) {
413 String objectId = ObjectPropertyUtils.getPropertyValue(dataObject, UifPropertyPaths.OBJECT_ID);
414 if (StringUtils.isBlank(objectId)) {
415 objectId = UUID.randomUUID().toString();
416 ObjectPropertyUtils.setPropertyValue(dataObject, UifPropertyPaths.OBJECT_ID, objectId);
417 }
418
419 identifierString = objectId;
420 } else {
421
422 Map<String, ?> primaryKeyFieldValues = getPrimaryKeyFieldValues(dataObject, true);
423 for (Map.Entry<String, ?> primaryKeyValue : primaryKeyFieldValues.entrySet()) {
424 if (primaryKeyValue.getValue() == null) {
425 identifierString += "Null";
426 } else {
427 identifierString += primaryKeyValue.getValue();
428 }
429 identifierString += ":";
430 }
431 identifierString = StringUtils.removeEnd(identifierString, ":");
432 }
433
434 return identifierString;
435 }
436
437
438
439
440
441
442
443 protected DataObjectEntry getDataObjectEntry(Class<?> dataObjectClass) {
444 if (dataObjectClass == null) {
445 throw new IllegalArgumentException("invalid (null) dataObjectClass");
446 }
447
448 DataObjectEntry entry = getDataDictionaryService().getDataDictionary().getDataObjectEntry(
449 dataObjectClass.getName());
450
451 return entry;
452 }
453
454 @Override
455 public List<DataObjectRelationship> getDataObjectRelationships(Class<?> dataObjectClass) {
456 if (dataObjectClass == null) {
457 return null;
458 }
459
460 Map<String, Class> referenceClasses = null;
461 if (PersistableBusinessObject.class.isAssignableFrom(dataObjectClass)
462 && getPersistenceStructureService().isPersistable(dataObjectClass)) {
463 referenceClasses = getPersistenceStructureService().listReferenceObjectFields(dataObjectClass);
464 }
465 DataDictionaryEntry ddEntry = getDataDictionaryService().getDataDictionary().getDictionaryObjectEntry(
466 dataObjectClass.getName());
467 List<RelationshipDefinition> ddRelationships = (ddEntry == null ? new ArrayList<RelationshipDefinition>()
468 : ddEntry.getRelationships());
469 List<DataObjectRelationship> relationships = new ArrayList<DataObjectRelationship>();
470
471
472 if (referenceClasses != null) {
473 for (Map.Entry<String, Class> entry : referenceClasses.entrySet()) {
474 if (classHasSupportedFeatures(entry.getValue(), true, false)) {
475 Map<String, String> fkToPkRefs = getPersistenceStructureService().getForeignKeysForReference(dataObjectClass,
476 entry.getKey());
477 DataObjectRelationship rel = new DataObjectRelationship(dataObjectClass, entry.getKey(),
478 entry.getValue());
479 for (Map.Entry<String, String> ref : fkToPkRefs.entrySet()) {
480 rel.getParentToChildReferences().put(ref.getKey(), ref.getValue());
481 }
482 relationships.add(rel);
483 }
484 }
485 }
486
487 for (RelationshipDefinition rd : ddRelationships) {
488 if (classHasSupportedFeatures(rd.getTargetClass(), true, false)) {
489 DataObjectRelationship rel = new DataObjectRelationship(dataObjectClass, rd.getObjectAttributeName(),
490 rd.getTargetClass());
491 for (PrimitiveAttributeDefinition def : rd.getPrimitiveAttributes()) {
492 rel.getParentToChildReferences().put(def.getSourceName(), def.getTargetName());
493 }
494 relationships.add(rel);
495 }
496 }
497
498 return relationships;
499 }
500
501
502
503
504 @Override
505 public boolean hasLocalLookup(Class<?> dataObjectClass) {
506 return viewDictionaryService.isLookupable(dataObjectClass);
507 }
508
509
510
511
512 @Override
513 public boolean hasLocalInquiry(Class<?> dataObjectClass) {
514 return viewDictionaryService.isInquirable(dataObjectClass);
515 }
516
517
518
519
520
521
522 protected BusinessObjectEntry getBusinessObjectEntry(Class businessObjectClass) {
523 validateBusinessObjectClass(businessObjectClass);
524
525 BusinessObjectEntry entry = getDataDictionaryService().getDataDictionary().getBusinessObjectEntry(
526 businessObjectClass.getName());
527 return entry;
528 }
529
530
531
532
533
534 protected void validateBusinessObjectClass(Class businessObjectClass) {
535 if (businessObjectClass == null) {
536 throw new IllegalArgumentException("invalid (null) dataObjectClass");
537 }
538 if (!BusinessObject.class.isAssignableFrom(businessObjectClass)) {
539 throw new IllegalArgumentException(
540 "class '" + businessObjectClass.getName() + "' is not a descendant of BusinessObject");
541 }
542 }
543
544 protected DataDictionaryService getDataDictionaryService() {
545 return this.dataDictionaryService;
546 }
547
548 public void setDataDictionaryService(DataDictionaryService dataDictionaryService) {
549 this.dataDictionaryService = dataDictionaryService;
550 }
551
552 protected KualiModuleService getKualiModuleService() {
553 return this.kualiModuleService;
554 }
555
556 public void setKualiModuleService(KualiModuleService kualiModuleService) {
557 this.kualiModuleService = kualiModuleService;
558 }
559
560 protected PersistenceStructureService getPersistenceStructureService() {
561 return this.persistenceStructureService;
562 }
563
564 public void setPersistenceStructureService(PersistenceStructureService persistenceStructureService) {
565 this.persistenceStructureService = persistenceStructureService;
566 }
567
568 protected ViewDictionaryService getViewDictionaryService() {
569 if (this.viewDictionaryService == null) {
570 this.viewDictionaryService = KRADServiceLocatorWeb.getViewDictionaryService();
571 }
572 return this.viewDictionaryService;
573 }
574
575 public void setViewDictionaryService(ViewDictionaryService viewDictionaryService) {
576 this.viewDictionaryService = viewDictionaryService;
577 }
578
579 }