1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.kew.docsearch.xml;
17
18 import com.google.common.base.Function;
19 import org.apache.commons.lang.StringUtils;
20 import org.junit.Before;
21 import org.junit.Ignore;
22 import org.junit.Test;
23 import org.kuali.rice.core.api.uif.RemotableAttributeError;
24 import org.kuali.rice.core.api.uif.RemotableAttributeField;
25 import org.kuali.rice.core.framework.persistence.jdbc.sql.SQLUtils;
26 import org.kuali.rice.kew.api.KewApiConstants;
27 import org.kuali.rice.kew.api.WorkflowDocument;
28 import org.kuali.rice.kew.api.WorkflowDocumentFactory;
29 import org.kuali.rice.kew.api.document.attribute.WorkflowAttributeDefinition;
30 import org.kuali.rice.kew.api.document.search.DocumentSearchCriteria;
31 import org.kuali.rice.kew.api.document.search.DocumentSearchResults;
32 import org.kuali.rice.kew.api.extension.ExtensionDefinition;
33 import org.kuali.rice.kew.docsearch.DocumentSearchInternalUtils;
34 import org.kuali.rice.kew.docsearch.DocumentSearchTestBase;
35 import org.kuali.rice.kew.docsearch.SearchableAttributeDateTimeValue;
36 import org.kuali.rice.kew.docsearch.SearchableAttributeFloatValue;
37 import org.kuali.rice.kew.docsearch.SearchableAttributeLongValue;
38 import org.kuali.rice.kew.docsearch.SearchableAttributeStringValue;
39 import org.kuali.rice.kew.docsearch.TestXMLSearchableAttributeDateTime;
40 import org.kuali.rice.kew.docsearch.TestXMLSearchableAttributeFloat;
41 import org.kuali.rice.kew.docsearch.TestXMLSearchableAttributeLong;
42 import org.kuali.rice.kew.docsearch.TestXMLSearchableAttributeString;
43 import org.kuali.rice.kew.docsearch.service.DocumentSearchService;
44 import org.kuali.rice.kew.doctype.bo.DocumentType;
45 import org.kuali.rice.kew.doctype.service.DocumentTypeService;
46 import org.kuali.rice.kew.exception.WorkflowServiceErrorException;
47 import org.kuali.rice.kew.service.KEWServiceLocator;
48 import org.kuali.rice.kim.api.identity.Person;
49 import org.kuali.rice.kim.api.services.KimApiServiceLocator;
50 import org.kuali.rice.kns.util.FieldUtils;
51 import org.kuali.rice.kns.web.ui.Field;
52 import org.kuali.rice.kns.web.ui.Row;
53 import org.kuali.rice.krad.util.KRADConstants;
54
55 import javax.annotation.Nullable;
56 import java.math.BigDecimal;
57 import java.util.Calendar;
58 import java.util.List;
59 import java.util.concurrent.Callable;
60
61 import static org.junit.Assert.*;
62 import static org.junit.Assert.assertEquals;
63
64
65
66
67
68
69
70 public class StandardGenericXMLSearchableAttributeRangesTest extends DocumentSearchTestBase {
71 private DocumentSearchService docSearchService;
72
73 protected void loadTestData() throws Exception {
74 loadXmlFile("XmlConfig.xml");
75 }
76
77 @Before
78 public void retrieveDocSearchSvc() {
79 docSearchService = (DocumentSearchService) KEWServiceLocator.getService(KEWServiceLocator.DOCUMENT_SEARCH_SERVICE);
80 }
81
82
83
84
85
86
87 @Test public void testGetSearchingRowsUsingRangeSearches() {
88 StandardGenericXMLSearchableAttribute searchAttribute = getAttribute("XMLSearchableAttributeStringRange");
89 ExtensionDefinition ed = createExtensionDefinition("XMLSearchableAttributeStringRange");
90
91 String documentTypeName = "SearchDocType";
92 List<RemotableAttributeField> remotableAttributeFields = searchAttribute.getSearchFields(ed, documentTypeName);
93 List<Row> rows = FieldUtils.convertRemotableAttributeFields(remotableAttributeFields);
94
95 if ((new SearchableAttributeStringValue()).allowsRangeSearches()) {
96 assertEquals("Invalid number of search rows", 2, rows.size());
97 for (int i = 1; i <= rows.size(); i++) {
98 Row row = rows.get(i - 1);
99 assertEquals("Invalid number of fields for search row " + i, 1, row.getFields().size());
100 Field field = (Field)(row.getField(0));
101 assertTrue("Field should be the member of a range",field.isMemberOfRange());
102 if (i == 1) {
103 assertTrue("Field should be inclusive", field.isInclusive());
104 } else {
105 assertFalse("Field should not be inclusive", field.isInclusive());
106 }
107 assertFalse("Field should not be using datepicker", field.isDatePicker());
108 }
109 } else {
110 assertEquals("Invalid number of search rows", 1, remotableAttributeFields.size());
111 Row row = rows.get(0);
112 assertEquals("Invalid number of fields for search row", 1, row.getFields().size());
113 assertFalse("Field is the member of a range when ranges are not allowed",((Field)row.getField(0)).isMemberOfRange());
114 }
115
116 searchAttribute = getAttribute("XMLSearchableAttributeStdLongRange");
117 ed = createExtensionDefinition("XMLSearchableAttributeStdLongRange");
118
119
120
121
122 remotableAttributeFields = searchAttribute.getSearchFields(ed, documentTypeName);
123 rows = FieldUtils.convertRemotableAttributeFields(remotableAttributeFields);
124 if ((new SearchableAttributeLongValue()).allowsRangeSearches()) {
125 assertEquals("Invalid number of search rows", 2, rows.size());
126 for (int i = 1; i <= rows.size(); i++) {
127 Row row = rows.get(i - 1);
128 assertEquals("Invalid number of fields for search row " + i, 1, row.getFields().size());
129 Field field = (Field)(row.getField(0));
130 assertTrue("Field should be the member of a range",field.isMemberOfRange());
131 if (i == 1) {
132 assertTrue("Field should be inclusive", field.isInclusive());
133 } else {
134 assertFalse("Field should not be inclusive", field.isInclusive());
135 }
136 assertFalse("Field should not be using datepicker", field.isDatePicker());
137 }
138 } else {
139 assertEquals("Invalid number of search rows", 1, rows.size());
140 Row row = rows.get(0);
141 assertEquals("Invalid number of fields for search row", 1, row.getFields().size());
142 Field field = (Field)(row.getField(0));
143 assertFalse("Field is the member of a range when ranges are not allowed",field.isMemberOfRange());
144 assertFalse("Field is inclusive when ranges are not allowed",field.isInclusive());
145 assertFalse("Field should not be using datepicker", field.isDatePicker());
146 }
147
148 searchAttribute = getAttribute("XMLSearchableAttributeStdFloatRange");
149 ed = createExtensionDefinition("XMLSearchableAttributeStdFloatRange");
150
151
152
153
154 remotableAttributeFields = searchAttribute.getSearchFields(ed, documentTypeName);
155 rows = FieldUtils.convertRemotableAttributeFields(remotableAttributeFields);
156 if ((new SearchableAttributeFloatValue()).allowsRangeSearches()) {
157 assertEquals("Invalid number of search rows", 2, rows.size());
158 for (int i = 1; i <= rows.size(); i++) {
159 Row row = rows.get(i - 1);
160 assertEquals("Invalid number of fields for search row " + i, 1, row.getFields().size());
161 Field field = (Field)(row.getField(0));
162 assertTrue("Upper and Lower Fields should be members of a range",field.isMemberOfRange());
163 assertFalse("Upper and Lower Fields should not be inclusive",field.isInclusive());
164 String labelValue = null;
165 if (field.getPropertyName().startsWith(KRADConstants.LOOKUP_RANGE_LOWER_BOUND_PROPERTY_PREFIX)) {
166 labelValue = "starting";
167 } else {
168 labelValue = "ending";
169 }
170 assertEquals("Field label is incorrect.", labelValue, field.getFieldLabel());
171 assertFalse("Field should not be using datepicker", field.isDatePicker());
172 }
173 } else {
174 assertEquals("Invalid number of search rows", 1, rows.size());
175 Row row = rows.get(0);
176 assertEquals("Invalid number of fields for search row", 1, row.getFields().size());
177 Field field = (Field)(row.getField(0));
178 assertFalse("Field is the member of a range when ranges are not allowed",field.isMemberOfRange());
179 assertFalse("Field should not be using datepicker", field.isDatePicker());
180 }
181
182 searchAttribute = getAttribute("XMLSearchableAttributeStdDateTimeRange");
183 ed = createExtensionDefinition("XMLSearchableAttributeStdDateTimeRange");
184
185
186
187
188 remotableAttributeFields = searchAttribute.getSearchFields(ed, documentTypeName);
189 assertFalse(remotableAttributeFields.get(0).getAttributeLookupSettings().isLowerDatePicker());
190 assertTrue(remotableAttributeFields.get(0).getAttributeLookupSettings().isUpperDatePicker());
191 rows = FieldUtils.convertRemotableAttributeFields(remotableAttributeFields);
192 if ((new SearchableAttributeDateTimeValue()).allowsRangeSearches()) {
193 assertEquals("Invalid number of search rows", 2, rows.size());
194 for (int i = 0; i < rows.size(); i++) {
195 Row row = rows.get(i);
196 assertTrue("Invalid number of fields for search row", row.getFields().size() > 0);
197 Field field = (Field)(row.getField(0));
198 assertTrue("Field should be the member of a range search", field.isMemberOfRange());
199 if (field.getPropertyName().startsWith(KRADConstants.LOOKUP_RANGE_LOWER_BOUND_PROPERTY_PREFIX)) {
200
201 assertFalse("Lower Field should not be using datepicker field", field.isDatePicker());
202 assertFalse("Lower Field should not be inclusive", field.isInclusive());
203 } else {
204
205 assertTrue("Upper Field should be using datepicker field", field.isDatePicker());
206 assertTrue("Upper Field should not be inclusive", field.isInclusive());
207 assertEquals("Row should have 1 field (with datepicker)", 1, row.getFields().size());
208 assertEquals("Field in row should be of type text", Field.TEXT, row.getField(0).getFieldType());
209
210
211
212 }
213 }
214 } else {
215 assertEquals("Invalid number of search rows", 1, rows.size());
216 Row row = rows.get(0);
217
218 assertEquals("Invalid number of fields", 1, row.getFields().size());
219 assertFalse("Field is the member of a range when ranges are not allowed",((Field)(row.getField(0))).isMemberOfRange());
220 }
221 }
222
223
224
225
226
227 @Test public void testValidateUserSearchRangeInputs() {
228
229 StandardGenericXMLSearchableAttribute searchAttribute = getAttribute("XMLSearchableAttributeStringRange");
230 ExtensionDefinition ed = createExtensionDefinition("XMLSearchableAttributeStringRange");
231
232 RemotableAttributeError error = assertDocumentSearchCriteriaValidation(searchAttribute, ed, TestXMLSearchableAttributeString.SEARCH_STORAGE_KEY, ">= jack", null);
233 assertDocumentSearchCriteriaValidation(searchAttribute, ed, TestXMLSearchableAttributeString.SEARCH_STORAGE_KEY, "<= jack.jack", "differ on upper bound inclusivity");
234 assertDocumentSearchCriteriaValidation(searchAttribute, ed, TestXMLSearchableAttributeString.SEARCH_STORAGE_KEY, "< jack.jack", "Invalid first name");
235 assertDocumentSearchCriteriaValidation(searchAttribute, ed, TestXMLSearchableAttributeString.SEARCH_STORAGE_KEY, ">= jack*jack", null);
236
237
238
239 searchAttribute = getAttribute("XMLSearchableAttributeStdLongRange");
240 ed = createExtensionDefinition("XMLSearchableAttributeStdLongRange");
241
242 assertDocumentSearchCriteriaValidation(searchAttribute, ed, TestXMLSearchableAttributeLong.SEARCH_STORAGE_KEY, "<= " + TestXMLSearchableAttributeLong.SEARCH_STORAGE_VALUE.toString(), "differ on upper bound inclusivity");
243 assertDocumentSearchCriteriaValidation(searchAttribute, ed, TestXMLSearchableAttributeLong.SEARCH_STORAGE_KEY, "< " + TestXMLSearchableAttributeLong.SEARCH_STORAGE_VALUE.toString(), null);
244 assertDocumentSearchCriteriaValidation(searchAttribute, ed, TestXMLSearchableAttributeLong.SEARCH_STORAGE_KEY, ">= " + TestXMLSearchableAttributeLong.SEARCH_STORAGE_VALUE.toString() + ".33","does not conform to standard validation for field type.");
245 assertDocumentSearchCriteriaValidation(searchAttribute, ed, TestXMLSearchableAttributeLong.SEARCH_STORAGE_KEY, "<= jack*jack", "differ on upper bound inclusivity");
246 assertDocumentSearchCriteriaValidation(searchAttribute, ed, TestXMLSearchableAttributeLong.SEARCH_STORAGE_KEY, "< jack*jack", "does not conform to standard validation for field type.");
247
248
249
250
251
252
253
254 searchAttribute = getAttribute("XMLSearchableAttributeStdFloatRange");
255 ed = createExtensionDefinition("XMLSearchableAttributeStdFloatRange");
256 assertDocumentSearchCriteriaValidation(searchAttribute, ed, TestXMLSearchableAttributeFloat.SEARCH_STORAGE_KEY, ">= " + TestXMLSearchableAttributeFloat.SEARCH_STORAGE_VALUE.toString(), "differ on lower bound inclusivity");
257 assertDocumentSearchCriteriaValidation(searchAttribute, ed, TestXMLSearchableAttributeFloat.SEARCH_STORAGE_KEY, "> " + TestXMLSearchableAttributeFloat.SEARCH_STORAGE_VALUE.toString(), null);
258 assertDocumentSearchCriteriaValidation(searchAttribute, ed, TestXMLSearchableAttributeFloat.SEARCH_STORAGE_KEY, "<= " + TestXMLSearchableAttributeFloat.SEARCH_STORAGE_VALUE.toString() + "a", "differ on upper bound inclusivity");
259 assertDocumentSearchCriteriaValidation(searchAttribute, ed, TestXMLSearchableAttributeFloat.SEARCH_STORAGE_KEY, "< " + TestXMLSearchableAttributeFloat.SEARCH_STORAGE_VALUE.toString() + "a", "does not conform to standard validation for field type.");
260 assertDocumentSearchCriteriaValidation(searchAttribute, ed, TestXMLSearchableAttributeFloat.SEARCH_STORAGE_KEY, ">= " + TestXMLSearchableAttributeFloat.SEARCH_STORAGE_VALUE.toString() + "*", "differ on lower bound inclusivity");
261 assertDocumentSearchCriteriaValidation(searchAttribute, ed, TestXMLSearchableAttributeFloat.SEARCH_STORAGE_KEY, "> " + TestXMLSearchableAttributeFloat.SEARCH_STORAGE_VALUE.toString() + "*", "does not conform to standard validation for field type.");
262
263
264
265
266
267
268
269 searchAttribute = getAttribute("XMLSearchableAttributeStdDateTimeRange");
270 ed = createExtensionDefinition("XMLSearchableAttributeStdDateTimeRange");
271 assertDocumentSearchCriteriaValidation(searchAttribute, ed, TestXMLSearchableAttributeDateTime.SEARCH_STORAGE_KEY, "<= " + DocumentSearchInternalUtils.getDisplayValueWithDateOnly(TestXMLSearchableAttributeDateTime.SEARCH_STORAGE_VALUE), null);
272 assertDocumentSearchCriteriaValidation(searchAttribute, ed, TestXMLSearchableAttributeDateTime.SEARCH_STORAGE_KEY, ">= 001/5/08", "differ on lower bound inclusivity");
273 assertDocumentSearchCriteriaValidation(searchAttribute, ed, TestXMLSearchableAttributeDateTime.SEARCH_STORAGE_KEY, "> 001/5/08", null);
274 error = assertDocumentSearchCriteriaValidation(searchAttribute, ed, TestXMLSearchableAttributeDateTime.SEARCH_STORAGE_KEY, ">= 41/5/08", "differ on lower bound inclusivity");
275 error = assertDocumentSearchCriteriaValidation(searchAttribute, ed, TestXMLSearchableAttributeDateTime.SEARCH_STORAGE_KEY, "> 41/5/08", "does not conform to standard validation for field type.");
276 error = assertDocumentSearchCriteriaValidation(searchAttribute, ed, TestXMLSearchableAttributeDateTime.SEARCH_STORAGE_KEY, "<= 01/02/20*", "does not conform to standard validation for field type.");
277 }
278
279
280
281
282 protected RemotableAttributeError assertDocumentSearchCriteriaValidation(StandardGenericXMLSearchableAttribute attribute, ExtensionDefinition ed, String attrkey, String attrvalue, String expectedErrorMessage) {
283 DocumentSearchCriteria.Builder dscb = DocumentSearchCriteria.Builder.create();
284 dscb.addDocumentAttributeValue(attrkey, attrvalue);
285
286 List<RemotableAttributeError> errors = attribute.validateDocumentAttributeCriteria(ed, dscb.build());
287
288 if (expectedErrorMessage != null) {
289 assertEquals("Validation should return a single error message.", 1, errors.size());
290 if (StringUtils.isNotEmpty(expectedErrorMessage)) {
291 assertTrue("Validation error is incorrect", errors.get(0).getMessage().contains(expectedErrorMessage));
292 }
293 return errors.get(0);
294 } else {
295 assertEquals("Validation should not have returned an error.", 0, errors.size());
296 return null;
297 }
298 }
299
300
301
302
303 protected WorkflowDocument setUpSearchableDoc() {
304 String documentTypeName = "SearchDocTypeRangeSearchDataType";
305 DocumentType docType = ((DocumentTypeService)KEWServiceLocator.getService(KEWServiceLocator.DOCUMENT_TYPE_SERVICE)).findByName(documentTypeName);
306 String userNetworkId = "rkirkend";
307 WorkflowDocument workflowDocument = WorkflowDocumentFactory.createDocument(getPrincipalIdForName(userNetworkId), documentTypeName);
308
309
310
311
312
313
314 WorkflowAttributeDefinition.Builder stringXMLDef = WorkflowAttributeDefinition.Builder.create("XMLSearchableAttributeStringRange");
315 stringXMLDef.addPropertyDefinition(TestXMLSearchableAttributeString.SEARCH_STORAGE_KEY, TestXMLSearchableAttributeString.SEARCH_STORAGE_VALUE);
316 workflowDocument.addSearchableDefinition(stringXMLDef.build());
317
318 WorkflowAttributeDefinition.Builder longXMLDef = WorkflowAttributeDefinition.Builder.create("XMLSearchableAttributeStdLongRangeInclusive");
319 longXMLDef.addPropertyDefinition(TestXMLSearchableAttributeLong.SEARCH_STORAGE_KEY, TestXMLSearchableAttributeLong.SEARCH_STORAGE_VALUE.toString());
320 workflowDocument.addSearchableDefinition(longXMLDef.build());
321
322 WorkflowAttributeDefinition.Builder floatXMLDef = WorkflowAttributeDefinition.Builder.create("XMLSearchableAttributeStdFloatRangeInclusive");
323 floatXMLDef.addPropertyDefinition(TestXMLSearchableAttributeFloat.SEARCH_STORAGE_KEY, TestXMLSearchableAttributeFloat.SEARCH_STORAGE_VALUE.toString());
324 workflowDocument.addSearchableDefinition(floatXMLDef.build());
325
326 WorkflowAttributeDefinition.Builder dateXMLDef = WorkflowAttributeDefinition.Builder.create("XMLSearchableAttributeStdDateTimeRangeInclusive");
327 dateXMLDef.addPropertyDefinition(TestXMLSearchableAttributeDateTime.SEARCH_STORAGE_KEY, DocumentSearchInternalUtils
328 .getDisplayValueWithDateOnly(TestXMLSearchableAttributeDateTime.SEARCH_STORAGE_VALUE));
329 workflowDocument.addSearchableDefinition(dateXMLDef.build());
330
331 workflowDocument.setTitle("Routing style");
332 workflowDocument.route("routing this document.");
333
334 return WorkflowDocumentFactory.loadDocument(getPrincipalIdForName(userNetworkId), workflowDocument.getDocumentId());
335 }
336
337
338
339
340 private static final int EXPECT_EXCEPTION = -1;
341
342
343
344
345 protected void assertRangeSearchResults(String docType, String userId, String attrKey, String lowerBound, String upperBound, boolean upperBoundInclusive, int expected) throws WorkflowServiceErrorException {
346 DocumentSearchCriteria.Builder criteria = DocumentSearchCriteria.Builder.create();
347 criteria.setDocumentTypeName(docType);
348
349 addSearchableAttribute(criteria, attrKey, createSearchableAttributeRange(lowerBound, upperBound, upperBoundInclusive));
350
351 DocumentSearchResults results;
352 try {
353 results = docSearchService.lookupDocuments(userId, criteria.build());
354 if (expected == EXPECT_EXCEPTION) fail("Error should have been thrown for invalid range");
355 } catch (WorkflowServiceErrorException e) {
356 if (expected == EXPECT_EXCEPTION) return;
357 else throw e;
358 }
359
360 assertEquals("Search results should have " + expected + " document(s).", expected,
361 results.getSearchResults().size());
362 }
363
364 @Test public void testStringRanges() throws Exception {
365 WorkflowDocument doc = setUpSearchableDoc();
366 String userId = doc.getInitiatorPrincipalId();
367 String docType = doc.getDocumentTypeName();
368
369 assertRangeSearchResults(docType, userId, TestXMLSearchableAttributeString.SEARCH_STORAGE_KEY, TestXMLSearchableAttributeString.SEARCH_STORAGE_VALUE, null, false, 1);
370 }
371
372 @Test public void testLongRanges() throws Exception {
373 WorkflowDocument doc = setUpSearchableDoc();
374 String userId = doc.getInitiatorPrincipalId();
375 String docType = doc.getDocumentTypeName();
376
377 String searchAttributeLongKey = TestXMLSearchableAttributeLong.SEARCH_STORAGE_KEY;
378 Long searchAttributeLongValue = TestXMLSearchableAttributeLong.SEARCH_STORAGE_VALUE.longValue();
379 Long longValueToUse = null;
380
381
382 longValueToUse = searchAttributeLongValue;
383 assertRangeSearchResults(docType, userId, searchAttributeLongKey, longValueToUse.toString(), null, false, 1);
384
385 longValueToUse = Long.valueOf(searchAttributeLongValue.longValue() - 1);
386 assertRangeSearchResults(docType, userId, searchAttributeLongKey, longValueToUse.toString(), null, false, 1);
387
388 longValueToUse = Long.valueOf(searchAttributeLongValue.longValue() + 1);
389 assertRangeSearchResults(docType, userId, searchAttributeLongKey, longValueToUse.toString(), null, false, 0);
390
391
392 longValueToUse = searchAttributeLongValue;
393 assertRangeSearchResults(docType, userId, searchAttributeLongKey, null, longValueToUse.toString(), true, 1);
394
395 longValueToUse = Long.valueOf(searchAttributeLongValue.longValue() - 1);
396 assertRangeSearchResults(docType, userId, searchAttributeLongKey, null, longValueToUse.toString(), true, 0);
397
398 longValueToUse = Long.valueOf(searchAttributeLongValue.longValue() + 1);
399 assertRangeSearchResults(docType, userId, searchAttributeLongKey, null, longValueToUse.toString(), true, 1);
400
401
402
403 assertRangeSearchResults(docType, userId, searchAttributeLongKey,
404 Long.valueOf(searchAttributeLongValue.longValue()).toString(),
405 Long.valueOf(searchAttributeLongValue.longValue()).toString(), true, 1);
406
407
408 assertRangeSearchResults(docType, userId, searchAttributeLongKey,
409 Long.valueOf(searchAttributeLongValue.longValue() + 2).toString(),
410 Long.valueOf(searchAttributeLongValue.longValue() + 4).toString(), true, 0);
411
412
413 assertRangeSearchResults(docType, userId, searchAttributeLongKey,
414 Long.valueOf(searchAttributeLongValue.longValue() - 2).toString(),
415 Long.valueOf(searchAttributeLongValue.longValue() - 4).toString(), true, EXPECT_EXCEPTION);
416
417 assertRangeSearchResults(docType, userId, searchAttributeLongKey,
418 Long.valueOf(searchAttributeLongValue.longValue() - 4).toString(),
419 Long.valueOf(searchAttributeLongValue.longValue() - 2).toString(), true, 0);
420
421
422 assertRangeSearchResults(docType, userId, searchAttributeLongKey,
423 Long.valueOf(searchAttributeLongValue.longValue() - 2).toString(),
424 Long.valueOf(searchAttributeLongValue.longValue() + 2).toString(), true, 1);
425
426
427 assertRangeSearchResults(docType, userId, searchAttributeLongKey,
428 Long.valueOf(searchAttributeLongValue.longValue() + 2).toString(),
429 Long.valueOf(searchAttributeLongValue.longValue() - 2).toString(), true, EXPECT_EXCEPTION);
430 }
431
432 @Test public void testFloatRanges() throws Exception {
433 WorkflowDocument doc = setUpSearchableDoc();
434 String userId = doc.getInitiatorPrincipalId();
435 String docType = doc.getDocumentTypeName();
436
437 String searchAttributeFloatKey = TestXMLSearchableAttributeFloat.SEARCH_STORAGE_KEY;
438 BigDecimal searchAttributeFloatValue = TestXMLSearchableAttributeFloat.SEARCH_STORAGE_VALUE;
439
440 BigDecimal floatValueToUse = null;
441
442 floatValueToUse = searchAttributeFloatValue;
443
444 assertRangeSearchResults(docType, userId, searchAttributeFloatKey, floatValueToUse.toString(), null, false, 1);
445
446 floatValueToUse = searchAttributeFloatValue.subtract(BigDecimal.ONE);
447 assertRangeSearchResults(docType, userId, searchAttributeFloatKey, floatValueToUse.toString(), null, false, 1);
448
449 floatValueToUse = searchAttributeFloatValue.add(BigDecimal.ONE);
450 assertRangeSearchResults(docType, userId, searchAttributeFloatKey, floatValueToUse.toString(), null, false, 0);
451
452
453 floatValueToUse = searchAttributeFloatValue;
454
455 assertRangeSearchResults(docType, userId, searchAttributeFloatKey, null, floatValueToUse.toString(), true, 1);
456
457 floatValueToUse = searchAttributeFloatValue.subtract(BigDecimal.ONE);
458 assertRangeSearchResults(docType, userId, searchAttributeFloatKey, null, floatValueToUse.toString(), true, 0);
459
460 floatValueToUse = searchAttributeFloatValue.add(BigDecimal.ONE);
461 assertRangeSearchResults(docType, userId, searchAttributeFloatKey, null, floatValueToUse.toString(), true, 1);
462
463
464
465
466
467 assertRangeSearchResults(docType, userId, searchAttributeFloatKey, searchAttributeFloatValue.toString(), searchAttributeFloatValue.toString(), true, 1);
468
469
470 assertRangeSearchResults(docType, userId, searchAttributeFloatKey,
471 searchAttributeFloatValue.add(new BigDecimal(2)).toString(),
472 searchAttributeFloatValue.add(new BigDecimal(4)).toString(), true, 0);
473
474
475 assertRangeSearchResults(docType, userId, searchAttributeFloatKey,
476 searchAttributeFloatValue.subtract(new BigDecimal(4)).toString(),
477 searchAttributeFloatValue.subtract(new BigDecimal(2)).toString(), true, 0);
478
479
480 assertRangeSearchResults(docType, userId, searchAttributeFloatKey,
481 searchAttributeFloatValue.subtract(new BigDecimal(2)).toString(),
482 searchAttributeFloatValue.add(new BigDecimal(2)).toString(), true, 1);
483
484
485 assertRangeSearchResults(docType, userId, searchAttributeFloatKey,
486 searchAttributeFloatValue.add(new BigDecimal(2)).toString(),
487 searchAttributeFloatValue.subtract(new BigDecimal(2)).toString(), true, EXPECT_EXCEPTION);
488 }
489
490 @Test public void testDateRanges() throws Exception {
491 WorkflowDocument doc = setUpSearchableDoc();
492 String userId = doc.getInitiatorPrincipalId();
493 String docType = doc.getDocumentTypeName();
494
495
496
497 String searchAttributeDateTimeKey = TestXMLSearchableAttributeDateTime.SEARCH_STORAGE_KEY;
498 Calendar searchAttributeDateTimeValue = TestXMLSearchableAttributeDateTime.SEARCH_STORAGE_VALUE.toGregorianCalendar();
499
500 Calendar calendarValueToUse = null;
501
502 calendarValueToUse = (Calendar) searchAttributeDateTimeValue.clone();
503 String valueToSearch = DocumentSearchInternalUtils.getDisplayValueWithDateOnly(SQLUtils.convertCalendar(calendarValueToUse));
504
505 assertRangeSearchResults(docType, userId, searchAttributeDateTimeKey, valueToSearch, null, false, 1);
506
507 calendarValueToUse = (Calendar) searchAttributeDateTimeValue.clone();
508 calendarValueToUse.add(Calendar.DATE, -1);
509 valueToSearch = DocumentSearchInternalUtils.getDisplayValueWithDateOnly(SQLUtils.convertCalendar(calendarValueToUse));
510 assertRangeSearchResults(docType, userId, searchAttributeDateTimeKey, valueToSearch, null, false, 1);
511
512 calendarValueToUse = (Calendar) searchAttributeDateTimeValue.clone();
513 calendarValueToUse.add(Calendar.DATE, 1);
514 valueToSearch = DocumentSearchInternalUtils.getDisplayValueWithDateOnly(SQLUtils.convertCalendar(calendarValueToUse));
515 assertRangeSearchResults(docType, userId, searchAttributeDateTimeKey, valueToSearch, null, false, 0);
516
517
518 calendarValueToUse = (Calendar) searchAttributeDateTimeValue.clone();
519 assertRangeSearchResults(docType, userId, searchAttributeDateTimeKey,
520 null,
521 DocumentSearchInternalUtils.getDisplayValueWithDateOnly(SQLUtils.convertCalendar(calendarValueToUse)), true, 1);
522
523 calendarValueToUse = (Calendar) searchAttributeDateTimeValue.clone();
524 calendarValueToUse.add(Calendar.DATE, -1);
525 assertRangeSearchResults(docType, userId, searchAttributeDateTimeKey,
526 null,
527 DocumentSearchInternalUtils.getDisplayValueWithDateOnly(SQLUtils.convertCalendar(calendarValueToUse)), true, 0);
528
529 calendarValueToUse = (Calendar) searchAttributeDateTimeValue.clone();
530 calendarValueToUse.add(Calendar.DATE, 1);
531 assertRangeSearchResults(docType, userId, searchAttributeDateTimeKey,
532 null,
533 DocumentSearchInternalUtils.getDisplayValueWithDateOnly(SQLUtils.convertCalendar(calendarValueToUse)), true, 1);
534
535
536 Calendar lowerBoundValue = (Calendar) searchAttributeDateTimeValue.clone();
537 Calendar upperBoundValue = (Calendar) searchAttributeDateTimeValue.clone();
538
539 assertRangeSearchResults(docType, userId, searchAttributeDateTimeKey,
540 DocumentSearchInternalUtils.getDisplayValueWithDateOnly(SQLUtils.convertCalendar(lowerBoundValue)),
541 DocumentSearchInternalUtils.getDisplayValueWithDateOnly(SQLUtils.convertCalendar(upperBoundValue)), true, 1);
542
543 lowerBoundValue = (Calendar) searchAttributeDateTimeValue.clone();
544 lowerBoundValue.add(Calendar.DATE, 2);
545 upperBoundValue = (Calendar) searchAttributeDateTimeValue.clone();
546 upperBoundValue.add(Calendar.DATE, 4);
547 assertRangeSearchResults(docType, userId, searchAttributeDateTimeKey,
548 DocumentSearchInternalUtils.getDisplayValueWithDateOnly(SQLUtils.convertCalendar(lowerBoundValue)),
549 DocumentSearchInternalUtils.getDisplayValueWithDateOnly(SQLUtils.convertCalendar(upperBoundValue)), true, 0);
550
551 lowerBoundValue = (Calendar) searchAttributeDateTimeValue.clone();
552 lowerBoundValue.add(Calendar.DATE, -4);
553 upperBoundValue = (Calendar) searchAttributeDateTimeValue.clone();
554 upperBoundValue.add(Calendar.DATE, -2);
555 assertRangeSearchResults(docType, userId, searchAttributeDateTimeKey,
556 DocumentSearchInternalUtils.getDisplayValueWithDateOnly(SQLUtils.convertCalendar(lowerBoundValue)),
557 DocumentSearchInternalUtils.getDisplayValueWithDateOnly(SQLUtils.convertCalendar(upperBoundValue)), true, 0);
558
559 lowerBoundValue = (Calendar) searchAttributeDateTimeValue.clone();
560 lowerBoundValue.add(Calendar.DATE, -2);
561 upperBoundValue = (Calendar) searchAttributeDateTimeValue.clone();
562 upperBoundValue.add(Calendar.DATE, 2);
563 assertRangeSearchResults(docType, userId, searchAttributeDateTimeKey,
564 DocumentSearchInternalUtils.getDisplayValueWithDateOnly(SQLUtils.convertCalendar(lowerBoundValue)),
565 DocumentSearchInternalUtils.getDisplayValueWithDateOnly(SQLUtils.convertCalendar(upperBoundValue)), true, 1);
566
567 lowerBoundValue = (Calendar) searchAttributeDateTimeValue.clone();
568 lowerBoundValue.add(Calendar.DATE, 2);
569 upperBoundValue = (Calendar) searchAttributeDateTimeValue.clone();
570 upperBoundValue.add(Calendar.DATE, -2);
571 assertRangeSearchResults(docType, userId, searchAttributeDateTimeKey,
572 DocumentSearchInternalUtils.getDisplayValueWithDateOnly(SQLUtils.convertCalendar(lowerBoundValue)),
573 DocumentSearchInternalUtils.getDisplayValueWithDateOnly(SQLUtils.convertCalendar(upperBoundValue)), true, EXPECT_EXCEPTION);
574 }
575
576
577
578
579 @Test public void testRangeDefinitionStringAttributes() throws Exception {
580 String documentTypeName = "RangeDefinitionTestDocType";
581 DocumentType docType = KEWServiceLocator.getDocumentTypeService().findByName(documentTypeName);
582 String principalName = "rkirkend";
583 String principalId = KimApiServiceLocator.getPersonService().getPersonByPrincipalName(principalName).getPrincipalId();
584 WorkflowDocument workflowDocument = WorkflowDocumentFactory.createDocument(principalId, documentTypeName);
585
586
587 WorkflowAttributeDefinition.Builder inclusiveLowerXMLDef = WorkflowAttributeDefinition.Builder.create("TextFieldWithInclusiveLower");
588 inclusiveLowerXMLDef.addPropertyDefinition("textFieldWithInclusiveLower", "newvalue");
589 workflowDocument.addSearchableDefinition(inclusiveLowerXMLDef.build());
590
591 WorkflowAttributeDefinition.Builder caseSensitiveXMLDef = WorkflowAttributeDefinition.Builder.create("TextFieldWithCaseSensitivity");
592 caseSensitiveXMLDef.addPropertyDefinition("textFieldWithCaseSensitivity", "thevalue");
593 workflowDocument.addSearchableDefinition(caseSensitiveXMLDef.build());
594
595 WorkflowAttributeDefinition.Builder overridesXMLDef = WorkflowAttributeDefinition.Builder.create("TextFieldWithOverrides");
596 overridesXMLDef.addPropertyDefinition("textFieldWithOverrides", "SomeVal");
597 workflowDocument.addSearchableDefinition(overridesXMLDef.build());
598
599 workflowDocument.setTitle("Range Def Test");
600 workflowDocument.route("routing range def doc.");
601
602 workflowDocument = WorkflowDocumentFactory.loadDocument(principalId, workflowDocument.getDocumentId());
603
604
605
606 assertSearchBehavesAsExpected(docType, principalId, "textFieldWithInclusiveLower",
607 new String[] { "newvalue", "" , "" , "NEWVALUD", "newValuf", "newValuj", "newvaluf"},
608 new String[] { "" , "newvalue", "Newvaluf", "NEWVALUF", "newValud", "NEWVALUK", "" },
609 new int[] { 1 , 1 , 1 , 1 , -1 , 0 , 0 });
610
611
612 assertSearchBehavesAsExpected(docType, principalId, "textFieldWithCaseSensitivity",
613 new String[] { "thevalue", "" , "" , "THEVALUD", "thevalud", "Thevalud", "THEVALUF"},
614 new String[] { "" , "thevalue", "Thevalue", "THEVALUF", "THEVALUF", "Thevaluf", "" },
615 new int[] { 1 , 1 , 0 , 0 , -1 , 0 , 1 });
616
617
618 assertSearchBehavesAsExpected(docType, principalId, "textFieldWithOverrides",
619 new String[] { "> someval", "> SomeVal", "<= SOMEVAL", "<= SomeVal", "SOMEVAK>..SomeVam", "SomeVam>..SOMEVAK", "SOMEVAM>..SomeVak", "> somevak", "<= SomeVak" },
620
621 new int[] { 0 , 0 , 1 , 1 , 1 , -1 , -1 , 1 , 0 });
622 }
623
624
625
626
627
628
629
630
631
632
633
634
635 private void assertSearchBehavesAsExpected(DocumentType docType, String principalId, String fieldDefKey, final String[] lowBounds, final String[] upBounds, int[] resultSizes) throws Exception {
636 assertSearchResults(KEWServiceLocator.getDocumentSearchService(), docType, principalId, fieldDefKey, resultSizes, new Function<Integer, String>() {
637 @Override public String apply(@Nullable Integer index) {
638 return createSearchableAttributeRange(lowBounds[index], upBounds[index], true);
639 }
640 });
641 }
642
643
644
645
646
647
648
649
650
651
652
653 private void assertSearchBehavesAsExpected(DocumentType docType, String principalId, String fieldDefKey, final String[] expr, int[] resultSizes) throws Exception {
654 assertSearchResults(KEWServiceLocator.getDocumentSearchService(), docType, principalId, fieldDefKey, resultSizes, new Function<Integer, String>() {
655 @Override public String apply(@Nullable Integer index) {
656 return expr[index];
657 }
658 });
659 }
660
661 private void assertSearchResults(DocumentSearchService docSearchService, DocumentType docType, String principalId, String fieldDefKey, int[] resultSizes, Function<Integer, String> closure) {
662 DocumentSearchCriteria.Builder criteria = null;
663 DocumentSearchResults results = null;
664 for (int i = 0; i < resultSizes.length; i++) {
665 criteria = DocumentSearchCriteria.Builder.create();
666 criteria.setDocumentTypeName(docType.getName());
667
668 addSearchableAttribute(criteria, fieldDefKey, closure.apply(i));
669
670 try {
671 results = docSearchService.lookupDocuments(principalId, criteria.build());
672 if (resultSizes[i] < 0) {
673 fail(fieldDefKey + "'s search at loop index " + i + " should have thrown an exception");
674 }
675 assertEquals(fieldDefKey
676 + "'s search results at loop index "
677 + i
678 + " returned the wrong number of documents.", resultSizes[i], results.getSearchResults().size());
679 } catch (Exception ex) {
680 if (resultSizes[i] >= 0) {
681 fail(fieldDefKey + "'s search at loop index " + i + " should not have thrown an exception");
682 }
683 }
684 }
685 }
686 }