View Javadoc
1 package jsdsi; 2 3 import java.math.BigInteger; 4 import java.util.Iterator; 5 6 import jsdsi.sexp.Sexp; 7 import jsdsi.sexp.SexpParseException; 8 import jsdsi.sexp.SexpUtil; 9 10 /*** 11 * A tag that specifies a range of allowed values. 12 * 13 * @author Sameer Ajmani 14 * @author Sean Radford 15 * @version $Revision: 1.3.2.1 $ $Date: 2005/11/08 03:12:52 $ 16 **/ 17 public class RangeTag extends ExprTag { 18 19 private static final long serialVersionUID = -4840725353015683369L; 20 21 /*** 22 * The ordering parameter: alpha, numeric, time, binary, date. 23 */ 24 private transient final RangeOrdering ordering; 25 26 /*** 27 * The upper limit of this range tag. 28 */ 29 private transient final String upperLimit; 30 31 /*** 32 * Is the upper limit strict? 33 */ 34 private transient final boolean strictUpper; 35 36 /*** 37 * The lower limit of this range tag. 38 */ 39 private transient final String lowerLimit; 40 41 /*** 42 * Is the lower limit strict? 43 */ 44 private transient final boolean strictLower; 45 46 /*** 47 * Creates a new <code>RangeTag</code> from a given lower and upper 48 * limit. 49 * 50 * @param o defines the ordering. 51 * @param u upper limit. 52 * @param su is the upper limit strict? 53 * @param l lower limit. 54 * @param sl is the lower limit strict? 55 */ 56 public RangeTag(String o, String u, boolean su, String l, boolean sl) { 57 assert(o != null) : "null ordering"; 58 assert(u != null) : "null upper bound"; // FIXME: allow! 59 assert(l != null) : "null lower bound"; // FIXME: allow! 60 ordering = RangeOrdering.parse(o); 61 assert(ordering.convert(l).compareTo(ordering.convert(u)) <= 0) 62 : "lower bound must be less than or equal to upper bound"; 63 upperLimit = u; 64 strictUpper = su; 65 lowerLimit = l; 66 strictLower = sl; 67 } 68 69 /*** 70 * @see jsdsi.Tag#intersect(Tag) 71 **/ 72 public Tag intersect(Tag that) 73 { 74 if (that instanceof RangeTag) { 75 return intersect((RangeTag)that); 76 } 77 if (that instanceof StringTag) { 78 return intersect((StringTag)that); 79 } 80 if (that instanceof SetTag) { 81 return that.intersect(this); 82 } 83 return Tag.NULL_TAG; 84 } 85 86 public Tag intersect(StringTag that) 87 { 88 if (ordering.contains(this, that.getValue())) { 89 return that; 90 } 91 return Tag.NULL_TAG; 92 } 93 94 public Tag intersect(RangeTag that) 95 { 96 if (this.ordering != that.ordering) { 97 return Tag.NULL_TAG; 98 } 99 return ordering.intersect(this, that); 100 } 101 102 /*** 103 * @see java.lang.Object#equals(Object) 104 */ 105 public boolean equals(Object that) { 106 if (that instanceof RangeTag) { 107 RangeTag r = (RangeTag) that; 108 return this.ordering == r.ordering 109 && this.upperLimit.equals(r.upperLimit) 110 && this.strictUpper == r.strictUpper 111 && this.lowerLimit.equals(r.lowerLimit) 112 && this.strictLower == r.strictLower; 113 } 114 return false; 115 } 116 117 /*** 118 * @see java.lang.Object#hashCode() 119 */ 120 public int hashCode() { 121 return ordering.hashCode() 122 ^ upperLimit.hashCode() 123 ^ lowerLimit.hashCode() 124 ^ (strictUpper ? 1 : 0) 125 ^ (strictLower ? 1 : 0); 126 } 127 128 /*** 129 * @return the ordering of this <code>RangeTag</code>; one of: 130 * <code>"alpha" | "numeric" | "time" | "binary" | "date"</code>. 131 */ 132 public String getOrdering() { 133 return ordering.toString(); 134 } 135 136 /*** 137 * @return the upper limit of this <code>RangeTag</code>. 138 */ 139 public String getUpperLimit() { 140 return upperLimit; 141 } 142 143 /*** 144 * @return the lower limit of this <code>RangeTag</code>. 145 */ 146 public String getLowerLimit() { 147 return lowerLimit; 148 } 149 150 /*** 151 * @return <code>true</code> if the upper limit of this 152 * <code>RangeTag</code> is strict, <code>false</code> otherwise. 153 */ 154 public boolean upperIsStrict() { 155 return strictUpper; 156 } 157 158 /*** 159 * @return <code>true</code> if the lower limit of this 160 * <code>RangeTag</code> is strict, <code>false</code> otherwise. 161 */ 162 public boolean lowerIsStrict() { 163 return strictLower; 164 } 165 166 public Sexp toTagSexp() { 167 Sexp[] ss = new Sexp[6]; 168 ss[0] = SexpUtil.toSexp("range"); 169 ss[1] = SexpUtil.toSexp(getOrdering()); 170 ss[2] = SexpUtil.toSexp(lowerIsStrict() ? "g" : "ge"); 171 ss[3] = SexpUtil.toSexp(getLowerLimit()); 172 ss[4] = SexpUtil.toSexp(upperIsStrict() ? "l" : "le"); 173 ss[5] = SexpUtil.toSexp(getUpperLimit()); 174 return SexpUtil.toSexp("*", ss); 175 } 176 177 static RangeTag parseRangeTag(Iterator tbody) throws SexpParseException { 178 String ordering = SexpUtil.getNextString(tbody, "range ordering"); 179 // lower strictness and limit 180 String gte = SexpUtil.getNextString(tbody, "range gte"); 181 boolean strictLower = gte.equals("g"); 182 if (!strictLower && !gte.equals("ge")) 183 throw new SexpParseException( 184 "range lower strictness is not 'g' or 'ge': " + gte); 185 String lowerLimit = SexpUtil.getNextString(tbody, "range lower limit"); 186 // upper strictness and limit 187 String lte = SexpUtil.getNextString(tbody, "range lte"); 188 boolean strictUpper = lte.equals("l"); 189 if (!strictUpper && !lte.equals("le")) 190 throw new SexpParseException( 191 "range upper strictness is not 'l' or 'le': " + lte); 192 String upperLimit = SexpUtil.getNextString(tbody, "range upper limit"); 193 SexpUtil.checkDone(tbody, "range tag"); 194 return new RangeTag(ordering, 195 upperLimit, 196 strictUpper, 197 lowerLimit, 198 strictLower); 199 } 200 private static abstract class RangeOrdering { 201 public abstract Comparable convert(String s); 202 public boolean contains(RangeTag r, String s) 203 { 204 assert(r.ordering == this); 205 try { 206 Comparable val = convert(s); 207 int lc = convert(r.lowerLimit).compareTo(val); 208 if (lc > 0 || (lc == 0 && r.strictLower)) { 209 return false; 210 } 211 int uc = convert(r.upperLimit).compareTo(val); 212 if (uc < 0 || (uc == 0 && r.strictUpper)) { 213 return false; 214 } 215 return true; 216 } catch (IllegalArgumentException e) { 217 // convert() failed, so fail safely 218 return false; 219 } 220 } 221 public Tag intersect(RangeTag r, RangeTag that) 222 { 223 assert(r.ordering == this); 224 assert(that.ordering == this); 225 try { 226 String ll, ul; 227 boolean sl, su; 228 int lc = convert(r.lowerLimit).compareTo 229 (convert(that.lowerLimit)); 230 if (lc > 0 || (lc == 0 && r.strictLower)) { 231 ll = r.lowerLimit; 232 sl = r.strictLower; 233 } else { 234 ll = that.lowerLimit; 235 sl = that.strictLower; 236 } 237 int uc = convert(r.upperLimit).compareTo 238 (convert(that.upperLimit)); 239 if (uc < 0 || (uc == 0 && r.strictUpper)) { 240 ul = r.upperLimit; 241 su = r.strictUpper; 242 } else { 243 ul = that.upperLimit; 244 su = that.strictUpper; 245 } 246 if (convert(ll).compareTo(convert(ul)) > 0) { 247 // lower limit greater than upper limit 248 return Tag.NULL_TAG; 249 } 250 return new RangeTag(this.toString(), ul, su, ll, sl); 251 } catch (IllegalArgumentException e) { 252 // convert() failed, so fail safely 253 return Tag.NULL_TAG; 254 } 255 } 256 257 public static RangeOrdering ALPHA = new RangeOrdering() { 258 public Comparable convert(String s) 259 { 260 return s; 261 } 262 public String toString() 263 { 264 return "alpha"; 265 } 266 }; 267 268 public static RangeOrdering BINARY = new RangeOrdering() { 269 public Comparable convert(String s) 270 { 271 return new BigInteger(s.getBytes()); 272 } 273 public String toString() 274 { 275 return "binary"; 276 } 277 }; 278 279 public static RangeOrdering NUMERIC = new RangeOrdering() { 280 public Comparable convert(String s) 281 { 282 try { 283 return new Float(Float.parseFloat(s)); 284 } catch (NumberFormatException e) { 285 throw new IllegalArgumentException("bad float:"+s); 286 } 287 } 288 public String toString() 289 { 290 return "numeric"; 291 } 292 }; 293 294 public static RangeOrdering TIME = new RangeOrdering() { 295 public Comparable convert(String s) 296 { 297 try { 298 return SexpUtil.parseDate(s); 299 } catch (SexpParseException e) { 300 throw new IllegalArgumentException("bad date: "+s); 301 } 302 } 303 public String toString() 304 { 305 return "time"; 306 } 307 }; 308 309 public static RangeOrdering DATE = new RangeOrdering() { 310 public Comparable convert(String s) 311 { 312 try { 313 return SexpUtil.parseDate(s); 314 } catch (SexpParseException e) { 315 throw new IllegalArgumentException("bad date: "+s); 316 } 317 } 318 public String toString() 319 { 320 return "date"; 321 } 322 }; 323 324 public static RangeOrdering parse(String name) 325 { 326 if (name.equals("alpha")) { 327 return ALPHA; 328 } 329 if (name.equals("numeric")) { 330 return NUMERIC; 331 } 332 if (name.equals("time")) { 333 return TIME; 334 } 335 if (name.equals("binary")) { 336 return BINARY; 337 } 338 if (name.equals("date")) { 339 return DATE; 340 } 341 throw new IllegalArgumentException(name); 342 } 343 } 344 }

This page was automatically generated by Maven