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.HashSet;
20 import java.util.Map;
21 import java.util.Set;
22
23 import org.apache.commons.lang.Validate;
24
25 import static java.lang.Boolean.FALSE;
26 import static java.lang.Boolean.TRUE;
27 import static net.sourceforge.domian.util.ReflectionUtils.canCast;
28 import static net.sourceforge.domian.util.ReflectionUtils.canCastAtLeastOneWay;
29
30
31
32
33
34
35
36
37
38
39
40 final class ConjunctionSpecification<T> extends AbstractCompositeSpecification<T> {
41
42 ConjunctionSpecification(final Class<T> type) {
43 super(type);
44 }
45
46 @Override
47 public Boolean isSatisfiedBy(final T candidate) {
48 if (super.isSatisfiedBy(candidate)) {
49 for (final Specification<? super T> wrappedSpec : this.specifications) {
50 if (wrappedSpec != null && !wrappedSpec.isSatisfiedBy(candidate)) {
51 return false;
52 }
53 }
54 return true;
55 }
56 return false;
57 }
58
59
60 @Override
61 public Boolean isDisjointWith(final Specification<?> specification) {
62 Validate.notNull(specification, "Specification parameter cannot be null");
63
64
65 if (this == specification || this.equals(specification)) {
66 return FALSE;
67 }
68
69
70 if (!canCastAtLeastOneWay(this.getType(), specification.getType())) {
71 return TRUE;
72 }
73
74
75 if (this.isSpecifyingAllInstancesOfItsType()) {
76 if (specification instanceof JointDenialSpecification) {
77 final Specification<?> negatedSpec = getNegatedSpecification((JointDenialSpecification<T>) specification);
78 if (negatedSpec.equals(this)) {
79 return TRUE;
80 }
81 }
82 return FALSE;
83 }
84
85
86 if (specification instanceof ParameterizedSpecification) {
87 return FALSE;
88 }
89
90 if (specification instanceof ValueBoundSpecification) {
91 for (final Specification<?> spec : this.specifications) {
92 if (!spec.isDisjointWith(specification)) {
93 return FALSE;
94 }
95 }
96 return TRUE;
97 }
98
99 if (specification instanceof JointDenialSpecification) {
100
101 final JointDenialSpecification jointDenialSpecification = (JointDenialSpecification) specification;
102 final Specification negatedSpec = getNegatedSpecification(jointDenialSpecification);
103 if (canCast(this.getType(), negatedSpec.getType()) && jointDenialSpecification.isTypeExcludingSpecification()) {
104 return TRUE;
105 }
106
107 return specification.isDisjointWith(this);
108 }
109
110 if (specification instanceof DisjunctionSpecification) {
111
112 return specification.isDisjointWith(this);
113 }
114
115
116 if (this.hasParameterization()) {
117 final AbstractCompositeSpecification candidateCompositeSpecification = (AbstractCompositeSpecification) specification;
118 if (candidateCompositeSpecification.hasParameterization()) {
119 final Map<String, Set<LeafSpecification>> leafSpecificationMap = this.getLeafSpecificationMap();
120 final Map<String, Set<LeafSpecification>> candidateLeafSpecificationMap = candidateCompositeSpecification.getLeafSpecificationMap();
121 for (final String memberName : leafSpecificationMap.keySet()) {
122 if (candidateLeafSpecificationMap.keySet().contains(memberName)) {
123 final Set<LeafSpecification> specificationSet = leafSpecificationMap.get(memberName);
124 final Set<LeafSpecification> memberSpecificationSet = candidateLeafSpecificationMap.get(memberName);
125 for (final Specification leafSpecification : specificationSet) {
126 for (final Specification memberLeafSpecification : memberSpecificationSet) {
127 if (leafSpecification.isDisjointWith(memberLeafSpecification)) {
128 return TRUE;
129 }
130 }
131 }
132 } else {
133 return FALSE;
134 }
135 }
136 for (final String memberName : candidateLeafSpecificationMap.keySet()) {
137 if (leafSpecificationMap.keySet().contains(memberName)) {
138 final Set<LeafSpecification> specificationSet = leafSpecificationMap.get(memberName);
139 final Set<LeafSpecification> memberSpecificationSet = candidateLeafSpecificationMap.get(memberName);
140 for (final Specification leafSpecification : memberSpecificationSet) {
141 for (final Specification memberLeafSpecification : specificationSet) {
142 if (leafSpecification.isDisjointWith(memberLeafSpecification)) {
143 return TRUE;
144 }
145 }
146 }
147 } else {
148 return FALSE;
149 }
150 }
151 return FALSE;
152
153 } else {
154 return FALSE;
155 }
156
157 } else {
158
159
160
161
162 final AbstractCompositeSpecification<?> compositeSpecification = (AbstractCompositeSpecification) specification;
163 final Set<Specification> notDisjointToSpecSet = new HashSet<Specification>();
164 for (final Specification wrappedSpec : this.specifications) {
165 for (final Specification spec : compositeSpecification.specifications) {
166 if (!wrappedSpec.isDisjointWith(spec)) {
167 notDisjointToSpecSet.add(spec);
168 }
169 }
170 }
171 return notDisjointToSpecSet.isEmpty() || notDisjointToSpecSet.equals(compositeSpecification.specifications);
172 }
173 }
174
175
176 @Override
177 protected Boolean isSpecifyingAllInstancesOfItsType() {
178 for (final Specification<? super T> wrappedSpec : this.specifications) {
179 if (wrappedSpec instanceof AbstractCompositeSpecification) {
180 if (!((AbstractCompositeSpecification) wrappedSpec).isSpecifyingAllInstancesOfItsType()) {
181 return false;
182 }
183 } else {
184 return false;
185 }
186 }
187 return true;
188 }
189
190
191 @Override
192 protected AbstractSpecification<T> purify(final boolean doPurifyInversions) {
193
194 if (this.specifications.isEmpty()) {
195 return this;
196 }
197 if (this.specifications.size() == 1) {
198 Specification<? super T> wrappedSpec = this.specifications.iterator().next();
199
200 if (!(wrappedSpec instanceof ParameterizedSpecification)) {
201 return ((AbstractSpecification<T>) wrappedSpec).purify(true);
202 }
203 }
204 final ConjunctionSpecification<T> newPurifiedConjunctionSpecification = new ConjunctionSpecification<T>(this.getType());
205
206 for (final Specification wrappedSpec : this.specifications) {
207 AbstractSpecification wrappedAbstractSpec = ((AbstractSpecification) wrappedSpec);
208
209 wrappedAbstractSpec = wrappedAbstractSpec.purify(true);
210
211 if (wrappedAbstractSpec instanceof AbstractCompositeSpecification) {
212 if (((AbstractCompositeSpecification) wrappedAbstractSpec).isSpecifyingAllInstancesOfItsType()) {
213 if (this.specifications.size() < 2) {
214 newPurifiedConjunctionSpecification.specifications.add(wrappedAbstractSpec);
215 }
216 } else {
217 newPurifiedConjunctionSpecification.specifications.add(wrappedAbstractSpec);
218 }
219 } else {
220 newPurifiedConjunctionSpecification.specifications.add(wrappedAbstractSpec);
221
222 }
223 }
224
225 if (this.specifications.size() == 1) {
226 Specification<? super T> wrappepSpec = this.specifications.iterator().next();
227
228 if (!(wrappepSpec instanceof ParameterizedSpecification)) {
229 return ((AbstractSpecification<T>) wrappepSpec).purify(true);
230 }
231 }
232 return newPurifiedConjunctionSpecification;
233 }
234
235
236 @Override
237 protected Boolean isInvertible() {
238 return containsValueBoundSpecificationsOnly(this) || containsSimpleCompositesOnly(this);
239 }
240
241
242 @Override
243 protected Specification<T> invert() {
244 if (containsValueBoundSpecificationsOnly(this) || containsSimpleCompositesOnly(this)) {
245 return doBooleanAlgebraInversion();
246 }
247 throw new IllegalStateException();
248 }
249
250
251 private Specification<T> doBooleanAlgebraInversion() {
252 final DisjunctionSpecification<T> disjunctionSpecification = new DisjunctionSpecification<T>(getType());
253 for (final Specification<?> specification : this.getAllSpecifications()) {
254 disjunctionSpecification.specifications.add(((AbstractSpecification<? super T>) specification).invert());
255 }
256 return disjunctionSpecification;
257 }
258 }