001 /*
002 * Copyright 2002-2004 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
005 * use this file except in compliance with the License. You may obtain a copy of
006 * the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
012 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
013 * License for the specific language governing permissions and limitations under
014 * the License.
015 */
016 package org.springframework.rules.constraint;
017
018 import java.util.Comparator;
019
020 import org.springframework.rules.constraint.Constraint;
021 import org.springframework.core.style.ToStringCreator;
022 import org.springframework.util.Assert;
023
024 /**
025 * A range whose edges are defined by a minimum Comparable and a maximum
026 * Comparable.
027 *
028 * @author Keith Donald
029 */
030 public final class Range extends AbstractConstraint {
031 private Object min;
032
033 private Object max;
034
035 private boolean inclusive = true;
036
037 private Constraint rangeConstraint;
038
039 /**
040 * Creates a range with the specified <code>Comparable</code> min and max
041 * edges.
042 *
043 * @param min
044 * the low edge of the range
045 * @param max
046 * the high edge of the range
047 */
048 public Range(Comparable min, Comparable max) {
049 this(min, max, true);
050 }
051
052 /**
053 * Creates a range with the specified <code>Comparable</code> min and max
054 * edges.
055 *
056 * @param min
057 * the low edge of the range
058 * @param max
059 * the high edge of the range
060 * @param inclusive
061 * the range is inclusive?
062 */
063 public Range(Comparable min, Comparable max, boolean inclusive) {
064 commonAssert(min, max);
065 Constraint minimum;
066 Constraint maximum;
067 this.inclusive = inclusive;
068 if (this.inclusive) {
069 Assert.isTrue(LessThanEqualTo.instance().test(min, max), "Minimum " + min
070 + " must be less than or equal to maximum " + max);
071 minimum = gte(min);
072 maximum = lte(max);
073 }
074 else {
075 Assert.isTrue(LessThan.instance().test(min, max), "Minimum " + min + " must be less than maximum " + max);
076 minimum = gt(min);
077 maximum = lt(max);
078 }
079 this.rangeConstraint = and(minimum, maximum);
080 this.min = min;
081 this.max = max;
082 }
083
084 /**
085 * Creates a range with the specified min and max edges.
086 *
087 * @param min
088 * the low edge of the range
089 * @param max
090 * the high edge of the range
091 * @param comparator
092 * the comparator to use to perform value comparisons
093 */
094 public Range(Object min, Object max, Comparator comparator) {
095 this(min, max, comparator, true);
096 }
097
098 /**
099 * Creates a range with the specified min and max edges.
100 *
101 * @param min
102 * the low edge of the range
103 * @param max
104 * the high edge of the range
105 * @param comparator
106 * the comparator to use to perform value comparisons
107 */
108 public Range(Object min, Object max, Comparator comparator, boolean inclusive) {
109 commonAssert(min, max);
110 Constraint minimum;
111 Constraint maximum;
112 this.inclusive = inclusive;
113 if (this.inclusive) {
114 Assert.isTrue(LessThanEqualTo.instance(comparator).test(min, max), "Minimum " + min
115 + " must be less than or equal to maximum " + max);
116 minimum = bind(GreaterThanEqualTo.instance(comparator), min);
117 maximum = bind(LessThanEqualTo.instance(comparator), max);
118 }
119 else {
120 Assert.isTrue(LessThan.instance(comparator).test(min, max), "Minimum " + min
121 + " must be less than maximum " + max);
122 minimum = bind(GreaterThan.instance(comparator), min);
123 maximum = bind(LessThan.instance(comparator), max);
124 }
125 this.rangeConstraint = and(minimum, maximum);
126 this.min = min;
127 this.max = max;
128 }
129
130 private void commonAssert(Object min, Object max) {
131 Assert.isTrue(min != null && max != null, "Min and max are required");
132 Assert.isTrue(min.getClass().equals(max.getClass()), "Min and max must be of the same class");
133 }
134
135 /**
136 * Convenience constructor for <code>int</code> ranges.
137 */
138 public Range(int min, int max) {
139 this(new Integer(min), new Integer(max));
140 }
141
142 /**
143 * Convenience constructor for <code>int</code> ranges.
144 */
145 public Range(int min, int max, boolean inclusive) {
146 this(new Integer(min), new Integer(max), inclusive);
147 }
148
149 /**
150 * Convenience constructor for <code>float</code> ranges.
151 */
152 public Range(float min, float max) {
153 this(new Float(min), new Float(max));
154 }
155
156 /**
157 * Convenience constructor for <code>float</code> ranges.
158 */
159 public Range(float min, float max, boolean inclusive) {
160 this(new Float(min), new Float(max), inclusive);
161 }
162
163 /**
164 * Convenience constructor for <code>double</code> ranges.
165 */
166 public Range(double min, double max) {
167 this(new Double(min), new Double(max));
168 }
169
170 /**
171 * Convenience constructor for <code>double</code> ranges.
172 */
173 public Range(double min, double max, boolean inclusive) {
174 this(new Double(min), new Double(max), inclusive);
175 }
176
177 public Object getMin() {
178 return min;
179 }
180
181 public Object getMax() {
182 return max;
183 }
184
185 public boolean isInclusive() {
186 return inclusive;
187 }
188
189 /**
190 * Test if the specified argument falls within the established range.
191 *
192 * @see Constraint#test(java.lang.Object)
193 */
194 public boolean test(Object argument) {
195 return this.rangeConstraint.test(argument);
196 }
197
198 public String toString() {
199 return new ToStringCreator(this).append("rangeConstraint", rangeConstraint).toString();
200 }
201
202 }