View Javadoc
1   /**
2    * Copyright 2005-2011 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.rice.kew.docsearch;
17  
18  import org.apache.commons.lang.StringUtils;
19  import org.joda.time.DateTime;
20  import org.joda.time.Days;
21  import org.joda.time.Years;
22  import org.junit.Test;
23  import org.kuali.rice.kew.api.KewApiConstants;
24  import org.kuali.rice.kew.api.WorkflowDocument;
25  import org.kuali.rice.kew.api.WorkflowDocumentFactory;
26  import org.kuali.rice.kew.api.action.RequestedActions;
27  import org.kuali.rice.kew.api.document.Document;
28  import org.kuali.rice.kew.api.document.DocumentStatus;
29  import org.kuali.rice.kew.api.document.DocumentStatusCategory;
30  import org.kuali.rice.kew.api.document.search.DocumentSearchCriteria;
31  import org.kuali.rice.kew.api.document.search.DocumentSearchResult;
32  import org.kuali.rice.kew.api.document.search.DocumentSearchResults;
33  import org.kuali.rice.kew.api.document.search.RouteNodeLookupLogic;
34  import org.kuali.rice.kew.docsearch.service.DocumentSearchService;
35  import org.kuali.rice.kew.doctype.bo.DocumentType;
36  import org.kuali.rice.kew.doctype.service.DocumentTypeService;
37  import org.kuali.rice.kew.engine.node.RouteNode;
38  import org.kuali.rice.kew.service.KEWServiceLocator;
39  import org.kuali.rice.kew.test.KEWTestCase;
40  import org.kuali.rice.kew.useroptions.UserOptions;
41  import org.kuali.rice.kew.useroptions.UserOptionsService;
42  import org.kuali.rice.kim.api.identity.Person;
43  import org.kuali.rice.kim.api.services.KimApiServiceLocator;
44  import org.kuali.rice.test.BaselineTestCase;
45  import org.kuali.rice.test.TestHarnessServiceLocator;
46  import org.springframework.jdbc.core.JdbcTemplate;
47  
48  import java.util.Arrays;
49  import java.util.Collection;
50  import java.util.HashMap;
51  import java.util.Iterator;
52  import java.util.List;
53  import java.util.Map;
54  import java.util.Set;
55  
56  import static org.junit.Assert.*;
57  
58  @BaselineTestCase.BaselineMode(BaselineTestCase.Mode.CLEAR_DB)
59  public class DocumentSearchTest extends KEWTestCase {
60      private static final String KREW_DOC_HDR_T = "KREW_DOC_HDR_T";
61      private static final String INITIATOR_COL = "INITR_PRNCPL_ID";
62  
63      DocumentSearchService docSearchService;
64      UserOptionsService userOptionsService;
65  
66      @Override
67      protected void loadTestData() throws Exception {
68          loadXmlFile("SearchAttributeConfig.xml");
69      }
70  
71      @Override
72      protected void setUpAfterDataLoad() throws Exception {
73          docSearchService = (DocumentSearchService)KEWServiceLocator.getDocumentSearchService();
74          userOptionsService = (UserOptionsService)KEWServiceLocator.getUserOptionsService();
75      }
76  
77  
78      @Test public void testDocSearch() throws Exception {
79          Person user = KimApiServiceLocator.getPersonService().getPersonByPrincipalName("bmcgough");
80          DocumentSearchCriteria.Builder criteria = DocumentSearchCriteria.Builder.create();
81          DocumentSearchResults results = null;
82          criteria.setTitle("*IN");
83          criteria.setSaveName("bytitle");
84          results = docSearchService.lookupDocuments(user.getPrincipalId(), criteria.build());
85          criteria = DocumentSearchCriteria.Builder.create();
86          criteria.setTitle("*IN-CFSG");
87          criteria.setSaveName("for in accounts");
88          results = docSearchService.lookupDocuments(user.getPrincipalId(), criteria.build());
89          criteria = DocumentSearchCriteria.Builder.create();
90          criteria.setDateApprovedFrom(new DateTime(2004, 9, 16, 0, 0));
91          results = docSearchService.lookupDocuments(user.getPrincipalId(), criteria.build());
92          criteria = DocumentSearchCriteria.Builder.create();
93          user = KimApiServiceLocator.getPersonService().getPersonByPrincipalName("bmcgough");
94          DocumentSearchCriteria savedCriteria = docSearchService.getNamedSearchCriteria(user.getPrincipalId(), "bytitle");
95          assertNotNull(savedCriteria);
96          assertEquals("bytitle", savedCriteria.getSaveName());
97          savedCriteria = docSearchService.getNamedSearchCriteria(user.getPrincipalId(), "for in accounts");
98          assertNotNull(savedCriteria);
99          assertEquals("for in accounts", savedCriteria.getSaveName());
100     }
101 
102     // KULRICE-5755 tests that the Document in the DocumentResult is properly populated
103     @Test public void testDocSearchDocumentResult() throws Exception {
104         String[] docIds = routeTestDocs();
105         Person user = KimApiServiceLocator.getPersonService().getPersonByPrincipalName("bmcgough");
106         DocumentSearchCriteria.Builder criteria = DocumentSearchCriteria.Builder.create();
107         DocumentSearchResults results = docSearchService.lookupDocuments(user.getPrincipalId(), criteria.build());
108         assertEquals(3, results.getSearchResults().size());
109         DocumentSearchResult result = results.getSearchResults().get(0);
110         Document doc = result.getDocument();
111 
112         // check all the DocumentContract properties
113         assertNotNull(doc.getApplicationDocumentStatus());
114         assertNotNull(doc.getApplicationDocumentStatusDate());
115         assertNotNull(doc.getDateApproved());
116         assertNotNull(doc.getDateCreated());
117         assertNotNull(doc.getDateFinalized());
118         assertNotNull(doc.getDocumentId());
119         assertNotNull(doc.getDocumentTypeName());
120         assertNotNull(doc.getApplicationDocumentId());
121         assertNotNull(doc.getDateLastModified());
122         assertNotNull(doc.getDocumentHandlerUrl());
123         assertNotNull(doc.getDocumentTypeId());
124         assertNotNull(doc.getInitiatorPrincipalId());
125         assertNotNull(doc.getRoutedByPrincipalId());
126         assertNotNull(doc.getStatus());
127         assertNotNull(doc.getTitle());
128         // route variables are currently excluded
129         assertTrue(doc.getVariables().isEmpty());
130     }
131 
132     @Test public void testDocSearch_appDocStatuses() throws Exception {
133         String[] docIds = routeTestDocs();
134 
135         DateTime now = DateTime.now();
136         DateTime before = now.minusDays(2);
137         DateTime after = now.plusDays(2);
138 
139         String principalId = getPrincipalId("bmcgough");
140 
141         // first test basic multi-appDocStatus search without dates.  search for 2 out of 3 existing statuses
142 
143         List<String> appDocStatusSearch = Arrays.asList("Submitted", "Pending");
144         DocumentSearchResults results = doAppStatusDocSearch(principalId, appDocStatusSearch, null, null);
145 
146         assertEquals("should have matched one doc for each status", 2, results.getSearchResults().size());
147 
148         for (DocumentSearchResult result : results.getSearchResults()) {
149             assertTrue("app doc status should be in " + StringUtils.join(appDocStatusSearch, ", "),
150                     appDocStatusSearch.contains(result.getDocument().getApplicationDocumentStatus()));
151         }
152 
153         // use times to verify app doc status change date functionality
154 
155         // first try to bring all 3 docs back with a range that includes all the test docs
156 
157         appDocStatusSearch = Arrays.asList("Submitted", "Pending", "Completed");
158         results = doAppStatusDocSearch(principalId, appDocStatusSearch, before, after);
159 
160         assertEquals("all docs are in the date range, should have matched them all", 3, results.getSearchResults().size());
161 
162         for (DocumentSearchResult result : results.getSearchResults()) {
163             assertTrue("app doc status should be in " + StringUtils.join(appDocStatusSearch, ", "),
164                     appDocStatusSearch.contains(result.getDocument().getApplicationDocumentStatus()));
165         }
166 
167         // test that the app doc status list still limits the results when a date range is set
168 
169         appDocStatusSearch = Arrays.asList("Submitted", "Pending");
170 
171         results = doAppStatusDocSearch(principalId, appDocStatusSearch, before, after);
172         assertEquals("should have matched one doc for each status", 2, results.getSearchResults().size());
173 
174         for (DocumentSearchResult result : results.getSearchResults()) {
175             assertTrue("app doc status should be in " + StringUtils.join(appDocStatusSearch, ", "),
176                     appDocStatusSearch.contains(result.getDocument().getApplicationDocumentStatus()));
177         }
178 
179         // test that the date range limits the results too.  No docs will be in this range.
180 
181         appDocStatusSearch = Arrays.asList("Submitted", "Pending", "Completed");
182 
183         results = doAppStatusDocSearch(principalId, appDocStatusSearch, after, after.plusDays(1));
184         assertEquals("none of the docs should be in the date range", 0, results.getSearchResults().size());
185 
186         // finally, test a legacy form of the search to make sure that the criteria is still respected
187 
188         DocumentSearchCriteria.Builder criteria = DocumentSearchCriteria.Builder.create();
189         criteria.setDocumentTypeName("SearchDocType");
190         criteria.setApplicationDocumentStatus("Submitted");
191 
192         results = docSearchService.lookupDocuments(principalId, criteria.build());
193         assertEquals("legacy style app doc status search should have matched one document",
194                 1, results.getSearchResults().size());
195         assertTrue("app doc status should match the search criteria",
196                 "Submitted".equals(results.getSearchResults().get(0).getDocument().getApplicationDocumentStatus()));
197     }
198 
199     private DocumentSearchResults doAppStatusDocSearch(String principalId, List<String> appDocStatuses,
200             DateTime appStatusChangedFrom, DateTime appStatusChangedTo) {
201         DocumentSearchCriteria.Builder criteria = DocumentSearchCriteria.Builder.create();
202         criteria.setDocumentTypeName("SearchDocType");
203         criteria.setApplicationDocumentStatuses(appDocStatuses);
204         criteria.setDateApplicationDocumentStatusChangedFrom(appStatusChangedFrom);
205         criteria.setDateApplicationDocumentStatusChangedTo(appStatusChangedTo);
206         return docSearchService.lookupDocuments(principalId, criteria.build());
207     }
208 
209     @Test public void testDocSearch_maxResults() throws Exception {
210         String[] docIds = routeTestDocs();
211 
212         String principalId = getPrincipalId("bmcgough");
213 
214         DocumentSearchCriteria.Builder criteria = DocumentSearchCriteria.Builder.create();
215         criteria.setDocumentTypeName("SearchDocType");
216         criteria.setMaxResults(5);
217         DocumentSearchResults results = docSearchService.lookupDocuments(principalId, criteria.build());
218         assertEquals(3, results.getSearchResults().size());
219         criteria.setMaxResults(2);
220         results = docSearchService.lookupDocuments(principalId, criteria.build());
221         assertEquals(2, results.getSearchResults().size());
222 
223         // test search result document population
224         // break out into separate test if/when we have more fields to test
225         assertEquals("_blank", results.getSearchResults().get(0).getDocument().getDocumentHandlerUrl());
226     }
227 
228     @Test public void testDocSearch_maxResultsIsNull() throws Exception {
229         String[] docIds = routeTestDocs();
230 
231         String principalId = getPrincipalId("bmcgough");
232 
233         DocumentSearchCriteria.Builder criteria = DocumentSearchCriteria.Builder.create();
234         criteria.setDocumentTypeName("SearchDocType");
235         criteria.setMaxResults(5);
236         DocumentSearchResults results = docSearchService.lookupDocuments(principalId, criteria.build());
237         assertEquals(3, results.getSearchResults().size());
238         criteria.setMaxResults(null);
239         results = docSearchService.lookupDocuments(principalId, criteria.build());
240         assertEquals(3, results.getSearchResults().size());
241     }
242 
243     @Test public void testDocSearch_maxResultsIsZero() throws Exception {
244         String[] docIds = routeTestDocs();
245 
246         String principalId = getPrincipalId("bmcgough");
247 
248         DocumentSearchCriteria.Builder criteria = DocumentSearchCriteria.Builder.create();
249         criteria.setDocumentTypeName("SearchDocType");
250         criteria.setMaxResults(5);
251         DocumentSearchResults results = docSearchService.lookupDocuments(principalId, criteria.build());
252         assertEquals(3, results.getSearchResults().size());
253         criteria.setMaxResults(0);
254         results = docSearchService.lookupDocuments(principalId, criteria.build());
255         assertEquals(0, results.getSearchResults().size());
256     }
257 
258     @Test public void testDocSearch_startAtIndex() throws Exception {
259         String[] docIds = routeTestDocs();
260 
261         String principalId = getPrincipalId("bmcgough");
262 
263         DocumentSearchCriteria.Builder criteria = DocumentSearchCriteria.Builder.create();
264         criteria.setDocumentTypeName("SearchDocType");
265         criteria.setMaxResults(5);
266         DocumentSearchResults results = docSearchService.lookupDocuments(principalId, criteria.build());
267         assertEquals(3, results.getSearchResults().size());
268         criteria.setStartAtIndex(1);
269         results = docSearchService.lookupDocuments(principalId, criteria.build());
270         assertEquals(2, results.getSearchResults().size());
271     }
272 
273     @Test public void testDocSearch_startAtIndexMoreThanResuls() throws Exception {
274         String[] docIds = routeTestDocs();
275 
276         String principalId = getPrincipalId("bmcgough");
277 
278         DocumentSearchCriteria.Builder criteria = DocumentSearchCriteria.Builder.create();
279         criteria.setDocumentTypeName("SearchDocType");
280         criteria.setMaxResults(5);
281         DocumentSearchResults results = docSearchService.lookupDocuments(principalId, criteria.build());
282         assertEquals(3, results.getSearchResults().size());
283         criteria.setStartAtIndex(5);
284         results = docSearchService.lookupDocuments(principalId, criteria.build());
285         assertEquals(0, results.getSearchResults().size());
286 
287     }
288 
289     @Test public void testDocSearch_startAtIndexNegative() throws Exception {
290         String[] docIds = routeTestDocs();
291 
292         String principalId = getPrincipalId("bmcgough");
293 
294         DocumentSearchCriteria.Builder criteria = DocumentSearchCriteria.Builder.create();
295         criteria.setDocumentTypeName("SearchDocType");
296         criteria.setMaxResults(5);
297         DocumentSearchResults results = docSearchService.lookupDocuments(principalId, criteria.build());
298         assertEquals(3, results.getSearchResults().size());
299         criteria.setStartAtIndex(-1);
300         results = docSearchService.lookupDocuments(principalId, criteria.build());
301         assertEquals(0, results.getSearchResults().size());
302 
303     }
304 
305     @Test public void testDocSearch_startAtIndexZero() throws Exception {
306         String[] docIds = routeTestDocs();
307 
308         String principalId = getPrincipalId("bmcgough");
309 
310         DocumentSearchCriteria.Builder criteria = DocumentSearchCriteria.Builder.create();
311         criteria.setDocumentTypeName("SearchDocType");
312         criteria.setMaxResults(5);
313         DocumentSearchResults results = docSearchService.lookupDocuments(principalId, criteria.build());
314         assertEquals(3, results.getSearchResults().size());
315         criteria.setStartAtIndex(0);
316         results = docSearchService.lookupDocuments(principalId, criteria.build());
317         assertEquals(3, results.getSearchResults().size());
318 
319     }
320 
321     /**
322      * Tests that performing a search automatically saves the last search criteria
323      */
324     @Test public void testUnnamedDocSearchPersistence() throws Exception {
325         Person user = KimApiServiceLocator.getPersonService().getPersonByPrincipalName("bmcgough");
326         Collection<UserOptions> allUserOptions_before = userOptionsService.findByWorkflowUser(user.getPrincipalId());
327         List<UserOptions> namedSearches_before = userOptionsService.findByUserQualified(user.getPrincipalId(), "DocSearch.NamedSearch.%");
328 
329         assertEquals(0, namedSearches_before.size());
330         assertEquals(0, allUserOptions_before.size());
331 
332         DocumentSearchCriteria.Builder criteria = DocumentSearchCriteria.Builder.create();
333         criteria.setTitle("*IN");
334         criteria.setDateCreatedFrom(DateTime.now().minus(Years.ONE)); // otherwise one is set for us
335         DocumentSearchCriteria c1 = criteria.build();
336         DocumentSearchResults results = docSearchService.lookupDocuments(user.getPrincipalId(), c1);
337 
338         Collection<UserOptions> allUserOptions_after = userOptionsService.findByWorkflowUser(user.getPrincipalId());
339         List<UserOptions> namedSearches_after = userOptionsService.findByUserQualified(user.getPrincipalId(), "DocSearch.NamedSearch.%");
340 
341         // saves the "last doc search criteria"
342         // and a pointer to the "last doc search criteria"
343         assertEquals(allUserOptions_before.size() + 2, allUserOptions_after.size());
344         assertEquals(namedSearches_before.size(), namedSearches_after.size());
345 
346         assertEquals("DocSearch.LastSearch.Holding0", userOptionsService.findByOptionId("DocSearch.LastSearch.Order".toString(), user.getPrincipalId()).getOptionVal());
347         assertEquals(marshall(c1), userOptionsService.findByOptionId("DocSearch.LastSearch.Holding0", user.getPrincipalId()).getOptionVal());
348 
349         // 2nd search
350 
351         criteria = DocumentSearchCriteria.Builder.create();
352         criteria.setTitle("*IN-CFSG*");
353         criteria.setDateCreatedFrom(DateTime.now().minus(Years.ONE)); // otherwise one is set for us
354         DocumentSearchCriteria c2 = criteria.build();
355         results = docSearchService.lookupDocuments(user.getPrincipalId(), c2);
356 
357         // still only 2 more user options
358         assertEquals(allUserOptions_before.size() + 2, allUserOptions_after.size());
359         assertEquals(namedSearches_before.size(), namedSearches_after.size());
360 
361         assertEquals("DocSearch.LastSearch.Holding1,DocSearch.LastSearch.Holding0", userOptionsService.findByOptionId("DocSearch.LastSearch.Order", user.getPrincipalId()).getOptionVal());
362         assertEquals(marshall(c1), userOptionsService.findByOptionId("DocSearch.LastSearch.Holding0", user.getPrincipalId()).getOptionVal());
363         assertEquals(marshall(c2), userOptionsService.findByOptionId("DocSearch.LastSearch.Holding1", user.getPrincipalId()).getOptionVal());
364     }
365 
366      /**
367      * Tests that performing a named search automatically saves the last search criteria as well as named search
368      */
369     @Test public void testNamedDocSearchPersistence() throws Exception {
370         Person user = KimApiServiceLocator.getPersonService().getPersonByPrincipalName("bmcgough");
371         Collection<UserOptions> allUserOptions_before = userOptionsService.findByWorkflowUser(user.getPrincipalId());
372         List<UserOptions> namedSearches_before = userOptionsService.findByUserQualified(user.getPrincipalId(), "DocSearch.NamedSearch.%");
373 
374         DocumentSearchCriteria.Builder criteria = DocumentSearchCriteria.Builder.create();
375         criteria.setTitle("*IN");
376         criteria.setSaveName("bytitle");
377         criteria.setDateCreatedFrom(DateTime.now().minus(Years.ONE)); // otherwise one is set for us
378         DocumentSearchCriteria c1 = criteria.build();
379         DocumentSearchResults results = docSearchService.lookupDocuments(user.getPrincipalId(), c1);
380 
381         Collection<UserOptions> allUserOptions_after = userOptionsService.findByWorkflowUser(user.getPrincipalId());
382         List<UserOptions> namedSearches_after = userOptionsService.findByUserQualified(user.getPrincipalId(), "DocSearch.NamedSearch.%");
383 
384         assertEquals(allUserOptions_before.size() + 1, allUserOptions_after.size());
385         assertEquals(namedSearches_before.size() + 1, namedSearches_after.size());
386 
387         assertEquals(marshall(c1), userOptionsService.findByOptionId("DocSearch.NamedSearch." + criteria.getSaveName(), user.getPrincipalId()).getOptionVal());
388 
389         // second search
390         criteria = DocumentSearchCriteria.Builder.create();
391         criteria.setTitle("*IN");
392         criteria.setSaveName("bytitle2");
393         criteria.setDateCreatedFrom(DateTime.now().minus(Years.ONE)); // otherwise one is set for us
394         DocumentSearchCriteria c2 = criteria.build();
395         results = docSearchService.lookupDocuments(user.getPrincipalId(), c2);
396 
397         allUserOptions_after = userOptionsService.findByWorkflowUser(user.getPrincipalId());
398         namedSearches_after = userOptionsService.findByUserQualified(user.getPrincipalId(), "DocSearch.NamedSearch.%");
399 
400         // saves a second named search
401         assertEquals(allUserOptions_before.size() + 2, allUserOptions_after.size());
402         assertEquals(namedSearches_before.size() + 2, namedSearches_after.size());
403 
404         assertEquals(marshall(c2), userOptionsService.findByOptionId("DocSearch.NamedSearch." + criteria.getSaveName(), user.getPrincipalId()).getOptionVal());
405 
406     }
407 
408     protected static String marshall(DocumentSearchCriteria criteria) throws Exception {
409         return DocumentSearchInternalUtils.marshalDocumentSearchCriteria(criteria);
410     }
411 
412     @Test
413     public void testDocSearch_criteriaModified() throws Exception {
414         String principalId = getPrincipalId("ewestfal");
415 
416         // if no criteria is specified, the dateCreatedFrom is defaulted to today
417         DocumentSearchCriteria.Builder criteria = DocumentSearchCriteria.Builder.create();
418         DocumentSearchResults results = docSearchService.lookupDocuments(principalId, criteria.build());
419         assertTrue("criteria should have been modified", results.isCriteriaModified());
420         assertNull("original date created from should have been null", criteria.getDateCreatedFrom());
421         assertNotNull("modified date created from should be non-null", results.getCriteria().getDateCreatedFrom());
422         assertEquals("Criteria date minus today's date should equal the constant value",
423                 KewApiConstants.DOCUMENT_SEARCH_NO_CRITERIA_CREATE_DATE_DAYS_AGO.intValue(),
424                 getDifferenceInDays(results.getCriteria().getDateCreatedFrom()));
425 
426         // now set some attributes which should still result in modified criteria since they don't count toward
427         // determining if the criteria is empty or not
428         criteria.setMaxResults(new Integer(50));
429         criteria.setSaveName("myRadSearch");
430         results = docSearchService.lookupDocuments(principalId, criteria.build());
431         assertTrue("criteria should have been modified", results.isCriteriaModified());
432         assertNotNull("modified date created from should be non-null", results.getCriteria().getDateCreatedFrom());
433 
434         // now set the title, when only title is specified, date created from is defaulted
435         criteria.setTitle("My rad title search!");
436         results = docSearchService.lookupDocuments(principalId, criteria.build());
437         assertTrue("criteria should have been modified", results.isCriteriaModified());
438         assertNotNull("modified date created from should be non-null", results.getCriteria().getDateCreatedFrom());
439         assertEquals("Criteria date minus today's date should equal the constant value",
440                 Math.abs(KewApiConstants.DOCUMENT_SEARCH_DOC_TITLE_CREATE_DATE_DAYS_AGO.intValue()),
441                 getDifferenceInDays(results.getCriteria().getDateCreatedFrom()));
442 
443         // now set another field on the criteria, modification should *not* occur
444         criteria.setApplicationDocumentId("12345");
445         results = docSearchService.lookupDocuments(principalId, criteria.build());
446         assertFalse("criteria should *not* have been modified", results.isCriteriaModified());
447         assertNull("modified date created from should still be null", results.getCriteria().getDateCreatedFrom());
448         assertEquals("both criterias should be equal", criteria.build(), results.getCriteria());
449     }
450 
451     /**
452      * Test for https://test.kuali.org/jira/browse/KULRICE-1968 - Document search fails when users are missing
453      * Tests that we can safely search on docs whose initiator no longer exists in the identity management system
454      * This test searches by doc type name criteria.
455      * @throws Exception
456      */
457     @Test public void testDocSearch_MissingInitiator() throws Exception {
458         String documentTypeName = "SearchDocType";
459         DocumentType docType = ((DocumentTypeService)KEWServiceLocator.getService(KEWServiceLocator.DOCUMENT_TYPE_SERVICE)).findByName(documentTypeName);
460         String userNetworkId = "arh14";
461         // route a document to enroute and route one to final
462         WorkflowDocument workflowDocument = WorkflowDocumentFactory.createDocument(getPrincipalId(userNetworkId), documentTypeName);
463         workflowDocument.setTitle("testDocSearch_MissingInitiator");
464         workflowDocument.route("routing this document.");
465 
466         // verify the document is enroute for jhopf
467         workflowDocument = WorkflowDocumentFactory.loadDocument(getPrincipalId("jhopf"),workflowDocument.getDocumentId());
468         assertTrue(workflowDocument.isEnroute());
469         assertTrue(workflowDocument.isApprovalRequested());
470 
471         // now nuke the initiator...
472         new JdbcTemplate(TestHarnessServiceLocator.getDataSource()).execute("update " + KREW_DOC_HDR_T + " set " + INITIATOR_COL + " = 'bogus user' where DOC_HDR_ID = " + workflowDocument.getDocumentId());
473 
474 
475         Person user = KimApiServiceLocator.getPersonService().getPersonByPrincipalName("jhopf");
476         DocumentSearchCriteria.Builder criteria = DocumentSearchCriteria.Builder.create();
477         criteria.setDocumentTypeName(documentTypeName);
478         DocumentSearchResults results = docSearchService.lookupDocuments(user.getPrincipalId(), criteria.build());
479         assertEquals("Search returned invalid number of documents", 1, results.getSearchResults().size());
480     }
481 
482     /**
483      * Test for https://test.kuali.org/jira/browse/KULRICE-1968 - Tests that we get an error if we try and search on an initiator that doesn't exist in the IDM system
484      * @throws Exception
485      */
486     @Test public void testDocSearch_SearchOnMissingInitiator() throws Exception {
487         String documentTypeName = "SearchDocType";
488         DocumentType docType = ((DocumentTypeService)KEWServiceLocator.getService(KEWServiceLocator.DOCUMENT_TYPE_SERVICE)).findByName(documentTypeName);
489         String userNetworkId = "arh14";
490         // route a document to enroute and route one to final
491         WorkflowDocument workflowDocument = WorkflowDocumentFactory.createDocument(getPrincipalId(userNetworkId), documentTypeName);
492         workflowDocument.setTitle("testDocSearch_MissingInitiator");
493         workflowDocument.route("routing this document.");
494 
495         // verify the document is enroute for jhopf
496         workflowDocument = WorkflowDocumentFactory.loadDocument(getPrincipalId("jhopf"),workflowDocument.getDocumentId());
497         assertTrue(workflowDocument.isEnroute());
498         assertTrue(workflowDocument.isApprovalRequested());
499 
500         // now nuke the initiator...
501         new JdbcTemplate(TestHarnessServiceLocator.getDataSource()).execute("update " + KREW_DOC_HDR_T + " set " + INITIATOR_COL + " = 'bogus user' where DOC_HDR_ID = " + workflowDocument.getDocumentId());
502 
503 
504         Person user = KimApiServiceLocator.getPersonService().getPersonByPrincipalName("jhopf");
505         DocumentSearchCriteria.Builder criteria = DocumentSearchCriteria.Builder.create();
506         criteria.setInitiatorPrincipalName("bogus user");
507 
508         DocumentSearchResults results = docSearchService.lookupDocuments(user.getPrincipalId(),
509                 criteria.build());
510         int size = results.getSearchResults().size();
511         assertTrue("Searching by an invalid initiator should return nothing", size == 0);
512 
513     }
514 
515     @Test public void testDocSearch_RouteNodeName() throws Exception {
516         loadXmlFile("DocSearchTest_RouteNode.xml");
517         String documentTypeName = "SearchDocType_RouteNodeTest";
518         DocumentType docType = ((DocumentTypeService)KEWServiceLocator.getService(KEWServiceLocator.DOCUMENT_TYPE_SERVICE)).findByName(documentTypeName);
519         String userNetworkId = "rkirkend";
520 
521         // route a document to enroute and route one to final
522         WorkflowDocument workflowDocument = WorkflowDocumentFactory.createDocument(getPrincipalId(userNetworkId), documentTypeName);
523         workflowDocument.setTitle("Routing style");
524         workflowDocument.route("routing this document.");
525         // verify the document is enroute for jhopf
526         workflowDocument = WorkflowDocumentFactory.loadDocument(getPrincipalId("jhopf"),workflowDocument.getDocumentId());
527         assertTrue(workflowDocument.isEnroute());
528         assertTrue(workflowDocument.isApprovalRequested());
529         workflowDocument.approve("");
530         workflowDocument = WorkflowDocumentFactory.loadDocument(getPrincipalId("jhopf"),workflowDocument.getDocumentId());
531         assertTrue(workflowDocument.isFinal());
532         workflowDocument = WorkflowDocumentFactory.createDocument(getPrincipalId(userNetworkId), documentTypeName);
533         workflowDocument.setTitle("Routing style");
534         workflowDocument.route("routing this document.");
535         // verify the document is enroute for jhopf
536         workflowDocument = WorkflowDocumentFactory.loadDocument(getPrincipalId("jhopf"),workflowDocument.getDocumentId());
537         assertTrue(workflowDocument.isEnroute());
538         assertTrue(workflowDocument.isApprovalRequested());
539 
540 
541         Person user = KimApiServiceLocator.getPersonService().getPersonByPrincipalName(userNetworkId);
542         DocumentSearchCriteria.Builder criteria = DocumentSearchCriteria.Builder.create();
543         criteria.setDocumentTypeName(documentTypeName);
544         DocumentSearchResults results = docSearchService.lookupDocuments(user.getPrincipalId(),
545                 criteria.build());
546         assertEquals("Search returned invalid number of documents", 2, results.getSearchResults().size());
547 
548         criteria.setRouteNodeName(getRouteNodeForSearch(documentTypeName,workflowDocument.getNodeNames()));
549         criteria.setRouteNodeLookupLogic(RouteNodeLookupLogic.EXACTLY);
550         results = docSearchService.lookupDocuments(user.getPrincipalId(), criteria.build());
551         assertEquals("Search returned invalid number of documents", 1, results.getSearchResults().size());
552 
553         // load the document type again to change the route node ids
554         loadXmlFile("DocSearchTest_RouteNode.xml");
555 
556         workflowDocument = WorkflowDocumentFactory.loadDocument(getPrincipalId("jhopf"),workflowDocument.getDocumentId());
557         assertTrue(workflowDocument.isEnroute());
558         assertTrue(workflowDocument.isApprovalRequested());
559         criteria.setRouteNodeName(getRouteNodeForSearch(documentTypeName, workflowDocument.getNodeNames()));
560         results = docSearchService.lookupDocuments(user.getPrincipalId(), criteria.build());
561         assertEquals("Search returned invalid number of documents", 1, results.getSearchResults().size());
562 
563     }
564 
565     private String getRouteNodeForSearch(String documentTypeName, Set<String> nodeNames) {
566         assertEquals(1,	nodeNames.size());
567     String expectedNodeName = nodeNames.iterator().next();
568         List routeNodes = KEWServiceLocator.getRouteNodeService().getFlattenedNodes(KEWServiceLocator.getDocumentTypeService().findByName(documentTypeName), true);
569         for (Iterator iterator = routeNodes.iterator(); iterator.hasNext();) {
570         RouteNode node = (RouteNode) iterator.next();
571         if (expectedNodeName.equals(node.getRouteNodeName())) {
572         return node.getRouteNodeName();
573         }
574     }
575         return null;
576     }
577 
578     @Test public void testGetNamedDocSearches() throws Exception {
579         List namedSearches = docSearchService.getNamedSearches(getPrincipalId("bmcgough"));
580         assertNotNull(namedSearches);
581     }
582 
583     private static int getDifferenceInDays(DateTime compareDate) {
584         return Days.daysBetween(compareDate, new DateTime()).getDays();
585     }
586 
587     /**
588      * Tests searching against document search attrs
589      * @throws Exception
590      */
591     @Test public void testDocSearchWithAttributes() throws Exception {
592         String[] docIds = routeTestDocs();
593 
594         String principalId = getPrincipalId("bmcgough");
595         DocumentSearchCriteria.Builder builder = DocumentSearchCriteria.Builder.create();
596         builder.setDocumentTypeName("SearchDocType");
597         builder.setSaveName("testDocSearchWithAttributes");
598         Map<String, List<String>> docAttrs = new HashMap<String, List<String>>();
599         docAttrs.put(TestXMLSearchableAttributeString.SEARCH_STORAGE_KEY, Arrays.asList(new String[]{TestXMLSearchableAttributeString.SEARCH_STORAGE_VALUE}));
600         builder.setDocumentAttributeValues(docAttrs);
601 
602         DocumentSearchResults results = docSearchService.lookupDocuments(principalId, builder.build());
603         assertEquals(docIds.length, results.getSearchResults().size());
604 
605         DocumentSearchCriteria loaded = docSearchService.getNamedSearchCriteria(principalId, builder.getSaveName());
606         assertNotNull(loaded);
607         assertEquals(docAttrs, loaded.getDocumentAttributeValues());
608 
609         // re-run saved search
610         results = docSearchService.lookupDocuments(principalId, loaded);
611         assertEquals(docIds.length, results.getSearchResults().size());
612     }
613 
614     /**
615      * Tests the usage of wildcards on the regular document search attributes.
616      * @throws Exception
617      */
618     @Test public void testDocSearch_WildcardsOnRegularAttributes() throws Exception {
619         // TODO: Add some wildcard testing for the document type attribute once wildcards are usable with it.
620 
621         // Route some test documents.
622         String[] docIds = routeTestDocs();
623 
624         String principalId = getPrincipalId("bmcgough");
625         DocumentSearchCriteria.Builder criteria = null;
626         DocumentSearchResults results = null;
627 
628         /**
629          * BEGIN - commenting out until we can resolve issues with person service not returning proper persons based on wildcards and various things
630          */
631         // Test the wildcards on the initiator attribute.
632         String[] searchStrings = {"!quickstart", "!quickstart&&!rkirkend", "!admin", "user1", "quickstart|bmcgough",
633         		"admin|rkirkend", ">bmcgough", ">=rkirkend", "<bmcgough", "<=quickstart", ">bmcgough&&<=rkirkend", "<rkirkend&&!bmcgough",
634         		"?mc?oug?", "*t", "*i?k*", "*", "!quick*", "!*g*&&!*k*", "quickstart..rkirkend"};
635         int[] expectedResults = {2, 1, 3, 0, 2, 1, 2, 1, 0, 2, 2, 1, 1, 1, 2, 3, 2, 0, 2/*1*/};
636         for (int i = 0; i < searchStrings.length; i++) {
637         	criteria = DocumentSearchCriteria.Builder.create();
638         	criteria.setInitiatorPrincipalName(searchStrings[i]);
639         	results = docSearchService.lookupDocuments(principalId, criteria.build());
640         	assertEquals("Initiator search at index " + i + " retrieved the wrong number of documents.", expectedResults[i], results.getSearchResults().size());
641         }
642 
643         // Test the wildcards on the approver attribute.
644         searchStrings = new String[] {"jhopf","!jhopf", ">jhopf", "<jjopf", ">=quickstart", "<=jhopf", "jhope..jhopg", "?hopf", "*i*", "!*f", "j*"};
645         expectedResults = new int[] {1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1};
646         for (int i = 0; i < searchStrings.length; i++) {
647         	criteria = DocumentSearchCriteria.Builder.create();
648         	criteria.setApproverPrincipalName(searchStrings[i]);
649         	results = docSearchService.lookupDocuments(principalId, criteria.build());
650         	assertEquals("Approver search at index " + i + " retrieved the wrong number of documents.", expectedResults[i], results.getSearchResults().size());
651         }
652 
653         // Test the wildcards on the viewer attribute.
654         searchStrings = new String[] {"jhopf","!jhopf", ">jhopf", "<jjopf", ">=quickstart", "<=jhopf", "jhope..jhopg", "?hopf", "*i*", "!*f", "j*"};
655         expectedResults = new int[] {3, 0, 0, 3, 0, 3, 3, 3, 0, 0, 3};
656         for (int i = 0; i < searchStrings.length; i++) {
657         	criteria = DocumentSearchCriteria.Builder.create();
658         	criteria.setViewerPrincipalName(searchStrings[i]);
659         	results = docSearchService.lookupDocuments(principalId, criteria.build());
660         	if(expectedResults[i] !=  results.getSearchResults().size()){
661         		assertEquals("Viewer search at index " + i + " retrieved the wrong number of documents.", expectedResults[i], results.getSearchResults().size());
662         	}
663         }
664 
665         /**
666          * END
667          */
668 
669         // Test the wildcards on the document/notification ID attribute. The string wildcards should work, since the doc ID is not a string.
670         searchStrings = new String[] {"!"+docIds[0], docIds[1]+"|"+docIds[2], "<="+docIds[1], ">="+docIds[2], "<"+docIds[0]+"&&>"+docIds[2],
671                 ">"+docIds[1], "<"+docIds[2]+"&&!"+docIds[0], docIds[0]+".."+docIds[2], "?"+docIds[1]+"*", "?"+docIds[1].substring(1)+"*", "?9*7abc"};
672         expectedResults = new int[] {2, 2, 2, 1, 0, 1, 1, 3, 0, 1, 0};
673         for (int i = 0; i < searchStrings.length; i++) {
674             criteria = DocumentSearchCriteria.Builder.create();
675             criteria.setDocumentId(searchStrings[i]);
676             results = docSearchService.lookupDocuments(principalId, criteria.build());
677             assertEquals("Doc ID search at index " + i + " retrieved the wrong number of documents.", expectedResults[i], results.getSearchResults().size());
678         }
679 
680         // Test the wildcards on the application document/notification ID attribute. The string wildcards should work, since the app doc ID is a string.
681         searchStrings = new String[] {"6543", "5432|4321", ">4321", "<=5432", ">=6543", "<3210", "!3210", "!5432", "!4321!5432", ">4321&&!6543",
682                 "*5?3*", "*", "?3?1", "!*43*", "!???2", ">43*1", "<=5432&&!?32?", "5432..6543"};
683         expectedResults = new int[] {1, 2, 2, 2, 1, 0, 3, 2, 1, 1, 2, 3, 1, 0, 2, 3, 1, 2/*1*/};
684         for (int i = 0; i < searchStrings.length; i++) {
685             criteria = DocumentSearchCriteria.Builder.create();
686             criteria.setApplicationDocumentId(searchStrings[i]);
687             results = docSearchService.lookupDocuments(principalId, criteria.build());
688             if(expectedResults[i] !=  results.getSearchResults().size()){
689                 assertEquals("App doc ID search at index " + i + " retrieved the wrong number of documents.", expectedResults[i], results.getSearchResults().size());
690             }
691         }
692 
693         // Test the wildcards on the title attribute.
694         searchStrings = new String[] {"Some New Document", "Document Number 2|The New Doc", "!The New Doc", "!Some New Document!Document Number 2",
695                 "!The New Doc&&!Some New Document", ">Document Number 2", "<=Some New Document", ">=The New Doc&&<Some New Document", ">A New Doc",
696                 "<Some New Document|The New Doc", ">=Document Number 2&&!Some New Document", "*Docu??nt*", "*New*", "The ??? Doc", "*Doc*", "*Number*",
697                 "Some New Document..The New Doc", "Document..The", "*New*&&!*Some*", "!The ??? Doc|!*New*"};
698         expectedResults = new int[] {1, 2, 2, 1, 1, 2, 2, 0, 3, 2, 2, 2, 2, 1, 3, 1, 2/*1*/, 2, 1, 2};
699         for (int i = 0; i < searchStrings.length; i++) {
700             criteria = DocumentSearchCriteria.Builder.create();
701             criteria.setTitle(searchStrings[i]);
702             results = docSearchService.lookupDocuments(principalId, criteria.build());
703             if(expectedResults[i] !=  results.getSearchResults().size()){
704                 assertEquals("Doc title search at index " + i + " retrieved the wrong number of documents.", expectedResults[i], results.getSearchResults().size());
705             }
706         }
707 
708     }
709 
710     @Test public void testAdditionalDocumentTypesCriteria() throws Exception {
711         String[] docIds = routeTestDocs();
712         String docId2 = routeTestDoc2();
713 
714         String principalId = getPrincipalId("bmcgough");
715 
716         DocumentSearchCriteria.Builder criteria = DocumentSearchCriteria.Builder.create();
717         criteria.setDocumentTypeName("SearchDocType");
718 
719         // TODO finish this test
720         DocumentSearchResults results = docSearchService.lookupDocuments(principalId, criteria.build());
721         assertEquals(3, results.getSearchResults().size());
722 
723         criteria.setDocumentTypeName("SearchDocType2");
724         results = docSearchService.lookupDocuments(principalId, criteria.build());
725         assertEquals(1, results.getSearchResults().size());
726 
727         criteria.getAdditionalDocumentTypeNames().add("SearchDocType");
728         results = docSearchService.lookupDocuments(principalId, criteria.build());
729         assertEquals(4, results.getSearchResults().size());
730     }
731 
732     /**
733      * Tests searching on document status and document status category
734      */
735     @Test public void testDocumentStatusSearching() {
736         String dt = "SearchDocType";
737         String pid = getPrincipalIdForName("quickstart");
738         WorkflowDocument initiated = WorkflowDocumentFactory.createDocument(pid, dt);
739         WorkflowDocument saved = WorkflowDocumentFactory.createDocument(pid, dt);
740         saved.saveDocument("saved");
741         assertEquals(DocumentStatus.SAVED, saved.getStatus());
742 
743         WorkflowDocument enroute = WorkflowDocumentFactory.createDocument(pid, dt);
744         enroute.route("routed");
745         assertEquals(DocumentStatus.ENROUTE, enroute.getStatus());
746 
747         WorkflowDocument exception = WorkflowDocumentFactory.createDocument(pid, dt);
748         exception.route("routed");
749         exception.placeInExceptionRouting("placed in exception routing");
750         assertEquals(DocumentStatus.EXCEPTION, exception.getStatus());
751 
752         // no acks on this doc, can't test?
753         //WorkflowDocument processed = WorkflowDocumentFactory.createDocument(pid, dt);
754         //processed.route("routed");
755 
756         WorkflowDocument finl = WorkflowDocumentFactory.createDocument(pid, dt);
757         finl.route("routed");
758         finl.switchPrincipal(getPrincipalId("jhopf"));
759         finl.approve("approved");
760         assertEquals(DocumentStatus.FINAL, finl.getStatus());
761 
762         WorkflowDocument canceled = WorkflowDocumentFactory.createDocument(pid, dt);
763         canceled.cancel("canceled");
764         assertEquals(DocumentStatus.CANCELED, canceled.getStatus());
765 
766         WorkflowDocument disapproved = WorkflowDocumentFactory.createDocument(pid, dt);
767         disapproved.route("routed");
768         disapproved.switchPrincipal(getPrincipalId("jhopf"));
769         RequestedActions ra = disapproved.getRequestedActions();
770         disapproved.disapprove("disapproved");
771         assertEquals(DocumentStatus.DISAPPROVED, disapproved.getStatus());
772 
773         assertDocumentStatuses(dt, pid, 1, 1, 1, 1, 0, 1, 1, 1);
774     }
775 
776     /**
777      * Asserts that documents are present in the given statuses, including document status categories (this requires that
778      * no docs are in the system prior to routing of the test docs)
779      */
780     protected void assertDocumentStatuses(String documentType, String principalId, int initiated, int saved, int enroute, int exception,
781                                                           int processed, int finl, int canceled, int disapproved) {
782         assertDocumentStatus(documentType, principalId, DocumentStatus.INITIATED, initiated);
783         assertDocumentStatus(documentType, principalId, DocumentStatus.SAVED, saved);
784         assertDocumentStatus(documentType, principalId, DocumentStatus.ENROUTE, enroute);
785         assertDocumentStatus(documentType, principalId, DocumentStatus.EXCEPTION, exception);
786 
787         assertDocumentStatusCategory(documentType, principalId, DocumentStatusCategory.PENDING,
788                 initiated + saved + enroute + exception);
789 
790         assertDocumentStatus(documentType, principalId, DocumentStatus.PROCESSED, processed);
791         assertDocumentStatus(documentType, principalId, DocumentStatus.FINAL, finl);
792 
793         assertDocumentStatusCategory(documentType, principalId, DocumentStatusCategory.SUCCESSFUL, processed + finl);
794 
795         assertDocumentStatus(documentType, principalId, DocumentStatus.CANCELED, canceled);
796         assertDocumentStatus(documentType, principalId, DocumentStatus.DISAPPROVED, finl);
797 
798         assertDocumentStatusCategory(documentType, principalId, DocumentStatusCategory.UNSUCCESSFUL,
799                 canceled + disapproved);
800     }
801 
802     /**
803      * Asserts that there are a certain number of docs in the given status
804      */
805     protected void assertDocumentStatus(String documentType, String principalId, DocumentStatus status, int num) {
806         DocumentSearchCriteria.Builder criteria = DocumentSearchCriteria.Builder.create();
807         criteria.setDocumentTypeName(documentType);
808         criteria.setDocumentStatuses(Arrays.asList(new DocumentStatus[] { status }));
809         DocumentSearchResults result = docSearchService.lookupDocuments(principalId, criteria.build());
810         assertEquals("Expected " + num + " documents in status " + status, num, result.getSearchResults().size());
811     }
812 
813     /**
814      * Asserts that there are a certain number of docs in the given document status category
815      */
816     protected void assertDocumentStatusCategory(String documentType, String principalId, DocumentStatusCategory status, int num) {
817         DocumentSearchCriteria.Builder criteria = DocumentSearchCriteria.Builder.create();
818         criteria.setDocumentTypeName(documentType);
819         criteria.setDocumentStatusCategories(Arrays.asList(new DocumentStatusCategory[]{status}));
820         DocumentSearchResults result = docSearchService.lookupDocuments(principalId, criteria.build());
821         assertEquals("Expected " + num + " documents in status category " + status, num,
822                 result.getSearchResults().size());
823     }
824 
825     private static final class TestDocData {
826         private TestDocData() { throw new IllegalStateException("leave me alone"); }
827 
828         static String docTypeName = "SearchDocType";
829         static String[] principalNames = {"bmcgough", "quickstart", "rkirkend"};
830         static String[] titles = {"The New Doc", "Document Number 2", "Some New Document"};
831         static String[] appDocIds = {"6543", "5432", "4321"};
832         static String[] appDocStatuses = {"Submitted", "Pending", "Completed"};
833         static String[] approverNames = {null, "jhopf", null};
834     }
835 
836     /**
837      * Routes some test docs for searching
838      * @return String[] of doc ids
839      */
840     protected String[] routeTestDocs() {
841         // Route some test documents.
842         String[] docIds = new String[TestDocData.titles.length];
843 
844         for (int i = 0; i < TestDocData.titles.length; i++) {
845             WorkflowDocument workflowDocument = WorkflowDocumentFactory.createDocument(
846                     getPrincipalId(TestDocData.principalNames[i]), TestDocData.docTypeName);
847             workflowDocument.setTitle(TestDocData.titles[i]);
848             workflowDocument.setApplicationDocumentId(TestDocData.appDocIds[i]);
849             workflowDocument.route("routing this document.");
850 
851             docIds[i] = workflowDocument.getDocumentId();
852 
853             if (TestDocData.approverNames[i] != null) {
854                 workflowDocument.switchPrincipal(getPrincipalId(TestDocData.approverNames[i]));
855                 workflowDocument.approve("approving this document.");
856             }
857 
858             workflowDocument.setApplicationDocumentStatus(TestDocData.appDocStatuses[i]);
859             workflowDocument.saveDocumentData();
860         }
861 
862         return docIds;
863     }
864 
865     /**
866      * "Saves" a single instance of a "SearchDocType2" document and returns it's id.
867      */
868     protected String routeTestDoc2() {
869         // Route some test documents.
870         String docTypeName = "SearchDocType2";
871         WorkflowDocument workflowDocument = WorkflowDocumentFactory.createDocument(getPrincipalId("ewestfal"), docTypeName);
872         workflowDocument.setTitle("Search Doc Type 2!");
873         workflowDocument.saveDocument("saving the document");
874         return workflowDocument.getDocumentId();
875     }
876 
877     private String getPrincipalId(String principalName) {
878         return KimApiServiceLocator.getIdentityService().getPrincipalByPrincipalName(principalName).getPrincipalId();
879     }
880 
881     @Test
882     public void testDocSearch_maxResultsCap() throws Exception {
883         DocumentSearchCriteria.Builder criteria = DocumentSearchCriteria.Builder.create();
884         criteria.setDocumentTypeName("SearchDocType");
885         int maxResultsCap = docSearchService.getMaxResultCap(criteria.build());
886         assertEquals(500, maxResultsCap);
887 
888         criteria.setMaxResults(5);
889         int maxResultsCap1 = docSearchService.getMaxResultCap(criteria.build());
890         assertEquals(5, maxResultsCap1);
891 
892         criteria.setMaxResults(2);
893         int maxResultsCap2 = docSearchService.getMaxResultCap(criteria.build());
894         assertEquals(2, maxResultsCap2);
895     }
896 
897     @Test
898     public void testDocSearch_fetchMoreIterationLimit() throws Exception {
899         DocumentSearchCriteria.Builder criteria = DocumentSearchCriteria.Builder.create();
900         criteria.setDocumentTypeName("SearchDocType");
901         int fetchIterationLimit = docSearchService.getFetchMoreIterationLimit();
902         assertEquals(10, fetchIterationLimit);
903 
904     }
905 }