Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/text/src/java/text/DecimalFormatSymbols.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/text/src/java/text/DecimalFormatSymbols.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/text/src/java/text/DecimalFormatSymbols.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/text/src/java/text/DecimalFormatSymbols.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,525 @@
+/* Copyright 1998, 2005 The Apache Software Foundation or its licensors, as applicable
+ *
+ * Licensed 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 java.text;
+
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.ObjectStreamField;
+import java.io.Serializable;
+import java.util.Arrays;
+import java.util.Currency;
+import java.util.Locale;
+import java.util.ResourceBundle;
+
+/**
+ * DecimalFormatSymbols holds the symbols used in the formating and parsing of
+ * numbers.
+ */
+public final class DecimalFormatSymbols implements Cloneable, Serializable {
+
+ static final long serialVersionUID = 5772796243397350300L;
+
+ private final int ZeroDigit = 0, Digit = 1, DecimalSeparator = 2,
+ GroupingSeparator = 3, PatternSeparator = 4, Percent = 5,
+ PerMill = 6, Exponent = 7, MonetaryDecimalSeparator = 8,
+ MinusSign = 9;
+
+ transient char[] patternChars;
+
+ private transient Currency currency;
+
+ private transient Locale locale;
+
+ private String infinity, NaN, currencySymbol, intlCurrencySymbol;
+
+ /**
+ * Constructs a new DecimalFormatSymbols containing the symbols for the
+ * default Locale.
+ */
+ public DecimalFormatSymbols() {
+ this(Locale.getDefault());
+ }
+
+ /**
+ * Constructs a new DecimalFormatSymbols containing the symbols for the
+ * specified Locale.
+ *
+ * @param locale
+ * the Locale
+ */
+ public DecimalFormatSymbols(Locale locale) {
+ ResourceBundle bundle = Format.getBundle(locale);
+ patternChars = bundle.getString("DecimalPatternChars").toCharArray();
+ infinity = bundle.getString("Infinity");
+ NaN = bundle.getString("NaN");
+ this.locale = locale;
+ try {
+ currency = Currency.getInstance(locale);
+ currencySymbol = currency.getSymbol(locale);
+ intlCurrencySymbol = currency.getCurrencyCode();
+ } catch (IllegalArgumentException e) {
+ currency = Currency.getInstance("XXX");
+ currencySymbol = bundle.getString("CurrencySymbol");
+ intlCurrencySymbol = bundle.getString("IntCurrencySymbol");
+ }
+ }
+
+ /**
+ * Answers a new DecimalFormatSymbols with the same symbols as this
+ * DecimalFormatSymbols.
+ *
+ * @return a shallow copy of this DecimalFormatSymbols
+ *
+ * @see java.lang.Cloneable
+ */
+ public Object clone() {
+ try {
+ DecimalFormatSymbols symbols = (DecimalFormatSymbols) super.clone();
+ symbols.patternChars = (char[]) patternChars.clone();
+ return symbols;
+ } catch (CloneNotSupportedException e) {
+ return null;
+ }
+ }
+
+ /**
+ * Compares the specified object to this DecimalFormatSymbols and answer if
+ * they are equal. The object must be an instance of DecimalFormatSymbols
+ * with the same symbols.
+ *
+ * @param object
+ * the object to compare with this object
+ * @return true if the specified object is equal to this
+ * DecimalFormatSymbols, false otherwise
+ *
+ * @see #hashCode
+ */
+ public boolean equals(Object object) {
+ if (this == object)
+ return true;
+ if (!(object instanceof DecimalFormatSymbols))
+ return false;
+ DecimalFormatSymbols obj = (DecimalFormatSymbols) object;
+ return Arrays.equals(patternChars, obj.patternChars)
+ && infinity.equals(obj.infinity) && NaN.equals(obj.NaN)
+ && currencySymbol.equals(obj.currencySymbol)
+ && intlCurrencySymbol.equals(obj.intlCurrencySymbol);
+ }
+
+ /**
+ * Answers the currency.
+ * <p>
+ * <code>null<code> is returned
+ * if <code>setInternationalCurrencySymbol()</code> has 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, <code>setCurrency()</code>,
+ * or <code>setInternationalCurrencySymbol()</code>, or </code>null</code>
+ *
+ * @see #setCurrency(Currency)
+ * @see #setInternationalCurrencySymbol(String)
+ */
+ public Currency getCurrency() {
+ return currency;
+ }
+
+ /**
+ * Answers the international currency symbol.
+ *
+ * @return a String
+ */
+ public String getInternationalCurrencySymbol() {
+ return intlCurrencySymbol;
+ }
+
+ /**
+ * Answers the currency symbol.
+ *
+ * @return a String
+ */
+ public String getCurrencySymbol() {
+ return currencySymbol;
+ }
+
+ /**
+ * Answers the character which represents the decimal point in a number.
+ *
+ * @return a char
+ */
+ public char getDecimalSeparator() {
+ return patternChars[DecimalSeparator];
+ }
+
+ /**
+ * Answers the character which represents a single digit in a format
+ * pattern.
+ *
+ * @return a char
+ */
+ public char getDigit() {
+ return patternChars[Digit];
+ }
+
+ /**
+ * Answers the character used as the thousands separator in a number.
+ *
+ * @return a char
+ */
+ public char getGroupingSeparator() {
+ return patternChars[GroupingSeparator];
+ }
+
+ /**
+ * Answers the String which represents infinity.
+ *
+ * @return a String
+ */
+ public String getInfinity() {
+ return infinity;
+ }
+
+ String getLocalPatternChars() {
+ // Don't include the MonetaryDecimalSeparator or the MinusSign
+ return new String(patternChars, 0, patternChars.length - 2);
+ }
+
+ /**
+ * Answers the minus sign character.
+ *
+ * @return a char
+ */
+ public char getMinusSign() {
+ return patternChars[MinusSign];
+ }
+
+ /**
+ * Answers the character which represents the decimal point in a monetary
+ * value.
+ *
+ * @return a char
+ */
+ public char getMonetaryDecimalSeparator() {
+ return patternChars[MonetaryDecimalSeparator];
+ }
+
+ /**
+ * Answers the String which represents NaN.
+ *
+ * @return a String
+ */
+ public String getNaN() {
+ return NaN;
+ }
+
+ /**
+ * Answers the character which separates the positive and negative patterns
+ * in a format pattern.
+ *
+ * @return a char
+ */
+ public char getPatternSeparator() {
+ return patternChars[PatternSeparator];
+ }
+
+ /**
+ * Answers the percent character.
+ *
+ * @return a char
+ */
+ public char getPercent() {
+ return patternChars[Percent];
+ }
+
+ /**
+ * Answers the mille percent sign character.
+ *
+ * @return a char
+ */
+ public char getPerMill() {
+ return patternChars[PerMill];
+ }
+
+ /**
+ * Answers the character which represents zero.
+ *
+ * @return a char
+ */
+ public char getZeroDigit() {
+ return patternChars[ZeroDigit];
+ }
+
+ char getExponential() {
+ return patternChars[Exponent];
+ }
+
+ /**
+ * Answers an integer hash code for the receiver. Objects which are equal
+ * answer the same value for this method.
+ *
+ * @return the receiver's hash
+ *
+ * @see #equals
+ */
+ public int hashCode() {
+ return new String(patternChars).hashCode() + infinity.hashCode()
+ + NaN.hashCode() + currencySymbol.hashCode()
+ + intlCurrencySymbol.hashCode();
+ }
+
+ /**
+ * Sets the currency.
+ * <p>
+ * The international currency symbol and currency symbol are updated, but
+ * the min and max number of fraction digits stay the same.
+ * <p>
+ *
+ * @param currency
+ * the new currency
+ *
+ * @throws java.lang.NullPointerException
+ * if currency is null
+ */
+ public void setCurrency(Currency currency) {
+ if (currency == null)
+ throw new NullPointerException();
+ if (currency == this.currency)
+ return;
+ this.currency = currency;
+ intlCurrencySymbol = currency.getCurrencyCode();
+ currencySymbol = currency.getSymbol(locale);
+ }
+
+ /**
+ * Sets the international currency symbol.
+ * <p>
+ * currency and currency symbol also are updated, if <code>value</code> is
+ * a valid ISO4217 currency code.
+ * <p>
+ * The min and max number of fraction digits stay the same.
+ *
+ * @param value
+ * currency code
+ */
+ public void setInternationalCurrencySymbol(String value) {
+ if (value == null) {
+ currency = null;
+ intlCurrencySymbol = null;
+ return;
+ }
+
+ if (value.equals(intlCurrencySymbol))
+ return;
+
+ try {
+ currency = Currency.getInstance(value);
+ currencySymbol = currency.getSymbol(locale);
+ } catch (IllegalArgumentException e) {
+ currency = null;
+ }
+ intlCurrencySymbol = value;
+ }
+
+ /**
+ * Sets the currency symbol.
+ *
+ * @param value
+ * a String
+ */
+ public void setCurrencySymbol(String value) {
+ currencySymbol = value;
+ }
+
+ /**
+ * Sets the character which represents the decimal point in a number.
+ *
+ * @param value
+ * the decimal separator character
+ */
+ public void setDecimalSeparator(char value) {
+ patternChars[DecimalSeparator] = value;
+ }
+
+ /**
+ * Sets the character which represents a single digit in a format pattern.
+ *
+ * @param value
+ * the digit character
+ */
+ public void setDigit(char value) {
+ patternChars[Digit] = value;
+ }
+
+ /**
+ * Sets the character used as the thousands separator in a number.
+ *
+ * @param value
+ * the grouping separator character
+ */
+ public void setGroupingSeparator(char value) {
+ patternChars[GroupingSeparator] = value;
+ }
+
+ /**
+ * Sets the String which represents infinity.
+ *
+ * @param value
+ * the String
+ */
+ public void setInfinity(String value) {
+ infinity = value;
+ }
+
+ /**
+ * Sets the minus sign character.
+ *
+ * @param value
+ * the minus sign character
+ */
+ public void setMinusSign(char value) {
+ patternChars[MinusSign] = value;
+ }
+
+ /**
+ * Sets the character which represents the decimal point in a monetary
+ * value.
+ *
+ * @param value
+ * the monetary decimal separator character
+ */
+ public void setMonetaryDecimalSeparator(char value) {
+ patternChars[MonetaryDecimalSeparator] = value;
+ }
+
+ /**
+ * Sets the String which represents NaN.
+ *
+ * @param value
+ * the String
+ */
+ public void setNaN(String value) {
+ NaN = value;
+ }
+
+ /**
+ * Sets the character which separates the positive and negative patterns in
+ * a format pattern.
+ *
+ * @param value
+ * the pattern separator character
+ */
+ public void setPatternSeparator(char value) {
+ patternChars[PatternSeparator] = value;
+ }
+
+ /**
+ * Sets the percent character.
+ *
+ * @param value
+ * the percent character
+ */
+ public void setPercent(char value) {
+ patternChars[Percent] = value;
+ }
+
+ /**
+ * Sets the mille percent sign character.
+ *
+ * @param value
+ * the mille percent character
+ */
+ public void setPerMill(char value) {
+ patternChars[PerMill] = value;
+ }
+
+ /**
+ * Sets the character which represents zero.
+ *
+ * @param value
+ * the zero digit character
+ */
+ public void setZeroDigit(char value) {
+ patternChars[ZeroDigit] = value;
+ }
+
+ void setExponential(char value) {
+ patternChars[Exponent] = value;
+ }
+
+ private static final ObjectStreamField[] serialPersistentFields = {
+ new ObjectStreamField("currencySymbol", String.class),
+ new ObjectStreamField("decimalSeparator", Character.TYPE),
+ new ObjectStreamField("digit", Character.TYPE),
+ new ObjectStreamField("exponential", Character.TYPE),
+ new ObjectStreamField("groupingSeparator", Character.TYPE),
+ new ObjectStreamField("infinity", String.class),
+ new ObjectStreamField("intlCurrencySymbol", String.class),
+ new ObjectStreamField("minusSign", Character.TYPE),
+ new ObjectStreamField("monetarySeparator", Character.TYPE),
+ new ObjectStreamField("NaN", String.class),
+ new ObjectStreamField("patternSeparator", Character.TYPE),
+ new ObjectStreamField("percent", Character.TYPE),
+ new ObjectStreamField("perMill", Character.TYPE),
+ new ObjectStreamField("serialVersionOnStream", Integer.TYPE),
+ new ObjectStreamField("zeroDigit", Character.TYPE), };
+
+ private void writeObject(ObjectOutputStream stream) throws IOException {
+ ObjectOutputStream.PutField fields = stream.putFields();
+ fields.put("currencySymbol", currencySymbol);
+ fields.put("decimalSeparator", getDecimalSeparator());
+ fields.put("digit", getDigit());
+ fields.put("exponential", getExponential());
+ fields.put("groupingSeparator", getGroupingSeparator());
+ fields.put("infinity", infinity);
+ fields.put("intlCurrencySymbol", intlCurrencySymbol);
+ fields.put("minusSign", getMinusSign());
+ fields.put("monetarySeparator", getMonetaryDecimalSeparator());
+ fields.put("NaN", NaN);
+ fields.put("patternSeparator", getPatternSeparator());
+ fields.put("percent", getPercent());
+ fields.put("perMill", getPerMill());
+ fields.put("serialVersionOnStream", 1);
+ fields.put("zeroDigit", getZeroDigit());
+ stream.writeFields();
+ }
+
+ private void readObject(ObjectInputStream stream) throws IOException,
+ ClassNotFoundException {
+ ObjectInputStream.GetField fields = stream.readFields();
+ patternChars = new char[10];
+ currencySymbol = (String) fields.get("currencySymbol", "");
+ setDecimalSeparator(fields.get("decimalSeparator", '.'));
+ setDigit(fields.get("digit", '#'));
+ setGroupingSeparator(fields.get("groupingSeparator", ','));
+ infinity = (String) fields.get("infinity", "");
+ intlCurrencySymbol = (String) fields.get("intlCurrencySymbol", "");
+ setMinusSign(fields.get("minusSign", '-'));
+ NaN = (String) fields.get("NaN", "");
+ setPatternSeparator(fields.get("patternSeparator", ';'));
+ setPercent(fields.get("percent", '%'));
+ setPerMill(fields.get("perMill", '\u2030'));
+ setZeroDigit(fields.get("zeroDigit", '0'));
+ if (fields.get("serialVersionOnStream", 0) == 0) {
+ setMonetaryDecimalSeparator(getDecimalSeparator());
+ setExponential('E');
+ } else {
+ setMonetaryDecimalSeparator(fields.get("monetarySeparator", '.'));
+ setExponential(fields.get("exponential", 'E'));
+ }
+ }
+}
Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/text/src/java/text/FieldPosition.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/text/src/java/text/FieldPosition.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/text/src/java/text/FieldPosition.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/text/src/java/text/FieldPosition.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,166 @@
+/* Copyright 1998, 2005 The Apache Software Foundation or its licensors, as applicable
+ *
+ * Licensed 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 java.text;
+
+
+/**
+ * FieldPosition is used to identify fields in formatted Strings.
+ */
+public class FieldPosition {
+
+ private int myField, beginIndex, endIndex;
+
+ private Format.Field myAttribute;
+
+ /**
+ * Constructs a new FieldPosition on the specified field.
+ *
+ * @param field
+ * the field to identify
+ */
+ public FieldPosition(int field) {
+ myField = field;
+ }
+
+ /**
+ * Constructs a new FieldPosition on the specified Field attribute.
+ *
+ * @param attribute
+ * the field attribute to identify
+ */
+ public FieldPosition(Format.Field attribute) {
+ myAttribute = attribute;
+ myField = -1;
+ }
+
+ /**
+ * Constructs a new FieldPosition on the specified Field attribute and field
+ * id.
+ *
+ * @param attribute
+ * the field attribute to identify
+ * @param field
+ * the field to identify
+ */
+ public FieldPosition(Format.Field attribute, int field) {
+ myAttribute = attribute;
+ myField = field;
+ }
+
+ void clear() {
+ beginIndex = endIndex = 0;
+ }
+
+ /**
+ * Compares the specified object to this FieldPosition and answer if they
+ * are equal. The object must be an instance of FieldPosition with the same
+ * field, begin index and end index.
+ *
+ * @param object
+ * the object to compare with this object
+ * @return true if the specified object is equal to this fieldPosition,
+ * false otherwise
+ *
+ * @see #hashCode
+ */
+ public boolean equals(Object object) {
+ if (!(object instanceof FieldPosition))
+ return false;
+ FieldPosition pos = (FieldPosition) object;
+ return myField == pos.myField && myAttribute == pos.myAttribute
+ && beginIndex == pos.beginIndex && endIndex == pos.endIndex;
+ }
+
+ /**
+ * Answers the index of the beginning of the field.
+ *
+ * @return the first index of the field
+ */
+ public int getBeginIndex() {
+ return beginIndex;
+ }
+
+ /**
+ * Answers the index one past the end of the field.
+ *
+ * @return one past the index of the last character in the field
+ */
+ public int getEndIndex() {
+ return endIndex;
+ }
+
+ /**
+ * Answers the field which is being identified.
+ *
+ * @return the field
+ */
+ public int getField() {
+ return myField;
+ }
+
+ /**
+ * Answers the attribute which is being identified.
+ *
+ * @return the field
+ */
+ public Format.Field getFieldAttribute() {
+ return myAttribute;
+ }
+
+ /**
+ * Answers an integer hash code for the receiver. Objects which are equal
+ * answer the same value for this method.
+ *
+ * @return the receiver's hash
+ *
+ * @see #equals
+ */
+ public int hashCode() {
+ int attributeHash = (myAttribute == null) ? 0 : myAttribute.hashCode();
+ return attributeHash + myField * 10 + beginIndex * 100 + endIndex;
+ }
+
+ /**
+ * Sets the index of the beginning of the field.
+ *
+ * @param index
+ * the index of the first character in the field
+ */
+ public void setBeginIndex(int index) {
+ beginIndex = index;
+ }
+
+ /**
+ * Sets the index of the end of the field.
+ *
+ * @param index
+ * one past the index of the last character in the field
+ */
+ public void setEndIndex(int index) {
+ endIndex = index;
+ }
+
+ /**
+ * Answers the string representation of this FieldPosition.
+ *
+ * @return the string representation of this FieldPosition
+ */
+ public String toString() {
+ return getClass().getName() + "[attribute=" + myAttribute + ", field="
+ + myField + ", beginIndex=" + beginIndex + ", endIndex="
+ + endIndex + "]";
+ }
+}
Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/text/src/java/text/Format.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/text/src/java/text/Format.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/text/src/java/text/Format.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/text/src/java/text/Format.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,243 @@
+/* Copyright 1998, 2005 The Apache Software Foundation or its licensors, as applicable
+ *
+ * Licensed 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 java.text;
+
+
+import java.io.Serializable;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Locale;
+import java.util.ResourceBundle;
+
+import com.ibm.oti.util.Msg;
+
+/**
+ * Format is the abstract superclass of classes which format and parse objects
+ * according to Locale specific rules.
+ */
+public abstract class Format implements Serializable, Cloneable {
+
+ static final long serialVersionUID = -299282585814624189L;
+
+ /**
+ * Constructs a new instance of Format.
+ *
+ */
+ public Format() {
+ }
+
+ /**
+ * Answers a copy of this Format.
+ *
+ * @return a shallow copy of this Format
+ *
+ * @see java.lang.Cloneable
+ */
+ public Object clone() {
+ try {
+ return super.clone();
+ } catch (CloneNotSupportedException e) {
+ return null;
+ }
+ }
+
+ static ResourceBundle getBundle(final Locale locale) {
+ return (ResourceBundle) AccessController
+ .doPrivileged(new PrivilegedAction() {
+ public Object run() {
+ return ResourceBundle.getBundle(
+ "com.ibm.oti.locale.Locale", locale);
+ }
+ });
+ }
+
+ String convertPattern(String template, String fromChars, String toChars,
+ boolean check) {
+ if (!check && fromChars.equals(toChars))
+ return template;
+ boolean quote = false;
+ StringBuffer output = new StringBuffer();
+ int length = template.length();
+ for (int i = 0; i < length; i++) {
+ int index;
+ char next = template.charAt(i);
+ if (next == '\'')
+ quote = !quote;
+ if (!quote && (index = fromChars.indexOf(next)) != -1)
+ output.append(toChars.charAt(index));
+ else if (check
+ && !quote
+ && ((next >= 'a' && next <= 'z') || (next >= 'A' && next <= 'Z')))
+ throw new IllegalArgumentException(Msg.getString("K001c", String.valueOf(next), template));
+ else
+ output.append(next);
+ }
+ if (quote)
+ throw new IllegalArgumentException(Msg.getString("K0019"));
+ return output.toString();
+ }
+
+ /**
+ * Formats the specified object using the rules of this Format.
+ *
+ *
+ * @param object
+ * the object to format
+ * @return the formatted String
+ *
+ * @exception IllegalArgumentException
+ * when the object cannot be formatted by this Format
+ */
+ public final String format(Object object) {
+ return format(object, new StringBuffer(), new FieldPosition(0))
+ .toString();
+ }
+
+ /**
+ * Formats the specified object into the specified StringBuffer using the
+ * rules of this Format. If the field specified by the FieldPosition is
+ * formatted, set the begin and end index of the formatted field in the
+ * FieldPosition.
+ *
+ * @param object
+ * the object to format
+ * @param buffer
+ * the StringBuffer
+ * @param field
+ * the FieldPosition
+ * @return the StringBuffer parameter <code>buffer</code>
+ *
+ * @exception IllegalArgumentException
+ * when the object cannot be formatted by this Format
+ */
+ public abstract StringBuffer format(Object object, StringBuffer buffer,
+ FieldPosition field);
+
+ /**
+ * Formats the specified object using the rules of this format and returns
+ * an AttributedCharacterIterator with the formatted String and no
+ * attributes.
+ * <p>
+ * Subclasses should return an AttributedCharacterIterator with the
+ * appropriate attributes.
+ *
+ * @param object
+ * the object to format
+ * @return an AttributedCharacterIterator with the formatted object and
+ * attributes
+ *
+ * @exception IllegalArgumentException
+ * when the object cannot be formatted by this Format
+ */
+ public AttributedCharacterIterator formatToCharacterIterator(Object object) {
+ return new AttributedString(format(object)).getIterator();
+ }
+
+ /**
+ * Parse the specified String using the rules of this Format.
+ *
+ * @param string
+ * the String to parse
+ * @return the object resulting from the parse
+ *
+ * @exception ParseException
+ * when an error occurs during parsing
+ */
+ public Object parseObject(String string) throws ParseException {
+ ParsePosition position = new ParsePosition(0);
+ Object result = parseObject(string, position);
+ if (position.getErrorIndex() != -1 || position.getIndex() == 0)
+ throw new ParseException(null, position.getErrorIndex());
+ return result;
+ }
+
+ /**
+ * Parse the specified String starting at the index specified by the
+ * ParsePosition. If the string is successfully parsed, the index of the
+ * ParsePosition is updated to the index following the parsed text.
+ *
+ * @param string
+ * the String to parse
+ * @param position
+ * the ParsePosition, updated on return with the index following
+ * the parsed text, or on error the index is unchanged and the
+ * error index is set to the index where the error occurred
+ * @return the object resulting from the parse, or null if there is an error
+ */
+ public abstract Object parseObject(String string, ParsePosition position);
+
+ static boolean upTo(String string, ParsePosition position,
+ StringBuffer buffer, char stop) {
+ int index = position.getIndex(), length = string.length();
+ boolean lastQuote = false, quote = false;
+ while (index < length) {
+ char ch = string.charAt(index++);
+ if (ch == '\'') {
+ if (lastQuote)
+ buffer.append('\'');
+ quote = !quote;
+ lastQuote = true;
+ } else if (ch == stop && !quote) {
+ position.setIndex(index);
+ return true;
+ } else {
+ lastQuote = false;
+ buffer.append(ch);
+ }
+ }
+ position.setIndex(index);
+ return false;
+ }
+
+ static boolean upToWithQuotes(String string, ParsePosition position,
+ StringBuffer buffer, char stop, char start) {
+ int index = position.getIndex(), length = string.length(), count = 1;
+ boolean quote = false;
+ while (index < length) {
+ char ch = string.charAt(index++);
+ if (ch == '\'')
+ quote = !quote;
+ if (!quote) {
+ if (ch == stop)
+ count--;
+ if (count == 0) {
+ position.setIndex(index);
+ return true;
+ }
+ if (ch == start)
+ count++;
+ }
+ buffer.append(ch);
+ }
+ position.setIndex(index);
+ return false;
+ }
+
+ /**
+ * This inner class is used to represent Format attributes in the
+ * AttributedCharacterIterator that formatToCharacterIterator() method
+ * returns in the Format subclasses.
+ */
+ public static class Field extends AttributedCharacterIterator.Attribute {
+
+ /**
+ * Constructs a new instance of Field with the given fieldName.
+ */
+ protected Field(String fieldName) {
+ super(fieldName);
+ }
+ }
+}
Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/text/src/java/text/MessageFormat.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/text/src/java/text/MessageFormat.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/text/src/java/text/MessageFormat.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/text/src/java/text/MessageFormat.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,941 @@
+/* Copyright 1998, 2005 The Apache Software Foundation or its licensors, as applicable
+ *
+ * Licensed 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 java.text;
+
+
+import java.io.IOException;
+import java.io.InvalidObjectException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.ObjectStreamField;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.Locale;
+import java.util.Vector;
+
+import com.ibm.oti.util.Msg;
+
+/**
+ * MessageFormat is used to format and parse arguments based on a pattern. The
+ * pattern specifies how each argument will be formatted and concatenated with
+ * other text to produce the formatted output.
+ */
+public class MessageFormat extends Format {
+
+ static final long serialVersionUID = 6479157306784022952L;
+
+ private Locale locale = Locale.getDefault();
+
+ transient private String[] strings;
+
+ private int[] argumentNumbers;
+
+ private Format[] formats;
+
+ private int maxOffset;
+
+ transient private int maxArgumentIndex;
+
+ /**
+ * Constructs a new MessageFormat using the specified pattern and the
+ * specified Locale for Formats.
+ *
+ * @param template
+ * the pattern
+ * @param locale
+ * the locale
+ *
+ * @exception IllegalArgumentException
+ * when the pattern cannot be parsed
+ */
+ public MessageFormat(String template, Locale locale) {
+ this.locale = locale;
+ applyPattern(template);
+ }
+
+ /**
+ * Constructs a new MessageFormat using the specified pattern and the
+ * default Locale for Formats.
+ *
+ * @param template
+ * the pattern
+ *
+ * @exception IllegalArgumentException
+ * when the pattern cannot be parsed
+ */
+ public MessageFormat(String template) {
+ applyPattern(template);
+ }
+
+ /**
+ * Changes this MessageFormat to use the specified pattern.
+ *
+ * @param template
+ * the pattern
+ *
+ * @exception IllegalArgumentException
+ * when the pattern cannot be parsed
+ */
+ public void applyPattern(String template) {
+ int length = template.length();
+ StringBuffer buffer = new StringBuffer();
+ ParsePosition position = new ParsePosition(0);
+ Vector localStrings = new Vector();
+ int argCount = 0;
+ int[] args = new int[10];
+ int maxArg = -1;
+ Vector localFormats = new Vector();
+ while (position.getIndex() < length) {
+ if (Format.upTo(template, position, buffer, '{')) {
+ byte arg;
+ int offset = position.getIndex();
+ if (offset >= length
+ || (arg = (byte) Character.digit(template
+ .charAt(offset++), 10)) == -1)
+ throw new IllegalArgumentException(Msg
+ .getString("K001d"));
+ position.setIndex(offset);
+ localFormats.addElement(parseVariable(template, position));
+ if (argCount >= args.length) {
+ int[] newArgs = new int[args.length * 2];
+ System.arraycopy(args, 0, newArgs, 0, args.length);
+ args = newArgs;
+ }
+ args[argCount++] = arg;
+ if (arg > maxArg)
+ maxArg = arg;
+ }
+ localStrings.addElement(buffer.toString());
+ buffer.setLength(0);
+ }
+ this.strings = new String[localStrings.size()];
+ for (int i = 0; i < localStrings.size(); i++)
+ this.strings[i] = (String) localStrings.elementAt(i);
+ argumentNumbers = args;
+ this.formats = new Format[argCount];
+ for (int i = 0; i < argCount; i++)
+ this.formats[i] = (Format) localFormats.elementAt(i);
+ maxOffset = argCount - 1;
+ maxArgumentIndex = maxArg;
+ }
+
+ /**
+ * Answers a new instance of MessageFormat with the same pattern and Formats
+ * as this MessageFormat.
+ *
+ * @return a shallow copy of this MessageFormat
+ *
+ * @see java.lang.Cloneable
+ */
+ public Object clone() {
+ MessageFormat clone = (MessageFormat) super.clone();
+ Format[] array = new Format[formats.length];
+ for (int i = formats.length; --i >= 0;) {
+ if (formats[i] != null)
+ array[i] = (Format) formats[i].clone();
+ }
+ clone.formats = array;
+ return clone;
+ }
+
+ /**
+ * Compares the specified object to this MessageFormat and answer if they
+ * are equal. The object must be an instance of MessageFormat and have the
+ * same pattern.
+ *
+ * @param object
+ * the object to compare with this object
+ * @return true if the specified object is equal to this MessageFormat,
+ * false otherwise
+ *
+ * @see #hashCode
+ */
+ public boolean equals(Object object) {
+ if (this == object)
+ return true;
+ if (!(object instanceof MessageFormat))
+ return false;
+ MessageFormat format = (MessageFormat) object;
+ if (maxOffset != format.maxOffset)
+ return false;
+ // Must use a loop since the lengths may be different due
+ // to serialization cross-loading
+ for (int i = 0; i <= maxOffset; i++) {
+ if (argumentNumbers[i] != format.argumentNumbers[i])
+ return false;
+ }
+ return locale.equals(format.locale)
+ && Arrays.equals(strings, format.strings)
+ && Arrays.equals(formats, format.formats);
+ }
+
+ /**
+ * Formats the specified object using the rules of this MessageFormat and
+ * returns an AttributedCharacterIterator with the formatted message and
+ * attributes. The AttributedCharacterIterator returned also includes the
+ * attributes from the formats of this MessageFormat.
+ *
+ * @param object
+ * the object to format
+ * @return an AttributedCharacterIterator with the formatted message and
+ * attributes
+ *
+ * @exception IllegalArgumentException
+ * when the arguments in the object array cannot be formatted
+ * by this Format
+ */
+ public AttributedCharacterIterator formatToCharacterIterator(Object object) {
+ StringBuffer buffer = new StringBuffer();
+ Vector fields = new Vector();
+
+ // format the message, and find fields
+ formatImpl((Object[]) object, buffer, new FieldPosition(0), fields);
+
+ // create an AttributedString with the formatted buffer
+ AttributedString as = new AttributedString(buffer.toString());
+
+ // add MessageFormat field attributes and values to the AttributedString
+ for (int i = 0; i < fields.size(); i++) {
+ FieldContainer fc = (FieldContainer) fields.elementAt(i);
+ as.addAttribute(fc.attribute, fc.value, fc.start, fc.end);
+ }
+
+ // return the CharacterIterator from AttributedString
+ return as.getIterator();
+ }
+
+ /**
+ * Formats the Object arguments into the specified StringBuffer using the
+ * pattern of this MessageFormat.
+ * <p>
+ * If Field Attribute of the FieldPosition supplied is
+ * MessageFormat.Field.ARGUMENT, then begin and end index of this
+ * fieldposition is set to the location of the first occurance of a message
+ * format argument. Otherwise the FieldPosition is ignored
+ * <p>
+ *
+ * @param objects
+ * the array of Objects to format
+ * @param buffer
+ * the StringBuffer
+ * @param field
+ * a FieldPosition.
+ *
+ * @return the StringBuffer parameter <code>buffer</code>
+ */
+ public final StringBuffer format(Object[] objects, StringBuffer buffer,
+ FieldPosition field) {
+ return formatImpl(objects, buffer, field, null);
+ }
+
+ private StringBuffer formatImpl(Object[] objects, StringBuffer buffer,
+ FieldPosition position, Vector fields) {
+ FieldPosition passedField = new FieldPosition(0);
+ for (int i = 0; i <= maxOffset; i++) {
+ buffer.append(strings[i]);
+ int begin = buffer.length();
+ Object arg;
+ if (objects != null && argumentNumbers[i] < objects.length)
+ arg = objects[argumentNumbers[i]];
+ else {
+ buffer.append('{');
+ buffer.append(argumentNumbers[i]);
+ buffer.append('}');
+ handleArgumentField(begin, buffer.length(), argumentNumbers[i],
+ position, fields);
+ continue;
+ }
+ Format format = formats[i];
+ if (format == null || arg == null) {
+ if (arg instanceof Number)
+ format = NumberFormat.getInstance();
+ else if (arg instanceof Date)
+ format = DateFormat.getInstance();
+ else {
+ buffer.append(arg);
+ handleArgumentField(begin, buffer.length(),
+ argumentNumbers[i], position, fields);
+ continue;
+ }
+ }
+ if (format instanceof ChoiceFormat) {
+ String result = format.format(arg);
+ MessageFormat mf = new MessageFormat(result);
+ mf.setLocale(locale);
+ mf.format(objects, buffer, passedField);
+ handleArgumentField(begin, buffer.length(), argumentNumbers[i],
+ position, fields);
+ handleformat(format, arg, begin, fields);
+ } else {
+ format.format(arg, buffer, passedField);
+ handleArgumentField(begin, buffer.length(), argumentNumbers[i],
+ position, fields);
+ handleformat(format, arg, begin, fields);
+ }
+ }
+ if (maxOffset + 1 < strings.length)
+ buffer.append(strings[maxOffset + 1]);
+ return buffer;
+ }
+
+ /**
+ * Adds a new FieldContainer with MessageFormat.Field.ARGUMENT field,
+ * argnumber, begin and end index to the fields vector, or sets the
+ * position's begin and end index if it has MessageFormat.Field.ARGUMENT as
+ * its field attribute.
+ *
+ * @param begin
+ * @param end
+ * @param argnumber
+ * @param position
+ * @param fields
+ */
+ private void handleArgumentField(int begin, int end, int argnumber,
+ FieldPosition position, Vector fields) {
+ if (fields != null)
+ fields.add(new FieldContainer(begin, end, Field.ARGUMENT,
+ new Integer(argnumber)));
+ else {
+ if (position != null
+ && position.getFieldAttribute() == Field.ARGUMENT
+ && position.getEndIndex() == 0) {
+ position.setBeginIndex(begin);
+ position.setEndIndex(end);
+ }
+ }
+ }
+
+ /**
+ * An inner class to store attributes, values, start and end indices.
+ * Instances of this inner class are used as elements for the fields vector
+ */
+ private static class FieldContainer {
+ int start, end;
+
+ AttributedCharacterIterator.Attribute attribute;
+
+ Object value;
+
+ public FieldContainer(int start, int end,
+ AttributedCharacterIterator.Attribute attribute, Object value) {
+ this.start = start;
+ this.end = end;
+ this.attribute = attribute;
+ this.value = value;
+ }
+ }
+
+ /**
+ * If fields vector is not null, find and add the fields of this format to
+ * the fields vector by iterating through its AttributedCharacterIterator
+ *
+ * @param format
+ * the format to find fields for
+ * @param arg
+ * object to format
+ * @param begin
+ * the index where the string this format has formatted begins
+ * @param fields
+ * fields vector, each entry in this vector are of type
+ * FieldContainer.
+ */
+ private void handleformat(Format format, Object arg, int begin,
+ Vector fields) {
+ if (fields != null) {
+ AttributedCharacterIterator iterator = format
+ .formatToCharacterIterator(arg);
+ while (iterator.getIndex() != iterator.getEndIndex()) {
+ int start = iterator.getRunStart();
+ int end = iterator.getRunLimit();
+
+ Iterator it = iterator.getAttributes().keySet().iterator();
+ while (it.hasNext()) {
+ AttributedCharacterIterator.Attribute attribute = (AttributedCharacterIterator.Attribute) it
+ .next();
+ Object value = iterator.getAttribute(attribute);
+ fields.add(new FieldContainer(begin + start, begin + end,
+ attribute, value));
+ }
+ iterator.setIndex(end);
+ }
+ }
+ }
+
+ /**
+ * Formats the specified object into the specified StringBuffer using the
+ * pattern of this MessageFormat.
+ *
+ * @param object
+ * the object to format, must be an array of Object
+ * @param buffer
+ * the StringBuffer
+ * @param field
+ * a FieldPosition which is ignored
+ * @return the StringBuffer parameter <code>buffer</code>
+ *
+ * @exception ClassCastException
+ * when <code>object</code> is not an array of Object
+ */
+ public final StringBuffer format(Object object, StringBuffer buffer,
+ FieldPosition field) {
+ return format((Object[]) object, buffer, field);
+ }
+
+ /**
+ * Formats the Object arguments using the specified MessageFormat pattern.
+ *
+ * @param template
+ * the pattern
+ * @param objects
+ * the array of Objects to format
+ * @return the formatted result
+ *
+ * @exception IllegalArgumentException
+ * when the pattern cannot be parsed
+ */
+ public static String format(String template, Object[] objects) {
+ return new MessageFormat(template).format(objects);
+ }
+
+ /**
+ * Answers the Formats of this MessageFormat.
+ *
+ * @return an array of Format
+ */
+ public Format[] getFormats() {
+ return (Format[]) formats.clone();
+ }
+
+ /**
+ * Answers the formats used for each argument index. If an argument is
+ * placed more than once in the pattern string, than returns the format of
+ * the last one.
+ *
+ * @return an array of formats, ordered by argument index
+ */
+ public Format[] getFormatsByArgumentIndex() {
+ Format[] answer = new Format[maxArgumentIndex + 1];
+ for (int i = 0; i < maxOffset + 1; i++) {
+ answer[argumentNumbers[i]] = formats[i];
+ }
+ return answer;
+ }
+
+ /**
+ * Sets the format used for argument at index <code>argIndex</code>to
+ * <code>format</code>
+ *
+ * @param argIndex
+ * @param format
+ */
+ public void setFormatByArgumentIndex(int argIndex, Format format) {
+ for (int i = 0; i < maxOffset + 1; i++) {
+ if (argumentNumbers[i] == argIndex)
+ formats[i] = format;
+ }
+ }
+
+ /**
+ * Sets the formats used for each argument <code>The formats</code> array
+ * elements should be in the order of the argument indices.
+ *
+ * @param formats
+ */
+ public void setFormatsByArgumentIndex(Format[] formats) {
+ for (int j = 0; j < formats.length; j++) {
+ for (int i = 0; i < maxOffset + 1; i++) {
+ if (argumentNumbers[i] == j)
+ this.formats[i] = formats[j];
+ }
+ }
+ }
+
+ /**
+ * Answers the Locale used when creating Formats.
+ *
+ * @return the Locale used to create Formats
+ */
+ public Locale getLocale() {
+ return locale;
+ }
+
+ /**
+ * Answers an integer hash code for the receiver. Objects which are equal
+ * answer the same value for this method.
+ *
+ * @return the receiver's hash
+ *
+ * @see #equals
+ */
+ public int hashCode() {
+ int hashCode = 0;
+ for (int i = 0; i <= maxOffset; i++) {
+ hashCode += argumentNumbers[i] + strings[i].hashCode();
+ if (formats[i] != null)
+ hashCode += formats[i].hashCode();
+ }
+ if (maxOffset + 1 < strings.length)
+ hashCode += strings[maxOffset + 1].hashCode();
+ return hashCode + locale.hashCode();
+ }
+
+ /**
+ * Parse the message arguments from the specified String using the rules of
+ * this MessageFormat.
+ *
+ * @param string
+ * the String to parse
+ * @return the array of Object arguments resulting from the parse
+ *
+ * @exception ParseException
+ * when an error occurs during parsing
+ */
+ public Object[] parse(String string) throws ParseException {
+ ParsePosition position = new ParsePosition(0);
+ Object[] result = parse(string, position);
+ if (position.getErrorIndex() != -1 || position.getIndex() == 0)
+ throw new ParseException(null, position.getErrorIndex());
+ return result;
+ }
+
+ /**
+ * Parse the message argument from the specified String starting at the
+ * index specified by the ParsePosition. If the string is successfully
+ * parsed, the index of the ParsePosition is updated to the index following
+ * the parsed text.
+ *
+ * @param string
+ * the String to parse
+ * @param position
+ * the ParsePosition, updated on return with the index following
+ * the parsed text, or on error the index is unchanged and the
+ * error index is set to the index where the error occurred
+ * @return the array of Object arguments resulting from the parse, or null
+ * if there is an error
+ */
+ public Object[] parse(String string, ParsePosition position) {
+ if (string == null)
+ return new Object[0];
+ ParsePosition internalPos = new ParsePosition(0);
+ int offset = position.getIndex();
+ Object[] result = new Object[10];
+ for (int i = 0; i <= maxOffset; i++) {
+ String sub = strings[i];
+ if (!string.startsWith(sub, offset)) {
+ position.setErrorIndex(offset);
+ return null;
+ }
+ offset += sub.length();
+ Object parse;
+ Format format = formats[i];
+ if (format == null) {
+ if (i + 1 < strings.length) {
+ int next = string.indexOf(strings[i + 1], offset);
+ if (next == -1) {
+ position.setErrorIndex(offset);
+ return null;
+ }
+ parse = string.substring(offset, next);
+ offset = next;
+ } else {
+ parse = string.substring(offset);
+ offset = string.length();
+ }
+ } else {
+ internalPos.setIndex(offset);
+ parse = format.parseObject(string, internalPos);
+ if (internalPos.getErrorIndex() != -1) {
+ position.setErrorIndex(offset);
+ return null;
+ }
+ offset = internalPos.getIndex();
+ }
+ result[argumentNumbers[i]] = parse;
+ }
+ if (maxOffset + 1 < strings.length) {
+ String sub = strings[maxOffset + 1];
+ if (!string.startsWith(sub, offset)) {
+ position.setErrorIndex(offset);
+ return null;
+ }
+ offset += sub.length();
+ }
+ position.setIndex(offset);
+ return result;
+ }
+
+ /**
+ * Parse the message argument from the specified String starting at the
+ * index specified by the ParsePosition. If the string is successfully
+ * parsed, the index of the ParsePosition is updated to the index following
+ * the parsed text.
+ *
+ * @param string
+ * the String to parse
+ * @param position
+ * the ParsePosition, updated on return with the index following
+ * the parsed text, or on error the index is unchanged and the
+ * error index is set to the index where the error occurred
+ * @return the array of Object arguments resulting from the parse, or null
+ * if there is an error
+ */
+ public Object parseObject(String string, ParsePosition position) {
+ return parse(string, position);
+ }
+
+ private int match(String string, ParsePosition position, boolean last,
+ String[] tokens) {
+ int length = string.length(), offset = position.getIndex(), token = -1;
+ while (offset < length && Character.isWhitespace(string.charAt(offset)))
+ offset++;
+ for (int i = tokens.length; --i >= 0;) {
+ if (string.regionMatches(true, offset, tokens[i], 0, tokens[i]
+ .length())) {
+ token = i;
+ break;
+ }
+ }
+ if (token == -1)
+ return -1;
+ offset += tokens[token].length();
+ while (offset < length && Character.isWhitespace(string.charAt(offset)))
+ offset++;
+ char ch;
+ if (offset < length
+ && ((ch = string.charAt(offset)) == '}' || (!last && ch == ','))) {
+ position.setIndex(offset + 1);
+ return token;
+ }
+ return -1;
+ }
+
+ private Format parseVariable(String string, ParsePosition position) {
+ int length = string.length(), offset = position.getIndex();
+ char ch;
+ if (offset >= length
+ || ((ch = string.charAt(offset++)) != '}' && ch != ','))
+ throw new IllegalArgumentException(Msg
+ .getString("K001e"));
+ position.setIndex(offset);
+ if (ch == '}')
+ return null;
+ int type = match(string, position, false, new String[] { "time",
+ "date", "number", "choice" });
+ if (type == -1)
+ throw new IllegalArgumentException(Msg
+ .getString("K001f"));
+ StringBuffer buffer = new StringBuffer();
+ ch = string.charAt(position.getIndex() - 1);
+ switch (type) {
+ case 0: // time
+ case 1: // date
+ if (ch == '}')
+ return type == 1 ? DateFormat.getDateInstance(
+ DateFormat.DEFAULT, locale) : DateFormat
+ .getTimeInstance(DateFormat.DEFAULT, locale);
+ int dateStyle = match(string, position, true, new String[] {
+ "full", "long", "medium", "short" });
+ if (dateStyle == -1) {
+ Format.upToWithQuotes(string, position, buffer, '}', '{');
+ return new SimpleDateFormat(buffer.toString(), locale);
+ }
+ switch (dateStyle) {
+ case 0:
+ dateStyle = DateFormat.FULL;
+ break;
+ case 1:
+ dateStyle = DateFormat.LONG;
+ break;
+ case 2:
+ dateStyle = DateFormat.MEDIUM;
+ break;
+ case 3:
+ dateStyle = DateFormat.SHORT;
+ break;
+ }
+ return type == 1 ? DateFormat.getDateInstance(dateStyle, locale)
+ : DateFormat.getTimeInstance(dateStyle, locale);
+ case 2: // number
+ if (ch == '}')
+ return NumberFormat.getInstance();
+ int numberStyle = match(string, position, true, new String[] {
+ "currency", "percent", "integer" });
+ if (numberStyle == -1) {
+ Format.upToWithQuotes(string, position, buffer, '}', '{');
+ return new DecimalFormat(buffer.toString(),
+ new DecimalFormatSymbols(locale));
+ }
+ switch (numberStyle) {
+ case 0: // currency
+ return NumberFormat.getCurrencyInstance(locale);
+ case 1: // percent
+ return NumberFormat.getPercentInstance(locale);
+ }
+ return NumberFormat.getIntegerInstance(locale);
+ }
+ // choice
+ Format.upToWithQuotes(string, position, buffer, '}', '{');
+ return new ChoiceFormat(buffer.toString());
+ }
+
+ /**
+ * Sets the specified Format used by this MessageFormat.
+ *
+ * @param offset
+ * the format to change
+ * @param format
+ * the Format
+ */
+ public void setFormat(int offset, Format format) {
+ formats[offset] = format;
+ }
+
+ /**
+ * Sets the Formats used by this MessageFormat.
+ *
+ * @param formats
+ * an array of Format
+ */
+ public void setFormats(Format[] formats) {
+ this.formats = (Format[]) formats.clone();
+ }
+
+ /**
+ * Sets the Locale to use when creating Formats.
+ *
+ * @param locale
+ * the Locale
+ */
+ public void setLocale(Locale locale) {
+ this.locale = locale;
+ for (int i = 0; i <= maxOffset; i++) {
+ Format format = formats[i];
+ if (format instanceof DecimalFormat) {
+ formats[i] = new DecimalFormat(((DecimalFormat) format)
+ .toPattern(), new DecimalFormatSymbols(locale));
+ } else if (format instanceof SimpleDateFormat) {
+ formats[i] = new SimpleDateFormat(((SimpleDateFormat) format)
+ .toPattern(), locale);
+ }
+
+ }
+ }
+
+ private String decodeDecimalFormat(StringBuffer buffer, Format format) {
+ buffer.append(",number");
+ if (format.equals(NumberFormat.getNumberInstance(locale))) {
+ // Empty block
+ } else if (format.equals(NumberFormat.getIntegerInstance(locale)))
+ buffer.append(",integer");
+ else if (format.equals(NumberFormat.getCurrencyInstance(locale)))
+ buffer.append(",currency");
+ else if (format.equals(NumberFormat.getPercentInstance(locale)))
+ buffer.append(",percent");
+ else {
+ buffer.append(',');
+ return ((DecimalFormat) format).toPattern();
+ }
+ return null;
+ }
+
+ private String decodeSimpleDateFormat(StringBuffer buffer, Format format) {
+ if (format.equals(DateFormat
+ .getTimeInstance(DateFormat.DEFAULT, locale)))
+ buffer.append(",time");
+ else if (format.equals(DateFormat.getDateInstance(DateFormat.DEFAULT,
+ locale)))
+ buffer.append(",date");
+ else if (format.equals(DateFormat.getTimeInstance(DateFormat.SHORT,
+ locale)))
+ buffer.append(",time,short");
+ else if (format.equals(DateFormat.getDateInstance(DateFormat.SHORT,
+ locale)))
+ buffer.append(",date,short");
+ else if (format.equals(DateFormat.getTimeInstance(DateFormat.LONG,
+ locale)))
+ buffer.append(",time,long");
+ else if (format.equals(DateFormat.getDateInstance(DateFormat.LONG,
+ locale)))
+ buffer.append(",date,long");
+ else if (format.equals(DateFormat.getTimeInstance(DateFormat.FULL,
+ locale)))
+ buffer.append(",time,full");
+ else if (format.equals(DateFormat.getDateInstance(DateFormat.FULL,
+ locale)))
+ buffer.append(",date,full");
+ else {
+ buffer.append(",date,");
+ return ((SimpleDateFormat) format).toPattern();
+ }
+ return null;
+ }
+
+ /**
+ * Answers the pattern of this MessageFormat.
+ *
+ * @return the pattern
+ */
+ public String toPattern() {
+ StringBuffer buffer = new StringBuffer();
+ for (int i = 0; i <= maxOffset; i++) {
+ appendQuoted(buffer, strings[i]);
+ buffer.append('{');
+ buffer.append(argumentNumbers[i]);
+ Format format = formats[i];
+ String pattern = null;
+ if (format instanceof ChoiceFormat) {
+ buffer.append(",choice,");
+ pattern = ((ChoiceFormat) format).toPattern();
+ } else if (format instanceof DecimalFormat) {
+ pattern = decodeDecimalFormat(buffer, format);
+ } else if (format instanceof SimpleDateFormat) {
+ pattern = decodeSimpleDateFormat(buffer, format);
+ } else if (format != null)
+ throw new IllegalArgumentException(Msg
+ .getString("K0020"));
+ if (pattern != null) {
+ boolean quote = false;
+ int index = 0, length = pattern.length(), count = 0;
+ while (index < length) {
+ char ch = pattern.charAt(index++);
+ if (ch == '\'')
+ quote = !quote;
+ if (!quote) {
+ if (ch == '{')
+ count++;
+ if (ch == '}') {
+ if (count > 0)
+ count--;
+ else {
+ buffer.append("'}");
+ ch = '\'';
+ }
+ }
+ }
+ buffer.append(ch);
+ }
+ }
+ buffer.append('}');
+ }
+ if (maxOffset + 1 < strings.length)
+ appendQuoted(buffer, strings[maxOffset + 1]);
+ return buffer.toString();
+ }
+
+ private void appendQuoted(StringBuffer buffer, String string) {
+ int length = string.length();
+ for (int i = 0; i < length; i++) {
+ char ch = string.charAt(i);
+ if (ch == '{' || ch == '}') {
+ buffer.append('\'');
+ buffer.append(ch);
+ buffer.append('\'');
+ } else
+ buffer.append(ch);
+ }
+ }
+
+ private static final ObjectStreamField[] serialPersistentFields = {
+ new ObjectStreamField("argumentNumbers", int[].class),
+ new ObjectStreamField("formats", Format[].class),
+ new ObjectStreamField("locale", Locale.class),
+ new ObjectStreamField("maxOffset", Integer.TYPE),
+ new ObjectStreamField("offsets", int[].class),
+ new ObjectStreamField("pattern", String.class), };
+
+ private void writeObject(ObjectOutputStream stream) throws IOException {
+ ObjectOutputStream.PutField fields = stream.putFields();
+ fields.put("argumentNumbers", argumentNumbers);
+ Format[] compatibleFormats = formats;
+ fields.put("formats", compatibleFormats);
+ fields.put("locale", locale);
+ fields.put("maxOffset", maxOffset);
+ int offset = 0;
+ int offsetsLength = maxOffset + 1;
+ int[] offsets = new int[offsetsLength];
+ StringBuffer pattern = new StringBuffer();
+ for (int i = 0; i <= maxOffset; i++) {
+ offset += strings[i].length();
+ offsets[i] = offset;
+ pattern.append(strings[i]);
+ }
+ if (maxOffset + 1 < strings.length)
+ pattern.append(strings[maxOffset + 1]);
+ fields.put("offsets", offsets);
+ fields.put("pattern", pattern.toString());
+ stream.writeFields();
+ }
+
+ private void readObject(ObjectInputStream stream) throws IOException,
+ ClassNotFoundException {
+ ObjectInputStream.GetField fields = stream.readFields();
+ argumentNumbers = (int[]) fields.get("argumentNumbers", null);
+ formats = (Format[]) fields.get("formats", null);
+ locale = (Locale) fields.get("locale", null);
+ maxOffset = fields.get("maxOffset", 0);
+ int[] offsets = (int[]) fields.get("offsets", null);
+ String pattern = (String) fields.get("pattern", null);
+ int length;
+ if (maxOffset < 0)
+ length = pattern.length() > 0 ? 1 : 0;
+ else
+ length = maxOffset
+ + (offsets[maxOffset] == pattern.length() ? 1 : 2);
+ strings = new String[length];
+ int last = 0;
+ for (int i = 0; i <= maxOffset; i++) {
+ strings[i] = pattern.substring(last, offsets[i]);
+ last = offsets[i];
+ }
+ if (maxOffset + 1 < strings.length)
+ strings[strings.length - 1] = pattern.substring(last, pattern
+ .length());
+ }
+
+ /**
+ * The instances of this inner class are used as attribute keys in
+ * AttributedCharacterIterator that
+ * MessageFormat.formatToCharacterIterator() method returns.
+ * <p>
+ * There is no public constructor to this class, the only instances are the
+ * constants defined here.
+ */
+ public static class Field extends Format.Field {
+
+ public static final Field ARGUMENT = new Field("message argument field");
+
+ /**
+ * Constructs a new instance of MessageFormat.Field with the given field
+ * name.
+ */
+ protected Field(String fieldName) {
+ super(fieldName);
+ }
+
+ /**
+ * serizalization method resolve instances to the constant
+ * MessageFormat.Field values
+ */
+ protected Object readResolve() throws InvalidObjectException {
+ if (this.equals(ARGUMENT))
+ return ARGUMENT;
+ throw new InvalidObjectException(Msg
+ .getString("K000d"));
+ }
+ }
+
+}
Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/text/src/java/text/NumberFormat.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/text/src/java/text/NumberFormat.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/text/src/java/text/NumberFormat.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/text/src/java/text/NumberFormat.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,700 @@
+/* Copyright 1998, 2005 The Apache Software Foundation or its licensors, as applicable
+ *
+ * Licensed 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 java.text;
+
+
+import java.io.IOException;
+import java.io.InvalidObjectException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.ObjectStreamField;
+import java.util.Currency;
+import java.util.Locale;
+import java.util.ResourceBundle;
+
+import com.ibm.oti.util.Msg;
+
+/**
+ * NumberFormat is the abstract superclass of Formats which format and parse
+ * Numbers.
+ */
+public abstract class NumberFormat extends Format {
+
+ static final long serialVersionUID = -2308460125733713944L;
+
+ /**
+ * Field constant.
+ */
+ public static final int INTEGER_FIELD = 0;
+
+ /**
+ * Field constant.
+ */
+ public static final int FRACTION_FIELD = 1;
+
+ private boolean groupingUsed = true, parseIntegerOnly = false;
+
+ private int maximumIntegerDigits = 40, minimumIntegerDigits = 1,
+ maximumFractionDigits = 3, minimumFractionDigits = 0;
+
+ /**
+ * Constructs a new instance of DateFormat.
+ */
+ public NumberFormat() {
+ }
+
+ /**
+ * Answers a new NumberFormat with the same properties as this NumberFormat.
+ *
+ * @return a shallow copy of this NumberFormat
+ *
+ * @see java.lang.Cloneable
+ */
+ public Object clone() {
+ return super.clone();
+ }
+
+ /**
+ * Compares the specified object to this NumberFormat and answer if they are
+ * equal. The object must be an instance of NumberFormat and have the same
+ * properties.
+ *
+ * @param object
+ * the object to compare with this object
+ * @return true if the specified object is equal to this NumberFormat, false
+ * otherwise
+ *
+ * @see #hashCode
+ */
+ public boolean equals(Object object) {
+ if (object == this)
+ return true;
+ if (!(object instanceof NumberFormat))
+ return false;
+ NumberFormat obj = (NumberFormat) object;
+ return groupingUsed == obj.groupingUsed
+ && parseIntegerOnly == obj.parseIntegerOnly
+ && maximumFractionDigits == obj.maximumFractionDigits
+ && maximumIntegerDigits == obj.maximumIntegerDigits
+ && minimumFractionDigits == obj.minimumFractionDigits
+ && minimumIntegerDigits == obj.minimumIntegerDigits;
+ }
+
+ /**
+ * Formats the specified double using the rules of this NumberFormat.
+ *
+ * @param value
+ * the double to format
+ * @return the formatted String
+ */
+ public final String format(double value) {
+ return format(value, new StringBuffer(), new FieldPosition(0))
+ .toString();
+ }
+
+ /**
+ * Formats the double value into the specified StringBuffer using the rules
+ * of this NumberFormat. If the field specified by the FieldPosition is
+ * formatted, set the begin and end index of the formatted field in the
+ * FieldPosition.
+ *
+ * @param value
+ * the double to format
+ * @param buffer
+ * the StringBuffer
+ * @param field
+ * the FieldPosition
+ * @return the StringBuffer parameter <code>buffer</code>
+ */
+ public abstract StringBuffer format(double value, StringBuffer buffer,
+ FieldPosition field);
+
+ /**
+ * Formats the specified long using the rules of this NumberFormat.
+ *
+ * @param value
+ * the long to format
+ * @return the formatted String
+ */
+ public final String format(long value) {
+ return format(value, new StringBuffer(), new FieldPosition(0))
+ .toString();
+ }
+
+ /**
+ * Formats the long value into the specified StringBuffer using the rules of
+ * this NumberFormat. If the field specified by the FieldPosition is
+ * formatted, set the begin and end index of the formatted field in the
+ * FieldPosition.
+ *
+ * @param value
+ * the long to format
+ * @param buffer
+ * the StringBuffer
+ * @param field
+ * the FieldPosition
+ * @return the StringBuffer parameter <code>buffer</code>
+ */
+ public abstract StringBuffer format(long value, StringBuffer buffer,
+ FieldPosition field);
+
+ /**
+ * Formats the specified object into the specified StringBuffer using the
+ * rules of this DateFormat. If the field specified by the FieldPosition is
+ * formatted, set the begin and end index of the formatted field in the
+ * FieldPosition.
+ *
+ * @param object
+ * the object to format, must be a Number
+ * @param buffer
+ * the StringBuffer
+ * @param field
+ * the FieldPosition
+ * @return the StringBuffer parameter <code>buffer</code>
+ *
+ * @exception IllegalArgumentException
+ * when the object is not a Number
+ */
+ public final StringBuffer format(Object object, StringBuffer buffer,
+ FieldPosition field) {
+ if (object instanceof Number) {
+ double dv = ((Number) object).doubleValue();
+ long lv = ((Number) object).longValue();
+ if (dv == lv)
+ return format(lv, buffer, field);
+ return format(dv, buffer, field);
+ }
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * Gets the list of installed Locales which support NumberFormat.
+ *
+ * @return an array of Locale
+ */
+ public static Locale[] getAvailableLocales() {
+ return Locale.getAvailableLocales();
+ }
+
+ /**
+ * Answers the currency used by this number format
+ * <p>
+ * This implementation throws UnsupportedOperationException, concrete sub
+ * classes should override if they support currency formatting.
+ * <p>
+ *
+ * @return currency currency that was set in getInstance() or in
+ * setCurrency(), or null
+ * @throws java.lang.UnsupportedOperationException
+ */
+ public Currency getCurrency() {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Answers a NumberFormat for formatting and parsing currency for the
+ * default Locale.
+ *
+ * @return a NumberFormat
+ */
+ public final static NumberFormat getCurrencyInstance() {
+ return getCurrencyInstance(Locale.getDefault());
+ }
+
+ /**
+ * Answers a NumberFormat for formatting and parsing currency for the
+ * specified Locale.
+ *
+ * @param locale
+ * the Locale
+ * @return a NumberFormat
+ */
+ public static NumberFormat getCurrencyInstance(Locale locale) {
+ return getInstance(locale, "Currency");
+ }
+
+ /**
+ * Answers a NumberFormat for formatting and parsing integers for the
+ * default Locale.
+ *
+ * @return a NumberFormat
+ */
+ public final static NumberFormat getIntegerInstance() {
+ return getIntegerInstance(Locale.getDefault());
+ }
+
+ /**
+ * Answers a NumberFormat for formatting and parsing integers for the
+ * specified Locale.
+ *
+ * @param locale
+ * the Locale
+ * @return a NumberFormat
+ */
+ public static NumberFormat getIntegerInstance(Locale locale) {
+ NumberFormat format = getInstance(locale, "Integer");
+ format.setParseIntegerOnly(true);
+ return format;
+ }
+
+ /**
+ * Answers a NumberFormat for formatting and parsing numbers for the default
+ * Locale.
+ *
+ * @return a NumberFormat
+ */
+ public final static NumberFormat getInstance() {
+ return getNumberInstance();
+ }
+
+ /**
+ * Answers a NumberFormat for formatting and parsing numbers for the
+ * specified Locale.
+ *
+ * @param locale
+ * the Locale
+ * @return a NumberFormat
+ */
+ public static NumberFormat getInstance(Locale locale) {
+ return getNumberInstance(locale);
+ }
+
+ static NumberFormat getInstance(Locale locale, String type) {
+ return new DecimalFormat(getPattern(locale, type),
+ new DecimalFormatSymbols(locale));
+ }
+
+ /**
+ * Answers the maximum number of fraction digits that are printed when
+ * formatting. If the maximum is less than the number of fraction digits,
+ * the least significant digits are truncated.
+ *
+ * @return the maximum number of fraction digits
+ */
+ public int getMaximumFractionDigits() {
+ return maximumFractionDigits;
+ }
+
+ /**
+ * Answers the maximum number of integer digits that are printed when
+ * formatting. If the maximum is less than the number of integer digits, the
+ * most significant digits are truncated.
+ *
+ * @return the maximum number of integer digits
+ */
+ public int getMaximumIntegerDigits() {
+ return maximumIntegerDigits;
+ }
+
+ /**
+ * Answers the minimum number of fraction digits that are printed when
+ * formatting.
+ *
+ * @return the minimum number of fraction digits
+ */
+ public int getMinimumFractionDigits() {
+ return minimumFractionDigits;
+ }
+
+ /**
+ * Answers the minimum number of integer digits that are printed when
+ * formatting.
+ *
+ * @return the minimum number of integer digits
+ */
+ public int getMinimumIntegerDigits() {
+ return minimumIntegerDigits;
+ }
+
+ /**
+ * Answers a NumberFormat for formatting and parsing numbers for the default
+ * Locale.
+ *
+ * @return a NumberFormat
+ */
+ public final static NumberFormat getNumberInstance() {
+ return getNumberInstance(Locale.getDefault());
+ }
+
+ /**
+ * Answers a NumberFormat for formatting and parsing numbers for the
+ * specified Locale.
+ *
+ * @param locale
+ * the Locale
+ * @return a NumberFormat
+ */
+ public static NumberFormat getNumberInstance(Locale locale) {
+ return getInstance(locale, "Number");
+ }
+
+ static String getPattern(Locale locale, String type) {
+ ResourceBundle bundle = getBundle(locale);
+ return bundle.getString(type);
+ }
+
+ /**
+ * Answers a NumberFormat for formatting and parsing percentages for the
+ * default Locale.
+ *
+ * @return a NumberFormat
+ */
+ public final static NumberFormat getPercentInstance() {
+ return getPercentInstance(Locale.getDefault());
+ }
+
+ /**
+ * Answers a NumberFormat for formatting and parsing percentages for the
+ * specified Locale.
+ *
+ * @param locale
+ * the Locale
+ * @return a NumberFormat
+ */
+ public static NumberFormat getPercentInstance(Locale locale) {
+ return getInstance(locale, "Percent");
+ }
+
+ /**
+ * Answers an integer hash code for the receiver. Objects which are equal
+ * answer the same value for this method.
+ *
+ * @return the receiver's hash
+ *
+ * @see #equals
+ */
+ public int hashCode() {
+ return (groupingUsed ? 1231 : 1237) + (parseIntegerOnly ? 1231 : 1237)
+ + maximumFractionDigits + maximumIntegerDigits
+ + minimumFractionDigits + minimumIntegerDigits;
+ }
+
+ /**
+ * Answers whether this NumberFormat formats and parses numbers using a
+ * grouping separator.
+ *
+ * @return true when a grouping separator is used, false otherwise
+ */
+ public boolean isGroupingUsed() {
+ return groupingUsed;
+ }
+
+ /**
+ * Answers whether this NumberFormat only parses integer numbers. Parsing
+ * stops if a decimal separator is encountered.
+ *
+ * @return true if this NumberFormat only parses integers, false for parsing
+ * integers or fractions
+ */
+ public boolean isParseIntegerOnly() {
+ return parseIntegerOnly;
+ }
+
+ /**
+ * Parse a Number from the specified String using the rules of this
+ * NumberFormat.
+ *
+ * @param string
+ * the String to parse
+ * @return the Number resulting from the parse
+ *
+ * @exception ParseException
+ * when an error occurs during parsing
+ */
+ public Number parse(String string) throws ParseException {
+ ParsePosition pos = new ParsePosition(0);
+ Number number = parse(string, pos);
+ if (pos.getErrorIndex() != -1 || pos.getIndex() == 0)
+ throw new ParseException(null, pos.getErrorIndex());
+ return number;
+ }
+
+ /**
+ * Parse a Number from the specified String starting at the index specified
+ * by the ParsePosition. If the string is successfully parsed, the index of
+ * the ParsePosition is updated to the index following the parsed text.
+ *
+ * @param string
+ * the String to parse
+ * @param position
+ * the ParsePosition, updated on return with the index following
+ * the parsed text, or on error the index is unchanged and the
+ * error index is set to the index where the error occurred
+ * @return the Number resulting from the parse, or null if there is an error
+ */
+ public abstract Number parse(String string, ParsePosition position);
+
+ /**
+ * Parse a Number from the specified String starting at the index specified
+ * by the ParsePosition. If the string is successfully parsed, the index of
+ * the ParsePosition is updated to the index following the parsed text.
+ *
+ * @param string
+ * the String to parse
+ * @param position
+ * the ParsePosition, updated on return with the index following
+ * the parsed text, or on error the index is unchanged and the
+ * error index is set to the index where the error occurred
+ * @return the Number resulting from the parse, or null if there is an error
+ */
+ public final Object parseObject(String string, ParsePosition position) {
+ return parse(string, position);
+ }
+
+ /**
+ * Sets the currency used by this number format when formatting currency
+ * values.
+ * <p>
+ * The min and max fraction digits remain the same.
+ * <p>
+ * This implementation throws UnsupportedOperationException, concrete sub
+ * classes should override if they support currency formatting.
+ * <p>
+ *
+ * @param currency
+ * the new Currency
+ * @throws java.lang.UnsupportedOperationException
+ */
+ public void setCurrency(Currency currency) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Sets whether this NumberFormat formats and parses numbers using a
+ * grouping separator.
+ *
+ * @param value
+ * true when a grouping separator is used, false otherwise
+ */
+ public void setGroupingUsed(boolean value) {
+ groupingUsed = value;
+ }
+
+ /**
+ * Sets the maximum number of fraction digits that are printed when
+ * formatting. If the maximum is less than the number of fraction digits,
+ * the least significant digits are truncated.
+ *
+ * @param value
+ * the maximum number of fraction digits
+ */
+ public void setMaximumFractionDigits(int value) {
+ maximumFractionDigits = value < 0 ? 0 : value;
+ if (maximumFractionDigits < minimumFractionDigits)
+ minimumFractionDigits = maximumFractionDigits;
+ }
+
+ /**
+ * Used to specify the new maximum count of integer digits that are printed
+ * when formatting. If the maximum is less than the number of integer
+ * digits, the most significant digits are truncated.
+ *
+ * @param value
+ * the new maximum number of integer numerals for display
+ */
+ public void setMaximumIntegerDigits(int value) {
+ maximumIntegerDigits = value < 0 ? 0 : value;
+ if (maximumIntegerDigits < minimumIntegerDigits)
+ minimumIntegerDigits = maximumIntegerDigits;
+ }
+
+ /**
+ * Sets the minimum number of fraction digits that are printed when
+ * formatting.
+ *
+ * @param value
+ * the minimum number of fraction digits
+ */
+ public void setMinimumFractionDigits(int value) {
+ minimumFractionDigits = value < 0 ? 0 : value;
+ if (maximumFractionDigits < minimumFractionDigits)
+ maximumFractionDigits = minimumFractionDigits;
+ }
+
+ /**
+ * Sets the minimum number of integer digits that are printed when
+ * formatting.
+ *
+ * @param value
+ * the minimum number of integer digits
+ */
+ public void setMinimumIntegerDigits(int value) {
+ minimumIntegerDigits = value < 0 ? 0 : value;
+ if (maximumIntegerDigits < minimumIntegerDigits)
+ maximumIntegerDigits = minimumIntegerDigits;
+ }
+
+ /**
+ * Specifies if this NumberFormat should only parse numbers as integers or
+ * else as any kind of number. If this is called with a <code>true</code>
+ * value then subsequent parsing attempts will stop if a decimal separator
+ * is encountered.
+ *
+ * @param value
+ * <code>true</code> to only parse integers, <code>false</code>
+ * to parse integers and fractions
+ */
+ public void setParseIntegerOnly(boolean value) {
+ parseIntegerOnly = value;
+ }
+
+ private static final ObjectStreamField[] serialPersistentFields = {
+ new ObjectStreamField("groupingUsed", Boolean.TYPE),
+ new ObjectStreamField("maxFractionDigits", Byte.TYPE),
+ new ObjectStreamField("maximumFractionDigits", Integer.TYPE),
+ new ObjectStreamField("maximumIntegerDigits", Integer.TYPE),
+ new ObjectStreamField("maxIntegerDigits", Byte.TYPE),
+ new ObjectStreamField("minFractionDigits", Byte.TYPE),
+ new ObjectStreamField("minimumFractionDigits", Integer.TYPE),
+ new ObjectStreamField("minimumIntegerDigits", Integer.TYPE),
+ new ObjectStreamField("minIntegerDigits", Byte.TYPE),
+ new ObjectStreamField("parseIntegerOnly", Boolean.TYPE),
+ new ObjectStreamField("serialVersionOnStream", Integer.TYPE), };
+
+ private void writeObject(ObjectOutputStream stream) throws IOException {
+ ObjectOutputStream.PutField fields = stream.putFields();
+ fields.put("groupingUsed", groupingUsed);
+ fields
+ .put(
+ "maxFractionDigits",
+ maximumFractionDigits < Byte.MAX_VALUE ? (byte) maximumFractionDigits
+ : Byte.MAX_VALUE);
+ fields.put("maximumFractionDigits", maximumFractionDigits);
+ fields.put("maximumIntegerDigits", maximumIntegerDigits);
+ fields
+ .put(
+ "maxIntegerDigits",
+ maximumIntegerDigits < Byte.MAX_VALUE ? (byte) maximumIntegerDigits
+ : Byte.MAX_VALUE);
+ fields
+ .put(
+ "minFractionDigits",
+ minimumFractionDigits < Byte.MAX_VALUE ? (byte) minimumFractionDigits
+ : Byte.MAX_VALUE);
+ fields.put("minimumFractionDigits", minimumFractionDigits);
+ fields.put("minimumIntegerDigits", minimumIntegerDigits);
+ fields
+ .put(
+ "minIntegerDigits",
+ minimumIntegerDigits < Byte.MAX_VALUE ? (byte) minimumIntegerDigits
+ : Byte.MAX_VALUE);
+ fields.put("parseIntegerOnly", parseIntegerOnly);
+ fields.put("serialVersionOnStream", 1);
+ stream.writeFields();
+ }
+
+ private void readObject(ObjectInputStream stream) throws IOException,
+ ClassNotFoundException {
+ ObjectInputStream.GetField fields = stream.readFields();
+ groupingUsed = fields.get("groupingUsed", true);
+ parseIntegerOnly = fields.get("parseIntegerOnly", false);
+ if (fields.get("serialVersionOnStream", 0) == 0) {
+ maximumFractionDigits = fields.get("maxFractionDigits", (byte) 3);
+ maximumIntegerDigits = fields.get("maxIntegerDigits", (byte) 40);
+ minimumFractionDigits = fields.get("minFractionDigits", (byte) 0);
+ minimumIntegerDigits = fields.get("minIntegerDigits", (byte) 1);
+ } else {
+ maximumFractionDigits = fields.get("maximumFractionDigits", 3);
+ maximumIntegerDigits = fields.get("maximumIntegerDigits", 40);
+ minimumFractionDigits = fields.get("minimumFractionDigits", 0);
+ minimumIntegerDigits = fields.get("minimumIntegerDigits", 1);
+ }
+ if (minimumIntegerDigits > maximumIntegerDigits
+ || minimumFractionDigits > maximumFractionDigits)
+ throw new InvalidObjectException(com.ibm.oti.util.Msg
+ .getString("K00fa"));
+ if (minimumIntegerDigits < 0 || maximumIntegerDigits < 0
+ || minimumFractionDigits < 0 || maximumFractionDigits < 0)
+ throw new InvalidObjectException(com.ibm.oti.util.Msg
+ .getString("K00fb"));
+ }
+
+ /**
+ * The instances of this inner class are used as attribute keys and values
+ * in AttributedCharacterIterator that
+ * NumberFormat.formatToCharacterIterator() method returns.
+ * <p>
+ * There is no public constructor to this class, the only instances are the
+ * constants defined here.
+ * <p>
+ */
+ public static class Field extends Format.Field {
+
+ public static final Field SIGN = new Field("sign");
+
+ public static final Field INTEGER = new Field("integer");
+
+ public static final Field FRACTION = new Field("fraction");
+
+ public static final Field EXPONENT = new Field("exponent");
+
+ public static final Field EXPONENT_SIGN = new Field("exponent sign");
+
+ public static final Field EXPONENT_SYMBOL = new Field("exponent symbol");
+
+ public static final Field DECIMAL_SEPARATOR = new Field(
+ "decimal separator");
+
+ public static final Field GROUPING_SEPARATOR = new Field(
+ "grouping separator");
+
+ public static final Field PERCENT = new Field("percent");
+
+ public static final Field PERMILLE = new Field("per mille");
+
+ public static final Field CURRENCY = new Field("currency");
+
+ /**
+ * Constructs a new instance of NumberFormat.Field with the given field
+ * name.
+ */
+ protected Field(String fieldName) {
+ super(fieldName);
+ }
+
+ /**
+ * serizalization method resolve instances to the constant
+ * NumberFormat.Field values
+ */
+ protected Object readResolve() throws InvalidObjectException {
+ if (this.equals(INTEGER))
+ return INTEGER;
+ if (this.equals(FRACTION))
+ return FRACTION;
+ if (this.equals(EXPONENT))
+ return EXPONENT;
+ if (this.equals(EXPONENT_SIGN))
+ return EXPONENT_SIGN;
+ if (this.equals(EXPONENT_SYMBOL))
+ return EXPONENT_SYMBOL;
+ if (this.equals(CURRENCY))
+ return CURRENCY;
+ if (this.equals(DECIMAL_SEPARATOR))
+ return DECIMAL_SEPARATOR;
+ if (this.equals(GROUPING_SEPARATOR))
+ return GROUPING_SEPARATOR;
+ if (this.equals(PERCENT))
+ return PERCENT;
+ if (this.equals(PERMILLE))
+ return PERMILLE;
+ if (this.equals(SIGN))
+ return SIGN;
+
+ throw new InvalidObjectException(Msg.getString("K000d"));
+ }
+ }
+
+}
Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/text/src/java/text/ParseException.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/text/src/java/text/ParseException.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/text/src/java/text/ParseException.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/text/src/java/text/ParseException.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,51 @@
+/* Copyright 1998, 2004 The Apache Software Foundation or its licensors, as applicable
+ *
+ * Licensed 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 java.text;
+
+
+/**
+ * A ParseException is thrown when the String being parsed is not in the correct
+ * form.
+ */
+public class ParseException extends Exception {
+
+ static final long serialVersionUID = 2703218443322787634L;
+
+ private int errorOffset;
+
+ /**
+ * Constructs a new instance of this class with its walkback, message and
+ * the location of the error filled in.
+ *
+ * @param detailMessage
+ * String The detail message for the exception.
+ * @param location
+ * int The index at which the parse exception occurred.
+ */
+ public ParseException(String detailMessage, int location) {
+ super(detailMessage);
+ errorOffset = location;
+ }
+
+ /**
+ * Answers the index at which the parse exception occurred.
+ *
+ * @return int The index of the parse exception.
+ */
+ public int getErrorOffset() {
+ return errorOffset;
+ }
+}
Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/text/src/java/text/ParsePosition.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/text/src/java/text/ParsePosition.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/text/src/java/text/ParsePosition.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/text/src/java/text/ParsePosition.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,115 @@
+/* Copyright 1998, 2004 The Apache Software Foundation or its licensors, as applicable
+ *
+ * Licensed 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 java.text;
+
+
+/**
+ * ParsePosition is used to track the current position in a String being parsed.
+ */
+public class ParsePosition {
+
+ private int currentPosition, errorIndex = -1;
+
+ /**
+ * Constructs a new ParsePosition at the specified index.
+ *
+ * @param index
+ * the index to begin parsing
+ */
+ public ParsePosition(int index) {
+ currentPosition = index;
+ }
+
+ /**
+ * Compares the specified object to this ParsePosition and answer if they
+ * are equal. The object must be an instance of ParsePosition and have the
+ * same index and error index.
+ *
+ * @param object
+ * the object to compare with this object
+ * @return true if the specified object is equal to this ParsePosition,
+ * false otherwise
+ *
+ * @see #hashCode
+ */
+ public boolean equals(Object object) {
+ if (!(object instanceof ParsePosition))
+ return false;
+ ParsePosition pos = (ParsePosition) object;
+ return currentPosition == pos.currentPosition
+ && errorIndex == pos.errorIndex;
+ }
+
+ /**
+ * Answers the index at which the parse could not continue.
+ *
+ * @return the index of the parse error, or -1 if there is no error
+ */
+ public int getErrorIndex() {
+ return errorIndex;
+ }
+
+ /**
+ * Answers the current parse position.
+ *
+ * @return the current position
+ */
+ public int getIndex() {
+ return currentPosition;
+ }
+
+ /**
+ * Answers an integer hash code for the receiver. Objects which are equal
+ * answer the same value for this method.
+ *
+ * @return the receiver's hash
+ *
+ * @see #equals
+ */
+ public int hashCode() {
+ return currentPosition + errorIndex;
+ }
+
+ /**
+ * Sets the index at which the parse could not continue.
+ *
+ * @param index
+ * the index of the parse error
+ */
+ public void setErrorIndex(int index) {
+ errorIndex = index;
+ }
+
+ /**
+ * Sets the current parse position.
+ *
+ * @param index
+ * the current parse position
+ */
+ public void setIndex(int index) {
+ currentPosition = index;
+ }
+
+ /**
+ * Answers the string representation of this FieldPosition.
+ *
+ * @return the string representation of this FieldPosition
+ */
+ public String toString() {
+ return getClass().getName() + "[index=" + currentPosition
+ + ", errorIndex=" + errorIndex + "]";
+ }
+}
|