diff options
author | Jesse Wilson <jessewilson@google.com> | 2009-08-24 14:05:44 -0700 |
---|---|---|
committer | Jesse Wilson <jessewilson@google.com> | 2009-08-24 14:22:25 -0700 |
commit | 9b354e75f2418e54638e02d153216660b67d01b8 (patch) | |
tree | 81e0a62567b8ee134f1287a32b394e691af0a01b | |
parent | 3abb0161b285c422fe50d54cdfa248f0aefd65e5 (diff) | |
download | libcore-9b354e75f2418e54638e02d153216660b67d01b8.zip libcore-9b354e75f2418e54638e02d153216660b67d01b8.tar.gz libcore-9b354e75f2418e54638e02d153216660b67d01b8.tar.bz2 |
Update java.text to Harmony r802921.
Notable changes:
- Replaced some StringBuffers with StringBuilders
- Harmony moved to ICU, we stayed with ResourceBundles
- Harmony now uses ICU's Bidi, we continue to use BidiWrapper
- Fixed DateFormat.readResolve()
- Fixed DecimalFormat serialization for setMaximumIntegerDigits
- Fixed currency to support "XXX" for null
- Support for null in MessageFormat.format()
- Rearranged methods in SimpleDateFormat. Body is the same.
- Fixed tests for Bidi.getRunLimit(). These are new failures.
commit 112ab830475bc1a1fab9c7a16589b5525892e6a0
Merge: 39b03a1 62c2b2e
Author: Jesse Wilson <jessewilson@google.com>
Date: Mon Aug 24 14:03:31 2009 -0700
Merge dalvik and Harmony for java.text
Conflicts:
libcore/text/.classpath
libcore/text/META-INF/MANIFEST.MF
libcore/text/build.xml
libcore/text/make/exclude.common
libcore/text/make/run-test.xml
libcore/text/src/main/java/java/text/Annotation.java
libcore/text/src/main/java/java/text/AttributedCharacterIterator.java
libcore/text/src/main/java/java/text/AttributedString.java
libcore/text/src/main/java/java/text/Bidi.java
libcore/text/src/main/java/java/text/BreakIterator.java
libcore/text/src/main/java/java/text/CharacterIterator.java
libcore/text/src/main/java/java/text/ChoiceFormat.java
libcore/text/src/main/java/java/text/CollationElementIterator.java
libcore/text/src/main/java/java/text/CollationKey.java
libcore/text/src/main/java/java/text/Collator.java
libcore/text/src/main/java/java/text/DateFormat.java
libcore/text/src/main/java/java/text/DateFormatSymbols.java
libcore/text/src/main/java/java/text/DecimalFormat.java
libcore/text/src/main/java/java/text/DecimalFormatSymbols.java
libcore/text/src/main/java/java/text/FieldPosition.java
libcore/text/src/main/java/java/text/Format.java
libcore/text/src/main/java/java/text/MessageFormat.java
libcore/text/src/main/java/java/text/NumberFormat.java
libcore/text/src/main/java/java/text/ParseException.java
libcore/text/src/main/java/java/text/ParsePosition.java
libcore/text/src/main/java/java/text/RuleBasedCollator.java
libcore/text/src/main/java/java/text/SimpleDateFormat.java
libcore/text/src/main/java/java/text/StringCharacterIterator.java
libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/AttributedCharacterIteratorAttributeTest.java
libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/BidiTest.java
libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/CollationElementIteratorTest.java
libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/DateFormatSymbolsTest.java
libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/DateFormatTest.java
libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/DecimalFormatSymbolsTest.java
libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/DecimalFormatTest.java
libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/FieldPositionTest.java
libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/MessageFormatTest.java
libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/ParsePositionTest.java
libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/RuleBasedCollatorTest.java
libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/SimpleDateFormatTest.java
commit 39b03a1b2b150d468cc15d8ff8a92a07c9098a5c
Author: Jesse Wilson <jessewilson@google.com>
Date: Wed Aug 19 17:00:36 2009 -0700
text_dalvik
commit 62c2b2e932da51858998820fe2558631999c1241
Author: Jesse Wilson <jessewilson@google.com>
Date: Wed Aug 19 17:00:23 2009 -0700
text_802921
commit 2da8bc3457b9db827d96652e2bf159b7d5040ad1
Author: Jesse Wilson <jessewilson@google.com>
Date: Wed Aug 19 17:00:08 2009 -0700
text_527399
37 files changed, 2108 insertions, 1685 deletions
diff --git a/text/src/main/java/java/text/Annotation.java b/text/src/main/java/java/text/Annotation.java index a45ccaa..4023449 100644 --- a/text/src/main/java/java/text/Annotation.java +++ b/text/src/main/java/java/text/Annotation.java @@ -30,13 +30,9 @@ package java.text; * By wrapping text attribute values into an {@code Annotation}, these aspects * will be taken into account when handling annotation text and the * corresponding main text. - * </p> * <p> * Note: There is no semantic connection between this annotation class and the * {@code java.lang.annotation} package. - * </p> - * - * @since Android 1.0 */ public class Annotation { @@ -44,10 +40,9 @@ public class Annotation { /** * Constructs a new {@code Annotation}. - * + * * @param attribute the attribute attached to this annotation. This may be * {@code null}. - * @since Android 1.0 */ public Annotation(Object attribute) { value = attribute; @@ -55,9 +50,8 @@ public class Annotation { /** * Returns the value of this annotation. The value may be {@code null}. - * + * * @return the value of this annotation or {@code null}. - * @since Android 1.0 */ public Object getValue() { return value; @@ -65,9 +59,8 @@ public class Annotation { /** * Returns this annotation in string representation. - * + * * @return the string representation of this annotation. - * @since Android 1.0 */ @Override public String toString() { diff --git a/text/src/main/java/java/text/AttributedCharacterIterator.java b/text/src/main/java/java/text/AttributedCharacterIterator.java index 07bbdec..4f260ec 100644 --- a/text/src/main/java/java/text/AttributedCharacterIterator.java +++ b/text/src/main/java/java/text/AttributedCharacterIterator.java @@ -31,15 +31,11 @@ import org.apache.harmony.text.internal.nls.Messages; * {@code AttributedCharacterIterator} also allows the user to find runs and * their limits. Runs are defined as ranges of characters that all have the same * attributes with the same values. - * - * @since Android 1.0 */ public interface AttributedCharacterIterator extends CharacterIterator { /** * Defines keys for text attributes. - * - * @since Android 1.0 */ public static class Attribute implements Serializable { @@ -48,11 +44,9 @@ public interface AttributedCharacterIterator extends CharacterIterator { /** * This attribute marks segments from an input method. Most input * methods create these segments for words. - * + * * The value objects are of the type {@code Annotation} which contain * {@code null}. - * - * @since Android 1.0 */ public static final Attribute INPUT_METHOD_SEGMENT = new Attribute( "input_method_segment"); //$NON-NLS-1$ @@ -60,8 +54,6 @@ public interface AttributedCharacterIterator extends CharacterIterator { /** * The attribute describing the language of a character. The value * objects are of type {@code Locale} or a subtype of it. - * - * @since Android 1.0 */ public static final Attribute LANGUAGE = new Attribute("language"); //$NON-NLS-1$ @@ -70,8 +62,6 @@ public interface AttributedCharacterIterator extends CharacterIterator { * Japanese), this attribute allows to define which reading should be * used. The value objects are of type {@code Annotation} which * contain a {@code String}. - * - * @since Android 1.0 */ public static final Attribute READING = new Attribute("reading"); //$NON-NLS-1$ @@ -79,10 +69,9 @@ public interface AttributedCharacterIterator extends CharacterIterator { /** * The constructor for an {@code Attribute} with the name passed. - * + * * @param name * the name of the new {@code Attribute}. - * @since Android 1.0 */ protected Attribute(String name) { this.name = name; @@ -92,23 +81,21 @@ public interface AttributedCharacterIterator extends CharacterIterator { * Compares this attribute with the specified object. Checks if both * objects are the same instance. It is defined final so all subclasses * have the same behavior for this method. - * + * * @param object * the object to compare against. * @return {@code true} if the object passed is equal to this instance; * {@code false} otherwise. - * @since Android 1.0 */ @Override public final boolean equals(Object object) { - return super.equals(object); + return this == object; } /** * Returns the name of this attribute. - * + * * @return the name of this attribute. - * @since Android 1.0 */ protected String getName() { return name; @@ -118,9 +105,8 @@ public interface AttributedCharacterIterator extends CharacterIterator { * Calculates the hash code for objects of type {@code Attribute}. It * is defined final so all sub types calculate their hash code * identically. - * + * * @return the hash code for this instance of {@code Attribute}. - * @since Android 1.0 */ @Override public final int hashCode() { @@ -129,27 +115,30 @@ public interface AttributedCharacterIterator extends CharacterIterator { /** * Resolves a deserialized instance to the correct constant attribute. - * + * * @return the {@code Attribute} this instance represents. * @throws InvalidObjectException * if this instance is not of type {@code Attribute.class} * or if it is not a known {@code Attribute}. - * @since Android 1.0 */ protected Object readResolve() throws InvalidObjectException { if (this.getClass() != Attribute.class) { // text.0C=cannot resolve subclasses throw new InvalidObjectException(Messages.getString("text.0C")); //$NON-NLS-1$ } - if (this.name.equals(INPUT_METHOD_SEGMENT.name)) { + // BEGIN android-changed + // call getName() only once + String name = this.getName(); + if (name.equals(INPUT_METHOD_SEGMENT.getName())) { return INPUT_METHOD_SEGMENT; } - if (this.name.equals(LANGUAGE.name)) { + if (name.equals(LANGUAGE.getName())) { return LANGUAGE; } - if (this.name.equals(READING.name)) { + if (name.equals(READING.getName())) { return READING; } + // END android-changed // text.02=Unknown attribute throw new InvalidObjectException(Messages.getString("text.02")); //$NON-NLS-1$ } @@ -157,9 +146,8 @@ public interface AttributedCharacterIterator extends CharacterIterator { /** * Returns the name of the class followed by a "(", the name of the * attribute, and a ")". - * + * * @return the string representing this instance. - * @since Android 1.0 */ @Override public String toString() { @@ -171,20 +159,18 @@ public interface AttributedCharacterIterator extends CharacterIterator { * Returns a set of attributes present in the {@code * AttributedCharacterIterator}. An empty set is returned if no attributes * were defined. - * + * * @return a set of attribute keys; may be empty. - * @since Android 1.0 */ public Set<Attribute> getAllAttributeKeys(); /** * Returns the value stored in the attribute for the current character. If * the attribute was not defined then {@code null} is returned. - * + * * @param attribute the attribute for which the value should be returned. * @return the value of the requested attribute for the current character or * {@code null} if it was not defined. - * @since Android 1.0 */ public Object getAttribute(Attribute attribute); @@ -192,72 +178,65 @@ public interface AttributedCharacterIterator extends CharacterIterator { * Returns a map of all attributes of the current character. If no * attributes were defined for the current character then an empty map is * returned. - * + * * @return a map of all attributes for the current character or an empty * map. - * @since Android 1.0 */ public Map<Attribute, Object> getAttributes(); /** * Returns the index of the last character in the run having the same * attributes as the current character. - * + * * @return the index of the last character of the current run. - * @since Android 1.0 */ public int getRunLimit(); /** * Returns the index of the last character in the run that has the same * attribute value for the given attribute as the current character. - * + * * @param attribute * the attribute which the run is based on. * @return the index of the last character of the current run. - * @since Android 1.0 */ public int getRunLimit(Attribute attribute); /** * Returns the index of the last character in the run that has the same * attribute values for the attributes in the set as the current character. - * + * * @param attributes * the set of attributes which the run is based on. * @return the index of the last character of the current run. - * @since Android 1.0 */ public int getRunLimit(Set<? extends Attribute> attributes); /** * Returns the index of the first character in the run that has the same * attributes as the current character. - * + * * @return the index of the last character of the current run. - * @since Android 1.0 */ public int getRunStart(); /** * Returns the index of the first character in the run that has the same * attribute value for the given attribute as the current character. - * + * * @param attribute * the attribute which the run is based on. * @return the index of the last character of the current run. - * @since Android 1.0 */ public int getRunStart(Attribute attribute); /** * Returns the index of the first character in the run that has the same * attribute values for the attributes in the set as the current character. - * + * * @param attributes * the set of attributes which the run is based on. * @return the index of the last character of the current run. - * @since Android 1.0 */ public int getRunStart(Set<? extends Attribute> attributes); } diff --git a/text/src/main/java/java/text/AttributedString.java b/text/src/main/java/java/text/AttributedString.java index 540e671..77bbf78 100644 --- a/text/src/main/java/java/text/AttributedString.java +++ b/text/src/main/java/java/text/AttributedString.java @@ -33,8 +33,6 @@ import org.apache.harmony.text.internal.nls.Messages; /** * Holds a string with attributes describing the characters of * this string. - * - * @since Android 1.0 */ public class AttributedString { @@ -180,8 +178,8 @@ public class AttributedString { /** * Returns a set of attributes present in the {@code AttributedString}. - * An empty set returned indicates that no attributes where defined - * + * An empty set returned indicates that no attributes where defined. + * * @return a set of attribute keys that may be empty. */ public Set<AttributedIterator.Attribute> getAllAttributeKeys() { @@ -384,18 +382,17 @@ public class AttributedString { /** * Constructs an {@code AttributedString} from an {@code * AttributedCharacterIterator}, which represents attributed text. - * + * * @param iterator * the {@code AttributedCharacterIterator} that contains the text * for this attributed string. - * @since Android 1.0 */ public AttributedString(AttributedCharacterIterator iterator) { if (iterator.getBeginIndex() > iterator.getEndIndex()) { // text.0A=Invalid substring range throw new IllegalArgumentException(Messages.getString("text.0A")); //$NON-NLS-1$ } - StringBuffer buffer = new StringBuffer(); + StringBuilder buffer = new StringBuilder(); for (int i = iterator.getBeginIndex(); i < iterator.getEndIndex(); i++) { buffer.append(iterator.current()); iterator.next(); @@ -436,7 +433,7 @@ public class AttributedString { return; } - StringBuffer buffer = new StringBuffer(); + StringBuilder buffer = new StringBuilder(); iterator.setIndex(start); while (iterator.getIndex() < end) { buffer.append(iterator.current()); @@ -470,7 +467,7 @@ public class AttributedString { * in the specified {@code AttributedCharacterIterator}, starting at {@code * start} and ending at {@code end}. All attributes will be copied to this * attributed string. - * + * * @param iterator * the {@code AttributedCharacterIterator} that contains the text * for this attributed string. @@ -479,10 +476,9 @@ public class AttributedString { * @param end * the end index of the range of the copied text. * @throws IllegalArgumentException - * if {@code start} is less than first index of + * if {@code start} is less than first index of * {@code iterator}, {@code end} is greater than the last * index + 1 in {@code iterator} or if {@code start > end}. - * @since Android 1.0 */ public AttributedString(AttributedCharacterIterator iterator, int start, int end) { @@ -495,7 +491,7 @@ public class AttributedString { * start}, ending at {@code end} and it will copy the attributes defined in * the specified set. If the set is {@code null} then all attributes are * copied. - * + * * @param iterator * the {@code AttributedCharacterIterator} that contains the text * for this attributed string. @@ -507,10 +503,9 @@ public class AttributedString { * the set of attributes that will be copied, or all if it is * {@code null}. * @throws IllegalArgumentException - * if {@code start} is less than first index of - * {@code iterator}, {@code end} is greater than the last index + + * if {@code start} is less than first index of + * {@code iterator}, {@code end} is greater than the last index + * 1 in {@code iterator} or if {@code start > end}. - * @since Android 1.0 */ public AttributedString(AttributedCharacterIterator iterator, int start, int end, AttributedCharacterIterator.Attribute[] attributes) { @@ -527,10 +522,9 @@ public class AttributedString { /** * Creates an {@code AttributedString} from the given text. - * + * * @param value * the text to take as base for this attributed string. - * @since Android 1.0 */ public AttributedString(String value) { if (value == null) { @@ -543,7 +537,7 @@ public class AttributedString { /** * Creates an {@code AttributedString} from the given text and the * attributes. The whole text has the given attributes applied. - * + * * @param value * the text to take as base for this attributed string. * @param attributes @@ -553,7 +547,6 @@ public class AttributedString { * attributes} is greater than 0. * @throws NullPointerException * if {@code value} is {@code null}. - * @since Android 1.0 */ public AttributedString(String value, Map<? extends AttributedCharacterIterator.Attribute, ?> attributes) { @@ -579,7 +572,7 @@ public class AttributedString { /** * Applies a given attribute to this string. - * + * * @param attribute * the attribute that will be applied to this string. * @param value @@ -589,7 +582,6 @@ public class AttributedString { * if the length of this attributed string is 0. * @throws NullPointerException * if {@code attribute} is {@code null}. - * @since Android 1.0 */ public void addAttribute(AttributedCharacterIterator.Attribute attribute, Object value) { @@ -612,7 +604,7 @@ public class AttributedString { /** * Applies a given attribute to the given range of this string. - * + * * @param attribute * the attribute that will be applied to this string. * @param value @@ -627,7 +619,6 @@ public class AttributedString { * of this string, or if {@code start >= end}. * @throws NullPointerException * if {@code attribute} is {@code null}. - * @since Android 1.0 */ public void addAttribute(AttributedCharacterIterator.Attribute attribute, Object value, int start, int end) { @@ -650,9 +641,6 @@ public class AttributedString { return; } ListIterator<Range> it = ranges.listIterator(); - // BEGIN android-changed - // copied from a newer version of harmony - // value can't be null while (it.hasNext()) { Range range = it.next(); if (end <= range.start) { @@ -710,13 +698,12 @@ public class AttributedString { return; } } - // END android-changed it.add(new Range(start, end, value)); } /** * Applies a given set of attributes to the given range of the string. - * + * * @param attributes * the set of attributes that will be applied to this string. * @param start @@ -726,7 +713,6 @@ public class AttributedString { * @throws IllegalArgumentException * if {@code start < 0}, {@code end} is greater than the length * of this string, or if {@code start >= end}. - * @since Android 1.0 */ public void addAttributes( Map<? extends AttributedCharacterIterator.Attribute, ?> attributes, @@ -743,9 +729,8 @@ public class AttributedString { /** * Returns an {@code AttributedCharacterIterator} that gives access to the * complete content of this attributed string. - * + * * @return the newly created {@code AttributedCharacterIterator}. - * @since Android 1.0 */ public AttributedCharacterIterator getIterator() { return new AttributedIterator(this); @@ -756,12 +741,11 @@ public class AttributedString { * complete content of this attributed string. Only attributes contained in * {@code attributes} are available from this iterator if they are defined * for this text. - * + * * @param attributes * the array containing attributes that will be in the new * iterator if they are defined for this text. * @return the newly created {@code AttributedCharacterIterator}. - * @since Android 1.0 */ public AttributedCharacterIterator getIterator( AttributedCharacterIterator.Attribute[] attributes) { @@ -773,7 +757,7 @@ public class AttributedString { * contents of this attributed string starting at index {@code start} up to * index {@code end}. Only attributes contained in {@code attributes} are * available from this iterator if they are defined for this text. - * + * * @param attributes * the array containing attributes that will be in the new * iterator if they are defined for this text. @@ -782,7 +766,6 @@ public class AttributedString { * @param end * the end index of the iterator on the underlying text. * @return the newly created {@code AttributedCharacterIterator}. - * @since Android 1.0 */ public AttributedCharacterIterator getIterator( AttributedCharacterIterator.Attribute[] attributes, int start, diff --git a/text/src/main/java/java/text/Bidi.java b/text/src/main/java/java/text/Bidi.java index 228dab3..7939dea 100644 --- a/text/src/main/java/java/text/Bidi.java +++ b/text/src/main/java/java/text/Bidi.java @@ -15,8 +15,13 @@ * limitations under the License. */ +// BEGIN android-note +// changed from icu.text.Bidi to BidiWrapper +// END android-note + package java.text; +// BEGIN android-added import java.awt.font.NumericShaper; import java.awt.font.TextAttribute; import java.util.Arrays; @@ -24,6 +29,7 @@ import java.util.LinkedList; import org.apache.harmony.text.BidiRun; import org.apache.harmony.text.BidiWrapper; +// END android-added import org.apache.harmony.text.internal.nls.Messages; /** @@ -40,40 +46,51 @@ import org.apache.harmony.text.internal.nls.Messages; * obtained from the run index. The level of any particular run indicates the * direction of the text as well as the nesting level. Left-to-right runs have * even levels while right-to-left runs have odd levels. - * - * @since Android 1.0 */ public final class Bidi { /** * Constant that indicates the default base level. If there is no strong * character, then set the paragraph level to 0 (left-to-right). - * - * @since Android 1.0 */ public static final int DIRECTION_DEFAULT_LEFT_TO_RIGHT = -2; /** * Constant that indicates the default base level. If there is no strong * character, then set the paragraph level to 1 (right-to-left). - * - * @since Android 1.0 */ public static final int DIRECTION_DEFAULT_RIGHT_TO_LEFT = -1; /** * Constant that specifies the default base level as 0 (left-to-right). - * - * @since Android 1.0 */ public static final int DIRECTION_LEFT_TO_RIGHT = 0; /** * Constant that specifies the default base level as 1 (right-to-left). - * - * @since Android 1.0 */ public static final int DIRECTION_RIGHT_TO_LEFT = 1; + // BEGIN android-removed + // /* + // * Converts the constant from the value specified in the Java spec, to the + // * value required by the ICU implementation. + // */ + // private final static int convertDirectionConstant(int javaConst) { + // switch (javaConst) { + // case DIRECTION_DEFAULT_LEFT_TO_RIGHT : return com.ibm.icu.text.Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT; + // case DIRECTION_DEFAULT_RIGHT_TO_LEFT : return com.ibm.icu.text.Bidi.DIRECTION_DEFAULT_RIGHT_TO_LEFT; + // case DIRECTION_LEFT_TO_RIGHT : return com.ibm.icu.text.Bidi.DIRECTION_LEFT_TO_RIGHT; + // case DIRECTION_RIGHT_TO_LEFT : return com.ibm.icu.text.Bidi.DIRECTION_RIGHT_TO_LEFT; + // default : return com.ibm.icu.text.Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT; + // } + // } + // + // /* + // * Use an embedded ICU4J Bidi object to do all the work + // */ + // private com.ibm.icu.text.Bidi icuBidi; + // END android-removed + /** * Creates a {@code Bidi} object from the {@code * AttributedCharacterIterator} of a paragraph text. The RUN_DIRECTION @@ -89,16 +106,15 @@ public final class Bidi { * attribute specifies the instance of NumericShaper used to convert * European digits to other decimal digits before performing the bidi * algorithm. - * + * * @param paragraph * the String containing the paragraph text to perform the * algorithm. * @throws IllegalArgumentException * if {@code paragraph} is {@code null}. - * @see TextAttribute#BIDI_EMBEDDING - * @see TextAttribute#NUMERIC_SHAPING - * @see TextAttribute#RUN_DIRECTION - * @since Android 1.0 + * @see java.awt.font.TextAttribute#BIDI_EMBEDDING + * @see java.awt.font.TextAttribute#NUMERIC_SHAPING + * @see java.awt.font.TextAttribute#RUN_DIRECTION */ public Bidi(AttributedCharacterIterator paragraph) { if (paragraph == null) { @@ -106,6 +122,7 @@ public final class Bidi { throw new IllegalArgumentException(Messages.getString("text.14")); //$NON-NLS-1$ } + // BEGIN android-added int begin = paragraph.getBeginIndex(); int end = paragraph.getEndIndex(); int length = end - begin; @@ -164,6 +181,7 @@ public final class Bidi { long pBidi = createUBiDi(text, 0, embeddings, 0, length, flags); readBidiInfo(pBidi); BidiWrapper.ubidi_close(pBidi); + // END android-added } /** @@ -191,17 +209,27 @@ public final class Bidi { * DIRECTION_DEFAULT_LEFT_TO_RIGHT. * @throws IllegalArgumentException * if {@code textStart}, {@code embStart}, or {@code - * paragraphLength} is negative; if - * {@code text.length < textStart + paragraphLength} or + * paragraphLength} is negative; if + * {@code text.length < textStart + paragraphLength} or * {@code embeddings.length < embStart + paragraphLength}. * @see #DIRECTION_LEFT_TO_RIGHT * @see #DIRECTION_RIGHT_TO_LEFT * @see #DIRECTION_DEFAULT_RIGHT_TO_LEFT * @see #DIRECTION_DEFAULT_LEFT_TO_RIGHT - * @since Android 1.0 */ public Bidi(char[] text, int textStart, byte[] embeddings, int embStart, int paragraphLength, int flags) { + + if (text == null || text.length - textStart < paragraphLength) { + throw new IllegalArgumentException(); + } + + if (embeddings != null) { + if (embeddings.length - embStart < paragraphLength) { + throw new IllegalArgumentException(); + } + } + if (textStart < 0) { // text.0D=Negative textStart value {0} throw new IllegalArgumentException(Messages.getString( @@ -217,10 +245,13 @@ public final class Bidi { throw new IllegalArgumentException(Messages.getString( "text.11", paragraphLength)); //$NON-NLS-1$ } + + // BEGIN android-changed long pBidi = createUBiDi(text, textStart, embeddings, embStart, paragraphLength, flags); readBidiInfo(pBidi); BidiWrapper.ubidi_close(pBidi); + // END android-changed } /** @@ -238,13 +269,13 @@ public final class Bidi { * @see #DIRECTION_RIGHT_TO_LEFT * @see #DIRECTION_DEFAULT_RIGHT_TO_LEFT * @see #DIRECTION_DEFAULT_LEFT_TO_RIGHT - * @since Android 1.0 */ public Bidi(String paragraph, int flags) { this((paragraph == null ? null : paragraph.toCharArray()), 0, null, 0, (paragraph == null ? 0 : paragraph.length()), flags); } + // BEGIN android-added // create the native UBiDi struct, need to be closed with ubidi_close(). private static long createUBiDi(char[] text, int textStart, byte[] embeddings, int embStart, int paragraphLength, int flags) { @@ -291,7 +322,7 @@ public final class Bidi { return bidi; } - // private constructor, used by createLineBidi() + /* private constructor used by createLineBidi() */ private Bidi(long pBidi) { readBidiInfo(pBidi); } @@ -335,15 +366,17 @@ public final class Bidi { private int direction; private boolean unidirectional; + // END android-added /** * Returns whether the base level is from left to right. * * @return true if the base level is from left to right. - * @since Android 1.0 */ public boolean baseIsLeftToRight() { + // BEGIN android-changed return baseLevel % 2 == 0 ? true : false; + // END android-changed } /** @@ -360,15 +393,19 @@ public final class Bidi { * if {@code lineStart < 0}, {@code lineLimit < 0}, {@code * lineStart > lineLimit} or if {@code lineStart} is greater * than the length of this object's paragraph text. - * @since Android 1.0 */ public Bidi createLineBidi(int lineStart, int lineLimit) { + // BEGIN android-removed + // int length = icuBidi.getLength(); + // END android-removed if (lineStart < 0 || lineLimit < 0 || lineLimit > length || lineStart > lineLimit) { // text.12=Invalid ranges (start={0}, limit={1}, length={2}) throw new IllegalArgumentException(Messages.getString( "text.12", new Object[] { lineStart, lineLimit, length })); //$NON-NLS-1$ } + + // BEGIN android-changed char[] text = new char[this.length]; Arrays.fill(text, 'a'); byte[] embeddings = new byte[this.length]; @@ -386,26 +423,29 @@ public final class Bidi { BidiWrapper.ubidi_close(line); BidiWrapper.ubidi_close(parent); return result; + // END android-changed } /** * Returns the base level. * * @return the base level. - * @since Android 1.0 */ public int getBaseLevel() { + // BEGIN android-changed return baseLevel; + // END android-changed } /** * Returns the length of the text in the {@code Bidi} object. * * @return the length. - * @since Android 1.0 */ public int getLength() { + // BEGIN android-changed return length; + // END android-changed } /** @@ -414,24 +454,26 @@ public final class Bidi { * @param offset * the offset of the character. * @return the level. - * @since Android 1.0 */ public int getLevelAt(int offset) { + // BEGIN android-changed try { return offsetLevel[offset] & ~BidiWrapper.UBIDI_LEVEL_OVERRIDE; } catch (RuntimeException e) { return baseLevel; } + // END android-changed } /** * Returns the number of runs in the bidirectional text. * * @return the number of runs, at least 1. - * @since Android 1.0 */ public int getRunCount() { + // BEGIN android-changed return unidirectional ? 1 : runs.length; + // END android-changed } /** @@ -440,10 +482,11 @@ public final class Bidi { * @param run * the index of the run. * @return the level of the run. - * @since Android 1.0 */ public int getRunLevel(int run) { + // BEGIN android-changed return unidirectional ? baseLevel : runs[run].getLevel(); + // END android-changed } /** @@ -452,10 +495,11 @@ public final class Bidi { * @param run * the index of the run. * @return the limit offset of the run. - * @since Android 1.0 */ public int getRunLimit(int run) { + // BEGIN android-changed return unidirectional ? length : runs[run].getLimit(); + // END android-changed } /** @@ -464,10 +508,11 @@ public final class Bidi { * @param run * the index of the run. * @return the start offset of the run. - * @since Android 1.0 */ public int getRunStart(int run) { + // BEGIN android-changed return unidirectional ? 0 : runs[run].getStart(); + // END android-changed } /** @@ -476,10 +521,11 @@ public final class Bidi { * * @return {@code true} if the text is from left to right; {@code false} * otherwise. - * @since Android 1.0 */ public boolean isLeftToRight() { + // BEGIN android-changed return direction == BidiWrapper.UBiDiDirection_UBIDI_LTR; + // END android-changed } /** @@ -487,10 +533,11 @@ public final class Bidi { * * @return {@code true} if the text direction is mixed; {@code false} * otherwise. - * @since Android 1.0 */ public boolean isMixed() { + // BEGIN android-changed return direction == BidiWrapper.UBiDiDirection_UBIDI_MIXED; + // END android-changed } /** @@ -499,10 +546,11 @@ public final class Bidi { * * @return {@code true} if the text is from right to left; {@code false} * otherwise. - * @since Android 1.0 */ public boolean isRightToLeft() { + // BEGIN android-changed return direction == BidiWrapper.UBiDiDirection_UBIDI_RTL; + // END android-changed } /** @@ -526,7 +574,6 @@ public final class Bidi { * if {@code count}, {@code levelStart} or {@code objectStart} * is negative; if {@code count > levels.length - levelStart} or * if {@code count > objects.length - objectStart}. - * @since Android 1.0 */ public static void reorderVisually(byte[] levels, int levelStart, Object[] objects, int objectStart, int count) { @@ -539,6 +586,8 @@ public final class Bidi { new Object[] { levels.length, levelStart, objects.length, objectStart, count })); } + + // BEGIN android-changed byte[] realLevels = new byte[count]; System.arraycopy(levels, levelStart, realLevels, 0, count); @@ -550,6 +599,7 @@ public final class Bidi { } System.arraycopy(result.toArray(), 0, objects, objectStart, count); + // END android-changed } /** @@ -568,15 +618,17 @@ public final class Bidi { * if {@code start} or {@code limit} is negative; {@code start > * limit} or {@code limit} is greater than the length of this * object's paragraph text. - * @since Android 1.0 */ public static boolean requiresBidi(char[] text, int start, int limit) { - int length = text.length; - if (limit < 0 || start < 0 || start > limit || limit > length) { + //int length = text.length; + if (limit < 0 || start < 0 || start > limit || limit > text.length) { throw new IllegalArgumentException(); } + + // BEGIN android-changed Bidi bidi = new Bidi(text, start, null, 0, limit - start, 0); return !bidi.isLeftToRight(); + // END android-changed } /** @@ -584,12 +636,13 @@ public final class Bidi { * debugging. * * @return a string containing the internal message. - * @since Android 1.0 */ @Override public String toString() { + // BEGIN android-changed return super.toString() + "[direction: " + direction + " baselevel: " + baseLevel //$NON-NLS-1$ //$NON-NLS-2$ + " length: " + length + " runs: " + (unidirectional ? "null" : runs.toString()) + "]"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ + // END android-changed } } diff --git a/text/src/main/java/java/text/BreakIterator.java b/text/src/main/java/java/text/BreakIterator.java index 76b848e..7d19179 100644 --- a/text/src/main/java/java/text/BreakIterator.java +++ b/text/src/main/java/java/text/BreakIterator.java @@ -14,17 +14,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/** -******************************************************************************* -* Copyright (C) 1996-2007, International Business Machines Corporation and * -* others. All Rights Reserved. * -******************************************************************************* -*/ // BEGIN android-note -// The class javadoc and some of the method descriptions are copied from ICU4J -// source files. Changes have been made to the copied descriptions. -// The icu license header was added to this file. // The icu implementation used was changed from icu4j to icu4jni. // END android-note @@ -93,7 +84,6 @@ import java.util.Locale; * {@link CharacterIterator}, which makes it possible to use {@code * BreakIterator} to analyze text in any text-storage vehicle that provides a * {@code CharacterIterator} interface. - * </p> * <p> * <em>Note:</em> Some types of {@code BreakIterator} can take a long time to * create, and instances of {@code BreakIterator} are not currently cached by @@ -104,12 +94,10 @@ import java.util.Locale; * wrapping) and use it to do the whole job of wrapping the text. * <p> * <em>Examples</em>: - * </p> * <p> * Creating and using text boundaries: - * </p> * <blockquote> - * + * * <pre> * public static void main(String args[]) { * if (args.length == 1) { @@ -127,13 +115,12 @@ import java.util.Locale; * } * } * </pre> - * + * * </blockquote> * <p> * Print each element in order: - * </p> * <blockquote> - * + * * <pre> * public static void printEachForward(BreakIterator boundary, String source) { * int start = boundary.first(); @@ -142,13 +129,12 @@ import java.util.Locale; * } * } * </pre> - * + * * </blockquote> * <p> * Print each element in reverse order: - * </p> * <blockquote> - * + * * <pre> * public static void printEachBackward(BreakIterator boundary, String source) { * int end = boundary.last(); @@ -158,13 +144,12 @@ import java.util.Locale; * } * } * </pre> - * + * * </blockquote> * <p> * Print the first element: - * </p> * <blockquote> - * + * * <pre> * public static void printFirst(BreakIterator boundary, String source) { * int start = boundary.first(); @@ -172,13 +157,12 @@ import java.util.Locale; * System.out.println(source.substring(start, end)); * } * </pre> - * + * * </blockquote> * <p> * Print the last element: - * </p> * <blockquote> - * + * * <pre> * public static void printLast(BreakIterator boundary, String source) { * int end = boundary.last(); @@ -186,13 +170,12 @@ import java.util.Locale; * System.out.println(source.substring(start, end)); * } * </pre> - * + * * </blockquote> * <p> * Print the element at a specified position: - * </p> * <blockquote> - * + * * <pre> * public static void printAt(BreakIterator boundary, int pos, String source) { * int end = boundary.following(pos); @@ -200,13 +183,12 @@ import java.util.Locale; * System.out.println(source.substring(start, end)); * } * </pre> - * + * * </blockquote> * <p> * Find the next word: - * </p> * <blockquote> - * + * * <pre> * public static int nextWordStartAfter(int pos, String text) { * BreakIterator wb = BreakIterator.getWordInstance(); @@ -224,7 +206,7 @@ import java.util.Locale; * return BreakIterator.DONE; * } * </pre> - * + * * </blockquote> * <p> * The iterator returned by {@code BreakIterator.getWordInstance()} is unique in @@ -239,23 +221,14 @@ import java.util.Locale; * CJK ideograph, a Hangul syllable, a Kana character, etc.), then the text * between this boundary and the next is a word; otherwise, it's the material * between words.) - * </p> - * + * * @see CharacterIterator - * @since Android 1.0 */ public abstract class BreakIterator implements Cloneable { - /* - * ----------------------------------------------------------------------- - * constants - * ----------------------------------------------------------------------- - */ /** * This constant is returned by iterate methods like {@code previous()} or * {@code next()} if they have returned all valid boundaries. - * - * @since Android 1.0 */ public static final int DONE = -1; @@ -265,23 +238,11 @@ public abstract class BreakIterator implements Cloneable { private static final int SHORT_LENGTH = 2; - /* - * ----------------------------------------------------------------------- - * variables - * ----------------------------------------------------------------------- - */ // the wrapped ICU implementation com.ibm.icu4jni.text.BreakIterator wrapped; - /* - * ----------------------------------------------------------------------- - * constructors - * ----------------------------------------------------------------------- - */ /** * Default constructor, just for invocation by a subclass. - * - * @since Android 1.0 */ protected BreakIterator() { super(); @@ -294,16 +255,10 @@ public abstract class BreakIterator implements Cloneable { wrapped = iterator; } - /* - * ----------------------------------------------------------------------- - * methods - * ----------------------------------------------------------------------- - */ /** * Returns all supported locales in an array. * * @return all supported locales. - * @since Android 1.0 */ public static Locale[] getAvailableLocales() { return com.ibm.icu4jni.text.BreakIterator.getAvailableLocales(); @@ -314,7 +269,6 @@ public abstract class BreakIterator implements Cloneable { * characters using the default locale. * * @return a new instance of {@code BreakIterator} using the default locale. - * @since Android 1.0 */ public static BreakIterator getCharacterInstance() { return new RuleBasedBreakIterator(com.ibm.icu4jni.text.BreakIterator @@ -328,7 +282,6 @@ public abstract class BreakIterator implements Cloneable { * @param where * the given locale. * @return a new instance of {@code BreakIterator} using the given locale. - * @since Android 1.0 */ public static BreakIterator getCharacterInstance(Locale where) { if (where == null) { @@ -344,7 +297,6 @@ public abstract class BreakIterator implements Cloneable { * line breaks using the default locale. * * @return a new instance of {@code BreakIterator} using the default locale. - * @since Android 1.0 */ public static BreakIterator getLineInstance() { return new RuleBasedBreakIterator(com.ibm.icu4jni.text.BreakIterator @@ -359,7 +311,6 @@ public abstract class BreakIterator implements Cloneable { * the given locale. * @return a new instance of {@code BreakIterator} using the given locale. * @throws NullPointerException if {@code where} is {@code null}. - * @since Android 1.0 */ public static BreakIterator getLineInstance(Locale where) { if (where == null) { @@ -375,7 +326,6 @@ public abstract class BreakIterator implements Cloneable { * sentence-breaks using the default locale. * * @return a new instance of {@code BreakIterator} using the default locale. - * @since Android 1.0 */ public static BreakIterator getSentenceInstance() { return new RuleBasedBreakIterator(com.ibm.icu4jni.text.BreakIterator @@ -390,7 +340,6 @@ public abstract class BreakIterator implements Cloneable { * the given locale. * @return a new instance of {@code BreakIterator} using the given locale. * @throws NullPointerException if {@code where} is {@code null}. - * @since Android 1.0 */ public static BreakIterator getSentenceInstance(Locale where) { if (where == null) { @@ -406,7 +355,6 @@ public abstract class BreakIterator implements Cloneable { * word-breaks using the default locale. * * @return a new instance of {@code BreakIterator} using the default locale. - * @since Android 1.0 */ public static BreakIterator getWordInstance() { return new RuleBasedBreakIterator(com.ibm.icu4jni.text.BreakIterator @@ -421,7 +369,6 @@ public abstract class BreakIterator implements Cloneable { * the given locale. * @return a new instance of {@code BreakIterator} using the given locale. * @throws NullPointerException if {@code where} is {@code null}. - * @since Android 1.0 */ public static BreakIterator getWordInstance(Locale where) { if (where == null) { @@ -442,7 +389,6 @@ public abstract class BreakIterator implements Cloneable { * the given offset to check. * @return {@code true} if the given offset is a boundary position; {@code * false} otherwise. - * @since Android 1.0 */ public boolean isBoundary(int offset) { return wrapped.isBoundary(offset); @@ -452,11 +398,12 @@ public abstract class BreakIterator implements Cloneable { * Returns the position of last boundary preceding the given offset, and * sets the current position to the returned value, or {@code DONE} if the * given offset specifies the starting position. - * + * * @param offset * the given start position to be searched for. * @return the position of the last boundary preceding the given offset. - * @since Android 1.0 + * @throws IllegalArgumentException + * if the offset is invalid. */ public int preceding(int offset) { return wrapped.preceding(offset); @@ -469,22 +416,15 @@ public abstract class BreakIterator implements Cloneable { * * @param newText * the new text string to be analyzed. - * @since Android 1.0 */ public void setText(String newText) { wrapped.setText(newText); } - /* - * ----------------------------------------------------------------------- - * abstract methods - * ----------------------------------------------------------------------- - */ /** * Returns this iterator's current position. * * @return this iterator's current position. - * @since Android 1.0 */ public abstract int current(); @@ -493,7 +433,6 @@ public abstract class BreakIterator implements Cloneable { * that position. * * @return the position of the first boundary. - * @since Android 1.0 */ public abstract int first(); @@ -501,11 +440,12 @@ public abstract class BreakIterator implements Cloneable { * Sets the position of the first boundary to the one following the given * offset and returns this position. Returns {@code DONE} if there is no * boundary after the given offset. - * + * * @param offset * the given position to be searched for. * @return the position of the first boundary following the given offset. - * @since Android 1.0 + * @throws IllegalArgumentException + * if the offset is invalid. */ public abstract int following(int offset); @@ -518,7 +458,6 @@ public abstract class BreakIterator implements Cloneable { * * @return a {@code CharacterIterator} which represents the text being * analyzed. - * @since Android 1.0 */ public abstract CharacterIterator getText(); @@ -527,7 +466,6 @@ public abstract class BreakIterator implements Cloneable { * that position. * * @return the position of last boundary. - * @since Android 1.0 */ public abstract int last(); @@ -537,7 +475,6 @@ public abstract class BreakIterator implements Cloneable { * boundary was found after the current position. * * @return the position of last boundary. - * @since Android 1.0 */ public abstract int next(); @@ -549,7 +486,6 @@ public abstract class BreakIterator implements Cloneable { * @param n * the given position. * @return the position of last boundary. - * @since Android 1.0 */ public abstract int next(int n); @@ -559,7 +495,6 @@ public abstract class BreakIterator implements Cloneable { * no boundary was found before the current position. * * @return the position of last boundary. - * @since Android 1.0 */ public abstract int previous(); @@ -571,21 +506,14 @@ public abstract class BreakIterator implements Cloneable { * @param newText * the {@code CharacterIterator} referring to the text to be * analyzed. - * @since Android 1.0 */ public abstract void setText(CharacterIterator newText); - /* - * ----------------------------------------------------------------------- - * methods override Object - * ----------------------------------------------------------------------- - */ /** * Creates a copy of this iterator, all status information including the * current position are kept the same. * * @return a copy of this iterator. - * @since Android 1.0 */ @Override public Object clone() { @@ -612,7 +540,6 @@ public abstract class BreakIterator implements Cloneable { * @throws ArrayIndexOutOfBoundsException * if {@code offset < 0} or {@code offset + LONG_LENGTH} is * greater than the length of {@code buf}. - * @since Android 1.0 */ protected static long getLong(byte[] buf, int offset) { if (null == buf) { @@ -642,7 +569,6 @@ public abstract class BreakIterator implements Cloneable { * @throws ArrayIndexOutOfBoundsException * if {@code offset < 0} or {@code offset + INT_LENGTH} is * greater than the length of {@code buf}. - * @since Android 1.0 */ protected static int getInt(byte[] buf, int offset) { if (null == buf) { @@ -672,7 +598,6 @@ public abstract class BreakIterator implements Cloneable { * @throws ArrayIndexOutOfBoundsException * if {@code offset < 0} or {@code offset + SHORT_LENGTH} is * greater than the length of {@code buf}. - * @since Android 1.0 */ protected static short getShort(byte[] buf, int offset) { if (null == buf) { diff --git a/text/src/main/java/java/text/CharacterIterator.java b/text/src/main/java/java/text/CharacterIterator.java index dfcd21d..81c1fa4 100644 --- a/text/src/main/java/java/text/CharacterIterator.java +++ b/text/src/main/java/java/text/CharacterIterator.java @@ -21,16 +21,12 @@ package java.text; * An interface for the bidirectional iteration over a group of characters. The * iteration starts at the begin index in the group of characters and continues * to one index before the end index. - * - * @since Android 1.0 */ public interface CharacterIterator extends Cloneable { /** * A constant which indicates that there is no character at the current * index. - * - * @since Android 1.0 */ public static final char DONE = '\uffff'; @@ -40,7 +36,6 @@ public interface CharacterIterator extends Cloneable { * @return a shallow copy of this character iterator. * * @see java.lang.Cloneable - * @since Android 1.0 */ public Object clone(); @@ -49,7 +44,6 @@ public interface CharacterIterator extends Cloneable { * * @return the current character, or {@code DONE} if the current index is * past the beginning or end of the sequence. - * @since Android 1.0 */ public char current(); @@ -58,7 +52,6 @@ public interface CharacterIterator extends Cloneable { * the new position. * * @return the character at the begin index. - * @since Android 1.0 */ public char first(); @@ -66,7 +59,6 @@ public interface CharacterIterator extends Cloneable { * Returns the begin index. * * @return the index of the first character of the iteration. - * @since Android 1.0 */ public int getBeginIndex(); @@ -74,7 +66,6 @@ public interface CharacterIterator extends Cloneable { * Returns the end index. * * @return the index one past the last character of the iteration. - * @since Android 1.0 */ public int getEndIndex(); @@ -82,7 +73,6 @@ public interface CharacterIterator extends Cloneable { * Returns the current index. * * @return the current index. - * @since Android 1.0 */ public int getIndex(); @@ -91,7 +81,6 @@ public interface CharacterIterator extends Cloneable { * at the new position. * * @return the character before the end index. - * @since Android 1.0 */ public char last(); @@ -100,7 +89,6 @@ public interface CharacterIterator extends Cloneable { * * @return the character at the next index, or {@code DONE} if the next * index would be past the end. - * @since Android 1.0 */ public char next(); @@ -109,7 +97,6 @@ public interface CharacterIterator extends Cloneable { * * @return the character at the previous index, or {@code DONE} if the * previous index would be past the beginning. - * @since Android 1.0 */ public char previous(); @@ -121,10 +108,9 @@ public interface CharacterIterator extends Cloneable { * the new index that this character iterator is set to. * @return the character at the new index, or {@code DONE} if the index is * past the end. - * @exception IllegalArgumentException - * if {@code location} is less than the begin index or - * greater than the end index. - * @since Android 1.0 + * @throws IllegalArgumentException + * if {@code location} is less than the begin index or greater than + * the end index. */ public char setIndex(int location); } diff --git a/text/src/main/java/java/text/ChoiceFormat.java b/text/src/main/java/java/text/ChoiceFormat.java index 41daced..1a61781 100644 --- a/text/src/main/java/java/text/ChoiceFormat.java +++ b/text/src/main/java/java/text/ChoiceFormat.java @@ -14,18 +14,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/** -******************************************************************************* -* Copyright (C) 1996-2007, International Business Machines Corporation and * -* others. All Rights Reserved. * -******************************************************************************* -*/ - -// BEGIN android-note -// The class javadoc description is copied from ICU UserGuide. -// Changes have been made to the copied descriptions. -// The icu license header was added to this file. -// END android-note package java.text; @@ -46,44 +34,38 @@ import java.util.Locale; * or last index is used depending on whether the number is too low or too high. * The length of the format array must be the same as the length of the limits * array. - * </p> * <h5>Examples:</h5> * <blockquote> - * + * * <pre> * double[] limits = {1, 2, 3, 4, 5, 6, 7}; * String[] fmts = {"Sun", "Mon", "Tue", "Wed", "Thur", "Fri", "Sat"}; - * + * * double[] limits2 = {0, 1, ChoiceFormat.nextDouble(1)}; * String[] fmts2 = {"no files", "one file", "many files"}; * </pre> * </blockquote> - * <p> + * <p> * ChoiceFormat.nextDouble(double) allows to get the double following the one * passed to the method. This is used to create half open intervals. - * </p> * <p> * {@code ChoiceFormat} objects also may be converted to and from patterns. * The conversion can be done programmatically, as in the example above, or * by using a pattern like the following: - * </p> * <blockquote> - * + * * <pre> * "1#Sun|2#Mon|3#Tue|4#Wed|5#Thur|6#Fri|7#Sat" * "0#are no files|1#is one file|1<are many files" * </pre> - * + * * </blockquote> * <p> * where: - * </p> * <ul> * <li><number>"#"</number> specifies an inclusive limit value;</li> * <li><number>"<"</number> specifies an exclusive limit value.</li> * </ul> - * - * @since Android 1.0 */ public class ChoiceFormat extends NumberFormat { @@ -102,8 +84,7 @@ public class ChoiceFormat extends NumberFormat { * <p> * The length of the {@code limits} and {@code formats} arrays must be the * same. - * </p> - * + * * @param limits * an array of doubles in ascending order. The lowest and highest * possible values are negative and positive infinity. @@ -111,7 +92,6 @@ public class ChoiceFormat extends NumberFormat { * the strings associated with the ranges defined through {@code * limits}. The lower bound of the associated range is at the * same index as the string. - * @since Android 1.0 */ public ChoiceFormat(double[] limits, String[] formats) { setChoices(limits, formats); @@ -123,10 +103,8 @@ public class ChoiceFormat extends NumberFormat { * * @param template * the pattern of strings and ranges. - * - * @exception IllegalArgumentException - * if an error occurs while parsing the pattern. - * @since Android 1.0 + * @throws IllegalArgumentException + * if an error occurs while parsing the pattern. */ public ChoiceFormat(String template) { applyPattern(template); @@ -138,10 +116,8 @@ public class ChoiceFormat extends NumberFormat { * * @param template * the pattern of strings and ranges. - * - * @exception IllegalArgumentException - * if an error occurs while parsing the pattern. - * @since Android 1.0 + * @throws IllegalArgumentException + * if an error occurs while parsing the pattern. */ public void applyPattern(String template) { double[] limits = new double[5]; @@ -212,7 +188,6 @@ public class ChoiceFormat extends NumberFormat { * @return a shallow copy of this {@code ChoiceFormat}. * * @see java.lang.Cloneable - * @since Android 1.0 */ @Override public Object clone() { @@ -232,7 +207,6 @@ public class ChoiceFormat extends NumberFormat { * @return {@code true} if the specified object is equal to this instance; * {@code false} otherwise. * @see #hashCode - * @since Android 1.0 */ @Override public boolean equals(Object object) { @@ -258,7 +232,6 @@ public class ChoiceFormat extends NumberFormat { * @param field * a {@code FieldPosition} which is ignored. * @return the string buffer. - * @since Android 1.0 */ @Override public StringBuffer format(double value, StringBuffer buffer, @@ -283,7 +256,6 @@ public class ChoiceFormat extends NumberFormat { * @param field * a {@code FieldPosition} which is ignored. * @return the string buffer. - * @since Android 1.0 */ @Override public StringBuffer format(long value, StringBuffer buffer, @@ -296,7 +268,6 @@ public class ChoiceFormat extends NumberFormat { * ChoiceFormat}. * * @return an array of format strings. - * @since Android 1.0 */ public Object[] getFormats() { return choiceFormats; @@ -307,7 +278,6 @@ public class ChoiceFormat extends NumberFormat { * * @return the array of doubles which make up the limits of this {@code * ChoiceFormat}. - * @since Android 1.0 */ public double[] getLimits() { return choiceLimits; @@ -320,7 +290,6 @@ public class ChoiceFormat extends NumberFormat { * @return the receiver's hash. * * @see #equals - * @since Android 1.0 */ @Override public int hashCode() { @@ -339,7 +308,6 @@ public class ChoiceFormat extends NumberFormat { * @param value * a double value. * @return the next larger double value. - * @since Android 1.0 */ public static final double nextDouble(double value) { if (value == Double.POSITIVE_INFINITY) { @@ -365,7 +333,6 @@ public class ChoiceFormat extends NumberFormat { * {@code true} to get the next larger value, {@code false} to * get the previous smaller value. * @return the next larger or smaller double value. - * @since Android 1.0 */ public static double nextDouble(double value, boolean increment) { return increment ? nextDouble(value) : previousDouble(value); @@ -378,26 +345,30 @@ public class ChoiceFormat extends NumberFormat { * corresponding range in the limits array is returned. If the string is * successfully parsed then the index of the {@code ParsePosition} passed to * this method is updated to the index following the parsed text. - * - * @param string - * the source string to parse. - * @param position - * input/output parameter, specifies the start index in {@code string} - * from where to start parsing. See the <em>Returns</em> section for - * a description of the output values. - * @return if one of the format strings of this {@code ChoiceFormat} instance - * is found in {@code string} starting at the index specified by {@code position.getIndex()} then + * <p> + * If one of the format strings of this {@code ChoiceFormat} instance is + * found in {@code string} starting at {@code position.getIndex()} then * <ul> - * <li>the index in {@code position} is set to the index following the parsed text; - * <li>the {@link java.lang.Double Double} corresponding to the format string is returned.</li> + * <li>the index in {@code position} is set to the index following the + * parsed text; + * <li>the {@link java.lang.Double Double} corresponding to the format + * string is returned.</li> * </ul> * <p> * If none of the format strings is found in {@code string} then - * <ul> - * <li>the error index in {@code position} is set to the current index in {@code position};</li> + * <ul> + * <li>the error index in {@code position} is set to the current index in + * {@code position};</li> * <li> {@link java.lang.Double#NaN Double.NaN} is returned. * </ul> - * @since Android 1.0 + * @param string + * the source string to parse. + * @param position + * input/output parameter, specifies the start index in {@code + * string} from where to start parsing. See the <em>Returns</em> + * section for a description of the output values. + * @return a Double resulting from the parse, or Double.NaN if there is an + * error */ @Override public Number parse(String string, ParsePosition position) { @@ -419,7 +390,6 @@ public class ChoiceFormat extends NumberFormat { * @param value * a double value. * @return the next smaller double value. - * @since Android 1.0 */ public static final double previousDouble(double value) { if (value == Double.NEGATIVE_INFINITY) { @@ -439,13 +409,12 @@ public class ChoiceFormat extends NumberFormat { * Sets the double values and associated strings of this ChoiceFormat. When * calling {@link #format(double, StringBuffer, FieldPosition) format} with * a double value {@code d}, then the element {@code i} in {@code formats} - * is selected where {@code i} fulfills + * is selected where {@code i} fulfills * {@code limits[i] <= d < limits[i+1]}. * <p> * The length of the {@code limits} and {@code formats} arrays must be the * same. - * </p> - * + * * @param limits * an array of doubles in ascending order. The lowest and highest * possible values are negative and positive infinity. @@ -453,7 +422,6 @@ public class ChoiceFormat extends NumberFormat { * the strings associated with the ranges defined through {@code * limits}. The lower bound of the associated range is at the * same index as the string. - * @since Android 1.0 */ public void setChoices(double[] limits, String[] formats) { if (limits.length != formats.length) { @@ -476,10 +444,9 @@ public class ChoiceFormat extends NumberFormat { * ranges and their associated strings. * * @return the pattern. - * @since Android 1.0 */ public String toPattern() { - StringBuffer buffer = new StringBuffer(); + StringBuilder buffer = new StringBuilder(); for (int i = 0; i < choiceLimits.length; i++) { if (i != 0) { buffer.append('|'); diff --git a/text/src/main/java/java/text/CollationElementIterator.java b/text/src/main/java/java/text/CollationElementIterator.java index 66c0079..fb562d8 100644 --- a/text/src/main/java/java/text/CollationElementIterator.java +++ b/text/src/main/java/java/text/CollationElementIterator.java @@ -28,31 +28,23 @@ package java.text; * source string. * <p> * For illustration, consider the following in Spanish: - * </p> * <p> * "ca": the first collation element is collation_element('c') and second * collation element is collation_element('a'). - * </p> * <p> * Since "ch" in Spanish sorts as one entity, the example below returns one * collation element for the two characters 'c' and 'h': - * </p> * <p> * "cha": the first collation element is collation_element('ch') and the second * one is collation_element('a'). - * </p> * <p> * In German, since the character '\u0086' is a composed character of 'a' * and 'e', the iterator returns two collation elements for the single character * '\u0086': - * </p> * <p> * "\u0086b": the first collation element is collation_element('a'), the * second one is collation_element('e'), and the third collation element is * collation_element('b'). - * </p> - * - * @since Android 1.0 */ public final class CollationElementIterator { @@ -61,8 +53,6 @@ public final class CollationElementIterator { * {@code next()} and {@code previous()} when the end or the * beginning of the source string has been reached, and there are no more * valid collation elements to return. - * - * @since Android 1.0 */ public static final int NULLORDER = -1; @@ -83,7 +73,6 @@ public final class CollationElementIterator { * method. * @return the maximum length of any expansion sequence ending with the * specified collation element. - * @since Android 1.0 */ public int getMaxExpansion(int order) { return this.icuIterator.getMaxExpansion(order); @@ -111,7 +100,6 @@ public final class CollationElementIterator { * @return The position of the collation element in the source string that * will be returned by the next invocation of the {@link #next()} * method. - * @since Android 1.0 */ public int getOffset() { return this.icuIterator.getOffset(); @@ -122,7 +110,6 @@ public final class CollationElementIterator { * * @return the next collation element or {@code NULLORDER} if the end * of the iteration has been reached. - * @since Android 1.0 */ public int next() { return this.icuIterator.next(); @@ -133,7 +120,6 @@ public final class CollationElementIterator { * * @return the previous collation element, or {@code NULLORDER} when * the start of the iteration has been reached. - * @since Android 1.0 */ public int previous() { return this.icuIterator.previous(); @@ -146,7 +132,6 @@ public final class CollationElementIterator { * @param order * the element of the collation. * @return the element's 16 bit primary order. - * @since Android 1.0 */ public static final int primaryOrder(int order) { return com.ibm.icu4jni.text.CollationElementIterator.primaryOrder(order); @@ -160,9 +145,6 @@ public final class CollationElementIterator { * If the {@code RuleBasedCollator} used by this iterator has had its * attributes changed, calling {@code reset()} reinitializes the iterator to * use the new attributes. - * </p> - * - * @since Android 1.0 */ public void reset() { this.icuIterator.reset(); @@ -175,7 +157,6 @@ public final class CollationElementIterator { * @param order * the element of the collator. * @return the 8 bit secondary order of the element. - * @since Android 1.0 */ public static final short secondaryOrder(int order) { return (short) com.ibm.icu4jni.text.CollationElementIterator @@ -193,19 +174,16 @@ public final class CollationElementIterator { * adjusted to the start of that sequence. As a result of this, any * subsequent call made to {@code getOffset()} may not return the same value * set by this method. - * </p> * <p> * If the decomposition mode is on, and offset is in the middle of a * decomposable range of source text, the iterator may not return a correct * result for the next forwards or backwards iteration. The user must ensure * that the offset is not in the middle of a decomposable range. - * </p> * * @param newOffset * the character offset into the original source string to set. * Note that this is not an offset into the corresponding * sequence of collation elements. - * @since Android 1.0 */ public void setOffset(int newOffset) { this.icuIterator.setOffset(newOffset); @@ -217,7 +195,6 @@ public final class CollationElementIterator { * * @param source * the new source string iterator for iteration. - * @since Android 1.0 */ public void setText(CharacterIterator source) { this.icuIterator.setText(source); @@ -229,7 +206,6 @@ public final class CollationElementIterator { * * @param source * the new source string for iteration. - * @since Android 1.0 */ public void setText(String source) { this.icuIterator.setText(source); @@ -242,7 +218,6 @@ public final class CollationElementIterator { * @param order * the element of the collation. * @return the 8 bit tertiary order of the element. - * @since Android 1.0 */ public static final short tertiaryOrder(int order) { return (short) com.ibm.icu4jni.text.CollationElementIterator diff --git a/text/src/main/java/java/text/CollationKey.java b/text/src/main/java/java/text/CollationKey.java index f43bfd1..a994fe2 100644 --- a/text/src/main/java/java/text/CollationKey.java +++ b/text/src/main/java/java/text/CollationKey.java @@ -14,17 +14,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/** -******************************************************************************* -* Copyright (C) 1996-2006, International Business Machines Corporation and * -* others. All Rights Reserved. * -******************************************************************************* -*/ // BEGIN android-note -// The class javadoc and some of the method descriptions are copied from ICU4J -// source files. Changes have been made to the copied descriptions. -// The icu license header was added to this file. // The icu implementation used was changed from icu4j to icu4jni. // END android-note @@ -38,13 +29,11 @@ package java.text; * string under two different {@code Collator} instances might differ. Hence * comparing collation keys generated from different {@code Collator} instances * can give incorrect results. - * </p> * <p> * Both the method {@code CollationKey.compareTo(CollationKey)} and the method * {@code Collator.compare(String, String)} compares two strings and returns * their relative order. The performance characteristics of these two approaches * can differ. - * </p> * <p> * During the construction of a {@code CollationKey}, the entire source string * is examined and processed into a series of bits terminated by a null, that @@ -54,19 +43,16 @@ package java.text; * the {@code CollationKey}, but once the key is created, binary comparisons * are fast. This approach is recommended when the same strings are to be * compared over and over again. - * </p> * <p> * On the other hand, implementations of * {@code Collator.compare(String, String)} can examine and process the strings * only until the first characters differ in order. This approach is * recommended if the strings are to be compared only once. - * </p> * <p> * The following example shows how collation keys can be used to sort a * list of strings: - * </p> * <blockquote> - * + * * <pre> * // Create an array of CollationKeys for the Strings to be sorted. * Collator myCollator = Collator.getInstance(); @@ -89,12 +75,11 @@ package java.text; * System.out.println(keys[1].getSourceString()); * System.out.println(keys[2].getSourceString()); * </pre> - * + * * </blockquote> - * + * * @see Collator * @see RuleBasedCollator - * @since Android 1.0 */ public final class CollationKey implements Comparable<CollationKey> { @@ -116,7 +101,6 @@ public final class CollationKey implements Comparable<CollationKey> { * @return a negative value if this {@code CollationKey} is less than the * specified {@code CollationKey}, 0 if they are equal and a * positive value if this {@code CollationKey} is greater. - * @since Android 1.0 */ public int compareTo(CollationKey value) { return icuKey.compareTo(value.icuKey); @@ -133,7 +117,6 @@ public final class CollationKey implements Comparable<CollationKey> { * @return {@code true} if {@code object} is equal to this collation key; * {@code false} otherwise. * @see #hashCode - * @since Android 1.0 */ @Override public boolean equals(Object object) { @@ -148,7 +131,6 @@ public final class CollationKey implements Comparable<CollationKey> { * Returns the string from which this collation key was created. * * @return the source string of this collation key. - * @since Android 1.0 */ public String getSourceString() { return this.source; @@ -161,7 +143,6 @@ public final class CollationKey implements Comparable<CollationKey> { * @return the receiver's hash. * * @see #equals - * @since Android 1.0 */ @Override public int hashCode() { @@ -172,7 +153,6 @@ public final class CollationKey implements Comparable<CollationKey> { * Returns the collation key as a byte array. * * @return an array of bytes. - * @since Android 1.0 */ public byte[] toByteArray() { return icuKey.toByteArray(); diff --git a/text/src/main/java/java/text/Collator.java b/text/src/main/java/java/text/Collator.java index a34b412..aaa3e12 100644 --- a/text/src/main/java/java/text/Collator.java +++ b/text/src/main/java/java/text/Collator.java @@ -14,17 +14,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/** -******************************************************************************* -* Copyright (C) 1996-2007, International Business Machines Corporation and * -* others. All Rights Reserved. * -******************************************************************************* -*/ // BEGIN android-note -// The class javadoc and some of the method descriptions are copied from ICU4J -// source files. Changes have been made to the copied descriptions. -// The icu license header was added to this file. // The icu implementation used was changed from icu4j to icu4jni. // END android-note @@ -47,7 +38,6 @@ import org.apache.harmony.luni.util.PriviAction; * href="http://www.unicode.org/unicode/reports/tr10/"> Unicode Collation * Algorithm (UCA)</a>, there are 4 different levels of strength used in * comparisons: - * </p> * <ul> * <li>PRIMARY strength: Typically, this is used to denote differences between * base characters (for example, "a" < "b"). It is the strongest difference. @@ -83,12 +73,10 @@ import org.apache.harmony.luni.util.PriviAction; * NFD. If canonical decomposition is turned off, it is the user's * responsibility to ensure that all text is already in the appropriate form * before performing a comparison or before getting a {@link CollationKey}. - * </p> * <p> * <em>Examples:</em> - * </p> * <blockquote> - * + * * <pre> * // Get the Collator for US English and set its strength to PRIMARY * Collator usCollator = Collator.getInstance(Locale.US); @@ -97,14 +85,13 @@ import org.apache.harmony.luni.util.PriviAction; * System.out.println("Strings are equivalent"); * } * </pre> - * + * * </blockquote> * <p> * The following example shows how to compare two strings using the collator for * the default locale. - * </p> * <blockquote> - * + * * <pre> * // Compare two strings in the default locale * Collator myCollator = Collator.getInstance(); @@ -121,12 +108,11 @@ import org.apache.harmony.luni.util.PriviAction; * System.out.println("Error: \u00e0\u0325 should be not equal to a\u0325\u0300 without decomposition"); * } * </pre> - * + * * </blockquote> - * + * * @see RuleBasedCollator * @see CollationKey - * @since Android 1.0 */ public abstract class Collator implements Comparator<Object>, Cloneable { @@ -138,51 +124,37 @@ public abstract class Collator implements Comparator<Object>, Cloneable { /** * Constant used to specify the decomposition rule. - * - * @since Android 1.0 */ public static final int NO_DECOMPOSITION = 0; /** * Constant used to specify the decomposition rule. - * - * @since Android 1.0 */ public static final int CANONICAL_DECOMPOSITION = 1; /** * Constant used to specify the decomposition rule. This value for * decomposition is not supported. - * - * @since Android 1.0 */ public static final int FULL_DECOMPOSITION = 2; /** * Constant used to specify the collation strength. - * - * @since Android 1.0 */ public static final int PRIMARY = 0; /** * Constant used to specify the collation strength. - * - * @since Android 1.0 */ public static final int SECONDARY = 1; /** * Constant used to specify the collation strength. - * - * @since Android 1.0 */ public static final int TERTIARY = 2; /** * Constant used to specify the collation strength. - * - * @since Android 1.0 */ public static final int IDENTICAL = 3; @@ -214,8 +186,6 @@ public abstract class Collator implements Comparator<Object>, Cloneable { /** * Constructs a new {@code Collator} instance. - * - * @since Android 1.0 */ protected Collator() { super(); @@ -230,7 +200,6 @@ public abstract class Collator implements Comparator<Object>, Cloneable { * * @return a shallow copy of this collator. * @see java.lang.Cloneable - * @since Android 1.0 */ @Override public Object clone() { @@ -254,10 +223,8 @@ public abstract class Collator implements Comparator<Object>, Cloneable { * @return a negative value if {@code object1} is less than {@code object2}, * 0 if they are equal, and a positive value if {@code object1} is * greater than {@code object2}. - * @exception ClassCastException - * if {@code object1} or {@code object2} is not a - * {@code String}. - * @since Android 1.0 + * @throws ClassCastException + * if {@code object1} or {@code object2} is not a {@code String}. */ public int compare(Object object1, Object object2) { return compare((String) object1, (String) object2); @@ -273,7 +240,6 @@ public abstract class Collator implements Comparator<Object>, Cloneable { * @return a negative value if {@code string1} is less than {@code string2}, * 0 if they are equal and a positive value if {@code string1} is * greater than {@code string2}. - * @since Android 1.0 */ public abstract int compare(String string1, String string2); @@ -287,7 +253,6 @@ public abstract class Collator implements Comparator<Object>, Cloneable { * it has the same strength and decomposition values as this * collator; {@code false} otherwise. * @see #hashCode - * @since Android 1.0 */ @Override public boolean equals(Object object) { @@ -309,7 +274,6 @@ public abstract class Collator implements Comparator<Object>, Cloneable { * the second string to compare. * @return {@code true} if {@code string1} and {@code string2} are equal * using the collation rules, false otherwise. - * @since Android 1.0 */ public boolean equals(String string1, String string2) { return compare(string1, string2) == 0; @@ -320,7 +284,6 @@ public abstract class Collator implements Comparator<Object>, Cloneable { * {@code Collator}. * * @return an array of {@code Locale}. - * @since Android 1.0 */ public static Locale[] getAvailableLocales() { return com.ibm.icu4jni.text.Collator.getAvailableLocales(); @@ -333,7 +296,6 @@ public abstract class Collator implements Comparator<Object>, Cloneable { * @param string * the source string that is converted into a collation key. * @return the collation key for {@code string}. - * @since Android 1.0 */ public abstract CollationKey getCollationKey(String string); @@ -343,7 +305,6 @@ public abstract class Collator implements Comparator<Object>, Cloneable { * @return the decomposition rule, either {@code NO_DECOMPOSITION} or * {@code CANONICAL_DECOMPOSITION}. {@code FULL_DECOMPOSITION} is * not supported. - * @since Android 1.0 */ public int getDecomposition() { return decompositionMode_ICU_Java(this.icuColl.getDecomposition()); @@ -354,7 +315,6 @@ public abstract class Collator implements Comparator<Object>, Cloneable { * {@code Locale}. * * @return the collator for the default locale. - * @since Android 1.0 */ public static Collator getInstance() { return getInstance(Locale.getDefault()); @@ -367,7 +327,6 @@ public abstract class Collator implements Comparator<Object>, Cloneable { * @param locale * the locale. * @return the collator for {@code locale}. - * @since Android 1.0 */ public static Collator getInstance(Locale locale) { String key = locale.toString(); @@ -386,7 +345,6 @@ public abstract class Collator implements Comparator<Object>, Cloneable { * * @return the strength value, either PRIMARY, SECONDARY, TERTIARY or * IDENTICAL. - * @since Android 1.0 */ public int getStrength() { return strength_ICU_Java(this.icuColl.getStrength()); @@ -399,7 +357,6 @@ public abstract class Collator implements Comparator<Object>, Cloneable { * * @see #equals(Object) * @see #equals(String, String) - * @since Android 1.0 */ @Override public abstract int hashCode(); @@ -411,10 +368,9 @@ public abstract class Collator implements Comparator<Object>, Cloneable { * the decomposition rule, either {@code NO_DECOMPOSITION} or * {@code CANONICAL_DECOMPOSITION}. {@code FULL_DECOMPOSITION} * is not supported. - * @exception IllegalArgumentException - * if the provided decomposition rule is not valid. This - * includes {@code FULL_DECOMPOSITION}. - * @since Android 1.0 + * @throws IllegalArgumentException + * if the provided decomposition rule is not valid. This includes + * {@code FULL_DECOMPOSITION}. */ public void setDecomposition(int value) { this.icuColl.setDecomposition(decompositionMode_Java_ICU(value)); @@ -426,10 +382,8 @@ public abstract class Collator implements Comparator<Object>, Cloneable { * @param value * the strength value, either PRIMARY, SECONDARY, TERTIARY, or * IDENTICAL. - * - * @exception IllegalArgumentException - * if the provided strength value is not valid. - * @since Android 1.0 + * @throws IllegalArgumentException + * if the provided strength value is not valid. */ public void setStrength(int value) { this.icuColl.setStrength(strength_Java_ICU(value)); diff --git a/text/src/main/java/java/text/DateFormat.java b/text/src/main/java/java/text/DateFormat.java index 38759ae..f39965a 100644 --- a/text/src/main/java/java/text/DateFormat.java +++ b/text/src/main/java/java/text/DateFormat.java @@ -14,17 +14,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/** -******************************************************************************* -* Copyright (C) 1996-2007, International Business Machines Corporation and * -* others. All Rights Reserved. * -******************************************************************************* -*/ // BEGIN android-note -// The class javadoc and some of the method descriptions are copied from ICU4J -// source files. Changes have been made to the copied descriptions. -// The icu license header was added to this file. +// changed from ICU to resource bundles // END android-note package java.text; @@ -34,7 +26,9 @@ import java.util.Calendar; import java.util.Date; import java.util.Hashtable; import java.util.Locale; +// BEGIN android-added import java.util.ResourceBundle; +// BEGIN android-added import java.util.TimeZone; import org.apache.harmony.text.internal.nls.Messages; @@ -52,58 +46,52 @@ import org.apache.harmony.text.internal.nls.Messages; * styles. The formatting styles include FULL, LONG, MEDIUM, and SHORT. More * details and examples for using these styles are provided in the method * descriptions. - * </p> * <p> * {@code DateFormat} helps you to format and parse dates for any locale. Your * code can be completely independent of the locale conventions for months, days * of the week, or even the calendar format: lunar vs. solar. - * </p> * <p> * To format a date for the current Locale, use one of the static factory * methods: - * </p> * <blockquote> - * + * * <pre> * myString = DateFormat.getDateInstance().format(myDate); * </pre> - * + * * </blockquote> * <p> * If you are formatting multiple dates, it is more efficient to get the format * and use it multiple times so that the system doesn't have to fetch the * information about the local language and country conventions multiple times. - * </p> * <blockquote> - * + * * <pre> * DateFormat df = DateFormat.getDateInstance(); * for (int i = 0; i < a.length; ++i) { * output.println(df.format(myDate[i]) + "; "); * } * </pre> - * + * * </blockquote> * <p> * To format a number for a different locale, specify it in the call to * {@code getDateInstance}: - * </p> * <blockquote> - * + * * <pre> * DateFormat df = DateFormat.getDateInstance(DateFormat.LONG, Locale.FRANCE); * </pre> - * + * * </blockquote> * <p> * {@code DateFormat} can also be used to parse strings: - * </p> * <blockquote> - * + * * <pre> * myDate = df.parse(myString); * </pre> - * + * * </blockquote> * <p> * Use {@code getDateInstance} to get the normal date format for a country. @@ -112,7 +100,6 @@ import org.apache.harmony.text.internal.nls.Messages; * date and time format. You can pass in different options to these factory * methods to control the length of the result; from SHORT to MEDIUM to LONG to * FULL. The exact result depends on the locale, but generally: - * </p> * <ul> * <li>SHORT is completely numeric, such as 12.13.52 or 3:30pm * <li>MEDIUM is longer, such as Jan 12, 1952 @@ -126,7 +113,6 @@ import org.apache.harmony.text.internal.nls.Messages; * from the factory methods to a {@code SimpleDateFormat}. This will work for * the majority of countries; just remember to put it in a try block in case you * encounter an unusual one. - * </p> * <p> * There are versions of the parse and format methods which use * {@code ParsePosition} and {@code FieldPosition} to allow you to @@ -139,13 +125,11 @@ import org.apache.harmony.text.internal.nls.Messages; * Date formats are not synchronized. It is recommended to create separate * format instances for each thread. If multiple threads access a format * concurrently, it must be synchronized externally. - * </p> - * + * * @see NumberFormat * @see SimpleDateFormat * @see Calendar * @see TimeZone - * @since Android 1.0 */ public abstract class DateFormat extends Format { @@ -154,83 +138,61 @@ public abstract class DateFormat extends Format { /** * The calendar that this {@code DateFormat} uses to format a number * representing a date. - * - * @since Android 1.0 */ protected Calendar calendar; /** * The number format used to format a number. - * - * @since Android 1.0 */ protected NumberFormat numberFormat; /** * The format style constant defining the default format style. The default * is MEDIUM. - * - * @since Android 1.0 */ public final static int DEFAULT = 2; /** * The format style constant defining the full style. - * - * @since Android 1.0 */ public final static int FULL = 0; /** * The format style constant defining the long style. - * - * @since Android 1.0 */ public final static int LONG = 1; /** * The format style constant defining the medium style. - * - * @since Android 1.0 */ public final static int MEDIUM = 2; /** * The format style constant defining the short style. - * - * @since Android 1.0 */ public final static int SHORT = 3; /** * The {@code FieldPosition} selector for 'G' field alignment, corresponds * to the {@link Calendar#ERA} field. - * - * @since Android 1.0 */ public final static int ERA_FIELD = 0; /** * The {@code FieldPosition} selector for 'y' field alignment, corresponds * to the {@link Calendar#YEAR} field. - * - * @since Android 1.0 */ public final static int YEAR_FIELD = 1; /** * The {@code FieldPosition} selector for 'M' field alignment, corresponds * to the {@link Calendar#MONTH} field. - * - * @since Android 1.0 */ public final static int MONTH_FIELD = 2; /** * The {@code FieldPosition} selector for 'd' field alignment, corresponds * to the {@link Calendar#DATE} field. - * - * @since Android 1.0 */ public final static int DATE_FIELD = 3; @@ -239,8 +201,6 @@ public abstract class DateFormat extends Format { * to the {@link Calendar#HOUR_OF_DAY} field. {@code HOUR_OF_DAY1_FIELD} is * used for the one-based 24-hour clock. For example, 23:59 + 01:00 results * in 24:59. - * - * @since Android 1.0 */ public final static int HOUR_OF_DAY1_FIELD = 4; @@ -249,80 +209,60 @@ public abstract class DateFormat extends Format { * to the {@link Calendar#HOUR_OF_DAY} field. {@code HOUR_OF_DAY0_FIELD} is * used for the zero-based 24-hour clock. For example, 23:59 + 01:00 results * in 00:59. - * - * @since Android 1.0 */ public final static int HOUR_OF_DAY0_FIELD = 5; /** * FieldPosition selector for 'm' field alignment, corresponds to the * {@link Calendar#MINUTE} field. - * - * @since Android 1.0 */ public final static int MINUTE_FIELD = 6; /** * FieldPosition selector for 's' field alignment, corresponds to the * {@link Calendar#SECOND} field. - * - * @since Android 1.0 */ public final static int SECOND_FIELD = 7; /** * FieldPosition selector for 'S' field alignment, corresponds to the * {@link Calendar#MILLISECOND} field. - * - * @since Android 1.0 */ public final static int MILLISECOND_FIELD = 8; /** * FieldPosition selector for 'E' field alignment, corresponds to the * {@link Calendar#DAY_OF_WEEK} field. - * - * @since Android 1.0 */ public final static int DAY_OF_WEEK_FIELD = 9; /** * FieldPosition selector for 'D' field alignment, corresponds to the * {@link Calendar#DAY_OF_YEAR} field. - * - * @since Android 1.0 */ public final static int DAY_OF_YEAR_FIELD = 10; /** * FieldPosition selector for 'F' field alignment, corresponds to the * {@link Calendar#DAY_OF_WEEK_IN_MONTH} field. - * - * @since Android 1.0 */ public final static int DAY_OF_WEEK_IN_MONTH_FIELD = 11; /** * FieldPosition selector for 'w' field alignment, corresponds to the * {@link Calendar#WEEK_OF_YEAR} field. - * - * @since Android 1.0 */ public final static int WEEK_OF_YEAR_FIELD = 12; /** * FieldPosition selector for 'W' field alignment, corresponds to the * {@link Calendar#WEEK_OF_MONTH} field. - * - * @since Android 1.0 */ public final static int WEEK_OF_MONTH_FIELD = 13; /** * FieldPosition selector for 'a' field alignment, corresponds to the * {@link Calendar#AM_PM} field. - * - * @since Android 1.0 */ public final static int AM_PM_FIELD = 14; @@ -331,8 +271,6 @@ public abstract class DateFormat extends Format { * {@link Calendar#HOUR} field. {@code HOUR1_FIELD} is used for the * one-based 12-hour clock. For example, 11:30 PM + 1 hour results in 12:30 * AM. - * - * @since Android 1.0 */ public final static int HOUR1_FIELD = 15; @@ -340,8 +278,6 @@ public abstract class DateFormat extends Format { * The {@code FieldPosition} selector for 'z' field alignment, corresponds * to the {@link Calendar#ZONE_OFFSET} and {@link Calendar#DST_OFFSET} * fields. - * - * @since Android 1.0 */ public final static int HOUR0_FIELD = 16; @@ -349,15 +285,11 @@ public abstract class DateFormat extends Format { * The {@code FieldPosition} selector for 'z' field alignment, corresponds * to the {@link Calendar#ZONE_OFFSET} and {@link Calendar#DST_OFFSET} * fields. - * - * @since Android 1.0 */ public final static int TIMEZONE_FIELD = 17; /** * Constructs a new instance of {@code DateFormat}. - * - * @since Android 1.0 */ protected DateFormat() { } @@ -368,7 +300,6 @@ public abstract class DateFormat extends Format { * @return a shallow copy of this {@code DateFormat}. * * @see java.lang.Cloneable - * @since Android 1.0 */ @Override public Object clone() { @@ -388,7 +319,6 @@ public abstract class DateFormat extends Format { * it has the same properties as this date format; {@code false} * otherwise. * @see #hashCode - * @since Android 1.0 */ @Override public boolean equals(Object object) { @@ -417,8 +347,7 @@ public abstract class DateFormat extends Format { * a format field, then its {@code beginIndex} and {@code endIndex} members * will be updated with the position of the first occurrence of this field * in the formatted text. - * </p> - * + * * @param object * the source object to format, must be a {@code Date} or a * {@code Number}. If {@code object} is a number then a date is @@ -429,10 +358,9 @@ public abstract class DateFormat extends Format { * on input: an optional alignment field; on output: the offsets * of the alignment field in the formatted text. * @return the string buffer. - * @exception IllegalArgumentException - * if {@code object} is neither a {@code Date} nor a - * {@code Number} instance. - * @since Android 1.0 + * @throws IllegalArgumentException + * if {@code object} is neither a {@code Date} nor a + * {@code Number} instance. */ @Override public final StringBuffer format(Object object, StringBuffer buffer, @@ -453,7 +381,6 @@ public abstract class DateFormat extends Format { * @param date * the date to format. * @return the formatted string. - * @since Android 1.0 */ public final String format(Date date) { return format(date, new StringBuffer(), new FieldPosition(0)) @@ -468,8 +395,7 @@ public abstract class DateFormat extends Format { * a format field, then its {@code beginIndex} and {@code endIndex} members * will be updated with the position of the first occurrence of this field * in the formatted text. - * </p> - * + * * @param date * the date to format. * @param buffer @@ -478,7 +404,6 @@ public abstract class DateFormat extends Format { * on input: an optional alignment field; on output: the offsets * of the alignment field in the formatted text. * @return the string buffer. - * @since Android 1.0 */ public abstract StringBuffer format(Date date, StringBuffer buffer, FieldPosition field); @@ -487,7 +412,6 @@ public abstract class DateFormat extends Format { * Gets the list of installed locales which support {@code DateFormat}. * * @return an array of locales. - * @since Android 1.0 */ public static Locale[] getAvailableLocales() { return Locale.getAvailableLocales(); @@ -497,7 +421,6 @@ public abstract class DateFormat extends Format { * Returns the calendar used by this {@code DateFormat}. * * @return the calendar used by this date format. - * @since Android 1.0 */ public Calendar getCalendar() { return calendar; @@ -508,7 +431,6 @@ public abstract class DateFormat extends Format { * the DEFAULT style for the default locale. * * @return the {@code DateFormat} instance for the default style and locale. - * @since Android 1.0 */ public final static DateFormat getDateInstance() { return getDateInstance(DEFAULT); @@ -525,7 +447,6 @@ public abstract class DateFormat extends Format { * @throws IllegalArgumentException * if {@code style} is not one of SHORT, MEDIUM, LONG, FULL, or * DEFAULT. - * @since Android 1.0 */ public final static DateFormat getDateInstance(int style) { checkDateStyle(style); @@ -545,13 +466,14 @@ public abstract class DateFormat extends Format { * DEFAULT. * @return the {@code DateFormat} instance for {@code style} and * {@code locale}. - * @since Android 1.0 */ public final static DateFormat getDateInstance(int style, Locale locale) { checkDateStyle(style); + // BEGIN android-changed ResourceBundle bundle = getBundle(locale); String pattern = bundle.getString("Date_" + getStyleName(style)); //$NON-NLS-1$ return new SimpleDateFormat(pattern, locale); + // END android-changed } /** @@ -559,7 +481,6 @@ public abstract class DateFormat extends Format { * and time values in the DEFAULT style for the default locale. * * @return the {@code DateFormat} instance for the default style and locale. - * @since Android 1.0 */ public final static DateFormat getDateTimeInstance() { return getDateTimeInstance(DEFAULT, DEFAULT); @@ -578,7 +499,6 @@ public abstract class DateFormat extends Format { * @throws IllegalArgumentException * if {@code dateStyle} or {@code timeStyle} is not one of * SHORT, MEDIUM, LONG, FULL, or DEFAULT. - * @since Android 1.0 */ public final static DateFormat getDateTimeInstance(int dateStyle, int timeStyle) { @@ -602,16 +522,17 @@ public abstract class DateFormat extends Format { * @throws IllegalArgumentException * if {@code dateStyle} or {@code timeStyle} is not one of * SHORT, MEDIUM, LONG, FULL, or DEFAULT. - * @since Android 1.0 */ public final static DateFormat getDateTimeInstance(int dateStyle, int timeStyle, Locale locale) { checkTimeStyle(timeStyle); checkDateStyle(dateStyle); + // BEGIN android-changed ResourceBundle bundle = getBundle(locale); String pattern = bundle.getString("Date_" + getStyleName(dateStyle)) //$NON-NLS-1$ + " " + bundle.getString("Time_" + getStyleName(timeStyle)); //$NON-NLS-1$ //$NON-NLS-2$ return new SimpleDateFormat(pattern, locale); + // END android-changed } /** @@ -620,7 +541,6 @@ public abstract class DateFormat extends Format { * * @return the {@code DateFormat} instance for the SHORT style and default * locale. - * @since Android 1.0 */ public final static DateFormat getInstance() { return getDateTimeInstance(SHORT, SHORT); @@ -630,7 +550,6 @@ public abstract class DateFormat extends Format { * Returns the {@code NumberFormat} used by this {@code DateFormat}. * * @return the {@code NumberFormat} used by this date format. - * @since Android 1.0 */ public NumberFormat getNumberFormat() { return numberFormat; @@ -662,7 +581,6 @@ public abstract class DateFormat extends Format { * values in the DEFAULT style for the default locale. * * @return the {@code DateFormat} instance for the default style and locale. - * @since Android 1.0 */ public final static DateFormat getTimeInstance() { return getTimeInstance(DEFAULT); @@ -679,7 +597,6 @@ public abstract class DateFormat extends Format { * @throws IllegalArgumentException * if {@code style} is not one of SHORT, MEDIUM, LONG, FULL, or * DEFAULT. - * @since Android 1.0 */ public final static DateFormat getTimeInstance(int style) { checkTimeStyle(style); @@ -699,20 +616,20 @@ public abstract class DateFormat extends Format { * DEFAULT. * @return the {@code DateFormat} instance for {@code style} and * {@code locale}. - * @since Android 1.0 */ public final static DateFormat getTimeInstance(int style, Locale locale) { checkTimeStyle(style); + // BEGIN android-changed ResourceBundle bundle = getBundle(locale); String pattern = bundle.getString("Time_" + getStyleName(style)); //$NON-NLS-1$ return new SimpleDateFormat(pattern, locale); + // END android-changed } /** * Returns the time zone of this date format's calendar. * * @return the time zone of the calendar used by this date format. - * @since Android 1.0 */ public TimeZone getTimeZone() { return calendar.getTimeZone(); @@ -731,7 +648,6 @@ public abstract class DateFormat extends Format { * Indicates whether the calendar used by this date format is lenient. * * @return {@code true} if the calendar is lenient; {@code false} otherwise. - * @since Android 1.0 */ public boolean isLenient() { return calendar.isLenient(); @@ -744,9 +660,8 @@ public abstract class DateFormat extends Format { * @param string * the string to parse. * @return the {@code Date} resulting from the parsing. - * @exception ParseException - * if an error occurs during parsing. - * @since Android 1.0 + * @throws ParseException + * if an error occurs during parsing. */ public Date parse(String string) throws ParseException { ParsePosition position = new ParsePosition(0); @@ -770,8 +685,7 @@ public abstract class DateFormat extends Format { * this object's format method but can still be parsed as a date, then the * parse succeeds. Clients may insist on strict adherence to the format by * calling {@code setLenient(false)}. - * </p> - * + * * @param string * the string to parse. * @param position @@ -782,7 +696,6 @@ public abstract class DateFormat extends Format { * the index where the error occurred. * @return the date resulting from the parse, or {@code null} if there is an * error. - * @since Android 1.0 */ public abstract Date parse(String string, ParsePosition position); @@ -797,8 +710,7 @@ public abstract class DateFormat extends Format { * this object's format method but can still be parsed as a date, then the * parse succeeds. Clients may insist on strict adherence to the format by * calling {@code setLenient(false)}. - * </p> - * + * * @param string * the string to parse. * @param position @@ -809,7 +721,6 @@ public abstract class DateFormat extends Format { * is set to the index where the error occurred. * @return the date resulting from the parsing, or {@code null} if there is * an error. - * @since Android 1.0 */ @Override public Object parseObject(String string, ParsePosition position) { @@ -821,7 +732,6 @@ public abstract class DateFormat extends Format { * * @param cal * the new calendar. - * @since Android 1.0 */ public void setCalendar(Calendar cal) { calendar = cal; @@ -836,7 +746,6 @@ public abstract class DateFormat extends Format { * @param value * {@code true} to set the calendar to be lenient, {@code false} * otherwise. - * @since Android 1.0 */ public void setLenient(boolean value) { calendar.setLenient(value); @@ -847,7 +756,6 @@ public abstract class DateFormat extends Format { * * @param format * the new number format. - * @since Android 1.0 */ public void setNumberFormat(NumberFormat format) { numberFormat = format; @@ -858,7 +766,6 @@ public abstract class DateFormat extends Format { * * @param timezone * the new time zone. - * @since Android 1.0 */ public void setTimeZone(TimeZone timezone) { calendar.setTimeZone(timezone); @@ -871,8 +778,6 @@ public abstract class DateFormat extends Format { * <p> * There is no public constructor in this class, the only instances are the * constants defined here. - * </p> - * @since Android 1.0 */ public static class Field extends Format.Field { @@ -882,135 +787,99 @@ public abstract class DateFormat extends Format { /** * Marks the era part of a date. - * - * @since Android 1.0 */ public final static Field ERA = new Field("era", Calendar.ERA); //$NON-NLS-1$ /** * Marks the year part of a date. - * - * @since Android 1.0 */ public final static Field YEAR = new Field("year", Calendar.YEAR); //$NON-NLS-1$ /** * Marks the month part of a date. - * - * @since Android 1.0 */ public final static Field MONTH = new Field("month", Calendar.MONTH); //$NON-NLS-1$ /** * Marks the hour of the day part of a date (0-11). - * - * @since Android 1.0 */ public final static Field HOUR_OF_DAY0 = new Field("hour of day", //$NON-NLS-1$ Calendar.HOUR_OF_DAY); /** * Marks the hour of the day part of a date (1-12). - * - * @since Android 1.0 */ public final static Field HOUR_OF_DAY1 = new Field("hour of day 1", -1); //$NON-NLS-1$ /** * Marks the minute part of a time. - * - * @since Android 1.0 */ public final static Field MINUTE = new Field("minute", Calendar.MINUTE); //$NON-NLS-1$ /** * Marks the second part of a time. - * - * @since Android 1.0 */ public final static Field SECOND = new Field("second", Calendar.SECOND); //$NON-NLS-1$ /** * Marks the millisecond part of a time. - * - * @since Android 1.0 */ public final static Field MILLISECOND = new Field("millisecond", //$NON-NLS-1$ Calendar.MILLISECOND); /** * Marks the day of the week part of a date. - * - * @since Android 1.0 */ public final static Field DAY_OF_WEEK = new Field("day of week", //$NON-NLS-1$ Calendar.DAY_OF_WEEK); /** * Marks the day of the month part of a date. - * - * @since Android 1.0 */ public final static Field DAY_OF_MONTH = new Field("day of month", //$NON-NLS-1$ Calendar.DAY_OF_MONTH); /** * Marks the day of the year part of a date. - * - * @since Android 1.0 */ public final static Field DAY_OF_YEAR = new Field("day of year", //$NON-NLS-1$ Calendar.DAY_OF_YEAR); /** * Marks the day of the week in the month part of a date. - * - * @since Android 1.0 */ public final static Field DAY_OF_WEEK_IN_MONTH = new Field( "day of week in month", Calendar.DAY_OF_WEEK_IN_MONTH); //$NON-NLS-1$ /** * Marks the week of the year part of a date. - * - * @since Android 1.0 */ public final static Field WEEK_OF_YEAR = new Field("week of year", //$NON-NLS-1$ Calendar.WEEK_OF_YEAR); /** * Marks the week of the month part of a date. - * - * @since Android 1.0 */ public final static Field WEEK_OF_MONTH = new Field("week of month", //$NON-NLS-1$ Calendar.WEEK_OF_MONTH); /** * Marks the time indicator part of a date. - * - * @since Android 1.0 */ public final static Field AM_PM = new Field("am pm", Calendar.AM_PM); //$NON-NLS-1$ /** * Marks the hour part of a date (0-11). - * - * @since Android 1.0 */ public final static Field HOUR0 = new Field("hour", Calendar.HOUR); //$NON-NLS-1$ /** * Marks the hour part of a date (1-12). - * - * @since Android 1.0 */ public final static Field HOUR1 = new Field("hour 1", -1); //$NON-NLS-1$ /** * Marks the time zone part of a date. - * - * @since Android 1.0 */ public final static Field TIME_ZONE = new Field("time zone", -1); //$NON-NLS-1$ @@ -1022,12 +891,11 @@ public abstract class DateFormat extends Format { /** * Constructs a new instance of {@code DateFormat.Field} with the given * fieldName and calendar field. - * + * * @param fieldName * the field name. * @param calendarField * the calendar field type of the field. - * @since Android 1.0 */ protected Field(String fieldName, int calendarField) { super(fieldName); @@ -1042,7 +910,6 @@ public abstract class DateFormat extends Format { * Returns the Calendar field that this field represents. * * @return the calendar field. - * @since Android 1.0 */ public int getCalendarField() { return calendarField; @@ -1059,7 +926,6 @@ public abstract class DateFormat extends Format { * @throws IllegalArgumentException * if {@code calendarField} is negative or greater than the * field count of {@code Calendar}. - * @since Android 1.0 */ public static Field ofCalendarField(int calendarField) { if (calendarField < 0 || calendarField >= Calendar.FIELD_COUNT) { @@ -1072,18 +938,23 @@ public abstract class DateFormat extends Format { /** * Resolves instances that are deserialized to the constant * {@code DateFormat.Field} values. - * + * * @return the resolved field object. * @throws InvalidObjectException * if an error occurs while resolving the field object. - * @since Android 1.0 */ @Override protected Object readResolve() throws InvalidObjectException { + if (this.getClass() != Field.class) { + // text.0C=cannot resolve subclasses + throw new InvalidObjectException(Messages.getString("text.0C")); //$NON-NLS-1$ + } + if (calendarField != -1) { try { Field result = ofCalendarField(calendarField); - if (result != null && this.equals(result)) { + + if (result != null && this.getName().equals(result.getName())) { return result; } } catch (IllegalArgumentException e) { diff --git a/text/src/main/java/java/text/DateFormatSymbols.java b/text/src/main/java/java/text/DateFormatSymbols.java index 22c74e9..ad25bd8 100644 --- a/text/src/main/java/java/text/DateFormatSymbols.java +++ b/text/src/main/java/java/text/DateFormatSymbols.java @@ -14,29 +14,21 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/** -******************************************************************************* -* Copyright (C) 1996-2007, International Business Machines Corporation and * -* others. All Rights Reserved. * -******************************************************************************* -*/ // BEGIN android-note -// The class javadoc and some of the method descriptions are copied from ICU4J -// source files. Changes have been made to the copied descriptions. -// The icu license header was added to this file. +// The icu implementation used was changed from icu4j to icu4jni. // END android-note package java.text; -import java.io.Serializable; -// BEGIN android-added import java.io.IOException; import java.io.ObjectOutputStream; -// END android-added +import java.io.Serializable; import java.util.Arrays; import java.util.Locale; +// BEGIN android-added import java.util.ResourceBundle; +// END android-added // BEGIN android-added import com.ibm.icu4jni.util.Resources; @@ -55,17 +47,15 @@ import com.ibm.icu4jni.util.Resources; * the formatter is created, you may modify its format pattern using the * {@code setPattern} method. For more information about creating formatters * using {@code DateFormat}'s factory methods, see {@link DateFormat}. - * </p> * <p> * If you decide to create a date/time formatter with a specific format pattern * for a specific locale, you can do so with: - * </p> * <blockquote> - * + * * <pre> * new SimpleDateFormat(aPattern, new DateFormatSymbols(aLocale)). * </pre> - * + * * </blockquote> * <p> * {@code DateFormatSymbols} objects can be cloned. When you obtain a @@ -73,15 +63,12 @@ import com.ibm.icu4jni.util.Resources; * formatting data. For instance, you can replace the localized date/time format * pattern characters with the ones that you feel easy to remember or you can * change the representative cities to your favorite ones. - * </p> * <p> * New {@code DateFormatSymbols} subclasses may be added to support * {@code SimpleDateFormat} for date/time formatting for additional locales. - * </p> - * + * * @see DateFormat * @see SimpleDateFormat - * @since Android 1.0 */ public class DateFormatSymbols implements Serializable, Cloneable { @@ -93,6 +80,10 @@ public class DateFormatSymbols implements Serializable, Cloneable { String[][] zoneStrings; + // BEGIN android-removed + // transient private com.ibm.icu4jni.text.DateFormatSymbols icuSymbols; + // END android-removed + // BEGIN android-added /** * Locale, necessary to lazily load time zone strings. We force the time @@ -110,15 +101,13 @@ public class DateFormatSymbols implements Serializable, Cloneable { if (zoneStrings == null) { zoneStrings = Resources.getDisplayTimeZones(locale.toString()); } - return zoneStrings; + return zoneStrings; } // END android-added /** * Constructs a new {@code DateFormatSymbols} instance containing the * symbols for the default locale. - * - * @since Android 1.0 */ public DateFormatSymbols() { this(Locale.getDefault()); @@ -130,9 +119,9 @@ public class DateFormatSymbols implements Serializable, Cloneable { * * @param locale * the locale. - * @since Android 1.0 */ public DateFormatSymbols(Locale locale) { + // BEGIN android-changed ResourceBundle bundle = Format.getBundle(locale); localPatternChars = bundle.getString("LocalPatternChars"); //$NON-NLS-1$ ampms = bundle.getStringArray("ampm"); //$NON-NLS-1$ @@ -141,12 +130,33 @@ public class DateFormatSymbols implements Serializable, Cloneable { shortMonths = bundle.getStringArray("shortMonths"); //$NON-NLS-1$ shortWeekdays = bundle.getStringArray("shortWeekdays"); //$NON-NLS-1$ weekdays = bundle.getStringArray("weekdays"); //$NON-NLS-1$ - // BEGIN android-changed - // zoneStrings = (String[][]) bundle.getObject("timezones"); //$NON-NLS-1$ this.locale = locale; // END android-changed } + + private void writeObject(ObjectOutputStream oos) throws IOException { + // BEGIN android-changed + internalZoneStrings(); + // END android-changed + oos.defaultWriteObject(); + } + + // BEGIN android-removed + // DateFormatSymbols(Locale locale, + // com.ibm.icu4jni.text.DateFormatSymbols icuSymbols) { + // + // this.icuSymbols = icuSymbols; + // localPatternChars = icuSymbols.getLocalPatternChars(); + // ampms = icuSymbols.getAmPmStrings(); + // eras = icuSymbols.getEras(); + // months = icuSymbols.getMonths(); + // shortMonths = icuSymbols.getShortMonths(); + // shortWeekdays = icuSymbols.getShortWeekdays(); + // weekdays = icuSymbols.getWeekdays(); + // } + // END android-removed + @Override public Object clone() { // BEGIN android-changed @@ -168,7 +178,6 @@ public class DateFormatSymbols implements Serializable, Cloneable { * {@code DateFormatSymbols} and has the same symbols as this * object, {@code false} otherwise. * @see #hashCode - * @since Android 1.0 */ @Override public boolean equals(Object object) { @@ -178,7 +187,18 @@ public class DateFormatSymbols implements Serializable, Cloneable { if (!(object instanceof DateFormatSymbols)) { return false; } + + // BEGIN android-removed + // if (zoneStrings == null) { + // zoneStrings = icuSymbols.getZoneStrings(); + // } + // END android-removed DateFormatSymbols obj = (DateFormatSymbols) object; + // BEGIN android-removed + // if (obj.zoneStrings == null) { + // obj.zoneStrings = obj.icuSymbols.getZoneStrings(); + // } + // END android-removed if (!localPatternChars.equals(obj.localPatternChars)) { return false; } @@ -233,7 +253,6 @@ public class DateFormatSymbols implements Serializable, Cloneable { * {@code Calendar.PM} as indices for the array. * * @return an array of strings. - * @since Android 1.0 */ public String[] getAmPmStrings() { return ampms.clone(); @@ -245,7 +264,6 @@ public class DateFormatSymbols implements Serializable, Cloneable { * {@code GregorianCalendar.AD} as indices for the array. * * @return an array of strings. - * @since Android 1.0 */ public String[] getEras() { return eras.clone(); @@ -256,7 +274,6 @@ public class DateFormatSymbols implements Serializable, Cloneable { * specify date and time fields. * * @return a string containing the pattern characters. - * @since Android 1.0 */ public String getLocalPatternChars() { return localPatternChars; @@ -268,7 +285,6 @@ public class DateFormatSymbols implements Serializable, Cloneable { * indices for the array. * * @return an array of strings. - * @since Android 1.0 */ public String[] getMonths() { return months.clone(); @@ -280,7 +296,6 @@ public class DateFormatSymbols implements Serializable, Cloneable { * {@code Calendar.JANUARY} etc. as indices for the array. * * @return an array of strings. - * @since Android 1.0 */ public String[] getShortMonths() { return shortMonths.clone(); @@ -292,7 +307,6 @@ public class DateFormatSymbols implements Serializable, Cloneable { * {@code Calendar.SUNDAY} etc. as indices for the array. * * @return an array of strings. - * @since Android 1.0 */ public String[] getShortWeekdays() { return shortWeekdays.clone(); @@ -304,7 +318,6 @@ public class DateFormatSymbols implements Serializable, Cloneable { * {@code Calendar.SUNDAY} etc. as indices for the array. * * @return an array of strings. - * @since Android 1.0 */ public String[] getWeekdays() { return weekdays.clone(); @@ -318,12 +331,11 @@ public class DateFormatSymbols implements Serializable, Cloneable { * and abbreviated names for daylight time. * * @return a two-dimensional array of strings. - * @since Android 1.0 */ public String[][] getZoneStrings() { - // BEGIN android-added + // BEGIN android-changed String[][] zoneStrings = internalZoneStrings(); - // END android-added + // END android-changed String[][] clone = new String[zoneStrings.length][]; for (int i = zoneStrings.length; --i >= 0;) { clone[i] = zoneStrings[i].clone(); @@ -333,6 +345,9 @@ public class DateFormatSymbols implements Serializable, Cloneable { @Override public int hashCode() { + // BEGIN android-changed + String[][] zoneStrings = internalZoneStrings(); + // END android-changed int hashCode; hashCode = localPatternChars.hashCode(); for (String element : ampms) { @@ -353,12 +368,11 @@ public class DateFormatSymbols implements Serializable, Cloneable { for (String element : weekdays) { hashCode += element.hashCode(); } - // BEGIN android-added - String[][] zoneStrings = internalZoneStrings(); - // END android-added for (String[] element : zoneStrings) { for (int j = 0; j < element.length; j++) { - hashCode += element[j].hashCode(); + if (element[j] != null) { + hashCode += element[j].hashCode(); + } } } return hashCode; @@ -371,7 +385,6 @@ public class DateFormatSymbols implements Serializable, Cloneable { * * @param data * the array of strings for AM and PM. - * @since Android 1.0 */ public void setAmPmStrings(String[] data) { ampms = data.clone(); @@ -384,7 +397,6 @@ public class DateFormatSymbols implements Serializable, Cloneable { * * @param data * the array of strings for BC and AD. - * @since Android 1.0 */ public void setEras(String[] data) { eras = data.clone(); @@ -396,7 +408,8 @@ public class DateFormatSymbols implements Serializable, Cloneable { * * @param data * the string containing the pattern characters. - * @since Android 1.0 + * @throws NullPointerException + * if {@code data} is null */ public void setLocalPatternChars(String data) { if (data == null) { @@ -412,7 +425,6 @@ public class DateFormatSymbols implements Serializable, Cloneable { * * @param data * the array of strings. - * @since Android 1.0 */ public void setMonths(String[] data) { months = data.clone(); @@ -425,7 +437,6 @@ public class DateFormatSymbols implements Serializable, Cloneable { * * @param data * the array of strings. - * @since Android 1.0 */ public void setShortMonths(String[] data) { shortMonths = data.clone(); @@ -438,7 +449,6 @@ public class DateFormatSymbols implements Serializable, Cloneable { * * @param data * the array of strings. - * @since Android 1.0 */ public void setShortWeekdays(String[] data) { shortWeekdays = data.clone(); @@ -451,7 +461,6 @@ public class DateFormatSymbols implements Serializable, Cloneable { * * @param data * the array of strings. - * @since Android 1.0 */ public void setWeekdays(String[] data) { weekdays = data.clone(); @@ -466,20 +475,8 @@ public class DateFormatSymbols implements Serializable, Cloneable { * * @param data * the two-dimensional array of strings. - * @since Android 1.0 */ public void setZoneStrings(String[][] data) { zoneStrings = data.clone(); } - - // BEGIN android-added - private void writeObject(ObjectOutputStream out) - throws IOException { - // Ensure internal zone strings are initialized to ensure backward - // compatibility. - internalZoneStrings(); - - out.defaultWriteObject(); - } - // END android-added } diff --git a/text/src/main/java/java/text/DecimalFormat.java b/text/src/main/java/java/text/DecimalFormat.java index 393a2e5..7a0f529 100644 --- a/text/src/main/java/java/text/DecimalFormat.java +++ b/text/src/main/java/java/text/DecimalFormat.java @@ -14,24 +14,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/** -******************************************************************************* -* Copyright (C) 1996-2007, International Business Machines Corporation and * -* others. All Rights Reserved. * -******************************************************************************* -*/ // BEGIN android-note -// The class javadoc and some of the method descriptions are copied from ICU4J -// source files. Changes have been made to the copied descriptions. -// The icu license header was added to this file. // The icu implementation used was changed from icu4j to icu4jni. // END android-note package java.text; import java.io.IOException; -import java.io.InvalidObjectException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.ObjectStreamField; @@ -42,8 +32,6 @@ import java.security.PrivilegedAction; import java.util.Currency; import java.util.Locale; -import org.apache.harmony.text.internal.nls.Messages; - /** * A concrete subclass of {@link NumberFormat} that formats decimal numbers. It * has a variety of features designed to make it possible to parse and format @@ -56,7 +44,6 @@ import org.apache.harmony.text.internal.nls.Messages; * <strong>This is an enhanced version of {@code DecimalFormat} that is based on * the standard version in the RI. New or changed functionality is labeled * <strong><font color="red">NEW</font></strong>.</strong> - * </p> * <p> * To obtain a {@link NumberFormat} for a specific locale (including the default * locale), call one of {@code NumberFormat}'s factory methods such as @@ -65,18 +52,18 @@ import org.apache.harmony.text.internal.nls.Messages; * {@link NumberFormat} factory methods may return subclasses other than * {@code DecimalFormat}. If you need to customize the format object, do * something like this: <blockquote> - * + * * <pre> * NumberFormat f = NumberFormat.getInstance(loc); * if (f instanceof DecimalFormat) { * ((DecimalFormat)f).setDecimalSeparatorAlwaysShown(true); * } * </pre> - * + * * </blockquote> * <h5>Example:</h5> * <blockquote> - * + * * <pre> * // Print out a number using the localized number, currency, * // and percent format for each locale @@ -115,7 +102,7 @@ import org.apache.harmony.text.internal.nls.Messages; * } * } * </pre> - * + * * </blockquote> * <h4>Patterns</h4> * <p> @@ -126,7 +113,6 @@ import org.apache.harmony.text.internal.nls.Messages; * digits. The symbols are stored in a {@link DecimalFormatSymbols} object. When * using the {@link NumberFormat} factory methods, the pattern and symbols are * read from ICU's locale data. - * </p> * <h4>Special Pattern Characters</h4> * <p> * Many characters in a pattern are taken literally; they are matched during @@ -139,19 +125,16 @@ import org.apache.harmony.text.internal.nls.Messages; * character changes. Some special characters affect the behavior of the * formatter by their presence; for example, if the percent character is seen, * then the value is multiplied by 100 before being displayed. - * </p> * <p> * To insert a special character in a pattern as a literal, that is, without any * special meaning, the character must be quoted. There are some exceptions to * this which are noted below. - * </p> * <p> * The characters listed here are used in non-localized patterns. Localized * patterns use the corresponding characters taken from this formatter's * {@link DecimalFormatSymbols} object instead, and these characters lose their * special status. Two exceptions are the currency sign and quote, which are not * localized. - * </p> * <blockquote> <table border="0" cellspacing="3" cellpadding="0" summary="Chart * showing symbol, location, localized, and meaning."> * <tr bgcolor="#ccccff"> @@ -297,7 +280,7 @@ import org.apache.harmony.text.internal.nls.Messages; * {@code DecimalFormat} to throw an {@link IllegalArgumentException} with a * message that describes the problem. * <h4>Pattern BNF</h4> - * + * * <pre> * pattern := subpattern (';' subpattern)? * subpattern := prefix? number exponent? suffix? @@ -310,7 +293,7 @@ import org.apache.harmony.text.internal.nls.Messages; * exponent := 'E' '+'? '0'* '0' * padSpec := '*' padChar * padChar := '\\u0000'..'\\uFFFD' - quote - * + * * Notation: * X* 0 or more instances of X * X? 0 or 1 instances of X @@ -318,7 +301,7 @@ import org.apache.harmony.text.internal.nls.Messages; * C..D any character from C up to D, inclusive * S-T characters in S, except those in T * </pre> - * + * * The first subpattern is for positive numbers. The second (optional) * subpattern is for negative numbers. * <p> @@ -446,7 +429,6 @@ import org.apache.harmony.text.internal.nls.Messages; * specified directly, and the formatter settings for these counts are ignored. * Instead, the formatter uses as many integer and fraction digits as required * to display the specified number of significant digits. - * </p> * <h5>Examples:</h5> * <blockquote> <table border=0 cellspacing=3 cellpadding=0> * <tr bgcolor="#ccccff"> @@ -554,10 +536,9 @@ import org.apache.harmony.text.internal.nls.Messages; * <p> * {@code DecimalFormat} objects are not synchronized. Multiple threads should * not access one formatter concurrently. - * + * * @see Format * @see NumberFormat - * @since Android 1.0 */ public class DecimalFormat extends NumberFormat { @@ -578,11 +559,20 @@ public class DecimalFormat extends NumberFormat { /** * Constructs a new {@code DecimalFormat} for formatting and parsing numbers * for the default locale. - * - * @since Android 1.0 */ public DecimalFormat() { - this(getPattern(Locale.getDefault(), "Number")); //$NON-NLS-1$ + Locale locale = Locale.getDefault(); + icuSymbols = new com.ibm.icu4jni.text.DecimalFormatSymbols(locale); + symbols = new DecimalFormatSymbols(locale); + // BEGIN android-changed + dform = new com.ibm.icu4jni.text.DecimalFormat( + getPattern(Locale.getDefault(), "Number"), icuSymbols); + // END android-changed + + super.setMaximumFractionDigits(dform.getMaximumFractionDigits()); + super.setMaximumIntegerDigits(dform.getMaximumIntegerDigits()); + super.setMinimumFractionDigits(dform.getMinimumFractionDigits()); + super.setMinimumIntegerDigits(dform.getMinimumIntegerDigits()); } /** @@ -591,12 +581,19 @@ public class DecimalFormat extends NumberFormat { * * @param pattern * the non-localized pattern. - * @exception IllegalArgumentException - * if the pattern cannot be parsed. - * @since Android 1.0 + * @throws IllegalArgumentException + * if the pattern cannot be parsed. */ public DecimalFormat(String pattern) { - this(pattern, new DecimalFormatSymbols()); + Locale locale = Locale.getDefault(); + icuSymbols = new com.ibm.icu4jni.text.DecimalFormatSymbols(locale); + symbols = new DecimalFormatSymbols(locale); + dform = new com.ibm.icu4jni.text.DecimalFormat(pattern, icuSymbols); + + super.setMaximumFractionDigits(dform.getMaximumFractionDigits()); + super.setMaximumIntegerDigits(dform.getMaximumIntegerDigits()); + super.setMinimumFractionDigits(dform.getMinimumFractionDigits()); + super.setMinimumIntegerDigits(dform.getMinimumIntegerDigits()); } /** @@ -607,13 +604,12 @@ public class DecimalFormat extends NumberFormat { * the non-localized pattern. * @param value * the DecimalFormatSymbols. - * @exception IllegalArgumentException - * if the pattern cannot be parsed. - * @since Android 1.0 + * @throws IllegalArgumentException + * if the pattern cannot be parsed. */ public DecimalFormat(String pattern, DecimalFormatSymbols value) { symbols = (DecimalFormatSymbols) value.clone(); - Locale locale = (Locale) this.getInternalField("locale", symbols); //$NON-NLS-1$ + Locale locale = symbols.getLocale(); icuSymbols = new com.ibm.icu4jni.text.DecimalFormatSymbols(locale); copySymbols(icuSymbols, symbols); @@ -625,15 +621,27 @@ public class DecimalFormat extends NumberFormat { super.setMinimumIntegerDigits(dform.getMinimumIntegerDigits()); } + // BEGIN android-removed + // DecimalFormat(String pattern, DecimalFormatSymbols value, com.ibm.icu4jni.text.DecimalFormat icuFormat) { + // symbols = value; + // icuSymbols = value.getIcuSymbols(); + // dform = icuFormat; + // + // super.setMaximumFractionDigits(dform.getMaximumFractionDigits()); + // super.setMaximumIntegerDigits(dform.getMaximumIntegerDigits()); + // super.setMinimumFractionDigits(dform.getMinimumFractionDigits()); + // super.setMinimumIntegerDigits(dform.getMinimumIntegerDigits()); + // } + // END android-removed + /** * Changes the pattern of this decimal format to the specified pattern which * uses localized pattern characters. * * @param pattern * the localized pattern. - * @exception IllegalArgumentException - * if the pattern cannot be parsed. - * @since Android 1.0 + * @throws IllegalArgumentException + * if the pattern cannot be parsed. */ public void applyLocalizedPattern(String pattern) { dform.applyLocalizedPattern(pattern); @@ -645,9 +653,8 @@ public class DecimalFormat extends NumberFormat { * * @param pattern * the non-localized pattern. - * @exception IllegalArgumentException - * if the pattern cannot be parsed. - * @since Android 1.0 + * @throws IllegalArgumentException + * if the pattern cannot be parsed. */ public void applyPattern(String pattern) { @@ -660,7 +667,6 @@ public class DecimalFormat extends NumberFormat { * * @return a shallow copy of this decimal format. * @see java.lang.Cloneable - * @since Android 1.0 */ @Override public Object clone() { @@ -680,7 +686,6 @@ public class DecimalFormat extends NumberFormat { * @return {@code true} if the specified object is equal to this decimal * format; {@code false} otherwise. * @see #hashCode - * @since Android 1.0 */ @Override public boolean equals(Object object) { @@ -708,7 +713,6 @@ public class DecimalFormat extends NumberFormat { * if {@code object} cannot be formatted by this format. * @throws NullPointerException * if {@code object} is {@code null}. - * @since Android 1.0 */ @Override public AttributedCharacterIterator formatToCharacterIterator(Object object) { @@ -726,8 +730,7 @@ public class DecimalFormat extends NumberFormat { * specifying a format field, then its {@code beginIndex} and * {@code endIndex} members will be updated with the position of the first * occurrence of this field in the formatted text. - * </p> - * + * * @param value * the double to format. * @param buffer @@ -737,7 +740,6 @@ public class DecimalFormat extends NumberFormat { * on input: an optional alignment field; on output: the offsets * of the alignment field in the formatted text. * @return the string buffer. - * @since Android 1.0 */ @Override public StringBuffer format(double value, StringBuffer buffer, @@ -753,8 +755,7 @@ public class DecimalFormat extends NumberFormat { * specifying a format field, then its {@code beginIndex} and * {@code endIndex} members will be updated with the position of the first * occurrence of this field in the formatted text. - * </p> - * + * * @param value * the long to format. * @param buffer @@ -764,7 +765,6 @@ public class DecimalFormat extends NumberFormat { * on input: an optional alignment field; on output: the offsets * of the alignment field in the formatted text. * @return the string buffer. - * @since Android 1.0 */ @Override public StringBuffer format(long value, StringBuffer buffer, @@ -780,8 +780,7 @@ public class DecimalFormat extends NumberFormat { * specifying a format field, then its {@code beginIndex} and * {@code endIndex} members will be updated with the position of the first * occurrence of this field in the formatted text. - * </p> - * + * * @param number * the object to format. * @param toAppendTo @@ -794,7 +793,6 @@ public class DecimalFormat extends NumberFormat { * if {@code number} is not an instance of {@code Number}. * @throws NullPointerException * if {@code toAppendTo} or {@code pos} is {@code null}. - * @since Android 1.0 */ @Override public final StringBuffer format(Object number, StringBuffer toAppendTo, @@ -816,7 +814,6 @@ public class DecimalFormat extends NumberFormat { * * @return a copy of the {@code DecimalFormatSymbols} used by this decimal * format. - * @since Android 1.0 */ public DecimalFormatSymbols getDecimalFormatSymbols() { return (DecimalFormatSymbols) symbols.clone(); @@ -827,7 +824,6 @@ public class DecimalFormat extends NumberFormat { * * @return the currency used by this decimal format. * @see DecimalFormatSymbols#getCurrency() - * @since Android 1.0 */ @Override public Currency getCurrency() { @@ -841,9 +837,8 @@ public class DecimalFormat extends NumberFormat { * Returns the number of digits grouped together by the grouping separator. * This only allows to get the primary grouping size. There is no API to get * the secondary grouping size. - * + * * @return the number of digits grouped together. - * @since Android 1.0 */ public int getGroupingSize() { return dform.getGroupingSize(); @@ -854,7 +849,6 @@ public class DecimalFormat extends NumberFormat { * or after parsing. * * @return the multiplier. - * @since Android 1.0 */ public int getMultiplier() { return dform.getMultiplier(); @@ -864,7 +858,6 @@ public class DecimalFormat extends NumberFormat { * Returns the prefix which is formatted or parsed before a negative number. * * @return the negative prefix. - * @since Android 1.0 */ public String getNegativePrefix() { return dform.getNegativePrefix(); @@ -874,7 +867,6 @@ public class DecimalFormat extends NumberFormat { * Returns the suffix which is formatted or parsed after a negative number. * * @return the negative suffix. - * @since Android 1.0 */ public String getNegativeSuffix() { return dform.getNegativeSuffix(); @@ -884,7 +876,6 @@ public class DecimalFormat extends NumberFormat { * Returns the prefix which is formatted or parsed before a positive number. * * @return the positive prefix. - * @since Android 1.0 */ public String getPositivePrefix() { return dform.getPositivePrefix(); @@ -894,7 +885,6 @@ public class DecimalFormat extends NumberFormat { * Returns the suffix which is formatted or parsed after a positive number. * * @return the positive suffix. - * @since Android 1.0 */ public String getPositiveSuffix() { return dform.getPositiveSuffix(); @@ -911,7 +901,6 @@ public class DecimalFormat extends NumberFormat { * * @return {@code true} if the decimal separator should always be formatted; * {@code false} otherwise. - * @since Android 1.0 */ public boolean isDecimalSeparatorAlwaysShown() { return dform.isDecimalSeparatorAlwaysShown(); @@ -924,7 +913,6 @@ public class DecimalFormat extends NumberFormat { * @return {@code true} if parse always returns {@code BigDecimals}, * {@code false} if the type of the result is {@code Long} or * {@code Double}. - * @since Android 1.0 */ public boolean isParseBigDecimal() { return this.parseBigDecimal; @@ -937,14 +925,18 @@ public class DecimalFormat extends NumberFormat { * {@code java.lang.Integer}. Special cases are NaN, positive and negative * infinity, which are still returned as {@code java.lang.Double}. * + * * @param value * {@code true} that the resulting numbers of parse operations * will be of type {@code java.lang.Integer} except for the * special cases described above. - * @since Android 1.0 */ @Override public void setParseIntegerOnly(boolean value) { + // In this implementation, com.ibm.icu.text.DecimalFormat is wrapped to + // fulfill most of the format and parse feature. And this method is + // delegated to the wrapped instance of com.ibm.icu.text.DecimalFormat. + dform.setParseIntegerOnly(value); } @@ -954,7 +946,6 @@ public class DecimalFormat extends NumberFormat { * * @return {@code true} if this {@code DecimalFormat}'s parse method only * returns {@code java.lang.Integer}; {@code false} otherwise. - * @since Android 1.0 */ @Override public boolean isParseIntegerOnly() { @@ -985,7 +976,6 @@ public class DecimalFormat extends NumberFormat { * long, otherwise the result is a {@code Double}. If * {@code isParseBigDecimal} is {@code true} then it returns the * result as a {@code BigDecimal}. - * @since Android 1.0 */ @Override public Number parse(String string, ParsePosition position) { @@ -1048,7 +1038,6 @@ public class DecimalFormat extends NumberFormat { * * @param value * the {@code DecimalFormatSymbols} to set. - * @since Android 1.0 */ public void setDecimalFormatSymbols(DecimalFormatSymbols value) { if (value != null) { @@ -1066,7 +1055,6 @@ public class DecimalFormat extends NumberFormat { * @param currency * the currency this {@code DecimalFormat} should use. * @see DecimalFormatSymbols#setCurrency(Currency) - * @since Android 1.0 */ @Override public void setCurrency(Currency currency) { @@ -1084,7 +1072,6 @@ public class DecimalFormat extends NumberFormat { * @param value * {@code true} if the decimal separator should always be * formatted; {@code false} otherwise. - * @since Android 1.0 */ public void setDecimalSeparatorAlwaysShown(boolean value) { dform.setDecimalSeparatorAlwaysShown(value); @@ -1094,10 +1081,9 @@ public class DecimalFormat extends NumberFormat { * Sets the number of digits grouped together by the grouping separator. * This only allows to set the primary grouping size; the secondary grouping * size can only be set with a pattern. - * + * * @param value * the number of digits grouped together. - * @since Android 1.0 */ public void setGroupingSize(int value) { dform.setGroupingSize(value); @@ -1109,7 +1095,6 @@ public class DecimalFormat extends NumberFormat { * * @param value * {@code true} if grouping is used; {@code false} otherwise. - * @since Android 1.0 */ @Override public void setGroupingUsed(boolean value) { @@ -1120,7 +1105,6 @@ public class DecimalFormat extends NumberFormat { * Indicates whether grouping will be used in this format. * * @return {@code true} if grouping is used; {@code false} otherwise. - * @since Android 1.0 */ @Override public boolean isGroupingUsed() { @@ -1137,7 +1121,6 @@ public class DecimalFormat extends NumberFormat { * * @param value * the maximum number of fraction digits. - * @since Android 1.0 */ @Override public void setMaximumFractionDigits(int value) { @@ -1155,7 +1138,6 @@ public class DecimalFormat extends NumberFormat { * * @param value * the maximum number of integer digits. - * @since Android 1.0 */ @Override public void setMaximumIntegerDigits(int value) { @@ -1171,7 +1153,6 @@ public class DecimalFormat extends NumberFormat { * * @param value * the minimum number of fraction digits. - * @since Android 1.0 */ @Override public void setMinimumFractionDigits(int value) { @@ -1187,7 +1168,6 @@ public class DecimalFormat extends NumberFormat { * * @param value * the minimum number of integer digits. - * @since Android 1.0 */ @Override public void setMinimumIntegerDigits(int value) { @@ -1201,7 +1181,6 @@ public class DecimalFormat extends NumberFormat { * * @param value * the multiplier. - * @since Android 1.0 */ public void setMultiplier(int value) { dform.setMultiplier(value); @@ -1212,7 +1191,6 @@ public class DecimalFormat extends NumberFormat { * * @param value * the negative prefix. - * @since Android 1.0 */ public void setNegativePrefix(String value) { dform.setNegativePrefix(value); @@ -1223,7 +1201,6 @@ public class DecimalFormat extends NumberFormat { * * @param value * the negative suffix. - * @since Android 1.0 */ public void setNegativeSuffix(String value) { dform.setNegativeSuffix(value); @@ -1234,7 +1211,6 @@ public class DecimalFormat extends NumberFormat { * * @param value * the positive prefix. - * @since Android 1.0 */ public void setPositivePrefix(String value) { dform.setPositivePrefix(value); @@ -1245,7 +1221,6 @@ public class DecimalFormat extends NumberFormat { * * @param value * the positive suffix. - * @since Android 1.0 */ public void setPositiveSuffix(String value) { dform.setPositiveSuffix(value); @@ -1258,7 +1233,6 @@ public class DecimalFormat extends NumberFormat { * @param newValue * {@code true} if all the returned objects should be of type * {@code BigDecimal}; {@code false} otherwise. - * @since Android 1.0 */ public void setParseBigDecimal(boolean newValue) { this.parseBigDecimal = newValue; @@ -1269,7 +1243,6 @@ public class DecimalFormat extends NumberFormat { * characters. * * @return the localized pattern. - * @since Android 1.0 */ public String toLocalizedPattern() { return dform.toLocalizedPattern(); @@ -1280,7 +1253,6 @@ public class DecimalFormat extends NumberFormat { * characters. * * @return the non-localized pattern. - * @since Android 1.0 */ public String toPattern() { return dform.toPattern(); @@ -1322,47 +1294,47 @@ public class DecimalFormat extends NumberFormat { * if some I/O error occurs * @throws ClassNotFoundException */ + @SuppressWarnings("nls") private void writeObject(ObjectOutputStream stream) throws IOException, ClassNotFoundException { ObjectOutputStream.PutField fields = stream.putFields(); - fields.put("positivePrefix", dform.getPositivePrefix()); //$NON-NLS-1$ - fields.put("positiveSuffix", dform.getPositiveSuffix()); //$NON-NLS-1$ - fields.put("negativePrefix", dform.getNegativePrefix()); //$NON-NLS-1$ - fields.put("negativeSuffix", dform.getNegativeSuffix()); //$NON-NLS-1$ - String posPrefixPattern = (String) this.getInternalField( - "posPrefixPattern", dform); //$NON-NLS-1$ - fields.put("posPrefixPattern", posPrefixPattern); //$NON-NLS-1$ - String posSuffixPattern = (String) this.getInternalField( - "posSuffixPattern", dform); //$NON-NLS-1$ - fields.put("posSuffixPattern", posSuffixPattern); //$NON-NLS-1$ - String negPrefixPattern = (String) this.getInternalField( - "negPrefixPattern", dform); //$NON-NLS-1$ - fields.put("negPrefixPattern", negPrefixPattern); //$NON-NLS-1$ - String negSuffixPattern = (String) this.getInternalField( - "negSuffixPattern", dform); //$NON-NLS-1$ - fields.put("negSuffixPattern", negSuffixPattern); //$NON-NLS-1$ - fields.put("multiplier", dform.getMultiplier()); //$NON-NLS-1$ - fields.put("groupingSize", (byte) dform.getGroupingSize()); //$NON-NLS-1$ + fields.put("positivePrefix", dform.getPositivePrefix()); + fields.put("positiveSuffix", dform.getPositiveSuffix()); + fields.put("negativePrefix", dform.getNegativePrefix()); + fields.put("negativeSuffix", dform.getNegativeSuffix()); + String posPrefixPattern = (String) Format.getInternalField( + "posPrefixPattern", dform); + fields.put("posPrefixPattern", posPrefixPattern); + String posSuffixPattern = (String) Format.getInternalField( + "posSuffixPattern", dform); + fields.put("posSuffixPattern", posSuffixPattern); + String negPrefixPattern = (String) Format.getInternalField( + "negPrefixPattern", dform); + fields.put("negPrefixPattern", negPrefixPattern); + String negSuffixPattern = (String) Format.getInternalField( + "negSuffixPattern", dform); + fields.put("negSuffixPattern", negSuffixPattern); + fields.put("multiplier", dform.getMultiplier()); + fields.put("groupingSize", (byte) dform.getGroupingSize()); // BEGIN android-added - fields.put("groupingUsed", dform.isGroupingUsed()); //$NON-NLS-1$ + fields.put("groupingUsed", dform.isGroupingUsed()); // END android-added - fields.put("decimalSeparatorAlwaysShown", dform //$NON-NLS-1$ + fields.put("decimalSeparatorAlwaysShown", dform .isDecimalSeparatorAlwaysShown()); - fields.put("parseBigDecimal", parseBigDecimal); //$NON-NLS-1$ - fields.put("symbols", symbols); //$NON-NLS-1$ - boolean useExponentialNotation = ((Boolean) this.getInternalField( - "useExponentialNotation", dform)).booleanValue(); //$NON-NLS-1$ - fields.put("useExponentialNotation", useExponentialNotation); //$NON-NLS-1$ - byte minExponentDigits = ((Byte) this.getInternalField( - "minExponentDigits", dform)).byteValue(); //$NON-NLS-1$ - fields.put("minExponentDigits", minExponentDigits); //$NON-NLS-1$ - fields.put("maximumIntegerDigits", dform.getMaximumIntegerDigits()); //$NON-NLS-1$ - fields.put("minimumIntegerDigits", dform.getMinimumIntegerDigits()); //$NON-NLS-1$ - fields.put("maximumFractionDigits", dform.getMaximumFractionDigits()); //$NON-NLS-1$ - fields.put("minimumFractionDigits", dform.getMinimumFractionDigits()); //$NON-NLS-1$ - fields.put("serialVersionOnStream", CURRENT_SERIAL_VERTION); //$NON-NLS-1$ + fields.put("parseBigDecimal", parseBigDecimal); + fields.put("symbols", symbols); + boolean useExponentialNotation = ((Boolean) Format.getInternalField( + "useExponentialNotation", dform)).booleanValue(); + fields.put("useExponentialNotation", useExponentialNotation); + byte minExponentDigits = ((Byte) Format.getInternalField( + "minExponentDigits", dform)).byteValue(); + fields.put("minExponentDigits", minExponentDigits); + fields.put("maximumIntegerDigits", dform.getMaximumIntegerDigits()); + fields.put("minimumIntegerDigits", dform.getMinimumIntegerDigits()); + fields.put("maximumFractionDigits", dform.getMaximumFractionDigits()); + fields.put("minimumFractionDigits", dform.getMinimumFractionDigits()); + fields.put("serialVersionOnStream", CURRENT_SERIAL_VERTION); stream.writeFields(); - } /** @@ -1376,41 +1348,42 @@ public class DecimalFormat extends NumberFormat { * @throws ClassNotFoundException * if some class of serialized objects or fields cannot be found */ + @SuppressWarnings("nls") private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { ObjectInputStream.GetField fields = stream.readFields(); - String positivePrefix = (String) fields.get("positivePrefix", ""); //$NON-NLS-1$ //$NON-NLS-2$ - String positiveSuffix = (String) fields.get("positiveSuffix", ""); //$NON-NLS-1$ //$NON-NLS-2$ - String negativePrefix = (String) fields.get("negativePrefix", "-"); //$NON-NLS-1$ //$NON-NLS-2$ - String negativeSuffix = (String) fields.get("negativeSuffix", ""); //$NON-NLS-1$ //$NON-NLS-2$ - - String posPrefixPattern = (String) fields.get("posPrefixPattern", ""); //$NON-NLS-1$ //$NON-NLS-2$ - String posSuffixPattern = (String) fields.get("posSuffixPattern", ""); //$NON-NLS-1$ //$NON-NLS-2$ - String negPrefixPattern = (String) fields.get("negPrefixPattern", "-"); //$NON-NLS-1$ //$NON-NLS-2$ - String negSuffixPattern = (String) fields.get("negSuffixPattern", ""); //$NON-NLS-1$ //$NON-NLS-2$ - - int multiplier = fields.get("multiplier", 1); //$NON-NLS-1$ - byte groupingSize = fields.get("groupingSize", (byte) 3); //$NON-NLS-1$ + String positivePrefix = (String) fields.get("positivePrefix", ""); + String positiveSuffix = (String) fields.get("positiveSuffix", ""); + String negativePrefix = (String) fields.get("negativePrefix", "-"); + String negativeSuffix = (String) fields.get("negativeSuffix", ""); + + String posPrefixPattern = (String) fields.get("posPrefixPattern", ""); + String posSuffixPattern = (String) fields.get("posSuffixPattern", ""); + String negPrefixPattern = (String) fields.get("negPrefixPattern", "-"); + String negSuffixPattern = (String) fields.get("negSuffixPattern", ""); + + int multiplier = fields.get("multiplier", 1); + byte groupingSize = fields.get("groupingSize", (byte) 3); // BEGIN android-added - boolean groupingUsed = fields.get("groupingUsed", true); //$NON-NLS-1$ + boolean groupingUsed = fields.get("groupingUsed", true); // END android-added boolean decimalSeparatorAlwaysShown = fields.get( - "decimalSeparatorAlwaysShown", false); //$NON-NLS-1$ - boolean parseBigDecimal = fields.get("parseBigDecimal", false); //$NON-NLS-1$ - symbols = (DecimalFormatSymbols) fields.get("symbols", null); //$NON-NLS-1$ + "decimalSeparatorAlwaysShown", false); + boolean parseBigDecimal = fields.get("parseBigDecimal", false); + symbols = (DecimalFormatSymbols) fields.get("symbols", null); - boolean useExponentialNotation = fields.get("useExponentialNotation", //$NON-NLS-1$ + boolean useExponentialNotation = fields.get("useExponentialNotation", false); - byte minExponentDigits = fields.get("minExponentDigits", (byte) 0); //$NON-NLS-1$ + byte minExponentDigits = fields.get("minExponentDigits", (byte) 0); - int maximumIntegerDigits = fields.get("maximumIntegerDigits", 309); //$NON-NLS-1$ - int minimumIntegerDigits = fields.get("minimumIntegerDigits", 309); //$NON-NLS-1$ - int maximumFractionDigits = fields.get("maximumFractionDigits", 340); //$NON-NLS-1$ - int minimumFractionDigits = fields.get("minimumFractionDigits", 340); //$NON-NLS-1$ - this.serialVersionOnStream = fields.get("serialVersionOnStream", 0); //$NON-NLS-1$ + int maximumIntegerDigits = fields.get("maximumIntegerDigits", 309); + int minimumIntegerDigits = fields.get("minimumIntegerDigits", 309); + int maximumFractionDigits = fields.get("maximumFractionDigits", 340); + int minimumFractionDigits = fields.get("minimumFractionDigits", 340); + this.serialVersionOnStream = fields.get("serialVersionOnStream", 0); - Locale locale = (Locale) getInternalField("locale", symbols); //$NON-NLS-1$ + Locale locale = (Locale) Format.getInternalField("locale", symbols); // BEGIN android-removed // dform = new com.ibm.icu4jni.text.DecimalFormat("", //$NON-NLS-1$ // new com.ibm.icu4jni.text.DecimalFormatSymbols(locale)); @@ -1421,18 +1394,18 @@ public class DecimalFormat extends NumberFormat { dform = new com.ibm.icu4jni.text.DecimalFormat("", //$NON-NLS-1$ icuSymbols); // END android-added - setInternalField("useExponentialNotation", dform, new Boolean( //$NON-NLS-1$ - useExponentialNotation)); - setInternalField("minExponentDigits", dform, //$NON-NLS-1$ + setInternalField("useExponentialNotation", dform, Boolean + .valueOf(useExponentialNotation)); + setInternalField("minExponentDigits", dform, new Byte(minExponentDigits)); dform.setPositivePrefix(positivePrefix); dform.setPositiveSuffix(positiveSuffix); dform.setNegativePrefix(negativePrefix); dform.setNegativeSuffix(negativeSuffix); - setInternalField("posPrefixPattern", dform, posPrefixPattern); //$NON-NLS-1$ - setInternalField("posSuffixPattern", dform, posSuffixPattern); //$NON-NLS-1$ - setInternalField("negPrefixPattern", dform, negPrefixPattern); //$NON-NLS-1$ - setInternalField("negSuffixPattern", dform, negSuffixPattern); //$NON-NLS-1$ + setInternalField("posPrefixPattern", dform, posPrefixPattern); + setInternalField("posSuffixPattern", dform, posSuffixPattern); + setInternalField("negPrefixPattern", dform, negPrefixPattern); + setInternalField("negSuffixPattern", dform, negSuffixPattern); dform.setMultiplier(multiplier); dform.setGroupingSize(groupingSize); // BEGIN android-added @@ -1445,21 +1418,14 @@ public class DecimalFormat extends NumberFormat { dform.setMaximumFractionDigits(maximumFractionDigits); this.setParseBigDecimal(parseBigDecimal); - if (super.getMaximumIntegerDigits() > Integer.MAX_VALUE - || super.getMinimumIntegerDigits() > Integer.MAX_VALUE - || super.getMaximumFractionDigits() > Integer.MAX_VALUE - || super.getMinimumIntegerDigits() > Integer.MAX_VALUE) { - // text.09=The deserialized date is invalid - throw new InvalidObjectException(Messages.getString("text.09")); //$NON-NLS-1$ - } if (serialVersionOnStream < 3) { - setMaximumIntegerDigits(super.getMinimumIntegerDigits()); + setMaximumIntegerDigits(super.getMaximumIntegerDigits()); setMinimumIntegerDigits(super.getMinimumIntegerDigits()); setMaximumFractionDigits(super.getMaximumFractionDigits()); setMinimumFractionDigits(super.getMinimumFractionDigits()); } if (serialVersionOnStream < 1) { - this.setInternalField("useExponentialNotation", dform, //$NON-NLS-1$ + this.setInternalField("useExponentialNotation", dform, Boolean.FALSE); } serialVersionOnStream = 3; @@ -1473,10 +1439,16 @@ public class DecimalFormat extends NumberFormat { */ private void copySymbols(final com.ibm.icu4jni.text.DecimalFormatSymbols icu, final DecimalFormatSymbols dfs) { + Currency currency = dfs.getCurrency(); // BEGIN android-changed - icu.setCurrency(Currency.getInstance(dfs.getCurrency() - .getCurrencyCode())); + if (currency == null) { + icu.setCurrency(Currency.getInstance("XXX")); //$NON-NLS-1$ + } else { + icu.setCurrency(Currency.getInstance(dfs.getCurrency() + .getCurrencyCode())); + } // END android-changed + icu.setCurrencySymbol(dfs.getCurrencySymbol()); icu.setDecimalSeparator(dfs.getDecimalSeparator()); icu.setDigit(dfs.getDigit()); @@ -1518,31 +1490,4 @@ public class DecimalFormat extends NumberFormat { } }); } - - /* - * Gets private field value by reflection. - * - * @param fieldName the field name to be set @param target the object which - * field to be gotten - */ - private Object getInternalField(final String fieldName, final Object target) { - Object value = AccessController - .doPrivileged(new PrivilegedAction<Object>() { - public Object run() { - Object result = null; - java.lang.reflect.Field field = null; - try { - field = target.getClass().getDeclaredField( - fieldName); - field.setAccessible(true); - result = field.get(target); - } catch (Exception e1) { - return null; - } - return result; - } - }); - return value; - } - } diff --git a/text/src/main/java/java/text/DecimalFormatSymbols.java b/text/src/main/java/java/text/DecimalFormatSymbols.java index 3415ee8..a71a4c6 100644 --- a/text/src/main/java/java/text/DecimalFormatSymbols.java +++ b/text/src/main/java/java/text/DecimalFormatSymbols.java @@ -14,17 +14,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/** -******************************************************************************* -* Copyright (C) 1996-2007, International Business Machines Corporation and * -* others. All Rights Reserved. * -******************************************************************************* -*/ // BEGIN android-note -// The class javadoc and some of the method descriptions are copied from ICU4J -// source files. Changes have been made to the copied descriptions. -// The icu license header was added to this file. +// changed from ICU to resource bundles // END android-note package java.text; @@ -37,7 +29,9 @@ import java.io.Serializable; import java.util.Arrays; import java.util.Currency; import java.util.Locale; +// BEGIN android-added import java.util.ResourceBundle; +// END android-added /** * Encapsulates the set of symbols (such as the decimal separator, the grouping @@ -46,10 +40,9 @@ import java.util.ResourceBundle; * {@code DecimalFormatSymbols} from its locale data. If you need to change any * of these symbols, you can get the {@code DecimalFormatSymbols} object from * your {@code DecimalFormat} and modify it. - * + * * @see java.util.Locale * @see DecimalFormat - * @since Android 1.0 */ public final class DecimalFormatSymbols implements Cloneable, Serializable { @@ -73,8 +66,6 @@ public final class DecimalFormatSymbols implements Cloneable, Serializable { * the default locale. Best practice is to create a {@code DecimalFormat} * and then to get the {@code DecimalFormatSymbols} from that object by * calling {@link DecimalFormat#getDecimalFormatSymbols()}. - * - * @since Android 1.0 */ public DecimalFormatSymbols() { this(Locale.getDefault()); @@ -88,9 +79,9 @@ public final class DecimalFormatSymbols implements Cloneable, Serializable { * * @param locale * the locale. - * @since Android 1.0 */ public DecimalFormatSymbols(Locale locale) { + // BEGIN android-changed ResourceBundle bundle = Format.getBundle(locale); patternChars = bundle.getString("DecimalPatternChars").toCharArray(); //$NON-NLS-1$ infinity = bundle.getString("Infinity"); //$NON-NLS-1$ @@ -105,8 +96,10 @@ public final class DecimalFormatSymbols implements Cloneable, Serializable { currencySymbol = bundle.getString("CurrencySymbol"); //$NON-NLS-1$ intlCurrencySymbol = bundle.getString("IntCurrencySymbol"); //$NON-NLS-1$ } + // END android-changed } + /** * Returns a new {@code DecimalFormatSymbols} with the same symbols as this * {@code DecimalFormatSymbols}. @@ -114,7 +107,6 @@ public final class DecimalFormatSymbols implements Cloneable, Serializable { * @return a shallow copy of this {@code DecimalFormatSymbols}. * * @see java.lang.Cloneable - * @since Android 1.0 */ @Override public Object clone() { @@ -137,7 +129,6 @@ public final class DecimalFormatSymbols implements Cloneable, Serializable { * @return {@code true} if the specified object is equal to this * {@code DecimalFormatSymbols}; {@code false} otherwise. * @see #hashCode - * @since Android 1.0 */ @Override public boolean equals(Object object) { @@ -161,13 +152,12 @@ public final class DecimalFormatSymbols implements Cloneable, Serializable { * been previously called with a value that is not a valid ISO 4217 currency * code. * <p> - * + * * @return the currency that was set in the constructor or by calling * {@code setCurrency()} or {@code setInternationalCurrencySymbol()}, * or {@code null} if an invalid currency was set. * @see #setCurrency(Currency) * @see #setInternationalCurrencySymbol(String) - * @since Android 1.0 */ public Currency getCurrency() { return currency; @@ -177,7 +167,6 @@ public final class DecimalFormatSymbols implements Cloneable, Serializable { * Returns the international currency symbol. * * @return the international currency symbol as string. - * @since Android 1.0 */ public String getInternationalCurrencySymbol() { return intlCurrencySymbol; @@ -187,7 +176,6 @@ public final class DecimalFormatSymbols implements Cloneable, Serializable { * Returns the currency symbol. * * @return the currency symbol as string. - * @since Android 1.0 */ public String getCurrencySymbol() { return currencySymbol; @@ -197,7 +185,6 @@ public final class DecimalFormatSymbols implements Cloneable, Serializable { * Returns the character which represents the decimal point in a number. * * @return the decimal separator character. - * @since Android 1.0 */ public char getDecimalSeparator() { return patternChars[DecimalSeparator]; @@ -208,7 +195,6 @@ public final class DecimalFormatSymbols implements Cloneable, Serializable { * pattern. * * @return the digit pattern character. - * @since Android 1.0 */ public char getDigit() { return patternChars[Digit]; @@ -218,7 +204,6 @@ public final class DecimalFormatSymbols implements Cloneable, Serializable { * Returns the character used as the thousands separator in a number. * * @return the thousands separator character. - * @since Android 1.0 */ public char getGroupingSeparator() { return patternChars[GroupingSeparator]; @@ -228,7 +213,6 @@ public final class DecimalFormatSymbols implements Cloneable, Serializable { * Returns the string which represents infinity. * * @return the infinity symbol as a string. - * @since Android 1.0 */ public String getInfinity() { return infinity; @@ -238,7 +222,6 @@ public final class DecimalFormatSymbols implements Cloneable, Serializable { * Returns the minus sign character. * * @return the minus sign as a character. - * @since Android 1.0 */ public char getMinusSign() { return patternChars[MinusSign]; @@ -249,7 +232,6 @@ public final class DecimalFormatSymbols implements Cloneable, Serializable { * value. * * @return the monetary decimal point as a character. - * @since Android 1.0 */ public char getMonetaryDecimalSeparator() { return patternChars[MonetaryDecimalSeparator]; @@ -259,7 +241,6 @@ public final class DecimalFormatSymbols implements Cloneable, Serializable { * Returns the string which represents NaN. * * @return the symbol NaN as a string. - * @since Android 1.0 */ public String getNaN() { return NaN; @@ -270,7 +251,6 @@ public final class DecimalFormatSymbols implements Cloneable, Serializable { * in a format pattern. * * @return the pattern separator character. - * @since Android 1.0 */ public char getPatternSeparator() { return patternChars[PatternSeparator]; @@ -280,7 +260,6 @@ public final class DecimalFormatSymbols implements Cloneable, Serializable { * Returns the percent character. * * @return the percent character. - * @since Android 1.0 */ public char getPercent() { return patternChars[Percent]; @@ -290,7 +269,6 @@ public final class DecimalFormatSymbols implements Cloneable, Serializable { * Returns the per mill sign character. * * @return the per mill sign character. - * @since Android 1.0 */ public char getPerMill() { return patternChars[PerMill]; @@ -300,7 +278,6 @@ public final class DecimalFormatSymbols implements Cloneable, Serializable { * Returns the character which represents zero. * * @return the zero character. - * @since Android 1.0 */ public char getZeroDigit() { return patternChars[ZeroDigit]; @@ -331,7 +308,6 @@ public final class DecimalFormatSymbols implements Cloneable, Serializable { * the new currency. * @throws NullPointerException * if {@code currency} is {@code null}. - * @since Android 1.0 */ public void setCurrency(Currency currency) { if (currency == null) { @@ -355,7 +331,6 @@ public final class DecimalFormatSymbols implements Cloneable, Serializable { * * @param value * the currency code. - * @since Android 1.0 */ public void setInternationalCurrencySymbol(String value) { if (value == null) { @@ -382,7 +357,6 @@ public final class DecimalFormatSymbols implements Cloneable, Serializable { * * @param value * the currency symbol. - * @since Android 1.0 */ public void setCurrencySymbol(String value) { currencySymbol = value; @@ -393,7 +367,6 @@ public final class DecimalFormatSymbols implements Cloneable, Serializable { * * @param value * the decimal separator character. - * @since Android 1.0 */ public void setDecimalSeparator(char value) { patternChars[DecimalSeparator] = value; @@ -404,7 +377,6 @@ public final class DecimalFormatSymbols implements Cloneable, Serializable { * * @param value * the digit character. - * @since Android 1.0 */ public void setDigit(char value) { patternChars[Digit] = value; @@ -415,7 +387,6 @@ public final class DecimalFormatSymbols implements Cloneable, Serializable { * * @param value * the grouping separator character. - * @since Android 1.0 */ public void setGroupingSeparator(char value) { patternChars[GroupingSeparator] = value; @@ -426,7 +397,6 @@ public final class DecimalFormatSymbols implements Cloneable, Serializable { * * @param value * the string representing infinity. - * @since Android 1.0 */ public void setInfinity(String value) { infinity = value; @@ -437,7 +407,6 @@ public final class DecimalFormatSymbols implements Cloneable, Serializable { * * @param value * the minus sign character. - * @since Android 1.0 */ public void setMinusSign(char value) { patternChars[MinusSign] = value; @@ -449,7 +418,6 @@ public final class DecimalFormatSymbols implements Cloneable, Serializable { * * @param value * the monetary decimal separator character. - * @since Android 1.0 */ public void setMonetaryDecimalSeparator(char value) { patternChars[MonetaryDecimalSeparator] = value; @@ -460,7 +428,6 @@ public final class DecimalFormatSymbols implements Cloneable, Serializable { * * @param value * the string representing NaN. - * @since Android 1.0 */ public void setNaN(String value) { NaN = value; @@ -472,7 +439,6 @@ public final class DecimalFormatSymbols implements Cloneable, Serializable { * * @param value * the pattern separator character. - * @since Android 1.0 */ public void setPatternSeparator(char value) { patternChars[PatternSeparator] = value; @@ -483,7 +449,6 @@ public final class DecimalFormatSymbols implements Cloneable, Serializable { * * @param value * the percent character. - * @since Android 1.0 */ public void setPercent(char value) { patternChars[Percent] = value; @@ -494,7 +459,6 @@ public final class DecimalFormatSymbols implements Cloneable, Serializable { * * @param value * the per mill character. - * @since Android 1.0 */ public void setPerMill(char value) { patternChars[PerMill] = value; @@ -505,7 +469,6 @@ public final class DecimalFormatSymbols implements Cloneable, Serializable { * * @param value * the zero digit character. - * @since Android 1.0 */ public void setZeroDigit(char value) { patternChars[ZeroDigit] = value; @@ -588,4 +551,14 @@ public final class DecimalFormatSymbols implements Cloneable, Serializable { currency = null; } } + + Locale getLocale(){ + return locale; + } + + // BEGIN android-removed + // com.ibm.icu4jni.text.DecimalFormatSymbols getIcuSymbols() { + // return icuSymbols; + // } + // END android-removed } diff --git a/text/src/main/java/java/text/FieldPosition.java b/text/src/main/java/java/text/FieldPosition.java index 4cf985d..d2da297 100644 --- a/text/src/main/java/java/text/FieldPosition.java +++ b/text/src/main/java/java/text/FieldPosition.java @@ -25,13 +25,9 @@ package java.text; * A {@code FieldPosition} can be created by using the integer constants in the * various format classes (for example {@code NumberFormat.INTEGER_FIELD}) or * one of the fields of type {@code Format.Field}. - * </p> * <p> * If more than one field information is needed, the method * {@link NumberFormat#formatToCharacterIterator(Object)} should be used. - * </p> - * - * @since Android 1.0 */ public class FieldPosition { @@ -44,7 +40,6 @@ public class FieldPosition { * * @param field * the field to identify. - * @since Android 1.0 */ public FieldPosition(int field) { myField = field; @@ -56,7 +51,6 @@ public class FieldPosition { * * @param attribute * the field attribute to identify. - * @since Android 1.0 */ public FieldPosition(Format.Field attribute) { myAttribute = attribute; @@ -71,7 +65,6 @@ public class FieldPosition { * the field attribute to identify. * @param field * the field to identify. - * @since Android 1.0 */ public FieldPosition(Format.Field attribute, int field) { myAttribute = attribute; @@ -92,7 +85,6 @@ public class FieldPosition { * @return {@code true} if the specified object is equal to this field * position; {@code false} otherwise. * @see #hashCode - * @since Android 1.0 */ @Override public boolean equals(Object object) { @@ -108,7 +100,6 @@ public class FieldPosition { * Returns the index of the beginning of the field. * * @return the first index of the field. - * @since Android 1.0 */ public int getBeginIndex() { return beginIndex; @@ -118,7 +109,6 @@ public class FieldPosition { * Returns the index one past the end of the field. * * @return one past the index of the last character in the field. - * @since Android 1.0 */ public int getEndIndex() { return endIndex; @@ -128,7 +118,6 @@ public class FieldPosition { * Returns the field which is being identified. * * @return the field constant. - * @since Android 1.0 */ public int getField() { return myField; @@ -138,7 +127,6 @@ public class FieldPosition { * Returns the attribute which is being identified. * * @return the field. - * @since Android 1.0 */ public Format.Field getFieldAttribute() { return myAttribute; @@ -155,7 +143,6 @@ public class FieldPosition { * * @param index * the index of the first character in the field. - * @since Android 1.0 */ public void setBeginIndex(int index) { beginIndex = index; @@ -166,7 +153,6 @@ public class FieldPosition { * * @param index * one past the index of the last character in the field. - * @since Android 1.0 */ public void setEndIndex(int index) { endIndex = index; @@ -176,7 +162,6 @@ public class FieldPosition { * Returns the string representation of this field position. * * @return the string representation of this field position. - * @since Android 1.0 */ @Override public String toString() { diff --git a/text/src/main/java/java/text/Format.java b/text/src/main/java/java/text/Format.java index 5e31cd4..6ee1ba2 100644 --- a/text/src/main/java/java/text/Format.java +++ b/text/src/main/java/java/text/Format.java @@ -14,26 +14,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/** -******************************************************************************* -* Copyright (C) 1996-2007, International Business Machines Corporation and * -* others. All Rights Reserved. * -******************************************************************************* -*/ - -// BEGIN android-note -// The class javadoc and some of the method descriptions are copied from ICU4J -// source files. Changes have been made to the copied descriptions. -// The icu license header was added to this file. -// END android-note package java.text; import java.io.Serializable; import java.security.AccessController; import java.security.PrivilegedAction; +// BEGIN android-added import java.util.Locale; import java.util.ResourceBundle; +// END android-added import org.apache.harmony.text.internal.nls.Messages; @@ -49,7 +39,6 @@ import org.apache.harmony.text.internal.nls.Messages; * A date and time formatter like {@code SimpleDateFormat} may represent a * specific date, encoded numerically, as a string such as "Wednesday, February * 26, 1997 AD". - * </p> * <p> * Many of the concrete subclasses of {@code Format} employ the notion of a * pattern. A pattern is a string representation of the rules which govern the @@ -60,7 +49,6 @@ import org.apache.harmony.text.internal.nls.Messages; * of a pattern is defined by each subclass. Even though many subclasses use * patterns, the notion of a pattern is not inherent to {@code Format} classes * in general, and is not part of the explicit base class protocol. - * </p> * <p> * Two complex formatting classes are worth mentioning: {@code MessageFormat} * and {@code ChoiceFormat}. {@code ChoiceFormat} is a subclass of @@ -73,9 +61,6 @@ import org.apache.harmony.text.internal.nls.Messages; * 27, 1997." given the arguments 0, "MyDisk", and the date value of 2/27/97. * See the {@link ChoiceFormat} and {@link MessageFormat} descriptions for * further information. - * </p> - * - * @since Android 1.0 */ public abstract class Format implements Serializable, Cloneable { @@ -83,8 +68,6 @@ public abstract class Format implements Serializable, Cloneable { /** * Constructs a new {@code Format} instance. - * - * @since Android 1.0 */ public Format() { } @@ -95,7 +78,6 @@ public abstract class Format implements Serializable, Cloneable { * @return a shallow copy of this format. * * @see java.lang.Cloneable - * @since Android 1.0 */ @Override public Object clone() { @@ -106,6 +88,7 @@ public abstract class Format implements Serializable, Cloneable { } } + // BEGIN android-added static ResourceBundle getBundle(final Locale locale) { return AccessController .doPrivileged(new PrivilegedAction<ResourceBundle>() { @@ -116,6 +99,7 @@ public abstract class Format implements Serializable, Cloneable { } }); } + // END android-added String convertPattern(String template, String fromChars, String toChars, boolean check) { @@ -156,9 +140,8 @@ public abstract class Format implements Serializable, Cloneable { * @param object * the object to format. * @return the formatted string. - * @exception IllegalArgumentException - * if the object cannot be formatted by this format. - * @since Android 1.0 + * @throws IllegalArgumentException + * if the object cannot be formatted by this format. */ public final String format(Object object) { return format(object, new StringBuffer(), new FieldPosition(0)) @@ -173,8 +156,7 @@ public abstract class Format implements Serializable, Cloneable { * member contains an enum value specifying a field on input, then its * {@code beginIndex} and {@code endIndex} members will be updated with the * text offset of the first occurrence of this field in the formatted text. - * </p> - * + * * @param object * the object to format. * @param buffer @@ -183,9 +165,8 @@ public abstract class Format implements Serializable, Cloneable { * on input: an optional alignment field; on output: the offsets * of the alignment field in the formatted text. * @return the string buffer. - * @exception IllegalArgumentException - * if the object cannot be formatted by this format. - * @since Android 1.0 + * @throws IllegalArgumentException + * if the object cannot be formatted by this format. */ public abstract StringBuffer format(Object object, StringBuffer buffer, FieldPosition field); @@ -197,15 +178,13 @@ public abstract class Format implements Serializable, Cloneable { * <p> * Subclasses should return an {@code AttributedCharacterIterator} with the * appropriate attributes. - * </p> - * + * * @param object * the object to format. * @return an {@code AttributedCharacterIterator} with the formatted object * and attributes. - * @exception IllegalArgumentException - * if the object cannot be formatted by this format. - * @since Android 1.0 + * @throws IllegalArgumentException + * if the object cannot be formatted by this format. */ public AttributedCharacterIterator formatToCharacterIterator(Object object) { return new AttributedString(format(object)).getIterator(); @@ -217,9 +196,8 @@ public abstract class Format implements Serializable, Cloneable { * @param string * the string to parse. * @return the object resulting from the parse. - * @exception ParseException - * if an error occurs during parsing. - * @since Android 1.0 + * @throws ParseException + * if an error occurs during parsing. */ public Object parseObject(String string) throws ParseException { ParsePosition position = new ParsePosition(0); @@ -247,10 +225,35 @@ public abstract class Format implements Serializable, Cloneable { * set to the index where the error occurred. * @return the object resulting from the parse or {@code null} if there is * an error. - * @since Android 1.0 */ public abstract Object parseObject(String string, ParsePosition position); + /* + * Gets private field value by reflection. + * + * @param fieldName the field name to be set @param target the object which + * field to be gotten + */ + static Object getInternalField(final String fieldName, final Object target) { + Object value = AccessController + .doPrivileged(new PrivilegedAction<Object>() { + public Object run() { + Object result = null; + java.lang.reflect.Field field = null; + try { + field = target.getClass().getDeclaredField( + fieldName); + field.setAccessible(true); + result = field.get(target); + } catch (Exception e1) { + return null; + } + return result; + } + }); + return value; + } + static boolean upTo(String string, ParsePosition position, StringBuffer buffer, char stop) { int index = position.getIndex(), length = string.length(); @@ -307,8 +310,6 @@ public abstract class Format implements Serializable, Cloneable { * {@code AttributedCharacterIterator} that the * {@code formatToCharacterIterator()} method returns in {@code Format} * subclasses. - * - * @since Android 1.0 */ public static class Field extends AttributedCharacterIterator.Attribute { @@ -316,10 +317,9 @@ public abstract class Format implements Serializable, Cloneable { /** * Constructs a new instance of {@code Field} with the given field name. - * + * * @param fieldName * the field name. - * @since Android 1.0 */ protected Field(String fieldName) { super(fieldName); diff --git a/text/src/main/java/java/text/MessageFormat.java b/text/src/main/java/java/text/MessageFormat.java index 6405b6c..4ab1ade 100644 --- a/text/src/main/java/java/text/MessageFormat.java +++ b/text/src/main/java/java/text/MessageFormat.java @@ -14,18 +14,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/** -******************************************************************************* -* Copyright (C) 1996-2007, International Business Machines Corporation and * -* others. All Rights Reserved. * -******************************************************************************* -*/ - -// BEGIN android-note -// The class javadoc and some of the method descriptions are copied from ICU4J -// source files. Changes have been made to the copied descriptions. -// The icu license header was added to this file. -// END android-note package java.text; @@ -44,12 +32,11 @@ import org.apache.harmony.text.internal.nls.Messages; /** * Produces concatenated - * messages in language-neutral way. Use this class to construct messages + * messages in language-neutral way. Use this class to construct messages * displayed for end users. * <p> * {@code MessageFormat} takes a set of objects, formats them and then * inserts the formatted strings into the pattern at the appropriate places. - * </p> * <p> * <strong>Note:</strong> {@code MessageFormat} differs from the other * {@code Format} classes in that you create a {@code MessageFormat} @@ -58,12 +45,12 @@ import org.apache.harmony.text.internal.nls.Messages; * {@code MessageFormat} itself doesn't implement locale specific * behavior. Any locale specific behavior is defined by the pattern that you * provide as well as the subformats used for inserted arguments. - * + * * <h4><a name="patterns">Patterns and their interpretation</a></h4> - * + * * {@code MessageFormat} uses patterns of the following form: * <blockquote> - * + * * <pre> * <i>MessageFormatPattern:</i> * <i>String</i> @@ -97,9 +84,9 @@ import org.apache.harmony.text.internal.nls.Messages; * ' <i>QuotedPattern</i> ' * <i>UnquotedPattern</i> * </pre> - * + * * </blockquote> - * + * * <p> * Within a <i>String</i>, {@code "''"} represents a single quote. A * <i>QuotedString</i> can contain arbitrary characters except single quotes; @@ -118,7 +105,6 @@ import org.apache.harmony.text.internal.nls.Messages; * {@code "ab {0} de"} and {@code "ab '}' de"} are valid subformat * patterns, but {@code "ab {0'}' de"} and {@code "ab } de"} are * not. - * </p> * <dl> * <dt><b>Warning:</b></dt> * <dd>The rules for using quotes within message format patterns unfortunately @@ -233,11 +219,11 @@ import org.apache.harmony.text.internal.nls.Messages; * <td>{@code new ChoiceFormat(subformatPattern)}</td> * </tr> * </table> - * + * * <h4>Usage Information</h4> * <p> * Here are some examples of usage: <blockquote> - * + * * <pre> * Object[] arguments = { * new Integer(7), new Date(System.currentTimeMillis()), @@ -250,15 +236,14 @@ import org.apache.harmony.text.internal.nls.Messages; * </em> * At 12:30 PM on Jul 3, 2053, there was a disturbance in the Force on planet 7. * </pre> - * - * </blockquote> + * + * </blockquote> * <p> * Typically, the message format will come from resources, and the * arguments will be dynamically set at runtime. - * </p> * <p> * Example 2: <blockquote> - * + * * <pre> * Object[] testArgs = {new Long(3), "MyDisk"}; * MessageFormat form = new MessageFormat("The disk \"{1}\" contains {0} file(s)."); @@ -270,15 +255,14 @@ import org.apache.harmony.text.internal.nls.Messages; * The disk "MyDisk" contains 1 file(s). * The disk "MyDisk" contains 1,273 file(s). * </pre> - * + * * </blockquote> - * + * * <p> * For more sophisticated patterns, you can use a {@code ChoiceFormat} to - * get output such as: - * </p> + * get output such as: * <blockquote> - * + * * <pre> * MessageFormat form = new MessageFormat("The disk \"{1}\" contains {0}."); * double[] filelimits = {0,1,2}; @@ -294,15 +278,15 @@ import org.apache.harmony.text.internal.nls.Messages; * The disk "MyDisk" contains one file. * The disk "MyDisk" contains 1,273 files. * </pre> - * + * * </blockquote> You can either do this programmatically, as in the above * example, or by using a pattern (see {@link ChoiceFormat} for more * information) as in: <blockquote> - * + * * <pre> * form.applyPattern("There {0,choice,0#are no files|1#is one file|1<are {0,number,integer} files}."); * </pre> - * + * * </blockquote> * <p> * <strong>Note:</strong> As we see above, the string produced by a @@ -312,11 +296,9 @@ import org.apache.harmony.text.internal.nls.Messages; * {@code ChoiceFormat} programmatically (instead of using the string * patterns), then be careful not to produce a format that recurses on itself, * which will cause an infinite loop. - * </p> * <p> * When a single argument is parsed more than once in the string, the last match * will be the final result of the parsing. For example: - * </p> * <blockquote> * <pre> * MessageFormat mf = new MessageFormat("{0,number,#.##}, {0,number,#.#}"); @@ -329,10 +311,9 @@ import org.apache.harmony.text.internal.nls.Messages; * </pre> * </blockquote> * <p> - * Likewise, parsing with a {@code MessageFormat} object using patterns - * containing multiple occurrences of the same argument would return the last + * Likewise, parsing with a {@code MessageFormat} object using patterns + * containing multiple occurrences of the same argument would return the last * match. For example: - * </p> * <blockquote> * <pre> * MessageFormat mf = new MessageFormat("{0}, {0}, {0}"); @@ -346,14 +327,12 @@ import org.apache.harmony.text.internal.nls.Messages; * Message formats are not synchronized. It is recommended to create separate * format instances for each thread. If multiple threads access a format * concurrently, it must be synchronized externally. - * </p> - * + * * @see java.util.Locale * @see Format * @see NumberFormat * @see DecimalFormat * @see ChoiceFormat - * @since Android 1.0 */ public class MessageFormat extends Format { @@ -379,9 +358,8 @@ public class MessageFormat extends Format { * the pattern. * @param locale * the locale. - * @exception IllegalArgumentException - * if the pattern cannot be parsed. - * @since Android 1.0 + * @throws IllegalArgumentException + * if the pattern cannot be parsed. */ public MessageFormat(String template, Locale locale) { this.locale = locale; @@ -394,9 +372,8 @@ public class MessageFormat extends Format { * * @param template * the pattern. - * @exception IllegalArgumentException - * if the pattern cannot be parsed. - * @since Android 1.0 + * @throws IllegalArgumentException + * if the pattern cannot be parsed. */ public MessageFormat(String template) { applyPattern(template); @@ -407,9 +384,8 @@ public class MessageFormat extends Format { * * @param template * the new pattern. - * @exception IllegalArgumentException - * if the pattern cannot be parsed. - * @since Android 1.0 + * @throws IllegalArgumentException + * if the pattern cannot be parsed. */ public void applyPattern(String template) { int length = template.length(); @@ -422,15 +398,31 @@ public class MessageFormat extends Format { Vector<Format> localFormats = new Vector<Format>(); while (position.getIndex() < length) { if (Format.upTo(template, position, buffer, '{')) { - byte arg; + int arg = 0; int offset = position.getIndex(); - if (offset >= length - || (arg = (byte) Character.digit(template - .charAt(offset++), 10)) == -1) { + if (offset >= length) { // text.19=Invalid argument number throw new IllegalArgumentException(Messages .getString("text.19")); //$NON-NLS-1$ } + // Get argument number + char ch; + while ((ch = template.charAt(offset++)) != '}' && ch != ',') { + if (ch < '0' && ch > '9') { + // text.19=Invalid argument number + throw new IllegalArgumentException(Messages + .getString("text.19")); //$NON-NLS-1$ + } + + arg = arg * 10 + (ch - '0'); + + if (arg < 0 || offset >= length) { + // text.19=Invalid argument number + throw new IllegalArgumentException(Messages + .getString("text.19")); //$NON-NLS-1$ + } + } + offset--; position.setIndex(offset); localFormats.addElement(parseVariable(template, position)); if (argCount >= args.length) { @@ -465,7 +457,6 @@ public class MessageFormat extends Format { * * @return a shallow copy of this {@code MessageFormat}. * @see java.lang.Cloneable - * @since Android 1.0 */ @Override public Object clone() { @@ -490,7 +481,6 @@ public class MessageFormat extends Format { * @return {@code true} if the specified object is equal to this * {@code MessageFormat}; {@code false} otherwise. * @see #hashCode - * @since Android 1.0 */ @Override public boolean equals(Object object) { @@ -526,10 +516,9 @@ public class MessageFormat extends Format { * the object to format. * @return an {@code AttributedCharacterIterator} with the formatted message and * attributes. - * @exception IllegalArgumentException - * if the arguments in the object array cannot be formatted - * by this message format. - * @since Android 1.0 + * @throws IllegalArgumentException + * if the arguments in the object array cannot be formatted + * by this message format. */ @Override public AttributedCharacterIterator formatToCharacterIterator(Object object) { @@ -564,8 +553,7 @@ public class MessageFormat extends Format { * {@code MessageFormat.Field.ARGUMENT}, then the begin and end index of * this field position is set to the location of the first occurrence of a * message format argument. Otherwise, the {@code FieldPosition} is ignored. - * </p> - * + * * @param objects * the array of objects to format. * @param buffer @@ -574,7 +562,6 @@ public class MessageFormat extends Format { * on input: an optional alignment field; on output: the offsets * of the alignment field in the formatted text. * @return the string buffer. - * @since Android 1.0 */ public final StringBuffer format(Object[] objects, StringBuffer buffer, FieldPosition field) { @@ -723,18 +710,16 @@ public class MessageFormat extends Format { * {@code MessageFormat.Field.ARGUMENT}, then the begin and end index of * this field position is set to the location of the first occurrence of a * message format argument. Otherwise, the {@code FieldPosition} is ignored. - * </p> * <p> * Calling this method is equivalent to calling - * </p> * <blockquote> * * <pre> * format((Object[])object, buffer, field) * </pre> - * + * * </blockquote> - * + * * @param object * the object to format, must be an array of {@code Object}. * @param buffer @@ -745,7 +730,6 @@ public class MessageFormat extends Format { * @return the string buffer. * @throws ClassCastException * if {@code object} is not an array of {@code Object}. - * @since Android 1.0 */ @Override public final StringBuffer format(Object object, StringBuffer buffer, @@ -761,22 +745,26 @@ public class MessageFormat extends Format { * @param objects * the array of objects to format. * @return the formatted result. - * @exception IllegalArgumentException - * if the pattern cannot be parsed. - * @since Android 1.0 + * @throws IllegalArgumentException + * if the pattern cannot be parsed. */ public static String format(String template, Object... objects) { - // BEGIN android-note - // changed parameter type from array to varargs. - // END android-note + if (objects != null) { + for (int i = 0; i < objects.length; i++) { + if (objects[i] == null) { + objects[i] = "null"; + } + } + } + // BEGIN android-changed return new MessageFormat(template).format(objects); + // END android-changed } /** * Returns the {@code Format} instances used by this message format. * * @return an array of {@code Format} instances. - * @since Android 1.0 */ public Format[] getFormats() { return formats.clone(); @@ -788,7 +776,6 @@ public class MessageFormat extends Format { * of the last one. * * @return an array of formats, ordered by argument index. - * @since Android 1.0 */ public Format[] getFormatsByArgumentIndex() { Format[] answer = new Format[maxArgumentIndex + 1]; @@ -806,7 +793,6 @@ public class MessageFormat extends Format { * the index of the format to set. * @param format * the format that will be set at index {@code argIndex}. - * @since Android 1.0 */ public void setFormatByArgumentIndex(int argIndex, Format format) { for (int i = 0; i < maxOffset + 1; i++) { @@ -822,7 +808,6 @@ public class MessageFormat extends Format { * * @param formats * the formats in an array. - * @since Android 1.0 */ public void setFormatsByArgumentIndex(Format[] formats) { for (int j = 0; j < formats.length; j++) { @@ -838,7 +823,6 @@ public class MessageFormat extends Format { * Returns the locale used when creating formats. * * @return the locale used to create formats. - * @since Android 1.0 */ public Locale getLocale() { return locale; @@ -869,9 +853,8 @@ public class MessageFormat extends Format { * @param string * the string to parse. * @return the array of {@code Object} arguments resulting from the parse. - * @exception ParseException - * if an error occurs during parsing. - * @since Android 1.0 + * @throws ParseException + * if an error occurs during parsing. */ public Object[] parse(String string) throws ParseException { ParsePosition position = new ParsePosition(0); @@ -900,7 +883,6 @@ public class MessageFormat extends Format { * set to the index where the error occurred. * @return the array of objects resulting from the parse, or {@code null} if * there is an error. - * @since Android 1.0 */ public Object[] parse(String string, ParsePosition position) { if (string == null) { @@ -972,7 +954,6 @@ public class MessageFormat extends Format { * set to the index where the error occurred. * @return the array of objects resulting from the parse, or {@code null} if * there is an error. - * @since Android 1.0 */ @Override public Object parseObject(String string, ParsePosition position) { @@ -1096,7 +1077,6 @@ public class MessageFormat extends Format { * the index of the format to change. * @param format * the {@code Format} that replaces the old format. - * @since Android 1.0 */ public void setFormat(int offset, Format format) { formats[offset] = format; @@ -1107,7 +1087,6 @@ public class MessageFormat extends Format { * * @param formats * an array of {@code Format}. - * @since Android 1.0 */ public void setFormats(Format[] formats) { int min = this.formats.length; @@ -1126,7 +1105,6 @@ public class MessageFormat extends Format { * * @param locale * the new locale. - * @since Android 1.0 */ public void setLocale(Locale locale) { this.locale = locale; @@ -1216,7 +1194,6 @@ public class MessageFormat extends Format { * Returns the pattern of this message format. * * @return the pattern. - * @since Android 1.0 */ public String toPattern() { StringBuffer buffer = new StringBuffer(); @@ -1302,7 +1279,7 @@ public class MessageFormat extends Format { int offset = 0; int offsetsLength = maxOffset + 1; int[] offsets = new int[offsetsLength]; - StringBuffer pattern = new StringBuffer(); + StringBuilder pattern = new StringBuilder(); for (int i = 0; i <= maxOffset; i++) { offset += strings[i].length(); offsets[i] = offset; @@ -1351,32 +1328,22 @@ public class MessageFormat extends Format { * <p> * There is no public constructor in this class, the only instances are the * constants defined here. - * </p> - * - * @since Android 1.0 */ public static class Field extends Format.Field { private static final long serialVersionUID = 7899943957617360810L; - // BEGIN android-removed - // public static final Field ARGUMENT = new Field("message argument field"); //$NON-NLS-1$ - // END android-removed - /** * This constant stands for the message argument. - * - * @since Android 1.0 */ public static final Field ARGUMENT = new Field("message argument field"); //$NON-NLS-1$ /** * Constructs a new instance of {@code MessageFormat.Field} with the * given field name. - * + * * @param fieldName * the field name. - * @since Android 1.0 */ protected Field(String fieldName) { super(fieldName); @@ -1385,7 +1352,7 @@ public class MessageFormat extends Format { /** * Resolves instances that are deserialized to the constant * {@code MessageFormat.Field} values. - * + * * @return the resolved field object. * @throws InvalidObjectException * if an error occurs while resolving the field object. diff --git a/text/src/main/java/java/text/NumberFormat.java b/text/src/main/java/java/text/NumberFormat.java index 7510240..5b8d883 100644 --- a/text/src/main/java/java/text/NumberFormat.java +++ b/text/src/main/java/java/text/NumberFormat.java @@ -14,17 +14,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/** -******************************************************************************* -* Copyright (C) 1996-2007, International Business Machines Corporation and * -* others. All Rights Reserved. * -******************************************************************************* -*/ // BEGIN android-note -// The class javadoc and some of the method descriptions are copied from ICU4J -// source files. Changes have been made to the copied descriptions. -// The icu license header was added to this file. +// changed from ICU to resource bundles // END android-note package java.text; @@ -36,7 +28,9 @@ import java.io.ObjectOutputStream; import java.io.ObjectStreamField; import java.util.Currency; import java.util.Locale; +// BEGIN android-added import java.util.ResourceBundle; +// END android-added import org.apache.harmony.text.internal.nls.Messages; @@ -50,53 +44,48 @@ import org.apache.harmony.text.internal.nls.Messages; * Your code can be completely independent of the locale conventions for decimal * points, thousands-separators, or even the particular decimal digits used, or * whether the number format is even decimal. - * </p> * <p> * To format a number for the current locale, use one of the factory class * methods: - * </p> * <blockquote> - * + * * <pre> * myString = NumberFormat.getInstance().format(myNumber); * </pre> - * + * * </blockquote> * <p> * If you are formatting multiple numbers, it is more efficient to get the * format and use it multiple times so that the system doesn't have to fetch the * information about the local language and country conventions multiple times. - * </p> * <blockquote> - * + * * <pre> * NumberFormat nf = NumberFormat.getInstance(); * for (int i = 0; i < a.length; ++i) { * output.println(nf.format(myNumber[i]) + "; "); * } * </pre> - * + * * </blockquote> * <p> * To format a number for a different locale, specify it in the call to * {@code getInstance}. - * </p> * <blockquote> - * + * * <pre> * NumberFormat nf = NumberFormat.getInstance(Locale.FRENCH); * </pre> - * + * * </blockquote> * <p> * You can also use a {@code NumberFormat} to parse numbers: - * </p> * <blockquote> - * + * * <pre> * myNumber = nf.parse(myString); * </pre> - * + * * </blockquote> * <p> * Use {@code getInstance} or {@code getNumberInstance} to get the normal number @@ -104,7 +93,6 @@ import org.apache.harmony.text.internal.nls.Messages; * {@code getCurrencyInstance} to get the currency number format and use * {@code getPercentInstance} to get a format for displaying percentages. With * this format, a fraction like 0.53 is displayed as 53%. - * </p> * <p> * You can also control the display of numbers with methods such as * {@code setMinimumFractionDigits}. If you want even more control over the @@ -113,7 +101,6 @@ import org.apache.harmony.text.internal.nls.Messages; * {@code DecimalFormat}. This will work for the vast majority of locales; just * remember to put it in a {@code try} block in case you encounter an unusual * one. - * </p> * <p> * {@code NumberFormat} is designed such that some controls work for formatting * and others work for parsing. For example, {@code setParseIntegerOnly} only @@ -121,7 +108,6 @@ import org.apache.harmony.text.internal.nls.Messages; * leaves the parse position just after '6'); if set to {@code false}, * "3456.78" is parsed as 3456.78 (and leaves the parse position just after * '8'). This is independent of formatting. - * </p> * <p> * You can also use forms of the {@code parse} and {@code format} methods with * {@code ParsePosition} and {@code FieldPosition} to allow you to: @@ -155,11 +141,9 @@ import org.apache.harmony.text.internal.nls.Messages; * and the {@code NumberFormat} API is essentially an abstraction of * {@code DecimalFormat's} API. Refer to {@code DecimalFormat} for more * information about this API. - * </p> - * + * * @see DecimalFormat * @see java.text.ChoiceFormat - * @since Android 1.0 */ public abstract class NumberFormat extends Format { @@ -167,15 +151,11 @@ public abstract class NumberFormat extends Format { /** * Field constant identifying the integer part of a number. - * - * @since Android 1.0 */ public static final int INTEGER_FIELD = 0; /** * Field constant identifying the fractional part of a number. - * - * @since Android 1.0 */ public static final int FRACTION_FIELD = 1; @@ -186,8 +166,6 @@ public abstract class NumberFormat extends Format { /** * Constructs a new instance of {@code NumberFormat}. - * - * @since Android 1.0 */ public NumberFormat() { } @@ -198,7 +176,6 @@ public abstract class NumberFormat extends Format { * * @return a shallow copy of this {@code NumberFormat}. * @see java.lang.Cloneable - * @since Android 1.0 */ @Override public Object clone() { @@ -215,7 +192,6 @@ public abstract class NumberFormat extends Format { * @return {@code true} if the specified object is equal to this number * format; {@code false} otherwise. * @see #hashCode - * @since Android 1.0 */ @Override public boolean equals(Object object) { @@ -240,7 +216,6 @@ public abstract class NumberFormat extends Format { * @param value * the double to format. * @return the formatted string. - * @since Android 1.0 */ public final String format(double value) { return format(value, new StringBuffer(), new FieldPosition(0)) @@ -255,8 +230,7 @@ public abstract class NumberFormat extends Format { * specifying a format field, then its {@code beginIndex} and * {@code endIndex} members will be updated with the position of the first * occurrence of this field in the formatted text. - * </p> - * + * * @param value * the double to format. * @param buffer @@ -266,7 +240,6 @@ public abstract class NumberFormat extends Format { * on input: an optional alignment field; on output: the offsets * of the alignment field in the formatted text. * @return the string buffer. - * @since Android 1.0 */ public abstract StringBuffer format(double value, StringBuffer buffer, FieldPosition field); @@ -277,7 +250,6 @@ public abstract class NumberFormat extends Format { * @param value * the long to format. * @return the formatted string. - * @since Android 1.0 */ public final String format(long value) { return format(value, new StringBuffer(), new FieldPosition(0)) @@ -292,8 +264,7 @@ public abstract class NumberFormat extends Format { * specifying a format field, then its {@code beginIndex} and * {@code endIndex} members will be updated with the position of the first * occurrence of this field in the formatted text. - * </p> - * + * * @param value * the long to format. * @param buffer @@ -303,7 +274,6 @@ public abstract class NumberFormat extends Format { * on input: an optional alignment field; on output: the offsets * of the alignment field in the formatted text. * @return the string buffer. - * @since Android 1.0 */ public abstract StringBuffer format(long value, StringBuffer buffer, FieldPosition field); @@ -316,8 +286,7 @@ public abstract class NumberFormat extends Format { * a format field, then its {@code beginIndex} and {@code endIndex} members * will be updated with the position of the first occurrence of this field * in the formatted text. - * </p> - * + * * @param object * the object to format, must be a {@code Number}. * @param buffer @@ -328,7 +297,6 @@ public abstract class NumberFormat extends Format { * @return the string buffer. * @throws IllegalArgumentException * if {@code object} is not an instance of {@code Number}. - * @since Android 1.0 */ @Override public StringBuffer format(Object object, StringBuffer buffer, @@ -348,7 +316,6 @@ public abstract class NumberFormat extends Format { * Gets the list of installed locales which support {@code NumberFormat}. * * @return an array of locales. - * @since Android 1.0 */ public static Locale[] getAvailableLocales() { return Locale.getAvailableLocales(); @@ -365,7 +332,6 @@ public abstract class NumberFormat extends Format { * @return the currency that was set in getInstance() or in setCurrency(), * or {@code null}. * @throws UnsupportedOperationException - * @since Android 1.0 */ public Currency getCurrency() { throw new UnsupportedOperationException(); @@ -376,7 +342,6 @@ public abstract class NumberFormat extends Format { * for the default locale. * * @return a {@code NumberFormat} for handling currency values. - * @since Android 1.0 */ public final static NumberFormat getCurrencyInstance() { return getCurrencyInstance(Locale.getDefault()); @@ -389,10 +354,11 @@ public abstract class NumberFormat extends Format { * @param locale * the locale to use. * @return a {@code NumberFormat} for handling currency values. - * @since Android 1.0 */ public static NumberFormat getCurrencyInstance(Locale locale) { + // BEGIN android-changed return getInstance(locale, "Currency"); //$NON-NLS-1$ + // END android-changed } /** @@ -400,7 +366,6 @@ public abstract class NumberFormat extends Format { * default locale. * * @return a {@code NumberFormat} for handling integers. - * @since Android 1.0 */ public final static NumberFormat getIntegerInstance() { return getIntegerInstance(Locale.getDefault()); @@ -413,12 +378,13 @@ public abstract class NumberFormat extends Format { * @param locale * the locale to use. * @return a {@code NumberFormat} for handling integers. - * @since Android 1.0 */ public static NumberFormat getIntegerInstance(Locale locale) { + // BEGIN android-changed NumberFormat format = getInstance(locale, "Integer"); //$NON-NLS-1$ format.setParseIntegerOnly(true); return format; + // END android-changed } /** @@ -426,7 +392,6 @@ public abstract class NumberFormat extends Format { * default locale. * * @return a {@code NumberFormat} for handling {@code Number} objects. - * @since Android 1.0 */ public final static NumberFormat getInstance() { return getNumberInstance(); @@ -439,16 +404,17 @@ public abstract class NumberFormat extends Format { * @param locale * the locale to use. * @return a {@code NumberFormat} for handling {@code Number} objects. - * @since Android 1.0 */ public static NumberFormat getInstance(Locale locale) { return getNumberInstance(locale); } + // BEGIN android-added static NumberFormat getInstance(Locale locale, String type) { return new DecimalFormat(getPattern(locale, type), new DecimalFormatSymbols(locale)); } + // END android-added /** * Returns the maximum number of fraction digits that are printed when @@ -456,7 +422,6 @@ public abstract class NumberFormat extends Format { * the least significant digits are truncated. * * @return the maximum number of fraction digits. - * @since Android 1.0 */ public int getMaximumFractionDigits() { return maximumFractionDigits; @@ -468,7 +433,6 @@ public abstract class NumberFormat extends Format { * most significant digits are truncated. * * @return the maximum number of integer digits. - * @since Android 1.0 */ public int getMaximumIntegerDigits() { return maximumIntegerDigits; @@ -479,7 +443,6 @@ public abstract class NumberFormat extends Format { * formatting. * * @return the minimum number of fraction digits. - * @since Android 1.0 */ public int getMinimumFractionDigits() { return minimumFractionDigits; @@ -490,7 +453,6 @@ public abstract class NumberFormat extends Format { * formatting. * * @return the minimum number of integer digits. - * @since Android 1.0 */ public int getMinimumIntegerDigits() { return minimumIntegerDigits; @@ -501,7 +463,6 @@ public abstract class NumberFormat extends Format { * default locale. * * @return a {@code NumberFormat} for handling {@code Number} objects. - * @since Android 1.0 */ public final static NumberFormat getNumberInstance() { return getNumberInstance(Locale.getDefault()); @@ -514,23 +475,25 @@ public abstract class NumberFormat extends Format { * @param locale * the locale to use. * @return a {@code NumberFormat} for handling {@code Number} objects. - * @since Android 1.0 */ public static NumberFormat getNumberInstance(Locale locale) { + // BEGIN android-changed return getInstance(locale, "Number"); //$NON-NLS-1$ + // END android-changed } + // BEGIN android-added static String getPattern(Locale locale, String type) { ResourceBundle bundle = getBundle(locale); return bundle.getString(type); } + // END android-added /** * Returns a {@code NumberFormat} for formatting and parsing percentage * values for the default locale. * * @return a {@code NumberFormat} for handling percentage values. - * @since Android 1.0 */ public final static NumberFormat getPercentInstance() { return getPercentInstance(Locale.getDefault()); @@ -543,10 +506,11 @@ public abstract class NumberFormat extends Format { * @param locale * the locale to use. * @return a {@code NumberFormat} for handling percentage values. - * @since Android 1.0 */ public static NumberFormat getPercentInstance(Locale locale) { + // BEGIN android-changed return getInstance(locale, "Percent"); //$NON-NLS-1$ + // END android-changed } @Override @@ -562,7 +526,6 @@ public abstract class NumberFormat extends Format { * * @return {@code true} if a grouping separator is used; {@code false} * otherwise. - * @since Android 1.0 */ public boolean isGroupingUsed() { return groupingUsed; @@ -574,7 +537,6 @@ public abstract class NumberFormat extends Format { * * @return {@code true} if this number format only parses integers, * {@code false} if if parsese integers as well as fractions. - * @since Android 1.0 */ public boolean isParseIntegerOnly() { return parseIntegerOnly; @@ -587,9 +549,8 @@ public abstract class NumberFormat extends Format { * @param string * the string to parse. * @return the {@code Number} resulting from the parsing. - * @exception ParseException - * if an error occurs during parsing. - * @since Android 1.0 + * @throws ParseException + * if an error occurs during parsing. */ public Number parse(String string) throws ParseException { ParsePosition pos = new ParsePosition(0); @@ -617,7 +578,6 @@ public abstract class NumberFormat extends Format { * set to the index where the error occurred. * @return the {@code Number} resulting from the parse or {@code null} if * there is an error. - * @since Android 1.0 */ public abstract Number parse(String string, ParsePosition position); @@ -642,12 +602,10 @@ public abstract class NumberFormat extends Format { * This implementation throws {@code UnsupportedOperationException}, * concrete subclasses should override this method if they support currency * formatting. - * </p> - * + * * @param currency * the new currency. * @throws UnsupportedOperationException - * @since Android 1.0 */ public void setCurrency(Currency currency) { throw new UnsupportedOperationException(); @@ -660,7 +618,6 @@ public abstract class NumberFormat extends Format { * @param value * {@code true} if a grouping separator is used; {@code false} * otherwise. - * @since Android 1.0 */ public void setGroupingUsed(boolean value) { groupingUsed = value; @@ -673,7 +630,6 @@ public abstract class NumberFormat extends Format { * * @param value * the maximum number of fraction digits. - * @since Android 1.0 */ public void setMaximumFractionDigits(int value) { maximumFractionDigits = value < 0 ? 0 : value; @@ -689,7 +645,6 @@ public abstract class NumberFormat extends Format { * * @param value * the new maximum number of integer numerals for display. - * @since Android 1.0 */ public void setMaximumIntegerDigits(int value) { maximumIntegerDigits = value < 0 ? 0 : value; @@ -704,7 +659,6 @@ public abstract class NumberFormat extends Format { * * @param value * the minimum number of fraction digits. - * @since Android 1.0 */ public void setMinimumFractionDigits(int value) { minimumFractionDigits = value < 0 ? 0 : value; @@ -719,7 +673,6 @@ public abstract class NumberFormat extends Format { * * @param value * the minimum number of integer digits. - * @since Android 1.0 */ public void setMinimumIntegerDigits(int value) { minimumIntegerDigits = value < 0 ? 0 : value; @@ -737,7 +690,6 @@ public abstract class NumberFormat extends Format { * @param value * {@code true} to only parse integers, {@code false} to parse * integers as well as fractions. - * @since Android 1.0 */ public void setParseIntegerOnly(boolean value) { parseIntegerOnly = value; @@ -824,8 +776,6 @@ public abstract class NumberFormat extends Format { * There is no public constructor in this class, the only instances are the * constants defined here. * <p> - * - * @since Android 1.0 */ public static class Field extends Format.Field { @@ -833,90 +783,67 @@ public abstract class NumberFormat extends Format { /** * This constant stands for the number sign. - * - * @since Android 1.0 */ public static final Field SIGN = new Field("sign"); //$NON-NLS-1$ /** * This constant stands for the integer part of the number. - * - * @since Android 1.0 */ public static final Field INTEGER = new Field("integer"); //$NON-NLS-1$ /** * This constant stands for the fraction part of the number. - * - * @since Android 1.0 */ public static final Field FRACTION = new Field("fraction"); //$NON-NLS-1$ /** * This constant stands for the exponent part of the number. - * - * @since Android 1.0 */ public static final Field EXPONENT = new Field("exponent"); //$NON-NLS-1$ /** * This constant stands for the exponent sign symbol. - * - * @since Android 1.0 */ public static final Field EXPONENT_SIGN = new Field("exponent sign"); //$NON-NLS-1$ /** * This constant stands for the exponent symbol. - * - * @since Android 1.0 */ public static final Field EXPONENT_SYMBOL = new Field("exponent symbol"); //$NON-NLS-1$ /** * This constant stands for the decimal separator. - * - * @since Android 1.0 */ public static final Field DECIMAL_SEPARATOR = new Field( "decimal separator"); //$NON-NLS-1$ /** * This constant stands for the grouping separator. - * - * @since Android 1.0 */ public static final Field GROUPING_SEPARATOR = new Field( "grouping separator"); //$NON-NLS-1$ /** * This constant stands for the percent symbol. - * - * @since Android 1.0 */ public static final Field PERCENT = new Field("percent"); //$NON-NLS-1$ /** * This constant stands for the permille symbol. - * - * @since Android 1.0 */ public static final Field PERMILLE = new Field("per mille"); //$NON-NLS-1$ /** * This constant stands for the currency symbol. - * - * @since Android 1.0 */ public static final Field CURRENCY = new Field("currency"); //$NON-NLS-1$ /** * Constructs a new instance of {@code NumberFormat.Field} with the * given field name. - * + * * @param fieldName * the field name. - * @since Android 1.0 */ protected Field(String fieldName) { super(fieldName); @@ -925,7 +852,7 @@ public abstract class NumberFormat extends Format { /** * Resolves instances that are deserialized to the constant * {@code NumberFormat.Field} values. - * + * * @return the resolved field object. * @throws InvalidObjectException * if an error occurs while resolving the field object. diff --git a/text/src/main/java/java/text/ParseException.java b/text/src/main/java/java/text/ParseException.java index 5218462..b5a9c62 100644 --- a/text/src/main/java/java/text/ParseException.java +++ b/text/src/main/java/java/text/ParseException.java @@ -19,8 +19,6 @@ package java.text; /** * Thrown when the string being parsed is not in the correct form. - * - * @since Android 1.0 */ public class ParseException extends Exception { @@ -36,7 +34,6 @@ public class ParseException extends Exception { * the detail message for this exception. * @param location * the index at which the parse exception occurred. - * @since Android 1.0 */ public ParseException(String detailMessage, int location) { super(detailMessage); @@ -47,7 +44,6 @@ public class ParseException extends Exception { * Returns the index at which this parse exception occurred. * * @return the location of this exception in the parsed string. - * @since Android 1.0 */ public int getErrorOffset() { return errorOffset; diff --git a/text/src/main/java/java/text/ParsePosition.java b/text/src/main/java/java/text/ParsePosition.java index c3d1001..c643df9 100644 --- a/text/src/main/java/java/text/ParsePosition.java +++ b/text/src/main/java/java/text/ParsePosition.java @@ -21,8 +21,6 @@ package java.text; * Tracks the current position in a parsed string. In case of an error the error * index can be set to the position where the error occurred without having to * change the parse position. - * - * @since Android 1.0 */ public class ParsePosition { @@ -33,7 +31,6 @@ public class ParsePosition { * * @param index * the index to begin parsing. - * @since Android 1.0 */ public ParsePosition(int index) { currentPosition = index; @@ -50,7 +47,6 @@ public class ParsePosition { * @return {@code true} if the specified object is equal to this * {@code ParsePosition}; {@code false} otherwise. * @see #hashCode - * @since Android 1.0 */ @Override public boolean equals(Object object) { @@ -66,7 +62,6 @@ public class ParsePosition { * Returns the index at which the parse could not continue. * * @return the index of the parse error or -1 if there is no error. - * @since Android 1.0 */ public int getErrorIndex() { return errorIndex; @@ -76,7 +71,6 @@ public class ParsePosition { * Returns the current parse position. * * @return the current position. - * @since Android 1.0 */ public int getIndex() { return currentPosition; @@ -92,7 +86,6 @@ public class ParsePosition { * * @param index * the index of the parse error. - * @since Android 1.0 */ public void setErrorIndex(int index) { errorIndex = index; @@ -103,7 +96,6 @@ public class ParsePosition { * * @param index * the current parse position. - * @since Android 1.0 */ public void setIndex(int index) { currentPosition = index; @@ -113,7 +105,6 @@ public class ParsePosition { * Returns the string representation of this parse position. * * @return the string representation of this parse position. - * @since Android 1.0 */ @Override public String toString() { diff --git a/text/src/main/java/java/text/RuleBasedCollator.java b/text/src/main/java/java/text/RuleBasedCollator.java index 6418962..1a3bab7 100644 --- a/text/src/main/java/java/text/RuleBasedCollator.java +++ b/text/src/main/java/java/text/RuleBasedCollator.java @@ -15,17 +15,7 @@ * limitations under the License. */ -/** -******************************************************************************* -* Copyright (C) 1996-2007, International Business Machines Corporation and * -* others. All Rights Reserved. * -******************************************************************************* -*/ - // BEGIN android-note -// The class javadoc and some of the method descriptions are copied from ICU4J -// source files. Changes have been made to the copied descriptions. -// The icu license header was added to this file. // The icu implementation used was changed from icu4j to icu4jni. // END android-note @@ -38,7 +28,6 @@ import org.apache.harmony.text.internal.nls.Messages; * <p> * {@code RuleBasedCollator} has the following restrictions for efficiency * (other subclasses may be used for more complex languages): - * </p> * <ol> * <li> If a French secondary ordering is specified it applies to the whole * collator object.</li> @@ -51,19 +40,17 @@ import org.apache.harmony.text.internal.nls.Messages; * <p> * The collation table is composed of a list of collation rules, where each rule * is of three forms: - * </p> * <blockquote> - * + * * <pre> * <modifier> * <relation> <text-argument> * <reset> <text-argument> * </pre> - * + * * </blockquote> * <p> * The rule elements are defined as follows: - * </p> * <ul type="disc"> * <li><strong>Text-Argument</strong>: A text-argument is any sequence of * characters, excluding special characters (that is, common whitespace @@ -76,7 +63,6 @@ import org.apache.harmony.text.internal.nls.Messages; * specify that all accents (secondary differences) are backwards. * <p> * '@' : Indicates that accents are sorted backwards, as in French. - * </p> * </li> * <li><strong>Relation</strong>: The relations are the following: * <ul type=square> @@ -92,33 +78,30 @@ import org.apache.harmony.text.internal.nls.Messages; * <p> * '&' : Indicates that the next rule follows the position to where the reset * text-argument would be sorted. - * </p> * </li> * </ul> * <p> * This sounds more complicated than it is in practice. For example, the * following are equivalent ways of expressing the same thing: - * </p> * <blockquote> - * + * * <pre> * a < b < c * a < b & b < c * a < c & a < b * </pre> - * + * * </blockquote> * <p> * Notice that the order is important, as the subsequent item goes immediately * after the text-argument. The following are not equivalent: - * </p> * <blockquote> - * + * * <pre> * a < b & a < c * a < c & a < b * </pre> - * + * * </blockquote> * <p> * Either the text-argument must already be present in the sequence, or some @@ -132,7 +115,6 @@ import org.apache.harmony.text.internal.nls.Messages; * German a-umlaut is treated as if it expands to two characters (expressed as * {@code "a,A < b,B ... & ae;\u00e3 & AE;\u00c3"}, where \u00e3 and \u00c3 * are the escape sequences for a-umlaut). - * </p> * <h4>Ignorable Characters</h4> * <p> * For ignorable characters, the first rule must start with a relation (the @@ -141,7 +123,6 @@ import org.apache.harmony.text.internal.nls.Messages; * {@code "<"}, then all text-arguments up to the first {@code "<"} are * ignorable. For example, {@code ", - < a < b"} makes {@code "-"} an ignorable * character. - * </p> * <h4>Normalization and Accents</h4> * <p> * {@code RuleBasedCollator} automatically processes its rule table to include @@ -150,7 +131,6 @@ import org.apache.harmony.text.internal.nls.Messages; * combining accent characters, the pre-composed accented characters matching * all canonical combinations of characters from the rule string will be entered * in the table. - * </p> * <p> * This allows you to use a RuleBasedCollator to compare accented strings even * when the collator is set to NO_DECOMPOSITION. However, if the strings to be @@ -158,11 +138,9 @@ import org.apache.harmony.text.internal.nls.Messages; * should set the collator to CANONICAL_DECOMPOSITION to enable sorting of * combining sequences. For more information, see <a * href="http://www.aw.com/devpress">The Unicode Standard, Version 3.0</a>. - * </p> * <h4>Errors</h4> * <p> * The following rules are not valid: - * </p> * <ul type="disc"> * <li>A text-argument contains unquoted punctuation symbols, for example * {@code "a < b-c < d"}.</li> @@ -175,7 +153,6 @@ import org.apache.harmony.text.internal.nls.Messages; * <p> * If you produce one of these errors, {@code RuleBasedCollator} throws a * {@code ParseException}. - * </p> * <h4>Examples</h4> * <p> * Normally, to create a rule-based collator object, you will use @@ -183,117 +160,109 @@ import org.apache.harmony.text.internal.nls.Messages; * rule-based collator object with specialized rules tailored to your needs, you * construct the {@code RuleBasedCollator} with the rules contained in a * {@code String} object. For example: - * </p> * <blockquote> - * + * * <pre> * String Simple = "< a < b < c < d"; - * + * * RuleBasedCollator mySimple = new RuleBasedCollator(Simple); * </pre> - * + * * </blockquote> * <p> * Or: - * </p> * <blockquote> - * + * * <pre> * String Norwegian = "< a,A< b,B< c,C< d,D< e,E< f,F< g,G< h,H< i,I" - * + "< j,J< k,K< l,L< m,M< n,N< o,O< p,P< q,Q< r,R" + * + "< j,J< k,K< l,L< m,M< n,N< o,O< p,P< q,Q< r,R" * + "< s,S< t,T< u,U< v,V< w,W< x,X< y,Y< z,Z" - * + "< \u00E5=a\u030A,\u00C5=A\u030A" + * + "< \u00E5=a\u030A,\u00C5=A\u030A" * + ";aa,AA< \u00E6,\u00C6< \u00F8,\u00D8"; - * + * * RuleBasedCollator myNorwegian = new RuleBasedCollator(Norwegian); * </pre> - * + * * </blockquote> * <p> * Combining {@code Collator}s is as simple as concatenating strings. Here is * an example that combines two {@code Collator}s from two different locales: - * </p> * <blockquote> - * + * * <pre> * // Create an en_US Collator object * RuleBasedCollator en_USCollator = (RuleBasedCollator)Collator * .getInstance(new Locale("en", "US", "")); - * + * * // Create a da_DK Collator object * RuleBasedCollator da_DKCollator = (RuleBasedCollator)Collator * .getInstance(new Locale("da", "DK", "")); - * + * * // Combine the two collators * // First, get the collation rules from en_USCollator * String en_USRules = en_USCollator.getRules(); - * + * * // Second, get the collation rules from da_DKCollator * String da_DKRules = da_DKCollator.getRules(); - * + * * RuleBasedCollator newCollator = new RuleBasedCollator(en_USRules + da_DKRules); * // newCollator has the combined rules * </pre> - * + * * </blockquote> * <p> * The next example shows to make changes on an existing table to create a new * {@code Collator} object. For example, add {@code "& C < ch, cH, Ch, CH"} to * the {@code en_USCollator} object to create your own: - * </p> * <blockquote> - * + * * <pre> * // Create a new Collator object with additional rules * String addRules = "& C < ch, cH, Ch, CH"; - * + * * RuleBasedCollator myCollator = new RuleBasedCollator(en_USCollator + addRules); * // myCollator contains the new rules * </pre> - * + * * </blockquote> * <p> * The following example demonstrates how to change the order of non-spacing * accents: - * </p> * <blockquote> - * + * * <pre> * // old rule * String oldRules = "= \u00a8 ; \u00af ; \u00bf" + "< a , A ; ae, AE ; \u00e6 , \u00c6" * + "< b , B < c, C < e, E & C < d, D"; - * + * * // change the order of accent characters * String addOn = "& \u00bf ; \u00af ; \u00a8;"; - * + * * RuleBasedCollator myCollator = new RuleBasedCollator(oldRules + addOn); * </pre> - * + * * </blockquote> * <p> * The last example shows how to put new primary ordering in before the default * setting. For example, in the Japanese {@code Collator}, you can either sort * English characters before or after Japanese characters: - * </p> * <blockquote> - * + * * <pre> * // get en_US Collator rules * RuleBasedCollator en_USCollator = (RuleBasedCollator) * Collator.getInstance(Locale.US); - * + * * // add a few Japanese character to sort before English characters * // suppose the last character before the first base letter 'a' in * // the English collation rule is \u30A2 * String jaString = "& \u30A2 , \u30FC < \u30C8"; - * - * RuleBasedCollator myJapaneseCollator = + * + * RuleBasedCollator myJapaneseCollator = * new RuleBasedCollator(en_USCollator.getRules() + jaString); * </pre> - * + * * </blockquote> - * - * @since Android 1.0 */ public class RuleBasedCollator extends Collator { @@ -320,7 +289,6 @@ public class RuleBasedCollator extends Collator { * @throws ParseException * if {@code rules} contains rules with invalid collation rule * syntax. - * @since Android 1.0 */ public RuleBasedCollator(String rules) throws ParseException { if (rules == null) { @@ -359,7 +327,6 @@ public class RuleBasedCollator extends Collator { * @param source * the source character iterator. * @return a {@code CollationElementIterator} for {@code source}. - * @since Android 1.0 */ public CollationElementIterator getCollationElementIterator( CharacterIterator source) { @@ -377,7 +344,6 @@ public class RuleBasedCollator extends Collator { * @param source * the source string. * @return the {@code CollationElementIterator} for {@code source}. - * @since Android 1.0 */ public CollationElementIterator getCollationElementIterator(String source) { if (source == null) { @@ -399,7 +365,6 @@ public class RuleBasedCollator extends Collator { * specifications and may result in different behavior. * * @return the collation rules. - * @since Android 1.0 */ public String getRules() { return ((com.ibm.icu4jni.text.RuleBasedCollator) this.icuColl).getRules(); @@ -411,7 +376,6 @@ public class RuleBasedCollator extends Collator { * * @return a shallow copy of this collator. * @see java.lang.Cloneable - * @since Android 1.0 */ @Override public Object clone() { @@ -431,7 +395,6 @@ public class RuleBasedCollator extends Collator { * {@code CollationKey.compareTo(CollationKey)} for the comparisons. If each * string is compared to only once, using * {@code RuleBasedCollator.compare(String, String)} has better performance. - * </p> * * @param source * the source text. @@ -440,7 +403,6 @@ public class RuleBasedCollator extends Collator { * @return an integer which may be a negative value, zero, or else a * positive value depending on whether {@code source} is less than, * equivalent to, or greater than {@code target}. - * @since Android 1.0 */ @Override public int compare(String source, String target) { @@ -457,7 +419,6 @@ public class RuleBasedCollator extends Collator { * @param source * the specified source text. * @return the {@code CollationKey} for the given source text. - * @since Android 1.0 */ @Override public CollationKey getCollationKey(String source) { @@ -486,7 +447,6 @@ public class RuleBasedCollator extends Collator { * @return {@code true} if the specified object is equal to this * {@code RuleBasedCollator}; {@code false} otherwise. * @see #hashCode - * @since Android 1.0 */ @Override public boolean equals(Object obj) { diff --git a/text/src/main/java/java/text/SimpleDateFormat.java b/text/src/main/java/java/text/SimpleDateFormat.java index c78f29e..52c5e1b 100644 --- a/text/src/main/java/java/text/SimpleDateFormat.java +++ b/text/src/main/java/java/text/SimpleDateFormat.java @@ -15,17 +15,8 @@ * limitations under the License. */ -/** -******************************************************************************* -* Copyright (C) 1996-2007, International Business Machines Corporation and * -* others. All Rights Reserved. * -******************************************************************************* -*/ - // BEGIN android-note -// The class javadoc and some of the method descriptions are copied from ICU4J -// source files. Changes have been made to the copied descriptions. -// The icu license header was added to this file. +// changed from ICU to resource bundles and Java parsing/formatting // END android-note package java.text; @@ -38,9 +29,11 @@ import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; import java.util.Locale; +// BEGIN android-added import java.util.ResourceBundle; import java.util.SimpleTimeZone; import java.util.TimeZone; +// END android-added import java.util.Vector; import org.apache.harmony.text.internal.nls.Messages; @@ -58,13 +51,11 @@ import org.apache.harmony.text.internal.nls.Messages; * default format pattern. You may modify the format pattern using the {@code * applyPattern} methods as desired. For more information on using these * methods, see {@link DateFormat}. - * </p> * <h4>Time Format Syntax</h4> * <p> * To specify the time format, use a <em>time pattern</em> string. In this * pattern, all ASCII letters are reserved as pattern letters, which are defined * as follows: - * </p> * <table border=0 cellspacing=3 cellpadding=0> * <tr bgcolor="#ccccff"> * <th>Symbol</th> @@ -217,7 +208,6 @@ import org.apache.harmony.text.internal.nls.Messages; * <strong>(Text)</strong>: 4 or more pattern letters → use the full form, * less than 4 pattern letters → use a short or abbreviated form if one * exists. - * </p> * <p> * <strong>(Number)</strong>: the minimum number of digits. Shorter numbers are * zero-padded to this amount. Year is handled specially; that is, if the count @@ -225,18 +215,15 @@ import org.apache.harmony.text.internal.nls.Messages; * "1997", "yy" produces "97".) Unlike other fields, fractional seconds are * padded on the right with zero. * <p> - * </p> * <strong>(Text & Number)</strong>: 3 or over, use text, otherwise use number. * <p> * Any characters in the pattern that are not in the ranges of ['a'..'z'] and * ['A'..'Z'] will be treated as quoted text. For instance, characters like ':', * '.', ' ', '#' and '@' will appear in the resulting time text even they are * not embraced within single quotes. - * </p> * <p> * A pattern containing any invalid pattern letter will result in an exception * thrown during formatting or parsing. - * </p> * <h4>Examples Using the US Locale</h4> <blockquote> * * <pre> @@ -275,7 +262,6 @@ import org.apache.harmony.text.internal.nls.Messages; * am/pm marker 'a' is left out from the format pattern while the * "hour in am/pm" pattern symbol is used. This information loss can happen when * formatting the time in PM. - * </p> * <p> * When parsing a date string using the abbreviated year pattern ("yy"), {@code * SimpleDateFormat} must interpret the abbreviated year relative to some @@ -291,12 +277,10 @@ import org.apache.harmony.text.internal.nls.Messages; * example, "-1"), is interpreted literally. So "01/02/3" or "01/02/003" are * parsed, using the same pattern, as Jan 2, 3 AD. Likewise, "01/02/-3" is * parsed as Jan 2, 4 BC. - * </p> * <p> * If the year pattern does not have exactly two 'y' characters, the year is * interpreted literally, regardless of the number of digits. So using the * pattern "MM/dd/yyyy", "01/11/12" parses to Jan 11, 12 A.D. - * </p> * <p> * When numeric fields are adjacent directly, with no intervening delimiter * characters, they constitute a run of adjacent numeric fields. Such runs are @@ -308,11 +292,9 @@ import org.apache.harmony.text.internal.nls.Messages; * parsed again. This is repeated until either the parse succeeds or the * leftmost field is one character in length. If the parse still fails at that * point, the parse of the run fails. - * </p> * <p> * For time zones that have no names, use the strings "GMT+hours:minutes" or * "GMT-hours:minutes". - * </p> * <p> * The calendar defines the first day of the week, the first week of the year, * whether hours are zero based or not (0 vs. 12 or 24) and the time zone. There @@ -324,17 +306,19 @@ import org.apache.harmony.text.internal.nls.Messages; * * @see Calendar * @see GregorianCalendar - * @see TimeZone + * @see java.util.TimeZone * @see DateFormat * @see DateFormatSymbols * @see DecimalFormat - * @since Android 1.0 */ public class SimpleDateFormat extends DateFormat { private static final long serialVersionUID = 4774881970558875024L; + // BEGIN android-changed + // private static final String patternChars = "GyMdkHmsSEDFwWahKzYeugAZvcLQqV"; //$NON-NLS-1$ private static final String patternChars = "GyMdkHmsSEDFwWahKzZ"; //$NON-NLS-1$ + // END android-changed private String pattern; @@ -344,15 +328,21 @@ public class SimpleDateFormat extends DateFormat { private Date defaultCenturyStart; + // BEGIN android-removed + // private transient String tzId; + // + // private transient com.ibm.icu.text.SimpleDateFormat icuFormat; + // END android-removed + /** * Constructs a new {@code SimpleDateFormat} for formatting and parsing * dates and times in the {@code SHORT} style for the default locale. - * - * @since Android 1.0 */ public SimpleDateFormat() { this(Locale.getDefault()); + // BEGIN android-changed pattern = defaultPattern(); + // END android-changed formatData = new DateFormatSymbols(Locale.getDefault()); } @@ -363,35 +353,133 @@ public class SimpleDateFormat extends DateFormat { * * @param pattern * the pattern. - * @exception IllegalArgumentException - * if {@code pattern} is not considered to be usable by this - * formatter. - * @since Android 1.0 + * @throws NullPointerException + * if the pattern is {@code null}. + * @throws IllegalArgumentException + * if {@code pattern} is not considered to be usable by this + * formatter. */ public SimpleDateFormat(String pattern) { this(pattern, Locale.getDefault()); } + + /** + * Validates the format character. + * + * @param format + * the format character + * + * @throws IllegalArgumentException + * when the format character is invalid + */ + private void validateFormat(char format) { + int index = patternChars.indexOf(format); + if (index == -1) { + // text.03=Unknown pattern character - '{0}' + throw new IllegalArgumentException(Messages.getString( + "text.03", format)); //$NON-NLS-1$ + } + } + + /** + * Validates the pattern. + * + * @param template + * the pattern to validate. + * + * @throws NullPointerException + * if the pattern is null + * @throws IllegalArgumentException + * if the pattern is invalid + */ + private void validatePattern(String template) { + boolean quote = false; + int next, last = -1, count = 0; + + final int patternLength = template.length(); + for (int i = 0; i < patternLength; i++) { + next = (template.charAt(i)); + if (next == '\'') { + if (count > 0) { + validateFormat((char) last); + count = 0; + } + if (last == next) { + last = -1; + } else { + last = next; + } + quote = !quote; + continue; + } + if (!quote + && (last == next || (next >= 'a' && next <= 'z') || (next >= 'A' && next <= 'Z'))) { + if (last == next) { + count++; + } else { + if (count > 0) { + validateFormat((char) last); + } + last = next; + count = 1; + } + } else { + if (count > 0) { + validateFormat((char) last); + count = 0; + } + last = -1; + } + } + if (count > 0) { + validateFormat((char) last); + } + + if (quote) { + // text.04=Unterminated quote {0} + throw new IllegalArgumentException(Messages.getString("text.04")); //$NON-NLS-1$ + } + } + /** * Constructs a new {@code SimpleDateFormat} using the specified * non-localized pattern and {@code DateFormatSymbols} and the {@code * Calendar} for the default locale. - * + * * @param template * the pattern. * @param value * the DateFormatSymbols. - * @exception IllegalArgumentException - * if the pattern is invalid. - * @since Android 1.0 + * @throws NullPointerException + * if the pattern is {@code null}. + * @throws IllegalArgumentException + * if the pattern is invalid. */ public SimpleDateFormat(String template, DateFormatSymbols value) { this(Locale.getDefault()); validatePattern(template); + // BEGIN android-removed + // icuFormat = new com.ibm.icu.text.SimpleDateFormat(template, Locale.getDefault()); + // icuFormat.setTimeZone(com.ibm.icu.util.TimeZone.getTimeZone(tzId)); + // END android-removed pattern = template; formatData = (DateFormatSymbols) value.clone(); } + // BEGIN android-removed + // private void copySymbols(DateFormatSymbols value, com.ibm.icu.text.DateFormatSymbols icuSymbols) { + // icuSymbols.setAmPmStrings(value.getAmPmStrings()); + // icuSymbols.setEras(value.getEras()); + // icuSymbols.setLocalPatternChars(value.getLocalPatternChars()); + // icuSymbols.setMonths(value.getMonths()); + // icuSymbols.setShortMonths(value.getShortMonths()); + // icuSymbols.setShortWeekdays(value.getShortWeekdays()); + // icuSymbols.setWeekdays(value.getWeekdays()); + // icuSymbols.setZoneStrings(value.getZoneStrings()); + // } + // END android-removed + /** * Constructs a new {@code SimpleDateFormat} using the specified * non-localized pattern and the {@code DateFormatSymbols} and {@code @@ -401,27 +489,299 @@ public class SimpleDateFormat extends DateFormat { * the pattern. * @param locale * the locale. - * @exception IllegalArgumentException - * if the pattern is invalid. - * @since Android 1.0 + * @throws NullPointerException + * if the pattern is {@code null}. + * @throws IllegalArgumentException + * if the pattern is invalid. */ public SimpleDateFormat(String template, Locale locale) { this(locale); validatePattern(template); + // BEGIN android-removed + // icuFormat = new com.ibm.icu.text.SimpleDateFormat(template, locale); + // icuFormat.setTimeZone(com.ibm.icu.util.TimeZone.getTimeZone(tzId)); + // END android-removed pattern = template; + // BEGIN android-changed formatData = new DateFormatSymbols(locale); + // END android-changed } + // BEGIN android-removed + // SimpleDateFormat(Locale locale, com.ibm.icu.text.SimpleDateFormat icuFormat){ + // this(locale); + // this.icuFormat = icuFormat; + // this.icuFormat.setTimeZone(com.ibm.icu.util.TimeZone.getTimeZone(tzId)); + // pattern = (String)Format.getInternalField("pattern", icuFormat); //$NON-NLS-1$ + // formatData = new DateFormatSymbols(locale); + // } + // END android-removed + private SimpleDateFormat(Locale locale) { numberFormat = NumberFormat.getInstance(locale); numberFormat.setParseIntegerOnly(true); numberFormat.setGroupingUsed(false); calendar = new GregorianCalendar(locale); calendar.add(Calendar.YEAR, -80); + // BEGIN android-removed + // tzId = calendar.getTimeZone().getID(); + // END android-removed creationYear = calendar.get(Calendar.YEAR); defaultCenturyStart = calendar.getTime(); } + /** + * Changes the pattern of this simple date format to the specified pattern + * which uses localized pattern characters. + * + * @param template + * the localized pattern. + */ + public void applyLocalizedPattern(String template) { + // BEGIN android-changed + pattern = convertPattern(template, formatData.getLocalPatternChars(), + patternChars, true); + // END android-changed + } + + /** + * Changes the pattern of this simple date format to the specified pattern + * which uses non-localized pattern characters. + * + * @param template + * the non-localized pattern. + * @throws NullPointerException + * if the pattern is {@code null}. + * @throws IllegalArgumentException + * if the pattern is invalid. + */ + public void applyPattern(String template) { + validatePattern(template); + // BEGIN android-removed + // /* + // * ICU spec explicitly mentions that "ICU interprets a single 'y' + // * differently than Java." We need to do a trick here to follow Java + // * spec. + // */ + // String templateForICU = patternForICU(template); + // icuFormat.applyPattern(templateForICU); + // END android-removed + pattern = template; + } + + /** + * Converts the Java-spec pattern into an equivalent pattern used by ICU. + * + * @param p + * the Java-spec style pattern. + * @return the ICU-style pattern. + */ + @SuppressWarnings("nls") + private String patternForICU(String p) { + String[] subPatterns = p.split("'"); + boolean quote = false; + boolean first = true; + StringBuilder result = new StringBuilder(); + for (String subPattern : subPatterns) { + if (!quote) { + // replace 'y' with 'yy' for ICU to follow Java spec + result.append((first ? "" : "'") + + subPattern.replaceAll("(?<!y)y(?!y)", "yy")); + first = false; + } else { + result.append("'" + subPattern); + } + quote = !quote; + } + if (p.endsWith("'")) { + result.append("'"); + } + return result.toString(); + } + + /** + * Returns a new {@code SimpleDateFormat} with the same pattern and + * properties as this simple date format. + * + * @return a shallow copy of this simple date format. + * @see java.lang.Cloneable + */ + @Override + public Object clone() { + SimpleDateFormat clone = (SimpleDateFormat) super.clone(); + clone.formatData = (DateFormatSymbols) formatData.clone(); + clone.defaultCenturyStart = new Date(defaultCenturyStart.getTime()); + // BEGIN android-removed + // clone.tzId = tzId; + // END android-removed + return clone; + } + + // BEGIN android-added + private static String defaultPattern() { + ResourceBundle bundle = getBundle(Locale.getDefault()); + String styleName = getStyleName(SHORT); + return bundle.getString("Date_" + styleName) + " " //$NON-NLS-1$ //$NON-NLS-2$ + + bundle.getString("Time_" + styleName); //$NON-NLS-1$ + } + // END android-added + + /** + * Compares the specified object with this simple date format and indicates + * if they are equal. In order to be equal, {@code object} must be an + * instance of {@code SimpleDateFormat} and have the same {@code DateFormat} + * properties, pattern, {@code DateFormatSymbols} and creation year. + * + * @param object + * the object to compare with this object. + * @return {@code true} if the specified object is equal to this simple date + * format; {@code false} otherwise. + * @see #hashCode + */ + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + if (!(object instanceof SimpleDateFormat)) { + return false; + } + SimpleDateFormat simple = (SimpleDateFormat) object; + return super.equals(object) && pattern.equals(simple.pattern) + && formatData.equals(simple.formatData); + } + + /** + * Formats the specified object using the rules of this simple date format + * and returns an {@code AttributedCharacterIterator} with the formatted + * date and attributes. + * + * @param object + * the object to format. + * @return an {@code AttributedCharacterIterator} with the formatted date + * and attributes. + * @throws NullPointerException + * if the object is {@code null}. + * @throws IllegalArgumentException + * if the object cannot be formatted by this simple date + * format. + */ + @Override + public AttributedCharacterIterator formatToCharacterIterator(Object object) { + if (object == null) { + throw new NullPointerException(); + } + if (object instanceof Date) { + return formatToCharacterIteratorImpl((Date) object); + } + if (object instanceof Number) { + return formatToCharacterIteratorImpl(new Date(((Number) object) + .longValue())); + } + throw new IllegalArgumentException(); + + } + + private AttributedCharacterIterator formatToCharacterIteratorImpl(Date date) { + StringBuffer buffer = new StringBuffer(); + Vector<FieldPosition> fields = new Vector<FieldPosition>(); + + // format the date, and find fields + formatImpl(date, buffer, null, fields); + + // create and AttributedString with the formatted buffer + AttributedString as = new AttributedString(buffer.toString()); + + // add DateFormat field attributes to the AttributedString + for (int i = 0; i < fields.size(); i++) { + FieldPosition pos = fields.elementAt(i); + Format.Field attribute = pos.getFieldAttribute(); + as.addAttribute(attribute, attribute, pos.getBeginIndex(), pos + .getEndIndex()); + } + + // return the CharacterIterator from AttributedString + return as.getIterator(); + } + + /** + * Formats the date. + * <p> + * If the FieldPosition {@code field} is not null, and the field + * specified by this FieldPosition is formatted, set the begin and end index + * of the formatted field in the FieldPosition. + * <p> + * If the Vector {@code fields} is not null, find fields of this + * date, set FieldPositions with these fields, and add them to the fields + * vector. + * + * @param date + * Date to Format + * @param buffer + * StringBuffer to store the resulting formatted String + * @param field + * FieldPosition to set begin and end index of the field + * specified, if it is part of the format for this date + * @param fields + * Vector used to store the FieldPositions for each field in this + * date + * @return the formatted Date + * @throws IllegalArgumentException + * if the object cannot be formatted by this Format. + */ + private StringBuffer formatImpl(Date date, StringBuffer buffer, + FieldPosition field, Vector<FieldPosition> fields) { + + boolean quote = false; + int next, last = -1, count = 0; + calendar.setTime(date); + if (field != null) { + field.clear(); + } + + final int patternLength = pattern.length(); + for (int i = 0; i < patternLength; i++) { + next = (pattern.charAt(i)); + if (next == '\'') { + if (count > 0) { + append(buffer, field, fields, (char) last, count); + count = 0; + } + if (last == next) { + buffer.append('\''); + last = -1; + } else { + last = next; + } + quote = !quote; + continue; + } + if (!quote + && (last == next || (next >= 'a' && next <= 'z') || (next >= 'A' && next <= 'Z'))) { + if (last == next) { + count++; + } else { + if (count > 0) { + append(buffer, field, fields, (char) last, count); + } + last = next; + count = 1; + } + } else { + if (count > 0) { + append(buffer, field, fields, (char) last, count); + count = 0; + } + last = -1; + buffer.append((char) next); + } + } + if (count > 0) { + append(buffer, field, fields, (char) last, count); + } + return buffer; + } + private void append(StringBuffer buffer, FieldPosition position, Vector<FieldPosition> fields, char format, int count) { int field = -1; @@ -434,7 +794,6 @@ public class SimpleDateFormat extends DateFormat { int beginPosition = buffer.length(); Field dateFormatField = null; - switch (index) { case ERA_FIELD: dateFormatField = Field.ERA; @@ -528,10 +887,12 @@ public class SimpleDateFormat extends DateFormat { dateFormatField = Field.TIME_ZONE; appendTimeZone(buffer, count, true); break; + // BEGIN android-changed case (TIMEZONE_FIELD + 1): // Z dateFormatField = Field.TIME_ZONE; appendTimeZone(buffer, count, false); break; + // END android-changed } if (field != -1) { appendNumber(buffer, count, calendar.get(field)); @@ -552,7 +913,7 @@ public class SimpleDateFormat extends DateFormat { } } } - + private void appendTimeZone(StringBuffer buffer, int count, boolean generalTimezone) { // cannot call TimeZone.getDisplayName() because it would not use @@ -612,139 +973,13 @@ public class SimpleDateFormat extends DateFormat { numberFormat.setMinimumIntegerDigits(minimumIntegerDigits); } - /** - * Changes the pattern of this simple date format to the specified pattern - * which uses localized pattern characters. - * - * @param template - * the localized pattern. - * @since Android 1.0 - */ - public void applyLocalizedPattern(String template) { - pattern = convertPattern(template, formatData.getLocalPatternChars(), - patternChars, true); - } - - /** - * Changes the pattern of this simple date format to the specified pattern - * which uses non-localized pattern characters. - * - * @param template - * the non-localized pattern. - * @exception IllegalArgumentException - * if the pattern is invalid. - * @since Android 1.0 - */ - public void applyPattern(String template) { - validatePattern(template); - pattern = template; - } - - /** - * Returns a new {@code SimpleDateFormat} with the same pattern and - * properties as this simple date format. - * - * @return a shallow copy of this simple date format. - * @see java.lang.Cloneable - * @since Android 1.0 - */ - @Override - public Object clone() { - SimpleDateFormat clone = (SimpleDateFormat) super.clone(); - clone.formatData = (DateFormatSymbols) formatData.clone(); - clone.defaultCenturyStart = new Date(defaultCenturyStart.getTime()); - return clone; - } - - private static String defaultPattern() { - ResourceBundle bundle = getBundle(Locale.getDefault()); - String styleName = getStyleName(SHORT); - return bundle.getString("Date_" + styleName) + " " //$NON-NLS-1$ //$NON-NLS-2$ - + bundle.getString("Time_" + styleName); //$NON-NLS-1$ - } - - /** - * Compares the specified object with this simple date format and indicates - * if they are equal. In order to be equal, {@code object} must be an - * instance of {@code SimpleDateFormat} and have the same {@code DateFormat} - * properties, pattern, {@code DateFormatSymbols} and creation year. - * - * @param object - * the object to compare with this object. - * @return {@code true} if the specified object is equal to this simple date - * format; {@code false} otherwise. - * @see #hashCode - * @since Android 1.0 - */ - @Override - public boolean equals(Object object) { - if (this == object) { - return true; - } - if (!(object instanceof SimpleDateFormat)) { - return false; - } - SimpleDateFormat simple = (SimpleDateFormat) object; - return super.equals(object) && pattern.equals(simple.pattern) - && formatData.equals(simple.formatData); - } - + // BEGIN android-added private Date error(ParsePosition position, int offset, TimeZone zone) { position.setErrorIndex(offset); calendar.setTimeZone(zone); return null; } - - /** - * Formats the specified object using the rules of this simple date format - * and returns an {@code AttributedCharacterIterator} with the formatted - * date and attributes. - * - * @param object - * the object to format. - * @return an {@code AttributedCharacterIterator} with the formatted date - * and attributes. - * @exception IllegalArgumentException - * when the object cannot be formatted by this simple date - * format. - * @since Android 1.0 - */ - @Override - public AttributedCharacterIterator formatToCharacterIterator(Object object) { - if (object == null) { - throw new NullPointerException(); - } - if (object instanceof Date) { - return formatToCharacterIteratorImpl((Date) object); - } - if (object instanceof Number) { - return formatToCharacterIteratorImpl(new Date(((Number) object) - .longValue())); - } - throw new IllegalArgumentException(); - } - - private AttributedCharacterIterator formatToCharacterIteratorImpl(Date date) { - StringBuffer buffer = new StringBuffer(); - Vector<FieldPosition> fields = new Vector<FieldPosition>(); - - // format the date, and find fields - formatImpl(date, buffer, null, fields); - - // create and AttributedString with the formatted buffer - AttributedString as = new AttributedString(buffer.toString()); - - // add DateFormat field attributes to the AttributedString - for (int i = 0; i < fields.size(); i++) { - FieldPosition pos = fields.elementAt(i); - Format.Field attribute = pos.getFieldAttribute(); - as.addAttribute(attribute, attribute, pos.getBeginIndex(), pos - .getEndIndex()); - } - - // return the CharacterIterator from AttributedString - return as.getIterator(); - } + // END android-added /** * Formats the specified date as a string using the pattern of this date @@ -754,191 +989,39 @@ public class SimpleDateFormat extends DateFormat { * a format field, then its {@code beginIndex} and {@code endIndex} members * will be updated with the position of the first occurrence of this field * in the formatted text. - * </p> - * + * * @param date * the date to format. * @param buffer * the target string buffer to append the formatted date/time to. - * @param field + * @param fieldPos * on input: an optional alignment field; on output: the offsets * of the alignment field in the formatted text. * @return the string buffer. * @throws IllegalArgumentException * if there are invalid characters in the pattern. - * @since Android 1.0 */ @Override public StringBuffer format(Date date, StringBuffer buffer, - FieldPosition field) { - return formatImpl(date, buffer, field, null); - } - - /** - * Validates the format character. - * - * @param format - * the format character - * - * @throws IllegalArgumentException - * when the format character is invalid - */ - private void validateFormat(char format) { - int index = patternChars.indexOf(format); - if (index == -1) { - // text.03=Unknown pattern character - '{0}' - throw new IllegalArgumentException(Messages.getString( - "text.03", format)); //$NON-NLS-1$ - } + FieldPosition fieldPos) { + // BEGIN android-changed + // Harmony delegates to ICU's SimpleDateFormat, we implement it directly + return formatImpl(date, buffer, fieldPos, null); + // END android-changed } - /** - * Validates the pattern. - * - * @param template - * the pattern to validate. - * - * @throws NullPointerException - * if the pattern is null - * @throws IllegalArgumentException - * if the pattern is invalid - */ - private void validatePattern(String template) { - boolean quote = false; - int next, last = -1, count = 0; - - final int patternLength = template.length(); - for (int i = 0; i < patternLength; i++) { - next = (template.charAt(i)); - if (next == '\'') { - if (count > 0) { - validateFormat((char) last); - count = 0; - } - if (last == next) { - last = -1; - } else { - last = next; - } - quote = !quote; - continue; - } - if (!quote - && (last == next || (next >= 'a' && next <= 'z') || (next >= 'A' && next <= 'Z'))) { - if (last == next) { - count++; - } else { - if (count > 0) { - validateFormat((char) last); - } - last = next; - count = 1; - } - } else { - if (count > 0) { - validateFormat((char) last); - count = 0; - } - last = -1; - } - } - if (count > 0) { - validateFormat((char) last); - } - - if (quote) { - // text.04=Unterminated quote {0} - throw new IllegalArgumentException(Messages.getString("text.04")); //$NON-NLS-1$ - } - - } + // BEGIN android-removed + // private com.ibm.icu.text.DateFormat.Field toICUField( + // DateFormat.Field attribute) { + // ... + // } + // END android-removed /** - * Formats the date. - * <p> - * If the FieldPosition {@code field} is not null, and the field - * specified by this FieldPosition is formatted, set the begin and end index - * of the formatted field in the FieldPosition. - * <p> - * If the Vector {@code fields} is not null, find fields of this - * date, set FieldPositions with these fields, and add them to the fields - * vector. - * - * @param date - * Date to Format - * @param buffer - * StringBuffer to store the resulting formatted String - * @param field - * FieldPosition to set begin and end index of the field - * specified, if it is part of the format for this date - * @param fields - * Vector used to store the FieldPositions for each field in this - * date - * - * @return the formatted Date - * - * @exception IllegalArgumentException - * when the object cannot be formatted by this Format - */ - private StringBuffer formatImpl(Date date, StringBuffer buffer, - FieldPosition field, Vector<FieldPosition> fields) { - - boolean quote = false; - int next, last = -1, count = 0; - calendar.setTime(date); - if (field != null) { - field.clear(); - } - - final int patternLength = pattern.length(); - for (int i = 0; i < patternLength; i++) { - next = (pattern.charAt(i)); - if (next == '\'') { - if (count > 0) { - append(buffer, field, fields, (char) last, count); - count = 0; - } - if (last == next) { - buffer.append('\''); - last = -1; - } else { - last = next; - } - quote = !quote; - continue; - } - if (!quote - && (last == next || (next >= 'a' && next <= 'z') || (next >= 'A' && next <= 'Z'))) { - if (last == next) { - count++; - } else { - if (count > 0) { - append(buffer, field, fields, (char) last, count); - } - last = next; - count = 1; - } - } else { - if (count > 0) { - append(buffer, field, fields, (char) last, count); - count = 0; - } - last = -1; - buffer.append((char) next); - } - } - if (count > 0) { - append(buffer, field, fields, (char) last, count); - } - return buffer; - } - - /** - * Returns the date which is the start of the one hundred year period for + * Answers the Date which is the start of the one hundred year period for * two digits year values. * - * @return a date. - * @since Android 1.0 + * @return a Date */ public Date get2DigitYearStart() { return defaultCenturyStart; @@ -946,9 +1029,8 @@ public class SimpleDateFormat extends DateFormat { /** * Returns the {@code DateFormatSymbols} used by this simple date format. - * + * * @return the {@code DateFormatSymbols} object. - * @since Android 1.0 */ public DateFormatSymbols getDateFormatSymbols() { // Return a clone so the arrays in the ResourceBundle are not modified @@ -961,6 +1043,7 @@ public class SimpleDateFormat extends DateFormat { + creationYear; } + // BEGIN android-added private int parse(String string, int offset, char format, int count) { int index = patternChars.indexOf(format); if (index == -1) { @@ -1085,6 +1168,7 @@ public class SimpleDateFormat extends DateFormat { } return offset; } + // END android-added /** * Parses a date from the specified string starting at the index specified @@ -1092,7 +1176,7 @@ public class SimpleDateFormat extends DateFormat { * of the {@code ParsePosition} is updated to the index following the parsed * text. On error, the index is unchanged and the error index of {@code * ParsePosition} is set to the index where the error occurred. - * + * * @param string * the string to parse using the pattern of this simple date * format. @@ -1106,10 +1190,11 @@ public class SimpleDateFormat extends DateFormat { * error. * @throws IllegalArgumentException * if there are invalid characters in the pattern. - * @since Android 1.0 */ @Override public Date parse(String string, ParsePosition position) { + // BEGIN android-changed + // Harmony delegates to ICU's SimpleDateFormat, we implement it directly boolean quote = false; int next, last = -1, count = 0, offset = position.getIndex(); int length = string.length(); @@ -1178,8 +1263,10 @@ public class SimpleDateFormat extends DateFormat { position.setIndex(offset); calendar.setTimeZone(zone); return date; + // END android-changed } + // BEGIN android-added private Number parseNumber(int max, String string, ParsePosition position) { int digit, length = string.length(), result = 0; int index = position.getIndex(); @@ -1299,6 +1386,7 @@ public class SimpleDateFormat extends DateFormat { } return -offset - 1; } + // END android-added /** * Sets the date which is the start of the one hundred year period for two @@ -1306,9 +1394,11 @@ public class SimpleDateFormat extends DateFormat { * * @param date * the new date. - * @since Android 1.0 */ public void set2DigitYearStart(Date date) { + // BEGIN android-removed + // icuFormat.set2DigitYearStart(date); + // END android-removed defaultCenturyStart = date; Calendar cal = new GregorianCalendar(); cal.setTime(date); @@ -1320,9 +1410,13 @@ public class SimpleDateFormat extends DateFormat { * * @param value * the new {@code DateFormatSymbols} object. - * @since Android 1.0 */ public void setDateFormatSymbols(DateFormatSymbols value) { + // BEGIN android-removed + // com.ibm.icu.text.DateFormatSymbols icuSymbols = new com.ibm.icu.text.DateFormatSymbols(); + // copySymbols(value, icuSymbols); + // icuFormat.setDateFormatSymbols(icuSymbols); + // END android-removed formatData = (DateFormatSymbols) value.clone(); } @@ -1331,11 +1425,12 @@ public class SimpleDateFormat extends DateFormat { * characters. * * @return the localized pattern. - * @since Android 1.0 */ public String toLocalizedPattern() { + // BEGIN android-changed return convertPattern(pattern, patternChars, formatData .getLocalPatternChars(), false); + // END android-changed } /** @@ -1343,7 +1438,6 @@ public class SimpleDateFormat extends DateFormat { * pattern characters. * * @return the non-localized pattern. - * @since Android 1.0 */ public String toPattern() { return pattern; diff --git a/text/src/main/java/java/text/StringCharacterIterator.java b/text/src/main/java/java/text/StringCharacterIterator.java index 5d02ceb..8ef0341 100644 --- a/text/src/main/java/java/text/StringCharacterIterator.java +++ b/text/src/main/java/java/text/StringCharacterIterator.java @@ -19,8 +19,6 @@ package java.text; /** * An implementation of {@link CharacterIterator} for strings. - * - * @since Android 1.0 */ public final class StringCharacterIterator implements CharacterIterator { @@ -35,7 +33,6 @@ public final class StringCharacterIterator implements CharacterIterator { * * @param value * the source string to iterate over. - * @since Android 1.0 */ public StringCharacterIterator(String value) { string = value; @@ -53,10 +50,9 @@ public final class StringCharacterIterator implements CharacterIterator { * the source string to iterate over. * @param location * the current index. - * @exception IllegalArgumentException - * if {@code location} is negative or greater than the length - * of the source string. - * @since Android 1.0 + * @throws IllegalArgumentException + * if {@code location} is negative or greater than the length + * of the source string. */ public StringCharacterIterator(String value, int location) { string = value; @@ -80,11 +76,10 @@ public final class StringCharacterIterator implements CharacterIterator { * the index one past the last character to iterate. * @param location * the current index. - * @exception IllegalArgumentException - * if {@code start < 0}, {@code start > end}, - * {@code location < start}, {@code location > end} or if - * {@code end} is greater than the length of {@code value}. - * @since Android 1.0 + * @throws IllegalArgumentException + * if {@code start < 0}, {@code start > end}, {@code location < + * start}, {@code location > end} or if {@code end} is greater + * than the length of {@code value}. */ public StringCharacterIterator(String value, int start, int end, int location) { @@ -104,7 +99,6 @@ public final class StringCharacterIterator implements CharacterIterator { * * @return a shallow copy of this iterator. * @see java.lang.Cloneable - * @since Android 1.0 */ @Override public Object clone() { @@ -120,7 +114,6 @@ public final class StringCharacterIterator implements CharacterIterator { * * @return the current character, or {@code DONE} if the current index is * past the end. - * @since Android 1.0 */ public char current() { if (offset == end) { @@ -140,7 +133,6 @@ public final class StringCharacterIterator implements CharacterIterator { * @return {@code true} if the specified object is equal to this * {@code StringCharacterIterator}; {@code false} otherwise. * @see #hashCode - * @since Android 1.0 */ @Override public boolean equals(Object object) { @@ -158,7 +150,6 @@ public final class StringCharacterIterator implements CharacterIterator { * * @return the character at the begin index or {@code DONE} if the begin * index is equal to the end index. - * @since Android 1.0 */ public char first() { if (start == end) { @@ -172,7 +163,6 @@ public final class StringCharacterIterator implements CharacterIterator { * Returns the begin index in the source string. * * @return the index of the first character of the iteration. - * @since Android 1.0 */ public int getBeginIndex() { return start; @@ -182,7 +172,6 @@ public final class StringCharacterIterator implements CharacterIterator { * Returns the end index in the source string. * * @return the index one past the last character of the iteration. - * @since Android 1.0 */ public int getEndIndex() { return end; @@ -192,7 +181,6 @@ public final class StringCharacterIterator implements CharacterIterator { * Returns the current index in the source string. * * @return the current index. - * @since Android 1.0 */ public int getIndex() { return offset; @@ -209,9 +197,8 @@ public final class StringCharacterIterator implements CharacterIterator { * * @return the character before the end index or {@code DONE} if the begin * index is equal to the end index. - * @since Android 1.0 */ - public char last() { + public char last() { if (start == end) { return DONE; } @@ -219,14 +206,13 @@ public final class StringCharacterIterator implements CharacterIterator { return string.charAt(offset); } - /** - * Increments the current index and returns the character at the new index. - * - * @return the character at the next index, or {@code DONE} if the next - * index would be past the end. - * @since Android 1.0 - */ - public char next() { + /** + * Increments the current index and returns the character at the new index. + * + * @return the character at the next index, or {@code DONE} if the next + * index would be past the end. + */ + public char next() { if (offset >= (end - 1)) { offset = end; return DONE; @@ -234,13 +220,12 @@ public final class StringCharacterIterator implements CharacterIterator { return string.charAt(++offset); } - /** - * Decrements the current index and returns the character at the new index. - * - * @return the character at the previous index, or {@code DONE} if the - * previous index would be past the beginning. - * @since Android 1.0 - */ + /** + * Decrements the current index and returns the character at the new index. + * + * @return the character at the previous index, or {@code DONE} if the + * previous index would be past the beginning. + */ public char previous() { if (offset == start) { return DONE; @@ -255,10 +240,9 @@ public final class StringCharacterIterator implements CharacterIterator { * the index the current position is set to. * @return the character at the new index, or {@code DONE} if * {@code location} is set to the end index. - * @exception IllegalArgumentException - * if {@code location} is smaller than the begin index or - * greater than the end index. - * @since Android 1.0 + * @throws IllegalArgumentException + * if {@code location} is smaller than the begin index or greater + * than the end index. */ public char setIndex(int location) { if (location < start || location > end) { @@ -277,7 +261,6 @@ public final class StringCharacterIterator implements CharacterIterator { * * @param value * the new source string. - * @since Android 1.0 */ public void setText(String value) { string = value; diff --git a/text/src/main/java/org/apache/harmony/text/BidiWrapper.java b/text/src/main/java/org/apache/harmony/text/BidiWrapper.java index 240fcdf..fac25b9 100644 --- a/text/src/main/java/org/apache/harmony/text/BidiWrapper.java +++ b/text/src/main/java/org/apache/harmony/text/BidiWrapper.java @@ -18,7 +18,8 @@ package org.apache.harmony.text; /** - * TODO: type description + * Dalvik Bidi wrapper. Derived from an old version of Harmony; today they use + * straight through to ICU4J. */ public final class BidiWrapper { diff --git a/text/src/test/java/org/apache/harmony/text/tests/java/text/BidiTest.java b/text/src/test/java/org/apache/harmony/text/tests/java/text/BidiTest.java index e3ea9dc..deef841 100644 --- a/text/src/test/java/org/apache/harmony/text/tests/java/text/BidiTest.java +++ b/text/src/test/java/org/apache/harmony/text/tests/java/text/BidiTest.java @@ -1757,8 +1757,13 @@ public class BidiTest extends TestCase { // Expected } -// Outsourced to _AndroidFailure: -// bidi.createLineBidi(2, 2); + // BEGIN android-removed + // Outsourced to _AndroidFailure: + // try { + // bidi.createLineBidi(2, 2); + // } catch (IllegalArgumentException expected) { + // } + // END android-removed try { bidi.createLineBidi(2, 4); @@ -1974,19 +1979,23 @@ public class BidiTest extends TestCase { @TestTargetNew( level = TestLevel.PARTIAL_COMPLETE, - notes = "Doesn't verify any int value between 0 and getRunCount().", + notes = "", method = "getRunLimit", args = {int.class} ) + @KnownFailure("Doesn't verify any int value between 0 and getRunCount().") public void testGetRunLimit() { bd = new Bidi("text", Bidi.DIRECTION_LEFT_TO_RIGHT); try { assertTrue(4 == bd.getRunLimit(-1)); - } catch (Exception e) { - fail("Unexpected exception: " + e); + } catch (IllegalArgumentException e) { + // Expected for illegal run limit + return; } + + fail("Expected IllegalArgumentException to be thrown for invalid run limit"); } - + @TestTargetNew( level = TestLevel.COMPLETE, notes = "", @@ -2052,13 +2061,17 @@ public class BidiTest extends TestCase { method = "Bidi", args = {java.text.AttributedCharacterIterator.class} ) + @KnownFailure("Doesn't verify any int value between 0 and getRunCount().") public void testBidiConstructor_Iterator() { AttributedString paragraph = new AttributedString("text"); bd = new Bidi(paragraph.getIterator()); try { assertTrue(4 == bd.getRunLimit(1)); - } catch (Exception e) { - fail("Unexpected exception: " + e); + } catch (IllegalArgumentException e) { + // Expected for illegal run limit + return; } + + fail("Expected IllegalArgumentException to be thrown for invalid run limit"); } } diff --git a/text/src/test/java/org/apache/harmony/text/tests/java/text/DataFormatFieldTest.java b/text/src/test/java/org/apache/harmony/text/tests/java/text/DataFormatFieldTest.java index ff05e64..ff6dd8e 100644 --- a/text/src/test/java/org/apache/harmony/text/tests/java/text/DataFormatFieldTest.java +++ b/text/src/test/java/org/apache/harmony/text/tests/java/text/DataFormatFieldTest.java @@ -207,7 +207,6 @@ public class DataFormatFieldTest extends TestCase { method = "readResolve", args = {} ) - @KnownFailure("readResolve does not work properly") public void test_readResolve() { // test for method java.lang.Object readResolve() diff --git a/text/src/test/java/org/apache/harmony/text/tests/java/text/DateFormatSymbolsTest.java b/text/src/test/java/org/apache/harmony/text/tests/java/text/DateFormatSymbolsTest.java index 4151dc8..8b97ee7 100644 --- a/text/src/test/java/org/apache/harmony/text/tests/java/text/DateFormatSymbolsTest.java +++ b/text/src/test/java/org/apache/harmony/text/tests/java/text/DateFormatSymbolsTest.java @@ -16,11 +16,14 @@ */ package org.apache.harmony.text.tests.java.text; -import dalvik.annotation.TestTargets; import dalvik.annotation.TestLevel; -import dalvik.annotation.TestTargetNew; import dalvik.annotation.TestTargetClass; +import dalvik.annotation.TestTargetNew; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; import java.text.DateFormatSymbols; import java.util.Arrays; import java.util.Locale; @@ -42,11 +45,7 @@ public class DateFormatSymbolsTest extends junit.framework.TestCase { public void test_Constructor() { // Test for method java.text.DateFormatSymbols() // Used in tests - try { - new DateFormatSymbols(); - } catch (Exception e) { - fail("Constructor failed."); - } + new DateFormatSymbols(); } /** @@ -60,11 +59,7 @@ public class DateFormatSymbolsTest extends junit.framework.TestCase { ) public void test_ConstructorLjava_util_Locale() { // Test for method java.text.DateFormatSymbols(java.util.Locale) - try { - new DateFormatSymbols(new Locale("en", "us")); - } catch (Exception e) { - fail("Constructor failed."); - } + new DateFormatSymbols(new Locale("en", "us")); } /** @@ -156,8 +151,10 @@ public class DateFormatSymbolsTest extends junit.framework.TestCase { String retVal = dfs.getLocalPatternChars(); String val = "GyMdkHmsSEDFwWahKzZ"; + // Harmony uses a different set of pattern chars + // String val = "GyMdkHmsSEDFwWahKzYeugAZvcLQqV"; - assertTrue("Returned incorrect pattern string", retVal.equals(val)); + assertEquals("Returned incorrect pattern string", val, retVal); } /** @@ -175,9 +172,9 @@ public class DateFormatSymbolsTest extends junit.framework.TestCase { String[] retVal = dfs.getMonths(); String[] val = { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", - "December", "" }; - if (retVal.length != val.length) - fail("Returned wrong array: " + retVal.length); + "December", ""}; + // Note: Harmony doesn't include "" at the end of the array + assertEquals("Returned wrong array: ", val.length, retVal.length); for (int i = 0; i < val.length; i++) assertTrue("Array values do not match", retVal[i].equals(val[i])); } @@ -196,9 +193,9 @@ public class DateFormatSymbolsTest extends junit.framework.TestCase { // java.text.DateFormatSymbols.getShortMonths() String[] retVal = dfs.getShortMonths(); String[] val = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", - "Aug", "Sep", "Oct", "Nov", "Dec", "" }; - if (retVal.length != val.length) - fail("Returned wrong array"); + "Aug", "Sep", "Oct", "Nov", "Dec", ""}; + // Note: Harmony doesn't include "" at the end of the array + assertEquals("Returned wrong array: ", val.length, retVal.length); for (int i = 0; i < val.length; i++) assertTrue("Array values do not match", retVal[i].equals(val[i])); } @@ -482,4 +479,32 @@ public class DateFormatSymbolsTest extends junit.framework.TestCase { */ protected void tearDown() { } + + @TestTargetNew( + level = TestLevel.COMPLETE, + notes = "Checks serialization mechanism.", + method = "!SerializationSelf", + args = {} + ) +[] public void test_serialization() throws Exception { + DateFormatSymbols symbols = new DateFormatSymbols(Locale.FRANCE); + String[][] zoneStrings = symbols.getZoneStrings(); + assertNotNull(zoneStrings); + + // serialize + ByteArrayOutputStream byteOStream = new ByteArrayOutputStream(); + ObjectOutputStream objectOStream = new ObjectOutputStream(byteOStream); + objectOStream.writeObject(symbols); + + // and deserialize + ObjectInputStream objectIStream = new ObjectInputStream( + new ByteArrayInputStream(byteOStream.toByteArray())); + DateFormatSymbols symbolsD = (DateFormatSymbols) objectIStream + .readObject(); + + // The associated currency will not persist + String[][] zoneStringsD = symbolsD.getZoneStrings(); + assertNotNull(zoneStringsD); + assertEquals(symbols, symbolsD); + } } diff --git a/text/src/test/java/org/apache/harmony/text/tests/java/text/DateFormatTest.java b/text/src/test/java/org/apache/harmony/text/tests/java/text/DateFormatTest.java index e70aaf2..e7609a8 100644 --- a/text/src/test/java/org/apache/harmony/text/tests/java/text/DateFormatTest.java +++ b/text/src/test/java/org/apache/harmony/text/tests/java/text/DateFormatTest.java @@ -1079,4 +1079,43 @@ public class DateFormatTest extends junit.framework.TestCase { fail("Unexpected exception " + e.toString()); } } + + /** + * @tests java.text.DateFormat#parse(String) + */ + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "", + method = "parse", + args = {java.lang.String.class} + ) + public void test_parse_LString() { + DateFormat format = DateFormat.getInstance(); + try { + format.parse("not a Date"); + fail("should throw ParseException first"); + } catch (ParseException e) { + assertNotNull(e.getMessage()); + } + } + + /** + * @tests java.text.DateFormat#setLenient(boolean) + */ + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "", + method = "setLenient", + args = {boolean.class} + ) + public void test_setLenient() { + Date d = null; + DateFormat output = new SimpleDateFormat("MM/dd/yy"); + output.setLenient(false); + try { + d = output.parse("01/01/-1"); + fail("Should throw ParseException here."); + } catch (ParseException e) {} + } + } diff --git a/text/src/test/java/org/apache/harmony/text/tests/java/text/DecimalFormatSymbolsTest.java b/text/src/test/java/org/apache/harmony/text/tests/java/text/DecimalFormatSymbolsTest.java index ce2e6d5..47107cd 100644 --- a/text/src/test/java/org/apache/harmony/text/tests/java/text/DecimalFormatSymbolsTest.java +++ b/text/src/test/java/org/apache/harmony/text/tests/java/text/DecimalFormatSymbolsTest.java @@ -149,8 +149,8 @@ public class DecimalFormatSymbolsTest extends TestCase { @KnownFailure("some locales were removed last minute in cupcake") public void test_getCurrency() { Currency currency = Currency.getInstance("USD"); - assertTrue("Returned incorrect currency", - dfsUS.getCurrency() == currency); + assertEquals("Returned incorrect currency", + dfsUS.getCurrency(), currency); // use cs_CZ instead //Currency currK = Currency.getInstance("KRW"); @@ -446,8 +446,8 @@ public class DecimalFormatSymbolsTest extends TestCase { dfs.setCurrency(currency); assertTrue("Returned incorrect currency", currency == dfs.getCurrency()); - assertTrue("Returned incorrect currency symbol", currency.getSymbol( - locale).equals(dfs.getCurrencySymbol())); + assertEquals("Returned incorrect currency symbol", currency.getSymbol( + locale), dfs.getCurrencySymbol()); assertTrue("Returned incorrect international currency symbol", currency .getCurrencyCode().equals(dfs.getInternationalCurrencySymbol())); } @@ -551,8 +551,8 @@ public class DecimalFormatSymbolsTest extends TestCase { assertTrue("Test1: Returned incorrect currency", currency == dfs .getCurrency()); - assertTrue("Test1: Returned incorrect currency symbol", currency - .getSymbol(locale).equals(dfs.getCurrencySymbol())); + assertEquals("Test1: Returned incorrect currency symbol", currency + .getSymbol(locale), dfs.getCurrencySymbol()); assertTrue("Test1: Returned incorrect international currency symbol", currency.getCurrencyCode().equals( dfs.getInternationalCurrencySymbol())); @@ -754,8 +754,43 @@ public class DecimalFormatSymbolsTest extends TestCase { i.close(); } } catch (Exception e) { - // ignore } } + assertDecimalFormatSymbolsRIFrance(dfs); + } + + static void assertDecimalFormatSymbolsRIFrance(DecimalFormatSymbols dfs) { + // Values based on Java 1.5 RI DecimalFormatSymbols for Locale.FRANCE + /* + * currency = [EUR] + * currencySymbol = [€][U+20ac] + * decimalSeparator = [,][U+002c] + * digit = [#][U+0023] + * groupingSeparator = [ ][U+00a0] + * infinity = [∞][U+221e] + * internationalCurrencySymbol = [EUR] + * minusSign = [-][U+002d] + * monetaryDecimalSeparator = [,][U+002c] + * naN = [�][U+fffd] + * patternSeparator = [;][U+003b] + * perMill = [‰][U+2030] + * percent = [%][U+0025] + * zeroDigit = [0][U+0030] + */ + assertEquals("EUR", dfs.getCurrency().getCurrencyCode()); + assertEquals("\u20AC", dfs.getCurrencySymbol()); + assertEquals(',', dfs.getDecimalSeparator()); + assertEquals('#', dfs.getDigit()); + assertEquals('\u00a0', dfs.getGroupingSeparator()); + assertEquals("\u221e", dfs.getInfinity()); + assertEquals("EUR", dfs.getInternationalCurrencySymbol()); + assertEquals('-', dfs.getMinusSign()); + assertEquals(',', dfs.getMonetaryDecimalSeparator()); + // RI's default NaN is U+FFFD, Harmony's is based on ICU + assertEquals("\uFFFD", dfs.getNaN()); + assertEquals('\u003b', dfs.getPatternSeparator()); + assertEquals('\u2030', dfs.getPerMill()); + assertEquals('%', dfs.getPercent()); + assertEquals('0', dfs.getZeroDigit()); } } diff --git a/text/src/test/java/org/apache/harmony/text/tests/java/text/DecimalFormatTest.java b/text/src/test/java/org/apache/harmony/text/tests/java/text/DecimalFormatTest.java index a802ad8..aa36abc 100644 --- a/text/src/test/java/org/apache/harmony/text/tests/java/text/DecimalFormatTest.java +++ b/text/src/test/java/org/apache/harmony/text/tests/java/text/DecimalFormatTest.java @@ -31,6 +31,7 @@ import tests.support.Support_BitSet; import tests.support.Support_DecimalFormat; import java.io.ObjectInputStream; +import java.io.IOException; import java.math.BigDecimal; import java.math.BigInteger; import java.text.AttributedCharacterIterator; @@ -40,6 +41,7 @@ import java.text.FieldPosition; import java.text.NumberFormat; import java.text.ParseException; import java.text.ParsePosition; +import java.util.BitSet; import java.util.Currency; import java.util.Locale; @@ -1495,7 +1497,7 @@ public class DecimalFormatTest extends TestCase { .t_format_with_FieldPosition(); int failCount = 0; - Support_BitSet failures = new Support_BitSet(); + BitSet failures = new BitSet(); final DecimalFormatSymbols dfs = new DecimalFormatSymbols(Locale.US); @@ -1729,7 +1731,7 @@ public class DecimalFormatTest extends TestCase { @KnownFailure("Something seems wrong with Android implementation, here!") public void test_formatJLjava_lang_StringBufferLjava_text_FieldPosition() { int failCount = 0; - Support_BitSet failures = new Support_BitSet(); + BitSet failures = new BitSet(); final DecimalFormatSymbols dfs = new DecimalFormatSymbols(Locale.US); @@ -2437,7 +2439,7 @@ public class DecimalFormatTest extends TestCase { args = {} ) @KnownFailure("a regression. This didn't fail before") - public void test_serializationHarmonyRICompatible() { + public void test_serializationHarmonyRICompatible() throws Exception { NumberFormat nf = NumberFormat.getInstance(Locale.FRANCE); DecimalFormat df = null; @@ -2455,8 +2457,6 @@ public class DecimalFormatTest extends TestCase { oinput = new ObjectInputStream(this.getClass().getResource( "/serialization/java/text/DecimalFormat.ser").openStream()); deserializedDF = (DecimalFormat) oinput.readObject(); - } catch (Exception e) { - fail("Error occurs during deserialization"); } finally { try { if (null != oinput) { @@ -2473,8 +2473,7 @@ public class DecimalFormatTest extends TestCase { assertEquals(df.getPositiveSuffix(), deserializedDF.getPositiveSuffix()); assertEquals(df.getCurrency(), deserializedDF.getCurrency()); - assertEquals(df.getDecimalFormatSymbols(), deserializedDF - .getDecimalFormatSymbols()); + DecimalFormatSymbolsTest.assertDecimalFormatSymbolsRIFrance(deserializedDF.getDecimalFormatSymbols()); assertEquals(df.getGroupingSize(), df.getGroupingSize()); assertEquals(df.getMaximumFractionDigits(), deserializedDF @@ -2545,11 +2544,7 @@ public class DecimalFormatTest extends TestCase { ) public void testSetDecimalFormatSymbolsAsNull() { // Regression for HARMONY-1070 - try { - DecimalFormat format = (DecimalFormat) DecimalFormat.getInstance(); - format.setDecimalFormatSymbols(null); - } catch (Exception e) { - fail("Unexpected exception caught: " + e); - } + DecimalFormat format = (DecimalFormat) DecimalFormat.getInstance(); + format.setDecimalFormatSymbols(null); } } diff --git a/text/src/test/java/org/apache/harmony/text/tests/java/text/MessageFormatTest.java b/text/src/test/java/org/apache/harmony/text/tests/java/text/MessageFormatTest.java index 0265a51..57a1206 100644 --- a/text/src/test/java/org/apache/harmony/text/tests/java/text/MessageFormatTest.java +++ b/text/src/test/java/org/apache/harmony/text/tests/java/text/MessageFormatTest.java @@ -145,22 +145,15 @@ public class MessageFormatTest extends TestCase { assertEquals("Simple string", "Test message", new MessageFormat( "Test message").format(new Object[0])); - try { - result = new MessageFormat("Don't").format(new Object[0]); - assertTrue("Should not throw IllegalArgumentException: " + result, + result = new MessageFormat("Don't").format(new Object[0]); + assertTrue("Should not throw IllegalArgumentException: " + result, "Dont".equals(result)); - } catch (Exception e) { - fail("Unexpected exception: " + e); - } try { new MessageFormat("Invalid {1,foobar} format descriptor!"); fail("Expected test_ConstructorLjava_lang_String to throw IAE."); } catch (IllegalArgumentException ex) { // expected - } catch (Throwable ex) { - fail("Expected test_ConstructorLjava_lang_String to throw IAE, not a " - + ex.getClass().getName()); } try { @@ -168,9 +161,6 @@ public class MessageFormatTest extends TestCase { "Invalid {1,date,invalid-spec} format descriptor!"); } catch (IllegalArgumentException ex) { // expected - } catch (Throwable ex) { - fail("Expected test_ConstructorLjava_lang_String to throw IAE, not a " - + ex.getClass().getName()); } checkSerialization(new MessageFormat("")); @@ -1177,10 +1167,10 @@ public class MessageFormatTest extends TestCase { * java.text.MessageFormat#parse(java.lang.String). */ @TestTargetNew( - level = TestLevel.COMPLETE, - notes = "", - method = "parse", - args = {java.lang.String.class} + level = TestLevel.COMPLETE, + notes = "", + method = "parse", + args = {java.lang.String.class} ) public void test_parseLjava_lang_String() throws ParseException { String pattern = "A {3, number, currency} B {2, time} C {0, number, percent} D {4} E {1,choice,0#off|1#on} F {0, date}"; @@ -1242,10 +1232,10 @@ public class MessageFormatTest extends TestCase { * argument ParsePosition as null. */ @TestTargetNew( - level = TestLevel.COMPLETE, - notes = "", - method = "parseObject", - args = {java.lang.String.class, java.text.ParsePosition.class} + level = TestLevel.COMPLETE, + notes = "", + method = "parseObject", + args = {java.lang.String.class, java.text.ParsePosition.class} ) public void test_parseObjectLjava_lang_StringLjavajava_text_ParsePosition() { MessageFormat mf = new MessageFormat("{0,number,#.##}, {0,number,#.#}"); @@ -1288,10 +1278,10 @@ public class MessageFormatTest extends TestCase { } } @TestTargetNew( - level = TestLevel.PARTIAL, - notes = "Regression test. Doesn't verifies exception.", - method = "format", - args = {java.lang.Object.class} + level = TestLevel.PARTIAL, + notes = "Regression test. Doesn't verifies exception.", + method = "format", + args = {java.lang.Object.class} ) public void test_format_Object() { // Regression for HARMONY-1875 @@ -1304,4 +1294,35 @@ public class MessageFormatTest extends TestCase { assertEquals(etalon, obj.format(new Object[] { new Date() })); } + /** + * @tests java.text.MessageFormat#parse(java.lang.String) + */ + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "", + method = "parse", + args = {java.lang.String.class} + ) + public void test_parse() throws ParseException { + // Regression for HARMONY-63 + MessageFormat mf = new MessageFormat("{0,number,#,####}", Locale.US); + Object[] res = mf.parse("1,00,00"); + assertEquals("Assert 0: incorrect size of parsed data ", 1, res.length); + assertEquals("Assert 1: parsed value incorrectly", new Long(10000), (Long)res[0]); + } + + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "", + method = "format", + args = {java.lang.String.class, java.lang.Object[].class} + ) + public void testHARMONY5323() { + Object []messageArgs = new Object[11]; + for (int i = 0; i < messageArgs.length; i++) + messageArgs[i] = "dumb"+i; + + String res = MessageFormat.format("bgcolor=\"{10}\"", messageArgs); + assertEquals(res, "bgcolor=\"dumb10\""); + } } diff --git a/text/src/test/java/org/apache/harmony/text/tests/java/text/NumberFormatTest.java b/text/src/test/java/org/apache/harmony/text/tests/java/text/NumberFormatTest.java index 93e58db..0480704 100644 --- a/text/src/test/java/org/apache/harmony/text/tests/java/text/NumberFormatTest.java +++ b/text/src/test/java/org/apache/harmony/text/tests/java/text/NumberFormatTest.java @@ -206,7 +206,7 @@ public class NumberFormatTest extends TestCase { "#,##0;#,##0-", format.toPattern()); assertEquals( "Test8: NumberFormat.getIntegerInstance(new Locale(\"ar\", \"AE\")).format(-35.76) returned wrong value", - "36-", format.format(-35.76)); + "\u0666-", format.format(-6)); assertEquals( "Test9: NumberFormat.getIntegerInstance(new Locale(\"ar\", \"AE\")).parse(\"-36-\") returned wrong number", new Long(-36), format.parse("36-")); diff --git a/text/src/test/java/org/apache/harmony/text/tests/java/text/ParsePositionTest.java b/text/src/test/java/org/apache/harmony/text/tests/java/text/ParsePositionTest.java index 9c1fb21..89cb7e4 100644 --- a/text/src/test/java/org/apache/harmony/text/tests/java/text/ParsePositionTest.java +++ b/text/src/test/java/org/apache/harmony/text/tests/java/text/ParsePositionTest.java @@ -39,15 +39,10 @@ public class ParsePositionTest extends junit.framework.TestCase { ) public void test_ConstructorI() { // Test for method java.text.ParsePosition(int) - try { - ParsePosition pp1 = new ParsePosition(Integer.MIN_VALUE); - assertTrue("Initialization failed.", - pp1.getIndex() == Integer.MIN_VALUE); - assertEquals("Initialization failed.", -1, pp1.getErrorIndex()); - } catch (Exception e) { - fail("Constructor failed."); - } - + ParsePosition pp1 = new ParsePosition(Integer.MIN_VALUE); + assertTrue("Initialization failed.", + pp1.getIndex() == Integer.MIN_VALUE); + assertEquals("Initialization failed.", -1, pp1.getErrorIndex()); } /** diff --git a/text/src/test/java/org/apache/harmony/text/tests/java/text/Support_DecimalFormat.java b/text/src/test/java/org/apache/harmony/text/tests/java/text/Support_DecimalFormat.java new file mode 100644 index 0000000..2fe1107 --- /dev/null +++ b/text/src/test/java/org/apache/harmony/text/tests/java/text/Support_DecimalFormat.java @@ -0,0 +1,287 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.harmony.text.tests.java.text; + +import java.text.DecimalFormat; +import java.text.NumberFormat; +import java.util.Locale; +import java.util.Vector; + + +public class Support_DecimalFormat extends Support_Format { + + public Support_DecimalFormat(String p1) { + super(p1); + } + + @Override + public void runTest() { + t_formatToCharacterIterator(); + t_format_with_FieldPosition(); + } + + public static void main(String[] args) { + new Support_DecimalFormat("").runTest(); + } + + public void t_format_with_FieldPosition() { + DecimalFormat format = (DecimalFormat) NumberFormat + .getCurrencyInstance(Locale.US); + Number number = new Double(10000000.76); + String text = "$10,000,000.76"; + + t_FormatWithField(0, format, number, text, NumberFormat.Field.CURRENCY, + 0, 1); + t_FormatWithField(1, format, number, text, NumberFormat.Field.INTEGER, + 1, 11); + t_FormatWithField(2, format, number, text, + NumberFormat.Field.GROUPING_SEPARATOR, 3, 4); + t_FormatWithField(3, format, number, text, + NumberFormat.Field.DECIMAL_SEPARATOR, 11, 12); + t_FormatWithField(4, format, number, text, NumberFormat.Field.FRACTION, + 12, 14); + + // test fields that are not included in the formatted text + t_FormatWithField(5, format, number, text, NumberFormat.Field.SIGN, 0, + 0); + t_FormatWithField(6, format, number, text, NumberFormat.Field.EXPONENT, + 0, 0); + t_FormatWithField(7, format, number, text, + NumberFormat.Field.EXPONENT_SIGN, 0, 0); + t_FormatWithField(8, format, number, text, + NumberFormat.Field.EXPONENT_SYMBOL, 0, 0); + t_FormatWithField(9, format, number, text, NumberFormat.Field.PERCENT, + 0, 0); + t_FormatWithField(10, format, number, text, + NumberFormat.Field.PERMILLE, 0, 0); + + // test Exponential + format = new DecimalFormat("000000000.0#E0"); + text = "100000007.6E-1"; + t_FormatWithField(11, format, number, text, NumberFormat.Field.INTEGER, + 0, 9); + t_FormatWithField(12, format, number, text, + NumberFormat.Field.DECIMAL_SEPARATOR, 9, 10); + t_FormatWithField(13, format, number, text, + NumberFormat.Field.FRACTION, 10, 11); + t_FormatWithField(14, format, number, text, + NumberFormat.Field.EXPONENT_SYMBOL, 11, 12); + t_FormatWithField(15, format, number, text, + NumberFormat.Field.EXPONENT_SIGN, 12, 13); + t_FormatWithField(16, format, number, text, + NumberFormat.Field.EXPONENT, 13, 14); + + // test fields that are not included in the formatted text + t_FormatWithField(17, format, number, text, + NumberFormat.Field.GROUPING_SEPARATOR, 0, 0); + t_FormatWithField(18, format, number, text, NumberFormat.Field.SIGN, 0, + 0); + t_FormatWithField(19, format, number, text, + NumberFormat.Field.CURRENCY, 0, 0); + t_FormatWithField(20, format, number, text, NumberFormat.Field.PERCENT, + 0, 0); + t_FormatWithField(21, format, number, text, + NumberFormat.Field.PERMILLE, 0, 0); + + // test currency instance with TR Locale + number = new Double(350.76); + format = (DecimalFormat) NumberFormat.getCurrencyInstance(new Locale( + "tr", "TR")); + text = "351 TL"; + t_FormatWithField(22, format, number, text, NumberFormat.Field.INTEGER, + 0, 3); + t_FormatWithField(23, format, number, text, + NumberFormat.Field.CURRENCY, 4, 6); + + // test fields that are not included in the formatted text + t_FormatWithField(25, format, number, text, + NumberFormat.Field.GROUPING_SEPARATOR, 0, 0); + t_FormatWithField(26, format, number, text, + NumberFormat.Field.DECIMAL_SEPARATOR, 0, 0); + t_FormatWithField(27, format, number, text, NumberFormat.Field.SIGN, 0, + 0); + t_FormatWithField(28, format, number, text, + NumberFormat.Field.EXPONENT, 0, 0); + t_FormatWithField(29, format, number, text, + NumberFormat.Field.EXPONENT_SIGN, 0, 0); + t_FormatWithField(30, format, number, text, + NumberFormat.Field.EXPONENT_SYMBOL, 0, 0); + t_FormatWithField(31, format, number, text, NumberFormat.Field.PERCENT, + 0, 0); + t_FormatWithField(32, format, number, text, + NumberFormat.Field.PERMILLE, 0, 0); + + } + + public void t_formatToCharacterIterator() { + + Number number = new Double(350.76); + Number negativeNumber = new Double(-350.76); + + Locale us = Locale.US; + Locale tr = new Locale("tr", "TR"); + + // test number instance + t_Format(1, number, NumberFormat.getNumberInstance(us), + getNumberVectorUS()); + + // test integer instance + // testFormat(2, number, NumberFormat.getIntegerInstance(us), + // getPercentVectorUS()); + + // test percent instance + t_Format(3, number, NumberFormat.getPercentInstance(us), + getPercentVectorUS()); + + // test permille pattern + DecimalFormat format = new DecimalFormat("###0.##\u2030"); + t_Format(4, number, format, getPermilleVector()); + + // test exponential pattern with positive exponent + format = new DecimalFormat("00.0#E0"); + t_Format(5, number, format, getPositiveExponentVector()); + + // test exponential pattern with negative exponent + format = new DecimalFormat("0000.0#E0"); + t_Format(6, number, format, getNegativeExponentVector()); + + // test currency instance with US Locale + t_Format(7, number, NumberFormat.getCurrencyInstance(us), + getPositiveCurrencyVectorUS()); + + // test negative currency instance with US Locale + t_Format(8, negativeNumber, NumberFormat.getCurrencyInstance(us), + getNegativeCurrencyVectorUS()); + + // test currency instance with TR Locale + t_Format(9, number, NumberFormat.getCurrencyInstance(tr), + getPositiveCurrencyVectorTR()); + + // test negative currency instance with TR Locale + t_Format(10, negativeNumber, NumberFormat.getCurrencyInstance(tr), + getNegativeCurrencyVectorTR()); + + // test multiple grouping seperators + number = new Long(100300400); + t_Format(11, number, NumberFormat.getNumberInstance(us), + getNumberVector2US()); + + // test 0 + number = new Long(0); + t_Format(12, number, NumberFormat.getNumberInstance(us), + getZeroVector()); + } + + private static Vector<FieldContainer> getNumberVectorUS() { + Vector<FieldContainer> v = new Vector<FieldContainer>(); + v.add(new FieldContainer(0, 3, NumberFormat.Field.INTEGER)); + v.add(new FieldContainer(3, 4, NumberFormat.Field.DECIMAL_SEPARATOR)); + v.add(new FieldContainer(4, 6, NumberFormat.Field.FRACTION)); + return v; + } + + private static Vector<FieldContainer> getPositiveCurrencyVectorTR() { + Vector<FieldContainer> v = new Vector<FieldContainer>(); + v.add(new FieldContainer(0, 3, NumberFormat.Field.INTEGER)); + v.add(new FieldContainer(4, 6, NumberFormat.Field.CURRENCY)); + return v; + } + + private static Vector<FieldContainer> getNegativeCurrencyVectorTR() { + Vector<FieldContainer> v = new Vector<FieldContainer>(); + v.add(new FieldContainer(0, 1, NumberFormat.Field.SIGN)); + v.add(new FieldContainer(1, 4, NumberFormat.Field.INTEGER)); + v.add(new FieldContainer(5, 7, NumberFormat.Field.CURRENCY)); + return v; + } + + private static Vector<FieldContainer> getPositiveCurrencyVectorUS() { + Vector<FieldContainer> v = new Vector<FieldContainer>(); + v.add(new FieldContainer(0, 1, NumberFormat.Field.CURRENCY)); + v.add(new FieldContainer(1, 4, NumberFormat.Field.INTEGER)); + v.add(new FieldContainer(4, 5, NumberFormat.Field.DECIMAL_SEPARATOR)); + v.add(new FieldContainer(5, 7, NumberFormat.Field.FRACTION)); + return v; + } + + private static Vector<FieldContainer> getNegativeCurrencyVectorUS() { + Vector<FieldContainer> v = new Vector<FieldContainer>(); + v.add(new FieldContainer(1, 2, NumberFormat.Field.CURRENCY)); + v.add(new FieldContainer(2, 5, NumberFormat.Field.INTEGER)); + v.add(new FieldContainer(5, 6, NumberFormat.Field.DECIMAL_SEPARATOR)); + v.add(new FieldContainer(6, 8, NumberFormat.Field.FRACTION)); + return v; + } + + private static Vector<FieldContainer> getPercentVectorUS() { + Vector<FieldContainer> v = new Vector<FieldContainer>(); + v.add(new FieldContainer(0, 2, NumberFormat.Field.INTEGER)); + v.add(new FieldContainer(2, 3, NumberFormat.Field.INTEGER)); + v.add(new FieldContainer(2, 3, NumberFormat.Field.GROUPING_SEPARATOR)); + v.add(new FieldContainer(3, 6, NumberFormat.Field.INTEGER)); + v.add(new FieldContainer(6, 7, NumberFormat.Field.PERCENT)); + return v; + } + + private static Vector<FieldContainer> getPermilleVector() { + Vector<FieldContainer> v = new Vector<FieldContainer>(); + v.add(new FieldContainer(0, 6, NumberFormat.Field.INTEGER)); + v.add(new FieldContainer(6, 7, NumberFormat.Field.PERMILLE)); + return v; + } + + private static Vector<FieldContainer> getNegativeExponentVector() { + Vector<FieldContainer> v = new Vector<FieldContainer>(); + v.add(new FieldContainer(0, 4, NumberFormat.Field.INTEGER)); + v.add(new FieldContainer(4, 5, NumberFormat.Field.DECIMAL_SEPARATOR)); + v.add(new FieldContainer(5, 6, NumberFormat.Field.FRACTION)); + v.add(new FieldContainer(6, 7, NumberFormat.Field.EXPONENT_SYMBOL)); + v.add(new FieldContainer(7, 8, NumberFormat.Field.EXPONENT_SIGN)); + v.add(new FieldContainer(8, 9, NumberFormat.Field.EXPONENT)); + return v; + } + + private static Vector<FieldContainer> getPositiveExponentVector() { + Vector<FieldContainer> v = new Vector<FieldContainer>(); + v.add(new FieldContainer(0, 2, NumberFormat.Field.INTEGER)); + v.add(new FieldContainer(2, 3, NumberFormat.Field.DECIMAL_SEPARATOR)); + v.add(new FieldContainer(3, 5, NumberFormat.Field.FRACTION)); + v.add(new FieldContainer(5, 6, NumberFormat.Field.EXPONENT_SYMBOL)); + v.add(new FieldContainer(6, 7, NumberFormat.Field.EXPONENT)); + return v; + } + + private static Vector<FieldContainer> getNumberVector2US() { + Vector<FieldContainer> v = new Vector<FieldContainer>(); + v.add(new FieldContainer(0, 3, NumberFormat.Field.INTEGER)); + v.add(new FieldContainer(3, 4, NumberFormat.Field.GROUPING_SEPARATOR)); + v.add(new FieldContainer(3, 4, NumberFormat.Field.INTEGER)); + v.add(new FieldContainer(4, 7, NumberFormat.Field.INTEGER)); + v.add(new FieldContainer(7, 8, NumberFormat.Field.GROUPING_SEPARATOR)); + v.add(new FieldContainer(7, 8, NumberFormat.Field.INTEGER)); + v.add(new FieldContainer(8, 11, NumberFormat.Field.INTEGER)); + return v; + } + + private static Vector<FieldContainer> getZeroVector() { + Vector<FieldContainer> v = new Vector<FieldContainer>(); + v.add(new FieldContainer(0, 1, NumberFormat.Field.INTEGER)); + return v; + } + +} diff --git a/text/src/test/java/org/apache/harmony/text/tests/java/text/Support_Format.java b/text/src/test/java/org/apache/harmony/text/tests/java/text/Support_Format.java new file mode 100644 index 0000000..ffcdf1c --- /dev/null +++ b/text/src/test/java/org/apache/harmony/text/tests/java/text/Support_Format.java @@ -0,0 +1,143 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.harmony.text.tests.java.text; + +import java.text.AttributedCharacterIterator; +import java.text.FieldPosition; +import java.text.Format; +import java.text.AttributedCharacterIterator.Attribute; +import java.util.Iterator; +import java.util.Vector; +import junit.framework.TestCase; + +public class Support_Format extends TestCase { + + protected String text; + + public Support_Format(String p1) { + super(p1); + } + + protected void t_FormatWithField(int count, Format format, Object object, + String text, Format.Field field, int begin, int end) { + StringBuffer buffer = new StringBuffer(); + FieldPosition pos = new FieldPosition(field); + format.format(object, buffer, pos); + + // System.out.println(buffer); + // System.out.println(pos); + + if (text == null) { + assertEquals("Test " + count + ": incorrect formatted text", + this.text, buffer.toString()); + } else { + assertEquals("Test " + count + ": incorrect formatted text", text, + buffer.toString()); + } + + assertEquals("Test " + count + ": incorrect begin index for field " + + field, begin, pos.getBeginIndex()); + assertEquals("Test " + count + ": incorrect end index for field" + + field, end, pos.getEndIndex()); + } + + protected void t_Format(int count, Object object, Format format, + Vector<FieldContainer> expectedResults) { + // System.out.println(format.format(object)); + Vector<FieldContainer> results = findFields(format.formatToCharacterIterator(object)); + assertTrue("Test " + count + + ": Format returned incorrect CharacterIterator for " + + format.format(object), compare(results, expectedResults)); + } + + /** + * compares two vectors regardless of the order of their elements + */ + protected static boolean compare(Vector<FieldContainer> vector1, Vector<FieldContainer> vector2) { + return vector1.size() == vector2.size() && vector1.containsAll(vector2); + } + + /** + * finds attributes with regards to char index in this + * AttributedCharacterIterator, and puts them in a vector + * + * @param iterator + * @return a vector, each entry in this vector are of type FieldContainer , + * which stores start and end indexes and an attribute this range + * has + */ + protected static Vector<FieldContainer> findFields(AttributedCharacterIterator iterator) { + Vector<FieldContainer> result = new Vector<FieldContainer>(); + while (iterator.getIndex() != iterator.getEndIndex()) { + int start = iterator.getRunStart(); + int end = iterator.getRunLimit(); + + Iterator<Attribute> it = iterator.getAttributes().keySet().iterator(); + while (it.hasNext()) { + AttributedCharacterIterator.Attribute attribute = it.next(); + Object value = iterator.getAttribute(attribute); + result.add(new FieldContainer(start, end, attribute, value)); + // System.out.println(start + " " + end + ": " + attribute + ", + // " + value ); + // System.out.println("v.add(new FieldContainer(" + start +"," + + // end +"," + attribute+ "," + value+ "));"); + } + iterator.setIndex(end); + } + return result; + } + + protected static class FieldContainer { + int start, end; + + AttributedCharacterIterator.Attribute attribute; + + Object value; + + // called from support_decimalformat and support_simpledateformat tests + public FieldContainer(int start, int end, + AttributedCharacterIterator.Attribute attribute) { + this(start, end, attribute, attribute); + } + + // called from support_messageformat tests + public FieldContainer(int start, int end, Attribute attribute, int value) { + this(start, end, attribute, new Integer(value)); + } + + // called from support_messageformat tests + public FieldContainer(int start, int end, Attribute attribute, + Object value) { + this.start = start; + this.end = end; + this.attribute = attribute; + this.value = value; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof FieldContainer)) { + return false; + } + + FieldContainer fc = (FieldContainer) obj; + return (start == fc.start && end == fc.end + && attribute == fc.attribute && value.equals(fc.value)); + } + } +} diff --git a/text/src/test/java/org/apache/harmony/text/tests/java/text/Support_MessageFormat.java b/text/src/test/java/org/apache/harmony/text/tests/java/text/Support_MessageFormat.java new file mode 100644 index 0000000..454caeb --- /dev/null +++ b/text/src/test/java/org/apache/harmony/text/tests/java/text/Support_MessageFormat.java @@ -0,0 +1,120 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.harmony.text.tests.java.text; + +import java.text.DateFormat; +import java.text.MessageFormat; +import java.text.NumberFormat; +import java.text.MessageFormat.Field; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.Locale; +import java.util.Vector; + + +public class Support_MessageFormat extends Support_Format { + + public Support_MessageFormat(String p1) { + super(p1); + } + + @Override + public void runTest() { + t_formatToCharacterIterator(); + t_format_with_FieldPosition(); + } + + public static void main(String[] args) { + new Support_MessageFormat("").runTest(); + } + + public void t_format_with_FieldPosition() { + + String pattern = "On {4,date} at {3,time}, he ate {2,number, integer} hamburger{2,choice,1#|1<s} and drank {1, number} litres of coke. That was {0,choice,1#just enough|1<more than enough} food!"; + MessageFormat format = new MessageFormat(pattern, Locale.US); + + Date date = new GregorianCalendar(2005, 1, 28, 14, 20, 16).getTime(); + Integer hamburgers = new Integer(8); + Object[] objects = new Object[] { hamburgers, new Double(3.5), + hamburgers, date, date }; + + super.text = "On Feb 28, 2005 at 2:20:16 PM, he ate 8 hamburgers and drank 3.5 litres of coke. That was more than enough food!"; + + // test with MessageFormat.Field.ARGUMENT + t_FormatWithField(1, format, objects, null, Field.ARGUMENT, 3, 15); + + // test other format fields that are included in the formatted text + t_FormatWithField(2, format, objects, null, DateFormat.Field.AM_PM, 0, + 0); + t_FormatWithField(3, format, objects, null, + NumberFormat.Field.FRACTION, 0, 0); + + // test fields that are not included in the formatted text + t_FormatWithField(4, format, objects, null, DateFormat.Field.ERA, 0, 0); + t_FormatWithField(5, format, objects, null, + NumberFormat.Field.EXPONENT_SIGN, 0, 0); + } + + public void t_formatToCharacterIterator() { + + String pattern = "On {4,date} at {3,time}, he ate {2,number, integer} hamburger{2,choice,1#|1<s} and drank {1, number} litres of coke. That was {0,choice,1#just enough|1<more than enough} food!"; + MessageFormat format = new MessageFormat(pattern, Locale.US); + + Date date = new GregorianCalendar(2005, 1, 28, 14, 20, 16).getTime(); + Integer hamburgers = new Integer(8); + Object[] objects = new Object[] { hamburgers, new Double(3.5), + hamburgers, date, date }; + + t_Format(1, objects, format, getMessageVector1()); + } + + private Vector<FieldContainer> getMessageVector1() { + Vector<FieldContainer> v = new Vector<FieldContainer>(); + v.add(new FieldContainer(3, 6, Field.ARGUMENT, 4)); + v.add(new FieldContainer(3, 6, DateFormat.Field.MONTH)); + v.add(new FieldContainer(6, 7, Field.ARGUMENT, 4)); + v.add(new FieldContainer(7, 9, Field.ARGUMENT, 4)); + v.add(new FieldContainer(7, 9, DateFormat.Field.DAY_OF_MONTH)); + v.add(new FieldContainer(9, 11, Field.ARGUMENT, 4)); + v.add(new FieldContainer(11, 15, Field.ARGUMENT, 4)); + v.add(new FieldContainer(11, 15, DateFormat.Field.YEAR)); + v.add(new FieldContainer(19, 20, Field.ARGUMENT, 3)); + v.add(new FieldContainer(19, 20, DateFormat.Field.HOUR1)); + v.add(new FieldContainer(20, 21, Field.ARGUMENT, 3)); + v.add(new FieldContainer(21, 23, Field.ARGUMENT, 3)); + v.add(new FieldContainer(21, 23, DateFormat.Field.MINUTE)); + v.add(new FieldContainer(23, 24, Field.ARGUMENT, 3)); + v.add(new FieldContainer(24, 26, Field.ARGUMENT, 3)); + v.add(new FieldContainer(24, 26, DateFormat.Field.SECOND)); + v.add(new FieldContainer(26, 27, Field.ARGUMENT, 3)); + v.add(new FieldContainer(27, 29, Field.ARGUMENT, 3)); + v.add(new FieldContainer(27, 29, DateFormat.Field.AM_PM)); + v.add(new FieldContainer(38, 39, Field.ARGUMENT, 2)); + v.add(new FieldContainer(38, 39, NumberFormat.Field.INTEGER)); + v.add(new FieldContainer(49, 50, Field.ARGUMENT, 2)); + v.add(new FieldContainer(61, 62, Field.ARGUMENT, 1)); + v.add(new FieldContainer(61, 62, NumberFormat.Field.INTEGER)); + v.add(new FieldContainer(62, 63, Field.ARGUMENT, 1)); + v.add(new FieldContainer(62, 63, NumberFormat.Field.DECIMAL_SEPARATOR)); + v.add(new FieldContainer(63, 64, Field.ARGUMENT, 1)); + v.add(new FieldContainer(63, 64, NumberFormat.Field.FRACTION)); + v.add(new FieldContainer(90, 106, Field.ARGUMENT, 0)); + return v; + } + +} diff --git a/text/src/test/java/org/apache/harmony/text/tests/java/text/Support_SimpleDateFormat.java b/text/src/test/java/org/apache/harmony/text/tests/java/text/Support_SimpleDateFormat.java new file mode 100644 index 0000000..24a436b --- /dev/null +++ b/text/src/test/java/org/apache/harmony/text/tests/java/text/Support_SimpleDateFormat.java @@ -0,0 +1,266 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.harmony.text.tests.java.text; + +import java.text.DateFormat; +import java.text.NumberFormat; +import java.text.SimpleDateFormat; +import java.text.DateFormat.Field; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.Locale; +import java.util.TimeZone; +import java.util.Vector; + +import org.apache.harmony.text.tests.java.text.Support_Format.FieldContainer; + + +public class Support_SimpleDateFormat extends Support_Format { + + public Support_SimpleDateFormat(String p1) { + super(p1); + } + + @Override + public void runTest() { + t_formatToCharacterIterator(); + t_format_with_FieldPosition(); + } + + public static void main(String[] args) { + new Support_SimpleDateFormat("").runTest(); + } + + public void t_format_with_FieldPosition() { + TimeZone tz = TimeZone.getTimeZone("EST"); + Calendar cal = new GregorianCalendar(tz); + cal.set(1999, Calendar.SEPTEMBER, 13, 17, 19, 01); + cal.set(Calendar.MILLISECOND, 0); + Date date = cal.getTime(); + SimpleDateFormat format = (SimpleDateFormat) DateFormat + .getDateInstance(DateFormat.DEFAULT, Locale.US); + format.setTimeZone(tz); + + // test with all pattern chars, and multiple occurances + format + .applyPattern("G GGGG y yy yyyy M MM MMM MMMM d dd ddd k kk kkk H HH HHH h hh hhh m mmm s ss sss S SS SSS EE EEEE D DD DDD F FF w www W WWW a aaa K KKK z zzzz Z ZZZZ"); + + StringBuffer textbuffer = new StringBuffer( + "AD Anno Domini 99 99 1999 9 09 Sep September 13 13 013 17 17 017 17 17 017 5 05"); + textbuffer + .append(" 005 19 019 1 01 001 0 00 000 Mon Monday 256 256 256 2 02 38 038 3 003 PM"); + textbuffer.append(" PM 5 005 GMT-05:00 GMT-05:00 -0500 GMT-05:00"); + + // to avoid passing the huge Stringbuffer each time. + super.text = textbuffer.toString(); + + // test if field positions are set correctly for these fields occuring + // multiple times. + t_FormatWithField(0, format, date, null, Field.ERA, 0, 2); + t_FormatWithField(1, format, date, null, Field.YEAR, 15, 17); + t_FormatWithField(2, format, date, null, Field.MONTH, 26, 27); + t_FormatWithField(3, format, date, null, Field.DAY_OF_MONTH, 45, 47); + t_FormatWithField(4, format, date, null, Field.HOUR_OF_DAY1, 55, 57); + t_FormatWithField(5, format, date, null, Field.HOUR_OF_DAY0, 65, 67); + t_FormatWithField(6, format, date, null, Field.HOUR1, 75, 76); + t_FormatWithField(7, format, date, null, Field.MINUTE, 84, 86); + t_FormatWithField(8, format, date, null, Field.SECOND, 91, 92); + t_FormatWithField(9, format, date, null, Field.MILLISECOND, 100, 101); + t_FormatWithField(10, format, date, null, Field.DAY_OF_WEEK, 109, 112); + t_FormatWithField(11, format, date, null, Field.DAY_OF_YEAR, 120, 123); + t_FormatWithField(12, format, date, null, Field.DAY_OF_WEEK_IN_MONTH, + 132, 133); + t_FormatWithField(13, format, date, null, Field.WEEK_OF_YEAR, 137, 139); + t_FormatWithField(14, format, date, null, Field.WEEK_OF_MONTH, 144, 145); + t_FormatWithField(15, format, date, null, Field.AM_PM, 150, 152); + t_FormatWithField(16, format, date, null, Field.HOUR0, 158, 159); + t_FormatWithField(17, format, date, null, Field.TIME_ZONE, 164, 173); + + // test fields that are not included in the formatted text + t_FormatWithField(18, format, date, null, + NumberFormat.Field.EXPONENT_SIGN, 0, 0); + + // test with simple example + format.applyPattern("h:m z"); + + super.text = "5:19 GMT-05:00"; + t_FormatWithField(21, format, date, null, Field.HOUR1, 0, 1); + t_FormatWithField(22, format, date, null, Field.MINUTE, 2, 4); + t_FormatWithField(23, format, date, null, Field.TIME_ZONE, 5, 14); + + // test fields that are not included in the formatted text + + t_FormatWithField(24, format, date, null, Field.ERA, 0, 0); + t_FormatWithField(25, format, date, null, Field.YEAR, 0, 0); + t_FormatWithField(26, format, date, null, Field.MONTH, 0, 0); + t_FormatWithField(27, format, date, null, Field.DAY_OF_MONTH, 0, 0); + t_FormatWithField(28, format, date, null, Field.HOUR_OF_DAY1, 0, 0); + t_FormatWithField(29, format, date, null, Field.HOUR_OF_DAY0, 0, 0); + t_FormatWithField(30, format, date, null, Field.SECOND, 0, 0); + t_FormatWithField(31, format, date, null, Field.MILLISECOND, 0, 0); + t_FormatWithField(32, format, date, null, Field.DAY_OF_WEEK, 0, 0); + t_FormatWithField(33, format, date, null, Field.DAY_OF_YEAR, 0, 0); + t_FormatWithField(34, format, date, null, Field.DAY_OF_WEEK_IN_MONTH, + 0, 0); + t_FormatWithField(35, format, date, null, Field.WEEK_OF_YEAR, 0, 0); + t_FormatWithField(36, format, date, null, Field.WEEK_OF_MONTH, 0, 0); + t_FormatWithField(37, format, date, null, Field.AM_PM, 0, 0); + t_FormatWithField(38, format, date, null, Field.HOUR0, 0, 0); + + t_FormatWithField(39, format, date, null, NumberFormat.Field.EXPONENT, + 0, 0); + + // test with simple example with pattern char Z + format.applyPattern("h:m Z z"); + super.text = "5:19 -0500 GMT-05:00"; + t_FormatWithField(40, format, date, null, Field.HOUR1, 0, 1); + t_FormatWithField(41, format, date, null, Field.MINUTE, 2, 4); + t_FormatWithField(42, format, date, null, Field.TIME_ZONE, 5, 10); + } + + public void t_formatToCharacterIterator() { + TimeZone tz = TimeZone.getTimeZone("EST"); + Calendar cal = new GregorianCalendar(tz); + cal.set(1999, Calendar.SEPTEMBER, 13, 17, 19, 01); + cal.set(Calendar.MILLISECOND, 0); + Date date = cal.getTime(); + SimpleDateFormat format = (SimpleDateFormat) DateFormat + .getDateInstance(DateFormat.DEFAULT, Locale.US); + format.setTimeZone(tz); + + format.applyPattern("yyyyMMddHHmmss"); + t_Format(1, date, format, getDateVector1()); + + format.applyPattern("w W dd MMMM yyyy EEEE"); + t_Format(2, date, format, getDateVector2()); + + format.applyPattern("h:m z"); + t_Format(3, date, format, getDateVector3()); + + format.applyPattern("h:m Z"); + t_Format(5, date, format, getDateVector5()); + + // with all pattern chars, and multiple occurances + format + .applyPattern("G GGGG y yy yyyy M MM MMM MMMM d dd ddd k kk kkk H HH HHH h hh hhh m mmm s ss sss S SS SSS EE EEEE D DD DDD F FF w www W WWW a aaa K KKK z zzzz Z ZZZZ"); + t_Format(4, date, format, getDateVector4()); + } + + private Vector<FieldContainer> getDateVector1() { + // "19990913171901" + Vector<FieldContainer> v = new Vector<FieldContainer>(); + v.add(new FieldContainer(0, 4, Field.YEAR)); + v.add(new FieldContainer(4, 6, Field.MONTH)); + v.add(new FieldContainer(6, 8, Field.DAY_OF_MONTH)); + v.add(new FieldContainer(8, 10, Field.HOUR_OF_DAY0)); + v.add(new FieldContainer(10, 12, Field.MINUTE)); + v.add(new FieldContainer(12, 14, Field.SECOND)); + return v; + } + + private Vector<FieldContainer> getDateVector2() { + // "12 3 5 March 2002 Monday" + Vector<FieldContainer> v = new Vector<FieldContainer>(); + v.add(new FieldContainer(0, 2, Field.WEEK_OF_YEAR)); + v.add(new FieldContainer(3, 4, Field.WEEK_OF_MONTH)); + v.add(new FieldContainer(5, 7, Field.DAY_OF_MONTH)); + v.add(new FieldContainer(8, 17, Field.MONTH)); + v.add(new FieldContainer(18, 22, Field.YEAR)); + v.add(new FieldContainer(23, 29, Field.DAY_OF_WEEK)); + return v; + } + + private Vector<FieldContainer> getDateVector3() { + // "5:19 EDT" + Vector<FieldContainer> v = new Vector<FieldContainer>(); + v.add(new FieldContainer(0, 1, Field.HOUR1)); + v.add(new FieldContainer(2, 4, Field.MINUTE)); + v.add(new FieldContainer(5, 14, Field.TIME_ZONE)); + return v; + } + + private Vector<FieldContainer> getDateVector5() { + // "5:19 -0400" + Vector<FieldContainer> v = new Vector<FieldContainer>(); + v.add(new FieldContainer(0, 1, Field.HOUR1)); + v.add(new FieldContainer(2, 4, Field.MINUTE)); + v.add(new FieldContainer(5, 10, Field.TIME_ZONE)); + return v; + } + + private Vector<FieldContainer> getDateVector4() { + Vector<FieldContainer> v = new Vector<FieldContainer>(); + + // "AD AD 99 99 1999 9 09 Sep September 13 13 013 17 17 017 17 17 017 5 + // 05 + // 005 19 019 1 01 001 0 00 000 Mon Monday 256 256 256 2 02 38 038 3 003 + // PM + // PM 5 005 EDT Eastern Daylight Time -0400 -0400" + v.add(new FieldContainer(0, 2, Field.ERA)); + v.add(new FieldContainer(3, 5, Field.ERA)); + v.add(new FieldContainer(6, 8, Field.YEAR)); + v.add(new FieldContainer(9, 11, Field.YEAR)); + v.add(new FieldContainer(12, 16, Field.YEAR)); + v.add(new FieldContainer(17, 18, Field.MONTH)); + v.add(new FieldContainer(19, 21, Field.MONTH)); + v.add(new FieldContainer(22, 25, Field.MONTH)); + v.add(new FieldContainer(26, 35, Field.MONTH)); + v.add(new FieldContainer(36, 38, Field.DAY_OF_MONTH)); + v.add(new FieldContainer(39, 41, Field.DAY_OF_MONTH)); + v.add(new FieldContainer(42, 45, Field.DAY_OF_MONTH)); + v.add(new FieldContainer(46, 48, Field.HOUR_OF_DAY1)); + v.add(new FieldContainer(49, 51, Field.HOUR_OF_DAY1)); + v.add(new FieldContainer(52, 55, Field.HOUR_OF_DAY1)); + v.add(new FieldContainer(56, 58, Field.HOUR_OF_DAY0)); + v.add(new FieldContainer(59, 61, Field.HOUR_OF_DAY0)); + v.add(new FieldContainer(62, 65, Field.HOUR_OF_DAY0)); + v.add(new FieldContainer(66, 67, Field.HOUR1)); + v.add(new FieldContainer(68, 70, Field.HOUR1)); + v.add(new FieldContainer(71, 74, Field.HOUR1)); + v.add(new FieldContainer(75, 77, Field.MINUTE)); + v.add(new FieldContainer(78, 81, Field.MINUTE)); + v.add(new FieldContainer(82, 83, Field.SECOND)); + v.add(new FieldContainer(84, 86, Field.SECOND)); + v.add(new FieldContainer(87, 90, Field.SECOND)); + v.add(new FieldContainer(91, 92, Field.MILLISECOND)); + v.add(new FieldContainer(93, 95, Field.MILLISECOND)); + v.add(new FieldContainer(96, 99, Field.MILLISECOND)); + v.add(new FieldContainer(100, 103, Field.DAY_OF_WEEK)); + v.add(new FieldContainer(104, 110, Field.DAY_OF_WEEK)); + v.add(new FieldContainer(111, 114, Field.DAY_OF_YEAR)); + v.add(new FieldContainer(115, 118, Field.DAY_OF_YEAR)); + v.add(new FieldContainer(119, 122, Field.DAY_OF_YEAR)); + v.add(new FieldContainer(123, 124, Field.DAY_OF_WEEK_IN_MONTH)); + v.add(new FieldContainer(125, 127, Field.DAY_OF_WEEK_IN_MONTH)); + v.add(new FieldContainer(128, 130, Field.WEEK_OF_YEAR)); + v.add(new FieldContainer(131, 134, Field.WEEK_OF_YEAR)); + v.add(new FieldContainer(135, 136, Field.WEEK_OF_MONTH)); + v.add(new FieldContainer(137, 140, Field.WEEK_OF_MONTH)); + v.add(new FieldContainer(141, 143, Field.AM_PM)); + v.add(new FieldContainer(145, 147, Field.AM_PM)); + v.add(new FieldContainer(149, 150, Field.HOUR0)); + v.add(new FieldContainer(151, 154, Field.HOUR0)); + v.add(new FieldContainer(155, 164, Field.TIME_ZONE)); + v.add(new FieldContainer(165, 174, Field.TIME_ZONE)); + v.add(new FieldContainer(175, 180, Field.TIME_ZONE)); + v.add(new FieldContainer(181, 186, Field.TIME_ZONE)); + return v; + } + +} |