1 |
/* SetOfIntegerSyntax.java -- |
/* SetOfIntegerSyntax.java -- |
2 |
Copyright (C) 2003, 2004 Free Software Foundation, Inc. |
Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. |
3 |
|
|
4 |
This file is part of GNU Classpath. |
This file is part of GNU Classpath. |
5 |
|
|
45 |
import java.util.Comparator; |
import java.util.Comparator; |
46 |
|
|
47 |
/** |
/** |
48 |
* @author Michael Koch |
* <code>SetOfIntegerSyntax</code> is the abstract base class of all attribute |
49 |
|
* classes which provide a set of non-negative integers as value (e.g. the |
50 |
|
* page ranges to print) represented as single values or ranges of values. |
51 |
|
* <p> |
52 |
|
* A <code>SetOfIntegerSyntax</code> instance consists of an integer array of |
53 |
|
* ranges. Ranges may have the same lower and upper bound representing a single |
54 |
|
* integer value. Ranges with a lower bound greater than the upper bound are |
55 |
|
* null ranges and discarded. Ranges may overlap in their values. In no case |
56 |
|
* negative integers are allowed. |
57 |
|
* </p> |
58 |
|
* <p> |
59 |
|
* There are several constructors available: |
60 |
|
* <ul> |
61 |
|
* <li><code>SetOfIntegerSyntax(int member)</code><br> |
62 |
|
* Constructor for an instance with only one integer value. |
63 |
|
* </li><br> |
64 |
|
* <li><code>SetOfIntegerSyntax(int lowerBound, int upperBound)</code><br> |
65 |
|
* Constructor for an instance with one range of integer values. |
66 |
|
* </li><br> |
67 |
|
* <li><code>SetOfIntegerSyntax(int[][] members)</code><br> |
68 |
|
* Flexible constructor for an instance with several single integer values |
69 |
|
* and/or several ranges of integer values. The allowed array form is an |
70 |
|
* array of integer arrays of length one or two. Examples are: |
71 |
|
* <code>int[0][]</code> for empty set of integers, <code>int[][] {{1}}</code> |
72 |
|
* , <code>int[][] {{1,5}}</code>, <code>int[][] {{1,5},{7,9}}</code>, |
73 |
|
* <code>int[][] {{3,7},{19}}</code>. |
74 |
|
* </li><br> |
75 |
|
* <li><code>SetOfIntegerSyntax(String s)</code><br> |
76 |
|
* Flexible constructor for an instance with several single integer values |
77 |
|
* and/or several ranges of integer values. The allowed String instance have |
78 |
|
* to be a String with comma separated ranges of integer values or single |
79 |
|
* values. Ranges are represented by two integer with a hypen (-) or colon (:) |
80 |
|
* between the lower and upper bound value. Whitespace characters are ignored. |
81 |
|
* Examples are: <code>""</code> for an empty set of integers, |
82 |
|
* <code>"1"</code>, <code>"1-5"</code>, <code>"1-5,7-9"</code>, |
83 |
|
* <code>"3-7,19"</code> and <code>"1:2,4"</code>. |
84 |
|
* </li> |
85 |
|
* </ul> |
86 |
|
* </p> |
87 |
|
* <p> |
88 |
|
* <b>Internal storage:</b><br> |
89 |
|
* The set of integers are stored internally in a normalized array form. |
90 |
|
* In the normalized array form the set of integer ranges are represented |
91 |
|
* in as few ranges as possible and overlapping ranges are merged. The ranges |
92 |
|
* are always represented as an integer array of length two with ranges |
93 |
|
* stored in {lower bound, upper bound} form. The ranges are stored in |
94 |
|
* ascending order, without any null ranges. |
95 |
|
* </p> |
96 |
|
* @author Michael Koch (konqueror@gmx.de) |
97 |
*/ |
*/ |
98 |
public abstract class SetOfIntegerSyntax |
public abstract class SetOfIntegerSyntax |
99 |
implements Cloneable, Serializable |
implements Cloneable, Serializable |
144 |
* |
* |
145 |
* @param member the member value |
* @param member the member value |
146 |
* |
* |
147 |
* @exception IllegalArgumentException if member is < 0 |
* @exception IllegalArgumentException if member is < 0 |
148 |
*/ |
*/ |
149 |
protected SetOfIntegerSyntax(int member) |
protected SetOfIntegerSyntax(int member) |
150 |
{ |
{ |
157 |
/** |
/** |
158 |
* Creates a <code>SetOfIntegerSyntax</code> object. |
* Creates a <code>SetOfIntegerSyntax</code> object. |
159 |
* |
* |
160 |
* @param members the members to use in this set |
* @param members the members to use in this set. If |
161 |
|
* <code>null</code> an empty set is created. |
162 |
* |
* |
163 |
* @exception IllegalArgumentException if any element is invalid |
* @exception IllegalArgumentException if any element is invalid |
164 |
* @exception NullPointerException if any element of members is null |
* @exception NullPointerException if any element of members is null |
225 |
return readAny; |
return readAny; |
226 |
} |
} |
227 |
|
|
228 |
|
/** |
229 |
|
* Creates a <code>SetOfIntegerSyntax</code> object. |
230 |
|
* |
231 |
|
* @param s the members to use in this set in string form. If |
232 |
|
* <code>null</code> an empty set is created. |
233 |
|
* |
234 |
|
* @exception IllegalArgumentException if any element is invalid |
235 |
|
*/ |
236 |
protected SetOfIntegerSyntax(String s) |
protected SetOfIntegerSyntax(String s) |
237 |
{ |
{ |
238 |
ArrayList vals = new ArrayList(); |
if (s == null) |
239 |
|
this.members = normalize(new int[0][], 0); |
240 |
StringCharacterIterator it = new StringCharacterIterator(s); |
else |
241 |
|
{ |
242 |
while (true) |
ArrayList vals = new ArrayList(); |
243 |
{ |
|
244 |
// Skip whitespace. |
StringCharacterIterator it = new StringCharacterIterator(s); |
245 |
if (skipWhitespace(it)) |
|
246 |
break; |
while (true) |
|
|
|
|
// Parse integer. |
|
|
int index = it.getIndex(); |
|
|
if (! skipNumber(it)) |
|
|
throw new IllegalArgumentException(); |
|
|
int[] item = new int[2]; |
|
|
item[0] = Integer.parseInt(s.substring(index, it.getIndex())); |
|
|
|
|
|
if (! skipWhitespace(it)) |
|
247 |
{ |
{ |
248 |
char c = it.current(); |
// Skip whitespace. |
249 |
if (c == ':' || c == '-') |
if (skipWhitespace(it)) |
250 |
|
break; |
251 |
|
|
252 |
|
// Parse integer. |
253 |
|
int index = it.getIndex(); |
254 |
|
if (! skipNumber(it)) |
255 |
|
throw new IllegalArgumentException(); |
256 |
|
int[] item = new int[2]; |
257 |
|
item[0] = Integer.parseInt(s.substring(index, it.getIndex())); |
258 |
|
|
259 |
|
if (! skipWhitespace(it)) |
260 |
{ |
{ |
261 |
it.next(); |
char c = it.current(); |
262 |
if (skipWhitespace(it)) |
if (c == ':' || c == '-') |
263 |
throw new IllegalArgumentException(); |
{ |
264 |
index = it.getIndex(); |
it.next(); |
265 |
if (! skipNumber(it)) |
if (skipWhitespace(it)) |
266 |
throw new IllegalArgumentException(); |
throw new IllegalArgumentException(); |
267 |
item[1] = Integer.parseInt(s.substring(index, it.getIndex())); |
index = it.getIndex(); |
268 |
|
if (! skipNumber(it)) |
269 |
|
throw new IllegalArgumentException(); |
270 |
|
item[1] = Integer.parseInt(s.substring(index, it.getIndex())); |
271 |
|
} |
272 |
|
else |
273 |
|
item[1] = item[0]; |
274 |
} |
} |
275 |
else |
else |
276 |
item[1] = item[0]; |
item[1] = item[0]; |
277 |
|
|
278 |
|
if (item[0] <= item[1]) |
279 |
|
vals.add(item); |
280 |
|
|
281 |
|
if (skipWhitespace(it)) |
282 |
|
break; |
283 |
|
if (it.current() != ',') |
284 |
|
throw new IllegalArgumentException(); |
285 |
|
it.next(); |
286 |
} |
} |
|
else |
|
|
item[1] = item[0]; |
|
|
|
|
|
if (item[0] <= item[1]) |
|
|
vals.add(item); |
|
287 |
|
|
288 |
if (skipWhitespace(it)) |
members = normalize((int[][]) vals.toArray(new int[0][]), vals.size()); |
|
break; |
|
|
if (it.current() != ',') |
|
|
throw new IllegalArgumentException(); |
|
|
it.next(); |
|
289 |
} |
} |
|
|
|
|
members = normalize((int[][]) vals.toArray(new int[0][]), vals.size()); |
|
290 |
} |
} |
291 |
|
|
292 |
/** |
/** |
310 |
} |
} |
311 |
|
|
312 |
/** |
/** |
313 |
* Checks if this set contains value. |
* Checks if this set contains the given value. |
314 |
* |
* |
315 |
* @param value the value to test for |
* @param value the value to test for |
316 |
* |
* |
331 |
} |
} |
332 |
|
|
333 |
/** |
/** |
334 |
* Checks if this set contains value. |
* Checks if this set contains the given value. |
335 |
* |
* |
336 |
* @param value the value to test for |
* @param value the value to test for |
337 |
* |
* |
343 |
} |
} |
344 |
|
|
345 |
/** |
/** |
346 |
* Tests of obj is equal to this object. |
* Tests if the given object is equal to this object. |
347 |
* |
* |
348 |
* @param obj the object to test |
* @param obj the object to test |
349 |
* |
* |
368 |
/** |
/** |
369 |
* Returns an array describing the members included in this set. |
* Returns an array describing the members included in this set. |
370 |
* |
* |
371 |
* @return the array with the members |
* @return The members in normalized array form. |
372 |
*/ |
*/ |
373 |
public int[][] getMembers() |
public int[][] getMembers() |
374 |
{ |
{ |
378 |
/** |
/** |
379 |
* Returns the hashcode for this object. |
* Returns the hashcode for this object. |
380 |
* |
* |
381 |
* @return the hashcode |
* @return The hashcode. |
382 |
*/ |
*/ |
383 |
public int hashCode() |
public int hashCode() |
384 |
{ |
{ |
393 |
* |
* |
394 |
* @param x an integer value |
* @param x an integer value |
395 |
* |
* |
396 |
* @return the next value |
* @return The next smallest integer value, or <code>-1</code> if there |
397 |
|
* is no greater integer in the set. |
398 |
*/ |
*/ |
399 |
public int next(int x) |
public int next(int x) |
400 |
{ |
{ |
412 |
|
|
413 |
/** |
/** |
414 |
* Returns the string representation for this object. |
* Returns the string representation for this object. |
415 |
|
* The value is a zero length string for an empty set, or a comma seperated |
416 |
|
* list of ranges and single values in the form <code>"1-2,5-7,10"</code>. |
417 |
* |
* |
418 |
* @return the string representation |
* @return The string representation. |
419 |
*/ |
*/ |
420 |
public String toString() |
public String toString() |
421 |
{ |
{ |