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 }