diff --git a/.gitattributes b/.gitattributes index f3814469f6b..1221edbc2f0 100644 --- a/.gitattributes +++ b/.gitattributes @@ -75,6 +75,11 @@ icu4j/main/classes/core/.project -text icu4j/main/classes/core/.settings/org.eclipse.jdt.core.prefs -text icu4j/main/classes/core/manifest.stub -text icu4j/main/classes/core/src/com/ibm/icu/text/SelectFormat.java -text +icu4j/main/classes/currdata/.externalToolBuilders/copy-data-currdata.launch -text +icu4j/main/classes/currdata/.externalToolBuilders/copy-data-langdata.launch -text +icu4j/main/classes/currdata/.settings/org.eclipse.jdt.core.prefs -text +icu4j/main/classes/currdata/.settings/org.eclipse.jdt.ui.prefs -text +icu4j/main/classes/currdata/currdata-build.launch -text icu4j/main/classes/langdata/.externalToolBuilders/copy-data-langdata.launch -text icu4j/main/classes/langdata/.settings/org.eclipse.jdt.core.prefs -text icu4j/main/classes/langdata/.settings/org.eclipse.jdt.ui.prefs -text diff --git a/icu4j/main/classes/core/build.xml b/icu4j/main/classes/core/build.xml index 8e3472752c7..6006c856306 100644 --- a/icu4j/main/classes/core/build.xml +++ b/icu4j/main/classes/core/build.xml @@ -29,14 +29,14 @@ - + + - - - + + + - diff --git a/icu4j/main/classes/core/src/com/ibm/icu/impl/CurrencyData.java b/icu4j/main/classes/core/src/com/ibm/icu/impl/CurrencyData.java new file mode 100644 index 00000000000..8bfd1c1613c --- /dev/null +++ b/icu4j/main/classes/core/src/com/ibm/icu/impl/CurrencyData.java @@ -0,0 +1,151 @@ +/* + ******************************************************************************* + * Copyright (C) 2009, International Business Machines Corporation and * + * others. All Rights Reserved. * + ******************************************************************************* + */ +package com.ibm.icu.impl; + +import java.util.Collections; +import java.util.Map; + +import com.ibm.icu.util.ULocale; + +public class CurrencyData { + public static final CurrencyDisplayInfoProvider provider; + + public static interface CurrencyDisplayInfoProvider { + CurrencyDisplayInfo getInstance(ULocale locale, boolean withFallback); + boolean hasData(); + } + + public static abstract class CurrencyDisplayInfo extends CurrencyDisplayNames { + public abstract Map getUnitPatterns(); + public abstract CurrencyFormatInfo getFormatInfo(String isoCode); + public abstract CurrencySpacingInfo getSpacingInfo(); + } + + public static final class CurrencyFormatInfo { + public final String currencyPattern; + public final char monetarySeparator; + public final char monetaryGroupingSeparator; + + public CurrencyFormatInfo(String currencyPattern, char monetarySeparator, + char monetaryGroupingSeparator) { + this.currencyPattern = currencyPattern; + this.monetarySeparator = monetarySeparator; + this.monetaryGroupingSeparator = monetaryGroupingSeparator; + } + } + + public static final class CurrencySpacingInfo { + public final String beforeCurrencyMatch; + public final String beforeContextMatch; + public final String beforeInsert; + public final String afterCurrencyMatch; + public final String afterContextMatch; + public final String afterInsert; + + public CurrencySpacingInfo( + String beforeCurrencyMatch, String beforeContextMatch, String beforeInsert, + String afterCurrencyMatch, String afterContextMatch, String afterInsert) { + this.beforeCurrencyMatch = beforeCurrencyMatch; + this.beforeContextMatch = beforeContextMatch; + this.beforeInsert = beforeInsert; + this.afterCurrencyMatch = afterCurrencyMatch; + this.afterContextMatch = afterContextMatch; + this.afterInsert = afterInsert; + } + + + private static final String DEFAULT_CUR_MATCH = "[:letter:]"; + private static final String DEFAULT_CTX_MATCH = "[:digit:]"; + private static final String DEFAULT_INSERT = " "; + + public static final CurrencySpacingInfo DEFAULT = new CurrencySpacingInfo( + DEFAULT_CUR_MATCH, DEFAULT_CTX_MATCH, DEFAULT_INSERT, + DEFAULT_CUR_MATCH, DEFAULT_CTX_MATCH, DEFAULT_INSERT); + } + + static { + CurrencyDisplayInfoProvider temp = null; + try { + Class clzz = Class.forName("com.ibm.icu.impl.ICUCurrencyDisplayInfoProvider"); + temp = (CurrencyDisplayInfoProvider) clzz.newInstance(); + } catch (Throwable t) { + temp = new CurrencyDisplayInfoProvider() { + public CurrencyDisplayInfo getInstance(ULocale locale, boolean withFallback) { + return DefaultInfo.getWithFallback(withFallback); + } + + public boolean hasData() { + return false; + } + }; + } + provider = temp; + } + + public static class DefaultInfo extends CurrencyDisplayInfo { + private final boolean fallback; + + private DefaultInfo(boolean fallback) { + this.fallback = fallback; + } + + public static final CurrencyDisplayInfo getWithFallback(boolean fallback) { + return fallback ? FALLBACK_INSTANCE : NO_FALLBACK_INSTANCE; + } + + @Override + public String getName(String isoCode) { + return fallback ? isoCode : null; + } + + @Override + public String getPluralName(String isoCode, String pluralType) { + return fallback ? isoCode : null; + } + + @Override + public String getSymbol(String isoCode) { + return fallback ? isoCode : null; + } + + @Override + public Map symbolMap() { + return Collections.emptyMap(); + } + + @Override + public Map nameMap() { + return Collections.emptyMap(); + } + + @Override + public ULocale getLocale() { + return ULocale.ROOT; + } + + @Override + public Map getUnitPatterns() { + if (fallback) { + return Collections.emptyMap(); + } + return null; + } + + @Override + public CurrencyFormatInfo getFormatInfo(String isoCode) { + return null; + } + + @Override + public CurrencySpacingInfo getSpacingInfo() { + return fallback ? CurrencySpacingInfo.DEFAULT : null; + } + + private static final CurrencyDisplayInfo FALLBACK_INSTANCE = new DefaultInfo(true); + private static final CurrencyDisplayInfo NO_FALLBACK_INSTANCE = new DefaultInfo(false); + } +} diff --git a/icu4j/main/classes/core/src/com/ibm/icu/impl/CurrencyDisplayNames.java b/icu4j/main/classes/core/src/com/ibm/icu/impl/CurrencyDisplayNames.java new file mode 100644 index 00000000000..4507aa490e0 --- /dev/null +++ b/icu4j/main/classes/core/src/com/ibm/icu/impl/CurrencyDisplayNames.java @@ -0,0 +1,74 @@ +/* + ******************************************************************************* + * Copyright (C) 2009, International Business Machines Corporation and * + * others. All Rights Reserved. * + ******************************************************************************* + */ +package com.ibm.icu.impl; + +import com.ibm.icu.util.ULocale; +import java.util.Map; + +/** + * Returns information about currency display names in a locale. + */ +public abstract class CurrencyDisplayNames { + /** + * Return an instance of CurrencyDisplayNames that provides information + * localized for display in the provided locale. + * @param locale the locale into which to localize the names + * @return a CurrencyDisplayNames + */ + public static CurrencyDisplayNames getInstance(ULocale locale) { + return CurrencyData.provider.getInstance(locale, true); + } + + /** + * Returns true if currency display name data is available. + * @return true if currency display name data is available. + */ + public static boolean hasData() { + return CurrencyData.provider.hasData(); + } + + /** + * Returns the locale used to determine how to translate the currency names. + * @return the display locale + */ + public abstract ULocale getLocale(); + + /** + * Returns the symbol for the currency with the provided ISO code. + * @param isoCode the three-letter ISO code. + * @return the display name. + */ + public abstract String getSymbol(String isoCode); + + /** + * Returns the 'long name' for the currency with the provided ISO code. + * @param isoCode the three-letter ISO code + * @return the display name + */ + public abstract String getName(String isoCode); + + /** + * Returns a 'plural name' for the currency with the provided ISO code corresponding to + * the pluralKey. + * @param isoCode the three-letter ISO code + * @param pluralKey the plural key, for example "one", "other" + * @return the display name + */ + public abstract String getPluralName(String isoCode, String pluralKey); + + /** + * Returns a mapping from localized symbols and currency codes to currency codes. + * The returned map is unmodifiable. + */ + public abstract Map symbolMap(); + + /** + * Returns a mapping from localized names (standard and plural) to currency codes. + * The returned map is unmodifiable. + */ + public abstract Map nameMap(); +} diff --git a/icu4j/main/classes/core/src/com/ibm/icu/impl/CurrencyMetaInfo.java b/icu4j/main/classes/core/src/com/ibm/icu/impl/CurrencyMetaInfo.java new file mode 100644 index 00000000000..c8d0b71ece3 --- /dev/null +++ b/icu4j/main/classes/core/src/com/ibm/icu/impl/CurrencyMetaInfo.java @@ -0,0 +1,425 @@ +/* + ******************************************************************************* + * Copyright (C) 2009, International Business Machines Corporation and * + * others. All Rights Reserved. * + ******************************************************************************* + */ +package com.ibm.icu.impl; + +import java.lang.reflect.Field; +import java.util.Collections; +import java.util.Date; +import java.util.List; + +import com.ibm.icu.util.Calendar; +import com.ibm.icu.util.GregorianCalendar; + +/** + * Represents information about currencies common to all locales. + */ +public class CurrencyMetaInfo { + private static final CurrencyMetaInfo impl; + private static final boolean hasData; + + /** + * Returns the unique instance of the currency meta info. This information is shared + * across locales. + * @return the meta info + */ + public static CurrencyMetaInfo getInstance() { + return impl; + } + + /** + * Returns true if there is actual data for the currency meta info, false if the info + * is not available (values returned will be defaults). + * @return true if there is actual data + */ + public static boolean hasData() { + return hasData; + } + + /** + * Subclass constructor. + */ + protected CurrencyMetaInfo() { + } + + /** + * A filter used to select which currency info is returned, and the ordering of the info. + */ + public static final class CurrencyFilter { + /** + * The region to filter on. If null, accepts any region. + */ + public final String region; + /** + * The currency to filter on. If null, accepts any currency. + */ + public final String currency; + /** + * The from date to filter on (milliseconds). Accepts any currency on or after this date. + */ + public final long from; + /** + * The to date to filter on (milliseconds). Accepts any currency on or before this date. + */ + public final long to; + + private CurrencyFilter (String region, String currency, long from, long to) { + this.region = region; + this.currency = currency; + this.from = from; + this.to = to; + } + + private CurrencyFilter (String region, String currency, Date dateFrom, Date dateTo) { + this.region = region; + this.currency = currency; + this.from = dateFrom == null ? Long.MIN_VALUE : dateFrom.getTime(); + this.to = dateTo == null ? Long.MAX_VALUE : dateTo.getTime(); + } + + private static CurrencyFilter ALL = new CurrencyFilter(null, null, null, null); + + /** + * Returns a filter that accepts all currency data. + * @return a filter + */ + public static CurrencyFilter all() { + return ALL; + } + + /** + * Returns a filter that accepts all currencies in use as of the current date. + * @return a filter + * @see #withDate(Date) + */ + public static CurrencyFilter now() { + return ALL.withDate(new Date()); + } + + /** + * Returns a filter that accepts all currencies ever used in the given region. + * @param region the region code + * @return a filter + * @see #withRegion(String) + */ + public static CurrencyFilter onRegion(String region) { + return ALL.withRegion(region); + } + + /** + * Returns a filter that accepts the given currency. + * @param currency the currency code + * @return a filter + * @see #withCurrency(String) + */ + public static CurrencyFilter onCurrency(String currency) { + return ALL.withCurrency(currency); + } + + /** + * Returns a filter that accepts all currencies in use on the given date. + * @param date the date + * @return a filter + * @see #withDate(Date) + */ + public static CurrencyFilter onDate(Date date) { + return ALL.withDate(date); + } + + /** + * Returns a filter that accepts all currencies that were in use at some point between + * the given dates, or if dates are equal, currencies in use on that date. + * @param from date on or after a currency must have been in use + * @param to date before which a currency must have been in use, or if equal to from, + * the date on which a currency must have been in use + * @return a filter + * @see #withRange(Date, Date) + */ + public static CurrencyFilter onRange(Date from, Date to) { + return ALL.withRange(from, to); + } + + /** + * Returns a copy of this filter, with the specified region. Region can be null to + * indicate no filter on region. + * @param region the region code + * @return the filter + * @see #onRegion(String) + */ + public CurrencyFilter withRegion(String region) { + return new CurrencyFilter(region, this.currency, this.from, this.to); + } + + /** + * Returns a copy of this filter, with the specified currency. Currency can be null to + * indicate no filter on currency. + * @param currency the currency code + * @return the filter + * @see #onCurrency(String) + */ + public CurrencyFilter withCurrency(String currency) { + return new CurrencyFilter(this.region, currency, this.from, this.to); + } + + /** + * Returns a copy of this filter, with from and to set to the given date. + * @param date the date on which the currency must have been in use + * @return the filter + * @see #onDate(Date) + */ + public CurrencyFilter withDate(Date date) { + return new CurrencyFilter(this.region, this.currency, date, date); + } + + /** + * Returns a copy of this filter, with from and to set to the given dates. + * @param from date on or after which the currency must have been in use + * @param to date before which the currency must have been in use + * @return the filter + * @see #onRange(Date, Date) + */ + public CurrencyFilter withRange(Date from, Date to) { + return new CurrencyFilter(this.region, this.currency, from, to); + } + + @Override + public boolean equals(Object rhs) { + return rhs instanceof CurrencyFilter && + equals((CurrencyFilter) rhs); + } + + /** + * Type-safe override of {@link #equals(Object)}. + * @param rhs the currency filter to compare to + * @return true if the filters are equal + */ + public boolean equals(CurrencyFilter rhs) { + return this == rhs || (rhs != null && + equals(this.region, rhs.region) && + equals(this.currency, rhs.currency) && + this.from == rhs.from && + this.to == rhs.to); + } + + @Override + public int hashCode() { + int hc = 0; + if (region != null) { + hc = region.hashCode(); + } + if (currency != null) { + hc = hc * 31 + currency.hashCode(); + } + hc = hc * 31 + (int) from; + hc = hc * 31 + (int) (from >>> 32); + hc = hc * 31 + (int) to; + hc = hc * 31 + (int) (to >>> 32); + return hc; + } + + /** + * Return a string representing the filter, for debugging. + */ + @Override + public String toString() { + return debugString(this); + } + + private static boolean equals(String lhs, String rhs) { + return lhs == rhs || (lhs != null && lhs.equals(rhs)); + } + } + + /** + * Represents the raw information about fraction digits and rounding increment. + */ + public static final class CurrencyDigits { + /** + * Number of fraction digits used to display this currency. + */ + public final byte fractionDigits; + /** + * Rounding increment used when displaying this currency. + */ + public final byte roundingIncrement; + + /** + * Constructor for CurrencyDigits. + * @param fractionDigits the fraction digits + * @param roundingIncrement the rounding increment + */ + public CurrencyDigits(int fractionDigits, int roundingIncrement) { + this.fractionDigits = (byte) fractionDigits; + this.roundingIncrement = (byte) roundingIncrement; + } + + /** + * Returns a string representing the currency digits, for debugging. + */ + @Override + public String toString() { + return debugString(this); + } + } + + /** + * Represents a complete currency info record listing the region, currency, from and to dates, + * and priority. + */ + public static final class CurrencyInfo { + /** + * Region code where currency is used. + */ + public final String region; + /** + * The three-letter ISO currency code. + */ + public final String code; + /** + * Date on which the currency was first officially used in the region. If there is no + * date, this is Long.MIN_VALUE; + */ + public final long from; + /** + * Date at which the currency stopped being officially used in the region. If there is + * no date, this is Long.MAX_VALUE; + */ + public final long to; + /** + * Preference order of currencies being used at the same time in the region. Lower + * values are preferred (generally, this is a transition from an older to a newer + * currency). Priorities within a single country are unique. + */ + public final short priority; + + /** + * Constructs a currency info. + * @param region region code + * @param code currency code + * @param from start date in milliseconds + * @param to end date in milliseconds + * @param priority priority value, 0 is highest priority, increasing values are lower + */ + public CurrencyInfo(String region, String code, long from, long to, int priority) { + this.region = region; + this.code = code; + this.from = from; + this.to = to; + this.priority = (short) priority; + } + + /** + * Returns a string useful for debugging. + */ + @Override + public String toString() { + return debugString(this); + } + } + + /** + * Returns the list of CurrencyInfos matching the provided filter. Results + * are ordered by country code, then by highest to lowest priority (0 is highest). + * The returned list is unmodifiable. + * @param filter the filter to control which currency info to return + * @return the matching information + */ + public List currencyInfo(CurrencyFilter filter) { + return Collections.emptyList(); + } + + /** + * Returns the list of currency codes matching the provided filter. + * Results are ordered as in {@link #currencyInfo(CurrencyFilter)}. + * The returned list is unmodifiable. + * @param filter the filter to control which currencies to return. If filter is null, + * returns all currencies for which information is available. + * @return the matching currency codes + */ + public List currencies(CurrencyFilter filter) { + return Collections.emptyList(); + } + + /** + * Returns the list of region codes matching the provided filter. + * Results are ordered as in {@link #currencyInfo(CurrencyFilter)}. + * The returned list is unmodifiable. + * @param filter the filter to control which regions to return. If filter is null, + * returns all regions for which information is available. + * @return the matching region codes + */ + public List regions(CurrencyFilter filter) { + return Collections.emptyList(); + } + + /** + * Returns the CurrencyDigits for the currency code. + * @param isoCode the currency code + * @return the CurrencyDigits + */ + public CurrencyDigits currencyDigits(String isoCode) { + return defaultDigits; + } + + protected static final CurrencyDigits defaultDigits = new CurrencyDigits(2, 0); + + static { + CurrencyMetaInfo temp = null; + boolean tempHasData = false; + try { + Class clzz = Class.forName("com.ibm.icu.impl.ICUCurrencyMetaInfo"); + temp = (CurrencyMetaInfo) clzz.newInstance(); + tempHasData = true; + } catch (Throwable t) { + temp = new CurrencyMetaInfo(); + } + impl = temp; + hasData = tempHasData; + } + + private static String dateString(long date) { + if (date == Long.MAX_VALUE || date == Long.MIN_VALUE) { + return null; + } + GregorianCalendar gc = new GregorianCalendar(); + gc.setTimeInMillis(date); + return "" + gc.get(Calendar.YEAR) + '-' + (gc.get(Calendar.MONTH) + 1) + '-' + + gc.get(Calendar.DAY_OF_MONTH); + } + + private static String debugString(Object o) { + StringBuilder sb = new StringBuilder(); + try { + for (Field f : o.getClass().getFields()) { + Object v = f.get(o); + if (v != null) { + String s; + if (v instanceof Date) { + s = dateString(((Date)v).getTime()); + } else if (v instanceof Long) { + s = dateString(((Long)v).longValue()); + } else { + s = String.valueOf(v); + } + if (s == null) { + continue; + } + if (sb.length() > 0) { + sb.append(","); + } + sb.append(f.getName()) + .append("='") + .append(s) + .append("'"); + } + } + } catch (Throwable t) { + } + sb.insert(0, o.getClass().getSimpleName() + "("); + sb.append(")"); + return sb.toString(); + } +} diff --git a/icu4j/main/classes/core/src/com/ibm/icu/impl/ICUResourceBundle.java b/icu4j/main/classes/core/src/com/ibm/icu/impl/ICUResourceBundle.java index ef5f1608b0e..f25b98ead65 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/impl/ICUResourceBundle.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/impl/ICUResourceBundle.java @@ -153,8 +153,7 @@ public class ICUResourceBundle extends UResourceBundle { * @return the locale * @internal ICU 3.0 */ - public static final ULocale getFunctionalEquivalent(String baseName, - ClassLoader loader, + public static final ULocale getFunctionalEquivalent(String baseName, ClassLoader loader, String resName, String keyword, ULocale locID, boolean isAvailable[], boolean omitDefault) { String kwVal = locID.getKeywordValue(keyword); @@ -337,12 +336,11 @@ public class ICUResourceBundle extends UResourceBundle { * @return resource represented by the key * @exception MissingResourceException If a resource was not found. */ - public ICUResourceBundle getWithFallback(String path) - throws MissingResourceException { + public ICUResourceBundle getWithFallback(String path) throws MissingResourceException { ICUResourceBundle result = null; ICUResourceBundle actualBundle = this; - // now recuse to pick up sub levels of the items + // now recurse to pick up sub levels of the items result = findResourceWithFallback(path, actualBundle, null); if (result == null) { @@ -353,6 +351,38 @@ public class ICUResourceBundle extends UResourceBundle { } return result; } + + public ICUResourceBundle at(int index) { + return (ICUResourceBundle) handleGet(index, null, this); + } + + public ICUResourceBundle at(String key) { + // don't ever presume the key is an int in disguise, like ResourceArray does. + if (this instanceof ICUResourceBundleImpl.ResourceTable) { + return (ICUResourceBundle) handleGet(key, null, this); + } + return null; + } + + @Override + public ICUResourceBundle findTopLevel(int index) { + return (ICUResourceBundle) super.findTopLevel(index); + } + + @Override + public ICUResourceBundle findTopLevel(String aKey) { + return (ICUResourceBundle) super.findTopLevel(aKey); + } + + /** + * Like getWithFallback, but returns null if the resource is not found instead of + * throwing an exception. + * @param path the path to the resource + * @return the resource, or null + */ + public ICUResourceBundle findWithFallback(String path) { + return findResourceWithFallback(path, this, null); + } // will throw type mismatch exception if the resource is not a string public String getStringWithFallback(String path) throws MissingResourceException { diff --git a/icu4j/main/classes/core/src/com/ibm/icu/text/CurrencyPluralInfo.java b/icu4j/main/classes/core/src/com/ibm/icu/text/CurrencyPluralInfo.java index 210038a19f8..7b91e6bd932 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/text/CurrencyPluralInfo.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/text/CurrencyPluralInfo.java @@ -8,25 +8,21 @@ package com.ibm.icu.text; import java.io.Serializable; import java.util.HashMap; -import java.util.HashSet; import java.util.Iterator; import java.util.Locale; import java.util.Map; -import java.util.MissingResourceException; -import java.util.Set; -import com.ibm.icu.impl.ICUResourceBundle; +import com.ibm.icu.impl.CurrencyData; import com.ibm.icu.util.ULocale; -import com.ibm.icu.util.UResourceBundle; /** - * This class represents the information needed by - * DecimalFormat to format currency plural, - * such as "3.00 US dollars" or "1.00 US dollar". + * This class represents the information needed by + * DecimalFormat to format currency plural, + * such as "3.00 US dollars" or "1.00 US dollar". * DecimalFormat creates for itself an instance of - * CurrencyPluralInfo from its locale data. + * CurrencyPluralInfo from its locale data. * If you need to change any of these symbols, you can get the - * CurrencyPluralInfo object from your + * CurrencyPluralInfo object from your * DecimalFormat and modify it. * * Following are the information needed for currency plural format and parse: @@ -47,7 +43,7 @@ public class CurrencyPluralInfo implements Cloneable, Serializable { * @provisional This API might change or be removed in a future release. */ public CurrencyPluralInfo() { - initialize( ULocale.getDefault() ); + initialize(ULocale.getDefault()); } /** @@ -56,8 +52,8 @@ public class CurrencyPluralInfo implements Cloneable, Serializable { * @draft ICU 4.2 * @provisional This API might change or be removed in a future release. */ - public CurrencyPluralInfo( Locale locale ) { - initialize( ULocale.forLocale(locale) ); + public CurrencyPluralInfo(Locale locale) { + initialize(ULocale.forLocale(locale)); } /** @@ -66,13 +62,13 @@ public class CurrencyPluralInfo implements Cloneable, Serializable { * @draft ICU 4.2 * @provisional This API might change or be removed in a future release. */ - public CurrencyPluralInfo( ULocale locale ) { - initialize( locale ); + public CurrencyPluralInfo(ULocale locale) { + initialize(locale); } /** * Gets a CurrencyPluralInfo instance for the default locale. - * + * * @return A CurrencyPluralInfo instance. * @draft ICU 4.2 * @provisional This API might change or be removed in a future release. @@ -83,7 +79,7 @@ public class CurrencyPluralInfo implements Cloneable, Serializable { /** * Gets a CurrencyPluralInfo instance for the given locale. - * + * * @param locale the locale. * @return A CurrencyPluralInfo instance. * @draft ICU 4.2 @@ -95,7 +91,7 @@ public class CurrencyPluralInfo implements Cloneable, Serializable { /** * Gets a CurrencyPluralInfo instance for the given locale. - * + * * @param locale the locale. * @return A CurrencyPluralInfo instance. * @draft ICU 4.2 @@ -117,7 +113,7 @@ public class CurrencyPluralInfo implements Cloneable, Serializable { } /** - * Given a plural count, gets currency plural pattern of this locale, + * Given a plural count, gets currency plural pattern of this locale, * used for currency plural format * * @param pluralCount currency plural count @@ -133,8 +129,8 @@ public class CurrencyPluralInfo implements Cloneable, Serializable { currencyPluralPattern = pluralCountToCurrencyUnitPattern.get("other"); } if (currencyPluralPattern == null) { - // no currencyUnitPatterns defined, - // fallback to predefined defult. + // no currencyUnitPatterns defined, + // fallback to predefined default. // This should never happen when ICU resource files are // available, since currencyUnitPattern of "other" is always // defined in root. @@ -145,7 +141,7 @@ public class CurrencyPluralInfo implements Cloneable, Serializable { } /** - * Get locale + * Get locale * * @return locale * @@ -157,11 +153,8 @@ public class CurrencyPluralInfo implements Cloneable, Serializable { } /** - * Set plural rules. - * The plural rule is set when CurrencyPluralInfo - * instance is created. - * You can call this method to reset plural rules only if you want - * to modify the default plural rule of the locale. + * Set plural rules. These are initially set in the constructor based on the locale, + * and usually do not need to be changed. * * @param ruleDescription new plural rule description * @draft ICU 4.2 @@ -172,13 +165,10 @@ public class CurrencyPluralInfo implements Cloneable, Serializable { } /** - * Set currency plural patterns. - * The currency plural pattern is set when CurrencyPluralInfo - * instance is created. - * You can call this method to reset currency plural patterns only if - * you want to modify the default currency plural pattern of the locale. + * Set currency plural patterns. These are initially set in the constructor based on the + * locale, and usually do not need to be changed. * - * @param pluralCount the plural count for which the currency pattern will + * @param pluralCount the plural count for which the currency pattern will * be overridden. * @param pattern the new currency plural pattern * @draft ICU 4.2 @@ -189,7 +179,8 @@ public class CurrencyPluralInfo implements Cloneable, Serializable { } /** - * Set locale + * Set locale. This also sets both the plural rules and the currency plural patterns to be + * the defaults for the locale. * * @param loc the new locale to set * @draft ICU 4.2 @@ -235,15 +226,15 @@ public class CurrencyPluralInfo implements Cloneable, Serializable { public boolean equals(Object a) { if (a instanceof CurrencyPluralInfo) { CurrencyPluralInfo other = (CurrencyPluralInfo)a; - return pluralRules.equals(other.pluralRules) && + return pluralRules.equals(other.pluralRules) && pluralCountToCurrencyUnitPattern.equals(other.pluralCountToCurrencyUnitPattern); } return false; } /** - * Given a number, returns the keyword of the first rule that applies - * to the number + * Given a number, returns the keyword of the first rule that applies + * to the number. */ String select(double number) { return pluralRules.select(number); @@ -252,7 +243,7 @@ public class CurrencyPluralInfo implements Cloneable, Serializable { /** * Currency plural pattern iterator. * - * @return a iterator on currency plural pattern key set. + * @return a iterator on the currency plural pattern key set. */ Iterator pluralPatternIterator() { return pluralCountToCurrencyUnitPattern.keySet().iterator(); @@ -266,8 +257,7 @@ public class CurrencyPluralInfo implements Cloneable, Serializable { private void setupCurrencyPluralPattern(ULocale uloc) { pluralCountToCurrencyUnitPattern = new HashMap(); - Set pluralCountSet = new HashSet(); - ULocale parentLocale = uloc; + String numberStylePattern = NumberFormat.getPattern(uloc, NumberFormat.NUMBERSTYLE); // Split the number style pattern into pos and neg if applicable int separatorIndex = numberStylePattern.indexOf(";"); @@ -276,42 +266,29 @@ public class CurrencyPluralInfo implements Cloneable, Serializable { negNumberPattern = numberStylePattern.substring(separatorIndex + 1); numberStylePattern = numberStylePattern.substring(0, separatorIndex); } - while (parentLocale != null) { - try { - ICUResourceBundle resource = (ICUResourceBundle) UResourceBundle. - getBundleInstance(ICUResourceBundle.ICU_CURR_BASE_NAME, parentLocale); - ICUResourceBundle currencyRes = resource.getWithFallback("CurrencyUnitPatterns"); - int size = currencyRes.getSize(); - for (int index = 0; index < size; ++index) { - String pluralCount = currencyRes.get(index).getKey(); - if (pluralCountSet.contains(pluralCount)) { - continue; - } - String pattern = currencyRes.get(index).getString(); - // replace {0} with numberStylePattern - // and {1} with triple currency sign - String patternWithNumber = pattern.replace("{0}", numberStylePattern); - String patternWithCurrencySign = patternWithNumber.replace("{1}", tripleCurrencyStr); - if (separatorIndex != -1) { - String negPattern = pattern; - String negWithNumber = negPattern.replace("{0}", negNumberPattern); - String negWithCurrSign = negWithNumber.replace("{1}", tripleCurrencyStr); - StringBuffer posNegPatterns = new StringBuffer(patternWithCurrencySign); - posNegPatterns.append(";"); - posNegPatterns.append(negWithCurrSign); - patternWithCurrencySign = posNegPatterns.toString(); - } - pluralCountToCurrencyUnitPattern.put(pluralCount, patternWithCurrencySign); - pluralCountSet.add(pluralCount); - } - } catch (MissingResourceException e) { + Map map = CurrencyData.provider.getInstance(uloc, true).getUnitPatterns(); + for (Map.Entry e : map.entrySet()) { + String pluralCount = e.getKey(); + String pattern = e.getValue(); + + // replace {0} with numberStylePattern + // and {1} with triple currency sign + String patternWithNumber = pattern.replace("{0}", numberStylePattern); + String patternWithCurrencySign = patternWithNumber.replace("{1}", tripleCurrencyStr); + if (separatorIndex != -1) { + String negPattern = pattern; + String negWithNumber = negPattern.replace("{0}", negNumberPattern); + String negWithCurrSign = negWithNumber.replace("{1}", tripleCurrencyStr); + StringBuffer posNegPatterns = new StringBuffer(patternWithCurrencySign); + posNegPatterns.append(";"); + posNegPatterns.append(negWithCurrSign); + patternWithCurrencySign = posNegPatterns.toString(); } - parentLocale = parentLocale.getFallback(); + pluralCountToCurrencyUnitPattern.put(pluralCount, patternWithCurrencySign); } } - //-------------------- private data member --------------------- // // triple currency sign char array @@ -325,15 +302,15 @@ public class CurrencyPluralInfo implements Cloneable, Serializable { private static final String defaultCurrencyPluralPattern = new String(defaultCurrencyPluralPatternChar); // map from plural count to currency plural pattern, for example - // one (plural count) --> {0} {1} (currency plural pattern, - // in which, {0} is the amount number, and {1} is the currency plural name. + // one (plural count) --> {0} {1} (currency plural pattern, + // in which {0} is the amount number, and {1} is the currency plural name). private Map pluralCountToCurrencyUnitPattern = null; /* * The plural rule is used to format currency plural name, * for example: "3.00 US Dollars". - * If there are 3 currency signs in the currency patttern, - * the 3 currency signs will be replaced by currency plural name. + * If there are 3 currency signs in the currency pattern, + * the 3 currency signs will be replaced by the currency plural name. */ private PluralRules pluralRules = null; diff --git a/icu4j/main/classes/core/src/com/ibm/icu/text/DecimalFormatSymbols.java b/icu4j/main/classes/core/src/com/ibm/icu/text/DecimalFormatSymbols.java index 60c565761de..565b45b39b0 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/text/DecimalFormatSymbols.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/text/DecimalFormatSymbols.java @@ -12,9 +12,12 @@ import java.io.Serializable; import java.text.ChoiceFormat; import java.util.Hashtable; import java.util.Locale; -import java.util.MissingResourceException; +import com.ibm.icu.impl.CurrencyData; import com.ibm.icu.impl.ICUResourceBundle; +import com.ibm.icu.impl.CurrencyData.CurrencyDisplayInfo; +import com.ibm.icu.impl.CurrencyData.CurrencyFormatInfo; +import com.ibm.icu.impl.CurrencyData.CurrencySpacingInfo; import com.ibm.icu.util.Currency; import com.ibm.icu.util.ULocale; import com.ibm.icu.util.UResourceBundle; @@ -572,18 +575,9 @@ public class DecimalFormatSymbols implements Cloneable, Serializable { } public static final int CURRENCY_SPC_CURRENCY_MATCH = 0; - public static final int CURRENCT_SPC_SURROUNDING_MATCH = 1; + public static final int CURRENCY_SPC_SURROUNDING_MATCH = 1; public static final int CURRENCY_SPC_INSERT = 2; - private static final String CURRENCY_SPACING = "currencySpacing"; - private static final String BEFORE_CURRENCY = "beforeCurrency"; - private static final String AFTER_CURRENCY = "afterCurrency"; - private static final String[] CURRENCY_SPACING_KEYS = - { "currencyMatch", "surroundingMatch" ,"insertBetween"}; - private static final String DEFAULT_SPC_MATCH = "[:letter:]"; - private static final String DEFAULT_SPC_INSERT = " "; - private static final String DEFAULT_SPC_SUR_MATCH = "[:digit:]"; - private String[] currencySpcBeforeSym; // before currency symbol. private String[] currencySpcAfterSym; // after currency symbol. /** @@ -780,6 +774,8 @@ public class DecimalFormatSymbols implements Cloneable, Serializable { zeroDigit = ns.getDescription().charAt(0); } + CurrencyDisplayInfo info = CurrencyData.provider.getInstance(locale, true); + // Obtain currency data from the currency API. This is strictly // for backward compatibility; we don't use DecimalFormatSymbols // for currency data anymore. @@ -801,48 +797,33 @@ public class DecimalFormatSymbols implements Cloneable, Serializable { currencySymbol = "\u00A4"; // 'OX' currency symbol } - ICUResourceBundle currResource = - (ICUResourceBundle) UResourceBundle.getBundleInstance( - ICUResourceBundle.ICU_CURR_BASE_NAME, locale); - // If there is a currency decimal, use it. + + // Get currency pattern/separator overrides if they exist. monetarySeparator = decimalSeparator; monetaryGroupingSeparator = groupingSeparator; Currency curr = Currency.getInstance(locale); - if(curr!=null){ - String currencyCode = curr.getCurrencyCode(); - if(currencyCode != null) { - /* An explicit currency was requested */ - ICUResourceBundle currencyRes = currResource.getWithFallback("Currencies"); - try{ - currencyRes = currencyRes.getWithFallback(currencyCode); - if(currencyRes.getSize()>2) { - currencyRes = (ICUResourceBundle)currencyRes.get(2); - currencyPattern = currencyRes.getString(0); - monetarySeparator = currencyRes.getString(1).charAt(0); - monetaryGroupingSeparator = currencyRes.getString(2).charAt(0); - } - }catch(MissingResourceException ex){ - /* else An explicit currency was requested and is unknown or locale data is malformed. */ - /* decimal format API will get the correct value later on. */ - } - } - /* else no currency keyword used. */ - } - //monetarySeparator = numberElements[11].charAt(0); - - // Get Currency Spacing data. - currencySpcBeforeSym = new String[CURRENCY_SPC_INSERT+1]; - currencySpcAfterSym = new String[CURRENCY_SPC_INSERT+1]; - ICUResourceBundle curSpcBundle = (ICUResourceBundle)currResource.get(CURRENCY_SPACING); - if (curSpcBundle != null) { - ICUResourceBundle beforeCurBundle = (ICUResourceBundle)curSpcBundle.get(BEFORE_CURRENCY); - ICUResourceBundle afterCurBundle = (ICUResourceBundle)curSpcBundle.get(AFTER_CURRENCY); - for (int i = CURRENCY_SPC_CURRENCY_MATCH; i <= CURRENCY_SPC_INSERT; i++) { - currencySpcBeforeSym[i] = beforeCurBundle.getStringWithFallback(CURRENCY_SPACING_KEYS[i]); - currencySpcAfterSym[i] = afterCurBundle.getStringWithFallback(CURRENCY_SPACING_KEYS[i]); + if (curr != null){ + CurrencyFormatInfo fmtInfo = info.getFormatInfo(curr.getCurrencyCode()); + if (fmtInfo != null) { + currencyPattern = fmtInfo.currencyPattern; + monetarySeparator = fmtInfo.monetarySeparator; + monetaryGroupingSeparator = fmtInfo.monetaryGroupingSeparator; } } - + + // Get currency spacing data. + currencySpcBeforeSym = new String[3]; + currencySpcAfterSym = new String[3]; + initSpacingInfo(info.getSpacingInfo()); + } + + private void initSpacingInfo(CurrencySpacingInfo spcInfo) { + currencySpcBeforeSym[CURRENCY_SPC_CURRENCY_MATCH] = spcInfo.beforeCurrencyMatch; + currencySpcBeforeSym[CURRENCY_SPC_SURROUNDING_MATCH] = spcInfo.beforeContextMatch; + currencySpcBeforeSym[CURRENCY_SPC_INSERT] = spcInfo.beforeInsert; + currencySpcAfterSym[CURRENCY_SPC_CURRENCY_MATCH] = spcInfo.afterCurrencyMatch; + currencySpcAfterSym[CURRENCY_SPC_SURROUNDING_MATCH] = spcInfo.afterContextMatch; + currencySpcAfterSym[CURRENCY_SPC_INSERT] = spcInfo.afterInsert; } /** @@ -902,12 +883,7 @@ public class DecimalFormatSymbols implements Cloneable, Serializable { if (currencySpcAfterSym == null) { currencySpcAfterSym = new String[CURRENCY_SPC_INSERT+1]; } - currencySpcBeforeSym[CURRENCY_SPC_CURRENCY_MATCH] = - currencySpcAfterSym[CURRENCY_SPC_CURRENCY_MATCH] = DEFAULT_SPC_MATCH; - currencySpcBeforeSym[CURRENCT_SPC_SURROUNDING_MATCH] = - currencySpcAfterSym[CURRENCT_SPC_SURROUNDING_MATCH] = DEFAULT_SPC_SUR_MATCH; - currencySpcBeforeSym[CURRENCY_SPC_INSERT] = - currencySpcAfterSym[CURRENCY_SPC_INSERT] = DEFAULT_SPC_INSERT; + initSpacingInfo(CurrencyData.CurrencySpacingInfo.DEFAULT); } serialVersionOnStream = currentSerialVersion; diff --git a/icu4j/main/classes/core/src/com/ibm/icu/util/Currency.java b/icu4j/main/classes/core/src/com/ibm/icu/util/Currency.java index b9d10892501..30f07ca09bf 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/util/Currency.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/util/Currency.java @@ -7,26 +7,24 @@ package com.ibm.icu.util; import java.io.Serializable; -import java.text.ChoiceFormat; import java.text.ParsePosition; import java.util.ArrayList; import java.util.Date; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Map; -import java.util.MissingResourceException; -import java.util.Set; import java.util.Vector; +import com.ibm.icu.impl.CurrencyDisplayNames; +import com.ibm.icu.impl.CurrencyMetaInfo; import com.ibm.icu.impl.ICUCache; import com.ibm.icu.impl.ICUDebug; import com.ibm.icu.impl.ICUResourceBundle; import com.ibm.icu.impl.SimpleCache; import com.ibm.icu.impl.TextTrieMap; +import com.ibm.icu.impl.CurrencyMetaInfo.CurrencyDigits; +import com.ibm.icu.impl.CurrencyMetaInfo.CurrencyFilter; /** * A class encapsulating a currency, as defined by ISO 4217. A @@ -148,140 +146,51 @@ public class Currency extends MeasureUnit implements Serializable { /** * Returns an array of Strings which contain the currency - * identifiers which are valid for the given locale on the - * given date. + * identifiers that are valid for the given locale on the + * given date. If there are no such identifiers, returns null. + * Returned identifiers are in preference order. * @param loc the locale for which to retrieve currency codes. * @param d the date for which to retrieve currency codes for the given locale. * @return The array of ISO currency codes. * @stable ICU 4.0 */ - public static String[] getAvailableCurrencyCodes(ULocale loc, Date d) - { - // local variables - String country = loc.getCountry(); - long dateL = d.getTime(); - long mask = 4294967295L; - - Vector currCodeVector = new Vector(); - - // Get supplementalData - ICUResourceBundle bundle = (ICUResourceBundle)ICUResourceBundle.getBundleInstance(ICUResourceBundle.ICU_CURR_BASE_NAME, - "supplementalData", - ICUResourceBundle.ICU_DATA_CLASS_LOADER); - if (bundle == null) - { - // no data + public static String[] getAvailableCurrencyCodes(ULocale loc, Date d) { + CurrencyMetaInfo info = CurrencyMetaInfo.getInstance(); + CurrencyFilter filter = CurrencyFilter.onDate(d).withRegion(loc.getCountry()); + List list = info.currencies(filter); + // Note: Prior to 4.4 the spec didn't say that we return null if there are no results, but + // the test assumed it did. Kept the behavior and amended the spec. + if (list.isEmpty()) { return null; } - - // Work with the supplementalData - try - { - // Process each currency to see which one is valid for the given date. - // Some regions can have more than one current currency in use for - // a given date. - UResourceBundle cm = bundle.get("CurrencyMap"); - UResourceBundle countryArray = cm.get(country); - - // Get valid currencies - for (int i = 0; i < countryArray.getSize(); i++) - { - // get the currency resource - UResourceBundle currencyReq = countryArray.get(i); - String curriso = null; - curriso = currencyReq.getString("id"); - - // get the from date - long fromDate = 0; - UResourceBundle fromRes = currencyReq.get("from"); - int[] fromArray = fromRes.getIntVector(); - fromDate = (long)fromArray[0] << 32; - fromDate |= ((long)fromArray[1] & mask); - - // get the to date and check the date range - if (currencyReq.getSize() > 2) - { - long toDate = 0; - UResourceBundle toRes = currencyReq.get("to"); - int[] toArray = toRes.getIntVector(); - toDate = (long)toArray[0] << 32; - toDate |= ((long)toArray[1] & mask); - - if ((fromDate <= dateL) && (dateL < toDate)) - { - currCodeVector.addElement(curriso); - } - } - else - { - if (fromDate <= dateL) - { - currCodeVector.addElement(curriso); - } - } - - } // end For loop - - // return the String array if we have matches - currCodeVector.trimToSize(); - if (currCodeVector.size() != 0) - { - return currCodeVector.toArray(new String[0]); - } - - } - catch (MissingResourceException ex) - { - // We don't know about this region. - // As of CLDR 1.5.1, the data includes deprecated region history too. - // So if we get here, either the region doesn't exist, or the data is really bad. - // Deprecated regions should return the last valid currency for that region in the data. - // We don't try to resolve it to a new region. - } - - // if we get this far, return nothing - return null; + return list.toArray(new String[list.size()]); } private static final String EUR_STR = "EUR"; + /** - * Instantiate a currency from a resource bundle found in Locale loc. + * Instantiate a currency from resource data. */ /* package */ static Currency createCurrency(ULocale loc) { - String country = loc.getCountry(); String variant = loc.getVariant(); - boolean isPreEuro = variant.equals("PREEURO"); - boolean isEuro = variant.equals("EURO"); - // TODO: ICU4C has service registration, and the currency is requested from the service here. - ICUResourceBundle bundle = (ICUResourceBundle) ICUResourceBundle.getBundleInstance(ICUResourceBundle.ICU_CURR_BASE_NAME,"supplementalData", ICUResourceBundle.ICU_DATA_CLASS_LOADER); - if(bundle==null){ - //throw new MissingResourceException() - return null; + if ("EURO".equals(variant)) { + return new Currency(EUR_STR); } - try { - UResourceBundle cm = bundle.get("CurrencyMap"); - String curriso = null; - UResourceBundle countryArray = cm.get(country); - // Some regions can have more than one current currency in use. - // The latest default currency is always the first one. - UResourceBundle currencyReq = countryArray.get(0); - curriso = currencyReq.getString("id"); - if (isPreEuro && curriso.equals(EUR_STR)) { - currencyReq = countryArray.get(1); - curriso = currencyReq.getString("id"); + + String country = loc.getCountry(); + + CurrencyMetaInfo info = CurrencyMetaInfo.getInstance(); + List list = info.currencies(CurrencyFilter.onRegion(country)); + if (list.size() > 0) { + String code = list.get(0); + boolean isPreEuro = "PREEURO".equals(variant); + if (isPreEuro && EUR_STR.equals(code)) { + if (list.size() < 2) { + return null; + } + code = list.get(1); } - else if (isEuro) { - curriso = EUR_STR; - } - if (curriso != null) { - return new Currency(curriso); - } - } catch (MissingResourceException ex) { - // We don't know about this region. - // As of CLDR 1.5.1, the data includes deprecated region history too. - // So if we get here, either the region doesn't exist, or the data is really bad. - // Deprecated regions should return the last valid currency for that region in the data. - // We don't try to resolve it to a new region. + return new Currency(code); } return null; } @@ -379,88 +288,76 @@ public class Currency extends MeasureUnit implements Serializable { // end registry stuff /** - * Given a key and a locale, returns an array of string values in a preferred - * order that would make a difference. These are all and only those values where - * the open (creation) of the service with the locale formed from the input locale - * plus input keyword and that value has different behavior than creation with the - * input locale alone. - * @param key one of the keys supported by this service. For now, only - * "currency" is supported. + * Given a key and a locale, returns an array of values for the key for which data + * exists. If commonlyUsed is true, these are the values that typically are used + * with this locale, otherwise these are all values for which data exists. + * This is a common service API. + *

+ * The only supported key is "currency", other values return an empty array. + *

+ * Currency information is based on the region of the locale. If the locale does not + * indicate a region, {@link ULocale#addLikelySubtags(ULocale)} is used to infer a region, + * except for the 'und' locale. + *

+ * If commonlyUsed is true, only the currencies known to be in use as of the current date + * are returned. When there are more than one, these are returned in preference order + * (typically, this occurs when a country is transitioning to a new currency, and the + * newer currency is preferred), see + * Unicode TR#35 Sec. C1. + * If commonlyUsed is false, all currencies ever used in any locale are returned, in no + * particular order. + * + * @param key key whose values to look up. the only recognized key is "currency" * @param locale the locale - * @param commonlyUsed if set to true it will return only commonly used values - * with the given locale in preferred order. Otherwise, - * it will return all the available values for the locale. - * @return an array of string values for the given key and the locale. + * @param commonlyUsed if true, return only values that are currently used in the locale. + * Otherwise returns all values. + * @return an array of values for the given key and the locale. If there is no data, the + * array will be empty. * @draft ICU 4.2 * @provisional This API might change or be removed in a future release. */ - public static final String[] getKeywordValuesForLocale(String key, ULocale locale, boolean commonlyUsed) { - // Resolve region + public static final String[] getKeywordValuesForLocale(String key, ULocale locale, + boolean commonlyUsed) { + + // The only keyword we recognize is 'currency' + if (!"currency".equals(key)) { + return EMPTY_STRING_ARRAY; + } + + CurrencyMetaInfo info = CurrencyMetaInfo.getInstance(); + if (!commonlyUsed) { + // Behavior change from 4.3.3, no longer sort the currencies + List result = info.currencies(null); + return result.toArray(new String[result.size()]); + } + + // Don't resolve region if the requested locale is 'und', it will resolve to US + // which we don't want. String prefRegion = locale.getCountry(); - if (prefRegion.length() == 0){ + if (prefRegion.length() == 0) { + if (UND.equals(locale)) { + return EMPTY_STRING_ARRAY; + } ULocale loc = ULocale.addLikelySubtags(locale); prefRegion = loc.getCountry(); + } + + CurrencyFilter filter = CurrencyFilter.now().withRegion(prefRegion); + + // currencies are in region's preferred order when we're filtering on region, which + // matches our spec + List result = info.currencies(filter); + + // No fallback anymore (change from 4.3.3) + if (result.size() == 0) { + return EMPTY_STRING_ARRAY; } - // Read values from supplementalData - List values = new ArrayList(); - List otherValues = new ArrayList(); - - UResourceBundle bundle = UResourceBundle.getBundleInstance( - ICUResourceBundle.ICU_CURR_BASE_NAME, "supplementalData"); - bundle = bundle.get("CurrencyMap"); - Enumeration keyEnum = bundle.getKeys(); - boolean done = false; - while (keyEnum.hasMoreElements() && !done) { - String region = keyEnum.nextElement(); - boolean isPrefRegion = prefRegion.equals(region); - if (!isPrefRegion && commonlyUsed) { - // With commonlyUsed=true, we do not put - // currencies for other regions in the - // result list. - continue; - } - UResourceBundle regbndl = bundle.get(region); - for (int i = 0; i < regbndl.getSize(); i++) { - UResourceBundle curbndl = regbndl.get(i); - if (curbndl.getType() != UResourceBundle.TABLE) { - // Currently, an empty ARRAY is mixed in.. - continue; - } - String curID = curbndl.getString("id"); - boolean hasTo = false; - try { - UResourceBundle to = curbndl.get("to"); - if (to != null) { - hasTo = true; - } - } catch (MissingResourceException e) { - // Do nothing here... - } - if (isPrefRegion && !hasTo && !values.contains(curID)) { - // Currently active currency for the target country - values.add(curID); - } else if (!otherValues.contains(curID) && !commonlyUsed){ - otherValues.add(curID); - } - } - } - if (commonlyUsed) { - if (values.size() == 0) { - // This could happen if no valid region is supplied in the input - // locale. In this case, we use the CLDR's default. - return getKeywordValuesForLocale(key, new ULocale("und"), true); - } - } else { - // Consolidate the list - for (String curID : otherValues) { - if (!values.contains(curID)) { - values.add(curID); - } - } - } - return values.toArray(new String[values.size()]); + return result.toArray(new String[result.size()]); } + + private static final ULocale UND = new ULocale("und"); + private static final String[] EMPTY_STRING_ARRAY = new String[0]; /** * Return a hashcode for this currency. @@ -554,79 +451,39 @@ public class Currency extends MeasureUnit implements Serializable { * @return display string for this currency. If the resource data * contains no entry for this currency, then the ISO 4217 code is * returned. If isChoiceFormat[0] is true, then the result is a - * ChoiceFormat pattern. Otherwise it is a static string. + * ChoiceFormat pattern. Otherwise it is a static string. Note: + * as of ICU 4.4, choice formats are not used, and the value returned + * in isChoiceFormat is always false. + *

* @throws IllegalArgumentException if the nameStyle is not SYMBOL_NAME * or LONG_NAME. + * @see #getName(ULocale, int, String, boolean[]) * @stable ICU 3.2 */ - public String getName(ULocale locale, - int nameStyle, - boolean[] isChoiceFormat) { - - // Look up the Currencies resource for the given locale. The - // Currencies locale data looks like this: - //|en { - //| Currencies { - //| USD { "US$", "US Dollar" } - //| CHF { "Sw F", "Swiss Franc" } - //| INR { "=0#Rs|1#Re|1 1) { - throw new IllegalArgumentException(); + public String getName(ULocale locale, int nameStyle, boolean[] isChoiceFormat) { + if (!(nameStyle == SYMBOL_NAME || nameStyle == LONG_NAME)) { + throw new IllegalArgumentException("bad name style: " + nameStyle); } - String s = null; - - try { - UResourceBundle rb = UResourceBundle.getBundleInstance(ICUResourceBundle.ICU_CURR_BASE_NAME,locale); - ICUResourceBundle currencies = (ICUResourceBundle)rb.get("Currencies"); - - // Fetch resource with multi-level resource inheritance fallback - s = currencies.getWithFallback(isoCode).getString(nameStyle); - }catch (MissingResourceException e) { - //TODO what should be done here? + // We no longer support choice format data in names. Data should not contain + // choice patterns. + if (isChoiceFormat != null) { + isChoiceFormat[0] = false; } - // Determine if this is a ChoiceFormat pattern. One leading mark - // indicates a ChoiceFormat. Two indicates a static string that - // starts with a mark. In either case, the first mark is ignored, - // if present. Marks in the rest of the string have no special - // meaning. - isChoiceFormat[0] = false; - if (s != null) { - int i=0; - while (i < s.length() && s.charAt(i) == '=' && i < 2) { - ++i; - } - isChoiceFormat[0]= (i == 1); - if (i != 0) { - // Skip over first mark - s = s.substring(1); - } - return s; - } - - // If we fail to find a match, use the ISO 4217 code - return isoCode; + CurrencyDisplayNames names = CurrencyDisplayNames.getInstance(locale); + return nameStyle == SYMBOL_NAME ? names.getSymbol(isoCode) : names.getName(isoCode); } /** - * Returns the display name for the given currency in the - * given locale. - * This is a convenient method of - * getName(ULocale, int, String, boolean[]); + * Returns the display name for the given currency in the given locale. + * This is a convenience overload of getName(ULocale, int, String, boolean[]); * @draft ICU 4.2 * @provisional This API might change or be removed in a future release. */ - public String getName(Locale locale, - int nameStyle, - String pluralCount, - boolean[] isChoiceFormat) { - return getName(ULocale.forLocale(locale), nameStyle, - pluralCount, isChoiceFormat); + public String getName(Locale locale, int nameStyle, String pluralCount, + boolean[] isChoiceFormat) { + return getName(ULocale.forLocale(locale), nameStyle, pluralCount, isChoiceFormat); } /** @@ -646,68 +503,27 @@ public class Currency extends MeasureUnit implements Serializable { * @return display string for this currency. If the resource data * contains no entry for this currency, then the ISO 4217 code is * returned. If isChoiceFormat[0] is true, then the result is a - * ChoiceFormat pattern. Otherwise it is a static string. - * @throws IllegalArgumentException if the nameStyle is not SYMBOL_NAME - * or LONG_NAME, or PLURAL_LONG_NAME. + * ChoiceFormat pattern. Otherwise it is a static string. Note: + * as of ICU 4.4, choice formats are not used, and the value returned + * in isChoiceFormat is always false. + * @throws IllegalArgumentException if the nameStyle is not SYMBOL_NAME, + * LONG_NAME, or PLURAL_LONG_NAME. * @draft ICU 4.2 * @provisional This API might change or be removed in a future release. */ - public String getName(ULocale locale, - int nameStyle, - String pluralCount, - boolean[] isChoiceFormat) { + public String getName(ULocale locale, int nameStyle, String pluralCount, + boolean[] isChoiceFormat) { if (nameStyle != PLURAL_LONG_NAME) { return getName(locale, nameStyle, isChoiceFormat); } - // Look up the CurrencyPlurals resource for the given locale. The - // CurrencyPlurals locale data looks like this: - //|en { - //| CurrencyPlurals { - //| USD{ - //| one{"US dollar"} - //| other{"US dollars"} - //| } - //| ... - //| } - //|} - // - // Algorithm detail: http://unicode.org/reports/tr35/#Currencies - // especially the fallback rule. - String s = null; - ICUResourceBundle isoCodeBundle; - // search at run time, not saved in initialization - try { - UResourceBundle rb = UResourceBundle.getBundleInstance(ICUResourceBundle.ICU_CURR_BASE_NAME,locale); - // get handles fallback - ICUResourceBundle currencies = (ICUResourceBundle)rb.get("CurrencyPlurals"); - - // Fetch resource with multi-level resource inheritance fallback - isoCodeBundle = currencies.getWithFallback(isoCode); - } catch (MissingResourceException e) { - // if there is no CurrencyPlurals defined or no plural long names - // defined in the locale chain, fall back to long name. - return getName(locale, LONG_NAME, isChoiceFormat); + // We no longer support choice format + if (isChoiceFormat != null) { + isChoiceFormat[0] = false; } - try { - s = isoCodeBundle.getStringWithFallback(pluralCount); - } catch (MissingResourceException e1) { - try { - // if there is no name corresponding to 'pluralCount' defined, - // fall back to name corresponding to "other". - s = isoCodeBundle.getStringWithFallback("other"); - } catch (MissingResourceException e) { - // if there is no name corresponding to plural count "other", - // fall back to long name. - return getName(locale, LONG_NAME, isChoiceFormat); - } - } - // No support for choice format for getting plural currency names. - if (s != null) { - return s; - } - // If we fail to find a match, use the ISO 4217 code - return isoCode; + + CurrencyDisplayNames names = CurrencyDisplayNames.getInstance(locale); + return names.getPluralName(isoCode, pluralCount); } /** @@ -734,8 +550,10 @@ public class Currency extends MeasureUnit implements Serializable { public static String parse(ULocale locale, String text, int type, ParsePosition pos) { Vector> currencyTrieVec = CURRENCY_NAME_CACHE.get(locale); if (currencyTrieVec == null) { - TextTrieMap currencyNameTrie = new TextTrieMap(true); - TextTrieMap currencySymbolTrie = new TextTrieMap(false); + TextTrieMap currencyNameTrie = + new TextTrieMap(true); + TextTrieMap currencySymbolTrie = + new TextTrieMap(false); currencyTrieVec = new Vector>(); currencyTrieVec.addElement(currencySymbolTrie); currencyTrieVec.addElement(currencyNameTrie); @@ -784,126 +602,22 @@ public class Currency extends MeasureUnit implements Serializable { return isoResult; } - private static void setupCurrencyTrieVec(ULocale locale, Vector> trieVec) { - // Look up the Currencies resource for the given locale. The - // Currencies locale data looks like this: - //|en { - //| Currencies { - //| USD { "US$", "US Dollar" } - //| CHF { "Sw F", "Swiss Franc" } - //| INR { "=0#Rs|1#Re|1> trieVec) { TextTrieMap symTrie = trieVec.elementAt(0); TextTrieMap trie = trieVec.elementAt(1); - HashSet visited = new HashSet(); - ULocale parentLocale = locale; - while (parentLocale != null) { - UResourceBundle rb = UResourceBundle.getBundleInstance(ICUResourceBundle.ICU_CURR_BASE_NAME,parentLocale); - // We can't cast this to String[][]; the cast has to happen later - try { - UResourceBundle currencies = rb.get("Currencies"); - // Do a linear search - for (int i=0; i 1 && name.charAt(0) == '=' && - name.charAt(1) != '=') { - // handle choice format here - name = name.substring(1); - ChoiceFormat choice = new ChoiceFormat(name); - Object[] names = choice.getFormats(); - for (int nameIndex = 0; nameIndex < names.length; - ++nameIndex) { - info = new CurrencyStringInfo(ISOCode, - (String)names[nameIndex]); - symTrie.put((String)names[nameIndex], info); - } - } else { - info = new CurrencyStringInfo(ISOCode, name); - symTrie.put(name, info); - } - - info = new CurrencyStringInfo(ISOCode, item.getString(1)); - trie.put(item.getString(1), info); - visited.add(ISOCode); - } - } - } - catch (MissingResourceException e) {} - - parentLocale = parentLocale.getFallback(); + CurrencyDisplayNames names = CurrencyDisplayNames.getInstance(locale); + for (Map.Entry e : names.symbolMap().entrySet()) { + String symbol = e.getKey(); + String isoCode = e.getValue(); + symTrie.put(symbol, new CurrencyStringInfo(isoCode, symbol)); } - // Look up the CurrencyPlurals resource for the given locale. The - // CurrencyPlurals locale data looks like this: - //|en { - //| CurrencyPlurals { - //| USD { - //| one{"US Dollar"} - //| other{"US dollars"} - //| } - //| //... - //| } - //|} - - Map> visitedInMap = new HashMap>(); - parentLocale = locale; - while (parentLocale != null) { - UResourceBundle rb = UResourceBundle.getBundleInstance(ICUResourceBundle.ICU_CURR_BASE_NAME,parentLocale); - try { - UResourceBundle currencies; - currencies = rb.get("CurrencyPlurals"); - for (int i=0; i visitPluralCount = visitedInMap.get(ISOCode); - if (visitPluralCount == null) { - visitPluralCount = new HashSet(); - visitedInMap.put(ISOCode, visitPluralCount); - } - for (int j=0; j e : names.nameMap().entrySet()) { + String name = e.getKey(); + String isoCode = e.getValue(); + trie.put(name, new CurrencyStringInfo(isoCode, name)); } } @@ -925,7 +639,8 @@ public class Currency extends MeasureUnit implements Serializable { } } - private static class CurrencyNameResultHandler implements TextTrieMap.ResultHandler { + private static class CurrencyNameResultHandler + implements TextTrieMap.ResultHandler { private ArrayList resultList; public boolean handlePrefixMatch(int matchLength, Iterator values) { @@ -971,7 +686,9 @@ public class Currency extends MeasureUnit implements Serializable { * @stable ICU 2.2 */ public int getDefaultFractionDigits() { - return (findData())[0]; + CurrencyMetaInfo info = CurrencyMetaInfo.getInstance(); + CurrencyDigits digits = info.currencyDigits(isoCode); + return digits.fractionDigits; } /** @@ -981,9 +698,10 @@ public class Currency extends MeasureUnit implements Serializable { * @stable ICU 2.2 */ public double getRoundingIncrement() { - int[] data = findData(); + CurrencyMetaInfo info = CurrencyMetaInfo.getInstance(); + CurrencyDigits digits = info.currencyDigits(isoCode); - int data1 = data[1]; // rounding increment + int data1 = digits.roundingIncrement; // If there is no rounding return 0.0 to indicate no rounding. // This is the high-runner case, by far. @@ -991,7 +709,7 @@ public class Currency extends MeasureUnit implements Serializable { return 0.0; } - int data0 = data[0]; // fraction digits + int data0 = digits.fractionDigits; // If the meta data is invalid, return 0.0 to indicate no rounding. if (data0 < 0 || data0 >= POW10.length) { @@ -1022,67 +740,10 @@ public class Currency extends MeasureUnit implements Serializable { isoCode = theISOCode; } - /** - * Internal function to look up currency data. Result is an array of - * two Integers. The first is the fraction digits. The second is the - * rounding increment, or 0 if none. The rounding increment is in - * units of 10^(-fraction_digits). - */ - private int[] findData() { - - try { - // Get CurrencyMeta resource out of root locale file. [This may - // move out of the root locale file later; if it does, update this - // code.] - UResourceBundle root = ICUResourceBundle.getBundleInstance(ICUResourceBundle.ICU_CURR_BASE_NAME, "supplementalData", ICUResourceBundle.ICU_DATA_CLASS_LOADER); - UResourceBundle currencyMeta = root.get("CurrencyMeta"); - - //Integer[] i = null; - //int defaultPos = -1; - int[] i = currencyMeta.get(isoCode).getIntVector(); - - // Do a linear search for isoCode. At the same time, - // record the position of the DEFAULT meta data. If the - // meta data becomes large, make this faster. - /*for (int j=0; j= 0) { - break; - } - } - */ - if (i == null) { - i = currencyMeta.get("DEFAULT").getIntVector(); - } - - if (i != null && i.length >= 2) { - return i; - } - } - catch (MissingResourceException e) {} - - // Config/build error; return hard-coded defaults - return LAST_RESORT_DATA; - } - - // Default currency meta data of last resort. We try to use the - // defaults encoded in the meta data resource bundle. If there is a - // configuration/build error and these are not available, we use these - // hard-coded defaults (which should be identical). - private static final int[] LAST_RESORT_DATA = new int[] { 2, 0 }; - // POW10[i] = 10^i - private static final int[] POW10 = { 1, 10, 100, 1000, 10000, 100000, - 1000000, 10000000, 100000000, 1000000000 }; + private static final int[] POW10 = { + 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 + }; // -------- BEGIN ULocale boilerplate -------- diff --git a/icu4j/main/classes/core/src/com/ibm/icu/util/UResourceBundle.java b/icu4j/main/classes/core/src/com/ibm/icu/util/UResourceBundle.java index 49cc2be9a71..72fbc604adb 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/util/UResourceBundle.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/util/UResourceBundle.java @@ -653,22 +653,37 @@ public abstract class UResourceBundle extends ResourceBundle{ * @stable ICU 3.8 */ public UResourceBundle get(String aKey) { - UResourceBundle obj = handleGet(aKey, null, this); + UResourceBundle obj = findTopLevel(aKey); if (obj == null) { - UResourceBundle res = this; - while ((res = res.getParent()) != null && obj == null) { - //call the get method to recursively fetch the resource - obj = res.handleGet(aKey, null, this); - } - if (obj == null) { - String fullName = ICUResourceBundle.getFullName(getBaseName(), getLocaleID()); - throw new MissingResourceException( - "Can't find resource for bundle " + fullName + ", key " - + aKey, this.getClass().getName(), aKey); + String fullName = ICUResourceBundle.getFullName(getBaseName(), getLocaleID()); + throw new MissingResourceException( + "Can't find resource for bundle " + fullName + ", key " + + aKey, this.getClass().getName(), aKey); + } + return obj; + } + + /** + * Returns a resource in a given resource that has a given key, or null if the + * resource is not found. + * + * @param aKey the key associated with the wanted resource + * @return the resource, or null + * @internal ICU internal use only + * @see #get(String) + */ + protected UResourceBundle findTopLevel(String aKey) { + // NOTE: this only works for top-level resources. For resources at lower + // levels, it fails when you fall back to the parent, since you're now + // looking at root resources, not at the corresponding nested resource. + for (UResourceBundle res = this; res != null; res = res.getParent()) { + UResourceBundle obj = res.handleGet(aKey, null, this); + if (obj != null) { + ((ICUResourceBundle) obj).setLoadingStatus(getLocaleID()); + return obj; } } - ((ICUResourceBundle)obj).setLoadingStatus(getLocaleID()); - return obj; + return null; } /** @@ -713,6 +728,33 @@ public abstract class UResourceBundle extends ResourceBundle{ ((ICUResourceBundle)obj).setLoadingStatus(getLocaleID()); return obj; } + + /** + * Returns a resource in a given resource that has a given index, or null if the + * resource is not found. + * + * @param aKey the key associated with the wanted resource + * @return the resource, or null + * @see #get(int) + * @internal ICU internal use only + */ + protected UResourceBundle findTopLevel(int index) { + // NOTE: this _barely_ works for top-level resources. For resources at lower + // levels, it fails when you fall back to the parent, since you're now + // looking at root resources, not at the corresponding nested resource. + // Not only that, but unless the indices correspond 1-to-1, the index will + // lose meaning. Essentially this only works if the child resource arrays + // are prefixes of their parent arrays. + for (UResourceBundle res = this; res != null; res = res.getParent()) { + UResourceBundle obj = res.handleGet(index, null, this); + if (obj != null) { + ((ICUResourceBundle) obj).setLoadingStatus(getLocaleID()); + return obj; + } + } + return null; + } + /** * Returns the keys in this bundle as an enumeration * @return an enumeration containing key strings, @@ -754,6 +796,7 @@ public abstract class UResourceBundle extends ResourceBundle{ } return keys; } + private Set keys = null; /** * Returns a Set of the keys contained only in this ResourceBundle. diff --git a/icu4j/main/classes/currdata/.classpath b/icu4j/main/classes/currdata/.classpath new file mode 100644 index 00000000000..f145b1f226d --- /dev/null +++ b/icu4j/main/classes/currdata/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/icu4j/main/classes/currdata/.externalToolBuilders/copy-data-currdata.launch b/icu4j/main/classes/currdata/.externalToolBuilders/copy-data-currdata.launch new file mode 100644 index 00000000000..ba71d5ab375 --- /dev/null +++ b/icu4j/main/classes/currdata/.externalToolBuilders/copy-data-currdata.launch @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/icu4j/main/classes/currdata/.externalToolBuilders/copy-data-langdata.launch b/icu4j/main/classes/currdata/.externalToolBuilders/copy-data-langdata.launch new file mode 100644 index 00000000000..8d9cef16ce9 --- /dev/null +++ b/icu4j/main/classes/currdata/.externalToolBuilders/copy-data-langdata.launch @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/icu4j/main/classes/currdata/.project b/icu4j/main/classes/currdata/.project new file mode 100644 index 00000000000..377b9c51b12 --- /dev/null +++ b/icu4j/main/classes/currdata/.project @@ -0,0 +1,29 @@ + + + icu4j-currdata + + + icu4j-core + icu4j-shared + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.ui.externaltools.ExternalToolBuilder + full,incremental, + + + LaunchConfigHandle + <project>/.externalToolBuilders/copy-data-currdata.launch.launch + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/icu4j/main/classes/currdata/.settings/org.eclipse.jdt.core.prefs b/icu4j/main/classes/currdata/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000000..e46367f90ca --- /dev/null +++ b/icu4j/main/classes/currdata/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,345 @@ +#Thu Aug 27 17:47:12 EDT 2009 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.5 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.doc.comment.support=enabled +org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.autoboxing=ignore +org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning +org.eclipse.jdt.core.compiler.problem.deadCode=warning +org.eclipse.jdt.core.compiler.problem.deprecation=ignore +org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled +org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled +org.eclipse.jdt.core.compiler.problem.discouragedReference=warning +org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning +org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled +org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore +org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning +org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning +org.eclipse.jdt.core.compiler.problem.forbiddenReference=error +org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning +org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning +org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore +org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore +org.eclipse.jdt.core.compiler.problem.invalidJavadoc=warning +org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=disabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=public +org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore +org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning +org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore +org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore +org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore +org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public +org.eclipse.jdt.core.compiler.problem.missingJavadocTagDescription=all_standard_tags +org.eclipse.jdt.core.compiler.problem.missingJavadocTags=ignore +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=public +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore +org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning +org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore +org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning +org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning +org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore +org.eclipse.jdt.core.compiler.problem.nullReference=warning +org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning +org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore +org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore +org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore +org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning +org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore +org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore +org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled +org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning +org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled +org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore +org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning +org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning +org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore +org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning +org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore +org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore +org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled +org.eclipse.jdt.core.compiler.problem.unusedImport=warning +org.eclipse.jdt.core.compiler.problem.unusedLabel=warning +org.eclipse.jdt.core.compiler.problem.unusedLocal=warning +org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled +org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning +org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning +org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning +org.eclipse.jdt.core.compiler.source=1.5 +org.eclipse.jdt.core.formatter.align_type_members_on_columns=false +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_assignment=0 +org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_compact_if=16 +org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80 +org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0 +org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16 +org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16 +org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16 +org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_after_package=1 +org.eclipse.jdt.core.formatter.blank_lines_before_field=0 +org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0 +org.eclipse.jdt.core.formatter.blank_lines_before_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 +org.eclipse.jdt.core.formatter.blank_lines_before_method=1 +org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 +org.eclipse.jdt.core.formatter.blank_lines_before_package=0 +org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1 +org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 +org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false +org.eclipse.jdt.core.formatter.comment.format_block_comments=true +org.eclipse.jdt.core.formatter.comment.format_header=false +org.eclipse.jdt.core.formatter.comment.format_html=true +org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true +org.eclipse.jdt.core.formatter.comment.format_line_comments=true +org.eclipse.jdt.core.formatter.comment.format_source_code=true +org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true +org.eclipse.jdt.core.formatter.comment.indent_root_tags=true +org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert +org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert +org.eclipse.jdt.core.formatter.comment.line_length=120 +org.eclipse.jdt.core.formatter.compact_else_if=true +org.eclipse.jdt.core.formatter.continuation_indentation=2 +org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2 +org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true +org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_empty_lines=false +org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true +org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false +org.eclipse.jdt.core.formatter.indentation.size=4 +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert +org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.join_lines_in_comments=true +org.eclipse.jdt.core.formatter.join_wrapped_lines=true +org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false +org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false +org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false +org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false +org.eclipse.jdt.core.formatter.lineSplit=120 +org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false +org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0 +org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1 +org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true +org.eclipse.jdt.core.formatter.tabulation.char=space +org.eclipse.jdt.core.formatter.tabulation.size=4 +org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false +org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true diff --git a/icu4j/main/classes/currdata/.settings/org.eclipse.jdt.ui.prefs b/icu4j/main/classes/currdata/.settings/org.eclipse.jdt.ui.prefs new file mode 100644 index 00000000000..646a3929f0a --- /dev/null +++ b/icu4j/main/classes/currdata/.settings/org.eclipse.jdt.ui.prefs @@ -0,0 +1,10 @@ +#Wed Jun 17 11:09:27 EDT 2009 +eclipse.preferences.version=1 +formatter_profile=_ICU4J Standard +formatter_settings_version=11 +org.eclipse.jdt.ui.ignorelowercasenames=true +org.eclipse.jdt.ui.importorder=java;javax;org;com; +org.eclipse.jdt.ui.javadoc=true +org.eclipse.jdt.ui.ondemandthreshold=99 +org.eclipse.jdt.ui.staticondemandthreshold=99 +org.eclipse.jdt.ui.text.custom_code_templates= diff --git a/icu4j/main/classes/currdata/build.properties b/icu4j/main/classes/currdata/build.properties new file mode 100644 index 00000000000..a21fb196196 --- /dev/null +++ b/icu4j/main/classes/currdata/build.properties @@ -0,0 +1,6 @@ +#******************************************************************************* +#* Copyright (C) 2009, International Business Machines Corporation and * +#* others. All Rights Reserved. * +#******************************************************************************* +shared.dir = ../../shared +javac.compilerarg = -Xlint:all,-deprecation,-dep-ann diff --git a/icu4j/main/classes/currdata/build.xml b/icu4j/main/classes/currdata/build.xml new file mode 100644 index 00000000000..3051404f6a0 --- /dev/null +++ b/icu4j/main/classes/currdata/build.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/icu4j/main/classes/currdata/currdata-build.launch b/icu4j/main/classes/currdata/currdata-build.launch new file mode 100644 index 00000000000..959fd3eb7a0 --- /dev/null +++ b/icu4j/main/classes/currdata/currdata-build.launch @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/icu4j/main/classes/currdata/manifest.stub b/icu4j/main/classes/currdata/manifest.stub new file mode 100644 index 00000000000..57d1a636059 --- /dev/null +++ b/icu4j/main/classes/currdata/manifest.stub @@ -0,0 +1,11 @@ +Manifest-Version: 1.0 + +Name: com/ibm/icu/impl +Specification-Title: ICU for Java Currency Name Data +Specification-Version: @SPECVERSION@ +Specification-Vendor: ICU +Implementation-Title: ICU for Java Currency Name Data +Implementation-Version: @IMPLVERSION@ +Implementation-Vendor: IBM Corporation +Implementation-Vendor-Id: com.ibm +Copyright-Info: @COPYRIGHT@ \ No newline at end of file diff --git a/icu4j/main/classes/currdata/src/com/ibm/icu/impl/ICUCurrencyDisplayInfoProvider.java b/icu4j/main/classes/currdata/src/com/ibm/icu/impl/ICUCurrencyDisplayInfoProvider.java new file mode 100644 index 00000000000..b293c976f72 --- /dev/null +++ b/icu4j/main/classes/currdata/src/com/ibm/icu/impl/ICUCurrencyDisplayInfoProvider.java @@ -0,0 +1,280 @@ +/* + ******************************************************************************* + * Copyright (C) 2009, International Business Machines Corporation and * + * others. All Rights Reserved. * + ******************************************************************************* + */ +package com.ibm.icu.impl; + +import java.lang.ref.SoftReference; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; + +import com.ibm.icu.impl.CurrencyData.CurrencyDisplayInfo; +import com.ibm.icu.impl.CurrencyData.CurrencyDisplayInfoProvider; +import com.ibm.icu.impl.CurrencyData.CurrencyFormatInfo; +import com.ibm.icu.impl.CurrencyData.CurrencySpacingInfo; +import com.ibm.icu.util.ULocale; +import com.ibm.icu.util.UResourceBundle; + +public class ICUCurrencyDisplayInfoProvider implements CurrencyDisplayInfoProvider { + public ICUCurrencyDisplayInfoProvider() { + } + + public CurrencyDisplayInfo getInstance(ULocale locale, boolean withFallback) { + // this is a test + ICUResourceBundle rb = (ICUResourceBundle) UResourceBundle.getBundleInstance( + ICUResourceBundle.ICU_CURR_BASE_NAME, locale); + if (!withFallback) { + int status = rb.getLoadingStatus(); + if (status == ICUResourceBundle.FROM_DEFAULT || status == ICUResourceBundle.FROM_ROOT) { + return CurrencyData.DefaultInfo.getWithFallback(false); + } + } + return new ICUCurrencyDisplayInfo(rb, withFallback); + } + + public boolean hasData() { + return true; + } + + static class ICUCurrencyDisplayInfo extends CurrencyDisplayInfo { + private final boolean fallback; + private final ICUResourceBundle rb; + private final ICUResourceBundle currencies; + private final ICUResourceBundle plurals; + private SoftReference> _symbolMapRef; + private SoftReference> _nameMapRef; + + public ICUCurrencyDisplayInfo(ICUResourceBundle rb, boolean fallback) { + this.fallback = fallback; + this.rb = rb; + this.currencies = rb.findTopLevel("Currencies"); + this.plurals = rb.findTopLevel("CurrencyPlurals"); + } + + @Override + public ULocale getLocale() { + return rb.getULocale(); + } + + @Override + public String getName(String isoCode) { + return getName(isoCode, false); + } + + @Override + public String getSymbol(String isoCode) { + return getName(isoCode, true); + } + + private String getName(String isoCode, boolean symbolName) { + if (currencies != null) { + ICUResourceBundle result = currencies.findWithFallback(isoCode); + if (result != null) { + if (!fallback) { + int status = result.getLoadingStatus(); + if (status == ICUResourceBundle.FROM_DEFAULT || + status == ICUResourceBundle.FROM_ROOT) { + return null; + } + } + return result.getString(symbolName ? 0 : 1); + } + } + + return fallback ? isoCode : null; + } + + @Override + public String getPluralName(String isoCode, String pluralKey ) { + // See http://unicode.org/reports/tr35/#Currencies, especially the fallback rule. + if (plurals != null) { + ICUResourceBundle pluralsBundle = plurals.findWithFallback(isoCode); + if (pluralsBundle != null) { + ICUResourceBundle pluralBundle = pluralsBundle.findWithFallback(pluralKey); + if (pluralBundle == null) { + if (!fallback) { + return null; + } + pluralBundle = pluralsBundle.findWithFallback("other"); + if (pluralBundle == null) { + return getName(isoCode); + } + } + return pluralBundle.getString(); + } + } + + return fallback ? getName(isoCode) : null; + } + + @Override + public Map symbolMap() { + Map map = _symbolMapRef == null ? null : _symbolMapRef.get(); + if (map == null) { + map = _createSymbolMap(); + // atomic and idempotent + _symbolMapRef = new SoftReference>(map); + } + return map; + } + + @Override + public Map nameMap() { + Map map = _nameMapRef == null ? null : _nameMapRef.get(); + if (map == null) { + map = _createNameMap(); + // atomic and idempotent + _nameMapRef = new SoftReference>(map); + } + return map; + } + + @Override + public Map getUnitPatterns() { + Map result = new HashMap(); + + ULocale locale = rb.getULocale(); + for (;locale != null; locale = locale.getFallback()) { + ICUResourceBundle r = (ICUResourceBundle) UResourceBundle.getBundleInstance( + ICUResourceBundle.ICU_CURR_BASE_NAME, locale); + if (r == null) { + continue; + } + ICUResourceBundle cr = r.findWithFallback("CurrencyUnitPatterns"); + if (cr == null) { + continue; + } + for (int index = 0, size = cr.getSize(); index < size; ++index) { + ICUResourceBundle b = (ICUResourceBundle) cr.get(index); + String key = b.getKey(); + if (result.containsKey(key)) { + continue; + } + result.put(key, b.getString()); + } + } + + // Default result is the empty map. Callers who require a pattern will have to + // supply a default. + return Collections.unmodifiableMap(result); + } + + @Override + public CurrencyFormatInfo getFormatInfo(String isoCode) { + ICUResourceBundle crb = currencies.findWithFallback(isoCode); + if (crb != null && crb.getSize() > 2) { + crb = crb.at(2); + if (crb != null) { + String pattern = crb.getString(0); + char separator = crb.getString(1).charAt(0); + char groupingSeparator = crb.getString(2).charAt(0); + return new CurrencyFormatInfo(pattern, separator, groupingSeparator); + } + } + return null; + } + + @Override + public CurrencySpacingInfo getSpacingInfo() { + ICUResourceBundle srb = rb.findWithFallback("currencySpacing"); + if (srb != null) { + ICUResourceBundle brb = srb.findWithFallback("beforeCurrency"); + ICUResourceBundle arb = srb.findWithFallback("afterCurrency"); + if (brb != null && brb != null) { + String beforeCurrencyMatch = brb.findWithFallback("currencyMatch").getString(); + String beforeContextMatch = brb.findWithFallback("surroundingMatch").getString(); + String beforeInsert = brb.findWithFallback("insertBetween").getString(); + String afterCurrencyMatch = arb.findWithFallback("currencyMatch").getString(); + String afterContextMatch = arb.findWithFallback("surroundingMatch").getString(); + String afterInsert = arb.findWithFallback("insertBetween").getString(); + + return new CurrencySpacingInfo( + beforeCurrencyMatch, beforeContextMatch, beforeInsert, + afterCurrencyMatch, afterContextMatch, afterInsert); + } + } + return fallback ? CurrencySpacingInfo.DEFAULT : null; + } + + private Map _createSymbolMap() { + Map result = new HashMap(); + + for (ULocale locale = rb.getULocale(); locale != null; locale = locale.getFallback()) { + ICUResourceBundle bundle = (ICUResourceBundle) + UResourceBundle.getBundleInstance(ICUResourceBundle.ICU_CURR_BASE_NAME, locale); + ICUResourceBundle curr = bundle.findTopLevel("Currencies"); + if (curr == null) { + continue; + } + for (int i = 0; i < curr.getSize(); ++i) { + ICUResourceBundle item = curr.at(i); + String isoCode = item.getKey(); + if (!result.containsKey(isoCode)) { + // put the code itself + result.put(isoCode, isoCode); + // 0 == symbol element + String symbol = item.getString(0); + result.put(symbol, isoCode); + } + } + } + + return Collections.unmodifiableMap(result); + } + + private Map _createNameMap() { + // ignore case variants + Map result = new TreeMap(String.CASE_INSENSITIVE_ORDER); + + Set visited = new HashSet(); + Map> visitedPlurals = new HashMap>(); + for (ULocale locale = rb.getULocale(); locale != null; locale = locale.getFallback()) { + ICUResourceBundle bundle = (ICUResourceBundle) + UResourceBundle.getBundleInstance(ICUResourceBundle.ICU_CURR_BASE_NAME, locale); + ICUResourceBundle curr = bundle.findTopLevel("Currencies"); + if (curr != null) { + for (int i = 0; i < curr.getSize(); ++i) { + ICUResourceBundle item = curr.at(i); + String isoCode = item.getKey(); + if (!visited.contains(isoCode)) { + visited.add(isoCode); + // 1 == name element + String name = item.getString(1); + result.put(name, isoCode); + } + } + } + + ICUResourceBundle plurals = bundle.findTopLevel("CurrencyPlurals"); + if (plurals != null) { + for (int i = 0; i < plurals.getSize(); ++i) { + ICUResourceBundle item = plurals.at(i); + String isoCode = item.getKey(); + Set pluralSet = visitedPlurals.get(isoCode); + if (pluralSet == null) { + pluralSet = new HashSet(); + visitedPlurals.put(isoCode, pluralSet); + } + for (int j = 0; j < item.getSize(); ++j) { + ICUResourceBundle plural = item.at(j); + String pluralType = plural.getKey(); + if (!pluralSet.contains(pluralType)) { + String pluralName = plural.getString(); + result.put(pluralName, isoCode); + pluralSet.add(pluralType); + } + } + } + } + } + + return Collections.unmodifiableMap(result); + } + } +} diff --git a/icu4j/main/classes/currdata/src/com/ibm/icu/impl/ICUCurrencyMetaInfo.java b/icu4j/main/classes/currdata/src/com/ibm/icu/impl/ICUCurrencyMetaInfo.java new file mode 100644 index 00000000000..8964a659d68 --- /dev/null +++ b/icu4j/main/classes/currdata/src/com/ibm/icu/impl/ICUCurrencyMetaInfo.java @@ -0,0 +1,250 @@ +/* + ******************************************************************************* + * Copyright (C) 2009, International Business Machines Corporation and * + * others. All Rights Reserved. * + ******************************************************************************* + */ +package com.ibm.icu.impl; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * ICU's currency meta info data. + */ +public class ICUCurrencyMetaInfo extends CurrencyMetaInfo { + private ICUResourceBundle regionInfo; + private ICUResourceBundle digitInfo; + + public ICUCurrencyMetaInfo() { + ICUResourceBundle bundle = (ICUResourceBundle) ICUResourceBundle.getBundleInstance( + ICUResourceBundle.ICU_CURR_BASE_NAME, "supplementalData", + ICUResourceBundle.ICU_DATA_CLASS_LOADER); + regionInfo = bundle.findTopLevel("CurrencyMap"); + digitInfo = bundle.findTopLevel("CurrencyMeta"); + } + + @Override + public List currencyInfo(CurrencyFilter filter) { + return collect(new InfoCollector(), filter); + } + + @Override + public List currencies(CurrencyFilter filter) { + return collect(new CurrencyCollector(), filter); + } + + @Override + public List regions(CurrencyFilter filter) { + return collect(new RegionCollector(), filter); + } + + @Override + public CurrencyDigits currencyDigits(String isoCode) { + ICUResourceBundle b = digitInfo.findWithFallback(isoCode); + if (b == null) { + b = digitInfo.findWithFallback("DEFAULT"); + } + int[] data = b.getIntVector(); + return new CurrencyDigits(data[0], data[1]); + } + + private List collect(Collector collector, CurrencyFilter filter) { + // We rely on the fact that the data lists the regions in order, and the + // priorities in order within region. This means we don't need + // to sort the results to ensure the ordering matches the spec. + + if (filter == null) { + filter = CurrencyFilter.all(); + } + int needed = collector.collects(); + if (filter.region != null) { + needed |= Region; + } + if (filter.currency != null) { + needed |= Currency; + } + if (filter.from != Long.MIN_VALUE || filter.to != Long.MAX_VALUE) { + needed |= Date; + } + + if (needed != 0) { + if (filter.region != null) { + ICUResourceBundle b = regionInfo.findWithFallback(filter.region); + if (b != null) { + collectRegion(collector, filter, needed, b); + } + } else { + for (int i = 0; i < regionInfo.getSize(); i++) { + collectRegion(collector, filter, needed, regionInfo.at(i)); + } + } + } + + return collector.getList(); + } + + private void collectRegion(Collector collector, CurrencyFilter filter, + int needed, ICUResourceBundle b) { + + String region = b.getKey(); + if ((needed & nonRegion) == 0) { + collector.collect(b.getKey(), null, 0, 0, -1); + return; + } + + for (int i = 0; i < b.getSize(); i++) { + ICUResourceBundle r = b.at(i); + if (r.getSize() == 0) { + // AQ[0] is an empty array instead of a table, so the bundle is null. + // There's no data here, so we skip this entirely. + // We'd do a type test, but the ResourceArray type is private. + continue; + } + String currency = null; + long from = Long.MIN_VALUE; + long to = Long.MAX_VALUE; + + if ((needed & Currency) != 0) { + ICUResourceBundle currBundle = r.at("id"); + currency = currBundle.getString(); + if (filter.currency != null && !filter.currency.equals(currency)) { + continue; + } + } + + if ((needed & Date) != 0) { + from = getDate(r.at("from"), Long.MIN_VALUE); + to = getDate(r.at("to"), Long.MAX_VALUE); + // In the data, to is always > from. This means that when we have a range + // from == to, the comparisons below will always do the right thing, despite + // the range being technically empty. It really should be [from, from+1) but + // this way we don't need to fiddle with it. + if (filter.from >= to) { + continue; + } + if (filter.to <= from) { + continue; + } + } + + // data lists elements in priority order, so 'i' suffices + collector.collect(region, currency, from, to, i); + } + } + + private static final long MASK = 4294967295L; + private long getDate(ICUResourceBundle b, long defaultValue) { + if (b == null) { + return defaultValue; + } + int[] values = b.getIntVector(); + return ((long) values[0] << 32) | ((long) values[1] & MASK); + } + + // Utility, just because I don't like the n^2 behavior of using list.contains to build a + // list of unique items. If we used java 6 we could use their class for this. + private static class UniqueList { + private Set seen = new HashSet(); + private List list = new ArrayList(); + + private static UniqueList create() { + return new UniqueList(); + } + + void add(T value) { + if (!seen.contains(value)) { + list.add(value); + seen.add(value); + } + } + + List list() { + return Collections.unmodifiableList(list); + } + } + + private static class InfoCollector implements Collector { + // Data is already unique by region/priority, so we don't need to be concerned + // about duplicates. + private List result = new ArrayList(); + + public void collect(String region, String currency, long from, long to, int priority) { + result.add(new CurrencyInfo(region, currency, from, to, priority)); + } + + public List getList() { + return Collections.unmodifiableList(result); + } + + public int collects() { + return Region | Currency | Date; + } + } + + private static class RegionCollector implements Collector { + private final UniqueList result = UniqueList.create(); + + public void collect(String region, String currency, long from, long to, int priority) { + result.add(region); + } + + public int collects() { + return Region; + } + + public List getList() { + return result.list(); + } + } + + private static class CurrencyCollector implements Collector { + private final UniqueList result = UniqueList.create(); + + public void collect(String region, String currency, long from, long to, int priority) { + result.add(currency); + } + + public int collects() { + return Currency; + } + + public List getList() { + return result.list(); + } + } + + private static final int Region = 1; + private static final int Currency = 2; + private static final int Date = 4; + + private static final int nonRegion = Currency | Date; + + private static interface Collector { + /** + * A bitmask of Region/Currency/Date indicating which features we collect. + * @return the bitmask + */ + int collects(); + + /** + * Called with data passed by filter. Values not collected by filter should be ignored. + * @param region the region code (null if ignored) + * @param currency the currency code (null if ignored) + * @param from start time (0 if ignored) + * @param to end time (0 if ignored) + * @param priority priority (-1 if ignored) + */ + void collect(String region, String currency, long from, long to, int priority); + + /** + * Return the list of unique items in the order in which we encountered them for the + * first time. The returned list is unmodifiable. + * @return the list + */ + List getList(); + } +} diff --git a/icu4j/main/shared/build/common-targets.xml b/icu4j/main/shared/build/common-targets.xml index bdcb30bfb7f..1807f28f6db 100644 --- a/icu4j/main/shared/build/common-targets.xml +++ b/icu4j/main/shared/build/common-targets.xml @@ -99,6 +99,15 @@ + + + + + + + + + diff --git a/icu4j/main/shared/build/common.properties b/icu4j/main/shared/build/common.properties index f332ef4c4cf..a78474649a9 100644 --- a/icu4j/main/shared/build/common.properties +++ b/icu4j/main/shared/build/common.properties @@ -36,6 +36,7 @@ icu4j.testdata.jar = ${shared.dir}/data/testdata.jar icu4j.core.jar = ${icu4j.core.dir}/${jar.dir}/icu4j-core.jar icu4j.collate.jar = ${icu4j.collate.dir}/${jar.dir}/icu4j-collate.jar icu4j.charset.jar = ${icu4j.charset.dir}/${jar.dir}/icu4j-charsets.jar +icu4j.currdata.jar = ${icu4j.currdata.dir}/${jar.dir}/icu4j-currdata.jar icu4j.langdata.jar = ${icu4j.langdata.dir}/${jar.dir}/icu4j-langdata.jar icu4j.localespi.jar = ${icu4j.localespi.dir}/${jar.dir}/icu4j-localespi.jar icu4j.regiondata.jar = ${icu4j.regiondata.dir}/${jar.dir}/icu4j-regiondata.jar diff --git a/icu4j/main/shared/build/locations-eclipse.properties b/icu4j/main/shared/build/locations-eclipse.properties index 14fb6c64faa..8d61433a295 100644 --- a/icu4j/main/shared/build/locations-eclipse.properties +++ b/icu4j/main/shared/build/locations-eclipse.properties @@ -7,6 +7,7 @@ shared.dir = ${workspace_loc:/icu4j-shared} icu4j.core.dir = ${workspace_loc:/icu4j-core} icu4j.charset.dir = ${workspace_loc:/icu4j-charset} icu4j.collate.dir = ${workspace_loc:/icu4j-collate} +icu4j.currdata.dir = ${workspace_loc:/icu4j-currdata} icu4j.langdata.dir = ${workspace_loc:/icu4j-langdata} icu4j.localespi.dir = ${workspace_loc:/icu4j-localespi} icu4j.regiondata.dir = ${workspace_loc:/icu4j-regiondata} diff --git a/icu4j/main/shared/build/locations.properties b/icu4j/main/shared/build/locations.properties index d8a0b93d701..c9fb47b667b 100644 --- a/icu4j/main/shared/build/locations.properties +++ b/icu4j/main/shared/build/locations.properties @@ -6,6 +6,7 @@ icu4j.collate.dir = ${shared.dir}/../classes/collate icu4j.core.dir = ${shared.dir}/../classes/core icu4j.charset.dir = ${shared.dir}/../classes/charset +icu4j.currdata.dir = ${shared.dir}/../classes/currdata icu4j.langdata.dir = ${shared.dir}/../classes/langdata icu4j.localespi.dir = ${shared.dir}/../classes/localespi icu4j.regiondata.dir = ${shared.dir}/../classes/regiondata diff --git a/icu4j/main/tests/core/.classpath b/icu4j/main/tests/core/.classpath index e710a5cc973..bccc2225a90 100644 --- a/icu4j/main/tests/core/.classpath +++ b/icu4j/main/tests/core/.classpath @@ -6,5 +6,6 @@ + diff --git a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/util/CurrencyTest.java b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/util/CurrencyTest.java index 5ab77b9e21b..b18d42d9cc6 100644 --- a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/util/CurrencyTest.java +++ b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/util/CurrencyTest.java @@ -11,10 +11,13 @@ package com.ibm.icu.dev.test.util; +import java.text.DateFormat; +import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.Date; import java.util.HashSet; import java.util.Locale; +import java.util.Set; import com.ibm.icu.dev.test.TestFmwk; import com.ibm.icu.text.DecimalFormatSymbols; @@ -196,216 +199,63 @@ public class CurrencyTest extends TestFmwk { } } - public void TestAvailableCurrencyCodes() - { - // local Variables - String[] currency; - - // Cycle through historical currencies - currency = Currency.getAvailableCurrencyCodes(new ULocale("eo_AM"), new Date(-630720000000L)); // pre 1961 - if (currency != null) - { - errln("FAIL: didn't return null for eo_AM"); + public void TestAvailableCurrencyCodes() { + String[][] tests = { + { "eo_AM", "1950-01-05" }, + { "eo_AM", "1969-12-31", "SUR" }, + { "eo_AM", "1991-12-26", "RUR" }, + { "eo_AM", "2000-12-23", "AMD" }, + { "eo_AD", "2000-12-23", "EUR", "ESP", "FRF", "ADP" }, + { "eo_AD", "1969-12-31", "ESP", "FRF", "ADP" }, + { "eo_AD", "1950-01-05", "ESP", "ADP" }, + { "eo_AD", "1900-01-17", "ESP" }, + { "eo_UA", "1994-12-25" }, + { "eo_QQ", "1969-12-31" }, + { "eo_AO", "2000-12-23", "AOA" }, + { "eo_AO", "1995-12-25", "AOR", "AON" }, + { "eo_AO", "1990-12-26", "AON", "AOK" }, + { "eo_AO", "1979-12-29", "AOK" }, + { "eo_AO", "1969-12-31" }, + { "eo_DE@currency=DEM", "2000-12-23", "EUR", "DEM" }, + { "en_US", null, "USD" }, + { "en_US_PREEURO", null, "USD" }, + { "en_US_Q", null, "USD" }, + }; + + DateFormat fmt = new SimpleDateFormat("yyyy-MM-dd", Locale.US); + for (String[] test : tests) { + ULocale locale = new ULocale(test[0]); + String timeString = test[1]; + Date date; + if (timeString == null) { + date = new Date(); + timeString = "today"; + } else { + try { + date = fmt.parse(timeString); + } catch (Exception e) { + fail("could not parse date: " + timeString); + continue; + } + } + String[] expected = null; + if (test.length > 2) { + expected = new String[test.length - 2]; + System.arraycopy(test, 2, expected, 0, expected.length); + } + String[] actual = Currency.getAvailableCurrencyCodes(locale, date); + + // Order is not important as of 4.4. We never documented that it was. + Set expectedSet = new HashSet(); + if (expected != null) { + expectedSet.addAll(Arrays.asList(expected)); + } + Set actualSet = new HashSet(); + if (actual != null) { + actualSet.addAll(Arrays.asList(actual)); + } + assertEquals(locale + " on " + timeString, expectedSet, actualSet); } - - currency = Currency.getAvailableCurrencyCodes(new ULocale("eo_AM"), new Date(0L)); // 1970 - if (currency.length != 1) - { - errln("FAIL: didn't return 1 for eo_AM returned: " + currency.length); - } - if (!"SUR".equals(currency[0])) - { - errln("didn't return SUR for eo_AM returned: " + currency[0]); - } - - currency = Currency.getAvailableCurrencyCodes(new ULocale("eo_AM"), new Date(693792000000L)); // 1992 - if (currency.length != 1) - { - errln("FAIL: didn't return 1 for eo_AM returned: " + currency.length); - } - if (!"RUR".equals(currency[0])) - { - errln("didn't return RUR for eo_AM returned: " + currency[0]); - } - - currency = Currency.getAvailableCurrencyCodes(new ULocale("eo_AM"), new Date(977616000000L)); // post 1993 - if (currency.length != 1) - { - errln("FAIL: didn't return 1 for eo_AM returned: " + currency.length); - } - if (!"AMD".equals(currency[0])) - { - errln("didn't return AMD for eo_AM returned: " + currency[0]); - } - - // Locale AD has multiple currencies at once - currency = Currency.getAvailableCurrencyCodes(new ULocale("eo_AD"), new Date(977616000000L)); // 2001 - if (currency.length != 4) - { - errln("FAIL: didn't return 4 for eo_AD returned: " + currency.length); - } - if (!"EUR".equals(currency[0])) - { - errln("didn't return EUR for eo_AD returned: " + currency[0]); - } - if (!"ESP".equals(currency[1])) - { - errln("didn't return ESP for eo_AD returned: " + currency[1]); - } - if (!"FRF".equals(currency[2])) - { - errln("didn't return FRF for eo_AD returned: " + currency[2]); - } - if (!"ADP".equals(currency[3])) - { - errln("didn't return ADP for eo_AD returned: " + currency[3]); - } - - currency = Currency.getAvailableCurrencyCodes(new ULocale("eo_AD"), new Date(0L)); // 1970 - if (currency.length != 3) - { - errln("FAIL: didn't return 3 for eo_AD returned: " + currency.length); - } - if (!"ESP".equals(currency[0])) - { - errln("didn't return ESP for eo_AD returned: " + currency[0]); - } - if (!"FRF".equals(currency[1])) - { - errln("didn't return FRF for eo_AD returned: " + currency[1]); - } - if (!"ADP".equals(currency[2])) - { - errln("didn't return ADP for eo_AD returned: " + currency[2]); - } - - currency = Currency.getAvailableCurrencyCodes(new ULocale("eo_AD"), new Date(-630720000000L)); // 1950 - if (currency.length != 2) - { - errln("FAIL: didn't return 2 for eo_AD returned: " + currency.length); - } - if (!"ESP".equals(currency[0])) - { - errln("didn't return ESP for eo_AD returned: " + currency[0]); - } - if (!"ADP".equals(currency[1])) - { - errln("didn't return ADP for eo_AD returned: " + currency[1]); - } - - currency = Currency.getAvailableCurrencyCodes(new ULocale("eo_AD"), new Date(-2207520000000L)); // 1900 - if (currency.length != 1) - { - errln("FAIL: didn't return 1 for eo_AD returned: " + currency.length); - } - if (!"ESP".equals(currency[0])) - { - errln("didn't return ESP for eo_AD returned: " + currency[0]); - } - - // Locale UA has gap between years 1994 - 1996 - currency = Currency.getAvailableCurrencyCodes(new ULocale("eo_UA"), new Date(788400000000L)); - if (currency != null) - { - errln("FAIL: didn't return null for eo_UA"); - } - - // Test for bogus locale - currency = Currency.getAvailableCurrencyCodes(new ULocale("eo_QQ"), new Date(0L)); - if (currency != null) - { - errln("FAIL: didn't return null for eo_QQ"); - } - - // Cycle through historical currencies - currency = Currency.getAvailableCurrencyCodes(new ULocale("eo_AO"), new Date(977616000000L)); // 2001 - if (currency.length != 1) - { - errln("FAIL: didn't return 1 for eo_AO returned: " + currency.length); - } - if (!"AOA".equals(currency[0])) - { - errln("didn't return AOA for eo_AO returned: " + currency[0]); - } - - currency = Currency.getAvailableCurrencyCodes(new ULocale("eo_AO"), new Date(819936000000L)); // 1996 - if (currency.length != 2) - { - errln("FAIL: didn't return 2 for eo_AO returned: " + currency.length); - } - if (!"AOR".equals(currency[0])) - { - errln("didn't return AOR for eo_AO returned: " + currency[0]); - } - if (!"AON".equals(currency[1])) - { - errln("didn't return AON for eo_AO returned: " + currency[1]); - } - - currency = Currency.getAvailableCurrencyCodes(new ULocale("eo_AO"), new Date(662256000000L)); // - if (currency.length != 2) - { - errln("FAIL: didn't return 2 for eo_AO returned: " + currency.length); - } - if (!"AON".equals(currency[0])) - { - errln("didn't return AON for eo_AO returned: " + currency[0]); - } - if (!"AOK".equals(currency[1])) - { - errln("didn't return AOK for eo_AO returned: " + currency[1]); - } - - currency = Currency.getAvailableCurrencyCodes(new ULocale("eo_AO"), new Date(315360000000L)); // 1980 - if (currency.length != 1) - { - errln("FAIL: didn't return 1 for eo_AO returned: " + currency.length); - } - if (!"AOK".equals(currency[0])) - { - errln("didn't return AOK for eo_AO returned: " + currency[0]); - } - - currency = Currency.getAvailableCurrencyCodes(new ULocale("eo_AO"), new Date(0L)); // 1970 - if (currency != null) - { - errln("FAIL: didn't return null for eo_AO"); - } - - // Test with currency keyword override - currency = Currency.getAvailableCurrencyCodes(new ULocale("eo_DE@currency=DEM"), new Date(977616000000L)); // 2001 - if (currency.length != 2) - { - errln("FAIL: didn't return 2 for eo_DE@currency=DEM returned: " + currency.length); - } - if (!"EUR".equals(currency[0])) - { - errln("didn't return EUR for eo_DE@currency=DEM returned: " + currency[0]); - } - if (!"DEM".equals(currency[1])) - { - errln("didn't return DEM for eo_DE@currency=DEM returned: " + currency[1]); - } - - // Test Euro Support - currency = Currency.getAvailableCurrencyCodes(new ULocale("en_US"), new Date(System.currentTimeMillis())); - if (!"USD".equals(currency[0])) - { - errln("didn't return USD for en_US returned: " + currency[0]); - } - - currency = Currency.getAvailableCurrencyCodes(new ULocale("en_US_PREEURO"), new Date(System.currentTimeMillis())); - if (!"USD".equals(currency[0])) - { - errln("didn't return USD for en_US_PREEURO returned: " + currency[0]); - } - - currency = Currency.getAvailableCurrencyCodes(new ULocale("en_US_Q"), new Date(System.currentTimeMillis())); - if (!"USD".equals(currency[0])) - { - errln("didn't return USD for en_US_Q returned: " + currency[0]); - } - } public void TestDeprecatedCurrencyFormat() { @@ -427,14 +277,15 @@ public class CurrencyTest extends TestFmwk { public void TestGetKeywordValues(){ final String[][] PREFERRED = { - {"root", "USD"}, - {"und", "USD"}, - {"und_ZZ", "USD"}, + {"root", }, + {"und", }, + {"und_ZZ", }, {"en_US", "USD"}, - {"en_029", "USD"}, + {"en_029", }, {"en_TH", "THB"}, {"de", "EUR"}, {"de_DE", "EUR"}, + {"de_ZZ", }, {"ar", "EGP"}, {"ar_PS", "JOD", "ILS"}, {"en@currency=CAD", "USD"}, @@ -447,42 +298,20 @@ public class CurrencyTest extends TestFmwk { for (int i = 0; i < ALL.length; i++) { ALLSET.add(ALL[i]); } - + for (int i = 0; i < PREFERRED.length; i++) { ULocale loc = new ULocale(PREFERRED[i][0]); String[] expected = new String[PREFERRED[i].length - 1]; System.arraycopy(PREFERRED[i], 1, expected, 0, expected.length); - String[] pref = Currency.getKeywordValuesForLocale("currency", loc, true); - boolean matchPref = false; - if (pref.length == expected.length) { - matchPref = true; - for (int j = 0; j < pref.length; j++) { - if (!pref[j].equals(expected[j])) { - matchPref = false; - } - } - } - if (!matchPref) { - errln("FAIL: Preferred values for locale " + loc - + " got:" + Arrays.toString(pref) + " expected:" + Arrays.toString(expected)); - } + assertEquals(loc.toString(), expected, pref); String[] all = Currency.getKeywordValuesForLocale("currency", loc, false); - boolean matchAll = false; - if (all.length == ALLSET.size()) { - matchAll = true; - for (int j = 0; j < all.length; j++) { - if (!ALLSET.contains(all[j])) { - matchAll = false; - break; - } - } - } - if (!matchAll) { - errln("FAIL: All values for locale " + loc - + " got:" + Arrays.toString(all)); - } + // The items in the two collections should match (ignore order, + // behavior change from 4.3.3) + Set returnedSet = new HashSet(); + returnedSet.addAll(Arrays.asList(all)); + assertEquals(loc.toString(), ALLSET, returnedSet); } } } diff --git a/icu4j/main/tests/framework/src/com/ibm/icu/dev/test/TestFmwk.java b/icu4j/main/tests/framework/src/com/ibm/icu/dev/test/TestFmwk.java index 25332f41885..a70a42825c4 100644 --- a/icu4j/main/tests/framework/src/com/ibm/icu/dev/test/TestFmwk.java +++ b/icu4j/main/tests/framework/src/com/ibm/icu/dev/test/TestFmwk.java @@ -21,6 +21,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; import java.util.HashMap; +import java.util.List; import java.util.Locale; import java.util.MissingResourceException; import java.util.Random; @@ -1763,6 +1764,13 @@ public class TestFmwk extends AbstractTestLog { .valueOf(actual)); } + protected boolean assertEquals(String message, T[] expected, T[] actual) { + // Use toString on a List to get useful, readable messages + String expectedString = expected == null ? "null" : Arrays.asList(expected).toString(); + String actualString = actual == null ? "null" : Arrays.asList(actual).toString(); + return assertEquals(message, expectedString, actualString); + } + protected boolean assertEquals(String message, Object expected, Object actual) { boolean result = expected == null ? actual == null : expected @@ -1776,18 +1784,18 @@ public class TestFmwk extends AbstractTestLog { boolean result = !(expected == null ? actual == null : expected .equals(actual)); return handleAssert(result, message, stringFor(expected), - stringFor(actual), "not equal to", true, 3); + stringFor(actual), "not equal to", true); } protected boolean assertSame(String message, Object expected, Object actual) { return handleAssert(expected == actual, message, stringFor(expected), - stringFor(actual), "==", false, 3); + stringFor(actual), "==", false); } protected boolean assertNotSame(String message, Object expected, Object actual) { return handleAssert(expected != actual, message, stringFor(expected), - stringFor(actual), "!=", true, 3); + stringFor(actual), "!=", true); } protected boolean assertNull(String message, Object actual) { @@ -1796,7 +1804,7 @@ public class TestFmwk extends AbstractTestLog { protected boolean assertNotNull(String message, Object actual) { return handleAssert(actual != null, message, null, stringFor(actual), - "!=", true, 3); + "!=", true); } protected void fail(String message) { @@ -1805,13 +1813,13 @@ public class TestFmwk extends AbstractTestLog { private boolean handleAssert(boolean result, String message, String expected, String actual) { - return handleAssert(result, message, expected, actual, null, false, 4); + return handleAssert(result, message, expected, actual, null, false); } public boolean handleAssert(boolean result, String message, - Object expected, Object actual, String relation, boolean flip, int callDepth) { + Object expected, Object actual, String relation, boolean flip) { if (!result || isVerbose()) { - String testLocation = sourceLocation(callDepth); + String testLocation = sourceLocation(); if (message == null) { message = ""; } @@ -1835,19 +1843,25 @@ public class TestFmwk extends AbstractTestLog { } private final String stringFor(Object obj) { - if (obj == null) + if (obj == null) { return "null"; - if (obj instanceof String) + } + if (obj instanceof String) { return "\"" + obj + '"'; + } return obj.getClass().getName() + "<" + obj + ">"; } // Return the source code location of the caller located callDepth frames up the stack. - private String sourceLocation(int callDepth) { + private String sourceLocation() { + // Walk up the stack to the first call site outside this file StackTraceElement[] st = new Throwable().getStackTrace(); - String w = "File " + st[callDepth].getFileName() + - ", Line " + st[callDepth].getLineNumber(); - return w; + for (int i = 0; i < st.length; ++i) { + if (!"TestFmwk.java".equals(st[i].getFileName())) { + return "File " + st[i].getFileName() + ", Line " + st[i].getLineNumber(); + } + } + throw new InternalError(); } diff --git a/icu4j/main/tests/translit/src/com/ibm/icu/dev/test/translit/AnyScriptTest.java b/icu4j/main/tests/translit/src/com/ibm/icu/dev/test/translit/AnyScriptTest.java index 797d8b563e9..8549e7332a4 100644 --- a/icu4j/main/tests/translit/src/com/ibm/icu/dev/test/translit/AnyScriptTest.java +++ b/icu4j/main/tests/translit/src/com/ibm/icu/dev/test/translit/AnyScriptTest.java @@ -132,11 +132,11 @@ public class AnyScriptTest extends TestFmwk { // might want to add to TestFmwk private void assertContainsAll(String message, UnicodeSet set, String string) { - handleAssert(set.containsAll(string), message, set, string, "contains all of", false, 3); + handleAssert(set.containsAll(string), message, set, string, "contains all of", false); } private void assertContainsNone(String message, UnicodeSet set, String string) { - handleAssert(set.containsNone(string), message, set, string, "contains none of", false, 3); + handleAssert(set.containsNone(string), message, set, string, "contains none of", false); } // might want to add to UnicodeSet