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.Collections;
20 import java.util.Map;
21 import java.util.Set;
22
23 import org.apache.commons.lang.NotImplementedException;
24 import org.apache.commons.lang.Validate;
25
26 import static java.lang.Boolean.FALSE;
27 import static java.lang.Boolean.TRUE;
28 import static net.sourceforge.domian.util.ReflectionUtils.canCast;
29
30
31
32
33
34
35
36
37
38
39
40 final class JointDenialSpecification<T> extends AbstractCompositeSpecification<T> {
41
42 JointDenialSpecification(final Class<T> type) {
43 super(type);
44 }
45
46 @Override
47 protected Boolean isSpecifyingAllInstancesOfItsType() {
48 return FALSE;
49 }
50
51
52 Boolean isTypeExcludingSpecification() {
53 for (final Specification<? super T> wrappedSpec : this.specifications) {
54 if (wrappedSpec instanceof CompositeSpecification) {
55 if (((AbstractCompositeSpecification) wrappedSpec).isSpecifyingAllInstancesOfItsType()) {
56 return TRUE;
57 }
58 }
59 }
60 return FALSE;
61 }
62
63 @Override
64 public Boolean isSatisfiedBy(final T candidate) {
65 if (super.isSatisfiedBy(candidate)) {
66 for (final Specification<? super T> specification : this.specifications) {
67 if (specification.isSatisfiedBy(candidate)) {
68 return FALSE;
69 }
70 }
71 return TRUE;
72 }
73 return FALSE;
74 }
75
76
77 @Override
78 public Boolean isDisjointWith(final Specification<?> specification) {
79 Validate.notNull(specification, "Specification parameter cannot be null");
80
81
82 if (this == specification || this.equals(specification)) {
83 return FALSE;
84 }
85
86 Specification<?> negatedThis = null;
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103 AbstractSpecification<T> purifiedThis = this.purify(true);
104 if (purifiedThis != this) {
105 if (purifiedThis instanceof JointDenialSpecification) {
106 negatedThis = getNegatedSpecification((JointDenialSpecification<T>) purifiedThis);
107 } else {
108 return purifiedThis.isDisjointWith(specification);
109 }
110 } else {
111 negatedThis = getNegatedSpecification(this);
112 }
113
114
115 try {
116 if (canCast(this.getType(), negatedThis.getType()) && this.isTypeExcludingSpecification()) {
117 return TRUE;
118 }
119
120
121 } catch (NotImplementedException e) {
122
123 }
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138 final int numberOfLevelsOfInversions = getNumberOfLevelsOfNegations(this, 0);
139
140 if (negatedThis instanceof ValueBoundSpecification) {
141
142 if (negatedThis instanceof AbstractComparableValueBoundSpecification) {
143 final AbstractComparableValueBoundSpecification negatedValueBoundSpecification = (AbstractComparableValueBoundSpecification) negatedThis;
144 final Specification resolvedSpecification;
145 if (isOddNumber(numberOfLevelsOfInversions)) {
146 resolvedSpecification = negatedValueBoundSpecification.invert();
147 } else {
148 resolvedSpecification = negatedValueBoundSpecification;
149 }
150
151 if (specification instanceof ValueBoundSpecification) {
152 if (resolvedSpecification instanceof DisjunctionSpecification) {
153 final AbstractCompositeSpecification<?> compositeSpecification = (AbstractCompositeSpecification) resolvedSpecification;
154 for (final Specification spec : compositeSpecification.specifications) {
155 if (!specification.isDisjointWith(spec)) {
156 return FALSE;
157 }
158 }
159 return TRUE;
160
161 } else if (resolvedSpecification instanceof ValueBoundSpecification) {
162 return resolvedSpecification.isDisjointWith(specification);
163 }
164
165 } else if (specification instanceof JointDenialSpecification) {
166 return specification.isDisjointWith(resolvedSpecification);
167
168 } else {
169 return resolvedSpecification.isDisjointWith(specification);
170 }
171
172 } else {
173 if (isOddNumber(numberOfLevelsOfInversions)) {
174 if (specification instanceof DisjunctionSpecification) {
175 return FALSE;
176 }
177 return !negatedThis.isDisjointWith(specification);
178
179 } else {
180 return negatedThis.isDisjointWith(specification);
181 }
182 }
183
184 } else if (negatedThis instanceof DisjunctionSpecification) {
185
186 if (((DisjunctionSpecification) negatedThis).hasParameterization()) {
187
188 final AbstractCompositeSpecification candidateConjuntionSpecification = (AbstractCompositeSpecification) specification;
189 if (candidateConjuntionSpecification.hasParameterization()) {
190 final Map<String, Set<LeafSpecification>> leafSpecificationMap = this.getLeafSpecificationMap();
191 final Map<String, Set<LeafSpecification>> candidateLeafSpecificationMap = candidateConjuntionSpecification.getLeafSpecificationMap();
192 for (final String memberName : leafSpecificationMap.keySet()) {
193 if (candidateLeafSpecificationMap.keySet().contains(memberName)) {
194 final Set<LeafSpecification> specificationSet = leafSpecificationMap.get(memberName);
195 final Set<LeafSpecification> memberSpecificationSet = candidateLeafSpecificationMap.get(memberName);
196 for (final Specification leafSpecification : specificationSet) {
197 for (final Specification memberLeafSpecification : memberSpecificationSet) {
198 if (!leafSpecification.isDisjointWith(memberLeafSpecification)) {
199 return FALSE;
200 }
201 }
202 }
203 } else {
204 if (specification instanceof DisjunctionSpecification) {
205 return FALSE;
206 } else {
207 return TRUE;
208 }
209 }
210 }
211 for (final String memberName : candidateLeafSpecificationMap.keySet()) {
212 if (leafSpecificationMap.keySet().contains(memberName)) {
213 final Set<LeafSpecification> specificationSet = leafSpecificationMap.get(memberName);
214 final Set<LeafSpecification> memberSpecificationSet = candidateLeafSpecificationMap.get(memberName);
215 for (final Specification leafSpecification : memberSpecificationSet) {
216 for (final Specification memberLeafSpecification : specificationSet) {
217 if (!leafSpecification.isDisjointWith(memberLeafSpecification)) {
218 return FALSE;
219 }
220 }
221 }
222 } else {
223 if (specification instanceof DisjunctionSpecification) {
224 return FALSE;
225 } else {
226 return TRUE;
227 }
228 }
229 }
230 if (specification instanceof DisjunctionSpecification) {
231 return TRUE;
232 } else {
233 return FALSE;
234 }
235 }
236
237
238
239 for (Specification<?> spec : this.specifications) {
240 if (!spec.isDisjointWith(specification)) {
241 return FALSE;
242 }
243 }
244 return TRUE;
245 }
246
247 Specification resolvedSpecification;
248
249
250 if (isOddNumber(numberOfLevelsOfInversions)) {
251 if (((DisjunctionSpecification) negatedThis).isInvertible()) {
252 resolvedSpecification = ((DisjunctionSpecification) negatedThis).invert();
253 if (resolvedSpecification instanceof ValueBoundSpecification) {
254 return resolvedSpecification.isDisjointWith(specification);
255 } else {
256 return !resolvedSpecification.isDisjointWith(specification);
257 }
258 } else {
259
260 throw new NotImplementedException();
261 }
262
263 } else {
264 resolvedSpecification = negatedThis;
265 }
266
267
268 if (resolvedSpecification instanceof JointDenialSpecification) {
269 throw new NotImplementedException();
270 }
271
272 if (resolvedSpecification instanceof CompositeSpecification) {
273
274 final AbstractCompositeSpecification<?> compositeSpecification = (AbstractCompositeSpecification) resolvedSpecification;
275 for (final Specification spec : compositeSpecification.specifications) {
276 if (!resolvedSpecification.isDisjointWith(spec)) {
277 return FALSE;
278 }
279 }
280 return TRUE;
281 }
282
283
284 throw new NotImplementedException();
285
286
287 } else if (negatedThis instanceof ConjunctionSpecification) {
288
289 if (((ConjunctionSpecification) negatedThis).hasParameterization()) {
290 final AbstractCompositeSpecification candidateConjuntionSpecification = (AbstractCompositeSpecification) specification;
291 if (candidateConjuntionSpecification.hasParameterization()) {
292 final Map<String, Set<LeafSpecification>> leafSpecificationMap = this.getLeafSpecificationMap();
293 final Map<String, Set<LeafSpecification>> candidateLeafSpecificationMap = candidateConjuntionSpecification.getLeafSpecificationMap();
294 for (final String memberName : leafSpecificationMap.keySet()) {
295 if (candidateLeafSpecificationMap.keySet().contains(memberName)) {
296 final Set<LeafSpecification> specificationSet = leafSpecificationMap.get(memberName);
297 final Set<LeafSpecification> memberSpecificationSet = candidateLeafSpecificationMap.get(memberName);
298 for (final Specification leafSpecification : specificationSet) {
299 for (final Specification memberLeafSpecification : memberSpecificationSet) {
300 if (!leafSpecification.isDisjointWith(memberLeafSpecification)) {
301 return FALSE;
302 }
303 }
304 }
305 } else {
306 if (specification instanceof DisjunctionSpecification) {
307 return FALSE;
308 } else {
309 if (isOddNumber(numberOfLevelsOfInversions)) {
310 return FALSE;
311 } else {
312 return TRUE;
313 }
314
315 }
316 }
317 }
318 for (final String memberName : candidateLeafSpecificationMap.keySet()) {
319 if (leafSpecificationMap.keySet().contains(memberName)) {
320 final Set<LeafSpecification> specificationSet = leafSpecificationMap.get(memberName);
321 final Set<LeafSpecification> memberSpecificationSet = candidateLeafSpecificationMap.get(memberName);
322 for (final Specification leafSpecification : memberSpecificationSet) {
323 for (final Specification memberLeafSpecification : specificationSet) {
324 if (!leafSpecification.isDisjointWith(memberLeafSpecification)) {
325 return FALSE;
326 }
327 }
328 }
329 } else {
330 if (specification instanceof DisjunctionSpecification) {
331 return FALSE;
332 } else {
333 return TRUE;
334 }
335 }
336 }
337 if (specification instanceof DisjunctionSpecification) {
338 return TRUE;
339 } else {
340 return FALSE;
341 }
342 }
343
344
345
346 for (Specification<?> spec : this.specifications) {
347 if (!spec.isDisjointWith(specification)) {
348 return FALSE;
349 }
350 }
351 return TRUE;
352 }
353
354
355 Specification resolvedSpecification;
356
357
358 if (isOddNumber(numberOfLevelsOfInversions)) {
359 return negatedThis.isDisjointWith(specification);
360
361 } else {
362 resolvedSpecification = negatedThis;
363 }
364
365
366 if (specification instanceof JointDenialSpecification) {
367 final JointDenialSpecification jointDenialCandidateSpecification = (JointDenialSpecification) specification;
368 final Specification negatedCandidateSpec = getNegatedSpecification(jointDenialCandidateSpecification);
369 return negatedCandidateSpec.isDisjointWith(negatedThis);
370 }
371
372
373 if (resolvedSpecification instanceof JointDenialSpecification) {
374
375
376 throw new NotImplementedException();
377 }
378
379 if (resolvedSpecification instanceof CompositeSpecification) {
380
381 final AbstractCompositeSpecification<?> compositeSpecification = (AbstractCompositeSpecification) resolvedSpecification;
382 for (final Specification spec : compositeSpecification.specifications) {
383 if (!resolvedSpecification.isDisjointWith(spec)) {
384 return FALSE;
385 }
386 }
387 return TRUE;
388 }
389
390
391 throw new NotImplementedException();
392
393
394 } else {
395 if (isOddNumber(numberOfLevelsOfInversions)) {
396 return !negatedThis.isDisjointWith(specification);
397 } else {
398 return negatedThis.isDisjointWith(specification);
399 }
400 }
401 throw new NotImplementedException();
402 }
403
404
405 @Override
406 protected AbstractSpecification<T> purify(final boolean doPurifyInversions) {
407
408 final Specification<T> negatedSpec = getNegatedSpecification(this);
409 final int numberOfLevelsOfInversions = getNumberOfLevelsOfNegations(this, 0);
410 if (negatedSpec instanceof AbstractValueBoundSpecification) {
411 if (doPurifyInversions) {
412 if (isOddNumber(numberOfLevelsOfInversions)) {
413 if (((AbstractValueBoundSpecification<T>) negatedSpec).isInvertible()) {
414 return ((AbstractSpecification<T>) ((AbstractValueBoundSpecification<T>) negatedSpec).invert()).purify(true);
415 } else {
416 return purifyWithoutAnyInversionOfWrappedSpecs();
417 }
418 } else {
419 return ((AbstractSpecification<T>) negatedSpec).purify(true);
420 }
421 }
422 return purifyWithoutAnyInversionOfWrappedSpecs();
423
424 } else if (negatedSpec instanceof DisjunctionSpecification) {
425 if (doPurifyInversions) {
426 if (isOddNumber(numberOfLevelsOfInversions)) {
427 if (((DisjunctionSpecification<T>) negatedSpec).isInvertible()) {
428 return ((AbstractSpecification<T>) ((DisjunctionSpecification<T>) negatedSpec).invert()).purify(true);
429 } else {
430 return purifyWithoutAnyInversionOfWrappedSpecs();
431 }
432 } else {
433 return ((AbstractSpecification<T>) negatedSpec).purify(true);
434 }
435 }
436 return purifyWithoutAnyInversionOfWrappedSpecs();
437
438 } else if (negatedSpec instanceof ConjunctionSpecification) {
439 if (doPurifyInversions) {
440 if (isOddNumber(numberOfLevelsOfInversions)) {
441 if (((ConjunctionSpecification<T>) negatedSpec).isInvertible()) {
442 return ((AbstractSpecification<T>) ((ConjunctionSpecification<T>) negatedSpec).invert()).purify(true);
443 } else {
444 return purifyWithoutAnyInversionOfWrappedSpecs();
445 }
446 } else {
447 return ((AbstractSpecification<T>) negatedSpec).purify(true);
448 }
449 }
450 return purifyWithoutAnyInversionOfWrappedSpecs();
451 }
452
453
454
455
456 return purifyWithoutAnyInversionOfWrappedSpecs();
457 }
458
459
460 private AbstractSpecification<T> purifyWithoutAnyInversionOfWrappedSpecs() {
461
462
463
464
465
466 this.specifications = Collections.unmodifiableSet(this.specifications);
467 return this;
468 }
469 }