1 package net.sf.twip.parameterhandler;
2
3 import java.util.regex.*;
4
5 import net.sf.twip.Assume;
6 import net.sf.twip.internal.TwipConfigurationErrorIllegalAssumeExpression;
7 import net.sf.twip.util.Parameter;
8
9
10
11
12
13
14
15
16 abstract public class AbstractNumberParameterHandler extends ParameterHandler {
17
18 private static final class AndTester implements Tester {
19 private final Tester[] testers;
20
21 private AndTester(Tester... testers) {
22 this.testers = testers;
23 }
24
25 @Override
26 public boolean test(Object value) {
27 for (Tester tester : testers) {
28 if (!tester.test(value)) {
29 return false;
30 }
31 }
32 return true;
33 }
34 }
35
36 private static final class EqualsTester implements Tester {
37 private final Comparable<Object> comparable;
38
39 private EqualsTester(Comparable<Object> comparable) {
40 this.comparable = comparable;
41 }
42
43 @Override
44 public boolean test(Object value) {
45 return value == null || 0 != comparable.compareTo(value);
46 }
47 }
48
49 private static final class GreaterOrEqualsTester implements Tester {
50 private final Comparable<Object> comparable;
51
52 private GreaterOrEqualsTester(Comparable<Object> comparable) {
53 this.comparable = comparable;
54 }
55
56 @Override
57 public boolean test(Object value) {
58 return value == null || 0 >= comparable.compareTo(value);
59 }
60 }
61
62 private static final class GreaterThanTester implements Tester {
63 private final Comparable<Object> comparable;
64
65 private GreaterThanTester(Comparable<Object> comparable) {
66 this.comparable = comparable;
67 }
68
69 @Override
70 public boolean test(Object value) {
71 return value == null || 0 > comparable.compareTo(value);
72 }
73 }
74
75 private static final class LessOrEqualsTester implements Tester {
76 private final Comparable<Object> comparable;
77
78 private LessOrEqualsTester(Comparable<Object> comparable) {
79 this.comparable = comparable;
80 }
81
82 @Override
83 public boolean test(Object value) {
84 return value == null || 0 <= comparable.compareTo(value);
85 }
86 }
87
88 private static final class LessThanTester implements Tester {
89 private final Comparable<Object> comparable;
90
91 private LessThanTester(Comparable<Object> comparable) {
92 this.comparable = comparable;
93 }
94
95 @Override
96 public boolean test(Object value) {
97 return value == null || 0 < comparable.compareTo(value);
98 }
99 }
100
101 protected interface Tester {
102 public boolean test(Object value);
103 }
104
105 private static final class TrueTester implements Tester {
106 @Override
107 public boolean test(Object value) {
108 return true;
109 }
110 }
111
112 private static final Pattern EXPRESSION = Pattern.compile("(<|>|!)(=?)\\s*(-?\\w+)");
113
114 private final Tester tester;
115
116 public AbstractNumberParameterHandler(Parameter parameter) {
117 super(parameter);
118 this.tester = getTester();
119 }
120
121 protected abstract Comparable<? extends Number> getComparable(String numberExpression);
122
123 private Tester getTester() {
124 final Assume assumption = parameter.getAnnotation(Assume.class);
125 if (assumption == null)
126 return new TrueTester();
127
128 final String expression = assumption.value();
129 return getTester(expression);
130 }
131
132 protected Tester getTester(final String expression) {
133 int andIndex = expression.indexOf('&');
134 if (andIndex >= 0) {
135 String left = expression.substring(0, andIndex).trim();
136 String right = expression.substring(andIndex + 1).trim();
137 return new AndTester(getTester(left), getTester(right));
138 }
139 final Matcher matcher = EXPRESSION.matcher(expression);
140 if (!matcher.matches())
141 throw new TwipConfigurationErrorIllegalAssumeExpression("illegal assume expression ["
142 + expression + "] for [" + parameter.getType().getSimpleName() + "]");
143 @SuppressWarnings("unchecked")
144 final Comparable<Object> comparable =
145 (Comparable<Object>) (Comparable<?>) getComparable(matcher.group(3));
146 if (">".equals(matcher.group(1))) {
147 if ("=".equals(matcher.group(2))) {
148 return new GreaterOrEqualsTester(comparable);
149 } else {
150 return new GreaterThanTester(comparable);
151 }
152 } else if ("<".equals(matcher.group(1))) {
153 if ("=".equals(matcher.group(2))) {
154 return new LessOrEqualsTester(comparable);
155 } else {
156 return new LessThanTester(comparable);
157 }
158 } else {
159 if ("=".equals(matcher.group(2))) {
160 return new EqualsTester(comparable);
161 } else {
162 throw new TwipConfigurationErrorIllegalAssumeExpression(
163 "illegal assume expression [" + expression + "] for ["
164 + parameter.getType().getSimpleName() + "]");
165 }
166 }
167 }
168
169 @Override
170 public boolean test(Object value) {
171 return tester.test(value);
172 }
173 }