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.Arrays;
20 import java.util.Collections;
21 import java.util.Date;
22 import java.util.List;
23
24 import org.apache.commons.lang.builder.EqualsBuilder;
25 import org.apache.commons.lang.builder.HashCodeBuilder;
26
27 import net.sourceforge.domian.entity.AbstractUUIDEntity;
28 import static net.sourceforge.domian.specification.SpecificationFactory.is;
29 import static net.sourceforge.domian.specification.SpecificationFactory.isAfter;
30 import static net.sourceforge.domian.specification.SpecificationFactory.isBefore;
31 import static net.sourceforge.domian.specification.SpecificationFactory.isEqualTo;
32 import static net.sourceforge.domian.specification.SpecificationFactory.isGreaterThanOrEqualTo;
33 import net.sourceforge.domian.test.domain.Customer;
34 import static net.sourceforge.domian.test.domain.Customer.Gender;
35 import net.sourceforge.domian.test.domain.Order;
36 import net.sourceforge.domian.test.domain.OrderLine;
37 import net.sourceforge.domian.test.domain.Testdata;
38 import static net.sourceforge.domian.test.domain.Testdata.customer12;
39 import static net.sourceforge.domian.test.domain.Testdata.order23;
40 import static net.sourceforge.domian.test.domain.Testdata.thisDate;
41 import static net.sourceforge.domian.test.domain.Testdata.thisMonth;
42 import static net.sourceforge.domian.test.domain.Testdata.thisYear;
43 import static net.sourceforge.domian.test.domain.Testdata.twoDaysAgo;
44 import static net.sourceforge.domian.test.domain.Testdata.yesterday;
45 import static net.sourceforge.domian.util.DateUtils.getTime;
46 import net.sourceforge.domian.util.ReflectionUtils;
47
48 import junit.framework.TestCase;
49
50
51 public class SpecificationsShouldBeImmutableTest extends TestCase {
52
53 public void testPreventValueFromEscapingEncapsulation_MutableValueObject() {
54 final Boolean originalDoCopyObjectFlag = ReflectionUtils.DO_COPY_OBJECTS;
55 ReflectionUtils.DO_COPY_OBJECTS = true;
56
57 Date thirtyYearsAgo = getTime(thisYear - 30, thisMonth, thisDate);
58 Date thirtyYearsAhead = getTime(thisYear + 30, thisMonth, thisDate);
59
60 Specification<Date> lessThanThirtyYearsAgo = isAfter(thirtyYearsAgo);
61 Specification<Date> lessThanThirtyYearsAhead = isBefore(thirtyYearsAhead);
62
63 Specification<Date> plusMinusThirtyYears = is(lessThanThirtyYearsAgo).and(lessThanThirtyYearsAhead);
64 assertTrue(plusMinusThirtyYears.isSatisfiedBy(new Date()));
65 assertTrue(plusMinusThirtyYears.isSatisfiedBy(getTime(1990, 7, 30)));
66 assertTrue(plusMinusThirtyYears.isSatisfiedBy(getTime(2037, 7, 29)));
67 assertFalse(plusMinusThirtyYears.isSatisfiedBy(getTime(1977, 7, 30)));
68 assertFalse(plusMinusThirtyYears.isSatisfiedBy(getTime(2050, 7, 30)));
69
70
71 thirtyYearsAgo.setTime(new Date().getTime());
72
73
74 assertFalse(plusMinusThirtyYears.isSatisfiedBy(null));
75 assertTrue(plusMinusThirtyYears.isSatisfiedBy(new Date()));
76 assertTrue(plusMinusThirtyYears.isSatisfiedBy(getTime(1990, 7, 30)));
77 assertTrue(plusMinusThirtyYears.isSatisfiedBy(getTime(2037, 7, 29)));
78 assertFalse(plusMinusThirtyYears.isSatisfiedBy(getTime(1977, 7, 30)));
79 assertFalse(plusMinusThirtyYears.isSatisfiedBy(getTime(2050, 7, 30)));
80
81
82 thirtyYearsAgo = getTime(thisYear - 30, thisMonth, thisDate);
83 lessThanThirtyYearsAgo = isAfter(thirtyYearsAgo);
84 lessThanThirtyYearsAhead = isBefore(thirtyYearsAhead);
85 plusMinusThirtyYears = is(lessThanThirtyYearsAgo).and(lessThanThirtyYearsAhead);
86
87 Date obtainedThirtyYearsAgo = ((ValueBoundSpecification<Date>) lessThanThirtyYearsAgo).getValue();
88 assertSame(obtainedThirtyYearsAgo, thirtyYearsAgo);
89
90 obtainedThirtyYearsAgo.setTime(new Date().getTime());
91
92 assertFalse(plusMinusThirtyYears.isSatisfiedBy(null));
93 assertTrue(plusMinusThirtyYears.isSatisfiedBy(new Date()));
94 assertTrue(plusMinusThirtyYears.isSatisfiedBy(getTime(1990, 7, 30)));
95 assertTrue(plusMinusThirtyYears.isSatisfiedBy(getTime(2037, 7, 29)));
96 assertFalse(plusMinusThirtyYears.isSatisfiedBy(getTime(1977, 7, 30)));
97 assertFalse(plusMinusThirtyYears.isSatisfiedBy(getTime(2050, 7, 30)));
98
99
100 ReflectionUtils.DO_COPY_OBJECTS = false;
101 lessThanThirtyYearsAgo = isAfter(thirtyYearsAgo);
102 lessThanThirtyYearsAhead = isBefore(thirtyYearsAhead);
103 plusMinusThirtyYears = is(lessThanThirtyYearsAgo).and(lessThanThirtyYearsAhead);
104
105 thirtyYearsAgo.setTime(new Date().getTime());
106 assertFalse(plusMinusThirtyYears.isSatisfiedBy(new Date()));
107 assertFalse(plusMinusThirtyYears.isSatisfiedBy(getTime(1990, 7, 30)));
108 assertTrue(plusMinusThirtyYears.isSatisfiedBy(getTime(2037, 7, 29)));
109
110
111 ReflectionUtils.DO_COPY_OBJECTS = originalDoCopyObjectFlag;
112 }
113
114
115 public void testPreventValueFromEscapingEncapsulation_BusinessKeyEntityObject() {
116 Customer customer12 = new Customer(12L, twoDaysAgo).gender(Gender.MALE).birthDate(getTime(1978, 11, 25));
117 CustomerAwareBusinessKeyOrder order22 = new CustomerAwareBusinessKeyOrder(22L, yesterday, customer12, Collections.<OrderLine>emptyList());
118 Specification<Order> order22Spec = isEqualTo((Order) order22);
119
120 assertTrue(order22Spec.isSatisfiedBy(order22));
121 assertFalse(order22Spec.isSatisfiedBy(order23));
122
123
124
125 customer12.setCustomerId(42L);
126
127 assertTrue(order22Spec.isSatisfiedBy(order22));
128 assertFalse(order22Spec.isSatisfiedBy(order23));
129
130
131 customer12 = new Customer(12L, twoDaysAgo).gender(Gender.MALE).birthDate(getTime(1978, 11, 25));
132 order22 = new CustomerAwareBusinessKeyOrder(22L, yesterday, customer12, Collections.<OrderLine>emptyList());
133 order22Spec = isEqualTo((Order) order22);
134
135 Customer obtainedCustomer12 = ((ValueBoundSpecification<Order>) order22Spec).getValue().getCustomer();
136 assertSame(obtainedCustomer12, customer12);
137
138 obtainedCustomer12.setCustomerId(42L);
139
140 assertTrue(order22Spec.isSatisfiedBy(order22));
141 assertFalse(order22Spec.isSatisfiedBy(order23));
142 }
143
144
145 public void testPreventValueFromEscapingEncapsulation_ComparableEntityObject() {
146 final Boolean originalDoCopyObjectFlag = ReflectionUtils.DO_COPY_OBJECTS;
147 ReflectionUtils.DO_COPY_OBJECTS = true;
148
149 ComparableEntity entityWithInt1024 = new ComparableEntity();
150 entityWithInt1024.field1 = 1024;
151 Specification<ComparableEntity> greaterThanEntityWithInt1024 = isGreaterThanOrEqualTo(entityWithInt1024);
152
153 ComparableEntity entityWithInt1025 = new ComparableEntity();
154 entityWithInt1025.field1 = 1025;
155 ComparableEntity entityWithInt1023 = new ComparableEntity();
156 entityWithInt1023.field1 = 1023;
157
158 assertTrue(greaterThanEntityWithInt1024.isSatisfiedBy(entityWithInt1025));
159 assertFalse(greaterThanEntityWithInt1024.isSatisfiedBy(entityWithInt1023));
160
161
162 entityWithInt1024.field1 = 12;
163
164
165 assertTrue(greaterThanEntityWithInt1024.isSatisfiedBy(entityWithInt1025));
166
167 ReflectionUtils.DO_COPY_OBJECTS = false;
168 entityWithInt1024 = new ComparableEntity();
169 entityWithInt1024.field1 = 1024;
170 greaterThanEntityWithInt1024 = isGreaterThanOrEqualTo(entityWithInt1024);
171 assertTrue(greaterThanEntityWithInt1024.isSatisfiedBy(entityWithInt1025));
172 assertFalse(greaterThanEntityWithInt1024.isSatisfiedBy(entityWithInt1023));
173
174
175 entityWithInt1024.field1 = 12;
176
177
178 assertTrue(greaterThanEntityWithInt1024.isSatisfiedBy(entityWithInt1025));
179 assertTrue(greaterThanEntityWithInt1024.isSatisfiedBy(entityWithInt1023));
180
181
182 ReflectionUtils.DO_COPY_OBJECTS = originalDoCopyObjectFlag;
183 }
184
185
186 public void testPreventValueFromEscapingEncapsulation_EntityObject() {
187
188 Order order22 = new Order(22L, yesterday, customer12, Collections.<OrderLine>emptyList());
189
190 Specification<Order> order22Spec = isEqualTo(order22);
191
192 assertFalse(order22Spec.isSatisfiedBy(Testdata.order22));
193 assertFalse(order22Spec.isSatisfiedBy(Testdata.order23));
194
195
196 order22.setOrderId(23L);
197
198 assertFalse(order22Spec.isSatisfiedBy(Testdata.order22));
199 assertFalse(order22Spec.isSatisfiedBy(Testdata.order23));
200
201
202 order22 = new Order(22L, yesterday, customer12, Collections.<OrderLine>emptyList());
203 order22Spec = isEqualTo(order22);
204
205 Order obtainedOrder22 = ((ValueBoundSpecification<Order>) order22Spec).getValue();
206 assertSame(obtainedOrder22, order22);
207
208 obtainedOrder22.setOrderId(23L);
209
210 assertFalse(order22Spec.isSatisfiedBy(Testdata.order22));
211 assertFalse(order22Spec.isSatisfiedBy(Testdata.order23));
212 }
213 }
214
215
216
217 class CustomerAwareBusinessKeyOrder extends Order {
218
219 CustomerAwareBusinessKeyOrder(final Long orderId, final Date orderDate, final Customer customer, final List<OrderLine> orderLines) {
220 super(orderId, orderDate, customer, orderLines);
221 }
222
223 public List<?> getKey() {
224 return Collections.unmodifiableList(Arrays.asList(orderId, customer));
225 }
226
227 @Override
228 public int hashCode() {
229 final HashCodeBuilder hashCodeBuilder = new HashCodeBuilder(9373645, 28373649);
230 for (Object partialKey : getKey()) {
231 if (partialKey != null) {
232 hashCodeBuilder.append(partialKey);
233 } else {
234 return System.identityHashCode(this);
235 }
236 }
237 return hashCodeBuilder.toHashCode();
238 }
239
240 @Override
241 public boolean equals(final Object otherObject) {
242 if (otherObject == null) {
243 return false;
244 }
245 if (!(otherObject instanceof Order)) {
246 return false;
247 }
248 Order otherOrder = (Order) otherObject;
249 return new EqualsBuilder()
250 .append(getOrderId(), otherOrder.getOrderId())
251 .append(getCustomer(), otherOrder.getCustomer())
252 .isEquals();
253 }
254 }
255
256
257 class ComparableEntity extends AbstractUUIDEntity implements Comparable<ComparableEntity> {
258 Integer field1;
259
260 public int compareTo(ComparableEntity otherComparableEntityo) {
261 return this.field1 - otherComparableEntityo.field1;
262 }
263 }