]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.databoard/src/org/simantics/databoard/util/Range.java
Re-implement URIStringUtils escape and unescape using Unicode
[simantics/platform.git] / bundles / org.simantics.databoard / src / org / simantics / databoard / util / Range.java
1 /*******************************************************************************\r
2  *  Copyright (c) 2010 Association for Decentralized Information Management in\r
3  *  Industry THTH ry.\r
4  *  All rights reserved. This program and the accompanying materials\r
5  *  are made available under the terms of the Eclipse Public License v1.0\r
6  *  which accompanies this distribution, and is available at\r
7  *  http://www.eclipse.org/legal/epl-v10.html\r
8  *\r
9  *  Contributors:\r
10  *      VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.simantics.databoard.util;
13
14 import java.util.regex.Matcher;\r
15 import java.util.regex.Pattern;\r
16
17
18
19 /**
20  * Number range.
21  *  
22  * Examples:
23  *      Inclusive "[0..100]"
24  *  Exclusive "[0..100)"
25  *  Unlimited "[..]"
26  *  No upper limit "[0..)"
27  *  No lower limit "(..0]"
28  *  Exact value "0"
29  *  Exclude all "()"
30  *
31  *      Inclusive "[0.5..100.5]"
32  *  Exclusive "[0.5..100.5)"
33  *  Unlimited "[..]"
34  *  No upper limit "[0.5..)"
35  *  No lower limit "(..0.5]"
36  *  Exact value "[0.5]"
37  *  
38  *      Inclusive "[0e..100]"
39  *  Exclusive "[0..100)"
40  *  Unlimited ""
41  *  No upper limit "[0..)"
42  *  No lower limit "(..0]"
43  *  Exact value "0"
44  *
45  * @author Toni Kalajainen <toni.kalajainen@vtt.fi>
46  */
47 public class Range {
48         
49         Limit lower; 
50         Limit upper; 
51
52         public static Range create(Byte lower, Byte upper, boolean lowerInclusive, boolean upperInclusive)
53         {
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);
57         }
58         
59         public static Range create(Integer lower, Integer upper, boolean lowerInclusive, boolean upperInclusive)
60         {
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);
64         }
65
66         public static Range create(Long lower, Long upper, boolean lowerInclusive, boolean upperInclusive)
67         {
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);
71         }
72         
73         public static Range create(Float lower, Float upper, boolean lowerInclusive, boolean upperInclusive)
74         {
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);
78         }
79         
80         public static Range create(Double lower, Double upper, boolean lowerInclusive, boolean upperInclusive)
81         {
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);
85         }
86
87         public static Range create(Byte exact)
88         {
89                 Limit l = Limit.inclusive(exact);
90                 return new Range(l, l);
91         }       
92         
93         public static Range create(Integer exact)
94         {
95                 Limit l = Limit.inclusive(exact);
96                 return new Range(l, l);
97         }       
98         
99         public static Range create(Long exact)
100         {
101                 Limit l = Limit.inclusive(exact);
102                 return new Range(l, l);
103         }       
104         
105         public static Range create(Float exact)
106         {
107                 Limit l = Limit.inclusive(exact);
108                 return new Range(l, l);
109         }       
110         
111         public static Range create(Double exact)
112         {
113                 Limit l = Limit.inclusive(exact);
114                 return new Range(l, l);
115         }       
116
117         public static Range includeAll()
118         {
119                 Limit l = Limit.nolimit();
120                 return new Range(l, l);
121         }
122         
123         public static Range excludeAll()
124         {
125                 Limit l = Limit.exclusive(0);
126                 return new Range(l, l);
127         }
128         
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);
135                 }
136                 return new Range(limit1, limit2);
137         }
138         
139         public Range(Limit lower, Limit upper)
140         {
141                 this.lower = lower;
142                 this.upper = upper;
143                 
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");
150                 }
151
152                 // Exact value
153                 if (l!=null && u!=null && l.equals(u)) {                        
154                         if (lower.isExclusive() || upper.isExclusive())
155                                 this.lower = this.upper = Limit.exclusive(0);
156                 }
157                 
158         }
159
160         public Limit getLower() {
161                 return lower;
162         }
163         
164         public Limit getUpper() {
165                 return upper;
166         }
167         
168         @Override
169         public String toString() {
170                 if (lower instanceof Limit.Nolimit && upper instanceof Limit.Nolimit) return "[..]";
171                                 
172                 // Range
173                 StringBuilder sb = new StringBuilder();
174                                 
175                 
176                 Number l = lower.getValue();
177                 Number u = upper.getValue();
178                 
179                 if (l!=null && u!=null && l.equals(u))
180                 {
181                         if (lower.isExclusive() || upper.isExclusive())
182                                 return "()";
183                         
184                         // Exact value
185                         return l.toString();
186                 }
187                 
188                 sb.append( !lower.isInclusive() ? '(' : "[" );
189                 // Range
190                 if (lower instanceof Limit.Nolimit == false) sb.append( l );
191                 sb.append( ".." );
192                 if (upper instanceof Limit.Nolimit == false) sb.append( u );
193                 sb.append( !upper.isInclusive() ? ')' : "]" );
194                 
195                 return sb.toString();
196         }
197
198         /**
199          * Double pattern
200          * 
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
203          * parsing. 
204          */
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
209                 "\\(\\)"); // () 
210         
211         public static Range valueOfUnchecked(String txt) {              
212                 try {
213                         return valueOf(txt);
214                 } catch (RangeException e) {
215                         throw new IllegalArgumentException(e);
216                 }
217         }
218
219         public static Range valueOf(String txt) 
220         throws RangeException
221         {\r
222                 Matcher m = RANGE_PATTERN.matcher(txt);
223                 if (!m.matches()) throw new RangeException("Illegal range '" + txt + "'");
224                 
225                 if ( (m.group(1)!=null) || (m.group(2)!=null) || (m.group(3)!=null) || (m.group(4)!=null) ) {
226                         
227                         Limit l1, l2;
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();
232                         } else {
233                                 try {
234                                         Long l = Long.parseLong( m.group(2) );
235                                         l1 = m.group(1).equals("[") ? Limit.inclusive(l) : Limit.exclusive(l);
236                                 } catch (NumberFormatException nfe) {
237                                         try {
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);
242                                         }
243                                 }
244                         }
245
246                         if (m.group(3)==null) {
247                                 l2 = Limit.nolimit();
248                         } else {
249                                 try {
250                                         Long l = Long.parseLong( m.group(3) );
251                                         l2 = m.group(4).equals("]") ? Limit.inclusive(l) : Limit.exclusive(l);
252                                 } catch (NumberFormatException nfe) {
253                                         try {\r
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);
258                                         }
259                                 }
260                         }
261                         
262                         return new Range(l1, l2);
263                 }
264                 
265                 if ( (m.group(5)!=null) ) {                     
266                         try {
267                                 Long l = Long.parseLong( m.group(5) );
268                                 Limit l1 = Limit.inclusive(l);
269                                 return new Range(l1, l1);
270                         } catch (NumberFormatException nfe) {
271                                 try {
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);
277                                 }
278                         }
279                 }
280                 
281                 Range result = new Range(Limit.exclusive(0), Limit.exclusive(0));
282                 return result;
283         }
284         
285         @Override
286         public boolean equals(Object obj) {
287                 if (obj instanceof Range == false) return false;
288                 Range other = (Range) obj;
289                 return 
290                         ( other.upper == null ? upper == null : other.upper.equals( upper ) ) &&
291                         ( other.lower == null ? lower == null : other.lower.equals( lower ) );
292         }
293         
294         @Override
295         public int hashCode() {
296                 return 
297                         ObjectUtils.hashCode(upper) * 13 +
298                         ObjectUtils.hashCode(lower);
299         }
300         
301         public boolean contains(Number value)
302         {
303                 if (lower instanceof Limit.Nolimit==false) 
304                 {
305                         int compare = NumberComparator.INSTANCE.compare(lower.getValue(), value);
306                         if (compare==0 && lower.isExclusive()) return false;
307                         if (compare<0) return false;
308                 }
309                                 
310                 if (upper instanceof Limit.Nolimit==false) 
311                 {
312                         int compare = NumberComparator.INSTANCE.compare(upper.getValue(), value);
313                         if (compare==0 && upper.isExclusive()) return false;
314                         if (compare>0) return false;
315                 }
316                 
317                 return true;
318         }
319         
320         
321 }
322