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