001: /*
002: * Copyright 2005-2007 The Kuali Foundation.
003: *
004: *
005: * Licensed under the Educational Community License, Version 1.0 (the "License");
006: * you may not use this file except in compliance with the License.
007: * You may obtain a copy of the License at
008: *
009: * http://www.opensource.org/licenses/ecl1.php
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package edu.iu.uis.eden.docsearch;
018:
019: import java.sql.Timestamp;
020: import java.util.Calendar;
021: import java.util.Iterator;
022: import java.util.List;
023:
024: import org.junit.Test;
025: import org.kuali.workflow.test.WorkflowTestCase;
026:
027: import edu.iu.uis.eden.KEWServiceLocator;
028: import edu.iu.uis.eden.WorkflowServiceErrorException;
029: import edu.iu.uis.eden.clientapp.WorkflowDocument;
030: import edu.iu.uis.eden.clientapp.vo.NetworkIdVO;
031: import edu.iu.uis.eden.doctype.DocumentType;
032: import edu.iu.uis.eden.doctype.DocumentTypeService;
033: import edu.iu.uis.eden.lookupable.Field;
034: import edu.iu.uis.eden.lookupable.Row;
035: import edu.iu.uis.eden.routeheader.DocumentRouteHeaderValue;
036: import edu.iu.uis.eden.user.AuthenticationUserId;
037: import edu.iu.uis.eden.user.UserService;
038: import edu.iu.uis.eden.user.WorkflowUser;
039:
040: /**
041: * Tests the StandardGenericXMLSearchableAttribute.
042: *
043: * KULWF-654: Tests the resolution to this issue by configuring a CustomActionListAttribute as well as a
044: * searchable attribute.
045: */
046: public class SearchableAttributeTest extends WorkflowTestCase {
047:
048: protected void loadTestData() throws Exception {
049: loadXmlFile("SearchAttributeConfig.xml");
050: }
051:
052: // private StandardGenericXMLSearchableAttribute getAttribute(String name) {
053: // String attName = name;
054: // if (attName == null) {
055: // attName = "XMLSearchableAttribute";
056: // }
057: // RuleAttribute ruleAttribute = KEWServiceLocator.getRuleAttributeService().findByName(attName);
058: //
059: // StandardGenericXMLSearchableAttribute attribute = new StandardGenericXMLSearchableAttribute();
060: // attribute.setRuleAttribute(ruleAttribute);
061: // return attribute;
062: // }
063: //
064: private SearchAttributeCriteriaComponent createSearchAttributeCriteriaComponent(
065: String key, String value, Boolean isLowerBoundValue,
066: DocumentType docType) {
067: String formKey = (isLowerBoundValue == null) ? key
068: : ((isLowerBoundValue != null && isLowerBoundValue
069: .booleanValue()) ? SearchableAttribute.RANGE_LOWER_BOUND_PROPERTY_PREFIX
070: : SearchableAttribute.RANGE_UPPER_BOUND_PROPERTY_PREFIX);
071: String savedKey = key;
072: SearchAttributeCriteriaComponent sacc = new SearchAttributeCriteriaComponent(
073: formKey, value, savedKey);
074: Field field = getFieldByFormKey(docType, formKey);
075: if (field != null) {
076: sacc.setSearchableAttributeValue(DocSearchUtils
077: .getSearchableAttributeValueByDataTypeString(field
078: .getFieldDataType()));
079: sacc.setRangeSearch(field.isMemberOfRange());
080: sacc.setAllowWildcards(field.isAllowingWildcards());
081: sacc.setAutoWildcardBeginning(field
082: .isAutoWildcardAtBeginning());
083: sacc.setAutoWildcardEnd(field.isAutoWildcardAtEnding());
084: sacc.setCaseSensitive(field.isCaseSensitive());
085: sacc.setSearchInclusive(field.isInclusive());
086: sacc.setSearchable(field.isSearchable());
087: sacc.setCanHoldMultipleValues(Field.MULTI_VALUE_FIELD_TYPES
088: .contains(field.getFieldType()));
089: }
090: return sacc;
091: }
092:
093: private Field getFieldByFormKey(DocumentType docType, String formKey) {
094: if (docType == null) {
095: return null;
096: }
097: for (SearchableAttribute searchableAttribute : docType
098: .getSearchableAttributes()) {
099: for (Row row : searchableAttribute.getSearchingRows()) {
100: for (Field field : row.getFields()) {
101: if (field.getPropertyName().equals(formKey)) {
102: return field;
103: }
104: }
105: }
106: }
107: return null;
108: }
109:
110: @Test
111: public void testCustomSearchableAttributesWithDataType()
112: throws Exception {
113: String documentTypeName = "SearchDocType";
114: DocumentType docType = ((DocumentTypeService) KEWServiceLocator
115: .getService(KEWServiceLocator.DOCUMENT_TYPE_SERVICE))
116: .findByName(documentTypeName);
117: String userNetworkId = "rkirkend";
118: WorkflowDocument workflowDocument = new WorkflowDocument(
119: new NetworkIdVO(userNetworkId), documentTypeName);
120: workflowDocument.setTitle("Routing style");
121: workflowDocument.routeDocument("routing this document.");
122:
123: workflowDocument = new WorkflowDocument(new NetworkIdVO(
124: userNetworkId), workflowDocument.getRouteHeaderId());
125: DocumentRouteHeaderValue doc = KEWServiceLocator
126: .getRouteHeaderService().getRouteHeader(
127: workflowDocument.getRouteHeaderId());
128: assertEquals("Wrong number of searchable attributes", 4, doc
129: .getSearchableAttributeValues().size());
130: for (Iterator iter = doc.getSearchableAttributeValues()
131: .iterator(); iter.hasNext();) {
132: SearchableAttributeValue attributeValue = (SearchableAttributeValue) iter
133: .next();
134: if (attributeValue instanceof SearchableAttributeStringValue) {
135: SearchableAttributeStringValue realValue = (SearchableAttributeStringValue) attributeValue;
136: assertEquals(
137: "The only String attribute that should have been added has key '"
138: + TestXMLSearchableAttributeString.SEARCH_STORAGE_KEY
139: + "'",
140: TestXMLSearchableAttributeString.SEARCH_STORAGE_KEY,
141: realValue.getSearchableAttributeKey());
142: assertEquals(
143: "The only String attribute that should have been added has value '"
144: + TestXMLSearchableAttributeString.SEARCH_STORAGE_VALUE
145: + "'",
146: TestXMLSearchableAttributeString.SEARCH_STORAGE_VALUE,
147: realValue.getSearchableAttributeValue());
148: } else if (attributeValue instanceof SearchableAttributeLongValue) {
149: SearchableAttributeLongValue realValue = (SearchableAttributeLongValue) attributeValue;
150: assertEquals(
151: "The only Long attribute that should have been added has key '"
152: + TestXMLSearchableAttributeLong.SEARCH_STORAGE_KEY
153: + "'",
154: TestXMLSearchableAttributeLong.SEARCH_STORAGE_KEY,
155: realValue.getSearchableAttributeKey());
156: assertEquals(
157: "The only Long attribute that should have been added has value '"
158: + TestXMLSearchableAttributeLong.SEARCH_STORAGE_VALUE
159: + "'",
160: TestXMLSearchableAttributeLong.SEARCH_STORAGE_VALUE,
161: realValue.getSearchableAttributeValue());
162: } else if (attributeValue instanceof SearchableAttributeFloatValue) {
163: SearchableAttributeFloatValue realValue = (SearchableAttributeFloatValue) attributeValue;
164: assertEquals(
165: "The only Float attribute that should have been added has key '"
166: + TestXMLSearchableAttributeFloat.SEARCH_STORAGE_KEY
167: + "'",
168: TestXMLSearchableAttributeFloat.SEARCH_STORAGE_KEY,
169: realValue.getSearchableAttributeKey());
170: assertEquals(
171: "The only Float attribute that should have been added has value '"
172: + TestXMLSearchableAttributeFloat.SEARCH_STORAGE_VALUE
173: + "'",
174: TestXMLSearchableAttributeFloat.SEARCH_STORAGE_VALUE,
175: realValue.getSearchableAttributeValue());
176: } else if (attributeValue instanceof SearchableAttributeDateTimeValue) {
177: SearchableAttributeDateTimeValue realValue = (SearchableAttributeDateTimeValue) attributeValue;
178: assertEquals(
179: "The only DateTime attribute that should have been added has key '"
180: + TestXMLSearchableAttributeDateTime.SEARCH_STORAGE_KEY
181: + "'",
182: TestXMLSearchableAttributeDateTime.SEARCH_STORAGE_KEY,
183: realValue.getSearchableAttributeKey());
184: Calendar testDate = Calendar.getInstance();
185: testDate
186: .setTimeInMillis(TestXMLSearchableAttributeDateTime.SEARCH_STORAGE_VALUE_IN_MILLS);
187: testDate.set(Calendar.SECOND, 0);
188: testDate.set(Calendar.MILLISECOND, 0);
189: Calendar attributeDate = Calendar.getInstance();
190: attributeDate.setTimeInMillis(realValue
191: .getSearchableAttributeValue().getTime());
192: attributeDate.set(Calendar.SECOND, 0);
193: attributeDate.set(Calendar.MILLISECOND, 0);
194: assertEquals(
195: "The month value for the searchable attribute is wrong",
196: testDate.get(Calendar.MONTH), attributeDate
197: .get(Calendar.MONTH));
198: assertEquals(
199: "The date value for the searchable attribute is wrong",
200: testDate.get(Calendar.DATE), attributeDate
201: .get(Calendar.DATE));
202: assertEquals(
203: "The year value for the searchable attribute is wrong",
204: testDate.get(Calendar.YEAR), attributeDate
205: .get(Calendar.YEAR));
206: } else {
207: fail("Searchable Attribute Value base class should be one of the four checked always");
208: }
209: }
210:
211: DocumentSearchService docSearchService = (DocumentSearchService) KEWServiceLocator
212: .getService(KEWServiceLocator.DOCUMENT_SEARCH_SERVICE);
213: UserService userService = (UserService) KEWServiceLocator
214: .getService(KEWServiceLocator.USER_SERVICE);
215: WorkflowUser user = userService
216: .getWorkflowUser(new AuthenticationUserId(userNetworkId));
217:
218: DocSearchCriteriaVO criteria = new DocSearchCriteriaVO();
219: criteria.setDocTypeFullName(documentTypeName);
220: criteria
221: .addSearchableAttribute(createSearchAttributeCriteriaComponent(
222: TestXMLSearchableAttributeString.SEARCH_STORAGE_KEY,
223: TestXMLSearchableAttributeString.SEARCH_STORAGE_VALUE,
224: null, docType));
225: DocumentSearchResultComponents result = docSearchService
226: .getList(user, criteria);
227: List searchResults = result.getSearchResults();
228:
229: assertEquals("Search results should have one document.", 1,
230: searchResults.size());
231:
232: criteria = new DocSearchCriteriaVO();
233: criteria.setDocTypeFullName(documentTypeName);
234: criteria
235: .addSearchableAttribute(createSearchAttributeCriteriaComponent(
236: TestXMLSearchableAttributeString.SEARCH_STORAGE_KEY,
237: "fred", null, docType));
238: result = docSearchService.getList(user, criteria);
239: searchResults = result.getSearchResults();
240:
241: assertEquals("Search results should be empty.", 0,
242: searchResults.size());
243:
244: criteria = new DocSearchCriteriaVO();
245: criteria.setDocTypeFullName(documentTypeName);
246: criteria
247: .addSearchableAttribute(createSearchAttributeCriteriaComponent(
248: "fakeproperty", "doesntexist", null, docType));
249: try {
250: result = docSearchService.getList(user, criteria);
251: fail("Search results should be throwing a validation exception for use of non-existant searchable attribute");
252: } catch (WorkflowServiceErrorException e) {
253: }
254:
255: criteria = new DocSearchCriteriaVO();
256: criteria.setDocTypeFullName(documentTypeName);
257: criteria
258: .addSearchableAttribute(createSearchAttributeCriteriaComponent(
259: TestXMLSearchableAttributeLong.SEARCH_STORAGE_KEY,
260: TestXMLSearchableAttributeLong.SEARCH_STORAGE_VALUE
261: .toString(), null, docType));
262: result = docSearchService.getList(user, criteria);
263: searchResults = result.getSearchResults();
264: assertEquals("Search results should have one document.", 1,
265: searchResults.size());
266:
267: criteria = new DocSearchCriteriaVO();
268: criteria.setDocTypeFullName(documentTypeName);
269: criteria
270: .addSearchableAttribute(createSearchAttributeCriteriaComponent(
271: TestXMLSearchableAttributeLong.SEARCH_STORAGE_KEY,
272: "1111111", null, docType));
273: result = docSearchService.getList(user, criteria);
274: searchResults = result.getSearchResults();
275: assertEquals("Search results should be empty.", 0,
276: searchResults.size());
277:
278: criteria = new DocSearchCriteriaVO();
279: criteria.setDocTypeFullName(documentTypeName);
280: criteria
281: .addSearchableAttribute(createSearchAttributeCriteriaComponent(
282: "fakeymcfakefake", "99999999", null, docType));
283: try {
284: result = docSearchService.getList(user, criteria);
285: fail("Search results should be throwing a validation exception for use of non-existant searchable attribute");
286: } catch (WorkflowServiceErrorException e) {
287: }
288:
289: criteria = new DocSearchCriteriaVO();
290: criteria.setDocTypeFullName(documentTypeName);
291: criteria
292: .addSearchableAttribute(createSearchAttributeCriteriaComponent(
293: TestXMLSearchableAttributeFloat.SEARCH_STORAGE_KEY,
294: TestXMLSearchableAttributeFloat.SEARCH_STORAGE_VALUE
295: .toString(), null, docType));
296: result = docSearchService.getList(user, criteria);
297: searchResults = result.getSearchResults();
298: assertEquals("Search results should have one document.", 1,
299: searchResults.size());
300:
301: criteria = new DocSearchCriteriaVO();
302: criteria.setDocTypeFullName(documentTypeName);
303: criteria
304: .addSearchableAttribute(createSearchAttributeCriteriaComponent(
305: TestXMLSearchableAttributeFloat.SEARCH_STORAGE_KEY,
306: "215.3548", null, docType));
307: result = docSearchService.getList(user, criteria);
308: searchResults = result.getSearchResults();
309: assertEquals("Search results should be empty.", 0,
310: searchResults.size());
311:
312: criteria = new DocSearchCriteriaVO();
313: criteria.setDocTypeFullName(documentTypeName);
314: criteria
315: .addSearchableAttribute(createSearchAttributeCriteriaComponent(
316: "fakeylostington", "9999.9999", null, docType));
317: try {
318: result = docSearchService.getList(user, criteria);
319: fail("Search results should be throwing a validation exception for use of non-existant searchable attribute");
320: } catch (WorkflowServiceErrorException e) {
321: }
322:
323: criteria = new DocSearchCriteriaVO();
324: criteria.setDocTypeFullName(documentTypeName);
325: criteria
326: .addSearchableAttribute(createSearchAttributeCriteriaComponent(
327: TestXMLSearchableAttributeDateTime.SEARCH_STORAGE_KEY,
328: DocSearchUtils
329: .getDisplayValueWithDateOnly(new Timestamp(
330: TestXMLSearchableAttributeDateTime.SEARCH_STORAGE_VALUE_IN_MILLS)),
331: null, docType));
332: result = docSearchService.getList(user, criteria);
333: searchResults = result.getSearchResults();
334: assertEquals("Search results should have one document.", 1,
335: searchResults.size());
336:
337: criteria = new DocSearchCriteriaVO();
338: criteria.setDocTypeFullName(documentTypeName);
339: criteria
340: .addSearchableAttribute(createSearchAttributeCriteriaComponent(
341: TestXMLSearchableAttributeDateTime.SEARCH_STORAGE_KEY,
342: "07/06/1979", null, docType));
343: result = docSearchService.getList(user, criteria);
344: searchResults = result.getSearchResults();
345: assertEquals("Search results should be empty.", 0,
346: searchResults.size());
347:
348: criteria = new DocSearchCriteriaVO();
349: criteria.setDocTypeFullName(documentTypeName);
350: criteria
351: .addSearchableAttribute(createSearchAttributeCriteriaComponent(
352: "lastingsfakerson", "07/06/2007", null, docType));
353: try {
354: result = docSearchService.getList(user, criteria);
355: fail("Search results should be throwing a validation exception for use of non-existant searchable attribute");
356: } catch (WorkflowServiceErrorException e) {
357: }
358: }
359:
360: /**
361: * Tests searching documents with searchable attributes
362: * @throws WorkflowException
363: */
364: @Test
365: public void testSearchAttributesAcrossDocumentTypeVersions()
366: throws Exception {
367: // first test searching for an initial version of the doc which does not have a searchable attribute
368: loadXmlFile("testdoc0.xml");
369:
370: String documentTypeName = "SearchDoc";
371: WorkflowDocument doc = new WorkflowDocument(new NetworkIdVO(
372: "arh14"), documentTypeName);
373: DocumentType docType = ((DocumentTypeService) KEWServiceLocator
374: .getService(KEWServiceLocator.DOCUMENT_TYPE_SERVICE))
375: .findByName(documentTypeName);
376: doc.routeDocument("routing");
377:
378: DocumentSearchService docSearchService = (DocumentSearchService) KEWServiceLocator
379: .getService(KEWServiceLocator.DOCUMENT_SEARCH_SERVICE);
380: UserService userService = (UserService) KEWServiceLocator
381: .getService(KEWServiceLocator.USER_SERVICE);
382:
383: DocSearchCriteriaVO criteria = new DocSearchCriteriaVO();
384: criteria.setDocTypeFullName(documentTypeName);
385: criteria.setFromDateCreated("01/01/2004");
386:
387: WorkflowUser user = userService
388: .getWorkflowUser(new AuthenticationUserId("arh14"));
389: DocumentSearchResultComponents result = docSearchService
390: .getList(user, criteria);
391: assertEquals(1, result.getSearchResults().size());
392:
393: // now upload the new version with a searchable attribute
394: loadXmlFile("testdoc1.xml");
395: docType = ((DocumentTypeService) KEWServiceLocator
396: .getService(KEWServiceLocator.DOCUMENT_TYPE_SERVICE))
397: .findByName(documentTypeName);
398:
399: // route a new doc
400: doc = new WorkflowDocument(new NetworkIdVO("arh14"),
401: documentTypeName);
402: doc.routeDocument("routing");
403:
404: // with no attribute criteria, both docs should be found
405: criteria = new DocSearchCriteriaVO();
406: criteria.setDocTypeFullName(documentTypeName);
407: criteria.setFromDateCreated("01/01/2004");
408:
409: result = docSearchService.getList(user, criteria);
410: assertEquals(2, result.getSearchResults().size());
411:
412: // search with specific SearchableAttribute value
413: criteria = new DocSearchCriteriaVO();
414: criteria.setDocTypeFullName(documentTypeName);
415: criteria.setFromDateCreated("01/01/2004");
416: criteria
417: .addSearchableAttribute(createSearchAttributeCriteriaComponent(
418: "MockSearchableAttributeKey",
419: "Mock Searchable Attribute", null, docType));
420: criteria.getSearchableAttributes().set(
421: 0,
422: createSearchAttributeCriteriaComponent(
423: "MockSearchableAttributeKey",
424: "MockSearchableAttributeValue", null, docType));
425: // criteria.addSearchableAttribute(new KeyLabelPair("MockSearchableAttributeKey", "Mock Searchable Attribute"));
426: // criteria.setSearchableAttribute(0, new KeyLabelPair("MockSearchableAttributeKey", "MockSearchableAttributeValue"));
427:
428: result = docSearchService.getList(user, criteria);
429: assertEquals(1, result.getSearchResults().size());
430:
431: // search with any SearchableAttribute value
432: criteria = new DocSearchCriteriaVO();
433: criteria.setDocTypeFullName(documentTypeName);
434: criteria.setFromDateCreated("01/01/2004");
435: criteria
436: .addSearchableAttribute(createSearchAttributeCriteriaComponent(
437: "MockSearchableAttributeKey",
438: "Mock Searchable Attribute", null, docType));
439: criteria.getSearchableAttributes()
440: .set(
441: 0,
442: createSearchAttributeCriteriaComponent(
443: "MockSearchableAttributeKey", "", null,
444: docType));
445: // criteria.addSearchableAttribute(new KeyLabelPair("MockSearchableAttributeKey", "Mock Searchable Attribute"));
446: // criteria.setSearchableAttribute(0, new KeyLabelPair("MockSearchableAttributeKey", ""));
447:
448: result = docSearchService.getList(user, criteria);
449: // should return two because an empty value above will return any value of the 'MockSearchableAttributeKey' key including the previous document
450: // that doesn't even have a record of that field being saved to the database
451: assertEquals(2, result.getSearchResults().size());
452: }
453:
454: }
|