1
2
3
4
5
6
7
8
9
10
11 package org.kuali.rice.krad.service.impl;
12
13 import java.util.ArrayList;
14 import java.util.HashMap;
15 import java.util.Iterator;
16 import java.util.List;
17 import java.util.Map;
18 import java.util.TreeMap;
19
20 import org.apache.commons.lang.StringUtils;
21 import org.kuali.rice.krad.bo.BusinessObject;
22 import org.kuali.rice.krad.bo.DataObjectRelationship;
23 import org.kuali.rice.krad.datadictionary.BusinessObjectEntry;
24 import org.kuali.rice.krad.datadictionary.DataDictionaryEntry;
25 import org.kuali.rice.krad.datadictionary.DataObjectEntry;
26 import org.kuali.rice.krad.datadictionary.PrimitiveAttributeDefinition;
27 import org.kuali.rice.krad.datadictionary.RelationshipDefinition;
28 import org.kuali.rice.krad.datadictionary.SupportAttributeDefinition;
29 import org.kuali.rice.krad.service.DataDictionaryService;
30 import org.kuali.rice.krad.service.DataObjectMetaDataService;
31 import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
32 import org.kuali.rice.krad.service.KualiModuleService;
33 import org.kuali.rice.krad.service.ModuleService;
34 import org.kuali.rice.krad.service.PersistenceStructureService;
35 import org.kuali.rice.krad.uif.service.ViewDictionaryService;
36 import org.kuali.rice.krad.uif.util.ObjectPropertyUtils;
37 import org.kuali.rice.krad.util.ObjectUtils;
38 import org.kuali.rice.krad.web.controller.UifControllerBase;
39 import org.springframework.beans.BeanWrapper;
40
41
42
43
44 public class DataObjectMetaDataServiceImpl implements DataObjectMetaDataService {
45
46 private DataDictionaryService dataDictionaryService;
47 private KualiModuleService kualiModuleService;
48 private PersistenceStructureService persistenceStructureService;
49 private ViewDictionaryService viewDictionaryService;
50
51
52
53
54 @Override
55 public List<String> listPrimaryKeyFieldNames(Class<?> clazz) {
56 if (persistenceStructureService.isPersistable(clazz)) {
57 return persistenceStructureService.listPrimaryKeyFieldNames(clazz);
58 }
59
60 ModuleService responsibleModuleService = getKualiModuleService().getResponsibleModuleService(clazz);
61 if (responsibleModuleService != null && responsibleModuleService.isExternalizable(clazz)) {
62 return responsibleModuleService.listPrimaryKeyFieldNames(clazz);
63 }
64
65
66 List<String> pks = dataDictionaryService.getDataDictionary().getDataObjectEntry(clazz.getName())
67 .getPrimaryKeys();
68 if (pks != null && !pks.isEmpty()) {
69 return pks;
70 }
71
72 return new ArrayList<String>();
73 }
74
75
76
77
78 @Override
79 public Map<String, ?> getPrimaryKeyFieldValues(Object dataObject) {
80 return getPrimaryKeyFieldValues(dataObject, false);
81 }
82
83
84
85
86
87 @Override
88 public Map<String, ?> getPrimaryKeyFieldValues(Object dataObject, boolean sortFieldNames) {
89 Map<String, Object> keyValueMap;
90
91 if (sortFieldNames) {
92 keyValueMap = new TreeMap<String, Object>();
93 } else {
94 keyValueMap = new HashMap<String, Object>();
95 }
96
97 BeanWrapper wrapper = ObjectPropertyUtils.wrapObject(dataObject);
98
99 List<String> fields = listPrimaryKeyFieldNames(dataObject.getClass());
100 for (String fieldName : fields) {
101 keyValueMap.put(fieldName, wrapper.getPropertyValue(fieldName));
102 }
103
104 return keyValueMap;
105 }
106
107
108
109
110
111 @Override
112 public boolean equalsByPrimaryKeys(Object do1, Object do2) {
113 boolean equal = true;
114
115 if (do1 == null && do2 == null) {
116 equal = true;
117 } else if (do1 == null || do2 == null) {
118 equal = false;
119 } else if (!do1.getClass().getName().equals(do2.getClass().getName())) {
120 equal = false;
121 } else {
122 Map<String, ?> do1Keys = getPrimaryKeyFieldValues(do1);
123 Map<String, ?> do2Keys = getPrimaryKeyFieldValues(do2);
124 for (Iterator<String> iter = do1Keys.keySet().iterator(); iter.hasNext(); ) {
125 String keyName = iter.next();
126 if (do1Keys.get(keyName) != null && do2Keys.get(keyName) != null) {
127 if (!do1Keys.get(keyName).toString().equals(do2Keys.get(keyName).toString())) {
128 equal = false;
129 }
130 } else {
131 equal = false;
132 }
133 }
134 }
135
136 return equal;
137 }
138
139
140
141
142
143
144 public DataObjectRelationship getDataObjectRelationship(Object dataObject, Class<?> dataObjectClass,
145 String attributeName, String attributePrefix, boolean keysOnly, boolean supportsLookup,
146 boolean supportsInquiry) {
147 RelationshipDefinition ddReference = getDictionaryRelationship(dataObjectClass, attributeName);
148
149 return getDataObjectRelationship(ddReference, dataObject, dataObjectClass, attributeName, attributePrefix,
150 keysOnly, supportsLookup, supportsInquiry);
151 }
152
153 protected DataObjectRelationship getDataObjectRelationship(RelationshipDefinition ddReference, Object dataObject,
154 Class<?> dataObjectClass, String attributeName, String attributePrefix, boolean keysOnly,
155 boolean supportsLookup, boolean supportsInquiry) {
156 DataObjectRelationship relationship = null;
157
158
159
160 if (ObjectUtils.isNestedAttribute(attributeName)) {
161 if (ddReference != null) {
162 if (classHasSupportedFeatures(ddReference.getTargetClass(), supportsLookup, supportsInquiry)) {
163 relationship = populateRelationshipFromDictionaryReference(dataObjectClass, ddReference,
164 attributePrefix, keysOnly);
165
166 return relationship;
167 }
168 }
169
170
171 String localPrefix = StringUtils.substringBefore(attributeName, ".");
172 String localAttributeName = StringUtils.substringAfter(attributeName, ".");
173 if (dataObject == null) {
174 dataObject = ObjectUtils.createNewObjectFromClass(dataObjectClass);
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 public RelationshipDefinition getDictionaryRelationship(Class<?> c, String attributeName) {
250 DataDictionaryEntry entryBase = getDataDictionaryService().getDataDictionary().getDictionaryObjectEntry(
251 c.getName());
252 if (entryBase == null) {
253 return null;
254 }
255
256 RelationshipDefinition relationship = null;
257
258 List<RelationshipDefinition> ddRelationships = entryBase.getRelationships();
259
260 int minKeys = Integer.MAX_VALUE;
261 for (RelationshipDefinition def : ddRelationships) {
262
263 if (def.getPrimitiveAttributes().size() == 1) {
264 for (PrimitiveAttributeDefinition primitive : def.getPrimitiveAttributes()) {
265 if (primitive.getSourceName().equals(attributeName) || def.getObjectAttributeName().equals(
266 attributeName)) {
267 relationship = def;
268 minKeys = 1;
269 break;
270 }
271 }
272 } else if (def.getPrimitiveAttributes().size() < minKeys) {
273 for (PrimitiveAttributeDefinition primitive : def.getPrimitiveAttributes()) {
274 if (primitive.getSourceName().equals(attributeName) || def.getObjectAttributeName().equals(
275 attributeName)) {
276 relationship = def;
277 minKeys = def.getPrimitiveAttributes().size();
278 break;
279 }
280 }
281 }
282 }
283
284
285 if (relationship == null) {
286 for (RelationshipDefinition def : ddRelationships) {
287 if (def.hasIdentifier()) {
288 if (def.getIdentifier().getSourceName().equals(attributeName)) {
289 relationship = def;
290 }
291 }
292 }
293 }
294
295 return relationship;
296 }
297
298 protected DataObjectRelationship populateRelationshipFromDictionaryReference(Class<?> dataObjectClass,
299 RelationshipDefinition ddReference, String attributePrefix, boolean keysOnly) {
300 DataObjectRelationship relationship = new DataObjectRelationship(dataObjectClass,
301 ddReference.getObjectAttributeName(), ddReference.getTargetClass());
302
303 for (PrimitiveAttributeDefinition def : ddReference.getPrimitiveAttributes()) {
304 if (StringUtils.isNotBlank(attributePrefix)) {
305 relationship.getParentToChildReferences().put(attributePrefix + "." + def.getSourceName(),
306 def.getTargetName());
307 } else {
308 relationship.getParentToChildReferences().put(def.getSourceName(), def.getTargetName());
309 }
310 }
311
312 if (!keysOnly) {
313 for (SupportAttributeDefinition def : ddReference.getSupportAttributes()) {
314 if (StringUtils.isNotBlank(attributePrefix)) {
315 relationship.getParentToChildReferences().put(attributePrefix + "." + def.getSourceName(),
316 def.getTargetName());
317 if (def.isIdentifier()) {
318 relationship.setUserVisibleIdentifierKey(attributePrefix + "." + def.getSourceName());
319 }
320 } else {
321 relationship.getParentToChildReferences().put(def.getSourceName(), def.getTargetName());
322 if (def.isIdentifier()) {
323 relationship.setUserVisibleIdentifierKey(def.getSourceName());
324 }
325 }
326 }
327 }
328
329 return relationship;
330 }
331
332 protected DataObjectRelationship getRelationshipMetadata(Class<?> dataObjectClass, String attributeName,
333 String attributePrefix) {
334
335 RelationshipDefinition relationshipDefinition = getDictionaryRelationship(dataObjectClass, attributeName);
336 if (relationshipDefinition == null) {
337 return null;
338 }
339
340 DataObjectRelationship dataObjectRelationship = new DataObjectRelationship(
341 relationshipDefinition.getSourceClass(), relationshipDefinition.getObjectAttributeName(),
342 relationshipDefinition.getTargetClass());
343
344 if (!StringUtils.isEmpty(attributePrefix)) {
345 attributePrefix += ".";
346 }
347
348 List<PrimitiveAttributeDefinition> primitives = relationshipDefinition.getPrimitiveAttributes();
349 for (PrimitiveAttributeDefinition primitiveAttributeDefinition : primitives) {
350 dataObjectRelationship.getParentToChildReferences().put(
351 attributePrefix + primitiveAttributeDefinition.getSourceName(),
352 primitiveAttributeDefinition.getTargetName());
353 }
354
355 return dataObjectRelationship;
356 }
357
358
359
360
361 @Override
362 public String getTitleAttribute(Class<?> dataObjectClass) {
363 String titleAttribute = null;
364
365 DataObjectEntry entry = getDataObjectEntry(dataObjectClass);
366 if (entry != null) {
367 titleAttribute = entry.getTitleAttribute();
368 }
369
370 return titleAttribute;
371 }
372
373
374
375
376 @Override
377 public boolean areNotesSupported(Class dataObjectClass) {
378 boolean hasNotesSupport = false;
379
380 DataObjectEntry entry = getDataObjectEntry(UifControllerBase.class);
381 if (entry != null) {
382 hasNotesSupport = entry.isBoNotesEnabled();
383 }
384
385 return hasNotesSupport;
386 }
387
388
389
390
391
392
393
394 protected DataObjectEntry getDataObjectEntry(Class<?> dataObjectClass) {
395 if (dataObjectClass == null) {
396 throw new IllegalArgumentException("invalid (null) dataObjectClass");
397 }
398
399 DataObjectEntry entry = getDataDictionaryService().getDataDictionary().getDataObjectEntry(
400 dataObjectClass.getName());
401
402 return entry;
403 }
404
405
406
407
408
409
410 protected BusinessObjectEntry getBusinessObjectEntry(Class businessObjectClass) {
411 validateBusinessObjectClass(businessObjectClass);
412
413 BusinessObjectEntry entry = getDataDictionaryService().getDataDictionary().getBusinessObjectEntry(
414 businessObjectClass.getName());
415 return entry;
416 }
417
418
419
420
421
422 protected void validateBusinessObjectClass(Class businessObjectClass) {
423 if (businessObjectClass == null) {
424 throw new IllegalArgumentException("invalid (null) dataObjectClass");
425 }
426 if (!BusinessObject.class.isAssignableFrom(businessObjectClass)) {
427 throw new IllegalArgumentException(
428 "class '" + businessObjectClass.getName() + "' is not a descendant of BusinessObject");
429 }
430 }
431
432
433
434
435
436
437 protected DataDictionaryService getDataDictionaryService() {
438 return this.dataDictionaryService;
439 }
440
441 public void setDataDictionaryService(DataDictionaryService dataDictionaryService) {
442 this.dataDictionaryService = dataDictionaryService;
443 }
444
445
446
447
448
449
450 protected KualiModuleService getKualiModuleService() {
451 return this.kualiModuleService;
452 }
453
454 public void setKualiModuleService(KualiModuleService kualiModuleService) {
455 this.kualiModuleService = kualiModuleService;
456 }
457
458
459
460
461
462
463
464 protected PersistenceStructureService getPersistenceStructureService() {
465 return this.persistenceStructureService;
466 }
467
468 public void setPersistenceStructureService(PersistenceStructureService persistenceStructureService) {
469 this.persistenceStructureService = persistenceStructureService;
470 }
471
472 protected ViewDictionaryService getViewDictionaryService() {
473 if (this.viewDictionaryService == null) {
474 this.viewDictionaryService = KRADServiceLocatorWeb.getViewDictionaryService();
475 }
476 return this.viewDictionaryService;
477 }
478
479 public void setViewDictionaryService(ViewDictionaryService viewDictionaryService) {
480 this.viewDictionaryService = viewDictionaryService;
481 }
482
483 }