1 /*******************************************************************************
2 * Copyright (c) 2010 Association for Decentralized Information Management in
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.databoard.util;
14 import java.util.regex.Matcher;
15 import java.util.regex.Pattern;
23 * Inclusive "[0..100]"
24 * Exclusive "[0..100)"
26 * No upper limit "[0..)"
27 * No lower limit "(..0]"
31 * Inclusive "[0.5..100.5]"
32 * Exclusive "[0.5..100.5)"
34 * No upper limit "[0.5..)"
35 * No lower limit "(..0.5]"
38 * Inclusive "[0e..100]"
39 * Exclusive "[0..100)"
41 * No upper limit "[0..)"
42 * No lower limit "(..0]"
45 * @author Toni Kalajainen <toni.kalajainen@vtt.fi>
52 public static Range create(Byte lower, Byte upper, boolean lowerInclusive, boolean upperInclusive)
54 Limit ll = lowerInclusive ? Limit.inclusive(lower) : Limit.exclusive(lower);
55 Limit ul = upperInclusive ? Limit.inclusive(upper) : Limit.exclusive(upper);
56 return new Range(ll, ul);
59 public static Range create(Integer lower, Integer upper, boolean lowerInclusive, boolean upperInclusive)
61 Limit ll = lowerInclusive ? Limit.inclusive(lower) : Limit.exclusive(lower);
62 Limit ul = upperInclusive ? Limit.inclusive(upper) : Limit.exclusive(upper);
63 return new Range(ll, ul);
66 public static Range create(Long lower, Long upper, boolean lowerInclusive, boolean upperInclusive)
68 Limit ll = lowerInclusive ? Limit.inclusive(lower) : Limit.exclusive(lower);
69 Limit ul = upperInclusive ? Limit.inclusive(upper) : Limit.exclusive(upper);
70 return new Range(ll, ul);
73 public static Range create(Float lower, Float upper, boolean lowerInclusive, boolean upperInclusive)
75 Limit ll = lowerInclusive ? Limit.inclusive(lower) : Limit.exclusive(lower);
76 Limit ul = upperInclusive ? Limit.inclusive(upper) : Limit.exclusive(upper);
77 return new Range(ll, ul);
80 public static Range create(Double lower, Double upper, boolean lowerInclusive, boolean upperInclusive)
82 Limit ll = lowerInclusive ? Limit.inclusive(lower) : Limit.exclusive(lower);
83 Limit ul = upperInclusive ? Limit.inclusive(upper) : Limit.exclusive(upper);
84 return new Range(ll, ul);
87 public static Range create(Byte exact)
89 Limit l = Limit.inclusive(exact);
90 return new Range(l, l);
93 public static Range create(Integer exact)
95 Limit l = Limit.inclusive(exact);
96 return new Range(l, l);
99 public static Range create(Long exact)
101 Limit l = Limit.inclusive(exact);
102 return new Range(l, l);
105 public static Range create(Float exact)
107 Limit l = Limit.inclusive(exact);
108 return new Range(l, l);
111 public static Range create(Double exact)
113 Limit l = Limit.inclusive(exact);
114 return new Range(l, l);
117 public static Range includeAll()
119 Limit l = Limit.nolimit();
120 return new Range(l, l);
123 public static Range excludeAll()
125 Limit l = Limit.exclusive(0);
126 return new Range(l, l);
129 public static Range between(Limit limit1, Limit limit2) {
130 Number l = limit1.getValue();
131 Number u = limit2.getValue();
132 if (l!=null && u!=null) {
133 if (NumberComparator.INSTANCE.compare(l, u)<0)
134 return new Range(limit2, limit1);
136 return new Range(limit1, limit2);
139 public Range(Limit lower, Limit upper)
144 // Ensure lower < upper
145 Number l = lower.getValue();
146 Number u = upper.getValue();
147 if (l!=null && u!=null) {
148 if (NumberComparator.INSTANCE.compare(l, u)<0)
149 throw new IllegalArgumentException("Lower limit must be less-or-equal to upper limit");
153 if (l!=null && u!=null && l.equals(u)) {
154 if (lower.isExclusive() || upper.isExclusive())
155 this.lower = this.upper = Limit.exclusive(0);
160 public Limit getLower() {
164 public Limit getUpper() {
169 public String toString() {
170 if (lower instanceof Limit.Nolimit && upper instanceof Limit.Nolimit) return "[..]";
173 StringBuilder sb = new StringBuilder();
176 Number l = lower.getValue();
177 Number u = upper.getValue();
179 if (l!=null && u!=null && l.equals(u))
181 if (lower.isExclusive() || upper.isExclusive())
188 sb.append( !lower.isInclusive() ? '(' : "[" );
190 if (lower instanceof Limit.Nolimit == false) sb.append( l );
192 if (upper instanceof Limit.Nolimit == false) sb.append( u );
193 sb.append( !upper.isInclusive() ? ')' : "]" );
195 return sb.toString();
201 * This pattern is not perfect as it accepts strings such as
202 * "e0", "", and ".", but its good enough as Double class does the final
205 // static Pattern DOUBLE_PATTERN = Pattern.compile("-?+\\d*(?:\\.\\d*)?(?:[eE]\\d++)?");
206 static Pattern RANGE_PATTERN = Pattern.compile(
207 "(?:([\\(\\[])(-?\\d*(?:\\.\\d*)?(?:[eE]-?\\d+)?)??\\.\\.(-?\\d*(?:\\.\\d*)?(?:[eE]-?\\d+)?)??([\\)\\]]))|"+ // [x..y] [x..y) (x..y)
208 "(-?+\\d*(?:\\.\\d*)?(?:[eE]-?\\d+)?)|"+ // x
211 public static Range valueOfUnchecked(String txt) {
214 } catch (RangeException e) {
215 throw new IllegalArgumentException(e);
219 public static Range valueOf(String txt)
220 throws RangeException
222 Matcher m = RANGE_PATTERN.matcher(txt);
223 if (!m.matches()) throw new RangeException("Illegal range '" + txt + "'");
225 if ( (m.group(1)!=null) || (m.group(2)!=null) || (m.group(3)!=null) || (m.group(4)!=null) ) {
228 if (m.group(2)==null && m.group(3)==null) {
229 return new Range(Limit.nolimit(), Limit.nolimit());
230 } else if (m.group(2)==null) {
231 l1 = Limit.nolimit();
234 Long l = Long.parseLong( m.group(2) );
235 l1 = m.group(1).equals("[") ? Limit.inclusive(l) : Limit.exclusive(l);
236 } catch (NumberFormatException nfe) {
238 Double d = Double.parseDouble( m.group(2) );
239 l1 = m.group(1).equals("[") ? Limit.inclusive(d) : Limit.exclusive(d);
240 } catch (NumberFormatException e) {
241 throw new RangeException(e);
246 if (m.group(3)==null) {
247 l2 = Limit.nolimit();
250 Long l = Long.parseLong( m.group(3) );
251 l2 = m.group(4).equals("]") ? Limit.inclusive(l) : Limit.exclusive(l);
252 } catch (NumberFormatException nfe) {
254 Double d = Double.parseDouble( m.group(3) );
255 l2 = m.group(4).equals("]") ? Limit.inclusive(d) : Limit.exclusive(d);
256 } catch (NumberFormatException e) {
257 throw new RangeException(e);
262 return new Range(l1, l2);
265 if ( (m.group(5)!=null) ) {
267 Long l = Long.parseLong( m.group(5) );
268 Limit l1 = Limit.inclusive(l);
269 return new Range(l1, l1);
270 } catch (NumberFormatException nfe) {
272 Double d = Double.parseDouble( m.group(5) );
273 Limit l1 = Limit.inclusive(d);
274 return new Range(l1, l1);
275 } catch (NumberFormatException e) {
276 throw new RangeException(e);
281 Range result = new Range(Limit.exclusive(0), Limit.exclusive(0));
286 public boolean equals(Object obj) {
287 if (obj instanceof Range == false) return false;
288 Range other = (Range) obj;
290 ( other.upper == null ? upper == null : other.upper.equals( upper ) ) &&
291 ( other.lower == null ? lower == null : other.lower.equals( lower ) );
295 public int hashCode() {
297 ObjectUtils.hashCode(upper) * 13 +
298 ObjectUtils.hashCode(lower);
301 public boolean contains(Number value)
303 if (lower instanceof Limit.Nolimit==false)
305 int compare = NumberComparator.INSTANCE.compare(lower.getValue(), value);
306 if (compare==0 && lower.isExclusive()) return false;
307 if (compare<0) return false;
310 if (upper instanceof Limit.Nolimit==false)
312 int compare = NumberComparator.INSTANCE.compare(upper.getValue(), value);
313 if (compare==0 && upper.isExclusive()) return false;
314 if (compare>0) return false;