Source Code Cross Referenced for SetOfIntegerSyntax.java in  » 6.0-JDK-Core » print » javax » print » attribute » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Home
Java Source Code / Java Documentation
1.6.0 JDK Core
2.6.0 JDK Modules
3.6.0 JDK Modules com.sun
4.6.0 JDK Modules com.sun.java
5.6.0 JDK Modules sun
6.6.0 JDK Platform
7.Ajax
8.Apache Harmony Java SE
9.Aspect oriented
10.Authentication Authorization
11.Blogger System
12.Build
13.Byte Code
14.Cache
15.Chart
16.Chat
17.Code Analyzer
18.Collaboration
19.Content Management System
20.Database Client
21.Database DBMS
22.Database JDBC Connection Pool
23.Database ORM
24.Development
25.EJB Server
26.ERP CRM Financial
27.ESB
28.Forum
29.Game
30.GIS
31.Graphic 3D
32.Graphic Library
33.Groupware
34.HTML Parser
35.IDE
36.IDE Eclipse
37.IDE Netbeans
38.Installer
39.Internationalization Localization
40.Inversion of Control
41.Issue Tracking
42.J2EE
43.J2ME
44.JBoss
45.JMS
46.JMX
47.Library
48.Mail Clients
49.Music
50.Net
51.Parser
52.PDF
53.Portal
54.Profiler
55.Project Management
56.Report
57.RSS RDF
58.Rule Engine
59.Science
60.Scripting
61.Search Engine
62.Security
63.Sevlet Container
64.Source Control
65.Swing Library
66.Template Engine
67.Test Coverage
68.Testing
69.UML
70.Web Crawler
71.Web Framework
72.Web Mail
73.Web Server
74.Web Services
75.Web Services apache cxf 2.2.6
76.Web Services AXIS2
77.Wiki Engine
78.Workflow Engines
79.XML
80.XML UI
Java Source Code / Java Documentation » 6.0 JDK Core » print » javax.print.attribute 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


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