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