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