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