harmony-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ge...@apache.org
Subject svn commit: r350181 [137/198] - in /incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core: ./ depends/ depends/files/ depends/jars/ depends/libs/ depends/libs/linux.IA32/ depends/libs/win.IA32/ depends/oss/ depends/oss/linux.IA32/ depends/oss/win....
Date Thu, 01 Dec 2005 06:04:00 GMT
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 + "]";
+	}
+}



Mime
View raw message