1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package net.sourceforge.domian.specification.example;
17
18
19 import java.util.Date;
20
21 import org.junit.Assert;
22 import org.junit.Before;
23 import org.junit.Test;
24
25 import net.sourceforge.domian.specification.CompositeSpecification;
26 import net.sourceforge.domian.specification.Specification;
27 import net.sourceforge.domian.specification.SpecificationFactory;
28 import net.sourceforge.domian.test.domain.Customer;
29 import net.sourceforge.domian.test.domain.Order;
30 import net.sourceforge.domian.test.domain.OrderLine;
31
32 import junit.framework.TestCase;
33
34 import static net.sourceforge.domian.specification.SpecificationFactory.a;
35 import static net.sourceforge.domian.specification.SpecificationFactory.after;
36 import static net.sourceforge.domian.specification.SpecificationFactory.afterOrAtTheSameTimeAs;
37 import static net.sourceforge.domian.specification.SpecificationFactory.all;
38 import static net.sourceforge.domian.specification.SpecificationFactory.allObjects;
39 import static net.sourceforge.domian.specification.SpecificationFactory.atLeast;
40 import static net.sourceforge.domian.specification.SpecificationFactory.atMost;
41 import static net.sourceforge.domian.specification.SpecificationFactory.atTheSameTimeAs;
42 import static net.sourceforge.domian.specification.SpecificationFactory.before;
43 import static net.sourceforge.domian.specification.SpecificationFactory.both;
44 import static net.sourceforge.domian.specification.SpecificationFactory.createDefaultNumberSpecification;
45 import static net.sourceforge.domian.specification.SpecificationFactory.createSpecificationFor;
46 import static net.sourceforge.domian.specification.SpecificationFactory.equalTo;
47 import static net.sourceforge.domian.specification.SpecificationFactory.greaterThan;
48 import static net.sourceforge.domian.specification.SpecificationFactory.haveSizeOf;
49 import static net.sourceforge.domian.specification.SpecificationFactory.include;
50 import static net.sourceforge.domian.specification.SpecificationFactory.includeAPercentageOf;
51 import static net.sourceforge.domian.specification.SpecificationFactory.is;
52 import static net.sourceforge.domian.specification.SpecificationFactory.isAfter;
53 import static net.sourceforge.domian.specification.SpecificationFactory.isAfterOrAtTheSameTimeAs;
54 import static net.sourceforge.domian.specification.SpecificationFactory.isBefore;
55 import static net.sourceforge.domian.specification.SpecificationFactory.isDate;
56 import static net.sourceforge.domian.specification.SpecificationFactory.isEnum;
57 import static net.sourceforge.domian.specification.SpecificationFactory.isFalse;
58 import static net.sourceforge.domian.specification.SpecificationFactory.isFrom;
59 import static net.sourceforge.domian.specification.SpecificationFactory.isTrue;
60 import static net.sourceforge.domian.specification.SpecificationFactory.matches;
61 import static net.sourceforge.domian.specification.SpecificationFactory.matchesWildcardExpression;
62 import static net.sourceforge.domian.specification.SpecificationFactory.moreThan;
63 import static net.sourceforge.domian.specification.SpecificationFactory.not;
64 import static net.sourceforge.domian.specification.SpecificationFactory.specify;
65 import static net.sourceforge.domian.test.domain.Customer.Gender.FEMALE;
66 import static net.sourceforge.domian.test.domain.Customer.Gender.MALE;
67 import static net.sourceforge.domian.test.domain.Testdata.femaleCustomer;
68 import static net.sourceforge.domian.test.domain.Testdata.maleCustomer;
69 import static net.sourceforge.domian.test.domain.Testdata.thisDate;
70 import static net.sourceforge.domian.test.domain.Testdata.thisMonth;
71 import static net.sourceforge.domian.test.domain.Testdata.thisYear;
72 import static net.sourceforge.domian.test.domain.Testdata.today;
73 import static net.sourceforge.domian.util.DateUtils.getTime;
74 import static org.junit.Assert.assertFalse;
75 import static org.junit.Assert.assertTrue;
76
77
78 public class IntroductionExamplesTest {
79
80 OrderLine cancelledOrderLine = new OrderLine(8001L).paymentReceived(false).cancelled(true);
81 OrderLine paymentReceivedOrderLine = new OrderLine(8002L).paymentReceived(true).cancelled(false);
82 OrderLine paymentNotReceivedOrderLine = new OrderLine(8003L).paymentReceived(false).cancelled(false);
83 OrderLine toBeRefundedOrderLine = new OrderLine(8004L).paymentReceived(true).cancelled(true);
84
85 Order orderFromThisYear_1 = new Order(1L);
86 Order orderFromThisYear_2 = new Order(2L);
87 Order orderFromThisYear_3 = new Order(3L);
88 Order orderFromThisYear_4 = new Order(4L);
89 Order orderFromOneYearAgo_1 = new Order(101L);
90 Order orderFromOneYearAgo_2 = new Order(102L);
91 Order orderFromOneYearAgo_3 = new Order(103L);
92 Order orderFromOneYearAgo_4 = new Order(104L);
93 Order orderFromTwoYearsAgo_1 = new Order(201L);
94 Order orderFromTwoYearsAgo_2 = new Order(202L);
95 Order orderFromThreeYearsAgo_1 = new Order(301L);
96 Order orderFromThreeYearsAgo_2 = new Order(302L);
97
98 Customer aCustomerWithNoOrders = new Customer(8001L, getTime(1999, 9, 1));
99 Customer aCustomerWithOneOrder = new Customer(8002L, getTime(1999, 9, 1));
100 Customer aCustomerWithTwoOrders = new Customer(8003L, getTime(1999, 9, 1));
101 Customer aCustomerWithThreeOrders = new Customer(8004L, getTime(1999, 9, 1));
102 Customer aCustomerWithFourOrders = new Customer(8005L, getTime(1999, 9, 1));
103 Customer aCustomerWithFiveOrders = new Customer(8006L, getTime(1999, 9, 1));
104 Customer aCustomerWithSixOrders = new Customer(8007L, getTime(1999, 9, 1));
105 Customer aCustomerWithEightOrders = new Customer(8008L, getTime(1999, 9, 1));
106
107
108 @Before
109 public void beforeEachMethod() {
110
111 orderFromThisYear_1.setOrderDate(getTime(thisYear, thisMonth, thisDate));
112 orderFromThisYear_1.addOrderLine(paymentReceivedOrderLine);
113 orderFromThisYear_2.setOrderDate(getTime(thisYear, thisMonth, thisDate - 1));
114 orderFromThisYear_2.addOrderLine(paymentReceivedOrderLine);
115 orderFromThisYear_3.setOrderDate(getTime(thisYear, thisMonth, thisDate - 2));
116 orderFromThisYear_3.addOrderLine(paymentReceivedOrderLine);
117 orderFromThisYear_3.addOrderLine(paymentReceivedOrderLine);
118 orderFromThisYear_3.addOrderLine(cancelledOrderLine);
119 orderFromThisYear_4.setOrderDate(getTime(thisYear, thisMonth - 3, thisDate - 3));
120 orderFromThisYear_4.addOrderLine(paymentNotReceivedOrderLine);
121
122 orderFromOneYearAgo_1.setOrderDate(getTime(thisYear - 1, thisMonth, thisDate));
123 orderFromOneYearAgo_1.addOrderLine(paymentReceivedOrderLine);
124 orderFromOneYearAgo_2.setOrderDate(getTime(thisYear - 1, thisMonth, thisDate - 1));
125 orderFromOneYearAgo_2.addOrderLine(paymentReceivedOrderLine);
126 orderFromOneYearAgo_3.setOrderDate(getTime(thisYear - 1, thisMonth, thisDate - 2));
127 orderFromOneYearAgo_3.addOrderLine(paymentReceivedOrderLine);
128 orderFromOneYearAgo_4.setOrderDate(getTime(thisYear - 1, thisMonth, thisDate - 3));
129 orderFromOneYearAgo_4.addOrderLine(paymentReceivedOrderLine);
130
131 orderFromTwoYearsAgo_1.setOrderDate(getTime(thisYear - 2, thisMonth, thisDate));
132 orderFromTwoYearsAgo_1.addOrderLine(paymentReceivedOrderLine);
133 orderFromTwoYearsAgo_2.setOrderDate(getTime(thisYear - 2, thisMonth, thisDate - 1));
134 orderFromTwoYearsAgo_2.addOrderLine(paymentReceivedOrderLine);
135
136 orderFromThreeYearsAgo_1.setOrderDate(getTime(thisYear - 3, thisMonth, thisDate));
137 orderFromThreeYearsAgo_1.addOrderLine(paymentReceivedOrderLine);
138 orderFromThreeYearsAgo_2.setOrderDate(getTime(thisYear - 3, thisMonth, thisDate - 1));
139 orderFromThreeYearsAgo_2.addOrderLine(paymentReceivedOrderLine);
140
141 aCustomerWithOneOrder.addOrder(orderFromThisYear_4);
142
143 aCustomerWithTwoOrders.addOrder(orderFromThisYear_1);
144 aCustomerWithTwoOrders.addOrder(orderFromThisYear_2);
145
146 aCustomerWithThreeOrders.addOrder(orderFromThisYear_1);
147 aCustomerWithThreeOrders.addOrder(orderFromThisYear_3);
148 aCustomerWithThreeOrders.addOrder(orderFromOneYearAgo_1);
149
150 aCustomerWithFourOrders.addOrder(orderFromThisYear_1);
151 aCustomerWithFourOrders.addOrder(orderFromThisYear_2);
152 aCustomerWithFourOrders.addOrder(orderFromOneYearAgo_1);
153 aCustomerWithFourOrders.addOrder(orderFromOneYearAgo_2);
154
155 aCustomerWithFiveOrders.addOrder(orderFromThisYear_1);
156 aCustomerWithFiveOrders.addOrder(orderFromThisYear_2);
157 aCustomerWithFiveOrders.addOrder(orderFromOneYearAgo_1);
158 aCustomerWithFiveOrders.addOrder(orderFromOneYearAgo_2);
159 aCustomerWithFiveOrders.addOrder(orderFromTwoYearsAgo_1);
160
161 aCustomerWithSixOrders.addOrder(orderFromThisYear_1);
162 aCustomerWithSixOrders.addOrder(orderFromThisYear_2);
163 aCustomerWithSixOrders.addOrder(orderFromOneYearAgo_1);
164 aCustomerWithSixOrders.addOrder(orderFromOneYearAgo_2);
165 aCustomerWithSixOrders.addOrder(orderFromTwoYearsAgo_1);
166 aCustomerWithSixOrders.addOrder(orderFromTwoYearsAgo_2);
167
168 aCustomerWithEightOrders.addOrder(orderFromThisYear_1);
169 aCustomerWithEightOrders.addOrder(orderFromThisYear_2);
170 aCustomerWithEightOrders.addOrder(orderFromThisYear_3);
171 aCustomerWithEightOrders.addOrder(orderFromThisYear_4);
172 aCustomerWithEightOrders.addOrder(orderFromOneYearAgo_1);
173 aCustomerWithEightOrders.addOrder(orderFromOneYearAgo_2);
174 aCustomerWithEightOrders.addOrder(orderFromTwoYearsAgo_1);
175 aCustomerWithEightOrders.addOrder(orderFromTwoYearsAgo_2);
176 }
177
178
179 static Date createOneYearAgoDate() {
180 return getTime(thisYear - 1, thisMonth, thisDate);
181 }
182
183
184 static Date createThirtyYearsAheadDate() {
185 return getTime(thisYear + 30, thisMonth, thisDate);
186 }
187
188
189 static Date createThirtyYearsAgoDate() {
190 return getTime(thisYear - 30, thisMonth, thisDate);
191 }
192
193
194 class SubclassedCustomer extends Customer {}
195
196
197 @Test
198 public void testAllKindOffObjectsWithoutImports() {
199 net.sourceforge.domian.specification.Specification spec = net.sourceforge.domian.specification.SpecificationFactory.allObjects();
200
201 assertFalse(spec.isSatisfiedBy(null));
202 assertTrue(spec.isSatisfiedBy(""));
203 assertTrue(spec.isSatisfiedBy(new Float("3.14")));
204 assertTrue(spec.isSatisfiedBy(new ShippingContainer(18, false)));
205 }
206
207
208 @Test
209 public void testAllKindOffObjects() {
210 Specification spec = allObjects();
211
212 assertFalse(spec.isSatisfiedBy(null));
213 assertTrue(spec.isSatisfiedBy(""));
214 assertTrue(spec.isSatisfiedBy(new Float("3.14")));
215 assertTrue(spec.isSatisfiedBy(new ShippingContainer(18, false)));
216 }
217
218
219 @Test
220 public void testTypeParameterizeddObjectsWithoutImports() {
221 Customer aCustomer = maleCustomer;
222 Customer anotherCustomer = femaleCustomer;
223
224 net.sourceforge.domian.specification.Specification<Customer> spec = createSpecificationFor(Customer.class);
225
226 assertFalse(spec.isSatisfiedBy(null));
227 assertTrue(spec.isSatisfiedBy(aCustomer));
228 assertTrue(spec.isSatisfiedBy(anotherCustomer));
229
230 }
231
232
233 @Test
234 public void testTypedParameterizedObjects() {
235 Customer aCustomer = maleCustomer;
236 Customer anotherCustomer = femaleCustomer;
237 SubclassedCustomer subclassedCustomer = new SubclassedCustomer();
238
239 Specification<Customer> spec = createSpecificationFor(Customer.class);
240
241 assertFalse(spec.isSatisfiedBy(null));
242 assertTrue(spec.isSatisfiedBy(aCustomer));
243 assertTrue(spec.isSatisfiedBy(anotherCustomer));
244 assertTrue(spec.isSatisfiedBy(subclassedCustomer));
245
246 }
247
248
249 @Test
250 public void testRawSpecifications() {
251 Customer aCustomer = maleCustomer;
252 Customer anotherCustomer = femaleCustomer;
253 SubclassedCustomer subclassedCustomer = new SubclassedCustomer();
254
255 Specification spec = createSpecificationFor(Customer.class);
256
257 assertFalse(spec.isSatisfiedBy(null));
258 assertTrue(spec.isSatisfiedBy(aCustomer));
259 assertTrue(spec.isSatisfiedBy(anotherCustomer));
260 assertTrue(spec.isSatisfiedBy(subclassedCustomer));
261 assertFalse(spec.isSatisfiedBy(new Date()));
262 }
263
264
265 @Test
266 public void testEquality() {
267 Specification<Long> long42 = equalTo(42L);
268 Specification<Date> oneYearAgo = atTheSameTimeAs(createOneYearAgoDate());
269 }
270
271
272 @Test
273 public void testRegularExpressionMatcherStringSpecification() {
274 Specification<String> shorterThanThree = matches(".{0," + (2) + "}");
275 assertFalse(shorterThanThree.isSatisfiedBy(null));
276 assertTrue(shorterThanThree.isSatisfiedBy(""));
277 assertTrue(shorterThanThree.isSatisfiedBy("1"));
278 assertTrue(shorterThanThree.isSatisfiedBy("12"));
279 assertFalse(shorterThanThree.isSatisfiedBy("123"));
280 assertFalse(shorterThanThree.isSatisfiedBy("1 2 3 4 5 6 7 9"));
281 }
282
283
284 @Test
285 public void testWildcardExpressionMatcherStringSpecification() {
286 Specification<String> startsAndEndsWithA_AtLeastSevenCharsLong = matchesWildcardExpression("A?????*a");
287 assertFalse(startsAndEndsWithA_AtLeastSevenCharsLong.isSatisfiedBy(null));
288 assertFalse(startsAndEndsWithA_AtLeastSevenCharsLong.isSatisfiedBy("Aloha"));
289 assertTrue(startsAndEndsWithA_AtLeastSevenCharsLong.isSatisfiedBy("Arizona"));
290 assertTrue(startsAndEndsWithA_AtLeastSevenCharsLong.isSatisfiedBy("Australia"));
291 assertFalse(startsAndEndsWithA_AtLeastSevenCharsLong.isSatisfiedBy("australia"));
292 }
293
294
295 @Test
296 public void testComparison() {
297 Specification<Integer> greaterThan10 = greaterThan(10);
298 Specification<Date> lessThanOneYearAgo = after(createOneYearAgoDate());
299 }
300
301
302 @Test
303 public void testDefaultValue() {
304 Specification<Number> defaultNumber = createDefaultNumberSpecification();
305 assertTrue(defaultNumber.isSatisfiedBy(0));
306 assertTrue(defaultNumber.isSatisfiedBy(0L));
307 assertTrue(defaultNumber.isSatisfiedBy(0.0));
308 assertTrue(defaultNumber.isSatisfiedBy(0.0d));
309 assertFalse(defaultNumber.isSatisfiedBy(-1));
310 assertFalse(defaultNumber.isSatisfiedBy(1234567890123L));
311 assertFalse(defaultNumber.isSatisfiedBy(0.1));
312 assertFalse(defaultNumber.isSatisfiedBy(0.164537d));
313
314 Specification<Number> notDefaultNumber = not(defaultNumber);
315 assertFalse(notDefaultNumber.isSatisfiedBy(0));
316 assertFalse(notDefaultNumber.isSatisfiedBy(0L));
317 assertFalse(notDefaultNumber.isSatisfiedBy(0.0));
318 assertFalse(notDefaultNumber.isSatisfiedBy(0.0d));
319 assertTrue(notDefaultNumber.isSatisfiedBy(-1));
320 assertTrue(notDefaultNumber.isSatisfiedBy(1234567890123L));
321 assertTrue(notDefaultNumber.isSatisfiedBy(0.1));
322 assertTrue(notDefaultNumber.isSatisfiedBy(0.164537d));
323 }
324
325
326 @Test
327 public void testDateStringSpecification() {
328 Specification<String> spec = isDate("ddMMyyyy");
329 assertFalse(spec.isSatisfiedBy("01-01-2007"));
330 assertFalse(spec.isSatisfiedBy("32032007"));
331 assertFalse(spec.isSatisfiedBy("01132007"));
332 assertFalse(spec.isSatisfiedBy("29022007"));
333 assertTrue(spec.isSatisfiedBy("01012007"));
334 assertTrue(spec.isSatisfiedBy("01012007"));
335
336 Specification<Date> dateSpec = before("2008-06-07");
337 assertFalse(dateSpec.isSatisfiedBy(getTime(2008, 6, 7)));
338 assertTrue(dateSpec.isSatisfiedBy(getTime(2008, 6, 6)));
339 }
340
341
342 enum Colour {
343 BLACK, WHITE
344 }
345
346
347 @Test
348 public void testEnumNameStringSpecification() {
349 Specification<String> spec = isEnum(Colour.class);
350 assertFalse(spec.isSatisfiedBy(null));
351 assertFalse(spec.isSatisfiedBy("01012007"));
352 assertFalse(spec.isSatisfiedBy("SHADY"));
353 assertTrue(spec.isSatisfiedBy("WHITE"));
354 }
355
356
357 @Test
358 public void testSimpleCompositeSpecification() {
359 Specification<Date> lessThanThirtyYearsAgo = isAfter(createThirtyYearsAgoDate());
360 Specification<Date> lessThanThirtyYearsAhead = isBefore(createThirtyYearsAheadDate());
361
362 Specification<Date> plusMinusThirtyYears = lessThanThirtyYearsAgo.and(lessThanThirtyYearsAhead);
363
364 assertTrue(plusMinusThirtyYears.isSatisfiedBy(new Date()));
365 assertTrue(plusMinusThirtyYears.isSatisfiedBy(getTime(1990, 7, 30)));
366 assertTrue(plusMinusThirtyYears.isSatisfiedBy(getTime(2037, 7, 29)));
367 assertFalse(plusMinusThirtyYears.isSatisfiedBy(getTime(1977, 7, 30)));
368 assertFalse(plusMinusThirtyYears.isSatisfiedBy(getTime(2050, 7, 30)));
369
370 plusMinusThirtyYears = is(lessThanThirtyYearsAgo).and(lessThanThirtyYearsAhead);
371
372 assertTrue(plusMinusThirtyYears.isSatisfiedBy(new Date()));
373 assertTrue(plusMinusThirtyYears.isSatisfiedBy(getTime(1990, 7, 30)));
374 assertTrue(plusMinusThirtyYears.isSatisfiedBy(getTime(2037, 7, 29)));
375 assertFalse(plusMinusThirtyYears.isSatisfiedBy(getTime(1977, 7, 30)));
376 assertFalse(plusMinusThirtyYears.isSatisfiedBy(getTime(2050, 7, 30)));
377
378 plusMinusThirtyYears = both(lessThanThirtyYearsAgo, lessThanThirtyYearsAhead);
379
380 assertTrue(plusMinusThirtyYears.isSatisfiedBy(new Date()));
381 assertTrue(plusMinusThirtyYears.isSatisfiedBy(getTime(1990, 7, 30)));
382 assertTrue(plusMinusThirtyYears.isSatisfiedBy(getTime(2037, 7, 29)));
383 assertFalse(plusMinusThirtyYears.isSatisfiedBy(getTime(1977, 7, 30)));
384 assertFalse(plusMinusThirtyYears.isSatisfiedBy(getTime(2050, 7, 30)));
385 }
386
387
388 @Test
389 public void testCompositeSpecifications() {
390 Date thirtyYearsAgo = createThirtyYearsAgoDate();
391 Date thirtyYearsAhead = createThirtyYearsAheadDate();
392
393 Specification<Date> lessThanThirtyYearsAgo = isAfter(thirtyYearsAgo);
394 Specification<Date> lessThanThirtyYearsAhead = isBefore(thirtyYearsAhead);
395
396 Specification<Date> plusMinusThirtyYears = is(lessThanThirtyYearsAgo).and(lessThanThirtyYearsAhead);
397 assertFalse(plusMinusThirtyYears.isSatisfiedBy(null));
398 assertTrue(plusMinusThirtyYears.isSatisfiedBy(new Date()));
399 assertTrue(plusMinusThirtyYears.isSatisfiedBy(getTime(1990, 7, 30)));
400 assertTrue(plusMinusThirtyYears.isSatisfiedBy(getTime(2037, 7, 29)));
401 assertFalse(plusMinusThirtyYears.isSatisfiedBy(getTime(1977, 7, 30)));
402 assertFalse(plusMinusThirtyYears.isSatisfiedBy(getTime(2050, 7, 30)));
403
404 plusMinusThirtyYears = both(lessThanThirtyYearsAgo, lessThanThirtyYearsAhead);
405 assertFalse(plusMinusThirtyYears.isSatisfiedBy(null));
406 assertTrue(plusMinusThirtyYears.isSatisfiedBy(new Date()));
407 assertTrue(plusMinusThirtyYears.isSatisfiedBy(getTime(1990, 7, 30)));
408 assertTrue(plusMinusThirtyYears.isSatisfiedBy(getTime(2037, 7, 29)));
409 assertFalse(plusMinusThirtyYears.isSatisfiedBy(getTime(1977, 7, 30)));
410 assertFalse(plusMinusThirtyYears.isSatisfiedBy(getTime(2050, 7, 30)));
411 }
412
413
414 @Test
415 public void testNotAssosiativeSpecificationBuilding() {
416 Date oneYearAgo = getTime(thisYear - 1, thisMonth, thisDate);
417 Date oneYearAndOneMonthAgo = getTime(thisYear - 1, thisMonth - 1, thisDate);
418 Date tenYearsAgo = getTime(thisYear - 10, thisMonth, thisDate);
419 Date sixteenYearsAgo = getTime(thisYear - 16, thisMonth, thisDate);
420
421 Customer aChildMaleCustomer = new Customer().gender(FEMALE).birthDate(tenYearsAgo).membershipDate(today);
422 Customer aTeenageMaleCustomer = new Customer().gender(MALE).birthDate(sixteenYearsAgo).membershipDate(today);
423 Customer aMaleCustomer = new Customer().gender(MALE).birthDate(getTime(1975, 10, 10)).membershipDate(today);
424 Customer aChildFemaleCustomer = new Customer().gender(FEMALE).birthDate(tenYearsAgo).membershipDate(today);
425 Customer aTeenageFemaleCustomer = new Customer().gender(FEMALE).birthDate(sixteenYearsAgo).membershipDate(today);
426 Customer aFreshFemaleCustomer = new Customer().gender(FEMALE).birthDate(getTime(1975, 10, 10)).membershipDate(today);
427 Customer aVeteranFemaleCustomer = new Customer().gender(FEMALE).birthDate(getTime(1975, 10, 10)).membershipDate(oneYearAndOneMonthAgo);
428 Customer aVeteranChildFemaleCustomer = new Customer().gender(FEMALE).birthDate(tenYearsAgo).membershipDate(oneYearAndOneMonthAgo);
429
430 Specification<Customer> spec = specify(Customer.class)
431 .where("gender", is(FEMALE))
432 .and("membershipDate", isBefore(oneYearAgo))
433 .or("gender", is(MALE))
434 .and("birthDate", is(not(afterOrAtTheSameTimeAs(tenYearsAgo))));
435
436 assertTrue(spec.isSatisfiedBy(aVeteranFemaleCustomer));
437 assertFalse(spec.isSatisfiedBy(aFreshFemaleCustomer));
438 assertTrue(spec.isSatisfiedBy(aMaleCustomer));
439 assertFalse(spec.isSatisfiedBy(aTeenageFemaleCustomer));
440 assertTrue(spec.isSatisfiedBy(aTeenageMaleCustomer));
441 assertFalse(spec.isSatisfiedBy(aChildFemaleCustomer));
442 assertFalse(spec.isSatisfiedBy(aChildMaleCustomer));
443
444 Specification<Customer> femaleCustomer = specify(Customer.class).where("gender", is(FEMALE));
445 Specification<Customer> maleCustomer = specify(Customer.class).where("gender", is(MALE));
446 Specification<Customer> veteranCustomer = specify(Customer.class).where("membershipDate", isBefore(oneYearAgo));
447 Specification<Customer> childCustomer = specify(Customer.class).where("birthDate", isAfterOrAtTheSameTimeAs(tenYearsAgo));
448
449 Specification<Customer> notChildCustomer = not(a(childCustomer));
450
451 spec = ((both(femaleCustomer, veteranCustomer)).or(a(maleCustomer))).and(not(a(childCustomer)));
452
453 assertTrue(spec.isSatisfiedBy(aVeteranFemaleCustomer));
454 assertFalse(spec.isSatisfiedBy(aFreshFemaleCustomer));
455 assertTrue(spec.isSatisfiedBy(aMaleCustomer));
456 assertFalse(spec.isSatisfiedBy(aTeenageFemaleCustomer));
457 assertTrue(spec.isSatisfiedBy(aTeenageMaleCustomer));
458 assertFalse(spec.isSatisfiedBy(aChildFemaleCustomer));
459 assertFalse(spec.isSatisfiedBy(aChildMaleCustomer));
460
461
462 spec = both(femaleCustomer, veteranCustomer).or(maleCustomer).and(not(childCustomer));
463
464 assertTrue(spec.isSatisfiedBy(aVeteranFemaleCustomer));
465 assertFalse(spec.isSatisfiedBy(aFreshFemaleCustomer));
466 assertTrue(spec.isSatisfiedBy(aMaleCustomer));
467 assertFalse(spec.isSatisfiedBy(aTeenageFemaleCustomer));
468 assertTrue(spec.isSatisfiedBy(aTeenageMaleCustomer));
469 assertFalse(spec.isSatisfiedBy(aChildFemaleCustomer));
470 assertFalse(spec.isSatisfiedBy(aChildMaleCustomer));
471
472
473 spec = a(veteranCustomer).or(maleCustomer).and(not(childCustomer));
474
475 assertTrue(spec.isSatisfiedBy(aVeteranFemaleCustomer));
476 assertFalse(spec.isSatisfiedBy(aFreshFemaleCustomer));
477 assertTrue(spec.isSatisfiedBy(aMaleCustomer));
478 assertFalse(spec.isSatisfiedBy(aTeenageFemaleCustomer));
479 assertTrue(spec.isSatisfiedBy(aTeenageMaleCustomer));
480 assertFalse(spec.isSatisfiedBy(aChildFemaleCustomer));
481 assertFalse(spec.isSatisfiedBy(aChildMaleCustomer));
482 assertFalse(spec.isSatisfiedBy(aVeteranChildFemaleCustomer));
483
484
485 spec = maleCustomer.and(not(childCustomer)).or(veteranCustomer);
486
487 assertTrue(spec.isSatisfiedBy(aVeteranFemaleCustomer));
488 assertFalse(spec.isSatisfiedBy(aFreshFemaleCustomer));
489 assertTrue(spec.isSatisfiedBy(aMaleCustomer));
490 assertFalse(spec.isSatisfiedBy(aTeenageFemaleCustomer));
491 assertTrue(spec.isSatisfiedBy(aTeenageMaleCustomer));
492 assertFalse(spec.isSatisfiedBy(aChildFemaleCustomer));
493 assertFalse(spec.isSatisfiedBy(aChildMaleCustomer));
494 assertTrue(spec.isSatisfiedBy(aVeteranChildFemaleCustomer));
495
496
497 spec = a(maleCustomer).and(not(a(childCustomer))).or(a(veteranCustomer));
498
499 assertTrue(spec.isSatisfiedBy(aVeteranFemaleCustomer));
500 assertFalse(spec.isSatisfiedBy(aFreshFemaleCustomer));
501 assertTrue(spec.isSatisfiedBy(aMaleCustomer));
502 assertFalse(spec.isSatisfiedBy(aTeenageFemaleCustomer));
503 assertTrue(spec.isSatisfiedBy(aTeenageMaleCustomer));
504 assertFalse(spec.isSatisfiedBy(aChildFemaleCustomer));
505 assertFalse(spec.isSatisfiedBy(aChildMaleCustomer));
506 assertTrue(spec.isSatisfiedBy(aVeteranChildFemaleCustomer));
507 }
508
509
510 @Test
511 public void testCollectionSpecification_1() {
512
513 Specification<Customer> goodCustomers = all(Customer.class).where("orders", haveSizeOf(atLeast(4)));
514
515 assertFalse(goodCustomers.isSatisfiedBy(null));
516 assertFalse(goodCustomers.isSatisfiedBy(aCustomerWithNoOrders));
517 assertFalse(goodCustomers.isSatisfiedBy(aCustomerWithOneOrder));
518 assertFalse(goodCustomers.isSatisfiedBy(aCustomerWithTwoOrders));
519 assertFalse(goodCustomers.isSatisfiedBy(aCustomerWithThreeOrders));
520 assertTrue(goodCustomers.isSatisfiedBy(aCustomerWithFourOrders));
521 assertTrue(goodCustomers.isSatisfiedBy(aCustomerWithFiveOrders));
522 assertTrue(goodCustomers.isSatisfiedBy(aCustomerWithSixOrders));
523 assertTrue(goodCustomers.isSatisfiedBy(aCustomerWithEightOrders));
524 }
525
526
527 @Test
528 public void testCollectionSpecification_2_1() {
529
530 final Date beginningOfNextYear = getTime(thisYear + 1);
531 final Date beginningOfThisYear = getTime(thisYear);
532 final Date beginningOfLastYear = getTime(thisYear - 1);
533 final Date beginningOfNextToLastYear = getTime(thisYear - 2);
534 final Date beginningOfNextToNextToLastYear = getTime(thisYear - 3);
535 final Date beginningOfNextToNextToNextToLastYear = getTime(thisYear - 4);
536 final Date beginningOfNextToNextToNextToNextToLastYear = getTime(thisYear - 5);
537
538 final Specification<Date> beforeThisYear = isBefore(beginningOfThisYear);
539 final Specification<Date> beforeLastYear = isBefore(beginningOfLastYear);
540 final Specification<Date> beforeNextToLastYear = isBefore(beginningOfNextToLastYear);
541 final Specification<Date> beforeNextToNextToLastYear = isBefore(beginningOfNextToNextToLastYear);
542 final Specification<Date> beforeNextToNextToNextToLastYear = isBefore(beginningOfNextToNextToNextToLastYear);
543 final Specification<Date> beforeNextToNextToNextToNextToLastYear = isBefore(beginningOfNextToNextToNextToNextToLastYear);
544
545 final Specification<Date> afterThisYear = isAfterOrAtTheSameTimeAs(beginningOfNextYear);
546 final Specification<Date> afterLastYear = isAfterOrAtTheSameTimeAs(beginningOfThisYear);
547 final Specification<Date> afterNextToLastYear = isAfterOrAtTheSameTimeAs(beginningOfLastYear);
548 final Specification<Date> afterNextToNextToLastYear = isAfterOrAtTheSameTimeAs(beginningOfNextToLastYear);
549 final Specification<Date> afterNextToNextToNextToLastYear = isAfterOrAtTheSameTimeAs(beginningOfNextToNextToLastYear);
550 final Specification<Date> afterNextToNextToNextToNextToLastYear = isAfterOrAtTheSameTimeAs(beginningOfNextToNextToNextToLastYear);
551
552 final Specification<Date> duringThisYear = is(not(beforeThisYear)).and(not(afterThisYear));
553 final Specification<Date> duringLastYear = is(beforeThisYear).and(afterNextToLastYear);
554 final Specification<Date> duringNextToLastYear = is(beforeLastYear).and(afterNextToNextToLastYear);
555 final Specification<Date> duringNextToNextToLastYear = is(beforeNextToLastYear).and(afterNextToNextToNextToLastYear);
556 final Specification<Date> duringNextToNextToNextToLastYear = is(beforeNextToNextToLastYear).and(afterNextToNextToNextToNextToLastYear);
557
558 final Specification<Order> ordersFromThisYear = all(Order.class).where("orderDate", isFrom(duringThisYear));
559 assertTrue(ordersFromThisYear.isSatisfiedBy(orderFromThisYear_1));
560 assertTrue(ordersFromThisYear.isSatisfiedBy(orderFromThisYear_2));
561 assertFalse(ordersFromThisYear.isSatisfiedBy(orderFromOneYearAgo_1));
562 assertFalse(ordersFromThisYear.isSatisfiedBy(orderFromTwoYearsAgo_1));
563 final Specification<Order> ordersFromLastYear = all(Order.class).where("orderDate", isFrom(duringLastYear));
564 assertFalse(ordersFromLastYear.isSatisfiedBy(orderFromThisYear_1));
565 assertFalse(ordersFromLastYear.isSatisfiedBy(orderFromThisYear_2));
566 assertTrue(ordersFromLastYear.isSatisfiedBy(orderFromOneYearAgo_1));
567 assertFalse(ordersFromLastYear.isSatisfiedBy(orderFromTwoYearsAgo_1));
568 final Specification<Order> ordersFromNextToLastYear = all(Order.class).where("orderDate", isFrom(duringNextToLastYear));
569 assertFalse(ordersFromNextToLastYear.isSatisfiedBy(orderFromThisYear_1));
570 assertFalse(ordersFromNextToLastYear.isSatisfiedBy(orderFromThisYear_2));
571 assertFalse(ordersFromNextToLastYear.isSatisfiedBy(orderFromOneYearAgo_1));
572 assertTrue(ordersFromNextToLastYear.isSatisfiedBy(orderFromTwoYearsAgo_1));
573
574 CompositeSpecification<Customer> goodCustomers = all(Customer.class)
575 .where("orders", include(atLeast(2), ordersFromThisYear));
576 assertFalse(goodCustomers.isSatisfiedBy(null));
577 assertFalse(goodCustomers.isSatisfiedBy(aCustomerWithNoOrders));
578 assertFalse(goodCustomers.isSatisfiedBy(aCustomerWithOneOrder));
579 assertTrue(goodCustomers.isSatisfiedBy(aCustomerWithTwoOrders));
580 assertTrue(goodCustomers.isSatisfiedBy(aCustomerWithThreeOrders));
581 assertTrue(goodCustomers.isSatisfiedBy(aCustomerWithFourOrders));
582 assertTrue(goodCustomers.isSatisfiedBy(aCustomerWithFiveOrders));
583 assertTrue(goodCustomers.isSatisfiedBy(aCustomerWithSixOrders));
584 assertTrue(goodCustomers.isSatisfiedBy(aCustomerWithEightOrders));
585
586 goodCustomers = goodCustomers.and("orders", include(atLeast(2), ordersFromLastYear));
587 assertFalse(goodCustomers.isSatisfiedBy(null));
588 assertFalse(goodCustomers.isSatisfiedBy(aCustomerWithNoOrders));
589 assertFalse(goodCustomers.isSatisfiedBy(aCustomerWithOneOrder));
590 assertFalse(goodCustomers.isSatisfiedBy(aCustomerWithTwoOrders));
591 assertFalse(goodCustomers.isSatisfiedBy(aCustomerWithThreeOrders));
592 assertTrue(goodCustomers.isSatisfiedBy(aCustomerWithFourOrders));
593 assertTrue(goodCustomers.isSatisfiedBy(aCustomerWithFiveOrders));
594 assertTrue(goodCustomers.isSatisfiedBy(aCustomerWithSixOrders));
595 assertTrue(goodCustomers.isSatisfiedBy(aCustomerWithEightOrders));
596
597 goodCustomers = goodCustomers.and("orders", include(atLeast(2), ordersFromNextToLastYear));
598 assertFalse(goodCustomers.isSatisfiedBy(null));
599 assertFalse(goodCustomers.isSatisfiedBy(aCustomerWithNoOrders));
600 assertFalse(goodCustomers.isSatisfiedBy(aCustomerWithOneOrder));
601 assertFalse(goodCustomers.isSatisfiedBy(aCustomerWithTwoOrders));
602 assertFalse(goodCustomers.isSatisfiedBy(aCustomerWithThreeOrders));
603 assertFalse(goodCustomers.isSatisfiedBy(aCustomerWithFourOrders));
604 assertFalse(goodCustomers.isSatisfiedBy(aCustomerWithFiveOrders));
605 assertTrue(goodCustomers.isSatisfiedBy(aCustomerWithSixOrders));
606 assertTrue(goodCustomers.isSatisfiedBy(aCustomerWithEightOrders));
607 }
608
609
610 @Test
611 public void testCollectionSpecification_2() {
612 Date beginningOfNextYear = getTime(thisYear + 1);
613 Date beginningOfThisYear = getTime(thisYear);
614 Date beginningOfLastYear = getTime(thisYear - 1);
615 Date beginningOfTwoYearsAgo = getTime(thisYear - 2);
616
617 Specification<Date> afterThisYear = isAfterOrAtTheSameTimeAs(beginningOfNextYear);
618 Specification<Date> beforeThisYear = isBefore(beginningOfThisYear);
619 Specification<Date> beforeLastYear = isBefore(beginningOfLastYear);
620 Specification<Date> beforeTheYearBeforeLastYear = isBefore(beginningOfTwoYearsAgo);
621
622 Specification<Date> duringThisYear = is(not(beforeThisYear)).and(not(afterThisYear));
623 Specification<Date> duringLastYear = is(not(beforeLastYear)).and(beforeThisYear);
624 Specification<Date> duringTheYearBeforeLastYear = is(not(beforeTheYearBeforeLastYear)).and(beforeLastYear);
625
626 Specification<Order> ordersFromThisYear = all(Order.class).where("orderDate", isFrom(duringThisYear));
627 Specification<Order> ordersFromLastYear = all(Order.class).where("orderDate", isFrom(duringLastYear));
628 Specification<Order> ordersFromTheYearBeforeLastYear = all(Order.class).where("orderDate", isFrom(duringTheYearBeforeLastYear));
629
630 CompositeSpecification<Customer> goodCustomers = all(Customer.class)
631 .where("orders", include(atLeast(2), ordersFromThisYear))
632 .and("orders", include(atLeast(2), ordersFromLastYear))
633 .and("orders", include(atLeast(2), ordersFromTheYearBeforeLastYear));
634 assertFalse(goodCustomers.isSatisfiedBy(null));
635 assertFalse(goodCustomers.isSatisfiedBy(aCustomerWithNoOrders));
636 assertFalse(goodCustomers.isSatisfiedBy(aCustomerWithOneOrder));
637 assertFalse(goodCustomers.isSatisfiedBy(aCustomerWithTwoOrders));
638 assertFalse(goodCustomers.isSatisfiedBy(aCustomerWithThreeOrders));
639 assertFalse(goodCustomers.isSatisfiedBy(aCustomerWithFourOrders));
640 assertFalse(goodCustomers.isSatisfiedBy(aCustomerWithFiveOrders));
641 assertTrue(goodCustomers.isSatisfiedBy(aCustomerWithSixOrders));
642 assertTrue(goodCustomers.isSatisfiedBy(aCustomerWithEightOrders));
643
644
645 Date aMonthAgo = getTime(thisYear, thisMonth - 1, thisDate);
646
647 Specification<OrderLine> cancelledOrderLines = all(OrderLine.class).where("cancelled", isTrue());
648 Specification<OrderLine> pendingOrderLines = all(OrderLine.class).where("paymentReceived", isFalse());
649
650 Specification<Order> badOrders = all(Order.class).where("orderLines", includeAPercentageOf(atLeast(25), cancelledOrderLines));
651 Specification<Order> pendingOrders = all(Order.class).where("orderDate", isBefore(aMonthAgo)).and("orderLines", includeAPercentageOf(atLeast(50), pendingOrderLines));
652
653
654 Specification<Customer> badCustomers = all(Customer.class)
655 .where("orders", not(includeAPercentageOf(atMost(20), badOrders)))
656 .or("orders", includeAPercentageOf(moreThan(10), pendingOrders));
657
658 goodCustomers = goodCustomers.and(not(badCustomers));
659
660 assertFalse(goodCustomers.isSatisfiedBy(null));
661 assertFalse(goodCustomers.isSatisfiedBy(aCustomerWithNoOrders));
662 assertFalse(goodCustomers.isSatisfiedBy(aCustomerWithOneOrder));
663 assertFalse(goodCustomers.isSatisfiedBy(aCustomerWithTwoOrders));
664 assertFalse(goodCustomers.isSatisfiedBy(aCustomerWithThreeOrders));
665 assertFalse(goodCustomers.isSatisfiedBy(aCustomerWithFourOrders));
666 assertFalse(goodCustomers.isSatisfiedBy(aCustomerWithFiveOrders));
667 assertTrue(goodCustomers.isSatisfiedBy(aCustomerWithSixOrders));
668 assertFalse(goodCustomers.isSatisfiedBy(aCustomerWithEightOrders));
669
670 badCustomers = all(Customer.class)
671 .where("orders", includeAPercentageOf(moreThan(20), badOrders))
672 .or("orders", includeAPercentageOf(moreThan(10), pendingOrders));
673
674 goodCustomers = goodCustomers.and(not(badCustomers));
675
676 assertFalse(goodCustomers.isSatisfiedBy(null));
677 assertFalse(goodCustomers.isSatisfiedBy(aCustomerWithNoOrders));
678 assertFalse(goodCustomers.isSatisfiedBy(aCustomerWithOneOrder));
679 assertFalse(goodCustomers.isSatisfiedBy(aCustomerWithTwoOrders));
680 assertFalse(goodCustomers.isSatisfiedBy(aCustomerWithThreeOrders));
681 assertFalse(goodCustomers.isSatisfiedBy(aCustomerWithFourOrders));
682 assertFalse(goodCustomers.isSatisfiedBy(aCustomerWithFiveOrders));
683 assertTrue(goodCustomers.isSatisfiedBy(aCustomerWithSixOrders));
684 assertFalse(goodCustomers.isSatisfiedBy(aCustomerWithEightOrders));
685
686 Specification<OrderLine> activeOrderLines = all(OrderLine.class).where("cancelled", isFalse());
687 Specification<Order> consistentOrders = all(Order.class).where("orderLines", includeAPercentageOf(atLeast(75), not(cancelledOrderLines)));
688
689 badCustomers = all(Customer.class)
690 .where("orders", includeAPercentageOf(not(moreThan(80)), consistentOrders))
691 .or("orders", includeAPercentageOf(moreThan(10), pendingOrders));
692 goodCustomers = goodCustomers.and(not(badCustomers));
693
694 assertFalse(goodCustomers.isSatisfiedBy(null));
695 assertFalse(goodCustomers.isSatisfiedBy(aCustomerWithNoOrders));
696 assertFalse(goodCustomers.isSatisfiedBy(aCustomerWithOneOrder));
697 assertFalse(goodCustomers.isSatisfiedBy(aCustomerWithTwoOrders));
698 assertFalse(goodCustomers.isSatisfiedBy(aCustomerWithThreeOrders));
699 assertFalse(goodCustomers.isSatisfiedBy(aCustomerWithFourOrders));
700 assertFalse(goodCustomers.isSatisfiedBy(aCustomerWithFiveOrders));
701 assertTrue(goodCustomers.isSatisfiedBy(aCustomerWithSixOrders));
702 assertFalse(goodCustomers.isSatisfiedBy(aCustomerWithEightOrders));
703 }
704
705
706
707 @Test
708 public void testOrdersWithGoodCustomers() {}
709 }