1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.kns.workflow;
17
18 import org.apache.commons.lang.exception.ExceptionUtils;
19 import org.junit.Assert;
20 import org.junit.Test;
21 import org.kuali.rice.core.api.uif.RemotableAttributeError;
22 import org.kuali.rice.core.api.util.type.KualiDecimal;
23 import org.kuali.rice.kew.api.document.search.DocumentSearchCriteria;
24 import org.kuali.rice.kew.api.document.search.DocumentSearchResults;
25 import org.kuali.rice.kew.api.exception.WorkflowException;
26 import org.kuali.rice.kew.docsearch.service.DocumentSearchService;
27 import org.kuali.rice.kew.doctype.bo.DocumentType;
28 import org.kuali.rice.kew.service.KEWServiceLocator;
29 import org.kuali.rice.kim.api.services.KimApiServiceLocator;
30 import org.kuali.rice.krad.UserSession;
31 import org.kuali.rice.krad.datadictionary.exception.UnknownDocumentTypeException;
32 import org.kuali.rice.krad.service.DocumentService;
33 import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
34 import org.kuali.rice.krad.test.document.AccountWithDDAttributesDocument;
35 import org.kuali.rice.krad.util.GlobalVariables;
36 import org.kuali.rice.kns.workflow.attribute.DataDictionarySearchableAttribute;
37 import org.kuali.rice.krad.test.KRADTestCase;
38
39 import java.sql.Timestamp;
40 import java.util.ArrayList;
41 import java.util.Calendar;
42 import java.util.Collections;
43 import java.util.HashMap;
44 import java.util.List;
45 import java.util.Map;
46 import java.util.concurrent.Callable;
47
48 import static junit.framework.Assert.assertEquals;
49 import static junit.framework.Assert.fail;
50
51
52
53
54
55
56
57
58 @Deprecated
59 public class DataDictionarySearchableAttributeTest extends KRADTestCase {
60
61 @Override
62 public void setUp() throws Exception {
63 super.setUp();
64 GlobalVariables.setUserSession(new UserSession("quickstart"));
65 }
66
67 private final static String ACCOUNT_WITH_DD_ATTRIBUTES_DOCUMENT_NAME = "AccountWithDDAttributes";
68
69 enum DOCUMENT_FIXTURE {
70 NORMAL_DOCUMENT("Testing NORMAL_DOCUMENT", new Integer(1234567890), "John Doe", new KualiDecimal(501.77), createTimestamp(
71 2009, Calendar.OCTOBER, 15, 0, 0, 0), createTimestamp(2009, Calendar.NOVEMBER, 1, 0, 0, 0), "SecondState", true),
72 ZERO_NUMBER_DOCUMENT("Testing ZERO_NUMBER_DOCUMENT", new Integer(0), "Jane Doe", new KualiDecimal(-100), createTimestamp(
73 2009, Calendar.OCTOBER, 16, 0, 0, 0), createTimestamp(2015, Calendar.NOVEMBER, 2, 0, 0, 0), "FirstState", true),
74 FALSE_AWAKE_DOCUMENT("Testing FALSE_AWAKE_DOCUMENT", new Integer(987654321), "John D'oh", new KualiDecimal(0.0), createTimestamp(
75 2006, Calendar.OCTOBER, 17, 0, 0, 0), createTimestamp(1900, Calendar.NOVEMBER, 3, 0, 0, 0), "FourthState", false),
76 ODD_NAME_DOCUMENT("Testing ODD_NAME_DOCUMENT", new Integer(88), "_", new KualiDecimal(10000051.0), createTimestamp(
77 2009, Calendar.OCTOBER, 18, 0, 0, 0), createTimestamp(2009, Calendar.NOVEMBER, 4, 0, 0, 0), "FourthState", true),
78 ODD_TIMESTAMP_DOCUMENT("Testing ODD_TIMESTAMP_DOCUMENT", new Integer(9000), "Shane Kloe", new KualiDecimal(4.54), createTimestamp(
79 2012, Calendar.OCTOBER, 19, 0, 0, 0), createTimestamp(2007, Calendar.NOVEMBER, 5, 12, 4, 38), "ThirdState", false),
80 ANOTHER_ODD_NAME_DOCUMENT("Testing ANOTHER_ODD_NAME_DOCUMENT", new Integer(1234567889), "---", new KualiDecimal(501), createTimestamp(
81 2009, Calendar.APRIL, 20, 0, 0, 0), createTimestamp(2009, Calendar.NOVEMBER, 6, 12, 59, 59), "ThirdState", true),
82 INVALID_STATE_DOCUMENT("Testing INVALID_STATE_DOCUMENT", new Integer(99999), "AAAAAAAAA", new KualiDecimal(2.22), createTimestamp(
83 2009, Calendar.OCTOBER, 21, 0, 0, 0), createTimestamp(2009, Calendar.NOVEMBER, 7, 0, 0, 1), "SeventhState", true),
84 WILDCARD_NAME_DOCUMENT("Testing WILDCARD_NAME_DOCUMENT", new Integer(1), "Sh*ne><K!=e?", new KualiDecimal(771.05), createTimestamp(
85 2054, Calendar.OCTOBER, 22, 0, 0, 0), createTimestamp(2008, Calendar.NOVEMBER, 8, 12, 0, 0), "FirstState", true);
86
87 private String accountDocumentDescription;
88 private Integer accountNumber;
89 private String accountOwner;
90 private KualiDecimal accountBalance;
91 private Timestamp accountOpenDate;
92 private Timestamp accountUpdateDateTime;
93 private String accountState;
94 private boolean accountAwake;
95
96 private DOCUMENT_FIXTURE(String accountDocumentDescription, Integer accountNumber, String accountOwner, KualiDecimal accountBalance, Timestamp accountOpenDate, Timestamp accountUpdateDateTime, String accountState, boolean accountAwake) {
97 this.accountDocumentDescription = accountDocumentDescription;
98 this.accountNumber = accountNumber;
99 this.accountOwner = accountOwner;
100 this.accountBalance = accountBalance;
101 this.accountOpenDate = accountOpenDate;
102 this.accountUpdateDateTime = accountUpdateDateTime;
103 this.accountState = accountState;
104 this.accountAwake = accountAwake;
105 }
106
107 public AccountWithDDAttributesDocument getDocument(DocumentService docService) throws WorkflowException {
108 AccountWithDDAttributesDocument acctDoc = (AccountWithDDAttributesDocument) docService.getNewDocument(ACCOUNT_WITH_DD_ATTRIBUTES_DOCUMENT_NAME);
109 acctDoc.getDocumentHeader().setDocumentDescription(this.accountDocumentDescription);
110 acctDoc.setAccountNumber(this.accountNumber);
111 acctDoc.setAccountOwner(this.accountOwner);
112 acctDoc.setAccountBalance(this.accountBalance);
113 acctDoc.setAccountOpenDate(this.accountOpenDate);
114 acctDoc.setAccountUpdateDateTime(this.accountUpdateDateTime);
115 acctDoc.setAccountState(this.accountState);
116 acctDoc.setAccountAwake(this.accountAwake);
117
118 return acctDoc;
119 }
120 }
121
122
123
124
125 @Test
126 public void testWildcardsAndMultiSelectsOnDDSearchableAttributes() throws Exception {
127 DocumentService docService = KRADServiceLocatorWeb.getDocumentService();
128
129 DocumentType docType = KEWServiceLocator.getDocumentTypeService().findByName("AccountWithDDAttributes");
130 String principalName = "quickstart";
131 String principalId = KimApiServiceLocator.getPersonService().getPersonByPrincipalName(principalName).getPrincipalId();
132
133
134 docService.routeDocument(DOCUMENT_FIXTURE.NORMAL_DOCUMENT.getDocument(docService), "Routing NORMAL_DOCUMENT", null);
135 docService.routeDocument(DOCUMENT_FIXTURE.ZERO_NUMBER_DOCUMENT.getDocument(docService), "Routing ZERO_NUMBER_DOCUMENT", null);
136 docService.routeDocument(DOCUMENT_FIXTURE.FALSE_AWAKE_DOCUMENT.getDocument(docService), "Routing FALSE_AWAKE_DOCUMENT", null);
137 docService.routeDocument(DOCUMENT_FIXTURE.ODD_NAME_DOCUMENT.getDocument(docService), "Routing ODD_NAME_DOCUMENT", null);
138 docService.routeDocument(DOCUMENT_FIXTURE.ODD_TIMESTAMP_DOCUMENT.getDocument(docService), "Routing ODD_TIMESTAMP_DOCUMENT", null);
139 docService.routeDocument(DOCUMENT_FIXTURE.ANOTHER_ODD_NAME_DOCUMENT.getDocument(docService), "Routing ANOTHER_ODD_NAME_DOCUMENT", null);
140 docService.routeDocument(DOCUMENT_FIXTURE.INVALID_STATE_DOCUMENT.getDocument(docService), "Routing INVALID_STATE_DOCUMENT", null);
141 docService.routeDocument(DOCUMENT_FIXTURE.WILDCARD_NAME_DOCUMENT.getDocument(docService), "Routing WILDCARD_NAME_DOCUMENT", null);
142
143
144
145 assertDDSearchableAttributeWildcardsWork(docType, principalId, "accountNumber",
146 new String[] {"!1234567890", "9???9", ">1", "987654321|1234567889", "<100", ">=99999", "<=-42", ">9000|<=1", "<1|>=1234567890",
147 ">1234567889&&<1234567890", ">=88&&<=99999", "0|>10&&<10000", "9000..1000000", "0..100|>1234567889", "1..10000&&>50", "250..50"},
148 new int[] {7 , -1 , 6 , 2 , 3 , 4 , -1 , 6 , 2,
149 0 , 3 , 3 , 2 , 4 , 2 , 0});
150
151
152
153 assertDDSearchableAttributeWildcardsWork(docType, principalId, "accountOwner",
154 new String[] {"!John Doe", "!John*", "!John Doe&&!Shane Kloe", "!Jane ???", "!Jane Doe!John Doe", "_", "_|---", "Sh*ne><K!=e",
155 ">Jane Doe", "<Shane Kloe", ">=Johnny", "<=John D'oh", ">John Doe|<---", ">=AAAAAAAAA&&<=Jane Doe", ">---&&!John D'oh",
156 "<Shane Kloe&&!John*", "*oe", "???? Doe", "Jane Doe..John Doe", "AAAAAAAAA..Shane Kloe&&!John Doe", "John D'oh|---..Jane Doe"},
157 new int[] {7 , 6 , 6 , 7 , 6 , 1 , 2 , 8,
158 5 , 6 , 3 , 4 , 3 , 2 , 6,
159 4 , 3 , 2 , 3 , 5 , 4});
160
161
162 assertDDSearchableAttributeWildcardsWork(docType, principalId, "accountBalance",
163 new String[] {"501.??", "*.54" , "!2.22", "10000051.0|771.05", "<0.0", ">501", "<=4.54", ">=-99.99", ">4.54|<=-1", ">=0&&<501.77", "!",
164 "<=0|>=10000051", ">501&&<501.77", "-100|>771.05", "2.22..501", "-100..4.54&&<=0", "2.22|501.77..10000051.0", "Zero",
165 "-$100", "<(501)&&>=($2.22)", "$4.54|<(1)", "($0.00)..$771.05", ">=$(500)", ")501(", "4.54$", "$501..0"},
166 new int[] {-1 , -1 , 7 , 2 , 1 , 3 , 4 , 7 , 5 , 4 , -1,
167 3 , 0 , 2 , 3 , 2 , 4 , -1,
168 1 , 2 , 3 , 6 , -1 , -1 , -1 , 0});
169
170
171
172 assertDDSearchableAttributeWildcardsWork(docType, principalId, "accountOpenDate",
173 new String[] {"!10/15/2009", "Unknown", "10/15/2009|10/21/2009", "10/22/????", "*/*/05", ">10/17/06", "<=12-31-09&&>=10/16/2009",
174 ">101809&&<102012", ">=10/22/2054|<10/16/2009", ">2-29-12|<=10/21/09", "<2009", ">=10/19/2012|04/20/09", ">2/29/09", "2009..2008",
175 "10/15/2009..10/21/2009", "1/1/2009..10/20/2009|10/22/2054", "<=06/32/03", ">2008&&<2011|10/17/06",
176 "<02/26/10500", ">05-07-333", ">=03/26/1001", "<=11-11-9900"},
177 new int[] {-1 , -1 , 2 , -1 , -1 , 7 , 3,
178 2 , 4 , 8 , 1 , 3 , -1 , -1,
179 4 , 5 , -1 , 6 ,
180 -1 , -1 , 8 , 8});
181
182
183
184 assertDDSearchableAttributeWildcardsWork(docType, principalId, "accountStateMultiselect",
185 new String[][] {{"FirstState"}, {"SecondState"}, {"ThirdState"}, {"FourthState"}, {"FirstState","ThirdState"},
186 {"SecondState","FourthState"}, {"ThirdState","SecondState"}, {"FourthState","FirstState","SecondState"}, {"SeventhState"},
187 {"ThirdState","FirstState","SecondState","FourthState"}},
188 new int[] {2 , 1 , 2 , 2 , 4,
189 3 , 3 , 5 , 1,
190 7});
191
192
193
194 assertDDSearchableAttributeWildcardsWork(docType, principalId, "accountAwake", new String[] {"Y", "N"}, new int[] {6, 2});
195
196
197
198
199
200
201
202
203 assertDDSearchableAttributeWildcardsWork(docType, principalId, "accountUpdateDateTime",
204 new String[] {"!11/01/2009 00:00:00", "11/02/2015 00:00:00|11/06/2009 12:59:59", "11/??/2009 ??:??:??", ">110609 12:59:59",
205 "<=2009 1:2:3", ">=11/06/09 12:59:59", "<11/8/2008 12:00 PM", "Blank",
206 "11/3/1900 00:00:00|>11-7-09 00:00:01", "02/29/2008 07:00:00..11/04/2009 00:00:00",
207 "11/1/09 00:00:00..11/06/09 12:59:59|11/03/1900 00:00:00", "2009..2008", "2000..2009&&>=110507 12:4:38",
208 "<=11/08/2008 12:00 AM", ">=01-01-1000 00:00:00", ">12/31/999 23:59:59", "<01-01-10000 00:00:00", "<=12/31/9999 23:59:59"},
209 new int[] {-1 , 2 , -1 , 2,
210 3 , 3 , 2 , -1,
211 2 , 3,
212 4 , -1 , 2,
213 2 , 8 , -1 , -1 , 8});
214 }
215
216
217
218
219
220
221
222
223
224
225
226
227 private static Timestamp createTimestamp(int year, int month, int day, int hour, int minute, int second) {
228 Calendar date = Calendar.getInstance();
229 date.set(year, month, day, hour, minute, second);
230 return new java.sql.Timestamp(date.getTimeInMillis());
231 }
232
233
234
235
236
237
238
239
240
241
242
243 private void assertDDSearchableAttributeWildcardsWork(DocumentType docType, String principalId, String fieldName, Object[] searchValues,
244 int[] resultSizes) throws Exception {
245 if (!(searchValues instanceof String[]) && !(searchValues instanceof String[][])) {
246 throw new IllegalArgumentException("'searchValues' parameter has to be either a String[] or a String[][]");
247 }
248 DocumentSearchCriteria.Builder criteria = null;
249 DocumentSearchResults results = null;
250 DocumentSearchService docSearchService = KEWServiceLocator.getDocumentSearchService();
251 for (int i = 0; i < resultSizes.length; i++) {
252 if (searchValues[i].toString().equalsIgnoreCase("Zero")) {
253 int num = 1 + 1;
254 }
255 criteria = DocumentSearchCriteria.Builder.create();
256 criteria.setDocumentTypeName(docType.getName());
257 if (searchValues instanceof String[][]) {
258 String[] innerArray = (String[]) searchValues[i];
259 for (int j=0; j<innerArray.length; j++) {
260 criteria.addDocumentAttributeValue(fieldName, innerArray[j]);
261 }
262 } else {
263 criteria.addDocumentAttributeValue(fieldName, searchValues[i].toString());
264 }
265
266 try {
267 results = docSearchService.lookupDocuments(principalId, criteria.build());
268 if (resultSizes[i] < 0) {
269 Assert.fail(fieldName + "'s search at loop index " + i + " should have thrown an exception");
270 }
271 if(resultSizes[i] != results.getSearchResults().size()){
272 assertEquals(fieldName + "'s search results at loop index " + i + " returned the wrong number of documents.", resultSizes[i], results.getSearchResults().size());
273 }
274 } catch (Exception ex) {
275 if (resultSizes[i] >= 0) {
276 LOG.error("exception", ex);
277 Assert.fail(fieldName
278 + "'s search at loop index "
279 + i
280 + " for search value '"
281 + searchValues[i]
282 + "' should not have thrown an exception");
283 }
284 }
285 GlobalVariables.clear();
286 }
287 }
288
289
290
291
292 @Test
293 public void testValidateUserSearchInputsNoCast() throws Exception {
294 DataDictionarySearchableAttribute searchableAttribute = new DataDictionarySearchableAttribute();
295 final DocumentService documentService = KRADServiceLocatorWeb.getDocumentService();
296
297 try {
298 AccountWithDDAttributesDocument document = DOCUMENT_FIXTURE.NORMAL_DOCUMENT.getDocument(documentService);
299 documentService.saveDocument(document);
300 final String documentNumber = document.getDocumentNumber();
301 } catch (UnknownDocumentTypeException udte) {
302 fail("CI failure - https://jira.kuali.org/browse/KULRICE-9289 " + udte.getMessage() + ExceptionUtils.getStackTrace(udte));
303 }
304
305 Exception caughtException;
306 List foundErrors;
307
308 caughtException = null;
309 foundErrors = new ArrayList();
310 DocumentSearchCriteria.Builder criteria = DocumentSearchCriteria.Builder.create();
311 criteria.setDocumentTypeName(ACCOUNT_WITH_DD_ATTRIBUTES_DOCUMENT_NAME);
312 Map<String, List<String>> simpleParamMap = new HashMap<String, List<String>>();
313 simpleParamMap.put("accountState", Collections.singletonList("FirstState"));
314 criteria.setDocumentAttributeValues(simpleParamMap);
315 try {
316 foundErrors = searchableAttribute.validateDocumentAttributeCriteria(null, criteria.build());
317 } catch (RuntimeException re) {
318 caughtException = re;
319 }
320 Assert.assertNull("Found Exception " + caughtException, caughtException);
321 Assert.assertTrue("There were errors: " + foundErrors, (foundErrors == null || foundErrors.isEmpty()));
322
323 caughtException = null;
324 foundErrors = new ArrayList();
325 Map<String, List<String>> listParamMap = new HashMap<String, List<String>>();
326 List<String> paramValues = new ArrayList<String>();
327 paramValues.add("FirstState");
328 paramValues.add("SecondState");
329 listParamMap.put("accountState", paramValues);
330 criteria.setDocumentAttributeValues(listParamMap);
331 try {
332 foundErrors = searchableAttribute.validateDocumentAttributeCriteria(null, criteria.build());
333 } catch (RuntimeException re) {
334 caughtException = re;
335 }
336 Assert.assertNull("Found Exception " + caughtException, caughtException);
337 Assert.assertTrue("There were errors: " + foundErrors, (foundErrors == null || foundErrors.isEmpty()));
338 }
339
340
341
342
343 @Test
344 public void testErrorMessageResolution() throws Exception {
345 final DataDictionarySearchableAttribute searchableAttribute = new DataDictionarySearchableAttribute();
346 final DocumentSearchCriteria.Builder criteria = DocumentSearchCriteria.Builder.create();
347
348
349
350
351 List<RemotableAttributeError> errors = GlobalVariables.doInNewGlobalVariables(new Callable<List<RemotableAttributeError>>() {
352 public List<RemotableAttributeError> call() {
353 GlobalVariables.getMessageMap().putError("fake.property", "error.custom", "the error message");
354 return searchableAttribute.validateDocumentAttributeCriteria(null, criteria.build());
355 }
356 });
357 Assert.assertEquals(1, errors.size());
358 assertEquals("the error message", errors.get(0).getMessage());
359 }
360
361
362
363
364 @Test
365 public void testMultiSelectIntegration() throws Exception {
366 final DocumentService docService = KRADServiceLocatorWeb.getDocumentService();
367
368 DocumentType docType = KEWServiceLocator.getDocumentTypeService().findByName("AccountWithDDAttributes");
369 String principalName = "quickstart";
370 String principalId = KimApiServiceLocator.getPersonService().getPersonByPrincipalName(principalName).getPrincipalId();
371
372
373 docService.routeDocument(DOCUMENT_FIXTURE.NORMAL_DOCUMENT.getDocument(docService), "Routing NORMAL_DOCUMENT", null);
374
375 assertDDSearchableAttributeWildcardsWork(docType, principalId, "accountStateMultiselect",
376 new String[][] {{"FirstState"}, {"SecondState"}, {"ThirdState"}, {"FourthState"}, {"FirstState", "SecondState"}, {"FirstState","ThirdState"}, {"FirstState", "FourthState"}, {"SecondState", "ThirdState"}, {"SecondState", "FourthState"}, {"ThirdState", "FourthState"}, {"FirstState", "SecondState", "ThirdState"}, {"FirstState", "ThirdState", "FourthState"}, {"SecondState", "ThirdState", "FourthState"}, {"FirstState","SecondState", "ThirdState", "FourthState"}},
377 new int[] { 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1 });
378
379 assertDDSearchableAttributeWildcardsWork(docType, principalId, "accountOpenDate",
380 new String[][] {{"10/15/2009"}, {"10/15/2009","10/17/2009"}, {"10/14/2009","10/16/2009"}},
381 new int[] { 1, 1, 0 });
382
383 assertDDSearchableAttributeWildcardsWork(docType, principalId, "accountBalance",
384 new String[][] {{"501.77"},{"501.77", "63.54"},{"501.78","501.74"}, {"502.00"}, {"0.00"} },
385 new int[] { 1, 1, 0, 0, 0 });
386
387 assertDDSearchableAttributeWildcardsWork(docType, principalId, "accountNumber",
388 new String[][] {{"1234567890"},{"1234567890", "9876543210"},{"9876543210","77774"}, {"88881"}, {"0"} },
389 new int[] { 1, 1, 0, 0, 0 });
390 }
391 }