1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.kew.docsearch.service.impl;
17
18 import org.apache.commons.collections.CollectionUtils;
19 import org.apache.commons.lang.StringUtils;
20 import org.joda.time.DateTime;
21 import org.joda.time.MutableDateTime;
22 import org.kuali.rice.core.api.CoreApiServiceLocator;
23 import org.kuali.rice.core.api.config.property.ConfigContext;
24 import org.kuali.rice.core.api.config.property.ConfigurationService;
25 import org.kuali.rice.core.api.reflect.ObjectDefinition;
26 import org.kuali.rice.core.api.resourceloader.GlobalResourceLoader;
27 import org.kuali.rice.core.api.uif.RemotableAttributeError;
28 import org.kuali.rice.core.api.uif.RemotableAttributeField;
29 import org.kuali.rice.core.api.util.ConcreteKeyValue;
30 import org.kuali.rice.core.api.util.KeyValue;
31 import org.kuali.rice.kew.api.WorkflowRuntimeException;
32 import org.kuali.rice.kew.api.document.search.DocumentSearchCriteria;
33 import org.kuali.rice.kew.api.document.search.DocumentSearchResult;
34 import org.kuali.rice.kew.api.document.search.DocumentSearchResults;
35 import org.kuali.rice.kew.docsearch.DocumentSearchInternalUtils;
36 import org.kuali.rice.kew.docsearch.DocumentSearchCustomizationMediator;
37 import org.kuali.rice.kew.framework.document.search.AttributeFields;
38 import org.kuali.rice.kew.api.document.attribute.DocumentAttribute;
39 import org.kuali.rice.kew.api.document.attribute.DocumentAttributeFactory;
40 import org.kuali.rice.kew.docsearch.dao.DocumentSearchDAO;
41 import org.kuali.rice.kew.docsearch.service.DocumentSearchService;
42 import org.kuali.rice.kew.doctype.SecuritySession;
43 import org.kuali.rice.kew.doctype.bo.DocumentType;
44 import org.kuali.rice.kew.exception.WorkflowServiceError;
45 import org.kuali.rice.kew.exception.WorkflowServiceErrorException;
46 import org.kuali.rice.kew.exception.WorkflowServiceErrorImpl;
47 import org.kuali.rice.kew.framework.document.search.DocumentSearchCriteriaConfiguration;
48 import org.kuali.rice.kew.framework.document.search.DocumentSearchResultValue;
49 import org.kuali.rice.kew.framework.document.search.DocumentSearchResultValues;
50 import org.kuali.rice.kew.impl.document.search.DocumentSearchGenerator;
51 import org.kuali.rice.kew.impl.document.search.DocumentSearchGeneratorImpl;
52 import org.kuali.rice.kew.service.KEWServiceLocator;
53 import org.kuali.rice.kew.useroptions.UserOptions;
54 import org.kuali.rice.kew.useroptions.UserOptionsService;
55 import org.kuali.rice.kew.api.KewApiConstants;
56 import org.kuali.rice.kim.api.group.Group;
57 import org.kuali.rice.kim.api.services.KimApiServiceLocator;
58 import org.kuali.rice.krad.service.KRADServiceLocator;
59 import org.kuali.rice.krad.util.GlobalVariables;
60
61 import java.io.IOException;
62 import java.util.ArrayList;
63 import java.util.Collection;
64 import java.util.Collections;
65 import java.util.HashMap;
66 import java.util.HashSet;
67 import java.util.LinkedHashMap;
68 import java.util.List;
69 import java.util.Map;
70 import java.util.Set;
71
72 public class DocumentSearchServiceImpl implements DocumentSearchService {
73
74 private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(DocumentSearchServiceImpl.class);
75
76 private static final int MAX_SEARCH_ITEMS = 5;
77 private static final String LAST_SEARCH_ORDER_OPTION = "DocSearch.LastSearch.Order";
78 private static final String NAMED_SEARCH_ORDER_BASE = "DocSearch.NamedSearch.";
79 private static final String LAST_SEARCH_BASE_NAME = "DocSearch.LastSearch.Holding";
80
81 private volatile ConfigurationService kualiConfigurationService;
82 private DocumentSearchCustomizationMediator documentSearchCustomizationMediator;
83
84 private DocumentSearchDAO docSearchDao;
85 private UserOptionsService userOptionsService;
86
87 public void setDocumentSearchDAO(DocumentSearchDAO docSearchDao) {
88 this.docSearchDao = docSearchDao;
89 }
90
91 public void setUserOptionsService(UserOptionsService userOptionsService) {
92 this.userOptionsService = userOptionsService;
93 }
94
95 public void setDocumentSearchCustomizationMediator(DocumentSearchCustomizationMediator documentSearchCustomizationMediator) {
96 this.documentSearchCustomizationMediator = documentSearchCustomizationMediator;
97 }
98
99 protected DocumentSearchCustomizationMediator getDocumentSearchCustomizationMediator() {
100 return this.documentSearchCustomizationMediator;
101 }
102
103 public void clearNamedSearches(String principalId) {
104 String[] clearListNames = { NAMED_SEARCH_ORDER_BASE + "%", LAST_SEARCH_BASE_NAME + "%", LAST_SEARCH_ORDER_OPTION + "%" };
105 for (String clearListName : clearListNames)
106 {
107 List<UserOptions> records = userOptionsService.findByUserQualified(principalId, clearListName);
108 for (UserOptions userOptions : records) {
109 userOptionsService.deleteUserOptions((UserOptions) userOptions);
110 }
111 }
112 }
113
114 public DocumentSearchCriteria getNamedSearchCriteria(String principalId, String searchName) {
115 return getSavedSearchCriteria(principalId, NAMED_SEARCH_ORDER_BASE + searchName);
116 }
117
118 public DocumentSearchCriteria getSavedSearchCriteria(String principalId, String searchName) {
119 UserOptions savedSearch = userOptionsService.findByOptionId(searchName, principalId);
120 if (savedSearch == null) {
121 return null;
122 }
123 return getCriteriaFromSavedSearch(savedSearch);
124 }
125
126 protected DocumentSearchCriteria getCriteriaFromSavedSearch(UserOptions savedSearch) {
127 String optionValue = savedSearch.getOptionVal();
128 try {
129 return DocumentSearchInternalUtils.unmarshalDocumentSearchCriteria(optionValue);
130 } catch (IOException e) {
131 throw new WorkflowRuntimeException("Failed to load saved search for name '" + savedSearch.getOptionId() + "'", e);
132 }
133 }
134
135 private String getOptionCriteriaField(UserOptions userOption, String fieldName) {
136 String value = userOption.getOptionVal();
137 if (value != null) {
138 String[] fields = value.split(",,");
139 for (String field : fields)
140 {
141 if (field.startsWith(fieldName + "="))
142 {
143 return field.substring(field.indexOf(fieldName) + fieldName.length() + 1, field.length());
144 }
145 }
146 }
147 return null;
148 }
149
150 @Override
151 public DocumentSearchResults lookupDocuments(String principalId, DocumentSearchCriteria criteria) {
152 DocumentSearchGenerator docSearchGenerator = getStandardDocumentSearchGenerator();
153 DocumentType documentType = KEWServiceLocator.getDocumentTypeService().findByName(criteria.getDocumentTypeName());
154 DocumentSearchCriteria.Builder criteriaBuilder = DocumentSearchCriteria.Builder.create(criteria);
155 validateDocumentSearchCriteria(docSearchGenerator, criteriaBuilder);
156 DocumentSearchCriteria builtCriteria = applyCriteriaCustomizations(documentType, criteriaBuilder.build());
157 builtCriteria = applyCriteriaDefaults(builtCriteria);
158 boolean criteriaModified = !criteria.equals(builtCriteria);
159 List<RemotableAttributeField> searchFields = determineSearchFields(documentType);
160 DocumentSearchResults.Builder searchResults = docSearchDao.findDocuments(docSearchGenerator, builtCriteria, criteriaModified, searchFields);
161 if (documentType != null) {
162 DocumentSearchResultValues resultValues = getDocumentSearchCustomizationMediator().customizeResults(documentType, builtCriteria, searchResults.build());
163 if (resultValues != null && CollectionUtils.isNotEmpty(resultValues.getResultValues())) {
164 Map<String, DocumentSearchResultValue> resultValueMap = new HashMap<String, DocumentSearchResultValue>();
165 for (DocumentSearchResultValue resultValue : resultValues.getResultValues()) {
166 resultValueMap.put(resultValue.getDocumentId(), resultValue);
167 }
168 for (DocumentSearchResult.Builder result : searchResults.getSearchResults()) {
169 DocumentSearchResultValue value = resultValueMap.get(result.getDocument().getDocumentId());
170 if (value != null) {
171 applyResultCustomization(result, value);
172 }
173 }
174 }
175 }
176
177 if (StringUtils.isNotBlank(principalId) && !searchResults.getSearchResults().isEmpty()) {
178 DocumentSearchResults builtResults = searchResults.build();
179 Set<String> authorizedDocumentIds = KEWServiceLocator.getDocumentSecurityService().documentSearchResultAuthorized(
180 principalId, builtResults, new SecuritySession(principalId));
181 if (CollectionUtils.isNotEmpty(authorizedDocumentIds)) {
182 int numFiltered = 0;
183 List<DocumentSearchResult.Builder> finalResults = new ArrayList<DocumentSearchResult.Builder>();
184 for (DocumentSearchResult.Builder result : searchResults.getSearchResults()) {
185 if (authorizedDocumentIds.contains(result.getDocument().getDocumentId())) {
186 finalResults.add(result);
187 } else {
188 numFiltered++;
189 }
190 }
191 searchResults.setSearchResults(finalResults);
192 searchResults.setNumberOfSecurityFilteredResults(numFiltered);
193 } else {
194 searchResults.setNumberOfSecurityFilteredResults(searchResults.getSearchResults().size());
195 searchResults.setSearchResults(Collections.<DocumentSearchResult.Builder>emptyList());
196 }
197 }
198 saveSearch(principalId, builtCriteria);
199 return searchResults.build();
200 }
201
202 protected void applyResultCustomization(DocumentSearchResult.Builder result, DocumentSearchResultValue value) {
203 Map<String, List<DocumentAttribute.AbstractBuilder<?>>> customizedAttributeMap =
204 new LinkedHashMap<String, List<DocumentAttribute.AbstractBuilder<?>>>();
205 for (DocumentAttribute customizedAttribute : value.getDocumentAttributes()) {
206 List<DocumentAttribute.AbstractBuilder<?>> attributesForName = customizedAttributeMap.get(value.getDocumentId());
207 if (attributesForName == null) {
208 attributesForName = new ArrayList<DocumentAttribute.AbstractBuilder<?>>();
209 customizedAttributeMap.put(value.getDocumentId(), attributesForName);
210 }
211 attributesForName.add(DocumentAttributeFactory.loadContractIntoBuilder(customizedAttribute));
212 }
213
214 Set<String> documentAttributeNamesCustomized = new HashSet<String>();
215 List<DocumentAttribute.AbstractBuilder<?>> newDocumentAttributes = new ArrayList<DocumentAttribute.AbstractBuilder<?>>();
216 for (DocumentAttribute.AbstractBuilder<?> documentAttribute : result.getDocumentAttributes()) {
217 String name = documentAttribute.getName();
218 if (!documentAttributeNamesCustomized.contains(name) && customizedAttributeMap.containsKey(name)) {
219 documentAttributeNamesCustomized.add(name);
220 newDocumentAttributes.addAll(customizedAttributeMap.get(name));
221 }
222 }
223 }
224
225
226
227
228
229
230
231 protected DocumentSearchCriteria applyCriteriaCustomizations(DocumentType documentType, DocumentSearchCriteria criteria) {
232 if (documentType == null) {
233 return criteria;
234 }
235 DocumentSearchCriteria customizedCriteria = getDocumentSearchCustomizationMediator().customizeCriteria(documentType, criteria);
236 if (customizedCriteria != null) {
237 return customizedCriteria;
238 }
239 return criteria;
240 }
241
242 protected DocumentSearchCriteria applyCriteriaDefaults(DocumentSearchCriteria criteria) {
243 DocumentSearchCriteria.Builder comparisonCriteria = createEmptyComparisonCriteria(criteria);
244 boolean isCriteriaEmpty = criteria.equals(comparisonCriteria.build());
245 boolean isTitleOnly = false;
246 if (!isCriteriaEmpty) {
247 comparisonCriteria.setTitle(criteria.getTitle());
248 isTitleOnly = criteria.equals(comparisonCriteria.build());
249 }
250
251 if (isCriteriaEmpty || isTitleOnly) {
252 DocumentSearchCriteria.Builder criteriaBuilder = DocumentSearchCriteria.Builder.create(criteria);
253 Integer defaultCreateDateDaysAgoValue = null;
254 if (isCriteriaEmpty) {
255
256 defaultCreateDateDaysAgoValue = KewApiConstants.DOCUMENT_SEARCH_NO_CRITERIA_CREATE_DATE_DAYS_AGO;
257 } else if (isTitleOnly) {
258
259
260 defaultCreateDateDaysAgoValue = KewApiConstants.DOCUMENT_SEARCH_DOC_TITLE_CREATE_DATE_DAYS_AGO;
261 }
262 if (defaultCreateDateDaysAgoValue != null) {
263
264 MutableDateTime mutableDateTime = new MutableDateTime();
265 mutableDateTime.addDays(defaultCreateDateDaysAgoValue.intValue());
266 criteriaBuilder.setDateCreatedFrom(mutableDateTime.toDateTime());
267 }
268 criteria = criteriaBuilder.build();
269 }
270 return criteria;
271 }
272
273 protected DocumentSearchCriteria.Builder createEmptyComparisonCriteria(DocumentSearchCriteria criteria) {
274 DocumentSearchCriteria.Builder builder = DocumentSearchCriteria.Builder.create();
275
276 builder.setSaveName(criteria.getSaveName());
277 builder.setStartAtIndex(criteria.getStartAtIndex());
278 builder.setMaxResults(criteria.getMaxResults());
279 return builder;
280 }
281
282 protected List<RemotableAttributeField> determineSearchFields(DocumentType documentType) {
283 List<RemotableAttributeField> searchFields = new ArrayList<RemotableAttributeField>();
284 if (documentType != null) {
285 DocumentSearchCriteriaConfiguration searchConfiguration =
286 getDocumentSearchCustomizationMediator().getDocumentSearchCriteriaConfiguration(documentType);
287 if (searchConfiguration != null) {
288 List<AttributeFields> attributeFields = searchConfiguration.getSearchAttributeFields();
289 if (attributeFields != null) {
290 for (AttributeFields fields : attributeFields) {
291 searchFields.addAll(fields.getRemotableAttributeFields());
292 }
293 }
294 }
295 }
296 return searchFields;
297 }
298
299 public DocumentSearchGenerator getStandardDocumentSearchGenerator() {
300 String searchGeneratorClass = ConfigContext.getCurrentContextConfig().getProperty(KewApiConstants.STANDARD_DOC_SEARCH_GENERATOR_CLASS_CONFIG_PARM);
301 if (searchGeneratorClass == null){
302 return new DocumentSearchGeneratorImpl();
303 }
304 return (DocumentSearchGenerator)GlobalResourceLoader.getObject(new ObjectDefinition(searchGeneratorClass));
305 }
306
307 @Override
308 public void validateDocumentSearchCriteria(DocumentSearchGenerator docSearchGenerator, DocumentSearchCriteria.Builder criteria) {
309 List<WorkflowServiceError> errors = this.validateWorkflowDocumentSearchCriteria(criteria);
310 List<RemotableAttributeError> searchAttributeErrors = docSearchGenerator.validateSearchableAttributes(criteria);
311 if (!CollectionUtils.isEmpty(searchAttributeErrors)) {
312
313 for (RemotableAttributeError searchAttributeError : searchAttributeErrors) {
314 for (String errorMessage : searchAttributeError.getErrors()) {
315 WorkflowServiceError error = new WorkflowServiceErrorImpl(errorMessage, "error.custom", errorMessage);
316 errors.add(error);
317 }
318 }
319 }
320 if (!errors.isEmpty() || !GlobalVariables.getMessageMap().hasNoErrors()) {
321 throw new WorkflowServiceErrorException("Document Search Validation Errors", errors);
322 }
323 }
324
325 protected List<WorkflowServiceError> validateWorkflowDocumentSearchCriteria(DocumentSearchCriteria.Builder criteria) {
326 List<WorkflowServiceError> errors = new ArrayList<WorkflowServiceError>();
327
328
329
330 criteria.setApproverPrincipalName(trimCriteriaValue(criteria.getApproverPrincipalName()));
331 criteria.setViewerPrincipalName(trimCriteriaValue(criteria.getViewerPrincipalName()));
332 criteria.setInitiatorPrincipalName(trimCriteriaValue(criteria.getInitiatorPrincipalName()));
333 validateGroupCriteria(criteria, errors);
334 criteria.setDocumentId(criteria.getDocumentId());
335 return errors;
336 }
337
338 private String trimCriteriaValue(String criteriaValue) {
339 if (StringUtils.isNotBlank(criteriaValue)) {
340 criteriaValue = criteriaValue.trim();
341 }
342 if (StringUtils.isBlank(criteriaValue)) {
343 return null;
344 }
345 return criteriaValue;
346 }
347
348 private void validateGroupCriteria(DocumentSearchCriteria.Builder criteria, List<WorkflowServiceError> errors) {
349 if (StringUtils.isNotBlank(criteria.getViewerGroupId())) {
350 Group group = KimApiServiceLocator.getGroupService().getGroup(criteria.getViewerGroupId());
351 if (group == null) {
352 errors.add(new WorkflowServiceErrorImpl("Workgroup Viewer Name is not a workgroup", "docsearch.DocumentSearchService.workgroup.viewer"));
353 }
354 } else {
355 criteria.setViewerGroupId(null);
356 }
357 }
358
359 @Override
360 public List<KeyValue> getNamedSearches(String principalId) {
361 List<UserOptions> namedSearches = userOptionsService.findByUserQualified(principalId, NAMED_SEARCH_ORDER_BASE + "%");
362 List<KeyValue> sortedNamedSearches = new ArrayList<KeyValue>(0);
363 if (!namedSearches.isEmpty()) {
364 Collections.sort(namedSearches);
365 for (UserOptions namedSearch : namedSearches) {
366 KeyValue keyValue = new ConcreteKeyValue(namedSearch.getOptionId(), namedSearch.getOptionId().substring(NAMED_SEARCH_ORDER_BASE.length(), namedSearch.getOptionId().length()));
367 sortedNamedSearches.add(keyValue);
368 }
369 }
370 return sortedNamedSearches;
371 }
372
373 @Override
374 public List<KeyValue> getMostRecentSearches(String principalId) {
375 UserOptions order = userOptionsService.findByOptionId(LAST_SEARCH_ORDER_OPTION, principalId);
376 List<KeyValue> sortedMostRecentSearches = new ArrayList<KeyValue>();
377 if (order != null && order.getOptionVal() != null && !"".equals(order.getOptionVal())) {
378 List<UserOptions> mostRecentSearches = userOptionsService.findByUserQualified(principalId, LAST_SEARCH_BASE_NAME + "%");
379 String[] ordered = order.getOptionVal().split(",");
380 for (String anOrdered : ordered) {
381 UserOptions matchingOption = null;
382 for (UserOptions option : mostRecentSearches) {
383 if (anOrdered.equals(option.getOptionId())) {
384 matchingOption = option;
385 break;
386 }
387 }
388 if (matchingOption != null) {
389 DocumentSearchCriteria matchingCriteria = getCriteriaFromSavedSearch(matchingOption);
390 sortedMostRecentSearches.add(new ConcreteKeyValue(anOrdered, getSavedSearchAbbreviatedString(matchingCriteria)));
391 }
392 }
393 }
394 return sortedMostRecentSearches;
395 }
396
397 public DocumentSearchCriteria clearCriteria(DocumentType documentType, DocumentSearchCriteria criteria) {
398 DocumentSearchCriteria clearedCriteria = getDocumentSearchCustomizationMediator().customizeClearCriteria(
399 documentType, criteria);
400 if (clearedCriteria == null) {
401 clearedCriteria = getStandardDocumentSearchGenerator().clearSearch(criteria);
402 }
403 return clearedCriteria;
404 }
405
406 protected String getSavedSearchAbbreviatedString(DocumentSearchCriteria criteria) {
407 Map<String, String> abbreviatedStringMap = new LinkedHashMap<String, String>();
408 addAbbreviatedString(abbreviatedStringMap, "Doc Type", criteria.getDocumentTypeName());
409 addAbbreviatedString(abbreviatedStringMap, "Initiator", criteria.getInitiatorPrincipalName());
410 addAbbreviatedString(abbreviatedStringMap, "Doc Id", criteria.getDocumentId());
411 addAbbreviatedRangeString(abbreviatedStringMap, "Created", criteria.getDateCreatedFrom(),
412 criteria.getDateCreatedTo());
413 addAbbreviatedString(abbreviatedStringMap, "Title", criteria.getTitle());
414 addAbbreviatedString(abbreviatedStringMap, "App Doc Id", criteria.getApplicationDocumentId());
415 addAbbreviatedRangeString(abbreviatedStringMap, "Approved", criteria.getDateApprovedFrom(),
416 criteria.getDateApprovedTo());
417 addAbbreviatedRangeString(abbreviatedStringMap, "Modified", criteria.getDateLastModifiedFrom(), criteria.getDateLastModifiedTo());
418 addAbbreviatedRangeString(abbreviatedStringMap, "Finalized", criteria.getDateFinalizedFrom(), criteria.getDateFinalizedTo());
419 addAbbreviatedRangeString(abbreviatedStringMap, "App Doc Status Changed", criteria.getDateApplicationDocumentStatusChangedFrom(), criteria.getDateApplicationDocumentStatusChangedTo());
420 addAbbreviatedString(abbreviatedStringMap, "Approver", criteria.getApproverPrincipalName());
421 addAbbreviatedString(abbreviatedStringMap, "Viewer", criteria.getViewerPrincipalName());
422 addAbbreviatedString(abbreviatedStringMap, "Group Viewer", criteria.getViewerGroupId());
423 addAbbreviatedString(abbreviatedStringMap, "Node", criteria.getRouteNodeName());
424 addAbbreviatedMultiValuedString(abbreviatedStringMap, "Status", criteria.getDocumentStatuses());
425 addAbbreviatedMultiValuedString(abbreviatedStringMap, "Category", criteria.getDocumentStatusCategories());
426 for (String documentAttributeName : criteria.getDocumentAttributeValues().keySet()) {
427 addAbbreviatedMultiValuedString(abbreviatedStringMap, documentAttributeName, criteria.getDocumentAttributeValues().get(documentAttributeName));
428 }
429 StringBuilder stringBuilder = new StringBuilder();
430 int iteration = 0;
431 for (String label : abbreviatedStringMap.keySet()) {
432 stringBuilder.append(label).append("=").append(abbreviatedStringMap.get(label));
433 if (iteration < abbreviatedStringMap.keySet().size()) {
434 stringBuilder.append("; ");
435 }
436 }
437 return stringBuilder.toString();
438 }
439
440 protected void addAbbreviatedString(Map<String, String> abbreviatedStringMap, String label, String value) {
441 if (StringUtils.isNotBlank(value)) {
442 abbreviatedStringMap.put(label, value);
443 }
444 }
445
446 protected void addAbbreviatedMultiValuedString(Map<String, String> abbreviatedStringMap, String label, Collection<? extends Object> values) {
447 if (CollectionUtils.isNotEmpty(values)) {
448 List<String> stringValues = new ArrayList<String>();
449 for (Object value : values) {
450 stringValues.add(value.toString());
451 }
452 abbreviatedStringMap.put(label, StringUtils.join(stringValues, ","));
453 }
454 }
455
456 protected void addAbbreviatedRangeString(Map<String, String> abbreviatedStringMap, String label, DateTime dateFrom, DateTime dateTo) {
457 if (dateFrom != null || dateTo != null) {
458 StringBuilder abbreviatedString = new StringBuilder();
459 if (dateFrom != null) {
460 abbreviatedString.append(CoreApiServiceLocator.getDateTimeService().toDateString(dateFrom.toDate()));
461 }
462 abbreviatedString.append("..");
463 if (dateTo != null) {
464 abbreviatedString.append(CoreApiServiceLocator.getDateTimeService().toDateString(dateTo.toDate()));
465 }
466 abbreviatedStringMap.put(label, abbreviatedString.toString());
467 }
468 }
469
470
471
472
473
474
475
476
477
478 private void saveSearch(String principalId, DocumentSearchCriteria criteria) {
479 if (StringUtils.isBlank(principalId)) {
480 return;
481 }
482
483
484
485 try {
486 String savedSearchString = DocumentSearchInternalUtils.marshalDocumentSearchCriteria(criteria);
487
488 if (StringUtils.isNotBlank(criteria.getSaveName())) {
489 userOptionsService.save(principalId, NAMED_SEARCH_ORDER_BASE + criteria.getSaveName(), savedSearchString);
490 } else {
491
492 UserOptions searchOrder = userOptionsService.findByOptionId(LAST_SEARCH_ORDER_OPTION, principalId);
493
494 if (searchOrder == null) {
495 userOptionsService.save(principalId, LAST_SEARCH_BASE_NAME + "0", savedSearchString);
496 userOptionsService.save(principalId, LAST_SEARCH_ORDER_OPTION, LAST_SEARCH_BASE_NAME + "0");
497 } else {
498 String[] currentOrder = searchOrder.getOptionVal().split(",");
499
500 if (currentOrder.length == MAX_SEARCH_ITEMS) {
501
502
503
504 String searchName = currentOrder[currentOrder.length - 1];
505 String[] newOrder = new String[MAX_SEARCH_ITEMS];
506 newOrder[0] = searchName;
507 for (int i = 0; i < currentOrder.length - 1; i++) {
508 newOrder[i + 1] = currentOrder[i];
509 }
510
511 String newSearchOrder = "";
512 for (String aNewOrder : newOrder) {
513 if (!"".equals(newSearchOrder)) {
514 newSearchOrder += ",";
515 }
516 newSearchOrder += aNewOrder;
517 }
518
519 userOptionsService.save(principalId, searchName, savedSearchString);
520 userOptionsService.save(principalId, LAST_SEARCH_ORDER_OPTION, newSearchOrder);
521 } else {
522
523
524
525
526 int absMax = 0;
527 for (String aCurrentOrder : currentOrder) {
528 int current = new Integer(aCurrentOrder.substring(LAST_SEARCH_BASE_NAME.length(),
529 aCurrentOrder.length()));
530 if (current > absMax) {
531 absMax = current;
532 }
533 }
534 String searchName = LAST_SEARCH_BASE_NAME + ++absMax;
535 String[] newOrder = new String[currentOrder.length + 1];
536 newOrder[0] = searchName;
537 for (int i = 0; i < currentOrder.length; i++) {
538 newOrder[i + 1] = currentOrder[i];
539 }
540 String newSearchOrder = "";
541 for (String aNewOrder : newOrder) {
542 if (!"".equals(newSearchOrder)) {
543 newSearchOrder += ",";
544 }
545 newSearchOrder += aNewOrder;
546 }
547 userOptionsService.save(principalId, searchName, savedSearchString);
548 userOptionsService.save(principalId, LAST_SEARCH_ORDER_OPTION, newSearchOrder);
549 }
550 }
551 }
552 } catch (Exception e) {
553
554
555 LOG.error("Unable to save search due to exception", e);
556 }
557 }
558
559 public ConfigurationService getKualiConfigurationService() {
560 if (kualiConfigurationService == null) {
561 kualiConfigurationService = KRADServiceLocator.getKualiConfigurationService();
562 }
563 return kualiConfigurationService;
564 }
565
566 }