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 link.setDisplayText("Route Log for document " + documentId);
491 String url = ConfigContext.getCurrentContextConfig().getProperty(Config.KEW_URL) + "/" +
492 "RouteLog.do?documentId=" + documentId;
493 link.setHref(url);
494 return link;
495 }
496
497
498
499
500 protected boolean isDocumentHandlerPopup() {
501 return BooleanUtils.toBooleanDefaultIfNull(
502 CoreFrameworkServiceLocator.getParameterService().getParameterValueAsBoolean(
503 KewApiConstants.KEW_NAMESPACE,
504 KRADConstants.DetailTypes.DOCUMENT_SEARCH_DETAIL_TYPE,
505 KewApiConstants.DOCUMENT_SEARCH_DOCUMENT_POPUP_IND),
506 DOCUMENT_HANDLER_POPUP_DEFAULT);
507 }
508
509
510
511
512 public boolean isRouteLogPopup() {
513 return BooleanUtils.toBooleanDefaultIfNull(
514 CoreFrameworkServiceLocator.getParameterService().getParameterValueAsBoolean(KewApiConstants.KEW_NAMESPACE,
515 KRADConstants.DetailTypes.DOCUMENT_SEARCH_DETAIL_TYPE,
516 KewApiConstants.DOCUMENT_SEARCH_ROUTE_LOG_POPUP_IND), ROUTE_LOG_POPUP_DEFAULT);
517 }
518
519
520
521
522 protected boolean isFlagSet(String flagName) {
523 if(this.getParameters().containsKey(flagName)) {
524 String[] params = (String[])this.getParameters().get(flagName);
525 if (ArrayUtils.isNotEmpty(params)) {
526 return "YES".equalsIgnoreCase(params[0]);
527 }
528 }
529 return false;
530 }
531
532
533
534
535 protected boolean isSuperUserSearch() {
536 return isFlagSet(DocumentSearchCriteriaProcessorKEWAdapter.SUPERUSER_SEARCH_FIELD);
537 }
538
539
540
541
542 protected boolean isAdvancedSearch() {
543 return isFlagSet(DocumentSearchCriteriaProcessorKEWAdapter.ADVANCED_SEARCH_FIELD);
544 }
545
546
547
548
549 protected boolean isClearSavedSearch() {
550 return isFlagSet(DocumentSearchCriteriaProcessorKEWAdapter.CLEARSAVED_SEARCH_FIELD);
551 }
552
553 protected String getSavedSearchName() {
554 String[] savedSearchName = getParameters().get(SAVED_SEARCH_NAME_PARAM);
555 if (savedSearchName != null && savedSearchName.length > 0) {
556 return savedSearchName[0];
557 }
558 return null;
559 }
560
561
562
563
564 @Override
565 protected void setRows() {
566 this.setRows(null);
567 }
568
569
570
571
572 protected FormFields getFormFields() {
573 return new FormFields(this.getRows());
574 }
575
576
577
578
579
580
581
582
583
584 protected void setRows(String documentTypeName) {
585
586 super.setRows();
587
588 List<Row> lookupRows = new ArrayList<Row>();
589
590 for (Row row : getRows()) {
591 lookupRows.add(row);
592 }
593
594 getRows().clear();
595
596 DocumentType docType = getValidDocumentType(documentTypeName);
597
598 boolean advancedSearch = isAdvancedSearch();
599 boolean superUserSearch = isSuperUserSearch();
600
601
602 List<Row> rows = getDocumentSearchCriteriaProcessor().getRows(docType,lookupRows, advancedSearch, superUserSearch);
603
604 BusinessObjectEntry boe = (BusinessObjectEntry) KRADServiceLocatorWeb.getDataDictionaryService().getDataDictionary().getBusinessObjectEntry(this.getBusinessObjectClass().getName());
605 int numCols = boe.getLookupDefinition().getNumOfColumns();
606 if(numCols == 0) {
607 numCols = KRADConstants.DEFAULT_NUM_OF_COLUMNS;
608 }
609
610 super.getRows().addAll(FieldUtils.wrapFields(new FormFields(rows).getFieldList(), numCols));
611
612 }
613
614
615
616
617
618
619 private DocumentType getValidDocumentType(String documentTypeName) {
620 if (StringUtils.isNotEmpty(documentTypeName)) {
621 DocumentType documentType = KEWServiceLocator.getDocumentTypeService().findByNameCaseInsensitive(documentTypeName.trim());
622 if (documentType != null && documentType.isActive()) {
623 return documentType;
624 }
625 }
626 return null;
627 }
628
629 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''/>";
630
631 @Override
632 public String getSupplementalMenuBar() {
633 boolean advancedSearch = isAdvancedSearch();
634 boolean superUserSearch = isSuperUserSearch();
635 StringBuilder suppMenuBar = new StringBuilder();
636
637
638
639
640 String type = advancedSearch ? "basic" : "detailed";
641 suppMenuBar.append(MessageFormat.format(TOGGLE_BUTTON, "toggleAdvancedSearch", KewApiConstants.WEBAPP_DIRECTORY, type, type));
642
643
644 suppMenuBar.append(" ");
645 suppMenuBar.append(MessageFormat.format(TOGGLE_BUTTON, "toggleSuperUserSearch", KewApiConstants.WEBAPP_DIRECTORY, superUserSearch ? "nonsupu" : "superuser", superUserSearch ? "non-superuser" : "superuser"));
646
647
648 suppMenuBar.append(" ");
649 suppMenuBar.append(MessageFormat.format(TOGGLE_BUTTON, DocumentSearchCriteriaProcessorKEWAdapter.CLEARSAVED_SEARCH_FIELD, KewApiConstants.WEBAPP_DIRECTORY, "clearsaved", "clear saved searches"));
650
651
652 suppMenuBar.append("<script type=\"text/javascript\">"
653 + " jQuery(document).ready(function () {"
654 + " jQuery(\"#documentTypeName\").blur(function () { validateDocTypeAndRefresh( this ); });"
655 + "});</script>");
656
657 return suppMenuBar.toString();
658 }
659
660 @Override
661 public boolean shouldDisplayHeaderNonMaintActions() {
662 return true;
663 }
664
665 @Override
666 public boolean shouldDisplayLookupCriteria() {
667 return true;
668 }
669
670
671
672
673
674 @Override
675 public boolean checkForAdditionalFields(Map<String, String> fieldValues) {
676 return checkForAdditionalFieldsForDocumentType(fieldValues.get(DOCUMENT_TYPE_NAME_PARAM));
677 }
678
679 private boolean checkForAdditionalFieldsMultiValued(Map<String, String[]> fieldValues) {
680 String[] valArray = fieldValues.get(DOCUMENT_TYPE_NAME_PARAM);
681 String val = null;
682 if (valArray != null && valArray.length > 0) {
683 val = valArray[0];
684 }
685 return checkForAdditionalFieldsForDocumentType(val);
686 }
687
688 private boolean checkForAdditionalFieldsForDocumentType(String documentTypeName) {
689 if (StringUtils.isNotBlank(documentTypeName)) {
690 setRows(documentTypeName);
691 }
692 return true;
693 }
694
695 @Override
696 public Field getExtraField() {
697 SavedSearchValuesFinder savedSearchValuesFinder = new SavedSearchValuesFinder();
698 List<KeyValue> savedSearchValues = savedSearchValuesFinder.getKeyValues();
699 Field savedSearch = new Field();
700 savedSearch.setPropertyName(SAVED_SEARCH_NAME_PARAM);
701 savedSearch.setFieldType(Field.DROPDOWN_SCRIPT);
702 savedSearch.setScript("customLookupChanged()");
703 savedSearch.setFieldValidValues(savedSearchValues);
704 savedSearch.setFieldLabel("Saved Searches");
705 return savedSearch;
706 }
707
708 @Override
709 public void performClear(LookupForm lookupForm) {
710 DocumentSearchCriteria criteria = loadCriteria(lookupForm.getFields());
711 super.performClear(lookupForm);
712 repopulateSearchTypeFlags();
713 DocumentType documentType = getValidDocumentType(criteria.getDocumentTypeName());
714 if (documentType != null) {
715 DocumentSearchCriteria clearedCriteria = documentSearchService.clearCriteria(documentType, criteria);
716 applyCriteriaChangesToFields(DocumentSearchCriteria.Builder.create(clearedCriteria));
717 }
718 }
719
720
721
722
723 protected void repopulateSearchTypeFlags() {
724 boolean advancedSearch = isAdvancedSearch();
725 boolean superUserSearch = isSuperUserSearch();
726 int fieldsRepopulated = 0;
727 Map<String, String[]> values = new HashMap<String, String[]>();
728 values.put(DocumentSearchCriteriaProcessorKEWAdapter.ADVANCED_SEARCH_FIELD, new String[] { advancedSearch ? "YES" : "NO" });
729 values.put(DocumentSearchCriteriaProcessorKEWAdapter.SUPERUSER_SEARCH_FIELD, new String[] { superUserSearch ? "YES" : "NO" });
730 getFormFields().setFieldValues(values);
731 }
732
733
734
735
736 protected void postProcessResults(Collection<ResultRow> resultRows, DocumentSearchResults searchResults) {
737 if (resultRows.size() != searchResults.getSearchResults().size()) {
738 throw new IllegalStateException("Encountered a mismatch between ResultRow items and document search results "
739 + resultRows.size() + " != " + searchResults.getSearchResults().size());
740 }
741 DocumentType documentType = getValidDocumentType(criteria.getDocumentTypeName());
742 DocumentSearchResultSetConfiguration resultSetConfiguration = null;
743 DocumentSearchCriteriaConfiguration criteriaConfiguration = null;
744 if (documentType != null) {
745 resultSetConfiguration = KEWServiceLocator.getDocumentSearchCustomizationMediator().customizeResultSetConfiguration(documentType, criteria);
746 criteriaConfiguration = KEWServiceLocator.getDocumentSearchCustomizationMediator().getDocumentSearchCriteriaConfiguration(documentType);
747 }
748 int index = 0;
749 for (ResultRow resultRow : resultRows) {
750 DocumentSearchResult searchResult = searchResults.getSearchResults().get(index);
751 executeColumnCustomization(resultRow, searchResult, resultSetConfiguration, criteriaConfiguration);
752 index++;
753 }
754 }
755
756
757
758
759
760 protected void executeColumnCustomization(ResultRow resultRow, DocumentSearchResult searchResult,
761 DocumentSearchResultSetConfiguration resultSetConfiguration,
762 DocumentSearchCriteriaConfiguration criteriaConfiguration) {
763 if (resultSetConfiguration == null) {
764 resultSetConfiguration = DocumentSearchResultSetConfiguration.Builder.create().build();
765 }
766 if (criteriaConfiguration == null) {
767 criteriaConfiguration = DocumentSearchCriteriaConfiguration.Builder.create().build();
768 }
769 List<StandardResultField> standardFieldsToRemove = resultSetConfiguration.getStandardResultFieldsToRemove();
770 if (standardFieldsToRemove == null) {
771 standardFieldsToRemove = Collections.emptyList();
772 }
773 List<Column> newColumns = new ArrayList<Column>();
774 for (Column standardColumn : resultRow.getColumns()) {
775 if (!standardFieldsToRemove.contains(StandardResultField.fromFieldName(standardColumn.getPropertyName()))) {
776 newColumns.add(standardColumn);
777
778
779 if (standardColumn.getPropertyName().equals(
780 KEWPropertyConstants.DOC_SEARCH_RESULT_PROPERTY_NAME_ROUTE_LOG)) {
781 standardColumn.setEscapeXMLValue(false);
782 }
783 }
784 }
785
786
787 List<RemotableAttributeField> searchAttributeFields = criteriaConfiguration.getFlattenedSearchAttributeFields();
788 List<String> additionalFieldNamesToInclude = new ArrayList<String>();
789 if (!resultSetConfiguration.isOverrideSearchableAttributes()) {
790 for (RemotableAttributeField searchAttributeField : searchAttributeFields) {
791
792
793 if (searchAttributeField.getAttributeLookupSettings() == null ||
794 searchAttributeField.getAttributeLookupSettings().isInResults()) {
795 additionalFieldNamesToInclude.add(searchAttributeField.getName());
796 }
797 }
798 }
799 if (resultSetConfiguration.getCustomFieldNamesToAdd() != null) {
800 additionalFieldNamesToInclude.addAll(resultSetConfiguration.getCustomFieldNamesToAdd());
801 }
802
803
804 List<Column> customColumns = new ArrayList<Column>();
805 List<Column> additionalAttributeColumns = FieldUtils.constructColumnsFromAttributeFields(resultSetConfiguration.getAdditionalAttributeFields());
806
807 outer:for (String additionalFieldNameToInclude : additionalFieldNamesToInclude) {
808
809 for (RemotableAttributeField searchAttributeField : searchAttributeFields) {
810 if (additionalFieldNameToInclude.equals(searchAttributeField.getName())) {
811 Column searchAttributeColumn = FieldUtils.constructColumnFromAttributeField(searchAttributeField);
812 wrapDocumentAttributeColumnName(searchAttributeColumn);
813 customColumns.add(searchAttributeColumn);
814 continue outer;
815 }
816 }
817 for (Column additionalAttributeColumn : additionalAttributeColumns) {
818 if (additionalFieldNameToInclude.equals(additionalAttributeColumn.getPropertyName())) {
819 wrapDocumentAttributeColumnName(additionalAttributeColumn);
820 customColumns.add(additionalAttributeColumn);
821 continue outer;
822 }
823 }
824 LOG.warn("Failed to locate a proper column definition for requested additional field to include in"
825 + "result set with name '"
826 + additionalFieldNameToInclude
827 + "'");
828 }
829 populateCustomColumns(customColumns, searchResult);
830
831
832 if (newColumns.isEmpty() || !StandardResultField.ROUTE_LOG.isFieldNameValid(newColumns.get(newColumns.size() - 1).getPropertyName())) {
833 newColumns.addAll(customColumns);
834 } else {
835 newColumns.addAll(newColumns.size() - 1, customColumns);
836 }
837 resultRow.setColumns(newColumns);
838 }
839
840 protected void populateCustomColumns(List<Column> customColumns, DocumentSearchResult searchResult) {
841 for (Column customColumn : customColumns) {
842 DocumentAttribute documentAttribute = searchResult.getSingleDocumentAttributeByName(customColumn.getPropertyName());
843 if (documentAttribute != null && documentAttribute.getValue() != null) {
844 wrapDocumentAttributeColumnName(customColumn);
845
846 Formatter formatter = customColumn.getFormatter();
847 customColumn.setPropertyValue(formatter.format(documentAttribute.getValue()).toString());
848 }
849 }
850 }
851
852 private void wrapDocumentAttributeColumnName(Column column) {
853
854
855 }
856
857 public void setDocumentSearchService(DocumentSearchService documentSearchService) {
858 this.documentSearchService = documentSearchService;
859 }
860
861 public DocumentSearchService getDocumentSearchService() {
862 return documentSearchService;
863 }
864
865 public DocumentSearchCriteriaProcessor getDocumentSearchCriteriaProcessor() {
866 return documentSearchCriteriaProcessor;
867 }
868
869 public void setDocumentSearchCriteriaProcessor(DocumentSearchCriteriaProcessor documentSearchCriteriaProcessor) {
870 this.documentSearchCriteriaProcessor = documentSearchCriteriaProcessor;
871 }
872
873 public DocumentSearchCriteriaTranslator getDocumentSearchCriteriaTranslator() {
874 return documentSearchCriteriaTranslator;
875 }
876
877 public void setDocumentSearchCriteriaTranslator(DocumentSearchCriteriaTranslator documentSearchCriteriaTranslator) {
878 this.documentSearchCriteriaTranslator = documentSearchCriteriaTranslator;
879 }
880 }