aboutsummaryrefslogtreecommitdiff
path: root/libjava/classpath/java/util
diff options
context:
space:
mode:
Diffstat (limited to 'libjava/classpath/java/util')
-rw-r--r--libjava/classpath/java/util/AbstractMap.java29
-rw-r--r--libjava/classpath/java/util/Arrays.java998
-rw-r--r--libjava/classpath/java/util/Calendar.java250
-rw-r--r--libjava/classpath/java/util/Collections.java217
-rw-r--r--libjava/classpath/java/util/Currency.java33
-rw-r--r--libjava/classpath/java/util/Date.java2
-rw-r--r--libjava/classpath/java/util/GregorianCalendar.java18
-rw-r--r--libjava/classpath/java/util/HashMap.java16
-rw-r--r--libjava/classpath/java/util/Hashtable.java18
-rw-r--r--libjava/classpath/java/util/LinkedList.java271
-rw-r--r--libjava/classpath/java/util/Locale.java76
-rw-r--r--libjava/classpath/java/util/PriorityQueue.java1
-rw-r--r--libjava/classpath/java/util/ServiceConfigurationError.java94
-rw-r--r--libjava/classpath/java/util/ServiceLoader.java274
-rw-r--r--libjava/classpath/java/util/StringTokenizer.java8
-rw-r--r--libjava/classpath/java/util/TreeMap.java1970
-rw-r--r--libjava/classpath/java/util/TreeSet.java244
-rw-r--r--libjava/classpath/java/util/class-dependencies.conf78
-rw-r--r--libjava/classpath/java/util/concurrent/CopyOnWriteArrayList.java3
-rw-r--r--libjava/classpath/java/util/logging/LogManager.java16
-rw-r--r--libjava/classpath/java/util/logging/Logger.java18
-rw-r--r--libjava/classpath/java/util/prefs/AbstractPreferences.java17
-rw-r--r--libjava/classpath/java/util/prefs/Preferences.java6
-rw-r--r--libjava/classpath/java/util/regex/Pattern.java14
-rw-r--r--libjava/classpath/java/util/spi/CurrencyNameProvider.java100
-rw-r--r--libjava/classpath/java/util/spi/LocaleNameProvider.java135
-rw-r--r--libjava/classpath/java/util/spi/LocaleServiceProvider.java125
-rw-r--r--libjava/classpath/java/util/spi/TimeZoneNameProvider.java97
-rw-r--r--libjava/classpath/java/util/spi/package.html50
-rw-r--r--libjava/classpath/java/util/zip/DeflaterEngine.java3
-rw-r--r--libjava/classpath/java/util/zip/ZipInputStream.java1
31 files changed, 4782 insertions, 400 deletions
diff --git a/libjava/classpath/java/util/AbstractMap.java b/libjava/classpath/java/util/AbstractMap.java
index 29249e1..2f58121 100644
--- a/libjava/classpath/java/util/AbstractMap.java
+++ b/libjava/classpath/java/util/AbstractMap.java
@@ -69,10 +69,23 @@ import java.io.Serializable;
*/
public abstract class AbstractMap<K, V> implements Map<K, V>
{
- /** @since 1.6 */
+ /**
+ * A class containing an immutable key and value. The
+ * implementation of {@link Entry#setValue(V)} for this class
+ * simply throws an {@link UnsupportedOperationException},
+ * thus preventing changes being made. This is useful when
+ * a static thread-safe view of a map is required.
+ *
+ * @since 1.6
+ */
public static class SimpleImmutableEntry<K, V>
implements Entry<K, V>, Serializable
{
+ /**
+ * Compatible with JDK 1.6
+ */
+ private static final long serialVersionUID = 7138329143949025153L;
+
K key;
V value;
@@ -670,6 +683,12 @@ public abstract class AbstractMap<K, V> implements Map<K, V>
*/
public static class SimpleEntry<K, V> implements Entry<K, V>, Serializable
{
+
+ /**
+ * Compatible with JDK 1.6
+ */
+ private static final long serialVersionUID = -8499721149061103585L;
+
/**
* The key. Package visible for direct manipulation.
*/
@@ -730,7 +749,7 @@ public abstract class AbstractMap<K, V> implements Map<K, V>
*
* @return the key
*/
- public final K getKey()
+ public K getKey()
{
return key;
}
@@ -741,7 +760,7 @@ public abstract class AbstractMap<K, V> implements Map<K, V>
*
* @return the value
*/
- public final V getValue()
+ public V getValue()
{
return value;
}
@@ -755,7 +774,7 @@ public abstract class AbstractMap<K, V> implements Map<K, V>
*
* @return the hash code
*/
- public final int hashCode()
+ public int hashCode()
{
return (AbstractMap.hashCode(key) ^ AbstractMap.hashCode(value));
}
@@ -788,7 +807,7 @@ public abstract class AbstractMap<K, V> implements Map<K, V>
*
* @return the string representation
*/
- public final String toString()
+ public String toString()
{
return key + "=" + value;
}
diff --git a/libjava/classpath/java/util/Arrays.java b/libjava/classpath/java/util/Arrays.java
index 41e8045..9443ced 100644
--- a/libjava/classpath/java/util/Arrays.java
+++ b/libjava/classpath/java/util/Arrays.java
@@ -92,8 +92,38 @@ public class Arrays
*/
public static int binarySearch(byte[] a, byte key)
{
- int low = 0;
- int hi = a.length - 1;
+ if (a.length == 0)
+ return -1;
+ return binarySearch(a, 0, a.length - 1, key);
+ }
+
+ /**
+ * Perform a binary search of a range of a byte array for a key. The range
+ * must be sorted (as by the <code>sort(byte[], int, int)</code> method) -
+ * if it is not, the behaviour of this method is undefined, and may be an
+ * infinite loop. If the array contains the key more than once, any one of
+ * them may be found. Note: although the specification allows for an infinite
+ * loop if the array is unsorted, it will not happen in this implementation.
+ *
+ * @param a the array to search (must be sorted)
+ * @param low the lowest index to search from.
+ * @param hi the highest index to search to.
+ * @param key the value to search for
+ * @return the index at which the key was found, or -n-1 if it was not
+ * found, where n is the index of the first value higher than key or
+ * a.length if there is no such value.
+ * @throws IllegalArgumentException if <code>low > hi</code>
+ * @throws ArrayIndexOutOfBoundsException if <code>low < 0</code> or
+ * <code>hi > a.length</code>.
+ */
+ public static int binarySearch(byte[] a, int low, int hi, byte key)
+ {
+ if (low > hi)
+ throw new IllegalArgumentException("The start index is higher than " +
+ "the finish index.");
+ if (low < 0 || hi > a.length)
+ throw new ArrayIndexOutOfBoundsException("One of the indices is out " +
+ "of bounds.");
int mid = 0;
while (low <= hi)
{
@@ -126,8 +156,38 @@ public class Arrays
*/
public static int binarySearch(char[] a, char key)
{
- int low = 0;
- int hi = a.length - 1;
+ if (a.length == 0)
+ return -1;
+ return binarySearch(a, 0, a.length - 1, key);
+ }
+
+ /**
+ * Perform a binary search of a range of a char array for a key. The range
+ * must be sorted (as by the <code>sort(char[], int, int)</code> method) -
+ * if it is not, the behaviour of this method is undefined, and may be an
+ * infinite loop. If the array contains the key more than once, any one of
+ * them may be found. Note: although the specification allows for an infinite
+ * loop if the array is unsorted, it will not happen in this implementation.
+ *
+ * @param a the array to search (must be sorted)
+ * @param low the lowest index to search from.
+ * @param hi the highest index to search to.
+ * @param key the value to search for
+ * @return the index at which the key was found, or -n-1 if it was not
+ * found, where n is the index of the first value higher than key or
+ * a.length if there is no such value.
+ * @throws IllegalArgumentException if <code>low > hi</code>
+ * @throws ArrayIndexOutOfBoundsException if <code>low < 0</code> or
+ * <code>hi > a.length</code>.
+ */
+ public static int binarySearch(char[] a, int low, int hi, char key)
+ {
+ if (low > hi)
+ throw new IllegalArgumentException("The start index is higher than " +
+ "the finish index.");
+ if (low < 0 || hi > a.length)
+ throw new ArrayIndexOutOfBoundsException("One of the indices is out " +
+ "of bounds.");
int mid = 0;
while (low <= hi)
{
@@ -160,8 +220,38 @@ public class Arrays
*/
public static int binarySearch(short[] a, short key)
{
- int low = 0;
- int hi = a.length - 1;
+ if (a.length == 0)
+ return -1;
+ return binarySearch(a, 0, a.length - 1, key);
+ }
+
+ /**
+ * Perform a binary search of a range of a short array for a key. The range
+ * must be sorted (as by the <code>sort(short[], int, int)</code> method) -
+ * if it is not, the behaviour of this method is undefined, and may be an
+ * infinite loop. If the array contains the key more than once, any one of
+ * them may be found. Note: although the specification allows for an infinite
+ * loop if the array is unsorted, it will not happen in this implementation.
+ *
+ * @param a the array to search (must be sorted)
+ * @param low the lowest index to search from.
+ * @param hi the highest index to search to.
+ * @param key the value to search for
+ * @return the index at which the key was found, or -n-1 if it was not
+ * found, where n is the index of the first value higher than key or
+ * a.length if there is no such value.
+ * @throws IllegalArgumentException if <code>low > hi</code>
+ * @throws ArrayIndexOutOfBoundsException if <code>low < 0</code> or
+ * <code>hi > a.length</code>.
+ */
+ public static int binarySearch(short[] a, int low, int hi, short key)
+ {
+ if (low > hi)
+ throw new IllegalArgumentException("The start index is higher than " +
+ "the finish index.");
+ if (low < 0 || hi > a.length)
+ throw new ArrayIndexOutOfBoundsException("One of the indices is out " +
+ "of bounds.");
int mid = 0;
while (low <= hi)
{
@@ -194,8 +284,38 @@ public class Arrays
*/
public static int binarySearch(int[] a, int key)
{
- int low = 0;
- int hi = a.length - 1;
+ if (a.length == 0)
+ return -1;
+ return binarySearch(a, 0, a.length - 1, key);
+ }
+
+ /**
+ * Perform a binary search of a range of an integer array for a key. The range
+ * must be sorted (as by the <code>sort(int[], int, int)</code> method) -
+ * if it is not, the behaviour of this method is undefined, and may be an
+ * infinite loop. If the array contains the key more than once, any one of
+ * them may be found. Note: although the specification allows for an infinite
+ * loop if the array is unsorted, it will not happen in this implementation.
+ *
+ * @param a the array to search (must be sorted)
+ * @param low the lowest index to search from.
+ * @param hi the highest index to search to.
+ * @param key the value to search for
+ * @return the index at which the key was found, or -n-1 if it was not
+ * found, where n is the index of the first value higher than key or
+ * a.length if there is no such value.
+ * @throws IllegalArgumentException if <code>low > hi</code>
+ * @throws ArrayIndexOutOfBoundsException if <code>low < 0</code> or
+ * <code>hi > a.length</code>.
+ */
+ public static int binarySearch(int[] a, int low, int hi, int key)
+ {
+ if (low > hi)
+ throw new IllegalArgumentException("The start index is higher than " +
+ "the finish index.");
+ if (low < 0 || hi > a.length)
+ throw new ArrayIndexOutOfBoundsException("One of the indices is out " +
+ "of bounds.");
int mid = 0;
while (low <= hi)
{
@@ -228,8 +348,38 @@ public class Arrays
*/
public static int binarySearch(long[] a, long key)
{
- int low = 0;
- int hi = a.length - 1;
+ if (a.length == 0)
+ return -1;
+ return binarySearch(a, 0, a.length - 1, key);
+ }
+
+ /**
+ * Perform a binary search of a range of a long array for a key. The range
+ * must be sorted (as by the <code>sort(long[], int, int)</code> method) -
+ * if it is not, the behaviour of this method is undefined, and may be an
+ * infinite loop. If the array contains the key more than once, any one of
+ * them may be found. Note: although the specification allows for an infinite
+ * loop if the array is unsorted, it will not happen in this implementation.
+ *
+ * @param a the array to search (must be sorted)
+ * @param low the lowest index to search from.
+ * @param hi the highest index to search to.
+ * @param key the value to search for
+ * @return the index at which the key was found, or -n-1 if it was not
+ * found, where n is the index of the first value higher than key or
+ * a.length if there is no such value.
+ * @throws IllegalArgumentException if <code>low > hi</code>
+ * @throws ArrayIndexOutOfBoundsException if <code>low < 0</code> or
+ * <code>hi > a.length</code>.
+ */
+ public static int binarySearch(long[] a, int low, int hi, long key)
+ {
+ if (low > hi)
+ throw new IllegalArgumentException("The start index is higher than " +
+ "the finish index.");
+ if (low < 0 || hi > a.length)
+ throw new ArrayIndexOutOfBoundsException("One of the indices is out " +
+ "of bounds.");
int mid = 0;
while (low <= hi)
{
@@ -262,9 +412,39 @@ public class Arrays
*/
public static int binarySearch(float[] a, float key)
{
+ if (a.length == 0)
+ return -1;
+ return binarySearch(a, 0, a.length - 1, key);
+ }
+
+ /**
+ * Perform a binary search of a range of a float array for a key. The range
+ * must be sorted (as by the <code>sort(float[], int, int)</code> method) -
+ * if it is not, the behaviour of this method is undefined, and may be an
+ * infinite loop. If the array contains the key more than once, any one of
+ * them may be found. Note: although the specification allows for an infinite
+ * loop if the array is unsorted, it will not happen in this implementation.
+ *
+ * @param a the array to search (must be sorted)
+ * @param low the lowest index to search from.
+ * @param hi the highest index to search to.
+ * @param key the value to search for
+ * @return the index at which the key was found, or -n-1 if it was not
+ * found, where n is the index of the first value higher than key or
+ * a.length if there is no such value.
+ * @throws IllegalArgumentException if <code>low > hi</code>
+ * @throws ArrayIndexOutOfBoundsException if <code>low < 0</code> or
+ * <code>hi > a.length</code>.
+ */
+ public static int binarySearch(float[] a, int low, int hi, float key)
+ {
+ if (low > hi)
+ throw new IllegalArgumentException("The start index is higher than " +
+ "the finish index.");
+ if (low < 0 || hi > a.length)
+ throw new ArrayIndexOutOfBoundsException("One of the indices is out " +
+ "of bounds.");
// Must use Float.compare to take into account NaN, +-0.
- int low = 0;
- int hi = a.length - 1;
int mid = 0;
while (low <= hi)
{
@@ -297,9 +477,39 @@ public class Arrays
*/
public static int binarySearch(double[] a, double key)
{
+ if (a.length == 0)
+ return -1;
+ return binarySearch(a, 0, a.length - 1, key);
+ }
+
+ /**
+ * Perform a binary search of a range of a double array for a key. The range
+ * must be sorted (as by the <code>sort(double[], int, int)</code> method) -
+ * if it is not, the behaviour of this method is undefined, and may be an
+ * infinite loop. If the array contains the key more than once, any one of
+ * them may be found. Note: although the specification allows for an infinite
+ * loop if the array is unsorted, it will not happen in this implementation.
+ *
+ * @param a the array to search (must be sorted)
+ * @param low the lowest index to search from.
+ * @param hi the highest index to search to.
+ * @param key the value to search for
+ * @return the index at which the key was found, or -n-1 if it was not
+ * found, where n is the index of the first value higher than key or
+ * a.length if there is no such value.
+ * @throws IllegalArgumentException if <code>low > hi</code>
+ * @throws ArrayIndexOutOfBoundsException if <code>low < 0</code> or
+ * <code>hi > a.length</code>.
+ */
+ public static int binarySearch(double[] a, int low, int hi, double key)
+ {
+ if (low > hi)
+ throw new IllegalArgumentException("The start index is higher than " +
+ "the finish index.");
+ if (low < 0 || hi > a.length)
+ throw new ArrayIndexOutOfBoundsException("One of the indices is out " +
+ "of bounds.");
// Must use Double.compare to take into account NaN, +-0.
- int low = 0;
- int hi = a.length - 1;
int mid = 0;
while (low <= hi)
{
@@ -337,10 +547,33 @@ public class Arrays
*/
public static int binarySearch(Object[] a, Object key)
{
+ if (a.length == 0)
+ return -1;
return binarySearch(a, key, null);
}
/**
+ * Perform a binary search of a range of an Object array for a key. The range
+ * must be sorted (as by the <code>sort(Object[], int, int)</code> method) -
+ * if it is not, the behaviour of this method is undefined, and may be an
+ * infinite loop. If the array contains the key more than once, any one of
+ * them may be found. Note: although the specification allows for an infinite
+ * loop if the array is unsorted, it will not happen in this implementation.
+ *
+ * @param a the array to search (must be sorted)
+ * @param low the lowest index to search from.
+ * @param hi the highest index to search to.
+ * @param key the value to search for
+ * @return the index at which the key was found, or -n-1 if it was not
+ * found, where n is the index of the first value higher than key or
+ * a.length if there is no such value.
+ */
+ public static int binarySearch(Object[] a, int low, int hi, Object key)
+ {
+ return binarySearch(a, low, hi, key, null);
+ }
+
+ /**
* Perform a binary search of an Object array for a key, using a supplied
* Comparator. The array must be sorted (as by the sort() method with the
* same Comparator) - if it is not, the behaviour of this method is
@@ -364,8 +597,44 @@ public class Arrays
*/
public static <T> int binarySearch(T[] a, T key, Comparator<? super T> c)
{
- int low = 0;
- int hi = a.length - 1;
+ if (a.length == 0)
+ return -1;
+ return binarySearch(a, 0, a.length - 1, key, c);
+ }
+
+ /**
+ * Perform a binary search of a range of an Object array for a key using
+ * a {@link Comparator}. The range must be sorted (as by the
+ * <code>sort(Object[], int, int)</code> method) - if it is not, the
+ * behaviour of this method is undefined, and may be an infinite loop. If
+ * the array contains the key more than once, any one of them may be found.
+ * Note: although the specification allows for an infinite loop if the array
+ * is unsorted, it will not happen in this implementation.
+ *
+ * @param a the array to search (must be sorted)
+ * @param low the lowest index to search from.
+ * @param hi the highest index to search to.
+ * @param key the value to search for
+ * @param c the comparator by which the array is sorted; or null to
+ * use the elements' natural order
+ * @return the index at which the key was found, or -n-1 if it was not
+ * found, where n is the index of the first value higher than key or
+ * a.length if there is no such value.
+ * @throws ClassCastException if key could not be compared with one of the
+ * elements of a
+ * @throws IllegalArgumentException if <code>low > hi</code>
+ * @throws ArrayIndexOutOfBoundsException if <code>low < 0</code> or
+ * <code>hi > a.length</code>.
+ */
+ public static <T> int binarySearch(T[] a, int low, int hi, T key,
+ Comparator<? super T> c)
+ {
+ if (low > hi)
+ throw new IllegalArgumentException("The start index is higher than " +
+ "the finish index.");
+ if (low < 0 || hi > a.length)
+ throw new ArrayIndexOutOfBoundsException("One of the indices is out " +
+ "of bounds.");
int mid = 0;
while (low <= hi)
{
@@ -3062,4 +3331,701 @@ public class Arrays
return array;
}
}
+
+ /**
+ * Returns a copy of the supplied array, truncating or padding as
+ * necessary with <code>false</code> to obtain the specified length.
+ * Indices that are valid for both arrays will return the same value.
+ * Indices that only exist in the returned array (due to the new length
+ * being greater than the original length) will return <code>false</code>.
+ * This is equivalent to calling
+ * <code>copyOfRange(original, 0, newLength)</code>.
+ *
+ * @param original the original array to be copied.
+ * @param newLength the length of the returned array.
+ * @return a copy of the original array, truncated or padded with
+ * <code>false</code> to obtain the required length.
+ * @throws NegativeArraySizeException if <code>newLength</code> is negative.
+ * @throws NullPointerException if <code>original</code> is <code>null</code>.
+ * @since 1.6
+ * @see #copyOfRange(boolean[],int,int)
+ */
+ public static boolean[] copyOf(boolean[] original, int newLength)
+ {
+ if (newLength < 0)
+ throw new NegativeArraySizeException("The array size is negative.");
+ return copyOfRange(original, 0, newLength);
+ }
+
+ /**
+ * Copies the specified range of the supplied array to a new
+ * array, padding as necessary with <code>false</code>
+ * if <code>to</code> is greater than the length of the original
+ * array. <code>from</code> must be in the range zero to
+ * <code>original.length</code> and can not be greater than
+ * <code>to</code>. The initial element of the
+ * returned array will be equal to <code>original[from]</code>,
+ * except where <code>from</code> is equal to <code>to</code>
+ * (where a zero-length array will be returned) or <code>
+ * <code>from</code> is equal to <code>original.length</code>
+ * (where an array padded with <code>false</code> will be
+ * returned). The returned array is always of length
+ * <code>to - from</code>.
+ *
+ * @param original the array from which to copy.
+ * @param from the initial index of the range, inclusive.
+ * @param to the final index of the range, exclusive.
+ * @return a copy of the specified range, with padding to
+ * obtain the required length.
+ * @throws ArrayIndexOutOfBoundsException if <code>from < 0</code>
+ * or <code>from > original.length</code>
+ * @throws IllegalArgumentException if <code>from > to</code>
+ * @throws NullPointerException if <code>original</code> is <code>null</code>.
+ * @since 1.6
+ * @see #copyOf(boolean[],int)
+ */
+ public static boolean[] copyOfRange(boolean[] original, int from, int to)
+ {
+ if (from > to)
+ throw new IllegalArgumentException("The initial index is after " +
+ "the final index.");
+ boolean[] newArray = new boolean[to - from];
+ if (to > original.length)
+ {
+ System.arraycopy(original, from, newArray, 0,
+ original.length - from);
+ fill(newArray, original.length, newArray.length, false);
+ }
+ else
+ System.arraycopy(original, from, newArray, 0, to - from);
+ return newArray;
+ }
+
+ /**
+ * Returns a copy of the supplied array, truncating or padding as
+ * necessary with <code>(byte)0</code> to obtain the specified length.
+ * Indices that are valid for both arrays will return the same value.
+ * Indices that only exist in the returned array (due to the new length
+ * being greater than the original length) will return <code>(byte)0</code>.
+ * This is equivalent to calling
+ * <code>copyOfRange(original, 0, newLength)</code>.
+ *
+ * @param original the original array to be copied.
+ * @param newLength the length of the returned array.
+ * @return a copy of the original array, truncated or padded with
+ * <code>(byte)0</code> to obtain the required length.
+ * @throws NegativeArraySizeException if <code>newLength</code> is negative.
+ * @throws NullPointerException if <code>original</code> is <code>null</code>.
+ * @since 1.6
+ * @see #copyOfRange(byte[],int,int)
+ */
+ public static byte[] copyOf(byte[] original, int newLength)
+ {
+ if (newLength < 0)
+ throw new NegativeArraySizeException("The array size is negative.");
+ return copyOfRange(original, 0, newLength);
+ }
+
+ /**
+ * Copies the specified range of the supplied array to a new
+ * array, padding as necessary with <code>(byte)0</code>
+ * if <code>to</code> is greater than the length of the original
+ * array. <code>from</code> must be in the range zero to
+ * <code>original.length</code> and can not be greater than
+ * <code>to</code>. The initial element of the
+ * returned array will be equal to <code>original[from]</code>,
+ * except where <code>from</code> is equal to <code>to</code>
+ * (where a zero-length array will be returned) or <code>
+ * <code>from</code> is equal to <code>original.length</code>
+ * (where an array padded with <code>(byte)0</code> will be
+ * returned). The returned array is always of length
+ * <code>to - from</code>.
+ *
+ * @param original the array from which to copy.
+ * @param from the initial index of the range, inclusive.
+ * @param to the final index of the range, exclusive.
+ * @return a copy of the specified range, with padding to
+ * obtain the required length.
+ * @throws ArrayIndexOutOfBoundsException if <code>from < 0</code>
+ * or <code>from > original.length</code>
+ * @throws IllegalArgumentException if <code>from > to</code>
+ * @throws NullPointerException if <code>original</code> is <code>null</code>.
+ * @since 1.6
+ * @see #copyOf(byte[],int)
+ */
+ public static byte[] copyOfRange(byte[] original, int from, int to)
+ {
+ if (from > to)
+ throw new IllegalArgumentException("The initial index is after " +
+ "the final index.");
+ byte[] newArray = new byte[to - from];
+ if (to > original.length)
+ {
+ System.arraycopy(original, from, newArray, 0,
+ original.length - from);
+ fill(newArray, original.length, newArray.length, (byte)0);
+ }
+ else
+ System.arraycopy(original, from, newArray, 0, to - from);
+ return newArray;
+ }
+
+ /**
+ * Returns a copy of the supplied array, truncating or padding as
+ * necessary with <code>'\0'</code> to obtain the specified length.
+ * Indices that are valid for both arrays will return the same value.
+ * Indices that only exist in the returned array (due to the new length
+ * being greater than the original length) will return <code>'\0'</code>.
+ * This is equivalent to calling
+ * <code>copyOfRange(original, 0, newLength)</code>.
+ *
+ * @param original the original array to be copied.
+ * @param newLength the length of the returned array.
+ * @return a copy of the original array, truncated or padded with
+ * <code>'\0'</code> to obtain the required length.
+ * @throws NegativeArraySizeException if <code>newLength</code> is negative.
+ * @throws NullPointerException if <code>original</code> is <code>null</code>.
+ * @since 1.6
+ * @see #copyOfRange(char[],int,int)
+ */
+ public static char[] copyOf(char[] original, int newLength)
+ {
+ if (newLength < 0)
+ throw new NegativeArraySizeException("The array size is negative.");
+ return copyOfRange(original, 0, newLength);
+ }
+
+ /**
+ * Copies the specified range of the supplied array to a new
+ * array, padding as necessary with <code>'\0'</code>
+ * if <code>to</code> is greater than the length of the original
+ * array. <code>from</code> must be in the range zero to
+ * <code>original.length</code> and can not be greater than
+ * <code>to</code>. The initial element of the
+ * returned array will be equal to <code>original[from]</code>,
+ * except where <code>from</code> is equal to <code>to</code>
+ * (where a zero-length array will be returned) or <code>
+ * <code>from</code> is equal to <code>original.length</code>
+ * (where an array padded with <code>'\0'</code> will be
+ * returned). The returned array is always of length
+ * <code>to - from</code>.
+ *
+ * @param original the array from which to copy.
+ * @param from the initial index of the range, inclusive.
+ * @param to the final index of the range, exclusive.
+ * @return a copy of the specified range, with padding to
+ * obtain the required length.
+ * @throws ArrayIndexOutOfBoundsException if <code>from < 0</code>
+ * or <code>from > original.length</code>
+ * @throws IllegalArgumentException if <code>from > to</code>
+ * @throws NullPointerException if <code>original</code> is <code>null</code>.
+ * @since 1.6
+ * @see #copyOf(char[],int)
+ */
+ public static char[] copyOfRange(char[] original, int from, int to)
+ {
+ if (from > to)
+ throw new IllegalArgumentException("The initial index is after " +
+ "the final index.");
+ char[] newArray = new char[to - from];
+ if (to > original.length)
+ {
+ System.arraycopy(original, from, newArray, 0,
+ original.length - from);
+ fill(newArray, original.length, newArray.length, '\0');
+ }
+ else
+ System.arraycopy(original, from, newArray, 0, to - from);
+ return newArray;
+ }
+
+ /**
+ * Returns a copy of the supplied array, truncating or padding as
+ * necessary with <code>0d</code> to obtain the specified length.
+ * Indices that are valid for both arrays will return the same value.
+ * Indices that only exist in the returned array (due to the new length
+ * being greater than the original length) will return <code>0d</code>.
+ * This is equivalent to calling
+ * <code>copyOfRange(original, 0, newLength)</code>.
+ *
+ * @param original the original array to be copied.
+ * @param newLength the length of the returned array.
+ * @return a copy of the original array, truncated or padded with
+ * <code>0d</code> to obtain the required length.
+ * @throws NegativeArraySizeException if <code>newLength</code> is negative.
+ * @throws NullPointerException if <code>original</code> is <code>null</code>.
+ * @since 1.6
+ * @see #copyOfRange(double[],int,int)
+ */
+ public static double[] copyOf(double[] original, int newLength)
+ {
+ if (newLength < 0)
+ throw new NegativeArraySizeException("The array size is negative.");
+ return copyOfRange(original, 0, newLength);
+ }
+
+ /**
+ * Copies the specified range of the supplied array to a new
+ * array, padding as necessary with <code>0d</code>
+ * if <code>to</code> is greater than the length of the original
+ * array. <code>from</code> must be in the range zero to
+ * <code>original.length</code> and can not be greater than
+ * <code>to</code>. The initial element of the
+ * returned array will be equal to <code>original[from]</code>,
+ * except where <code>from</code> is equal to <code>to</code>
+ * (where a zero-length array will be returned) or <code>
+ * <code>from</code> is equal to <code>original.length</code>
+ * (where an array padded with <code>0d</code> will be
+ * returned). The returned array is always of length
+ * <code>to - from</code>.
+ *
+ * @param original the array from which to copy.
+ * @param from the initial index of the range, inclusive.
+ * @param to the final index of the range, exclusive.
+ * @return a copy of the specified range, with padding to
+ * obtain the required length.
+ * @throws ArrayIndexOutOfBoundsException if <code>from < 0</code>
+ * or <code>from > original.length</code>
+ * @throws IllegalArgumentException if <code>from > to</code>
+ * @throws NullPointerException if <code>original</code> is <code>null</code>.
+ * @since 1.6
+ * @see #copyOf(double[],int)
+ */
+ public static double[] copyOfRange(double[] original, int from, int to)
+ {
+ if (from > to)
+ throw new IllegalArgumentException("The initial index is after " +
+ "the final index.");
+ double[] newArray = new double[to - from];
+ if (to > original.length)
+ {
+ System.arraycopy(original, from, newArray, 0,
+ original.length - from);
+ fill(newArray, original.length, newArray.length, 0d);
+ }
+ else
+ System.arraycopy(original, from, newArray, 0, to - from);
+ return newArray;
+ }
+
+ /**
+ * Returns a copy of the supplied array, truncating or padding as
+ * necessary with <code>0f</code> to obtain the specified length.
+ * Indices that are valid for both arrays will return the same value.
+ * Indices that only exist in the returned array (due to the new length
+ * being greater than the original length) will return <code>0f</code>.
+ * This is equivalent to calling
+ * <code>copyOfRange(original, 0, newLength)</code>.
+ *
+ * @param original the original array to be copied.
+ * @param newLength the length of the returned array.
+ * @return a copy of the original array, truncated or padded with
+ * <code>0f</code> to obtain the required length.
+ * @throws NegativeArraySizeException if <code>newLength</code> is negative.
+ * @throws NullPointerException if <code>original</code> is <code>null</code>.
+ * @since 1.6
+ * @see #copyOfRange(float[],int,int)
+ */
+ public static float[] copyOf(float[] original, int newLength)
+ {
+ if (newLength < 0)
+ throw new NegativeArraySizeException("The array size is negative.");
+ return copyOfRange(original, 0, newLength);
+ }
+
+ /**
+ * Copies the specified range of the supplied array to a new
+ * array, padding as necessary with <code>0f</code>
+ * if <code>to</code> is greater than the length of the original
+ * array. <code>from</code> must be in the range zero to
+ * <code>original.length</code> and can not be greater than
+ * <code>to</code>. The initial element of the
+ * returned array will be equal to <code>original[from]</code>,
+ * except where <code>from</code> is equal to <code>to</code>
+ * (where a zero-length array will be returned) or <code>
+ * <code>from</code> is equal to <code>original.length</code>
+ * (where an array padded with <code>0f</code> will be
+ * returned). The returned array is always of length
+ * <code>to - from</code>.
+ *
+ * @param original the array from which to copy.
+ * @param from the initial index of the range, inclusive.
+ * @param to the final index of the range, exclusive.
+ * @return a copy of the specified range, with padding to
+ * obtain the required length.
+ * @throws ArrayIndexOutOfBoundsException if <code>from < 0</code>
+ * or <code>from > original.length</code>
+ * @throws IllegalArgumentException if <code>from > to</code>
+ * @throws NullPointerException if <code>original</code> is <code>null</code>.
+ * @since 1.6
+ * @see #copyOf(float[],int)
+ */
+ public static float[] copyOfRange(float[] original, int from, int to)
+ {
+ if (from > to)
+ throw new IllegalArgumentException("The initial index is after " +
+ "the final index.");
+ float[] newArray = new float[to - from];
+ if (to > original.length)
+ {
+ System.arraycopy(original, from, newArray, 0,
+ original.length - from);
+ fill(newArray, original.length, newArray.length, 0f);
+ }
+ else
+ System.arraycopy(original, from, newArray, 0, to - from);
+ return newArray;
+ }
+
+ /**
+ * Returns a copy of the supplied array, truncating or padding as
+ * necessary with <code>0</code> to obtain the specified length.
+ * Indices that are valid for both arrays will return the same value.
+ * Indices that only exist in the returned array (due to the new length
+ * being greater than the original length) will return <code>0</code>.
+ * This is equivalent to calling
+ * <code>copyOfRange(original, 0, newLength)</code>.
+ *
+ * @param original the original array to be copied.
+ * @param newLength the length of the returned array.
+ * @return a copy of the original array, truncated or padded with
+ * <code>0</code> to obtain the required length.
+ * @throws NegativeArraySizeException if <code>newLength</code> is negative.
+ * @throws NullPointerException if <code>original</code> is <code>null</code>.
+ * @since 1.6
+ * @see #copyOfRange(int[],int,int)
+ */
+ public static int[] copyOf(int[] original, int newLength)
+ {
+ if (newLength < 0)
+ throw new NegativeArraySizeException("The array size is negative.");
+ return copyOfRange(original, 0, newLength);
+ }
+
+ /**
+ * Copies the specified range of the supplied array to a new
+ * array, padding as necessary with <code>0</code>
+ * if <code>to</code> is greater than the length of the original
+ * array. <code>from</code> must be in the range zero to
+ * <code>original.length</code> and can not be greater than
+ * <code>to</code>. The initial element of the
+ * returned array will be equal to <code>original[from]</code>,
+ * except where <code>from</code> is equal to <code>to</code>
+ * (where a zero-length array will be returned) or <code>
+ * <code>from</code> is equal to <code>original.length</code>
+ * (where an array padded with <code>0</code> will be
+ * returned). The returned array is always of length
+ * <code>to - from</code>.
+ *
+ * @param original the array from which to copy.
+ * @param from the initial index of the range, inclusive.
+ * @param to the final index of the range, exclusive.
+ * @return a copy of the specified range, with padding to
+ * obtain the required length.
+ * @throws ArrayIndexOutOfBoundsException if <code>from < 0</code>
+ * or <code>from > original.length</code>
+ * @throws IllegalArgumentException if <code>from > to</code>
+ * @throws NullPointerException if <code>original</code> is <code>null</code>.
+ * @since 1.6
+ * @see #copyOf(int[],int)
+ */
+ public static int[] copyOfRange(int[] original, int from, int to)
+ {
+ if (from > to)
+ throw new IllegalArgumentException("The initial index is after " +
+ "the final index.");
+ int[] newArray = new int[to - from];
+ if (to > original.length)
+ {
+ System.arraycopy(original, from, newArray, 0,
+ original.length - from);
+ fill(newArray, original.length, newArray.length, 0);
+ }
+ else
+ System.arraycopy(original, from, newArray, 0, to - from);
+ return newArray;
+ }
+
+ /**
+ * Returns a copy of the supplied array, truncating or padding as
+ * necessary with <code>0L</code> to obtain the specified length.
+ * Indices that are valid for both arrays will return the same value.
+ * Indices that only exist in the returned array (due to the new length
+ * being greater than the original length) will return <code>0L</code>.
+ * This is equivalent to calling
+ * <code>copyOfRange(original, 0, newLength)</code>.
+ *
+ * @param original the original array to be copied.
+ * @param newLength the length of the returned array.
+ * @return a copy of the original array, truncated or padded with
+ * <code>0L</code> to obtain the required length.
+ * @throws NegativeArraySizeException if <code>newLength</code> is negative.
+ * @throws NullPointerException if <code>original</code> is <code>null</code>.
+ * @since 1.6
+ * @see #copyOfRange(long[],int,int)
+ */
+ public static long[] copyOf(long[] original, int newLength)
+ {
+ if (newLength < 0)
+ throw new NegativeArraySizeException("The array size is negative.");
+ return copyOfRange(original, 0, newLength);
+ }
+
+ /**
+ * Copies the specified range of the supplied array to a new
+ * array, padding as necessary with <code>0L</code>
+ * if <code>to</code> is greater than the length of the original
+ * array. <code>from</code> must be in the range zero to
+ * <code>original.length</code> and can not be greater than
+ * <code>to</code>. The initial element of the
+ * returned array will be equal to <code>original[from]</code>,
+ * except where <code>from</code> is equal to <code>to</code>
+ * (where a zero-length array will be returned) or <code>
+ * <code>from</code> is equal to <code>original.length</code>
+ * (where an array padded with <code>0L</code> will be
+ * returned). The returned array is always of length
+ * <code>to - from</code>.
+ *
+ * @param original the array from which to copy.
+ * @param from the initial index of the range, inclusive.
+ * @param to the final index of the range, exclusive.
+ * @return a copy of the specified range, with padding to
+ * obtain the required length.
+ * @throws ArrayIndexOutOfBoundsException if <code>from < 0</code>
+ * or <code>from > original.length</code>
+ * @throws IllegalArgumentException if <code>from > to</code>
+ * @throws NullPointerException if <code>original</code> is <code>null</code>.
+ * @since 1.6
+ * @see #copyOf(long[],int)
+ */
+ public static long[] copyOfRange(long[] original, int from, int to)
+ {
+ if (from > to)
+ throw new IllegalArgumentException("The initial index is after " +
+ "the final index.");
+ long[] newArray = new long[to - from];
+ if (to > original.length)
+ {
+ System.arraycopy(original, from, newArray, 0,
+ original.length - from);
+ fill(newArray, original.length, newArray.length, 0L);
+ }
+ else
+ System.arraycopy(original, from, newArray, 0, to - from);
+ return newArray;
+ }
+
+ /**
+ * Returns a copy of the supplied array, truncating or padding as
+ * necessary with <code>(short)0</code> to obtain the specified length.
+ * Indices that are valid for both arrays will return the same value.
+ * Indices that only exist in the returned array (due to the new length
+ * being greater than the original length) will return <code>(short)0</code>.
+ * This is equivalent to calling
+ * <code>copyOfRange(original, 0, newLength)</code>.
+ *
+ * @param original the original array to be copied.
+ * @param newLength the length of the returned array.
+ * @return a copy of the original array, truncated or padded with
+ * <code>(short)0</code> to obtain the required length.
+ * @throws NegativeArraySizeException if <code>newLength</code> is negative.
+ * @throws NullPointerException if <code>original</code> is <code>null</code>.
+ * @since 1.6
+ * @see #copyOfRange(short[],int,int)
+ */
+ public static short[] copyOf(short[] original, int newLength)
+ {
+ if (newLength < 0)
+ throw new NegativeArraySizeException("The array size is negative.");
+ return copyOfRange(original, 0, newLength);
+ }
+
+ /**
+ * Copies the specified range of the supplied array to a new
+ * array, padding as necessary with <code>(short)0</code>
+ * if <code>to</code> is greater than the length of the original
+ * array. <code>from</code> must be in the range zero to
+ * <code>original.length</code> and can not be greater than
+ * <code>to</code>. The initial element of the
+ * returned array will be equal to <code>original[from]</code>,
+ * except where <code>from</code> is equal to <code>to</code>
+ * (where a zero-length array will be returned) or <code>
+ * <code>from</code> is equal to <code>original.length</code>
+ * (where an array padded with <code>(short)0</code> will be
+ * returned). The returned array is always of length
+ * <code>to - from</code>.
+ *
+ * @param original the array from which to copy.
+ * @param from the initial index of the range, inclusive.
+ * @param to the final index of the range, exclusive.
+ * @return a copy of the specified range, with padding to
+ * obtain the required length.
+ * @throws ArrayIndexOutOfBoundsException if <code>from < 0</code>
+ * or <code>from > original.length</code>
+ * @throws IllegalArgumentException if <code>from > to</code>
+ * @throws NullPointerException if <code>original</code> is <code>null</code>.
+ * @since 1.6
+ * @see #copyOf(short[],int)
+ */
+ public static short[] copyOfRange(short[] original, int from, int to)
+ {
+ if (from > to)
+ throw new IllegalArgumentException("The initial index is after " +
+ "the final index.");
+ short[] newArray = new short[to - from];
+ if (to > original.length)
+ {
+ System.arraycopy(original, from, newArray, 0,
+ original.length - from);
+ fill(newArray, original.length, newArray.length, (short)0);
+ }
+ else
+ System.arraycopy(original, from, newArray, 0, to - from);
+ return newArray;
+ }
+
+ /**
+ * Returns a copy of the supplied array, truncating or padding as
+ * necessary with <code>null</code> to obtain the specified length.
+ * Indices that are valid for both arrays will return the same value.
+ * Indices that only exist in the returned array (due to the new length
+ * being greater than the original length) will return <code>null</code>.
+ * This is equivalent to calling
+ * <code>copyOfRange(original, 0, newLength)</code>.
+ *
+ * @param original the original array to be copied.
+ * @param newLength the length of the returned array.
+ * @return a copy of the original array, truncated or padded with
+ * <code>null</code> to obtain the required length.
+ * @throws NegativeArraySizeException if <code>newLength</code> is negative.
+ * @throws NullPointerException if <code>original</code> is <code>null</code>.
+ * @since 1.6
+ * @see #copyOfRange(T[],int,int)
+ */
+ public static <T> T[] copyOf(T[] original, int newLength)
+ {
+ if (newLength < 0)
+ throw new NegativeArraySizeException("The array size is negative.");
+ return copyOfRange(original, 0, newLength);
+ }
+
+ /**
+ * Copies the specified range of the supplied array to a new
+ * array, padding as necessary with <code>null</code>
+ * if <code>to</code> is greater than the length of the original
+ * array. <code>from</code> must be in the range zero to
+ * <code>original.length</code> and can not be greater than
+ * <code>to</code>. The initial element of the
+ * returned array will be equal to <code>original[from]</code>,
+ * except where <code>from</code> is equal to <code>to</code>
+ * (where a zero-length array will be returned) or <code>
+ * <code>from</code> is equal to <code>original.length</code>
+ * (where an array padded with <code>null</code> will be
+ * returned). The returned array is always of length
+ * <code>to - from</code>.
+ *
+ * @param original the array from which to copy.
+ * @param from the initial index of the range, inclusive.
+ * @param to the final index of the range, exclusive.
+ * @return a copy of the specified range, with padding to
+ * obtain the required length.
+ * @throws ArrayIndexOutOfBoundsException if <code>from < 0</code>
+ * or <code>from > original.length</code>
+ * @throws IllegalArgumentException if <code>from > to</code>
+ * @throws NullPointerException if <code>original</code> is <code>null</code>.
+ * @since 1.6
+ * @see #copyOf(T[],int)
+ */
+ public static <T> T[] copyOfRange(T[] original, int from, int to)
+ {
+ if (from > to)
+ throw new IllegalArgumentException("The initial index is after " +
+ "the final index.");
+ T[] newArray = (T[]) new Object[to - from];
+ if (to > original.length)
+ {
+ System.arraycopy(original, from, newArray, 0,
+ original.length - from);
+ fill(newArray, original.length, newArray.length, null);
+ }
+ else
+ System.arraycopy(original, from, newArray, 0, to - from);
+ return newArray;
+ }
+
+ /**
+ * Returns a copy of the supplied array, truncating or padding as
+ * necessary with <code>null</code> to obtain the specified length.
+ * Indices that are valid for both arrays will return the same value.
+ * Indices that only exist in the returned array (due to the new length
+ * being greater than the original length) will return <code>null</code>.
+ * This is equivalent to calling
+ * <code>copyOfRange(original, 0, newLength, newType)</code>. The returned
+ * array will be of the specified type, <code>newType</code>.
+ *
+ * @param original the original array to be copied.
+ * @param newLength the length of the returned array.
+ * @param newType the type of the returned array.
+ * @return a copy of the original array, truncated or padded with
+ * <code>null</code> to obtain the required length.
+ * @throws NegativeArraySizeException if <code>newLength</code> is negative.
+ * @throws NullPointerException if <code>original</code> is <code>null</code>.
+ * @since 1.6
+ * @see #copyOfRange(U[],int,int,Class)
+ */
+ public static <T,U> T[] copyOf(U[] original, int newLength,
+ Class<? extends T[]> newType)
+ {
+ if (newLength < 0)
+ throw new NegativeArraySizeException("The array size is negative.");
+ return copyOfRange(original, 0, newLength, newType);
+ }
+
+ /**
+ * Copies the specified range of the supplied array to a new
+ * array, padding as necessary with <code>null</code>
+ * if <code>to</code> is greater than the length of the original
+ * array. <code>from</code> must be in the range zero to
+ * <code>original.length</code> and can not be greater than
+ * <code>to</code>. The initial element of the
+ * returned array will be equal to <code>original[from]</code>,
+ * except where <code>from</code> is equal to <code>to</code>
+ * (where a zero-length array will be returned) or <code>
+ * <code>from</code> is equal to <code>original.length</code>
+ * (where an array padded with <code>null</code> will be
+ * returned). The returned array is always of length
+ * <code>to - from</code> and will be of the specified type,
+ * <code>newType</code>.
+ *
+ * @param original the array from which to copy.
+ * @param from the initial index of the range, inclusive.
+ * @param to the final index of the range, exclusive.
+ * @param newType the type of the returned array.
+ * @return a copy of the specified range, with padding to
+ * obtain the required length.
+ * @throws ArrayIndexOutOfBoundsException if <code>from < 0</code>
+ * or <code>from > original.length</code>
+ * @throws IllegalArgumentException if <code>from > to</code>
+ * @throws NullPointerException if <code>original</code> is <code>null</code>.
+ * @since 1.6
+ * @see #copyOf(T[],int)
+ */
+ public static <T,U> T[] copyOfRange(U[] original, int from, int to,
+ Class<? extends T[]> newType)
+ {
+ if (from > to)
+ throw new IllegalArgumentException("The initial index is after " +
+ "the final index.");
+ T[] newArray = (T[]) Array.newInstance(newType.getComponentType(),
+ to - from);
+ if (to > original.length)
+ {
+ System.arraycopy(original, from, newArray, 0,
+ original.length - from);
+ fill(newArray, original.length, newArray.length, null);
+ }
+ else
+ System.arraycopy(original, from, newArray, 0, to - from);
+ return newArray;
+ }
}
diff --git a/libjava/classpath/java/util/Calendar.java b/libjava/classpath/java/util/Calendar.java
index 8c46c01..2b385b1 100644
--- a/libjava/classpath/java/util/Calendar.java
+++ b/libjava/classpath/java/util/Calendar.java
@@ -43,9 +43,12 @@ import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
+
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
+import java.text.DateFormatSymbols;
+
/**
* This class is an abstract base class for Calendars, which can be
* used to convert between <code>Date</code> objects and a set of
@@ -99,6 +102,20 @@ day_of_week + week_of_year</pre>
* specific field by one, propagating overflows), or
* <code>add</code>ing/substracting a fixed amount to a field.
*
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ * @author Jochen Hoenicke (Jochen.Hoenicke@Informatik.Uni-Oldenburg.de)
+ * @author Warren Levy (warrenl@cygnus.com)
+ * @author Jeff Sturm (jsturm@one-point.com)
+ * @author Tom Tromey (tromey@redhat.com)
+ * @author Bryce McKinlay (mckinlay@redhat.com)
+ * @author Ingo Proetel (proetel@aicas.com)
+ * @author Jerry Quinn (jlquinn@optonline.net)
+ * @author Jeroen Frijters (jeroen@frijters.net)
+ * @author Noa Resare (noa@resare.com)
+ * @author Sven de Marothy (sven@physto.se)
+ * @author David Gilbert (david.gilbert@object-refinery.com)
+ * @author Olivier Jolly (olivier.jolly@pcedev.com)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
* @see Date
* @see GregorianCalendar
* @see TimeZone
@@ -326,6 +343,34 @@ public abstract class Calendar
public static final int PM = 1;
/**
+ * A style specifier for {@link #getDisplayNames(int,int,Locale)}
+ * stating that names should be returned in both long and short variants.
+ *
+ * @since 1.6
+ * @see #SHORT
+ * @see #LONG
+ */
+ public static final int ALL_STYLES = 0;
+
+ /**
+ * A style specifier for {@link #getDisplayName(int,int,Locale)}
+ * and {@link #getDisplayNames(int,int,Locale)} stating that names
+ * should be returned in their short variant if applicable.
+ *
+ * @since 1.6
+ */
+ public static final int SHORT = 1;
+
+ /**
+ * A style specifier for {@link #getDisplayName(int,int,Locale)}
+ * and {@link #getDisplayNames(int,int,Locale)} stating that names
+ * should be returned in their long variant if applicable.
+ *
+ * @since 1.6
+ */
+ public static final int LONG = 2;
+
+ /**
* The time fields. The array is indexed by the constants YEAR to
* DST_OFFSET.
* @serial
@@ -527,7 +572,7 @@ public abstract class Calendar
* Cache of locale->calendar-class mappings. This avoids having to do a ResourceBundle
* lookup for every getInstance call.
*/
- private static HashMap cache = new HashMap();
+ private static HashMap<Locale,Class> cache = new HashMap<Locale,Class>();
/** Preset argument types for calendar-class constructor lookup. */
private static Class[] ctorArgTypes = new Class[]
@@ -549,7 +594,7 @@ public abstract class Calendar
*/
public static synchronized Calendar getInstance(TimeZone zone, Locale locale)
{
- Class calendarClass = (Class) cache.get(locale);
+ Class calendarClass = cache.get(locale);
Throwable exception = null;
try
@@ -1343,4 +1388,205 @@ public abstract class Calendar
areFieldsSet = false;
}
}
+
+ /**
+ * Returns a localised textual representation of the current value
+ * of the given field using the specified style. If there is no
+ * applicable textual representation (e.g. the field has a numeric
+ * value), then <code>null</code> is returned. If one does exist,
+ * then the value is obtained from {@link #get(int)} and converted
+ * appropriately. For example, if the <code>MONTH</code> field is
+ * requested, then <code>get(MONTH)</code> is called. This is then
+ * converted to a textual representation based on its value and
+ * the style requested; if the <code>LONG</code> style is requested
+ * and the returned value is <code>11</code> from a
+ * {@link GregorianCalendar} implementation, then <code>"December"</code>
+ * is returned. By default, a textual representation is available
+ * for all fields which have an applicable value obtainable from
+ * {@link java.text.DateFormatSymbols}.
+ *
+ * @param field the calendar field whose textual representation should
+ * be obtained.
+ * @param style the style to use; either {@link #LONG} or {@link #SHORT}.
+ * @param locale the locale to use for translation.
+ * @return the textual representation of the given field in the specified
+ * style, or <code>null</code> if none is applicable.
+ * @throws IllegalArgumentException if <code>field</code> or <code>style</code>
+ * or invalid, or the calendar is non-lenient
+ * and has invalid values.
+ * @throws NullPointerException if <code>locale</code> is <code>null</code>.
+ * @since 1.6
+ */
+ public String getDisplayName(int field, int style, Locale locale)
+ {
+ if (field < 0 || field >= FIELD_COUNT)
+ throw new IllegalArgumentException("The field value, " + field +
+ ", is invalid.");
+ if (style != SHORT && style != LONG)
+ throw new IllegalArgumentException("The style must be either " +
+ "short or long.");
+ if (field == YEAR || field == WEEK_OF_YEAR ||
+ field == WEEK_OF_MONTH || field == DAY_OF_MONTH ||
+ field == DAY_OF_YEAR || field == DAY_OF_WEEK_IN_MONTH ||
+ field == HOUR || field == HOUR_OF_DAY || field == MINUTE ||
+ field == SECOND || field == MILLISECOND)
+ return null;
+
+ int value = get(field);
+ DateFormatSymbols syms = DateFormatSymbols.getInstance(locale);
+ if (field == ERA)
+ return syms.getEras()[value];
+ if (field == MONTH)
+ if (style == LONG)
+ return syms.getMonths()[value];
+ else
+ return syms.getShortMonths()[value];
+ if (field == DAY_OF_WEEK)
+ if (style == LONG)
+ return syms.getWeekdays()[value];
+ else
+ return syms.getShortWeekdays()[value];
+ if (field == AM_PM)
+ return syms.getAmPmStrings()[value];
+ if (field == ZONE_OFFSET)
+ if (style == LONG)
+ return syms.getZoneStrings()[value][1];
+ else
+ return syms.getZoneStrings()[value][2];
+ if (field == DST_OFFSET)
+ if (style == LONG)
+ return syms.getZoneStrings()[value][3];
+ else
+ return syms.getZoneStrings()[value][4];
+
+ throw new InternalError("Failed to resolve field " + field +
+ " with style " + style + " for locale " +
+ locale);
+ }
+
+ /**
+ * Returns a map linking all specified textual representations
+ * of the given field to their numerical values. The textual
+ * representations included are determined by the specified
+ * style and locale. For example, if the style <code>LONG</code>
+ * is specified and the German locale, then the map will
+ * contain "Montag" to {@link #MONDAY}, "Dienstag" to
+ * {@link #TUESDAY}, "Mittwoch" to {@link #WEDNESDAY} and
+ * so on. The default implementation uses the values returned
+ * by {@link DateFormatSymbols} so, for example, the style
+ * {@link #ALL_STYLES} and the field {@link #MONTH} will return
+ * a map filled with the values returned from
+ * {@link DateFormatSymbols#getMonths()} and
+ * {@link DateFormatSymbols#getShortMonths()}. If there are
+ * no textual representations for a given field (usually because
+ * it is purely numeric, such as the year in the
+ * {@link GregorianCalendar}), <code>null</code> is returned.
+ *
+ * @param field the calendar field whose textual representation should
+ * be obtained.
+ * @param style the style to use; either {@link #LONG}, {@link #SHORT}
+ * or {@link ALL_STYLES}.
+ * @param locale the locale to use for translation.
+ * @return a map of the textual representations of the given field in the
+ * specified style to their numeric values, or <code>null</code>
+ * if none is applicable.
+ * @throws IllegalArgumentException if <code>field</code> or <code>style</code>
+ * or invalid, or the calendar is non-lenient
+ * and has invalid values.
+ * @throws NullPointerException if <code>locale</code> is <code>null</code>.
+ * @since 1.6
+ */
+ public Map<String,Integer> getDisplayNames(int field, int style, Locale locale)
+ {
+ if (field < 0 || field >= FIELD_COUNT)
+ throw new IllegalArgumentException("The field value, " + field +
+ ", is invalid.");
+ if (style != SHORT && style != LONG && style != ALL_STYLES)
+ throw new IllegalArgumentException("The style must be either " +
+ "short, long or all styles.");
+ if (field == YEAR || field == WEEK_OF_YEAR ||
+ field == WEEK_OF_MONTH || field == DAY_OF_MONTH ||
+ field == DAY_OF_YEAR || field == DAY_OF_WEEK_IN_MONTH ||
+ field == HOUR || field == HOUR_OF_DAY || field == MINUTE ||
+ field == SECOND || field == MILLISECOND)
+ return null;
+
+ DateFormatSymbols syms = DateFormatSymbols.getInstance(locale);
+ Map<String,Integer> map = new HashMap<String,Integer>();
+ if (field == ERA)
+ {
+ String[] eras = syms.getEras();
+ for (int a = 0; a < eras.length; ++a)
+ map.put(eras[a], a);
+ return map;
+ }
+ if (field == MONTH)
+ {
+ if (style == LONG || style == ALL_STYLES)
+ {
+ String[] months = syms.getMonths();
+ for (int a = 0; a < months.length; ++a)
+ map.put(months[a], a);
+ }
+ if (style == SHORT || style == ALL_STYLES)
+ {
+ String[] months = syms.getShortMonths();
+ for (int a = 0; a < months.length; ++a)
+ map.put(months[a], a);
+ }
+ return map;
+ }
+ if (field == DAY_OF_WEEK)
+ {
+ if (style == LONG || style == ALL_STYLES)
+ {
+ String[] weekdays = syms.getWeekdays();
+ for (int a = SUNDAY; a < weekdays.length; ++a)
+ map.put(weekdays[a], a);
+ }
+ if (style == SHORT || style == ALL_STYLES)
+ {
+ String[] weekdays = syms.getShortWeekdays();
+ for (int a = SUNDAY; a < weekdays.length; ++a)
+ map.put(weekdays[a], a);
+ }
+ return map;
+ }
+ if (field == AM_PM)
+ {
+ String[] ampms = syms.getAmPmStrings();
+ for (int a = 0; a < ampms.length; ++a)
+ map.put(ampms[a], a);
+ return map;
+ }
+ if (field == ZONE_OFFSET)
+ {
+ String[][] zones = syms.getZoneStrings();
+ for (int a = 0; a < zones.length; ++a)
+ {
+ if (style == LONG || style == ALL_STYLES)
+ map.put(zones[a][1], a);
+ if (style == SHORT || style == ALL_STYLES)
+ map.put(zones[a][2], a);
+ }
+ return map;
+ }
+ if (field == DST_OFFSET)
+ {
+ String[][] zones = syms.getZoneStrings();
+ for (int a = 0; a < zones.length; ++a)
+ {
+ if (style == LONG || style == ALL_STYLES)
+ map.put(zones[a][3], a);
+ if (style == SHORT || style == ALL_STYLES)
+ map.put(zones[a][4], a);
+ }
+ return map;
+ }
+
+ throw new InternalError("Failed to resolve field " + field +
+ " with style " + style + " for locale " +
+ locale);
+ }
+
}
diff --git a/libjava/classpath/java/util/Collections.java b/libjava/classpath/java/util/Collections.java
index 77ff6ed..fd802fe 100644
--- a/libjava/classpath/java/util/Collections.java
+++ b/libjava/classpath/java/util/Collections.java
@@ -706,14 +706,16 @@ public class Collections
{
if (!forward)
itr.next(); // Changing direction first.
- for ( ; i != pos; i++, o = itr.next());
+ for ( ; i != pos; i++, o = itr.next())
+ ;
forward = true;
}
else
{
if (forward)
itr.previous(); // Changing direction first.
- for ( ; i != pos; i--, o = itr.previous());
+ for ( ; i != pos; i--, o = itr.previous())
+ ;
forward = false;
}
final int d = compare(o, key, c);
@@ -1460,8 +1462,10 @@ public class Collections
public static int frequency (Collection<?> c, Object o)
{
int result = 0;
- for (Object v : c)
+ final Iterator<?> it = c.iterator();
+ while (it.hasNext())
{
+ Object v = it.next();
if (AbstractCollection.equals(o, v))
++result;
}
@@ -1522,8 +1526,9 @@ public class Collections
public static boolean disjoint(Collection<?> c1, Collection<?> c2)
{
Collection<Object> oc1 = (Collection<Object>) c1;
- for (Object o : oc1)
- if (c2.contains(o))
+ final Iterator<Object> it = oc1.iterator();
+ while (it.hasNext())
+ if (c2.contains(it.next()))
return false;
return true;
}
@@ -5113,7 +5118,7 @@ public class Collections
// The array returned is an array of UnmodifiableMapEntry instead of
// Map.Entry
- public Map.Entry<K,V>[] toArray()
+ public Object[] toArray()
{
Object[] mapEntryResult = super.toArray();
UnmodifiableMapEntry<K,V> result[] = null;
@@ -5127,7 +5132,7 @@ public class Collections
}
return result;
}
-
+
// The array returned is an array of UnmodifiableMapEntry instead of
// Map.Entry
public <S> S[] toArray(S[] array)
@@ -5825,8 +5830,10 @@ public class Collections
public boolean addAll(Collection<? extends E> coll)
{
Collection<E> typedColl = (Collection<E>) c;
- for (E element : typedColl)
+ final Iterator<E> it = typedColl.iterator();
+ while (it.hasNext())
{
+ final E element = it.next();
if (!type.isInstance(element))
throw new ClassCastException("A member of the collection is not of the correct type.");
}
@@ -6167,9 +6174,10 @@ public class Collections
public boolean addAll(int index, Collection<? extends E> coll)
{
Collection<E> typedColl = (Collection<E>) coll;
- for (E element : typedColl)
+ final Iterator<E> it = typedColl.iterator();
+ while (it.hasNext())
{
- if (!type.isInstance(element))
+ if (!type.isInstance(it.next()))
throw new ClassCastException("A member of the collection is not of the correct type.");
}
return list.addAll(index, coll);
@@ -6870,8 +6878,10 @@ public class Collections
public void putAll(Map<? extends K, ? extends V> map)
{
Map<K,V> typedMap = (Map<K,V>) map;
- for (Map.Entry<K,V> entry : typedMap.entrySet())
+ final Iterator<Map.Entry<K,V>> it = typedMap.entrySet().iterator();
+ while (it.hasNext())
{
+ final Map.Entry<K,V> entry = it.next();
if (!keyType.isInstance(entry.getKey()))
throw new ClassCastException("A key is of the wrong type.");
if (!valueType.isInstance(entry.getValue()))
@@ -7423,4 +7433,189 @@ public class Collections
}
} // class CheckedSortedSet
+ /**
+ * Returns a view of a {@link Deque} as a stack or LIFO (Last-In-First-Out)
+ * {@link Queue}. Each call to the LIFO queue corresponds to one
+ * equivalent method call to the underlying deque, with the exception
+ * of {@link Collection#addAll(Collection)}, which is emulated by a series
+ * of {@link Deque#push(E)} calls.
+ *
+ * @param deque the deque to convert to a LIFO queue.
+ * @return a LIFO queue.
+ * @since 1.6
+ */
+ public static <T> Queue<T> asLifoQueue(Deque<T> deque)
+ {
+ return new LIFOQueue<T>(deque);
+ }
+
+ /**
+ * Returns a set backed by the supplied map. The resulting set
+ * has the same performance, concurrency and ordering characteristics
+ * as the original map. The supplied map must be empty and should not
+ * be used after the set is created. Each call to the set corresponds
+ * to one equivalent method call to the underlying map, with the exception
+ * of {@link Set#addAll(Collection)} which is emulated by a series of
+ * calls to <code>put</code>.
+ *
+ * @param map the map to convert to a set.
+ * @return a set backed by the supplied map.
+ * @throws IllegalArgumentException if the map is not empty.
+ * @since 1.6
+ */
+ public static <E> Set<E> newSetFromMap(Map<E,Boolean> map)
+ {
+ return new MapSet<E>(map);
+ }
+
+ /**
+ * The implementation of {@link #asLIFOQueue(Deque)}.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.6
+ */
+ private static class LIFOQueue<T>
+ extends AbstractQueue<T>
+ {
+
+ /**
+ * The backing deque.
+ */
+ private Deque<T> deque;
+
+ /**
+ * Constructs a new {@link LIFOQueue} with the specified
+ * backing {@link Deque}.
+ *
+ * @param deque the backing deque.
+ */
+ public LIFOQueue(Deque<T> deque)
+ {
+ this.deque = deque;
+ }
+
+ public boolean add(T e)
+ {
+ return deque.offerFirst(e);
+ }
+
+ public boolean addAll(Collection<? extends T> c)
+ {
+ boolean result = false;
+ final Iterator<? extends T> it = c.iterator();
+ while (it.hasNext())
+ result |= deque.offerFirst(it.next());
+ return result;
+ }
+
+ public void clear()
+ {
+ deque.clear();
+ }
+
+ public boolean isEmpty()
+ {
+ return deque.isEmpty();
+ }
+
+ public Iterator<T> iterator()
+ {
+ return deque.iterator();
+ }
+
+ public boolean offer(T e)
+ {
+ return deque.offerFirst(e);
+ }
+
+ public T peek()
+ {
+ return deque.peek();
+ }
+
+ public T poll()
+ {
+ return deque.poll();
+ }
+
+ public int size()
+ {
+ return deque.size();
+ }
+ } // class LIFOQueue
+
+ /**
+ * The implementation of {@link #newSetFromMap(Map)}.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.6
+ */
+ private static class MapSet<E>
+ extends AbstractSet<E>
+ {
+
+ /**
+ * The backing map.
+ */
+ private Map<E,Boolean> map;
+
+ /**
+ * Constructs a new {@link MapSet} using the specified
+ * backing {@link Map}.
+ *
+ * @param map the backing map.
+ * @throws IllegalArgumentException if the map is not empty.
+ */
+ public MapSet(Map<E,Boolean> map)
+ {
+ if (!map.isEmpty())
+ throw new IllegalArgumentException("The map must be empty.");
+ this.map = map;
+ }
+
+ public boolean add(E e)
+ {
+ return map.put(e, true) == null;
+ }
+
+ public boolean addAll(Collection<? extends E> c)
+ {
+ boolean result = false;
+ final Iterator<? extends E> it = c.iterator();
+ while (it.hasNext())
+ result |= (map.put(it.next(), true) == null);
+ return result;
+ }
+
+ public void clear()
+ {
+ map.clear();
+ }
+
+ public boolean contains(Object o)
+ {
+ return map.containsKey(o);
+ }
+
+ public boolean isEmpty()
+ {
+ return map.isEmpty();
+ }
+
+ public Iterator<E> iterator()
+ {
+ return map.keySet().iterator();
+ }
+
+ public boolean remove(Object o)
+ {
+ return map.remove(o) != null;
+ }
+
+ public int size()
+ {
+ return map.size();
+ }
+ } // class MapSet
+
} // class Collections
diff --git a/libjava/classpath/java/util/Currency.java b/libjava/classpath/java/util/Currency.java
index 32ea753..a0933ec 100644
--- a/libjava/classpath/java/util/Currency.java
+++ b/libjava/classpath/java/util/Currency.java
@@ -44,6 +44,8 @@ import java.io.IOException;
import java.io.ObjectStreamException;
import java.io.Serializable;
+import java.util.spi.CurrencyNameProvider;
+
/**
* Representation of a currency for a particular locale. Each currency
* is identified by its ISO 4217 code, and only one instance of this
@@ -402,8 +404,35 @@ public final class Currency
*/
public String getSymbol(Locale locale)
{
- return LocaleHelper.getLocalizedString(locale, currencyCode,
- "currenciesSymbol", false, true);
+ String property = "currenciesSymbol." + currencyCode;
+ try
+ {
+ return ResourceBundle.getBundle("gnu.java.locale.LocaleInformation",
+ locale).getString(property);
+ }
+ catch (MissingResourceException exception)
+ {
+ /* This means runtime support for the locale
+ * is not available, so we check providers. */
+ }
+ for (CurrencyNameProvider p :
+ ServiceLoader.load(CurrencyNameProvider.class))
+ {
+ for (Locale loc : p.getAvailableLocales())
+ {
+ if (loc.equals(locale))
+ {
+ String localizedString = p.getSymbol(currencyCode,
+ locale);
+ if (localizedString != null)
+ return localizedString;
+ break;
+ }
+ }
+ }
+ if (locale.equals(Locale.ROOT)) // Base case
+ return currencyCode;
+ return getSymbol(LocaleHelper.getFallbackLocale(locale));
}
/**
diff --git a/libjava/classpath/java/util/Date.java b/libjava/classpath/java/util/Date.java
index f481753..1ad128e 100644
--- a/libjava/classpath/java/util/Date.java
+++ b/libjava/classpath/java/util/Date.java
@@ -856,7 +856,7 @@ public class Date
hour += 12;
}
else if (parseDayOfWeek(tok))
- ; // Ignore it; throw the token away.
+ { /* Ignore it; throw the token away. */ }
else if (tok.equals("UT") || tok.equals("UTC") || tok.equals("GMT"))
localTimezone = false;
else if (tok.startsWith("UT") || tok.startsWith("GMT"))
diff --git a/libjava/classpath/java/util/GregorianCalendar.java b/libjava/classpath/java/util/GregorianCalendar.java
index 83ac00e..6eb7ce8 100644
--- a/libjava/classpath/java/util/GregorianCalendar.java
+++ b/libjava/classpath/java/util/GregorianCalendar.java
@@ -1,5 +1,5 @@
/* java.util.GregorianCalendar
- Copyright (C) 1998, 1999, 2001, 2002, 2003, 2004
+ Copyright (C) 1998, 1999, 2001, 2002, 2003, 2004, 2007
Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -223,7 +223,6 @@ public class GregorianCalendar extends Calendar
{
this(zone, locale, false);
setTimeInMillis(System.currentTimeMillis());
- complete();
}
/**
@@ -842,13 +841,24 @@ public class GregorianCalendar extends Calendar
// which day of the week are we (0..6), relative to getFirstDayOfWeek
int relativeWeekday = (7 + fields[DAY_OF_WEEK] - getFirstDayOfWeek()) % 7;
- fields[WEEK_OF_MONTH] = (fields[DAY_OF_MONTH] - relativeWeekday + 12) / 7;
+ // which day of the week is the first of this month?
+ // nb 35 is the smallest multiple of 7 that ensures that
+ // the left hand side of the modulo operator is positive.
+ int relativeWeekdayOfFirst = (relativeWeekday - fields[DAY_OF_MONTH]
+ + 1 + 35) % 7;
+
+ // which week of the month is the first of this month in?
+ int minDays = getMinimalDaysInFirstWeek();
+ int weekOfFirst = ((7 - relativeWeekdayOfFirst) >= minDays) ? 1 : 0;
+
+ // which week of the month is this day in?
+ fields[WEEK_OF_MONTH] = (fields[DAY_OF_MONTH]
+ + relativeWeekdayOfFirst - 1) / 7 + weekOfFirst;
int weekOfYear = (fields[DAY_OF_YEAR] - relativeWeekday + 6) / 7;
// Do the Correction: getMinimalDaysInFirstWeek() is always in the
// first week.
- int minDays = getMinimalDaysInFirstWeek();
int firstWeekday = (7 + getWeekDay(fields[YEAR], minDays)
- getFirstDayOfWeek()) % 7;
if (minDays - firstWeekday < 1)
diff --git a/libjava/classpath/java/util/HashMap.java b/libjava/classpath/java/util/HashMap.java
index 92022a7..eca3ad6 100644
--- a/libjava/classpath/java/util/HashMap.java
+++ b/libjava/classpath/java/util/HashMap.java
@@ -380,11 +380,11 @@ public class HashMap<K, V> extends AbstractMap<K, V>
*/
public void putAll(Map<? extends K, ? extends V> m)
{
- Map<K,V> addMap;
-
- addMap = (Map<K,V>) m;
- for (Map.Entry<K,V> e : addMap.entrySet())
+ final Map<K,V> addMap = (Map<K,V>) m;
+ final Iterator<Map.Entry<K,V>> it = addMap.entrySet().iterator();
+ while (it.hasNext())
{
+ final Map.Entry<K,V> e = it.next();
// Optimize in case the Entry is one of our own.
if (e instanceof AbstractMap.SimpleEntry)
{
@@ -710,12 +710,12 @@ public class HashMap<K, V> extends AbstractMap<K, V>
*/
void putAllInternal(Map<? extends K, ? extends V> m)
{
- Map<K,V> addMap;
-
- addMap = (Map<K,V>) m;
+ final Map<K,V> addMap = (Map<K,V>) m;
+ final Iterator<Map.Entry<K,V>> it = addMap.entrySet().iterator();
size = 0;
- for (Map.Entry<K,V> e : addMap.entrySet())
+ while (it.hasNext())
{
+ final Map.Entry<K,V> e = it.next();
size++;
K key = e.getKey();
int idx = hash(key);
diff --git a/libjava/classpath/java/util/Hashtable.java b/libjava/classpath/java/util/Hashtable.java
index 2e265a4..a8567463 100644
--- a/libjava/classpath/java/util/Hashtable.java
+++ b/libjava/classpath/java/util/Hashtable.java
@@ -505,12 +505,11 @@ public class Hashtable<K, V> extends Dictionary<K, V>
*/
public synchronized void putAll(Map<? extends K, ? extends V> m)
{
- Map<K,V> addMap;
-
- addMap = (Map<K,V>) m;
-
- for (Map.Entry<K,V> e : addMap.entrySet())
+ final Map<K,V> addMap = (Map<K,V>) m;
+ final Iterator<Map.Entry<K,V>> it = addMap.entrySet().iterator();
+ while (it.hasNext())
{
+ final Map.Entry<K,V> e = it.next();
// Optimize in case the Entry is one of our own.
if (e instanceof AbstractMap.SimpleEntry)
{
@@ -857,13 +856,12 @@ public class Hashtable<K, V> extends Dictionary<K, V>
*/
void putAllInternal(Map<? extends K, ? extends V> m)
{
- Map<K,V> addMap;
-
- addMap = (Map<K,V>) m;
+ final Map<K,V> addMap = (Map<K,V>) m;
+ final Iterator<Map.Entry<K,V>> it = addMap.entrySet().iterator();
size = 0;
-
- for (Map.Entry<K,V> e : addMap.entrySet())
+ while (it.hasNext())
{
+ final Map.Entry<K,V> e = it.next();
size++;
K key = e.getKey();
int idx = hash(key);
diff --git a/libjava/classpath/java/util/LinkedList.java b/libjava/classpath/java/util/LinkedList.java
index 2d78573..3f8b2ad 100644
--- a/libjava/classpath/java/util/LinkedList.java
+++ b/libjava/classpath/java/util/LinkedList.java
@@ -1,5 +1,5 @@
/* LinkedList.java -- Linked list implementation of the List interface
- Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -64,15 +64,17 @@ import java.lang.reflect.Array;
* @author Original author unknown
* @author Bryce McKinlay
* @author Eric Blake (ebb9@email.byu.edu)
+ * @author Tom Tromey (tromey@redhat.com)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
* @see List
* @see ArrayList
* @see Vector
* @see Collections#synchronizedList(List)
* @since 1.2
- * @status missing javadoc, but complete to 1.4
+ * @status Complete to 1.6
*/
public class LinkedList<T> extends AbstractSequentialList<T>
- implements List<T>, Queue<T>, Cloneable, Serializable
+ implements List<T>, Deque<T>, Cloneable, Serializable
{
/**
* Compatible with JDK 1.2.
@@ -708,6 +710,10 @@ public class LinkedList<T> extends AbstractSequentialList<T>
}
/**
+ * Adds the specified element to the end of the list.
+ *
+ * @param value the value to add.
+ * @return true.
* @since 1.5
*/
public boolean offer(T value)
@@ -716,6 +722,11 @@ public class LinkedList<T> extends AbstractSequentialList<T>
}
/**
+ * Returns the first element of the list without removing
+ * it.
+ *
+ * @return the first element of the list.
+ * @throws NoSuchElementException if the list is empty.
* @since 1.5
*/
public T element()
@@ -724,6 +735,11 @@ public class LinkedList<T> extends AbstractSequentialList<T>
}
/**
+ * Returns the first element of the list without removing
+ * it.
+ *
+ * @return the first element of the list, or <code>null</code>
+ * if the list is empty.
* @since 1.5
*/
public T peek()
@@ -734,6 +750,10 @@ public class LinkedList<T> extends AbstractSequentialList<T>
}
/**
+ * Removes and returns the first element of the list.
+ *
+ * @return the first element of the list, or <code>null</code>
+ * if the list is empty.
* @since 1.5
*/
public T poll()
@@ -744,6 +764,10 @@ public class LinkedList<T> extends AbstractSequentialList<T>
}
/**
+ * Removes and returns the first element of the list.
+ *
+ * @return the first element of the list.
+ * @throws NoSuchElementException if the list is empty.
* @since 1.5
*/
public T remove()
@@ -992,4 +1016,245 @@ public class LinkedList<T> extends AbstractSequentialList<T>
lastReturned.data = o;
}
} // class LinkedListItr
+
+ /**
+ * Obtain an Iterator over this list in reverse sequential order.
+ *
+ * @return an Iterator over the elements of the list in
+ * reverse order.
+ * @since 1.6
+ */
+ public Iterator<T> descendingIterator()
+ {
+ return new Iterator<T>()
+ {
+ /** Number of modifications we know about. */
+ private int knownMod = modCount;
+
+ /** Entry that will be returned by next(). */
+ private Entry<T> next = last;
+
+ /** Entry that will be affected by remove() or set(). */
+ private Entry<T> lastReturned;
+
+ /** Index of `next'. */
+ private int position = size() - 1;
+
+ // This will get inlined, since it is private.
+ /**
+ * Checks for modifications made to the list from
+ * elsewhere while iteration is in progress.
+ *
+ * @throws ConcurrentModificationException if the
+ * list has been modified elsewhere.
+ */
+ private void checkMod()
+ {
+ if (knownMod != modCount)
+ throw new ConcurrentModificationException();
+ }
+
+ /**
+ * Tests to see if there are any more objects to
+ * return.
+ *
+ * @return true if the start of the list has not yet been
+ * reached.
+ */
+ public boolean hasNext()
+ {
+ return next != null;
+ }
+
+ /**
+ * Retrieves the next object from the list.
+ *
+ * @return The next object.
+ * @throws NoSuchElementException if there are
+ * no more objects to retrieve.
+ * @throws ConcurrentModificationException if the
+ * list has been modified elsewhere.
+ */
+ public T next()
+ {
+ checkMod();
+ if (next == null)
+ throw new NoSuchElementException();
+ --position;
+ lastReturned = next;
+ next = lastReturned.previous;
+ return lastReturned.data;
+ }
+
+ /**
+ * Removes the last object retrieved by <code>next()</code>
+ * from the list, if the list supports object removal.
+ *
+ * @throws ConcurrentModificationException if the list
+ * has been modified elsewhere.
+ * @throws IllegalStateException if the iterator is positioned
+ * before the start of the list or the last object has already
+ * been removed.
+ */
+ public void remove()
+ {
+ checkMod();
+ if (lastReturned == null)
+ throw new IllegalStateException();
+ removeEntry(lastReturned);
+ lastReturned = null;
+ ++knownMod;
+ }
+ };
+ }
+
+ /**
+ * Inserts the specified element at the front of the list.
+ *
+ * @param value the element to insert.
+ * @return true.
+ * @since 1.6
+ */
+ public boolean offerFirst(T value)
+ {
+ addFirst(value);
+ return true;
+ }
+
+ /**
+ * Inserts the specified element at the end of the list.
+ *
+ * @param value the element to insert.
+ * @return true.
+ * @since 1.6
+ */
+ public boolean offerLast(T value)
+ {
+ return add(value);
+ }
+
+ /**
+ * Returns the first element of the list without removing
+ * it.
+ *
+ * @return the first element of the list, or <code>null</code>
+ * if the list is empty.
+ * @since 1.6
+ */
+ public T peekFirst()
+ {
+ return peek();
+ }
+
+ /**
+ * Returns the last element of the list without removing
+ * it.
+ *
+ * @return the last element of the list, or <code>null</code>
+ * if the list is empty.
+ * @since 1.6
+ */
+ public T peekLast()
+ {
+ if (size == 0)
+ return null;
+ return getLast();
+ }
+
+ /**
+ * Removes and returns the first element of the list.
+ *
+ * @return the first element of the list, or <code>null</code>
+ * if the list is empty.
+ * @since 1.6
+ */
+ public T pollFirst()
+ {
+ return poll();
+ }
+
+ /**
+ * Removes and returns the last element of the list.
+ *
+ * @return the last element of the list, or <code>null</code>
+ * if the list is empty.
+ * @since 1.6
+ */
+ public T pollLast()
+ {
+ if (size == 0)
+ return null;
+ return removeLast();
+ }
+
+ /**
+ * Pops an element from the stack by removing and returning
+ * the first element in the list. This is equivalent to
+ * calling {@link #removeFirst()}.
+ *
+ * @return the top of the stack, which is the first element
+ * of the list.
+ * @throws NoSuchElementException if the list is empty.
+ * @since 1.6
+ * @see #removeFirst()
+ */
+ public T pop()
+ {
+ return removeFirst();
+ }
+
+ /**
+ * Pushes an element on to the stack by adding it to the
+ * front of the list. This is equivalent to calling
+ * {@link #addFirst(T)}.
+ *
+ * @param value the element to push on to the stack.
+ * @throws NoSuchElementException if the list is empty.
+ * @since 1.6
+ * @see #addFirst(T)
+ */
+ public void push(T value)
+ {
+ addFirst(value);
+ }
+
+ /**
+ * Removes the first occurrence of the specified element
+ * from the list, when traversing the list from head to
+ * tail. The list is unchanged if the element is not found.
+ * This is equivalent to calling {@link #remove(Object)}.
+ *
+ * @param o the element to remove.
+ * @return true if an instance of the object was removed.
+ * @since 1.6
+ */
+ public boolean removeFirstOccurrence(Object o)
+ {
+ return remove(o);
+ }
+
+ /**
+ * Removes the last occurrence of the specified element
+ * from the list, when traversing the list from head to
+ * tail. The list is unchanged if the element is not found.
+ *
+ * @param o the element to remove.
+ * @return true if an instance of the object was removed.
+ * @since 1.6
+ */
+ public boolean removeLastOccurrence(Object o)
+ {
+ Entry<T> e = last;
+ while (e != null)
+ {
+ if (equals(o, e.data))
+ {
+ removeEntry(e);
+ return true;
+ }
+ e = e.previous;
+ }
+ return false;
+ }
+
}
diff --git a/libjava/classpath/java/util/Locale.java b/libjava/classpath/java/util/Locale.java
index 4c91eeb..846ae7b 100644
--- a/libjava/classpath/java/util/Locale.java
+++ b/libjava/classpath/java/util/Locale.java
@@ -46,6 +46,8 @@ import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
+import java.util.spi.LocaleNameProvider;
+
/**
* Locales represent a specific country and culture. Classes which can be
* passed a Locale object tailor their information for a given locale. For
@@ -161,6 +163,11 @@ public final class Locale implements Serializable, Cloneable
/** Locale which represents the French speaking portion of Canada. */
public static final Locale CANADA_FRENCH = getLocale("fr", "CA");
+ /** The root locale, used as the base case in lookups by
+ * locale-sensitive operations.
+ */
+ public static final Locale ROOT = new Locale("","","");
+
/**
* Compatible with JDK 1.1+.
*/
@@ -674,6 +681,8 @@ public final class Locale implements Serializable, Cloneable
*/
public String getDisplayLanguage(Locale inLocale)
{
+ if (language.isEmpty())
+ return "";
try
{
ResourceBundle res =
@@ -685,8 +694,27 @@ public final class Locale implements Serializable, Cloneable
}
catch (MissingResourceException e)
{
- return language;
+ /* This means runtime support for the locale
+ * is not available, so we check providers. */
}
+ for (LocaleNameProvider p :
+ ServiceLoader.load(LocaleNameProvider.class))
+ {
+ for (Locale loc : p.getAvailableLocales())
+ {
+ if (loc.equals(inLocale))
+ {
+ String locLang = p.getDisplayLanguage(language,
+ inLocale);
+ if (locLang != null)
+ return locLang;
+ break;
+ }
+ }
+ }
+ if (inLocale.equals(Locale.ROOT)) // Base case
+ return language;
+ return getDisplayLanguage(LocaleHelper.getFallbackLocale(inLocale));
}
/**
@@ -732,6 +760,8 @@ public final class Locale implements Serializable, Cloneable
*/
public String getDisplayCountry(Locale inLocale)
{
+ if (country.isEmpty())
+ return "";
try
{
ResourceBundle res =
@@ -743,8 +773,27 @@ public final class Locale implements Serializable, Cloneable
}
catch (MissingResourceException e)
{
- return country;
+ /* This means runtime support for the locale
+ * is not available, so we check providers. */
}
+ for (LocaleNameProvider p :
+ ServiceLoader.load(LocaleNameProvider.class))
+ {
+ for (Locale loc : p.getAvailableLocales())
+ {
+ if (loc.equals(inLocale))
+ {
+ String locCountry = p.getDisplayCountry(country,
+ inLocale);
+ if (locCountry != null)
+ return locCountry;
+ break;
+ }
+ }
+ }
+ if (inLocale.equals(Locale.ROOT)) // Base case
+ return country;
+ return getDisplayCountry(LocaleHelper.getFallbackLocale(inLocale));
}
/**
@@ -791,6 +840,8 @@ public final class Locale implements Serializable, Cloneable
*/
public String getDisplayVariant(Locale inLocale)
{
+ if (variant.isEmpty())
+ return "";
try
{
ResourceBundle res =
@@ -802,8 +853,27 @@ public final class Locale implements Serializable, Cloneable
}
catch (MissingResourceException e)
{
- return variant;
+ /* This means runtime support for the locale
+ * is not available, so we check providers. */
+ }
+ for (LocaleNameProvider p :
+ ServiceLoader.load(LocaleNameProvider.class))
+ {
+ for (Locale loc : p.getAvailableLocales())
+ {
+ if (loc.equals(inLocale))
+ {
+ String locVar = p.getDisplayVariant(variant,
+ inLocale);
+ if (locVar != null)
+ return locVar;
+ break;
+ }
+ }
}
+ if (inLocale.equals(Locale.ROOT)) // Base case
+ return country;
+ return getDisplayVariant(LocaleHelper.getFallbackLocale(inLocale));
}
/**
diff --git a/libjava/classpath/java/util/PriorityQueue.java b/libjava/classpath/java/util/PriorityQueue.java
index c9cfd8b..9e738d6 100644
--- a/libjava/classpath/java/util/PriorityQueue.java
+++ b/libjava/classpath/java/util/PriorityQueue.java
@@ -164,6 +164,7 @@ public class PriorityQueue<E> extends AbstractQueue<E> implements Serializable
{
while (storage[++index] == null)
;
+
++count;
return storage[index];
}
diff --git a/libjava/classpath/java/util/ServiceConfigurationError.java b/libjava/classpath/java/util/ServiceConfigurationError.java
new file mode 100644
index 0000000..1d006c8
--- /dev/null
+++ b/libjava/classpath/java/util/ServiceConfigurationError.java
@@ -0,0 +1,94 @@
+/* ServiceConfigurationError.java -- An error on service loading.
+ Copyright (C) 2007 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.util;
+
+/**
+ * <p>
+ * An error thrown when a problem occurs during the loading
+ * of a service provider by a {@link ServiceLoader}. Such
+ * an error can occur for a number of reasons:
+ * </p>
+ * <ul>
+ * <li>An I/O error occurs</li>
+ * <li>The configuration file doesn't meet the specifications</li>
+ * <li>A listed class can not be found</li>
+ * <li>A listed class does not implement the service</li>
+ * <li>A listed class can not be instantiated</li>
+ * </ul>
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.6
+ */
+public class ServiceConfigurationError
+ extends Error
+{
+
+ /**
+ * Compatible with JDK 1.6
+ */
+ private static final long serialVersionUID = 74132770414881L;
+
+ /**
+ * Constructs a new {@link ServiceConfigurationError}
+ * with the specified message.
+ *
+ * @param message a message describing the error, or
+ * <code>null</code> if none is required.
+ */
+ public ServiceConfigurationError(String message)
+ {
+ super(message);
+ }
+
+ /**
+ * Constructs a new {@link ServiceConfigurationError}
+ * with the specified message and cause.
+ *
+ * @param message a message describing the error, or
+ * <code>null</code> if none is required.
+ * @param cause the cause of the error, or
+ * <code>null</code> if this is unknown
+ * or inappropriate.
+ */
+ public ServiceConfigurationError(String message,
+ Throwable cause)
+ {
+ super(message,cause);
+ }
+
+}
diff --git a/libjava/classpath/java/util/ServiceLoader.java b/libjava/classpath/java/util/ServiceLoader.java
new file mode 100644
index 0000000..9935416
--- /dev/null
+++ b/libjava/classpath/java/util/ServiceLoader.java
@@ -0,0 +1,274 @@
+/* ServiceLoader.java -- Allows loading of plug-in services.
+ Copyright (C) 2006, 2007 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.util;
+
+import gnu.classpath.ServiceFactory;
+
+/**
+ * <p>
+ * Facilities for loading service providers. A service is
+ * defined by a set of interfaces or abstract classes, and
+ * a service provider gives a concrete implementation of this.
+ * Service providers may be installed as part of the runtime
+ * environment using JAR files in the extension directories,
+ * or may be simply supplied on the classpath.
+ * </p>
+ * <p>
+ * In terms of loading a service, the service is defined by
+ * a single interface or abstract class which the provider
+ * implements. This may not constitute the entire service,
+ * but is simply a mechanism by which a provider of the
+ * service can be loaded and its capabilities determined.
+ * The variety of possible services means that no more
+ * requirements are made of the service provider other than
+ * that it must have an accessible zero argument constructor
+ * in order to allow an instance to be created.
+ * </p>
+ * <p>
+ * Service providers are listed in a file named after the
+ * service type in the directory <code>META-INF/services</code>.
+ * The file contains a list of classes, and must be encoded
+ * using UTF-8. Whitespace is ignored. Comments can be
+ * included by using a <code>'#'</code> prefix; anything occurring
+ * on the same line after this symbol is ignored. Duplicate classes
+ * are ignored.
+ * </p>
+ * <p>
+ * The classes are loaded using the same classloader that was
+ * queried in order to locate the configuration file. As a result,
+ * the providers do not need to reside in the same JAR file as the
+ * resource; they merely have to be accessible to this classloader,
+ * which may differ from the one that loaded the file itself.
+ * </p>
+ * <p>
+ * Providers are located and instantiated lazily, as calls to the
+ * {@link #iterator()} are made. Providers are cached, and those in
+ * the cache are returned first. The cache may be cleared by calling
+ * {@link #reload()}. Service loaders always execute in the security
+ * context of the caller, so ideally calls should be made from a trusted
+ * source.
+ * </p>
+ * <p>
+ * Note that this class is not thread-safe, and that strange errors may
+ * occur as the result of the use of remote URLs occurring on the classpath,
+ * which lead to erroneous web pages.
+ * </p>
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.6
+ */
+public final class ServiceLoader<S>
+ implements Iterable<S>
+{
+
+ /**
+ * The class of the service provider.
+ */
+ private Class<S> spi;
+
+ /**
+ * The class loader for the service provider.
+ */
+ private ClassLoader loader;
+
+ /**
+ * The cache of service providers.
+ */
+ private List<S> cache;
+
+ /**
+ * The {@link gnu.classpath.ServiceFactory} iterator
+ * from which providers are obtained.
+ */
+ private Iterator<S> serviceIt;
+
+ /**
+ * Constructs a new {@link ServiceLoader} with
+ * the specified provider and class loader.
+ *
+ * @param spi the service to load.
+ * @param loader the class loader to use.
+ */
+ private ServiceLoader(Class<S> spi, ClassLoader loader)
+ {
+ this.spi = spi;
+ this.loader = loader;
+ cache = new ArrayList<S>();
+ }
+
+ /**
+ * Lazily loads the available providers. The iterator first returns
+ * providers from the cache, in instantiation order, followed by any
+ * remaining providers, which are added to the cache after loading.
+ * The actual loading and parsing of the configuration file takes
+ * place in the {@link Iterator#hasNext()} and {@link Iterator#next()}
+ * methods, which means that they may result in a
+ * {@link ServiceConfigurationError} being thrown. If such an error
+ * does occur, subsequent invocations will attempt to recover.
+ * The {@link remove()} method is not supported and instead throws
+ * an {@link UnsupportedOperationException}.
+ *
+ * @return an iterator that lazily loads service providers.
+ */
+ public Iterator<S> iterator()
+ {
+ return new Iterator<S>()
+ {
+ /**
+ * The cache iterator.
+ */
+ private Iterator<S> cacheIt = cache.iterator();
+
+ public boolean hasNext()
+ {
+ if (cacheIt.hasNext())
+ return true;
+ if (serviceIt == null)
+ serviceIt =
+ ServiceFactory.lookupProviders(spi, loader, true);
+ return serviceIt.hasNext();
+ }
+
+ public S next()
+ {
+ if (cacheIt.hasNext())
+ return cacheIt.next();
+ if (serviceIt == null)
+ serviceIt =
+ ServiceFactory.lookupProviders(spi, loader, true);
+ S nextService = serviceIt.next();
+ cache.add(nextService);
+ return nextService;
+ }
+
+ public void remove()
+ {
+ throw new UnsupportedOperationException();
+ }
+ };
+ }
+
+ /**
+ * Creates a new service loader for the given service,
+ * using the context class loader of the current thread.
+ * This is equivalent to calling <code>ServiceLoader.load(service,
+ * Thread.currentThread().getContextClassLoader())</code>.
+ *
+ * @param service the interface or abstract class that represents
+ * the service.
+ * @return a new {@link ServiceLoader} instance.
+ */
+ public static <S> ServiceLoader<S> load(Class<S> service)
+ {
+ return load(service,
+ Thread.currentThread().getContextClassLoader());
+ }
+
+ /**
+ * Creates a new service loader for the given service,
+ * using the specified class loader. The class loader is
+ * used to access the configuration file and the service
+ * provider instances themselves. If the loader is
+ * <code>null</code>, the system class loader (or, if
+ * this is also <code>null</code>, the bootstrap class
+ * loader).
+ *
+ * @param service the interface or abstract class that represents
+ * the service.
+ * @param loader the class loader used to load the configuration
+ * file and service providers.
+ * @return a new {@link ServiceLoader} instance.
+ */
+ public static <S> ServiceLoader<S> load(Class<S> service,
+ ClassLoader loader)
+ {
+ if (loader == null)
+ loader = ClassLoader.getSystemClassLoader();
+ return new ServiceLoader(service, loader);
+ }
+
+ /**
+ * Creates a new service loader for the given service,
+ * using the extension class loader. If the extension
+ * class loader can not be found, the system class loader
+ * is used (or, if this is <code>null</code>, the
+ * bootstrap class loader). The primary use of this method
+ * is to only obtain installed services, ignoring any which
+ * may appear on the classpath. This is equivalent to calling
+ * <code>load(service, extClassLoader)</code> where
+ * <code>extClassLoader</code> is the extension class loader
+ * (or <code>null</code> if this is unavailable).
+ *
+ * @param service the interface or abstract class that represents
+ * the service.
+ * @return a new {@link ServiceLoader} instance.
+ */
+ public static <S> ServiceLoader<S> loadInstalled(Class<S> service)
+ {
+ /* We expect the extension class loader to be the parent
+ * of the system class loader, as in
+ * ClassLoader.getDefaultSystemClassLoader() */
+ return load(service,
+ ClassLoader.getSystemClassLoader().getParent());
+ }
+
+ /**
+ * Clears the cache of the provider, so that all providers
+ * are again read from the configuration file and instantiated.
+ */
+ public void reload()
+ {
+ cache.clear();
+ }
+
+ /**
+ * Returns a textual representation of this
+ * {@link ServiceLoader}.
+ *
+ * @return a textual representation of the
+ * service loader.
+ */
+ public String toString()
+ {
+ return getClass().getName() +
+ "[spi=" + spi +
+ ",loader=" + loader +
+ "]";
+ }
+
+}
diff --git a/libjava/classpath/java/util/StringTokenizer.java b/libjava/classpath/java/util/StringTokenizer.java
index 0b59abe..b230c73 100644
--- a/libjava/classpath/java/util/StringTokenizer.java
+++ b/libjava/classpath/java/util/StringTokenizer.java
@@ -181,13 +181,15 @@ public class StringTokenizer implements Enumeration<Object>
{
if (retDelims)
return str.substring(pos, ++pos);
- while (++pos < len && delim.indexOf(str.charAt(pos)) >= 0);
+ while (++pos < len && delim.indexOf(str.charAt(pos)) >= 0)
+ ;
}
if (pos < len)
{
int start = pos;
- while (++pos < len && delim.indexOf(str.charAt(pos)) < 0);
-
+ while (++pos < len && delim.indexOf(str.charAt(pos)) < 0)
+ ;
+
return str.substring(start, pos);
}
throw new NoSuchElementException();
diff --git a/libjava/classpath/java/util/TreeMap.java b/libjava/classpath/java/util/TreeMap.java
index 88abce1..f54cbc3 100644
--- a/libjava/classpath/java/util/TreeMap.java
+++ b/libjava/classpath/java/util/TreeMap.java
@@ -1,6 +1,6 @@
/* TreeMap.java -- a class providing a basic Red-Black Tree data structure,
mapping Object --> Object
- Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -79,6 +79,7 @@ import java.io.Serializable;
* @author Jon Zeppieri
* @author Bryce McKinlay
* @author Eric Blake (ebb9@email.byu.edu)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
* @see Map
* @see HashMap
* @see Hashtable
@@ -88,10 +89,10 @@ import java.io.Serializable;
* @see Collection
* @see Collections#synchronizedSortedMap(SortedMap)
* @since 1.2
- * @status updated to 1.4
+ * @status updated to 1.6
*/
public class TreeMap<K, V> extends AbstractMap<K, V>
- implements SortedMap<K, V>, Cloneable, Serializable
+ implements NavigableMap<K, V>, Cloneable, Serializable
{
// Implementation note:
// A red-black tree is a binary search tree with the additional properties
@@ -143,6 +144,16 @@ public class TreeMap<K, V> extends AbstractMap<K, V>
private transient Set<Map.Entry<K,V>> entries;
/**
+ * The cache for {@link #descendingMap()}.
+ */
+ private transient NavigableMap<K,V> descendingMap;
+
+ /**
+ * The cache for {@link #navigableKeySet()}.
+ */
+ private transient NavigableSet<K> nKeys;
+
+ /**
* Counts the number of modifications this TreeMap has undergone, used
* by Iterators to know when to throw ConcurrentModificationExceptions.
* Package visible for use by nested classes.
@@ -369,46 +380,7 @@ public class TreeMap<K, V> extends AbstractMap<K, V>
if (entries == null)
// Create an AbstractSet with custom implementations of those methods
// that can be overriden easily and efficiently.
- entries = new AbstractSet<Map.Entry<K,V>>()
- {
- public int size()
- {
- return size;
- }
-
- public Iterator<Map.Entry<K,V>> iterator()
- {
- return new TreeIterator(ENTRIES);
- }
-
- public void clear()
- {
- TreeMap.this.clear();
- }
-
- public boolean contains(Object o)
- {
- if (! (o instanceof Map.Entry))
- return false;
- Map.Entry<K,V> me = (Map.Entry<K,V>) o;
- Node<K,V> n = getNode(me.getKey());
- return n != nil && AbstractSet.equals(me.getValue(), n.value);
- }
-
- public boolean remove(Object o)
- {
- if (! (o instanceof Map.Entry))
- return false;
- Map.Entry<K,V> me = (Map.Entry<K,V>) o;
- Node<K,V> n = getNode(me.getKey());
- if (n != nil && AbstractSet.equals(me.getValue(), n.value))
- {
- removeNode(n);
- return true;
- }
- return false;
- }
- };
+ entries = new NavigableEntrySet();
return entries;
}
@@ -451,7 +423,9 @@ public class TreeMap<K, V> extends AbstractMap<K, V>
* in one appear in the other. The submap will throw an
* {@link IllegalArgumentException} for any attempt to access or add an
* element beyond the specified cutoff. The returned map does not include
- * the endpoint; if you want inclusion, pass the successor element.
+ * the endpoint; if you want inclusion, pass the successor element
+ * or call <code>headMap(toKey, true)</code>. This is equivalent to
+ * calling <code>headMap(toKey, false)</code>.
*
* @param toKey the (exclusive) cutoff point
* @return a view of the map less than the cutoff
@@ -462,7 +436,29 @@ public class TreeMap<K, V> extends AbstractMap<K, V>
*/
public SortedMap<K, V> headMap(K toKey)
{
- return new SubMap((K)(Object)nil, toKey);
+ return headMap(toKey, false);
+ }
+
+ /**
+ * Returns a view of this Map including all entries with keys less than
+ * (or equal to, if <code>inclusive</code> is true) <code>toKey</code>.
+ * The returned map is backed by the original, so changes in one appear
+ * in the other. The submap will throw an {@link IllegalArgumentException}
+ * for any attempt to access or add an element beyond the specified cutoff.
+ *
+ * @param toKey the cutoff point
+ * @param inclusive true if the cutoff point should be included.
+ * @return a view of the map less than (or equal to, if <code>inclusive</code>
+ * is true) the cutoff.
+ * @throws ClassCastException if <code>toKey</code> is not compatible with
+ * the comparator (or is not Comparable, for natural ordering)
+ * @throws NullPointerException if toKey is null, but the comparator does not
+ * tolerate null elements
+ */
+ public NavigableMap<K, V> headMap(K toKey, boolean inclusive)
+ {
+ return new SubMap((K)(Object)nil, inclusive
+ ? successor(getNode(toKey)).key : toKey);
}
/**
@@ -479,37 +475,7 @@ public class TreeMap<K, V> extends AbstractMap<K, V>
if (keys == null)
// Create an AbstractSet with custom implementations of those methods
// that can be overriden easily and efficiently.
- keys = new AbstractSet<K>()
- {
- public int size()
- {
- return size;
- }
-
- public Iterator<K> iterator()
- {
- return new TreeIterator(KEYS);
- }
-
- public void clear()
- {
- TreeMap.this.clear();
- }
-
- public boolean contains(Object o)
- {
- return containsKey(o);
- }
-
- public boolean remove(Object key)
- {
- Node<K,V> n = getNode((K) key);
- if (n == nil)
- return false;
- removeNode(n);
- return true;
- }
- };
+ keys = new KeySet();
return keys;
}
@@ -648,7 +614,9 @@ public class TreeMap<K, V> extends AbstractMap<K, V>
* {@link IllegalArgumentException} for any attempt to access or add an
* element beyond the specified cutoffs. The returned map includes the low
* endpoint but not the high; if you want to reverse this behavior on
- * either end, pass in the successor element.
+ * either end, pass in the successor element or call
+ * {@link #subMap(K,boolean,K,boolean)}. This call is equivalent to
+ * <code>subMap(fromKey, true, toKey, false)</code>.
*
* @param fromKey the (inclusive) low cutoff point
* @param toKey the (exclusive) high cutoff point
@@ -661,7 +629,34 @@ public class TreeMap<K, V> extends AbstractMap<K, V>
*/
public SortedMap<K, V> subMap(K fromKey, K toKey)
{
- return new SubMap(fromKey, toKey);
+ return subMap(fromKey, true, toKey, false);
+ }
+
+ /**
+ * Returns a view of this Map including all entries with keys greater (or
+ * equal to, if <code>fromInclusive</code> is true) <code>fromKey</code> and
+ * less than (or equal to, if <code>toInclusive</code> is true)
+ * <code>toKey</code>. The returned map is backed by the original, so
+ * changes in one appear in the other. The submap will throw an
+ * {@link IllegalArgumentException} for any attempt to access or add an
+ * element beyond the specified cutoffs.
+ *
+ * @param fromKey the low cutoff point
+ * @param fromInclusive true if the low cutoff point should be included.
+ * @param toKey the high cutoff point
+ * @param toInclusive true if the high cutoff point should be included.
+ * @return a view of the map for the specified range.
+ * @throws ClassCastException if either cutoff is not compatible with
+ * the comparator (or is not Comparable, for natural ordering)
+ * @throws NullPointerException if fromKey or toKey is null, but the
+ * comparator does not tolerate null elements
+ * @throws IllegalArgumentException if fromKey is greater than toKey
+ */
+ public NavigableMap<K, V> subMap(K fromKey, boolean fromInclusive,
+ K toKey, boolean toInclusive)
+ {
+ return new SubMap(fromInclusive ? fromKey : successor(getNode(fromKey)).key,
+ toInclusive ? successor(getNode(toKey)).key : toKey);
}
/**
@@ -671,6 +666,7 @@ public class TreeMap<K, V> extends AbstractMap<K, V>
* {@link IllegalArgumentException} for any attempt to access or add an
* element beyond the specified cutoff. The returned map includes the
* endpoint; if you want to exclude it, pass in the successor element.
+ * This is equivalent to calling <code>tailMap(fromKey, true)</code>.
*
* @param fromKey the (inclusive) low cutoff point
* @return a view of the map above the cutoff
@@ -681,7 +677,29 @@ public class TreeMap<K, V> extends AbstractMap<K, V>
*/
public SortedMap<K, V> tailMap(K fromKey)
{
- return new SubMap(fromKey, (K)(Object)nil);
+ return tailMap(fromKey, true);
+ }
+
+ /**
+ * Returns a view of this Map including all entries with keys greater or
+ * equal to <code>fromKey</code>. The returned map is backed by the
+ * original, so changes in one appear in the other. The submap will throw an
+ * {@link IllegalArgumentException} for any attempt to access or add an
+ * element beyond the specified cutoff. The returned map includes the
+ * endpoint; if you want to exclude it, pass in the successor element.
+ *
+ * @param fromKey the low cutoff point
+ * @param inclusive true if the cutoff point should be included.
+ * @return a view of the map above the cutoff
+ * @throws ClassCastException if <code>fromKey</code> is not compatible with
+ * the comparator (or is not Comparable, for natural ordering)
+ * @throws NullPointerException if fromKey is null, but the comparator
+ * does not tolerate null elements
+ */
+ public NavigableMap<K, V> tailMap(K fromKey, boolean inclusive)
+ {
+ return new SubMap(inclusive ? fromKey : successor(getNode(fromKey)).key,
+ (K)(Object)nil);
}
/**
@@ -972,6 +990,21 @@ public class TreeMap<K, V> extends AbstractMap<K, V>
*/
final Node<K,V> highestLessThan(K key)
{
+ return highestLessThan(key, false);
+ }
+
+ /**
+ * Find the "highest" node which is &lt; (or equal to,
+ * if <code>equal</code> is true) key. If key is nil,
+ * return last node. Package visible for use by nested
+ * classes.
+ *
+ * @param key the upper bound, exclusive
+ * @param equal true if the key should be returned if found.
+ * @return the previous node
+ */
+ final Node<K,V> highestLessThan(K key, boolean equal)
+ {
if (key == nil)
return lastNode();
@@ -988,9 +1021,9 @@ public class TreeMap<K, V> extends AbstractMap<K, V>
else if (comparison < 0)
current = current.left;
else // Exact match.
- return predecessor(last);
+ return (equal ? last : predecessor(last));
}
- return comparison <= 0 ? predecessor(last) : last;
+ return comparison < 0 ? predecessor(last) : last;
}
/**
@@ -1084,8 +1117,8 @@ public class TreeMap<K, V> extends AbstractMap<K, V>
/**
* Find the "lowest" node which is &gt;= key. If key is nil, return either
- * nil or the first node, depending on the parameter first.
- * Package visible for use by nested classes.
+ * nil or the first node, depending on the parameter first. Package visible
+ * for use by nested classes.
*
* @param key the lower bound, inclusive
* @param first true to return the first element instead of nil for nil key
@@ -1093,6 +1126,21 @@ public class TreeMap<K, V> extends AbstractMap<K, V>
*/
final Node<K,V> lowestGreaterThan(K key, boolean first)
{
+ return lowestGreaterThan(key, first, true);
+ }
+
+ /**
+ * Find the "lowest" node which is &gt; (or equal to, if <code>equal</code>
+ * is true) key. If key is nil, return either nil or the first node, depending
+ * on the parameter first. Package visible for use by nested classes.
+ *
+ * @param key the lower bound, inclusive
+ * @param first true to return the first element instead of nil for nil key
+ * @param equal true if the key should be returned if found.
+ * @return the next node
+ */
+ final Node<K,V> lowestGreaterThan(K key, boolean first, boolean equal)
+ {
if (key == nil)
return first ? firstNode() : nil;
@@ -1109,7 +1157,7 @@ public class TreeMap<K, V> extends AbstractMap<K, V>
else if (comparison < 0)
current = current.left;
else
- return current;
+ return (equal ? current : successor(current));
}
return comparison > 0 ? successor(last) : last;
}
@@ -1409,11 +1457,7 @@ public class TreeMap<K, V> extends AbstractMap<K, V>
*/
TreeIterator(int type)
{
- // FIXME gcj cannot handle this. Bug java/4695
- // this(type, firstNode(), nil);
- this.type = type;
- this.next = firstNode();
- this.max = nil;
+ this(type, firstNode(), nil);
}
/**
@@ -1489,26 +1533,36 @@ public class TreeMap<K, V> extends AbstractMap<K, V>
*
* @author Eric Blake (ebb9@email.byu.edu)
*/
- private final class SubMap<SK extends K,SV extends V>
- extends AbstractMap<SK,SV>
- implements SortedMap<SK,SV>
+ private final class SubMap
+ extends AbstractMap<K,V>
+ implements NavigableMap<K,V>
{
/**
* The lower range of this view, inclusive, or nil for unbounded.
* Package visible for use by nested classes.
*/
- final SK minKey;
+ final K minKey;
/**
* The upper range of this view, exclusive, or nil for unbounded.
* Package visible for use by nested classes.
*/
- final SK maxKey;
+ final K maxKey;
/**
* The cache for {@link #entrySet()}.
*/
- private Set<Map.Entry<SK,SV>> entries;
+ private Set<Map.Entry<K,V>> entries;
+
+ /**
+ * The cache for {@link #descendingMap()}.
+ */
+ private NavigableMap<K,V> descendingMap;
+
+ /**
+ * The cache for {@link #navigableKeySet()}.
+ */
+ private NavigableSet<K> nKeys;
/**
* Create a SubMap representing the elements between minKey (inclusive)
@@ -1519,9 +1573,9 @@ public class TreeMap<K, V> extends AbstractMap<K, V>
* @param maxKey the upper bound
* @throws IllegalArgumentException if minKey &gt; maxKey
*/
- SubMap(SK minKey, SK maxKey)
+ SubMap(K minKey, K maxKey)
{
- if (minKey != nil && maxKey != nil && compare((K) minKey, (K) maxKey) > 0)
+ if (minKey != nil && maxKey != nil && compare(minKey, maxKey) > 0)
throw new IllegalArgumentException("fromKey > toKey");
this.minKey = minKey;
this.maxKey = maxKey;
@@ -1535,12 +1589,41 @@ public class TreeMap<K, V> extends AbstractMap<K, V>
* @param key the key to check
* @return true if the key is in range
*/
- boolean keyInRange(SK key)
+ boolean keyInRange(K key)
{
- return ((minKey == nil || compare((K) key, (K) minKey) >= 0)
- && (maxKey == nil || compare((K) key, (K) maxKey) < 0));
+ return ((minKey == nil || compare(key, minKey) >= 0)
+ && (maxKey == nil || compare(key, maxKey) < 0));
}
+ public Entry<K,V> ceilingEntry(K key)
+ {
+ Entry<K,V> n = TreeMap.this.ceilingEntry(key);
+ if (n != null && keyInRange(n.getKey()))
+ return n;
+ return null;
+ }
+
+ public K ceilingKey(K key)
+ {
+ K found = TreeMap.this.ceilingKey(key);
+ if (keyInRange(found))
+ return found;
+ else
+ return null;
+ }
+
+ public NavigableSet<K> descendingKeySet()
+ {
+ return descendingMap().navigableKeySet();
+ }
+
+ public NavigableMap<K,V> descendingMap()
+ {
+ if (descendingMap == null)
+ descendingMap = new DescendingMap(this);
+ return descendingMap;
+ }
+
public void clear()
{
Node next = lowestGreaterThan(minKey, true);
@@ -1553,14 +1636,14 @@ public class TreeMap<K, V> extends AbstractMap<K, V>
}
}
- public Comparator<? super SK> comparator()
+ public Comparator<? super K> comparator()
{
return comparator;
}
public boolean containsKey(Object key)
{
- return keyInRange((SK) key) && TreeMap.this.containsKey(key);
+ return keyInRange((K) key) && TreeMap.this.containsKey(key);
}
public boolean containsValue(Object value)
@@ -1576,150 +1659,160 @@ public class TreeMap<K, V> extends AbstractMap<K, V>
return false;
}
- public Set<Map.Entry<SK,SV>> entrySet()
+ public Set<Map.Entry<K,V>> entrySet()
{
if (entries == null)
// Create an AbstractSet with custom implementations of those methods
// that can be overriden easily and efficiently.
- entries = new AbstractSet<Map.Entry<SK,SV>>()
- {
- public int size()
- {
- return SubMap.this.size();
- }
-
- public Iterator<Map.Entry<SK,SV>> iterator()
- {
- Node first = lowestGreaterThan(minKey, true);
- Node max = lowestGreaterThan(maxKey, false);
- return new TreeIterator(ENTRIES, first, max);
- }
-
- public void clear()
- {
- SubMap.this.clear();
- }
-
- public boolean contains(Object o)
- {
- if (! (o instanceof Map.Entry))
- return false;
- Map.Entry<SK,SV> me = (Map.Entry<SK,SV>) o;
- SK key = me.getKey();
- if (! keyInRange(key))
- return false;
- Node<K,V> n = getNode((K) key);
- return n != nil && AbstractSet.equals(me.getValue(), n.value);
- }
-
- public boolean remove(Object o)
- {
- if (! (o instanceof Map.Entry))
- return false;
- Map.Entry<SK,SV> me = (Map.Entry<SK,SV>) o;
- SK key = me.getKey();
- if (! keyInRange(key))
- return false;
- Node<K,V> n = getNode((K) key);
- if (n != nil && AbstractSet.equals(me.getValue(), n.value))
- {
- removeNode(n);
- return true;
- }
- return false;
- }
- };
+ entries = new SubMap.NavigableEntrySet();
return entries;
}
- public SK firstKey()
+ public Entry<K,V> firstEntry()
{
- Node<SK,SV> node = (Node<SK,SV>) lowestGreaterThan(minKey, true);
+ Node<K,V> node = lowestGreaterThan(minKey, true);
if (node == nil || ! keyInRange(node.key))
+ return null;
+ return node;
+ }
+
+ public K firstKey()
+ {
+ Entry<K,V> e = firstEntry();
+ if (e == null)
throw new NoSuchElementException();
- return node.key;
+ return e.getKey();
}
- public SV get(Object key)
+ public Entry<K,V> floorEntry(K key)
{
- if (keyInRange((SK) key))
- return (SV) TreeMap.this.get(key);
+ Entry<K,V> n = TreeMap.this.floorEntry(key);
+ if (n != null && keyInRange(n.getKey()))
+ return n;
return null;
}
- public SortedMap<SK,SV> headMap(SK toKey)
+ public K floorKey(K key)
{
- if (! keyInRange(toKey))
- throw new IllegalArgumentException("key outside range");
- return new SubMap(minKey, toKey);
+ K found = TreeMap.this.floorKey(key);
+ if (keyInRange(found))
+ return found;
+ else
+ return null;
+ }
+
+ public V get(Object key)
+ {
+ if (keyInRange((K) key))
+ return TreeMap.this.get(key);
+ return null;
}
- public Set<SK> keySet()
+ public SortedMap<K,V> headMap(K toKey)
+ {
+ return headMap(toKey, false);
+ }
+
+ public NavigableMap<K,V> headMap(K toKey, boolean inclusive)
+ {
+ if (!keyInRange(toKey))
+ throw new IllegalArgumentException("Key outside submap range");
+ return new SubMap(minKey, (inclusive ?
+ successor(getNode(toKey)).key : toKey));
+ }
+
+ public Set<K> keySet()
{
if (this.keys == null)
// Create an AbstractSet with custom implementations of those methods
// that can be overriden easily and efficiently.
- this.keys = new AbstractSet()
- {
- public int size()
- {
- return SubMap.this.size();
- }
-
- public Iterator<SK> iterator()
- {
- Node first = lowestGreaterThan(minKey, true);
- Node max = lowestGreaterThan(maxKey, false);
- return new TreeIterator(KEYS, first, max);
- }
+ this.keys = new SubMap.KeySet();
+ return this.keys;
+ }
- public void clear()
- {
- SubMap.this.clear();
- }
+ public Entry<K,V> higherEntry(K key)
+ {
+ Entry<K,V> n = TreeMap.this.higherEntry(key);
+ if (n != null && keyInRange(n.getKey()))
+ return n;
+ return null;
+ }
- public boolean contains(Object o)
- {
- if (! keyInRange((SK) o))
- return false;
- return getNode((K) o) != nil;
- }
+ public K higherKey(K key)
+ {
+ K found = TreeMap.this.higherKey(key);
+ if (keyInRange(found))
+ return found;
+ else
+ return null;
+ }
- public boolean remove(Object o)
- {
- if (! keyInRange((SK) o))
- return false;
- Node n = getNode((K) o);
- if (n != nil)
- {
- removeNode(n);
- return true;
- }
- return false;
- }
- };
- return this.keys;
+ public Entry<K,V> lastEntry()
+ {
+ return lowerEntry(maxKey);
}
- public SK lastKey()
+ public K lastKey()
{
- Node<SK,SV> node = (Node<SK,SV>) highestLessThan(maxKey);
- if (node == nil || ! keyInRange(node.key))
+ Entry<K,V> e = lastEntry();
+ if (e == null)
throw new NoSuchElementException();
- return (SK) node.key;
+ return e.getKey();
+ }
+
+ public Entry<K,V> lowerEntry(K key)
+ {
+ Entry<K,V> n = TreeMap.this.lowerEntry(key);
+ if (n != null && keyInRange(n.getKey()))
+ return n;
+ return null;
+ }
+
+ public K lowerKey(K key)
+ {
+ K found = TreeMap.this.lowerKey(key);
+ if (keyInRange(found))
+ return found;
+ else
+ return null;
+ }
+
+ public NavigableSet<K> navigableKeySet()
+ {
+ if (this.nKeys == null)
+ // Create an AbstractSet with custom implementations of those methods
+ // that can be overriden easily and efficiently.
+ this.nKeys = new SubMap.NavigableKeySet();
+ return this.nKeys;
+ }
+
+ public Entry<K,V> pollFirstEntry()
+ {
+ Entry<K,V> e = firstEntry();
+ if (e != null)
+ removeNode((Node<K,V>) e);
+ return e;
}
- public SV put(SK key, SV value)
+ public Entry<K,V> pollLastEntry()
+ {
+ Entry<K,V> e = lastEntry();
+ if (e != null)
+ removeNode((Node<K,V>) e);
+ return e;
+ }
+
+ public V put(K key, V value)
{
if (! keyInRange(key))
throw new IllegalArgumentException("Key outside range");
- return (SV) TreeMap.this.put(key, value);
+ return TreeMap.this.put(key, value);
}
- public SV remove(Object key)
+ public V remove(Object key)
{
- if (keyInRange((SK)key))
- return (SV) TreeMap.this.remove(key);
+ if (keyInRange((K)key))
+ return TreeMap.this.remove(key);
return null;
}
@@ -1736,21 +1829,34 @@ public class TreeMap<K, V> extends AbstractMap<K, V>
return count;
}
- public SortedMap<SK, SV> subMap(SK fromKey, SK toKey)
+ public SortedMap<K,V> subMap(K fromKey, K toKey)
+ {
+ return subMap(fromKey, true, toKey, false);
+ }
+
+ public NavigableMap<K,V> subMap(K fromKey, boolean fromInclusive,
+ K toKey, boolean toInclusive)
{
if (! keyInRange(fromKey) || ! keyInRange(toKey))
throw new IllegalArgumentException("key outside range");
- return new SubMap(fromKey, toKey);
+ return new SubMap(fromInclusive ? fromKey : successor(getNode(fromKey)).key,
+ toInclusive ? successor(getNode(toKey)).key : toKey);
}
- public SortedMap<SK, SV> tailMap(SK fromKey)
+ public SortedMap<K, V> tailMap(K fromKey)
+ {
+ return tailMap(fromKey, true);
+ }
+
+ public NavigableMap<K,V> tailMap(K fromKey, boolean inclusive)
{
if (! keyInRange(fromKey))
throw new IllegalArgumentException("key outside range");
- return new SubMap(fromKey, maxKey);
+ return new SubMap(inclusive ? fromKey : successor(getNode(fromKey)).key,
+ maxKey);
}
- public Collection<SV> values()
+ public Collection<V> values()
{
if (this.values == null)
// Create an AbstractCollection with custom implementations of those
@@ -1762,7 +1868,7 @@ public class TreeMap<K, V> extends AbstractMap<K, V>
return SubMap.this.size();
}
- public Iterator<SV> iterator()
+ public Iterator<V> iterator()
{
Node first = lowestGreaterThan(minKey, true);
Node max = lowestGreaterThan(maxKey, false);
@@ -1776,5 +1882,1439 @@ public class TreeMap<K, V> extends AbstractMap<K, V>
};
return this.values;
}
- } // class SubMap
+
+ private class KeySet
+ extends AbstractSet<K>
+ {
+ public int size()
+ {
+ return SubMap.this.size();
+ }
+
+ public Iterator<K> iterator()
+ {
+ Node first = lowestGreaterThan(minKey, true);
+ Node max = lowestGreaterThan(maxKey, false);
+ return new TreeIterator(KEYS, first, max);
+ }
+
+ public void clear()
+ {
+ SubMap.this.clear();
+ }
+
+ public boolean contains(Object o)
+ {
+ if (! keyInRange((K) o))
+ return false;
+ return getNode((K) o) != nil;
+ }
+
+ public boolean remove(Object o)
+ {
+ if (! keyInRange((K) o))
+ return false;
+ Node n = getNode((K) o);
+ if (n != nil)
+ {
+ removeNode(n);
+ return true;
+ }
+ return false;
+ }
+
+ } // class SubMap.KeySet
+
+ private final class NavigableKeySet
+ extends KeySet
+ implements NavigableSet<K>
+ {
+
+ public K ceiling(K k)
+ {
+ return SubMap.this.ceilingKey(k);
+ }
+
+ public Comparator<? super K> comparator()
+ {
+ return comparator;
+ }
+
+ public Iterator<K> descendingIterator()
+ {
+ return descendingSet().iterator();
+ }
+
+ public NavigableSet<K> descendingSet()
+ {
+ return new DescendingSet(this);
+ }
+
+ public K first()
+ {
+ return SubMap.this.firstKey();
+ }
+
+ public K floor(K k)
+ {
+ return SubMap.this.floorKey(k);
+ }
+
+ public SortedSet<K> headSet(K to)
+ {
+ return headSet(to, false);
+ }
+
+ public NavigableSet<K> headSet(K to, boolean inclusive)
+ {
+ return SubMap.this.headMap(to, inclusive).navigableKeySet();
+ }
+
+ public K higher(K k)
+ {
+ return SubMap.this.higherKey(k);
+ }
+
+ public K last()
+ {
+ return SubMap.this.lastKey();
+ }
+
+ public K lower(K k)
+ {
+ return SubMap.this.lowerKey(k);
+ }
+
+ public K pollFirst()
+ {
+ return SubMap.this.pollFirstEntry().getKey();
+ }
+
+ public K pollLast()
+ {
+ return SubMap.this.pollLastEntry().getKey();
+ }
+
+ public SortedSet<K> subSet(K from, K to)
+ {
+ return subSet(from, true, to, false);
+ }
+
+ public NavigableSet<K> subSet(K from, boolean fromInclusive,
+ K to, boolean toInclusive)
+ {
+ return SubMap.this.subMap(from, fromInclusive,
+ to, toInclusive).navigableKeySet();
+ }
+
+ public SortedSet<K> tailSet(K from)
+ {
+ return tailSet(from, true);
+ }
+
+ public NavigableSet<K> tailSet(K from, boolean inclusive)
+ {
+ return SubMap.this.tailMap(from, inclusive).navigableKeySet();
+ }
+
+ } // class SubMap.NavigableKeySet
+
+ /**
+ * Implementation of {@link #entrySet()}.
+ */
+ private class EntrySet
+ extends AbstractSet<Entry<K,V>>
+ {
+
+ public int size()
+ {
+ return SubMap.this.size();
+ }
+
+ public Iterator<Map.Entry<K,V>> iterator()
+ {
+ Node first = lowestGreaterThan(minKey, true);
+ Node max = lowestGreaterThan(maxKey, false);
+ return new TreeIterator(ENTRIES, first, max);
+ }
+
+ public void clear()
+ {
+ SubMap.this.clear();
+ }
+
+ public boolean contains(Object o)
+ {
+ if (! (o instanceof Map.Entry))
+ return false;
+ Map.Entry<K,V> me = (Map.Entry<K,V>) o;
+ K key = me.getKey();
+ if (! keyInRange(key))
+ return false;
+ Node<K,V> n = getNode(key);
+ return n != nil && AbstractSet.equals(me.getValue(), n.value);
+ }
+
+ public boolean remove(Object o)
+ {
+ if (! (o instanceof Map.Entry))
+ return false;
+ Map.Entry<K,V> me = (Map.Entry<K,V>) o;
+ K key = me.getKey();
+ if (! keyInRange(key))
+ return false;
+ Node<K,V> n = getNode(key);
+ if (n != nil && AbstractSet.equals(me.getValue(), n.value))
+ {
+ removeNode(n);
+ return true;
+ }
+ return false;
+ }
+ } // class SubMap.EntrySet
+
+ private final class NavigableEntrySet
+ extends EntrySet
+ implements NavigableSet<Entry<K,V>>
+ {
+
+ public Entry<K,V> ceiling(Entry<K,V> e)
+ {
+ return SubMap.this.ceilingEntry(e.getKey());
+ }
+
+ public Comparator<? super Entry<K,V>> comparator()
+ {
+ return new Comparator<Entry<K,V>>()
+ {
+ public int compare(Entry<K,V> t1, Entry<K,V> t2)
+ {
+ return comparator.compare(t1.getKey(), t2.getKey());
+ }
+ };
+ }
+
+ public Iterator<Entry<K,V>> descendingIterator()
+ {
+ return descendingSet().iterator();
+ }
+
+ public NavigableSet<Entry<K,V>> descendingSet()
+ {
+ return new DescendingSet(this);
+ }
+
+ public Entry<K,V> first()
+ {
+ return SubMap.this.firstEntry();
+ }
+
+ public Entry<K,V> floor(Entry<K,V> e)
+ {
+ return SubMap.this.floorEntry(e.getKey());
+ }
+
+ public SortedSet<Entry<K,V>> headSet(Entry<K,V> to)
+ {
+ return headSet(to, false);
+ }
+
+ public NavigableSet<Entry<K,V>> headSet(Entry<K,V> to, boolean inclusive)
+ {
+ return (NavigableSet<Entry<K,V>>)
+ SubMap.this.headMap(to.getKey(), inclusive).entrySet();
+ }
+
+ public Entry<K,V> higher(Entry<K,V> e)
+ {
+ return SubMap.this.higherEntry(e.getKey());
+ }
+
+ public Entry<K,V> last()
+ {
+ return SubMap.this.lastEntry();
+ }
+
+ public Entry<K,V> lower(Entry<K,V> e)
+ {
+ return SubMap.this.lowerEntry(e.getKey());
+ }
+
+ public Entry<K,V> pollFirst()
+ {
+ return SubMap.this.pollFirstEntry();
+ }
+
+ public Entry<K,V> pollLast()
+ {
+ return SubMap.this.pollLastEntry();
+ }
+
+ public SortedSet<Entry<K,V>> subSet(Entry<K,V> from, Entry<K,V> to)
+ {
+ return subSet(from, true, to, false);
+ }
+
+ public NavigableSet<Entry<K,V>> subSet(Entry<K,V> from, boolean fromInclusive,
+ Entry<K,V> to, boolean toInclusive)
+ {
+ return (NavigableSet<Entry<K,V>>)
+ SubMap.this.subMap(from.getKey(), fromInclusive,
+ to.getKey(), toInclusive).entrySet();
+ }
+
+ public SortedSet<Entry<K,V>> tailSet(Entry<K,V> from)
+ {
+ return tailSet(from, true);
+ }
+
+ public NavigableSet<Entry<K,V>> tailSet(Entry<K,V> from, boolean inclusive)
+ {
+ return (NavigableSet<Entry<K,V>>)
+ SubMap.this.tailMap(from.getKey(), inclusive).navigableKeySet();
+ }
+
+ } // class SubMap.NavigableEntrySet
+
+} // class SubMap
+
+ /**
+ * Returns the entry associated with the least or lowest key
+ * that is greater than or equal to the specified key, or
+ * <code>null</code> if there is no such key.
+ *
+ * @param key the key relative to the returned entry.
+ * @return the entry with the least key greater than or equal
+ * to the given key, or <code>null</code> if there is
+ * no such key.
+ * @throws ClassCastException if the specified key can not
+ * be compared with those in the map.
+ * @throws NullPointerException if the key is <code>null</code>
+ * and this map either uses natural
+ * ordering or a comparator that does
+ * not permit null keys.
+ * @since 1.6
+ */
+ public Entry<K,V> ceilingEntry(K key)
+ {
+ Node<K,V> n = lowestGreaterThan(key, false);
+ return (n == nil) ? null : n;
+ }
+
+ /**
+ * Returns the the least or lowest key that is greater than
+ * or equal to the specified key, or <code>null</code> if
+ * there is no such key.
+ *
+ * @param key the key relative to the returned entry.
+ * @return the least key greater than or equal to the given key,
+ * or <code>null</code> if there is no such key.
+ * @throws ClassCastException if the specified key can not
+ * be compared with those in the map.
+ * @throws NullPointerException if the key is <code>null</code>
+ * and this map either uses natural
+ * ordering or a comparator that does
+ * not permit null keys.
+ * @since 1.6
+ */
+ public K ceilingKey(K key)
+ {
+ Entry<K,V> e = ceilingEntry(key);
+ return (e == null) ? null : e.getKey();
+ }
+
+ /**
+ * Returns a reverse ordered {@link NavigableSet} view of this
+ * map's keys. The set is backed by the {@link TreeMap}, so changes
+ * in one show up in the other. The set supports element removal,
+ * but not element addition.
+ *
+ * @return a reverse ordered set view of the keys.
+ * @since 1.6
+ * @see #descendingMap()
+ */
+ public NavigableSet<K> descendingKeySet()
+ {
+ return descendingMap().navigableKeySet();
+ }
+
+ /**
+ * Returns a view of the map in reverse order. The descending map
+ * is backed by the original map, so that changes affect both maps.
+ * Any changes occurring to either map while an iteration is taking
+ * place (with the exception of a {@link Iterator#remove()} operation)
+ * result in undefined behaviour from the iteration. The ordering
+ * of the descending map is the same as for a map with a
+ * {@link Comparator} given by {@link Collections#reverseOrder()},
+ * and calling {@link #descendingMap()} on the descending map itself
+ * results in a view equivalent to the original map.
+ *
+ * @return a reverse order view of the map.
+ * @since 1.6
+ */
+ public NavigableMap<K,V> descendingMap()
+ {
+ if (descendingMap == null)
+ descendingMap = new DescendingMap<K,V>(this);
+ return descendingMap;
+ }
+
+ /**
+ * Returns the entry associated with the least or lowest key
+ * in the map, or <code>null</code> if the map is empty.
+ *
+ * @return the lowest entry, or <code>null</code> if the map
+ * is empty.
+ * @since 1.6
+ */
+ public Entry<K,V> firstEntry()
+ {
+ Node<K,V> n = firstNode();
+ return (n == nil) ? null : n;
+ }
+
+ /**
+ * Returns the entry associated with the greatest or highest key
+ * that is less than or equal to the specified key, or
+ * <code>null</code> if there is no such key.
+ *
+ * @param key the key relative to the returned entry.
+ * @return the entry with the greatest key less than or equal
+ * to the given key, or <code>null</code> if there is
+ * no such key.
+ * @throws ClassCastException if the specified key can not
+ * be compared with those in the map.
+ * @throws NullPointerException if the key is <code>null</code>
+ * and this map either uses natural
+ * ordering or a comparator that does
+ * not permit null keys.
+ * @since 1.6
+ */
+ public Entry<K,V> floorEntry(K key)
+ {
+ Node<K,V> n = highestLessThan(key, true);
+ return (n == nil) ? null : n;
+ }
+
+ /**
+ * Returns the the greatest or highest key that is less than
+ * or equal to the specified key, or <code>null</code> if
+ * there is no such key.
+ *
+ * @param key the key relative to the returned entry.
+ * @return the greatest key less than or equal to the given key,
+ * or <code>null</code> if there is no such key.
+ * @throws ClassCastException if the specified key can not
+ * be compared with those in the map.
+ * @throws NullPointerException if the key is <code>null</code>
+ * and this map either uses natural
+ * ordering or a comparator that does
+ * not permit null keys.
+ * @since 1.6
+ */
+ public K floorKey(K key)
+ {
+ Entry<K,V> e = floorEntry(key);
+ return (e == null) ? null : e.getKey();
+ }
+
+ /**
+ * Returns the entry associated with the least or lowest key
+ * that is strictly greater than the specified key, or
+ * <code>null</code> if there is no such key.
+ *
+ * @param key the key relative to the returned entry.
+ * @return the entry with the least key greater than
+ * the given key, or <code>null</code> if there is
+ * no such key.
+ * @throws ClassCastException if the specified key can not
+ * be compared with those in the map.
+ * @throws NullPointerException if the key is <code>null</code>
+ * and this map either uses natural
+ * ordering or a comparator that does
+ * not permit null keys.
+ * @since 1.6
+ */
+ public Entry<K,V> higherEntry(K key)
+ {
+ Node<K,V> n = lowestGreaterThan(key, false, false);
+ return (n == nil) ? null : n;
+ }
+
+ /**
+ * Returns the the least or lowest key that is strictly
+ * greater than the specified key, or <code>null</code> if
+ * there is no such key.
+ *
+ * @param key the key relative to the returned entry.
+ * @return the least key greater than the given key,
+ * or <code>null</code> if there is no such key.
+ * @throws ClassCastException if the specified key can not
+ * be compared with those in the map.
+ * @throws NullPointerException if the key is <code>null</code>
+ * and this map either uses natural
+ * ordering or a comparator that does
+ * not permit null keys.
+ * @since 1.6
+ */
+ public K higherKey(K key)
+ {
+ Entry<K,V> e = higherEntry(key);
+ return (e == null) ? null : e.getKey();
+ }
+
+ /**
+ * Returns the entry associated with the greatest or highest key
+ * in the map, or <code>null</code> if the map is empty.
+ *
+ * @return the highest entry, or <code>null</code> if the map
+ * is empty.
+ * @since 1.6
+ */
+ public Entry<K,V> lastEntry()
+ {
+ Node<K,V> n = lastNode();
+ return (n == nil) ? null : n;
+ }
+
+ /**
+ * Returns the entry associated with the greatest or highest key
+ * that is strictly less than the specified key, or
+ * <code>null</code> if there is no such key.
+ *
+ * @param key the key relative to the returned entry.
+ * @return the entry with the greatest key less than
+ * the given key, or <code>null</code> if there is
+ * no such key.
+ * @throws ClassCastException if the specified key can not
+ * be compared with those in the map.
+ * @throws NullPointerException if the key is <code>null</code>
+ * and this map either uses natural
+ * ordering or a comparator that does
+ * not permit null keys.
+ * @since 1.6
+ */
+ public Entry<K,V> lowerEntry(K key)
+ {
+ Node<K,V> n = highestLessThan(key);
+ return (n == nil) ? null : n;
+ }
+
+ /**
+ * Returns the the greatest or highest key that is strictly
+ * less than the specified key, or <code>null</code> if
+ * there is no such key.
+ *
+ * @param key the key relative to the returned entry.
+ * @return the greatest key less than the given key,
+ * or <code>null</code> if there is no such key.
+ * @throws ClassCastException if the specified key can not
+ * be compared with those in the map.
+ * @throws NullPointerException if the key is <code>null</code>
+ * and this map either uses natural
+ * ordering or a comparator that does
+ * not permit null keys.
+ * @since 1.6
+ */
+ public K lowerKey(K key)
+ {
+ Entry<K,V> e = lowerEntry(key);
+ return (e == null) ? null : e.getKey();
+ }
+
+ /**
+ * Returns a {@link NavigableSet} view of this map's keys. The set is
+ * backed by the {@link TreeMap}, so changes in one show up in the other.
+ * Any changes occurring to either while an iteration is taking
+ * place (with the exception of a {@link Iterator#remove()} operation)
+ * result in undefined behaviour from the iteration. The ordering
+ * The set supports element removal, but not element addition.
+ *
+ * @return a {@link NavigableSet} view of the keys.
+ * @since 1.6
+ */
+ public NavigableSet<K> navigableKeySet()
+ {
+ if (nKeys == null)
+ nKeys = new NavigableKeySet();
+ return nKeys;
+ }
+
+ /**
+ * Removes and returns the entry associated with the least
+ * or lowest key in the map, or <code>null</code> if the map
+ * is empty.
+ *
+ * @return the removed first entry, or <code>null</code> if the
+ * map is empty.
+ * @since 1.6
+ */
+ public Entry<K,V> pollFirstEntry()
+ {
+ Entry<K,V> e = firstEntry();
+ if (e != null)
+ removeNode((Node<K,V>)e);
+ return e;
+ }
+
+ /**
+ * Removes and returns the entry associated with the greatest
+ * or highest key in the map, or <code>null</code> if the map
+ * is empty.
+ *
+ * @return the removed last entry, or <code>null</code> if the
+ * map is empty.
+ * @since 1.6
+ */
+ public Entry<K,V> pollLastEntry()
+ {
+ Entry<K,V> e = lastEntry();
+ if (e != null)
+ removeNode((Node<K,V>)e);
+ return e;
+ }
+
+ /**
+ * Implementation of {@link #descendingMap()} and associated
+ * derivatives. This class provides a view of the
+ * original backing map in reverse order, and throws
+ * {@link IllegalArgumentException} for attempts to
+ * access beyond that range.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ */
+ private static final class DescendingMap<DK,DV>
+ implements NavigableMap<DK,DV>
+ {
+
+ /**
+ * The cache for {@link #entrySet()}.
+ */
+ private Set<Map.Entry<DK,DV>> entries;
+
+ /**
+ * The cache for {@link #keySet()}.
+ */
+ private Set<DK> keys;
+
+ /**
+ * The cache for {@link #navigableKeySet()}.
+ */
+ private NavigableSet<DK> nKeys;
+
+ /**
+ * The cache for {@link #values()}.
+ */
+ private Collection<DV> values;
+
+ /**
+ * The backing {@link NavigableMap}.
+ */
+ private NavigableMap<DK,DV> map;
+
+ /**
+ * Create a {@link DescendingMap} around the specified
+ * map.
+ *
+ * @param map the map to wrap.
+ */
+ public DescendingMap(NavigableMap<DK,DV> map)
+ {
+ this.map = map;
+ }
+
+ public Map.Entry<DK,DV> ceilingEntry(DK key)
+ {
+ return map.floorEntry(key);
+ }
+
+ public DK ceilingKey(DK key)
+ {
+ return map.floorKey(key);
+ }
+
+ public void clear()
+ {
+ map.clear();
+ }
+
+ public Comparator<? super DK> comparator()
+ {
+ return Collections.reverseOrder(map.comparator());
+ }
+
+ public boolean containsKey(Object o)
+ {
+ return map.containsKey(o);
+ }
+
+ public boolean containsValue(Object o)
+ {
+ return map.containsValue(o);
+ }
+
+ public NavigableSet<DK> descendingKeySet()
+ {
+ return descendingMap().navigableKeySet();
+ }
+
+ public NavigableMap<DK,DV> descendingMap()
+ {
+ return map;
+ }
+
+ public Set<Entry<DK,DV>> entrySet()
+ {
+ if (entries == null)
+ entries =
+ new DescendingSet<Entry<DK,DV>>((NavigableSet<Entry<DK,DV>>)
+ map.entrySet());
+ return entries;
+ }
+
+ public boolean equals(Object o)
+ {
+ return map.equals(o);
+ }
+
+ public Entry<DK,DV> firstEntry()
+ {
+ return map.lastEntry();
+ }
+
+ public DK firstKey()
+ {
+ return map.lastKey();
+ }
+
+ public Entry<DK,DV> floorEntry(DK key)
+ {
+ return map.ceilingEntry(key);
+ }
+
+ public DK floorKey(DK key)
+ {
+ return map.ceilingKey(key);
+ }
+
+ public DV get(Object key)
+ {
+ return map.get(key);
+ }
+
+ public int hashCode()
+ {
+ return map.hashCode();
+ }
+
+ public SortedMap<DK,DV> headMap(DK toKey)
+ {
+ return headMap(toKey, false);
+ }
+
+ public NavigableMap<DK,DV> headMap(DK toKey, boolean inclusive)
+ {
+ return new DescendingMap(map.tailMap(toKey, inclusive));
+ }
+
+ public Entry<DK,DV> higherEntry(DK key)
+ {
+ return map.lowerEntry(key);
+ }
+
+ public DK higherKey(DK key)
+ {
+ return map.lowerKey(key);
+ }
+
+ public Set<DK> keySet()
+ {
+ if (keys == null)
+ keys = new DescendingSet<DK>(map.navigableKeySet());
+ return keys;
+ }
+
+ public boolean isEmpty()
+ {
+ return map.isEmpty();
+ }
+
+ public Entry<DK,DV> lastEntry()
+ {
+ return map.firstEntry();
+ }
+
+ public DK lastKey()
+ {
+ return map.firstKey();
+ }
+
+ public Entry<DK,DV> lowerEntry(DK key)
+ {
+ return map.higherEntry(key);
+ }
+
+ public DK lowerKey(DK key)
+ {
+ return map.higherKey(key);
+ }
+
+ public NavigableSet<DK> navigableKeySet()
+ {
+ if (nKeys == null)
+ nKeys = new DescendingSet<DK>(map.navigableKeySet());
+ return nKeys;
+ }
+
+ public Entry<DK,DV> pollFirstEntry()
+ {
+ return pollLastEntry();
+ }
+
+ public Entry<DK,DV> pollLastEntry()
+ {
+ return pollFirstEntry();
+ }
+
+ public DV put(DK key, DV value)
+ {
+ return map.put(key, value);
+ }
+
+ public void putAll(Map<? extends DK, ? extends DV> m)
+ {
+ map.putAll(m);
+ }
+
+ public DV remove(Object key)
+ {
+ return map.remove(key);
+ }
+
+ public int size()
+ {
+ return map.size();
+ }
+
+ public SortedMap<DK,DV> subMap(DK fromKey, DK toKey)
+ {
+ return subMap(fromKey, true, toKey, false);
+ }
+
+ public NavigableMap<DK,DV> subMap(DK fromKey, boolean fromInclusive,
+ DK toKey, boolean toInclusive)
+ {
+ return new DescendingMap(map.subMap(fromKey, fromInclusive,
+ toKey, toInclusive));
+ }
+
+ public SortedMap<DK,DV> tailMap(DK fromKey)
+ {
+ return tailMap(fromKey, true);
+ }
+
+ public NavigableMap<DK,DV> tailMap(DK fromKey, boolean inclusive)
+ {
+ return new DescendingMap(map.headMap(fromKey, inclusive));
+ }
+
+ public String toString()
+ {
+ StringBuilder r = new StringBuilder("{");
+ final Iterator<Entry<DK,DV>> it = entrySet().iterator();
+ while (it.hasNext())
+ {
+ final Entry<DK,DV> e = it.next();
+ r.append(e.getKey());
+ r.append('=');
+ r.append(e.getValue());
+ r.append(", ");
+ }
+ r.replace(r.length() - 2, r.length(), "}");
+ return r.toString();
+ }
+
+ public Collection<DV> values()
+ {
+ if (values == null)
+ // Create an AbstractCollection with custom implementations of those
+ // methods that can be overriden easily and efficiently.
+ values = new AbstractCollection()
+ {
+ public int size()
+ {
+ return size();
+ }
+
+ public Iterator<DV> iterator()
+ {
+ return new Iterator<DV>()
+ {
+ /** The last Entry returned by a next() call. */
+ private Entry<DK,DV> last;
+
+ /** The next entry that should be returned by next(). */
+ private Entry<DK,DV> next = firstEntry();
+
+ public boolean hasNext()
+ {
+ return next != null;
+ }
+
+ public DV next()
+ {
+ if (next == null)
+ throw new NoSuchElementException();
+ last = next;
+ next = higherEntry(last.getKey());
+
+ return last.getValue();
+ }
+
+ public void remove()
+ {
+ if (last == null)
+ throw new IllegalStateException();
+
+ DescendingMap.this.remove(last.getKey());
+ last = null;
+ }
+ };
+ }
+
+ public void clear()
+ {
+ clear();
+ }
+ };
+ return values;
+ }
+
+ } // class DescendingMap
+
+ /**
+ * Implementation of {@link #keySet()}.
+ */
+ private class KeySet
+ extends AbstractSet<K>
+ {
+
+ public int size()
+ {
+ return size;
+ }
+
+ public Iterator<K> iterator()
+ {
+ return new TreeIterator(KEYS);
+ }
+
+ public void clear()
+ {
+ TreeMap.this.clear();
+ }
+
+ public boolean contains(Object o)
+ {
+ return containsKey(o);
+ }
+
+ public boolean remove(Object key)
+ {
+ Node<K,V> n = getNode((K) key);
+ if (n == nil)
+ return false;
+ removeNode(n);
+ return true;
+ }
+ } // class KeySet
+
+ /**
+ * Implementation of {@link #navigableKeySet()}.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ */
+ private final class NavigableKeySet
+ extends KeySet
+ implements NavigableSet<K>
+ {
+
+ public K ceiling(K k)
+ {
+ return ceilingKey(k);
+ }
+
+ public Comparator<? super K> comparator()
+ {
+ return comparator;
+ }
+
+ public Iterator<K> descendingIterator()
+ {
+ return descendingSet().iterator();
+ }
+
+ public NavigableSet<K> descendingSet()
+ {
+ return new DescendingSet<K>(this);
+ }
+
+ public K first()
+ {
+ return firstKey();
+ }
+
+ public K floor(K k)
+ {
+ return floorKey(k);
+ }
+
+ public SortedSet<K> headSet(K to)
+ {
+ return headSet(to, false);
+ }
+
+ public NavigableSet<K> headSet(K to, boolean inclusive)
+ {
+ return headMap(to, inclusive).navigableKeySet();
+ }
+
+ public K higher(K k)
+ {
+ return higherKey(k);
+ }
+
+ public K last()
+ {
+ return lastKey();
+ }
+
+ public K lower(K k)
+ {
+ return lowerKey(k);
+ }
+
+ public K pollFirst()
+ {
+ return pollFirstEntry().getKey();
+ }
+
+ public K pollLast()
+ {
+ return pollLastEntry().getKey();
+ }
+
+ public SortedSet<K> subSet(K from, K to)
+ {
+ return subSet(from, true, to, false);
+ }
+
+ public NavigableSet<K> subSet(K from, boolean fromInclusive,
+ K to, boolean toInclusive)
+ {
+ return subMap(from, fromInclusive,
+ to, toInclusive).navigableKeySet();
+ }
+
+ public SortedSet<K> tailSet(K from)
+ {
+ return tailSet(from, true);
+ }
+
+ public NavigableSet<K> tailSet(K from, boolean inclusive)
+ {
+ return tailMap(from, inclusive).navigableKeySet();
+ }
+
+
+ } // class NavigableKeySet
+
+ /**
+ * Implementation of {@link #descendingSet()} and associated
+ * derivatives. This class provides a view of the
+ * original backing set in reverse order, and throws
+ * {@link IllegalArgumentException} for attempts to
+ * access beyond that range.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ */
+ private static final class DescendingSet<D>
+ implements NavigableSet<D>
+ {
+
+ /**
+ * The backing {@link NavigableSet}.
+ */
+ private NavigableSet<D> set;
+
+ /**
+ * Create a {@link DescendingSet} around the specified
+ * set.
+ *
+ * @param map the set to wrap.
+ */
+ public DescendingSet(NavigableSet<D> set)
+ {
+ this.set = set;
+ }
+
+ public boolean add(D e)
+ {
+ return set.add(e);
+ }
+
+ public boolean addAll(Collection<? extends D> c)
+ {
+ return set.addAll(c);
+ }
+
+ public D ceiling(D e)
+ {
+ return set.floor(e);
+ }
+
+ public void clear()
+ {
+ set.clear();
+ }
+
+ public Comparator<? super D> comparator()
+ {
+ return Collections.reverseOrder(set.comparator());
+ }
+
+ public boolean contains(Object o)
+ {
+ return set.contains(o);
+ }
+
+ public boolean containsAll(Collection<?> c)
+ {
+ return set.containsAll(c);
+ }
+
+ public Iterator<D> descendingIterator()
+ {
+ return descendingSet().iterator();
+ }
+
+ public NavigableSet<D> descendingSet()
+ {
+ return set;
+ }
+
+ public boolean equals(Object o)
+ {
+ return set.equals(o);
+ }
+
+ public D first()
+ {
+ return set.last();
+ }
+
+ public D floor(D e)
+ {
+ return set.ceiling(e);
+ }
+
+ public int hashCode()
+ {
+ return set.hashCode();
+ }
+
+ public SortedSet<D> headSet(D to)
+ {
+ return headSet(to, false);
+ }
+
+ public NavigableSet<D> headSet(D to, boolean inclusive)
+ {
+ return new DescendingSet(set.tailSet(to, inclusive));
+ }
+
+ public D higher(D e)
+ {
+ return set.lower(e);
+ }
+
+ public boolean isEmpty()
+ {
+ return set.isEmpty();
+ }
+
+ public Iterator<D> iterator()
+ {
+ return new Iterator<D>()
+ {
+
+ /** The last element returned by a next() call. */
+ private D last;
+
+ /** The next element that should be returned by next(). */
+ private D next = first();
+
+ public boolean hasNext()
+ {
+ return next != null;
+ }
+
+ public D next()
+ {
+ if (next == null)
+ throw new NoSuchElementException();
+ last = next;
+ next = higher(last);
+
+ return last;
+ }
+
+ public void remove()
+ {
+ if (last == null)
+ throw new IllegalStateException();
+
+ DescendingSet.this.remove(last);
+ last = null;
+ }
+ };
+ }
+
+ public D last()
+ {
+ return set.first();
+ }
+
+ public D lower(D e)
+ {
+ return set.higher(e);
+ }
+
+ public D pollFirst()
+ {
+ return set.pollLast();
+ }
+
+ public D pollLast()
+ {
+ return set.pollFirst();
+ }
+
+ public boolean remove(Object o)
+ {
+ return set.remove(o);
+ }
+
+ public boolean removeAll(Collection<?> c)
+ {
+ return set.removeAll(c);
+ }
+
+ public boolean retainAll(Collection<?> c)
+ {
+ return set.retainAll(c);
+ }
+
+ public int size()
+ {
+ return set.size();
+ }
+
+ public SortedSet<D> subSet(D from, D to)
+ {
+ return subSet(from, true, to, false);
+ }
+
+ public NavigableSet<D> subSet(D from, boolean fromInclusive,
+ D to, boolean toInclusive)
+ {
+ return new DescendingSet(set.subSet(from, fromInclusive,
+ to, toInclusive));
+ }
+
+ public SortedSet<D> tailSet(D from)
+ {
+ return tailSet(from, true);
+ }
+
+ public NavigableSet<D> tailSet(D from, boolean inclusive)
+ {
+ return new DescendingSet(set.headSet(from, inclusive));
+ }
+
+ public Object[] toArray()
+ {
+ D[] array = (D[]) set.toArray();
+ Arrays.sort(array, comparator());
+ return array;
+ }
+
+ public <T> T[] toArray(T[] a)
+ {
+ T[] array = set.toArray(a);
+ Arrays.sort(array, (Comparator<? super T>) comparator());
+ return array;
+ }
+
+ public String toString()
+ {
+ StringBuilder r = new StringBuilder("[");
+ final Iterator<D> it = iterator();
+ while (it.hasNext())
+ {
+ final D o = it.next();
+ if (o == this)
+ r.append("<this>");
+ else
+ r.append(o);
+ r.append(", ");
+ }
+ r.replace(r.length() - 2, r.length(), "]");
+ return r.toString();
+ }
+
+ } // class DescendingSet
+
+ private class EntrySet
+ extends AbstractSet<Entry<K,V>>
+ {
+ public int size()
+ {
+ return size;
+ }
+
+ public Iterator<Map.Entry<K,V>> iterator()
+ {
+ return new TreeIterator(ENTRIES);
+ }
+
+ public void clear()
+ {
+ TreeMap.this.clear();
+ }
+
+ public boolean contains(Object o)
+ {
+ if (! (o instanceof Map.Entry))
+ return false;
+ Map.Entry<K,V> me = (Map.Entry<K,V>) o;
+ Node<K,V> n = getNode(me.getKey());
+ return n != nil && AbstractSet.equals(me.getValue(), n.value);
+ }
+
+ public boolean remove(Object o)
+ {
+ if (! (o instanceof Map.Entry))
+ return false;
+ Map.Entry<K,V> me = (Map.Entry<K,V>) o;
+ Node<K,V> n = getNode(me.getKey());
+ if (n != nil && AbstractSet.equals(me.getValue(), n.value))
+ {
+ removeNode(n);
+ return true;
+ }
+ return false;
+ }
+ }
+
+ private final class NavigableEntrySet
+ extends EntrySet
+ implements NavigableSet<Entry<K,V>>
+ {
+
+ public Entry<K,V> ceiling(Entry<K,V> e)
+ {
+ return ceilingEntry(e.getKey());
+ }
+
+ public Comparator<? super Entry<K,V>> comparator()
+ {
+ return new Comparator<Entry<K,V>>()
+ {
+ public int compare(Entry<K,V> t1, Entry<K,V> t2)
+ {
+ return comparator.compare(t1.getKey(), t2.getKey());
+ }
+ };
+ }
+
+ public Iterator<Entry<K,V>> descendingIterator()
+ {
+ return descendingSet().iterator();
+ }
+
+ public NavigableSet<Entry<K,V>> descendingSet()
+ {
+ return new DescendingSet(this);
+ }
+
+ public Entry<K,V> first()
+ {
+ return firstEntry();
+ }
+
+ public Entry<K,V> floor(Entry<K,V> e)
+ {
+ return floorEntry(e.getKey());
+ }
+
+ public SortedSet<Entry<K,V>> headSet(Entry<K,V> to)
+ {
+ return headSet(to, false);
+ }
+
+ public NavigableSet<Entry<K,V>> headSet(Entry<K,V> to, boolean inclusive)
+ {
+ return (NavigableSet<Entry<K,V>>) headMap(to.getKey(), inclusive).entrySet();
+ }
+
+ public Entry<K,V> higher(Entry<K,V> e)
+ {
+ return higherEntry(e.getKey());
+ }
+
+ public Entry<K,V> last()
+ {
+ return lastEntry();
+ }
+
+ public Entry<K,V> lower(Entry<K,V> e)
+ {
+ return lowerEntry(e.getKey());
+ }
+
+ public Entry<K,V> pollFirst()
+ {
+ return pollFirstEntry();
+ }
+
+ public Entry<K,V> pollLast()
+ {
+ return pollLastEntry();
+ }
+
+ public SortedSet<Entry<K,V>> subSet(Entry<K,V> from, Entry<K,V> to)
+ {
+ return subSet(from, true, to, false);
+ }
+
+ public NavigableSet<Entry<K,V>> subSet(Entry<K,V> from, boolean fromInclusive,
+ Entry<K,V> to, boolean toInclusive)
+ {
+ return (NavigableSet<Entry<K,V>>) subMap(from.getKey(), fromInclusive,
+ to.getKey(), toInclusive).entrySet();
+ }
+
+ public SortedSet<Entry<K,V>> tailSet(Entry<K,V> from)
+ {
+ return tailSet(from, true);
+ }
+
+ public NavigableSet<Entry<K,V>> tailSet(Entry<K,V> from, boolean inclusive)
+ {
+ return (NavigableSet<Entry<K,V>>) tailMap(from.getKey(), inclusive).navigableKeySet();
+ }
+
+ } // class NavigableEntrySet
+
} // class TreeMap
diff --git a/libjava/classpath/java/util/TreeSet.java b/libjava/classpath/java/util/TreeSet.java
index 2851e4a..572cda6 100644
--- a/libjava/classpath/java/util/TreeSet.java
+++ b/libjava/classpath/java/util/TreeSet.java
@@ -79,10 +79,10 @@ import java.io.Serializable;
* @see Collections#synchronizedSortedSet(SortedSet)
* @see TreeMap
* @since 1.2
- * @status updated to 1.4
+ * @status updated to 1.6
*/
public class TreeSet<T> extends AbstractSet<T>
- implements SortedSet<T>, Cloneable, Serializable
+ implements NavigableSet<T>, Cloneable, Serializable
{
/**
* Compatible with JDK 1.2.
@@ -90,11 +90,11 @@ public class TreeSet<T> extends AbstractSet<T>
private static final long serialVersionUID = -2479143000061671589L;
/**
- * The SortedMap which backs this Set.
+ * The NavigableMap which backs this Set.
*/
// Not final because of readObject. This will always be one of TreeMap or
// TreeMap.SubMap, which both extend AbstractMap.
- private transient SortedMap<T, String> map;
+ private transient NavigableMap<T, String> map;
/**
* Construct a new TreeSet whose backing TreeMap using the "natural"
@@ -163,7 +163,7 @@ public class TreeSet<T> extends AbstractSet<T>
*
* @param backingMap the submap
*/
- private TreeSet(SortedMap<T,String> backingMap)
+ private TreeSet(NavigableMap<T,String> backingMap)
{
map = backingMap;
}
@@ -220,7 +220,7 @@ public class TreeSet<T> extends AbstractSet<T>
{
copy = (TreeSet<T>) super.clone();
// Map may be either TreeMap or TreeMap.SubMap, hence the ugly casts.
- copy.map = (SortedMap<T, String>) ((AbstractMap<T, String>) map).clone();
+ copy.map = (NavigableMap<T, String>) ((AbstractMap<T, String>) map).clone();
}
catch (CloneNotSupportedException x)
{
@@ -269,7 +269,9 @@ public class TreeSet<T> extends AbstractSet<T>
* in one appear in the other. The subset will throw an
* {@link IllegalArgumentException} for any attempt to access or add an
* element beyond the specified cutoff. The returned set does not include
- * the endpoint; if you want inclusion, pass the successor element.
+ * the endpoint; if you want inclusion, pass the successor element or
+ * call {@link #headSet(T,boolean)}. This call is equivalent to
+ * <code>headSet(to, false)</code>.
*
* @param to the (exclusive) cutoff point
* @return a view of the set less than the cutoff
@@ -280,7 +282,28 @@ public class TreeSet<T> extends AbstractSet<T>
*/
public SortedSet<T> headSet(T to)
{
- return new TreeSet<T>(map.headMap(to));
+ return headSet(to, false);
+ }
+
+ /**
+ * Returns a view of this Set including all elements less than
+ * (or equal to, if <code>inclusive</code> is true) <code>to</code>.
+ * The returned set is backed by the original, so changes
+ * in one appear in the other. The subset will throw an
+ * {@link IllegalArgumentException} for any attempt to access or add an
+ * element beyond the specified cutoff.
+ *
+ * @param to the cutoff point
+ * @param inclusive true if <code>to</code> should be included.
+ * @return a view of the set for the specified range.
+ * @throws ClassCastException if <code>to</code> is not compatible with
+ * the comparator (or is not Comparable, for natural ordering)
+ * @throws NullPointerException if to is null, but the comparator does not
+ * tolerate null elements
+ */
+ public NavigableSet<T> headSet(T to, boolean inclusive)
+ {
+ return new TreeSet<T>(map.headMap(to, inclusive));
}
/**
@@ -345,7 +368,9 @@ public class TreeSet<T> extends AbstractSet<T>
* the other. The subset will throw an {@link IllegalArgumentException}
* for any attempt to access or add an element beyond the specified cutoffs.
* The returned set includes the low endpoint but not the high; if you want
- * to reverse this behavior on either end, pass in the successor element.
+ * to reverse this behavior on either end, pass in the successor element
+ * or call {@link #subSet(T,boolean,T,boolean)}. This is equivalent to
+ * calling <code>subSet(from,true,to,false)</code>.
*
* @param from the (inclusive) low cutoff point
* @param to the (exclusive) high cutoff point
@@ -358,7 +383,33 @@ public class TreeSet<T> extends AbstractSet<T>
*/
public SortedSet<T> subSet(T from, T to)
{
- return new TreeSet<T>(map.subMap(from, to));
+ return subSet(from, true, to, false);
+ }
+
+ /**
+ * Returns a view of this Set including all elements greater than (or equal to,
+ * if <code>fromInclusive</code> is true</code> <code>from</code> and less than
+ * (or equal to, if <code>toInclusive</code> is true) <code>to</code>.
+ * The returned set is backed by the original, so changes in one appear in
+ * the other. The subset will throw an {@link IllegalArgumentException}
+ * for any attempt to access or add an element beyond the specified cutoffs.
+ *
+ * @param from the low cutoff point
+ * @param fromInclusive true if <code>from</code> should be included.
+ * @param to the high cutoff point
+ * @param toInclusive true if <code>to</code> should be included.
+ * @return a view of the set for the specified range.
+ * @throws ClassCastException if either cutoff is not compatible with
+ * the comparator (or is not Comparable, for natural ordering)
+ * @throws NullPointerException if from or to is null, but the comparator
+ * does not tolerate null elements
+ * @throws IllegalArgumentException if from is greater than to
+ */
+ public NavigableSet<T> subSet(T from, boolean fromInclusive,
+ T to, boolean toInclusive)
+ {
+ return new TreeSet<T>(map.subMap(from, fromInclusive,
+ to, toInclusive));
}
/**
@@ -367,7 +418,9 @@ public class TreeSet<T> extends AbstractSet<T>
* changes in one appear in the other. The subset will throw an
* {@link IllegalArgumentException} for any attempt to access or add an
* element beyond the specified cutoff. The returned set includes the
- * endpoint; if you want to exclude it, pass in the successor element.
+ * endpoint; if you want to exclude it, pass in the successor element
+ * or call {@link #tailSet(T,boolean)}. This is equivalent to calling
+ * <code>tailSet(from, true)</code>.
*
* @param from the (inclusive) low cutoff point
* @return a view of the set above the cutoff
@@ -378,7 +431,27 @@ public class TreeSet<T> extends AbstractSet<T>
*/
public SortedSet<T> tailSet(T from)
{
- return new TreeSet<T>(map.tailMap(from));
+ return tailSet(from, true);
+ }
+
+ /**
+ * Returns a view of this Set including all elements greater (or equal to,
+ * if <code>inclusive</code> is true) <code>from</code>. The returned set
+ * is backed by the original, so changes in one appear in the other. The
+ * subset will throw an {@link IllegalArgumentException} for any attempt
+ * to access or add an element beyond the specified cutoff.
+ *
+ * @param from the low cutoff point.
+ * @param inclusive true if <code>from</code> should be included.
+ * @return a view of the set for the specified range.
+ * @throws ClassCastException if <code>from</code> is not compatible with
+ * the comparator (or is not Comparable, for natural ordering)
+ * @throws NullPointerException if from is null, but the comparator
+ * does not tolerate null elements
+ */
+ public NavigableSet<T> tailSet(T from, boolean inclusive)
+ {
+ return new TreeSet<T>(map.tailMap(from, inclusive));
}
/**
@@ -418,4 +491,151 @@ public class TreeSet<T> extends AbstractSet<T>
map = new TreeMap<T, String>(comparator);
((TreeMap<T, String>) map).putFromObjStream(s, size, false);
}
+
+ /**
+ * Returns the least or lowest element in the set greater than or
+ * equal to the given element, or <code>null</code> if there is
+ * no such element.
+ *
+ * @param e the element relative to the returned element.
+ * @return the least element greater than or equal
+ * to the given element, or <code>null</code> if there is
+ * no such element.
+ * @throws ClassCastException if the specified element can not
+ * be compared with those in the map.
+ * @throws NullPointerException if the element is <code>null</code>
+ * and this set either uses natural
+ * ordering or a comparator that does
+ * not permit null elements.
+ * @since 1.6
+ */
+ public T ceiling(T e)
+ {
+ return map.ceilingKey(e);
+ }
+
+ /**
+ * Returns an iterator over the elements of this set in descending
+ * order. This is equivalent to calling
+ * <code>descendingSet().iterator()</code>.
+ *
+ * @return an iterator over the elements in descending order.
+ * @since 1.6
+ */
+ public Iterator<T> descendingIterator()
+ {
+ return descendingSet().iterator();
+ }
+
+ /**
+ * Returns a view of the set in reverse order. The descending set
+ * is backed by the original set, so that changes affect both sets.
+ * Any changes occurring to either set while an iteration is taking
+ * place (with the exception of a {@link Iterator#remove()} operation)
+ * result in undefined behaviour from the iteration. The ordering
+ * of the descending set is the same as for a set with a
+ * {@link Comparator} given by {@link Collections#reverseOrder()},
+ * and calling {@link #descendingSet()} on the descending set itself
+ * results in a view equivalent to the original set.
+ *
+ * @return a reverse order view of the set.
+ * @since 1.6
+ */
+ public NavigableSet<T> descendingSet()
+ {
+ return map.descendingKeySet();
+ }
+
+ /**
+ * Returns the greatest or highest element in the set less than or
+ * equal to the given element, or <code>null</code> if there is
+ * no such element.
+ *
+ * @param e the element relative to the returned element.
+ * @return the greatest element less than or equal
+ * to the given element, or <code>null</code> if there is
+ * no such element.
+ * @throws ClassCastException if the specified element can not
+ * be compared with those in the map.
+ * @throws NullPointerException if the element is <code>null</code>
+ * and this set either uses natural
+ * ordering or a comparator that does
+ * not permit null elements.
+ * @since 1.6
+ */
+ public T floor(T e)
+ {
+ return map.floorKey(e);
+ }
+
+ /**
+ * Returns the least or lowest element in the set strictly greater
+ * than the given element, or <code>null</code> if there is
+ * no such element.
+ *
+ * @param e the element relative to the returned element.
+ * @return the least element greater than
+ * the given element, or <code>null</code> if there is
+ * no such element.
+ * @throws ClassCastException if the specified element can not
+ * be compared with those in the map.
+ * @throws NullPointerException if the element is <code>null</code>
+ * and this set either uses natural
+ * ordering or a comparator that does
+ * not permit null elements.
+ * @since 1.6
+ */
+ public T higher(T e)
+ {
+ return map.higherKey(e);
+ }
+
+ /**
+ * Returns the greatest or highest element in the set strictly less
+ * than the given element, or <code>null</code> if there is
+ * no such element.
+ *
+ * @param e the element relative to the returned element.
+ * @return the greatest element less than
+ * the given element, or <code>null</code> if there is
+ * no such element.
+ * @throws ClassCastException if the specified element can not
+ * be compared with those in the map.
+ * @throws NullPointerException if the element is <code>null</code>
+ * and this set either uses natural
+ * ordering or a comparator that does
+ * not permit null elements.
+ * @since 1.6
+ */
+ public T lower(T e)
+ {
+ return map.lowerKey(e);
+ }
+
+ /**
+ * Removes and returns the least or lowest element in the set,
+ * or <code>null</code> if the map is empty.
+ *
+ * @return the removed first element, or <code>null</code> if the
+ * map is empty.
+ * @since 1.6
+ */
+ public T pollFirst()
+ {
+ return map.pollFirstEntry().getKey();
+ }
+
+ /**
+ * Removes and returns the greatest or highest element in the set,
+ * or <code>null</code> if the map is empty.
+ *
+ * @return the removed last element, or <code>null</code> if the
+ * map is empty.
+ * @since 1.6
+ */
+ public T pollLast()
+ {
+ return map.pollLastEntry().getKey();
+ }
+
}
diff --git a/libjava/classpath/java/util/class-dependencies.conf b/libjava/classpath/java/util/class-dependencies.conf
deleted file mode 100644
index 39f9606..0000000
--- a/libjava/classpath/java/util/class-dependencies.conf
+++ /dev/null
@@ -1,78 +0,0 @@
-# This property file contains dependencies of classes, methods, and
-# field on other methods or classes.
-#
-# Syntax:
-#
-# <used>: <needed 1> [... <needed N>]
-#
-# means that when <used> is included, <needed 1> (... <needed N>) must
-# be included as well.
-#
-# <needed X> and <used> are of the form
-#
-# <class.methodOrField(signature)>
-#
-# or just
-#
-# <class>
-#
-# Within dependencies, variables can be used. A variable is defined as
-# follows:
-#
-# {variable}: value1 value2 ... value<n>
-#
-# variables can be used on the right side of dependencies as follows:
-#
-# <used>: com.bla.blu.{variable}.Class.m()V
-#
-# The use of the variable will expand to <n> dependencies of the form
-#
-# <used>: com.bla.blu.value1.Class.m()V
-# <used>: com.bla.blu.value2.Class.m()V
-# ...
-# <used>: com.bla.blu.value<n>.Class.m()V
-#
-# Variables can be redefined when building a system to select the
-# required support for features like encodings, protocols, etc.
-#
-# Hints:
-#
-# - For methods and fields, the signature is mandatory. For
-# specification, please see the Java Virtual Machine Specification by
-# SUN. Unlike in the spec, field signatures (types) are in brackets.
-#
-# - Package names must be separated by '/' (and not '.'). E.g.,
-# java/lang/Class (this is necessary, because the '.' is used to
-# separate method or field names from classes)
-#
-# - In case <needed> refers to a class, only the class itself will be
-# included in the resulting binary, NOT necessarily all its methods
-# and fields. If you want to refer to all methods and fields, you can
-# write class.* as an abbreviation.
-#
-# - Abbreviations for packages are also possible: my/package/* means all
-# methods and fields of all classes in my/package.
-#
-# - A line with a trailing '\' continues in the next line.
-
-
-# All calendars supported are loaded via java/util/Calendar.getBundle or
-# java/util/GregorianCalendar.getBundle from class
-# gnu/java/locale/Calendar_{locale_id}
-#
-# This introduces a dependency for the localized calendars. To allow an easy
-# selection and addition of locales, the library variable {calendar_locales}
-# can be set to the set of supported calendar locales.
-#
-
-{calendar_locales}: de en nl
-
-java/util/Calendar.getBundle(Ljava/util/Locale;)Ljava/util/ResourceBundle;: \
- gnu/java/locale/Calendar.* \
- gnu/java/locale/Calendar_{calendar_locales}.*
-
-java/util/GregorianCalendar.getBundle(Ljava/util/Locale;)Ljava/util/ResourceBundle;: \
- gnu/java/locale/Calendar.* \
- gnu/java/locale/Calendar_{calendar_locales}.*
-
-# end of file
diff --git a/libjava/classpath/java/util/concurrent/CopyOnWriteArrayList.java b/libjava/classpath/java/util/concurrent/CopyOnWriteArrayList.java
index 5ef37d9..48c017f 100644
--- a/libjava/classpath/java/util/concurrent/CopyOnWriteArrayList.java
+++ b/libjava/classpath/java/util/concurrent/CopyOnWriteArrayList.java
@@ -349,7 +349,8 @@ public class CopyOnWriteArrayList<E> extends AbstractList<E> implements
{
E[] data = this.data;
E[] newData = (E[]) new Object[data.length - 1];
- System.arraycopy(data, 0, newData, 0, index - 1);
+ if (index > 0)
+ System.arraycopy(data, 0, newData, 0, index - 1);
System.arraycopy(data, index + 1, newData, index,
data.length - index - 1);
E r = data[index];
diff --git a/libjava/classpath/java/util/logging/LogManager.java b/libjava/classpath/java/util/logging/LogManager.java
index fbc0fe7..6daf3db 100644
--- a/libjava/classpath/java/util/logging/LogManager.java
+++ b/libjava/classpath/java/util/logging/LogManager.java
@@ -1,6 +1,6 @@
/* LogManager.java -- a class for maintaining Loggers and managing
configuration properties
- Copyright (C) 2002, 2005, 2006 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2005, 2006, 2007 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -446,8 +446,8 @@ public class LogManager
Iterator<WeakReference<Logger>> iter = loggers.values().iterator();
while (iter.hasNext())
- for (WeakReference<Logger> ref : loggers.values())
{
+ WeakReference<Logger> ref;
Logger logger;
ref = iter.next();
@@ -559,13 +559,21 @@ public class LogManager
if ("handlers".equals(key))
{
- StringTokenizer tokenizer = new StringTokenizer(value);
+ // In Java 5 and earlier this was specified to be
+ // whitespace-separated, but in reality it also accepted
+ // commas (tomcat relied on this), and in Java 6 the
+ // documentation was updated to fit the implementation.
+ StringTokenizer tokenizer = new StringTokenizer(value,
+ " \t\n\r\f,");
while (tokenizer.hasMoreTokens())
{
String handlerName = tokenizer.nextToken();
Handler handler = (Handler)
createInstance(handlerName, Handler.class, key);
- Logger.root.addHandler(handler);
+ // Tomcat also relies on the implementation ignoring
+ // items in 'handlers' which are not class names.
+ if (handler != null)
+ Logger.root.addHandler(handler);
}
}
diff --git a/libjava/classpath/java/util/logging/Logger.java b/libjava/classpath/java/util/logging/Logger.java
index 46588e5..01ef8f5 100644
--- a/libjava/classpath/java/util/logging/Logger.java
+++ b/libjava/classpath/java/util/logging/Logger.java
@@ -1,5 +1,5 @@
/* Logger.java -- a class for logging messages
- Copyright (C) 2002, 2004, 2006 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2004, 2006, 2007 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -276,8 +276,8 @@ public class Logger
LogManager lm = LogManager.getLogManager();
Logger result;
- /* Throw NullPointerException if name is null. */
- name.getClass();
+ if (name == null)
+ throw new NullPointerException();
/* Without synchronized(lm), it could happen that another thread
* would create a logger between our calls to getLogger and
@@ -1013,8 +1013,8 @@ public class Logger
public synchronized void addHandler(Handler handler)
throws SecurityException
{
- /* Throw a new NullPointerException if handler is null. */
- handler.getClass();
+ if (handler == null)
+ throw new NullPointerException();
/* An application is allowed to control an anonymous logger
* without having the permission to control the logging
@@ -1057,8 +1057,8 @@ public class Logger
if (!anonymous)
LogManager.getLogManager().checkAccess();
- /* Throw a new NullPointerException if handler is null. */
- handler.getClass();
+ if (handler == null)
+ throw new NullPointerException();
handlerList.remove(handler);
handlers = getHandlers();
@@ -1166,8 +1166,8 @@ public class Logger
*/
public synchronized void setParent(Logger parent)
{
- /* Throw a new NullPointerException if parent is null. */
- parent.getClass();
+ if (parent == null)
+ throw new NullPointerException();
if (this == root)
throw new IllegalArgumentException(
diff --git a/libjava/classpath/java/util/prefs/AbstractPreferences.java b/libjava/classpath/java/util/prefs/AbstractPreferences.java
index e676dc3..f3a62e6 100644
--- a/libjava/classpath/java/util/prefs/AbstractPreferences.java
+++ b/libjava/classpath/java/util/prefs/AbstractPreferences.java
@@ -45,6 +45,7 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.TreeSet;
@@ -97,17 +98,18 @@ public abstract class AbstractPreferences extends Preferences {
* accessed by earlier <code>getChild()</code> or <code>childSpi()</code>
* invocations and that have not been removed.
*/
- private HashMap childCache = new HashMap();
+ private HashMap<String, AbstractPreferences> childCache
+ = new HashMap<String, AbstractPreferences>();
/**
* A list of all the registered NodeChangeListener objects.
*/
- private ArrayList nodeListeners;
+ private ArrayList<NodeChangeListener> nodeListeners;
/**
* A list of all the registered PreferenceChangeListener objects.
*/
- private ArrayList preferenceListeners;
+ private ArrayList<PreferenceChangeListener> preferenceListeners;
// constructor
@@ -202,7 +204,8 @@ public abstract class AbstractPreferences extends Preferences {
*/
protected final AbstractPreferences[] cachedChildren()
{
- return (AbstractPreferences[]) childCache.values().toArray();
+ Collection<AbstractPreferences> vals = childCache.values();
+ return vals.toArray(new AbstractPreferences[vals.size()]);
}
/**
@@ -228,7 +231,7 @@ public abstract class AbstractPreferences extends Preferences {
if (isRemoved())
throw new IllegalStateException("Node removed");
- TreeSet childrenNames = new TreeSet();
+ TreeSet<String> childrenNames = new TreeSet<String>();
// First get all cached node names
childrenNames.addAll(childCache.keySet());
@@ -1165,7 +1168,7 @@ public abstract class AbstractPreferences extends Preferences {
if (listener == null)
throw new NullPointerException("listener is null");
if (nodeListeners == null)
- nodeListeners = new ArrayList();
+ nodeListeners = new ArrayList<NodeChangeListener>();
nodeListeners.add(listener);
}
}
@@ -1184,7 +1187,7 @@ public abstract class AbstractPreferences extends Preferences {
if (listener == null)
throw new NullPointerException("listener is null");
if (preferenceListeners == null)
- preferenceListeners = new ArrayList();
+ preferenceListeners = new ArrayList<PreferenceChangeListener>();
preferenceListeners.add(listener);
}
}
diff --git a/libjava/classpath/java/util/prefs/Preferences.java b/libjava/classpath/java/util/prefs/Preferences.java
index e53e4fc..e8cdda8 100644
--- a/libjava/classpath/java/util/prefs/Preferences.java
+++ b/libjava/classpath/java/util/prefs/Preferences.java
@@ -183,9 +183,9 @@ public abstract class Preferences {
// Get the factory
if (factory == null) {
// Caller might not have enough permissions
- factory = (PreferencesFactory) AccessController.doPrivileged(
- new PrivilegedAction() {
- public Object run() {
+ factory = AccessController.doPrivileged(
+ new PrivilegedAction<PreferencesFactory>() {
+ public PreferencesFactory run() {
PreferencesFactory pf = null;
String className = System.getProperty
("java.util.prefs.PreferencesFactory");
diff --git a/libjava/classpath/java/util/regex/Pattern.java b/libjava/classpath/java/util/regex/Pattern.java
index d716fa4..217ce08 100644
--- a/libjava/classpath/java/util/regex/Pattern.java
+++ b/libjava/classpath/java/util/regex/Pattern.java
@@ -1,5 +1,5 @@
/* Pattern.java -- Compiled regular expression ready to be applied.
- Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2004, 2005, 2007 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -246,7 +246,7 @@ public final class Pattern implements Serializable
{
String t = input.subSequence(start, input.length()).toString();
if ("".equals(t) && limit == 0)
- ; // Don't add.
+ { /* Don't add. */ }
else
list.add(t);
}
@@ -260,4 +260,14 @@ public final class Pattern implements Serializable
{
return regex;
}
+
+ /**
+ * Return the regular expression used to construct this object.
+ * @specnote Prior to JDK 1.5 this method had a different behavior
+ * @since 1.5
+ */
+ public String toString()
+ {
+ return regex;
+ }
}
diff --git a/libjava/classpath/java/util/spi/CurrencyNameProvider.java b/libjava/classpath/java/util/spi/CurrencyNameProvider.java
new file mode 100644
index 0000000..14fae4d
--- /dev/null
+++ b/libjava/classpath/java/util/spi/CurrencyNameProvider.java
@@ -0,0 +1,100 @@
+/* CurrencyNameProvider.java -- Providers of localized currency symbols
+ Copyright (C) 2007 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.util.spi;
+
+import java.util.Locale;
+
+/**
+ * A {@link CurrencyNameProvider} provides localized
+ * versions of the symbols that represent a particular
+ * currency. Note that currency symbols are regarded
+ * as names, and thus a <code>null</code> value may
+ * be returned, which should be treated as a lack of
+ * support for the specified {@link Locale}.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.6
+ */
+public abstract class CurrencyNameProvider
+ extends LocaleServiceProvider
+{
+
+ /**
+ * Constructs a new {@link CurrencyNameProvider}.
+ * Provided for implicit invocation by subclasses.
+ */
+ protected CurrencyNameProvider()
+ {
+ }
+
+ /**
+ * <p>
+ * This method returns the symbol which precedes or follows a
+ * value in this particular currency. The returned value is
+ * the symbol used to denote the currency in the specified locale.
+ * </p>
+ * <p>
+ * For example, a supplied locale may specify a different symbol
+ * for the currency, due to conflicts with its own currency.
+ * This would be the case with the American currency, the dollar.
+ * Locales that also use a dollar-based currency (e.g. Canada, Australia)
+ * need to differentiate the American dollar using 'US$' rather than '$'.
+ * So, supplying one of these locales to <code>getSymbol()</code> would
+ * return this value, rather than the standard '$'.
+ * </p>
+ * <p>
+ * In cases where there is no such symbol for a particular currency,
+ * <code>null</code> should be returned.
+ * </p>
+ *
+ * @param currencyCode the ISO 4217 currency code, consisting
+ * of three uppercase letters from 'A' to 'Z'
+ * @param locale the locale to express the symbol in.
+ * @return the currency symbol, or <code>null</code> if one is
+ * unavailable.
+ * @throws NullPointerException if the locale is null.
+ * @throws IllegalArgumentException if the currency code is
+ * not in the correct format
+ * or the locale is not one
+ * returned by
+ * {@link getAvailableLocales()}
+ * @see java.util.Currency#getSymbol(java.util.Locale)
+ */
+ public abstract String getSymbol(String currencyCode, Locale locale);
+
+}
diff --git a/libjava/classpath/java/util/spi/LocaleNameProvider.java b/libjava/classpath/java/util/spi/LocaleNameProvider.java
new file mode 100644
index 0000000..dfd2e4c
--- /dev/null
+++ b/libjava/classpath/java/util/spi/LocaleNameProvider.java
@@ -0,0 +1,135 @@
+/* LocaleNameProvider.java -- Providers of localized locale names
+ Copyright (C) 2007 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.util.spi;
+
+import java.util.Locale;
+
+/**
+ * A {@link LocaleNameProvider} provides localized
+ * versions of the names that represent a particular
+ * locale. Note that a <code>null</code> value may
+ * be returned, which should be treated as a lack of
+ * support for the specified {@link Locale}.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.6
+ */
+public abstract class LocaleNameProvider
+ extends LocaleServiceProvider
+{
+
+ /**
+ * Constructs a new {@link LocaleNameProvider}.
+ * Provided for implicit invocation by subclasses.
+ */
+ protected LocaleNameProvider()
+ {
+ }
+
+ /**
+ * Returns the localized name for the specified ISO 3166
+ * country in the supplied {@link java.util.Locale}.
+ * For example, if the country code is <code>"DE"</code>,
+ * this method will return <code>"Germany"</code> for
+ * {@link Locale.ENGLISH} but <code>"Deutschland"</code>
+ * for {@link Locale.GERMANY}. If the name of the country
+ * in the given locale is not supported, <code>null</code>
+ * is returned.
+ *
+ * @param countryCode the ISO 3166 country code, consisting
+ * of two uppercase letters from 'A' to 'Z'
+ * @param locale the locale to express the country in.
+ * @return the country name, or <code>null</code> if one is
+ * not available.
+ * @throws NullPointerException if the locale is null.
+ * @throws IllegalArgumentException if the country code is
+ * not in the correct format
+ * or the locale is not one
+ * returned by
+ * {@link getAvailableLocales()}
+ * @see java.util.Locale#getDisplayCountry(java.util.Locale)
+ */
+ public abstract String getDisplayCountry(String countryCode,
+ Locale locale);
+
+ /**
+ * Returns the localized name for the specified ISO 639
+ * language in the supplied {@link java.util.Locale}.
+ * For example, if the language code is <code>"de"</code>,
+ * this method will return <code>"German"</code> for
+ * {@link Locale.ENGLISH} but <code>"Deutsch"</code>
+ * for {@link Locale.GERMANY}. If the name of the language
+ * in the given locale is not supported, <code>null</code>
+ * is returned.
+ *
+ * @param langCode the ISO 639 language code, consisting
+ * of two lowercase letters from 'a' to 'z'
+ * @param locale the locale to express the language in.
+ * @return the country name, or <code>null</code> if one is
+ * not available.
+ * @throws NullPointerException if the locale is null.
+ * @throws IllegalArgumentException if the language code is
+ * not in the correct format
+ * or the locale is not one
+ * returned by
+ * {@link getAvailableLocales()}
+ * @see java.util.Locale#getDisplayLanguage(java.util.Locale)
+ */
+ public abstract String getDisplayLanguage(String langCode,
+ Locale locale);
+
+ /**
+ * Returns the localized name for the specified variant
+ * in the supplied {@link java.util.Locale}. If the name
+ * of the variant in the given locale is not supported,
+ * <code>null</code> is returned.
+ *
+ * @param variant the variant.
+ * @param locale the locale to express the variant in.
+ * @return the localized variant, or <code>null</code> if one is
+ * not available.
+ * @throws NullPointerException if the locale is null.
+ * @throws IllegalArgumentException if the locale is not one
+ * returned by
+ * {@link getAvailableLocales()}
+ * @see java.util.Locale#getDisplayVariant(java.util.Locale)
+ */
+ public abstract String getDisplayVariant(String variant,
+ Locale locale);
+
+}
diff --git a/libjava/classpath/java/util/spi/LocaleServiceProvider.java b/libjava/classpath/java/util/spi/LocaleServiceProvider.java
new file mode 100644
index 0000000..bb5b685
--- /dev/null
+++ b/libjava/classpath/java/util/spi/LocaleServiceProvider.java
@@ -0,0 +1,125 @@
+/* LocaleServiceProvider.java -- Superclass of locale SPIs
+ Copyright (C) 2007 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.util.spi;
+
+import java.util.Locale;
+
+/**
+ * <p>
+ * This is the superclass of all the {@link Locale} service
+ * provider interfaces or SPIs. The locale SPIs are used
+ * to allow for the provision of additional support for
+ * locale-specific data. The runtime environment has its
+ * own collection of locale data, but these interfaces allow
+ * this to be extended by external classes.
+ * </p>
+ * <p>
+ * Service providers are created as concrete implementations
+ * of these interfaces, and accessed using the extension
+ * mechanism, realised by {@link ServiceLoader}. When a factory
+ * method of one of the locale-specific classes (such as
+ * {@link java.text.DateFormatSymbols} or {@link java.util.Currency})
+ * is called, the runtime environment is first asked to
+ * provide data for the specified locale. If the runtime
+ * environment fails to provide this, then the offer is
+ * made to service providers which implement the appropriate
+ * interface.
+ * </p>
+ * <p>
+ * Each provider implements the method specified by this
+ * class, {@link #getAvailableLocales()}. This method is
+ * called first to determine whether the provider will be of
+ * any use in providing data for the specified locale. If
+ * a provider is found to be capable, then a more specific
+ * method appropriate to the class requiring the data will
+ * be called. In the case of {@link java.text.DateFormatSymbols},
+ * this would be
+ * {@link java.text.spi.DateFormatSymbols#getInstance(Locale)}.
+ * </p>
+ * <p>
+ * If neither a service provider nor the runtime environment
+ * itself can fulfill the request, a fallback procedure is
+ * engaged. The locale is modified by applying the first
+ * applicable rule:
+ * </p>
+ * <ol>
+ * <li>If the variant contains a <code>'_'</code>, then
+ * this and everything following it is trimmed.</li>
+ * <li>If the variant is non-empty, it is converted to
+ * an empty string.</li>
+ * <li>If the country is non-empty, it is converted to
+ * an empty string.</li>
+ * <li>If the language is non-empty, it is converted to
+ * an empty string.</li>
+ * </ol>
+ * <p>
+ * The modified locale is then used to start the same
+ * process again. The root locale (@link java.util.Locale#ROOT}
+ * must be supported by the runtime environment in order
+ * to terminate this cycle.
+ * </p>
+ * <p>
+ * Note that any names returned by the providers may
+ * be <code>null</code>. Returning a <code>null</code>
+ * name is considered equivalent to not supporting a
+ * particular locale.
+ * </p>
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.6
+ */
+public abstract class LocaleServiceProvider
+{
+
+ /**
+ * Constructs a new {@link LocaleServiceProvider}.
+ * Provided for implicit invocation by subclasses.
+ */
+ protected LocaleServiceProvider()
+ {
+ }
+
+ /**
+ * Returns an array of {@link Locale} instances,
+ * for which the provider can supply localized data.
+ *
+ * @return an array of supported locales.
+ */
+ public abstract Locale[] getAvailableLocales();
+
+}
diff --git a/libjava/classpath/java/util/spi/TimeZoneNameProvider.java b/libjava/classpath/java/util/spi/TimeZoneNameProvider.java
new file mode 100644
index 0000000..2815670
--- /dev/null
+++ b/libjava/classpath/java/util/spi/TimeZoneNameProvider.java
@@ -0,0 +1,97 @@
+/* TimeZoneNameProvider.java -- Providers of localized currency symbols
+ Copyright (C) 2007 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.util.spi;
+
+import java.util.Locale;
+
+/**
+ * A {@link TimeZoneNameProvider} provides localized
+ * versions of the names that represent a particular
+ * timezone. A <code>null</code> value may
+ * be returned, which should be treated as a lack of
+ * support for the specified {@link Locale}. The names
+ * from this class are also used by
+ * {@link DateFormatSymbols#getZoneStrings()}.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.6
+ */
+public abstract class TimeZoneNameProvider
+ extends LocaleServiceProvider
+{
+
+ /**
+ * Constructs a new {@link TimeZoneNameProvider}.
+ * Provided for implicit invocation by subclasses.
+ */
+ protected TimeZoneNameProvider()
+ {
+ }
+
+ /**
+ * Returns a name for the specified time zone identifier
+ * localized to the supplied {@link java.util.Locale}.
+ * The time zone identifier is either <code>"GMT"</code>
+ * or one of the identifiers from the public domain "tz
+ * database" found at <a href="ftp://elsie.nci.nih.gov/pub/">
+ * ftp://elsie.nci.nih.gov/pub</a>. Note that a translated
+ * name for the daylight savings time variant should be returned,
+ * even if the timezone has not observed daylight savings
+ * time in the past. If the name of the timezone
+ * in the given locale is not supported, <code>null</code>
+ * is returned.
+ *
+ * @param id a time zone identifier.
+ * @param daylight true if the daylight savings time variant
+ * should be returned.
+ * @param style either {@link java.util.TimeZone.LONG} or
+ * {@link java.util.TimeZone.SHORT}
+ * @param locale the locale to express the timezone in.
+ * @return the localized time zone name, or <code>null</code>
+ * if one is not available.
+ * @throws NullPointerException if the identifer or locale is null.
+ * @throws IllegalArgumentException if the style is invalid
+ * or the locale is not one
+ * returned by
+ * {@link getAvailableLocales()}
+ * @see java.util.TimeZone#getDisplayName(boolean,int,java.util.Locale)
+ */
+ public abstract String getDisplayName(String id, boolean daylight,
+ int style, Locale locale);
+
+}
diff --git a/libjava/classpath/java/util/spi/package.html b/libjava/classpath/java/util/spi/package.html
new file mode 100644
index 0000000..1abdeb8
--- /dev/null
+++ b/libjava/classpath/java/util/spi/package.html
@@ -0,0 +1,50 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in java.util.spi package.
+ Copyright (C) 2007 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. -->
+
+<html>
+<head><title>GNU Classpath - java.util.spi</title></head>
+
+<body>
+
+<p>
+A series of service provider interfaces for use by the
+classes in <code>java.util</code>.
+</p>
+<p><span style="font-weight: bold;">Since</span>: 1.6</p>
+</body>
+</html>
diff --git a/libjava/classpath/java/util/zip/DeflaterEngine.java b/libjava/classpath/java/util/zip/DeflaterEngine.java
index 5158716..38a82d8 100644
--- a/libjava/classpath/java/util/zip/DeflaterEngine.java
+++ b/libjava/classpath/java/util/zip/DeflaterEngine.java
@@ -377,7 +377,8 @@ class DeflaterEngine implements DeflaterConstants
&& window[++scan] == window[++match]
&& window[++scan] == window[++match]
&& window[++scan] == window[++match]
- && scan < strend);
+ && scan < strend)
+ ;
if (scan > best_end) {
// if (DeflaterConstants.DEBUGGING && ins_h == 0)
diff --git a/libjava/classpath/java/util/zip/ZipInputStream.java b/libjava/classpath/java/util/zip/ZipInputStream.java
index 4539828..df44bb3 100644
--- a/libjava/classpath/java/util/zip/ZipInputStream.java
+++ b/libjava/classpath/java/util/zip/ZipInputStream.java
@@ -238,6 +238,7 @@ public class ZipInputStream extends InflaterInputStream implements ZipConstants
byte[] tmp = new byte[2048];
while (read(tmp) > 0)
;
+
/* read will close this entry */
return;
}