1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.krad.service.impl;
17
18 import static org.junit.Assert.assertEquals;
19 import static org.junit.Assert.assertNotNull;
20 import static org.junit.Assert.assertTrue;
21 import static org.junit.Assert.fail;
22 import static org.mockito.Matchers.any;
23 import static org.mockito.Mockito.mock;
24 import static org.mockito.Mockito.when;
25
26 import java.sql.Date;
27 import java.util.HashMap;
28 import java.util.Map;
29 import java.util.Set;
30
31 import org.joda.time.DateTime;
32 import org.joda.time.LocalDate;
33 import org.joda.time.format.DateTimeFormatter;
34 import org.junit.Before;
35 import org.junit.Test;
36 import org.junit.runner.RunWith;
37 import org.kuali.rice.core.api.criteria.AndPredicate;
38 import org.kuali.rice.core.api.criteria.GreaterThanOrEqualPredicate;
39 import org.kuali.rice.core.api.criteria.GreaterThanPredicate;
40 import org.kuali.rice.core.api.criteria.LessThanOrEqualPredicate;
41 import org.kuali.rice.core.api.criteria.LessThanPredicate;
42 import org.kuali.rice.core.api.criteria.LikeIgnoreCasePredicate;
43 import org.kuali.rice.core.api.criteria.LikePredicate;
44 import org.kuali.rice.core.api.criteria.OrPredicate;
45 import org.kuali.rice.core.api.criteria.Predicate;
46 import org.kuali.rice.core.api.criteria.QueryByCriteria;
47 import org.kuali.rice.core.api.datetime.DateTimeService;
48 import org.kuali.rice.core.api.search.SearchOperator;
49 import org.kuali.rice.krad.data.DataObjectService;
50 import org.kuali.rice.krad.data.DataObjectWrapper;
51 import org.kuali.rice.krad.data.metadata.DataObjectMetadata;
52 import org.kuali.rice.krad.data.provider.impl.DataObjectWrapperBase;
53 import org.kuali.rice.krad.data.util.ReferenceLinker;
54 import org.kuali.rice.krad.datadictionary.DataDictionary;
55 import org.kuali.rice.krad.service.DataDictionaryService;
56 import org.mockito.InjectMocks;
57 import org.mockito.Mock;
58 import org.mockito.invocation.InvocationOnMock;
59 import org.mockito.runners.MockitoJUnitRunner;
60 import org.mockito.stubbing.Answer;
61 import org.springframework.format.datetime.joda.DateTimeFormatterFactory;
62
63
64
65
66
67
68 @RunWith(MockitoJUnitRunner.class)
69 public class LookupCriteriaGeneratorImplTest {
70
71 @Mock DataDictionary dataDictionary;
72 @Mock DataDictionaryService dataDictionaryService;
73 @Mock DataObjectService dataObjectService;
74 @Mock ReferenceLinker referenceLinker;
75 @Mock DateTimeService dateTimeService;
76
77 @InjectMocks private LookupCriteriaGeneratorImpl generator = new LookupCriteriaGeneratorImpl();
78
79 private static final DateTimeFormatter formatter = new DateTimeFormatterFactory("mm/dd/yyyy").createDateTimeFormatter();
80
81 @Before
82 public void setUp() throws Exception {
83 when(dataDictionaryService.getDataDictionary()).thenReturn(dataDictionary);
84
85
86
87 when(dataDictionaryService.isAttributeDefined(TestClass.class, "prop2")).thenReturn(Boolean.TRUE);
88 when(dataDictionaryService.getAttributeForceUppercase(TestClass.class, "prop2")).thenReturn(Boolean.TRUE);
89
90 when(dataObjectService.wrap(any(TestClass.class))).thenAnswer(new Answer<DataObjectWrapper<TestClass>>() {
91 @Override
92 public DataObjectWrapper<TestClass> answer(InvocationOnMock invocation) throws Throwable {
93 return new DataObjectWrapperImpl<TestClass>((TestClass)invocation.getArguments()[0],
94 mock(DataObjectMetadata.class), dataObjectService, referenceLinker);
95 }
96 });
97 when(dateTimeService.convertToSqlDate(any(String.class))).thenAnswer(new Answer<Date>() {
98 @Override
99 public Date answer(InvocationOnMock invocation) throws Throwable {
100 String date = (String) invocation.getArguments()[0];
101 return new Date(LocalDate.parse(date, formatter).toDateTimeAtStartOfDay().getMillis());
102 }
103 });
104 when(dateTimeService.convertToSqlDateUpperBound(any(String.class))).thenAnswer(new Answer<Date>() {
105 @Override
106 public Date answer(InvocationOnMock invocation) throws Throwable {
107 String date = (String) invocation.getArguments()[0];
108 return new Date(LocalDate.parse(date, formatter).plusDays(1).toDateTimeAtStartOfDay().getMillis());
109 }
110 });
111 }
112
113 @Test
114 public void testGenerateCriteria_MultipleOr() throws Exception {
115 Map<String, String> mapCriteria = new HashMap<String, String>();
116 mapCriteria.put("prop1", "a|b");
117 mapCriteria.put("prop2", "c");
118 mapCriteria.put("prop3", "d");
119
120 QueryByCriteria.Builder qbcBuilder = generator.generateCriteria(TestClass.class, mapCriteria, false);
121 assertNotNull("build should not have been null", qbcBuilder);
122 QueryByCriteria qbc = qbcBuilder.build();
123
124
125
126
127
128
129
130
131
132
133
134 Predicate and = qbc.getPredicate();
135 assertTrue("top level predicate type incorrect. Was: " + and, and instanceof AndPredicate);
136 Set<Predicate> predicates = ((AndPredicate) and).getPredicates();
137
138 assertEquals("Wrong number of top-level predicates", 3, predicates.size());
139
140 boolean foundProp1 = false;
141 boolean foundProp2 = false;
142 boolean foundProp3 = false;
143 for (Predicate predicate : predicates) {
144 if (predicate instanceof LikePredicate) {
145 LikePredicate like = (LikePredicate)predicate;
146 if (like.getPropertyPath().equals("prop2")) {
147 assertEquals("prop2 had wrong value", "c", like.getValue().getValue());
148 foundProp2 = true;
149 } else {
150 fail("Invalid like predicate encountered: " + predicate);
151 }
152 } else if (predicate instanceof LikeIgnoreCasePredicate) {
153 LikeIgnoreCasePredicate like = (LikeIgnoreCasePredicate)predicate;
154 if (like.getPropertyPath().equals("prop3")) {
155 assertEquals("prop3 had wrong value", "d", like.getValue().getValue());
156 foundProp3 = true;
157 } else {
158 fail("Invalid likeIgnoreCase predicate encountered: " + predicate);
159 }
160 } else if (predicate instanceof OrPredicate) {
161 foundProp1 = true;
162
163 OrPredicate orPredicate = (OrPredicate)predicate;
164 assertEquals("wrong number of predicates in the internal OR predicate",2, orPredicate.getPredicates().size());
165 for (Predicate orSubPredicate : orPredicate.getPredicates()) {
166 if (orSubPredicate instanceof LikeIgnoreCasePredicate) {
167 LikeIgnoreCasePredicate likeInternal = (LikeIgnoreCasePredicate)orSubPredicate;
168 if (likeInternal.getPropertyPath().equals("prop1")) {
169 assertTrue("prop1 had wrong value", "a".equals(likeInternal.getValue().getValue()) ||
170 "b".equals(likeInternal.getValue().getValue()));
171 } else {
172 fail("Invalid predicate, does not have a propertypath of prop1:" + predicate);
173 }
174 } else {
175 fail("Unexpected predicate: " + orSubPredicate);
176 }
177 }
178 } else {
179 fail("Unexpected predicate: " + predicate);
180 }
181 }
182 assertTrue("prop1 predicate missing", foundProp1);
183 assertTrue("prop2 predicate missing", foundProp2);
184 assertTrue("prop3 predicate missing", foundProp3);
185 }
186
187
188
189
190
191
192
193
194
195
196 @Test
197 public void testGenerateCriteria_BetweenDate() {
198 String lowerDateString = "1/1/2010";
199 DateTime lowerDate = DateTime.parse(lowerDateString, formatter).withTimeAtStartOfDay();
200 String upperDateString = "1/2/2010";
201 DateTime upperDate = DateTime.parse(upperDateString, formatter).withTimeAtStartOfDay();
202
203 Map<String, String> mapCriteria = new HashMap<String, String>();
204 mapCriteria.put("prop4", lowerDateString + SearchOperator.BETWEEN.op() + upperDateString);
205
206 QueryByCriteria.Builder qbcBuilder = generator.generateCriteria(TestClass.class, mapCriteria, false);
207 assertNotNull(qbcBuilder);
208 QueryByCriteria qbc = qbcBuilder.build();
209
210 Predicate and = qbc.getPredicate();
211 assertTrue(and instanceof AndPredicate);
212 Set<Predicate> predicates = ((AndPredicate) and).getPredicates();
213
214 assertEquals(2, predicates.size());
215
216 boolean foundProp4Lower = false;
217 boolean foundProp4Upper = false;
218 for (Predicate predicate : predicates) {
219 if (predicate instanceof GreaterThanOrEqualPredicate) {
220 foundProp4Lower = true;
221 GreaterThanOrEqualPredicate greaterThanOrEqual = (GreaterThanOrEqualPredicate) predicate;
222 assertEquals(greaterThanOrEqual.getValue().getValue(), lowerDate);
223 } else if (predicate instanceof LessThanOrEqualPredicate) {
224 foundProp4Upper = true;
225 LessThanOrEqualPredicate lessThanOrEqual = (LessThanOrEqualPredicate) predicate;
226 assertEquals(lessThanOrEqual.getValue().getValue(), upperDate.plusDays(1));
227 }
228 }
229 assertTrue(foundProp4Lower);
230 assertTrue(foundProp4Upper);
231 }
232
233
234
235
236
237
238
239
240 @Test
241 public void testGenerateCriteria_GreaterThanEqualDate() {
242 String dateString = "1/1/2010";
243 DateTime date = DateTime.parse(dateString, formatter).withTimeAtStartOfDay();
244
245 Map<String, String> mapCriteria = new HashMap<String, String>();
246 mapCriteria.put("prop4", SearchOperator.GREATER_THAN_EQUAL.op() + dateString);
247
248 QueryByCriteria.Builder qbcBuilder = generator.generateCriteria(TestClass.class, mapCriteria, false);
249 assertNotNull(qbcBuilder);
250 QueryByCriteria qbc = qbcBuilder.build();
251
252 Predicate greaterThanEqual = qbc.getPredicate();
253 assertTrue(greaterThanEqual instanceof GreaterThanOrEqualPredicate);
254 assertEquals(((GreaterThanOrEqualPredicate) greaterThanEqual).getValue().getValue(), date);
255 }
256
257
258
259
260
261
262
263
264
265 @Test
266 public void testGenerateCriteria_LessThanEqualDate() {
267 String dateString = "1/2/2010";
268 DateTime date = DateTime.parse(dateString, formatter).withTimeAtStartOfDay();
269
270 Map<String, String> mapCriteria = new HashMap<String, String>();
271 mapCriteria.put("prop4", SearchOperator.LESS_THAN_EQUAL.op() + dateString);
272
273 QueryByCriteria.Builder qbcBuilder = generator.generateCriteria(TestClass.class, mapCriteria, false);
274 assertNotNull(qbcBuilder);
275 QueryByCriteria qbc = qbcBuilder.build();
276
277 Predicate lessThanEqual = qbc.getPredicate();
278 assertTrue(lessThanEqual instanceof LessThanOrEqualPredicate);
279 assertEquals(((LessThanOrEqualPredicate) lessThanEqual).getValue().getValue(), date.plusDays(1));
280 }
281
282
283
284
285
286
287
288
289 @Test
290 public void testGenerateCriteria_GreaterThanDate() {
291 String dateString = "1/1/2010";
292 DateTime date = DateTime.parse(dateString, formatter).withTimeAtStartOfDay();
293
294 Map<String, String> mapCriteria = new HashMap<String, String>();
295 mapCriteria.put("prop4", SearchOperator.GREATER_THAN.op() + dateString);
296
297 QueryByCriteria.Builder qbcBuilder = generator.generateCriteria(TestClass.class, mapCriteria, false);
298 assertNotNull(qbcBuilder);
299 QueryByCriteria qbc = qbcBuilder.build();
300
301 Predicate greaterThan = qbc.getPredicate();
302 assertTrue(greaterThan instanceof GreaterThanPredicate);
303 assertEquals(((GreaterThanPredicate) greaterThan).getValue().getValue(), date);
304 }
305
306
307
308
309
310
311
312
313 @Test
314 public void testGenerateCriteria_LessThanDate() {
315 String dateString = "1/2/2010";
316 DateTime date = DateTime.parse(dateString, formatter).withTimeAtStartOfDay();
317
318 Map<String, String> mapCriteria = new HashMap<String, String>();
319 mapCriteria.put("prop4", SearchOperator.LESS_THAN.op() + dateString);
320
321 QueryByCriteria.Builder qbcBuilder = generator.generateCriteria(TestClass.class, mapCriteria, false);
322 assertNotNull(qbcBuilder);
323 QueryByCriteria qbc = qbcBuilder.build();
324
325 Predicate lessThan = qbc.getPredicate();
326 assertTrue(lessThan instanceof LessThanPredicate);
327 assertEquals(((LessThanPredicate) lessThan).getValue().getValue(), date);
328 }
329
330 public static final class TestClass {
331
332 private String prop1;
333 private String prop2;
334 private String prop3;
335 private Date prop4;
336
337 public String getProp1() {
338 return prop1;
339 }
340
341 public void setProp1(String prop1) {
342 this.prop1 = prop1;
343 }
344
345 public String getProp2() {
346 return prop2;
347 }
348
349 public void setProp2(String prop2) {
350 this.prop2 = prop2;
351 }
352
353 public String getProp3() {
354 return prop3;
355 }
356
357 public void setProp3(String prop3) {
358 this.prop3 = prop3;
359 }
360
361 public Date getProp4() {
362 return prop4;
363 }
364
365 public void setProp4(Date prop4) {
366 this.prop4 = prop4;
367 }
368
369 }
370
371 private static final class DataObjectWrapperImpl<T> extends DataObjectWrapperBase<T> {
372 private DataObjectWrapperImpl(T dataObject, DataObjectMetadata metadata, DataObjectService dataObjectService,
373 ReferenceLinker referenceLinker) {
374 super(dataObject, metadata, dataObjectService, referenceLinker);
375 }
376 }
377
378 }