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.BusinessObjectRelationship;
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.springframework.beans.BeanWrapper;
39
40
41
42
43 public class DataObjectMetaDataServiceImpl implements DataObjectMetaDataService {
44
45 private DataDictionaryService dataDictionaryService;
46 private KualiModuleService kualiModuleService;
47 private PersistenceStructureService persistenceStructureService;
48 private ViewDictionaryService viewDictionaryService;
49
50
51
52
53 @Override
54 public List<String> listPrimaryKeyFieldNames(Class<?> clazz) {
55 if (persistenceStructureService.isPersistable(clazz)) {
56 return persistenceStructureService.listPrimaryKeyFieldNames(clazz);
57 }
58
59 ModuleService responsibleModuleService = getKualiModuleService().getResponsibleModuleService(clazz);
60 if (responsibleModuleService != null && responsibleModuleService.isExternalizable(clazz))
61 return responsibleModuleService.listPrimaryKeyFieldNames(clazz);
62
63
64 List<String> pks = dataDictionaryService.getDataDictionary().getDataObjectEntry(clazz.getName())
65 .getPrimaryKeys();
66 if (pks != null && !pks.isEmpty())
67 return pks;
68
69 return new ArrayList<String>();
70 }
71
72
73
74
75 @Override
76 public Map<String, ?> getPrimaryKeyFieldValues(Object dataObject) {
77 return getPrimaryKeyFieldValues(dataObject, false);
78 }
79
80
81
82
83
84 @Override
85 public Map<String, ?> getPrimaryKeyFieldValues(Object dataObject, boolean sortFieldNames) {
86 Map<String, Object> keyValueMap;
87
88 if (sortFieldNames) {
89 keyValueMap = new TreeMap<String, Object>();
90 } else {
91 keyValueMap = new HashMap<String, Object>();
92 }
93
94 BeanWrapper wrapper = ObjectPropertyUtils.wrapObject(dataObject);
95
96 List<String> fields = listPrimaryKeyFieldNames(dataObject.getClass());
97 for (String fieldName : fields) {
98 keyValueMap.put(fieldName, wrapper.getPropertyValue(fieldName));
99 }
100
101 return keyValueMap;
102 }
103
104
105
106
107
108 @Override
109 public boolean equalsByPrimaryKeys(Object do1, Object do2) {
110 boolean equal = true;
111
112 if (do1 == null && do2 == null) {
113 equal = true;
114 } else if (do1 == null || do2 == null) {
115 equal = false;
116 } else if (!do1.getClass().getName().equals(do2.getClass().getName())) {
117 equal = false;
118 } else {
119 Map<String, ?> do1Keys = getPrimaryKeyFieldValues(do1);
120 Map<String, ?> do2Keys = getPrimaryKeyFieldValues(do2);
121 for (Iterator<String> iter = do1Keys.keySet().iterator(); iter.hasNext();) {
122 String keyName = iter.next();
123 if (do1Keys.get(keyName) != null && do2Keys.get(keyName) != null) {
124 if (!do1Keys.get(keyName).toString().equals(do2Keys.get(keyName).toString())) {
125 equal = false;
126 }
127 } else {
128 equal = false;
129 }
130 }
131 }
132
133 return equal;
134 }
135
136
137
138
139
140
141 public BusinessObjectRelationship getDataObjectRelationship(Object dataObject, Class<?> dataObjectClass,
142 String attributeName, String attributePrefix, boolean keysOnly, boolean supportsLookup,
143 boolean supportsInquiry) {
144 RelationshipDefinition ddReference = getDictionaryRelationship(dataObjectClass, attributeName);
145
146 return getDataObjectRelationship(ddReference, dataObject, dataObjectClass, attributeName, attributePrefix,
147 keysOnly, supportsLookup, supportsInquiry);
148 }
149
150 protected BusinessObjectRelationship getDataObjectRelationship(RelationshipDefinition ddReference,
151 Object dataObject, Class<?> dataObjectClass, String attributeName, String attributePrefix,
152 boolean keysOnly, boolean supportsLookup, boolean supportsInquiry) {
153 BusinessObjectRelationship relationship = null;
154
155
156
157 if (ObjectUtils.isNestedAttribute(attributeName)) {
158 if (ddReference != null) {
159 if ((supportsLookup && getViewDictionaryService().isLookupable(ddReference.getTargetClass()))
160 || (supportsInquiry && getViewDictionaryService().isInquirable(ddReference.getTargetClass()))) {
161 relationship = populateRelationshipFromDictionaryReference(dataObjectClass, ddReference,
162 attributePrefix, keysOnly);
163
164 return relationship;
165 }
166 }
167
168
169 String localPrefix = StringUtils.substringBefore(attributeName, ".");
170 String localAttributeName = StringUtils.substringAfter(attributeName, ".");
171 if (dataObject == null) {
172 dataObject = ObjectUtils.createNewObjectFromClass(dataObjectClass);
173 }
174
175 Object nestedObject = ObjectPropertyUtils.getPropertyValue(dataObject, localPrefix);
176 Class<?> nestedClass = null;
177 if (nestedObject == null) {
178 nestedClass = ObjectPropertyUtils.getPropertyType(dataObject, localPrefix);
179 }
180 else {
181 nestedClass = nestedObject.getClass();
182 }
183
184 String fullPrefix = localPrefix;
185 if (StringUtils.isNotBlank(attributePrefix)) {
186 fullPrefix = attributePrefix + "." + localPrefix;
187 }
188
189 relationship = getDataObjectRelationship(nestedObject, nestedClass, localAttributeName, fullPrefix, keysOnly,
190 supportsLookup, supportsInquiry);
191
192 return relationship;
193 }
194
195
196 int maxSize = Integer.MAX_VALUE;
197
198
199 if (getPersistenceStructureService().isPersistable(dataObjectClass)) {
200 Map<String, BusinessObjectRelationship> rels = getPersistenceStructureService().getRelationshipMetadata(
201 dataObjectClass, attributeName, attributePrefix);
202 if (rels.size() > 0) {
203 for (BusinessObjectRelationship rel : rels.values()) {
204 if (rel.getParentToChildReferences().size() < maxSize) {
205 if ((supportsLookup && getViewDictionaryService().isLookupable(rel.getRelatedClass()))
206 || (supportsInquiry && getViewDictionaryService().isInquirable(rel.getRelatedClass()))) {
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) {
218 return relationship;
219 }
220 }
221 }
222
223 if (ddReference != null && ddReference.getPrimitiveAttributes().size() < maxSize) {
224 if ((supportsLookup && getViewDictionaryService().isLookupable(ddReference.getTargetClass()))
225 || (supportsInquiry && getViewDictionaryService().isInquirable(ddReference.getTargetClass()))) {
226 relationship = populateRelationshipFromDictionaryReference(dataObjectClass, ddReference, null, keysOnly);
227 }
228 }
229
230 return relationship;
231 }
232
233 public RelationshipDefinition getDictionaryRelationship(Class<?> c, String attributeName) {
234 DataDictionaryEntry entryBase = getDataDictionaryService().getDataDictionary().getDictionaryObjectEntry(
235 c.getName());
236 if (entryBase == null) {
237 return null;
238 }
239
240 RelationshipDefinition relationship = null;
241
242 List<RelationshipDefinition> ddRelationships = entryBase.getRelationships();
243
244 int minKeys = Integer.MAX_VALUE;
245 for (RelationshipDefinition def : ddRelationships) {
246
247 if (def.getPrimitiveAttributes().size() == 1) {
248 for (PrimitiveAttributeDefinition primitive : def.getPrimitiveAttributes()) {
249 if (primitive.getSourceName().equals(attributeName)
250 || def.getObjectAttributeName().equals(attributeName)) {
251 relationship = def;
252 minKeys = 1;
253 break;
254 }
255 }
256 } else if (def.getPrimitiveAttributes().size() < minKeys) {
257 for (PrimitiveAttributeDefinition primitive : def.getPrimitiveAttributes()) {
258 if (primitive.getSourceName().equals(attributeName)
259 || def.getObjectAttributeName().equals(attributeName)) {
260 relationship = def;
261 minKeys = def.getPrimitiveAttributes().size();
262 break;
263 }
264 }
265 }
266 }
267
268 if (relationship == null) {
269 for (RelationshipDefinition def : ddRelationships) {
270 if (def.hasIdentifier()) {
271 if (def.getIdentifier().getSourceName().equals(attributeName)) {
272 relationship = def;
273 }
274 }
275 }
276 }
277
278 return relationship;
279 }
280
281 protected BusinessObjectRelationship populateRelationshipFromDictionaryReference(Class<?> dataObjectClass,
282 RelationshipDefinition ddReference, String attributePrefix, boolean keysOnly) {
283 BusinessObjectRelationship relationship = new BusinessObjectRelationship(dataObjectClass,
284 ddReference.getObjectAttributeName(), ddReference.getTargetClass());
285
286 for (PrimitiveAttributeDefinition def : ddReference.getPrimitiveAttributes()) {
287 if (StringUtils.isNotBlank(attributePrefix)) {
288 relationship.getParentToChildReferences().put(attributePrefix + "." + def.getSourceName(),
289 def.getTargetName());
290 } else {
291 relationship.getParentToChildReferences().put(def.getSourceName(), def.getTargetName());
292 }
293 }
294
295 if (!keysOnly) {
296 for (SupportAttributeDefinition def : ddReference.getSupportAttributes()) {
297 if (StringUtils.isNotBlank(attributePrefix)) {
298 relationship.getParentToChildReferences().put(attributePrefix + "." + def.getSourceName(),
299 def.getTargetName());
300 if (def.isIdentifier()) {
301 relationship.setUserVisibleIdentifierKey(attributePrefix + "." + def.getSourceName());
302 }
303 } else {
304 relationship.getParentToChildReferences().put(def.getSourceName(), def.getTargetName());
305 if (def.isIdentifier()) {
306 relationship.setUserVisibleIdentifierKey(def.getSourceName());
307 }
308 }
309 }
310 }
311
312 return relationship;
313 }
314
315 protected BusinessObjectRelationship getRelationshipMetadata(Class<?> dataObjectClass, String attributeName,
316 String attributePrefix) {
317
318 RelationshipDefinition relationshipDefinition = getDictionaryRelationship(dataObjectClass, attributeName);
319 if (relationshipDefinition == null) {
320 return null;
321 }
322
323 BusinessObjectRelationship businessObjectRelationship = new BusinessObjectRelationship(
324 relationshipDefinition.getSourceClass(), relationshipDefinition.getObjectAttributeName(),
325 relationshipDefinition.getTargetClass());
326
327 if (!StringUtils.isEmpty(attributePrefix)) {
328 attributePrefix += ".";
329 }
330
331 List<PrimitiveAttributeDefinition> primitives = relationshipDefinition.getPrimitiveAttributes();
332 for (PrimitiveAttributeDefinition primitiveAttributeDefinition : primitives) {
333 businessObjectRelationship.getParentToChildReferences().put(
334 attributePrefix + primitiveAttributeDefinition.getSourceName(),
335 primitiveAttributeDefinition.getTargetName());
336 }
337
338 return businessObjectRelationship;
339 }
340
341
342
343
344 @Override
345 public String getTitleAttribute(Class<?> dataObjectClass) {
346 String titleAttribute = null;
347
348 DataObjectEntry entry = getDataObjectEntry(dataObjectClass);
349 if (entry != null) {
350 titleAttribute = entry.getTitleAttribute();
351 }
352
353 return titleAttribute;
354 }
355
356
357
358
359 @Override
360 public boolean areNotesSupported(Class dataObjectClass) {
361 boolean hasNotesSupport = false;
362
363 if (BusinessObject.class.isAssignableFrom(dataObjectClass)) {
364 BusinessObjectEntry entry = getBusinessObjectEntry(dataObjectClass);
365 if (entry != null) {
366 hasNotesSupport = entry.isBoNotesEnabled();
367 }
368 }
369
370 return hasNotesSupport;
371 }
372
373
374
375
376
377
378
379
380 protected DataObjectEntry getDataObjectEntry(Class<?> dataObjectClass) {
381 if (dataObjectClass == null) {
382 throw new IllegalArgumentException("invalid (null) dataObjectClass");
383 }
384
385 DataObjectEntry entry = getDataDictionaryService().getDataDictionary()
386 .getDataObjectEntry(dataObjectClass.getName());
387
388 return entry;
389 }
390
391
392
393
394
395
396 protected BusinessObjectEntry getBusinessObjectEntry(Class businessObjectClass) {
397 validateBusinessObjectClass(businessObjectClass);
398
399 BusinessObjectEntry entry =
400 getDataDictionaryService().getDataDictionary().getBusinessObjectEntry(businessObjectClass.getName());
401 return entry;
402 }
403
404
405
406
407
408 protected void validateBusinessObjectClass(Class businessObjectClass) {
409 if (businessObjectClass == null) {
410 throw new IllegalArgumentException("invalid (null) dataObjectClass");
411 }
412 if (!BusinessObject.class.isAssignableFrom(businessObjectClass)) {
413 throw new IllegalArgumentException(
414 "class '" + businessObjectClass.getName() + "' is not a descendant of BusinessObject");
415 }
416 }
417
418
419
420
421
422
423 protected DataDictionaryService getDataDictionaryService() {
424 return this.dataDictionaryService;
425 }
426
427 public void setDataDictionaryService(DataDictionaryService dataDictionaryService) {
428 this.dataDictionaryService = dataDictionaryService;
429 }
430
431
432
433
434
435
436 protected KualiModuleService getKualiModuleService() {
437 return this.kualiModuleService;
438 }
439
440 public void setKualiModuleService(KualiModuleService kualiModuleService) {
441 this.kualiModuleService = kualiModuleService;
442 }
443
444
445
446
447
448
449
450 protected PersistenceStructureService getPersistenceStructureService() {
451 return this.persistenceStructureService;
452 }
453
454 public void setPersistenceStructureService(PersistenceStructureService persistenceStructureService) {
455 this.persistenceStructureService = persistenceStructureService;
456 }
457
458 protected ViewDictionaryService getViewDictionaryService() {
459 if (this.viewDictionaryService == null) {
460 this.viewDictionaryService = KRADServiceLocatorWeb.getViewDictionaryService();
461 }
462 return this.viewDictionaryService;
463 }
464
465 public void setViewDictionaryService(ViewDictionaryService viewDictionaryService) {
466 this.viewDictionaryService = viewDictionaryService;
467 }
468
469 }