/* * Copyright (c) 2000, 2004, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package javax.print.attribute; import java.io.Serializable; import java.util.Vector; /** * Class SetOfIntegerSyntax is an abstract base class providing the common * implementation of all attributes whose value is a set of nonnegative * integers. This includes attributes whose value is a single range of integers * and attributes whose value is a set of ranges of integers. *
* You can construct an instance of SetOfIntegerSyntax by giving it in "string
* form." The string consists of zero or more comma-separated integer groups.
* Each integer group consists of either one integer, two integers separated by
* a hyphen (-
), or two integers separated by a colon
* (:
). Each integer consists of one or more decimal digits
* (0
through 9
). Whitespace characters cannot
* appear within an integer but are otherwise ignored. For example:
* ""
, "1"
, "5-10"
, "1:2,
* 4"
.
*
* You can also construct an instance of SetOfIntegerSyntax by giving it in
* "array form." Array form consists of an array of zero or more integer groups
* where each integer group is a length-1 or length-2 array of
* int
s; for example, int[0][]
,
* int[][]{{1}}
, int[][]{{5,10}}
,
* int[][]{{1,2},{4}}
.
*
* In both string form and array form, each successive integer group gives a * range of integers to be included in the set. The first integer in each group * gives the lower bound of the range; the second integer in each group gives * the upper bound of the range; if there is only one integer in the group, the * upper bound is the same as the lower bound. If the upper bound is less than * the lower bound, it denotes a null range (no values). If the upper bound is * equal to the lower bound, it denotes a range consisting of a single value. If * the upper bound is greater than the lower bound, it denotes a range * consisting of more than one value. The ranges may appear in any order and are * allowed to overlap. The union of all the ranges gives the set's contents. * Once a SetOfIntegerSyntax instance is constructed, its value is immutable. *
* The SetOfIntegerSyntax object's value is actually stored in "canonical
* array form." This is the same as array form, except there are no null ranges;
* the members of the set are represented in as few ranges as possible (i.e.,
* overlapping ranges are coalesced); the ranges appear in ascending order; and
* each range is always represented as a length-two array of int
s
* in the form {lower bound, upper bound}. An empty set is represented as a
* zero-length array.
*
* Class SetOfIntegerSyntax has operations to return the set's members in * canonical array form, to test whether a given integer is a member of the * set, and to iterate through the members of the set. *
*
* @author David Mendenhall
* @author Alan Kaminsky
*/
public abstract class SetOfIntegerSyntax implements Serializable, Cloneable {
private static final long serialVersionUID = 3666874174847632203L;
/**
* This set's members in canonical array form.
* @serial
*/
private int[][] members;
/**
* Construct a new set-of-integer attribute with the given members in
* string form.
*
* @param members Set members in string form. If null, an empty set is
* constructed.
*
* @exception IllegalArgumentException
* (Unchecked exception) Thrown if members
does not
* obey the proper syntax.
*/
protected SetOfIntegerSyntax(String members) {
this.members = parse (members);
}
/**
* Parse the given string, returning canonical array form.
*/
private static int[][] parse(String members) {
// Create vector to hold int[] elements, each element being one range
// parsed out of members.
Vectormembers
is null.
* @exception IllegalArgumentException
* (Unchecked exception) Thrown if any element of
* members
is not a length-one or length-two array or if
* any non-null range in members
has a lower bound less
* than zero.
*/
protected SetOfIntegerSyntax(int[][] members) {
this.members = parse (members);
}
/**
* Parse the given array form, returning canonical array form.
*/
private static int[][] parse(int[][] members) {
// Create vector to hold int[] elements, each element being one range
// parsed out of members.
Vectormember
is less than
* zero.
*/
protected SetOfIntegerSyntax(int member) {
if (member < 0) {
throw new IllegalArgumentException();
}
members = new int[][] {{member, member}};
}
/**
* Construct a new set-of-integer attribute containing a single range of
* integers. If the lower bound is greater than the upper bound (a null
* range), an empty set is constructed.
*
* @param lowerBound Lower bound of the range.
* @param upperBound Upper bound of the range.
*
* @exception IllegalArgumentException
* (Unchecked exception) Thrown if the range is non-null and
* lowerBound
is less than zero.
*/
protected SetOfIntegerSyntax(int lowerBound, int upperBound) {
if (lowerBound <= upperBound && lowerBound < 0) {
throw new IllegalArgumentException();
}
members = lowerBound <=upperBound ?
new int[][] {{lowerBound, upperBound}} :
new int[0][];
}
/**
* Obtain this set-of-integer attribute's members in canonical array form.
* The returned array is "safe;" the client may alter it without affecting
* this set-of-integer attribute.
*
* @return This set-of-integer attribute's members in canonical array form.
*/
public int[][] getMembers() {
int n = members.length;
int[][] result = new int[n][];
for (int i = 0; i < n; ++ i) {
result[i] = new int[] {members[i][0], members[i][1]};
}
return result;
}
/**
* Determine if this set-of-integer attribute contains the given value.
*
* @param x Integer value.
*
* @return True if this set-of-integer attribute contains the value
* x
, false otherwise.
*/
public boolean contains(int x) {
// Do a linear search to find the range that contains x, if any.
int n = members.length;
for (int i = 0; i < n; ++ i) {
if (x < members[i][0]) {
return false;
} else if (x <= members[i][1]) {
return true;
}
}
return false;
}
/**
* Determine if this set-of-integer attribute contains the given integer
* attribute's value.
*
* @param attribute Integer attribute.
*
* @return True if this set-of-integer attribute contains
* theAttribute
's value, false otherwise.
*/
public boolean contains(IntegerSyntax attribute) {
return contains (attribute.getValue());
}
/**
* Determine the smallest integer in this set-of-integer attribute that is
* greater than the given value. If there are no integers in this
* set-of-integer attribute greater than the given value, -1
is
* returned. (Since a set-of-integer attribute can only contain nonnegative
* values, -1
will never appear in the set.) You can use the
* next()
method to iterate through the integer values in a
* set-of-integer attribute in ascending order, like this:
*
* SetOfIntegerSyntax attribute = . . .;
* int i = -1;
* while ((i = attribute.next (i)) != -1)
* {
* foo (i);
* }
*
*
* @param x Integer value.
*
* @return The smallest integer in this set-of-integer attribute that is
* greater than x
, or -1
if no integer in
* this set-of-integer attribute is greater than x
.
*/
public int next(int x) {
// Do a linear search to find the range that contains x, if any.
int n = members.length;
for (int i = 0; i < n; ++ i) {
if (x < members[i][0]) {
return members[i][0];
} else if (x < members[i][1]) {
return x + 1;
}
}
return -1;
}
/**
* Returns whether this set-of-integer attribute is equivalent to the passed
* in object. To be equivalent, all of the following conditions must be
* true:
*
*
*
* @param object Object to compare to.
*
* @return True if object
is not null.
* object
is an instance of class SetOfIntegerSyntax.
* object
's
* members are the same.
* object
is equivalent to this
* set-of-integer attribute, false otherwise.
*/
public boolean equals(Object object) {
if (object != null && object instanceof SetOfIntegerSyntax) {
int[][] myMembers = this.members;
int[][] otherMembers = ((SetOfIntegerSyntax) object).members;
int m = myMembers.length;
int n = otherMembers.length;
if (m == n) {
for (int i = 0; i < m; ++ i) {
if (myMembers[i][0] != otherMembers[i][0] ||
myMembers[i][1] != otherMembers[i][1]) {
return false;
}
}
return true;
} else {
return false;
}
} else {
return false;
}
}
/**
* Returns a hash code value for this set-of-integer attribute. The hash
* code is the sum of the lower and upper bounds of the ranges in the
* canonical array form, or 0 for an empty set.
*/
public int hashCode() {
int result = 0;
int n = members.length;
for (int i = 0; i < n; ++ i) {
result += members[i][0] + members[i][1];
}
return result;
}
/**
* Returns a string value corresponding to this set-of-integer attribute.
* The string value is a zero-length string if this set is empty. Otherwise,
* the string value is a comma-separated list of the ranges in the canonical
* array form, where each range is represented as "i"
if
* the lower bound equals the upper bound or
* "i-j"
otherwise.
*/
public String toString() {
StringBuffer result = new StringBuffer();
int n = members.length;
for (int i = 0; i < n; i++) {
if (i > 0) {
result.append (',');
}
result.append (members[i][0]);
if (members[i][0] != members[i][1]) {
result.append ('-');
result.append (members[i][1]);
}
}
return result.toString();
}
}