1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.kns.workflow.attribute;
17
18 import org.apache.commons.collections.CollectionUtils;
19 import org.apache.commons.lang.StringUtils;
20 import org.apache.log4j.Logger;
21 import org.kuali.rice.core.api.CoreApiServiceLocator;
22 import org.kuali.rice.core.api.config.property.ConfigurationService;
23 import org.kuali.rice.core.api.uif.RemotableAttributeError;
24 import org.kuali.rice.core.api.uif.RemotableAttributeField;
25 import org.kuali.rice.core.api.util.io.SerializationUtils;
26 import org.kuali.rice.kew.api.KewApiConstants;
27 import org.kuali.rice.kew.api.document.DocumentWithContent;
28 import org.kuali.rice.kew.api.document.attribute.DocumentAttribute;
29 import org.kuali.rice.kew.api.document.attribute.DocumentAttributeFactory;
30 import org.kuali.rice.kew.api.document.attribute.DocumentAttributeString;
31 import org.kuali.rice.kew.api.document.attribute.WorkflowAttributeDefinition;
32 import org.kuali.rice.kew.api.document.search.DocumentSearchCriteria;
33 import org.kuali.rice.kew.api.exception.WorkflowException;
34 import org.kuali.rice.kew.api.extension.ExtensionDefinition;
35 import org.kuali.rice.kew.framework.document.attribute.SearchableAttribute;
36 import org.kuali.rice.kns.datadictionary.MaintenanceDocumentEntry;
37 import org.kuali.rice.kns.document.MaintenanceDocument;
38 import org.kuali.rice.kns.lookup.LookupUtils;
39 import org.kuali.rice.kns.maintenance.KualiGlobalMaintainableImpl;
40 import org.kuali.rice.kns.maintenance.Maintainable;
41 import org.kuali.rice.kns.service.DictionaryValidationService;
42 import org.kuali.rice.kns.service.KNSServiceLocator;
43 import org.kuali.rice.kns.service.WorkflowAttributePropertyResolutionService;
44 import org.kuali.rice.kns.util.FieldUtils;
45 import org.kuali.rice.kns.web.ui.Field;
46 import org.kuali.rice.kns.web.ui.Row;
47 import org.kuali.rice.krad.bo.BusinessObject;
48 import org.kuali.rice.krad.bo.DocumentHeader;
49 import org.kuali.rice.krad.bo.GlobalBusinessObject;
50 import org.kuali.rice.krad.bo.PersistableBusinessObject;
51 import org.kuali.rice.krad.datadictionary.BusinessObjectEntry;
52 import org.kuali.rice.krad.datadictionary.DocumentEntry;
53 import org.kuali.rice.krad.datadictionary.SearchingAttribute;
54 import org.kuali.rice.krad.datadictionary.SearchingTypeDefinition;
55 import org.kuali.rice.krad.datadictionary.WorkflowAttributes;
56 import org.kuali.rice.krad.document.Document;
57 import org.kuali.rice.krad.service.DocumentService;
58 import org.kuali.rice.krad.service.KRADServiceLocator;
59 import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
60 import org.kuali.rice.krad.util.ErrorMessage;
61 import org.kuali.rice.krad.util.GlobalVariables;
62 import org.kuali.rice.krad.util.KRADPropertyConstants;
63 import org.kuali.rice.krad.util.MessageMap;
64 import org.kuali.rice.krad.util.ObjectUtils;
65
66 import java.text.MessageFormat;
67 import java.util.ArrayList;
68 import java.util.LinkedHashMap;
69 import java.util.List;
70 import java.util.Map;
71
72
73
74
75 @Deprecated
76 public class DataDictionarySearchableAttribute implements SearchableAttribute {
77
78 private static final long serialVersionUID = 173059488280366451L;
79 private static final Logger LOG = Logger.getLogger(DataDictionarySearchableAttribute.class);
80 public static final String DATA_TYPE_BOOLEAN = "boolean";
81
82 @Override
83 public String generateSearchContent(ExtensionDefinition extensionDefinition,
84 String documentTypeName,
85 WorkflowAttributeDefinition attributeDefinition) {
86 return "";
87 }
88
89 @Override
90 public List<DocumentAttribute> extractDocumentAttributes(ExtensionDefinition extensionDefinition,
91 DocumentWithContent documentWithContent) {
92 List<DocumentAttribute> attributes = new ArrayList<DocumentAttribute>();
93
94 String docId = documentWithContent.getDocument().getDocumentId();
95
96 DocumentService docService = KRADServiceLocatorWeb.getDocumentService();
97 Document doc = null;
98 try {
99 doc = docService.getByDocumentHeaderIdSessionless(docId);
100 } catch (WorkflowException we) {
101 LOG.error( "Unable to retrieve document " + docId + " in getSearchStorageValues()", we);
102 }
103
104 String attributeValue = "";
105 if ( doc != null ) {
106 if ( doc.getDocumentHeader() != null ) {
107 attributeValue = doc.getDocumentHeader().getDocumentDescription();
108 } else {
109 attributeValue = "null document header";
110 }
111 } else {
112 attributeValue = "null document";
113 }
114 DocumentAttributeString attribute = DocumentAttributeFactory.createStringAttribute("documentDescription", attributeValue);
115 attributes.add(attribute);
116
117 attributeValue = "";
118 if ( doc != null ) {
119 if ( doc.getDocumentHeader() != null ) {
120 attributeValue = doc.getDocumentHeader().getOrganizationDocumentNumber();
121 } else {
122 attributeValue = "null document header";
123 }
124 } else {
125 attributeValue = "null document";
126 }
127 attribute = DocumentAttributeFactory.createStringAttribute("organizationDocumentNumber", attributeValue);
128 attributes.add(attribute);
129
130 if ( doc != null && doc instanceof MaintenanceDocument) {
131 final Class<? extends BusinessObject> businessObjectClass = getBusinessObjectClass(
132 documentWithContent.getDocument().getDocumentTypeName());
133 if (businessObjectClass != null) {
134 if (GlobalBusinessObject.class.isAssignableFrom(businessObjectClass)) {
135 final GlobalBusinessObject globalBO = retrieveGlobalBusinessObject(docId, businessObjectClass);
136
137 if (globalBO != null) {
138 attributes.addAll(findAllDocumentAttributesForGlobalBusinessObject(globalBO));
139 }
140 } else {
141 attributes.addAll(parsePrimaryKeyValuesFromDocument(businessObjectClass, (MaintenanceDocument)doc));
142 }
143
144 }
145 }
146 if ( doc != null ) {
147 DocumentEntry docEntry = KRADServiceLocatorWeb.getDataDictionaryService().getDataDictionary().getDocumentEntry(
148 documentWithContent.getDocument().getDocumentTypeName());
149 if ( docEntry != null ) {
150 WorkflowAttributes workflowAttributes = docEntry.getWorkflowAttributes();
151 WorkflowAttributePropertyResolutionService waprs = KNSServiceLocator
152 .getWorkflowAttributePropertyResolutionService();
153 attributes.addAll(waprs.resolveSearchableAttributeValues(doc, workflowAttributes));
154 } else {
155 LOG.error("Unable to find DD document entry for document type: " + documentWithContent.getDocument()
156 .getDocumentTypeName());
157 }
158 }
159 return attributes;
160 }
161
162 @Override
163 public List<RemotableAttributeField> getSearchFields(ExtensionDefinition extensionDefinition, String documentTypeName) {
164 List<Row> searchRows = getSearchingRows(documentTypeName);
165 return FieldUtils.convertRowsToAttributeFields(searchRows);
166 }
167
168
169
170
171
172 protected List<Row> getSearchingRows(String documentTypeName) {
173
174 List<Row> docSearchRows = new ArrayList<Row>();
175
176 Class boClass = DocumentHeader.class;
177
178 Field descriptionField = FieldUtils.getPropertyField(boClass, "documentDescription", true);
179 descriptionField.setFieldDataType(KewApiConstants.SearchableAttributeConstants.DATA_TYPE_STRING);
180
181 Field orgDocNumberField = FieldUtils.getPropertyField(boClass, "organizationDocumentNumber", true);
182 orgDocNumberField.setFieldDataType(KewApiConstants.SearchableAttributeConstants.DATA_TYPE_STRING);
183
184 List<Field> fieldList = new ArrayList<Field>();
185 fieldList.add(descriptionField);
186 docSearchRows.add(new Row(fieldList));
187
188 fieldList = new ArrayList<Field>();
189 fieldList.add(orgDocNumberField);
190 docSearchRows.add(new Row(fieldList));
191
192
193 DocumentEntry entry =
194 KRADServiceLocatorWeb.getDataDictionaryService().getDataDictionary().getDocumentEntry(documentTypeName);
195 if (entry == null)
196 return docSearchRows;
197 if (entry instanceof MaintenanceDocumentEntry) {
198 Class<? extends BusinessObject> businessObjectClass = getBusinessObjectClass(documentTypeName);
199 Class<? extends Maintainable> maintainableClass = getMaintainableClass(documentTypeName);
200
201 KualiGlobalMaintainableImpl globalMaintainable = null;
202 try {
203 globalMaintainable = (KualiGlobalMaintainableImpl)maintainableClass.newInstance();
204 businessObjectClass = globalMaintainable.getPrimaryEditedBusinessObjectClass();
205 } catch (Exception ie) {
206
207 }
208
209 if (businessObjectClass != null)
210 docSearchRows.addAll(createFieldRowsForBusinessObject(businessObjectClass));
211 }
212
213 WorkflowAttributes workflowAttributes = entry.getWorkflowAttributes();
214 if (workflowAttributes != null)
215 docSearchRows.addAll(createFieldRowsForWorkflowAttributes(workflowAttributes));
216
217 return docSearchRows;
218 }
219
220 @Override
221 public List<RemotableAttributeError> validateDocumentAttributeCriteria(ExtensionDefinition extensionDefinition,
222 DocumentSearchCriteria documentSearchCriteria) {
223 List<RemotableAttributeError> validationErrors = new ArrayList<RemotableAttributeError>();
224 DictionaryValidationService validationService = KNSServiceLocator.getKNSDictionaryValidationService();
225
226
227 Map<String, List<String>> documentAttributeValues = documentSearchCriteria.getDocumentAttributeValues();
228 for (String key : documentAttributeValues.keySet()) {
229 List<String> values = documentAttributeValues.get(key);
230 if (CollectionUtils.isNotEmpty(values)) {
231 for (String value : values) {
232 if (StringUtils.isNotBlank(value)) {
233 validationService.validateAttributeFormat(documentSearchCriteria.getDocumentTypeName(), key, value, key);
234 }
235 }
236 }
237 }
238
239 retrieveValidationErrorsFromGlobalVariables(validationErrors);
240
241 return validationErrors;
242 }
243
244
245
246
247
248 protected void retrieveValidationErrorsFromGlobalVariables(List<RemotableAttributeError> validationErrors) {
249
250 ConfigurationService configurationService = CoreApiServiceLocator.getKualiConfigurationService();
251
252 if(GlobalVariables.getMessageMap().hasErrors()){
253 MessageMap deepCopy = (MessageMap) SerializationUtils.deepCopy(GlobalVariables.getMessageMap());
254 for (String errorKey : deepCopy.getErrorMessages().keySet()) {
255 List<ErrorMessage> errorMessages = deepCopy.getErrorMessages().get(errorKey);
256 if (CollectionUtils.isNotEmpty(errorMessages)) {
257 List<String> errors = new ArrayList<String>();
258 for (ErrorMessage errorMessage : errorMessages) {
259
260 String error = MessageFormat.format(configurationService.getPropertyValueAsString(errorMessage.getErrorKey()), errorMessage.getMessageParameters());
261 errors.add(error);
262 }
263 RemotableAttributeError remotableAttributeError = RemotableAttributeError.Builder.create(errorKey, errors).build();
264 validationErrors.add(remotableAttributeError);
265 }
266 }
267
268 GlobalVariables.getMessageMap().clearErrorMessages();
269 }
270 }
271
272 protected List<Row> createFieldRowsForWorkflowAttributes(WorkflowAttributes attrs) {
273 List<Row> searchFields = new ArrayList<Row>();
274
275 List<SearchingTypeDefinition> searchingTypeDefinitions = attrs.getSearchingTypeDefinitions();
276 final WorkflowAttributePropertyResolutionService propertyResolutionService = KNSServiceLocator
277 .getWorkflowAttributePropertyResolutionService();
278 for (SearchingTypeDefinition definition: searchingTypeDefinitions) {
279 SearchingAttribute attr = definition.getSearchingAttribute();
280
281 final String attributeName = attr.getAttributeName();
282 final String businessObjectClassName = attr.getBusinessObjectClassName();
283 Class boClass = null;
284 BusinessObject businessObject = null;
285 try {
286 boClass = Class.forName(businessObjectClassName);
287 businessObject = (BusinessObject)boClass.newInstance();
288 } catch (Exception e) {
289 throw new RuntimeException(e);
290 }
291
292 Field searchField = FieldUtils.getPropertyField(boClass, attributeName, false);
293
294
295 searchField.setColumnVisible(attr.isShowAttributeInResultSet());
296
297
298
299 if (!attr.isShowAttributeInSearchCriteria()){
300 searchField.setFieldType(Field.HIDDEN);
301 }
302 String fieldDataType = propertyResolutionService.determineFieldDataType(boClass, attributeName);
303 if (fieldDataType.equals(DataDictionarySearchableAttribute.DATA_TYPE_BOOLEAN)) {
304 fieldDataType = KewApiConstants.SearchableAttributeConstants.DATA_TYPE_STRING;
305 }
306
307
308 if (fieldDataType.equals(KewApiConstants.SearchableAttributeConstants.DATA_TYPE_FLOAT) ||
309 fieldDataType.equals(KewApiConstants.SearchableAttributeConstants.DATA_TYPE_LONG) ||
310 fieldDataType.equals(KewApiConstants.SearchableAttributeConstants.DATA_TYPE_DATE)) {
311
312 searchField.setAllowInlineRange(true);
313 }
314 searchField.setFieldDataType(fieldDataType);
315 List displayedFieldNames = new ArrayList();
316 displayedFieldNames.add(attributeName);
317 LookupUtils.setFieldQuickfinder(businessObject, attributeName, searchField, displayedFieldNames);
318
319 List<Field> fieldList = new ArrayList<Field>();
320 fieldList.add(searchField);
321
322 Row row = new Row(fieldList);
323 if (!attr.isShowAttributeInSearchCriteria()) {
324 row.setHidden(true);
325 }
326 searchFields.add(row);
327 }
328
329 return searchFields;
330 }
331
332 protected List<DocumentAttribute> parsePrimaryKeyValuesFromDocument(Class<? extends BusinessObject> businessObjectClass, MaintenanceDocument document) {
333 List<DocumentAttribute> values = new ArrayList<DocumentAttribute>();
334
335 final List primaryKeyNames = KRADServiceLocatorWeb.getLegacyDataAdapter().listPrimaryKeyFieldNames(businessObjectClass);
336
337 for (Object primaryKeyNameAsObj : primaryKeyNames) {
338 final String primaryKeyName = (String)primaryKeyNameAsObj;
339 final DocumentAttribute searchableValue = parseSearchableAttributeValueForPrimaryKey(primaryKeyName, businessObjectClass, document);
340 if (searchableValue != null) {
341 values.add(searchableValue);
342 }
343 }
344 return values;
345 }
346
347
348
349
350
351
352
353
354 protected DocumentAttribute parseSearchableAttributeValueForPrimaryKey(String propertyName, Class<? extends BusinessObject> businessObjectClass, MaintenanceDocument document) {
355
356 Maintainable maintainable = document.getNewMaintainableObject();
357 PersistableBusinessObject bo = maintainable.getBusinessObject();
358
359 final Object propertyValue = ObjectUtils.getPropertyValue(bo, propertyName);
360 if (propertyValue == null) return null;
361
362 final WorkflowAttributePropertyResolutionService propertyResolutionService = KNSServiceLocator
363 .getWorkflowAttributePropertyResolutionService();
364 DocumentAttribute value = propertyResolutionService.buildSearchableAttribute(businessObjectClass, propertyName, propertyValue);
365 return value;
366 }
367
368
369
370
371
372
373 protected Class<? extends BusinessObject> getBusinessObjectClass(String documentTypeName) {
374 MaintenanceDocumentEntry entry = retrieveMaintenanceDocumentEntry(documentTypeName);
375 return (entry == null ? null : (Class<? extends BusinessObject>) entry.getDataObjectClass());
376 }
377
378
379
380
381
382
383 protected Class<? extends Maintainable> getMaintainableClass(String documentTypeName) {
384 MaintenanceDocumentEntry entry = retrieveMaintenanceDocumentEntry(documentTypeName);
385 return (entry == null ? null : entry.getMaintainableClass());
386 }
387
388
389
390
391
392
393
394 protected MaintenanceDocumentEntry retrieveMaintenanceDocumentEntry(String documentTypeName) {
395 return (MaintenanceDocumentEntry) KRADServiceLocatorWeb.getDataDictionaryService().getDataDictionary().getDocumentEntry(documentTypeName);
396 }
397
398 protected GlobalBusinessObject retrieveGlobalBusinessObject(String documentNumber, Class<? extends BusinessObject> businessObjectClass) {
399 GlobalBusinessObject globalBO = null;
400
401 Map pkMap = new LinkedHashMap();
402 pkMap.put(KRADPropertyConstants.DOCUMENT_NUMBER, documentNumber);
403
404 List returnedBOs = (List) KNSServiceLocator.getBusinessObjectService().findMatching(businessObjectClass, pkMap);
405 if (returnedBOs.size() > 0) {
406 globalBO = (GlobalBusinessObject)returnedBOs.get(0);
407 }
408
409 return globalBO;
410 }
411
412 protected List<DocumentAttribute> findAllDocumentAttributesForGlobalBusinessObject(GlobalBusinessObject globalBO) {
413 List<DocumentAttribute> searchValues = new ArrayList<DocumentAttribute>();
414
415 for (PersistableBusinessObject bo : globalBO.generateGlobalChangesToPersist()) {
416 DocumentAttribute value = generateSearchableAttributeFromChange(bo);
417 if (value != null) {
418 searchValues.add(value);
419 }
420 }
421
422 return searchValues;
423 }
424
425 protected DocumentAttribute generateSearchableAttributeFromChange(PersistableBusinessObject changeToPersist) {
426 List<String> primaryKeyNames = KRADServiceLocatorWeb.getLegacyDataAdapter().listPrimaryKeyFieldNames(changeToPersist.getClass());
427
428 for (Object primaryKeyNameAsObject : primaryKeyNames) {
429 String primaryKeyName = (String)primaryKeyNameAsObject;
430 Object value = ObjectUtils.getPropertyValue(changeToPersist, primaryKeyName);
431
432 if (value != null) {
433 final WorkflowAttributePropertyResolutionService propertyResolutionService = KNSServiceLocator
434 .getWorkflowAttributePropertyResolutionService();
435 DocumentAttribute saValue = propertyResolutionService.buildSearchableAttribute(changeToPersist.getClass(), primaryKeyName, value);
436 return saValue;
437 }
438 }
439 return null;
440 }
441
442
443
444
445
446
447 protected List<Row> createFieldRowsForBusinessObject(Class<? extends BusinessObject> businessObjectClass) {
448 List<Row> searchFields = new ArrayList<Row>();
449
450 final List primaryKeyNamesAsObjects = KRADServiceLocatorWeb.getLegacyDataAdapter().listPrimaryKeyFieldNames(businessObjectClass);
451 final BusinessObjectEntry boEntry = KRADServiceLocatorWeb.getDataDictionaryService().getDataDictionary().getBusinessObjectEntry(businessObjectClass.getName());
452 final WorkflowAttributePropertyResolutionService propertyResolutionService = KNSServiceLocator
453 .getWorkflowAttributePropertyResolutionService();
454 for (Object primaryKeyNameAsObject : primaryKeyNamesAsObjects) {
455
456 String attributeName = (String)primaryKeyNameAsObject;
457 BusinessObject businessObject = null;
458 try {
459 businessObject = businessObjectClass.newInstance();
460 } catch (Exception e) {
461 throw new RuntimeException(e);
462 }
463
464 Field searchField = FieldUtils.getPropertyField(businessObjectClass, attributeName, false);
465 String dataType = propertyResolutionService.determineFieldDataType(businessObjectClass, attributeName);
466 searchField.setFieldDataType(dataType);
467 List<Field> fieldList = new ArrayList<Field>();
468
469 List displayedFieldNames = new ArrayList();
470 displayedFieldNames.add(attributeName);
471 LookupUtils.setFieldQuickfinder(businessObject, attributeName, searchField, displayedFieldNames);
472
473 fieldList.add(searchField);
474 searchFields.add(new Row(fieldList));
475 }
476
477 return searchFields;
478 }
479
480 }