History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/javax/print/attribute/SetOfIntegerSyntax.java (1 of 18352 files). Show all

Unified · Split

java/pkg/javax/print/attribute/SetOfIntegerSyntax.java+558−0
@@ -0,0 +1,558 @@
1+/*
2+ * Copyright (c) 2000, 2004, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+
27+package javax.print.attribute;
28+
29+import java.io.Serializable;
30+import java.util.Vector;
31+
32+/**
33+ * Class SetOfIntegerSyntax is an abstract base class providing the common
34+ * implementation of all attributes whose value is a set of nonnegative
35+ * integers. This includes attributes whose value is a single range of integers
36+ * and attributes whose value is a set of ranges of integers.
37+ * <P>
38+ * You can construct an instance of SetOfIntegerSyntax by giving it in "string
39+ * form." The string consists of zero or more comma-separated integer groups.
40+ * Each integer group consists of either one integer, two integers separated by
41+ * a hyphen (<CODE>-</CODE>), or two integers separated by a colon
42+ * (<CODE>:</CODE>). Each integer consists of one or more decimal digits
43+ * (<CODE>0</CODE> through <CODE>9</CODE>). Whitespace characters cannot
44+ * appear within an integer but are otherwise ignored. For example:
45+ * <CODE>""</CODE>, <CODE>"1"</CODE>, <CODE>"5-10"</CODE>, <CODE>"1:2,
46+ * 4"</CODE>.
47+ * <P>
48+ * You can also construct an instance of SetOfIntegerSyntax by giving it in
49+ * "array form." Array form consists of an array of zero or more integer groups
50+ * where each integer group is a length-1 or length-2 array of
51+ * <CODE>int</CODE>s; for example, <CODE>int[0][]</CODE>,
52+ * <CODE>int[][]{{1}}</CODE>, <CODE>int[][]{{5,10}}</CODE>,
53+ * <CODE>int[][]{{1,2},{4}}</CODE>.
54+ * <P>
55+ * In both string form and array form, each successive integer group gives a
56+ * range of integers to be included in the set. The first integer in each group
57+ * gives the lower bound of the range; the second integer in each group gives
58+ * the upper bound of the range; if there is only one integer in the group, the
59+ * upper bound is the same as the lower bound. If the upper bound is less than
60+ * the lower bound, it denotes a null range (no values). If the upper bound is
61+ * equal to the lower bound, it denotes a range consisting of a single value. If
62+ * the upper bound is greater than the lower bound, it denotes a range
63+ * consisting of more than one value. The ranges may appear in any order and are
64+ * allowed to overlap. The union of all the ranges gives the set's contents.
65+ * Once a SetOfIntegerSyntax instance is constructed, its value is immutable.
66+ * <P>
67+ * The SetOfIntegerSyntax object's value is actually stored in "<I>canonical</I>
68+ * array form." This is the same as array form, except there are no null ranges;
69+ * the members of the set are represented in as few ranges as possible (i.e.,
70+ * overlapping ranges are coalesced); the ranges appear in ascending order; and
71+ * each range is always represented as a length-two array of <CODE>int</CODE>s
72+ * in the form {lower bound, upper bound}. An empty set is represented as a
73+ * zero-length array.
74+ * <P>
75+ * Class SetOfIntegerSyntax has operations to return the set's members in
76+ * canonical array form, to test whether a given integer is a member of the
77+ * set, and to iterate through the members of the set.
78+ * <P>
79+ *
80+ * @author David Mendenhall
81+ * @author Alan Kaminsky
82+ */
83+public abstract class SetOfIntegerSyntax implements Serializable, Cloneable {
84+
85+ private static final long serialVersionUID = 3666874174847632203L;
86+
87+ /**
88+ * This set's members in canonical array form.
89+ * @serial
90+ */
91+ private int[][] members;
92+
93+
94+ /**
95+ * Construct a new set-of-integer attribute with the given members in
96+ * string form.
97+ *
98+ * @param members Set members in string form. If null, an empty set is
99+ * constructed.
100+ *
101+ * @exception IllegalArgumentException
102+ * (Unchecked exception) Thrown if <CODE>members</CODE> does not
103+ * obey the proper syntax.
104+ */
105+ protected SetOfIntegerSyntax(String members) {
106+ this.members = parse (members);
107+ }
108+
109+ /**
110+ * Parse the given string, returning canonical array form.
111+ */
112+ private static int[][] parse(String members) {
113+ // Create vector to hold int[] elements, each element being one range
114+ // parsed out of members.
115+ Vector theRanges = new Vector();
116+
117+ // Run state machine over members.
118+ int n = (members == null ? 0 : members.length());
119+ int i = 0;
120+ int state = 0;
121+ int lb = 0;
122+ int ub = 0;
123+ char c;
124+ int digit;
125+ while (i < n) {
126+ c = members.charAt(i ++);
127+ switch (state) {
128+
129+ case 0: // Before first integer in first group
130+ if (Character.isWhitespace(c)) {
131+ state = 0;
132+ }
133+ else if ((digit = Character.digit(c, 10)) != -1) {
134+ lb = digit;
135+ state = 1;
136+ } else {
137+ throw new IllegalArgumentException();
138+ }
139+ break;
140+
141+ case 1: // In first integer in a group
142+ if (Character.isWhitespace(c)){
143+ state = 2;
144+ } else if ((digit = Character.digit(c, 10)) != -1) {
145+ lb = 10 * lb + digit;
146+ state = 1;
147+ } else if (c == '-' || c == ':') {
148+ state = 3;
149+ } else if (c == ',') {
150+ accumulate (theRanges, lb, lb);
151+ state = 6;
152+ } else {
153+ throw new IllegalArgumentException();
154+ }
155+ break;
156+
157+ case 2: // After first integer in a group
158+ if (Character.isWhitespace(c)) {
159+ state = 2;
160+ }
161+ else if (c == '-' || c == ':') {
162+ state = 3;
163+ }
164+ else if (c == ',') {
165+ accumulate(theRanges, lb, lb);
166+ state = 6;
167+ } else {
168+ throw new IllegalArgumentException();
169+ }
170+ break;
171+
172+ case 3: // Before second integer in a group
173+ if (Character.isWhitespace(c)) {
174+ state = 3;
175+ } else if ((digit = Character.digit(c, 10)) != -1) {
176+ ub = digit;
177+ state = 4;
178+ } else {
179+ throw new IllegalArgumentException();
180+ }
181+ break;
182+
183+ case 4: // In second integer in a group
184+ if (Character.isWhitespace(c)) {
185+ state = 5;
186+ } else if ((digit = Character.digit(c, 10)) != -1) {
187+ ub = 10 * ub + digit;
188+ state = 4;
189+ } else if (c == ',') {
190+ accumulate(theRanges, lb, ub);
191+ state = 6;
192+ } else {
193+ throw new IllegalArgumentException();
194+ }
195+ break;
196+
197+ case 5: // After second integer in a group
198+ if (Character.isWhitespace(c)) {
199+ state = 5;
200+ } else if (c == ',') {
201+ accumulate(theRanges, lb, ub);
202+ state = 6;
203+ } else {
204+ throw new IllegalArgumentException();
205+ }
206+ break;
207+
208+ case 6: // Before first integer in second or later group
209+ if (Character.isWhitespace(c)) {
210+ state = 6;
211+ } else if ((digit = Character.digit(c, 10)) != -1) {
212+ lb = digit;
213+ state = 1;
214+ } else {
215+ throw new IllegalArgumentException();
216+ }
217+ break;
218+ }
219+ }
220+
221+ // Finish off the state machine.
222+ switch (state) {
223+ case 0: // Before first integer in first group
224+ break;
225+ case 1: // In first integer in a group
226+ case 2: // After first integer in a group
227+ accumulate(theRanges, lb, lb);
228+ break;
229+ case 4: // In second integer in a group
230+ case 5: // After second integer in a group
231+ accumulate(theRanges, lb, ub);
232+ break;
233+ case 3: // Before second integer in a group
234+ case 6: // Before first integer in second or later group
235+ throw new IllegalArgumentException();
236+ }
237+
238+ // Return canonical array form.
239+ return canonicalArrayForm (theRanges);
240+ }
241+
242+ /**
243+ * Accumulate the given range (lb .. ub) into the canonical array form
244+ * into the given vector of int[] objects.
245+ */
246+ private static void accumulate(Vector ranges, int lb,int ub) {
247+ // Make sure range is non-null.
248+ if (lb <= ub) {
249+ // Stick range at the back of the vector.
250+ ranges.add(new int[] {lb, ub});
251+
252+ // Work towards the front of the vector to integrate the new range
253+ // with the existing ranges.
254+ for (int j = ranges.size()-2; j >= 0; -- j) {
255+ // Get lower and upper bounds of the two ranges being compared.
256+ int[] rangea = (int[]) ranges.elementAt (j);
257+ int lba = rangea[0];
258+ int uba = rangea[1];
259+ int[] rangeb = (int[]) ranges.elementAt (j+1);
260+ int lbb = rangeb[0];
261+ int ubb = rangeb[1];
262+
263+ /* If the two ranges overlap or are adjacent, coalesce them.
264+ * The two ranges overlap if the larger lower bound is less
265+ * than or equal to the smaller upper bound. The two ranges
266+ * are adjacent if the larger lower bound is one greater
267+ * than the smaller upper bound.
268+ */
269+ if (Math.max(lba, lbb) - Math.min(uba, ubb) <= 1) {
270+ // The coalesced range is from the smaller lower bound to
271+ // the larger upper bound.
272+ ranges.setElementAt(new int[]
273+ {Math.min(lba, lbb),
274+ Math.max(uba, ubb)}, j);
275+ ranges.remove (j+1);
276+ } else if (lba > lbb) {
277+
278+ /* If the two ranges don't overlap and aren't adjacent but
279+ * are out of order, swap them.
280+ */
281+ ranges.setElementAt (rangeb, j);
282+ ranges.setElementAt (rangea, j+1);
283+ } else {
284+ /* If the two ranges don't overlap and aren't adjacent and
285+ * aren't out of order, we're done early.
286+ */
287+ break;
288+ }
289+ }
290+ }
291+ }
292+
293+ /**
294+ * Convert the given vector of int[] objects to canonical array form.
295+ */
296+ private static int[][] canonicalArrayForm(Vector ranges) {
297+ return (int[][]) ranges.toArray (new int[ranges.size()][]);
298+ }
299+
300+ /**
301+ * Construct a new set-of-integer attribute with the given members in
302+ * array form.
303+ *
304+ * @param members Set members in array form. If null, an empty set is
305+ * constructed.
306+ *
307+ * @exception NullPointerException
308+ * (Unchecked exception) Thrown if any element of
309+ * <CODE>members</CODE> is null.
310+ * @exception IllegalArgumentException
311+ * (Unchecked exception) Thrown if any element of
312+ * <CODE>members</CODE> is not a length-one or length-two array or if
313+ * any non-null range in <CODE>members</CODE> has a lower bound less
314+ * than zero.
315+ */
316+ protected SetOfIntegerSyntax(int[][] members) {
317+ this.members = parse (members);
318+ }
319+
320+ /**
321+ * Parse the given array form, returning canonical array form.
322+ */
323+ private static int[][] parse(int[][] members) {
324+ // Create vector to hold int[] elements, each element being one range
325+ // parsed out of members.
326+ Vector ranges = new Vector();
327+
328+ // Process all integer groups in members.
329+ int n = (members == null ? 0 : members.length);
330+ for (int i = 0; i < n; ++ i) {
331+ // Get lower and upper bounds of the range.
332+ int lb, ub;
333+ if (members[i].length == 1) {
334+ lb = ub = members[i][0];
335+ } else if (members[i].length == 2) {
336+ lb = members[i][0];
337+ ub = members[i][1];
338+ } else {
339+ throw new IllegalArgumentException();
340+ }
341+
342+ // Verify valid bounds.
343+ if (lb <= ub && lb < 0) {
344+ throw new IllegalArgumentException();
345+ }
346+
347+ // Accumulate the range.
348+ accumulate(ranges, lb, ub);
349+ }
350+
351+ // Return canonical array form.
352+ return canonicalArrayForm (ranges);
353+ }
354+
355+ /**
356+ * Construct a new set-of-integer attribute containing a single integer.
357+ *
358+ * @param member Set member.
359+ *
360+ * @exception IllegalArgumentException
361+ * (Unchecked exception) Thrown if <CODE>member</CODE> is less than
362+ * zero.
363+ */
364+ protected SetOfIntegerSyntax(int member) {
365+ if (member < 0) {
366+ throw new IllegalArgumentException();
367+ }
368+ members = new int[][] {{member, member}};
369+ }
370+
371+ /**
372+ * Construct a new set-of-integer attribute containing a single range of
373+ * integers. If the lower bound is greater than the upper bound (a null
374+ * range), an empty set is constructed.
375+ *
376+ * @param lowerBound Lower bound of the range.
377+ * @param upperBound Upper bound of the range.
378+ *
379+ * @exception IllegalArgumentException
380+ * (Unchecked exception) Thrown if the range is non-null and
381+ * <CODE>lowerBound</CODE> is less than zero.
382+ */
383+ protected SetOfIntegerSyntax(int lowerBound, int upperBound) {
384+ if (lowerBound <= upperBound && lowerBound < 0) {
385+ throw new IllegalArgumentException();
386+ }
387+ members = lowerBound <=upperBound ?
388+ new int[][] {{lowerBound, upperBound}} :
389+ new int[0][];
390+ }
391+
392+
393+ /**
394+ * Obtain this set-of-integer attribute's members in canonical array form.
395+ * The returned array is "safe;" the client may alter it without affecting
396+ * this set-of-integer attribute.
397+ *
398+ * @return This set-of-integer attribute's members in canonical array form.
399+ */
400+ public int[][] getMembers() {
401+ int n = members.length;
402+ int[][] result = new int[n][];
403+ for (int i = 0; i < n; ++ i) {
404+ result[i] = new int[] {members[i][0], members[i][1]};
405+ }
406+ return result;
407+ }
408+
409+ /**
410+ * Determine if this set-of-integer attribute contains the given value.
411+ *
412+ * @param x Integer value.
413+ *
414+ * @return True if this set-of-integer attribute contains the value
415+ * <CODE>x</CODE>, false otherwise.
416+ */
417+ public boolean contains(int x) {
418+ // Do a linear search to find the range that contains x, if any.
419+ int n = members.length;
420+ for (int i = 0; i < n; ++ i) {
421+ if (x < members[i][0]) {
422+ return false;
423+ } else if (x <= members[i][1]) {
424+ return true;
425+ }
426+ }
427+ return false;
428+ }
429+
430+ /**
431+ * Determine if this set-of-integer attribute contains the given integer
432+ * attribute's value.
433+ *
434+ * @param attribute Integer attribute.
435+ *
436+ * @return True if this set-of-integer attribute contains
437+ * <CODE>theAttribute</CODE>'s value, false otherwise.
438+ */
439+ public boolean contains(IntegerSyntax attribute) {
440+ return contains (attribute.getValue());
441+ }
442+
443+ /**
444+ * Determine the smallest integer in this set-of-integer attribute that is
445+ * greater than the given value. If there are no integers in this
446+ * set-of-integer attribute greater than the given value, <CODE>-1</CODE> is
447+ * returned. (Since a set-of-integer attribute can only contain nonnegative
448+ * values, <CODE>-1</CODE> will never appear in the set.) You can use the
449+ * <CODE>next()</CODE> method to iterate through the integer values in a
450+ * set-of-integer attribute in ascending order, like this:
451+ * <PRE>
452+ * SetOfIntegerSyntax attribute = . . .;
453+ * int i = -1;
454+ * while ((i = attribute.next (i)) != -1)
455+ * {
456+ * foo (i);
457+ * }
458+ * </PRE>
459+ *
460+ * @param x Integer value.
461+ *
462+ * @return The smallest integer in this set-of-integer attribute that is
463+ * greater than <CODE>x</CODE>, or <CODE>-1</CODE> if no integer in
464+ * this set-of-integer attribute is greater than <CODE>x</CODE>.
465+ */
466+ public int next(int x) {
467+ // Do a linear search to find the range that contains x, if any.
468+ int n = members.length;
469+ for (int i = 0; i < n; ++ i) {
470+ if (x < members[i][0]) {
471+ return members[i][0];
472+ } else if (x < members[i][1]) {
473+ return x + 1;
474+ }
475+ }
476+ return -1;
477+ }
478+
479+ /**
480+ * Returns whether this set-of-integer attribute is equivalent to the passed
481+ * in object. To be equivalent, all of the following conditions must be
482+ * true:
483+ * <OL TYPE=1>
484+ * <LI>
485+ * <CODE>object</CODE> is not null.
486+ * <LI>
487+ * <CODE>object</CODE> is an instance of class SetOfIntegerSyntax.
488+ * <LI>
489+ * This set-of-integer attribute's members and <CODE>object</CODE>'s
490+ * members are the same.
491+ * </OL>
492+ *
493+ * @param object Object to compare to.
494+ *
495+ * @return True if <CODE>object</CODE> is equivalent to this
496+ * set-of-integer attribute, false otherwise.
497+ */
498+ public boolean equals(Object object) {
499+ if (object != null && object instanceof SetOfIntegerSyntax) {
500+ int[][] myMembers = this.members;
501+ int[][] otherMembers = ((SetOfIntegerSyntax) object).members;
502+ int m = myMembers.length;
503+ int n = otherMembers.length;
504+ if (m == n) {
505+ for (int i = 0; i < m; ++ i) {
506+ if (myMembers[i][0] != otherMembers[i][0] ||
507+ myMembers[i][1] != otherMembers[i][1]) {
508+ return false;
509+ }
510+ }
511+ return true;
512+ } else {
513+ return false;
514+ }
515+ } else {
516+ return false;
517+ }
518+ }
519+
520+ /**
521+ * Returns a hash code value for this set-of-integer attribute. The hash
522+ * code is the sum of the lower and upper bounds of the ranges in the
523+ * canonical array form, or 0 for an empty set.
524+ */
525+ public int hashCode() {
526+ int result = 0;
527+ int n = members.length;
528+ for (int i = 0; i < n; ++ i) {
529+ result += members[i][0] + members[i][1];
530+ }
531+ return result;
532+ }
533+
534+ /**
535+ * Returns a string value corresponding to this set-of-integer attribute.
536+ * The string value is a zero-length string if this set is empty. Otherwise,
537+ * the string value is a comma-separated list of the ranges in the canonical
538+ * array form, where each range is represented as <CODE>"<I>i</I>"</CODE> if
539+ * the lower bound equals the upper bound or
540+ * <CODE>"<I>i</I>-<I>j</I>"</CODE> otherwise.
541+ */
542+ public String toString() {
543+ StringBuffer result = new StringBuffer();
544+ int n = members.length;
545+ for (int i = 0; i < n; i++) {
546+ if (i > 0) {
547+ result.append (',');
548+ }
549+ result.append (members[i][0]);
550+ if (members[i][0] != members[i][1]) {
551+ result.append ('-');
552+ result.append (members[i][1]);
553+ }
554+ }
555+ return result.toString();
556+ }
557+
558+}