< prev index next >
src/java.base/share/classes/java/text/DecimalFormatSymbols.java
Print this page
rev 54198 : [mq]: 8220224
*** 1,7 ****
/*
! * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
--- 1,7 ----
/*
! * Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
*** 36,51 ****
--- 36,53 ----
*
*/
package java.text;
+ import java.io.InvalidObjectException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.text.spi.DecimalFormatSymbolsProvider;
import java.util.Currency;
import java.util.Locale;
+ import java.util.Objects;
import sun.util.locale.provider.CalendarDataUtility;
import sun.util.locale.provider.LocaleProviderAdapter;
import sun.util.locale.provider.LocaleServiceProviderPool;
import sun.util.locale.provider.ResourceBundleBasedAdapter;
*** 253,262 ****
--- 255,299 ----
*
* @param perMill the character used for per mille sign
*/
public void setPerMill(char perMill) {
this.perMill = perMill;
+ this.perMillText = Character.toString(perMill);
+ }
+
+ /**
+ * Gets the string used for per mille sign. Different for Arabic, etc.
+ *
+ * @return the string used for per mille sign
+ * @since 13
+ */
+ String getPerMillText() {
+ return perMillText;
+ }
+
+ /**
+ * Sets the string used for per mille sign. Different for Arabic, etc.
+ *
+ * Setting the {@code perMillText} affects the return value of
+ * {@link #getPerMill()}, in which the first non-format character of
+ * {@code perMillText} is returned.
+ *
+ * @param perMillText the string used for per mille sign
+ * @throws NullPointerException if {@code perMillText} is null
+ * @throws IllegalArgumentException if {@code perMillText} is an empty string
+ * @see #getPerMill()
+ * @see #getPerMillText()
+ * @since 13
+ */
+ void setPerMillText(String perMillText) {
+ Objects.requireNonNull(perMillText);
+ if (perMillText.isEmpty()) {
+ throw new IllegalArgumentException("Empty argument string");
+ }
+
+ this.perMillText = perMillText;
+ this.perMill = findNonFormatChar(perMillText, '\u2030');
}
/**
* Gets the character used for percent sign. Different for Arabic, etc.
*
*** 271,280 ****
--- 308,352 ----
*
* @param percent the character used for percent sign
*/
public void setPercent(char percent) {
this.percent = percent;
+ this.percentText = Character.toString(percent);
+ }
+
+ /**
+ * Gets the string used for percent sign. Different for Arabic, etc.
+ *
+ * @return the string used for percent sign
+ * @since 13
+ */
+ String getPercentText() {
+ return percentText;
+ }
+
+ /**
+ * Sets the string used for percent sign. Different for Arabic, etc.
+ *
+ * Setting the {@code percentText} affects the return value of
+ * {@link #getPercent()}, in which the first non-format character of
+ * {@code percentText} is returned.
+ *
+ * @param percentText the string used for percent sign
+ * @throws NullPointerException if {@code percentText} is null
+ * @throws IllegalArgumentException if {@code percentText} is an empty string
+ * @see #getPercent()
+ * @see #getPercentText()
+ * @since 13
+ */
+ void setPercentText(String percentText) {
+ Objects.requireNonNull(percentText);
+ if (percentText.isEmpty()) {
+ throw new IllegalArgumentException("Empty argument string");
+ }
+
+ this.percentText = percentText;
+ this.percent = findNonFormatChar(percentText, '%');
}
/**
* Gets the character used for a digit in a pattern.
*
*** 371,380 ****
--- 443,492 ----
*
* @param minusSign the character representing minus sign
*/
public void setMinusSign(char minusSign) {
this.minusSign = minusSign;
+ this.minusSignText = Character.toString(minusSign);
+ }
+
+ /**
+ * Gets the string used to represent minus sign. If no explicit
+ * negative format is specified, one is formed by prefixing
+ * minusSignText to the positive format.
+ *
+ * @return the string representing minus sign
+ * @since 13
+ */
+ String getMinusSignText() {
+ return minusSignText;
+ }
+
+ /**
+ * Sets the string used to represent minus sign. If no explicit
+ * negative format is specified, one is formed by prefixing
+ * minusSignText to the positive format.
+ *
+ * Setting the {@code minusSignText} affects the return value of
+ * {@link #getMinusSign()}, in which the first non-format character of
+ * {@code minusSignText} is returned.
+ *
+ * @param minusSignText the character representing minus sign
+ * @throws NullPointerException if {@code minusSignText} is null
+ * @throws IllegalArgumentException if {@code minusSignText} is an
+ * empty string
+ * @see #getMinusSign()
+ * @see #getMinusSignText()
+ * @since 13
+ */
+ void setMinusSignText(String minusSignText) {
+ Objects.requireNonNull(minusSignText);
+ if (minusSignText.isEmpty()) {
+ throw new IllegalArgumentException("Empty argument string");
+ }
+
+ this.minusSignText = minusSignText;
+ this.minusSign = findNonFormatChar(minusSignText, '-');
}
/**
* Returns the currency symbol for the currency of these
* DecimalFormatSymbols in their locale.
*** 581,593 ****
--- 693,708 ----
DecimalFormatSymbols other = (DecimalFormatSymbols) obj;
return (zeroDigit == other.zeroDigit &&
groupingSeparator == other.groupingSeparator &&
decimalSeparator == other.decimalSeparator &&
percent == other.percent &&
+ percentText.equals(other.percentText) &&
perMill == other.perMill &&
+ perMillText.equals(other.perMillText) &&
digit == other.digit &&
minusSign == other.minusSign &&
+ minusSignText.equals(other.minusSignText) &&
patternSeparator == other.patternSeparator &&
infinity.equals(other.infinity) &&
NaN.equals(other.NaN) &&
getCurrencySymbol().equals(other.getCurrencySymbol()) && // possible currency init occurs here
intlCurrencySymbol.equals(other.intlCurrencySymbol) &&
*** 629,645 ****
String[] numberElements = (String[]) data[0];
decimalSeparator = numberElements[0].charAt(0);
groupingSeparator = numberElements[1].charAt(0);
patternSeparator = numberElements[2].charAt(0);
! percent = numberElements[3].charAt(0);
zeroDigit = numberElements[4].charAt(0); //different for Arabic,etc.
digit = numberElements[5].charAt(0);
! minusSign = numberElements[6].charAt(0);
exponential = numberElements[7].charAt(0);
exponentialSeparator = numberElements[7]; //string representation new since 1.6
! perMill = numberElements[8].charAt(0);
infinity = numberElements[9];
NaN = numberElements[10];
// maybe filled with previously cached values, or null.
intlCurrencySymbol = (String) data[1];
--- 744,763 ----
String[] numberElements = (String[]) data[0];
decimalSeparator = numberElements[0].charAt(0);
groupingSeparator = numberElements[1].charAt(0);
patternSeparator = numberElements[2].charAt(0);
! percentText = numberElements[3];
! percent = findNonFormatChar(percentText, '%');
zeroDigit = numberElements[4].charAt(0); //different for Arabic,etc.
digit = numberElements[5].charAt(0);
! minusSignText = numberElements[6];
! minusSign = findNonFormatChar(minusSignText, '-');
exponential = numberElements[7].charAt(0);
exponentialSeparator = numberElements[7]; //string representation new since 1.6
! perMillText = numberElements[8];
! perMill = findNonFormatChar(perMillText, '\u2030');
infinity = numberElements[9];
NaN = numberElements[10];
// maybe filled with previously cached values, or null.
intlCurrencySymbol = (String) data[1];
*** 650,659 ****
--- 768,787 ----
// If that changes, add a new entry to NumberElements.
monetarySeparator = decimalSeparator;
}
/**
+ * Obtains non-format single character from String
+ */
+ private char findNonFormatChar(String src, char defChar) {
+ return (char)src.chars()
+ .filter(c -> Character.getType(c) != Character.FORMAT)
+ .findFirst()
+ .orElse(defChar);
+ }
+
+ /**
* Lazy initialization for currency related fields
*/
private void initializeCurrency(Locale locale) {
if (currencyInitialized) {
return;
*** 710,723 ****
--- 838,857 ----
* to be 'E'.
* If <code>serialVersionOnStream</code> is less than 2,
* initializes <code>locale</code>to the root locale, and initializes
* If <code>serialVersionOnStream</code> is less than 3, it initializes
* <code>exponentialSeparator</code> using <code>exponential</code>.
+ * If <code>serialVersionOnStream</code> is less than 4, it initializes
+ * <code>perMillText</code>, <code>percentText</code>, and
+ * <code>minusSignText</code> using <code>perMill</code>, <code>percent</code>, and
+ * <code>minusSign</code> respectively.
* Sets <code>serialVersionOnStream</code> back to the maximum allowed value so that
* default serialization will work properly if this object is streamed out again.
* Initializes the currency from the intlCurrencySymbol field.
*
+ * @throws InvalidObjectException if <code>char</code> and <code>String</code>
+ * representations of either percent, per mille, and/or minus sign disagree.
* @since 1.1.6
*/
private void readObject(ObjectInputStream stream)
throws IOException, ClassNotFoundException {
stream.defaultReadObject();
*** 733,742 ****
--- 867,893 ----
}
if (serialVersionOnStream < 3) {
// didn't have exponentialSeparator. Create one using exponential
exponentialSeparator = Character.toString(exponential);
}
+ if (serialVersionOnStream < 4) {
+ // didn't have perMillText, percentText, and minusSignText.
+ // Create one using corresponding char variations.
+ perMillText = Character.toString(perMill);
+ percentText = Character.toString(percent);
+ minusSignText = Character.toString(minusSign);
+ } else {
+ // Check whether char and text fields agree
+ if (findNonFormatChar(perMillText, '\uFFFF') != perMill ||
+ findNonFormatChar(percentText, '\uFFFF') != percent ||
+ findNonFormatChar(minusSignText, '\uFFFF') != minusSign) {
+ throw new InvalidObjectException(
+ "'char' and 'String' representations of either percent, " +
+ "per mille, and/or minus sign disagree.");
+ }
+ }
+
serialVersionOnStream = currentSerialVersion;
if (intlCurrencySymbol != null) {
try {
currency = Currency.getInstance(intlCurrencySymbol);
*** 876,885 ****
--- 1027,1069 ----
* @serial
* @since 1.4
*/
private Locale locale;
+ /**
+ * String representation of per mille sign, which may include
+ * formatting characters, such as BiDi control characters.
+ * The first non-format character of this string is the same as
+ * <code>perMill</code>.
+ *
+ * @serial
+ * @since 13
+ */
+ private String perMillText;
+
+ /**
+ * String representation of percent sign, which may include
+ * formatting characters, such as BiDi control characters.
+ * The first non-format character of this string is the same as
+ * <code>percent</code>.
+ *
+ * @serial
+ * @since 13
+ */
+ private String percentText;
+
+ /**
+ * String representation of minus sign, which may include
+ * formatting characters, such as BiDi control characters.
+ * The first non-format character of this string is the same as
+ * <code>minusSign</code>.
+ *
+ * @serial
+ * @since 13
+ */
+ private String minusSignText;
+
// currency; only the ISO code is serialized.
private transient Currency currency;
private transient volatile boolean currencyInitialized;
// Proclaim JDK 1.1 FCS compatibility
*** 889,899 ****
// - 0 (default) for version up to JDK 1.1.5
// - 1 for version from JDK 1.1.6, which includes two new fields:
// monetarySeparator and exponential.
// - 2 for version from J2SE 1.4, which includes locale field.
// - 3 for version from J2SE 1.6, which includes exponentialSeparator field.
! private static final int currentSerialVersion = 3;
/**
* Describes the version of <code>DecimalFormatSymbols</code> present on the stream.
* Possible values are:
* <ul>
--- 1073,1085 ----
// - 0 (default) for version up to JDK 1.1.5
// - 1 for version from JDK 1.1.6, which includes two new fields:
// monetarySeparator and exponential.
// - 2 for version from J2SE 1.4, which includes locale field.
// - 3 for version from J2SE 1.6, which includes exponentialSeparator field.
! // - 4 for version from Java SE 13, which includes perMillText, percentText,
! // and minusSignText field.
! private static final int currentSerialVersion = 4;
/**
* Describes the version of <code>DecimalFormatSymbols</code> present on the stream.
* Possible values are:
* <ul>
*** 903,912 ****
--- 1089,1101 ----
* two new fields: <code>monetarySeparator</code> and <code>exponential</code>.
* <li><b>2</b>: Versions written by J2SE 1.4 or later, which include a
* new <code>locale</code> field.
* <li><b>3</b>: Versions written by J2SE 1.6 or later, which include a
* new <code>exponentialSeparator</code> field.
+ * <li><b>4</b>: Versions written by Java SE 13 or later, which include
+ * new <code>perMillText</code>, <code>percentText</code>, and
+ * <code>minusSignText</code> field.
* </ul>
* When streaming out a <code>DecimalFormatSymbols</code>, the most recent format
* (corresponding to the highest allowable <code>serialVersionOnStream</code>)
* is always written.
*
< prev index next >