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 org.apache.commons.lang.Validate;
20 import org.apache.commons.lang.builder.EqualsBuilder;
21 import org.apache.commons.lang.builder.HashCodeBuilder;
22
23 import static java.lang.Boolean.FALSE;
24 import static java.lang.Boolean.TRUE;
25 import static net.sourceforge.domian.specification.RelationalOperator.DO_INVERT;
26 import static net.sourceforge.domian.util.ReflectionUtils.canCastAtLeastOneWay;
27 import static net.sourceforge.domian.util.ReflectionUtils.cloneOrDeepCopyIfNotImmutable;
28 import static net.sourceforge.domian.util.ReflectionUtils.isEntity;
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49 abstract class AbstractValueBoundSpecification<T> extends AbstractSpecification<T> implements ValueBoundSpecification<T> {
50
51 protected final T value;
52 protected final T originalValue;
53
54 @SuppressWarnings("unchecked")
55 AbstractValueBoundSpecification(final T value) {
56 Validate.notNull(value, "Value parameter cannot be null");
57
58 this.type = (Class<T>) value.getClass();
59 this.originalValue = value;
60
61 final boolean doCopyEntites = true;
62 if (this.originalValue instanceof Comparable<?> || !isEntity(this.originalValue)) {
63 this.value = cloneOrDeepCopyIfNotImmutable(this.originalValue, doCopyEntites);
64 } else {
65 this.value = cloneOrDeepCopyIfNotImmutable(this.originalValue, !doCopyEntites);
66 }
67 }
68
69 @Override
70 public T getValue() {
71 return this.originalValue;
72 }
73
74
75
76
77
78 protected RelationalOperator getBinaryRelation() {
79 return getBinaryRelation(FALSE);
80 }
81
82
83
84
85
86
87 protected abstract RelationalOperator getBinaryRelation(Boolean negated);
88
89
90
91
92
93 protected abstract Boolean getDisjointDecision(final RelationalOperator candidateRelationalOperator, final T candidateOperandValue);
94
95 @Override
96 public Boolean isDisjointWith(final Specification<?> specification) {
97 Validate.notNull(specification, "Specification parameter cannot be null");
98
99 if (this == specification || this.equals(specification)) {
100 return FALSE;
101 }
102
103 if (!canCastAtLeastOneWay(this.getType(), specification.getType())) {
104 return TRUE;
105 }
106 if (specification instanceof EqualSpecification) {
107 return !this.equals(specification);
108 }
109 return TRUE;
110 }
111
112 @Override
113 protected Specification<T> invert() {
114
115 return createValueBoundSpecification(this.getBinaryRelation(DO_INVERT), this.value);
116 }
117
118 @Override
119 public int hashCode() {
120 return new HashCodeBuilder(4877, 8555).append(this.value).toHashCode();
121 }
122
123 @Override
124 public boolean equals(final Object otherObject) {
125 if (otherObject == null) { return false; }
126 if (!(otherObject instanceof AbstractValueBoundSpecification)) { return false; }
127 return new EqualsBuilder()
128 .append(this.getClass(), otherObject.getClass())
129 .append(this.value, ((AbstractValueBoundSpecification) otherObject).value)
130 .isEquals();
131 }
132 }