1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.kew.impl.document.search;
17
18 import org.apache.commons.beanutils.PropertyUtils;
19 import org.apache.commons.lang.ArrayUtils;
20 import org.apache.commons.lang.BooleanUtils;
21 import org.apache.commons.lang.ObjectUtils;
22 import org.apache.commons.lang.StringUtils;
23 import org.kuali.rice.core.api.CoreApiServiceLocator;
24 import org.kuali.rice.core.api.config.property.Config;
25 import org.kuali.rice.core.api.config.property.ConfigContext;
26 import org.kuali.rice.core.api.search.SearchOperator;
27 import org.kuali.rice.core.api.uif.RemotableAttributeField;
28 import org.kuali.rice.core.api.util.KeyValue;
29 import org.kuali.rice.core.api.util.RiceKeyConstants;
30 import org.kuali.rice.core.framework.services.CoreFrameworkServiceLocator;
31 import org.kuali.rice.core.web.format.Formatter;
32 import org.kuali.rice.kew.api.KEWPropertyConstants;
33 import org.kuali.rice.kew.api.document.attribute.DocumentAttribute;
34 import org.kuali.rice.kew.api.document.search.DocumentSearchCriteria;
35 import org.kuali.rice.kew.api.document.search.DocumentSearchCriteriaContract;
36 import org.kuali.rice.kew.api.document.search.DocumentSearchResult;
37 import org.kuali.rice.kew.api.document.search.DocumentSearchResults;
38 import org.kuali.rice.kew.docsearch.DocumentSearchCriteriaProcessor;
39 import org.kuali.rice.kew.docsearch.DocumentSearchCriteriaProcessorKEWAdapter;
40 import org.kuali.rice.kew.docsearch.service.DocumentSearchService;
41 import org.kuali.rice.kew.doctype.bo.DocumentType;
42 import org.kuali.rice.kew.exception.WorkflowServiceError;
43 import org.kuali.rice.kew.exception.WorkflowServiceErrorException;
44 import org.kuali.rice.kew.framework.document.search.DocumentSearchCriteriaConfiguration;
45 import org.kuali.rice.kew.framework.document.search.DocumentSearchResultSetConfiguration;
46 import org.kuali.rice.kew.framework.document.search.StandardResultField;
47 import org.kuali.rice.kew.impl.document.search.DocumentSearchCriteriaBo;
48 import org.kuali.rice.kew.lookup.valuefinder.SavedSearchValuesFinder;
49 import org.kuali.rice.kew.service.KEWServiceLocator;
50 import org.kuali.rice.kew.api.KewApiConstants;
51 import org.kuali.rice.kns.datadictionary.BusinessObjectEntry;
52 import org.kuali.rice.kns.lookup.HtmlData;
53 import org.kuali.rice.kns.lookup.KualiLookupableHelperServiceImpl;
54 import org.kuali.rice.kns.util.FieldUtils;
55 import org.kuali.rice.kns.web.struts.form.LookupForm;
56 import org.kuali.rice.kns.web.ui.Column;
57 import org.kuali.rice.kns.web.ui.Field;
58 import org.kuali.rice.kns.web.ui.ResultRow;
59 import org.kuali.rice.kns.web.ui.Row;
60 import org.kuali.rice.krad.bo.BusinessObject;
61 import org.kuali.rice.krad.exception.ValidationException;
62 import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
63 import org.kuali.rice.krad.util.GlobalVariables;
64 import org.kuali.rice.krad.util.KRADConstants;
65
66 import java.lang.reflect.InvocationTargetException;
67 import java.text.MessageFormat;
68 import java.util.ArrayList;
69 import java.util.Collection;
70 import java.util.Collections;
71 import java.util.HashMap;
72 import java.util.List;
73 import java.util.Map;
74
75
76
77
78
79
80
81 public class DocumentSearchCriteriaBoLookupableHelperService extends KualiLookupableHelperServiceImpl {
82
83 private static final String DOCUMENT_ATTRIBUTE_PROPERTY_NAME_PREFIX = "documentAttribute.";
84
85 static final String SAVED_SEARCH_NAME_PARAM = "savedSearchToLoadAndExecute";
86
87
88
89 private static final String EXCEED_THRESHOLD_MESSAGE_KEY = "docsearch.DocumentSearchService.exceededThreshold";
90 private static final String SECURITY_FILTERED_MESSAGE_KEY = "docsearch.DocumentSearchService.securityFiltered";
91 private static final String EXCEED_THRESHOLD_AND_SECURITY_FILTERED_MESSAGE_KEY = "docsearch.DocumentSearchService.exceededThresholdAndSecurityFiltered";
92
93 private static final boolean DOCUMENT_HANDLER_POPUP_DEFAULT = true;
94 private static final boolean ROUTE_LOG_POPUP_DEFAULT = true;
95
96
97
98 private DocumentSearchService documentSearchService;
99 private DocumentSearchCriteriaProcessor documentSearchCriteriaProcessor;
100 private DocumentSearchCriteriaTranslator documentSearchCriteriaTranslator;
101
102
103 protected DocumentSearchResults searchResults = null;
104 protected DocumentSearchCriteria criteria = null;
105
106 @Override
107 protected List<? extends BusinessObject> getSearchResultsHelper(Map<String, String> fieldValues,
108 boolean unbounded) {
109 criteria = loadCriteria(fieldValues);
110 searchResults = null;
111 try {
112 searchResults = KEWServiceLocator.getDocumentSearchService().lookupDocuments(
113 GlobalVariables.getUserSession().getPrincipalId(), criteria);
114 if (searchResults.isCriteriaModified()) {
115 criteria = searchResults.getCriteria();
116 }
117 } catch (WorkflowServiceErrorException wsee) {
118 for (WorkflowServiceError workflowServiceError : (List<WorkflowServiceError>) wsee.getServiceErrors()) {
119 if (workflowServiceError.getMessageMap() != null && workflowServiceError.getMessageMap().hasErrors()) {
120
121 GlobalVariables.getMessageMap().merge(workflowServiceError.getMessageMap());
122 } else {
123 GlobalVariables.getMessageMap().putError(workflowServiceError.getMessage(),
124 RiceKeyConstants.ERROR_CUSTOM, workflowServiceError.getMessage());
125 }
126 }
127 }
128
129 if (!GlobalVariables.getMessageMap().hasNoErrors() || searchResults == null) {
130 throw new ValidationException("error with doc search");
131 }
132
133 populateResultWarningMessages(searchResults);
134
135 List<DocumentSearchResult> individualSearchResults = searchResults.getSearchResults();
136
137 setBackLocation(fieldValues.get(KRADConstants.BACK_LOCATION));
138 setDocFormKey(fieldValues.get(KRADConstants.DOC_FORM_KEY));
139
140 applyCriteriaChangesToFields(criteria);
141
142 return populateSearchResults(individualSearchResults);
143
144 }
145
146
147
148
149 protected void populateResultWarningMessages(DocumentSearchResults searchResults) {
150
151 boolean overThreshold = searchResults.isOverThreshold();
152 int numFiltered = searchResults.getNumberOfSecurityFilteredResults();
153 int numResults = searchResults.getSearchResults().size();
154 if (overThreshold && numFiltered > 0) {
155 GlobalVariables.getMessageMap().putWarning(KRADConstants.GLOBAL_MESSAGES,
156 EXCEED_THRESHOLD_AND_SECURITY_FILTERED_MESSAGE_KEY,
157 String.valueOf(numResults),
158 String.valueOf(numFiltered));
159 } else if (numFiltered > 0) {
160 GlobalVariables.getMessageMap().putWarning(KRADConstants.GLOBAL_MESSAGES,
161 SECURITY_FILTERED_MESSAGE_KEY,
162 String.valueOf(numFiltered));
163 } else if (overThreshold) {
164 GlobalVariables.getMessageMap().putWarning(KRADConstants.GLOBAL_MESSAGES,
165 EXCEED_THRESHOLD_MESSAGE_KEY,
166 String.valueOf(numResults));
167 }
168 }
169
170
171
172
173
174 protected void applyCriteriaChangesToFields(DocumentSearchCriteriaContract criteria) {
175 for (Field field: getFormFields()) {
176 if(StringUtils.equals(field.getPropertyName(), KRADConstants.LOOKUP_RANGE_LOWER_BOUND_PROPERTY_PREFIX + "dateCreated") && StringUtils.isEmpty(field.getPropertyValue())) {
177 if (criteria.getDateCreatedFrom() != null) {
178 field.setPropertyValue(CoreApiServiceLocator.getDateTimeService().toDateString(criteria.getDateCreatedFrom().toDate()));
179 }
180 }
181 }
182 }
183
184
185
186
187
188 protected Map<String, String> cleanupFieldValues(Map<String, String> fieldValues, Map<String, String[]> parameters) {
189 Map<String, String> cleanedUpFieldValues = new HashMap<String, String>(fieldValues);
190 if (ArrayUtils.isNotEmpty(parameters.get(KEWPropertyConstants.DOC_SEARCH_RESULT_PROPERTY_NAME_STATUS_CODE))) {
191 cleanedUpFieldValues.put(KEWPropertyConstants.DOC_SEARCH_RESULT_PROPERTY_NAME_STATUS_CODE,
192 StringUtils.join(parameters.get(KEWPropertyConstants.DOC_SEARCH_RESULT_PROPERTY_NAME_STATUS_CODE), ","));
193 }
194 Map<String, String> documentAttributeFieldValues = new HashMap<String, String>();
195 for (String parameterName : parameters.keySet()) {
196 if (parameterName.contains(KewApiConstants.DOCUMENT_ATTRIBUTE_FIELD_PREFIX)) {
197 String[] value = parameters.get(parameterName);
198 if (ArrayUtils.isNotEmpty(value)) {
199 documentAttributeFieldValues.put(parameterName, StringUtils.join(value, " " + SearchOperator.OR.op() + " "));
200 }
201 }
202 }
203
204 documentAttributeFieldValues.putAll(preProcessRangeFields(documentAttributeFieldValues));
205 cleanedUpFieldValues.putAll(documentAttributeFieldValues);
206 return cleanedUpFieldValues;
207 }
208
209
210
211
212
213 protected DocumentSearchCriteria loadCriteria(Map<String, String> fieldValues) {
214 fieldValues = cleanupFieldValues(fieldValues, getParameters());
215 String[] savedSearchToLoad = getParameters().get(SAVED_SEARCH_NAME_PARAM);
216 boolean savedSearch = savedSearchToLoad != null && savedSearchToLoad.length > 0 && StringUtils.isNotBlank(savedSearchToLoad[0]);
217 if (savedSearch) {
218 DocumentSearchCriteria criteria = getDocumentSearchService().getSavedSearchCriteria(GlobalVariables.getUserSession().getPrincipalId(), savedSearchToLoad[0]);
219 if (criteria != null) {
220 mergeFieldValues(getDocumentSearchCriteriaTranslator().translateCriteriaToFields(criteria));
221 return criteria;
222 }
223 }
224
225 return getDocumentSearchCriteriaTranslator().translateFieldsToCriteria(fieldValues);
226 }
227
228 protected List<DocumentSearchCriteriaBo> populateSearchResults(List<DocumentSearchResult> lookupResults) {
229 List<DocumentSearchCriteriaBo> searchResults = new ArrayList<DocumentSearchCriteriaBo>();
230 for (DocumentSearchResult searchResult : lookupResults) {
231 DocumentSearchCriteriaBo result = new DocumentSearchCriteriaBo();
232 result.populateFromDocumentSearchResult(searchResult);
233 searchResults.add(result);
234 }
235 return searchResults;
236 }
237
238 @Override
239 public Collection performLookup(LookupForm lookupForm, Collection resultTable, boolean bounded) {
240 Collection lookupResult = super.performLookup(lookupForm, resultTable, bounded);
241 postProcessResults(resultTable, this.searchResults);
242 return lookupResult;
243 }
244
245
246
247
248 protected static void setFieldValue(Field field, String[] values) {
249 if(!Field.MULTI_VALUE_FIELD_TYPES.contains(field.getFieldType())) {
250 field.setPropertyValue(values[0]);
251 } else {
252
253 field.setPropertyValues(values);
254 }
255 }
256
257
258
259
260
261
262
263
264 protected Map<String, String[]> getFormFieldsValues() {
265 Map<String, String[]> values = new HashMap<String, String[]>();
266 for (Field field : getFormFields()) {
267 String[] value;
268 if(!Field.MULTI_VALUE_FIELD_TYPES.contains(field.getFieldType())) {
269 value = new String[] { field.getPropertyValue() };
270 } else {
271
272 value = field.getPropertyValues();
273 }
274 values.put(field.getPropertyName(), value);
275 }
276 return values;
277 }
278
279
280
281
282 protected static void overrideFieldValue(Field field, Map<String, String[]> newValues, Map<String, String[]> oldValues) {
283 if (StringUtils.isNotBlank(field.getPropertyName())) {
284 if (newValues.get(field.getPropertyName()) != null) {
285 setFieldValue(field, newValues.get(field.getPropertyName()));
286 } else if (oldValues.get(field.getPropertyName()) != null) {
287 setFieldValue(field, oldValues.get(field.getPropertyName()));
288 }
289 }
290 }
291
292
293
294
295
296 protected void mergeFieldValues(Map<String, String[]> values) {
297 for (Field field: getFormFields()) {
298 if (StringUtils.isNotBlank(field.getPropertyName())) {
299 if (values.get(field.getPropertyName()) != null) {
300 setFieldValue(field, values.get(field.getPropertyName()));
301 }
302 }
303 }
304 }
305
306
307
308
309 protected void setFormField(String name, String value) {
310 for (Field field : getFormFields()) {
311 if(StringUtils.equals(field.getPropertyName(), name)) {
312 setFieldValue(field, new String[] { value });
313 break;
314 }
315 }
316 }
317
318
319
320
321
322 protected void toggleFormView() {
323 Map<String,String[]> fieldValues = new HashMap<String,String[]>();
324 Map<String, String[]> savedValues = getFormFieldsValues();
325
326
327
328
329
330 for (Field field: getFormFields()) {
331 overrideFieldValue(field, this.getParameters(), savedValues);
332
333
334 applyFieldAuthorizationsFromNestedLookups(field);
335 fieldValues.put(field.getPropertyName(), new String[] { field.getPropertyValue() });
336 }
337
338
339 if (checkForAdditionalFields(fieldValues)) {
340 for (Field field: getFormFields()) {
341 overrideFieldValue(field, this.getParameters(), savedValues);
342 fieldValues.put(field.getPropertyName(), new String[] { field.getPropertyValue() });
343 }
344 }
345
346
347
348 setFormField(DocumentSearchCriteriaProcessorKEWAdapter.CLEARSAVED_SEARCH_FIELD, "");
349 }
350
351
352
353
354
355 protected boolean loadSavedSearch(boolean ignoreErrors) {
356 Map<String,String[]> fieldValues = new HashMap<String,String[]>();
357
358 String savedSearchName = getSavedSearchName();
359 if(StringUtils.isEmpty(savedSearchName) || "*ignore*".equals(savedSearchName)) {
360 if(!ignoreErrors) {
361 GlobalVariables.getMessageMap().putError(SAVED_SEARCH_NAME_PARAM, RiceKeyConstants.ERROR_CUSTOM, "You must select a saved search");
362 } else {
363
364 return false;
365 }
366 setFormField(SAVED_SEARCH_NAME_PARAM, "");
367 }
368 if (!GlobalVariables.getMessageMap().hasNoErrors()) {
369 throw new ValidationException("errors in search criteria");
370 }
371
372 DocumentSearchCriteria criteria = KEWServiceLocator.getDocumentSearchService().getSavedSearchCriteria(GlobalVariables.getUserSession().getPrincipalId(), savedSearchName);
373
374
375 String docTypeName = criteria.getDocumentTypeName();
376
377 setRows(docTypeName);
378
379
380
381
382
383 for (Map.Entry<String, List<String>> entry: criteria.getDocumentAttributeValues().entrySet()) {
384 fieldValues.put(entry.getKey(), entry.getValue().toArray(new String[entry.getValue().size()]));
385 }
386
387
388 for (Field field : getFormFields()) {
389 if (field.getPropertyName() != null && !field.getPropertyName().equals("")) {
390
391
392 String[] values = null;
393 if (fieldValues.get(field.getPropertyName()) != null) {
394 values = fieldValues.get(field.getPropertyName());
395 } else {
396
397 try {
398 values = new String[] { ObjectUtils.toString(PropertyUtils.getProperty(criteria, field.getPropertyName())) };
399 } catch (IllegalAccessException e) {
400 e.printStackTrace();
401 } catch (InvocationTargetException e) {
402 e.printStackTrace();
403 } catch (NoSuchMethodException e) {
404
405
406 }
407 }
408 if (values != null) {
409 setFieldValue(field, values);
410 }
411 }
412 }
413
414 return true;
415 }
416
417
418
419
420
421
422
423
424
425
426 @Override
427 public boolean performCustomAction(boolean ignoreErrors) {
428
429 if (getSavedSearchName() != null) {
430 return loadSavedSearch(ignoreErrors);
431 } else {
432 if (isClearSavedSearch()) {
433 KEWServiceLocator.getDocumentSearchService().clearNamedSearches(GlobalVariables.getUserSession().getPrincipalId());
434 } else {
435 toggleFormView();
436 }
437
438 return false;
439 }
440 }
441
442
443
444
445 @Override
446 public HtmlData getInquiryUrl(BusinessObject bo, String propertyName) {
447 DocumentSearchCriteriaBo criteriaBo = (DocumentSearchCriteriaBo)bo;
448 if (KEWPropertyConstants.DOC_SEARCH_RESULT_PROPERTY_NAME_DOCUMENT_ID.equals(propertyName)) {
449 return generateDocumentHandlerUrl(criteriaBo.getDocumentId(), criteriaBo.getDocumentType(),
450 isSuperUserSearch());
451 } else if (KEWPropertyConstants.DOC_SEARCH_RESULT_PROPERTY_NAME_ROUTE_LOG.equals(propertyName)) {
452 return generateRouteLogUrl(criteriaBo.getDocumentId());
453 }
454 return super.getInquiryUrl(bo, propertyName);
455 }
456
457
458
459
460
461 protected HtmlData.AnchorHtmlData generateDocumentHandlerUrl(String documentId, DocumentType documentType, boolean superUserSearch) {
462 HtmlData.AnchorHtmlData link = new HtmlData.AnchorHtmlData();
463 link.setDisplayText(documentId);
464 if (isDocumentHandlerPopup()) {
465 link.setTarget("_blank");
466 }
467 String url = ConfigContext.getCurrentContextConfig().getProperty(Config.KEW_URL) + "/";
468 if (superUserSearch) {
469 if (documentType.getUseWorkflowSuperUserDocHandlerUrl().getPolicyValue().booleanValue()) {
470 url += "SuperUser.do?methodToCall=displaySuperUserDocument&documentId=" + documentId;
471 } else {
472 url = KewApiConstants.DOC_HANDLER_REDIRECT_PAGE
473 + "?" + KewApiConstants.COMMAND_PARAMETER + "="
474 + KewApiConstants.SUPERUSER_COMMAND + "&"
475 + KewApiConstants.DOCUMENT_ID_PARAMETER + "="
476 + documentId;
477 }
478 } else {
479 url += KewApiConstants.DOC_HANDLER_REDIRECT_PAGE + "?"
480 + KewApiConstants.COMMAND_PARAMETER + "="
481 + KewApiConstants.DOCSEARCH_COMMAND + "&"
482 + KewApiConstants.DOCUMENT_ID_PARAMETER + "="
483 + documentId;
484 }
485 link.setHref(url);
486 return link;
487 }
488
489 protected HtmlData.AnchorHtmlData generateRouteLogUrl(String documentId) {
490 HtmlData.AnchorHtmlData link = new HtmlData.AnchorHtmlData();
491 if (isRouteLogPopup()) {
492 link.setTarget("_blank");
493 }
494 link.setDisplayText("Route Log for document " + documentId);
495 String url = ConfigContext.getCurrentContextConfig().getProperty(Config.KEW_URL) + "/" +
496 "RouteLog.do?documentId=" + documentId;
497 link.setHref(url);
498 return link;
499 }
500
501
502
503
504 protected boolean isDocumentHandlerPopup() {
505 return BooleanUtils.toBooleanDefaultIfNull(
506 CoreFrameworkServiceLocator.getParameterService().getParameterValueAsBoolean(
507 KewApiConstants.KEW_NAMESPACE,
508 KRADConstants.DetailTypes.DOCUMENT_SEARCH_DETAIL_TYPE,
509 KewApiConstants.DOCUMENT_SEARCH_DOCUMENT_POPUP_IND),
510 DOCUMENT_HANDLER_POPUP_DEFAULT);
511 }
512
513
514
515
516 public boolean isRouteLogPopup() {
517 return BooleanUtils.toBooleanDefaultIfNull(
518 CoreFrameworkServiceLocator.getParameterService().getParameterValueAsBoolean(KewApiConstants.KEW_NAMESPACE,
519 KRADConstants.DetailTypes.DOCUMENT_SEARCH_DETAIL_TYPE,
520 KewApiConstants.DOCUMENT_SEARCH_ROUTE_LOG_POPUP_IND), ROUTE_LOG_POPUP_DEFAULT);
521 }
522
523
524
525
526 protected boolean isFlagSet(String flagName) {
527 if(this.getParameters().containsKey(flagName)) {
528 String[] params = (String[])this.getParameters().get(flagName);
529 if (ArrayUtils.isNotEmpty(params)) {
530 return "YES".equalsIgnoreCase(params[0]);
531 }
532 }
533 return false;
534 }
535
536
537
538
539 protected boolean isSuperUserSearch() {
540 return isFlagSet(DocumentSearchCriteriaProcessorKEWAdapter.SUPERUSER_SEARCH_FIELD);
541 }
542
543
544
545
546 protected boolean isAdvancedSearch() {
547 return isFlagSet(DocumentSearchCriteriaProcessorKEWAdapter.ADVANCED_SEARCH_FIELD);
548 }
549
550
551
552
553 protected boolean isClearSavedSearch() {
554 return isFlagSet(DocumentSearchCriteriaProcessorKEWAdapter.CLEARSAVED_SEARCH_FIELD);
555 }
556
557 protected String getSavedSearchName() {
558 String[] savedSearchName = getParameters().get(SAVED_SEARCH_NAME_PARAM);
559 if (savedSearchName != null && savedSearchName.length > 0) {
560 return savedSearchName[0];
561 }
562 return null;
563 }
564
565
566
567
568 @Override
569 protected void setRows() {
570 this.setRows(null);
571 }
572
573
574
575
576 protected Iterable<Field> getFormFields() {
577 return getFields(this.getRows());
578 }
579
580
581
582
583
584
585
586
587
588 protected void setRows(String documentTypeName) {
589 if (getRows() == null) {
590 super.setRows();
591 }
592 List<Row> lookupRows = new ArrayList<Row>();
593
594 for (Row row : getRows()) {
595 lookupRows.add(row);
596 }
597
598 getRows().clear();
599
600 DocumentType docType = getValidDocumentType(documentTypeName);
601
602 boolean advancedSearch = isAdvancedSearch();
603 boolean superUserSearch = isSuperUserSearch();
604
605
606 List<Row> rows = getDocumentSearchCriteriaProcessor().getRows(docType,lookupRows, advancedSearch, superUserSearch);
607
608 BusinessObjectEntry boe = (BusinessObjectEntry) KRADServiceLocatorWeb.getDataDictionaryService().getDataDictionary().getBusinessObjectEntry(this.getBusinessObjectClass().getName());
609 int numCols = boe.getLookupDefinition().getNumOfColumns();
610 if(numCols == 0) {
611 numCols = KRADConstants.DEFAULT_NUM_OF_COLUMNS;
612 }
613
614 super.getRows().addAll(FieldUtils.wrapFields(this.getFields(rows), numCols));
615
616 }
617
618 private static List<Field> getFields(Collection<? extends Row> rows) {
619 List<Field> rList = new ArrayList<Field>();
620 for (Row r : rows) {
621 for (Field f : r.getFields()) {
622 rList.add(f);
623 }
624 }
625 return rList;
626 }
627
628
629
630
631
632
633 private DocumentType getValidDocumentType(String documentTypeName) {
634 if (StringUtils.isNotEmpty(documentTypeName)) {
635 DocumentType documentType = KEWServiceLocator.getDocumentTypeService().findByNameCaseInsensitive(documentTypeName.trim());
636 if (documentType != null && documentType.isActive()) {
637 return documentType;
638 }
639 }
640 return null;
641 }
642
643 private static String TOGGLE_BUTTON = "<input type='image' name=''{0}'' id=''{0}'' class='tinybutton' src=''..{1}/images/tinybutton-{2}search.gif'' alt=''{3} search'' title=''{3} search''/>";
644
645 @Override
646 public String getSupplementalMenuBar() {
647 boolean advancedSearch = isAdvancedSearch();
648 boolean superUserSearch = isSuperUserSearch();
649 StringBuilder suppMenuBar = new StringBuilder();
650
651
652
653
654 String type = advancedSearch ? "basic" : "detailed";
655 suppMenuBar.append(MessageFormat.format(TOGGLE_BUTTON, "toggleAdvancedSearch", KewApiConstants.WEBAPP_DIRECTORY, type, type));
656
657
658 suppMenuBar.append(" ");
659 suppMenuBar.append(MessageFormat.format(TOGGLE_BUTTON, "toggleSuperUserSearch", KewApiConstants.WEBAPP_DIRECTORY, superUserSearch ? "nonsupu" : "superuser", superUserSearch ? "non-superuser" : "superuser"));
660
661
662 suppMenuBar.append(" ");
663 suppMenuBar.append(MessageFormat.format(TOGGLE_BUTTON, DocumentSearchCriteriaProcessorKEWAdapter.CLEARSAVED_SEARCH_FIELD, KewApiConstants.WEBAPP_DIRECTORY, "clearsaved", "clear saved searches"));
664
665 return suppMenuBar.toString();
666 }
667
668 @Override
669 public boolean shouldDisplayHeaderNonMaintActions() {
670 return true;
671 }
672
673 @Override
674 public boolean shouldDisplayLookupCriteria() {
675 return true;
676 }
677
678
679
680
681
682 @Override
683 public boolean checkForAdditionalFields(Map fieldValues) {
684
685 Object val = fieldValues.get("documentTypeName");
686 String documentTypeName;
687 if (val instanceof String[]) {
688 documentTypeName = ((String[]) val)[0];
689 } else {
690 documentTypeName = (String) val;
691 }
692 if (StringUtils.isNotBlank(documentTypeName)) {
693 setRows(documentTypeName);
694 }
695 return true;
696 }
697
698 @Override
699 public Field getExtraField() {
700 SavedSearchValuesFinder savedSearchValuesFinder = new SavedSearchValuesFinder();
701 List<KeyValue> savedSearchValues = savedSearchValuesFinder.getKeyValues();
702 Field savedSearch = new Field();
703 savedSearch.setPropertyName(SAVED_SEARCH_NAME_PARAM);
704 savedSearch.setFieldType(Field.DROPDOWN_SCRIPT);
705 savedSearch.setScript("customLookupChanged()");
706 savedSearch.setFieldValidValues(savedSearchValues);
707 savedSearch.setFieldLabel("Saved Searches");
708 return savedSearch;
709 }
710
711 @Override
712 public void performClear(LookupForm lookupForm) {
713 DocumentSearchCriteria criteria = loadCriteria(lookupForm.getFields());
714 super.performClear(lookupForm);
715 repopulateSearchTypeFlags();
716 DocumentType documentType = getValidDocumentType(criteria.getDocumentTypeName());
717 if (documentType != null) {
718 DocumentSearchCriteria clearedCriteria = documentSearchService.clearCriteria(documentType, criteria);
719 applyCriteriaChangesToFields(DocumentSearchCriteria.Builder.create(clearedCriteria));
720 }
721 }
722
723
724
725
726 protected void repopulateSearchTypeFlags() {
727 boolean advancedSearch = isAdvancedSearch();
728 boolean superUserSearch = isSuperUserSearch();
729 int fieldsRepopulated = 0;
730 for (Field field: getFields(super.getRows())) {
731 if (fieldsRepopulated >= 2) {
732 break;
733 }
734 if (DocumentSearchCriteriaProcessorKEWAdapter.ADVANCED_SEARCH_FIELD.equals(field.getPropertyName())) {
735 field.setPropertyValue(advancedSearch ? "YES" : "NO");
736 fieldsRepopulated++;
737 } else if (DocumentSearchCriteriaProcessorKEWAdapter.SUPERUSER_SEARCH_FIELD.equals(field.getPropertyName())) {
738 field.setPropertyValue(advancedSearch ? "YES" : "NO");
739 fieldsRepopulated++;
740 }
741 }
742
743 }
744
745
746
747
748 protected void postProcessResults(Collection<ResultRow> resultRows, DocumentSearchResults searchResults) {
749 if (resultRows.size() != searchResults.getSearchResults().size()) {
750 throw new IllegalStateException("Encountered a mismatch between ResultRow items and document search results "
751 + resultRows.size() + " != " + searchResults.getSearchResults().size());
752 }
753 DocumentType documentType = getValidDocumentType(criteria.getDocumentTypeName());
754 DocumentSearchResultSetConfiguration resultSetConfiguration = null;
755 DocumentSearchCriteriaConfiguration criteriaConfiguration = null;
756 if (documentType != null) {
757 resultSetConfiguration =
758 KEWServiceLocator.getDocumentSearchCustomizationMediator().customizeResultSetConfiguration(
759 documentType, criteria);
760 criteriaConfiguration =
761 KEWServiceLocator.getDocumentSearchCustomizationMediator().getDocumentSearchCriteriaConfiguration(
762 documentType);
763
764 }
765 int index = 0;
766 for (ResultRow resultRow : resultRows) {
767 DocumentSearchResult searchResult = searchResults.getSearchResults().get(index);
768 executeColumnCustomization(resultRow, searchResult, resultSetConfiguration, criteriaConfiguration);
769 index++;
770 }
771 }
772
773
774
775
776
777 protected void executeColumnCustomization(ResultRow resultRow, DocumentSearchResult searchResult,
778 DocumentSearchResultSetConfiguration resultSetConfiguration,
779 DocumentSearchCriteriaConfiguration criteriaConfiguration) {
780 if (resultSetConfiguration == null) {
781 resultSetConfiguration = DocumentSearchResultSetConfiguration.Builder.create().build();
782 }
783 if (criteriaConfiguration == null) {
784 criteriaConfiguration = DocumentSearchCriteriaConfiguration.Builder.create().build();
785 }
786 List<StandardResultField> standardFieldsToRemove = resultSetConfiguration.getStandardResultFieldsToRemove();
787 if (standardFieldsToRemove == null) {
788 standardFieldsToRemove = Collections.emptyList();
789 }
790 List<Column> newColumns = new ArrayList<Column>();
791 for (Column standardColumn : resultRow.getColumns()) {
792 if (!standardFieldsToRemove.contains(StandardResultField.fromFieldName(standardColumn.getPropertyName()))) {
793 newColumns.add(standardColumn);
794
795
796 if (standardColumn.getPropertyName().equals(
797 KEWPropertyConstants.DOC_SEARCH_RESULT_PROPERTY_NAME_ROUTE_LOG)) {
798 standardColumn.setEscapeXMLValue(false);
799 }
800 }
801 }
802
803
804 List<RemotableAttributeField> searchAttributeFields = criteriaConfiguration.getFlattenedSearchAttributeFields();
805 List<String> additionalFieldNamesToInclude = new ArrayList<String>();
806 if (!resultSetConfiguration.isOverrideSearchableAttributes()) {
807 for (RemotableAttributeField searchAttributeField : searchAttributeFields) {
808
809
810 additionalFieldNamesToInclude.add(searchAttributeField.getName());
811 }
812 }
813 if (resultSetConfiguration.getCustomFieldNamesToAdd() != null) {
814 additionalFieldNamesToInclude.addAll(resultSetConfiguration.getCustomFieldNamesToAdd());
815 }
816
817
818 List<Column> customColumns = new ArrayList<Column>();
819 List<Column> additionalAttributeColumns = FieldUtils.constructColumnsFromAttributeFields(
820 resultSetConfiguration.getAdditionalAttributeFields());
821
822 outer:for (String additionalFieldNameToInclude : additionalFieldNamesToInclude) {
823
824 for (RemotableAttributeField searchAttributeField : searchAttributeFields) {
825 if (additionalFieldNameToInclude.equals(searchAttributeField.getName())) {
826 Column searchAttributeColumn = FieldUtils.constructColumnFromAttributeField(searchAttributeField);
827 wrapDocumentAttributeColumnName(searchAttributeColumn);
828 customColumns.add(searchAttributeColumn);
829 continue outer;
830 }
831 }
832 for (Column additionalAttributeColumn : additionalAttributeColumns) {
833 if (additionalFieldNameToInclude.equals(additionalAttributeColumn.getPropertyName())) {
834 wrapDocumentAttributeColumnName(additionalAttributeColumn);
835 customColumns.add(additionalAttributeColumn);
836 continue outer;
837 }
838 }
839 LOG.warn("Failed to locate a proper column definition for requested additional field to include in"
840 + "result set with name '"
841 + additionalFieldNameToInclude
842 + "'");
843 }
844 populateCustomColumns(customColumns, searchResult);
845
846
847 if (newColumns.isEmpty() || !StandardResultField.ROUTE_LOG.isFieldNameValid(newColumns.get(newColumns.size() - 1).getPropertyName())) {
848 newColumns.addAll(customColumns);
849 } else {
850 newColumns.addAll(newColumns.size() - 1, customColumns);
851 }
852 resultRow.setColumns(newColumns);
853 }
854
855 protected void populateCustomColumns(List<Column> customColumns, DocumentSearchResult searchResult) {
856 for (Column customColumn : customColumns) {
857 DocumentAttribute documentAttribute =
858 searchResult.getSingleDocumentAttributeByName(customColumn.getPropertyName());
859 if (documentAttribute != null && documentAttribute.getValue() != null) {
860 wrapDocumentAttributeColumnName(customColumn);
861
862 Formatter formatter = customColumn.getFormatter();
863 customColumn.setPropertyValue(formatter.format(documentAttribute.getValue()).toString());
864 }
865 }
866 }
867
868 private void wrapDocumentAttributeColumnName(Column column) {
869
870
871 }
872
873 public void setDocumentSearchService(DocumentSearchService documentSearchService) {
874 this.documentSearchService = documentSearchService;
875 }
876
877 public DocumentSearchService getDocumentSearchService() {
878 return documentSearchService;
879 }
880
881 public DocumentSearchCriteriaProcessor getDocumentSearchCriteriaProcessor() {
882 return documentSearchCriteriaProcessor;
883 }
884
885 public void setDocumentSearchCriteriaProcessor(DocumentSearchCriteriaProcessor documentSearchCriteriaProcessor) {
886 this.documentSearchCriteriaProcessor = documentSearchCriteriaProcessor;
887 }
888
889 public DocumentSearchCriteriaTranslator getDocumentSearchCriteriaTranslator() {
890 return documentSearchCriteriaTranslator;
891 }
892
893 public void setDocumentSearchCriteriaTranslator(DocumentSearchCriteriaTranslator documentSearchCriteriaTranslator) {
894 this.documentSearchCriteriaTranslator = documentSearchCriteriaTranslator;
895 }
896
897 }