1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package net.sourceforge.domian.specification;
17
18
19 import java.util.Date;
20
21 import org.junit.Test;
22
23 import net.sourceforge.domian.test.domain.Customer;
24 import net.sourceforge.domian.test.domain.Order;
25 import net.sourceforge.domian.test.domain.VipCustomer;
26
27 import static net.sourceforge.domian.specification.SpecificationFactory.after;
28 import static net.sourceforge.domian.specification.SpecificationFactory.all;
29 import static net.sourceforge.domian.specification.SpecificationFactory.allInstancesOfType;
30 import static net.sourceforge.domian.specification.SpecificationFactory.before;
31 import static net.sourceforge.domian.specification.SpecificationFactory.both;
32 import static net.sourceforge.domian.specification.SpecificationFactory.either;
33 import static net.sourceforge.domian.specification.SpecificationFactory.empty;
34 import static net.sourceforge.domian.specification.SpecificationFactory.equalTo;
35 import static net.sourceforge.domian.specification.SpecificationFactory.equalsIgnoringCase;
36 import static net.sourceforge.domian.specification.SpecificationFactory.instanceOf;
37 import static net.sourceforge.domian.specification.SpecificationFactory.is;
38 import static net.sourceforge.domian.specification.SpecificationFactory.isAfter;
39 import static net.sourceforge.domian.specification.SpecificationFactory.isAfterOrAtTheSameTimeAs;
40 import static net.sourceforge.domian.specification.SpecificationFactory.isBefore;
41 import static net.sourceforge.domian.specification.SpecificationFactory.isBeforeOrAtTheSameTimeAs;
42 import static net.sourceforge.domian.specification.SpecificationFactory.isEqualTo;
43 import static net.sourceforge.domian.specification.SpecificationFactory.like;
44 import static net.sourceforge.domian.specification.SpecificationFactory.not;
45 import static net.sourceforge.domian.specification.SpecificationFactory.oneOf;
46 import static net.sourceforge.domian.specification.SpecificationFactory.shouldBe;
47 import static net.sourceforge.domian.test.domain.Testdata.theDayBeforeYesterday;
48 import static net.sourceforge.domian.test.domain.Testdata.thisDate;
49 import static net.sourceforge.domian.test.domain.Testdata.thisMonth;
50 import static net.sourceforge.domian.test.domain.Testdata.thisYear;
51 import static net.sourceforge.domian.test.domain.Testdata.tomorrow;
52 import static net.sourceforge.domian.test.domain.Testdata.yesterday;
53 import static net.sourceforge.domian.util.DateUtils.getTime;
54 import static org.junit.Assert.assertEquals;
55 import static org.junit.Assert.assertFalse;
56 import static org.junit.Assert.assertNotSame;
57 import static org.junit.Assert.assertSame;
58 import static org.junit.Assert.assertTrue;
59 import static org.junit.Assert.fail;
60
61
62 public class IsDisjointWith_CompositeSpecifications_Test {
63
64 @Test
65 public void shouldNotAcceptNull_compositeSpecification() {
66 try {
67 all(Customer.class).isDisjointWith(null);
68 fail("Should have thrown exception");
69
70 } catch (IllegalArgumentException e) {
71 String expectedMessage = "Specification parameter cannot be null";
72 String actualMessage = e.getMessage();
73 assertEquals(expectedMessage, actualMessage);
74 }
75 }
76
77
78 @Test
79 public void specificationsOfDifferentTypesAreAlwaysDisjoint() {
80 assertTrue(all(Customer.class).isDisjointWith(equalTo(42)));
81 assertTrue(all(Order.class).isDisjointWith(after(tomorrow)));
82 assertTrue(all(Customer.class).isDisjointWith(all(Order.class)));
83 assertTrue(all(Order.class).isDisjointWith(all(Customer.class)));
84 }
85
86
87 @Test
88 public void subtypesAreNotDisjoint() {
89 assertTrue(all(Customer.class).isGeneralizationOf(all(VipCustomer.class)));
90
91 assertFalse(all(Customer.class).isDisjointWith(all(VipCustomer.class)));
92
93
94 assertTrue(all(VipCustomer.class).isSpecialCaseOf(all(Customer.class)));
95 assertFalse(all(VipCustomer.class).isDisjointWith(all(Customer.class)));
96
97 Specification<Customer> customersWithOrders = all(Customer.class).where("orders", is(not(empty())));
98 Specification<VipCustomer> vipCustomersWithOrders = all(VipCustomer.class).where("orders", is(not(empty())));
99
100 assertTrue(customersWithOrders.isGeneralizationOf(vipCustomersWithOrders));
101
102 assertFalse(customersWithOrders.isDisjointWith(vipCustomersWithOrders));
103
104
105 assertTrue(vipCustomersWithOrders.isSpecialCaseOf(customersWithOrders));
106 assertFalse(vipCustomersWithOrders.isDisjointWith(customersWithOrders));
107 }
108
109
110 @Test
111 public void shouldNotBeReflexive() {
112 assertFalse(all(Customer.class).isDisjointWith(all(Customer.class)));
113
114 Specification<?> orderOrCustomer = either(instanceOf(Customer.class), instanceOf(Order.class));
115 assertFalse(orderOrCustomer.isDisjointWith(orderOrCustomer));
116
117 Specification<Customer> customerNamedTommy = all(Customer.class).where("name", isEqualTo("Tommy"));
118 Specification<VipCustomer> vipCustomerNamedTommy = all(VipCustomer.class).where("name", isEqualTo("Tommy"));
119 assertFalse(customerNamedTommy.isDisjointWith(customerNamedTommy));
120 assertFalse(vipCustomerNamedTommy.isDisjointWith(vipCustomerNamedTommy));
121 assertFalse(customerNamedTommy.isDisjointWith(vipCustomerNamedTommy));
122 assertFalse(vipCustomerNamedTommy.isDisjointWith(customerNamedTommy));
123 }
124
125
126 @Test
127 public void equalDisjointMemberSpecificationsMeansDisjoint() {
128 Specification<Customer> customersNamedTommy = all(Customer.class).where("name", isEqualTo("Tommy"));
129 Specification<Customer> customersNamedJasper = all(Customer.class).where("name", isEqualTo("Jasper"));
130 assertFalse(customersNamedTommy.isDisjointWith(customersNamedTommy));
131 assertTrue(customersNamedTommy.isDisjointWith(customersNamedJasper));
132 assertTrue(customersNamedJasper.isDisjointWith(customersNamedTommy));
133
134 Specification<Customer> customersNamedWithNameEndingWithLa = all(Customer.class).where("name", like("*la"));
135 Specification<Customer> customersNamedT_mmy = all(Customer.class).where("name", like("T?mmy"));
136 assertTrue(customersNamedT_mmy.isDisjointWith(customersNamedWithNameEndingWithLa));
137 assertTrue(customersNamedWithNameEndingWithLa.isDisjointWith(customersNamedT_mmy));
138
139 Specification<Customer> customersNamedTimmyIgnoringCase = all(Customer.class).where("name", equalsIgnoringCase("timmy"));
140 assertTrue(customersNamedTimmyIgnoringCase.isDisjointWith(customersNamedWithNameEndingWithLa));
141 assertTrue(customersNamedWithNameEndingWithLa.isDisjointWith(customersNamedTimmyIgnoringCase));
142
143 customersNamedTommy = all(Customer.class).where("name", isEqualTo("Tommy")).and("membershipDate", is(yesterday));
144 customersNamedJasper = all(Customer.class).where("name", isEqualTo("Jasper")).and("membershipDate", is(yesterday));
145 assertFalse(customersNamedTommy.isDisjointWith(customersNamedTommy));
146 assertTrue(customersNamedTommy.isDisjointWith(customersNamedJasper));
147 assertTrue(customersNamedJasper.isDisjointWith(customersNamedTommy));
148 }
149
150
151 @Test
152 public void equalNonDisjointMemberSpecificationsMeansNotDisjoint() {
153 Specification<Customer> customersNamedT_mmy = all(Customer.class).where("name", like("T?mmy"));
154 Specification<Customer> customersNamedTimmyIgnoringCase = all(Customer.class).where("name", equalsIgnoringCase("timmy"));
155 assertFalse(customersNamedT_mmy.isDisjointWith(customersNamedT_mmy));
156 assertFalse(customersNamedT_mmy.isDisjointWith(customersNamedTimmyIgnoringCase));
157 assertFalse(customersNamedTimmyIgnoringCase.isDisjointWith(customersNamedT_mmy));
158 }
159
160
161 @Test
162 public void equalNonDisjointMemberSpecificationsAndNonEqualMemberSpecificationsMeansNotDisjoint() {
163 Specification<Customer> customersNamedT_mmy = all(Customer.class).where("name", like("T?mmy")).and("membershipDate", is(yesterday));
164 Specification<Customer> customersNamedTimmyIgnoringCase = all(Customer.class).where("name", equalsIgnoringCase("timmy")).and("birthDate", before(tenYearsAgo));
165 assertFalse(customersNamedT_mmy.isDisjointWith(customersNamedT_mmy));
166 assertFalse(customersNamedT_mmy.isDisjointWith(customersNamedTimmyIgnoringCase));
167 }
168
169
170 @Test
171 public void equalDisjointMemberSpecificationOrEqualDisjointMemberSpecificationsMeansDisjoint() {
172 Specification<Customer> customersNamedTommy = all(Customer.class).where("name", isEqualTo("Tommy")).or("membershipDate", is(yesterday));
173 Specification<Customer> customersNamedJasper = all(Customer.class).where("name", isEqualTo("Jasper")).or("membershipDate", is(theDayBeforeYesterday));
174 assertTrue(customersNamedTommy.isDisjointWith(customersNamedJasper));
175 assertTrue(customersNamedJasper.isDisjointWith(customersNamedTommy));
176 }
177
178
179 @Test
180 public void equalDisjointMemberSpecificationOrEqualNonDisjointMemberSpecificationsMeansNotDisjoint() {
181 Specification<Customer> customersNamedTommy = all(Customer.class).where("name", isEqualTo("Tommy")).or("membershipDate", is(yesterday));
182 Specification<Customer> customersNamedJasper = all(Customer.class).where("name", isEqualTo("Jasper")).or("membershipDate", is(yesterday));
183 assertFalse(customersNamedTommy.isDisjointWith(customersNamedTommy));
184 assertFalse(customersNamedTommy.isDisjointWith(customersNamedJasper));
185 assertFalse(customersNamedJasper.isDisjointWith(customersNamedTommy));
186
187 customersNamedTommy = all(Customer.class).where("name", isEqualTo("Tommy")).or("membershipDate", isBefore(new Date()));
188 customersNamedJasper = all(Customer.class).where("name", isEqualTo("Jasper")).or("membershipDate", isBeforeOrAtTheSameTimeAs(yesterday));
189 assertFalse(customersNamedTommy.isDisjointWith(customersNamedTommy));
190 assertFalse(customersNamedTommy.isDisjointWith(customersNamedJasper));
191 assertFalse(customersNamedJasper.isDisjointWith(customersNamedTommy));
192 }
193
194
195
196 static final Date tenYearsAgo = getTime(thisYear - 10, thisMonth, thisDate);
197 static final Date tenYearsAhead = getTime(thisYear + 10, thisMonth, thisDate);
198 static final Date thirtyYearsAgo = getTime(thisYear - 30, thisMonth, thisDate);
199 static final Date thirtyYearsAhead = getTime(thisYear + 30, thisMonth, thisDate);
200
201 static final Specification<Date> lessThanOrExactlyTenYearsAgo = isAfterOrAtTheSameTimeAs(tenYearsAgo);
202 static final Specification<Date> moreThanTenYearsAgo = isBefore(tenYearsAgo);
203 static final Specification<Date> lessThanOrExactlyTenYearsAhead = isBeforeOrAtTheSameTimeAs(tenYearsAhead);
204 static final Specification<Date> moreThanTenYearsAhead = isAfter(tenYearsAhead);
205
206 static final Specification<Date> lessThanThirtyYearsAgo = isAfter(thirtyYearsAgo);
207 static final Specification<Date> moreThanThirtyYearsAgo = isBefore(thirtyYearsAgo);
208 static final Specification<Date> lessThanThirtyYearsAhead = isBefore(thirtyYearsAhead);
209 static final Specification<Date> moreThanThirtyYearsAhead = isAfter(thirtyYearsAhead);
210
211
212 @Test
213 public void cannotCreateConjunctionOutOfTwoDisjointValueBoundSpecifications_extra() {
214 try {
215 shouldBe(moreThanTenYearsAgo).and(moreThanTenYearsAhead);
216 fail("Should have thrown exception");
217
218 } catch (IllegalArgumentException e) {
219 String expectedMessage = "Cannot create a conjunction out of two disjoint specifications";
220 String actualMessage = e.getMessage();
221 assertEquals(expectedMessage, actualMessage);
222 }
223
224 try {
225 not(not(moreThanTenYearsAgo)).and(not(not(not(not(moreThanTenYearsAhead)))));
226 fail("Should have thrown exception");
227
228 } catch (IllegalArgumentException e) {
229 String expectedMessage = "Cannot create a conjunction out of two disjoint specifications";
230 String actualMessage = e.getMessage();
231 assertEquals(expectedMessage, actualMessage);
232 }
233 }
234
235
236 @Test
237 public void valueBoundConjunctionAndValueBoundDisjunction_notDisjoint() {
238 Specification<Date> plusMinusThirtyYears = lessThanThirtyYearsAgo.and(lessThanThirtyYearsAhead);
239 Specification<Date> atLeastTenYearsAway = moreThanTenYearsAgo.or(moreThanTenYearsAhead);
240
241 assertFalse(plusMinusThirtyYears.isDisjointWith(atLeastTenYearsAway));
242 assertFalse(atLeastTenYearsAway.isDisjointWith(plusMinusThirtyYears));
243 assertFalse(not(not(plusMinusThirtyYears)).isDisjointWith(not(not(atLeastTenYearsAway))));
244 assertFalse(not(not(atLeastTenYearsAway)).isDisjointWith(not(not(plusMinusThirtyYears))));
245
246 plusMinusThirtyYears = is(lessThanThirtyYearsAgo).and(lessThanThirtyYearsAhead);
247 atLeastTenYearsAway = is(moreThanTenYearsAgo).or(moreThanTenYearsAhead);
248
249 assertFalse(plusMinusThirtyYears.isDisjointWith(atLeastTenYearsAway));
250 assertFalse(atLeastTenYearsAway.isDisjointWith(plusMinusThirtyYears));
251 assertFalse(not(not(plusMinusThirtyYears)).isDisjointWith(not(not(atLeastTenYearsAway))));
252 assertFalse(not(not(atLeastTenYearsAway)).isDisjointWith(not(not(plusMinusThirtyYears))));
253
254 plusMinusThirtyYears = both(lessThanThirtyYearsAgo, lessThanThirtyYearsAhead);
255 atLeastTenYearsAway = either(moreThanTenYearsAgo, moreThanTenYearsAhead);
256
257 assertFalse(plusMinusThirtyYears.isDisjointWith(atLeastTenYearsAway));
258 assertFalse(atLeastTenYearsAway.isDisjointWith(plusMinusThirtyYears));
259 assertFalse(not(not(plusMinusThirtyYears)).isDisjointWith(not(not(atLeastTenYearsAway))));
260 assertFalse(not(not(atLeastTenYearsAway)).isDisjointWith(not(not(plusMinusThirtyYears))));
261
262 Specification<Date> plusMinusTenYears = is(lessThanOrExactlyTenYearsAgo).and(lessThanOrExactlyTenYearsAhead);
263 Specification<Date> moreThanTenYearsAway = not(plusMinusTenYears);
264 assertFalse(plusMinusThirtyYears.isDisjointWith(moreThanTenYearsAway));
265 assertFalse(moreThanTenYearsAway.isDisjointWith(plusMinusThirtyYears));
266 assertFalse(not(not(plusMinusThirtyYears)).isDisjointWith(not(not(moreThanTenYearsAway))));
267 assertFalse(not(not(moreThanTenYearsAway)).isDisjointWith(not(not(plusMinusThirtyYears))));
268
269 moreThanTenYearsAway = not(both(lessThanOrExactlyTenYearsAgo).and(lessThanOrExactlyTenYearsAhead));
270 assertFalse(plusMinusThirtyYears.isDisjointWith(atLeastTenYearsAway));
271 assertFalse(atLeastTenYearsAway.isDisjointWith(plusMinusThirtyYears));
272 assertFalse(not(not(plusMinusThirtyYears)).isDisjointWith(not(not(atLeastTenYearsAway))));
273 assertFalse(not(not(atLeastTenYearsAway)).isDisjointWith(not(not(plusMinusThirtyYears))));
274
275 Specification<Date> atLeastThirtyYearsAway = moreThanThirtyYearsAgo.or(moreThanThirtyYearsAhead);
276 plusMinusThirtyYears = not(atLeastThirtyYearsAway);
277 assertFalse(plusMinusThirtyYears.isDisjointWith(moreThanTenYearsAway));
278 assertFalse(moreThanTenYearsAway.isDisjointWith(plusMinusThirtyYears));
279 assertFalse(not(not(plusMinusThirtyYears)).isDisjointWith(not(not(moreThanTenYearsAway))));
280 assertFalse(not(not(moreThanTenYearsAway)).isDisjointWith(not(not(plusMinusThirtyYears))));
281
282 atLeastThirtyYearsAway = is(moreThanThirtyYearsAgo).or(moreThanThirtyYearsAhead);
283 plusMinusThirtyYears = not(atLeastThirtyYearsAway);
284 assertFalse(plusMinusThirtyYears.isDisjointWith(moreThanTenYearsAway));
285 assertFalse(moreThanTenYearsAway.isDisjointWith(plusMinusThirtyYears));
286 assertFalse(not(not(plusMinusThirtyYears)).isDisjointWith(not(not(moreThanTenYearsAway))));
287 assertFalse(not(not(moreThanTenYearsAway)).isDisjointWith(not(not(plusMinusThirtyYears))));
288 }
289
290
291 @Test
292 public void valueBoundConjunctionAndValueBoundDisjunction_disjoint() {
293 Specification<Date> plusMinusTenYears = lessThanOrExactlyTenYearsAgo.and(lessThanOrExactlyTenYearsAhead);
294 Specification<Date> moreThanThirtyYearsAway = moreThanThirtyYearsAgo.or(moreThanThirtyYearsAhead);
295
296 assertTrue(plusMinusTenYears.isDisjointWith(moreThanThirtyYearsAway));
297 assertTrue(moreThanThirtyYearsAway.isDisjointWith(plusMinusTenYears));
298 assertTrue(not(not(plusMinusTenYears)).isDisjointWith(not(not(moreThanThirtyYearsAway))));
299 assertTrue(not(not(moreThanThirtyYearsAway)).isDisjointWith(not(not(plusMinusTenYears))));
300
301 plusMinusTenYears = is(lessThanOrExactlyTenYearsAgo).and(lessThanOrExactlyTenYearsAhead);
302 moreThanThirtyYearsAway = is(moreThanThirtyYearsAgo).or(moreThanThirtyYearsAhead);
303
304 assertTrue(plusMinusTenYears.isDisjointWith(moreThanThirtyYearsAway));
305 assertTrue(moreThanThirtyYearsAway.isDisjointWith(plusMinusTenYears));
306 assertTrue(not(not(plusMinusTenYears)).isDisjointWith(not(not(moreThanThirtyYearsAway))));
307 assertTrue(not(not(moreThanThirtyYearsAway)).isDisjointWith(not(not(plusMinusTenYears))));
308
309 plusMinusTenYears = both(lessThanThirtyYearsAgo, lessThanThirtyYearsAhead);
310 moreThanThirtyYearsAway = oneOf(moreThanThirtyYearsAgo, moreThanThirtyYearsAhead);
311
312 assertTrue(plusMinusTenYears.isDisjointWith(moreThanThirtyYearsAway));
313 assertTrue(moreThanThirtyYearsAway.isDisjointWith(plusMinusTenYears));
314 assertTrue(not(not(plusMinusTenYears)).isDisjointWith(not(not(moreThanThirtyYearsAway))));
315 assertTrue(not(not(moreThanThirtyYearsAway)).isDisjointWith(not(not(plusMinusTenYears))));
316
317 Specification<Date> plusMinusThirtyYears = lessThanThirtyYearsAgo.and(lessThanThirtyYearsAhead);
318 Specification<Date> atLeastTenYearsAway = moreThanTenYearsAgo.or(moreThanTenYearsAhead);
319
320 plusMinusTenYears = not(atLeastTenYearsAway);
321 moreThanThirtyYearsAway = not(plusMinusThirtyYears);
322
323 assertTrue(plusMinusTenYears.isDisjointWith(moreThanThirtyYearsAway));
324 assertTrue(moreThanThirtyYearsAway.isDisjointWith(plusMinusTenYears));
325 assertTrue(not(not(plusMinusTenYears)).isDisjointWith(not(not(moreThanThirtyYearsAway))));
326 assertTrue(not(not(moreThanThirtyYearsAway)).isDisjointWith(not(not(plusMinusTenYears))));
327
328 plusMinusThirtyYears = is(lessThanThirtyYearsAgo).and(lessThanThirtyYearsAhead);
329 atLeastTenYearsAway = is(moreThanTenYearsAgo).or(moreThanTenYearsAhead);
330
331 plusMinusTenYears = not(atLeastTenYearsAway);
332 moreThanThirtyYearsAway = not(plusMinusThirtyYears);
333
334 assertTrue(plusMinusTenYears.isDisjointWith(moreThanThirtyYearsAway));
335 assertTrue(moreThanThirtyYearsAway.isDisjointWith(plusMinusTenYears));
336 assertTrue(not(not(plusMinusTenYears)).isDisjointWith(not(not(moreThanThirtyYearsAway))));
337 assertTrue(not(not(moreThanThirtyYearsAway)).isDisjointWith(not(not(plusMinusTenYears))));
338 }
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387 }