View Javadoc

1   /*
2    * Copyright 2005-2007 The Kuali Foundation
3    *
4    *
5    * Licensed under the Educational Community License, Version 2.0 (the "License");
6    * you may not use this file except in compliance with the License.
7    * You may obtain a copy of the License at
8    *
9    * http://www.opensource.org/licenses/ecl2.php
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.kuali.rice.kew.docsearch;
18  
19  import org.junit.Test;
20  import org.kuali.rice.kew.docsearch.service.DocumentSearchService;
21  import org.kuali.rice.kew.doctype.bo.DocumentType;
22  import org.kuali.rice.kew.doctype.service.DocumentTypeService;
23  import org.kuali.rice.kew.dto.NetworkIdDTO;
24  import org.kuali.rice.kew.engine.node.RouteNode;
25  import org.kuali.rice.kew.service.KEWServiceLocator;
26  import org.kuali.rice.kew.service.WorkflowDocument;
27  import org.kuali.rice.kew.test.KEWTestCase;
28  import org.kuali.rice.kew.util.KEWConstants;
29  import org.kuali.rice.kew.web.KeyValueSort;
30  import org.kuali.rice.kim.bo.Person;
31  import org.kuali.rice.kim.service.KIMServiceLocator;
32  import org.kuali.rice.test.TestHarnessServiceLocator;
33  import org.springframework.jdbc.core.JdbcTemplate;
34  
35  import java.math.BigDecimal;
36  import java.util.Calendar;
37  import java.util.Iterator;
38  import java.util.List;
39  
40  
41  public class DocumentSearchTest extends KEWTestCase {
42      private static final String KREW_DOC_HDR_T = "KREW_DOC_HDR_T";
43      private static final String INITIATOR_COL = "INITR_PRNCPL_ID";
44  
45      DocumentSearchService docSearchService;
46  
47      protected void loadTestData() throws Exception {
48          loadXmlFile("SearchAttributeConfig.xml");
49      }
50  
51      protected void setUpAfterDataLoad() throws Exception {
52          docSearchService = (DocumentSearchService)KEWServiceLocator.getService(KEWServiceLocator.DOCUMENT_SEARCH_SERVICE);
53      }
54  
55      @Test public void testDocSearch() throws Exception {
56          Person user = KIMServiceLocator.getPersonService().getPersonByPrincipalName("bmcgough");
57          DocSearchCriteriaDTO criteria = new DocSearchCriteriaDTO();
58          List searchResults = null;
59          DocumentSearchResultComponents result = null;
60          criteria.setDocTitle("*IN");
61          criteria.setNamedSearch("bytitle");
62          result = docSearchService.getList(user.getPrincipalId(), criteria);
63          criteria = new DocSearchCriteriaDTO();
64          criteria.setDocTitle("*IN-CFSG");
65          criteria.setNamedSearch("for in accounts");
66          result = docSearchService.getList(user.getPrincipalId(), criteria);
67          criteria = new DocSearchCriteriaDTO();
68          criteria.setFromDateApproved("09/16/2004");
69          result = docSearchService.getList(user.getPrincipalId(), criteria);
70          criteria = new DocSearchCriteriaDTO();
71          criteria.setDocRouteNodeId("3");
72          criteria.setDocRouteNodeLogic("equal");
73          result = docSearchService.getList(user.getPrincipalId(), criteria);
74          user = KIMServiceLocator.getPersonService().getPersonByPrincipalName("bmcgough");
75          SavedSearchResult savedSearchResults = docSearchService.getSavedSearchResults(user.getPrincipalId(), "DocSearch.NamedSearch.bytitle");
76          assertNotNull(savedSearchResults);
77          assertNotNull(savedSearchResults.getSearchResult());
78          savedSearchResults = docSearchService.getSavedSearchResults(user.getPrincipalId(), "DocSearch.NamedSearch.for in accounts");
79          assertNotNull(savedSearchResults);
80          assertNotNull(savedSearchResults.getSearchResult());
81      }
82  
83      /**
84       * Test for https://test.kuali.org/jira/browse/KULRICE-1968 - Document search fails when users are missing
85       * Tests that we can safely search on docs whose initiator no longer exists in the identity management system
86       * This test searches by doc type name criteria.
87       * @throws Exception
88       */
89      @Test public void testDocSearch_MissingInitiator() throws Exception {
90          String documentTypeName = "SearchDocType";
91          DocumentType docType = ((DocumentTypeService)KEWServiceLocator.getService(KEWServiceLocator.DOCUMENT_TYPE_SERVICE)).findByName(documentTypeName);
92          String userNetworkId = "arh14";
93          // route a document to enroute and route one to final
94          WorkflowDocument workflowDocument = new WorkflowDocument(new NetworkIdDTO(userNetworkId), documentTypeName);
95          workflowDocument.setTitle("testDocSearch_MissingInitiator");
96          workflowDocument.routeDocument("routing this document.");
97  
98          // verify the document is enroute for jhopf
99          workflowDocument = new WorkflowDocument(new NetworkIdDTO("jhopf"),workflowDocument.getRouteHeaderId());
100         assertTrue(workflowDocument.stateIsEnroute());
101         assertTrue(workflowDocument.isApprovalRequested());
102 
103         // now nuke the initiator...
104         new JdbcTemplate(TestHarnessServiceLocator.getDataSource()).execute("update " + KREW_DOC_HDR_T + " set " + INITIATOR_COL + " = 'bogus user' where DOC_HDR_ID = " + workflowDocument.getRouteHeaderId());
105 
106 
107         Person user = KIMServiceLocator.getPersonService().getPersonByPrincipalName("jhopf");
108         DocSearchCriteriaDTO criteria = new DocSearchCriteriaDTO();
109         criteria.setDocTypeFullName(documentTypeName);
110         DocumentSearchResultComponents result = docSearchService.getList(user.getPrincipalId(), criteria);
111         assertNotNull(result);
112         assertNotNull(result.getSearchResults());
113         assertEquals("Search returned invalid number of documents", 1, result.getSearchResults().size());
114     }
115 
116     /**
117      * 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
118      * @throws Exception
119      */
120     @Test public void testDocSearch_SearchOnMissingInitiator() throws Exception {
121         String documentTypeName = "SearchDocType";
122         DocumentType docType = ((DocumentTypeService)KEWServiceLocator.getService(KEWServiceLocator.DOCUMENT_TYPE_SERVICE)).findByName(documentTypeName);
123         String userNetworkId = "arh14";
124         // route a document to enroute and route one to final
125         WorkflowDocument workflowDocument = new WorkflowDocument(new NetworkIdDTO(userNetworkId), documentTypeName);
126         workflowDocument.setTitle("testDocSearch_MissingInitiator");
127         workflowDocument.routeDocument("routing this document.");
128 
129         // verify the document is enroute for jhopf
130         workflowDocument = new WorkflowDocument(new NetworkIdDTO("jhopf"),workflowDocument.getRouteHeaderId());
131         assertTrue(workflowDocument.stateIsEnroute());
132         assertTrue(workflowDocument.isApprovalRequested());
133 
134         // now nuke the initiator...
135         new JdbcTemplate(TestHarnessServiceLocator.getDataSource()).execute("update " + KREW_DOC_HDR_T + " set " + INITIATOR_COL + " = 'bogus user' where DOC_HDR_ID = " + workflowDocument.getRouteHeaderId());
136 
137 
138         Person user = KIMServiceLocator.getPersonService().getPersonByPrincipalName("jhopf");
139         DocSearchCriteriaDTO criteria = new DocSearchCriteriaDTO();
140         criteria.setInitiator("bogus user");
141 
142         DocumentSearchResultComponents result = docSearchService.getList(user.getPrincipalId(), criteria);
143         int size = result.getSearchResults().size();
144         assertTrue("Searching by an invalid initiator should return nothing", size == 0);
145 
146     }
147 
148     @Test public void testDocSearch_RouteNodeName() throws Exception {
149         loadXmlFile("DocSearchTest_RouteNode.xml");
150         String documentTypeName = "SearchDocType_RouteNodeTest";
151     	DocumentType docType = ((DocumentTypeService)KEWServiceLocator.getService(KEWServiceLocator.DOCUMENT_TYPE_SERVICE)).findByName(documentTypeName);
152         String userNetworkId = "rkirkend";
153 
154         // route a document to enroute and route one to final
155         WorkflowDocument workflowDocument = new WorkflowDocument(new NetworkIdDTO(userNetworkId), documentTypeName);
156         workflowDocument.setTitle("Routing style");
157         workflowDocument.routeDocument("routing this document.");
158         // verify the document is enroute for jhopf
159         workflowDocument = new WorkflowDocument(new NetworkIdDTO("jhopf"),workflowDocument.getRouteHeaderId());
160         assertTrue(workflowDocument.stateIsEnroute());
161         assertTrue(workflowDocument.isApprovalRequested());
162         workflowDocument.approve("");
163         workflowDocument = new WorkflowDocument(new NetworkIdDTO("jhopf"),workflowDocument.getRouteHeaderId());
164         assertTrue(workflowDocument.stateIsFinal());
165         workflowDocument = new WorkflowDocument(new NetworkIdDTO(userNetworkId), documentTypeName);
166         workflowDocument.setTitle("Routing style");
167         workflowDocument.routeDocument("routing this document.");
168         // verify the document is enroute for jhopf
169         workflowDocument = new WorkflowDocument(new NetworkIdDTO("jhopf"),workflowDocument.getRouteHeaderId());
170         assertTrue(workflowDocument.stateIsEnroute());
171         assertTrue(workflowDocument.isApprovalRequested());
172 
173 
174         Person user = KIMServiceLocator.getPersonService().getPersonByPrincipalName(userNetworkId);
175         DocSearchCriteriaDTO criteria = new DocSearchCriteriaDTO();
176         criteria.setDocTypeFullName(documentTypeName);
177         DocumentSearchResultComponents result = docSearchService.getList(user.getPrincipalId(), criteria);
178         assertNotNull(result);
179         assertNotNull(result.getSearchResults());
180         assertEquals("Search returned invalid number of documents", 2, result.getSearchResults().size());
181 
182         criteria.setDocRouteNodeId(getRouteNodeForSearch(documentTypeName,workflowDocument.getNodeNames()));
183         criteria.setDocRouteNodeLogic("equal");
184         result = docSearchService.getList(user.getPrincipalId(), criteria);
185         assertNotNull(result);
186         assertNotNull(result.getSearchResults());
187         assertEquals("Search returned invalid number of documents", 1, result.getSearchResults().size());
188 
189         // load the document type again to change the route node ids
190         loadXmlFile("DocSearchTest_RouteNode.xml");
191 
192         workflowDocument = new WorkflowDocument(new NetworkIdDTO("jhopf"),workflowDocument.getRouteHeaderId());
193         assertTrue(workflowDocument.stateIsEnroute());
194         assertTrue(workflowDocument.isApprovalRequested());
195         criteria.setDocRouteNodeId(getRouteNodeForSearch(documentTypeName,workflowDocument.getNodeNames()));
196         result = docSearchService.getList(user.getPrincipalId(), criteria);
197         assertNotNull(result);
198         assertNotNull(result.getSearchResults());
199         assertEquals("Search returned invalid number of documents", 1, result.getSearchResults().size());
200 
201     }
202 
203     private String getRouteNodeForSearch(String documentTypeName, String[] nodeNames) {
204         assertEquals(1,	nodeNames.length);
205 	String expectedNodeName = nodeNames[0];
206         List routeNodes = KEWServiceLocator.getRouteNodeService().getFlattenedNodes(KEWServiceLocator.getDocumentTypeService().findByName(documentTypeName), true);
207         for (Iterator iterator = routeNodes.iterator(); iterator.hasNext();) {
208 	    RouteNode node = (RouteNode) iterator.next();
209 	    if (expectedNodeName.equals(node.getRouteNodeName())) {
210 		return node.getRouteNodeName();
211 	    }
212 	}
213         return null;
214     }
215 
216     @Test public void testGetNamedDocSearches() throws Exception {
217     	Person user = KIMServiceLocator.getPersonService().getPersonByPrincipalName("bmcgough");
218         List namedSearches = docSearchService.getNamedSearches(user.getPrincipalId());
219         assertNotNull(namedSearches);
220     }
221 
222     @Test public void testDefaultCreateDateSearchCriteria() throws Exception {
223         Person user = KIMServiceLocator.getPersonService().getPersonByPrincipalName("bmcgough");
224         DocSearchCriteriaDTO criteria = new DocSearchCriteriaDTO();
225         DocumentSearchResultComponents result = docSearchService.getList(user.getPrincipalId(), criteria);
226         assertNotNull("Should have a date created value",criteria.getFromDateCreated());
227         Calendar criteriaDate = Calendar.getInstance();
228         criteriaDate.setTime(DocSearchUtils.convertStringDateToTimestamp(criteria.getFromDateCreated()));
229         assertEquals("Criteria date minus today's date should equal the constant value", KEWConstants.DOCUMENT_SEARCH_NO_CRITERIA_CREATE_DATE_DAYS_AGO.doubleValue(), getDifferenceInDays(criteriaDate), 0);
230 
231         criteria = new DocSearchCriteriaDTO();
232         criteria.setDocTitle("testing");
233         result = docSearchService.getList(user.getPrincipalId(), criteria);
234         assertNotNull("Should have a date created value",criteria.getFromDateCreated());
235         criteriaDate = Calendar.getInstance();
236         criteriaDate.setTime(DocSearchUtils.convertStringDateToTimestamp(criteria.getFromDateCreated()));
237         assertEquals("Criteria date minus today's date should equal the constant value", KEWConstants.DOCUMENT_SEARCH_DOC_TITLE_CREATE_DATE_DAYS_AGO.doubleValue(), getDifferenceInDays(criteriaDate), 0);
238     }
239 
240     private static double getDifferenceInDays(Calendar compareDate) {
241         Calendar today = Calendar.getInstance();
242         // First, get difference in whole days
243         today.set(Calendar.HOUR_OF_DAY, 0);
244         today.set(Calendar.MINUTE, 0);
245         today.set(Calendar.SECOND, 0);
246         today.set(Calendar.MILLISECOND, 0);
247 
248         compareDate.set(Calendar.HOUR_OF_DAY, 0);
249         compareDate.set(Calendar.MINUTE, 0);
250         compareDate.set(Calendar.SECOND, 0);
251         compareDate.set(Calendar.MILLISECOND, 0);
252 
253         return (BigDecimal.valueOf(compareDate.getTimeInMillis()).subtract(BigDecimal.valueOf(today.getTimeInMillis()))).divide(BigDecimal.valueOf(24 * 60 * 60 * 1000.00), BigDecimal.ROUND_HALF_UP).doubleValue();
254     }
255 
256     @Test public void testUseWorkflowSuperUserDocHandlerPolicy() throws Exception {
257         String customDocHandlerDocumentType = "SearchDocType";
258         String standardDocHandlerDocumentType = "SearchDocType2";
259     	DocumentType docType = ((DocumentTypeService)KEWServiceLocator.getService(KEWServiceLocator.DOCUMENT_TYPE_SERVICE)).findByName(customDocHandlerDocumentType);
260         String userNetworkId = "rkirkend";
261 
262         // route a document to enroute and route one to final
263         WorkflowDocument workflowDocument = new WorkflowDocument(new NetworkIdDTO(userNetworkId), standardDocHandlerDocumentType);
264         workflowDocument.setTitle("Routing style");
265         workflowDocument.routeDocument("routing this document.");
266         // verify the document is enroute for jhopf
267         workflowDocument = new WorkflowDocument(new NetworkIdDTO("jhopf"),workflowDocument.getRouteHeaderId());
268         assertTrue(workflowDocument.stateIsEnroute());
269 
270         // route a document to enroute and route one to final
271         workflowDocument = new WorkflowDocument(new NetworkIdDTO(userNetworkId), customDocHandlerDocumentType);
272         workflowDocument.setTitle("Routing style");
273         workflowDocument.routeDocument("routing this document.");
274         // verify the document is enroute for jhopf
275         workflowDocument = new WorkflowDocument(new NetworkIdDTO("jhopf"),workflowDocument.getRouteHeaderId());
276         assertTrue(workflowDocument.stateIsEnroute());
277         assertTrue(workflowDocument.isApprovalRequested());
278         workflowDocument.approve("");
279         workflowDocument = new WorkflowDocument(new NetworkIdDTO("jhopf"),workflowDocument.getRouteHeaderId());
280         assertTrue(workflowDocument.stateIsFinal());
281 
282         workflowDocument = new WorkflowDocument(new NetworkIdDTO(userNetworkId), customDocHandlerDocumentType);
283         workflowDocument.setTitle("Routing style");
284         workflowDocument.routeDocument("routing this document.");
285         // verify the document is enroute for jhopf
286         workflowDocument = new WorkflowDocument(new NetworkIdDTO("jhopf"),workflowDocument.getRouteHeaderId());
287         assertTrue(workflowDocument.stateIsEnroute());
288         assertTrue(workflowDocument.isApprovalRequested());
289 
290         Person user = KIMServiceLocator.getPersonService().getPersonByPrincipalName(userNetworkId);
291         DocSearchCriteriaDTO criteria = new DocSearchCriteriaDTO();
292         criteria.setSuperUserSearch("YES");
293         criteria.setDocTypeFullName(customDocHandlerDocumentType);
294         DocumentSearchResultComponents result = docSearchService.getList(user.getPrincipalId(), criteria);
295         assertNotNull(result);
296         assertNotNull(result.getSearchResults());
297         assertEquals("Search returned invalid number of documents", 2, result.getSearchResults().size());
298         for (DocumentSearchResult resultElement : result.getSearchResults()) {
299 	    KeyValueSort kvs = resultElement.getResultContainer(DocumentSearchResult.PROPERTY_NAME_ROUTE_HEADER_ID);
300 	    assertNotNull("A valid column field value should be returned for key " + DocumentSearchResult.PROPERTY_NAME_ROUTE_HEADER_ID, kvs);
301 	    assertTrue("The document handler redirect for the client should be included in the route header id url", kvs.getValue().contains(KEWConstants.DOC_HANDLER_REDIRECT_PAGE));
302 	    assertTrue("The document handler redirect for the client should include the command value for super user search", kvs.getValue().contains(KEWConstants.SUPERUSER_COMMAND));
303 	}
304 
305         user = KIMServiceLocator.getPersonService().getPersonByPrincipalName(userNetworkId);
306         criteria = new DocSearchCriteriaDTO();
307         criteria.setSuperUserSearch("YES");
308         result = docSearchService.getList(user.getPrincipalId(), criteria);
309         assertNotNull(result);
310         assertNotNull(result.getSearchResults());
311         assertEquals("Search returned invalid number of documents", 3, result.getSearchResults().size());
312         for (DocumentSearchResult resultElement : result.getSearchResults()) {
313 	    KeyValueSort routeHeaderIdValue = resultElement.getResultContainer(DocumentSearchResult.PROPERTY_NAME_ROUTE_HEADER_ID);
314 	    assertNotNull("A valid column field value should be returned for key " + DocumentSearchResult.PROPERTY_NAME_ROUTE_HEADER_ID, routeHeaderIdValue);
315 	    KeyValueSort documentTypeValue = resultElement.getResultContainer(DocumentSearchResult.PROPERTY_NAME_DOC_TYPE_LABEL);
316 	    assertNotNull("A valid column field value should be returned for key " + DocumentSearchResult.PROPERTY_NAME_DOC_TYPE_LABEL, documentTypeValue);
317 	    if (customDocHandlerDocumentType.equals(documentTypeValue.getValue())) {
318 		assertTrue("The document handler redirect for the client should be included in the route header id url", routeHeaderIdValue.getValue().contains(KEWConstants.DOC_HANDLER_REDIRECT_PAGE));
319 		assertTrue("The document handler redirect for the client should include the command value for super user search", routeHeaderIdValue.getValue().contains(KEWConstants.SUPERUSER_COMMAND));
320 	    } else if (standardDocHandlerDocumentType.equals(documentTypeValue.getValue())) {
321 		assertTrue("The document handler redirect for the client should be included in the route header id url", !routeHeaderIdValue.getValue().contains(KEWConstants.DOC_HANDLER_REDIRECT_PAGE));
322 	    } else {
323 		fail("Found document search result row with document type '" + documentTypeValue.getValue() + "' that should not have existed");
324 	    }
325 	}
326     }
327 
328     /**
329      * Tests the usage of wildcards on the regular document search attributes.
330      * @throws Exception
331      */
332     @Test public void testDocSearch_WildcardsOnRegularAttributes() throws Exception {
333     	// TODO: Add some wildcard testing for the document type attribute once wildcards are usable with it.
334 
335     	// Route some test documents.
336     	String docTypeName = "SearchDocType";
337     	String[] principalNames = {"bmcgough", "quickstart", "rkirkend"};
338     	String[] titles = {"The New Doc", "Document Number 2", "Some New Document"};
339     	String[] docIds = new String[titles.length];
340     	String[] appDocIds = {"6543", "5432", "4321"};
341     	String[] approverNames = {null, "jhopf", null};
342     	for (int i = 0; i < titles.length; i++) {
343         	WorkflowDocument workflowDocument = new WorkflowDocument(
344         			KIMServiceLocator.getPersonService().getPersonByPrincipalName(principalNames[i]).getPrincipalId(), docTypeName);
345         	workflowDocument.setTitle(titles[i]);
346         	workflowDocument.setAppDocId(appDocIds[i]);
347         	workflowDocument.routeDocument("routing this document.");
348         	docIds[i] = workflowDocument.getRouteHeaderId().toString();
349         	if (approverNames[i] != null) {
350         		workflowDocument.setPrincipalId(KIMServiceLocator.getPersonService().getPersonByPrincipalName(approverNames[i]).getPrincipalId());
351         		workflowDocument.approve("approving this document.");
352         	}
353     	}
354         String principalId = KIMServiceLocator.getPersonService().getPersonByPrincipalName("bmcgough").getPrincipalId();
355         DocSearchCriteriaDTO criteria = null;
356         List<DocumentSearchResult> searchResults = null;
357         DocumentSearchResultComponents result = null;
358 
359         // Test the wildcards on the initiator attribute.
360         String[] searchStrings = {"!quickstart", "!rkirkend!bmcgough", "!quickstart&&!rkirkend", "!admin", "user1", "quickstart|bmcgough",
361         		"admin|rkirkend", ">bmcgough", ">=rkirkend", "<bmcgough", "<=quickstart", ">bmcgough&&<=rkirkend", "<rkirkend&&!bmcgough",
362         		"?mc?oug?", "*t", "*i?k*", "*", "!quick*", "!b???????!?kirk???", "!*g*&&!*k*", ">bmc?ough", "<=quick*", "quickstart..rkirkend"};
363         int[] expectedResults = {2, 1, 1, 3, 0, 2, 1, 2, 1, 0, 2, 2, 1, 1, 1, 2, 3, 2, 1, 0, 2, 1, 2/*1*/};
364         for (int i = 0; i < searchStrings.length; i++) {
365         	criteria = new DocSearchCriteriaDTO();
366         	criteria.setInitiator(searchStrings[i]);
367         	result = docSearchService.getList(principalId, criteria);
368         	searchResults = result.getSearchResults();
369         	assertEquals("Initiator search at index " + i + " retrieved the wrong number of documents.", expectedResults[i], searchResults.size());
370         }
371 
372         // Test the wildcards on the approver attribute.
373         searchStrings = new String[] {"jhopf","!jhopf", ">jhopf", "<jjopf", ">=quickstart", "<=jhopf", "jhope..jhopg", "?hopf", "*i*", "!*f", "j*"};
374         expectedResults = new int[] {1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1};
375         for (int i = 0; i < searchStrings.length; i++) {
376         	criteria = new DocSearchCriteriaDTO();
377         	criteria.setApprover(searchStrings[i]);
378         	result = docSearchService.getList(principalId, criteria);
379         	searchResults = result.getSearchResults();
380         	assertEquals("Approver search at index " + i + " retrieved the wrong number of documents.", expectedResults[i], searchResults.size());
381         }
382 
383         // Test the wildcards on the document/notification ID attribute. The string wildcards should get ignored, since the doc ID is not a string.
384         searchStrings = new String[] {"!"+docIds[0], docIds[1]+"|"+docIds[2], "<="+docIds[1], ">="+docIds[2], "<"+docIds[0]+"&&>"+docIds[2],
385         		">"+docIds[1], "<"+docIds[2]+"&&!"+docIds[0], docIds[0]+".."+docIds[2], "?"+docIds[1]+"*", "?9*7"};
386         expectedResults = new int[] {1, 2, 2, 1, 0, 1, 1, 3/*2*/, 1, 0};
387         for (int i = 0; i < searchStrings.length; i++) {
388         	criteria = new DocSearchCriteriaDTO();
389         	criteria.setRouteHeaderId(searchStrings[i]);
390         	result = docSearchService.getList(principalId, criteria);
391         	searchResults = result.getSearchResults();
392         	assertEquals("Doc ID search at index " + i + " retrieved the wrong number of documents.", expectedResults[i], searchResults.size());
393         }
394 
395         // Test the wildcards on the application document/notification ID attribute. The string wildcards should work, since the app doc ID is a string.
396         searchStrings = new String[] {"6543", "5432|4321", ">4321", "<=5432", ">=6543", "<3210", "!3210", "!5432", "!4321!5432", ">4321&&!6543",
397         		"*5?3*", "*", "?3?1", "!*43*", "!???2", ">43*1", "<=5432&&!?32?", "5432..6543"};
398         expectedResults = new int[] {1, 2, 2, 2, 1, 0, 3, 2, 1, 1, 2, 3, 1, 0, 2, 3, 1, 2/*1*/};
399         for (int i = 0; i < searchStrings.length; i++) {
400         	criteria = new DocSearchCriteriaDTO();
401         	criteria.setAppDocId(searchStrings[i]);
402         	result = docSearchService.getList(principalId, criteria);
403         	searchResults = result.getSearchResults();
404         	if(expectedResults[i] !=  searchResults.size()){        		
405         		assertEquals("App doc ID search at index " + i + " retrieved the wrong number of documents.", expectedResults[i], searchResults.size());
406         	}
407         }
408 
409         // Test the wildcards on the viewer attribute.
410         searchStrings = new String[] {"jhopf","!jhopf", ">jhopf", "<jjopf", ">=quickstart", "<=jhopf", "jhope..jhopg", "?hopf", "*i*", "!*f", "j*"};
411         expectedResults = new int[] {3, 0, 0, 3, 0, 3, 3, 3, 0, 0, 3};
412         for (int i = 0; i < searchStrings.length; i++) {
413         	criteria = new DocSearchCriteriaDTO();
414         	criteria.setViewer(searchStrings[i]);
415         	result = docSearchService.getList(principalId, criteria);
416         	searchResults = result.getSearchResults();
417         	if(expectedResults[i] !=  searchResults.size()){        		
418         		assertEquals("Viewer search at index " + i + " retrieved the wrong number of documents.", expectedResults[i], searchResults.size());
419         	}
420         }
421 
422         // Test the wildcards on the title attribute.
423         searchStrings = new String[] {"Some New Document", "Document Number 2|The New Doc", "!The New Doc", "!Some New Document!Document Number 2",
424         		"!The New Doc&&!Some New Document", ">Document Number 2", "<=Some New Document", ">=The New Doc&&<Some New Document", ">A New Doc",
425         		"<Some New Document|The New Doc", ">=Document Number 2&&!Some New Document", "*Docu??nt*", "*New*", "The ??? Doc", "*Doc*", "*Number*",
426         		"Some New Document..The New Doc", "Document..The", "*New*&&!*Some*", "!The ??? Doc|!*New*"};
427         expectedResults = new int[] {1, 2, 2, 1, 1, 2, 2, 0, 3, 2, 2, 2, 2, 1, 3, 1, 2/*1*/, 2, 1, 2};
428         for (int i = 0; i < searchStrings.length; i++) {
429         	criteria = new DocSearchCriteriaDTO();
430         	criteria.setDocTitle(searchStrings[i]);
431         	result = docSearchService.getList(principalId, criteria);
432         	searchResults = result.getSearchResults();
433         	if(expectedResults[i] !=  searchResults.size()){
434         		assertEquals("Doc title search at index " + i + " retrieved the wrong number of documents.", expectedResults[i], searchResults.size());
435         	}
436         }
437 
438 
439     }
440 }