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", 1, 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 assertTrue("Field should not be inclusive", field.isInclusive());
198 assertEquals("Field in row should be of data type date", DataType.DATE.toString().toLowerCase(), field.getFieldDataType());
199
200 }
201 } else {
202 assertEquals("Invalid number of search rows", 1, rows.size());
203 Row row = rows.get(0);
204
205 assertEquals("Invalid number of fields", 1, row.getFields().size());
206 assertFalse("Field is the member of a range when ranges are not allowed",((Field)(row.getField(0))).isMemberOfRange());
207 }
208 }
209
210
211
212
213
214 @Test public void testValidateUserSearchRangeInputs() {
215
216 StandardGenericXMLSearchableAttribute searchAttribute = getAttribute("XMLSearchableAttributeStringRange");
217 ExtensionDefinition ed = createExtensionDefinition("XMLSearchableAttributeStringRange");
218
219 RemotableAttributeError error = assertDocumentSearchCriteriaValidation(searchAttribute, ed, TestXMLSearchableAttributeString.SEARCH_STORAGE_KEY, ">= jack", null);
220 assertDocumentSearchCriteriaValidation(searchAttribute, ed, TestXMLSearchableAttributeString.SEARCH_STORAGE_KEY, "<= jack.jack", "differ on upper bound inclusivity");
221 assertDocumentSearchCriteriaValidation(searchAttribute, ed, TestXMLSearchableAttributeString.SEARCH_STORAGE_KEY, "< jack.jack", "Invalid first name");
222 assertDocumentSearchCriteriaValidation(searchAttribute, ed, TestXMLSearchableAttributeString.SEARCH_STORAGE_KEY, ">= jack*jack", null);
223
224
225
226 searchAttribute = getAttribute("XMLSearchableAttributeStdLongRange");
227 ed = createExtensionDefinition("XMLSearchableAttributeStdLongRange");
228
229 assertDocumentSearchCriteriaValidation(searchAttribute, ed, TestXMLSearchableAttributeLong.SEARCH_STORAGE_KEY, "<= " + TestXMLSearchableAttributeLong.SEARCH_STORAGE_VALUE.toString(), "differ on upper bound inclusivity");
230 assertDocumentSearchCriteriaValidation(searchAttribute, ed, TestXMLSearchableAttributeLong.SEARCH_STORAGE_KEY, "< " + TestXMLSearchableAttributeLong.SEARCH_STORAGE_VALUE.toString(), null);
231 assertDocumentSearchCriteriaValidation(searchAttribute, ed, TestXMLSearchableAttributeLong.SEARCH_STORAGE_KEY, ">= " + TestXMLSearchableAttributeLong.SEARCH_STORAGE_VALUE.toString() + ".33","does not conform to standard validation for field type.");
232 assertDocumentSearchCriteriaValidation(searchAttribute, ed, TestXMLSearchableAttributeLong.SEARCH_STORAGE_KEY, "<= jack*jack", "differ on upper bound inclusivity");
233 assertDocumentSearchCriteriaValidation(searchAttribute, ed, TestXMLSearchableAttributeLong.SEARCH_STORAGE_KEY, "< jack*jack", "does not conform to standard validation for field type.");
234
235
236
237
238
239
240
241 searchAttribute = getAttribute("XMLSearchableAttributeStdFloatRange");
242 ed = createExtensionDefinition("XMLSearchableAttributeStdFloatRange");
243 assertDocumentSearchCriteriaValidation(searchAttribute, ed, TestXMLSearchableAttributeFloat.SEARCH_STORAGE_KEY, ">= " + TestXMLSearchableAttributeFloat.SEARCH_STORAGE_VALUE.toString(), "differ on lower bound inclusivity");
244 assertDocumentSearchCriteriaValidation(searchAttribute, ed, TestXMLSearchableAttributeFloat.SEARCH_STORAGE_KEY, "> " + TestXMLSearchableAttributeFloat.SEARCH_STORAGE_VALUE.toString(), null);
245 assertDocumentSearchCriteriaValidation(searchAttribute, ed, TestXMLSearchableAttributeFloat.SEARCH_STORAGE_KEY, "<= " + TestXMLSearchableAttributeFloat.SEARCH_STORAGE_VALUE.toString() + "a", "differ on upper bound inclusivity");
246 assertDocumentSearchCriteriaValidation(searchAttribute, ed, TestXMLSearchableAttributeFloat.SEARCH_STORAGE_KEY, "< " + TestXMLSearchableAttributeFloat.SEARCH_STORAGE_VALUE.toString() + "a", "does not conform to standard validation for field type.");
247 assertDocumentSearchCriteriaValidation(searchAttribute, ed, TestXMLSearchableAttributeFloat.SEARCH_STORAGE_KEY, ">= " + TestXMLSearchableAttributeFloat.SEARCH_STORAGE_VALUE.toString() + "*", "differ on lower bound inclusivity");
248 assertDocumentSearchCriteriaValidation(searchAttribute, ed, TestXMLSearchableAttributeFloat.SEARCH_STORAGE_KEY, "> " + TestXMLSearchableAttributeFloat.SEARCH_STORAGE_VALUE.toString() + "*", "does not conform to standard validation for field type.");
249
250
251
252
253
254
255
256 searchAttribute = getAttribute("XMLSearchableAttributeStdDateTimeRange");
257 ed = createExtensionDefinition("XMLSearchableAttributeStdDateTimeRange");
258 assertDocumentSearchCriteriaValidation(searchAttribute, ed, TestXMLSearchableAttributeDateTime.SEARCH_STORAGE_KEY, "<= " + DocumentSearchInternalUtils.getDisplayValueWithDateOnly(TestXMLSearchableAttributeDateTime.SEARCH_STORAGE_VALUE), null);
259 assertDocumentSearchCriteriaValidation(searchAttribute, ed, TestXMLSearchableAttributeDateTime.SEARCH_STORAGE_KEY, ">= 001/5/08", "differ on lower bound inclusivity");
260 assertDocumentSearchCriteriaValidation(searchAttribute, ed, TestXMLSearchableAttributeDateTime.SEARCH_STORAGE_KEY, "> 001/5/08", null);
261 error = assertDocumentSearchCriteriaValidation(searchAttribute, ed, TestXMLSearchableAttributeDateTime.SEARCH_STORAGE_KEY, ">= 41/5/08", "differ on lower bound inclusivity");
262 error = assertDocumentSearchCriteriaValidation(searchAttribute, ed, TestXMLSearchableAttributeDateTime.SEARCH_STORAGE_KEY, "> 41/5/08", "does not conform to standard validation for field type.");
263 error = assertDocumentSearchCriteriaValidation(searchAttribute, ed, TestXMLSearchableAttributeDateTime.SEARCH_STORAGE_KEY, "<= 01/02/20*", "does not conform to standard validation for field type.");
264 }
265
266
267
268
269 protected RemotableAttributeError assertDocumentSearchCriteriaValidation(StandardGenericXMLSearchableAttribute attribute, ExtensionDefinition ed, String attrkey, String attrvalue, String expectedErrorMessage) {
270 DocumentSearchCriteria.Builder dscb = DocumentSearchCriteria.Builder.create();
271 dscb.addDocumentAttributeValue(attrkey, attrvalue);
272
273 List<RemotableAttributeError> errors = attribute.validateDocumentAttributeCriteria(ed, dscb.build());
274
275 if (expectedErrorMessage != null) {
276 assertEquals("Validation should return a single error message.", 1, errors.size());
277 if (StringUtils.isNotEmpty(expectedErrorMessage)) {
278 assertTrue("Validation error is incorrect", errors.get(0).getMessage().contains(expectedErrorMessage));
279 }
280 return errors.get(0);
281 } else {
282 assertEquals("Validation should not have returned an error.", 0, errors.size());
283 return null;
284 }
285 }
286
287
288
289
290 protected WorkflowDocument setUpSearchableDoc() {
291 String documentTypeName = "SearchDocTypeRangeSearchDataType";
292 DocumentType docType = ((DocumentTypeService)KEWServiceLocator.getService(KEWServiceLocator.DOCUMENT_TYPE_SERVICE)).findByName(documentTypeName);
293 String userNetworkId = "rkirkend";
294 WorkflowDocument workflowDocument = WorkflowDocumentFactory.createDocument(getPrincipalIdForName(userNetworkId), documentTypeName);
295
296
297
298
299
300
301 WorkflowAttributeDefinition.Builder stringXMLDef = WorkflowAttributeDefinition.Builder.create("XMLSearchableAttributeStringRange");
302 stringXMLDef.addPropertyDefinition(TestXMLSearchableAttributeString.SEARCH_STORAGE_KEY, TestXMLSearchableAttributeString.SEARCH_STORAGE_VALUE);
303 workflowDocument.addSearchableDefinition(stringXMLDef.build());
304
305 WorkflowAttributeDefinition.Builder longXMLDef = WorkflowAttributeDefinition.Builder.create("XMLSearchableAttributeStdLongRangeInclusive");
306 longXMLDef.addPropertyDefinition(TestXMLSearchableAttributeLong.SEARCH_STORAGE_KEY, TestXMLSearchableAttributeLong.SEARCH_STORAGE_VALUE.toString());
307 workflowDocument.addSearchableDefinition(longXMLDef.build());
308
309 WorkflowAttributeDefinition.Builder floatXMLDef = WorkflowAttributeDefinition.Builder.create("XMLSearchableAttributeStdFloatRangeInclusive");
310 floatXMLDef.addPropertyDefinition(TestXMLSearchableAttributeFloat.SEARCH_STORAGE_KEY, TestXMLSearchableAttributeFloat.SEARCH_STORAGE_VALUE.toString());
311 workflowDocument.addSearchableDefinition(floatXMLDef.build());
312
313 WorkflowAttributeDefinition.Builder dateXMLDef = WorkflowAttributeDefinition.Builder.create("XMLSearchableAttributeStdDateTimeRangeInclusive");
314 dateXMLDef.addPropertyDefinition(TestXMLSearchableAttributeDateTime.SEARCH_STORAGE_KEY, DocumentSearchInternalUtils
315 .getDisplayValueWithDateOnly(TestXMLSearchableAttributeDateTime.SEARCH_STORAGE_VALUE));
316 workflowDocument.addSearchableDefinition(dateXMLDef.build());
317
318 workflowDocument.setTitle("Routing style");
319 workflowDocument.route("routing this document.");
320
321 return WorkflowDocumentFactory.loadDocument(getPrincipalIdForName(userNetworkId), workflowDocument.getDocumentId());
322 }
323
324
325
326
327 private static final int EXPECT_EXCEPTION = -1;
328
329
330
331
332 protected void assertRangeSearchResults(String docType, String userId, String attrKey, String lowerBound, String upperBound, boolean upperBoundInclusive, int expected) throws WorkflowServiceErrorException {
333 DocumentSearchCriteria.Builder criteria = DocumentSearchCriteria.Builder.create();
334 criteria.setDocumentTypeName(docType);
335
336 addSearchableAttribute(criteria, attrKey, createSearchableAttributeRange(lowerBound, upperBound, upperBoundInclusive));
337
338 DocumentSearchResults results;
339 try {
340 results = docSearchService.lookupDocuments(userId, criteria.build());
341 if (expected == EXPECT_EXCEPTION) fail("Error should have been thrown for invalid range");
342 } catch (WorkflowServiceErrorException e) {
343 if (expected == EXPECT_EXCEPTION) {
344 return;
345 } else {
346 throw e;
347 }
348 }
349
350 assertEquals("Search results should have " + expected + " document(s).", expected,
351 results.getSearchResults().size());
352 }
353
354 @Test public void testStringRanges() throws Exception {
355 WorkflowDocument doc = setUpSearchableDoc();
356 String userId = doc.getInitiatorPrincipalId();
357 String docType = doc.getDocumentTypeName();
358
359 assertRangeSearchResults(docType, userId, TestXMLSearchableAttributeString.SEARCH_STORAGE_KEY, TestXMLSearchableAttributeString.SEARCH_STORAGE_VALUE, null, false, 1);
360 }
361
362 @Test public void testLongRanges() throws Exception {
363 WorkflowDocument doc = setUpSearchableDoc();
364 String userId = doc.getInitiatorPrincipalId();
365 String docType = doc.getDocumentTypeName();
366
367 String searchAttributeLongKey = TestXMLSearchableAttributeLong.SEARCH_STORAGE_KEY;
368 Long searchAttributeLongValue = TestXMLSearchableAttributeLong.SEARCH_STORAGE_VALUE.longValue();
369 Long longValueToUse = null;
370
371
372 longValueToUse = searchAttributeLongValue;
373 assertRangeSearchResults(docType, userId, searchAttributeLongKey, longValueToUse.toString(), null, false, 1);
374
375 longValueToUse = Long.valueOf(searchAttributeLongValue.longValue() - 1);
376 assertRangeSearchResults(docType, userId, searchAttributeLongKey, longValueToUse.toString(), null, false, 1);
377
378 longValueToUse = Long.valueOf(searchAttributeLongValue.longValue() + 1);
379 assertRangeSearchResults(docType, userId, searchAttributeLongKey, longValueToUse.toString(), null, false, 0);
380
381
382 longValueToUse = searchAttributeLongValue;
383 assertRangeSearchResults(docType, userId, searchAttributeLongKey, null, longValueToUse.toString(), true, 1);
384
385 longValueToUse = Long.valueOf(searchAttributeLongValue.longValue() - 1);
386 assertRangeSearchResults(docType, userId, searchAttributeLongKey, null, longValueToUse.toString(), true, 0);
387
388 longValueToUse = Long.valueOf(searchAttributeLongValue.longValue() + 1);
389 assertRangeSearchResults(docType, userId, searchAttributeLongKey, null, longValueToUse.toString(), true, 1);
390
391
392
393 assertRangeSearchResults(docType, userId, searchAttributeLongKey,
394 Long.valueOf(searchAttributeLongValue.longValue()).toString(),
395 Long.valueOf(searchAttributeLongValue.longValue()).toString(), true, 1);
396
397
398 assertRangeSearchResults(docType, userId, searchAttributeLongKey,
399 Long.valueOf(searchAttributeLongValue.longValue() + 2).toString(),
400 Long.valueOf(searchAttributeLongValue.longValue() + 4).toString(), true, 0);
401
402
403 assertRangeSearchResults(docType, userId, searchAttributeLongKey,
404 Long.valueOf(searchAttributeLongValue.longValue() - 2).toString(),
405 Long.valueOf(searchAttributeLongValue.longValue() - 4).toString(), true, EXPECT_EXCEPTION);
406
407 assertRangeSearchResults(docType, userId, searchAttributeLongKey,
408 Long.valueOf(searchAttributeLongValue.longValue() - 4).toString(),
409 Long.valueOf(searchAttributeLongValue.longValue() - 2).toString(), true, 0);
410
411
412 assertRangeSearchResults(docType, userId, searchAttributeLongKey,
413 Long.valueOf(searchAttributeLongValue.longValue() - 2).toString(),
414 Long.valueOf(searchAttributeLongValue.longValue() + 2).toString(), true, 1);
415
416
417 assertRangeSearchResults(docType, userId, searchAttributeLongKey,
418 Long.valueOf(searchAttributeLongValue.longValue() + 2).toString(),
419 Long.valueOf(searchAttributeLongValue.longValue() - 2).toString(), true, EXPECT_EXCEPTION);
420 }
421
422 @Test public void testFloatRanges() throws Exception {
423 WorkflowDocument doc = setUpSearchableDoc();
424 String userId = doc.getInitiatorPrincipalId();
425 String docType = doc.getDocumentTypeName();
426
427 String searchAttributeFloatKey = TestXMLSearchableAttributeFloat.SEARCH_STORAGE_KEY;
428 BigDecimal searchAttributeFloatValue = TestXMLSearchableAttributeFloat.SEARCH_STORAGE_VALUE;
429
430 BigDecimal floatValueToUse = null;
431
432 floatValueToUse = searchAttributeFloatValue;
433
434 assertRangeSearchResults(docType, userId, searchAttributeFloatKey, floatValueToUse.toString(), null, false, 1);
435
436 floatValueToUse = searchAttributeFloatValue.subtract(BigDecimal.ONE);
437 assertRangeSearchResults(docType, userId, searchAttributeFloatKey, floatValueToUse.toString(), null, false, 1);
438
439 floatValueToUse = searchAttributeFloatValue.add(BigDecimal.ONE);
440 assertRangeSearchResults(docType, userId, searchAttributeFloatKey, floatValueToUse.toString(), null, false, 0);
441
442
443 floatValueToUse = searchAttributeFloatValue;
444
445 assertRangeSearchResults(docType, userId, searchAttributeFloatKey, null, floatValueToUse.toString(), true, 1);
446
447 floatValueToUse = searchAttributeFloatValue.subtract(BigDecimal.ONE);
448 assertRangeSearchResults(docType, userId, searchAttributeFloatKey, null, floatValueToUse.toString(), true, 0);
449
450 floatValueToUse = searchAttributeFloatValue.add(BigDecimal.ONE);
451 assertRangeSearchResults(docType, userId, searchAttributeFloatKey, null, floatValueToUse.toString(), true, 1);
452
453
454
455
456
457 assertRangeSearchResults(docType, userId, searchAttributeFloatKey, searchAttributeFloatValue.toString(), searchAttributeFloatValue.toString(), true, 1);
458
459
460 assertRangeSearchResults(docType, userId, searchAttributeFloatKey,
461 searchAttributeFloatValue.add(new BigDecimal(2)).toString(),
462 searchAttributeFloatValue.add(new BigDecimal(4)).toString(), true, 0);
463
464
465 assertRangeSearchResults(docType, userId, searchAttributeFloatKey,
466 searchAttributeFloatValue.subtract(new BigDecimal(4)).toString(),
467 searchAttributeFloatValue.subtract(new BigDecimal(2)).toString(), true, 0);
468
469
470 assertRangeSearchResults(docType, userId, searchAttributeFloatKey,
471 searchAttributeFloatValue.subtract(new BigDecimal(2)).toString(),
472 searchAttributeFloatValue.add(new BigDecimal(2)).toString(), true, 1);
473
474
475 assertRangeSearchResults(docType, userId, searchAttributeFloatKey,
476 searchAttributeFloatValue.add(new BigDecimal(2)).toString(),
477 searchAttributeFloatValue.subtract(new BigDecimal(2)).toString(), true, EXPECT_EXCEPTION);
478 }
479
480 @Test public void testDateRanges() throws Exception {
481 WorkflowDocument doc = setUpSearchableDoc();
482 String userId = doc.getInitiatorPrincipalId();
483 String docType = doc.getDocumentTypeName();
484
485
486
487 String searchAttributeDateTimeKey = TestXMLSearchableAttributeDateTime.SEARCH_STORAGE_KEY;
488 Calendar searchAttributeDateTimeValue = TestXMLSearchableAttributeDateTime.SEARCH_STORAGE_VALUE.toGregorianCalendar();
489
490 Calendar calendarValueToUse = null;
491
492 calendarValueToUse = (Calendar) searchAttributeDateTimeValue.clone();
493 String valueToSearch = DocumentSearchInternalUtils.getDisplayValueWithDateOnly(SQLUtils.convertCalendar(calendarValueToUse));
494
495 assertRangeSearchResults(docType, userId, searchAttributeDateTimeKey, valueToSearch, null, false, 1);
496
497 calendarValueToUse = (Calendar) searchAttributeDateTimeValue.clone();
498 calendarValueToUse.add(Calendar.DATE, -1);
499 valueToSearch = DocumentSearchInternalUtils.getDisplayValueWithDateOnly(SQLUtils.convertCalendar(calendarValueToUse));
500 assertRangeSearchResults(docType, userId, searchAttributeDateTimeKey, valueToSearch, null, false, 1);
501
502 calendarValueToUse = (Calendar) searchAttributeDateTimeValue.clone();
503 calendarValueToUse.add(Calendar.DATE, 1);
504 valueToSearch = DocumentSearchInternalUtils.getDisplayValueWithDateOnly(SQLUtils.convertCalendar(calendarValueToUse));
505 assertRangeSearchResults(docType, userId, searchAttributeDateTimeKey, valueToSearch, null, false, 0);
506
507
508 calendarValueToUse = (Calendar) searchAttributeDateTimeValue.clone();
509 assertRangeSearchResults(docType, userId, searchAttributeDateTimeKey,
510 null,
511 DocumentSearchInternalUtils.getDisplayValueWithDateOnly(SQLUtils.convertCalendar(calendarValueToUse)), true, 1);
512
513 calendarValueToUse = (Calendar) searchAttributeDateTimeValue.clone();
514 calendarValueToUse.add(Calendar.DATE, -1);
515 assertRangeSearchResults(docType, userId, searchAttributeDateTimeKey,
516 null,
517 DocumentSearchInternalUtils.getDisplayValueWithDateOnly(SQLUtils.convertCalendar(calendarValueToUse)), true, 0);
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, 1);
524
525
526 Calendar lowerBoundValue = (Calendar) searchAttributeDateTimeValue.clone();
527 Calendar upperBoundValue = (Calendar) searchAttributeDateTimeValue.clone();
528
529 assertRangeSearchResults(docType, userId, searchAttributeDateTimeKey,
530 DocumentSearchInternalUtils.getDisplayValueWithDateOnly(SQLUtils.convertCalendar(lowerBoundValue)),
531 DocumentSearchInternalUtils.getDisplayValueWithDateOnly(SQLUtils.convertCalendar(upperBoundValue)), true, 1);
532
533 lowerBoundValue = (Calendar) searchAttributeDateTimeValue.clone();
534 lowerBoundValue.add(Calendar.DATE, 2);
535 upperBoundValue = (Calendar) searchAttributeDateTimeValue.clone();
536 upperBoundValue.add(Calendar.DATE, 4);
537 assertRangeSearchResults(docType, userId, searchAttributeDateTimeKey,
538 DocumentSearchInternalUtils.getDisplayValueWithDateOnly(SQLUtils.convertCalendar(lowerBoundValue)),
539 DocumentSearchInternalUtils.getDisplayValueWithDateOnly(SQLUtils.convertCalendar(upperBoundValue)), true, 0);
540
541 lowerBoundValue = (Calendar) searchAttributeDateTimeValue.clone();
542 lowerBoundValue.add(Calendar.DATE, -4);
543 upperBoundValue = (Calendar) searchAttributeDateTimeValue.clone();
544 upperBoundValue.add(Calendar.DATE, -2);
545 assertRangeSearchResults(docType, userId, searchAttributeDateTimeKey,
546 DocumentSearchInternalUtils.getDisplayValueWithDateOnly(SQLUtils.convertCalendar(lowerBoundValue)),
547 DocumentSearchInternalUtils.getDisplayValueWithDateOnly(SQLUtils.convertCalendar(upperBoundValue)), true, 0);
548
549 lowerBoundValue = (Calendar) searchAttributeDateTimeValue.clone();
550 lowerBoundValue.add(Calendar.DATE, -2);
551 upperBoundValue = (Calendar) searchAttributeDateTimeValue.clone();
552 upperBoundValue.add(Calendar.DATE, 2);
553 assertRangeSearchResults(docType, userId, searchAttributeDateTimeKey,
554 DocumentSearchInternalUtils.getDisplayValueWithDateOnly(SQLUtils.convertCalendar(lowerBoundValue)),
555 DocumentSearchInternalUtils.getDisplayValueWithDateOnly(SQLUtils.convertCalendar(upperBoundValue)), true, 1);
556
557 lowerBoundValue = (Calendar) searchAttributeDateTimeValue.clone();
558 lowerBoundValue.add(Calendar.DATE, 2);
559 upperBoundValue = (Calendar) searchAttributeDateTimeValue.clone();
560 upperBoundValue.add(Calendar.DATE, -2);
561 assertRangeSearchResults(docType, userId, searchAttributeDateTimeKey,
562 DocumentSearchInternalUtils.getDisplayValueWithDateOnly(SQLUtils.convertCalendar(lowerBoundValue)),
563 DocumentSearchInternalUtils.getDisplayValueWithDateOnly(SQLUtils.convertCalendar(upperBoundValue)), true, EXPECT_EXCEPTION);
564 }
565
566
567
568
569 @Test public void testRangeDefinitionStringAttributes() throws Exception {
570 String documentTypeName = "RangeDefinitionTestDocType";
571 DocumentType docType = KEWServiceLocator.getDocumentTypeService().findByName(documentTypeName);
572 String principalName = "rkirkend";
573 String principalId = KimApiServiceLocator.getPersonService().getPersonByPrincipalName(principalName).getPrincipalId();
574 WorkflowDocument workflowDocument = WorkflowDocumentFactory.createDocument(principalId, documentTypeName);
575
576
577 WorkflowAttributeDefinition.Builder inclusiveLowerXMLDef = WorkflowAttributeDefinition.Builder.create("TextFieldWithInclusiveLower");
578 inclusiveLowerXMLDef.addPropertyDefinition("textFieldWithInclusiveLower", "newvalue");
579 workflowDocument.addSearchableDefinition(inclusiveLowerXMLDef.build());
580
581 WorkflowAttributeDefinition.Builder caseSensitiveXMLDef = WorkflowAttributeDefinition.Builder.create("TextFieldWithCaseSensitivity");
582 caseSensitiveXMLDef.addPropertyDefinition("textFieldWithCaseSensitivity", "thevalue");
583 workflowDocument.addSearchableDefinition(caseSensitiveXMLDef.build());
584
585 WorkflowAttributeDefinition.Builder overridesXMLDef = WorkflowAttributeDefinition.Builder.create("TextFieldWithOverrides");
586 overridesXMLDef.addPropertyDefinition("textFieldWithOverrides", "SomeVal");
587 workflowDocument.addSearchableDefinition(overridesXMLDef.build());
588
589 workflowDocument.setTitle("Range Def Test");
590 workflowDocument.route("routing range def doc.");
591
592 workflowDocument = WorkflowDocumentFactory.loadDocument(principalId, workflowDocument.getDocumentId());
593
594
595
596 assertSearchBehavesAsExpected(docType, principalId, "textFieldWithInclusiveLower",
597 new String[] { "newvalue", "" , "" , "NEWVALUD", "newValuf", "newValuj", "newvaluf"},
598 new String[] { "" , "newvalue", "Newvaluf", "NEWVALUF", "newValud", "NEWVALUK", "" },
599 new int[] { 1 , 1 , 1 , 1 , -1 , 0 , 0 });
600
601
602 assertSearchBehavesAsExpected(docType, principalId, "textFieldWithCaseSensitivity",
603 new String[] { "thevalue", "" , "" , "THEVALUD", "thevalud", "Thevalud", "THEVALUF"},
604 new String[] { "" , "thevalue", "Thevalue", "THEVALUF", "THEVALUF", "Thevaluf", "" },
605 new int[] { 1 , 1 , 0 , 0 , -1 , 0 , 1 });
606
607
608 assertSearchBehavesAsExpected(docType, principalId, "textFieldWithOverrides",
609 new String[] { "> someval", "> SomeVal", "<= SOMEVAL", "<= SomeVal", "SOMEVAK>..SomeVam", "SomeVam>..SOMEVAK", "SOMEVAM>..SomeVak", "> somevak", "<= SomeVak" },
610
611 new int[] { 0 , 0 , 1 , 1 , 1 , -1 , -1 , 1 , 0 });
612 }
613
614
615
616
617
618
619
620
621
622
623
624
625 private void assertSearchBehavesAsExpected(DocumentType docType, String principalId, String fieldDefKey, final String[] lowBounds, final String[] upBounds, int[] resultSizes) throws Exception {
626 assertSearchResults(KEWServiceLocator.getDocumentSearchService(), docType, principalId, fieldDefKey, resultSizes, new Function<Integer, String>() {
627 @Override public String apply(@Nullable Integer index) {
628 return createSearchableAttributeRange(lowBounds[index], upBounds[index], true);
629 }
630 });
631 }
632
633
634
635
636
637
638
639
640
641
642
643 private void assertSearchBehavesAsExpected(DocumentType docType, String principalId, String fieldDefKey, final String[] expr, int[] resultSizes) throws Exception {
644 assertSearchResults(KEWServiceLocator.getDocumentSearchService(), docType, principalId, fieldDefKey, resultSizes, new Function<Integer, String>() {
645 @Override public String apply(@Nullable Integer index) {
646 return expr[index];
647 }
648 });
649 }
650
651 private void assertSearchResults(DocumentSearchService docSearchService, DocumentType docType, String principalId, String fieldDefKey, int[] resultSizes, Function<Integer, String> closure) {
652 DocumentSearchCriteria.Builder criteria = null;
653 DocumentSearchResults results = null;
654 for (int i = 0; i < resultSizes.length; i++) {
655 criteria = DocumentSearchCriteria.Builder.create();
656 criteria.setDocumentTypeName(docType.getName());
657
658 addSearchableAttribute(criteria, fieldDefKey, closure.apply(i));
659
660 try {
661 results = docSearchService.lookupDocuments(principalId, criteria.build());
662 if (resultSizes[i] < 0) {
663 fail(fieldDefKey + "'s search at loop index " + i + " should have thrown an exception");
664 }
665 assertEquals(fieldDefKey
666 + "'s search results at loop index "
667 + i
668 + " returned the wrong number of documents.", resultSizes[i], results.getSearchResults().size());
669 } catch (Exception ex) {
670 if (resultSizes[i] >= 0) {
671 fail(fieldDefKey + "'s search at loop index " + i + " should not have thrown an exception");
672 }
673 }
674 }
675 }
676 }