feat(jdk8): move files to new folder to avoid resources compiled.
This commit is contained in:
261
jdkSrc/jdk8/sun/util/BuddhistCalendar.java
Normal file
261
jdkSrc/jdk8/sun/util/BuddhistCalendar.java
Normal file
@@ -0,0 +1,261 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.util;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.TimeZone;
|
||||
import sun.util.locale.provider.CalendarDataUtility;
|
||||
|
||||
public class BuddhistCalendar extends GregorianCalendar {
|
||||
|
||||
//////////////////
|
||||
// Class Variables
|
||||
//////////////////
|
||||
|
||||
private static final long serialVersionUID = -8527488697350388578L;
|
||||
|
||||
private static final int BUDDHIST_YEAR_OFFSET = 543;
|
||||
|
||||
///////////////
|
||||
// Constructors
|
||||
///////////////
|
||||
|
||||
/**
|
||||
* Constructs a default BuddhistCalendar using the current time
|
||||
* in the default time zone with the default locale.
|
||||
*/
|
||||
public BuddhistCalendar() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a BuddhistCalendar based on the current time
|
||||
* in the given time zone with the default locale.
|
||||
* @param zone the given time zone.
|
||||
*/
|
||||
public BuddhistCalendar(TimeZone zone) {
|
||||
super(zone);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a BuddhistCalendar based on the current time
|
||||
* in the default time zone with the given locale.
|
||||
* @param aLocale the given locale.
|
||||
*/
|
||||
public BuddhistCalendar(Locale aLocale) {
|
||||
super(aLocale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a BuddhistCalendar based on the current time
|
||||
* in the given time zone with the given locale.
|
||||
* @param zone the given time zone.
|
||||
* @param aLocale the given locale.
|
||||
*/
|
||||
public BuddhistCalendar(TimeZone zone, Locale aLocale) {
|
||||
super(zone, aLocale);
|
||||
}
|
||||
|
||||
/////////////////
|
||||
// Public methods
|
||||
/////////////////
|
||||
|
||||
/**
|
||||
* Returns {@code "buddhist"} as the calendar type of this Calendar.
|
||||
*/
|
||||
@Override
|
||||
public String getCalendarType() {
|
||||
return "buddhist";
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares this BuddhistCalendar to an object reference.
|
||||
* @param obj the object reference with which to compare
|
||||
* @return true if this object is equal to <code>obj</code>; false otherwise
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return obj instanceof BuddhistCalendar
|
||||
&& super.equals(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* Override hashCode.
|
||||
* Generates the hash code for the BuddhistCalendar object
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return super.hashCode() ^ BUDDHIST_YEAR_OFFSET;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value for a given time field.
|
||||
* @param field the given time field.
|
||||
* @return the value for the given time field.
|
||||
*/
|
||||
@Override
|
||||
public int get(int field)
|
||||
{
|
||||
if (field == YEAR) {
|
||||
return super.get(field) + yearOffset;
|
||||
}
|
||||
return super.get(field);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the time field with the given value.
|
||||
* @param field the given time field.
|
||||
* @param value the value to be set for the given time field.
|
||||
*/
|
||||
@Override
|
||||
public void set(int field, int value)
|
||||
{
|
||||
if (field == YEAR) {
|
||||
super.set(field, value - yearOffset);
|
||||
} else {
|
||||
super.set(field, value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the specified (signed) amount of time to the given time field.
|
||||
* @param field the time field.
|
||||
* @param amount the amount of date or time to be added to the field.
|
||||
*/
|
||||
@Override
|
||||
public void add(int field, int amount)
|
||||
{
|
||||
int savedYearOffset = yearOffset;
|
||||
// To let the superclass calculate date-time values correctly,
|
||||
// temporarily make this GregorianCalendar.
|
||||
yearOffset = 0;
|
||||
try {
|
||||
super.add(field, amount);
|
||||
} finally {
|
||||
yearOffset = savedYearOffset;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add to field a signed amount without changing larger fields.
|
||||
* A negative roll amount means to subtract from field without changing
|
||||
* larger fields.
|
||||
* @param field the time field.
|
||||
* @param amount the signed amount to add to <code>field</code>.
|
||||
*/
|
||||
@Override
|
||||
public void roll(int field, int amount)
|
||||
{
|
||||
int savedYearOffset = yearOffset;
|
||||
// To let the superclass calculate date-time values correctly,
|
||||
// temporarily make this GregorianCalendar.
|
||||
yearOffset = 0;
|
||||
try {
|
||||
super.roll(field, amount);
|
||||
} finally {
|
||||
yearOffset = savedYearOffset;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayName(int field, int style, Locale locale) {
|
||||
if (field != ERA) {
|
||||
return super.getDisplayName(field, style, locale);
|
||||
}
|
||||
|
||||
return CalendarDataUtility.retrieveFieldValueName("buddhist", field, get(field), style, locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String,Integer> getDisplayNames(int field, int style, Locale locale) {
|
||||
if (field != ERA) {
|
||||
return super.getDisplayNames(field, style, locale);
|
||||
}
|
||||
return CalendarDataUtility.retrieveFieldValueNames("buddhist", field, style, locale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the maximum value that this field could have, given the
|
||||
* current date. For example, with the date "Feb 3, 2540" and the
|
||||
* <code>DAY_OF_MONTH</code> field, the actual maximum is 28; for
|
||||
* "Feb 3, 2539" it is 29.
|
||||
*
|
||||
* @param field the field to determine the maximum of
|
||||
* @return the maximum of the given field for the current date of this Calendar
|
||||
*/
|
||||
@Override
|
||||
public int getActualMaximum(int field) {
|
||||
int savedYearOffset = yearOffset;
|
||||
// To let the superclass calculate date-time values correctly,
|
||||
// temporarily make this GregorianCalendar.
|
||||
yearOffset = 0;
|
||||
try {
|
||||
return super.getActualMaximum(field);
|
||||
} finally {
|
||||
yearOffset = savedYearOffset;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("empty-statement")
|
||||
public String toString() {
|
||||
// The super class produces a String with the Gregorian year
|
||||
// value (or '?')
|
||||
String s = super.toString();
|
||||
// If the YEAR field is UNSET, then return the Gregorian string.
|
||||
if (!isSet(YEAR)) {
|
||||
return s;
|
||||
}
|
||||
|
||||
final String yearField = "YEAR=";
|
||||
int p = s.indexOf(yearField);
|
||||
// If the string doesn't include the year value for some
|
||||
// reason, then return the Gregorian string.
|
||||
if (p == -1) {
|
||||
return s;
|
||||
}
|
||||
p += yearField.length();
|
||||
StringBuilder sb = new StringBuilder(s.substring(0, p));
|
||||
// Skip the year number
|
||||
while (Character.isDigit(s.charAt(p++)))
|
||||
;
|
||||
int year = internalGet(YEAR) + BUDDHIST_YEAR_OFFSET;
|
||||
sb.append(year).append(s.substring(p - 1));
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private transient int yearOffset = BUDDHIST_YEAR_OFFSET;
|
||||
|
||||
private void readObject(ObjectInputStream stream)
|
||||
throws IOException, ClassNotFoundException {
|
||||
stream.defaultReadObject();
|
||||
yearOffset = BUDDHIST_YEAR_OFFSET;
|
||||
}
|
||||
}
|
||||
114
jdkSrc/jdk8/sun/util/CoreResourceBundleControl.java
Normal file
114
jdkSrc/jdk8/sun/util/CoreResourceBundleControl.java
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
// -- This file was mechanically generated: Do not edit! -- //
|
||||
|
||||
package sun.util;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.ResourceBundle.Control;
|
||||
|
||||
/**
|
||||
* This is a convenient class for loading some of internal resources faster
|
||||
* if they are built with Resources.gmk defined in J2SE workspace. Also,
|
||||
* they have to be in class file format.
|
||||
*
|
||||
* "LOCALE_LIST" will be replaced at built time by a list of locales we
|
||||
* defined in Defs.gmk. We want to exclude these locales from search to
|
||||
* gain better performance. For example, since we know if the resource
|
||||
* is built with Resources.gmk, they are not going to provide basename_en.class
|
||||
* & basename_en_US.class resources, in that case, continuing searching them
|
||||
* is expensive. By excluding them from the candidate locale list, these
|
||||
* resources won't be searched.
|
||||
*
|
||||
* @since 1.6.
|
||||
*/
|
||||
public class CoreResourceBundleControl extends ResourceBundle.Control {
|
||||
/* the candidate locale list to search */
|
||||
private final Collection<Locale> excludedJDKLocales;
|
||||
/* singlton instance of the resource bundle control. */
|
||||
private static CoreResourceBundleControl resourceBundleControlInstance =
|
||||
new CoreResourceBundleControl();
|
||||
|
||||
protected CoreResourceBundleControl() {
|
||||
excludedJDKLocales = Arrays.asList( Locale.GERMANY, Locale.ENGLISH, Locale.US, new Locale("es", "ES"), Locale.FRANCE, Locale.ITALY, Locale.JAPAN, Locale.KOREA, new Locale("sv", "SE"), Locale.CHINESE);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is to provide a customized ResourceBundle.Control to speed
|
||||
* up the search of resources in JDK.
|
||||
*
|
||||
* @return the instance of resource bundle control.
|
||||
*/
|
||||
public static CoreResourceBundleControl getRBControlInstance() {
|
||||
return resourceBundleControlInstance;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is to provide a customized ResourceBundle.Control to speed
|
||||
* up the search of resources in JDK, with the bundle's package name check.
|
||||
*
|
||||
* @param bundleName bundle name to check
|
||||
* @return the instance of resource bundle control if the bundle is JDK's,
|
||||
* otherwise returns null.
|
||||
*/
|
||||
public static CoreResourceBundleControl getRBControlInstance(String bundleName) {
|
||||
if (bundleName.startsWith("com.sun.") ||
|
||||
bundleName.startsWith("java.") ||
|
||||
bundleName.startsWith("javax.") ||
|
||||
bundleName.startsWith("sun.")) {
|
||||
return resourceBundleControlInstance;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns a list of candidate locales to search from.
|
||||
* @exception NullPointerException if baseName or locale is null.
|
||||
*/
|
||||
@Override
|
||||
public List<Locale> getCandidateLocales(String baseName, Locale locale) {
|
||||
List<Locale> candidates = super.getCandidateLocales(baseName, locale);
|
||||
candidates.removeAll(excludedJDKLocales);
|
||||
return candidates;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ returns TTL_DONT_CACHE so that ResourceBundle instance won't be cached.
|
||||
* User of this CoreResourceBundleControl should probably maintain a hard reference
|
||||
* to the ResourceBundle object themselves.
|
||||
*/
|
||||
@Override
|
||||
public long getTimeToLive(String baseName, Locale locale) {
|
||||
return ResourceBundle.Control.TTL_DONT_CACHE;
|
||||
}
|
||||
}
|
||||
288
jdkSrc/jdk8/sun/util/PreHashedMap.java
Normal file
288
jdkSrc/jdk8/sun/util/PreHashedMap.java
Normal file
@@ -0,0 +1,288 @@
|
||||
/*
|
||||
* Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.util;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.AbstractMap;
|
||||
import java.util.AbstractSet;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
|
||||
/**
|
||||
* A precomputed hash map.
|
||||
*
|
||||
* <p> Subclasses of this class are of the following form:
|
||||
*
|
||||
* <blockquote><pre>
|
||||
* class FooMap
|
||||
* extends sun.util.PreHashedMap<String>
|
||||
* {
|
||||
*
|
||||
* private FooMap() {
|
||||
* super(ROWS, SIZE, SHIFT, MASK);
|
||||
* }
|
||||
*
|
||||
* protected void init(Object[] ht) {
|
||||
* ht[0] = new Object[] { "key-1", value_1 };
|
||||
* ht[1] = new Object[] { "key-2", value_2,
|
||||
* new Object { "key-3", value_3 } };
|
||||
* ...
|
||||
* }
|
||||
*
|
||||
* }</pre></blockquote>
|
||||
*
|
||||
* <p> The <tt>init</tt> method is invoked by the <tt>PreHashedMap</tt>
|
||||
* constructor with an object array long enough for the map's rows. The method
|
||||
* must construct the hash chain for each row and store it in the appropriate
|
||||
* element of the array.
|
||||
*
|
||||
* <p> Each entry in the map is represented by a unique hash-chain node. The
|
||||
* final node of a hash chain is a two-element object array whose first element
|
||||
* is the entry's key and whose second element is the entry's value. A
|
||||
* non-final node of a hash chain is a three-element object array whose first
|
||||
* two elements are the entry's key and value and whose third element is the
|
||||
* next node in the chain.
|
||||
*
|
||||
* <p> Instances of this class are mutable and are not safe for concurrent
|
||||
* access. They may be made immutable and thread-safe via the appropriate
|
||||
* methods in the {@link java.util.Collections} utility class.
|
||||
*
|
||||
* <p> In the JDK build, subclasses of this class are typically created via the
|
||||
* <tt>Hasher</tt> program in the <tt>make/tools/Hasher</tt> directory.
|
||||
*
|
||||
* @author Mark Reinhold
|
||||
* @since 1.5
|
||||
*
|
||||
* @see java.util.AbstractMap
|
||||
*/
|
||||
|
||||
public abstract class PreHashedMap<V>
|
||||
extends AbstractMap<String,V>
|
||||
{
|
||||
|
||||
private final int rows;
|
||||
private final int size;
|
||||
private final int shift;
|
||||
private final int mask;
|
||||
private final Object[] ht;
|
||||
|
||||
/**
|
||||
* Creates a new map.
|
||||
*
|
||||
* <p> This constructor invokes the {@link #init init} method, passing it a
|
||||
* newly-constructed row array that is <tt>rows</tt> elements long.
|
||||
*
|
||||
* @param rows
|
||||
* The number of rows in the map
|
||||
* @param size
|
||||
* The number of entries in the map
|
||||
* @param shift
|
||||
* The value by which hash codes are right-shifted
|
||||
* @param mask
|
||||
* The value with which hash codes are masked after being shifted
|
||||
*/
|
||||
protected PreHashedMap(int rows, int size, int shift, int mask) {
|
||||
this.rows = rows;
|
||||
this.size = size;
|
||||
this.shift = shift;
|
||||
this.mask = mask;
|
||||
this.ht = new Object[rows];
|
||||
init(ht);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes this map.
|
||||
*
|
||||
* <p> This method must construct the map's hash chains and store them into
|
||||
* the appropriate elements of the given hash-table row array.
|
||||
*
|
||||
* @param rows
|
||||
* The row array to be initialized
|
||||
*/
|
||||
protected abstract void init(Object[] ht);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private V toV(Object x) {
|
||||
return (V)x;
|
||||
}
|
||||
|
||||
public V get(Object k) {
|
||||
int h = (k.hashCode() >> shift) & mask;
|
||||
Object[] a = (Object[])ht[h];
|
||||
if (a == null) return null;
|
||||
for (;;) {
|
||||
if (a[0].equals(k))
|
||||
return toV(a[1]);
|
||||
if (a.length < 3)
|
||||
return null;
|
||||
a = (Object[])a[2];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws UnsupportedOperationException
|
||||
* If the given key is not part of this map's initial key set
|
||||
*/
|
||||
public V put(String k, V v) {
|
||||
int h = (k.hashCode() >> shift) & mask;
|
||||
Object[] a = (Object[])ht[h];
|
||||
if (a == null)
|
||||
throw new UnsupportedOperationException(k);
|
||||
for (;;) {
|
||||
if (a[0].equals(k)) {
|
||||
V ov = toV(a[1]);
|
||||
a[1] = v;
|
||||
return ov;
|
||||
}
|
||||
if (a.length < 3)
|
||||
throw new UnsupportedOperationException(k);
|
||||
a = (Object[])a[2];
|
||||
}
|
||||
}
|
||||
|
||||
public Set<String> keySet() {
|
||||
return new AbstractSet<String> () {
|
||||
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
public Iterator<String> iterator() {
|
||||
return new Iterator<String>() {
|
||||
private int i = -1;
|
||||
Object[] a = null;
|
||||
String cur = null;
|
||||
|
||||
private boolean findNext() {
|
||||
if (a != null) {
|
||||
if (a.length == 3) {
|
||||
a = (Object[])a[2];
|
||||
cur = (String)a[0];
|
||||
return true;
|
||||
}
|
||||
i++;
|
||||
a = null;
|
||||
}
|
||||
cur = null;
|
||||
if (i >= rows)
|
||||
return false;
|
||||
if (i < 0 || ht[i] == null) {
|
||||
do {
|
||||
if (++i >= rows)
|
||||
return false;
|
||||
} while (ht[i] == null);
|
||||
}
|
||||
a = (Object[])ht[i];
|
||||
cur = (String)a[0];
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean hasNext() {
|
||||
if (cur != null)
|
||||
return true;
|
||||
return findNext();
|
||||
}
|
||||
|
||||
public String next() {
|
||||
if (cur == null) {
|
||||
if (!findNext())
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
String s = cur;
|
||||
cur = null;
|
||||
return s;
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public Set<Map.Entry<String,V>> entrySet() {
|
||||
return new AbstractSet<Map.Entry<String,V>> () {
|
||||
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
public Iterator<Map.Entry<String,V>> iterator() {
|
||||
return new Iterator<Map.Entry<String,V>>() {
|
||||
final Iterator<String> i = keySet().iterator();
|
||||
|
||||
public boolean hasNext() {
|
||||
return i.hasNext();
|
||||
}
|
||||
|
||||
public Map.Entry<String,V> next() {
|
||||
return new Map.Entry<String,V>() {
|
||||
String k = i.next();
|
||||
public String getKey() { return k; }
|
||||
public V getValue() { return get(k); }
|
||||
public int hashCode() {
|
||||
V v = get(k);
|
||||
return (k.hashCode()
|
||||
+ (v == null
|
||||
? 0
|
||||
: v.hashCode()));
|
||||
}
|
||||
public boolean equals(Object ob) {
|
||||
if (ob == this)
|
||||
return true;
|
||||
if (!(ob instanceof Map.Entry))
|
||||
return false;
|
||||
Map.Entry<?,?> that = (Map.Entry<?,?>)ob;
|
||||
return ((this.getKey() == null
|
||||
? that.getKey() == null
|
||||
: this.getKey()
|
||||
.equals(that.getKey()))
|
||||
&&
|
||||
(this.getValue() == null
|
||||
? that.getValue() == null
|
||||
: this.getValue()
|
||||
.equals(that.getValue())));
|
||||
}
|
||||
public V setValue(V v) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
82
jdkSrc/jdk8/sun/util/ResourceBundleEnumeration.java
Normal file
82
jdkSrc/jdk8/sun/util/ResourceBundleEnumeration.java
Normal file
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2005, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.util;
|
||||
|
||||
import java.util.Enumeration;
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Implements an Enumeration that combines elements from a Set and
|
||||
* an Enumeration. Used by ListResourceBundle and PropertyResourceBundle.
|
||||
*/
|
||||
public class ResourceBundleEnumeration implements Enumeration<String> {
|
||||
|
||||
Set<String> set;
|
||||
Iterator<String> iterator;
|
||||
Enumeration<String> enumeration; // may remain null
|
||||
|
||||
/**
|
||||
* Constructs a resource bundle enumeration.
|
||||
* @param set an set providing some elements of the enumeration
|
||||
* @param enumeration an enumeration providing more elements of the enumeration.
|
||||
* enumeration may be null.
|
||||
*/
|
||||
public ResourceBundleEnumeration(Set<String> set, Enumeration<String> enumeration) {
|
||||
this.set = set;
|
||||
this.iterator = set.iterator();
|
||||
this.enumeration = enumeration;
|
||||
}
|
||||
|
||||
String next = null;
|
||||
|
||||
public boolean hasMoreElements() {
|
||||
if (next == null) {
|
||||
if (iterator.hasNext()) {
|
||||
next = iterator.next();
|
||||
} else if (enumeration != null) {
|
||||
while (next == null && enumeration.hasMoreElements()) {
|
||||
next = enumeration.nextElement();
|
||||
if (set.contains(next)) {
|
||||
next = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return next != null;
|
||||
}
|
||||
|
||||
public String nextElement() {
|
||||
if (hasMoreElements()) {
|
||||
String result = next;
|
||||
next = null;
|
||||
return result;
|
||||
} else {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
}
|
||||
}
|
||||
398
jdkSrc/jdk8/sun/util/calendar/AbstractCalendar.java
Normal file
398
jdkSrc/jdk8/sun/util/calendar/AbstractCalendar.java
Normal file
@@ -0,0 +1,398 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.util.calendar;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.TimeZone;
|
||||
|
||||
/**
|
||||
* The <code>AbstractCalendar</code> class provides a framework for
|
||||
* implementing a concrete calendar system.
|
||||
*
|
||||
* <p><a name="fixed_date"></a><B>Fixed Date</B><br>
|
||||
*
|
||||
* For implementing a concrete calendar system, each calendar must
|
||||
* have the common date numbering, starting from midnight the onset of
|
||||
* Monday, January 1, 1 (Gregorian). It is called a <I>fixed date</I>
|
||||
* in this class. January 1, 1 (Gregorian) is fixed date 1. (See
|
||||
* Nachum Dershowitz and Edward M. Reingold, <I>CALENDRICAL
|
||||
* CALCULATION The Millennium Edition</I>, Section 1.2 for details.)
|
||||
*
|
||||
* @author Masayoshi Okutsu
|
||||
* @since 1.5
|
||||
*/
|
||||
|
||||
public abstract class AbstractCalendar extends CalendarSystem {
|
||||
|
||||
// The constants assume no leap seconds support.
|
||||
static final int SECOND_IN_MILLIS = 1000;
|
||||
static final int MINUTE_IN_MILLIS = SECOND_IN_MILLIS * 60;
|
||||
static final int HOUR_IN_MILLIS = MINUTE_IN_MILLIS * 60;
|
||||
static final int DAY_IN_MILLIS = HOUR_IN_MILLIS * 24;
|
||||
|
||||
// The number of days between January 1, 1 and January 1, 1970 (Gregorian)
|
||||
static final int EPOCH_OFFSET = 719163;
|
||||
|
||||
private Era[] eras;
|
||||
|
||||
protected AbstractCalendar() {
|
||||
}
|
||||
|
||||
public Era getEra(String eraName) {
|
||||
if (eras != null) {
|
||||
for (int i = 0; i < eras.length; i++) {
|
||||
if (eras[i].equals(eraName)) {
|
||||
return eras[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Era[] getEras() {
|
||||
Era[] e = null;
|
||||
if (eras != null) {
|
||||
e = new Era[eras.length];
|
||||
System.arraycopy(eras, 0, e, 0, eras.length);
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
public void setEra(CalendarDate date, String eraName) {
|
||||
if (eras == null) {
|
||||
return; // should report an error???
|
||||
}
|
||||
for (int i = 0; i < eras.length; i++) {
|
||||
Era e = eras[i];
|
||||
if (e != null && e.getName().equals(eraName)) {
|
||||
date.setEra(e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("unknown era name: " + eraName);
|
||||
}
|
||||
|
||||
protected void setEras(Era[] eras) {
|
||||
this.eras = eras;
|
||||
}
|
||||
|
||||
public CalendarDate getCalendarDate() {
|
||||
return getCalendarDate(System.currentTimeMillis(), newCalendarDate());
|
||||
}
|
||||
|
||||
public CalendarDate getCalendarDate(long millis) {
|
||||
return getCalendarDate(millis, newCalendarDate());
|
||||
}
|
||||
|
||||
public CalendarDate getCalendarDate(long millis, TimeZone zone) {
|
||||
CalendarDate date = newCalendarDate(zone);
|
||||
return getCalendarDate(millis, date);
|
||||
}
|
||||
|
||||
public CalendarDate getCalendarDate(long millis, CalendarDate date) {
|
||||
int ms = 0; // time of day
|
||||
int zoneOffset = 0;
|
||||
int saving = 0;
|
||||
long days = 0; // fixed date
|
||||
|
||||
// adjust to local time if `date' has time zone.
|
||||
TimeZone zi = date.getZone();
|
||||
if (zi != null) {
|
||||
int[] offsets = new int[2];
|
||||
if (zi instanceof ZoneInfo) {
|
||||
zoneOffset = ((ZoneInfo)zi).getOffsets(millis, offsets);
|
||||
} else {
|
||||
zoneOffset = zi.getOffset(millis);
|
||||
offsets[0] = zi.getRawOffset();
|
||||
offsets[1] = zoneOffset - offsets[0];
|
||||
}
|
||||
|
||||
// We need to calculate the given millis and time zone
|
||||
// offset separately for java.util.GregorianCalendar
|
||||
// compatibility. (i.e., millis + zoneOffset could cause
|
||||
// overflow or underflow, which must be avoided.) Usually
|
||||
// days should be 0 and ms is in the range of -13:00 to
|
||||
// +14:00. However, we need to deal with extreme cases.
|
||||
days = zoneOffset / DAY_IN_MILLIS;
|
||||
ms = zoneOffset % DAY_IN_MILLIS;
|
||||
saving = offsets[1];
|
||||
}
|
||||
date.setZoneOffset(zoneOffset);
|
||||
date.setDaylightSaving(saving);
|
||||
|
||||
days += millis / DAY_IN_MILLIS;
|
||||
ms += (int) (millis % DAY_IN_MILLIS);
|
||||
if (ms >= DAY_IN_MILLIS) {
|
||||
// at most ms is (DAY_IN_MILLIS - 1) * 2.
|
||||
ms -= DAY_IN_MILLIS;
|
||||
++days;
|
||||
} else {
|
||||
// at most ms is (1 - DAY_IN_MILLIS) * 2. Adding one
|
||||
// DAY_IN_MILLIS results in still negative.
|
||||
while (ms < 0) {
|
||||
ms += DAY_IN_MILLIS;
|
||||
--days;
|
||||
}
|
||||
}
|
||||
|
||||
// convert to fixed date (offset from Jan. 1, 1 (Gregorian))
|
||||
days += EPOCH_OFFSET;
|
||||
|
||||
// calculate date fields from the fixed date
|
||||
getCalendarDateFromFixedDate(date, days);
|
||||
|
||||
// calculate time fields from the time of day
|
||||
setTimeOfDay(date, ms);
|
||||
date.setLeapYear(isLeapYear(date));
|
||||
date.setNormalized(true);
|
||||
return date;
|
||||
}
|
||||
|
||||
public long getTime(CalendarDate date) {
|
||||
long gd = getFixedDate(date);
|
||||
long ms = (gd - EPOCH_OFFSET) * DAY_IN_MILLIS + getTimeOfDay(date);
|
||||
int zoneOffset = 0;
|
||||
TimeZone zi = date.getZone();
|
||||
if (zi != null) {
|
||||
if (date.isNormalized()) {
|
||||
return ms - date.getZoneOffset();
|
||||
}
|
||||
// adjust time zone and daylight saving
|
||||
int[] offsets = new int[2];
|
||||
if (date.isStandardTime()) {
|
||||
// 1) 2:30am during starting-DST transition is
|
||||
// intrepreted as 2:30am ST
|
||||
// 2) 5:00pm during DST is still interpreted as 5:00pm ST
|
||||
// 3) 1:30am during ending-DST transition is interpreted
|
||||
// as 1:30am ST (after transition)
|
||||
if (zi instanceof ZoneInfo) {
|
||||
((ZoneInfo)zi).getOffsetsByStandard(ms, offsets);
|
||||
zoneOffset = offsets[0];
|
||||
} else {
|
||||
zoneOffset = zi.getOffset(ms - zi.getRawOffset());
|
||||
}
|
||||
} else {
|
||||
// 1) 2:30am during starting-DST transition is
|
||||
// intrepreted as 3:30am DT
|
||||
// 2) 5:00pm during DST is intrepreted as 5:00pm DT
|
||||
// 3) 1:30am during ending-DST transition is interpreted
|
||||
// as 1:30am DT/0:30am ST (before transition)
|
||||
if (zi instanceof ZoneInfo) {
|
||||
zoneOffset = ((ZoneInfo)zi).getOffsetsByWall(ms, offsets);
|
||||
} else {
|
||||
zoneOffset = zi.getOffset(ms - zi.getRawOffset());
|
||||
}
|
||||
}
|
||||
}
|
||||
ms -= zoneOffset;
|
||||
getCalendarDate(ms, date);
|
||||
return ms;
|
||||
}
|
||||
|
||||
protected long getTimeOfDay(CalendarDate date) {
|
||||
long fraction = date.getTimeOfDay();
|
||||
if (fraction != CalendarDate.TIME_UNDEFINED) {
|
||||
return fraction;
|
||||
}
|
||||
fraction = getTimeOfDayValue(date);
|
||||
date.setTimeOfDay(fraction);
|
||||
return fraction;
|
||||
}
|
||||
|
||||
public long getTimeOfDayValue(CalendarDate date) {
|
||||
long fraction = date.getHours();
|
||||
fraction *= 60;
|
||||
fraction += date.getMinutes();
|
||||
fraction *= 60;
|
||||
fraction += date.getSeconds();
|
||||
fraction *= 1000;
|
||||
fraction += date.getMillis();
|
||||
return fraction;
|
||||
}
|
||||
|
||||
public CalendarDate setTimeOfDay(CalendarDate cdate, int fraction) {
|
||||
if (fraction < 0) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
boolean normalizedState = cdate.isNormalized();
|
||||
int time = fraction;
|
||||
int hours = time / HOUR_IN_MILLIS;
|
||||
time %= HOUR_IN_MILLIS;
|
||||
int minutes = time / MINUTE_IN_MILLIS;
|
||||
time %= MINUTE_IN_MILLIS;
|
||||
int seconds = time / SECOND_IN_MILLIS;
|
||||
time %= SECOND_IN_MILLIS;
|
||||
cdate.setHours(hours);
|
||||
cdate.setMinutes(minutes);
|
||||
cdate.setSeconds(seconds);
|
||||
cdate.setMillis(time);
|
||||
cdate.setTimeOfDay(fraction);
|
||||
if (hours < 24 && normalizedState) {
|
||||
// If this time of day setting doesn't affect the date,
|
||||
// then restore the normalized state.
|
||||
cdate.setNormalized(normalizedState);
|
||||
}
|
||||
return cdate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns 7 in this default implementation.
|
||||
*
|
||||
* @return 7
|
||||
*/
|
||||
public int getWeekLength() {
|
||||
return 7;
|
||||
}
|
||||
|
||||
protected abstract boolean isLeapYear(CalendarDate date);
|
||||
|
||||
public CalendarDate getNthDayOfWeek(int nth, int dayOfWeek, CalendarDate date) {
|
||||
CalendarDate ndate = (CalendarDate) date.clone();
|
||||
normalize(ndate);
|
||||
long fd = getFixedDate(ndate);
|
||||
long nfd;
|
||||
if (nth > 0) {
|
||||
nfd = 7 * nth + getDayOfWeekDateBefore(fd, dayOfWeek);
|
||||
} else {
|
||||
nfd = 7 * nth + getDayOfWeekDateAfter(fd, dayOfWeek);
|
||||
}
|
||||
getCalendarDateFromFixedDate(ndate, nfd);
|
||||
return ndate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a date of the given day of week before the given fixed
|
||||
* date.
|
||||
*
|
||||
* @param fixedDate the fixed date
|
||||
* @param dayOfWeek the day of week
|
||||
* @return the calculated date
|
||||
*/
|
||||
static long getDayOfWeekDateBefore(long fixedDate, int dayOfWeek) {
|
||||
return getDayOfWeekDateOnOrBefore(fixedDate - 1, dayOfWeek);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a date of the given day of week that is closest to and
|
||||
* after the given fixed date.
|
||||
*
|
||||
* @param fixedDate the fixed date
|
||||
* @param dayOfWeek the day of week
|
||||
* @return the calculated date
|
||||
*/
|
||||
static long getDayOfWeekDateAfter(long fixedDate, int dayOfWeek) {
|
||||
return getDayOfWeekDateOnOrBefore(fixedDate + 7, dayOfWeek);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a date of the given day of week on or before the given fixed
|
||||
* date.
|
||||
*
|
||||
* @param fixedDate the fixed date
|
||||
* @param dayOfWeek the day of week
|
||||
* @return the calculated date
|
||||
*/
|
||||
// public for java.util.GregorianCalendar
|
||||
public static long getDayOfWeekDateOnOrBefore(long fixedDate, int dayOfWeek) {
|
||||
long fd = fixedDate - (dayOfWeek - 1);
|
||||
if (fd >= 0) {
|
||||
return fixedDate - (fd % 7);
|
||||
}
|
||||
return fixedDate - CalendarUtils.mod(fd, 7);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the fixed date calculated with the specified calendar
|
||||
* date. If the specified date is not normalized, its date fields
|
||||
* are normalized.
|
||||
*
|
||||
* @param date a <code>CalendarDate</code> with which the fixed
|
||||
* date is calculated
|
||||
* @return the calculated fixed date
|
||||
* @see AbstractCalendar.html#fixed_date
|
||||
*/
|
||||
protected abstract long getFixedDate(CalendarDate date);
|
||||
|
||||
/**
|
||||
* Calculates calendar fields from the specified fixed date. This
|
||||
* method stores the calculated calendar field values in the specified
|
||||
* <code>CalendarDate</code>.
|
||||
*
|
||||
* @param date a <code>CalendarDate</code> to stored the
|
||||
* calculated calendar fields.
|
||||
* @param fixedDate a fixed date to calculate calendar fields
|
||||
* @see AbstractCalendar.html#fixed_date
|
||||
*/
|
||||
protected abstract void getCalendarDateFromFixedDate(CalendarDate date,
|
||||
long fixedDate);
|
||||
|
||||
public boolean validateTime(CalendarDate date) {
|
||||
int t = date.getHours();
|
||||
if (t < 0 || t >= 24) {
|
||||
return false;
|
||||
}
|
||||
t = date.getMinutes();
|
||||
if (t < 0 || t >= 60) {
|
||||
return false;
|
||||
}
|
||||
t = date.getSeconds();
|
||||
// TODO: Leap second support.
|
||||
if (t < 0 || t >= 60) {
|
||||
return false;
|
||||
}
|
||||
t = date.getMillis();
|
||||
if (t < 0 || t >= 1000) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int normalizeTime(CalendarDate date) {
|
||||
long fraction = getTimeOfDay(date);
|
||||
long days = 0;
|
||||
|
||||
if (fraction >= DAY_IN_MILLIS) {
|
||||
days = fraction / DAY_IN_MILLIS;
|
||||
fraction %= DAY_IN_MILLIS;
|
||||
} else if (fraction < 0) {
|
||||
days = CalendarUtils.floorDivide(fraction, DAY_IN_MILLIS);
|
||||
if (days != 0) {
|
||||
fraction -= DAY_IN_MILLIS * days; // mod(fraction, DAY_IN_MILLIS)
|
||||
}
|
||||
}
|
||||
if (days != 0) {
|
||||
date.setTimeOfDay(fraction);
|
||||
}
|
||||
date.setMillis((int)(fraction % 1000));
|
||||
fraction /= 1000;
|
||||
date.setSeconds((int)(fraction % 60));
|
||||
fraction /= 60;
|
||||
date.setMinutes((int)(fraction % 60));
|
||||
date.setHours((int)(fraction / 60));
|
||||
return (int)days;
|
||||
}
|
||||
}
|
||||
537
jdkSrc/jdk8/sun/util/calendar/BaseCalendar.java
Normal file
537
jdkSrc/jdk8/sun/util/calendar/BaseCalendar.java
Normal file
@@ -0,0 +1,537 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.util.calendar;
|
||||
|
||||
import java.util.TimeZone;
|
||||
|
||||
/**
|
||||
* The <code>BaseCalendar</code> provides basic calendar calculation
|
||||
* functions to support the Julian, Gregorian, and Gregorian-based
|
||||
* calendar systems.
|
||||
*
|
||||
* @author Masayoshi Okutsu
|
||||
* @since 1.5
|
||||
*/
|
||||
|
||||
public abstract class BaseCalendar extends AbstractCalendar {
|
||||
|
||||
public static final int JANUARY = 1;
|
||||
public static final int FEBRUARY = 2;
|
||||
public static final int MARCH = 3;
|
||||
public static final int APRIL = 4;
|
||||
public static final int MAY = 5;
|
||||
public static final int JUNE = 6;
|
||||
public static final int JULY = 7;
|
||||
public static final int AUGUST = 8;
|
||||
public static final int SEPTEMBER = 9;
|
||||
public static final int OCTOBER = 10;
|
||||
public static final int NOVEMBER = 11;
|
||||
public static final int DECEMBER = 12;
|
||||
|
||||
// day of week constants
|
||||
public static final int SUNDAY = 1;
|
||||
public static final int MONDAY = 2;
|
||||
public static final int TUESDAY = 3;
|
||||
public static final int WEDNESDAY = 4;
|
||||
public static final int THURSDAY = 5;
|
||||
public static final int FRIDAY = 6;
|
||||
public static final int SATURDAY = 7;
|
||||
|
||||
// The base Gregorian year of FIXED_DATES[]
|
||||
private static final int BASE_YEAR = 1970;
|
||||
|
||||
// Pre-calculated fixed dates of January 1 from BASE_YEAR
|
||||
// (Gregorian). This table covers all the years that can be
|
||||
// supported by the POSIX time_t (32-bit) after the Epoch. Note
|
||||
// that the data type is int[].
|
||||
private static final int[] FIXED_DATES = {
|
||||
719163, // 1970
|
||||
719528, // 1971
|
||||
719893, // 1972
|
||||
720259, // 1973
|
||||
720624, // 1974
|
||||
720989, // 1975
|
||||
721354, // 1976
|
||||
721720, // 1977
|
||||
722085, // 1978
|
||||
722450, // 1979
|
||||
722815, // 1980
|
||||
723181, // 1981
|
||||
723546, // 1982
|
||||
723911, // 1983
|
||||
724276, // 1984
|
||||
724642, // 1985
|
||||
725007, // 1986
|
||||
725372, // 1987
|
||||
725737, // 1988
|
||||
726103, // 1989
|
||||
726468, // 1990
|
||||
726833, // 1991
|
||||
727198, // 1992
|
||||
727564, // 1993
|
||||
727929, // 1994
|
||||
728294, // 1995
|
||||
728659, // 1996
|
||||
729025, // 1997
|
||||
729390, // 1998
|
||||
729755, // 1999
|
||||
730120, // 2000
|
||||
730486, // 2001
|
||||
730851, // 2002
|
||||
731216, // 2003
|
||||
731581, // 2004
|
||||
731947, // 2005
|
||||
732312, // 2006
|
||||
732677, // 2007
|
||||
733042, // 2008
|
||||
733408, // 2009
|
||||
733773, // 2010
|
||||
734138, // 2011
|
||||
734503, // 2012
|
||||
734869, // 2013
|
||||
735234, // 2014
|
||||
735599, // 2015
|
||||
735964, // 2016
|
||||
736330, // 2017
|
||||
736695, // 2018
|
||||
737060, // 2019
|
||||
737425, // 2020
|
||||
737791, // 2021
|
||||
738156, // 2022
|
||||
738521, // 2023
|
||||
738886, // 2024
|
||||
739252, // 2025
|
||||
739617, // 2026
|
||||
739982, // 2027
|
||||
740347, // 2028
|
||||
740713, // 2029
|
||||
741078, // 2030
|
||||
741443, // 2031
|
||||
741808, // 2032
|
||||
742174, // 2033
|
||||
742539, // 2034
|
||||
742904, // 2035
|
||||
743269, // 2036
|
||||
743635, // 2037
|
||||
744000, // 2038
|
||||
744365, // 2039
|
||||
};
|
||||
|
||||
public abstract static class Date extends CalendarDate {
|
||||
protected Date() {
|
||||
super();
|
||||
}
|
||||
protected Date(TimeZone zone) {
|
||||
super(zone);
|
||||
}
|
||||
|
||||
public Date setNormalizedDate(int normalizedYear, int month, int dayOfMonth) {
|
||||
setNormalizedYear(normalizedYear);
|
||||
setMonth(month).setDayOfMonth(dayOfMonth);
|
||||
return this;
|
||||
}
|
||||
|
||||
public abstract int getNormalizedYear();
|
||||
|
||||
public abstract void setNormalizedYear(int normalizedYear);
|
||||
|
||||
// Cache for the fixed date of January 1 and year length of the
|
||||
// cachedYear. A simple benchmark showed 7% performance
|
||||
// improvement with >90% cache hit. The initial values are for Gregorian.
|
||||
int cachedYear = 2004;
|
||||
long cachedFixedDateJan1 = 731581L;
|
||||
long cachedFixedDateNextJan1 = cachedFixedDateJan1 + 366;
|
||||
|
||||
protected final boolean hit(int year) {
|
||||
return year == cachedYear;
|
||||
}
|
||||
|
||||
protected final boolean hit(long fixedDate) {
|
||||
return (fixedDate >= cachedFixedDateJan1 &&
|
||||
fixedDate < cachedFixedDateNextJan1);
|
||||
}
|
||||
protected int getCachedYear() {
|
||||
return cachedYear;
|
||||
}
|
||||
|
||||
protected long getCachedJan1() {
|
||||
return cachedFixedDateJan1;
|
||||
}
|
||||
|
||||
protected void setCache(int year, long jan1, int len) {
|
||||
cachedYear = year;
|
||||
cachedFixedDateJan1 = jan1;
|
||||
cachedFixedDateNextJan1 = jan1 + len;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean validate(CalendarDate date) {
|
||||
Date bdate = (Date) date;
|
||||
if (bdate.isNormalized()) {
|
||||
return true;
|
||||
}
|
||||
int month = bdate.getMonth();
|
||||
if (month < JANUARY || month > DECEMBER) {
|
||||
return false;
|
||||
}
|
||||
int d = bdate.getDayOfMonth();
|
||||
if (d <= 0 || d > getMonthLength(bdate.getNormalizedYear(), month)) {
|
||||
return false;
|
||||
}
|
||||
int dow = bdate.getDayOfWeek();
|
||||
if (dow != Date.FIELD_UNDEFINED && dow != getDayOfWeek(bdate)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!validateTime(date)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bdate.setNormalized(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean normalize(CalendarDate date) {
|
||||
if (date.isNormalized()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Date bdate = (Date) date;
|
||||
TimeZone zi = bdate.getZone();
|
||||
|
||||
// If the date has a time zone, then we need to recalculate
|
||||
// the calendar fields. Let getTime() do it.
|
||||
if (zi != null) {
|
||||
getTime(date);
|
||||
return true;
|
||||
}
|
||||
|
||||
int days = normalizeTime(bdate);
|
||||
normalizeMonth(bdate);
|
||||
long d = (long)bdate.getDayOfMonth() + days;
|
||||
int m = bdate.getMonth();
|
||||
int y = bdate.getNormalizedYear();
|
||||
int ml = getMonthLength(y, m);
|
||||
|
||||
if (!(d > 0 && d <= ml)) {
|
||||
if (d <= 0 && d > -28) {
|
||||
ml = getMonthLength(y, --m);
|
||||
d += ml;
|
||||
bdate.setDayOfMonth((int) d);
|
||||
if (m == 0) {
|
||||
m = DECEMBER;
|
||||
bdate.setNormalizedYear(y - 1);
|
||||
}
|
||||
bdate.setMonth(m);
|
||||
} else if (d > ml && d < (ml + 28)) {
|
||||
d -= ml;
|
||||
++m;
|
||||
bdate.setDayOfMonth((int)d);
|
||||
if (m > DECEMBER) {
|
||||
bdate.setNormalizedYear(y + 1);
|
||||
m = JANUARY;
|
||||
}
|
||||
bdate.setMonth(m);
|
||||
} else {
|
||||
long fixedDate = d + getFixedDate(y, m, 1, bdate) - 1L;
|
||||
getCalendarDateFromFixedDate(bdate, fixedDate);
|
||||
}
|
||||
} else {
|
||||
bdate.setDayOfWeek(getDayOfWeek(bdate));
|
||||
}
|
||||
date.setLeapYear(isLeapYear(bdate.getNormalizedYear()));
|
||||
date.setZoneOffset(0);
|
||||
date.setDaylightSaving(0);
|
||||
bdate.setNormalized(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
void normalizeMonth(CalendarDate date) {
|
||||
Date bdate = (Date) date;
|
||||
int year = bdate.getNormalizedYear();
|
||||
long month = bdate.getMonth();
|
||||
if (month <= 0) {
|
||||
long xm = 1L - month;
|
||||
year -= (int)((xm / 12) + 1);
|
||||
month = 13 - (xm % 12);
|
||||
bdate.setNormalizedYear(year);
|
||||
bdate.setMonth((int) month);
|
||||
} else if (month > DECEMBER) {
|
||||
year += (int)((month - 1) / 12);
|
||||
month = ((month - 1)) % 12 + 1;
|
||||
bdate.setNormalizedYear(year);
|
||||
bdate.setMonth((int) month);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns 366 if the specified date is in a leap year, or 365
|
||||
* otherwise This method does not perform the normalization with
|
||||
* the specified <code>CalendarDate</code>. The
|
||||
* <code>CalendarDate</code> must be normalized to get a correct
|
||||
* value.
|
||||
*
|
||||
* @param a <code>CalendarDate</code>
|
||||
* @return a year length in days
|
||||
* @throws ClassCastException if the specified date is not a
|
||||
* {@link BaseCalendar.Date}
|
||||
*/
|
||||
public int getYearLength(CalendarDate date) {
|
||||
return isLeapYear(((Date)date).getNormalizedYear()) ? 366 : 365;
|
||||
}
|
||||
|
||||
public int getYearLengthInMonths(CalendarDate date) {
|
||||
return 12;
|
||||
}
|
||||
|
||||
static final int[] DAYS_IN_MONTH
|
||||
// 12 1 2 3 4 5 6 7 8 9 10 11 12
|
||||
= { 31, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
|
||||
static final int[] ACCUMULATED_DAYS_IN_MONTH
|
||||
// 12/1 1/1 2/1 3/1 4/1 5/1 6/1 7/1 8/1 9/1 10/1 11/1 12/1
|
||||
= { -30, 0, 31, 59, 90,120,151,181,212,243, 273, 304, 334};
|
||||
|
||||
static final int[] ACCUMULATED_DAYS_IN_MONTH_LEAP
|
||||
// 12/1 1/1 2/1 3/1 4/1 5/1 6/1 7/1 8/1 9/1 10/1 11/1 12/1
|
||||
= { -30, 0, 31, 59+1, 90+1,120+1,151+1,181+1,212+1,243+1, 273+1, 304+1, 334+1};
|
||||
|
||||
public int getMonthLength(CalendarDate date) {
|
||||
Date gdate = (Date) date;
|
||||
int month = gdate.getMonth();
|
||||
if (month < JANUARY || month > DECEMBER) {
|
||||
throw new IllegalArgumentException("Illegal month value: " + month);
|
||||
}
|
||||
return getMonthLength(gdate.getNormalizedYear(), month);
|
||||
}
|
||||
|
||||
// accepts 0 (December in the previous year) to 12.
|
||||
private int getMonthLength(int year, int month) {
|
||||
int days = DAYS_IN_MONTH[month];
|
||||
if (month == FEBRUARY && isLeapYear(year)) {
|
||||
days++;
|
||||
}
|
||||
return days;
|
||||
}
|
||||
|
||||
public long getDayOfYear(CalendarDate date) {
|
||||
return getDayOfYear(((Date)date).getNormalizedYear(),
|
||||
date.getMonth(),
|
||||
date.getDayOfMonth());
|
||||
}
|
||||
|
||||
final long getDayOfYear(int year, int month, int dayOfMonth) {
|
||||
return (long) dayOfMonth
|
||||
+ (isLeapYear(year) ?
|
||||
ACCUMULATED_DAYS_IN_MONTH_LEAP[month] : ACCUMULATED_DAYS_IN_MONTH[month]);
|
||||
}
|
||||
|
||||
// protected
|
||||
public long getFixedDate(CalendarDate date) {
|
||||
if (!date.isNormalized()) {
|
||||
normalizeMonth(date);
|
||||
}
|
||||
return getFixedDate(((Date)date).getNormalizedYear(),
|
||||
date.getMonth(),
|
||||
date.getDayOfMonth(),
|
||||
(BaseCalendar.Date) date);
|
||||
}
|
||||
|
||||
// public for java.util.GregorianCalendar
|
||||
public long getFixedDate(int year, int month, int dayOfMonth, BaseCalendar.Date cache) {
|
||||
boolean isJan1 = month == JANUARY && dayOfMonth == 1;
|
||||
|
||||
// Look up the one year cache
|
||||
if (cache != null && cache.hit(year)) {
|
||||
if (isJan1) {
|
||||
return cache.getCachedJan1();
|
||||
}
|
||||
return cache.getCachedJan1() + getDayOfYear(year, month, dayOfMonth) - 1;
|
||||
}
|
||||
|
||||
// Look up the pre-calculated fixed date table
|
||||
int n = year - BASE_YEAR;
|
||||
if (n >= 0 && n < FIXED_DATES.length) {
|
||||
long jan1 = FIXED_DATES[n];
|
||||
if (cache != null) {
|
||||
cache.setCache(year, jan1, isLeapYear(year) ? 366 : 365);
|
||||
}
|
||||
return isJan1 ? jan1 : jan1 + getDayOfYear(year, month, dayOfMonth) - 1;
|
||||
}
|
||||
|
||||
long prevyear = (long)year - 1;
|
||||
long days = dayOfMonth;
|
||||
|
||||
if (prevyear >= 0) {
|
||||
days += (365 * prevyear)
|
||||
+ (prevyear / 4)
|
||||
- (prevyear / 100)
|
||||
+ (prevyear / 400)
|
||||
+ ((367 * month - 362) / 12);
|
||||
} else {
|
||||
days += (365 * prevyear)
|
||||
+ CalendarUtils.floorDivide(prevyear, 4)
|
||||
- CalendarUtils.floorDivide(prevyear, 100)
|
||||
+ CalendarUtils.floorDivide(prevyear, 400)
|
||||
+ CalendarUtils.floorDivide((367 * month - 362), 12);
|
||||
}
|
||||
|
||||
if (month > FEBRUARY) {
|
||||
days -= isLeapYear(year) ? 1 : 2;
|
||||
}
|
||||
|
||||
// If it's January 1, update the cache.
|
||||
if (cache != null && isJan1) {
|
||||
cache.setCache(year, days, isLeapYear(year) ? 366 : 365);
|
||||
}
|
||||
|
||||
return days;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates calendar fields and store them in the specified
|
||||
* <code>CalendarDate</code>.
|
||||
*/
|
||||
// should be 'protected'
|
||||
public void getCalendarDateFromFixedDate(CalendarDate date,
|
||||
long fixedDate) {
|
||||
Date gdate = (Date) date;
|
||||
int year;
|
||||
long jan1;
|
||||
boolean isLeap;
|
||||
if (gdate.hit(fixedDate)) {
|
||||
year = gdate.getCachedYear();
|
||||
jan1 = gdate.getCachedJan1();
|
||||
isLeap = isLeapYear(year);
|
||||
} else {
|
||||
// Looking up FIXED_DATES[] here didn't improve performance
|
||||
// much. So we calculate year and jan1. getFixedDate()
|
||||
// will look up FIXED_DATES[] actually.
|
||||
year = getGregorianYearFromFixedDate(fixedDate);
|
||||
jan1 = getFixedDate(year, JANUARY, 1, null);
|
||||
isLeap = isLeapYear(year);
|
||||
// Update the cache data
|
||||
gdate.setCache (year, jan1, isLeap ? 366 : 365);
|
||||
}
|
||||
|
||||
int priorDays = (int)(fixedDate - jan1);
|
||||
long mar1 = jan1 + 31 + 28;
|
||||
if (isLeap) {
|
||||
++mar1;
|
||||
}
|
||||
if (fixedDate >= mar1) {
|
||||
priorDays += isLeap ? 1 : 2;
|
||||
}
|
||||
int month = 12 * priorDays + 373;
|
||||
if (month > 0) {
|
||||
month /= 367;
|
||||
} else {
|
||||
month = CalendarUtils.floorDivide(month, 367);
|
||||
}
|
||||
long month1 = jan1 + ACCUMULATED_DAYS_IN_MONTH[month];
|
||||
if (isLeap && month >= MARCH) {
|
||||
++month1;
|
||||
}
|
||||
int dayOfMonth = (int)(fixedDate - month1) + 1;
|
||||
int dayOfWeek = getDayOfWeekFromFixedDate(fixedDate);
|
||||
assert dayOfWeek > 0 : "negative day of week " + dayOfWeek;
|
||||
gdate.setNormalizedYear(year);
|
||||
gdate.setMonth(month);
|
||||
gdate.setDayOfMonth(dayOfMonth);
|
||||
gdate.setDayOfWeek(dayOfWeek);
|
||||
gdate.setLeapYear(isLeap);
|
||||
gdate.setNormalized(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the day of week of the given Gregorian date.
|
||||
*/
|
||||
public int getDayOfWeek(CalendarDate date) {
|
||||
long fixedDate = getFixedDate(date);
|
||||
return getDayOfWeekFromFixedDate(fixedDate);
|
||||
}
|
||||
|
||||
public static final int getDayOfWeekFromFixedDate(long fixedDate) {
|
||||
// The fixed day 1 (January 1, 1 Gregorian) is Monday.
|
||||
if (fixedDate >= 0) {
|
||||
return (int)(fixedDate % 7) + SUNDAY;
|
||||
}
|
||||
return (int)CalendarUtils.mod(fixedDate, 7) + SUNDAY;
|
||||
}
|
||||
|
||||
public int getYearFromFixedDate(long fixedDate) {
|
||||
return getGregorianYearFromFixedDate(fixedDate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Gregorian year number of the given fixed date.
|
||||
*/
|
||||
final int getGregorianYearFromFixedDate(long fixedDate) {
|
||||
long d0;
|
||||
int d1, d2, d3, d4;
|
||||
int n400, n100, n4, n1;
|
||||
int year;
|
||||
|
||||
if (fixedDate > 0) {
|
||||
d0 = fixedDate - 1;
|
||||
n400 = (int)(d0 / 146097);
|
||||
d1 = (int)(d0 % 146097);
|
||||
n100 = d1 / 36524;
|
||||
d2 = d1 % 36524;
|
||||
n4 = d2 / 1461;
|
||||
d3 = d2 % 1461;
|
||||
n1 = d3 / 365;
|
||||
d4 = (d3 % 365) + 1;
|
||||
} else {
|
||||
d0 = fixedDate - 1;
|
||||
n400 = (int)CalendarUtils.floorDivide(d0, 146097L);
|
||||
d1 = (int)CalendarUtils.mod(d0, 146097L);
|
||||
n100 = CalendarUtils.floorDivide(d1, 36524);
|
||||
d2 = CalendarUtils.mod(d1, 36524);
|
||||
n4 = CalendarUtils.floorDivide(d2, 1461);
|
||||
d3 = CalendarUtils.mod(d2, 1461);
|
||||
n1 = CalendarUtils.floorDivide(d3, 365);
|
||||
d4 = CalendarUtils.mod(d3, 365) + 1;
|
||||
}
|
||||
year = 400 * n400 + 100 * n100 + 4 * n4 + n1;
|
||||
if (!(n100 == 4 || n1 == 4)) {
|
||||
++year;
|
||||
}
|
||||
return year;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if the specified year is a Gregorian leap year, or
|
||||
* false otherwise.
|
||||
* @see BaseCalendar#isGregorianLeapYear
|
||||
*/
|
||||
protected boolean isLeapYear(CalendarDate date) {
|
||||
return isLeapYear(((Date)date).getNormalizedYear());
|
||||
}
|
||||
|
||||
boolean isLeapYear(int normalizedYear) {
|
||||
return CalendarUtils.isGregorianLeapYear(normalizedYear);
|
||||
}
|
||||
}
|
||||
505
jdkSrc/jdk8/sun/util/calendar/CalendarDate.java
Normal file
505
jdkSrc/jdk8/sun/util/calendar/CalendarDate.java
Normal file
@@ -0,0 +1,505 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.util.calendar;
|
||||
|
||||
import java.lang.Cloneable;
|
||||
import java.util.Locale;
|
||||
import java.util.TimeZone;
|
||||
|
||||
/**
|
||||
* The <code>CalendarDate</code> class represents a specific instant
|
||||
* in time by calendar date and time fields that are multiple cycles
|
||||
* in different time unites. The semantics of each calendar field is
|
||||
* given by a concrete calendar system rather than this
|
||||
* <code>CalendarDate</code> class that holds calendar field values
|
||||
* without interpreting them. Therefore, this class can be used to
|
||||
* represent an amount of time, such as 2 years and 3 months.
|
||||
*
|
||||
* <p>A <code>CalendarDate</code> instance can be created by calling
|
||||
* the <code>newCalendarDate</code> or <code>getCalendarDate</code>
|
||||
* methods in <code>CalendarSystem</code>. A
|
||||
* <code>CalendarSystem</code> instance is obtained by calling one of
|
||||
* the factory methods in <code>CalendarSystem</code>. Manipulations
|
||||
* of calendar dates must be handled by the calendar system by which
|
||||
* <code>CalendarDate</code> instances have been created.
|
||||
*
|
||||
* <p>Some calendar fields can be modified through method calls. Any
|
||||
* modification of a calendar field brings the state of a
|
||||
* <code>CalendarDate</code> to <I>not normalized</I>. The
|
||||
* normalization must be performed to make all the calendar fields
|
||||
* consistent with a calendar system.
|
||||
*
|
||||
* <p>The <code>protected</code> methods are intended to be used for
|
||||
* implementing a concrete calendar system, not for general use as an
|
||||
* API.
|
||||
*
|
||||
* @see CalendarSystem
|
||||
* @author Masayoshi Okutsu
|
||||
* @since 1.5
|
||||
*/
|
||||
public abstract class CalendarDate implements Cloneable {
|
||||
public static final int FIELD_UNDEFINED = Integer.MIN_VALUE;
|
||||
public static final long TIME_UNDEFINED = Long.MIN_VALUE;
|
||||
|
||||
private Era era;
|
||||
private int year;
|
||||
private int month;
|
||||
private int dayOfMonth;
|
||||
private int dayOfWeek = FIELD_UNDEFINED;
|
||||
private boolean leapYear;
|
||||
|
||||
private int hours;
|
||||
private int minutes;
|
||||
private int seconds;
|
||||
private int millis; // fractional part of the second
|
||||
private long fraction; // time of day value in millisecond
|
||||
|
||||
private boolean normalized;
|
||||
|
||||
private TimeZone zoneinfo;
|
||||
private int zoneOffset;
|
||||
private int daylightSaving;
|
||||
private boolean forceStandardTime;
|
||||
|
||||
private Locale locale;
|
||||
|
||||
protected CalendarDate() {
|
||||
this(TimeZone.getDefault());
|
||||
}
|
||||
|
||||
protected CalendarDate(TimeZone zone) {
|
||||
zoneinfo = zone;
|
||||
}
|
||||
|
||||
public Era getEra() {
|
||||
return era;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the era of the date to the specified era. The default
|
||||
* implementation of this method accepts any Era value, including
|
||||
* <code>null</code>.
|
||||
*
|
||||
* @exception NullPointerException if the calendar system for this
|
||||
* <code>CalendarDate</code> requires eras and the specified era
|
||||
* is null.
|
||||
* @exception IllegalArgumentException if the specified
|
||||
* <code>era</code> is unknown to the calendar
|
||||
* system for this <code>CalendarDate</code>.
|
||||
*/
|
||||
public CalendarDate setEra(Era era) {
|
||||
if (this.era == era) {
|
||||
return this;
|
||||
}
|
||||
this.era = era;
|
||||
normalized = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getYear() {
|
||||
return year;
|
||||
}
|
||||
|
||||
public CalendarDate setYear(int year) {
|
||||
if (this.year != year) {
|
||||
this.year = year;
|
||||
normalized = false;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public CalendarDate addYear(int n) {
|
||||
if (n != 0) {
|
||||
year += n;
|
||||
normalized = false;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the year represented by this
|
||||
* <code>CalendarDate</code> is a leap year. If leap years are
|
||||
* not applicable to the calendar system, this method always
|
||||
* returns <code>false</code>.
|
||||
*
|
||||
* <p>If this <code>CalendarDate</code> hasn't been normalized,
|
||||
* <code>false</code> is returned. The normalization must be
|
||||
* performed to retrieve the correct leap year information.
|
||||
*
|
||||
* @return <code>true</code> if this <code>CalendarDate</code> is
|
||||
* normalized and the year of this <code>CalendarDate</code> is a
|
||||
* leap year, or <code>false</code> otherwise.
|
||||
* @see BaseCalendar#isGregorianLeapYear
|
||||
*/
|
||||
public boolean isLeapYear() {
|
||||
return leapYear;
|
||||
}
|
||||
|
||||
void setLeapYear(boolean leapYear) {
|
||||
this.leapYear = leapYear;
|
||||
}
|
||||
|
||||
public int getMonth() {
|
||||
return month;
|
||||
}
|
||||
|
||||
public CalendarDate setMonth(int month) {
|
||||
if (this.month != month) {
|
||||
this.month = month;
|
||||
normalized = false;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public CalendarDate addMonth(int n) {
|
||||
if (n != 0) {
|
||||
month += n;
|
||||
normalized = false;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getDayOfMonth() {
|
||||
return dayOfMonth;
|
||||
}
|
||||
|
||||
public CalendarDate setDayOfMonth(int date) {
|
||||
if (dayOfMonth != date) {
|
||||
dayOfMonth = date;
|
||||
normalized = false;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public CalendarDate addDayOfMonth(int n) {
|
||||
if (n != 0) {
|
||||
dayOfMonth += n;
|
||||
normalized = false;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the day of week value. If this CalendarDate is not
|
||||
* normalized, {@link #FIELD_UNDEFINED} is returned.
|
||||
*
|
||||
* @return day of week or {@link #FIELD_UNDEFINED}
|
||||
*/
|
||||
public int getDayOfWeek() {
|
||||
if (!isNormalized()) {
|
||||
dayOfWeek = FIELD_UNDEFINED;
|
||||
}
|
||||
return dayOfWeek;
|
||||
}
|
||||
|
||||
public int getHours() {
|
||||
return hours;
|
||||
}
|
||||
|
||||
public CalendarDate setHours(int hours) {
|
||||
if (this.hours != hours) {
|
||||
this.hours = hours;
|
||||
normalized = false;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public CalendarDate addHours(int n) {
|
||||
if (n != 0) {
|
||||
hours += n;
|
||||
normalized = false;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getMinutes() {
|
||||
return minutes;
|
||||
}
|
||||
|
||||
public CalendarDate setMinutes(int minutes) {
|
||||
if (this.minutes != minutes) {
|
||||
this.minutes = minutes;
|
||||
normalized = false;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public CalendarDate addMinutes(int n) {
|
||||
if (n != 0) {
|
||||
minutes += n;
|
||||
normalized = false;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getSeconds() {
|
||||
return seconds;
|
||||
}
|
||||
|
||||
public CalendarDate setSeconds(int seconds) {
|
||||
if (this.seconds != seconds) {
|
||||
this.seconds = seconds;
|
||||
normalized = false;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public CalendarDate addSeconds(int n) {
|
||||
if (n != 0) {
|
||||
seconds += n;
|
||||
normalized = false;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getMillis() {
|
||||
return millis;
|
||||
}
|
||||
|
||||
public CalendarDate setMillis(int millis) {
|
||||
if (this.millis != millis) {
|
||||
this.millis = millis;
|
||||
normalized = false;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public CalendarDate addMillis(int n) {
|
||||
if (n != 0) {
|
||||
millis += n;
|
||||
normalized = false;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public long getTimeOfDay() {
|
||||
if (!isNormalized()) {
|
||||
return fraction = TIME_UNDEFINED;
|
||||
}
|
||||
return fraction;
|
||||
}
|
||||
|
||||
public CalendarDate setDate(int year, int month, int dayOfMonth) {
|
||||
setYear(year);
|
||||
setMonth(month);
|
||||
setDayOfMonth(dayOfMonth);
|
||||
return this;
|
||||
}
|
||||
|
||||
public CalendarDate addDate(int year, int month, int dayOfMonth) {
|
||||
addYear(year);
|
||||
addMonth(month);
|
||||
addDayOfMonth(dayOfMonth);
|
||||
return this;
|
||||
}
|
||||
|
||||
public CalendarDate setTimeOfDay(int hours, int minutes, int seconds, int millis) {
|
||||
setHours(hours);
|
||||
setMinutes(minutes);
|
||||
setSeconds(seconds);
|
||||
setMillis(millis);
|
||||
return this;
|
||||
}
|
||||
|
||||
public CalendarDate addTimeOfDay(int hours, int minutes, int seconds, int millis) {
|
||||
addHours(hours);
|
||||
addMinutes(minutes);
|
||||
addSeconds(seconds);
|
||||
addMillis(millis);
|
||||
return this;
|
||||
}
|
||||
|
||||
protected void setTimeOfDay(long fraction) {
|
||||
this.fraction = fraction;
|
||||
}
|
||||
|
||||
public boolean isNormalized() {
|
||||
return normalized;
|
||||
}
|
||||
|
||||
|
||||
public boolean isStandardTime() {
|
||||
return forceStandardTime;
|
||||
}
|
||||
|
||||
public void setStandardTime(boolean standardTime) {
|
||||
forceStandardTime = standardTime;
|
||||
}
|
||||
|
||||
public boolean isDaylightTime() {
|
||||
if (isStandardTime()) {
|
||||
return false;
|
||||
}
|
||||
return daylightSaving != 0;
|
||||
}
|
||||
|
||||
protected void setLocale(Locale loc) {
|
||||
locale = loc;
|
||||
}
|
||||
|
||||
public TimeZone getZone() {
|
||||
return zoneinfo;
|
||||
}
|
||||
|
||||
public CalendarDate setZone(TimeZone zoneinfo) {
|
||||
this.zoneinfo = zoneinfo;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the specified date is the same date of this
|
||||
* <code>CalendarDate</code>. The time of the day fields are
|
||||
* ignored for the comparison.
|
||||
*/
|
||||
public boolean isSameDate(CalendarDate date) {
|
||||
return getDayOfWeek() == date.getDayOfWeek()
|
||||
&& getMonth() == date.getMonth()
|
||||
&& getYear() == date.getYear()
|
||||
&& getEra() == date.getEra();
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
if (!(obj instanceof CalendarDate)) {
|
||||
return false;
|
||||
}
|
||||
CalendarDate that = (CalendarDate) obj;
|
||||
if (isNormalized() != that.isNormalized()) {
|
||||
return false;
|
||||
}
|
||||
boolean hasZone = zoneinfo != null;
|
||||
boolean thatHasZone = that.zoneinfo != null;
|
||||
if (hasZone != thatHasZone) {
|
||||
return false;
|
||||
}
|
||||
if (hasZone && !zoneinfo.equals(that.zoneinfo)) {
|
||||
return false;
|
||||
}
|
||||
return (getEra() == that.getEra()
|
||||
&& year == that.year
|
||||
&& month == that.month
|
||||
&& dayOfMonth == that.dayOfMonth
|
||||
&& hours == that.hours
|
||||
&& minutes == that.minutes
|
||||
&& seconds == that.seconds
|
||||
&& millis == that.millis
|
||||
&& zoneOffset == that.zoneOffset);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
// a pseudo (local standard) time stamp value in milliseconds
|
||||
// from the Epoch, assuming Gregorian calendar fields.
|
||||
long hash = ((((((long)year - 1970) * 12) + (month - 1)) * 30) + dayOfMonth) * 24;
|
||||
hash = ((((((hash + hours) * 60) + minutes) * 60) + seconds) * 1000) + millis;
|
||||
hash -= zoneOffset;
|
||||
int normalized = isNormalized() ? 1 : 0;
|
||||
int era = 0;
|
||||
Era e = getEra();
|
||||
if (e != null) {
|
||||
era = e.hashCode();
|
||||
}
|
||||
int zone = zoneinfo != null ? zoneinfo.hashCode() : 0;
|
||||
return (int) hash * (int)(hash >> 32) ^ era ^ normalized ^ zone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of this <code>CalendarDate</code>. The
|
||||
* <code>TimeZone</code> object, if any, is not cloned.
|
||||
*
|
||||
* @return a copy of this <code>CalendarDate</code>
|
||||
*/
|
||||
public Object clone() {
|
||||
try {
|
||||
return super.clone();
|
||||
} catch (CloneNotSupportedException e) {
|
||||
// this shouldn't happen
|
||||
throw new InternalError(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts calendar date values to a <code>String</code> in the
|
||||
* following format.
|
||||
* <pre>
|
||||
* yyyy-MM-dd'T'HH:mm:ss.SSSz
|
||||
* </pre>
|
||||
*
|
||||
* @see java.text.SimpleDateFormat
|
||||
*/
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
CalendarUtils.sprintf0d(sb, year, 4).append('-');
|
||||
CalendarUtils.sprintf0d(sb, month, 2).append('-');
|
||||
CalendarUtils.sprintf0d(sb, dayOfMonth, 2).append('T');
|
||||
CalendarUtils.sprintf0d(sb, hours, 2).append(':');
|
||||
CalendarUtils.sprintf0d(sb, minutes, 2).append(':');
|
||||
CalendarUtils.sprintf0d(sb, seconds, 2).append('.');
|
||||
CalendarUtils.sprintf0d(sb, millis, 3);
|
||||
if (zoneOffset == 0) {
|
||||
sb.append('Z');
|
||||
} else if (zoneOffset != FIELD_UNDEFINED) {
|
||||
int offset;
|
||||
char sign;
|
||||
if (zoneOffset > 0) {
|
||||
offset = zoneOffset;
|
||||
sign = '+';
|
||||
} else {
|
||||
offset = -zoneOffset;
|
||||
sign = '-';
|
||||
}
|
||||
offset /= 60000;
|
||||
sb.append(sign);
|
||||
CalendarUtils.sprintf0d(sb, offset / 60, 2);
|
||||
CalendarUtils.sprintf0d(sb, offset % 60, 2);
|
||||
} else {
|
||||
sb.append(" local time");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
protected void setDayOfWeek(int dayOfWeek) {
|
||||
this.dayOfWeek = dayOfWeek;
|
||||
}
|
||||
|
||||
protected void setNormalized(boolean normalized) {
|
||||
this.normalized = normalized;
|
||||
}
|
||||
|
||||
public int getZoneOffset() {
|
||||
return zoneOffset;
|
||||
}
|
||||
|
||||
protected void setZoneOffset(int offset) {
|
||||
zoneOffset = offset;
|
||||
}
|
||||
|
||||
public int getDaylightSaving() {
|
||||
return daylightSaving;
|
||||
}
|
||||
|
||||
protected void setDaylightSaving(int daylightSaving) {
|
||||
this.daylightSaving = daylightSaving;
|
||||
}
|
||||
}
|
||||
395
jdkSrc/jdk8/sun/util/calendar/CalendarSystem.java
Normal file
395
jdkSrc/jdk8/sun/util/calendar/CalendarSystem.java
Normal file
@@ -0,0 +1,395 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.util.calendar;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedActionException;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
import java.util.Properties;
|
||||
import java.util.TimeZone;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
/**
|
||||
* <code>CalendarSystem</code> is an abstract class that defines the
|
||||
* programming interface to deal with calendar date and time.
|
||||
*
|
||||
* <p><code>CalendarSystem</code> instances are singletons. For
|
||||
* example, there exists only one Gregorian calendar instance in the
|
||||
* Java runtime environment. A singleton instance can be obtained
|
||||
* calling one of the static factory methods.
|
||||
*
|
||||
* <h4>CalendarDate</h4>
|
||||
*
|
||||
* <p>For the methods in a <code>CalendarSystem</code> that manipulate
|
||||
* a <code>CalendarDate</code>, <code>CalendarDate</code>s that have
|
||||
* been created by the <code>CalendarSystem</code> must be
|
||||
* specified. Otherwise, the methods throw an exception. This is
|
||||
* because, for example, a Chinese calendar date can't be understood
|
||||
* by the Hebrew calendar system.
|
||||
*
|
||||
* <h4>Calendar names</h4>
|
||||
*
|
||||
* Each calendar system has a unique name to be identified. The Java
|
||||
* runtime in this release supports the following calendar systems.
|
||||
*
|
||||
* <pre>
|
||||
* Name Calendar System
|
||||
* ---------------------------------------
|
||||
* gregorian Gregorian Calendar
|
||||
* julian Julian Calendar
|
||||
* japanese Japanese Imperial Calendar
|
||||
* </pre>
|
||||
*
|
||||
* @see CalendarDate
|
||||
* @author Masayoshi Okutsu
|
||||
* @since 1.5
|
||||
*/
|
||||
|
||||
public abstract class CalendarSystem {
|
||||
|
||||
/////////////////////// Calendar Factory Methods /////////////////////////
|
||||
|
||||
private volatile static boolean initialized = false;
|
||||
|
||||
// Map of calendar names and calendar class names
|
||||
private static ConcurrentMap<String, String> names;
|
||||
|
||||
// Map of calendar names and CalendarSystem instances
|
||||
private static ConcurrentMap<String,CalendarSystem> calendars;
|
||||
|
||||
private static final String PACKAGE_NAME = "sun.util.calendar.";
|
||||
|
||||
private static final String[] namePairs = {
|
||||
"gregorian", "Gregorian",
|
||||
"japanese", "LocalGregorianCalendar",
|
||||
"julian", "JulianCalendar",
|
||||
/*
|
||||
"hebrew", "HebrewCalendar",
|
||||
"iso8601", "ISOCalendar",
|
||||
"taiwanese", "LocalGregorianCalendar",
|
||||
"thaibuddhist", "LocalGregorianCalendar",
|
||||
*/
|
||||
};
|
||||
|
||||
private static void initNames() {
|
||||
ConcurrentMap<String,String> nameMap = new ConcurrentHashMap<>();
|
||||
|
||||
// Associate a calendar name with its class name and the
|
||||
// calendar class name with its date class name.
|
||||
StringBuilder clName = new StringBuilder();
|
||||
for (int i = 0; i < namePairs.length; i += 2) {
|
||||
clName.setLength(0);
|
||||
String cl = clName.append(PACKAGE_NAME).append(namePairs[i+1]).toString();
|
||||
nameMap.put(namePairs[i], cl);
|
||||
}
|
||||
synchronized (CalendarSystem.class) {
|
||||
if (!initialized) {
|
||||
names = nameMap;
|
||||
calendars = new ConcurrentHashMap<>();
|
||||
initialized = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final static Gregorian GREGORIAN_INSTANCE = new Gregorian();
|
||||
|
||||
/**
|
||||
* Returns the singleton instance of the <code>Gregorian</code>
|
||||
* calendar system.
|
||||
*
|
||||
* @return the <code>Gregorian</code> instance
|
||||
*/
|
||||
public static Gregorian getGregorianCalendar() {
|
||||
return GREGORIAN_INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a <code>CalendarSystem</code> specified by the calendar
|
||||
* name. The calendar name has to be one of the supported calendar
|
||||
* names.
|
||||
*
|
||||
* @param calendarName the calendar name
|
||||
* @return the <code>CalendarSystem</code> specified by
|
||||
* <code>calendarName</code>, or null if there is no
|
||||
* <code>CalendarSystem</code> associated with the given calendar name.
|
||||
*/
|
||||
public static CalendarSystem forName(String calendarName) {
|
||||
if ("gregorian".equals(calendarName)) {
|
||||
return GREGORIAN_INSTANCE;
|
||||
}
|
||||
|
||||
if (!initialized) {
|
||||
initNames();
|
||||
}
|
||||
|
||||
CalendarSystem cal = calendars.get(calendarName);
|
||||
if (cal != null) {
|
||||
return cal;
|
||||
}
|
||||
|
||||
String className = names.get(calendarName);
|
||||
if (className == null) {
|
||||
return null; // Unknown calendar name
|
||||
}
|
||||
|
||||
if (className.endsWith("LocalGregorianCalendar")) {
|
||||
// Create the specific kind of local Gregorian calendar system
|
||||
cal = LocalGregorianCalendar.getLocalGregorianCalendar(calendarName);
|
||||
} else {
|
||||
try {
|
||||
Class<?> cl = Class.forName(className);
|
||||
cal = (CalendarSystem) cl.newInstance();
|
||||
} catch (Exception e) {
|
||||
throw new InternalError(e);
|
||||
}
|
||||
}
|
||||
if (cal == null) {
|
||||
return null;
|
||||
}
|
||||
CalendarSystem cs = calendars.putIfAbsent(calendarName, cal);
|
||||
return (cs == null) ? cal : cs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link Properties} loaded from lib/calendars.properties.
|
||||
*
|
||||
* @return a {@link Properties} loaded from lib/calendars.properties
|
||||
* @throws IOException if an error occurred when reading from the input stream
|
||||
* @throws IllegalArgumentException if the input stream contains any malformed
|
||||
* Unicode escape sequences
|
||||
*/
|
||||
public static Properties getCalendarProperties() throws IOException {
|
||||
Properties calendarProps = null;
|
||||
try {
|
||||
String homeDir = AccessController.doPrivileged(
|
||||
new sun.security.action.GetPropertyAction("java.home"));
|
||||
final String fname = homeDir + File.separator + "lib" + File.separator
|
||||
+ "calendars.properties";
|
||||
calendarProps = AccessController.doPrivileged(new PrivilegedExceptionAction<Properties>() {
|
||||
@Override
|
||||
public Properties run() throws IOException {
|
||||
Properties props = new Properties();
|
||||
try (FileInputStream fis = new FileInputStream(fname)) {
|
||||
props.load(fis);
|
||||
}
|
||||
return props;
|
||||
}
|
||||
});
|
||||
} catch (PrivilegedActionException e) {
|
||||
Throwable cause = e.getCause();
|
||||
if (cause instanceof IOException) {
|
||||
throw (IOException) cause;
|
||||
} else if (cause instanceof IllegalArgumentException) {
|
||||
throw (IllegalArgumentException) cause;
|
||||
}
|
||||
// Should not happen
|
||||
throw new InternalError(cause);
|
||||
}
|
||||
return calendarProps;
|
||||
}
|
||||
|
||||
//////////////////////////////// Calendar API //////////////////////////////////
|
||||
|
||||
/**
|
||||
* Returns the name of this calendar system.
|
||||
*/
|
||||
public abstract String getName();
|
||||
|
||||
public abstract CalendarDate getCalendarDate();
|
||||
|
||||
/**
|
||||
* Calculates calendar fields from the specified number of
|
||||
* milliseconds since the Epoch, January 1, 1970 00:00:00 UTC
|
||||
* (Gregorian). This method doesn't check overflow or underflow
|
||||
* when adjusting the millisecond value (representing UTC) with
|
||||
* the time zone offsets (i.e., the GMT offset and amount of
|
||||
* daylight saving).
|
||||
*
|
||||
* @param millis the offset value in milliseconds from January 1,
|
||||
* 1970 00:00:00 UTC (Gregorian).
|
||||
* @return a <code>CalendarDate</code> instance that contains the
|
||||
* calculated calendar field values.
|
||||
*/
|
||||
public abstract CalendarDate getCalendarDate(long millis);
|
||||
|
||||
public abstract CalendarDate getCalendarDate(long millis, CalendarDate date);
|
||||
|
||||
public abstract CalendarDate getCalendarDate(long millis, TimeZone zone);
|
||||
|
||||
/**
|
||||
* Constructs a <code>CalendarDate</code> that is specific to this
|
||||
* calendar system. All calendar fields have their initial
|
||||
* values. The {@link TimeZone#getDefault() default time zone} is
|
||||
* set to the instance.
|
||||
*
|
||||
* @return a <code>CalendarDate</code> instance that contains the initial
|
||||
* calendar field values.
|
||||
*/
|
||||
public abstract CalendarDate newCalendarDate();
|
||||
|
||||
public abstract CalendarDate newCalendarDate(TimeZone zone);
|
||||
|
||||
/**
|
||||
* Returns the number of milliseconds since the Epoch, January 1,
|
||||
* 1970 00:00:00 UTC (Gregorian), represented by the specified
|
||||
* <code>CalendarDate</code>.
|
||||
*
|
||||
* @param date the <code>CalendarDate</code> from which the time
|
||||
* value is calculated
|
||||
* @return the number of milliseconds since the Epoch.
|
||||
*/
|
||||
public abstract long getTime(CalendarDate date);
|
||||
|
||||
/**
|
||||
* Returns the length in days of the specified year by
|
||||
* <code>date</code>. This method does not perform the
|
||||
* normalization with the specified <code>CalendarDate</code>. The
|
||||
* <code>CalendarDate</code> must be normalized to get a correct
|
||||
* value.
|
||||
*/
|
||||
public abstract int getYearLength(CalendarDate date);
|
||||
|
||||
/**
|
||||
* Returns the number of months of the specified year. This method
|
||||
* does not perform the normalization with the specified
|
||||
* <code>CalendarDate</code>. The <code>CalendarDate</code> must
|
||||
* be normalized to get a correct value.
|
||||
*/
|
||||
public abstract int getYearLengthInMonths(CalendarDate date);
|
||||
|
||||
/**
|
||||
* Returns the length in days of the month specified by the calendar
|
||||
* date. This method does not perform the normalization with the
|
||||
* specified calendar date. The <code>CalendarDate</code> must
|
||||
* be normalized to get a correct value.
|
||||
*
|
||||
* @param date the date from which the month value is obtained
|
||||
* @return the number of days in the month
|
||||
* @exception IllegalArgumentException if the specified calendar date
|
||||
* doesn't have a valid month value in this calendar system.
|
||||
*/
|
||||
public abstract int getMonthLength(CalendarDate date); // no setter
|
||||
|
||||
/**
|
||||
* Returns the length in days of a week in this calendar
|
||||
* system. If this calendar system has multiple radix weeks, this
|
||||
* method returns only one of them.
|
||||
*/
|
||||
public abstract int getWeekLength();
|
||||
|
||||
/**
|
||||
* Returns the <code>Era</code> designated by the era name that
|
||||
* has to be known to this calendar system. If no Era is
|
||||
* applicable to this calendar system, null is returned.
|
||||
*
|
||||
* @param eraName the name of the era
|
||||
* @return the <code>Era</code> designated by
|
||||
* <code>eraName</code>, or <code>null</code> if no Era is
|
||||
* applicable to this calendar system or the specified era name is
|
||||
* not known to this calendar system.
|
||||
*/
|
||||
public abstract Era getEra(String eraName);
|
||||
|
||||
/**
|
||||
* Returns valid <code>Era</code>s of this calendar system. The
|
||||
* return value is sorted in the descendant order. (i.e., the first
|
||||
* element of the returned array is the oldest era.) If no era is
|
||||
* applicable to this calendar system, <code>null</code> is returned.
|
||||
*
|
||||
* @return an array of valid <code>Era</code>s, or
|
||||
* <code>null</code> if no era is applicable to this calendar
|
||||
* system.
|
||||
*/
|
||||
public abstract Era[] getEras();
|
||||
|
||||
/**
|
||||
* @throws IllegalArgumentException if the specified era name is
|
||||
* unknown to this calendar system.
|
||||
* @see Era
|
||||
*/
|
||||
public abstract void setEra(CalendarDate date, String eraName);
|
||||
|
||||
/**
|
||||
* Returns a <code>CalendarDate</code> of the n-th day of week
|
||||
* which is on, after or before the specified date. For example, the
|
||||
* first Sunday in April 2002 (Gregorian) can be obtained as
|
||||
* below:
|
||||
*
|
||||
* <pre><code>
|
||||
* Gregorian cal = CalendarSystem.getGregorianCalendar();
|
||||
* CalendarDate date = cal.newCalendarDate();
|
||||
* date.setDate(2004, cal.APRIL, 1);
|
||||
* CalendarDate firstSun = cal.getNthDayOfWeek(1, cal.SUNDAY, date);
|
||||
* // firstSun represents April 4, 2004.
|
||||
* </code></pre>
|
||||
*
|
||||
* This method returns a new <code>CalendarDate</code> instance
|
||||
* and doesn't modify the original date.
|
||||
*
|
||||
* @param nth specifies the n-th one. A positive number specifies
|
||||
* <em>on or after</em> the <code>date</code>. A non-positive number
|
||||
* specifies <em>on or before</em> the <code>date</code>.
|
||||
* @param dayOfWeek the day of week
|
||||
* @param date the date
|
||||
* @return the date of the nth <code>dayOfWeek</code> after
|
||||
* or before the specified <code>CalendarDate</code>
|
||||
*/
|
||||
public abstract CalendarDate getNthDayOfWeek(int nth, int dayOfWeek,
|
||||
CalendarDate date);
|
||||
|
||||
public abstract CalendarDate setTimeOfDay(CalendarDate date, int timeOfDay);
|
||||
|
||||
/**
|
||||
* Checks whether the calendar fields specified by <code>date</code>
|
||||
* represents a valid date and time in this calendar system. If the
|
||||
* given date is valid, <code>date</code> is marked as <em>normalized</em>.
|
||||
*
|
||||
* @param date the <code>CalendarDate</code> to be validated
|
||||
* @return <code>true</code> if all the calendar fields are consistent,
|
||||
* otherwise, <code>false</code> is returned.
|
||||
* @exception NullPointerException if the specified
|
||||
* <code>date</code> is <code>null</code>
|
||||
*/
|
||||
public abstract boolean validate(CalendarDate date);
|
||||
|
||||
/**
|
||||
* Normalizes calendar fields in the specified
|
||||
* <code>date</code>. Also all {@link CalendarDate#FIELD_UNDEFINED
|
||||
* undefined} fields are set to correct values. The actual
|
||||
* normalization process is calendar system dependent.
|
||||
*
|
||||
* @param date the calendar date to be validated
|
||||
* @return <code>true</code> if all fields have been normalized;
|
||||
* <code>false</code> otherwise.
|
||||
* @exception NullPointerException if the specified
|
||||
* <code>date</code> is <code>null</code>
|
||||
*/
|
||||
public abstract boolean normalize(CalendarDate date);
|
||||
}
|
||||
193
jdkSrc/jdk8/sun/util/calendar/CalendarUtils.java
Normal file
193
jdkSrc/jdk8/sun/util/calendar/CalendarUtils.java
Normal file
@@ -0,0 +1,193 @@
|
||||
/*
|
||||
* Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.util.calendar;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class CalendarUtils {
|
||||
|
||||
/**
|
||||
* Returns whether the specified year is a leap year in the Gregorian
|
||||
* calendar system.
|
||||
*
|
||||
* @param gregorianYear a Gregorian calendar year
|
||||
* @return true if the given year is a leap year in the Gregorian
|
||||
* calendar system.
|
||||
* @see CalendarDate#isLeapYear
|
||||
*/
|
||||
public static final boolean isGregorianLeapYear(int gregorianYear) {
|
||||
return (((gregorianYear % 4) == 0)
|
||||
&& (((gregorianYear % 100) != 0) || ((gregorianYear % 400) == 0)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the specified year is a leap year in the Julian
|
||||
* calendar system. The year number must be a normalized one
|
||||
* (e.g., 45 B.C.E. is 1-45).
|
||||
*
|
||||
* @param normalizedJulianYear a normalized Julian calendar year
|
||||
* @return true if the given year is a leap year in the Julian
|
||||
* calendar system.
|
||||
* @see CalendarDate#isLeapYear
|
||||
*/
|
||||
public static final boolean isJulianLeapYear(int normalizedJulianYear) {
|
||||
return (normalizedJulianYear % 4) == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Divides two integers and returns the floor of the quotient.
|
||||
* For example, <code>floorDivide(-1, 4)</code> returns -1 while
|
||||
* -1/4 is 0.
|
||||
*
|
||||
* @param n the numerator
|
||||
* @param d a divisor that must be greater than 0
|
||||
* @return the floor of the quotient
|
||||
*/
|
||||
public static final long floorDivide(long n, long d) {
|
||||
return ((n >= 0) ?
|
||||
(n / d) : (((n + 1L) / d) - 1L));
|
||||
}
|
||||
|
||||
/**
|
||||
* Divides two integers and returns the floor of the quotient.
|
||||
* For example, <code>floorDivide(-1, 4)</code> returns -1 while
|
||||
* -1/4 is 0.
|
||||
*
|
||||
* @param n the numerator
|
||||
* @param d a divisor that must be greater than 0
|
||||
* @return the floor of the quotient
|
||||
*/
|
||||
public static final int floorDivide(int n, int d) {
|
||||
return ((n >= 0) ?
|
||||
(n / d) : (((n + 1) / d) - 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Divides two integers and returns the floor of the quotient and
|
||||
* the modulus remainder. For example,
|
||||
* <code>floorDivide(-1,4)</code> returns <code>-1</code> with
|
||||
* <code>3</code> as its remainder, while <code>-1/4</code> is
|
||||
* <code>0</code> and <code>-1%4</code> is <code>-1</code>.
|
||||
*
|
||||
* @param n the numerator
|
||||
* @param d a divisor which must be > 0
|
||||
* @param r an array of at least one element in which the value
|
||||
* <code>mod(n, d)</code> is returned.
|
||||
* @return the floor of the quotient.
|
||||
*/
|
||||
public static final int floorDivide(int n, int d, int[] r) {
|
||||
if (n >= 0) {
|
||||
r[0] = n % d;
|
||||
return n / d;
|
||||
}
|
||||
int q = ((n + 1) / d) - 1;
|
||||
r[0] = n - (q * d);
|
||||
return q;
|
||||
}
|
||||
|
||||
/**
|
||||
* Divides two integers and returns the floor of the quotient and
|
||||
* the modulus remainder. For example,
|
||||
* <code>floorDivide(-1,4)</code> returns <code>-1</code> with
|
||||
* <code>3</code> as its remainder, while <code>-1/4</code> is
|
||||
* <code>0</code> and <code>-1%4</code> is <code>-1</code>.
|
||||
*
|
||||
* @param n the numerator
|
||||
* @param d a divisor which must be > 0
|
||||
* @param r an array of at least one element in which the value
|
||||
* <code>mod(n, d)</code> is returned.
|
||||
* @return the floor of the quotient.
|
||||
*/
|
||||
public static final int floorDivide(long n, int d, int[] r) {
|
||||
if (n >= 0) {
|
||||
r[0] = (int)(n % d);
|
||||
return (int)(n / d);
|
||||
}
|
||||
int q = (int)(((n + 1) / d) - 1);
|
||||
r[0] = (int)(n - (q * d));
|
||||
return q;
|
||||
}
|
||||
|
||||
public static final long mod(long x, long y) {
|
||||
return (x - y * floorDivide(x, y));
|
||||
}
|
||||
|
||||
public static final int mod(int x, int y) {
|
||||
return (x - y * floorDivide(x, y));
|
||||
}
|
||||
|
||||
public static final int amod(int x, int y) {
|
||||
int z = mod(x, y);
|
||||
return (z == 0) ? y : z;
|
||||
}
|
||||
|
||||
public static final long amod(long x, long y) {
|
||||
long z = mod(x, y);
|
||||
return (z == 0) ? y : z;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mimics sprintf(buf, "%0*d", decaimal, width).
|
||||
*/
|
||||
public static final StringBuilder sprintf0d(StringBuilder sb, int value, int width) {
|
||||
long d = value;
|
||||
if (d < 0) {
|
||||
sb.append('-');
|
||||
d = -d;
|
||||
--width;
|
||||
}
|
||||
int n = 10;
|
||||
for (int i = 2; i < width; i++) {
|
||||
n *= 10;
|
||||
}
|
||||
for (int i = 1; i < width && d < n; i++) {
|
||||
sb.append('0');
|
||||
n /= 10;
|
||||
}
|
||||
sb.append(d);
|
||||
return sb;
|
||||
}
|
||||
|
||||
public static final StringBuffer sprintf0d(StringBuffer sb, int value, int width) {
|
||||
long d = value;
|
||||
if (d < 0) {
|
||||
sb.append('-');
|
||||
d = -d;
|
||||
--width;
|
||||
}
|
||||
int n = 10;
|
||||
for (int i = 2; i < width; i++) {
|
||||
n *= 10;
|
||||
}
|
||||
for (int i = 1; i < width && d < n; i++) {
|
||||
sb.append('0');
|
||||
n /= 10;
|
||||
}
|
||||
sb.append(d);
|
||||
return sb;
|
||||
}
|
||||
}
|
||||
154
jdkSrc/jdk8/sun/util/calendar/Era.java
Normal file
154
jdkSrc/jdk8/sun/util/calendar/Era.java
Normal file
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.util.calendar;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.TimeZone;
|
||||
|
||||
/**
|
||||
* The class <code>Era</code> represents a calendar era that defines a
|
||||
* period of time in which the same year numbering is used. For
|
||||
* example, Gregorian year 2004 is <I>Heisei</I> 16 in the Japanese
|
||||
* calendar system. An era starts at any point of time (Gregorian) that is
|
||||
* represented by <code>CalendarDate</code>.
|
||||
*
|
||||
* <p><code>Era</code>s that are applicable to a particular calendar
|
||||
* system can be obtained by calling {@link CalendarSystem#getEras}
|
||||
* one of which can be used to specify a date in
|
||||
* <code>CalendarDate</code>.
|
||||
*
|
||||
* <p>The following era names are defined in this release.
|
||||
* <pre>{@code
|
||||
* Calendar system Era name Since (in Gregorian)
|
||||
* -----------------------------------------------------------------------
|
||||
* Japanese calendar Meiji 1868-01-01T00:00:00 local time
|
||||
* Taisho 1912-07-30T00:00:00 local time
|
||||
* Showa 1926-12-25T00:00:00 local time
|
||||
* Heisei 1989-01-08T00:00:00 local time
|
||||
* Reiwa 2019-05-01T00:00:00 local time
|
||||
* -----------------------------------------------------------------------
|
||||
* }</pre>
|
||||
*
|
||||
* @author Masayoshi Okutsu
|
||||
* @since 1.5
|
||||
*/
|
||||
|
||||
public final class Era {
|
||||
private final String name;
|
||||
private final String abbr;
|
||||
private final long since;
|
||||
private final CalendarDate sinceDate;
|
||||
private final boolean localTime;
|
||||
|
||||
/**
|
||||
* Constructs an <code>Era</code> instance.
|
||||
*
|
||||
* @param name the era name (e.g., "BeforeCommonEra" for the Julian calendar system)
|
||||
* @param abbr the abbreviation of the era name (e.g., "B.C.E." for "BeforeCommonEra")
|
||||
* @param since the time (millisecond offset from January 1, 1970
|
||||
* (Gregorian) UTC or local time) when the era starts, inclusive.
|
||||
* @param localTime <code>true</code> if <code>since</code>
|
||||
* specifies a local time; <code>false</code> if
|
||||
* <code>since</code> specifies UTC
|
||||
*/
|
||||
public Era(String name, String abbr, long since, boolean localTime) {
|
||||
this.name = name;
|
||||
this.abbr = abbr;
|
||||
this.since = since;
|
||||
this.localTime = localTime;
|
||||
Gregorian gcal = CalendarSystem.getGregorianCalendar();
|
||||
BaseCalendar.Date d = (BaseCalendar.Date) gcal.newCalendarDate(null);
|
||||
gcal.getCalendarDate(since, d);
|
||||
sinceDate = new ImmutableGregorianDate(d);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getDisplayName(Locale locale) {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getAbbreviation() {
|
||||
return abbr;
|
||||
}
|
||||
|
||||
public String getDiaplayAbbreviation(Locale locale) {
|
||||
return abbr;
|
||||
}
|
||||
|
||||
public long getSince(TimeZone zone) {
|
||||
if (zone == null || !localTime) {
|
||||
return since;
|
||||
}
|
||||
int offset = zone.getOffset(since);
|
||||
return since - offset;
|
||||
}
|
||||
|
||||
public CalendarDate getSinceDate() {
|
||||
return sinceDate;
|
||||
}
|
||||
|
||||
public boolean isLocalTime() {
|
||||
return localTime;
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
if (!(o instanceof Era)) {
|
||||
return false;
|
||||
}
|
||||
Era that = (Era) o;
|
||||
return name.equals(that.name)
|
||||
&& abbr.equals(that.abbr)
|
||||
&& since == that.since
|
||||
&& localTime == that.localTime;
|
||||
}
|
||||
|
||||
private int hash = 0;
|
||||
|
||||
public int hashCode() {
|
||||
if (hash == 0) {
|
||||
hash = name.hashCode() ^ abbr.hashCode() ^ (int)since ^ (int)(since >> 32)
|
||||
^ (localTime ? 1 : 0);
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append('[');
|
||||
sb.append(getName()).append(" (");
|
||||
sb.append(getAbbreviation()).append(')');
|
||||
sb.append(" since ").append(getSinceDate());
|
||||
if (localTime) {
|
||||
sb.setLength(sb.length() - 1); // remove 'Z'
|
||||
sb.append(" local time");
|
||||
}
|
||||
sb.append(']');
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
87
jdkSrc/jdk8/sun/util/calendar/Gregorian.java
Normal file
87
jdkSrc/jdk8/sun/util/calendar/Gregorian.java
Normal file
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2005, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.util.calendar;
|
||||
|
||||
import java.util.TimeZone;
|
||||
|
||||
/**
|
||||
* Gregorian calendar implementation.
|
||||
*
|
||||
* @author Masayoshi Okutsu
|
||||
* @since 1.5
|
||||
*/
|
||||
|
||||
public class Gregorian extends BaseCalendar {
|
||||
|
||||
static class Date extends BaseCalendar.Date {
|
||||
protected Date() {
|
||||
super();
|
||||
}
|
||||
|
||||
protected Date(TimeZone zone) {
|
||||
super(zone);
|
||||
}
|
||||
|
||||
public int getNormalizedYear() {
|
||||
return getYear();
|
||||
}
|
||||
|
||||
public void setNormalizedYear(int normalizedYear) {
|
||||
setYear(normalizedYear);
|
||||
}
|
||||
}
|
||||
|
||||
Gregorian() {
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return "gregorian";
|
||||
}
|
||||
|
||||
public Date getCalendarDate() {
|
||||
return getCalendarDate(System.currentTimeMillis(), newCalendarDate());
|
||||
}
|
||||
|
||||
public Date getCalendarDate(long millis) {
|
||||
return getCalendarDate(millis, newCalendarDate());
|
||||
}
|
||||
|
||||
public Date getCalendarDate(long millis, CalendarDate date) {
|
||||
return (Date) super.getCalendarDate(millis, date);
|
||||
}
|
||||
|
||||
public Date getCalendarDate(long millis, TimeZone zone) {
|
||||
return getCalendarDate(millis, newCalendarDate(zone));
|
||||
}
|
||||
|
||||
public Date newCalendarDate() {
|
||||
return new Date();
|
||||
}
|
||||
|
||||
public Date newCalendarDate(TimeZone zone) {
|
||||
return new Date(zone);
|
||||
}
|
||||
}
|
||||
258
jdkSrc/jdk8/sun/util/calendar/ImmutableGregorianDate.java
Normal file
258
jdkSrc/jdk8/sun/util/calendar/ImmutableGregorianDate.java
Normal file
@@ -0,0 +1,258 @@
|
||||
/*
|
||||
* Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.util.calendar;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.TimeZone;
|
||||
|
||||
class ImmutableGregorianDate extends BaseCalendar.Date {
|
||||
private final BaseCalendar.Date date;
|
||||
|
||||
ImmutableGregorianDate(BaseCalendar.Date date) {
|
||||
if (date == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
this.date = date;
|
||||
}
|
||||
|
||||
public Era getEra() {
|
||||
return date.getEra();
|
||||
}
|
||||
|
||||
public CalendarDate setEra(Era era) {
|
||||
unsupported(); return this;
|
||||
}
|
||||
|
||||
public int getYear() {
|
||||
return date.getYear();
|
||||
}
|
||||
|
||||
public CalendarDate setYear(int year) {
|
||||
unsupported(); return this;
|
||||
}
|
||||
|
||||
public CalendarDate addYear(int n) {
|
||||
unsupported(); return this;
|
||||
}
|
||||
|
||||
public boolean isLeapYear() {
|
||||
return date.isLeapYear();
|
||||
}
|
||||
|
||||
void setLeapYear(boolean leapYear) {
|
||||
unsupported();
|
||||
}
|
||||
|
||||
public int getMonth() {
|
||||
return date.getMonth();
|
||||
}
|
||||
|
||||
public CalendarDate setMonth(int month) {
|
||||
unsupported(); return this;
|
||||
}
|
||||
|
||||
public CalendarDate addMonth(int n) {
|
||||
unsupported(); return this;
|
||||
}
|
||||
|
||||
public int getDayOfMonth() {
|
||||
return date.getDayOfMonth();
|
||||
}
|
||||
|
||||
public CalendarDate setDayOfMonth(int date) {
|
||||
unsupported(); return this;
|
||||
}
|
||||
|
||||
public CalendarDate addDayOfMonth(int n) {
|
||||
unsupported(); return this;
|
||||
}
|
||||
|
||||
public int getDayOfWeek() {
|
||||
return date.getDayOfWeek();
|
||||
}
|
||||
|
||||
public int getHours() {
|
||||
return date.getHours();
|
||||
}
|
||||
|
||||
public CalendarDate setHours(int hours) {
|
||||
unsupported(); return this;
|
||||
}
|
||||
|
||||
public CalendarDate addHours(int n) {
|
||||
unsupported(); return this;
|
||||
}
|
||||
|
||||
public int getMinutes() {
|
||||
return date.getMinutes();
|
||||
}
|
||||
|
||||
public CalendarDate setMinutes(int minutes) {
|
||||
unsupported(); return this;
|
||||
}
|
||||
|
||||
public CalendarDate addMinutes(int n) {
|
||||
unsupported(); return this;
|
||||
}
|
||||
|
||||
public int getSeconds() {
|
||||
return date.getSeconds();
|
||||
}
|
||||
|
||||
public CalendarDate setSeconds(int seconds) {
|
||||
unsupported(); return this;
|
||||
}
|
||||
|
||||
public CalendarDate addSeconds(int n) {
|
||||
unsupported(); return this;
|
||||
}
|
||||
|
||||
public int getMillis() {
|
||||
return date.getMillis();
|
||||
}
|
||||
|
||||
public CalendarDate setMillis(int millis) {
|
||||
unsupported(); return this;
|
||||
}
|
||||
|
||||
public CalendarDate addMillis(int n) {
|
||||
unsupported(); return this;
|
||||
}
|
||||
|
||||
public long getTimeOfDay() {
|
||||
return date.getTimeOfDay();
|
||||
}
|
||||
|
||||
public CalendarDate setDate(int year, int month, int dayOfMonth) {
|
||||
unsupported(); return this;
|
||||
}
|
||||
|
||||
public CalendarDate addDate(int year, int month, int dayOfMonth) {
|
||||
unsupported(); return this;
|
||||
}
|
||||
|
||||
public CalendarDate setTimeOfDay(int hours, int minutes, int seconds, int millis) {
|
||||
unsupported(); return this;
|
||||
}
|
||||
|
||||
public CalendarDate addTimeOfDay(int hours, int minutes, int seconds, int millis) {
|
||||
unsupported(); return this;
|
||||
}
|
||||
|
||||
protected void setTimeOfDay(long fraction) {
|
||||
unsupported();
|
||||
}
|
||||
|
||||
public boolean isNormalized() {
|
||||
return date.isNormalized();
|
||||
}
|
||||
|
||||
public boolean isStandardTime() {
|
||||
return date.isStandardTime();
|
||||
}
|
||||
|
||||
public void setStandardTime(boolean standardTime) {
|
||||
unsupported();
|
||||
}
|
||||
|
||||
public boolean isDaylightTime() {
|
||||
return date.isDaylightTime();
|
||||
}
|
||||
|
||||
protected void setLocale(Locale loc) {
|
||||
unsupported();
|
||||
}
|
||||
|
||||
public TimeZone getZone() {
|
||||
return date.getZone();
|
||||
}
|
||||
|
||||
public CalendarDate setZone(TimeZone zoneinfo) {
|
||||
unsupported(); return this;
|
||||
}
|
||||
|
||||
public boolean isSameDate(CalendarDate date) {
|
||||
return date.isSameDate(date);
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (!(obj instanceof ImmutableGregorianDate)) {
|
||||
return false;
|
||||
}
|
||||
return date.equals(((ImmutableGregorianDate) obj).date);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return date.hashCode();
|
||||
}
|
||||
|
||||
public Object clone() {
|
||||
return super.clone();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return date.toString();
|
||||
}
|
||||
|
||||
protected void setDayOfWeek(int dayOfWeek) {
|
||||
unsupported();
|
||||
}
|
||||
|
||||
protected void setNormalized(boolean normalized) {
|
||||
unsupported();
|
||||
}
|
||||
|
||||
public int getZoneOffset() {
|
||||
return date.getZoneOffset();
|
||||
}
|
||||
|
||||
protected void setZoneOffset(int offset) {
|
||||
unsupported();
|
||||
}
|
||||
|
||||
public int getDaylightSaving() {
|
||||
return date.getDaylightSaving();
|
||||
}
|
||||
|
||||
protected void setDaylightSaving(int daylightSaving) {
|
||||
unsupported();
|
||||
}
|
||||
|
||||
public int getNormalizedYear() {
|
||||
return date.getNormalizedYear();
|
||||
}
|
||||
|
||||
public void setNormalizedYear(int normalizedYear) {
|
||||
unsupported();
|
||||
}
|
||||
|
||||
private void unsupported() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
234
jdkSrc/jdk8/sun/util/calendar/JulianCalendar.java
Normal file
234
jdkSrc/jdk8/sun/util/calendar/JulianCalendar.java
Normal file
@@ -0,0 +1,234 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.util.calendar;
|
||||
|
||||
import java.util.TimeZone;
|
||||
|
||||
/**
|
||||
* Julian calendar implementation.
|
||||
*
|
||||
* @author Masayoshi Okutsu
|
||||
* @since 1.5
|
||||
*/
|
||||
public class JulianCalendar extends BaseCalendar {
|
||||
|
||||
private static final int BCE = 0;
|
||||
private static final int CE = 1;
|
||||
|
||||
private static final Era[] eras = {
|
||||
new Era("BeforeCommonEra", "B.C.E.", Long.MIN_VALUE, false),
|
||||
new Era("CommonEra", "C.E.", -62135709175808L, true)
|
||||
};
|
||||
private static final int JULIAN_EPOCH = -1;
|
||||
|
||||
private static class Date extends BaseCalendar.Date {
|
||||
protected Date() {
|
||||
super();
|
||||
setCache(1, -1L, 365); // January 1, 1 CE (Julian)
|
||||
}
|
||||
|
||||
protected Date(TimeZone zone) {
|
||||
super(zone);
|
||||
setCache(1, -1L, 365); // January 1, 1 CE (Julian)
|
||||
}
|
||||
|
||||
public Date setEra(Era era) {
|
||||
if (era == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
if (era != eras[0] || era != eras[1]) {
|
||||
throw new IllegalArgumentException("unknown era: " + era);
|
||||
}
|
||||
super.setEra(era);
|
||||
return this;
|
||||
}
|
||||
|
||||
protected void setKnownEra(Era era) {
|
||||
super.setEra(era);
|
||||
}
|
||||
|
||||
public int getNormalizedYear() {
|
||||
if (getEra() == eras[BCE]) {
|
||||
return 1 - getYear();
|
||||
}
|
||||
return getYear();
|
||||
}
|
||||
|
||||
// Use the year numbering ..., -2, -1, 0, 1, 2, ... for
|
||||
// normalized years. This differs from "Calendrical
|
||||
// Calculations" in which the numbering is ..., -2, -1, 1, 2,
|
||||
// ...
|
||||
public void setNormalizedYear(int year) {
|
||||
if (year <= 0) {
|
||||
setYear(1 - year);
|
||||
setKnownEra(eras[BCE]);
|
||||
} else {
|
||||
setYear(year);
|
||||
setKnownEra(eras[CE]);
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
String time = super.toString();
|
||||
time = time.substring(time.indexOf('T'));
|
||||
StringBuffer sb = new StringBuffer();
|
||||
Era era = getEra();
|
||||
if (era != null) {
|
||||
String n = era.getAbbreviation();
|
||||
if (n != null) {
|
||||
sb.append(n).append(' ');
|
||||
}
|
||||
}
|
||||
sb.append(getYear()).append('-');
|
||||
CalendarUtils.sprintf0d(sb, getMonth(), 2).append('-');
|
||||
CalendarUtils.sprintf0d(sb, getDayOfMonth(), 2);
|
||||
sb.append(time);
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
JulianCalendar() {
|
||||
setEras(eras);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return "julian";
|
||||
}
|
||||
|
||||
public Date getCalendarDate() {
|
||||
return getCalendarDate(System.currentTimeMillis(), newCalendarDate());
|
||||
}
|
||||
|
||||
public Date getCalendarDate(long millis) {
|
||||
return getCalendarDate(millis, newCalendarDate());
|
||||
}
|
||||
|
||||
public Date getCalendarDate(long millis, CalendarDate date) {
|
||||
return (Date) super.getCalendarDate(millis, date);
|
||||
}
|
||||
|
||||
public Date getCalendarDate(long millis, TimeZone zone) {
|
||||
return getCalendarDate(millis, newCalendarDate(zone));
|
||||
}
|
||||
|
||||
public Date newCalendarDate() {
|
||||
return new Date();
|
||||
}
|
||||
|
||||
public Date newCalendarDate(TimeZone zone) {
|
||||
return new Date(zone);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param jyear normalized Julian year
|
||||
*/
|
||||
public long getFixedDate(int jyear, int month, int dayOfMonth, BaseCalendar.Date cache) {
|
||||
boolean isJan1 = month == JANUARY && dayOfMonth == 1;
|
||||
|
||||
// Look up the one year cache
|
||||
if (cache != null && cache.hit(jyear)) {
|
||||
if (isJan1) {
|
||||
return cache.getCachedJan1();
|
||||
}
|
||||
return cache.getCachedJan1() + getDayOfYear(jyear, month, dayOfMonth) - 1;
|
||||
}
|
||||
|
||||
long y = jyear;
|
||||
long days = JULIAN_EPOCH - 1 + (365 * (y - 1)) + dayOfMonth;
|
||||
if (y > 0) {
|
||||
// CE years
|
||||
days += (y - 1) / 4;
|
||||
} else {
|
||||
// BCE years
|
||||
days += CalendarUtils.floorDivide(y - 1, 4);
|
||||
}
|
||||
if (month > 0) {
|
||||
days += ((367 * (long) month) - 362) / 12;
|
||||
} else {
|
||||
days += CalendarUtils.floorDivide((367 * (long) month) - 362, 12);
|
||||
}
|
||||
if (month > FEBRUARY) {
|
||||
days -= CalendarUtils.isJulianLeapYear(jyear) ? 1 : 2;
|
||||
}
|
||||
|
||||
// If it's January 1, update the cache.
|
||||
if (cache != null && isJan1) {
|
||||
cache.setCache(jyear, days, CalendarUtils.isJulianLeapYear(jyear) ? 366 : 365);
|
||||
}
|
||||
|
||||
return days;
|
||||
}
|
||||
|
||||
public void getCalendarDateFromFixedDate(CalendarDate date, long fixedDate) {
|
||||
Date jdate = (Date) date;
|
||||
long fd = 4 * (fixedDate - JULIAN_EPOCH) + 1464;
|
||||
int year;
|
||||
if (fd >= 0) {
|
||||
year = (int)(fd / 1461);
|
||||
} else {
|
||||
year = (int) CalendarUtils.floorDivide(fd, 1461);
|
||||
}
|
||||
int priorDays = (int)(fixedDate - getFixedDate(year, JANUARY, 1, jdate));
|
||||
boolean isLeap = CalendarUtils.isJulianLeapYear(year);
|
||||
if (fixedDate >= getFixedDate(year, MARCH, 1, jdate)) {
|
||||
priorDays += isLeap ? 1 : 2;
|
||||
}
|
||||
int month = 12 * priorDays + 373;
|
||||
if (month > 0) {
|
||||
month /= 367;
|
||||
} else {
|
||||
month = CalendarUtils.floorDivide(month, 367);
|
||||
}
|
||||
int dayOfMonth = (int)(fixedDate - getFixedDate(year, month, 1, jdate)) + 1;
|
||||
int dayOfWeek = getDayOfWeekFromFixedDate(fixedDate);
|
||||
assert dayOfWeek > 0 : "negative day of week " + dayOfWeek;
|
||||
jdate.setNormalizedYear(year);
|
||||
jdate.setMonth(month);
|
||||
jdate.setDayOfMonth(dayOfMonth);
|
||||
jdate.setDayOfWeek(dayOfWeek);
|
||||
jdate.setLeapYear(isLeap);
|
||||
jdate.setNormalized(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the normalized Julian year number of the given fixed date.
|
||||
*/
|
||||
public int getYearFromFixedDate(long fixedDate) {
|
||||
int year = (int) CalendarUtils.floorDivide(4 * (fixedDate - JULIAN_EPOCH) + 1464, 1461);
|
||||
return year;
|
||||
}
|
||||
|
||||
public int getDayOfWeek(CalendarDate date) {
|
||||
// TODO: should replace this with a faster calculation, such
|
||||
// as cache table lookup
|
||||
long fixedDate = getFixedDate(date);
|
||||
return getDayOfWeekFromFixedDate(fixedDate);
|
||||
}
|
||||
|
||||
boolean isLeapYear(int jyear) {
|
||||
return CalendarUtils.isJulianLeapYear(jyear);
|
||||
}
|
||||
}
|
||||
389
jdkSrc/jdk8/sun/util/calendar/LocalGregorianCalendar.java
Normal file
389
jdkSrc/jdk8/sun/util/calendar/LocalGregorianCalendar.java
Normal file
@@ -0,0 +1,389 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.util.calendar;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.TimeZone;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Masayoshi Okutsu
|
||||
* @since 1.6
|
||||
*/
|
||||
|
||||
public class LocalGregorianCalendar extends BaseCalendar {
|
||||
private String name;
|
||||
private Era[] eras;
|
||||
|
||||
public static class Date extends BaseCalendar.Date {
|
||||
|
||||
protected Date() {
|
||||
super();
|
||||
}
|
||||
|
||||
protected Date(TimeZone zone) {
|
||||
super(zone);
|
||||
}
|
||||
|
||||
private int gregorianYear = FIELD_UNDEFINED;
|
||||
|
||||
@Override
|
||||
public Date setEra(Era era) {
|
||||
if (getEra() != era) {
|
||||
super.setEra(era);
|
||||
gregorianYear = FIELD_UNDEFINED;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date addYear(int localYear) {
|
||||
super.addYear(localYear);
|
||||
gregorianYear += localYear;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date setYear(int localYear) {
|
||||
if (getYear() != localYear) {
|
||||
super.setYear(localYear);
|
||||
gregorianYear = FIELD_UNDEFINED;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNormalizedYear() {
|
||||
return gregorianYear;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNormalizedYear(int normalizedYear) {
|
||||
this.gregorianYear = normalizedYear;
|
||||
}
|
||||
|
||||
void setLocalEra(Era era) {
|
||||
super.setEra(era);
|
||||
}
|
||||
|
||||
void setLocalYear(int year) {
|
||||
super.setYear(year);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String time = super.toString();
|
||||
time = time.substring(time.indexOf('T'));
|
||||
StringBuffer sb = new StringBuffer();
|
||||
Era era = getEra();
|
||||
if (era != null) {
|
||||
String abbr = era.getAbbreviation();
|
||||
if (abbr != null) {
|
||||
sb.append(abbr);
|
||||
}
|
||||
}
|
||||
sb.append(getYear()).append('.');
|
||||
CalendarUtils.sprintf0d(sb, getMonth(), 2).append('.');
|
||||
CalendarUtils.sprintf0d(sb, getDayOfMonth(), 2);
|
||||
sb.append(time);
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
static LocalGregorianCalendar getLocalGregorianCalendar(String name) {
|
||||
Properties calendarProps;
|
||||
try {
|
||||
calendarProps = CalendarSystem.getCalendarProperties();
|
||||
} catch (IOException | IllegalArgumentException e) {
|
||||
throw new InternalError(e);
|
||||
}
|
||||
// Parse calendar.*.eras
|
||||
String props = calendarProps.getProperty("calendar." + name + ".eras");
|
||||
if (props == null) {
|
||||
return null;
|
||||
}
|
||||
List<Era> eras = new ArrayList<>();
|
||||
StringTokenizer eraTokens = new StringTokenizer(props, ";");
|
||||
while (eraTokens.hasMoreTokens()) {
|
||||
String items = eraTokens.nextToken().trim();
|
||||
StringTokenizer itemTokens = new StringTokenizer(items, ",");
|
||||
String eraName = null;
|
||||
boolean localTime = true;
|
||||
long since = 0;
|
||||
String abbr = null;
|
||||
|
||||
while (itemTokens.hasMoreTokens()) {
|
||||
String item = itemTokens.nextToken();
|
||||
int index = item.indexOf('=');
|
||||
// it must be in the key=value form.
|
||||
if (index == -1) {
|
||||
return null;
|
||||
}
|
||||
String key = item.substring(0, index);
|
||||
String value = item.substring(index + 1);
|
||||
if ("name".equals(key)) {
|
||||
eraName = value;
|
||||
} else if ("since".equals(key)) {
|
||||
if (value.endsWith("u")) {
|
||||
localTime = false;
|
||||
since = Long.parseLong(value.substring(0, value.length() - 1));
|
||||
} else {
|
||||
since = Long.parseLong(value);
|
||||
}
|
||||
} else if ("abbr".equals(key)) {
|
||||
abbr = value;
|
||||
} else {
|
||||
throw new RuntimeException("Unknown key word: " + key);
|
||||
}
|
||||
}
|
||||
Era era = new Era(eraName, abbr, since, localTime);
|
||||
eras.add(era);
|
||||
}
|
||||
Era[] eraArray = new Era[eras.size()];
|
||||
eras.toArray(eraArray);
|
||||
|
||||
return new LocalGregorianCalendar(name, eraArray);
|
||||
}
|
||||
|
||||
private LocalGregorianCalendar(String name, Era[] eras) {
|
||||
this.name = name;
|
||||
this.eras = eras;
|
||||
setEras(eras);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date getCalendarDate() {
|
||||
return getCalendarDate(System.currentTimeMillis(), newCalendarDate());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date getCalendarDate(long millis) {
|
||||
return getCalendarDate(millis, newCalendarDate());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date getCalendarDate(long millis, TimeZone zone) {
|
||||
return getCalendarDate(millis, newCalendarDate(zone));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date getCalendarDate(long millis, CalendarDate date) {
|
||||
Date ldate = (Date) super.getCalendarDate(millis, date);
|
||||
return adjustYear(ldate, millis, ldate.getZoneOffset());
|
||||
}
|
||||
|
||||
private Date adjustYear(Date ldate, long millis, int zoneOffset) {
|
||||
int i;
|
||||
for (i = eras.length - 1; i >= 0; --i) {
|
||||
Era era = eras[i];
|
||||
long since = era.getSince(null);
|
||||
if (era.isLocalTime()) {
|
||||
since -= zoneOffset;
|
||||
}
|
||||
if (millis >= since) {
|
||||
ldate.setLocalEra(era);
|
||||
int y = ldate.getNormalizedYear() - era.getSinceDate().getYear() + 1;
|
||||
ldate.setLocalYear(y);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i < 0) {
|
||||
ldate.setLocalEra(null);
|
||||
ldate.setLocalYear(ldate.getNormalizedYear());
|
||||
}
|
||||
ldate.setNormalized(true);
|
||||
return ldate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date newCalendarDate() {
|
||||
return new Date();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date newCalendarDate(TimeZone zone) {
|
||||
return new Date(zone);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validate(CalendarDate date) {
|
||||
Date ldate = (Date) date;
|
||||
Era era = ldate.getEra();
|
||||
if (era != null) {
|
||||
if (!validateEra(era)) {
|
||||
return false;
|
||||
}
|
||||
ldate.setNormalizedYear(era.getSinceDate().getYear() + ldate.getYear() - 1);
|
||||
Date tmp = newCalendarDate(date.getZone());
|
||||
tmp.setEra(era).setDate(date.getYear(), date.getMonth(), date.getDayOfMonth());
|
||||
normalize(tmp);
|
||||
if (tmp.getEra() != era) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (date.getYear() >= eras[0].getSinceDate().getYear()) {
|
||||
return false;
|
||||
}
|
||||
ldate.setNormalizedYear(ldate.getYear());
|
||||
}
|
||||
return super.validate(ldate);
|
||||
}
|
||||
|
||||
private boolean validateEra(Era era) {
|
||||
// Validate the era
|
||||
for (int i = 0; i < eras.length; i++) {
|
||||
if (era == eras[i]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean normalize(CalendarDate date) {
|
||||
if (date.isNormalized()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
normalizeYear(date);
|
||||
Date ldate = (Date) date;
|
||||
|
||||
// Normalize it as a Gregorian date and get its millisecond value
|
||||
super.normalize(ldate);
|
||||
|
||||
boolean hasMillis = false;
|
||||
long millis = 0;
|
||||
int year = ldate.getNormalizedYear();
|
||||
int i;
|
||||
Era era = null;
|
||||
for (i = eras.length - 1; i >= 0; --i) {
|
||||
era = eras[i];
|
||||
if (era.isLocalTime()) {
|
||||
CalendarDate sinceDate = era.getSinceDate();
|
||||
int sinceYear = sinceDate.getYear();
|
||||
if (year > sinceYear) {
|
||||
break;
|
||||
}
|
||||
if (year == sinceYear) {
|
||||
int month = ldate.getMonth();
|
||||
int sinceMonth = sinceDate.getMonth();
|
||||
if (month > sinceMonth) {
|
||||
break;
|
||||
}
|
||||
if (month == sinceMonth) {
|
||||
int day = ldate.getDayOfMonth();
|
||||
int sinceDay = sinceDate.getDayOfMonth();
|
||||
if (day > sinceDay) {
|
||||
break;
|
||||
}
|
||||
if (day == sinceDay) {
|
||||
long timeOfDay = ldate.getTimeOfDay();
|
||||
long sinceTimeOfDay = sinceDate.getTimeOfDay();
|
||||
if (timeOfDay >= sinceTimeOfDay) {
|
||||
break;
|
||||
}
|
||||
--i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!hasMillis) {
|
||||
millis = super.getTime(date);
|
||||
hasMillis = true;
|
||||
}
|
||||
|
||||
long since = era.getSince(date.getZone());
|
||||
if (millis >= since) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (i >= 0) {
|
||||
ldate.setLocalEra(era);
|
||||
int y = ldate.getNormalizedYear() - era.getSinceDate().getYear() + 1;
|
||||
ldate.setLocalYear(y);
|
||||
} else {
|
||||
// Set Gregorian year with no era
|
||||
ldate.setEra(null);
|
||||
ldate.setLocalYear(year);
|
||||
ldate.setNormalizedYear(year);
|
||||
}
|
||||
ldate.setNormalized(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
void normalizeMonth(CalendarDate date) {
|
||||
normalizeYear(date);
|
||||
super.normalizeMonth(date);
|
||||
}
|
||||
|
||||
void normalizeYear(CalendarDate date) {
|
||||
Date ldate = (Date) date;
|
||||
// Set the supposed-to-be-correct Gregorian year first
|
||||
// e.g., Showa 90 becomes 2015 (1926 + 90 - 1).
|
||||
Era era = ldate.getEra();
|
||||
if (era == null || !validateEra(era)) {
|
||||
ldate.setNormalizedYear(ldate.getYear());
|
||||
} else {
|
||||
ldate.setNormalizedYear(era.getSinceDate().getYear() + ldate.getYear() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the specified Gregorian year is a leap year.
|
||||
* @see #isLeapYear(Era, int)
|
||||
*/
|
||||
@Override
|
||||
public boolean isLeapYear(int gregorianYear) {
|
||||
return CalendarUtils.isGregorianLeapYear(gregorianYear);
|
||||
}
|
||||
|
||||
public boolean isLeapYear(Era era, int year) {
|
||||
if (era == null) {
|
||||
return isLeapYear(year);
|
||||
}
|
||||
int gyear = era.getSinceDate().getYear() + year - 1;
|
||||
return isLeapYear(gyear);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getCalendarDateFromFixedDate(CalendarDate date, long fixedDate) {
|
||||
Date ldate = (Date) date;
|
||||
super.getCalendarDateFromFixedDate(ldate, fixedDate);
|
||||
adjustYear(ldate, (fixedDate - EPOCH_OFFSET) * DAY_IN_MILLIS, 0);
|
||||
}
|
||||
}
|
||||
737
jdkSrc/jdk8/sun/util/calendar/ZoneInfo.java
Normal file
737
jdkSrc/jdk8/sun/util/calendar/ZoneInfo.java
Normal file
@@ -0,0 +1,737 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.util.calendar;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.security.AccessController;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.SimpleTimeZone;
|
||||
import java.util.TimeZone;
|
||||
|
||||
/**
|
||||
* <code>ZoneInfo</code> is an implementation subclass of {@link
|
||||
* java.util.TimeZone TimeZone} that represents GMT offsets and
|
||||
* daylight saving time transitions of a time zone.
|
||||
* <p>
|
||||
* The daylight saving time transitions are described in the {@link
|
||||
* #transitions transitions} table consisting of a chronological
|
||||
* sequence of transitions of GMT offset and/or daylight saving time
|
||||
* changes. Since all transitions are represented in UTC, in theory,
|
||||
* <code>ZoneInfo</code> can be used with any calendar systems except
|
||||
* for the {@link #getOffset(int,int,int,int,int,int) getOffset}
|
||||
* method that takes Gregorian calendar date fields.
|
||||
* <p>
|
||||
* This table covers transitions from 1900 until 2037 (as of version
|
||||
* 1.4), Before 1900, it assumes that there was no daylight saving
|
||||
* time and the <code>getOffset</code> methods always return the
|
||||
* {@link #getRawOffset} value. No Local Mean Time is supported. If a
|
||||
* specified date is beyond the transition table and this time zone is
|
||||
* supposed to observe daylight saving time in 2037, it delegates
|
||||
* operations to a {@link java.util.SimpleTimeZone SimpleTimeZone}
|
||||
* object created using the daylight saving time schedule as of 2037.
|
||||
* <p>
|
||||
* The date items, transitions, GMT offset(s), etc. are read from a database
|
||||
* file. See {@link ZoneInfoFile} for details.
|
||||
* @see java.util.SimpleTimeZone
|
||||
* @since 1.4
|
||||
*/
|
||||
|
||||
public class ZoneInfo extends TimeZone {
|
||||
|
||||
private static final int UTC_TIME = 0;
|
||||
private static final int STANDARD_TIME = 1;
|
||||
private static final int WALL_TIME = 2;
|
||||
|
||||
private static final long OFFSET_MASK = 0x0fL;
|
||||
private static final long DST_MASK = 0xf0L;
|
||||
private static final int DST_NSHIFT = 4;
|
||||
// this bit field is reserved for abbreviation support
|
||||
private static final long ABBR_MASK = 0xf00L;
|
||||
private static final int TRANSITION_NSHIFT = 12;
|
||||
|
||||
private static final CalendarSystem gcal = CalendarSystem.getGregorianCalendar();
|
||||
|
||||
/**
|
||||
* The raw GMT offset in milliseconds between this zone and GMT.
|
||||
* Negative offsets are to the west of Greenwich. To obtain local
|
||||
* <em>standard</em> time, add the offset to GMT time.
|
||||
* @serial
|
||||
*/
|
||||
private int rawOffset;
|
||||
|
||||
/**
|
||||
* Difference in milliseconds from the original GMT offset in case
|
||||
* the raw offset value has been modified by calling {@link
|
||||
* #setRawOffset}. The initial value is 0.
|
||||
* @serial
|
||||
*/
|
||||
private int rawOffsetDiff = 0;
|
||||
|
||||
/**
|
||||
* A CRC32 value of all pairs of transition time (in milliseconds
|
||||
* in <code>long</code>) in local time and its GMT offset (in
|
||||
* seconds in <code>int</code>) in the chronological order. Byte
|
||||
* values of each <code>long</code> and <code>int</code> are taken
|
||||
* in the big endian order (i.e., MSB to LSB).
|
||||
* @serial
|
||||
*/
|
||||
private int checksum;
|
||||
|
||||
/**
|
||||
* The amount of time in milliseconds saved during daylight saving
|
||||
* time. If <code>useDaylight</code> is false, this value is 0.
|
||||
* @serial
|
||||
*/
|
||||
private int dstSavings;
|
||||
|
||||
/**
|
||||
* This array describes transitions of GMT offsets of this time
|
||||
* zone, including both raw offset changes and daylight saving
|
||||
* time changes.
|
||||
* A long integer consists of four bit fields.
|
||||
* <ul>
|
||||
* <li>The most significant 52-bit field represents transition
|
||||
* time in milliseconds from Gregorian January 1 1970, 00:00:00
|
||||
* GMT.</li>
|
||||
* <li>The next 4-bit field is reserved and must be 0.</li>
|
||||
* <li>The next 4-bit field is an index value to {@link #offsets
|
||||
* offsets[]} for the amount of daylight saving at the
|
||||
* transition. If this value is zero, it means that no daylight
|
||||
* saving, not the index value zero.</li>
|
||||
* <li>The least significant 4-bit field is an index value to
|
||||
* {@link #offsets offsets[]} for <em>total</em> GMT offset at the
|
||||
* transition.</li>
|
||||
* </ul>
|
||||
* If this time zone doesn't observe daylight saving time and has
|
||||
* never changed any GMT offsets in the past, this value is null.
|
||||
* @serial
|
||||
*/
|
||||
private long[] transitions;
|
||||
|
||||
/**
|
||||
* This array holds all unique offset values in
|
||||
* milliseconds. Index values to this array are stored in the
|
||||
* transitions array elements.
|
||||
* @serial
|
||||
*/
|
||||
private int[] offsets;
|
||||
|
||||
/**
|
||||
* SimpleTimeZone parameter values. It has to have either 8 for
|
||||
* {@link java.util.SimpleTimeZone#SimpleTimeZone(int, String,
|
||||
* int, int , int , int , int , int , int , int , int) the
|
||||
* 11-argument SimpleTimeZone constructor} or 10 for {@link
|
||||
* java.util.SimpleTimeZone#SimpleTimeZone(int, String, int, int,
|
||||
* int , int , int , int , int , int , int, int, int) the
|
||||
* 13-argument SimpleTimeZone constructor} parameters.
|
||||
* @serial
|
||||
*/
|
||||
private int[] simpleTimeZoneParams;
|
||||
|
||||
/**
|
||||
* True if the raw GMT offset value would change after the time
|
||||
* zone data has been generated; false, otherwise. The default
|
||||
* value is false.
|
||||
* @serial
|
||||
*/
|
||||
private boolean willGMTOffsetChange = false;
|
||||
|
||||
/**
|
||||
* True if the object has been modified after its instantiation.
|
||||
*/
|
||||
transient private boolean dirty = false;
|
||||
|
||||
private static final long serialVersionUID = 2653134537216586139L;
|
||||
|
||||
/**
|
||||
* A constructor.
|
||||
*/
|
||||
public ZoneInfo() {
|
||||
}
|
||||
|
||||
/**
|
||||
* A Constructor for CustomID.
|
||||
*/
|
||||
public ZoneInfo(String ID, int rawOffset) {
|
||||
this(ID, rawOffset, 0, 0, null, null, null, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a ZoneInfo instance.
|
||||
*
|
||||
* @param ID time zone name
|
||||
* @param rawOffset GMT offset in milliseconds
|
||||
* @param dstSavings daylight saving value in milliseconds or 0
|
||||
* (zero) if this time zone doesn't observe Daylight Saving Time.
|
||||
* @param checksum CRC32 value with all transitions table entry
|
||||
* values
|
||||
* @param transitions transition table
|
||||
* @param offsets offset value table
|
||||
* @param simpleTimeZoneParams parameter values for constructing
|
||||
* SimpleTimeZone
|
||||
* @param willGMTOffsetChange the value of willGMTOffsetChange
|
||||
*/
|
||||
ZoneInfo(String ID,
|
||||
int rawOffset,
|
||||
int dstSavings,
|
||||
int checksum,
|
||||
long[] transitions,
|
||||
int[] offsets,
|
||||
int[] simpleTimeZoneParams,
|
||||
boolean willGMTOffsetChange) {
|
||||
setID(ID);
|
||||
this.rawOffset = rawOffset;
|
||||
this.dstSavings = dstSavings;
|
||||
this.checksum = checksum;
|
||||
this.transitions = transitions;
|
||||
this.offsets = offsets;
|
||||
this.simpleTimeZoneParams = simpleTimeZoneParams;
|
||||
this.willGMTOffsetChange = willGMTOffsetChange;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the difference in milliseconds between local time and UTC
|
||||
* of given time, taking into account both the raw offset and the
|
||||
* effect of daylight savings.
|
||||
*
|
||||
* @param date the milliseconds in UTC
|
||||
* @return the milliseconds to add to UTC to get local wall time
|
||||
*/
|
||||
public int getOffset(long date) {
|
||||
return getOffsets(date, null, UTC_TIME);
|
||||
}
|
||||
|
||||
public int getOffsets(long utc, int[] offsets) {
|
||||
return getOffsets(utc, offsets, UTC_TIME);
|
||||
}
|
||||
|
||||
public int getOffsetsByStandard(long standard, int[] offsets) {
|
||||
return getOffsets(standard, offsets, STANDARD_TIME);
|
||||
}
|
||||
|
||||
public int getOffsetsByWall(long wall, int[] offsets) {
|
||||
return getOffsets(wall, offsets, WALL_TIME);
|
||||
}
|
||||
|
||||
private int getOffsets(long date, int[] offsets, int type) {
|
||||
// if dst is never observed, there is no transition.
|
||||
if (transitions == null) {
|
||||
int offset = getLastRawOffset();
|
||||
if (offsets != null) {
|
||||
offsets[0] = offset;
|
||||
offsets[1] = 0;
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
date -= rawOffsetDiff;
|
||||
int index = getTransitionIndex(date, type);
|
||||
|
||||
// prior to the transition table, returns the raw offset.
|
||||
// FIXME: should support LMT.
|
||||
if (index < 0) {
|
||||
int offset = getLastRawOffset();
|
||||
if (offsets != null) {
|
||||
offsets[0] = offset;
|
||||
offsets[1] = 0;
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
if (index < transitions.length) {
|
||||
long val = transitions[index];
|
||||
int offset = this.offsets[(int)(val & OFFSET_MASK)] + rawOffsetDiff;
|
||||
if (offsets != null) {
|
||||
int dst = (int)((val >>> DST_NSHIFT) & 0xfL);
|
||||
int save = (dst == 0) ? 0 : this.offsets[dst];
|
||||
offsets[0] = offset - save;
|
||||
offsets[1] = save;
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
// beyond the transitions, delegate to SimpleTimeZone if there
|
||||
// is a rule; otherwise, return rawOffset.
|
||||
SimpleTimeZone tz = getLastRule();
|
||||
if (tz != null) {
|
||||
int rawoffset = tz.getRawOffset();
|
||||
long msec = date;
|
||||
if (type != UTC_TIME) {
|
||||
msec -= rawOffset;
|
||||
}
|
||||
int dstoffset = tz.getOffset(msec) - rawOffset;
|
||||
|
||||
// Check if it's in a standard-to-daylight transition.
|
||||
if (dstoffset > 0 && tz.getOffset(msec - dstoffset) == rawoffset && type == WALL_TIME) {
|
||||
dstoffset = 0;
|
||||
}
|
||||
|
||||
if (offsets != null) {
|
||||
offsets[0] = rawoffset;
|
||||
offsets[1] = dstoffset;
|
||||
}
|
||||
return rawoffset + dstoffset;
|
||||
}
|
||||
int offset = getLastRawOffset();
|
||||
if (offsets != null) {
|
||||
offsets[0] = offset;
|
||||
offsets[1] = 0;
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
private int getTransitionIndex(long date, int type) {
|
||||
int low = 0;
|
||||
int high = transitions.length - 1;
|
||||
|
||||
while (low <= high) {
|
||||
int mid = (low + high) / 2;
|
||||
long val = transitions[mid];
|
||||
long midVal = val >> TRANSITION_NSHIFT; // sign extended
|
||||
if (type != UTC_TIME) {
|
||||
midVal += offsets[(int)(val & OFFSET_MASK)]; // wall time
|
||||
}
|
||||
if (type == STANDARD_TIME) {
|
||||
int dstIndex = (int)((val >>> DST_NSHIFT) & 0xfL);
|
||||
if (dstIndex != 0) {
|
||||
midVal -= offsets[dstIndex]; // make it standard time
|
||||
}
|
||||
}
|
||||
|
||||
if (midVal < date) {
|
||||
low = mid + 1;
|
||||
} else if (midVal > date) {
|
||||
high = mid - 1;
|
||||
} else {
|
||||
return mid;
|
||||
}
|
||||
}
|
||||
|
||||
// if beyond the transitions, returns that index.
|
||||
if (low >= transitions.length) {
|
||||
return low;
|
||||
}
|
||||
return low - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the difference in milliseconds between local time and
|
||||
* UTC, taking into account both the raw offset and the effect of
|
||||
* daylight savings, for the specified date and time. This method
|
||||
* assumes that the start and end month are distinct. This method
|
||||
* assumes a Gregorian calendar for calculations.
|
||||
* <p>
|
||||
* <em>Note: In general, clients should use
|
||||
* {@link Calendar#ZONE_OFFSET Calendar.get(ZONE_OFFSET)} +
|
||||
* {@link Calendar#DST_OFFSET Calendar.get(DST_OFFSET)}
|
||||
* instead of calling this method.</em>
|
||||
*
|
||||
* @param era The era of the given date. The value must be either
|
||||
* GregorianCalendar.AD or GregorianCalendar.BC.
|
||||
* @param year The year in the given date.
|
||||
* @param month The month in the given date. Month is 0-based. e.g.,
|
||||
* 0 for January.
|
||||
* @param day The day-in-month of the given date.
|
||||
* @param dayOfWeek The day-of-week of the given date.
|
||||
* @param millis The milliseconds in day in <em>standard</em> local time.
|
||||
* @return The milliseconds to add to UTC to get local time.
|
||||
*/
|
||||
public int getOffset(int era, int year, int month, int day,
|
||||
int dayOfWeek, int milliseconds) {
|
||||
if (milliseconds < 0 || milliseconds >= AbstractCalendar.DAY_IN_MILLIS) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
if (era == java.util.GregorianCalendar.BC) { // BC
|
||||
year = 1 - year;
|
||||
} else if (era != java.util.GregorianCalendar.AD) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
CalendarDate date = gcal.newCalendarDate(null);
|
||||
date.setDate(year, month + 1, day);
|
||||
if (gcal.validate(date) == false) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
// bug-for-bug compatible argument checking
|
||||
if (dayOfWeek < java.util.GregorianCalendar.SUNDAY
|
||||
|| dayOfWeek > java.util.GregorianCalendar.SATURDAY) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
if (transitions == null) {
|
||||
return getLastRawOffset();
|
||||
}
|
||||
|
||||
long dateInMillis = gcal.getTime(date) + milliseconds;
|
||||
dateInMillis -= (long) rawOffset; // make it UTC
|
||||
return getOffsets(dateInMillis, null, UTC_TIME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the base time zone offset from GMT. This operation
|
||||
* modifies all the transitions of this ZoneInfo object, including
|
||||
* historical ones, if applicable.
|
||||
*
|
||||
* @param offsetMillis the base time zone offset to GMT.
|
||||
* @see getRawOffset
|
||||
*/
|
||||
public synchronized void setRawOffset(int offsetMillis) {
|
||||
if (offsetMillis == rawOffset + rawOffsetDiff) {
|
||||
return;
|
||||
}
|
||||
rawOffsetDiff = offsetMillis - rawOffset;
|
||||
if (lastRule != null) {
|
||||
lastRule.setRawOffset(offsetMillis);
|
||||
}
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the GMT offset of the current date. This GMT offset
|
||||
* value is not modified during Daylight Saving Time.
|
||||
*
|
||||
* @return the GMT offset value in milliseconds to add to UTC time
|
||||
* to get local standard time
|
||||
*/
|
||||
public int getRawOffset() {
|
||||
if (!willGMTOffsetChange) {
|
||||
return rawOffset + rawOffsetDiff;
|
||||
}
|
||||
|
||||
int[] offsets = new int[2];
|
||||
getOffsets(System.currentTimeMillis(), offsets, UTC_TIME);
|
||||
return offsets[0];
|
||||
}
|
||||
|
||||
public boolean isDirty() {
|
||||
return dirty;
|
||||
}
|
||||
|
||||
private int getLastRawOffset() {
|
||||
return rawOffset + rawOffsetDiff;
|
||||
}
|
||||
|
||||
/**
|
||||
* Queries if this time zone uses Daylight Saving Time in the last known rule.
|
||||
*/
|
||||
public boolean useDaylightTime() {
|
||||
return (simpleTimeZoneParams != null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean observesDaylightTime() {
|
||||
if (simpleTimeZoneParams != null) {
|
||||
return true;
|
||||
}
|
||||
if (transitions == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Look up the transition table to see if it's in DST right
|
||||
// now or if there's any standard-to-daylight transition at
|
||||
// any future.
|
||||
long utc = System.currentTimeMillis() - rawOffsetDiff;
|
||||
int index = getTransitionIndex(utc, UTC_TIME);
|
||||
|
||||
// before transitions in the transition table
|
||||
if (index < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// the time is in the table range.
|
||||
for (int i = index; i < transitions.length; i++) {
|
||||
if ((transitions[i] & DST_MASK) != 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// No further DST is observed.
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Queries if the specified date is in Daylight Saving Time.
|
||||
*/
|
||||
public boolean inDaylightTime(Date date) {
|
||||
if (date == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
|
||||
if (transitions == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
long utc = date.getTime() - rawOffsetDiff;
|
||||
int index = getTransitionIndex(utc, UTC_TIME);
|
||||
|
||||
// before transitions in the transition table
|
||||
if (index < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// the time is in the table range.
|
||||
if (index < transitions.length) {
|
||||
return (transitions[index] & DST_MASK) != 0;
|
||||
}
|
||||
|
||||
// beyond the transition table
|
||||
SimpleTimeZone tz = getLastRule();
|
||||
if (tz != null) {
|
||||
return tz.inDaylightTime(date);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the amount of time in milliseconds that the clock is advanced
|
||||
* during daylight saving time is in effect in its last daylight saving time rule.
|
||||
*
|
||||
* @return the number of milliseconds the time is advanced with respect to
|
||||
* standard time when daylight saving time is in effect.
|
||||
*/
|
||||
public int getDSTSavings() {
|
||||
return dstSavings;
|
||||
}
|
||||
|
||||
// /**
|
||||
// * @return the last year in the transition table or -1 if this
|
||||
// * time zone doesn't observe any daylight saving time.
|
||||
// */
|
||||
// public int getMaxTransitionYear() {
|
||||
// if (transitions == null) {
|
||||
// return -1;
|
||||
// }
|
||||
// long val = transitions[transitions.length - 1];
|
||||
// int offset = this.offsets[(int)(val & OFFSET_MASK)] + rawOffsetDiff;
|
||||
// val = (val >> TRANSITION_NSHIFT) + offset;
|
||||
// CalendarDate lastDate = Gregorian.getCalendarDate(val);
|
||||
// return lastDate.getYear();
|
||||
// }
|
||||
|
||||
/**
|
||||
* Returns a string representation of this time zone.
|
||||
* @return the string
|
||||
*/
|
||||
public String toString() {
|
||||
return getClass().getName() +
|
||||
"[id=\"" + getID() + "\"" +
|
||||
",offset=" + getLastRawOffset() +
|
||||
",dstSavings=" + dstSavings +
|
||||
",useDaylight=" + useDaylightTime() +
|
||||
",transitions=" + ((transitions != null) ? transitions.length : 0) +
|
||||
",lastRule=" + (lastRule == null ? getLastRuleInstance() : lastRule) +
|
||||
"]";
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all available IDs supported in the Java run-time.
|
||||
*
|
||||
* @return an array of time zone IDs.
|
||||
*/
|
||||
public static String[] getAvailableIDs() {
|
||||
return ZoneInfoFile.getZoneIds();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all available IDs that have the same value as the
|
||||
* specified raw GMT offset.
|
||||
*
|
||||
* @param rawOffset the GMT offset in milliseconds. This
|
||||
* value should not include any daylight saving time.
|
||||
*
|
||||
* @return an array of time zone IDs.
|
||||
*/
|
||||
public static String[] getAvailableIDs(int rawOffset) {
|
||||
return ZoneInfoFile.getZoneIds(rawOffset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the ZoneInfo for the given ID.
|
||||
*
|
||||
* @param ID the ID for a ZoneInfo. See TimeZone for detail.
|
||||
*
|
||||
* @return the specified ZoneInfo object, or null if there is no
|
||||
* time zone of the ID.
|
||||
*/
|
||||
public static TimeZone getTimeZone(String ID) {
|
||||
return ZoneInfoFile.getZoneInfo(ID);
|
||||
}
|
||||
|
||||
private transient SimpleTimeZone lastRule;
|
||||
|
||||
/**
|
||||
* Returns a SimpleTimeZone object representing the last GMT
|
||||
* offset and DST schedule or null if this time zone doesn't
|
||||
* observe DST.
|
||||
*/
|
||||
private synchronized SimpleTimeZone getLastRule() {
|
||||
if (lastRule == null) {
|
||||
lastRule = getLastRuleInstance();
|
||||
}
|
||||
return lastRule;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a SimpleTimeZone object that represents the last
|
||||
* known daylight saving time rules.
|
||||
*
|
||||
* @return a SimpleTimeZone object or null if this time zone
|
||||
* doesn't observe DST.
|
||||
*/
|
||||
public SimpleTimeZone getLastRuleInstance() {
|
||||
if (simpleTimeZoneParams == null) {
|
||||
return null;
|
||||
}
|
||||
if (simpleTimeZoneParams.length == 10) {
|
||||
return new SimpleTimeZone(getLastRawOffset(), getID(),
|
||||
simpleTimeZoneParams[0],
|
||||
simpleTimeZoneParams[1],
|
||||
simpleTimeZoneParams[2],
|
||||
simpleTimeZoneParams[3],
|
||||
simpleTimeZoneParams[4],
|
||||
simpleTimeZoneParams[5],
|
||||
simpleTimeZoneParams[6],
|
||||
simpleTimeZoneParams[7],
|
||||
simpleTimeZoneParams[8],
|
||||
simpleTimeZoneParams[9],
|
||||
dstSavings);
|
||||
}
|
||||
return new SimpleTimeZone(getLastRawOffset(), getID(),
|
||||
simpleTimeZoneParams[0],
|
||||
simpleTimeZoneParams[1],
|
||||
simpleTimeZoneParams[2],
|
||||
simpleTimeZoneParams[3],
|
||||
simpleTimeZoneParams[4],
|
||||
simpleTimeZoneParams[5],
|
||||
simpleTimeZoneParams[6],
|
||||
simpleTimeZoneParams[7],
|
||||
dstSavings);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of this <code>ZoneInfo</code>.
|
||||
*/
|
||||
public Object clone() {
|
||||
ZoneInfo zi = (ZoneInfo) super.clone();
|
||||
zi.lastRule = null;
|
||||
return zi;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a hash code value calculated from the GMT offset and
|
||||
* transitions.
|
||||
* @return a hash code of this time zone
|
||||
*/
|
||||
public int hashCode() {
|
||||
return getLastRawOffset() ^ checksum;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares the equity of two ZoneInfo objects.
|
||||
*
|
||||
* @param obj the object to be compared with
|
||||
* @return true if given object is same as this ZoneInfo object,
|
||||
* false otherwise.
|
||||
*/
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (!(obj instanceof ZoneInfo)) {
|
||||
return false;
|
||||
}
|
||||
ZoneInfo that = (ZoneInfo) obj;
|
||||
return (getID().equals(that.getID())
|
||||
&& (getLastRawOffset() == that.getLastRawOffset())
|
||||
&& (checksum == that.checksum));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this zone has the same raw GMT offset value and
|
||||
* transition table as another zone info. If the specified
|
||||
* TimeZone object is not a ZoneInfo instance, this method returns
|
||||
* true if the specified TimeZone object has the same raw GMT
|
||||
* offset value with no daylight saving time.
|
||||
*
|
||||
* @param other the ZoneInfo object to be compared with
|
||||
* @return true if the given <code>TimeZone</code> has the same
|
||||
* GMT offset and transition information; false, otherwise.
|
||||
*/
|
||||
public boolean hasSameRules(TimeZone other) {
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
if (other == null) {
|
||||
return false;
|
||||
}
|
||||
if (!(other instanceof ZoneInfo)) {
|
||||
if (getRawOffset() != other.getRawOffset()) {
|
||||
return false;
|
||||
}
|
||||
// if both have the same raw offset and neither observes
|
||||
// DST, they have the same rule.
|
||||
if ((transitions == null)
|
||||
&& (useDaylightTime() == false)
|
||||
&& (other.useDaylightTime() == false)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (getLastRawOffset() != ((ZoneInfo)other).getLastRawOffset()) {
|
||||
return false;
|
||||
}
|
||||
return (checksum == ((ZoneInfo)other).checksum);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a Map from alias time zone IDs to their standard
|
||||
* time zone IDs.
|
||||
*
|
||||
* @return the Map that holds the mappings from alias time zone IDs
|
||||
* to their standard time zone IDs, or null if
|
||||
* <code>ZoneInfoMappings</code> file is not available.
|
||||
*/
|
||||
public static Map<String, String> getAliasTable() {
|
||||
return ZoneInfoFile.getAliasMap();
|
||||
}
|
||||
|
||||
private void readObject(ObjectInputStream stream)
|
||||
throws IOException, ClassNotFoundException {
|
||||
stream.defaultReadObject();
|
||||
// We don't know how this object from 1.4.x or earlier has
|
||||
// been mutated. So it should always be marked as `dirty'.
|
||||
dirty = true;
|
||||
}
|
||||
}
|
||||
1007
jdkSrc/jdk8/sun/util/calendar/ZoneInfoFile.java
Normal file
1007
jdkSrc/jdk8/sun/util/calendar/ZoneInfoFile.java
Normal file
File diff suppressed because it is too large
Load Diff
49
jdkSrc/jdk8/sun/util/cldr/CLDRLocaleDataMetaInfo.java
Normal file
49
jdkSrc/jdk8/sun/util/cldr/CLDRLocaleDataMetaInfo.java
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.util.cldr;
|
||||
|
||||
import java.util.ListResourceBundle;
|
||||
|
||||
public class CLDRLocaleDataMetaInfo extends ListResourceBundle {
|
||||
@Override
|
||||
protected final Object[][] getContents() {
|
||||
final Object[][] data = new Object[][] {
|
||||
{ "All",
|
||||
"aa aa-DJ aa-ER aa-ET af af-NA af-ZA agq agq-CM ak ak-GH am am-ET ar ar-AE ar-BH ar-DZ ar-EG ar-IQ ar-JO ar-KW ar-LB ar-LY ar-MA ar-OM ar-QA ar-SA ar-SD ar-SY ar-TN ar-YE as as-IN asa asa-TZ az az-Cyrl az-Cyrl-AZ az-Latn-AZ bas bas-CM be be-BY bem bem-ZM bez bez-TZ bg bg-BG bm bm-ML bn bn-BD bn-IN bo bo-CN bo-IN br br-FR brx brx-IN bs bs-BA byn byn-ER ca ca-ES cgg cgg-UG chr chr-US cs cs-CZ cy cy-GB da da-DK dav dav-KE de de-AT de-BE de-CH de-DE de-LI de-LU dje dje-NE dua dua-CM dyo dyo-SN dz dz-BT ebu ebu-KE ee ee-GH ee-TG el el-CY el-GR en en-AS en-AU en-BB en-BE en-BM en-BW en-BZ en-CA en-Dsrt en-Dsrt-US en-GB en-GU en-GY en-HK en-IE en-IN en-JM en-MH en-MP en-MT en-MU en-NA en-NZ en-PH en-PK en-SG en-TT en-UM en-US en-US-POSIX en-VI en-ZA en-ZW eo es es-419 es-AR es-BO es-CL es-CO es-CR es-DO es-EC es-ES es-GQ es-GT es-HN es-MX es-NI es-PA es-PE es-PR es-PY es-SV es-US es-UY es-VE et et-EE eu eu-ES ewo ewo-CM fa fa-AF fa-IR ff ff-SN fi fi-FI fil fil-PH fo fo-FO fr fr-BE fr-BF fr-BI fr-BJ fr-BL fr-CA fr-CD fr-CF fr-CG fr-CH fr-CI fr-CM fr-DJ fr-FR fr-GA fr-GF fr-GN fr-GP fr-GQ fr-KM fr-LU fr-MC fr-MF fr-MG fr-ML fr-MQ fr-NE fr-RE fr-RW fr-SN fr-TD fr-TG fr-YT fur fur-IT ga ga-IE gd gd-GB gl gl-ES gsw gsw-CH gu gu-IN guz guz-KE gv gv-GB ha ha-Latn-GH ha-Latn-NE ha-Latn-NG haw haw-US he he-IL hi hi-IN hr hr-HR hu hu-HU hy hy-AM ia id id-ID ig ig-NG ii ii-CN is is-IS it it-CH it-IT ja ja-JP jmc jmc-TZ ka ka-GE kab kab-DZ kam kam-KE kde kde-TZ kea kea-CV khq khq-ML ki ki-KE kk kk-Cyrl-KZ kl kl-GL kln kln-KE km km-KH kn kn-IN ko ko-KR kok kok-IN ksb ksb-TZ ksf ksf-CM ksh ksh-DE kw kw-GB lag lag-TZ lg lg-UG ln ln-CD ln-CG lo lo-LA lt lt-LT lu lu-CD luo luo-KE luy luy-KE lv lv-LV mas mas-KE mas-TZ mer mer-KE mfe mfe-MU mg mg-MG mgh mgh-MZ mk mk-MK ml ml-IN mr mr-IN ms ms-BN ms-MY mt mt-MT mua mua-CM my my-MM naq naq-NA nb nb-NO nd nd-ZW ne ne-IN ne-NP nl nl-AW nl-BE nl-CW nl-NL nl-SX nmg nmg-CM nn nn-NO nr nr-ZA nso nso-ZA nus nus-SD nyn nyn-UG om om-ET om-KE or or-IN pa pa-Arab pa-Arab-PK pa-Guru-IN pl pl-PL ps ps-AF pt pt-AO pt-BR pt-GW pt-MZ pt-PT pt-ST rm rm-CH rn rn-BI ro ro-MD ro-RO rof rof-TZ ru ru-MD ru-RU ru-UA rw rw-RW rwk rwk-TZ sah sah-RU saq saq-KE sbp sbp-TZ se se-FI se-NO seh seh-MZ ses ses-ML sg sg-CF shi shi-Latn-MA shi-Tfng shi-Tfng-MA si si-LK sk sk-SK sl sl-SI sn sn-ZW so so-DJ so-ET so-KE so-SO sq sq-AL sr sr-Cyrl-BA sr-Cyrl-ME sr-Cyrl-RS sr-Latn sr-Latn-BA sr-Latn-ME sr-Latn-RS ss ss-SZ ss-ZA ssy ssy-ER st st-LS st-ZA sv sv-FI sv-SE sw sw-KE sw-TZ swc swc-CD ta ta-IN ta-LK te te-IN teo teo-KE teo-UG tg tg-Cyrl-TJ th th-TH ti ti-ER ti-ET tig tig-ER tn tn-ZA to to-TO tr tr-TR ts ts-ZA twq twq-NE tzm tzm-Latn-MA uk uk-UA ur ur-IN ur-PK uz uz-Arab uz-Arab-AF uz-Cyrl-UZ uz-Latn uz-Latn-UZ vai vai-Latn vai-Latn-LR vai-Vaii-LR ve ve-ZA vi vi-VN vun vun-TZ wae wae-CH wal wal-ET xh xh-ZA xog xog-UG yav yav-CM yo yo-NG zh zh-Hans-CN zh-Hans-HK zh-Hans-MO zh-Hans-SG zh-Hant zh-Hant-HK zh-Hant-MO zh-Hant-TW zu zu-ZA" },
|
||||
{ "CurrencyNames",
|
||||
"aa aa-DJ aa-ER af af-NA agq ak am ar asa az az-Cyrl bas be bem bez bg bm bn bo br brx bs byn ca cgg chr cs cy da dav de de-LU dje dyo dz ebu ee el en en-AU en-BB en-BM en-BW en-BZ en-CA en-HK en-JM en-MT en-NA en-NZ en-PH en-PK en-SG en-TT en-ZA es es-AR es-BO es-CL es-CO es-CR es-DO es-EC es-GT es-HN es-MX es-NI es-PA es-PE es-PR es-PY es-US es-UY es-VE et eu ewo fa fa-AF ff fi fil fo fr fr-BI fr-CA fr-DJ fr-GN fr-KM fr-LU ga gl gsw gu guz ha he hi hr hu hy id ig ii is it ja jmc ka kab kam kde kea khq ki kk kl kln km kn ko ksb ksf lag lg ln lo lt lu luo luy lv mas mas-TZ mer mfe mg mgh mk ml mr ms ms-BN mt mua my naq nb nd ne ne-IN nl nl-AW nl-CW nl-SX nmg nn nr nso nyn om om-KE or pa pa-Arab pl ps pt pt-AO pt-MZ pt-PT pt-ST rm rn ro rof ru rw rwk saq sbp se seh ses sg shi shi-Tfng si sk sl sn so so-DJ so-ET so-KE sq sr sr-Cyrl-BA sr-Latn ss ssy st st-LS sv sw swc ta ta-LK te teo teo-KE th ti ti-ER tig tn to tr ts twq tzm uk ur uz-Arab vai vai-Latn ve vi vun wal xh xog yav yo zh zh-Hans-HK zh-Hans-MO zh-Hans-SG zh-Hant zh-Hant-HK zu" },
|
||||
{ "CalendarData",
|
||||
"aa-DJ aa-ER aa-ET af-NA af-ZA agq-CM ak-GH am-ET ar-AE ar-BH ar-DZ ar-EG ar-IQ ar-JO ar-KW ar-LB ar-LY ar-MA ar-OM ar-QA ar-SA ar-SD ar-SY ar-TN ar-YE as-IN asa-TZ az-Cyrl-AZ az-Latn-AZ bas-CM be-BY bem-ZM bez-TZ bg-BG bm-ML bn-BD bn-IN bo-CN bo-IN br-FR brx-IN bs-BA byn-ER ca-ES cgg-UG chr-US cs-CZ cy-GB da-DK dav-KE de-AT de-BE de-CH de-DE de-LI de-LU dje-NE dua-CM dyo-SN dz-BT ebu-KE ee-GH ee-TG el-CY el-GR en-AS en-AU en-BB en-BE en-BM en-BW en-BZ en-CA en-Dsrt-US en-GB en-GU en-GY en-HK en-IE en-IN en-JM en-MH en-MP en-MT en-MU en-NA en-NZ en-PH en-PK en-SG en-TT en-UM en-US en-US-POSIX en-VI en-ZA en-ZW es-AR es-BO es-CL es-CO es-CR es-DO es-EC es-ES es-GQ es-GT es-HN es-MX es-NI es-PA es-PE es-PR es-PY es-SV es-US es-UY es-VE et-EE eu-ES ewo-CM fa-AF fa-IR ff-SN fi-FI fil-PH fo-FO fr-BE fr-BF fr-BI fr-BJ fr-BL fr-CA fr-CD fr-CF fr-CG fr-CH fr-CI fr-CM fr-DJ fr-FR fr-GA fr-GF fr-GN fr-GP fr-GQ fr-KM fr-LU fr-MC fr-MF fr-MG fr-ML fr-MQ fr-NE fr-RE fr-RW fr-SN fr-TD fr-TG fr-YT fur-IT ga-IE gd-GB gl-ES gsw-CH gu-IN guz-KE gv-GB ha-Latn-GH ha-Latn-NE ha-Latn-NG haw-US he-IL hi-IN hr-HR hu-HU hy-AM id-ID ig-NG ii-CN is-IS it-CH it-IT ja-JP jmc-TZ ka-GE kab-DZ kam-KE kde-TZ kea-CV khq-ML ki-KE kk-Cyrl-KZ kl-GL kln-KE km-KH kn-IN ko-KR kok-IN ksb-TZ ksf-CM ksh-DE kw-GB lag-TZ lg-UG ln-CD ln-CG lo-LA lt-LT lu-CD luo-KE luy-KE lv-LV mas-KE mas-TZ mer-KE mfe-MU mg-MG mgh-MZ mk-MK ml-IN mr-IN ms-BN ms-MY mt-MT mua-CM my-MM naq-NA nb-NO nd-ZW ne-IN ne-NP nl-AW nl-BE nl-CW nl-NL nl-SX nmg-CM nn-NO nr-ZA nso-ZA nus-SD nyn-UG om-ET om-KE or-IN pa-Arab-PK pa-Guru-IN pl-PL ps-AF pt-AO pt-BR pt-GW pt-MZ pt-PT pt-ST rm-CH rn-BI ro-MD ro-RO rof-TZ ru-MD ru-RU ru-UA rw-RW rwk-TZ sah-RU saq-KE sbp-TZ se-FI se-NO seh-MZ ses-ML sg-CF shi-Latn-MA shi-Tfng-MA si-LK sk-SK sl-SI sn-ZW so-DJ so-ET so-KE so-SO sq-AL sr-Cyrl-BA sr-Cyrl-ME sr-Cyrl-RS sr-Latn-BA sr-Latn-ME sr-Latn-RS ss-SZ ss-ZA ssy-ER st-LS st-ZA sv-FI sv-SE sw-KE sw-TZ swc-CD ta-IN ta-LK te-IN teo-KE teo-UG tg-Cyrl-TJ th-TH ti-ER ti-ET tig-ER tn-ZA to-TO tr-TR ts-ZA twq-NE tzm-Latn-MA uk-UA ur-IN ur-PK uz-Arab-AF uz-Cyrl-UZ uz-Latn-UZ vai-Latn-LR vai-Vaii-LR ve-ZA vi-VN vun-TZ wae-CH wal-ET xh-ZA xog-UG yav-CM yo-NG zh-Hans-CN zh-Hans-HK zh-Hans-MO zh-Hans-SG zh-Hant-HK zh-Hant-MO zh-Hant-TW zu-ZA" },
|
||||
{ "FormatData",
|
||||
"aa af af-NA agq ak am ar ar-DZ ar-JO ar-LB ar-MA ar-QA ar-SA ar-SY ar-TN ar-YE as asa az az-Cyrl bas be bem bez bg bm bn bn-IN bo br brx bs byn ca cgg chr cs cy da dav de de-AT de-CH de-LI dje dua dyo dz ebu ee el el-CY en en-AU en-BE en-BW en-BZ en-CA en-Dsrt en-GB en-HK en-IE en-IN en-JM en-MT en-NA en-NZ en-PK en-SG en-TT en-US-POSIX en-ZA en-ZW eo es es-419 es-AR es-BO es-CL es-CO es-CR es-EC es-GQ es-GT es-HN es-PA es-PE es-PR es-PY es-US es-UY es-VE et eu ewo fa fa-AF ff fi fil fo fr fr-BE fr-CA fr-CH fr-LU fur ga gd gl gsw gu guz gv ha haw he hi hr hu hy ia id ig ii is it it-CH ja jmc ka kab kam kde kea khq ki kk kl kln km kn ko kok ksb ksf ksh kw lag lg ln lo lt lu luo luy lv mas mer mfe mg mgh mk ml mr ms ms-BN mt mua my naq nb nd ne ne-IN nl nl-BE nmg nn nr nso nus nyn om or pa pa-Arab pl ps pt pt-PT rm rn ro rof ru ru-UA rw rwk saq sbp se seh ses sg shi shi-Tfng si sk sl sn so sq sr sr-Cyrl-BA sr-Latn sr-Latn-ME ss ssy st sv sv-FI sw sw-KE swc ta te teo th ti ti-ER tig tn to tr ts twq tzm uk ur ur-IN uz uz-Arab uz-Latn vai vai-Latn ve vi vun wae wal xh xog yav yo zh zh-Hans-HK zh-Hans-MO zh-Hans-SG zh-Hant zh-Hant-HK zh-Hant-MO zu" },
|
||||
{ "LocaleNames",
|
||||
"af agq ak am ar as asa az az-Cyrl bas be bem bez bg bm bn bn-IN bo br brx bs ca cgg chr cs cy da dav de de-CH dje dua dyo ebu ee el en en-Dsrt eo es es-CL et eu ewo fa fa-AF ff fi fil fo fr ga gl gsw gu guz gv ha haw he hi hr hu hy id ig ii is it ja jmc ka kab kam kde kea khq ki kk kl kln km kn ko kok ksb ksf kw lag lg ln lt lu luo luy lv mas mer mfe mg mgh mk ml mr ms mt mua my naq nb nd ne nl nl-BE nmg nn nus nyn om or pa pa-Arab pl ps pt pt-PT rm rn ro rof ru ru-UA rw rwk sah saq sbp se seh ses sg shi shi-Tfng si sk sl sn so sq sr sr-Latn st sv sw swc ta te teo tg th ti to tr twq tzm uk ur uz uz-Arab uz-Latn vai vai-Latn vi vun wae xog yav yo zh zh-Hans-HK zh-Hans-MO zh-Hans-SG zh-Hant zh-Hant-HK zu" },
|
||||
{ "TimeZoneNames",
|
||||
"af am ar as az be bg bn brx bs ca chr cs da de ee el en en-AU en-CA en-Dsrt en-GB en-GU en-HK en-IE en-IN en-NZ en-PK en-SG en-ZA en-ZW es es-419 es-AR et eu fa fi fil fr fr-CA ga gl gsw gu he hi hr hu id is it ja kea kk kn ko kok ksh lt lv mk ml mr ms mt my nb ne nl nn or pa pl pt pt-PT ro ru sk sl sq sr sr-Latn sv sw ta te th to tr uk ur vi zh zh-Hant zu" },
|
||||
};
|
||||
return data;
|
||||
}
|
||||
}
|
||||
117
jdkSrc/jdk8/sun/util/cldr/CLDRLocaleProviderAdapter.java
Normal file
117
jdkSrc/jdk8/sun/util/cldr/CLDRLocaleProviderAdapter.java
Normal file
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.util.cldr;
|
||||
|
||||
import java.io.File;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.text.spi.BreakIteratorProvider;
|
||||
import java.text.spi.CollatorProvider;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Locale;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.Set;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.spi.TimeZoneNameProvider;
|
||||
import sun.util.locale.provider.JRELocaleProviderAdapter;
|
||||
import sun.util.locale.provider.LocaleProviderAdapter;
|
||||
|
||||
/**
|
||||
* LocaleProviderAdapter implementation for the CLDR locale data.
|
||||
*
|
||||
* @author Masayoshi Okutsu
|
||||
* @author Naoto Sato
|
||||
*/
|
||||
public class CLDRLocaleProviderAdapter extends JRELocaleProviderAdapter {
|
||||
private static final String LOCALE_DATA_JAR_NAME = "cldrdata.jar";
|
||||
|
||||
public CLDRLocaleProviderAdapter() {
|
||||
final String sep = File.separator;
|
||||
String localeDataJar = java.security.AccessController.doPrivileged(
|
||||
new sun.security.action.GetPropertyAction("java.home"))
|
||||
+ sep + "lib" + sep + "ext" + sep + LOCALE_DATA_JAR_NAME;
|
||||
|
||||
// Peek at the installed extension directory to see if the jar file for
|
||||
// CLDR resources is installed or not.
|
||||
final File f = new File(localeDataJar);
|
||||
boolean result = AccessController.doPrivileged(
|
||||
new PrivilegedAction<Boolean>() {
|
||||
@Override
|
||||
public Boolean run() {
|
||||
return f.exists();
|
||||
}
|
||||
});
|
||||
if (!result) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type of this LocaleProviderAdapter
|
||||
* @return the type of this
|
||||
*/
|
||||
@Override
|
||||
public LocaleProviderAdapter.Type getAdapterType() {
|
||||
return LocaleProviderAdapter.Type.CLDR;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BreakIteratorProvider getBreakIteratorProvider() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CollatorProvider getCollatorProvider() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Locale[] getAvailableLocales() {
|
||||
Set<String> all = createLanguageTagSet("All");
|
||||
Locale[] locs = new Locale[all.size()];
|
||||
int index = 0;
|
||||
for (String tag : all) {
|
||||
locs[index++] = Locale.forLanguageTag(tag);
|
||||
}
|
||||
return locs;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Set<String> createLanguageTagSet(String category) {
|
||||
ResourceBundle rb = ResourceBundle.getBundle("sun.util.cldr.CLDRLocaleDataMetaInfo", Locale.ROOT);
|
||||
String supportedLocaleString = rb.getString(category);
|
||||
if (supportedLocaleString == null) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
Set<String> tagset = new HashSet<>();
|
||||
StringTokenizer tokens = new StringTokenizer(supportedLocaleString);
|
||||
while (tokens.hasMoreTokens()) {
|
||||
tagset.add(tokens.nextToken());
|
||||
}
|
||||
return tagset;
|
||||
}
|
||||
}
|
||||
208
jdkSrc/jdk8/sun/util/locale/AsciiUtil.java
Normal file
208
jdkSrc/jdk8/sun/util/locale/AsciiUtil.java
Normal file
@@ -0,0 +1,208 @@
|
||||
/*
|
||||
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2009, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*/
|
||||
package sun.util.locale;
|
||||
|
||||
public final class AsciiUtil {
|
||||
public static boolean caseIgnoreMatch(String s1, String s2) {
|
||||
if (s1 == s2) {
|
||||
return true;
|
||||
}
|
||||
int len = s1.length();
|
||||
if (len != s2.length()) {
|
||||
return false;
|
||||
}
|
||||
int i = 0;
|
||||
while (i < len) {
|
||||
char c1 = s1.charAt(i);
|
||||
char c2 = s2.charAt(i);
|
||||
if (c1 != c2 && toLower(c1) != toLower(c2)) {
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return (i == len);
|
||||
}
|
||||
|
||||
public static int caseIgnoreCompare(String s1, String s2) {
|
||||
if (s1 == s2) {
|
||||
return 0;
|
||||
}
|
||||
return AsciiUtil.toLowerString(s1).compareTo(AsciiUtil.toLowerString(s2));
|
||||
}
|
||||
|
||||
|
||||
public static char toUpper(char c) {
|
||||
if (c >= 'a' && c <= 'z') {
|
||||
c -= 0x20;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
public static char toLower(char c) {
|
||||
if (c >= 'A' && c <= 'Z') {
|
||||
c += 0x20;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
public static String toLowerString(String s) {
|
||||
int idx = 0;
|
||||
for (; idx < s.length(); idx++) {
|
||||
char c = s.charAt(idx);
|
||||
if (c >= 'A' && c <= 'Z') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (idx == s.length()) {
|
||||
return s;
|
||||
}
|
||||
StringBuilder buf = new StringBuilder(s.substring(0, idx));
|
||||
for (; idx < s.length(); idx++) {
|
||||
buf.append(toLower(s.charAt(idx)));
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
public static String toUpperString(String s) {
|
||||
int idx = 0;
|
||||
for (; idx < s.length(); idx++) {
|
||||
char c = s.charAt(idx);
|
||||
if (c >= 'a' && c <= 'z') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (idx == s.length()) {
|
||||
return s;
|
||||
}
|
||||
StringBuilder buf = new StringBuilder(s.substring(0, idx));
|
||||
for (; idx < s.length(); idx++) {
|
||||
buf.append(toUpper(s.charAt(idx)));
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
public static String toTitleString(String s) {
|
||||
if (s.length() == 0) {
|
||||
return s;
|
||||
}
|
||||
int idx = 0;
|
||||
char c = s.charAt(idx);
|
||||
if (!(c >= 'a' && c <= 'z')) {
|
||||
for (idx = 1; idx < s.length(); idx++) {
|
||||
if (c >= 'A' && c <= 'Z') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (idx == s.length()) {
|
||||
return s;
|
||||
}
|
||||
StringBuilder buf = new StringBuilder(s.substring(0, idx));
|
||||
if (idx == 0) {
|
||||
buf.append(toUpper(s.charAt(idx)));
|
||||
idx++;
|
||||
}
|
||||
for (; idx < s.length(); idx++) {
|
||||
buf.append(toLower(s.charAt(idx)));
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
public static boolean isAlpha(char c) {
|
||||
return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
|
||||
}
|
||||
|
||||
public static boolean isAlphaString(String s) {
|
||||
boolean b = true;
|
||||
for (int i = 0; i < s.length(); i++) {
|
||||
if (!isAlpha(s.charAt(i))) {
|
||||
b = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
public static boolean isNumeric(char c) {
|
||||
return (c >= '0' && c <= '9');
|
||||
}
|
||||
|
||||
public static boolean isNumericString(String s) {
|
||||
boolean b = true;
|
||||
for (int i = 0; i < s.length(); i++) {
|
||||
if (!isNumeric(s.charAt(i))) {
|
||||
b = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
public static boolean isAlphaNumeric(char c) {
|
||||
return isAlpha(c) || isNumeric(c);
|
||||
}
|
||||
|
||||
public static boolean isAlphaNumericString(String s) {
|
||||
boolean b = true;
|
||||
for (int i = 0; i < s.length(); i++) {
|
||||
if (!isAlphaNumeric(s.charAt(i))) {
|
||||
b = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
public static class CaseInsensitiveKey {
|
||||
private String _key;
|
||||
private int _hash;
|
||||
|
||||
public CaseInsensitiveKey(String key) {
|
||||
_key = key;
|
||||
_hash = AsciiUtil.toLowerString(key).hashCode();
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o instanceof CaseInsensitiveKey) {
|
||||
return AsciiUtil.caseIgnoreMatch(_key, ((CaseInsensitiveKey)o)._key);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return _hash;
|
||||
}
|
||||
}
|
||||
}
|
||||
315
jdkSrc/jdk8/sun/util/locale/BaseLocale.java
Normal file
315
jdkSrc/jdk8/sun/util/locale/BaseLocale.java
Normal file
@@ -0,0 +1,315 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2009-2010, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*/
|
||||
|
||||
package sun.util.locale;
|
||||
import java.lang.ref.SoftReference;
|
||||
|
||||
|
||||
public final class BaseLocale {
|
||||
|
||||
public static final String SEP = "_";
|
||||
|
||||
private static final Cache CACHE = new Cache();
|
||||
|
||||
private final String language;
|
||||
private final String script;
|
||||
private final String region;
|
||||
private final String variant;
|
||||
|
||||
private volatile int hash = 0;
|
||||
|
||||
// This method must be called only when creating the Locale.* constants.
|
||||
private BaseLocale(String language, String region) {
|
||||
this.language = language;
|
||||
this.script = "";
|
||||
this.region = region;
|
||||
this.variant = "";
|
||||
}
|
||||
|
||||
private BaseLocale(String language, String script, String region, String variant) {
|
||||
this.language = (language != null) ? LocaleUtils.toLowerString(language).intern() : "";
|
||||
this.script = (script != null) ? LocaleUtils.toTitleString(script).intern() : "";
|
||||
this.region = (region != null) ? LocaleUtils.toUpperString(region).intern() : "";
|
||||
this.variant = (variant != null) ? variant.intern() : "";
|
||||
}
|
||||
|
||||
// Called for creating the Locale.* constants. No argument
|
||||
// validation is performed.
|
||||
public static BaseLocale createInstance(String language, String region) {
|
||||
BaseLocale base = new BaseLocale(language, region);
|
||||
CACHE.put(new Key(language, region), base);
|
||||
return base;
|
||||
}
|
||||
|
||||
public static BaseLocale getInstance(String language, String script,
|
||||
String region, String variant) {
|
||||
// JDK uses deprecated ISO639.1 language codes for he, yi and id
|
||||
if (language != null) {
|
||||
if (LocaleUtils.caseIgnoreMatch(language, "he")) {
|
||||
language = "iw";
|
||||
} else if (LocaleUtils.caseIgnoreMatch(language, "yi")) {
|
||||
language = "ji";
|
||||
} else if (LocaleUtils.caseIgnoreMatch(language, "id")) {
|
||||
language = "in";
|
||||
}
|
||||
}
|
||||
|
||||
Key key = new Key(language, script, region, variant);
|
||||
BaseLocale baseLocale = CACHE.get(key);
|
||||
return baseLocale;
|
||||
}
|
||||
|
||||
public String getLanguage() {
|
||||
return language;
|
||||
}
|
||||
|
||||
public String getScript() {
|
||||
return script;
|
||||
}
|
||||
|
||||
public String getRegion() {
|
||||
return region;
|
||||
}
|
||||
|
||||
public String getVariant() {
|
||||
return variant;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (!(obj instanceof BaseLocale)) {
|
||||
return false;
|
||||
}
|
||||
BaseLocale other = (BaseLocale)obj;
|
||||
return language == other.language
|
||||
&& script == other.script
|
||||
&& region == other.region
|
||||
&& variant == other.variant;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder buf = new StringBuilder();
|
||||
if (language.length() > 0) {
|
||||
buf.append("language=");
|
||||
buf.append(language);
|
||||
}
|
||||
if (script.length() > 0) {
|
||||
if (buf.length() > 0) {
|
||||
buf.append(", ");
|
||||
}
|
||||
buf.append("script=");
|
||||
buf.append(script);
|
||||
}
|
||||
if (region.length() > 0) {
|
||||
if (buf.length() > 0) {
|
||||
buf.append(", ");
|
||||
}
|
||||
buf.append("region=");
|
||||
buf.append(region);
|
||||
}
|
||||
if (variant.length() > 0) {
|
||||
if (buf.length() > 0) {
|
||||
buf.append(", ");
|
||||
}
|
||||
buf.append("variant=");
|
||||
buf.append(variant);
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int h = hash;
|
||||
if (h == 0) {
|
||||
// Generating a hash value from language, script, region and variant
|
||||
h = language.hashCode();
|
||||
h = 31 * h + script.hashCode();
|
||||
h = 31 * h + region.hashCode();
|
||||
h = 31 * h + variant.hashCode();
|
||||
hash = h;
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
private static final class Key {
|
||||
private final SoftReference<String> lang;
|
||||
private final SoftReference<String> scrt;
|
||||
private final SoftReference<String> regn;
|
||||
private final SoftReference<String> vart;
|
||||
private final boolean normalized;
|
||||
private final int hash;
|
||||
|
||||
/**
|
||||
* Creates a Key. language and region must be normalized
|
||||
* (intern'ed in the proper case).
|
||||
*/
|
||||
private Key(String language, String region) {
|
||||
assert language.intern() == language
|
||||
&& region.intern() == region;
|
||||
|
||||
lang = new SoftReference(language);
|
||||
scrt = new SoftReference("");
|
||||
regn = new SoftReference(region);
|
||||
vart = new SoftReference("");
|
||||
this.normalized = true;
|
||||
|
||||
int h = language.hashCode();
|
||||
if (region != "") {
|
||||
int len = region.length();
|
||||
for (int i = 0; i < len; i++) {
|
||||
h = 31 * h + LocaleUtils.toLower(region.charAt(i));
|
||||
}
|
||||
}
|
||||
hash = h;
|
||||
}
|
||||
|
||||
public Key(String language, String script, String region, String variant) {
|
||||
this(language, script, region, variant, false);
|
||||
}
|
||||
|
||||
private Key(String language, String script, String region,
|
||||
String variant, boolean normalized) {
|
||||
int h = 0;
|
||||
if (language != null) {
|
||||
lang = new SoftReference(language);
|
||||
int len = language.length();
|
||||
for (int i = 0; i < len; i++) {
|
||||
h = 31*h + LocaleUtils.toLower(language.charAt(i));
|
||||
}
|
||||
} else {
|
||||
lang = new SoftReference("");
|
||||
}
|
||||
if (script != null) {
|
||||
scrt = new SoftReference(script);
|
||||
int len = script.length();
|
||||
for (int i = 0; i < len; i++) {
|
||||
h = 31*h + LocaleUtils.toLower(script.charAt(i));
|
||||
}
|
||||
} else {
|
||||
scrt = new SoftReference("");
|
||||
}
|
||||
if (region != null) {
|
||||
regn = new SoftReference(region);
|
||||
int len = region.length();
|
||||
for (int i = 0; i < len; i++) {
|
||||
h = 31*h + LocaleUtils.toLower(region.charAt(i));
|
||||
}
|
||||
} else {
|
||||
regn = new SoftReference("");
|
||||
}
|
||||
if (variant != null) {
|
||||
vart = new SoftReference(variant);
|
||||
int len = variant.length();
|
||||
for (int i = 0; i < len; i++) {
|
||||
h = 31*h + variant.charAt(i);
|
||||
}
|
||||
} else {
|
||||
vart = new SoftReference("");
|
||||
}
|
||||
hash = h;
|
||||
this.normalized = normalized;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (obj instanceof Key && this.hash == ((Key)obj).hash) {
|
||||
String tl = this.lang.get();
|
||||
String ol = ((Key)obj).lang.get();
|
||||
if (tl != null && ol != null &&
|
||||
LocaleUtils.caseIgnoreMatch(ol, tl)) {
|
||||
String ts = this.scrt.get();
|
||||
String os = ((Key)obj).scrt.get();
|
||||
if (ts != null && os != null &&
|
||||
LocaleUtils.caseIgnoreMatch(os, ts)) {
|
||||
String tr = this.regn.get();
|
||||
String or = ((Key)obj).regn.get();
|
||||
if (tr != null && or != null &&
|
||||
LocaleUtils.caseIgnoreMatch(or, tr)) {
|
||||
String tv = this.vart.get();
|
||||
String ov = ((Key)obj).vart.get();
|
||||
return (ov != null && ov.equals(tv));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return hash;
|
||||
}
|
||||
|
||||
public static Key normalize(Key key) {
|
||||
if (key.normalized) {
|
||||
return key;
|
||||
}
|
||||
|
||||
String lang = LocaleUtils.toLowerString(key.lang.get()).intern();
|
||||
String scrt = LocaleUtils.toTitleString(key.scrt.get()).intern();
|
||||
String regn = LocaleUtils.toUpperString(key.regn.get()).intern();
|
||||
String vart = key.vart.get().intern(); // preserve upper/lower cases
|
||||
|
||||
return new Key(lang, scrt, regn, vart, true);
|
||||
}
|
||||
}
|
||||
|
||||
private static class Cache extends LocaleObjectCache<Key, BaseLocale> {
|
||||
|
||||
public Cache() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Key normalizeKey(Key key) {
|
||||
assert key.lang.get() != null &&
|
||||
key.scrt.get() != null &&
|
||||
key.regn.get() != null &&
|
||||
key.vart.get() != null;
|
||||
|
||||
return Key.normalize(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BaseLocale createObject(Key key) {
|
||||
return new BaseLocale(key.lang.get(), key.scrt.get(),
|
||||
key.regn.get(), key.vart.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
68
jdkSrc/jdk8/sun/util/locale/Extension.java
Normal file
68
jdkSrc/jdk8/sun/util/locale/Extension.java
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2009-2010, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*/
|
||||
package sun.util.locale;
|
||||
|
||||
|
||||
class Extension {
|
||||
private final char key;
|
||||
private String value, id;
|
||||
|
||||
protected Extension(char key) {
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
Extension(char key, String value) {
|
||||
this.key = key;
|
||||
setValue(value);
|
||||
}
|
||||
|
||||
protected void setValue(String value) {
|
||||
this.value = value;
|
||||
this.id = key + LanguageTag.SEP + value;
|
||||
}
|
||||
|
||||
public char getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public String getID() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return getID();
|
||||
}
|
||||
}
|
||||
731
jdkSrc/jdk8/sun/util/locale/InternalLocaleBuilder.java
Normal file
731
jdkSrc/jdk8/sun/util/locale/InternalLocaleBuilder.java
Normal file
@@ -0,0 +1,731 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2009-2010, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*/
|
||||
package sun.util.locale;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public final class InternalLocaleBuilder {
|
||||
|
||||
private static final CaseInsensitiveChar PRIVATEUSE_KEY
|
||||
= new CaseInsensitiveChar(LanguageTag.PRIVATEUSE);
|
||||
|
||||
private String language = "";
|
||||
private String script = "";
|
||||
private String region = "";
|
||||
private String variant = "";
|
||||
|
||||
private Map<CaseInsensitiveChar, String> extensions;
|
||||
private Set<CaseInsensitiveString> uattributes;
|
||||
private Map<CaseInsensitiveString, String> ukeywords;
|
||||
|
||||
|
||||
public InternalLocaleBuilder() {
|
||||
}
|
||||
|
||||
public InternalLocaleBuilder setLanguage(String language) throws LocaleSyntaxException {
|
||||
if (LocaleUtils.isEmpty(language)) {
|
||||
this.language = "";
|
||||
} else {
|
||||
if (!LanguageTag.isLanguage(language)) {
|
||||
throw new LocaleSyntaxException("Ill-formed language: " + language, 0);
|
||||
}
|
||||
this.language = language;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public InternalLocaleBuilder setScript(String script) throws LocaleSyntaxException {
|
||||
if (LocaleUtils.isEmpty(script)) {
|
||||
this.script = "";
|
||||
} else {
|
||||
if (!LanguageTag.isScript(script)) {
|
||||
throw new LocaleSyntaxException("Ill-formed script: " + script, 0);
|
||||
}
|
||||
this.script = script;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public InternalLocaleBuilder setRegion(String region) throws LocaleSyntaxException {
|
||||
if (LocaleUtils.isEmpty(region)) {
|
||||
this.region = "";
|
||||
} else {
|
||||
if (!LanguageTag.isRegion(region)) {
|
||||
throw new LocaleSyntaxException("Ill-formed region: " + region, 0);
|
||||
}
|
||||
this.region = region;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public InternalLocaleBuilder setVariant(String variant) throws LocaleSyntaxException {
|
||||
if (LocaleUtils.isEmpty(variant)) {
|
||||
this.variant = "";
|
||||
} else {
|
||||
// normalize separators to "_"
|
||||
String var = variant.replaceAll(LanguageTag.SEP, BaseLocale.SEP);
|
||||
int errIdx = checkVariants(var, BaseLocale.SEP);
|
||||
if (errIdx != -1) {
|
||||
throw new LocaleSyntaxException("Ill-formed variant: " + variant, errIdx);
|
||||
}
|
||||
this.variant = var;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public InternalLocaleBuilder addUnicodeLocaleAttribute(String attribute) throws LocaleSyntaxException {
|
||||
if (!UnicodeLocaleExtension.isAttribute(attribute)) {
|
||||
throw new LocaleSyntaxException("Ill-formed Unicode locale attribute: " + attribute);
|
||||
}
|
||||
// Use case insensitive string to prevent duplication
|
||||
if (uattributes == null) {
|
||||
uattributes = new HashSet<>(4);
|
||||
}
|
||||
uattributes.add(new CaseInsensitiveString(attribute));
|
||||
return this;
|
||||
}
|
||||
|
||||
public InternalLocaleBuilder removeUnicodeLocaleAttribute(String attribute) throws LocaleSyntaxException {
|
||||
if (attribute == null || !UnicodeLocaleExtension.isAttribute(attribute)) {
|
||||
throw new LocaleSyntaxException("Ill-formed Unicode locale attribute: " + attribute);
|
||||
}
|
||||
if (uattributes != null) {
|
||||
uattributes.remove(new CaseInsensitiveString(attribute));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public InternalLocaleBuilder setUnicodeLocaleKeyword(String key, String type) throws LocaleSyntaxException {
|
||||
if (!UnicodeLocaleExtension.isKey(key)) {
|
||||
throw new LocaleSyntaxException("Ill-formed Unicode locale keyword key: " + key);
|
||||
}
|
||||
|
||||
CaseInsensitiveString cikey = new CaseInsensitiveString(key);
|
||||
if (type == null) {
|
||||
if (ukeywords != null) {
|
||||
// null type is used for remove the key
|
||||
ukeywords.remove(cikey);
|
||||
}
|
||||
} else {
|
||||
if (type.length() != 0) {
|
||||
// normalize separator to "-"
|
||||
String tp = type.replaceAll(BaseLocale.SEP, LanguageTag.SEP);
|
||||
// validate
|
||||
StringTokenIterator itr = new StringTokenIterator(tp, LanguageTag.SEP);
|
||||
while (!itr.isDone()) {
|
||||
String s = itr.current();
|
||||
if (!UnicodeLocaleExtension.isTypeSubtag(s)) {
|
||||
throw new LocaleSyntaxException("Ill-formed Unicode locale keyword type: "
|
||||
+ type,
|
||||
itr.currentStart());
|
||||
}
|
||||
itr.next();
|
||||
}
|
||||
}
|
||||
if (ukeywords == null) {
|
||||
ukeywords = new HashMap<>(4);
|
||||
}
|
||||
ukeywords.put(cikey, type);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public InternalLocaleBuilder setExtension(char singleton, String value) throws LocaleSyntaxException {
|
||||
// validate key
|
||||
boolean isBcpPrivateuse = LanguageTag.isPrivateusePrefixChar(singleton);
|
||||
if (!isBcpPrivateuse && !LanguageTag.isExtensionSingletonChar(singleton)) {
|
||||
throw new LocaleSyntaxException("Ill-formed extension key: " + singleton);
|
||||
}
|
||||
|
||||
boolean remove = LocaleUtils.isEmpty(value);
|
||||
CaseInsensitiveChar key = new CaseInsensitiveChar(singleton);
|
||||
|
||||
if (remove) {
|
||||
if (UnicodeLocaleExtension.isSingletonChar(key.value())) {
|
||||
// clear entire Unicode locale extension
|
||||
if (uattributes != null) {
|
||||
uattributes.clear();
|
||||
}
|
||||
if (ukeywords != null) {
|
||||
ukeywords.clear();
|
||||
}
|
||||
} else {
|
||||
if (extensions != null && extensions.containsKey(key)) {
|
||||
extensions.remove(key);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// validate value
|
||||
String val = value.replaceAll(BaseLocale.SEP, LanguageTag.SEP);
|
||||
StringTokenIterator itr = new StringTokenIterator(val, LanguageTag.SEP);
|
||||
while (!itr.isDone()) {
|
||||
String s = itr.current();
|
||||
boolean validSubtag;
|
||||
if (isBcpPrivateuse) {
|
||||
validSubtag = LanguageTag.isPrivateuseSubtag(s);
|
||||
} else {
|
||||
validSubtag = LanguageTag.isExtensionSubtag(s);
|
||||
}
|
||||
if (!validSubtag) {
|
||||
throw new LocaleSyntaxException("Ill-formed extension value: " + s,
|
||||
itr.currentStart());
|
||||
}
|
||||
itr.next();
|
||||
}
|
||||
|
||||
if (UnicodeLocaleExtension.isSingletonChar(key.value())) {
|
||||
setUnicodeLocaleExtension(val);
|
||||
} else {
|
||||
if (extensions == null) {
|
||||
extensions = new HashMap<>(4);
|
||||
}
|
||||
extensions.put(key, val);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set extension/private subtags in a single string representation
|
||||
*/
|
||||
public InternalLocaleBuilder setExtensions(String subtags) throws LocaleSyntaxException {
|
||||
if (LocaleUtils.isEmpty(subtags)) {
|
||||
clearExtensions();
|
||||
return this;
|
||||
}
|
||||
subtags = subtags.replaceAll(BaseLocale.SEP, LanguageTag.SEP);
|
||||
StringTokenIterator itr = new StringTokenIterator(subtags, LanguageTag.SEP);
|
||||
|
||||
List<String> extensions = null;
|
||||
String privateuse = null;
|
||||
|
||||
int parsed = 0;
|
||||
int start;
|
||||
|
||||
// Make a list of extension subtags
|
||||
while (!itr.isDone()) {
|
||||
String s = itr.current();
|
||||
if (LanguageTag.isExtensionSingleton(s)) {
|
||||
start = itr.currentStart();
|
||||
String singleton = s;
|
||||
StringBuilder sb = new StringBuilder(singleton);
|
||||
|
||||
itr.next();
|
||||
while (!itr.isDone()) {
|
||||
s = itr.current();
|
||||
if (LanguageTag.isExtensionSubtag(s)) {
|
||||
sb.append(LanguageTag.SEP).append(s);
|
||||
parsed = itr.currentEnd();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
itr.next();
|
||||
}
|
||||
|
||||
if (parsed < start) {
|
||||
throw new LocaleSyntaxException("Incomplete extension '" + singleton + "'",
|
||||
start);
|
||||
}
|
||||
|
||||
if (extensions == null) {
|
||||
extensions = new ArrayList<>(4);
|
||||
}
|
||||
extensions.add(sb.toString());
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!itr.isDone()) {
|
||||
String s = itr.current();
|
||||
if (LanguageTag.isPrivateusePrefix(s)) {
|
||||
start = itr.currentStart();
|
||||
StringBuilder sb = new StringBuilder(s);
|
||||
|
||||
itr.next();
|
||||
while (!itr.isDone()) {
|
||||
s = itr.current();
|
||||
if (!LanguageTag.isPrivateuseSubtag(s)) {
|
||||
break;
|
||||
}
|
||||
sb.append(LanguageTag.SEP).append(s);
|
||||
parsed = itr.currentEnd();
|
||||
|
||||
itr.next();
|
||||
}
|
||||
if (parsed <= start) {
|
||||
throw new LocaleSyntaxException("Incomplete privateuse:"
|
||||
+ subtags.substring(start),
|
||||
start);
|
||||
} else {
|
||||
privateuse = sb.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!itr.isDone()) {
|
||||
throw new LocaleSyntaxException("Ill-formed extension subtags:"
|
||||
+ subtags.substring(itr.currentStart()),
|
||||
itr.currentStart());
|
||||
}
|
||||
|
||||
return setExtensions(extensions, privateuse);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set a list of BCP47 extensions and private use subtags
|
||||
* BCP47 extensions are already validated and well-formed, but may contain duplicates
|
||||
*/
|
||||
private InternalLocaleBuilder setExtensions(List<String> bcpExtensions, String privateuse) {
|
||||
clearExtensions();
|
||||
|
||||
if (!LocaleUtils.isEmpty(bcpExtensions)) {
|
||||
Set<CaseInsensitiveChar> done = new HashSet<>(bcpExtensions.size());
|
||||
for (String bcpExt : bcpExtensions) {
|
||||
CaseInsensitiveChar key = new CaseInsensitiveChar(bcpExt);
|
||||
// ignore duplicates
|
||||
if (!done.contains(key)) {
|
||||
// each extension string contains singleton, e.g. "a-abc-def"
|
||||
if (UnicodeLocaleExtension.isSingletonChar(key.value())) {
|
||||
setUnicodeLocaleExtension(bcpExt.substring(2));
|
||||
} else {
|
||||
if (extensions == null) {
|
||||
extensions = new HashMap<>(4);
|
||||
}
|
||||
extensions.put(key, bcpExt.substring(2));
|
||||
}
|
||||
}
|
||||
done.add(key);
|
||||
}
|
||||
}
|
||||
if (privateuse != null && privateuse.length() > 0) {
|
||||
// privateuse string contains prefix, e.g. "x-abc-def"
|
||||
if (extensions == null) {
|
||||
extensions = new HashMap<>(1);
|
||||
}
|
||||
extensions.put(new CaseInsensitiveChar(privateuse), privateuse.substring(2));
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset Builder's internal state with the given language tag
|
||||
*/
|
||||
public InternalLocaleBuilder setLanguageTag(LanguageTag langtag) {
|
||||
clear();
|
||||
if (!langtag.getExtlangs().isEmpty()) {
|
||||
language = langtag.getExtlangs().get(0);
|
||||
} else {
|
||||
String lang = langtag.getLanguage();
|
||||
if (!lang.equals(LanguageTag.UNDETERMINED)) {
|
||||
language = lang;
|
||||
}
|
||||
}
|
||||
script = langtag.getScript();
|
||||
region = langtag.getRegion();
|
||||
|
||||
List<String> bcpVariants = langtag.getVariants();
|
||||
if (!bcpVariants.isEmpty()) {
|
||||
StringBuilder var = new StringBuilder(bcpVariants.get(0));
|
||||
int size = bcpVariants.size();
|
||||
for (int i = 1; i < size; i++) {
|
||||
var.append(BaseLocale.SEP).append(bcpVariants.get(i));
|
||||
}
|
||||
variant = var.toString();
|
||||
}
|
||||
|
||||
setExtensions(langtag.getExtensions(), langtag.getPrivateuse());
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public InternalLocaleBuilder setLocale(BaseLocale base, LocaleExtensions localeExtensions) throws LocaleSyntaxException {
|
||||
String language = base.getLanguage();
|
||||
String script = base.getScript();
|
||||
String region = base.getRegion();
|
||||
String variant = base.getVariant();
|
||||
|
||||
// Special backward compatibility support
|
||||
|
||||
// Exception 1 - ja_JP_JP
|
||||
if (language.equals("ja") && region.equals("JP") && variant.equals("JP")) {
|
||||
// When locale ja_JP_JP is created, ca-japanese is always there.
|
||||
// The builder ignores the variant "JP"
|
||||
assert("japanese".equals(localeExtensions.getUnicodeLocaleType("ca")));
|
||||
variant = "";
|
||||
}
|
||||
// Exception 2 - th_TH_TH
|
||||
else if (language.equals("th") && region.equals("TH") && variant.equals("TH")) {
|
||||
// When locale th_TH_TH is created, nu-thai is always there.
|
||||
// The builder ignores the variant "TH"
|
||||
assert("thai".equals(localeExtensions.getUnicodeLocaleType("nu")));
|
||||
variant = "";
|
||||
}
|
||||
// Exception 3 - no_NO_NY
|
||||
else if (language.equals("no") && region.equals("NO") && variant.equals("NY")) {
|
||||
// no_NO_NY is a valid locale and used by Java 6 or older versions.
|
||||
// The build ignores the variant "NY" and change the language to "nn".
|
||||
language = "nn";
|
||||
variant = "";
|
||||
}
|
||||
|
||||
// Validate base locale fields before updating internal state.
|
||||
// LocaleExtensions always store validated/canonicalized values,
|
||||
// so no checks are necessary.
|
||||
if (language.length() > 0 && !LanguageTag.isLanguage(language)) {
|
||||
throw new LocaleSyntaxException("Ill-formed language: " + language);
|
||||
}
|
||||
|
||||
if (script.length() > 0 && !LanguageTag.isScript(script)) {
|
||||
throw new LocaleSyntaxException("Ill-formed script: " + script);
|
||||
}
|
||||
|
||||
if (region.length() > 0 && !LanguageTag.isRegion(region)) {
|
||||
throw new LocaleSyntaxException("Ill-formed region: " + region);
|
||||
}
|
||||
|
||||
if (variant.length() > 0) {
|
||||
int errIdx = checkVariants(variant, BaseLocale.SEP);
|
||||
if (errIdx != -1) {
|
||||
throw new LocaleSyntaxException("Ill-formed variant: " + variant, errIdx);
|
||||
}
|
||||
}
|
||||
|
||||
// The input locale is validated at this point.
|
||||
// Now, updating builder's internal fields.
|
||||
this.language = language;
|
||||
this.script = script;
|
||||
this.region = region;
|
||||
this.variant = variant;
|
||||
clearExtensions();
|
||||
|
||||
Set<Character> extKeys = (localeExtensions == null) ? null : localeExtensions.getKeys();
|
||||
if (extKeys != null) {
|
||||
// map localeExtensions back to builder's internal format
|
||||
for (Character key : extKeys) {
|
||||
Extension e = localeExtensions.getExtension(key);
|
||||
if (e instanceof UnicodeLocaleExtension) {
|
||||
UnicodeLocaleExtension ue = (UnicodeLocaleExtension)e;
|
||||
for (String uatr : ue.getUnicodeLocaleAttributes()) {
|
||||
if (uattributes == null) {
|
||||
uattributes = new HashSet<>(4);
|
||||
}
|
||||
uattributes.add(new CaseInsensitiveString(uatr));
|
||||
}
|
||||
for (String ukey : ue.getUnicodeLocaleKeys()) {
|
||||
if (ukeywords == null) {
|
||||
ukeywords = new HashMap<>(4);
|
||||
}
|
||||
ukeywords.put(new CaseInsensitiveString(ukey), ue.getUnicodeLocaleType(ukey));
|
||||
}
|
||||
} else {
|
||||
if (extensions == null) {
|
||||
extensions = new HashMap<>(4);
|
||||
}
|
||||
extensions.put(new CaseInsensitiveChar(key), e.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public InternalLocaleBuilder clear() {
|
||||
language = "";
|
||||
script = "";
|
||||
region = "";
|
||||
variant = "";
|
||||
clearExtensions();
|
||||
return this;
|
||||
}
|
||||
|
||||
public InternalLocaleBuilder clearExtensions() {
|
||||
if (extensions != null) {
|
||||
extensions.clear();
|
||||
}
|
||||
if (uattributes != null) {
|
||||
uattributes.clear();
|
||||
}
|
||||
if (ukeywords != null) {
|
||||
ukeywords.clear();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public BaseLocale getBaseLocale() {
|
||||
String language = this.language;
|
||||
String script = this.script;
|
||||
String region = this.region;
|
||||
String variant = this.variant;
|
||||
|
||||
// Special private use subtag sequence identified by "lvariant" will be
|
||||
// interpreted as Java variant.
|
||||
if (extensions != null) {
|
||||
String privuse = extensions.get(PRIVATEUSE_KEY);
|
||||
if (privuse != null) {
|
||||
StringTokenIterator itr = new StringTokenIterator(privuse, LanguageTag.SEP);
|
||||
boolean sawPrefix = false;
|
||||
int privVarStart = -1;
|
||||
while (!itr.isDone()) {
|
||||
if (sawPrefix) {
|
||||
privVarStart = itr.currentStart();
|
||||
break;
|
||||
}
|
||||
if (LocaleUtils.caseIgnoreMatch(itr.current(), LanguageTag.PRIVUSE_VARIANT_PREFIX)) {
|
||||
sawPrefix = true;
|
||||
}
|
||||
itr.next();
|
||||
}
|
||||
if (privVarStart != -1) {
|
||||
StringBuilder sb = new StringBuilder(variant);
|
||||
if (sb.length() != 0) {
|
||||
sb.append(BaseLocale.SEP);
|
||||
}
|
||||
sb.append(privuse.substring(privVarStart).replaceAll(LanguageTag.SEP,
|
||||
BaseLocale.SEP));
|
||||
variant = sb.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return BaseLocale.getInstance(language, script, region, variant);
|
||||
}
|
||||
|
||||
public LocaleExtensions getLocaleExtensions() {
|
||||
if (LocaleUtils.isEmpty(extensions) && LocaleUtils.isEmpty(uattributes)
|
||||
&& LocaleUtils.isEmpty(ukeywords)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
LocaleExtensions lext = new LocaleExtensions(extensions, uattributes, ukeywords);
|
||||
return lext.isEmpty() ? null : lext;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove special private use subtag sequence identified by "lvariant"
|
||||
* and return the rest. Only used by LocaleExtensions
|
||||
*/
|
||||
static String removePrivateuseVariant(String privuseVal) {
|
||||
StringTokenIterator itr = new StringTokenIterator(privuseVal, LanguageTag.SEP);
|
||||
|
||||
// Note: privateuse value "abc-lvariant" is unchanged
|
||||
// because no subtags after "lvariant".
|
||||
|
||||
int prefixStart = -1;
|
||||
boolean sawPrivuseVar = false;
|
||||
while (!itr.isDone()) {
|
||||
if (prefixStart != -1) {
|
||||
// Note: privateuse value "abc-lvariant" is unchanged
|
||||
// because no subtags after "lvariant".
|
||||
sawPrivuseVar = true;
|
||||
break;
|
||||
}
|
||||
if (LocaleUtils.caseIgnoreMatch(itr.current(), LanguageTag.PRIVUSE_VARIANT_PREFIX)) {
|
||||
prefixStart = itr.currentStart();
|
||||
}
|
||||
itr.next();
|
||||
}
|
||||
if (!sawPrivuseVar) {
|
||||
return privuseVal;
|
||||
}
|
||||
|
||||
assert(prefixStart == 0 || prefixStart > 1);
|
||||
return (prefixStart == 0) ? null : privuseVal.substring(0, prefixStart -1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the given variant subtags separated by the given
|
||||
* separator(s) are valid
|
||||
*/
|
||||
private int checkVariants(String variants, String sep) {
|
||||
StringTokenIterator itr = new StringTokenIterator(variants, sep);
|
||||
while (!itr.isDone()) {
|
||||
String s = itr.current();
|
||||
if (!LanguageTag.isVariant(s)) {
|
||||
return itr.currentStart();
|
||||
}
|
||||
itr.next();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Private methods parsing Unicode Locale Extension subtags.
|
||||
* Duplicated attributes/keywords will be ignored.
|
||||
* The input must be a valid extension subtags (excluding singleton).
|
||||
*/
|
||||
private void setUnicodeLocaleExtension(String subtags) {
|
||||
// wipe out existing attributes/keywords
|
||||
if (uattributes != null) {
|
||||
uattributes.clear();
|
||||
}
|
||||
if (ukeywords != null) {
|
||||
ukeywords.clear();
|
||||
}
|
||||
|
||||
StringTokenIterator itr = new StringTokenIterator(subtags, LanguageTag.SEP);
|
||||
|
||||
// parse attributes
|
||||
while (!itr.isDone()) {
|
||||
if (!UnicodeLocaleExtension.isAttribute(itr.current())) {
|
||||
break;
|
||||
}
|
||||
if (uattributes == null) {
|
||||
uattributes = new HashSet<>(4);
|
||||
}
|
||||
uattributes.add(new CaseInsensitiveString(itr.current()));
|
||||
itr.next();
|
||||
}
|
||||
|
||||
// parse keywords
|
||||
CaseInsensitiveString key = null;
|
||||
String type;
|
||||
int typeStart = -1;
|
||||
int typeEnd = -1;
|
||||
while (!itr.isDone()) {
|
||||
if (key != null) {
|
||||
if (UnicodeLocaleExtension.isKey(itr.current())) {
|
||||
// next keyword - emit previous one
|
||||
assert(typeStart == -1 || typeEnd != -1);
|
||||
type = (typeStart == -1) ? "" : subtags.substring(typeStart, typeEnd);
|
||||
if (ukeywords == null) {
|
||||
ukeywords = new HashMap<>(4);
|
||||
}
|
||||
ukeywords.put(key, type);
|
||||
|
||||
// reset keyword info
|
||||
CaseInsensitiveString tmpKey = new CaseInsensitiveString(itr.current());
|
||||
key = ukeywords.containsKey(tmpKey) ? null : tmpKey;
|
||||
typeStart = typeEnd = -1;
|
||||
} else {
|
||||
if (typeStart == -1) {
|
||||
typeStart = itr.currentStart();
|
||||
}
|
||||
typeEnd = itr.currentEnd();
|
||||
}
|
||||
} else if (UnicodeLocaleExtension.isKey(itr.current())) {
|
||||
// 1. first keyword or
|
||||
// 2. next keyword, but previous one was duplicate
|
||||
key = new CaseInsensitiveString(itr.current());
|
||||
if (ukeywords != null && ukeywords.containsKey(key)) {
|
||||
// duplicate
|
||||
key = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (!itr.hasNext()) {
|
||||
if (key != null) {
|
||||
// last keyword
|
||||
assert(typeStart == -1 || typeEnd != -1);
|
||||
type = (typeStart == -1) ? "" : subtags.substring(typeStart, typeEnd);
|
||||
if (ukeywords == null) {
|
||||
ukeywords = new HashMap<>(4);
|
||||
}
|
||||
ukeywords.put(key, type);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
itr.next();
|
||||
}
|
||||
}
|
||||
|
||||
static final class CaseInsensitiveString {
|
||||
private final String str, lowerStr;
|
||||
|
||||
CaseInsensitiveString(String s) {
|
||||
str = s;
|
||||
lowerStr = LocaleUtils.toLowerString(s);
|
||||
}
|
||||
|
||||
public String value() {
|
||||
return str;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return lowerStr.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (!(obj instanceof CaseInsensitiveString)) {
|
||||
return false;
|
||||
}
|
||||
return lowerStr.equals(((CaseInsensitiveString)obj).lowerStr);
|
||||
}
|
||||
}
|
||||
|
||||
static final class CaseInsensitiveChar {
|
||||
private final char ch, lowerCh;
|
||||
|
||||
/**
|
||||
* Constructs a CaseInsensitiveChar with the first char of the
|
||||
* given s.
|
||||
*/
|
||||
private CaseInsensitiveChar(String s) {
|
||||
this(s.charAt(0));
|
||||
}
|
||||
|
||||
CaseInsensitiveChar(char c) {
|
||||
ch = c;
|
||||
lowerCh = LocaleUtils.toLower(ch);
|
||||
}
|
||||
|
||||
public char value() {
|
||||
return ch;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return lowerCh;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (!(obj instanceof CaseInsensitiveChar)) {
|
||||
return false;
|
||||
}
|
||||
return lowerCh == ((CaseInsensitiveChar)obj).lowerCh;
|
||||
}
|
||||
}
|
||||
}
|
||||
749
jdkSrc/jdk8/sun/util/locale/LanguageTag.java
Normal file
749
jdkSrc/jdk8/sun/util/locale/LanguageTag.java
Normal file
@@ -0,0 +1,749 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2010, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*/
|
||||
package sun.util.locale;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class LanguageTag {
|
||||
//
|
||||
// static fields
|
||||
//
|
||||
public static final String SEP = "-";
|
||||
public static final String PRIVATEUSE = "x";
|
||||
public static final String UNDETERMINED = "und";
|
||||
public static final String PRIVUSE_VARIANT_PREFIX = "lvariant";
|
||||
|
||||
//
|
||||
// Language subtag fields
|
||||
//
|
||||
private String language = ""; // language subtag
|
||||
private String script = ""; // script subtag
|
||||
private String region = ""; // region subtag
|
||||
private String privateuse = ""; // privateuse
|
||||
|
||||
private List<String> extlangs = Collections.emptyList(); // extlang subtags
|
||||
private List<String> variants = Collections.emptyList(); // variant subtags
|
||||
private List<String> extensions = Collections.emptyList(); // extensions
|
||||
|
||||
// Map contains grandfathered tags and its preferred mappings from
|
||||
// http://www.ietf.org/rfc/rfc5646.txt
|
||||
// Keys are lower-case strings.
|
||||
private static final Map<String, String[]> GRANDFATHERED = new HashMap<>();
|
||||
|
||||
static {
|
||||
// grandfathered = irregular ; non-redundant tags registered
|
||||
// / regular ; during the RFC 3066 era
|
||||
//
|
||||
// irregular = "en-GB-oed" ; irregular tags do not match
|
||||
// / "i-ami" ; the 'langtag' production and
|
||||
// / "i-bnn" ; would not otherwise be
|
||||
// / "i-default" ; considered 'well-formed'
|
||||
// / "i-enochian" ; These tags are all valid,
|
||||
// / "i-hak" ; but most are deprecated
|
||||
// / "i-klingon" ; in favor of more modern
|
||||
// / "i-lux" ; subtags or subtag
|
||||
// / "i-mingo" ; combination
|
||||
// / "i-navajo"
|
||||
// / "i-pwn"
|
||||
// / "i-tao"
|
||||
// / "i-tay"
|
||||
// / "i-tsu"
|
||||
// / "sgn-BE-FR"
|
||||
// / "sgn-BE-NL"
|
||||
// / "sgn-CH-DE"
|
||||
//
|
||||
// regular = "art-lojban" ; these tags match the 'langtag'
|
||||
// / "cel-gaulish" ; production, but their subtags
|
||||
// / "no-bok" ; are not extended language
|
||||
// / "no-nyn" ; or variant subtags: their meaning
|
||||
// / "zh-guoyu" ; is defined by their registration
|
||||
// / "zh-hakka" ; and all of these are deprecated
|
||||
// / "zh-min" ; in favor of a more modern
|
||||
// / "zh-min-nan" ; subtag or sequence of subtags
|
||||
// / "zh-xiang"
|
||||
|
||||
final String[][] entries = {
|
||||
//{"tag", "preferred"},
|
||||
{"art-lojban", "jbo"},
|
||||
{"cel-gaulish", "xtg-x-cel-gaulish"}, // fallback
|
||||
{"en-GB-oed", "en-GB-x-oed"}, // fallback
|
||||
{"i-ami", "ami"},
|
||||
{"i-bnn", "bnn"},
|
||||
{"i-default", "en-x-i-default"}, // fallback
|
||||
{"i-enochian", "und-x-i-enochian"}, // fallback
|
||||
{"i-hak", "hak"},
|
||||
{"i-klingon", "tlh"},
|
||||
{"i-lux", "lb"},
|
||||
{"i-mingo", "see-x-i-mingo"}, // fallback
|
||||
{"i-navajo", "nv"},
|
||||
{"i-pwn", "pwn"},
|
||||
{"i-tao", "tao"},
|
||||
{"i-tay", "tay"},
|
||||
{"i-tsu", "tsu"},
|
||||
{"no-bok", "nb"},
|
||||
{"no-nyn", "nn"},
|
||||
{"sgn-BE-FR", "sfb"},
|
||||
{"sgn-BE-NL", "vgt"},
|
||||
{"sgn-CH-DE", "sgg"},
|
||||
{"zh-guoyu", "cmn"},
|
||||
{"zh-hakka", "hak"},
|
||||
{"zh-min", "nan-x-zh-min"}, // fallback
|
||||
{"zh-min-nan", "nan"},
|
||||
{"zh-xiang", "hsn"},
|
||||
};
|
||||
for (String[] e : entries) {
|
||||
GRANDFATHERED.put(LocaleUtils.toLowerString(e[0]), e);
|
||||
}
|
||||
}
|
||||
|
||||
private LanguageTag() {
|
||||
}
|
||||
|
||||
/*
|
||||
* BNF in RFC5646
|
||||
*
|
||||
* Language-Tag = langtag ; normal language tags
|
||||
* / privateuse ; private use tag
|
||||
* / grandfathered ; grandfathered tags
|
||||
*
|
||||
*
|
||||
* langtag = language
|
||||
* ["-" script]
|
||||
* ["-" region]
|
||||
* *("-" variant)
|
||||
* *("-" extension)
|
||||
* ["-" privateuse]
|
||||
*
|
||||
* language = 2*3ALPHA ; shortest ISO 639 code
|
||||
* ["-" extlang] ; sometimes followed by
|
||||
* ; extended language subtags
|
||||
* / 4ALPHA ; or reserved for future use
|
||||
* / 5*8ALPHA ; or registered language subtag
|
||||
*
|
||||
* extlang = 3ALPHA ; selected ISO 639 codes
|
||||
* *2("-" 3ALPHA) ; permanently reserved
|
||||
*
|
||||
* script = 4ALPHA ; ISO 15924 code
|
||||
*
|
||||
* region = 2ALPHA ; ISO 3166-1 code
|
||||
* / 3DIGIT ; UN M.49 code
|
||||
*
|
||||
* variant = 5*8alphanum ; registered variants
|
||||
* / (DIGIT 3alphanum)
|
||||
*
|
||||
* extension = singleton 1*("-" (2*8alphanum))
|
||||
*
|
||||
* ; Single alphanumerics
|
||||
* ; "x" reserved for private use
|
||||
* singleton = DIGIT ; 0 - 9
|
||||
* / %x41-57 ; A - W
|
||||
* / %x59-5A ; Y - Z
|
||||
* / %x61-77 ; a - w
|
||||
* / %x79-7A ; y - z
|
||||
*
|
||||
* privateuse = "x" 1*("-" (1*8alphanum))
|
||||
*
|
||||
*/
|
||||
public static LanguageTag parse(String languageTag, ParseStatus sts) {
|
||||
if (sts == null) {
|
||||
sts = new ParseStatus();
|
||||
} else {
|
||||
sts.reset();
|
||||
}
|
||||
|
||||
StringTokenIterator itr;
|
||||
|
||||
// Check if the tag is grandfathered
|
||||
String[] gfmap = GRANDFATHERED.get(LocaleUtils.toLowerString(languageTag));
|
||||
if (gfmap != null) {
|
||||
// use preferred mapping
|
||||
itr = new StringTokenIterator(gfmap[1], SEP);
|
||||
} else {
|
||||
itr = new StringTokenIterator(languageTag, SEP);
|
||||
}
|
||||
|
||||
LanguageTag tag = new LanguageTag();
|
||||
|
||||
// langtag must start with either language or privateuse
|
||||
if (tag.parseLanguage(itr, sts)) {
|
||||
tag.parseExtlangs(itr, sts);
|
||||
tag.parseScript(itr, sts);
|
||||
tag.parseRegion(itr, sts);
|
||||
tag.parseVariants(itr, sts);
|
||||
tag.parseExtensions(itr, sts);
|
||||
}
|
||||
tag.parsePrivateuse(itr, sts);
|
||||
|
||||
if (!itr.isDone() && !sts.isError()) {
|
||||
String s = itr.current();
|
||||
sts.errorIndex = itr.currentStart();
|
||||
if (s.length() == 0) {
|
||||
sts.errorMsg = "Empty subtag";
|
||||
} else {
|
||||
sts.errorMsg = "Invalid subtag: " + s;
|
||||
}
|
||||
}
|
||||
|
||||
return tag;
|
||||
}
|
||||
|
||||
//
|
||||
// Language subtag parsers
|
||||
//
|
||||
|
||||
private boolean parseLanguage(StringTokenIterator itr, ParseStatus sts) {
|
||||
if (itr.isDone() || sts.isError()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean found = false;
|
||||
|
||||
String s = itr.current();
|
||||
if (isLanguage(s)) {
|
||||
found = true;
|
||||
language = s;
|
||||
sts.parseLength = itr.currentEnd();
|
||||
itr.next();
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
private boolean parseExtlangs(StringTokenIterator itr, ParseStatus sts) {
|
||||
if (itr.isDone() || sts.isError()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean found = false;
|
||||
|
||||
while (!itr.isDone()) {
|
||||
String s = itr.current();
|
||||
if (!isExtlang(s)) {
|
||||
break;
|
||||
}
|
||||
found = true;
|
||||
if (extlangs.isEmpty()) {
|
||||
extlangs = new ArrayList<>(3);
|
||||
}
|
||||
extlangs.add(s);
|
||||
sts.parseLength = itr.currentEnd();
|
||||
itr.next();
|
||||
|
||||
if (extlangs.size() == 3) {
|
||||
// Maximum 3 extlangs
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
private boolean parseScript(StringTokenIterator itr, ParseStatus sts) {
|
||||
if (itr.isDone() || sts.isError()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean found = false;
|
||||
|
||||
String s = itr.current();
|
||||
if (isScript(s)) {
|
||||
found = true;
|
||||
script = s;
|
||||
sts.parseLength = itr.currentEnd();
|
||||
itr.next();
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
private boolean parseRegion(StringTokenIterator itr, ParseStatus sts) {
|
||||
if (itr.isDone() || sts.isError()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean found = false;
|
||||
|
||||
String s = itr.current();
|
||||
if (isRegion(s)) {
|
||||
found = true;
|
||||
region = s;
|
||||
sts.parseLength = itr.currentEnd();
|
||||
itr.next();
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
private boolean parseVariants(StringTokenIterator itr, ParseStatus sts) {
|
||||
if (itr.isDone() || sts.isError()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean found = false;
|
||||
|
||||
while (!itr.isDone()) {
|
||||
String s = itr.current();
|
||||
if (!isVariant(s)) {
|
||||
break;
|
||||
}
|
||||
found = true;
|
||||
if (variants.isEmpty()) {
|
||||
variants = new ArrayList<>(3);
|
||||
}
|
||||
variants.add(s);
|
||||
sts.parseLength = itr.currentEnd();
|
||||
itr.next();
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
private boolean parseExtensions(StringTokenIterator itr, ParseStatus sts) {
|
||||
if (itr.isDone() || sts.isError()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean found = false;
|
||||
|
||||
while (!itr.isDone()) {
|
||||
String s = itr.current();
|
||||
if (isExtensionSingleton(s)) {
|
||||
int start = itr.currentStart();
|
||||
String singleton = s;
|
||||
StringBuilder sb = new StringBuilder(singleton);
|
||||
|
||||
itr.next();
|
||||
while (!itr.isDone()) {
|
||||
s = itr.current();
|
||||
if (isExtensionSubtag(s)) {
|
||||
sb.append(SEP).append(s);
|
||||
sts.parseLength = itr.currentEnd();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
itr.next();
|
||||
}
|
||||
|
||||
if (sts.parseLength <= start) {
|
||||
sts.errorIndex = start;
|
||||
sts.errorMsg = "Incomplete extension '" + singleton + "'";
|
||||
break;
|
||||
}
|
||||
|
||||
if (extensions.isEmpty()) {
|
||||
extensions = new ArrayList<>(4);
|
||||
}
|
||||
extensions.add(sb.toString());
|
||||
found = true;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
private boolean parsePrivateuse(StringTokenIterator itr, ParseStatus sts) {
|
||||
if (itr.isDone() || sts.isError()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean found = false;
|
||||
|
||||
String s = itr.current();
|
||||
if (isPrivateusePrefix(s)) {
|
||||
int start = itr.currentStart();
|
||||
StringBuilder sb = new StringBuilder(s);
|
||||
|
||||
itr.next();
|
||||
while (!itr.isDone()) {
|
||||
s = itr.current();
|
||||
if (!isPrivateuseSubtag(s)) {
|
||||
break;
|
||||
}
|
||||
sb.append(SEP).append(s);
|
||||
sts.parseLength = itr.currentEnd();
|
||||
|
||||
itr.next();
|
||||
}
|
||||
|
||||
if (sts.parseLength <= start) {
|
||||
// need at least 1 private subtag
|
||||
sts.errorIndex = start;
|
||||
sts.errorMsg = "Incomplete privateuse";
|
||||
} else {
|
||||
privateuse = sb.toString();
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
public static LanguageTag parseLocale(BaseLocale baseLocale, LocaleExtensions localeExtensions) {
|
||||
LanguageTag tag = new LanguageTag();
|
||||
|
||||
String language = baseLocale.getLanguage();
|
||||
String script = baseLocale.getScript();
|
||||
String region = baseLocale.getRegion();
|
||||
String variant = baseLocale.getVariant();
|
||||
|
||||
boolean hasSubtag = false;
|
||||
|
||||
String privuseVar = null; // store ill-formed variant subtags
|
||||
|
||||
if (isLanguage(language)) {
|
||||
// Convert a deprecated language code to its new code
|
||||
if (language.equals("iw")) {
|
||||
language = "he";
|
||||
} else if (language.equals("ji")) {
|
||||
language = "yi";
|
||||
} else if (language.equals("in")) {
|
||||
language = "id";
|
||||
}
|
||||
tag.language = language;
|
||||
}
|
||||
|
||||
if (isScript(script)) {
|
||||
tag.script = canonicalizeScript(script);
|
||||
hasSubtag = true;
|
||||
}
|
||||
|
||||
if (isRegion(region)) {
|
||||
tag.region = canonicalizeRegion(region);
|
||||
hasSubtag = true;
|
||||
}
|
||||
|
||||
// Special handling for no_NO_NY - use nn_NO for language tag
|
||||
if (tag.language.equals("no") && tag.region.equals("NO") && variant.equals("NY")) {
|
||||
tag.language = "nn";
|
||||
variant = "";
|
||||
}
|
||||
|
||||
if (variant.length() > 0) {
|
||||
List<String> variants = null;
|
||||
StringTokenIterator varitr = new StringTokenIterator(variant, BaseLocale.SEP);
|
||||
while (!varitr.isDone()) {
|
||||
String var = varitr.current();
|
||||
if (!isVariant(var)) {
|
||||
break;
|
||||
}
|
||||
if (variants == null) {
|
||||
variants = new ArrayList<>();
|
||||
}
|
||||
variants.add(var); // Do not canonicalize!
|
||||
varitr.next();
|
||||
}
|
||||
if (variants != null) {
|
||||
tag.variants = variants;
|
||||
hasSubtag = true;
|
||||
}
|
||||
if (!varitr.isDone()) {
|
||||
// ill-formed variant subtags
|
||||
StringBuilder buf = new StringBuilder();
|
||||
while (!varitr.isDone()) {
|
||||
String prvv = varitr.current();
|
||||
if (!isPrivateuseSubtag(prvv)) {
|
||||
// cannot use private use subtag - truncated
|
||||
break;
|
||||
}
|
||||
if (buf.length() > 0) {
|
||||
buf.append(SEP);
|
||||
}
|
||||
buf.append(prvv);
|
||||
varitr.next();
|
||||
}
|
||||
if (buf.length() > 0) {
|
||||
privuseVar = buf.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<String> extensions = null;
|
||||
String privateuse = null;
|
||||
|
||||
if (localeExtensions != null) {
|
||||
Set<Character> locextKeys = localeExtensions.getKeys();
|
||||
for (Character locextKey : locextKeys) {
|
||||
Extension ext = localeExtensions.getExtension(locextKey);
|
||||
if (isPrivateusePrefixChar(locextKey)) {
|
||||
privateuse = ext.getValue();
|
||||
} else {
|
||||
if (extensions == null) {
|
||||
extensions = new ArrayList<>();
|
||||
}
|
||||
extensions.add(locextKey.toString() + SEP + ext.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (extensions != null) {
|
||||
tag.extensions = extensions;
|
||||
hasSubtag = true;
|
||||
}
|
||||
|
||||
// append ill-formed variant subtags to private use
|
||||
if (privuseVar != null) {
|
||||
if (privateuse == null) {
|
||||
privateuse = PRIVUSE_VARIANT_PREFIX + SEP + privuseVar;
|
||||
} else {
|
||||
privateuse = privateuse + SEP + PRIVUSE_VARIANT_PREFIX
|
||||
+ SEP + privuseVar.replace(BaseLocale.SEP, SEP);
|
||||
}
|
||||
}
|
||||
|
||||
if (privateuse != null) {
|
||||
tag.privateuse = privateuse;
|
||||
}
|
||||
|
||||
if (tag.language.length() == 0 && (hasSubtag || privateuse == null)) {
|
||||
// use lang "und" when 1) no language is available AND
|
||||
// 2) any of other subtags other than private use are available or
|
||||
// no private use tag is available
|
||||
tag.language = UNDETERMINED;
|
||||
}
|
||||
|
||||
return tag;
|
||||
}
|
||||
|
||||
//
|
||||
// Getter methods for language subtag fields
|
||||
//
|
||||
|
||||
public String getLanguage() {
|
||||
return language;
|
||||
}
|
||||
|
||||
public List<String> getExtlangs() {
|
||||
if (extlangs.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return Collections.unmodifiableList(extlangs);
|
||||
}
|
||||
|
||||
public String getScript() {
|
||||
return script;
|
||||
}
|
||||
|
||||
public String getRegion() {
|
||||
return region;
|
||||
}
|
||||
|
||||
public List<String> getVariants() {
|
||||
if (variants.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return Collections.unmodifiableList(variants);
|
||||
}
|
||||
|
||||
public List<String> getExtensions() {
|
||||
if (extensions.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return Collections.unmodifiableList(extensions);
|
||||
}
|
||||
|
||||
public String getPrivateuse() {
|
||||
return privateuse;
|
||||
}
|
||||
|
||||
//
|
||||
// Language subtag syntax checking methods
|
||||
//
|
||||
|
||||
public static boolean isLanguage(String s) {
|
||||
// language = 2*3ALPHA ; shortest ISO 639 code
|
||||
// ["-" extlang] ; sometimes followed by
|
||||
// ; extended language subtags
|
||||
// / 4ALPHA ; or reserved for future use
|
||||
// / 5*8ALPHA ; or registered language subtag
|
||||
int len = s.length();
|
||||
return (len >= 2) && (len <= 8) && LocaleUtils.isAlphaString(s);
|
||||
}
|
||||
|
||||
public static boolean isExtlang(String s) {
|
||||
// extlang = 3ALPHA ; selected ISO 639 codes
|
||||
// *2("-" 3ALPHA) ; permanently reserved
|
||||
return (s.length() == 3) && LocaleUtils.isAlphaString(s);
|
||||
}
|
||||
|
||||
public static boolean isScript(String s) {
|
||||
// script = 4ALPHA ; ISO 15924 code
|
||||
return (s.length() == 4) && LocaleUtils.isAlphaString(s);
|
||||
}
|
||||
|
||||
public static boolean isRegion(String s) {
|
||||
// region = 2ALPHA ; ISO 3166-1 code
|
||||
// / 3DIGIT ; UN M.49 code
|
||||
return ((s.length() == 2) && LocaleUtils.isAlphaString(s))
|
||||
|| ((s.length() == 3) && LocaleUtils.isNumericString(s));
|
||||
}
|
||||
|
||||
public static boolean isVariant(String s) {
|
||||
// variant = 5*8alphanum ; registered variants
|
||||
// / (DIGIT 3alphanum)
|
||||
int len = s.length();
|
||||
if (len >= 5 && len <= 8) {
|
||||
return LocaleUtils.isAlphaNumericString(s);
|
||||
}
|
||||
if (len == 4) {
|
||||
return LocaleUtils.isNumeric(s.charAt(0))
|
||||
&& LocaleUtils.isAlphaNumeric(s.charAt(1))
|
||||
&& LocaleUtils.isAlphaNumeric(s.charAt(2))
|
||||
&& LocaleUtils.isAlphaNumeric(s.charAt(3));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isExtensionSingleton(String s) {
|
||||
// singleton = DIGIT ; 0 - 9
|
||||
// / %x41-57 ; A - W
|
||||
// / %x59-5A ; Y - Z
|
||||
// / %x61-77 ; a - w
|
||||
// / %x79-7A ; y - z
|
||||
|
||||
return (s.length() == 1)
|
||||
&& LocaleUtils.isAlphaString(s)
|
||||
&& !LocaleUtils.caseIgnoreMatch(PRIVATEUSE, s);
|
||||
}
|
||||
|
||||
public static boolean isExtensionSingletonChar(char c) {
|
||||
return isExtensionSingleton(String.valueOf(c));
|
||||
}
|
||||
|
||||
public static boolean isExtensionSubtag(String s) {
|
||||
// extension = singleton 1*("-" (2*8alphanum))
|
||||
int len = s.length();
|
||||
return (len >= 2) && (len <= 8) && LocaleUtils.isAlphaNumericString(s);
|
||||
}
|
||||
|
||||
public static boolean isPrivateusePrefix(String s) {
|
||||
// privateuse = "x" 1*("-" (1*8alphanum))
|
||||
return (s.length() == 1)
|
||||
&& LocaleUtils.caseIgnoreMatch(PRIVATEUSE, s);
|
||||
}
|
||||
|
||||
public static boolean isPrivateusePrefixChar(char c) {
|
||||
return (LocaleUtils.caseIgnoreMatch(PRIVATEUSE, String.valueOf(c)));
|
||||
}
|
||||
|
||||
public static boolean isPrivateuseSubtag(String s) {
|
||||
// privateuse = "x" 1*("-" (1*8alphanum))
|
||||
int len = s.length();
|
||||
return (len >= 1) && (len <= 8) && LocaleUtils.isAlphaNumericString(s);
|
||||
}
|
||||
|
||||
//
|
||||
// Language subtag canonicalization methods
|
||||
//
|
||||
|
||||
public static String canonicalizeLanguage(String s) {
|
||||
return LocaleUtils.toLowerString(s);
|
||||
}
|
||||
|
||||
public static String canonicalizeExtlang(String s) {
|
||||
return LocaleUtils.toLowerString(s);
|
||||
}
|
||||
|
||||
public static String canonicalizeScript(String s) {
|
||||
return LocaleUtils.toTitleString(s);
|
||||
}
|
||||
|
||||
public static String canonicalizeRegion(String s) {
|
||||
return LocaleUtils.toUpperString(s);
|
||||
}
|
||||
|
||||
public static String canonicalizeVariant(String s) {
|
||||
return LocaleUtils.toLowerString(s);
|
||||
}
|
||||
|
||||
public static String canonicalizeExtension(String s) {
|
||||
return LocaleUtils.toLowerString(s);
|
||||
}
|
||||
|
||||
public static String canonicalizeExtensionSingleton(String s) {
|
||||
return LocaleUtils.toLowerString(s);
|
||||
}
|
||||
|
||||
public static String canonicalizeExtensionSubtag(String s) {
|
||||
return LocaleUtils.toLowerString(s);
|
||||
}
|
||||
|
||||
public static String canonicalizePrivateuse(String s) {
|
||||
return LocaleUtils.toLowerString(s);
|
||||
}
|
||||
|
||||
public static String canonicalizePrivateuseSubtag(String s) {
|
||||
return LocaleUtils.toLowerString(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
if (language.length() > 0) {
|
||||
sb.append(language);
|
||||
|
||||
for (String extlang : extlangs) {
|
||||
sb.append(SEP).append(extlang);
|
||||
}
|
||||
|
||||
if (script.length() > 0) {
|
||||
sb.append(SEP).append(script);
|
||||
}
|
||||
|
||||
if (region.length() > 0) {
|
||||
sb.append(SEP).append(region);
|
||||
}
|
||||
|
||||
for (String variant : variants) {
|
||||
sb.append(SEP).append(variant);
|
||||
}
|
||||
|
||||
for (String extension : extensions) {
|
||||
sb.append(SEP).append(extension);
|
||||
}
|
||||
}
|
||||
if (privateuse.length() > 0) {
|
||||
if (sb.length() > 0) {
|
||||
sb.append(SEP);
|
||||
}
|
||||
sb.append(privateuse);
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
305
jdkSrc/jdk8/sun/util/locale/LocaleEquivalentMaps.java
Normal file
305
jdkSrc/jdk8/sun/util/locale/LocaleEquivalentMaps.java
Normal file
@@ -0,0 +1,305 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.util.locale;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
final class LocaleEquivalentMaps {
|
||||
|
||||
static final Map<String, String> singleEquivMap;
|
||||
static final Map<String, String[]> multiEquivsMap;
|
||||
static final Map<String, String> regionVariantEquivMap;
|
||||
|
||||
static {
|
||||
singleEquivMap = new HashMap<>();
|
||||
multiEquivsMap = new HashMap<>();
|
||||
regionVariantEquivMap = new HashMap<>();
|
||||
|
||||
// This is an auto-generated file and should not be manually edited.
|
||||
// LSR Revision: 2019-09-16
|
||||
singleEquivMap.put("aam", "aas");
|
||||
singleEquivMap.put("aas", "aam");
|
||||
singleEquivMap.put("acn", "xia");
|
||||
singleEquivMap.put("adp", "dz");
|
||||
singleEquivMap.put("adx", "pcr");
|
||||
singleEquivMap.put("ami", "i-ami");
|
||||
singleEquivMap.put("aog", "myd");
|
||||
singleEquivMap.put("art-lojban", "jbo");
|
||||
singleEquivMap.put("asd", "snz");
|
||||
singleEquivMap.put("ase", "sgn-us");
|
||||
singleEquivMap.put("aue", "ktz");
|
||||
singleEquivMap.put("ayx", "nun");
|
||||
singleEquivMap.put("bcg", "bgm");
|
||||
singleEquivMap.put("bfi", "sgn-gb");
|
||||
singleEquivMap.put("bfy", "ppa");
|
||||
singleEquivMap.put("bgm", "bcg");
|
||||
singleEquivMap.put("bjd", "drl");
|
||||
singleEquivMap.put("bmf", "krm");
|
||||
singleEquivMap.put("bnn", "i-bnn");
|
||||
singleEquivMap.put("bzs", "sgn-br");
|
||||
singleEquivMap.put("cax", "xba");
|
||||
singleEquivMap.put("cir", "meg");
|
||||
singleEquivMap.put("cjr", "mom");
|
||||
singleEquivMap.put("cka", "cmr");
|
||||
singleEquivMap.put("cmk", "xch");
|
||||
singleEquivMap.put("cmn-hans", "zh-cmn-hans");
|
||||
singleEquivMap.put("cmn-hant", "zh-cmn-hant");
|
||||
singleEquivMap.put("cmr", "cka");
|
||||
singleEquivMap.put("cqu", "quh");
|
||||
singleEquivMap.put("csn", "sgn-co");
|
||||
singleEquivMap.put("dev", "gav");
|
||||
singleEquivMap.put("dif", "dit");
|
||||
singleEquivMap.put("dit", "dif");
|
||||
singleEquivMap.put("drh", "khk");
|
||||
singleEquivMap.put("drl", "bjd");
|
||||
singleEquivMap.put("dse", "sgn-nl");
|
||||
singleEquivMap.put("dsl", "sgn-dk");
|
||||
singleEquivMap.put("duz", "guv");
|
||||
singleEquivMap.put("dz", "adp");
|
||||
singleEquivMap.put("ema", "uok");
|
||||
singleEquivMap.put("en-gb-oed", "en-gb-oxendict");
|
||||
singleEquivMap.put("en-gb-oxendict", "en-gb-oed");
|
||||
singleEquivMap.put("fsl", "sgn-fr");
|
||||
singleEquivMap.put("gal", "ilw");
|
||||
singleEquivMap.put("gan", "zh-gan");
|
||||
singleEquivMap.put("gav", "dev");
|
||||
singleEquivMap.put("gdj", "kvs");
|
||||
singleEquivMap.put("ggn", "gvr");
|
||||
singleEquivMap.put("gsg", "sgn-de");
|
||||
singleEquivMap.put("gss", "sgn-gr");
|
||||
singleEquivMap.put("gti", "nyc");
|
||||
singleEquivMap.put("guv", "duz");
|
||||
singleEquivMap.put("gvr", "ggn");
|
||||
singleEquivMap.put("he", "iw");
|
||||
singleEquivMap.put("hle", "sca");
|
||||
singleEquivMap.put("hrr", "jal");
|
||||
singleEquivMap.put("hsn", "zh-xiang");
|
||||
singleEquivMap.put("huw", "pmc");
|
||||
singleEquivMap.put("i-ami", "ami");
|
||||
singleEquivMap.put("i-bnn", "bnn");
|
||||
singleEquivMap.put("i-klingon", "tlh");
|
||||
singleEquivMap.put("i-lux", "lb");
|
||||
singleEquivMap.put("i-navajo", "nv");
|
||||
singleEquivMap.put("i-pwn", "pwn");
|
||||
singleEquivMap.put("i-tao", "tao");
|
||||
singleEquivMap.put("i-tay", "tay");
|
||||
singleEquivMap.put("i-tsu", "tsu");
|
||||
singleEquivMap.put("ibi", "opa");
|
||||
singleEquivMap.put("id", "in");
|
||||
singleEquivMap.put("ilw", "gal");
|
||||
singleEquivMap.put("in", "id");
|
||||
singleEquivMap.put("ise", "sgn-it");
|
||||
singleEquivMap.put("isg", "sgn-ie");
|
||||
singleEquivMap.put("iw", "he");
|
||||
singleEquivMap.put("jal", "hrr");
|
||||
singleEquivMap.put("jbo", "art-lojban");
|
||||
singleEquivMap.put("ji", "yi");
|
||||
singleEquivMap.put("jsl", "sgn-jp");
|
||||
singleEquivMap.put("jv", "jw");
|
||||
singleEquivMap.put("jw", "jv");
|
||||
singleEquivMap.put("kak", "tne");
|
||||
singleEquivMap.put("kdz", "ncp");
|
||||
singleEquivMap.put("kgc", "tdf");
|
||||
singleEquivMap.put("kgh", "kml");
|
||||
singleEquivMap.put("khk", "drh");
|
||||
singleEquivMap.put("kml", "kgh");
|
||||
singleEquivMap.put("koj", "kwv");
|
||||
singleEquivMap.put("krm", "bmf");
|
||||
singleEquivMap.put("ktz", "aue");
|
||||
singleEquivMap.put("kvs", "gdj");
|
||||
singleEquivMap.put("kwq", "yam");
|
||||
singleEquivMap.put("kwv", "koj");
|
||||
singleEquivMap.put("kxe", "tvd");
|
||||
singleEquivMap.put("lb", "i-lux");
|
||||
singleEquivMap.put("lcq", "ppr");
|
||||
singleEquivMap.put("lii", "raq");
|
||||
singleEquivMap.put("llo", "ngt");
|
||||
singleEquivMap.put("lmm", "rmx");
|
||||
singleEquivMap.put("lrr", "yma");
|
||||
singleEquivMap.put("meg", "cir");
|
||||
singleEquivMap.put("mfs", "sgn-mx");
|
||||
singleEquivMap.put("mo", "ro");
|
||||
singleEquivMap.put("mom", "cjr");
|
||||
singleEquivMap.put("mtm", "ymt");
|
||||
singleEquivMap.put("myd", "aog");
|
||||
singleEquivMap.put("nad", "xny");
|
||||
singleEquivMap.put("nan", "zh-min-nan");
|
||||
singleEquivMap.put("nb", "no-bok");
|
||||
singleEquivMap.put("nbr", "nns");
|
||||
singleEquivMap.put("ncp", "kdz");
|
||||
singleEquivMap.put("ncs", "sgn-ni");
|
||||
singleEquivMap.put("ngt", "llo");
|
||||
singleEquivMap.put("ngv", "nnx");
|
||||
singleEquivMap.put("nn", "no-nyn");
|
||||
singleEquivMap.put("nns", "nbr");
|
||||
singleEquivMap.put("nnx", "ngv");
|
||||
singleEquivMap.put("no-bok", "nb");
|
||||
singleEquivMap.put("no-nyn", "nn");
|
||||
singleEquivMap.put("nsl", "sgn-no");
|
||||
singleEquivMap.put("nun", "ayx");
|
||||
singleEquivMap.put("nv", "i-navajo");
|
||||
singleEquivMap.put("nyc", "gti");
|
||||
singleEquivMap.put("opa", "ibi");
|
||||
singleEquivMap.put("pcr", "adx");
|
||||
singleEquivMap.put("phr", "pmu");
|
||||
singleEquivMap.put("pmc", "huw");
|
||||
singleEquivMap.put("pmu", "phr");
|
||||
singleEquivMap.put("ppa", "bfy");
|
||||
singleEquivMap.put("ppr", "lcq");
|
||||
singleEquivMap.put("prt", "pry");
|
||||
singleEquivMap.put("pry", "prt");
|
||||
singleEquivMap.put("psr", "sgn-pt");
|
||||
singleEquivMap.put("pub", "puz");
|
||||
singleEquivMap.put("puz", "pub");
|
||||
singleEquivMap.put("pwn", "i-pwn");
|
||||
singleEquivMap.put("quh", "cqu");
|
||||
singleEquivMap.put("raq", "lii");
|
||||
singleEquivMap.put("ras", "tie");
|
||||
singleEquivMap.put("rmx", "lmm");
|
||||
singleEquivMap.put("ro", "mo");
|
||||
singleEquivMap.put("sca", "hle");
|
||||
singleEquivMap.put("sfb", "sgn-be-fr");
|
||||
singleEquivMap.put("sfs", "sgn-za");
|
||||
singleEquivMap.put("sgg", "sgn-ch-de");
|
||||
singleEquivMap.put("sgn-be-fr", "sfb");
|
||||
singleEquivMap.put("sgn-be-nl", "vgt");
|
||||
singleEquivMap.put("sgn-br", "bzs");
|
||||
singleEquivMap.put("sgn-ch-de", "sgg");
|
||||
singleEquivMap.put("sgn-co", "csn");
|
||||
singleEquivMap.put("sgn-de", "gsg");
|
||||
singleEquivMap.put("sgn-dk", "dsl");
|
||||
singleEquivMap.put("sgn-es", "ssp");
|
||||
singleEquivMap.put("sgn-fr", "fsl");
|
||||
singleEquivMap.put("sgn-gb", "bfi");
|
||||
singleEquivMap.put("sgn-gr", "gss");
|
||||
singleEquivMap.put("sgn-ie", "isg");
|
||||
singleEquivMap.put("sgn-it", "ise");
|
||||
singleEquivMap.put("sgn-jp", "jsl");
|
||||
singleEquivMap.put("sgn-mx", "mfs");
|
||||
singleEquivMap.put("sgn-ni", "ncs");
|
||||
singleEquivMap.put("sgn-nl", "dse");
|
||||
singleEquivMap.put("sgn-no", "nsl");
|
||||
singleEquivMap.put("sgn-pt", "psr");
|
||||
singleEquivMap.put("sgn-se", "swl");
|
||||
singleEquivMap.put("sgn-us", "ase");
|
||||
singleEquivMap.put("sgn-za", "sfs");
|
||||
singleEquivMap.put("snz", "asd");
|
||||
singleEquivMap.put("ssp", "sgn-es");
|
||||
singleEquivMap.put("swl", "sgn-se");
|
||||
singleEquivMap.put("taj", "tsf");
|
||||
singleEquivMap.put("tao", "i-tao");
|
||||
singleEquivMap.put("tay", "i-tay");
|
||||
singleEquivMap.put("tdf", "kgc");
|
||||
singleEquivMap.put("thc", "tpo");
|
||||
singleEquivMap.put("tie", "ras");
|
||||
singleEquivMap.put("tkk", "twm");
|
||||
singleEquivMap.put("tlh", "i-klingon");
|
||||
singleEquivMap.put("tlw", "weo");
|
||||
singleEquivMap.put("tmp", "tyj");
|
||||
singleEquivMap.put("tne", "kak");
|
||||
singleEquivMap.put("tpo", "thc");
|
||||
singleEquivMap.put("tsf", "taj");
|
||||
singleEquivMap.put("tsu", "i-tsu");
|
||||
singleEquivMap.put("tvd", "kxe");
|
||||
singleEquivMap.put("twm", "tkk");
|
||||
singleEquivMap.put("tyj", "tmp");
|
||||
singleEquivMap.put("uok", "ema");
|
||||
singleEquivMap.put("vgt", "sgn-be-nl");
|
||||
singleEquivMap.put("waw", "xkh");
|
||||
singleEquivMap.put("weo", "tlw");
|
||||
singleEquivMap.put("wuu", "zh-wuu");
|
||||
singleEquivMap.put("xba", "cax");
|
||||
singleEquivMap.put("xch", "cmk");
|
||||
singleEquivMap.put("xia", "acn");
|
||||
singleEquivMap.put("xkh", "waw");
|
||||
singleEquivMap.put("xny", "nad");
|
||||
singleEquivMap.put("yam", "kwq");
|
||||
singleEquivMap.put("yi", "ji");
|
||||
singleEquivMap.put("yma", "lrr");
|
||||
singleEquivMap.put("ymt", "mtm");
|
||||
singleEquivMap.put("yos", "zom");
|
||||
singleEquivMap.put("yue", "zh-yue");
|
||||
singleEquivMap.put("yug", "yuu");
|
||||
singleEquivMap.put("yuu", "yug");
|
||||
singleEquivMap.put("zh-cmn-hans", "cmn-hans");
|
||||
singleEquivMap.put("zh-cmn-hant", "cmn-hant");
|
||||
singleEquivMap.put("zh-gan", "gan");
|
||||
singleEquivMap.put("zh-min-nan", "nan");
|
||||
singleEquivMap.put("zh-wuu", "wuu");
|
||||
singleEquivMap.put("zh-xiang", "hsn");
|
||||
singleEquivMap.put("zh-yue", "yue");
|
||||
singleEquivMap.put("zom", "yos");
|
||||
|
||||
multiEquivsMap.put("ccq", new String[] {"rki", "ybd"});
|
||||
multiEquivsMap.put("cmn", new String[] {"zh-guoyu", "zh-cmn"});
|
||||
multiEquivsMap.put("coy", new String[] {"pij", "nts"});
|
||||
multiEquivsMap.put("drw", new String[] {"prs", "tnf"});
|
||||
multiEquivsMap.put("dtp", new String[] {"ktr", "kzj", "kzt", "tdu"});
|
||||
multiEquivsMap.put("gfx", new String[] {"vaj", "mwj", "oun"});
|
||||
multiEquivsMap.put("hak", new String[] {"i-hak", "zh-hakka"});
|
||||
multiEquivsMap.put("i-hak", new String[] {"hak", "zh-hakka"});
|
||||
multiEquivsMap.put("jeg", new String[] {"oyb", "skk", "thx"});
|
||||
multiEquivsMap.put("ktr", new String[] {"dtp", "kzj", "kzt", "tdu"});
|
||||
multiEquivsMap.put("kzj", new String[] {"dtp", "ktr", "kzt", "tdu"});
|
||||
multiEquivsMap.put("kzt", new String[] {"dtp", "ktr", "kzj", "tdu"});
|
||||
multiEquivsMap.put("mry", new String[] {"mst", "myt"});
|
||||
multiEquivsMap.put("mst", new String[] {"mry", "myt"});
|
||||
multiEquivsMap.put("mwj", new String[] {"vaj", "gfx", "oun"});
|
||||
multiEquivsMap.put("myt", new String[] {"mry", "mst"});
|
||||
multiEquivsMap.put("nts", new String[] {"pij", "coy"});
|
||||
multiEquivsMap.put("oun", new String[] {"vaj", "gfx", "mwj"});
|
||||
multiEquivsMap.put("oyb", new String[] {"jeg", "skk", "thx"});
|
||||
multiEquivsMap.put("pij", new String[] {"coy", "nts"});
|
||||
multiEquivsMap.put("prs", new String[] {"drw", "tnf"});
|
||||
multiEquivsMap.put("rki", new String[] {"ccq", "ybd"});
|
||||
multiEquivsMap.put("skk", new String[] {"oyb", "jeg", "thx"});
|
||||
multiEquivsMap.put("tdu", new String[] {"dtp", "ktr", "kzj", "kzt"});
|
||||
multiEquivsMap.put("thx", new String[] {"oyb", "jeg", "skk"});
|
||||
multiEquivsMap.put("tnf", new String[] {"prs", "drw"});
|
||||
multiEquivsMap.put("vaj", new String[] {"gfx", "mwj", "oun"});
|
||||
multiEquivsMap.put("ybd", new String[] {"rki", "ccq"});
|
||||
multiEquivsMap.put("zh-cmn", new String[] {"cmn", "zh-guoyu"});
|
||||
multiEquivsMap.put("zh-guoyu", new String[] {"cmn", "zh-cmn"});
|
||||
multiEquivsMap.put("zh-hakka", new String[] {"hak", "i-hak"});
|
||||
|
||||
regionVariantEquivMap.put("-alalc97", "-heploc");
|
||||
regionVariantEquivMap.put("-bu", "-mm");
|
||||
regionVariantEquivMap.put("-cd", "-zr");
|
||||
regionVariantEquivMap.put("-dd", "-de");
|
||||
regionVariantEquivMap.put("-de", "-dd");
|
||||
regionVariantEquivMap.put("-fr", "-fx");
|
||||
regionVariantEquivMap.put("-fx", "-fr");
|
||||
regionVariantEquivMap.put("-heploc", "-alalc97");
|
||||
regionVariantEquivMap.put("-mm", "-bu");
|
||||
regionVariantEquivMap.put("-tl", "-tp");
|
||||
regionVariantEquivMap.put("-tp", "-tl");
|
||||
regionVariantEquivMap.put("-yd", "-ye");
|
||||
regionVariantEquivMap.put("-ye", "-yd");
|
||||
regionVariantEquivMap.put("-zr", "-cd");
|
||||
}
|
||||
|
||||
}
|
||||
242
jdkSrc/jdk8/sun/util/locale/LocaleExtensions.java
Normal file
242
jdkSrc/jdk8/sun/util/locale/LocaleExtensions.java
Normal file
@@ -0,0 +1,242 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2009-2010, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*/
|
||||
package sun.util.locale;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.SortedMap;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeMap;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import sun.util.locale.InternalLocaleBuilder.CaseInsensitiveChar;
|
||||
import sun.util.locale.InternalLocaleBuilder.CaseInsensitiveString;
|
||||
|
||||
|
||||
public class LocaleExtensions {
|
||||
|
||||
private final Map<Character, Extension> extensionMap;
|
||||
private final String id;
|
||||
|
||||
public static final LocaleExtensions CALENDAR_JAPANESE
|
||||
= new LocaleExtensions("u-ca-japanese",
|
||||
UnicodeLocaleExtension.SINGLETON,
|
||||
UnicodeLocaleExtension.CA_JAPANESE);
|
||||
|
||||
public static final LocaleExtensions NUMBER_THAI
|
||||
= new LocaleExtensions("u-nu-thai",
|
||||
UnicodeLocaleExtension.SINGLETON,
|
||||
UnicodeLocaleExtension.NU_THAI);
|
||||
|
||||
private LocaleExtensions(String id, Character key, Extension value) {
|
||||
this.id = id;
|
||||
this.extensionMap = Collections.singletonMap(key, value);
|
||||
}
|
||||
|
||||
/*
|
||||
* Package private constructor, only used by InternalLocaleBuilder.
|
||||
*/
|
||||
LocaleExtensions(Map<CaseInsensitiveChar, String> extensions,
|
||||
Set<CaseInsensitiveString> uattributes,
|
||||
Map<CaseInsensitiveString, String> ukeywords) {
|
||||
boolean hasExtension = !LocaleUtils.isEmpty(extensions);
|
||||
boolean hasUAttributes = !LocaleUtils.isEmpty(uattributes);
|
||||
boolean hasUKeywords = !LocaleUtils.isEmpty(ukeywords);
|
||||
|
||||
if (!hasExtension && !hasUAttributes && !hasUKeywords) {
|
||||
id = "";
|
||||
extensionMap = Collections.emptyMap();
|
||||
return;
|
||||
}
|
||||
|
||||
// Build extension map
|
||||
SortedMap<Character, Extension> map = new TreeMap<>();
|
||||
if (hasExtension) {
|
||||
for (Entry<CaseInsensitiveChar, String> ext : extensions.entrySet()) {
|
||||
char key = LocaleUtils.toLower(ext.getKey().value());
|
||||
String value = ext.getValue();
|
||||
|
||||
if (LanguageTag.isPrivateusePrefixChar(key)) {
|
||||
// we need to exclude special variant in privuateuse, e.g. "x-abc-lvariant-DEF"
|
||||
value = InternalLocaleBuilder.removePrivateuseVariant(value);
|
||||
if (value == null) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
map.put(key, new Extension(key, LocaleUtils.toLowerString(value)));
|
||||
}
|
||||
}
|
||||
|
||||
if (hasUAttributes || hasUKeywords) {
|
||||
SortedSet<String> uaset = null;
|
||||
SortedMap<String, String> ukmap = null;
|
||||
|
||||
if (hasUAttributes) {
|
||||
uaset = new TreeSet<>();
|
||||
for (CaseInsensitiveString cis : uattributes) {
|
||||
uaset.add(LocaleUtils.toLowerString(cis.value()));
|
||||
}
|
||||
}
|
||||
|
||||
if (hasUKeywords) {
|
||||
ukmap = new TreeMap<>();
|
||||
for (Entry<CaseInsensitiveString, String> kwd : ukeywords.entrySet()) {
|
||||
String key = LocaleUtils.toLowerString(kwd.getKey().value());
|
||||
String type = LocaleUtils.toLowerString(kwd.getValue());
|
||||
ukmap.put(key, type);
|
||||
}
|
||||
}
|
||||
|
||||
UnicodeLocaleExtension ule = new UnicodeLocaleExtension(uaset, ukmap);
|
||||
map.put(UnicodeLocaleExtension.SINGLETON, ule);
|
||||
}
|
||||
|
||||
if (map.isEmpty()) {
|
||||
// this could happen when only privuateuse with special variant
|
||||
id = "";
|
||||
extensionMap = Collections.emptyMap();
|
||||
} else {
|
||||
id = toID(map);
|
||||
extensionMap = map;
|
||||
}
|
||||
}
|
||||
|
||||
public Set<Character> getKeys() {
|
||||
if (extensionMap.isEmpty()) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
return Collections.unmodifiableSet(extensionMap.keySet());
|
||||
}
|
||||
|
||||
public Extension getExtension(Character key) {
|
||||
return extensionMap.get(LocaleUtils.toLower(key));
|
||||
}
|
||||
|
||||
public String getExtensionValue(Character key) {
|
||||
Extension ext = extensionMap.get(LocaleUtils.toLower(key));
|
||||
if (ext == null) {
|
||||
return null;
|
||||
}
|
||||
return ext.getValue();
|
||||
}
|
||||
|
||||
public Set<String> getUnicodeLocaleAttributes() {
|
||||
Extension ext = extensionMap.get(UnicodeLocaleExtension.SINGLETON);
|
||||
if (ext == null) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
assert (ext instanceof UnicodeLocaleExtension);
|
||||
return ((UnicodeLocaleExtension)ext).getUnicodeLocaleAttributes();
|
||||
}
|
||||
|
||||
public Set<String> getUnicodeLocaleKeys() {
|
||||
Extension ext = extensionMap.get(UnicodeLocaleExtension.SINGLETON);
|
||||
if (ext == null) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
assert (ext instanceof UnicodeLocaleExtension);
|
||||
return ((UnicodeLocaleExtension)ext).getUnicodeLocaleKeys();
|
||||
}
|
||||
|
||||
public String getUnicodeLocaleType(String unicodeLocaleKey) {
|
||||
Extension ext = extensionMap.get(UnicodeLocaleExtension.SINGLETON);
|
||||
if (ext == null) {
|
||||
return null;
|
||||
}
|
||||
assert (ext instanceof UnicodeLocaleExtension);
|
||||
return ((UnicodeLocaleExtension)ext).getUnicodeLocaleType(LocaleUtils.toLowerString(unicodeLocaleKey));
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return extensionMap.isEmpty();
|
||||
}
|
||||
|
||||
public static boolean isValidKey(char c) {
|
||||
return LanguageTag.isExtensionSingletonChar(c) || LanguageTag.isPrivateusePrefixChar(c);
|
||||
}
|
||||
|
||||
public static boolean isValidUnicodeLocaleKey(String ukey) {
|
||||
return UnicodeLocaleExtension.isKey(ukey);
|
||||
}
|
||||
|
||||
private static String toID(SortedMap<Character, Extension> map) {
|
||||
StringBuilder buf = new StringBuilder();
|
||||
Extension privuse = null;
|
||||
for (Entry<Character, Extension> entry : map.entrySet()) {
|
||||
char singleton = entry.getKey();
|
||||
Extension extension = entry.getValue();
|
||||
if (LanguageTag.isPrivateusePrefixChar(singleton)) {
|
||||
privuse = extension;
|
||||
} else {
|
||||
if (buf.length() > 0) {
|
||||
buf.append(LanguageTag.SEP);
|
||||
}
|
||||
buf.append(extension);
|
||||
}
|
||||
}
|
||||
if (privuse != null) {
|
||||
if (buf.length() > 0) {
|
||||
buf.append(LanguageTag.SEP);
|
||||
}
|
||||
buf.append(privuse);
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getID() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return id.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
if (!(other instanceof LocaleExtensions)) {
|
||||
return false;
|
||||
}
|
||||
return id.equals(((LocaleExtensions)other).id);
|
||||
}
|
||||
}
|
||||
455
jdkSrc/jdk8/sun/util/locale/LocaleMatcher.java
Normal file
455
jdkSrc/jdk8/sun/util/locale/LocaleMatcher.java
Normal file
@@ -0,0 +1,455 @@
|
||||
/*
|
||||
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.util.locale;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Locale.*;
|
||||
import static java.util.Locale.FilteringMode.*;
|
||||
import static java.util.Locale.LanguageRange.*;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Implementation for BCP47 Locale matching
|
||||
*
|
||||
*/
|
||||
public final class LocaleMatcher {
|
||||
|
||||
public static List<Locale> filter(List<LanguageRange> priorityList,
|
||||
Collection<Locale> locales,
|
||||
FilteringMode mode) {
|
||||
if (priorityList.isEmpty() || locales.isEmpty()) {
|
||||
return new ArrayList<>(); // need to return a empty mutable List
|
||||
}
|
||||
|
||||
// Create a list of language tags to be matched.
|
||||
List<String> tags = new ArrayList<>();
|
||||
for (Locale locale : locales) {
|
||||
tags.add(locale.toLanguageTag());
|
||||
}
|
||||
|
||||
// Filter language tags.
|
||||
List<String> filteredTags = filterTags(priorityList, tags, mode);
|
||||
|
||||
// Create a list of matching locales.
|
||||
List<Locale> filteredLocales = new ArrayList<>(filteredTags.size());
|
||||
for (String tag : filteredTags) {
|
||||
filteredLocales.add(Locale.forLanguageTag(tag));
|
||||
}
|
||||
|
||||
return filteredLocales;
|
||||
}
|
||||
|
||||
public static List<String> filterTags(List<LanguageRange> priorityList,
|
||||
Collection<String> tags,
|
||||
FilteringMode mode) {
|
||||
if (priorityList.isEmpty() || tags.isEmpty()) {
|
||||
return new ArrayList<>(); // need to return a empty mutable List
|
||||
}
|
||||
|
||||
ArrayList<LanguageRange> list;
|
||||
if (mode == EXTENDED_FILTERING) {
|
||||
return filterExtended(priorityList, tags);
|
||||
} else {
|
||||
list = new ArrayList<>();
|
||||
for (LanguageRange lr : priorityList) {
|
||||
String range = lr.getRange();
|
||||
if (range.startsWith("*-")
|
||||
|| range.indexOf("-*") != -1) { // Extended range
|
||||
if (mode == AUTOSELECT_FILTERING) {
|
||||
return filterExtended(priorityList, tags);
|
||||
} else if (mode == MAP_EXTENDED_RANGES) {
|
||||
if (range.charAt(0) == '*') {
|
||||
range = "*";
|
||||
} else {
|
||||
range = range.replaceAll("-[*]", "");
|
||||
}
|
||||
list.add(new LanguageRange(range, lr.getWeight()));
|
||||
} else if (mode == REJECT_EXTENDED_RANGES) {
|
||||
throw new IllegalArgumentException("An extended range \""
|
||||
+ range
|
||||
+ "\" found in REJECT_EXTENDED_RANGES mode.");
|
||||
}
|
||||
} else { // Basic range
|
||||
list.add(lr);
|
||||
}
|
||||
}
|
||||
|
||||
return filterBasic(list, tags);
|
||||
}
|
||||
}
|
||||
|
||||
private static List<String> filterBasic(List<LanguageRange> priorityList,
|
||||
Collection<String> tags) {
|
||||
List<String> list = new ArrayList<>();
|
||||
for (LanguageRange lr : priorityList) {
|
||||
String range = lr.getRange();
|
||||
if (range.equals("*")) {
|
||||
return new ArrayList<String>(tags);
|
||||
} else {
|
||||
for (String tag : tags) {
|
||||
tag = tag.toLowerCase();
|
||||
if (tag.startsWith(range)) {
|
||||
int len = range.length();
|
||||
if ((tag.length() == len || tag.charAt(len) == '-')
|
||||
&& !list.contains(tag)) {
|
||||
list.add(tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
private static List<String> filterExtended(List<LanguageRange> priorityList,
|
||||
Collection<String> tags) {
|
||||
List<String> list = new ArrayList<>();
|
||||
for (LanguageRange lr : priorityList) {
|
||||
String range = lr.getRange();
|
||||
if (range.equals("*")) {
|
||||
return new ArrayList<String>(tags);
|
||||
}
|
||||
String[] rangeSubtags = range.split("-");
|
||||
for (String tag : tags) {
|
||||
tag = tag.toLowerCase();
|
||||
String[] tagSubtags = tag.split("-");
|
||||
if (!rangeSubtags[0].equals(tagSubtags[0])
|
||||
&& !rangeSubtags[0].equals("*")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int rangeIndex = 1;
|
||||
int tagIndex = 1;
|
||||
|
||||
while (rangeIndex < rangeSubtags.length
|
||||
&& tagIndex < tagSubtags.length) {
|
||||
if (rangeSubtags[rangeIndex].equals("*")) {
|
||||
rangeIndex++;
|
||||
} else if (rangeSubtags[rangeIndex].equals(tagSubtags[tagIndex])) {
|
||||
rangeIndex++;
|
||||
tagIndex++;
|
||||
} else if (tagSubtags[tagIndex].length() == 1
|
||||
&& !tagSubtags[tagIndex].equals("*")) {
|
||||
break;
|
||||
} else {
|
||||
tagIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
if (rangeSubtags.length == rangeIndex && !list.contains(tag)) {
|
||||
list.add(tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
public static Locale lookup(List<LanguageRange> priorityList,
|
||||
Collection<Locale> locales) {
|
||||
if (priorityList.isEmpty() || locales.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Create a list of language tags to be matched.
|
||||
List<String> tags = new ArrayList<>();
|
||||
for (Locale locale : locales) {
|
||||
tags.add(locale.toLanguageTag());
|
||||
}
|
||||
|
||||
// Look up a language tags.
|
||||
String lookedUpTag = lookupTag(priorityList, tags);
|
||||
|
||||
if (lookedUpTag == null) {
|
||||
return null;
|
||||
} else {
|
||||
return Locale.forLanguageTag(lookedUpTag);
|
||||
}
|
||||
}
|
||||
|
||||
public static String lookupTag(List<LanguageRange> priorityList,
|
||||
Collection<String> tags) {
|
||||
if (priorityList.isEmpty() || tags.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (LanguageRange lr : priorityList) {
|
||||
String range = lr.getRange();
|
||||
|
||||
// Special language range ("*") is ignored in lookup.
|
||||
if (range.equals("*")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String rangeForRegex = range.replaceAll("\\x2A", "\\\\p{Alnum}*");
|
||||
while (rangeForRegex.length() > 0) {
|
||||
for (String tag : tags) {
|
||||
tag = tag.toLowerCase();
|
||||
if (tag.matches(rangeForRegex)) {
|
||||
return tag;
|
||||
}
|
||||
}
|
||||
|
||||
// Truncate from the end....
|
||||
int index = rangeForRegex.lastIndexOf('-');
|
||||
if (index >= 0) {
|
||||
rangeForRegex = rangeForRegex.substring(0, index);
|
||||
|
||||
// if range ends with an extension key, truncate it.
|
||||
if (rangeForRegex.lastIndexOf('-') == rangeForRegex.length()-2) {
|
||||
rangeForRegex =
|
||||
rangeForRegex.substring(0, rangeForRegex.length()-2);
|
||||
}
|
||||
} else {
|
||||
rangeForRegex = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static List<LanguageRange> parse(String ranges) {
|
||||
ranges = ranges.replaceAll(" ", "").toLowerCase();
|
||||
if (ranges.startsWith("accept-language:")) {
|
||||
ranges = ranges.substring(16); // delete unnecessary prefix
|
||||
}
|
||||
|
||||
String[] langRanges = ranges.split(",");
|
||||
List<LanguageRange> list = new ArrayList<>(langRanges.length);
|
||||
List<String> tempList = new ArrayList<>();
|
||||
int numOfRanges = 0;
|
||||
|
||||
for (String range : langRanges) {
|
||||
int index;
|
||||
String r;
|
||||
double w;
|
||||
|
||||
if ((index = range.indexOf(";q=")) == -1) {
|
||||
r = range;
|
||||
w = MAX_WEIGHT;
|
||||
} else {
|
||||
r = range.substring(0, index);
|
||||
index += 3;
|
||||
try {
|
||||
w = Double.parseDouble(range.substring(index));
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new IllegalArgumentException("weight=\""
|
||||
+ range.substring(index)
|
||||
+ "\" for language range \"" + r + "\"");
|
||||
}
|
||||
|
||||
if (w < MIN_WEIGHT || w > MAX_WEIGHT) {
|
||||
throw new IllegalArgumentException("weight=" + w
|
||||
+ " for language range \"" + r
|
||||
+ "\". It must be between " + MIN_WEIGHT
|
||||
+ " and " + MAX_WEIGHT + ".");
|
||||
}
|
||||
}
|
||||
|
||||
if (!tempList.contains(r)) {
|
||||
LanguageRange lr = new LanguageRange(r, w);
|
||||
index = numOfRanges;
|
||||
for (int j = 0; j < numOfRanges; j++) {
|
||||
if (list.get(j).getWeight() < w) {
|
||||
index = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
list.add(index, lr);
|
||||
numOfRanges++;
|
||||
tempList.add(r);
|
||||
|
||||
// Check if the range has an equivalent using IANA LSR data.
|
||||
// If yes, add it to the User's Language Priority List as well.
|
||||
|
||||
// aa-XX -> aa-YY
|
||||
String equivalent;
|
||||
if ((equivalent = getEquivalentForRegionAndVariant(r)) != null
|
||||
&& !tempList.contains(equivalent)) {
|
||||
list.add(index+1, new LanguageRange(equivalent, w));
|
||||
numOfRanges++;
|
||||
tempList.add(equivalent);
|
||||
}
|
||||
|
||||
String[] equivalents;
|
||||
if ((equivalents = getEquivalentsForLanguage(r)) != null) {
|
||||
for (String equiv: equivalents) {
|
||||
// aa-XX -> bb-XX(, cc-XX)
|
||||
if (!tempList.contains(equiv)) {
|
||||
list.add(index+1, new LanguageRange(equiv, w));
|
||||
numOfRanges++;
|
||||
tempList.add(equiv);
|
||||
}
|
||||
|
||||
// bb-XX -> bb-YY(, cc-YY)
|
||||
equivalent = getEquivalentForRegionAndVariant(equiv);
|
||||
if (equivalent != null
|
||||
&& !tempList.contains(equivalent)) {
|
||||
list.add(index+1, new LanguageRange(equivalent, w));
|
||||
numOfRanges++;
|
||||
tempList.add(equivalent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
private static String[] getEquivalentsForLanguage(String range) {
|
||||
String r = range;
|
||||
|
||||
while (r.length() > 0) {
|
||||
if (LocaleEquivalentMaps.singleEquivMap.containsKey(r)) {
|
||||
String equiv = LocaleEquivalentMaps.singleEquivMap.get(r);
|
||||
// Return immediately for performance if the first matching
|
||||
// subtag is found.
|
||||
return new String[] {range.replaceFirst(r, equiv)};
|
||||
} else if (LocaleEquivalentMaps.multiEquivsMap.containsKey(r)) {
|
||||
String[] equivs = LocaleEquivalentMaps.multiEquivsMap.get(r);
|
||||
for (int i = 0; i < equivs.length; i++) {
|
||||
equivs[i] = range.replaceFirst(r, equivs[i]);
|
||||
}
|
||||
return equivs;
|
||||
}
|
||||
|
||||
// Truncate the last subtag simply.
|
||||
int index = r.lastIndexOf('-');
|
||||
if (index == -1) {
|
||||
break;
|
||||
}
|
||||
r = r.substring(0, index);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static String getEquivalentForRegionAndVariant(String range) {
|
||||
int extensionKeyIndex = getExtentionKeyIndex(range);
|
||||
|
||||
for (String subtag : LocaleEquivalentMaps.regionVariantEquivMap.keySet()) {
|
||||
int index;
|
||||
if ((index = range.indexOf(subtag)) != -1) {
|
||||
// Check if the matching text is a valid region or variant.
|
||||
if (extensionKeyIndex != Integer.MIN_VALUE
|
||||
&& index > extensionKeyIndex) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int len = index + subtag.length();
|
||||
if (range.length() == len || range.charAt(len) == '-') {
|
||||
return range.replaceFirst(subtag, LocaleEquivalentMaps.regionVariantEquivMap.get(subtag));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static int getExtentionKeyIndex(String s) {
|
||||
char[] c = s.toCharArray();
|
||||
int index = Integer.MIN_VALUE;
|
||||
for (int i = 1; i < c.length; i++) {
|
||||
if (c[i] == '-') {
|
||||
if (i - index == 2) {
|
||||
return index;
|
||||
} else {
|
||||
index = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return Integer.MIN_VALUE;
|
||||
}
|
||||
|
||||
public static List<LanguageRange> mapEquivalents(
|
||||
List<LanguageRange>priorityList,
|
||||
Map<String, List<String>> map) {
|
||||
if (priorityList.isEmpty()) {
|
||||
return new ArrayList<>(); // need to return a empty mutable List
|
||||
}
|
||||
if (map == null || map.isEmpty()) {
|
||||
return new ArrayList<LanguageRange>(priorityList);
|
||||
}
|
||||
|
||||
// Create a map, key=originalKey.toLowerCaes(), value=originalKey
|
||||
Map<String, String> keyMap = new HashMap<>();
|
||||
for (String key : map.keySet()) {
|
||||
keyMap.put(key.toLowerCase(), key);
|
||||
}
|
||||
|
||||
List<LanguageRange> list = new ArrayList<>();
|
||||
for (LanguageRange lr : priorityList) {
|
||||
String range = lr.getRange();
|
||||
String r = range;
|
||||
boolean hasEquivalent = false;
|
||||
|
||||
while (r.length() > 0) {
|
||||
if (keyMap.containsKey(r)) {
|
||||
hasEquivalent = true;
|
||||
List<String> equivalents = map.get(keyMap.get(r));
|
||||
if (equivalents != null) {
|
||||
int len = r.length();
|
||||
for (String equivalent : equivalents) {
|
||||
list.add(new LanguageRange(equivalent.toLowerCase()
|
||||
+ range.substring(len),
|
||||
lr.getWeight()));
|
||||
}
|
||||
}
|
||||
// Return immediately if the first matching subtag is found.
|
||||
break;
|
||||
}
|
||||
|
||||
// Truncate the last subtag simply.
|
||||
int index = r.lastIndexOf('-');
|
||||
if (index == -1) {
|
||||
break;
|
||||
}
|
||||
r = r.substring(0, index);
|
||||
}
|
||||
|
||||
if (!hasEquivalent) {
|
||||
list.add(lr);
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
private LocaleMatcher() {}
|
||||
|
||||
}
|
||||
117
jdkSrc/jdk8/sun/util/locale/LocaleObjectCache.java
Normal file
117
jdkSrc/jdk8/sun/util/locale/LocaleObjectCache.java
Normal file
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2009-2010, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*/
|
||||
package sun.util.locale;
|
||||
|
||||
import java.lang.ref.ReferenceQueue;
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
public abstract class LocaleObjectCache<K, V> {
|
||||
private ConcurrentMap<K, CacheEntry<K, V>> map;
|
||||
private ReferenceQueue<V> queue = new ReferenceQueue<>();
|
||||
|
||||
public LocaleObjectCache() {
|
||||
this(16, 0.75f, 16);
|
||||
}
|
||||
|
||||
public LocaleObjectCache(int initialCapacity, float loadFactor, int concurrencyLevel) {
|
||||
map = new ConcurrentHashMap<>(initialCapacity, loadFactor, concurrencyLevel);
|
||||
}
|
||||
|
||||
public V get(K key) {
|
||||
V value = null;
|
||||
|
||||
cleanStaleEntries();
|
||||
CacheEntry<K, V> entry = map.get(key);
|
||||
if (entry != null) {
|
||||
value = entry.get();
|
||||
}
|
||||
if (value == null) {
|
||||
V newVal = createObject(key);
|
||||
// make sure key is normalized *after* the object creation
|
||||
// so that newVal is assured to be created from a valid key.
|
||||
key = normalizeKey(key);
|
||||
if (key == null || newVal == null) {
|
||||
// subclass must return non-null key/value object
|
||||
return null;
|
||||
}
|
||||
|
||||
CacheEntry<K, V> newEntry = new CacheEntry<>(key, newVal, queue);
|
||||
|
||||
entry = map.putIfAbsent(key, newEntry);
|
||||
if (entry == null) {
|
||||
value = newVal;
|
||||
} else {
|
||||
value = entry.get();
|
||||
if (value == null) {
|
||||
map.put(key, newEntry);
|
||||
value = newVal;
|
||||
}
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
protected V put(K key, V value) {
|
||||
CacheEntry<K, V> entry = new CacheEntry<>(key, value, queue);
|
||||
CacheEntry<K, V> oldEntry = map.put(key, entry);
|
||||
return (oldEntry == null) ? null : oldEntry.get();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void cleanStaleEntries() {
|
||||
CacheEntry<K, V> entry;
|
||||
while ((entry = (CacheEntry<K, V>)queue.poll()) != null) {
|
||||
map.remove(entry.getKey());
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract V createObject(K key);
|
||||
|
||||
protected K normalizeKey(K key) {
|
||||
return key;
|
||||
}
|
||||
|
||||
private static class CacheEntry<K, V> extends SoftReference<V> {
|
||||
private K key;
|
||||
|
||||
CacheEntry(K key, V value, ReferenceQueue<V> queue) {
|
||||
super(value, queue);
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
K getKey() {
|
||||
return key;
|
||||
}
|
||||
}
|
||||
}
|
||||
52
jdkSrc/jdk8/sun/util/locale/LocaleSyntaxException.java
Normal file
52
jdkSrc/jdk8/sun/util/locale/LocaleSyntaxException.java
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2009, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*/
|
||||
package sun.util.locale;
|
||||
|
||||
public class LocaleSyntaxException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private int index = -1;
|
||||
|
||||
public LocaleSyntaxException(String msg) {
|
||||
this(msg, 0);
|
||||
}
|
||||
|
||||
public LocaleSyntaxException(String msg, int errorIndex) {
|
||||
super(msg);
|
||||
index = errorIndex;
|
||||
}
|
||||
|
||||
public int getErrorIndex() {
|
||||
return index;
|
||||
}
|
||||
}
|
||||
224
jdkSrc/jdk8/sun/util/locale/LocaleUtils.java
Normal file
224
jdkSrc/jdk8/sun/util/locale/LocaleUtils.java
Normal file
@@ -0,0 +1,224 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2009, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*/
|
||||
package sun.util.locale;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Collection of static utility methods for Locale support. The
|
||||
* methods which manipulate characters or strings support ASCII only.
|
||||
*/
|
||||
public final class LocaleUtils {
|
||||
|
||||
private LocaleUtils() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two ASCII Strings s1 and s2, ignoring case.
|
||||
*/
|
||||
public static boolean caseIgnoreMatch(String s1, String s2) {
|
||||
if (s1 == s2) {
|
||||
return true;
|
||||
}
|
||||
|
||||
int len = s1.length();
|
||||
if (len != s2.length()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < len; i++) {
|
||||
char c1 = s1.charAt(i);
|
||||
char c2 = s2.charAt(i);
|
||||
if (c1 != c2 && toLower(c1) != toLower(c2)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static int caseIgnoreCompare(String s1, String s2) {
|
||||
if (s1 == s2) {
|
||||
return 0;
|
||||
}
|
||||
return toLowerString(s1).compareTo(toLowerString(s2));
|
||||
}
|
||||
|
||||
static char toUpper(char c) {
|
||||
return isLower(c) ? (char)(c - 0x20) : c;
|
||||
}
|
||||
|
||||
static char toLower(char c) {
|
||||
return isUpper(c) ? (char)(c + 0x20) : c;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the given ASCII String to lower-case.
|
||||
*/
|
||||
public static String toLowerString(String s) {
|
||||
int len = s.length();
|
||||
int idx = 0;
|
||||
for (; idx < len; idx++) {
|
||||
if (isUpper(s.charAt(idx))) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (idx == len) {
|
||||
return s;
|
||||
}
|
||||
|
||||
char[] buf = new char[len];
|
||||
for (int i = 0; i < len; i++) {
|
||||
char c = s.charAt(i);
|
||||
buf[i] = (i < idx) ? c : toLower(c);
|
||||
}
|
||||
return new String(buf);
|
||||
}
|
||||
|
||||
static String toUpperString(String s) {
|
||||
int len = s.length();
|
||||
int idx = 0;
|
||||
for (; idx < len; idx++) {
|
||||
if (isLower(s.charAt(idx))) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (idx == len) {
|
||||
return s;
|
||||
}
|
||||
|
||||
char[] buf = new char[len];
|
||||
for (int i = 0; i < len; i++) {
|
||||
char c = s.charAt(i);
|
||||
buf[i] = (i < idx) ? c : toUpper(c);
|
||||
}
|
||||
return new String(buf);
|
||||
}
|
||||
|
||||
static String toTitleString(String s) {
|
||||
int len;
|
||||
if ((len = s.length()) == 0) {
|
||||
return s;
|
||||
}
|
||||
int idx = 0;
|
||||
if (!isLower(s.charAt(idx))) {
|
||||
for (idx = 1; idx < len; idx++) {
|
||||
if (isUpper(s.charAt(idx))) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (idx == len) {
|
||||
return s;
|
||||
}
|
||||
|
||||
char[] buf = new char[len];
|
||||
for (int i = 0; i < len; i++) {
|
||||
char c = s.charAt(i);
|
||||
if (i == 0 && idx == 0) {
|
||||
buf[i] = toUpper(c);
|
||||
} else if (i < idx) {
|
||||
buf[i] = c;
|
||||
} else {
|
||||
buf[i] = toLower(c);
|
||||
}
|
||||
}
|
||||
return new String(buf);
|
||||
}
|
||||
|
||||
private static boolean isUpper(char c) {
|
||||
return c >= 'A' && c <= 'Z';
|
||||
}
|
||||
|
||||
private static boolean isLower(char c) {
|
||||
return c >= 'a' && c <= 'z';
|
||||
}
|
||||
|
||||
static boolean isAlpha(char c) {
|
||||
return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
|
||||
}
|
||||
|
||||
static boolean isAlphaString(String s) {
|
||||
int len = s.length();
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (!isAlpha(s.charAt(i))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static boolean isNumeric(char c) {
|
||||
return (c >= '0' && c <= '9');
|
||||
}
|
||||
|
||||
static boolean isNumericString(String s) {
|
||||
int len = s.length();
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (!isNumeric(s.charAt(i))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static boolean isAlphaNumeric(char c) {
|
||||
return isAlpha(c) || isNumeric(c);
|
||||
}
|
||||
|
||||
public static boolean isAlphaNumericString(String s) {
|
||||
int len = s.length();
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (!isAlphaNumeric(s.charAt(i))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static boolean isEmpty(String str) {
|
||||
return str == null || str.length() == 0;
|
||||
}
|
||||
|
||||
static boolean isEmpty(Set<?> set) {
|
||||
return set == null || set.isEmpty();
|
||||
}
|
||||
|
||||
static boolean isEmpty(Map<?, ?> map) {
|
||||
return map == null || map.isEmpty();
|
||||
}
|
||||
|
||||
static boolean isEmpty(List<?> list) {
|
||||
return list == null || list.isEmpty();
|
||||
}
|
||||
}
|
||||
64
jdkSrc/jdk8/sun/util/locale/ParseStatus.java
Normal file
64
jdkSrc/jdk8/sun/util/locale/ParseStatus.java
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2010, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*/
|
||||
package sun.util.locale;
|
||||
|
||||
public class ParseStatus {
|
||||
int parseLength;
|
||||
int errorIndex;
|
||||
String errorMsg;
|
||||
|
||||
public ParseStatus() {
|
||||
reset();
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
parseLength = 0;
|
||||
errorIndex = -1;
|
||||
errorMsg = null;
|
||||
}
|
||||
|
||||
public boolean isError() {
|
||||
return (errorIndex >= 0);
|
||||
}
|
||||
|
||||
public int getErrorIndex() {
|
||||
return errorIndex;
|
||||
}
|
||||
|
||||
public int getParseLength() {
|
||||
return parseLength;
|
||||
}
|
||||
|
||||
public String getErrorMessage() {
|
||||
return errorMsg;
|
||||
}
|
||||
}
|
||||
129
jdkSrc/jdk8/sun/util/locale/StringTokenIterator.java
Normal file
129
jdkSrc/jdk8/sun/util/locale/StringTokenIterator.java
Normal file
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2009, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*/
|
||||
package sun.util.locale;
|
||||
|
||||
public class StringTokenIterator {
|
||||
private String text;
|
||||
private String dlms; // null if a single char delimiter
|
||||
private char delimiterChar; // delimiter if a single char delimiter
|
||||
|
||||
private String token;
|
||||
private int start;
|
||||
private int end;
|
||||
private boolean done;
|
||||
|
||||
public StringTokenIterator(String text, String dlms) {
|
||||
this.text = text;
|
||||
if (dlms.length() == 1) {
|
||||
delimiterChar = dlms.charAt(0);
|
||||
} else {
|
||||
this.dlms = dlms;
|
||||
}
|
||||
setStart(0);
|
||||
}
|
||||
|
||||
public String first() {
|
||||
setStart(0);
|
||||
return token;
|
||||
}
|
||||
|
||||
public String current() {
|
||||
return token;
|
||||
}
|
||||
|
||||
public int currentStart() {
|
||||
return start;
|
||||
}
|
||||
|
||||
public int currentEnd() {
|
||||
return end;
|
||||
}
|
||||
|
||||
public boolean isDone() {
|
||||
return done;
|
||||
}
|
||||
|
||||
public String next() {
|
||||
if (hasNext()) {
|
||||
start = end + 1;
|
||||
end = nextDelimiter(start);
|
||||
token = text.substring(start, end);
|
||||
} else {
|
||||
start = end;
|
||||
token = null;
|
||||
done = true;
|
||||
}
|
||||
return token;
|
||||
}
|
||||
|
||||
public boolean hasNext() {
|
||||
return (end < text.length());
|
||||
}
|
||||
|
||||
public StringTokenIterator setStart(int offset) {
|
||||
if (offset > text.length()) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
start = offset;
|
||||
end = nextDelimiter(start);
|
||||
token = text.substring(start, end);
|
||||
done = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
public StringTokenIterator setText(String text) {
|
||||
this.text = text;
|
||||
setStart(0);
|
||||
return this;
|
||||
}
|
||||
|
||||
private int nextDelimiter(int start) {
|
||||
int textlen = this.text.length();
|
||||
if (dlms == null) {
|
||||
for (int idx = start; idx < textlen; idx++) {
|
||||
if (text.charAt(idx) == delimiterChar) {
|
||||
return idx;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int dlmslen = dlms.length();
|
||||
for (int idx = start; idx < textlen; idx++) {
|
||||
char c = text.charAt(idx);
|
||||
for (int i = 0; i < dlmslen; i++) {
|
||||
if (c == dlms.charAt(i)) {
|
||||
return idx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return textlen;
|
||||
}
|
||||
}
|
||||
128
jdkSrc/jdk8/sun/util/locale/UnicodeLocaleExtension.java
Normal file
128
jdkSrc/jdk8/sun/util/locale/UnicodeLocaleExtension.java
Normal file
@@ -0,0 +1,128 @@
|
||||
|
||||
/*
|
||||
* Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2009-2010, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*/
|
||||
package sun.util.locale;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.SortedMap;
|
||||
import java.util.SortedSet;
|
||||
|
||||
public class UnicodeLocaleExtension extends Extension {
|
||||
public static final char SINGLETON = 'u';
|
||||
|
||||
private final Set<String> attributes;
|
||||
private final Map<String, String> keywords;
|
||||
|
||||
public static final UnicodeLocaleExtension CA_JAPANESE
|
||||
= new UnicodeLocaleExtension("ca", "japanese");
|
||||
public static final UnicodeLocaleExtension NU_THAI
|
||||
= new UnicodeLocaleExtension("nu", "thai");
|
||||
|
||||
private UnicodeLocaleExtension(String key, String value) {
|
||||
super(SINGLETON, key + "-" + value);
|
||||
attributes = Collections.emptySet();
|
||||
keywords = Collections.singletonMap(key, value);
|
||||
}
|
||||
|
||||
UnicodeLocaleExtension(SortedSet<String> attributes, SortedMap<String, String> keywords) {
|
||||
super(SINGLETON);
|
||||
if (attributes != null) {
|
||||
this.attributes = attributes;
|
||||
} else {
|
||||
this.attributes = Collections.emptySet();
|
||||
}
|
||||
if (keywords != null) {
|
||||
this.keywords = keywords;
|
||||
} else {
|
||||
this.keywords = Collections.emptyMap();
|
||||
}
|
||||
|
||||
if (!this.attributes.isEmpty() || !this.keywords.isEmpty()) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (String attribute : this.attributes) {
|
||||
sb.append(LanguageTag.SEP).append(attribute);
|
||||
}
|
||||
for (Entry<String, String> keyword : this.keywords.entrySet()) {
|
||||
String key = keyword.getKey();
|
||||
String value = keyword.getValue();
|
||||
|
||||
sb.append(LanguageTag.SEP).append(key);
|
||||
if (value.length() > 0) {
|
||||
sb.append(LanguageTag.SEP).append(value);
|
||||
}
|
||||
}
|
||||
setValue(sb.substring(1)); // skip leading '-'
|
||||
}
|
||||
}
|
||||
|
||||
public Set<String> getUnicodeLocaleAttributes() {
|
||||
if (attributes == Collections.EMPTY_SET) {
|
||||
return attributes;
|
||||
}
|
||||
return Collections.unmodifiableSet(attributes);
|
||||
}
|
||||
|
||||
public Set<String> getUnicodeLocaleKeys() {
|
||||
if (keywords == Collections.EMPTY_MAP) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
return Collections.unmodifiableSet(keywords.keySet());
|
||||
}
|
||||
|
||||
public String getUnicodeLocaleType(String unicodeLocaleKey) {
|
||||
return keywords.get(unicodeLocaleKey);
|
||||
}
|
||||
|
||||
public static boolean isSingletonChar(char c) {
|
||||
return (SINGLETON == LocaleUtils.toLower(c));
|
||||
}
|
||||
|
||||
public static boolean isAttribute(String s) {
|
||||
// 3*8alphanum
|
||||
int len = s.length();
|
||||
return (len >= 3) && (len <= 8) && LocaleUtils.isAlphaNumericString(s);
|
||||
}
|
||||
|
||||
public static boolean isKey(String s) {
|
||||
// 2alphanum
|
||||
return (s.length() == 2) && LocaleUtils.isAlphaNumericString(s);
|
||||
}
|
||||
|
||||
public static boolean isTypeSubtag(String s) {
|
||||
// 3*8alphanum
|
||||
int len = s.length();
|
||||
return (len >= 3) && (len <= 8) && LocaleUtils.isAlphaNumericString(s);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,188 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.util.locale.provider;
|
||||
|
||||
import java.text.spi.BreakIteratorProvider;
|
||||
import java.text.spi.CollatorProvider;
|
||||
import java.text.spi.DateFormatProvider;
|
||||
import java.text.spi.DateFormatSymbolsProvider;
|
||||
import java.text.spi.DecimalFormatSymbolsProvider;
|
||||
import java.text.spi.NumberFormatProvider;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.spi.CalendarDataProvider;
|
||||
import java.util.spi.CalendarNameProvider;
|
||||
import java.util.spi.CurrencyNameProvider;
|
||||
import java.util.spi.LocaleNameProvider;
|
||||
import java.util.spi.LocaleServiceProvider;
|
||||
import java.util.spi.TimeZoneNameProvider;
|
||||
import sun.util.spi.CalendarProvider;
|
||||
|
||||
/**
|
||||
* An abstract parent class for the
|
||||
* HostLocaleProviderAdapter/SPILocaleProviderAdapter.
|
||||
*
|
||||
* @author Naoto Sato
|
||||
* @author Masayoshi Okutsu
|
||||
*/
|
||||
public abstract class AuxLocaleProviderAdapter extends LocaleProviderAdapter {
|
||||
/**
|
||||
* SPI implementations map
|
||||
*/
|
||||
private ConcurrentMap<Class<? extends LocaleServiceProvider>, LocaleServiceProvider> providersMap =
|
||||
new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* Getter method for Locale Service Providers
|
||||
*/
|
||||
@Override
|
||||
public <P extends LocaleServiceProvider> P getLocaleServiceProvider(Class<P> c) {
|
||||
@SuppressWarnings("unchecked")
|
||||
P lsp = (P) providersMap.get(c);
|
||||
if (lsp == null) {
|
||||
lsp = findInstalledProvider(c);
|
||||
providersMap.putIfAbsent(c, lsp == null ? NULL_PROVIDER : lsp);
|
||||
}
|
||||
|
||||
return lsp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Real body to find an implementation for each SPI.
|
||||
*
|
||||
* @param <P>
|
||||
* @param c
|
||||
* @return
|
||||
*/
|
||||
protected abstract <P extends LocaleServiceProvider> P findInstalledProvider(final Class<P> c);
|
||||
|
||||
@Override
|
||||
public BreakIteratorProvider getBreakIteratorProvider() {
|
||||
return getLocaleServiceProvider(BreakIteratorProvider.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CollatorProvider getCollatorProvider() {
|
||||
return getLocaleServiceProvider(CollatorProvider.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DateFormatProvider getDateFormatProvider() {
|
||||
return getLocaleServiceProvider(DateFormatProvider.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DateFormatSymbolsProvider getDateFormatSymbolsProvider() {
|
||||
return getLocaleServiceProvider(DateFormatSymbolsProvider.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DecimalFormatSymbolsProvider getDecimalFormatSymbolsProvider() {
|
||||
return getLocaleServiceProvider(DecimalFormatSymbolsProvider.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NumberFormatProvider getNumberFormatProvider() {
|
||||
return getLocaleServiceProvider(NumberFormatProvider.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter methods for java.util.spi.* providers
|
||||
*/
|
||||
@Override
|
||||
public CurrencyNameProvider getCurrencyNameProvider() {
|
||||
return getLocaleServiceProvider(CurrencyNameProvider.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocaleNameProvider getLocaleNameProvider() {
|
||||
return getLocaleServiceProvider(LocaleNameProvider.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TimeZoneNameProvider getTimeZoneNameProvider() {
|
||||
return getLocaleServiceProvider(TimeZoneNameProvider.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CalendarDataProvider getCalendarDataProvider() {
|
||||
return getLocaleServiceProvider(CalendarDataProvider.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CalendarNameProvider getCalendarNameProvider() {
|
||||
return getLocaleServiceProvider(CalendarNameProvider.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter methods for sun.util.spi.* providers
|
||||
*/
|
||||
@Override
|
||||
public CalendarProvider getCalendarProvider() {
|
||||
return getLocaleServiceProvider(CalendarProvider.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocaleResources getLocaleResources(Locale locale) {
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Locale[] availableLocales = null;
|
||||
|
||||
@Override
|
||||
public Locale[] getAvailableLocales() {
|
||||
if (availableLocales == null) {
|
||||
Set<Locale> avail = new HashSet<>();
|
||||
for (Class<? extends LocaleServiceProvider> c :
|
||||
LocaleServiceProviderPool.spiClasses) {
|
||||
LocaleServiceProvider lsp = getLocaleServiceProvider(c);
|
||||
if (lsp != null) {
|
||||
avail.addAll(Arrays.asList(lsp.getAvailableLocales()));
|
||||
}
|
||||
}
|
||||
availableLocales = avail.toArray(new Locale[0]);
|
||||
}
|
||||
|
||||
// assuming caller won't mutate the array.
|
||||
return availableLocales;
|
||||
}
|
||||
|
||||
/**
|
||||
* A dummy locale service provider that indicates there is no
|
||||
* provider available
|
||||
*/
|
||||
private static NullProvider NULL_PROVIDER = new NullProvider();
|
||||
private static class NullProvider extends LocaleServiceProvider {
|
||||
@Override
|
||||
public Locale[] getAvailableLocales() {
|
||||
return new Locale[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.util.locale.provider;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* An interface to return a set of available language tags supported by a
|
||||
* LocaleServiceProvider.
|
||||
*
|
||||
* @author Masayoshi Okutsu
|
||||
*/
|
||||
public interface AvailableLanguageTags {
|
||||
/**
|
||||
* Returns a set of available language tags of a LocaleServiceProvider.
|
||||
* Note that the returned set doesn't contain the language tag for
|
||||
* {@code Locale.Root}.
|
||||
*
|
||||
* @return a Set of available language tags.
|
||||
*/
|
||||
public Set<String> getAvailableLanguageTags();
|
||||
}
|
||||
343
jdkSrc/jdk8/sun/util/locale/provider/BreakDictionary.java
Normal file
343
jdkSrc/jdk8/sun/util/locale/provider/BreakDictionary.java
Normal file
@@ -0,0 +1,343 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
* (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
|
||||
* (C) Copyright IBM Corp. 1996 - 2002 - All Rights Reserved
|
||||
*
|
||||
* The original version of this source code and documentation
|
||||
* is copyrighted and owned by Taligent, Inc., a wholly-owned
|
||||
* subsidiary of IBM. These materials are provided under terms
|
||||
* of a License Agreement between Taligent and Sun. This technology
|
||||
* is protected by multiple US and International patents.
|
||||
*
|
||||
* This notice and attribution to Taligent may not be removed.
|
||||
* Taligent is a registered trademark of Taligent, Inc.
|
||||
*/
|
||||
package sun.util.locale.provider;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.IOException;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedActionException;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
import java.util.MissingResourceException;
|
||||
import sun.text.CompactByteArray;
|
||||
import sun.text.SupplementaryCharacterData;
|
||||
|
||||
/**
|
||||
* This is the class that represents the list of known words used by
|
||||
* DictionaryBasedBreakIterator. The conceptual data structure used
|
||||
* here is a trie: there is a node hanging off the root node for every
|
||||
* letter that can start a word. Each of these nodes has a node hanging
|
||||
* off of it for every letter that can be the second letter of a word
|
||||
* if this node is the first letter, and so on. The trie is represented
|
||||
* as a two-dimensional array that can be treated as a table of state
|
||||
* transitions. Indexes are used to compress this array, taking
|
||||
* advantage of the fact that this array will always be very sparse.
|
||||
*/
|
||||
class BreakDictionary {
|
||||
|
||||
//=========================================================================
|
||||
// data members
|
||||
//=========================================================================
|
||||
|
||||
/**
|
||||
* The version of the dictionary that was read in.
|
||||
*/
|
||||
private static int supportedVersion = 1;
|
||||
|
||||
/**
|
||||
* Maps from characters to column numbers. The main use of this is to
|
||||
* avoid making room in the array for empty columns.
|
||||
*/
|
||||
private CompactByteArray columnMap = null;
|
||||
private SupplementaryCharacterData supplementaryCharColumnMap = null;
|
||||
|
||||
/**
|
||||
* The number of actual columns in the table
|
||||
*/
|
||||
private int numCols;
|
||||
|
||||
/**
|
||||
* Columns are organized into groups of 32. This says how many
|
||||
* column groups. (We could calculate this, but we store the
|
||||
* value to avoid having to repeatedly calculate it.)
|
||||
*/
|
||||
private int numColGroups;
|
||||
|
||||
/**
|
||||
* The actual compressed state table. Each conceptual row represents
|
||||
* a state, and the cells in it contain the row numbers of the states
|
||||
* to transition to for each possible letter. 0 is used to indicate
|
||||
* an illegal combination of letters (i.e., the error state). The
|
||||
* table is compressed by eliminating all the unpopulated (i.e., zero)
|
||||
* cells. Multiple conceptual rows can then be doubled up in a single
|
||||
* physical row by sliding them up and possibly shifting them to one
|
||||
* side or the other so the populated cells don't collide. Indexes
|
||||
* are used to identify unpopulated cells and to locate populated cells.
|
||||
*/
|
||||
private short[] table = null;
|
||||
|
||||
/**
|
||||
* This index maps logical row numbers to physical row numbers
|
||||
*/
|
||||
private short[] rowIndex = null;
|
||||
|
||||
/**
|
||||
* A bitmap is used to tell which cells in the comceptual table are
|
||||
* populated. This array contains all the unique bit combinations
|
||||
* in that bitmap. If the table is more than 32 columns wide,
|
||||
* successive entries in this array are used for a single row.
|
||||
*/
|
||||
private int[] rowIndexFlags = null;
|
||||
|
||||
/**
|
||||
* This index maps from a logical row number into the bitmap table above.
|
||||
* (This keeps us from storing duplicate bitmap combinations.) Since there
|
||||
* are a lot of rows with only one populated cell, instead of wasting space
|
||||
* in the bitmap table, we just store a negative number in this index for
|
||||
* rows with one populated cell. The absolute value of that number is
|
||||
* the column number of the populated cell.
|
||||
*/
|
||||
private short[] rowIndexFlagsIndex = null;
|
||||
|
||||
/**
|
||||
* For each logical row, this index contains a constant that is added to
|
||||
* the logical column number to get the physical column number
|
||||
*/
|
||||
private byte[] rowIndexShifts = null;
|
||||
|
||||
//=========================================================================
|
||||
// deserialization
|
||||
//=========================================================================
|
||||
|
||||
BreakDictionary(String dictionaryName)
|
||||
throws IOException, MissingResourceException {
|
||||
|
||||
readDictionaryFile(dictionaryName);
|
||||
}
|
||||
|
||||
private void readDictionaryFile(final String dictionaryName)
|
||||
throws IOException, MissingResourceException {
|
||||
|
||||
BufferedInputStream in;
|
||||
try {
|
||||
in = AccessController.doPrivileged(
|
||||
new PrivilegedExceptionAction<BufferedInputStream>() {
|
||||
@Override
|
||||
public BufferedInputStream run() throws Exception {
|
||||
return new BufferedInputStream(getClass().getResourceAsStream("/sun/text/resources/" + dictionaryName));
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
catch (PrivilegedActionException e) {
|
||||
throw new InternalError(e.toString(), e);
|
||||
}
|
||||
|
||||
byte[] buf = new byte[8];
|
||||
if (in.read(buf) != 8) {
|
||||
throw new MissingResourceException("Wrong data length",
|
||||
dictionaryName, "");
|
||||
}
|
||||
|
||||
// check version
|
||||
int version = RuleBasedBreakIterator.getInt(buf, 0);
|
||||
if (version != supportedVersion) {
|
||||
throw new MissingResourceException("Dictionary version(" + version + ") is unsupported",
|
||||
dictionaryName, "");
|
||||
}
|
||||
|
||||
// get data size
|
||||
int len = RuleBasedBreakIterator.getInt(buf, 4);
|
||||
buf = new byte[len];
|
||||
if (in.read(buf) != len) {
|
||||
throw new MissingResourceException("Wrong data length",
|
||||
dictionaryName, "");
|
||||
}
|
||||
|
||||
// close the stream
|
||||
in.close();
|
||||
|
||||
int l;
|
||||
int offset = 0;
|
||||
|
||||
// read in the column map for BMP characteres (this is serialized in
|
||||
// its internal form: an index array followed by a data array)
|
||||
l = RuleBasedBreakIterator.getInt(buf, offset);
|
||||
offset += 4;
|
||||
short[] temp = new short[l];
|
||||
for (int i = 0; i < l; i++, offset+=2) {
|
||||
temp[i] = RuleBasedBreakIterator.getShort(buf, offset);
|
||||
}
|
||||
l = RuleBasedBreakIterator.getInt(buf, offset);
|
||||
offset += 4;
|
||||
byte[] temp2 = new byte[l];
|
||||
for (int i = 0; i < l; i++, offset++) {
|
||||
temp2[i] = buf[offset];
|
||||
}
|
||||
columnMap = new CompactByteArray(temp, temp2);
|
||||
|
||||
// read in numCols and numColGroups
|
||||
numCols = RuleBasedBreakIterator.getInt(buf, offset);
|
||||
offset += 4;
|
||||
numColGroups = RuleBasedBreakIterator.getInt(buf, offset);
|
||||
offset += 4;
|
||||
|
||||
// read in the row-number index
|
||||
l = RuleBasedBreakIterator.getInt(buf, offset);
|
||||
offset += 4;
|
||||
rowIndex = new short[l];
|
||||
for (int i = 0; i < l; i++, offset+=2) {
|
||||
rowIndex[i] = RuleBasedBreakIterator.getShort(buf, offset);
|
||||
}
|
||||
|
||||
// load in the populated-cells bitmap: index first, then bitmap list
|
||||
l = RuleBasedBreakIterator.getInt(buf, offset);
|
||||
offset += 4;
|
||||
rowIndexFlagsIndex = new short[l];
|
||||
for (int i = 0; i < l; i++, offset+=2) {
|
||||
rowIndexFlagsIndex[i] = RuleBasedBreakIterator.getShort(buf, offset);
|
||||
}
|
||||
l = RuleBasedBreakIterator.getInt(buf, offset);
|
||||
offset += 4;
|
||||
rowIndexFlags = new int[l];
|
||||
for (int i = 0; i < l; i++, offset+=4) {
|
||||
rowIndexFlags[i] = RuleBasedBreakIterator.getInt(buf, offset);
|
||||
}
|
||||
|
||||
// load in the row-shift index
|
||||
l = RuleBasedBreakIterator.getInt(buf, offset);
|
||||
offset += 4;
|
||||
rowIndexShifts = new byte[l];
|
||||
for (int i = 0; i < l; i++, offset++) {
|
||||
rowIndexShifts[i] = buf[offset];
|
||||
}
|
||||
|
||||
// load in the actual state table
|
||||
l = RuleBasedBreakIterator.getInt(buf, offset);
|
||||
offset += 4;
|
||||
table = new short[l];
|
||||
for (int i = 0; i < l; i++, offset+=2) {
|
||||
table[i] = RuleBasedBreakIterator.getShort(buf, offset);
|
||||
}
|
||||
|
||||
// finally, prepare the column map for supplementary characters
|
||||
l = RuleBasedBreakIterator.getInt(buf, offset);
|
||||
offset += 4;
|
||||
int[] temp3 = new int[l];
|
||||
for (int i = 0; i < l; i++, offset+=4) {
|
||||
temp3[i] = RuleBasedBreakIterator.getInt(buf, offset);
|
||||
}
|
||||
supplementaryCharColumnMap = new SupplementaryCharacterData(temp3);
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
// access to the words
|
||||
//=========================================================================
|
||||
|
||||
/**
|
||||
* Uses the column map to map the character to a column number, then
|
||||
* passes the row and column number to getNextState()
|
||||
* @param row The current state
|
||||
* @param ch The character whose column we're interested in
|
||||
* @return The new state to transition to
|
||||
*/
|
||||
public final short getNextStateFromCharacter(int row, int ch) {
|
||||
int col;
|
||||
if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
|
||||
col = columnMap.elementAt((char)ch);
|
||||
} else {
|
||||
col = supplementaryCharColumnMap.getValue(ch);
|
||||
}
|
||||
return getNextState(row, col);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value in the cell with the specified (logical) row and
|
||||
* column numbers. In DictionaryBasedBreakIterator, the row number is
|
||||
* a state number, the column number is an input, and the return value
|
||||
* is the row number of the new state to transition to. (0 is the
|
||||
* "error" state, and -1 is the "end of word" state in a dictionary)
|
||||
* @param row The row number of the current state
|
||||
* @param col The column number of the input character (0 means "not a
|
||||
* dictionary character")
|
||||
* @return The row number of the new state to transition to
|
||||
*/
|
||||
public final short getNextState(int row, int col) {
|
||||
if (cellIsPopulated(row, col)) {
|
||||
// we map from logical to physical row number by looking up the
|
||||
// mapping in rowIndex; we map from logical column number to
|
||||
// physical column number by looking up a shift value for this
|
||||
// logical row and offsetting the logical column number by
|
||||
// the shift amount. Then we can use internalAt() to actually
|
||||
// get the value out of the table.
|
||||
return internalAt(rowIndex[row], col + rowIndexShifts[row]);
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Given (logical) row and column numbers, returns true if the
|
||||
* cell in that position is populated
|
||||
*/
|
||||
private boolean cellIsPopulated(int row, int col) {
|
||||
// look up the entry in the bitmap index for the specified row.
|
||||
// If it's a negative number, it's the column number of the only
|
||||
// populated cell in the row
|
||||
if (rowIndexFlagsIndex[row] < 0) {
|
||||
return col == -rowIndexFlagsIndex[row];
|
||||
}
|
||||
|
||||
// if it's a positive number, it's the offset of an entry in the bitmap
|
||||
// list. If the table is more than 32 columns wide, the bitmap is stored
|
||||
// successive entries in the bitmap list, so we have to divide the column
|
||||
// number by 32 and offset the number we got out of the index by the result.
|
||||
// Once we have the appropriate piece of the bitmap, test the appropriate
|
||||
// bit and return the result.
|
||||
else {
|
||||
int flags = rowIndexFlags[rowIndexFlagsIndex[row] + (col >> 5)];
|
||||
return (flags & (1 << (col & 0x1f))) != 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of getNextState() when we know the specified cell is
|
||||
* populated.
|
||||
* @param row The PHYSICAL row number of the cell
|
||||
* @param col The PHYSICAL column number of the cell
|
||||
* @return The value stored in the cell
|
||||
*/
|
||||
private short internalAt(int row, int col) {
|
||||
// the table is a one-dimensional array, so this just does the math necessary
|
||||
// to treat it as a two-dimensional array (we don't just use a two-dimensional
|
||||
// array because two-dimensional arrays are inefficient in Java)
|
||||
return table[row * numCols + col];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.util.locale.provider;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.text.BreakIterator;
|
||||
import java.text.spi.BreakIteratorProvider;
|
||||
import java.util.Locale;
|
||||
import java.util.MissingResourceException;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Concrete implementation of the {@link java.text.spi.BreakIteratorProvider
|
||||
* BreakIteratorProvider} class for the JRE LocaleProviderAdapter.
|
||||
*
|
||||
* @author Naoto Sato
|
||||
* @author Masayoshi Okutsu
|
||||
*/
|
||||
public class BreakIteratorProviderImpl extends BreakIteratorProvider
|
||||
implements AvailableLanguageTags {
|
||||
|
||||
private static final int CHARACTER_INDEX = 0;
|
||||
private static final int WORD_INDEX = 1;
|
||||
private static final int LINE_INDEX = 2;
|
||||
private static final int SENTENCE_INDEX = 3;
|
||||
|
||||
private final LocaleProviderAdapter.Type type;
|
||||
private final Set<String> langtags;
|
||||
|
||||
public BreakIteratorProviderImpl(LocaleProviderAdapter.Type type, Set<String> langtags) {
|
||||
this.type = type;
|
||||
this.langtags = langtags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of all locales for which this locale service provider
|
||||
* can provide localized objects or names.
|
||||
*
|
||||
* @return An array of all locales for which this locale service provider
|
||||
* can provide localized objects or names.
|
||||
*/
|
||||
@Override
|
||||
public Locale[] getAvailableLocales() {
|
||||
return LocaleProviderAdapter.toLocaleArray(langtags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new <code>BreakIterator</code> instance
|
||||
* for <a href="../BreakIterator.html#word">word breaks</a>
|
||||
* for the given locale.
|
||||
* @param locale the desired locale
|
||||
* @return A break iterator for word breaks
|
||||
* @exception NullPointerException if <code>locale</code> is null
|
||||
* @exception IllegalArgumentException if <code>locale</code> isn't
|
||||
* one of the locales returned from
|
||||
* {@link java.util.spi.LocaleServiceProvider#getAvailableLocales()
|
||||
* getAvailableLocales()}.
|
||||
* @see java.text.BreakIterator#getWordInstance(java.util.Locale)
|
||||
*/
|
||||
@Override
|
||||
public BreakIterator getWordInstance(Locale locale) {
|
||||
return getBreakInstance(locale,
|
||||
WORD_INDEX,
|
||||
"WordData",
|
||||
"WordDictionary");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new <code>BreakIterator</code> instance
|
||||
* for <a href="../BreakIterator.html#line">line breaks</a>
|
||||
* for the given locale.
|
||||
* @param locale the desired locale
|
||||
* @return A break iterator for line breaks
|
||||
* @exception NullPointerException if <code>locale</code> is null
|
||||
* @exception IllegalArgumentException if <code>locale</code> isn't
|
||||
* one of the locales returned from
|
||||
* {@link java.util.spi.LocaleServiceProvider#getAvailableLocales()
|
||||
* getAvailableLocales()}.
|
||||
* @see java.text.BreakIterator#getLineInstance(java.util.Locale)
|
||||
*/
|
||||
@Override
|
||||
public BreakIterator getLineInstance(Locale locale) {
|
||||
return getBreakInstance(locale,
|
||||
LINE_INDEX,
|
||||
"LineData",
|
||||
"LineDictionary");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new <code>BreakIterator</code> instance
|
||||
* for <a href="../BreakIterator.html#character">character breaks</a>
|
||||
* for the given locale.
|
||||
* @param locale the desired locale
|
||||
* @return A break iterator for character breaks
|
||||
* @exception NullPointerException if <code>locale</code> is null
|
||||
* @exception IllegalArgumentException if <code>locale</code> isn't
|
||||
* one of the locales returned from
|
||||
* {@link java.util.spi.LocaleServiceProvider#getAvailableLocales()
|
||||
* getAvailableLocales()}.
|
||||
* @see java.text.BreakIterator#getCharacterInstance(java.util.Locale)
|
||||
*/
|
||||
@Override
|
||||
public BreakIterator getCharacterInstance(Locale locale) {
|
||||
return getBreakInstance(locale,
|
||||
CHARACTER_INDEX,
|
||||
"CharacterData",
|
||||
"CharacterDictionary");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new <code>BreakIterator</code> instance
|
||||
* for <a href="../BreakIterator.html#sentence">sentence breaks</a>
|
||||
* for the given locale.
|
||||
* @param locale the desired locale
|
||||
* @return A break iterator for sentence breaks
|
||||
* @exception NullPointerException if <code>locale</code> is null
|
||||
* @exception IllegalArgumentException if <code>locale</code> isn't
|
||||
* one of the locales returned from
|
||||
* {@link java.util.spi.LocaleServiceProvider#getAvailableLocales()
|
||||
* getAvailableLocales()}.
|
||||
* @see java.text.BreakIterator#getSentenceInstance(java.util.Locale)
|
||||
*/
|
||||
@Override
|
||||
public BreakIterator getSentenceInstance(Locale locale) {
|
||||
return getBreakInstance(locale,
|
||||
SENTENCE_INDEX,
|
||||
"SentenceData",
|
||||
"SentenceDictionary");
|
||||
}
|
||||
|
||||
private BreakIterator getBreakInstance(Locale locale,
|
||||
int type,
|
||||
String dataName,
|
||||
String dictionaryName) {
|
||||
if (locale == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
|
||||
LocaleResources lr = LocaleProviderAdapter.forJRE().getLocaleResources(locale);
|
||||
String[] classNames = (String[]) lr.getBreakIteratorInfo("BreakIteratorClasses");
|
||||
String dataFile = (String) lr.getBreakIteratorInfo(dataName);
|
||||
|
||||
try {
|
||||
switch (classNames[type]) {
|
||||
case "RuleBasedBreakIterator":
|
||||
return new RuleBasedBreakIterator(dataFile);
|
||||
case "DictionaryBasedBreakIterator":
|
||||
String dictionaryFile = (String) lr.getBreakIteratorInfo(dictionaryName);
|
||||
return new DictionaryBasedBreakIterator(dataFile, dictionaryFile);
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid break iterator class \"" +
|
||||
classNames[type] + "\"");
|
||||
}
|
||||
} catch (IOException | MissingResourceException | IllegalArgumentException e) {
|
||||
throw new InternalError(e.toString(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getAvailableLanguageTags() {
|
||||
return langtags;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupportedLocale(Locale locale) {
|
||||
return LocaleProviderAdapter.isSupportedLocale(locale, type, langtags);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package sun.util.locale.provider;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import java.util.spi.CalendarDataProvider;
|
||||
|
||||
/**
|
||||
* Concrete implementation of the {@link java.util.spi.CalendarDataProvider
|
||||
* CalendarDataProvider} class for the JRE LocaleProviderAdapter.
|
||||
*
|
||||
* @author Masayoshi Okutsu
|
||||
* @author Naoto Sato
|
||||
*/
|
||||
public class CalendarDataProviderImpl extends CalendarDataProvider implements AvailableLanguageTags {
|
||||
private final LocaleProviderAdapter.Type type;
|
||||
private final Set<String> langtags;
|
||||
|
||||
public CalendarDataProviderImpl(LocaleProviderAdapter.Type type, Set<String> langtags) {
|
||||
this.type = type;
|
||||
this.langtags = langtags;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFirstDayOfWeek(Locale locale) {
|
||||
return LocaleProviderAdapter.forType(type).getLocaleResources(locale)
|
||||
.getCalendarData(CalendarDataUtility.FIRST_DAY_OF_WEEK);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinimalDaysInFirstWeek(Locale locale) {
|
||||
return LocaleProviderAdapter.forType(type).getLocaleResources(locale)
|
||||
.getCalendarData(CalendarDataUtility.MINIMAL_DAYS_IN_FIRST_WEEK);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Locale[] getAvailableLocales() {
|
||||
return LocaleProviderAdapter.toLocaleArray(langtags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getAvailableLanguageTags() {
|
||||
return langtags;
|
||||
}
|
||||
}
|
||||
208
jdkSrc/jdk8/sun/util/locale/provider/CalendarDataUtility.java
Normal file
208
jdkSrc/jdk8/sun/util/locale/provider/CalendarDataUtility.java
Normal file
@@ -0,0 +1,208 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.util.locale.provider;
|
||||
|
||||
import static java.util.Calendar.*;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.spi.CalendarDataProvider;
|
||||
import java.util.spi.CalendarNameProvider;
|
||||
|
||||
/**
|
||||
* {@code CalendarDataUtility} is a utility class for calling the
|
||||
* {@link CalendarDataProvider} methods.
|
||||
*
|
||||
* @author Masayoshi Okutsu
|
||||
* @author Naoto Sato
|
||||
*/
|
||||
public class CalendarDataUtility {
|
||||
public final static String FIRST_DAY_OF_WEEK = "firstDayOfWeek";
|
||||
public final static String MINIMAL_DAYS_IN_FIRST_WEEK = "minimalDaysInFirstWeek";
|
||||
|
||||
// No instantiation
|
||||
private CalendarDataUtility() {
|
||||
}
|
||||
|
||||
public static int retrieveFirstDayOfWeek(Locale locale) {
|
||||
LocaleServiceProviderPool pool =
|
||||
LocaleServiceProviderPool.getPool(CalendarDataProvider.class);
|
||||
Integer value = pool.getLocalizedObject(CalendarWeekParameterGetter.INSTANCE,
|
||||
locale, FIRST_DAY_OF_WEEK);
|
||||
return (value != null && (value >= SUNDAY && value <= SATURDAY)) ? value : SUNDAY;
|
||||
}
|
||||
|
||||
public static int retrieveMinimalDaysInFirstWeek(Locale locale) {
|
||||
LocaleServiceProviderPool pool =
|
||||
LocaleServiceProviderPool.getPool(CalendarDataProvider.class);
|
||||
Integer value = pool.getLocalizedObject(CalendarWeekParameterGetter.INSTANCE,
|
||||
locale, MINIMAL_DAYS_IN_FIRST_WEEK);
|
||||
return (value != null && (value >= 1 && value <= 7)) ? value : 1;
|
||||
}
|
||||
|
||||
public static String retrieveFieldValueName(String id, int field, int value, int style, Locale locale) {
|
||||
LocaleServiceProviderPool pool =
|
||||
LocaleServiceProviderPool.getPool(CalendarNameProvider.class);
|
||||
return pool.getLocalizedObject(CalendarFieldValueNameGetter.INSTANCE, locale, normalizeCalendarType(id),
|
||||
field, value, style, false);
|
||||
}
|
||||
|
||||
public static String retrieveJavaTimeFieldValueName(String id, int field, int value, int style, Locale locale) {
|
||||
LocaleServiceProviderPool pool =
|
||||
LocaleServiceProviderPool.getPool(CalendarNameProvider.class);
|
||||
String name;
|
||||
name = pool.getLocalizedObject(CalendarFieldValueNameGetter.INSTANCE, locale, normalizeCalendarType(id),
|
||||
field, value, style, true);
|
||||
if (name == null) {
|
||||
name = pool.getLocalizedObject(CalendarFieldValueNameGetter.INSTANCE, locale, normalizeCalendarType(id),
|
||||
field, value, style, false);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
public static Map<String, Integer> retrieveFieldValueNames(String id, int field, int style, Locale locale) {
|
||||
LocaleServiceProviderPool pool =
|
||||
LocaleServiceProviderPool.getPool(CalendarNameProvider.class);
|
||||
return pool.getLocalizedObject(CalendarFieldValueNamesMapGetter.INSTANCE, locale,
|
||||
normalizeCalendarType(id), field, style, false);
|
||||
}
|
||||
|
||||
public static Map<String, Integer> retrieveJavaTimeFieldValueNames(String id, int field, int style, Locale locale) {
|
||||
LocaleServiceProviderPool pool =
|
||||
LocaleServiceProviderPool.getPool(CalendarNameProvider.class);
|
||||
Map<String, Integer> map;
|
||||
map = pool.getLocalizedObject(CalendarFieldValueNamesMapGetter.INSTANCE, locale,
|
||||
normalizeCalendarType(id), field, style, true);
|
||||
if (map == null) {
|
||||
map = pool.getLocalizedObject(CalendarFieldValueNamesMapGetter.INSTANCE, locale,
|
||||
normalizeCalendarType(id), field, style, false);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
static String normalizeCalendarType(String requestID) {
|
||||
String type;
|
||||
if (requestID.equals("gregorian") || requestID.equals("iso8601")) {
|
||||
type = "gregory";
|
||||
} else if (requestID.startsWith("islamic")) {
|
||||
type = "islamic";
|
||||
} else {
|
||||
type = requestID;
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains a localized field value string from a CalendarDataProvider
|
||||
* implementation.
|
||||
*/
|
||||
private static class CalendarFieldValueNameGetter
|
||||
implements LocaleServiceProviderPool.LocalizedObjectGetter<CalendarNameProvider,
|
||||
String> {
|
||||
private static final CalendarFieldValueNameGetter INSTANCE =
|
||||
new CalendarFieldValueNameGetter();
|
||||
|
||||
@Override
|
||||
public String getObject(CalendarNameProvider calendarNameProvider,
|
||||
Locale locale,
|
||||
String requestID, // calendarType
|
||||
Object... params) {
|
||||
assert params.length == 4;
|
||||
int field = (int) params[0];
|
||||
int value = (int) params[1];
|
||||
int style = (int) params[2];
|
||||
boolean javatime = (boolean) params[3];
|
||||
|
||||
// If javatime is true, resources from CLDR have precedence over JRE
|
||||
// native resources.
|
||||
if (javatime && calendarNameProvider instanceof CalendarNameProviderImpl) {
|
||||
String name;
|
||||
name = ((CalendarNameProviderImpl)calendarNameProvider)
|
||||
.getJavaTimeDisplayName(requestID, field, value, style, locale);
|
||||
return name;
|
||||
}
|
||||
return calendarNameProvider.getDisplayName(requestID, field, value, style, locale);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains a localized field-value pairs from a CalendarDataProvider
|
||||
* implementation.
|
||||
*/
|
||||
private static class CalendarFieldValueNamesMapGetter
|
||||
implements LocaleServiceProviderPool.LocalizedObjectGetter<CalendarNameProvider,
|
||||
Map<String, Integer>> {
|
||||
private static final CalendarFieldValueNamesMapGetter INSTANCE =
|
||||
new CalendarFieldValueNamesMapGetter();
|
||||
|
||||
@Override
|
||||
public Map<String, Integer> getObject(CalendarNameProvider calendarNameProvider,
|
||||
Locale locale,
|
||||
String requestID, // calendarType
|
||||
Object... params) {
|
||||
assert params.length == 3;
|
||||
int field = (int) params[0];
|
||||
int style = (int) params[1];
|
||||
boolean javatime = (boolean) params[2];
|
||||
|
||||
// If javatime is true, resources from CLDR have precedence over JRE
|
||||
// native resources.
|
||||
if (javatime && calendarNameProvider instanceof CalendarNameProviderImpl) {
|
||||
Map<String, Integer> map;
|
||||
map = ((CalendarNameProviderImpl)calendarNameProvider)
|
||||
.getJavaTimeDisplayNames(requestID, field, style, locale);
|
||||
return map;
|
||||
}
|
||||
return calendarNameProvider.getDisplayNames(requestID, field, style, locale);
|
||||
}
|
||||
}
|
||||
|
||||
private static class CalendarWeekParameterGetter
|
||||
implements LocaleServiceProviderPool.LocalizedObjectGetter<CalendarDataProvider,
|
||||
Integer> {
|
||||
private static final CalendarWeekParameterGetter INSTANCE =
|
||||
new CalendarWeekParameterGetter();
|
||||
|
||||
@Override
|
||||
public Integer getObject(CalendarDataProvider calendarDataProvider,
|
||||
Locale locale,
|
||||
String requestID, // resource key
|
||||
Object... params) {
|
||||
assert params.length == 0;
|
||||
int value;
|
||||
switch (requestID) {
|
||||
case FIRST_DAY_OF_WEEK:
|
||||
value = calendarDataProvider.getFirstDayOfWeek(locale);
|
||||
break;
|
||||
case MINIMAL_DAYS_IN_FIRST_WEEK:
|
||||
value = calendarDataProvider.getMinimalDaysInFirstWeek(locale);
|
||||
break;
|
||||
default:
|
||||
throw new InternalError("invalid requestID: " + requestID);
|
||||
}
|
||||
return (value != 0) ? value : null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,352 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package sun.util.locale.provider;
|
||||
|
||||
import static java.util.Calendar.*;
|
||||
import java.util.Comparator;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
import java.util.spi.CalendarNameProvider;
|
||||
import sun.util.calendar.CalendarSystem;
|
||||
import sun.util.calendar.Era;
|
||||
|
||||
/**
|
||||
* Concrete implementation of the {@link java.util.spi.CalendarNameProvider
|
||||
* CalendarNameProvider} class for the JRE LocaleProviderAdapter.
|
||||
*
|
||||
* @author Masayoshi Okutsu
|
||||
* @author Naoto Sato
|
||||
*/
|
||||
public class CalendarNameProviderImpl extends CalendarNameProvider implements AvailableLanguageTags {
|
||||
private final LocaleProviderAdapter.Type type;
|
||||
private final Set<String> langtags;
|
||||
|
||||
public CalendarNameProviderImpl(LocaleProviderAdapter.Type type, Set<String> langtags) {
|
||||
this.type = type;
|
||||
this.langtags = langtags;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayName(String calendarType, int field, int value, int style, Locale locale) {
|
||||
return getDisplayNameImpl(calendarType, field, value, style, locale, false);
|
||||
}
|
||||
|
||||
public String getJavaTimeDisplayName(String calendarType, int field, int value, int style, Locale locale) {
|
||||
return getDisplayNameImpl(calendarType, field, value, style, locale, true);
|
||||
}
|
||||
|
||||
public String getDisplayNameImpl(String calendarType, int field, int value, int style, Locale locale, boolean javatime) {
|
||||
String name = null;
|
||||
String key = getResourceKey(calendarType, field, style, javatime);
|
||||
if (key != null) {
|
||||
LocaleResources lr = LocaleProviderAdapter.forType(type).getLocaleResources(locale);
|
||||
String[] strings = javatime ? lr.getJavaTimeNames(key) : lr.getCalendarNames(key);
|
||||
if (strings != null && strings.length > 0) {
|
||||
if (field == DAY_OF_WEEK || field == YEAR) {
|
||||
--value;
|
||||
}
|
||||
if (value < 0) {
|
||||
return null;
|
||||
} else if (value >= strings.length) {
|
||||
if (field == ERA && "japanese".equals(calendarType)) {
|
||||
Era[] jeras = CalendarSystem.forName("japanese").getEras();
|
||||
if (value <= jeras.length) {
|
||||
// Localized era name could not be retrieved from this provider.
|
||||
// This can occur either for Reiwa or SupEra.
|
||||
//
|
||||
// If it's CLDR provider, try COMPAT first, which is guaranteed to have
|
||||
// the name for Reiwa.
|
||||
if (type == LocaleProviderAdapter.Type.CLDR) {
|
||||
lr = LocaleProviderAdapter.forJRE().getLocaleResources(locale);
|
||||
key = getResourceKeyFor(LocaleProviderAdapter.Type.JRE,
|
||||
calendarType, field, style, javatime);
|
||||
strings =
|
||||
javatime ? lr.getJavaTimeNames(key) : lr.getCalendarNames(key);
|
||||
}
|
||||
if (strings == null || value >= strings.length) {
|
||||
// Get the default name for SupEra
|
||||
Era supEra = jeras[value - 1]; // 0-based index
|
||||
if (javatime) {
|
||||
return getBaseStyle(style) == NARROW_FORMAT ?
|
||||
supEra.getAbbreviation() :
|
||||
supEra.getName();
|
||||
} else {
|
||||
return (style & LONG) != 0 ?
|
||||
supEra.getName() :
|
||||
supEra.getAbbreviation();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
name = strings[value];
|
||||
// If name is empty in standalone, try its `format' style.
|
||||
if (name.length() == 0
|
||||
&& (style == SHORT_STANDALONE || style == LONG_STANDALONE
|
||||
|| style == NARROW_STANDALONE)) {
|
||||
name = getDisplayName(calendarType, field, value,
|
||||
getBaseStyle(style),
|
||||
locale);
|
||||
}
|
||||
}
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
private static int[] REST_OF_STYLES = {
|
||||
SHORT_STANDALONE, LONG_FORMAT, LONG_STANDALONE,
|
||||
NARROW_FORMAT, NARROW_STANDALONE
|
||||
};
|
||||
|
||||
@Override
|
||||
public Map<String, Integer> getDisplayNames(String calendarType, int field, int style, Locale locale) {
|
||||
Map<String, Integer> names;
|
||||
if (style == ALL_STYLES) {
|
||||
names = getDisplayNamesImpl(calendarType, field, SHORT_FORMAT, locale, false);
|
||||
for (int st : REST_OF_STYLES) {
|
||||
names.putAll(getDisplayNamesImpl(calendarType, field, st, locale, false));
|
||||
}
|
||||
} else {
|
||||
// specific style
|
||||
names = getDisplayNamesImpl(calendarType, field, style, locale, false);
|
||||
}
|
||||
return names.isEmpty() ? null : names;
|
||||
}
|
||||
|
||||
// NOTE: This method should be used ONLY BY JSR 310 classes.
|
||||
public Map<String, Integer> getJavaTimeDisplayNames(String calendarType, int field, int style, Locale locale) {
|
||||
Map<String, Integer> names;
|
||||
names = getDisplayNamesImpl(calendarType, field, style, locale, true);
|
||||
return names.isEmpty() ? null : names;
|
||||
}
|
||||
|
||||
private Map<String, Integer> getDisplayNamesImpl(String calendarType, int field,
|
||||
int style, Locale locale, boolean javatime) {
|
||||
String key = getResourceKey(calendarType, field, style, javatime);
|
||||
Map<String, Integer> map = new TreeMap<>(LengthBasedComparator.INSTANCE);
|
||||
if (key != null) {
|
||||
LocaleResources lr = LocaleProviderAdapter.forType(type).getLocaleResources(locale);
|
||||
String[] strings = javatime ? lr.getJavaTimeNames(key) : lr.getCalendarNames(key);
|
||||
if (strings != null) {
|
||||
if (!hasDuplicates(strings)) {
|
||||
if (field == YEAR) {
|
||||
if (strings.length > 0) {
|
||||
map.put(strings[0], 1);
|
||||
}
|
||||
} else {
|
||||
int base = (field == DAY_OF_WEEK) ? 1 : 0;
|
||||
for (int i = 0; i < strings.length; i++) {
|
||||
String name = strings[i];
|
||||
// Ignore any empty string (some standalone month names
|
||||
// are not defined)
|
||||
if (name.length() == 0) {
|
||||
continue;
|
||||
}
|
||||
map.put(name, base + i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
private static int getBaseStyle(int style) {
|
||||
return style & ~(SHORT_STANDALONE - SHORT_FORMAT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Comparator implementation for TreeMap which iterates keys from longest
|
||||
* to shortest.
|
||||
*/
|
||||
private static class LengthBasedComparator implements Comparator<String> {
|
||||
private static final LengthBasedComparator INSTANCE = new LengthBasedComparator();
|
||||
|
||||
private LengthBasedComparator() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compare(String o1, String o2) {
|
||||
int n = o2.length() - o1.length();
|
||||
return (n == 0) ? o1.compareTo(o2) : n;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Locale[] getAvailableLocales() {
|
||||
return LocaleProviderAdapter.toLocaleArray(langtags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupportedLocale(Locale locale) {
|
||||
if (Locale.ROOT.equals(locale)) {
|
||||
return true;
|
||||
}
|
||||
String calendarType = null;
|
||||
if (locale.hasExtensions()) {
|
||||
calendarType = locale.getUnicodeLocaleType("ca");
|
||||
locale = locale.stripExtensions();
|
||||
}
|
||||
|
||||
if (calendarType != null) {
|
||||
switch (calendarType) {
|
||||
case "buddhist":
|
||||
case "japanese":
|
||||
case "gregory":
|
||||
case "islamic":
|
||||
case "roc":
|
||||
break;
|
||||
default:
|
||||
// Unknown calendar type
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (langtags.contains(locale.toLanguageTag())) {
|
||||
return true;
|
||||
}
|
||||
if (type == LocaleProviderAdapter.Type.JRE) {
|
||||
String oldname = locale.toString().replace('_', '-');
|
||||
return langtags.contains(oldname);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getAvailableLanguageTags() {
|
||||
return langtags;
|
||||
}
|
||||
|
||||
private boolean hasDuplicates(String[] strings) {
|
||||
int len = strings.length;
|
||||
for (int i = 0; i < len - 1; i++) {
|
||||
String a = strings[i];
|
||||
if (a != null) {
|
||||
for (int j = i + 1; j < len; j++) {
|
||||
if (a.equals(strings[j])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private String getResourceKey(String type, int field, int style, boolean javatime) {
|
||||
return getResourceKeyFor(this.type, type, field, style, javatime);
|
||||
}
|
||||
|
||||
private static String getResourceKeyFor(LocaleProviderAdapter.Type adapterType,
|
||||
String type, int field, int style, boolean javatime) {
|
||||
int baseStyle = getBaseStyle(style);
|
||||
boolean isStandalone = (style != baseStyle);
|
||||
|
||||
if ("gregory".equals(type)) {
|
||||
type = null;
|
||||
}
|
||||
boolean isNarrow = (baseStyle == NARROW_FORMAT);
|
||||
StringBuilder key = new StringBuilder();
|
||||
// If javatime is true, use prefix "java.time.".
|
||||
if (javatime) {
|
||||
key.append("java.time.");
|
||||
}
|
||||
switch (field) {
|
||||
case ERA:
|
||||
if (type != null) {
|
||||
key.append(type).append('.');
|
||||
}
|
||||
if (isNarrow) {
|
||||
key.append("narrow.");
|
||||
} else {
|
||||
// JRE and CLDR use different resource key conventions
|
||||
// due to historical reasons. (JRE DateFormatSymbols.getEras returns
|
||||
// abbreviations while other getShort*() return abbreviations.)
|
||||
if (adapterType == LocaleProviderAdapter.Type.JRE) {
|
||||
if (javatime) {
|
||||
if (baseStyle == LONG) {
|
||||
key.append("long.");
|
||||
}
|
||||
}
|
||||
if (baseStyle == SHORT) {
|
||||
key.append("short.");
|
||||
}
|
||||
} else { // this.type == LocaleProviderAdapter.Type.CLDR
|
||||
if (baseStyle == LONG) {
|
||||
key.append("long.");
|
||||
}
|
||||
}
|
||||
}
|
||||
key.append("Eras");
|
||||
break;
|
||||
|
||||
case YEAR:
|
||||
if (!isNarrow) {
|
||||
key.append(type).append(".FirstYear");
|
||||
}
|
||||
break;
|
||||
|
||||
case MONTH:
|
||||
if ("islamic".equals(type)) {
|
||||
key.append(type).append('.');
|
||||
}
|
||||
if (isStandalone) {
|
||||
key.append("standalone.");
|
||||
}
|
||||
key.append("Month").append(toStyleName(baseStyle));
|
||||
break;
|
||||
|
||||
case DAY_OF_WEEK:
|
||||
// support standalone narrow day names
|
||||
if (isStandalone && isNarrow) {
|
||||
key.append("standalone.");
|
||||
}
|
||||
key.append("Day").append(toStyleName(baseStyle));
|
||||
break;
|
||||
|
||||
case AM_PM:
|
||||
if (isNarrow) {
|
||||
key.append("narrow.");
|
||||
}
|
||||
key.append("AmPmMarkers");
|
||||
break;
|
||||
}
|
||||
return key.length() > 0 ? key.toString() : null;
|
||||
}
|
||||
|
||||
private static String toStyleName(int baseStyle) {
|
||||
switch (baseStyle) {
|
||||
case SHORT:
|
||||
return "Abbreviations";
|
||||
case NARROW_FORMAT:
|
||||
return "Narrows";
|
||||
}
|
||||
return "Names";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.util.locale.provider;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.Calendar.Builder;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import java.util.TimeZone;
|
||||
import sun.util.spi.CalendarProvider;
|
||||
|
||||
/**
|
||||
* Concrete implementation of the {@link sun.util.spi.CalendarProvider
|
||||
* CalendarProvider} class for the JRE LocaleProviderAdapter.
|
||||
*
|
||||
* @author Naoto Sato
|
||||
*/
|
||||
public class CalendarProviderImpl extends CalendarProvider implements AvailableLanguageTags {
|
||||
private final LocaleProviderAdapter.Type type;
|
||||
private final Set<String> langtags;
|
||||
|
||||
public CalendarProviderImpl(LocaleProviderAdapter.Type type, Set<String> langtags) {
|
||||
this.type = type;
|
||||
this.langtags = langtags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of all locales for which this locale service provider
|
||||
* can provide localized objects or names.
|
||||
*
|
||||
* @return An array of all locales for which this locale service provider
|
||||
* can provide localized objects or names.
|
||||
*/
|
||||
@Override
|
||||
public Locale[] getAvailableLocales() {
|
||||
return LocaleProviderAdapter.toLocaleArray(langtags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupportedLocale(Locale locale) {
|
||||
// Support any locales.
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new <code>Calendar</code> instance for the
|
||||
* specified locale.
|
||||
*
|
||||
* @param zone the time zone
|
||||
* @param locale the desired locale
|
||||
* @exception NullPointerException if <code>locale</code> is null
|
||||
* @exception IllegalArgumentException if <code>locale</code> isn't
|
||||
* one of the locales returned from
|
||||
* {@link java.util.spi.LocaleServiceProvider#getAvailableLocales()
|
||||
* getAvailableLocales()}.
|
||||
* @return a <code>Calendar</code> instance.
|
||||
* @see java.util.Calendar#getInstance(java.util.Locale)
|
||||
*/
|
||||
@Override
|
||||
public Calendar getInstance(TimeZone zone, Locale locale) {
|
||||
return new Calendar.Builder()
|
||||
.setLocale(locale)
|
||||
.setTimeZone(zone)
|
||||
.setInstant(System.currentTimeMillis())
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getAvailableLanguageTags() {
|
||||
return langtags;
|
||||
}
|
||||
}
|
||||
277
jdkSrc/jdk8/sun/util/locale/provider/CollationRules.java
Normal file
277
jdkSrc/jdk8/sun/util/locale/provider/CollationRules.java
Normal file
@@ -0,0 +1,277 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* (C) Copyright Taligent, Inc. 1996,1997 - All Rights Reserved
|
||||
* (C) Copyright IBM Corp. 1996, 1997 - All Rights Reserved
|
||||
*
|
||||
* The original version of this source code and documentation is copyrighted
|
||||
* and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These
|
||||
* materials are provided under terms of a License Agreement between Taligent
|
||||
* and Sun. This technology is protected by multiple US and International
|
||||
* patents. This notice and attribution to Taligent may not be removed.
|
||||
* Taligent is a registered trademark of Taligent, Inc.
|
||||
*
|
||||
*/
|
||||
|
||||
package sun.util.locale.provider;
|
||||
/**
|
||||
* CollationRules contains the default en_US collation rules as a base
|
||||
* for building other collation tables.
|
||||
* <p>Note that decompositions are done before these rules are used,
|
||||
* so they do not have to contain accented characters, such as A-grave.
|
||||
* @see RuleBasedCollator
|
||||
* @see LocaleElements
|
||||
* @author Helena Shih, Mark Davis
|
||||
*/
|
||||
final class CollationRules {
|
||||
final static String DEFAULTRULES =
|
||||
"" // no FRENCH accent order by default, add in French Delta
|
||||
// IGNORABLES (up to first < character)
|
||||
// COMPLETELY IGNORE format characters
|
||||
+ "='\u200B'=\u200C=\u200D=\u200E=\u200F"
|
||||
// Control Characters
|
||||
+ "=\u0000 =\u0001 =\u0002 =\u0003 =\u0004" //null, .. eot
|
||||
+ "=\u0005 =\u0006 =\u0007 =\u0008 ='\u0009'" //enq, ...
|
||||
+ "='\u000b' =\u000e" //vt,, so
|
||||
+ "=\u000f ='\u0010' =\u0011 =\u0012 =\u0013" //si, dle, dc1, dc2, dc3
|
||||
+ "=\u0014 =\u0015 =\u0016 =\u0017 =\u0018" //dc4, nak, syn, etb, can
|
||||
+ "=\u0019 =\u001a =\u001b =\u001c =\u001d" //em, sub, esc, fs, gs
|
||||
+ "=\u001e =\u001f =\u007f" //rs, us, del
|
||||
//....then the C1 Latin 1 reserved control codes
|
||||
+ "=\u0080 =\u0081 =\u0082 =\u0083 =\u0084 =\u0085"
|
||||
+ "=\u0086 =\u0087 =\u0088 =\u0089 =\u008a =\u008b"
|
||||
+ "=\u008c =\u008d =\u008e =\u008f =\u0090 =\u0091"
|
||||
+ "=\u0092 =\u0093 =\u0094 =\u0095 =\u0096 =\u0097"
|
||||
+ "=\u0098 =\u0099 =\u009a =\u009b =\u009c =\u009d"
|
||||
+ "=\u009e =\u009f"
|
||||
// IGNORE except for secondary, tertiary difference
|
||||
// Spaces
|
||||
+ ";'\u0020';'\u00A0'" // spaces
|
||||
+ ";'\u2000';'\u2001';'\u2002';'\u2003';'\u2004'" // spaces
|
||||
+ ";'\u2005';'\u2006';'\u2007';'\u2008';'\u2009'" // spaces
|
||||
+ ";'\u200A';'\u3000';'\uFEFF'" // spaces
|
||||
+ ";'\r' ;'\t' ;'\n';'\f';'\u000b'" // whitespace
|
||||
|
||||
// Non-spacing accents
|
||||
|
||||
+ ";\u0301" // non-spacing acute accent
|
||||
+ ";\u0300" // non-spacing grave accent
|
||||
+ ";\u0306" // non-spacing breve accent
|
||||
+ ";\u0302" // non-spacing circumflex accent
|
||||
+ ";\u030c" // non-spacing caron/hacek accent
|
||||
+ ";\u030a" // non-spacing ring above accent
|
||||
+ ";\u030d" // non-spacing vertical line above
|
||||
+ ";\u0308" // non-spacing diaeresis accent
|
||||
+ ";\u030b" // non-spacing double acute accent
|
||||
+ ";\u0303" // non-spacing tilde accent
|
||||
+ ";\u0307" // non-spacing dot above/overdot accent
|
||||
+ ";\u0304" // non-spacing macron accent
|
||||
+ ";\u0337" // non-spacing short slash overlay (overstruck diacritic)
|
||||
+ ";\u0327" // non-spacing cedilla accent
|
||||
+ ";\u0328" // non-spacing ogonek accent
|
||||
+ ";\u0323" // non-spacing dot-below/underdot accent
|
||||
+ ";\u0332" // non-spacing underscore/underline accent
|
||||
// with the rest of the general diacritical marks in binary order
|
||||
+ ";\u0305" // non-spacing overscore/overline
|
||||
+ ";\u0309" // non-spacing hook above
|
||||
+ ";\u030e" // non-spacing double vertical line above
|
||||
+ ";\u030f" // non-spacing double grave
|
||||
+ ";\u0310" // non-spacing chandrabindu
|
||||
+ ";\u0311" // non-spacing inverted breve
|
||||
+ ";\u0312" // non-spacing turned comma above/cedilla above
|
||||
+ ";\u0313" // non-spacing comma above
|
||||
+ ";\u0314" // non-spacing reversed comma above
|
||||
+ ";\u0315" // non-spacing comma above right
|
||||
+ ";\u0316" // non-spacing grave below
|
||||
+ ";\u0317" // non-spacing acute below
|
||||
+ ";\u0318" // non-spacing left tack below
|
||||
+ ";\u0319" // non-spacing tack below
|
||||
+ ";\u031a" // non-spacing left angle above
|
||||
+ ";\u031b" // non-spacing horn
|
||||
+ ";\u031c" // non-spacing left half ring below
|
||||
+ ";\u031d" // non-spacing up tack below
|
||||
+ ";\u031e" // non-spacing down tack below
|
||||
+ ";\u031f" // non-spacing plus sign below
|
||||
+ ";\u0320" // non-spacing minus sign below
|
||||
+ ";\u0321" // non-spacing palatalized hook below
|
||||
+ ";\u0322" // non-spacing retroflex hook below
|
||||
+ ";\u0324" // non-spacing double dot below
|
||||
+ ";\u0325" // non-spacing ring below
|
||||
+ ";\u0326" // non-spacing comma below
|
||||
+ ";\u0329" // non-spacing vertical line below
|
||||
+ ";\u032a" // non-spacing bridge below
|
||||
+ ";\u032b" // non-spacing inverted double arch below
|
||||
+ ";\u032c" // non-spacing hacek below
|
||||
+ ";\u032d" // non-spacing circumflex below
|
||||
+ ";\u032e" // non-spacing breve below
|
||||
+ ";\u032f" // non-spacing inverted breve below
|
||||
+ ";\u0330" // non-spacing tilde below
|
||||
+ ";\u0331" // non-spacing macron below
|
||||
+ ";\u0333" // non-spacing double underscore
|
||||
+ ";\u0334" // non-spacing tilde overlay
|
||||
+ ";\u0335" // non-spacing short bar overlay
|
||||
+ ";\u0336" // non-spacing long bar overlay
|
||||
+ ";\u0338" // non-spacing long slash overlay
|
||||
+ ";\u0339" // non-spacing right half ring below
|
||||
+ ";\u033a" // non-spacing inverted bridge below
|
||||
+ ";\u033b" // non-spacing square below
|
||||
+ ";\u033c" // non-spacing seagull below
|
||||
+ ";\u033d" // non-spacing x above
|
||||
+ ";\u033e" // non-spacing vertical tilde
|
||||
+ ";\u033f" // non-spacing double overscore
|
||||
//+ ";\u0340" // non-spacing grave tone mark == \u0300
|
||||
//+ ";\u0341" // non-spacing acute tone mark == \u0301
|
||||
+ ";\u0342;"
|
||||
//+ "\u0343;" // == \u0313
|
||||
+ "\u0344;\u0345;\u0360;\u0361" // newer
|
||||
+ ";\u0483;\u0484;\u0485;\u0486" // Cyrillic accents
|
||||
|
||||
+ ";\u20D0;\u20D1;\u20D2" // symbol accents
|
||||
+ ";\u20D3;\u20D4;\u20D5" // symbol accents
|
||||
+ ";\u20D6;\u20D7;\u20D8" // symbol accents
|
||||
+ ";\u20D9;\u20DA;\u20DB" // symbol accents
|
||||
+ ";\u20DC;\u20DD;\u20DE" // symbol accents
|
||||
+ ";\u20DF;\u20E0;\u20E1" // symbol accents
|
||||
|
||||
+ ",'\u002D';\u00AD" // dashes
|
||||
+ ";\u2010;\u2011;\u2012" // dashes
|
||||
+ ";\u2013;\u2014;\u2015" // dashes
|
||||
+ ";\u2212" // dashes
|
||||
|
||||
// other punctuation
|
||||
|
||||
+ "<'\u005f'" // underline/underscore (spacing)
|
||||
+ "<\u00af" // overline or macron (spacing)
|
||||
+ "<'\u002c'" // comma (spacing)
|
||||
+ "<'\u003b'" // semicolon
|
||||
+ "<'\u003a'" // colon
|
||||
+ "<'\u0021'" // exclamation point
|
||||
+ "<\u00a1" // inverted exclamation point
|
||||
+ "<'\u003f'" // question mark
|
||||
+ "<\u00bf" // inverted question mark
|
||||
+ "<'\u002f'" // slash
|
||||
+ "<'\u002e'" // period/full stop
|
||||
+ "<\u00b4" // acute accent (spacing)
|
||||
+ "<'\u0060'" // grave accent (spacing)
|
||||
+ "<'\u005e'" // circumflex accent (spacing)
|
||||
+ "<\u00a8" // diaresis/umlaut accent (spacing)
|
||||
+ "<'\u007e'" // tilde accent (spacing)
|
||||
+ "<\u00b7" // middle dot (spacing)
|
||||
+ "<\u00b8" // cedilla accent (spacing)
|
||||
+ "<'\u0027'" // apostrophe
|
||||
+ "<'\"'" // quotation marks
|
||||
+ "<\u00ab" // left angle quotes
|
||||
+ "<\u00bb" // right angle quotes
|
||||
+ "<'\u0028'" // left parenthesis
|
||||
+ "<'\u0029'" // right parenthesis
|
||||
+ "<'\u005b'" // left bracket
|
||||
+ "<'\u005d'" // right bracket
|
||||
+ "<'\u007b'" // left brace
|
||||
+ "<'\u007d'" // right brace
|
||||
+ "<\u00a7" // section symbol
|
||||
+ "<\u00b6" // paragraph symbol
|
||||
+ "<\u00a9" // copyright symbol
|
||||
+ "<\u00ae" // registered trademark symbol
|
||||
+ "<'\u0040'" // at sign
|
||||
+ "<\u00a4" // international currency symbol
|
||||
+ "<\u0e3f" // baht sign
|
||||
+ "<\u00a2" // cent sign
|
||||
+ "<\u20a1" // colon sign
|
||||
+ "<\u20a2" // cruzeiro sign
|
||||
+ "<'\u0024'" // dollar sign
|
||||
+ "<\u20ab" // dong sign
|
||||
+ "<\u20ac" // euro sign
|
||||
+ "<\u20a3" // franc sign
|
||||
+ "<\u20a4" // lira sign
|
||||
+ "<\u20a5" // mill sign
|
||||
+ "<\u20a6" // naira sign
|
||||
+ "<\u20a7" // peseta sign
|
||||
+ "<\u00a3" // pound-sterling sign
|
||||
+ "<\u20a8" // rupee sign
|
||||
+ "<\u20aa" // new shekel sign
|
||||
+ "<\u20a9" // won sign
|
||||
+ "<\u00a5" // yen sign
|
||||
+ "<'\u002a'" // asterisk
|
||||
+ "<'\\'" // backslash
|
||||
+ "<'\u0026'" // ampersand
|
||||
+ "<'\u0023'" // number sign
|
||||
+ "<'\u0025'" // percent sign
|
||||
+ "<'\u002b'" // plus sign
|
||||
+ "<\u00b1" // plus-or-minus sign
|
||||
+ "<\u00f7" // divide sign
|
||||
+ "<\u00d7" // multiply sign
|
||||
+ "<'\u003c'" // less-than sign
|
||||
+ "<'\u003d'" // equal sign
|
||||
+ "<'\u003e'" // greater-than sign
|
||||
+ "<\u00ac" // end of line symbol/logical NOT symbol
|
||||
+ "<'\u007c'" // vertical line/logical OR symbol
|
||||
+ "<\u00a6" // broken vertical line
|
||||
+ "<\u00b0" // degree symbol
|
||||
+ "<\u00b5" // micro symbol
|
||||
|
||||
// NUMERICS
|
||||
|
||||
+ "<0<1<2<3<4<5<6<7<8<9"
|
||||
+ "<\u00bc<\u00bd<\u00be" // 1/4,1/2,3/4 fractions
|
||||
|
||||
// NON-IGNORABLES
|
||||
+ "<a,A"
|
||||
+ "<b,B"
|
||||
+ "<c,C"
|
||||
+ "<d,D"
|
||||
+ "<\u00F0,\u00D0" // eth
|
||||
+ "<e,E"
|
||||
+ "<f,F"
|
||||
+ "<g,G"
|
||||
+ "<h,H"
|
||||
+ "<i,I"
|
||||
+ "<j,J"
|
||||
+ "<k,K"
|
||||
+ "<l,L"
|
||||
+ "<m,M"
|
||||
+ "<n,N"
|
||||
+ "<o,O"
|
||||
+ "<p,P"
|
||||
+ "<q,Q"
|
||||
+ "<r,R"
|
||||
+ "<s, S & SS,\u00DF" // s-zet
|
||||
+ "<t,T"
|
||||
+ "& TH, \u00DE &TH, \u00FE " // thorn
|
||||
+ "<u,U"
|
||||
+ "<v,V"
|
||||
+ "<w,W"
|
||||
+ "<x,X"
|
||||
+ "<y,Y"
|
||||
+ "<z,Z"
|
||||
+ "&AE,\u00C6" // ae & AE ligature
|
||||
+ "&AE,\u00E6"
|
||||
+ "&OE,\u0152" // oe & OE ligature
|
||||
+ "&OE,\u0153";
|
||||
|
||||
// No instantiation
|
||||
private CollationRules() {
|
||||
}
|
||||
}
|
||||
131
jdkSrc/jdk8/sun/util/locale/provider/CollatorProviderImpl.java
Normal file
131
jdkSrc/jdk8/sun/util/locale/provider/CollatorProviderImpl.java
Normal file
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
* (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
|
||||
* (C) Copyright IBM Corp. 1996 - 2002 - All Rights Reserved
|
||||
*
|
||||
* The original version of this source code and documentation
|
||||
* is copyrighted and owned by Taligent, Inc., a wholly-owned
|
||||
* subsidiary of IBM. These materials are provided under terms
|
||||
* of a License Agreement between Taligent and Sun. This technology
|
||||
* is protected by multiple US and International patents.
|
||||
*
|
||||
* This notice and attribution to Taligent may not be removed.
|
||||
* Taligent is a registered trademark of Taligent, Inc.
|
||||
*/
|
||||
|
||||
package sun.util.locale.provider;
|
||||
|
||||
import java.text.Collator;
|
||||
import java.text.ParseException;
|
||||
import java.text.RuleBasedCollator;
|
||||
import java.text.spi.CollatorProvider;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Concrete implementation of the
|
||||
* {@link java.text.spi.CollatorProvider CollatorProvider} class
|
||||
* for the JRE LocaleProviderAdapter.
|
||||
*/
|
||||
public class CollatorProviderImpl extends CollatorProvider implements AvailableLanguageTags {
|
||||
private final LocaleProviderAdapter.Type type;
|
||||
private final Set<String> langtags;
|
||||
|
||||
public CollatorProviderImpl(LocaleProviderAdapter.Type type, Set<String> langtags) {
|
||||
this.type = type;
|
||||
this.langtags = langtags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of all locales for which this locale service provider
|
||||
* can provide localized objects or names.
|
||||
*
|
||||
* @return An array of all locales for which this locale service provider
|
||||
* can provide localized objects or names.
|
||||
*/
|
||||
@Override
|
||||
public Locale[] getAvailableLocales() {
|
||||
return LocaleProviderAdapter.toLocaleArray(langtags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupportedLocale(Locale locale) {
|
||||
return LocaleProviderAdapter.isSupportedLocale(locale, type, langtags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new <code>Collator</code> instance for the specified locale.
|
||||
* @param locale the desired locale.
|
||||
* @return the <code>Collator</code> for the desired locale.
|
||||
* @exception NullPointerException if
|
||||
* <code>locale</code> is null
|
||||
* @exception IllegalArgumentException if <code>locale</code> isn't
|
||||
* one of the locales returned from
|
||||
* {@link java.util.spi.LocaleServiceProvider#getAvailableLocales()
|
||||
* getAvailableLocales()}.
|
||||
* @see java.text.Collator#getInstance(java.util.Locale)
|
||||
*/
|
||||
@Override
|
||||
public Collator getInstance(Locale locale) {
|
||||
if (locale == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
|
||||
Collator result = null;
|
||||
|
||||
// Load the resource of the desired locale from resource
|
||||
// manager.
|
||||
String colString = LocaleProviderAdapter.forType(type).getLocaleResources(locale).getCollationData();
|
||||
try
|
||||
{
|
||||
result = new RuleBasedCollator(CollationRules.DEFAULTRULES +
|
||||
colString);
|
||||
}
|
||||
catch(ParseException foo)
|
||||
{
|
||||
// predefined tables should contain correct grammar
|
||||
try {
|
||||
result = new RuleBasedCollator(CollationRules.DEFAULTRULES);
|
||||
} catch (ParseException bar) {
|
||||
// the default rules should always be parsable.
|
||||
throw new InternalError(bar);
|
||||
}
|
||||
}
|
||||
// Now that RuleBasedCollator adds expansions for pre-composed characters
|
||||
// into their decomposed equivalents, the default collators don't need
|
||||
// to have decomposition turned on. Laura, 5/5/98, bug 4114077
|
||||
result.setDecomposition(Collator.NO_DECOMPOSITION);
|
||||
|
||||
return (Collator)result.clone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getAvailableLanguageTags() {
|
||||
return langtags;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.util.locale.provider;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import java.util.spi.CurrencyNameProvider;
|
||||
|
||||
/**
|
||||
* Concrete implementation of the
|
||||
* {@link java.util.spi.CurrencyNameProvider CurrencyNameProvider} class
|
||||
* for the JRE LocaleProviderAdapter.
|
||||
*
|
||||
* @author Naoto Sato
|
||||
* @author Masayoshi Okutsu
|
||||
*/
|
||||
public class CurrencyNameProviderImpl extends CurrencyNameProvider
|
||||
implements AvailableLanguageTags {
|
||||
private final LocaleProviderAdapter.Type type;
|
||||
private final Set<String> langtags;
|
||||
|
||||
public CurrencyNameProviderImpl(LocaleProviderAdapter.Type type, Set<String> langtags) {
|
||||
this.type = type;
|
||||
this.langtags = langtags;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getAvailableLanguageTags() {
|
||||
return langtags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of all locales for which this locale service provider
|
||||
* can provide localized objects or names.
|
||||
*
|
||||
* @return An array of all locales for which this locale service provider
|
||||
* can provide localized objects or names.
|
||||
*/
|
||||
@Override
|
||||
public Locale[] getAvailableLocales() {
|
||||
return LocaleProviderAdapter.toLocaleArray(langtags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the symbol of the given currency code for the specified locale.
|
||||
* For example, for "USD" (US Dollar), the symbol is "$" if the specified
|
||||
* locale is the US, while for other locales it may be "US$". If no
|
||||
* symbol can be determined, null should be returned.
|
||||
*
|
||||
* @param currencyCode the ISO 4217 currency code, which
|
||||
* consists of three upper-case letters between 'A' (U+0041) and
|
||||
* 'Z' (U+005A)
|
||||
* @param locale the desired locale
|
||||
* @return the symbol of the given currency code for the specified locale, or null if
|
||||
* the symbol is not available for the locale
|
||||
* @exception NullPointerException if <code>currencyCode</code> or
|
||||
* <code>locale</code> is null
|
||||
* @exception IllegalArgumentException if <code>currencyCode</code> is not in
|
||||
* the form of three upper-case letters, or <code>locale</code> isn't
|
||||
* one of the locales returned from
|
||||
* {@link java.util.spi.LocaleServiceProvider#getAvailableLocales()
|
||||
* getAvailableLocales()}.
|
||||
* @see java.util.Currency#getSymbol(java.util.Locale)
|
||||
*/
|
||||
@Override
|
||||
public String getSymbol(String currencyCode, Locale locale) {
|
||||
return getString(currencyCode.toUpperCase(Locale.ROOT), locale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a name for the currency that is appropriate for display to the
|
||||
* user. The default implementation returns null.
|
||||
*
|
||||
* @param currencyCode the ISO 4217 currency code, which
|
||||
* consists of three upper-case letters between 'A' (U+0041) and
|
||||
* 'Z' (U+005A)
|
||||
* @param locale the desired locale
|
||||
* @return the name for the currency that is appropriate for display to the
|
||||
* user, or null if the name is not available for the locale
|
||||
* @exception IllegalArgumentException if <code>currencyCode</code> is not in
|
||||
* the form of three upper-case letters, or <code>locale</code> isn't
|
||||
* one of the locales returned from
|
||||
* {@link java.util.spi.LocaleServiceProvider#getAvailableLocales()
|
||||
* getAvailableLocales()}.
|
||||
* @exception NullPointerException if <code>currencyCode</code> or
|
||||
* <code>locale</code> is <code>null</code>
|
||||
* @since 1.7
|
||||
*/
|
||||
@Override
|
||||
public String getDisplayName(String currencyCode, Locale locale) {
|
||||
return getString(currencyCode.toLowerCase(Locale.ROOT), locale);
|
||||
}
|
||||
|
||||
private String getString(String key, Locale locale) {
|
||||
if (locale == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
|
||||
return LocaleProviderAdapter.forType(type).getLocaleResources(locale).getCurrencyName(key);
|
||||
}
|
||||
}
|
||||
169
jdkSrc/jdk8/sun/util/locale/provider/DateFormatProviderImpl.java
Normal file
169
jdkSrc/jdk8/sun/util/locale/provider/DateFormatProviderImpl.java
Normal file
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.util.locale.provider;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.text.spi.DateFormatProvider;
|
||||
import java.util.Calendar;
|
||||
import java.util.Locale;
|
||||
import java.util.MissingResourceException;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Concrete implementation of the {@link java.text.spi.DateFormatProvider
|
||||
* DateFormatProvider} class for the JRE LocaleProviderAdapter.
|
||||
*
|
||||
* @author Naoto Sato
|
||||
* @author Masayoshi Okutsu
|
||||
*/
|
||||
public class DateFormatProviderImpl extends DateFormatProvider implements AvailableLanguageTags {
|
||||
private final LocaleProviderAdapter.Type type;
|
||||
private final Set<String> langtags;
|
||||
|
||||
public DateFormatProviderImpl(LocaleProviderAdapter.Type type, Set<String> langtags) {
|
||||
this.type = type;
|
||||
this.langtags = langtags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of all locales for which this locale service provider
|
||||
* can provide localized objects or names.
|
||||
*
|
||||
* @return An array of all locales for which this locale service provider
|
||||
* can provide localized objects or names.
|
||||
*/
|
||||
@Override
|
||||
public Locale[] getAvailableLocales() {
|
||||
return LocaleProviderAdapter.toLocaleArray(langtags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupportedLocale(Locale locale) {
|
||||
return LocaleProviderAdapter.isSupportedLocale(locale, type, langtags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new <code>DateFormat</code> instance which formats time
|
||||
* with the given formatting style for the specified locale.
|
||||
* @param style the given formatting style. Either one of
|
||||
* {@link java.text.DateFormat#SHORT DateFormat.SHORT},
|
||||
* {@link java.text.DateFormat#MEDIUM DateFormat.MEDIUM},
|
||||
* {@link java.text.DateFormat#LONG DateFormat.LONG}, or
|
||||
* {@link java.text.DateFormat#FULL DateFormat.FULL}.
|
||||
* @param locale the desired locale.
|
||||
* @exception IllegalArgumentException if <code>style</code> is invalid,
|
||||
* or if <code>locale</code> isn't
|
||||
* one of the locales returned from
|
||||
* {@link java.util.spi.LocaleServiceProvider#getAvailableLocales()
|
||||
* getAvailableLocales()}.
|
||||
* @exception NullPointerException if <code>locale</code> is null
|
||||
* @return a time formatter.
|
||||
* @see java.text.DateFormat#getTimeInstance(int, java.util.Locale)
|
||||
*/
|
||||
@Override
|
||||
public DateFormat getTimeInstance(int style, Locale locale) {
|
||||
return getInstance(-1, style, locale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new <code>DateFormat</code> instance which formats date
|
||||
* with the given formatting style for the specified locale.
|
||||
* @param style the given formatting style. Either one of
|
||||
* {@link java.text.DateFormat#SHORT DateFormat.SHORT},
|
||||
* {@link java.text.DateFormat#MEDIUM DateFormat.MEDIUM},
|
||||
* {@link java.text.DateFormat#LONG DateFormat.LONG}, or
|
||||
* {@link java.text.DateFormat#FULL DateFormat.FULL}.
|
||||
* @param locale the desired locale.
|
||||
* @exception IllegalArgumentException if <code>style</code> is invalid,
|
||||
* or if <code>locale</code> isn't
|
||||
* one of the locales returned from
|
||||
* {@link java.util.spi.LocaleServiceProvider#getAvailableLocales()
|
||||
* getAvailableLocales()}.
|
||||
* @exception NullPointerException if <code>locale</code> is null
|
||||
* @return a date formatter.
|
||||
* @see java.text.DateFormat#getDateInstance(int, java.util.Locale)
|
||||
*/
|
||||
@Override
|
||||
public DateFormat getDateInstance(int style, Locale locale) {
|
||||
return getInstance(style, -1, locale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new <code>DateFormat</code> instance which formats date and time
|
||||
* with the given formatting style for the specified locale.
|
||||
* @param dateStyle the given date formatting style. Either one of
|
||||
* {@link java.text.DateFormat#SHORT DateFormat.SHORT},
|
||||
* {@link java.text.DateFormat#MEDIUM DateFormat.MEDIUM},
|
||||
* {@link java.text.DateFormat#LONG DateFormat.LONG}, or
|
||||
* {@link java.text.DateFormat#FULL DateFormat.FULL}.
|
||||
* @param timeStyle the given time formatting style. Either one of
|
||||
* {@link java.text.DateFormat#SHORT DateFormat.SHORT},
|
||||
* {@link java.text.DateFormat#MEDIUM DateFormat.MEDIUM},
|
||||
* {@link java.text.DateFormat#LONG DateFormat.LONG}, or
|
||||
* {@link java.text.DateFormat#FULL DateFormat.FULL}.
|
||||
* @param locale the desired locale.
|
||||
* @exception IllegalArgumentException if <code>dateStyle</code> or
|
||||
* <code>timeStyle</code> is invalid,
|
||||
* or if <code>locale</code> isn't
|
||||
* one of the locales returned from
|
||||
* {@link java.util.spi.LocaleServiceProvider#getAvailableLocales()
|
||||
* getAvailableLocales()}.
|
||||
* @exception NullPointerException if <code>locale</code> is null
|
||||
* @return a date/time formatter.
|
||||
* @see java.text.DateFormat#getDateTimeInstance(int, int, java.util.Locale)
|
||||
*/
|
||||
@Override
|
||||
public DateFormat getDateTimeInstance(int dateStyle, int timeStyle,
|
||||
Locale locale) {
|
||||
return getInstance(dateStyle, timeStyle, locale);
|
||||
}
|
||||
|
||||
private DateFormat getInstance(int dateStyle, int timeStyle, Locale locale) {
|
||||
if (locale == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("", locale);
|
||||
Calendar cal = sdf.getCalendar();
|
||||
try {
|
||||
String pattern = LocaleProviderAdapter.forType(type)
|
||||
.getLocaleResources(locale).getDateTimePattern(timeStyle, dateStyle,
|
||||
cal);
|
||||
sdf.applyPattern(pattern);
|
||||
} catch (MissingResourceException mre) {
|
||||
// Specify the fallback pattern
|
||||
sdf.applyPattern("M/d/yy h:mm a");
|
||||
}
|
||||
|
||||
return sdf;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getAvailableLanguageTags() {
|
||||
return langtags;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.util.locale.provider;
|
||||
|
||||
import java.text.DateFormatSymbols;
|
||||
import java.text.spi.DateFormatSymbolsProvider;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Concrete implementation of the {@link java.text.spi.DateFormatSymbolsProvider
|
||||
* DateFormatSymbolsProvider} class for the JRE LocaleProviderAdapter.
|
||||
*
|
||||
* @author Naoto Sato
|
||||
* @author Masayoshi Okutsu
|
||||
*/
|
||||
public class DateFormatSymbolsProviderImpl extends DateFormatSymbolsProvider implements AvailableLanguageTags {
|
||||
private final LocaleProviderAdapter.Type type;
|
||||
private final Set<String> langtags;
|
||||
|
||||
public DateFormatSymbolsProviderImpl(LocaleProviderAdapter.Type type, Set<String> langtags) {
|
||||
this.type = type;
|
||||
this.langtags = langtags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of all locales for which this locale service provider
|
||||
* can provide localized objects or names.
|
||||
*
|
||||
* @return An array of all locales for which this locale service provider
|
||||
* can provide localized objects or names.
|
||||
*/
|
||||
@Override
|
||||
public Locale[] getAvailableLocales() {
|
||||
return LocaleProviderAdapter.toLocaleArray(langtags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupportedLocale(Locale locale) {
|
||||
return LocaleProviderAdapter.isSupportedLocale(locale, type, langtags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new <code>DateFormatSymbols</code> instance for the
|
||||
* specified locale.
|
||||
*
|
||||
* @param locale the desired locale
|
||||
* @exception NullPointerException if <code>locale</code> is null
|
||||
* @exception IllegalArgumentException if <code>locale</code> isn't
|
||||
* one of the locales returned from
|
||||
* {@link java.util.spi.LocaleServiceProvider#getAvailableLocales()
|
||||
* getAvailableLocales()}.
|
||||
* @return a <code>DateFormatSymbols</code> instance.
|
||||
* @see java.text.DateFormatSymbols#getInstance(java.util.Locale)
|
||||
*/
|
||||
@Override
|
||||
public DateFormatSymbols getInstance(Locale locale) {
|
||||
if (locale == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
|
||||
return new DateFormatSymbols(locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getAvailableLanguageTags() {
|
||||
return langtags;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.util.locale.provider;
|
||||
|
||||
import java.text.DecimalFormatSymbols;
|
||||
import java.text.spi.DecimalFormatSymbolsProvider;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Concrete implementation of the {@link java.text.spi.DecimalFormatSymbolsProvider
|
||||
* DecimalFormatSymbolsProvider} class for the JRE LocaleProviderAdapter.
|
||||
*
|
||||
* @author Naoto Sato
|
||||
* @author Masayoshi Okutsu
|
||||
*/
|
||||
public class DecimalFormatSymbolsProviderImpl extends DecimalFormatSymbolsProvider implements AvailableLanguageTags {
|
||||
private final LocaleProviderAdapter.Type type;
|
||||
private final Set<String> langtags;
|
||||
|
||||
public DecimalFormatSymbolsProviderImpl(LocaleProviderAdapter.Type type, Set<String> langtags) {
|
||||
this.type = type;
|
||||
this.langtags = langtags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of all locales for which this locale service provider
|
||||
* can provide localized objects or names.
|
||||
*
|
||||
* @return An array of all locales for which this locale service provider
|
||||
* can provide localized objects or names.
|
||||
*/
|
||||
@Override
|
||||
public Locale[] getAvailableLocales() {
|
||||
return LocaleProviderAdapter.toLocaleArray(langtags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupportedLocale(Locale locale) {
|
||||
return LocaleProviderAdapter.isSupportedLocale(locale, type, langtags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new <code>DecimalFormatSymbols</code> instance for the
|
||||
* specified locale.
|
||||
*
|
||||
* @param locale the desired locale
|
||||
* @exception NullPointerException if <code>locale</code> is null
|
||||
* @exception IllegalArgumentException if <code>locale</code> isn't
|
||||
* one of the locales returned from
|
||||
* {@link java.util.spi.LocaleServiceProvider#getAvailableLocales()
|
||||
* getAvailableLocales()}.
|
||||
* @return a <code>DecimalFormatSymbols</code> instance.
|
||||
* @see java.text.DecimalFormatSymbols#getInstance(java.util.Locale)
|
||||
*/
|
||||
@Override
|
||||
public DecimalFormatSymbols getInstance(Locale locale) {
|
||||
if (locale == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
|
||||
return new DecimalFormatSymbols(locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getAvailableLanguageTags() {
|
||||
return langtags;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,525 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
* (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
|
||||
* (C) Copyright IBM Corp. 1996 - 2002 - All Rights Reserved
|
||||
*
|
||||
* The original version of this source code and documentation
|
||||
* is copyrighted and owned by Taligent, Inc., a wholly-owned
|
||||
* subsidiary of IBM. These materials are provided under terms
|
||||
* of a License Agreement between Taligent and Sun. This technology
|
||||
* is protected by multiple US and International patents.
|
||||
*
|
||||
* This notice and attribution to Taligent may not be removed.
|
||||
* Taligent is a registered trademark of Taligent, Inc.
|
||||
*/
|
||||
|
||||
package sun.util.locale.provider;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.text.CharacterIterator;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Stack;
|
||||
|
||||
/**
|
||||
* A subclass of RuleBasedBreakIterator that adds the ability to use a dictionary
|
||||
* to further subdivide ranges of text beyond what is possible using just the
|
||||
* state-table-based algorithm. This is necessary, for example, to handle
|
||||
* word and line breaking in Thai, which doesn't use spaces between words. The
|
||||
* state-table-based algorithm used by RuleBasedBreakIterator is used to divide
|
||||
* up text as far as possible, and then contiguous ranges of letters are
|
||||
* repeatedly compared against a list of known words (i.e., the dictionary)
|
||||
* to divide them up into words.
|
||||
*
|
||||
* DictionaryBasedBreakIterator uses the same rule language as RuleBasedBreakIterator,
|
||||
* but adds one more special substitution name: <dictionary>. This substitution
|
||||
* name is used to identify characters in words in the dictionary. The idea is that
|
||||
* if the iterator passes over a chunk of text that includes two or more characters
|
||||
* in a row that are included in <dictionary>, it goes back through that range and
|
||||
* derives additional break positions (if possible) using the dictionary.
|
||||
*
|
||||
* DictionaryBasedBreakIterator is also constructed with the filename of a dictionary
|
||||
* file. It follows a prescribed search path to locate the dictionary (right now,
|
||||
* it looks for it in /com/ibm/text/resources in each directory in the classpath,
|
||||
* and won't find it in JAR files, but this location is likely to change). The
|
||||
* dictionary file is in a serialized binary format. We have a very primitive (and
|
||||
* slow) BuildDictionaryFile utility for creating dictionary files, but aren't
|
||||
* currently making it public. Contact us for help.
|
||||
*/
|
||||
class DictionaryBasedBreakIterator extends RuleBasedBreakIterator {
|
||||
|
||||
/**
|
||||
* a list of known words that is used to divide up contiguous ranges of letters,
|
||||
* stored in a compressed, indexed, format that offers fast access
|
||||
*/
|
||||
private BreakDictionary dictionary;
|
||||
|
||||
/**
|
||||
* a list of flags indicating which character categories are contained in
|
||||
* the dictionary file (this is used to determine which ranges of characters
|
||||
* to apply the dictionary to)
|
||||
*/
|
||||
private boolean[] categoryFlags;
|
||||
|
||||
/**
|
||||
* a temporary hiding place for the number of dictionary characters in the
|
||||
* last range passed over by next()
|
||||
*/
|
||||
private int dictionaryCharCount;
|
||||
|
||||
/**
|
||||
* when a range of characters is divided up using the dictionary, the break
|
||||
* positions that are discovered are stored here, preventing us from having
|
||||
* to use either the dictionary or the state table again until the iterator
|
||||
* leaves this range of text
|
||||
*/
|
||||
private int[] cachedBreakPositions;
|
||||
|
||||
/**
|
||||
* if cachedBreakPositions is not null, this indicates which item in the
|
||||
* cache the current iteration position refers to
|
||||
*/
|
||||
private int positionInCache;
|
||||
|
||||
/**
|
||||
* Constructs a DictionaryBasedBreakIterator.
|
||||
* @param description Same as the description parameter on RuleBasedBreakIterator,
|
||||
* except for the special meaning of "<dictionary>". This parameter is just
|
||||
* passed through to RuleBasedBreakIterator's constructor.
|
||||
* @param dictionaryFilename The filename of the dictionary file to use
|
||||
*/
|
||||
DictionaryBasedBreakIterator(String dataFile, String dictionaryFile)
|
||||
throws IOException {
|
||||
super(dataFile);
|
||||
byte[] tmp = super.getAdditionalData();
|
||||
if (tmp != null) {
|
||||
prepareCategoryFlags(tmp);
|
||||
super.setAdditionalData(null);
|
||||
}
|
||||
dictionary = new BreakDictionary(dictionaryFile);
|
||||
}
|
||||
|
||||
private void prepareCategoryFlags(byte[] data) {
|
||||
categoryFlags = new boolean[data.length];
|
||||
for (int i = 0; i < data.length; i++) {
|
||||
categoryFlags[i] = (data[i] == (byte)1) ? true : false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setText(CharacterIterator newText) {
|
||||
super.setText(newText);
|
||||
cachedBreakPositions = null;
|
||||
dictionaryCharCount = 0;
|
||||
positionInCache = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current iteration position to the beginning of the text.
|
||||
* (i.e., the CharacterIterator's starting offset).
|
||||
* @return The offset of the beginning of the text.
|
||||
*/
|
||||
@Override
|
||||
public int first() {
|
||||
cachedBreakPositions = null;
|
||||
dictionaryCharCount = 0;
|
||||
positionInCache = 0;
|
||||
return super.first();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current iteration position to the end of the text.
|
||||
* (i.e., the CharacterIterator's ending offset).
|
||||
* @return The text's past-the-end offset.
|
||||
*/
|
||||
@Override
|
||||
public int last() {
|
||||
cachedBreakPositions = null;
|
||||
dictionaryCharCount = 0;
|
||||
positionInCache = 0;
|
||||
return super.last();
|
||||
}
|
||||
|
||||
/**
|
||||
* Advances the iterator one step backwards.
|
||||
* @return The position of the last boundary position before the
|
||||
* current iteration position
|
||||
*/
|
||||
@Override
|
||||
public int previous() {
|
||||
CharacterIterator text = getText();
|
||||
|
||||
// if we have cached break positions and we're still in the range
|
||||
// covered by them, just move one step backward in the cache
|
||||
if (cachedBreakPositions != null && positionInCache > 0) {
|
||||
--positionInCache;
|
||||
text.setIndex(cachedBreakPositions[positionInCache]);
|
||||
return cachedBreakPositions[positionInCache];
|
||||
}
|
||||
|
||||
// otherwise, dump the cache and use the inherited previous() method to move
|
||||
// backward. This may fill up the cache with new break positions, in which
|
||||
// case we have to mark our position in the cache
|
||||
else {
|
||||
cachedBreakPositions = null;
|
||||
int result = super.previous();
|
||||
if (cachedBreakPositions != null) {
|
||||
positionInCache = cachedBreakPositions.length - 2;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current iteration position to the last boundary position
|
||||
* before the specified position.
|
||||
* @param offset The position to begin searching from
|
||||
* @return The position of the last boundary before "offset"
|
||||
*/
|
||||
@Override
|
||||
public int preceding(int offset) {
|
||||
CharacterIterator text = getText();
|
||||
checkOffset(offset, text);
|
||||
|
||||
// if we have no cached break positions, or "offset" is outside the
|
||||
// range covered by the cache, we can just call the inherited routine
|
||||
// (which will eventually call other routines in this class that may
|
||||
// refresh the cache)
|
||||
if (cachedBreakPositions == null || offset <= cachedBreakPositions[0] ||
|
||||
offset > cachedBreakPositions[cachedBreakPositions.length - 1]) {
|
||||
cachedBreakPositions = null;
|
||||
return super.preceding(offset);
|
||||
}
|
||||
|
||||
// on the other hand, if "offset" is within the range covered by the cache,
|
||||
// then all we have to do is search the cache for the last break position
|
||||
// before "offset"
|
||||
else {
|
||||
positionInCache = 0;
|
||||
while (positionInCache < cachedBreakPositions.length
|
||||
&& offset > cachedBreakPositions[positionInCache]) {
|
||||
++positionInCache;
|
||||
}
|
||||
--positionInCache;
|
||||
text.setIndex(cachedBreakPositions[positionInCache]);
|
||||
return text.getIndex();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current iteration position to the first boundary position after
|
||||
* the specified position.
|
||||
* @param offset The position to begin searching forward from
|
||||
* @return The position of the first boundary after "offset"
|
||||
*/
|
||||
@Override
|
||||
public int following(int offset) {
|
||||
CharacterIterator text = getText();
|
||||
checkOffset(offset, text);
|
||||
|
||||
// if we have no cached break positions, or if "offset" is outside the
|
||||
// range covered by the cache, then dump the cache and call our
|
||||
// inherited following() method. This will call other methods in this
|
||||
// class that may refresh the cache.
|
||||
if (cachedBreakPositions == null || offset < cachedBreakPositions[0] ||
|
||||
offset >= cachedBreakPositions[cachedBreakPositions.length - 1]) {
|
||||
cachedBreakPositions = null;
|
||||
return super.following(offset);
|
||||
}
|
||||
|
||||
// on the other hand, if "offset" is within the range covered by the
|
||||
// cache, then just search the cache for the first break position
|
||||
// after "offset"
|
||||
else {
|
||||
positionInCache = 0;
|
||||
while (positionInCache < cachedBreakPositions.length
|
||||
&& offset >= cachedBreakPositions[positionInCache]) {
|
||||
++positionInCache;
|
||||
}
|
||||
text.setIndex(cachedBreakPositions[positionInCache]);
|
||||
return text.getIndex();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the implementation function for next().
|
||||
*/
|
||||
@Override
|
||||
protected int handleNext() {
|
||||
CharacterIterator text = getText();
|
||||
|
||||
// if there are no cached break positions, or if we've just moved
|
||||
// off the end of the range covered by the cache, we have to dump
|
||||
// and possibly regenerate the cache
|
||||
if (cachedBreakPositions == null ||
|
||||
positionInCache == cachedBreakPositions.length - 1) {
|
||||
|
||||
// start by using the inherited handleNext() to find a tentative return
|
||||
// value. dictionaryCharCount tells us how many dictionary characters
|
||||
// we passed over on our way to the tentative return value
|
||||
int startPos = text.getIndex();
|
||||
dictionaryCharCount = 0;
|
||||
int result = super.handleNext();
|
||||
|
||||
// if we passed over more than one dictionary character, then we use
|
||||
// divideUpDictionaryRange() to regenerate the cached break positions
|
||||
// for the new range
|
||||
if (dictionaryCharCount > 1 && result - startPos > 1) {
|
||||
divideUpDictionaryRange(startPos, result);
|
||||
}
|
||||
|
||||
// otherwise, the value we got back from the inherited fuction
|
||||
// is our return value, and we can dump the cache
|
||||
else {
|
||||
cachedBreakPositions = null;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// if the cache of break positions has been regenerated (or existed all
|
||||
// along), then just advance to the next break position in the cache
|
||||
// and return it
|
||||
if (cachedBreakPositions != null) {
|
||||
++positionInCache;
|
||||
text.setIndex(cachedBreakPositions[positionInCache]);
|
||||
return cachedBreakPositions[positionInCache];
|
||||
}
|
||||
return -9999; // SHOULD NEVER GET HERE!
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks up a character category for a character.
|
||||
*/
|
||||
@Override
|
||||
protected int lookupCategory(int c) {
|
||||
// this override of lookupCategory() exists only to keep track of whether we've
|
||||
// passed over any dictionary characters. It calls the inherited lookupCategory()
|
||||
// to do the real work, and then checks whether its return value is one of the
|
||||
// categories represented in the dictionary. If it is, bump the dictionary-
|
||||
// character count.
|
||||
int result = super.lookupCategory(c);
|
||||
if (result != RuleBasedBreakIterator.IGNORE && categoryFlags[result]) {
|
||||
++dictionaryCharCount;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the function that actually implements the dictionary-based
|
||||
* algorithm. Given the endpoints of a range of text, it uses the
|
||||
* dictionary to determine the positions of any boundaries in this
|
||||
* range. It stores all the boundary positions it discovers in
|
||||
* cachedBreakPositions so that we only have to do this work once
|
||||
* for each time we enter the range.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private void divideUpDictionaryRange(int startPos, int endPos) {
|
||||
CharacterIterator text = getText();
|
||||
|
||||
// the range we're dividing may begin or end with non-dictionary characters
|
||||
// (i.e., for line breaking, we may have leading or trailing punctuation
|
||||
// that needs to be kept with the word). Seek from the beginning of the
|
||||
// range to the first dictionary character
|
||||
text.setIndex(startPos);
|
||||
int c = getCurrent();
|
||||
int category = lookupCategory(c);
|
||||
while (category == IGNORE || !categoryFlags[category]) {
|
||||
c = getNext();
|
||||
category = lookupCategory(c);
|
||||
}
|
||||
|
||||
// initialize. We maintain two stacks: currentBreakPositions contains
|
||||
// the list of break positions that will be returned if we successfully
|
||||
// finish traversing the whole range now. possibleBreakPositions lists
|
||||
// all other possible word ends we've passed along the way. (Whenever
|
||||
// we reach an error [a sequence of characters that can't begin any word
|
||||
// in the dictionary], we back up, possibly delete some breaks from
|
||||
// currentBreakPositions, move a break from possibleBreakPositions
|
||||
// to currentBreakPositions, and start over from there. This process
|
||||
// continues in this way until we either successfully make it all the way
|
||||
// across the range, or exhaust all of our combinations of break
|
||||
// positions.)
|
||||
Stack<Integer> currentBreakPositions = new Stack<>();
|
||||
Stack<Integer> possibleBreakPositions = new Stack<>();
|
||||
List<Integer> wrongBreakPositions = new ArrayList<>();
|
||||
|
||||
// the dictionary is implemented as a trie, which is treated as a state
|
||||
// machine. -1 represents the end of a legal word. Every word in the
|
||||
// dictionary is represented by a path from the root node to -1. A path
|
||||
// that ends in state 0 is an illegal combination of characters.
|
||||
int state = 0;
|
||||
|
||||
// these two variables are used for error handling. We keep track of the
|
||||
// farthest we've gotten through the range being divided, and the combination
|
||||
// of breaks that got us that far. If we use up all possible break
|
||||
// combinations, the text contains an error or a word that's not in the
|
||||
// dictionary. In this case, we "bless" the break positions that got us the
|
||||
// farthest as real break positions, and then start over from scratch with
|
||||
// the character where the error occurred.
|
||||
int farthestEndPoint = text.getIndex();
|
||||
Stack<Integer> bestBreakPositions = null;
|
||||
|
||||
// initialize (we always exit the loop with a break statement)
|
||||
c = getCurrent();
|
||||
while (true) {
|
||||
|
||||
// if we can transition to state "-1" from our current state, we're
|
||||
// on the last character of a legal word. Push that position onto
|
||||
// the possible-break-positions stack
|
||||
if (dictionary.getNextState(state, 0) == -1) {
|
||||
possibleBreakPositions.push(text.getIndex());
|
||||
}
|
||||
|
||||
// look up the new state to transition to in the dictionary
|
||||
state = dictionary.getNextStateFromCharacter(state, c);
|
||||
|
||||
// if the character we're sitting on causes us to transition to
|
||||
// the "end of word" state, then it was a non-dictionary character
|
||||
// and we've successfully traversed the whole range. Drop out
|
||||
// of the loop.
|
||||
if (state == -1) {
|
||||
currentBreakPositions.push(text.getIndex());
|
||||
break;
|
||||
}
|
||||
|
||||
// if the character we're sitting on causes us to transition to
|
||||
// the error state, or if we've gone off the end of the range
|
||||
// without transitioning to the "end of word" state, we've hit
|
||||
// an error...
|
||||
else if (state == 0 || text.getIndex() >= endPos) {
|
||||
|
||||
// if this is the farthest we've gotten, take note of it in
|
||||
// case there's an error in the text
|
||||
if (text.getIndex() > farthestEndPoint) {
|
||||
farthestEndPoint = text.getIndex();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Stack<Integer> currentBreakPositionsCopy = (Stack<Integer>) currentBreakPositions.clone();
|
||||
|
||||
bestBreakPositions = currentBreakPositionsCopy;
|
||||
}
|
||||
|
||||
// wrongBreakPositions is a list of all break positions
|
||||
// we've tried starting that didn't allow us to traverse
|
||||
// all the way through the text. Every time we pop a
|
||||
// break position off of currentBreakPositions, we put it
|
||||
// into wrongBreakPositions to avoid trying it again later.
|
||||
// If we make it to this spot, we're either going to back
|
||||
// up to a break in possibleBreakPositions and try starting
|
||||
// over from there, or we've exhausted all possible break
|
||||
// positions and are going to do the fallback procedure.
|
||||
// This loop prevents us from messing with anything in
|
||||
// possibleBreakPositions that didn't work as a starting
|
||||
// point the last time we tried it (this is to prevent a bunch of
|
||||
// repetitive checks from slowing down some extreme cases)
|
||||
while (!possibleBreakPositions.isEmpty()
|
||||
&& wrongBreakPositions.contains(possibleBreakPositions.peek())) {
|
||||
possibleBreakPositions.pop();
|
||||
}
|
||||
|
||||
// if we've used up all possible break-position combinations, there's
|
||||
// an error or an unknown word in the text. In this case, we start
|
||||
// over, treating the farthest character we've reached as the beginning
|
||||
// of the range, and "blessing" the break positions that got us that
|
||||
// far as real break positions
|
||||
if (possibleBreakPositions.isEmpty()) {
|
||||
if (bestBreakPositions != null) {
|
||||
currentBreakPositions = bestBreakPositions;
|
||||
if (farthestEndPoint < endPos) {
|
||||
text.setIndex(farthestEndPoint + 1);
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ((currentBreakPositions.size() == 0 ||
|
||||
currentBreakPositions.peek().intValue() != text.getIndex())
|
||||
&& text.getIndex() != startPos) {
|
||||
currentBreakPositions.push(new Integer(text.getIndex()));
|
||||
}
|
||||
getNext();
|
||||
currentBreakPositions.push(new Integer(text.getIndex()));
|
||||
}
|
||||
}
|
||||
|
||||
// if we still have more break positions we can try, then promote the
|
||||
// last break in possibleBreakPositions into currentBreakPositions,
|
||||
// and get rid of all entries in currentBreakPositions that come after
|
||||
// it. Then back up to that position and start over from there (i.e.,
|
||||
// treat that position as the beginning of a new word)
|
||||
else {
|
||||
Integer temp = possibleBreakPositions.pop();
|
||||
Integer temp2 = null;
|
||||
while (!currentBreakPositions.isEmpty() && temp.intValue() <
|
||||
currentBreakPositions.peek().intValue()) {
|
||||
temp2 = currentBreakPositions.pop();
|
||||
wrongBreakPositions.add(temp2);
|
||||
}
|
||||
currentBreakPositions.push(temp);
|
||||
text.setIndex(currentBreakPositions.peek().intValue());
|
||||
}
|
||||
|
||||
// re-sync "c" for the next go-round, and drop out of the loop if
|
||||
// we've made it off the end of the range
|
||||
c = getCurrent();
|
||||
if (text.getIndex() >= endPos) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// if we didn't hit any exceptional conditions on this last iteration,
|
||||
// just advance to the next character and loop
|
||||
else {
|
||||
c = getNext();
|
||||
}
|
||||
}
|
||||
|
||||
// dump the last break position in the list, and replace it with the actual
|
||||
// end of the range (which may be the same character, or may be further on
|
||||
// because the range actually ended with non-dictionary characters we want to
|
||||
// keep with the word)
|
||||
if (!currentBreakPositions.isEmpty()) {
|
||||
currentBreakPositions.pop();
|
||||
}
|
||||
currentBreakPositions.push(endPos);
|
||||
|
||||
// create a regular array to hold the break positions and copy
|
||||
// the break positions from the stack to the array (in addition,
|
||||
// our starting position goes into this array as a break position).
|
||||
// This array becomes the cache of break positions used by next()
|
||||
// and previous(), so this is where we actually refresh the cache.
|
||||
cachedBreakPositions = new int[currentBreakPositions.size() + 1];
|
||||
cachedBreakPositions[0] = startPos;
|
||||
|
||||
for (int i = 0; i < currentBreakPositions.size(); i++) {
|
||||
cachedBreakPositions[i + 1] = currentBreakPositions.elementAt(i).intValue();
|
||||
}
|
||||
positionInCache = 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.util.locale.provider;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* FallbackProviderAdapter implementation.
|
||||
*
|
||||
* @author Naoto Sato
|
||||
*/
|
||||
public class FallbackLocaleProviderAdapter extends JRELocaleProviderAdapter {
|
||||
|
||||
/**
|
||||
* Supported language tag set.
|
||||
*/
|
||||
private static final Set<String> rootTagSet =
|
||||
Collections.singleton(Locale.ROOT.toLanguageTag());
|
||||
|
||||
/**
|
||||
* Fallback provider only provides the ROOT locale data.
|
||||
*/
|
||||
private final LocaleResources rootLocaleResources =
|
||||
new LocaleResources(this, Locale.ROOT);
|
||||
|
||||
/**
|
||||
* Returns the type of this LocaleProviderAdapter
|
||||
*/
|
||||
@Override
|
||||
public LocaleProviderAdapter.Type getAdapterType() {
|
||||
return Type.FALLBACK;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocaleResources getLocaleResources(Locale locale) {
|
||||
return rootLocaleResources;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Set<String> createLanguageTagSet(String category) {
|
||||
return rootTagSet;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.util.locale.provider;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.spi.LocaleServiceProvider;
|
||||
|
||||
/**
|
||||
* LocaleProviderAdapter implementation for the host locale data.
|
||||
* Currently it is only implemented on Windows Vista or later.
|
||||
*
|
||||
* @author Naoto Sato
|
||||
*/
|
||||
public class HostLocaleProviderAdapter extends AuxLocaleProviderAdapter {
|
||||
|
||||
/**
|
||||
* Returns the type of this LocaleProviderAdapter
|
||||
*/
|
||||
@Override
|
||||
public LocaleProviderAdapter.Type getAdapterType() {
|
||||
return LocaleProviderAdapter.Type.HOST;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
protected <P extends LocaleServiceProvider> P findInstalledProvider(final Class<P> c) {
|
||||
try {
|
||||
Method getter = HostLocaleProviderAdapterImpl.class.getMethod(
|
||||
"get" + c.getSimpleName(), (Class<?>[]) null);
|
||||
return (P)getter.invoke(null, (Object[]) null);
|
||||
} catch (NoSuchMethodException |
|
||||
IllegalAccessException |
|
||||
IllegalArgumentException |
|
||||
InvocationTargetException ex) {
|
||||
LocaleServiceProviderPool.config(HostLocaleProviderAdapter.class, ex.toString());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,645 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package sun.util.locale.provider;
|
||||
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.text.DateFormat;
|
||||
import java.text.DateFormatSymbols;
|
||||
import java.text.DecimalFormat;
|
||||
import java.text.DecimalFormatSymbols;
|
||||
import java.text.NumberFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.text.spi.DateFormatProvider;
|
||||
import java.text.spi.DateFormatSymbolsProvider;
|
||||
import java.text.spi.DecimalFormatSymbolsProvider;
|
||||
import java.text.spi.NumberFormatProvider;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collections;
|
||||
import java.util.Currency;
|
||||
import java.util.HashSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.ResourceBundle.Control;
|
||||
import java.util.Set;
|
||||
import java.util.TimeZone;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.atomic.AtomicReferenceArray;
|
||||
import java.util.spi.CalendarDataProvider;
|
||||
import java.util.spi.CurrencyNameProvider;
|
||||
import java.util.spi.LocaleNameProvider;
|
||||
import sun.util.spi.CalendarProvider;
|
||||
|
||||
/**
|
||||
* LocaleProviderdapter implementation for the Windows locale data.
|
||||
*
|
||||
* @author Naoto Sato
|
||||
*/
|
||||
public class HostLocaleProviderAdapterImpl {
|
||||
|
||||
// locale categories
|
||||
private static final int CAT_DISPLAY = 0;
|
||||
private static final int CAT_FORMAT = 1;
|
||||
|
||||
// NumberFormat styles
|
||||
private static final int NF_NUMBER = 0;
|
||||
private static final int NF_CURRENCY = 1;
|
||||
private static final int NF_PERCENT = 2;
|
||||
private static final int NF_INTEGER = 3;
|
||||
private static final int NF_MAX = NF_INTEGER;
|
||||
|
||||
// CalendarData value types
|
||||
private static final int CD_FIRSTDAYOFWEEK = 0;
|
||||
private static final int CD_MINIMALDAYSINFIRSTWEEK = 1;
|
||||
|
||||
// Currency/Locale display name types
|
||||
private static final int DN_CURRENCY_NAME = 0;
|
||||
private static final int DN_CURRENCY_SYMBOL = 1;
|
||||
private static final int DN_LOCALE_LANGUAGE = 2;
|
||||
private static final int DN_LOCALE_SCRIPT = 3;
|
||||
private static final int DN_LOCALE_REGION = 4;
|
||||
private static final int DN_LOCALE_VARIANT = 5;
|
||||
|
||||
// Native Calendar ID to LDML calendar type map
|
||||
private static final String[] calIDToLDML = {
|
||||
"",
|
||||
"gregory",
|
||||
"gregory_en-US",
|
||||
"japanese",
|
||||
"roc",
|
||||
"", // No appropriate type for CAL_KOREA
|
||||
"islamic",
|
||||
"buddhist",
|
||||
"hebrew",
|
||||
"gregory_fr",
|
||||
"gregory_ar",
|
||||
"gregory_en",
|
||||
"gregory_fr",
|
||||
};
|
||||
|
||||
// Caches
|
||||
private static ConcurrentMap<Locale, SoftReference<AtomicReferenceArray<String>>> dateFormatCache = new ConcurrentHashMap<>();
|
||||
private static ConcurrentMap<Locale, SoftReference<DateFormatSymbols>> dateFormatSymbolsCache = new ConcurrentHashMap<>();
|
||||
private static ConcurrentMap<Locale, SoftReference<AtomicReferenceArray<String>>> numberFormatCache = new ConcurrentHashMap<>();
|
||||
private static ConcurrentMap<Locale, SoftReference<DecimalFormatSymbols>> decimalFormatSymbolsCache = new ConcurrentHashMap<>();
|
||||
|
||||
private static final Set<Locale> supportedLocaleSet;
|
||||
private static final String nativeDisplayLanguage;
|
||||
static {
|
||||
Set<Locale> tmpSet = new HashSet<>();
|
||||
if (initialize()) {
|
||||
// Assuming the default locales do not include any extensions, so
|
||||
// no stripping is needed here.
|
||||
Control c = Control.getNoFallbackControl(Control.FORMAT_DEFAULT);
|
||||
String displayLocale = getDefaultLocale(CAT_DISPLAY);
|
||||
Locale l = Locale.forLanguageTag(displayLocale.replace('_', '-'));
|
||||
tmpSet.addAll(c.getCandidateLocales("", l));
|
||||
nativeDisplayLanguage = l.getLanguage();
|
||||
|
||||
String formatLocale = getDefaultLocale(CAT_FORMAT);
|
||||
if (!formatLocale.equals(displayLocale)) {
|
||||
l = Locale.forLanguageTag(formatLocale.replace('_', '-'));
|
||||
tmpSet.addAll(c.getCandidateLocales("", l));
|
||||
}
|
||||
} else {
|
||||
nativeDisplayLanguage = "";
|
||||
}
|
||||
supportedLocaleSet = Collections.unmodifiableSet(tmpSet);
|
||||
}
|
||||
private final static Locale[] supportedLocale = supportedLocaleSet.toArray(new Locale[0]);
|
||||
|
||||
public static DateFormatProvider getDateFormatProvider() {
|
||||
return new DateFormatProvider() {
|
||||
@Override
|
||||
public Locale[] getAvailableLocales() {
|
||||
return getSupportedCalendarLocales();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupportedLocale(Locale locale) {
|
||||
return isSupportedCalendarLocale(locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DateFormat getDateInstance(int style, Locale locale) {
|
||||
AtomicReferenceArray<String> patterns = getDateTimePatterns(locale);
|
||||
return new SimpleDateFormat(patterns.get(style/2),
|
||||
getCalendarLocale(locale));
|
||||
}
|
||||
|
||||
@Override
|
||||
public DateFormat getTimeInstance(int style, Locale locale) {
|
||||
AtomicReferenceArray<String> patterns = getDateTimePatterns(locale);
|
||||
return new SimpleDateFormat(patterns.get(style/2+2),
|
||||
getCalendarLocale(locale));
|
||||
}
|
||||
|
||||
@Override
|
||||
public DateFormat getDateTimeInstance(int dateStyle,
|
||||
int timeStyle, Locale locale) {
|
||||
AtomicReferenceArray<String> patterns = getDateTimePatterns(locale);
|
||||
String pattern = new StringBuilder(patterns.get(dateStyle/2))
|
||||
.append(" ")
|
||||
.append(patterns.get(timeStyle/2+2))
|
||||
.toString();
|
||||
return new SimpleDateFormat(pattern, getCalendarLocale(locale));
|
||||
}
|
||||
|
||||
private AtomicReferenceArray<String> getDateTimePatterns(Locale locale) {
|
||||
AtomicReferenceArray<String> patterns;
|
||||
SoftReference<AtomicReferenceArray<String>> ref = dateFormatCache.get(locale);
|
||||
|
||||
if (ref == null || (patterns = ref.get()) == null) {
|
||||
String langtag = removeExtensions(locale).toLanguageTag();
|
||||
patterns = new AtomicReferenceArray<>(4);
|
||||
patterns.compareAndSet(0, null, convertDateTimePattern(
|
||||
getDateTimePattern(DateFormat.LONG, -1, langtag)));
|
||||
patterns.compareAndSet(1, null, convertDateTimePattern(
|
||||
getDateTimePattern(DateFormat.SHORT, -1, langtag)));
|
||||
patterns.compareAndSet(2, null, convertDateTimePattern(
|
||||
getDateTimePattern(-1, DateFormat.LONG, langtag)));
|
||||
patterns.compareAndSet(3, null, convertDateTimePattern(
|
||||
getDateTimePattern(-1, DateFormat.SHORT, langtag)));
|
||||
ref = new SoftReference<>(patterns);
|
||||
dateFormatCache.put(locale, ref);
|
||||
}
|
||||
|
||||
return patterns;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static DateFormatSymbolsProvider getDateFormatSymbolsProvider() {
|
||||
return new DateFormatSymbolsProvider() {
|
||||
|
||||
@Override
|
||||
public Locale[] getAvailableLocales() {
|
||||
return getSupportedCalendarLocales();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupportedLocale(Locale locale) {
|
||||
return isSupportedCalendarLocale(locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DateFormatSymbols getInstance(Locale locale) {
|
||||
DateFormatSymbols dfs;
|
||||
SoftReference<DateFormatSymbols> ref =
|
||||
dateFormatSymbolsCache.get(locale);
|
||||
|
||||
if (ref == null || (dfs = ref.get()) == null) {
|
||||
dfs = new DateFormatSymbols(locale);
|
||||
String langTag = removeExtensions(locale).toLanguageTag();
|
||||
|
||||
dfs.setAmPmStrings(getAmPmStrings(langTag, dfs.getAmPmStrings()));
|
||||
dfs.setEras(getEras(langTag, dfs.getEras()));
|
||||
dfs.setMonths(getMonths(langTag, dfs.getMonths()));
|
||||
dfs.setShortMonths(getShortMonths(langTag, dfs.getShortMonths()));
|
||||
dfs.setWeekdays(getWeekdays(langTag, dfs.getWeekdays()));
|
||||
dfs.setShortWeekdays(getShortWeekdays(langTag, dfs.getShortWeekdays()));
|
||||
ref = new SoftReference<>(dfs);
|
||||
dateFormatSymbolsCache.put(locale, ref);
|
||||
}
|
||||
return (DateFormatSymbols)dfs.clone();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static NumberFormatProvider getNumberFormatProvider() {
|
||||
return new NumberFormatProvider() {
|
||||
|
||||
@Override
|
||||
public Locale[] getAvailableLocales() {
|
||||
return getSupportedNativeDigitLocales();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupportedLocale(Locale locale) {
|
||||
return isSupportedNativeDigitLocale(locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NumberFormat getCurrencyInstance(Locale locale) {
|
||||
AtomicReferenceArray<String> patterns = getNumberPatterns(locale);
|
||||
return new DecimalFormat(patterns.get(NF_CURRENCY),
|
||||
DecimalFormatSymbols.getInstance(locale));
|
||||
}
|
||||
|
||||
@Override
|
||||
public NumberFormat getIntegerInstance(Locale locale) {
|
||||
AtomicReferenceArray<String> patterns = getNumberPatterns(locale);
|
||||
return new DecimalFormat(patterns.get(NF_INTEGER),
|
||||
DecimalFormatSymbols.getInstance(locale));
|
||||
}
|
||||
|
||||
@Override
|
||||
public NumberFormat getNumberInstance(Locale locale) {
|
||||
AtomicReferenceArray<String> patterns = getNumberPatterns(locale);
|
||||
return new DecimalFormat(patterns.get(NF_NUMBER),
|
||||
DecimalFormatSymbols.getInstance(locale));
|
||||
}
|
||||
|
||||
@Override
|
||||
public NumberFormat getPercentInstance(Locale locale) {
|
||||
AtomicReferenceArray<String> patterns = getNumberPatterns(locale);
|
||||
return new DecimalFormat(patterns.get(NF_PERCENT),
|
||||
DecimalFormatSymbols.getInstance(locale));
|
||||
}
|
||||
|
||||
private AtomicReferenceArray<String> getNumberPatterns(Locale locale) {
|
||||
AtomicReferenceArray<String> patterns;
|
||||
SoftReference<AtomicReferenceArray<String>> ref = numberFormatCache.get(locale);
|
||||
|
||||
if (ref == null || (patterns = ref.get()) == null) {
|
||||
String langtag = locale.toLanguageTag();
|
||||
patterns = new AtomicReferenceArray<>(NF_MAX+1);
|
||||
for (int i = 0; i <= NF_MAX; i++) {
|
||||
patterns.compareAndSet(i, null, getNumberPattern(i, langtag));
|
||||
}
|
||||
ref = new SoftReference<>(patterns);
|
||||
numberFormatCache.put(locale, ref);
|
||||
}
|
||||
return patterns;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static DecimalFormatSymbolsProvider getDecimalFormatSymbolsProvider() {
|
||||
return new DecimalFormatSymbolsProvider() {
|
||||
|
||||
@Override
|
||||
public Locale[] getAvailableLocales() {
|
||||
return getSupportedNativeDigitLocales();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupportedLocale(Locale locale) {
|
||||
return isSupportedNativeDigitLocale(locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DecimalFormatSymbols getInstance(Locale locale) {
|
||||
DecimalFormatSymbols dfs;
|
||||
SoftReference<DecimalFormatSymbols> ref =
|
||||
decimalFormatSymbolsCache.get(locale);
|
||||
|
||||
if (ref == null || (dfs = ref.get()) == null) {
|
||||
dfs = new DecimalFormatSymbols(getNumberLocale(locale));
|
||||
String langTag = removeExtensions(locale).toLanguageTag();
|
||||
|
||||
// DecimalFormatSymbols.setInternationalCurrencySymbol() has
|
||||
// a side effect of setting the currency symbol as well. So
|
||||
// the calling order is relevant here.
|
||||
dfs.setInternationalCurrencySymbol(getInternationalCurrencySymbol(langTag, dfs.getInternationalCurrencySymbol()));
|
||||
dfs.setCurrencySymbol(getCurrencySymbol(langTag, dfs.getCurrencySymbol()));
|
||||
dfs.setDecimalSeparator(getDecimalSeparator(langTag, dfs.getDecimalSeparator()));
|
||||
dfs.setGroupingSeparator(getGroupingSeparator(langTag, dfs.getGroupingSeparator()));
|
||||
dfs.setInfinity(getInfinity(langTag, dfs.getInfinity()));
|
||||
dfs.setMinusSign(getMinusSign(langTag, dfs.getMinusSign()));
|
||||
dfs.setMonetaryDecimalSeparator(getMonetaryDecimalSeparator(langTag, dfs.getMonetaryDecimalSeparator()));
|
||||
dfs.setNaN(getNaN(langTag, dfs.getNaN()));
|
||||
dfs.setPercent(getPercent(langTag, dfs.getPercent()));
|
||||
dfs.setPerMill(getPerMill(langTag, dfs.getPerMill()));
|
||||
dfs.setZeroDigit(getZeroDigit(langTag, dfs.getZeroDigit()));
|
||||
ref = new SoftReference<>(dfs);
|
||||
decimalFormatSymbolsCache.put(locale, ref);
|
||||
}
|
||||
return (DecimalFormatSymbols)dfs.clone();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static CalendarDataProvider getCalendarDataProvider() {
|
||||
return new CalendarDataProvider() {
|
||||
@Override
|
||||
public Locale[] getAvailableLocales() {
|
||||
return getSupportedCalendarLocales();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupportedLocale(Locale locale) {
|
||||
return isSupportedCalendarLocale(locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFirstDayOfWeek(Locale locale) {
|
||||
int first = getCalendarDataValue(
|
||||
removeExtensions(locale).toLanguageTag(),
|
||||
CD_FIRSTDAYOFWEEK);
|
||||
if (first != -1) {
|
||||
return (first + 1) % 7 + 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinimalDaysInFirstWeek(Locale locale) {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static CalendarProvider getCalendarProvider() {
|
||||
return new CalendarProvider() {
|
||||
@Override
|
||||
public Locale[] getAvailableLocales() {
|
||||
return getSupportedCalendarLocales();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupportedLocale(Locale locale) {
|
||||
return isSupportedCalendarLocale(locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Calendar getInstance(TimeZone zone, Locale locale) {
|
||||
return new Calendar.Builder()
|
||||
.setLocale(getCalendarLocale(locale))
|
||||
.setTimeZone(zone)
|
||||
.setInstant(System.currentTimeMillis())
|
||||
.build();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static CurrencyNameProvider getCurrencyNameProvider() {
|
||||
return new CurrencyNameProvider() {
|
||||
@Override
|
||||
public Locale[] getAvailableLocales() {
|
||||
return supportedLocale;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupportedLocale(Locale locale) {
|
||||
// Ignore the extensions for now
|
||||
return supportedLocaleSet.contains(locale.stripExtensions()) &&
|
||||
locale.getLanguage().equals(nativeDisplayLanguage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSymbol(String currencyCode, Locale locale) {
|
||||
// Retrieves the currency symbol by calling
|
||||
// GetLocaleInfoEx(LOCALE_SCURRENCY).
|
||||
// It only works with the "locale"'s currency in its native
|
||||
// language.
|
||||
try {
|
||||
if (Currency.getInstance(locale).getCurrencyCode()
|
||||
.equals(currencyCode)) {
|
||||
return getDisplayString(locale.toLanguageTag(),
|
||||
DN_CURRENCY_SYMBOL, currencyCode);
|
||||
}
|
||||
} catch (IllegalArgumentException iae) {}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayName(String currencyCode, Locale locale) {
|
||||
// Retrieves the display name by calling
|
||||
// GetLocaleInfoEx(LOCALE_SNATIVECURRNAME).
|
||||
// It only works with the "locale"'s currency in its native
|
||||
// language.
|
||||
try {
|
||||
if (Currency.getInstance(locale).getCurrencyCode()
|
||||
.equals(currencyCode)) {
|
||||
return getDisplayString(locale.toLanguageTag(),
|
||||
DN_CURRENCY_NAME, currencyCode);
|
||||
}
|
||||
} catch (IllegalArgumentException iae) {}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static LocaleNameProvider getLocaleNameProvider() {
|
||||
return new LocaleNameProvider() {
|
||||
@Override
|
||||
public Locale[] getAvailableLocales() {
|
||||
return supportedLocale;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupportedLocale(Locale locale) {
|
||||
return supportedLocaleSet.contains(locale.stripExtensions()) &&
|
||||
locale.getLanguage().equals(nativeDisplayLanguage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayLanguage(String languageCode, Locale locale) {
|
||||
// Retrieves the display language name by calling
|
||||
// GetLocaleInfoEx(LOCALE_SLOCALIZEDLANGUAGENAME).
|
||||
return getDisplayString(locale.toLanguageTag(),
|
||||
DN_LOCALE_LANGUAGE, languageCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayCountry(String countryCode, Locale locale) {
|
||||
// Retrieves the display country name by calling
|
||||
// GetLocaleInfoEx(LOCALE_SLOCALIZEDCOUNTRYNAME).
|
||||
return getDisplayString(locale.toLanguageTag(),
|
||||
DN_LOCALE_REGION, nativeDisplayLanguage+"-"+countryCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayScript(String scriptCode, Locale locale) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayVariant(String variantCode, Locale locale) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
private static String convertDateTimePattern(String winPattern) {
|
||||
String ret = winPattern.replaceAll("dddd", "EEEE");
|
||||
ret = ret.replaceAll("ddd", "EEE");
|
||||
ret = ret.replaceAll("tt", "aa");
|
||||
ret = ret.replaceAll("g", "GG");
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static Locale[] getSupportedCalendarLocales() {
|
||||
if (supportedLocale.length != 0 &&
|
||||
supportedLocaleSet.contains(Locale.JAPAN) &&
|
||||
isJapaneseCalendar()) {
|
||||
Locale[] sup = new Locale[supportedLocale.length+1];
|
||||
sup[0] = JRELocaleConstants.JA_JP_JP;
|
||||
System.arraycopy(supportedLocale, 0, sup, 1, supportedLocale.length);
|
||||
return sup;
|
||||
}
|
||||
return supportedLocale;
|
||||
}
|
||||
|
||||
private static boolean isSupportedCalendarLocale(Locale locale) {
|
||||
Locale base = locale;
|
||||
|
||||
if (base.hasExtensions() || base.getVariant() != "") {
|
||||
// strip off extensions and variant.
|
||||
base = new Locale.Builder()
|
||||
.setLocale(locale)
|
||||
.clearExtensions()
|
||||
.build();
|
||||
}
|
||||
|
||||
if (!supportedLocaleSet.contains(base)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int calid = getCalendarID(base.toLanguageTag());
|
||||
if (calid <= 0 || calid >= calIDToLDML.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String requestedCalType = locale.getUnicodeLocaleType("ca");
|
||||
String nativeCalType = calIDToLDML[calid]
|
||||
.replaceFirst("_.*", ""); // remove locale part.
|
||||
|
||||
if (requestedCalType == null) {
|
||||
return Calendar.getAvailableCalendarTypes().contains(nativeCalType);
|
||||
} else {
|
||||
return requestedCalType.equals(nativeCalType);
|
||||
}
|
||||
}
|
||||
|
||||
private static Locale[] getSupportedNativeDigitLocales() {
|
||||
if (supportedLocale.length != 0 &&
|
||||
supportedLocaleSet.contains(JRELocaleConstants.TH_TH) &&
|
||||
isNativeDigit("th-TH")) {
|
||||
Locale[] sup = new Locale[supportedLocale.length+1];
|
||||
sup[0] = JRELocaleConstants.TH_TH_TH;
|
||||
System.arraycopy(supportedLocale, 0, sup, 1, supportedLocale.length);
|
||||
return sup;
|
||||
}
|
||||
return supportedLocale;
|
||||
}
|
||||
|
||||
private static boolean isSupportedNativeDigitLocale(Locale locale) {
|
||||
// special case for th_TH_TH
|
||||
if (JRELocaleConstants.TH_TH_TH.equals(locale)) {
|
||||
return isNativeDigit("th-TH");
|
||||
}
|
||||
|
||||
String numtype = null;
|
||||
Locale base = locale;
|
||||
if (locale.hasExtensions()) {
|
||||
numtype = locale.getUnicodeLocaleType("nu");
|
||||
base = locale.stripExtensions();
|
||||
}
|
||||
|
||||
if (supportedLocaleSet.contains(base)) {
|
||||
// Only supports Latin or Thai (in thai locales) digits.
|
||||
if (numtype == null || numtype.equals("latn")) {
|
||||
return true;
|
||||
} else if (locale.getLanguage().equals("th")) {
|
||||
return "thai".equals(numtype) &&
|
||||
isNativeDigit(locale.toLanguageTag());
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static Locale removeExtensions(Locale src) {
|
||||
return new Locale.Builder().setLocale(src).clearExtensions().build();
|
||||
}
|
||||
|
||||
private static boolean isJapaneseCalendar() {
|
||||
return getCalendarID("ja-JP") == 3; // 3: CAL_JAPAN
|
||||
}
|
||||
|
||||
private static Locale getCalendarLocale(Locale locale) {
|
||||
int calid = getCalendarID(locale.toLanguageTag());
|
||||
if (calid > 0 && calid < calIDToLDML.length) {
|
||||
Locale.Builder lb = new Locale.Builder();
|
||||
String[] caltype = calIDToLDML[calid].split("_");
|
||||
if (caltype.length > 1) {
|
||||
lb.setLocale(Locale.forLanguageTag(caltype[1]));
|
||||
} else {
|
||||
lb.setLocale(locale);
|
||||
}
|
||||
lb.setUnicodeLocaleKeyword("ca", caltype[0]);
|
||||
return lb.build();
|
||||
}
|
||||
|
||||
return locale;
|
||||
}
|
||||
|
||||
private static Locale getNumberLocale(Locale src) {
|
||||
if (JRELocaleConstants.TH_TH.equals(src)) {
|
||||
if (isNativeDigit("th-TH")) {
|
||||
Locale.Builder lb = new Locale.Builder().setLocale(src);
|
||||
lb.setUnicodeLocaleKeyword("nu", "thai");
|
||||
return lb.build();
|
||||
}
|
||||
}
|
||||
|
||||
return src;
|
||||
}
|
||||
|
||||
// native methods
|
||||
|
||||
// initialize
|
||||
private static native boolean initialize();
|
||||
private static native String getDefaultLocale(int cat);
|
||||
|
||||
// For DateFormatProvider
|
||||
private static native String getDateTimePattern(int dateStyle, int timeStyle, String langTag);
|
||||
private static native int getCalendarID(String langTag);
|
||||
|
||||
// For DateFormatSymbolsProvider
|
||||
private static native String[] getAmPmStrings(String langTag, String[] ampm);
|
||||
private static native String[] getEras(String langTag, String[] eras);
|
||||
private static native String[] getMonths(String langTag, String[] months);
|
||||
private static native String[] getShortMonths(String langTag, String[] smonths);
|
||||
private static native String[] getWeekdays(String langTag, String[] wdays);
|
||||
private static native String[] getShortWeekdays(String langTag, String[] swdays);
|
||||
|
||||
// For NumberFormatProvider
|
||||
private static native String getNumberPattern(int numberStyle, String langTag);
|
||||
private static native boolean isNativeDigit(String langTag);
|
||||
|
||||
// For DecimalFormatSymbolsProvider
|
||||
private static native String getCurrencySymbol(String langTag, String currencySymbol);
|
||||
private static native char getDecimalSeparator(String langTag, char decimalSeparator);
|
||||
private static native char getGroupingSeparator(String langTag, char groupingSeparator);
|
||||
private static native String getInfinity(String langTag, String infinity);
|
||||
private static native String getInternationalCurrencySymbol(String langTag, String internationalCurrencySymbol);
|
||||
private static native char getMinusSign(String langTag, char minusSign);
|
||||
private static native char getMonetaryDecimalSeparator(String langTag, char monetaryDecimalSeparator);
|
||||
private static native String getNaN(String langTag, String nan);
|
||||
private static native char getPercent(String langTag, char percent);
|
||||
private static native char getPerMill(String langTag, char perMill);
|
||||
private static native char getZeroDigit(String langTag, char zeroDigit);
|
||||
|
||||
// For CalendarDataProvider
|
||||
private static native int getCalendarDataValue(String langTag, int type);
|
||||
|
||||
// For Locale/CurrencyNameProvider
|
||||
private static native String getDisplayString(String langTag, int key, String value);
|
||||
}
|
||||
45
jdkSrc/jdk8/sun/util/locale/provider/JRELocaleConstants.java
Normal file
45
jdkSrc/jdk8/sun/util/locale/provider/JRELocaleConstants.java
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.util.locale.provider;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Singletons for the well-known JRE-specific Locales. (th_TH isn't JRE specific,
|
||||
* but it's treated as a special Locale because of the Thai Buddhist calendar
|
||||
* support.)
|
||||
*
|
||||
* @author Masayoshi Okutsu
|
||||
*/
|
||||
public class JRELocaleConstants {
|
||||
public static final Locale JA_JP_JP = new Locale("ja", "JP", "JP");
|
||||
public static final Locale NO_NO_NY = new Locale("no", "NO", "NY");
|
||||
public static final Locale TH_TH = new Locale("th", "TH");
|
||||
public static final Locale TH_TH_TH = new Locale("th", "TH", "TH");
|
||||
|
||||
private JRELocaleConstants() {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,468 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.util.locale.provider;
|
||||
|
||||
import java.io.File;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.text.spi.BreakIteratorProvider;
|
||||
import java.text.spi.CollatorProvider;
|
||||
import java.text.spi.DateFormatProvider;
|
||||
import java.text.spi.DateFormatSymbolsProvider;
|
||||
import java.text.spi.DecimalFormatSymbolsProvider;
|
||||
import java.text.spi.NumberFormatProvider;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.spi.CalendarDataProvider;
|
||||
import java.util.spi.CalendarNameProvider;
|
||||
import java.util.spi.CurrencyNameProvider;
|
||||
import java.util.spi.LocaleNameProvider;
|
||||
import java.util.spi.LocaleServiceProvider;
|
||||
import java.util.spi.TimeZoneNameProvider;
|
||||
import sun.util.resources.LocaleData;
|
||||
import sun.util.spi.CalendarProvider;
|
||||
|
||||
/**
|
||||
* LocaleProviderAdapter implementation for the legacy JRE locale data.
|
||||
*
|
||||
* @author Naoto Sato
|
||||
* @author Masayoshi Okutsu
|
||||
*/
|
||||
public class JRELocaleProviderAdapter extends LocaleProviderAdapter implements ResourceBundleBasedAdapter {
|
||||
|
||||
private static final String LOCALE_DATA_JAR_NAME = "localedata.jar";
|
||||
|
||||
private final ConcurrentMap<String, Set<String>> langtagSets
|
||||
= new ConcurrentHashMap<>();
|
||||
|
||||
private final ConcurrentMap<Locale, LocaleResources> localeResourcesMap
|
||||
= new ConcurrentHashMap<>();
|
||||
|
||||
// LocaleData specific to this LocaleProviderAdapter.
|
||||
private volatile LocaleData localeData;
|
||||
|
||||
/**
|
||||
* Returns the type of this LocaleProviderAdapter
|
||||
*/
|
||||
@Override
|
||||
public LocaleProviderAdapter.Type getAdapterType() {
|
||||
return Type.JRE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter method for Locale Service Providers
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <P extends LocaleServiceProvider> P getLocaleServiceProvider(Class<P> c) {
|
||||
switch (c.getSimpleName()) {
|
||||
case "BreakIteratorProvider":
|
||||
return (P) getBreakIteratorProvider();
|
||||
case "CollatorProvider":
|
||||
return (P) getCollatorProvider();
|
||||
case "DateFormatProvider":
|
||||
return (P) getDateFormatProvider();
|
||||
case "DateFormatSymbolsProvider":
|
||||
return (P) getDateFormatSymbolsProvider();
|
||||
case "DecimalFormatSymbolsProvider":
|
||||
return (P) getDecimalFormatSymbolsProvider();
|
||||
case "NumberFormatProvider":
|
||||
return (P) getNumberFormatProvider();
|
||||
case "CurrencyNameProvider":
|
||||
return (P) getCurrencyNameProvider();
|
||||
case "LocaleNameProvider":
|
||||
return (P) getLocaleNameProvider();
|
||||
case "TimeZoneNameProvider":
|
||||
return (P) getTimeZoneNameProvider();
|
||||
case "CalendarDataProvider":
|
||||
return (P) getCalendarDataProvider();
|
||||
case "CalendarNameProvider":
|
||||
return (P) getCalendarNameProvider();
|
||||
case "CalendarProvider":
|
||||
return (P) getCalendarProvider();
|
||||
default:
|
||||
throw new InternalError("should not come down here");
|
||||
}
|
||||
}
|
||||
|
||||
private volatile BreakIteratorProvider breakIteratorProvider = null;
|
||||
private volatile CollatorProvider collatorProvider = null;
|
||||
private volatile DateFormatProvider dateFormatProvider = null;
|
||||
private volatile DateFormatSymbolsProvider dateFormatSymbolsProvider = null;
|
||||
private volatile DecimalFormatSymbolsProvider decimalFormatSymbolsProvider = null;
|
||||
private volatile NumberFormatProvider numberFormatProvider = null;
|
||||
|
||||
private volatile CurrencyNameProvider currencyNameProvider = null;
|
||||
private volatile LocaleNameProvider localeNameProvider = null;
|
||||
private volatile TimeZoneNameProvider timeZoneNameProvider = null;
|
||||
private volatile CalendarDataProvider calendarDataProvider = null;
|
||||
private volatile CalendarNameProvider calendarNameProvider = null;
|
||||
|
||||
private volatile CalendarProvider calendarProvider = null;
|
||||
|
||||
/*
|
||||
* Getter methods for java.text.spi.* providers
|
||||
*/
|
||||
@Override
|
||||
public BreakIteratorProvider getBreakIteratorProvider() {
|
||||
if (breakIteratorProvider == null) {
|
||||
BreakIteratorProvider provider = new BreakIteratorProviderImpl(getAdapterType(),
|
||||
getLanguageTagSet("FormatData"));
|
||||
synchronized (this) {
|
||||
if (breakIteratorProvider == null) {
|
||||
breakIteratorProvider = provider;
|
||||
}
|
||||
}
|
||||
}
|
||||
return breakIteratorProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CollatorProvider getCollatorProvider() {
|
||||
if (collatorProvider == null) {
|
||||
CollatorProvider provider = new CollatorProviderImpl(getAdapterType(),
|
||||
getLanguageTagSet("CollationData"));
|
||||
synchronized (this) {
|
||||
if (collatorProvider == null) {
|
||||
collatorProvider = provider;
|
||||
}
|
||||
}
|
||||
}
|
||||
return collatorProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DateFormatProvider getDateFormatProvider() {
|
||||
if (dateFormatProvider == null) {
|
||||
DateFormatProvider provider = new DateFormatProviderImpl(getAdapterType(),
|
||||
getLanguageTagSet("FormatData"));
|
||||
synchronized (this) {
|
||||
if (dateFormatProvider == null) {
|
||||
dateFormatProvider = provider;
|
||||
}
|
||||
}
|
||||
}
|
||||
return dateFormatProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DateFormatSymbolsProvider getDateFormatSymbolsProvider() {
|
||||
if (dateFormatSymbolsProvider == null) {
|
||||
DateFormatSymbolsProvider provider = new DateFormatSymbolsProviderImpl(getAdapterType(),
|
||||
getLanguageTagSet("FormatData"));
|
||||
synchronized (this) {
|
||||
if (dateFormatSymbolsProvider == null) {
|
||||
dateFormatSymbolsProvider = provider;
|
||||
}
|
||||
}
|
||||
}
|
||||
return dateFormatSymbolsProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DecimalFormatSymbolsProvider getDecimalFormatSymbolsProvider() {
|
||||
if (decimalFormatSymbolsProvider == null) {
|
||||
DecimalFormatSymbolsProvider provider = new DecimalFormatSymbolsProviderImpl(getAdapterType(), getLanguageTagSet("FormatData"));
|
||||
synchronized (this) {
|
||||
if (decimalFormatSymbolsProvider == null) {
|
||||
decimalFormatSymbolsProvider = provider;
|
||||
}
|
||||
}
|
||||
}
|
||||
return decimalFormatSymbolsProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NumberFormatProvider getNumberFormatProvider() {
|
||||
if (numberFormatProvider == null) {
|
||||
NumberFormatProvider provider = new NumberFormatProviderImpl(getAdapterType(),
|
||||
getLanguageTagSet("FormatData"));
|
||||
synchronized (this) {
|
||||
if (numberFormatProvider == null) {
|
||||
numberFormatProvider = provider;
|
||||
}
|
||||
}
|
||||
}
|
||||
return numberFormatProvider;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter methods for java.util.spi.* providers
|
||||
*/
|
||||
@Override
|
||||
public CurrencyNameProvider getCurrencyNameProvider() {
|
||||
if (currencyNameProvider == null) {
|
||||
CurrencyNameProvider provider = new CurrencyNameProviderImpl(getAdapterType(),
|
||||
getLanguageTagSet("CurrencyNames"));
|
||||
synchronized (this) {
|
||||
if (currencyNameProvider == null) {
|
||||
currencyNameProvider = provider;
|
||||
}
|
||||
}
|
||||
}
|
||||
return currencyNameProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocaleNameProvider getLocaleNameProvider() {
|
||||
if (localeNameProvider == null) {
|
||||
LocaleNameProvider provider = new LocaleNameProviderImpl(getAdapterType(),
|
||||
getLanguageTagSet("LocaleNames"));
|
||||
synchronized (this) {
|
||||
if (localeNameProvider == null) {
|
||||
localeNameProvider = provider;
|
||||
}
|
||||
}
|
||||
}
|
||||
return localeNameProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TimeZoneNameProvider getTimeZoneNameProvider() {
|
||||
if (timeZoneNameProvider == null) {
|
||||
TimeZoneNameProvider provider = new TimeZoneNameProviderImpl(getAdapterType(),
|
||||
getLanguageTagSet("TimeZoneNames"));
|
||||
synchronized (this) {
|
||||
if (timeZoneNameProvider == null) {
|
||||
timeZoneNameProvider = provider;
|
||||
}
|
||||
}
|
||||
}
|
||||
return timeZoneNameProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CalendarDataProvider getCalendarDataProvider() {
|
||||
if (calendarDataProvider == null) {
|
||||
CalendarDataProvider provider;
|
||||
provider = new CalendarDataProviderImpl(getAdapterType(),
|
||||
getLanguageTagSet("CalendarData"));
|
||||
synchronized (this) {
|
||||
if (calendarDataProvider == null) {
|
||||
calendarDataProvider = provider;
|
||||
}
|
||||
}
|
||||
}
|
||||
return calendarDataProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CalendarNameProvider getCalendarNameProvider() {
|
||||
if (calendarNameProvider == null) {
|
||||
CalendarNameProvider provider;
|
||||
provider = new CalendarNameProviderImpl(getAdapterType(),
|
||||
getLanguageTagSet("FormatData"));
|
||||
synchronized (this) {
|
||||
if (calendarNameProvider == null) {
|
||||
calendarNameProvider = provider;
|
||||
}
|
||||
}
|
||||
}
|
||||
return calendarNameProvider;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter methods for sun.util.spi.* providers
|
||||
*/
|
||||
@Override
|
||||
public CalendarProvider getCalendarProvider() {
|
||||
if (calendarProvider == null) {
|
||||
CalendarProvider provider = new CalendarProviderImpl(getAdapterType(),
|
||||
getLanguageTagSet("CalendarData"));
|
||||
synchronized (this) {
|
||||
if (calendarProvider == null) {
|
||||
calendarProvider = provider;
|
||||
}
|
||||
}
|
||||
}
|
||||
return calendarProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocaleResources getLocaleResources(Locale locale) {
|
||||
LocaleResources lr = localeResourcesMap.get(locale);
|
||||
if (lr == null) {
|
||||
lr = new LocaleResources(this, locale);
|
||||
LocaleResources lrc = localeResourcesMap.putIfAbsent(locale, lr);
|
||||
if (lrc != null) {
|
||||
lr = lrc;
|
||||
}
|
||||
}
|
||||
return lr;
|
||||
}
|
||||
|
||||
// ResourceBundleBasedAdapter method implementation
|
||||
@Override
|
||||
public LocaleData getLocaleData() {
|
||||
if (localeData == null) {
|
||||
synchronized (this) {
|
||||
if (localeData == null) {
|
||||
localeData = new LocaleData(getAdapterType());
|
||||
}
|
||||
}
|
||||
}
|
||||
return localeData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of the installed locales. Currently, this simply returns
|
||||
* the list of locales for which a sun.text.resources.FormatData bundle
|
||||
* exists. This bundle family happens to be the one with the broadest
|
||||
* locale coverage in the JRE.
|
||||
*/
|
||||
@Override
|
||||
public Locale[] getAvailableLocales() {
|
||||
return AvailableJRELocales.localeList.clone();
|
||||
}
|
||||
|
||||
public Set<String> getLanguageTagSet(String category) {
|
||||
Set<String> tagset = langtagSets.get(category);
|
||||
if (tagset == null) {
|
||||
tagset = createLanguageTagSet(category);
|
||||
Set<String> ts = langtagSets.putIfAbsent(category, tagset);
|
||||
if (ts != null) {
|
||||
tagset = ts;
|
||||
}
|
||||
}
|
||||
return tagset;
|
||||
}
|
||||
|
||||
protected Set<String> createLanguageTagSet(String category) {
|
||||
String supportedLocaleString = LocaleDataMetaInfo.getSupportedLocaleString(category);
|
||||
if (supportedLocaleString == null) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
Set<String> tagset = new HashSet<>();
|
||||
StringTokenizer tokens = new StringTokenizer(supportedLocaleString);
|
||||
while (tokens.hasMoreTokens()) {
|
||||
String token = tokens.nextToken();
|
||||
if (token.equals("|")) {
|
||||
if (isNonENLangSupported()) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
tagset.add(token);
|
||||
}
|
||||
|
||||
return tagset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lazy load available locales.
|
||||
*/
|
||||
private static class AvailableJRELocales {
|
||||
private static final Locale[] localeList = createAvailableLocales();
|
||||
private AvailableJRELocales() {
|
||||
}
|
||||
}
|
||||
|
||||
private static Locale[] createAvailableLocales() {
|
||||
/*
|
||||
* Gets the locale string list from LocaleDataMetaInfo class and then
|
||||
* contructs the Locale array and a set of language tags based on the
|
||||
* locale string returned above.
|
||||
*/
|
||||
String supportedLocaleString = LocaleDataMetaInfo.getSupportedLocaleString("AvailableLocales");
|
||||
|
||||
if (supportedLocaleString.length() == 0) {
|
||||
throw new InternalError("No available locales for JRE");
|
||||
}
|
||||
|
||||
/*
|
||||
* Look for "|" and construct a new locale string list.
|
||||
*/
|
||||
int barIndex = supportedLocaleString.indexOf('|');
|
||||
StringTokenizer localeStringTokenizer;
|
||||
if (isNonENLangSupported()) {
|
||||
localeStringTokenizer = new StringTokenizer(supportedLocaleString.substring(0, barIndex)
|
||||
+ supportedLocaleString.substring(barIndex + 1));
|
||||
} else {
|
||||
localeStringTokenizer = new StringTokenizer(supportedLocaleString.substring(0, barIndex));
|
||||
}
|
||||
|
||||
int length = localeStringTokenizer.countTokens();
|
||||
Locale[] locales = new Locale[length + 1];
|
||||
locales[0] = Locale.ROOT;
|
||||
for (int i = 1; i <= length; i++) {
|
||||
String currentToken = localeStringTokenizer.nextToken();
|
||||
switch (currentToken) {
|
||||
case "ja-JP-JP":
|
||||
locales[i] = JRELocaleConstants.JA_JP_JP;
|
||||
break;
|
||||
case "no-NO-NY":
|
||||
locales[i] = JRELocaleConstants.NO_NO_NY;
|
||||
break;
|
||||
case "th-TH-TH":
|
||||
locales[i] = JRELocaleConstants.TH_TH_TH;
|
||||
break;
|
||||
default:
|
||||
locales[i] = Locale.forLanguageTag(currentToken);
|
||||
}
|
||||
}
|
||||
return locales;
|
||||
}
|
||||
|
||||
private static volatile Boolean isNonENSupported = null;
|
||||
|
||||
/*
|
||||
* Returns true if the non EN resources jar file exists in jre
|
||||
* extension directory. @returns true if the jar file is there. Otherwise,
|
||||
* returns false.
|
||||
*/
|
||||
private static boolean isNonENLangSupported() {
|
||||
if (isNonENSupported == null) {
|
||||
synchronized (JRELocaleProviderAdapter.class) {
|
||||
if (isNonENSupported == null) {
|
||||
final String sep = File.separator;
|
||||
String localeDataJar =
|
||||
java.security.AccessController.doPrivileged(
|
||||
new sun.security.action.GetPropertyAction("java.home"))
|
||||
+ sep + "lib" + sep + "ext" + sep + LOCALE_DATA_JAR_NAME;
|
||||
|
||||
/*
|
||||
* Peek at the installed extension directory to see if
|
||||
* localedata.jar is installed or not.
|
||||
*/
|
||||
final File f = new File(localeDataJar);
|
||||
isNonENSupported =
|
||||
AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
|
||||
@Override
|
||||
public Boolean run() {
|
||||
return f.exists();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
return isNonENSupported;
|
||||
}
|
||||
}
|
||||
89
jdkSrc/jdk8/sun/util/locale/provider/LocaleDataMetaInfo.java
Normal file
89
jdkSrc/jdk8/sun/util/locale/provider/LocaleDataMetaInfo.java
Normal file
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
// -- This file was mechanically generated: Do not edit! -- //
|
||||
|
||||
/*
|
||||
* This class contains a map which records the locale list string for
|
||||
* each resource in sun.util.resources & sun.text.resources.
|
||||
* It is used to avoid loading non-existent localized resources so that
|
||||
* jar files won't be opened unnecessary to look up them.
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
package sun.util.locale.provider;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
|
||||
public class LocaleDataMetaInfo {
|
||||
|
||||
private static final HashMap<String, String> resourceNameToLocales =
|
||||
new HashMap<String, String>(7);
|
||||
|
||||
|
||||
static {
|
||||
/* During JDK build time, #XXX_YYY# will be replaced by a string contain all the locales
|
||||
supported by the resource.
|
||||
|
||||
Don't remove the space character between " and #. That is put there purposely so that
|
||||
look up locale string such as "en" could be based on if it contains " en ".
|
||||
*/
|
||||
resourceNameToLocales.put("FormatData",
|
||||
" en en-AU en-CA en-GB en-IE en-IN en-MT en-NZ en-PH en-SG en-US en-ZA | ar ar-JO ar-LB ar-SY be be-BY bg bg-BG ca ca-ES cs cs-CZ da da-DK de de-AT de-CH de-DE de-LU el el-CY el-GR es es-AR es-BO es-CL es-CO es-CR es-DO es-EC es-ES es-GT es-HN es-MX es-NI es-PA es-PE es-PR es-PY es-SV es-US es-UY es-VE et et-EE fi fi-FI fr fr-BE fr-CA fr-CH fr-FR ga ga-IE hi-IN hr hr-HR hu hu-HU in in-ID is is-IS it it-CH it-IT iw iw-IL ja ja-JP ko ko-KR lt lt-LT lv lv-LV mk mk-MK ms ms-MY mt mt-MT nl nl-BE nl-NL no no-NO no-NO-NY pl pl-PL pt pt-BR pt-PT ro ro-RO ru ru-RU sk sk-SK sl sl-SI sq sq-AL sr sr-BA sr-CS sr-Latn sr-Latn-ME sr-ME sr-RS sv sv-SE th th-TH tr tr-TR uk uk-UA vi vi-VN zh zh-CN zh-HK zh-SG zh-TW ");
|
||||
|
||||
resourceNameToLocales.put("CollationData",
|
||||
" | ar be bg ca cs da el es et fi fr hi hr hu is iw ja ko lt lv mk no pl ro ru sk sl sq sr sr-Latn sv th tr uk vi zh zh-HK zh-TW ");
|
||||
|
||||
resourceNameToLocales.put("BreakIteratorInfo",
|
||||
" | th ");
|
||||
|
||||
resourceNameToLocales.put("BreakIteratorRules",
|
||||
" | th ");
|
||||
|
||||
resourceNameToLocales.put("TimeZoneNames",
|
||||
" en en-CA en-GB en-IE | de es fr hi it ja ko pt-BR sv zh-CN zh-HK zh-TW ");
|
||||
|
||||
resourceNameToLocales.put("LocaleNames",
|
||||
" en en-MT en-PH en-SG | ar be bg ca cs da de el el-CY es es-US et fi fr ga hi hr hu in is it iw ja ko lt lv mk ms mt nl no no-NO-NY pl pt pt-PT ro ru sk sl sq sr sr-Latn sv th tr uk vi zh zh-HK zh-SG zh-TW ");
|
||||
|
||||
resourceNameToLocales.put("CurrencyNames",
|
||||
" en-AU en-CA en-GB en-IE en-IN en-MT en-NZ en-PH en-SG en-US en-ZA | ar-AE ar-BH ar-DZ ar-EG ar-IQ ar-JO ar-KW ar-LB ar-LY ar-MA ar-OM ar-QA ar-SA ar-SD ar-SY ar-TN ar-YE be-BY bg-BG ca-ES cs-CZ da-DK de de-AT de-CH de-DE de-GR de-LU el-CY el-GR es es-AR es-BO es-CL es-CO es-CR es-CU es-DO es-EC es-ES es-GT es-HN es-MX es-NI es-PA es-PE es-PR es-PY es-SV es-US es-UY es-VE et-EE fi-FI fr fr-BE fr-CA fr-CH fr-FR fr-LU ga-IE hi-IN hr-HR hu-HU in-ID is-IS it it-CH it-IT iw-IL ja ja-JP ko ko-KR lt-LT lv-LV mk-MK ms-MY mt-MT nl-BE nl-NL no-NO pl-PL pt pt-BR pt-PT ro-RO ru-RU sk-SK sl-SI sq-AL sr-BA sr-CS sr-Latn-BA sr-Latn-ME sr-Latn-RS sr-ME sr-RS sv sv-SE th-TH tr-TR uk-UA vi-VN zh-CN zh-HK zh-SG zh-TW ");
|
||||
|
||||
resourceNameToLocales.put("CalendarData",
|
||||
" en en-GB en-IE en-MT | ar be bg ca cs da de el el-CY es es-ES es-US et fi fr fr-CA hi hr hu in-ID is it iw ja ko lt lv mk ms-MY mt mt-MT nl no pl pt pt-BR pt-PT ro ru sk sl sq sr sr-Latn-BA sr-Latn-ME sr-Latn-RS sv th tr uk vi zh ");
|
||||
|
||||
resourceNameToLocales.put("AvailableLocales",
|
||||
" en en-AU en-CA en-GB en-IE en-IN en-MT en-NZ en-PH en-SG en-US en-ZA | ar ar-AE ar-BH ar-DZ ar-EG ar-IQ ar-JO ar-KW ar-LB ar-LY ar-MA ar-OM ar-QA ar-SA ar-SD ar-SY ar-TN ar-YE be be-BY bg bg-BG ca ca-ES cs cs-CZ da da-DK de de-AT de-CH de-DE de-GR de-LU el el-CY el-GR es es-AR es-BO es-CL es-CO es-CR es-CU es-DO es-EC es-ES es-GT es-HN es-MX es-NI es-PA es-PE es-PR es-PY es-SV es-US es-UY es-VE et et-EE fi fi-FI fr fr-BE fr-CA fr-CH fr-FR fr-LU ga ga-IE hi hi-IN hr hr-HR hu hu-HU in in-ID is is-IS it it-CH it-IT iw iw-IL ja ja-JP ja-JP-JP ko ko-KR lt lt-LT lv lv-LV mk mk-MK ms ms-MY mt mt-MT nl nl-BE nl-NL no no-NO no-NO-NY pl pl-PL pt pt-BR pt-PT ro ro-RO ru ru-RU sk sk-SK sl sl-SI sq sq-AL sr sr-BA sr-CS sr-Latn sr-Latn-BA sr-Latn-ME sr-Latn-RS sr-ME sr-RS sv sv-SE th th-TH th-TH-TH tr tr-TR uk uk-UA vi vi-VN zh zh-CN zh-HK zh-SG zh-TW ");
|
||||
}
|
||||
|
||||
/*
|
||||
* @param resourceName the resource name
|
||||
* @return the supported locale string for the passed in resource.
|
||||
*/
|
||||
public static String getSupportedLocaleString(String resourceName) {
|
||||
return resourceNameToLocales.get(resourceName);
|
||||
}
|
||||
}
|
||||
183
jdkSrc/jdk8/sun/util/locale/provider/LocaleNameProviderImpl.java
Normal file
183
jdkSrc/jdk8/sun/util/locale/provider/LocaleNameProviderImpl.java
Normal file
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.util.locale.provider;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import java.util.spi.LocaleNameProvider;
|
||||
|
||||
/**
|
||||
* Concrete implementation of the
|
||||
* {@link java.util.spi.LocaleNameProvider LocaleNameProvider} class
|
||||
* for the JRE LocaleProviderAdapter.
|
||||
*
|
||||
* @author Naoto Sato
|
||||
* @author Masayoshi Okutsu
|
||||
*/
|
||||
public class LocaleNameProviderImpl extends LocaleNameProvider implements AvailableLanguageTags {
|
||||
private final LocaleProviderAdapter.Type type;
|
||||
private final Set<String> langtags;
|
||||
|
||||
public LocaleNameProviderImpl(LocaleProviderAdapter.Type type, Set<String> langtags) {
|
||||
this.type = type;
|
||||
this.langtags = langtags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of all locales for which this locale service provider
|
||||
* can provide localized objects or names.
|
||||
*
|
||||
* @return An array of all locales for which this locale service provider
|
||||
* can provide localized objects or names.
|
||||
*/
|
||||
@Override
|
||||
public Locale[] getAvailableLocales() {
|
||||
return LocaleProviderAdapter.toLocaleArray(langtags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupportedLocale(Locale locale) {
|
||||
return LocaleProviderAdapter.isSupportedLocale(locale, type, langtags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a localized name for the given ISO 639 language code and the
|
||||
* given locale that is appropriate for display to the user.
|
||||
* For example, if <code>languageCode</code> is "fr" and <code>locale</code>
|
||||
* is en_US, getDisplayLanguage() will return "French"; if <code>languageCode</code>
|
||||
* is "en" and <code>locale</code> is fr_FR, getDisplayLanguage() will return "anglais".
|
||||
* If the name returned cannot be localized according to <code>locale</code>,
|
||||
* (say, the provider does not have a Japanese name for Croatian),
|
||||
* this method returns null.
|
||||
* @param languageCode the ISO 639 language code string in the form of two
|
||||
* lower-case letters between 'a' (U+0061) and 'z' (U+007A)
|
||||
* @param locale the desired locale
|
||||
* @return the name of the given language code for the specified locale, or null if it's not
|
||||
* available.
|
||||
* @exception NullPointerException if <code>languageCode</code> or <code>locale</code> is null
|
||||
* @exception IllegalArgumentException if <code>languageCode</code> is not in the form of
|
||||
* two lower-case letters, or <code>locale</code> isn't
|
||||
* one of the locales returned from
|
||||
* {@link java.util.spi.LocaleServiceProvider#getAvailableLocales()
|
||||
* getAvailableLocales()}.
|
||||
* @see java.util.Locale#getDisplayLanguage(java.util.Locale)
|
||||
*/
|
||||
@Override
|
||||
public String getDisplayLanguage(String lang, Locale locale) {
|
||||
return getDisplayString(lang, locale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a localized name for the given <a href="http://www.rfc-editor.org/rfc/bcp/bcp47.txt">
|
||||
* IETF BCP47</a> script code and the given locale that is appropriate for
|
||||
* display to the user.
|
||||
* For example, if <code>scriptCode</code> is "Latn" and <code>locale</code>
|
||||
* is en_US, getDisplayScript() will return "Latin"; if <code>scriptCode</code>
|
||||
* is "Cyrl" and <code>locale</code> is fr_FR, getDisplayScript() will return "cyrillique".
|
||||
* If the name returned cannot be localized according to <code>locale</code>,
|
||||
* (say, the provider does not have a Japanese name for Cyrillic),
|
||||
* this method returns null. The default implementation returns null.
|
||||
* @param scriptCode the four letter script code string in the form of title-case
|
||||
* letters (the first letter is upper-case character between 'A' (U+0041) and
|
||||
* 'Z' (U+005A) followed by three lower-case character between 'a' (U+0061)
|
||||
* and 'z' (U+007A)).
|
||||
* @param locale the desired locale
|
||||
* @return the name of the given script code for the specified locale, or null if it's not
|
||||
* available.
|
||||
* @exception NullPointerException if <code>scriptCode</code> or <code>locale</code> is null
|
||||
* @exception IllegalArgumentException if <code>scriptCode</code> is not in the form of
|
||||
* four title case letters, or <code>locale</code> isn't
|
||||
* one of the locales returned from
|
||||
* {@link java.util.spi.LocaleServiceProvider#getAvailableLocales()
|
||||
* getAvailableLocales()}.
|
||||
* @see java.util.Locale#getDisplayScript(java.util.Locale)
|
||||
*/
|
||||
@Override
|
||||
public String getDisplayScript(String scriptCode, Locale locale) {
|
||||
return getDisplayString(scriptCode, locale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a localized name for the given ISO 3166 country code and the
|
||||
* given locale that is appropriate for display to the user.
|
||||
* For example, if <code>countryCode</code> is "FR" and <code>locale</code>
|
||||
* is en_US, getDisplayCountry() will return "France"; if <code>countryCode</code>
|
||||
* is "US" and <code>locale</code> is fr_FR, getDisplayCountry() will return "Etats-Unis".
|
||||
* If the name returned cannot be localized according to <code>locale</code>,
|
||||
* (say, the provider does not have a Japanese name for Croatia),
|
||||
* this method returns null.
|
||||
* @param countryCode the ISO 3166 country code string in the form of two
|
||||
* upper-case letters between 'A' (U+0041) and 'Z' (U+005A)
|
||||
* @param locale the desired locale
|
||||
* @return the name of the given country code for the specified locale, or null if it's not
|
||||
* available.
|
||||
* @exception NullPointerException if <code>countryCode</code> or <code>locale</code> is null
|
||||
* @exception IllegalArgumentException if <code>countryCode</code> is not in the form of
|
||||
* two upper-case letters, or <code>locale</code> isn't
|
||||
* one of the locales returned from
|
||||
* {@link java.util.spi.LocaleServiceProvider#getAvailableLocales()
|
||||
* getAvailableLocales()}.
|
||||
* @see java.util.Locale#getDisplayCountry(java.util.Locale)
|
||||
*/
|
||||
@Override
|
||||
public String getDisplayCountry(String ctry, Locale locale) {
|
||||
return getDisplayString(ctry, locale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a localized name for the given variant code and the given locale that
|
||||
* is appropriate for display to the user.
|
||||
* If the name returned cannot be localized according to <code>locale</code>,
|
||||
* this method returns null.
|
||||
* @param variant the variant string
|
||||
* @param locale the desired locale
|
||||
* @return the name of the given variant string for the specified locale, or null if it's not
|
||||
* available.
|
||||
* @exception NullPointerException if <code>variant</code> or <code>locale</code> is null
|
||||
* @exception IllegalArgumentException if <code>locale</code> isn't
|
||||
* one of the locales returned from
|
||||
* {@link java.util.spi.LocaleServiceProvider#getAvailableLocales()
|
||||
* getAvailableLocales()}.
|
||||
* @see java.util.Locale#getDisplayVariant(java.util.Locale)
|
||||
*/
|
||||
@Override
|
||||
public String getDisplayVariant(String vrnt, Locale locale) {
|
||||
return getDisplayString("%%"+vrnt, locale);
|
||||
}
|
||||
|
||||
private String getDisplayString(String key, Locale locale) {
|
||||
if (key == null || locale == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
|
||||
return LocaleProviderAdapter.forType(type).getLocaleResources(locale).getLocaleName(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getAvailableLanguageTags() {
|
||||
return langtags;
|
||||
}
|
||||
}
|
||||
456
jdkSrc/jdk8/sun/util/locale/provider/LocaleProviderAdapter.java
Normal file
456
jdkSrc/jdk8/sun/util/locale/provider/LocaleProviderAdapter.java
Normal file
@@ -0,0 +1,456 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.util.locale.provider;
|
||||
|
||||
import java.security.AccessController;
|
||||
import java.text.spi.BreakIteratorProvider;
|
||||
import java.text.spi.CollatorProvider;
|
||||
import java.text.spi.DateFormatProvider;
|
||||
import java.text.spi.DateFormatSymbolsProvider;
|
||||
import java.text.spi.DecimalFormatSymbolsProvider;
|
||||
import java.text.spi.NumberFormatProvider;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.spi.CalendarDataProvider;
|
||||
import java.util.spi.CalendarNameProvider;
|
||||
import java.util.spi.CurrencyNameProvider;
|
||||
import java.util.spi.LocaleNameProvider;
|
||||
import java.util.spi.LocaleServiceProvider;
|
||||
import java.util.spi.TimeZoneNameProvider;
|
||||
import sun.util.cldr.CLDRLocaleProviderAdapter;
|
||||
import sun.util.spi.CalendarProvider;
|
||||
|
||||
/**
|
||||
* The LocaleProviderAdapter abstract class.
|
||||
*
|
||||
* @author Naoto Sato
|
||||
* @author Masayoshi Okutsu
|
||||
*/
|
||||
public abstract class LocaleProviderAdapter {
|
||||
/**
|
||||
* Adapter type.
|
||||
*/
|
||||
public static enum Type {
|
||||
JRE("sun.util.resources", "sun.text.resources"),
|
||||
CLDR("sun.util.resources.cldr", "sun.text.resources.cldr"),
|
||||
SPI,
|
||||
HOST,
|
||||
FALLBACK("sun.util.resources", "sun.text.resources");
|
||||
|
||||
private final String UTIL_RESOURCES_PACKAGE;
|
||||
private final String TEXT_RESOURCES_PACKAGE;
|
||||
|
||||
private Type() {
|
||||
this(null, null);
|
||||
}
|
||||
|
||||
private Type(String util, String text) {
|
||||
UTIL_RESOURCES_PACKAGE = util;
|
||||
TEXT_RESOURCES_PACKAGE = text;
|
||||
}
|
||||
|
||||
public String getUtilResourcesPackage() {
|
||||
return UTIL_RESOURCES_PACKAGE;
|
||||
}
|
||||
|
||||
public String getTextResourcesPackage() {
|
||||
return TEXT_RESOURCES_PACKAGE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* LocaleProviderAdapter preference list. The default list is intended
|
||||
* to behave the same manner in JDK7.
|
||||
*/
|
||||
private static final List<Type> adapterPreference;
|
||||
|
||||
/**
|
||||
* JRE Locale Data Adapter instance
|
||||
*/
|
||||
private static LocaleProviderAdapter jreLocaleProviderAdapter = new JRELocaleProviderAdapter();
|
||||
|
||||
/**
|
||||
* SPI Locale Data Adapter instance
|
||||
*/
|
||||
private static LocaleProviderAdapter spiLocaleProviderAdapter = new SPILocaleProviderAdapter();
|
||||
|
||||
/**
|
||||
* CLDR Locale Data Adapter instance, if any.
|
||||
*/
|
||||
private static LocaleProviderAdapter cldrLocaleProviderAdapter = null;
|
||||
|
||||
/**
|
||||
* HOST Locale Data Adapter instance, if any.
|
||||
*/
|
||||
private static LocaleProviderAdapter hostLocaleProviderAdapter = null;
|
||||
|
||||
/**
|
||||
* FALLBACK Locale Data Adapter instance. It's basically the same with JRE, but only kicks
|
||||
* in for the root locale.
|
||||
*/
|
||||
private static LocaleProviderAdapter fallbackLocaleProviderAdapter = null;
|
||||
|
||||
/**
|
||||
* Default fallback adapter type, which should return something meaningful in any case.
|
||||
* This is either JRE or FALLBACK.
|
||||
*/
|
||||
static LocaleProviderAdapter.Type defaultLocaleProviderAdapter = null;
|
||||
|
||||
/**
|
||||
* Adapter lookup cache.
|
||||
*/
|
||||
private static ConcurrentMap<Class<? extends LocaleServiceProvider>, ConcurrentMap<Locale, LocaleProviderAdapter>>
|
||||
adapterCache = new ConcurrentHashMap<>();
|
||||
|
||||
static {
|
||||
String order = AccessController.doPrivileged(
|
||||
new sun.security.action.GetPropertyAction("java.locale.providers"));
|
||||
List<Type> typeList = new ArrayList<>();
|
||||
|
||||
// Check user specified adapter preference
|
||||
if (order != null && order.length() != 0) {
|
||||
String[] types = order.split(",");
|
||||
for (String type : types) {
|
||||
try {
|
||||
Type aType = Type.valueOf(type.trim().toUpperCase(Locale.ROOT));
|
||||
|
||||
// load adapter if necessary
|
||||
switch (aType) {
|
||||
case CLDR:
|
||||
if (cldrLocaleProviderAdapter == null) {
|
||||
cldrLocaleProviderAdapter = new CLDRLocaleProviderAdapter();
|
||||
}
|
||||
break;
|
||||
case HOST:
|
||||
if (hostLocaleProviderAdapter == null) {
|
||||
hostLocaleProviderAdapter = new HostLocaleProviderAdapter();
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!typeList.contains(aType)) {
|
||||
typeList.add(aType);
|
||||
}
|
||||
} catch (IllegalArgumentException | UnsupportedOperationException e) {
|
||||
// could be caused by the user specifying wrong
|
||||
// provider name or format in the system property
|
||||
LocaleServiceProviderPool.config(LocaleProviderAdapter.class, e.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!typeList.isEmpty()) {
|
||||
if (!typeList.contains(Type.JRE)) {
|
||||
// Append FALLBACK as the last resort.
|
||||
fallbackLocaleProviderAdapter = new FallbackLocaleProviderAdapter();
|
||||
typeList.add(Type.FALLBACK);
|
||||
defaultLocaleProviderAdapter = Type.FALLBACK;
|
||||
} else {
|
||||
defaultLocaleProviderAdapter = Type.JRE;
|
||||
}
|
||||
} else {
|
||||
// Default preference list
|
||||
typeList.add(Type.JRE);
|
||||
typeList.add(Type.SPI);
|
||||
defaultLocaleProviderAdapter = Type.JRE;
|
||||
}
|
||||
|
||||
adapterPreference = Collections.unmodifiableList(typeList);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the singleton instance for each adapter type
|
||||
*/
|
||||
public static LocaleProviderAdapter forType(Type type) {
|
||||
switch (type) {
|
||||
case JRE:
|
||||
return jreLocaleProviderAdapter;
|
||||
case CLDR:
|
||||
return cldrLocaleProviderAdapter;
|
||||
case SPI:
|
||||
return spiLocaleProviderAdapter;
|
||||
case HOST:
|
||||
return hostLocaleProviderAdapter;
|
||||
case FALLBACK:
|
||||
return fallbackLocaleProviderAdapter;
|
||||
default:
|
||||
throw new InternalError("unknown locale data adapter type");
|
||||
}
|
||||
}
|
||||
|
||||
public static LocaleProviderAdapter forJRE() {
|
||||
return jreLocaleProviderAdapter;
|
||||
}
|
||||
|
||||
public static LocaleProviderAdapter getResourceBundleBased() {
|
||||
for (Type type : getAdapterPreference()) {
|
||||
if (type == Type.JRE || type == Type.CLDR || type == Type.FALLBACK) {
|
||||
return forType(type);
|
||||
}
|
||||
}
|
||||
// Shouldn't happen.
|
||||
throw new InternalError();
|
||||
}
|
||||
/**
|
||||
* Returns the preference order of LocaleProviderAdapter.Type
|
||||
*/
|
||||
public static List<Type> getAdapterPreference() {
|
||||
return adapterPreference;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a LocaleProviderAdapter for the given locale service provider that
|
||||
* best matches the given locale. This method returns the LocaleProviderAdapter
|
||||
* for JRE if none is found for the given locale.
|
||||
*
|
||||
* @param providerClass the class for the locale service provider
|
||||
* @param locale the desired locale.
|
||||
* @return a LocaleProviderAdapter
|
||||
*/
|
||||
public static LocaleProviderAdapter getAdapter(Class<? extends LocaleServiceProvider> providerClass,
|
||||
Locale locale) {
|
||||
LocaleProviderAdapter adapter;
|
||||
|
||||
// cache lookup
|
||||
ConcurrentMap<Locale, LocaleProviderAdapter> adapterMap = adapterCache.get(providerClass);
|
||||
if (adapterMap != null) {
|
||||
if ((adapter = adapterMap.get(locale)) != null) {
|
||||
return adapter;
|
||||
}
|
||||
} else {
|
||||
adapterMap = new ConcurrentHashMap<>();
|
||||
adapterCache.putIfAbsent(providerClass, adapterMap);
|
||||
}
|
||||
|
||||
// Fast look-up for the given locale
|
||||
adapter = findAdapter(providerClass, locale);
|
||||
if (adapter != null) {
|
||||
adapterMap.putIfAbsent(locale, adapter);
|
||||
return adapter;
|
||||
}
|
||||
|
||||
// Try finding an adapter in the normal candidate locales path of the given locale.
|
||||
List<Locale> lookupLocales = ResourceBundle.Control.getControl(ResourceBundle.Control.FORMAT_DEFAULT)
|
||||
.getCandidateLocales("", locale);
|
||||
for (Locale loc : lookupLocales) {
|
||||
if (loc.equals(locale)) {
|
||||
// We've already done with this loc.
|
||||
continue;
|
||||
}
|
||||
adapter = findAdapter(providerClass, loc);
|
||||
if (adapter != null) {
|
||||
adapterMap.putIfAbsent(locale, adapter);
|
||||
return adapter;
|
||||
}
|
||||
}
|
||||
|
||||
// returns the adapter for FALLBACK as the last resort
|
||||
adapterMap.putIfAbsent(locale, fallbackLocaleProviderAdapter);
|
||||
return fallbackLocaleProviderAdapter;
|
||||
}
|
||||
|
||||
private static LocaleProviderAdapter findAdapter(Class<? extends LocaleServiceProvider> providerClass,
|
||||
Locale locale) {
|
||||
for (Type type : getAdapterPreference()) {
|
||||
LocaleProviderAdapter adapter = forType(type);
|
||||
LocaleServiceProvider provider = adapter.getLocaleServiceProvider(providerClass);
|
||||
if (provider != null) {
|
||||
if (provider.isSupportedLocale(locale)) {
|
||||
return adapter;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* A utility method for implementing the default LocaleServiceProvider.isSupportedLocale
|
||||
* for the JRE, CLDR, and FALLBACK adapters.
|
||||
*/
|
||||
public static boolean isSupportedLocale(Locale locale, LocaleProviderAdapter.Type type, Set<String> langtags) {
|
||||
assert type == Type.JRE || type == Type.CLDR || type == Type.FALLBACK;
|
||||
if (Locale.ROOT.equals(locale)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (type == Type.FALLBACK) {
|
||||
// no other locales except ROOT are supported for FALLBACK
|
||||
return false;
|
||||
}
|
||||
|
||||
locale = locale.stripExtensions();
|
||||
if (langtags.contains(locale.toLanguageTag())) {
|
||||
return true;
|
||||
}
|
||||
if (type == Type.JRE) {
|
||||
String oldname = locale.toString().replace('_', '-');
|
||||
return langtags.contains(oldname) ||
|
||||
"ja-JP-JP".equals(oldname) ||
|
||||
"th-TH-TH".equals(oldname) ||
|
||||
"no-NO-NY".equals(oldname);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static Locale[] toLocaleArray(Set<String> tags) {
|
||||
Locale[] locs = new Locale[tags.size() + 1];
|
||||
int index = 0;
|
||||
locs[index++] = Locale.ROOT;
|
||||
for (String tag : tags) {
|
||||
switch (tag) {
|
||||
case "ja-JP-JP":
|
||||
locs[index++] = JRELocaleConstants.JA_JP_JP;
|
||||
break;
|
||||
case "th-TH-TH":
|
||||
locs[index++] = JRELocaleConstants.TH_TH_TH;
|
||||
break;
|
||||
default:
|
||||
locs[index++] = Locale.forLanguageTag(tag);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return locs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type of this LocaleProviderAdapter
|
||||
*/
|
||||
public abstract LocaleProviderAdapter.Type getAdapterType();
|
||||
|
||||
/**
|
||||
* Getter method for Locale Service Providers.
|
||||
*/
|
||||
public abstract <P extends LocaleServiceProvider> P getLocaleServiceProvider(Class<P> c);
|
||||
|
||||
/**
|
||||
* Returns a BreakIteratorProvider for this LocaleProviderAdapter, or null if no
|
||||
* BreakIteratorProvider is available.
|
||||
*
|
||||
* @return a BreakIteratorProvider
|
||||
*/
|
||||
public abstract BreakIteratorProvider getBreakIteratorProvider();
|
||||
|
||||
/**
|
||||
* Returns a ollatorProvider for this LocaleProviderAdapter, or null if no
|
||||
* ollatorProvider is available.
|
||||
*
|
||||
* @return a ollatorProvider
|
||||
*/
|
||||
public abstract CollatorProvider getCollatorProvider();
|
||||
|
||||
/**
|
||||
* Returns a DateFormatProvider for this LocaleProviderAdapter, or null if no
|
||||
* DateFormatProvider is available.
|
||||
*
|
||||
* @return a DateFormatProvider
|
||||
*/
|
||||
public abstract DateFormatProvider getDateFormatProvider();
|
||||
|
||||
/**
|
||||
* Returns a DateFormatSymbolsProvider for this LocaleProviderAdapter, or null if no
|
||||
* DateFormatSymbolsProvider is available.
|
||||
*
|
||||
* @return a DateFormatSymbolsProvider
|
||||
*/
|
||||
public abstract DateFormatSymbolsProvider getDateFormatSymbolsProvider();
|
||||
|
||||
/**
|
||||
* Returns a DecimalFormatSymbolsProvider for this LocaleProviderAdapter, or null if no
|
||||
* DecimalFormatSymbolsProvider is available.
|
||||
*
|
||||
* @return a DecimalFormatSymbolsProvider
|
||||
*/
|
||||
public abstract DecimalFormatSymbolsProvider getDecimalFormatSymbolsProvider();
|
||||
|
||||
/**
|
||||
* Returns a NumberFormatProvider for this LocaleProviderAdapter, or null if no
|
||||
* NumberFormatProvider is available.
|
||||
*
|
||||
* @return a NumberFormatProvider
|
||||
*/
|
||||
public abstract NumberFormatProvider getNumberFormatProvider();
|
||||
|
||||
/*
|
||||
* Getter methods for java.util.spi.* providers
|
||||
*/
|
||||
|
||||
/**
|
||||
* Returns a CurrencyNameProvider for this LocaleProviderAdapter, or null if no
|
||||
* CurrencyNameProvider is available.
|
||||
*
|
||||
* @return a CurrencyNameProvider
|
||||
*/
|
||||
public abstract CurrencyNameProvider getCurrencyNameProvider();
|
||||
|
||||
/**
|
||||
* Returns a LocaleNameProvider for this LocaleProviderAdapter, or null if no
|
||||
* LocaleNameProvider is available.
|
||||
*
|
||||
* @return a LocaleNameProvider
|
||||
*/
|
||||
public abstract LocaleNameProvider getLocaleNameProvider();
|
||||
|
||||
/**
|
||||
* Returns a TimeZoneNameProvider for this LocaleProviderAdapter, or null if no
|
||||
* TimeZoneNameProvider is available.
|
||||
*
|
||||
* @return a TimeZoneNameProvider
|
||||
*/
|
||||
public abstract TimeZoneNameProvider getTimeZoneNameProvider();
|
||||
|
||||
/**
|
||||
* Returns a CalendarDataProvider for this LocaleProviderAdapter, or null if no
|
||||
* CalendarDataProvider is available.
|
||||
*
|
||||
* @return a CalendarDataProvider
|
||||
*/
|
||||
public abstract CalendarDataProvider getCalendarDataProvider();
|
||||
|
||||
/**
|
||||
* Returns a CalendarNameProvider for this LocaleProviderAdapter, or null if no
|
||||
* CalendarNameProvider is available.
|
||||
*
|
||||
* @return a CalendarNameProvider
|
||||
*/
|
||||
public abstract CalendarNameProvider getCalendarNameProvider();
|
||||
|
||||
/**
|
||||
* Returns a CalendarProvider for this LocaleProviderAdapter, or null if no
|
||||
* CalendarProvider is available.
|
||||
*
|
||||
* @return a CalendarProvider
|
||||
*/
|
||||
public abstract CalendarProvider getCalendarProvider();
|
||||
|
||||
public abstract LocaleResources getLocaleResources(Locale locale);
|
||||
|
||||
public abstract Locale[] getAvailableLocales();
|
||||
}
|
||||
510
jdkSrc/jdk8/sun/util/locale/provider/LocaleResources.java
Normal file
510
jdkSrc/jdk8/sun/util/locale/provider/LocaleResources.java
Normal file
@@ -0,0 +1,510 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
|
||||
* (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved
|
||||
*
|
||||
* The original version of this source code and documentation
|
||||
* is copyrighted and owned by Taligent, Inc., a wholly-owned
|
||||
* subsidiary of IBM. These materials are provided under terms
|
||||
* of a License Agreement between Taligent and Sun. This technology
|
||||
* is protected by multiple US and International patents.
|
||||
*
|
||||
* This notice and attribution to Taligent may not be removed.
|
||||
* Taligent is a registered trademark of Taligent, Inc.
|
||||
*
|
||||
*/
|
||||
|
||||
package sun.util.locale.provider;
|
||||
|
||||
import java.lang.ref.ReferenceQueue;
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import sun.util.calendar.ZoneInfo;
|
||||
import sun.util.resources.LocaleData;
|
||||
import sun.util.resources.OpenListResourceBundle;
|
||||
import sun.util.resources.ParallelListResourceBundle;
|
||||
import sun.util.resources.TimeZoneNamesBundle;
|
||||
|
||||
/**
|
||||
* Central accessor to locale-dependent resources for JRE/CLDR provider adapters.
|
||||
*
|
||||
* @author Masayoshi Okutsu
|
||||
* @author Naoto Sato
|
||||
*/
|
||||
public class LocaleResources {
|
||||
|
||||
private final Locale locale;
|
||||
private final LocaleData localeData;
|
||||
private final LocaleProviderAdapter.Type type;
|
||||
|
||||
// Resource cache
|
||||
private ConcurrentMap<String, ResourceReference> cache = new ConcurrentHashMap<>();
|
||||
private ReferenceQueue<Object> referenceQueue = new ReferenceQueue<>();
|
||||
|
||||
// cache key prefixes
|
||||
private static final String BREAK_ITERATOR_INFO = "BII.";
|
||||
private static final String CALENDAR_DATA = "CALD.";
|
||||
private static final String COLLATION_DATA_CACHEKEY = "COLD";
|
||||
private static final String DECIMAL_FORMAT_SYMBOLS_DATA_CACHEKEY = "DFSD";
|
||||
private static final String CURRENCY_NAMES = "CN.";
|
||||
private static final String LOCALE_NAMES = "LN.";
|
||||
private static final String TIME_ZONE_NAMES = "TZN.";
|
||||
private static final String ZONE_IDS_CACHEKEY = "ZID";
|
||||
private static final String CALENDAR_NAMES = "CALN.";
|
||||
private static final String NUMBER_PATTERNS_CACHEKEY = "NP";
|
||||
private static final String DATE_TIME_PATTERN = "DTP.";
|
||||
|
||||
// null singleton cache value
|
||||
private static final Object NULLOBJECT = new Object();
|
||||
|
||||
LocaleResources(ResourceBundleBasedAdapter adapter, Locale locale) {
|
||||
this.locale = locale;
|
||||
this.localeData = adapter.getLocaleData();
|
||||
type = ((LocaleProviderAdapter)adapter).getAdapterType();
|
||||
}
|
||||
|
||||
private void removeEmptyReferences() {
|
||||
Object ref;
|
||||
while ((ref = referenceQueue.poll()) != null) {
|
||||
cache.remove(((ResourceReference)ref).getCacheKey());
|
||||
}
|
||||
}
|
||||
|
||||
Object getBreakIteratorInfo(String key) {
|
||||
Object biInfo;
|
||||
String cacheKey = BREAK_ITERATOR_INFO + key;
|
||||
|
||||
removeEmptyReferences();
|
||||
ResourceReference data = cache.get(cacheKey);
|
||||
if (data == null || ((biInfo = data.get()) == null)) {
|
||||
biInfo = localeData.getBreakIteratorInfo(locale).getObject(key);
|
||||
cache.put(cacheKey, new ResourceReference(cacheKey, biInfo, referenceQueue));
|
||||
}
|
||||
|
||||
return biInfo;
|
||||
}
|
||||
|
||||
int getCalendarData(String key) {
|
||||
Integer caldata;
|
||||
String cacheKey = CALENDAR_DATA + key;
|
||||
|
||||
removeEmptyReferences();
|
||||
|
||||
ResourceReference data = cache.get(cacheKey);
|
||||
if (data == null || ((caldata = (Integer) data.get()) == null)) {
|
||||
ResourceBundle rb = localeData.getCalendarData(locale);
|
||||
if (rb.containsKey(key)) {
|
||||
caldata = Integer.parseInt(rb.getString(key));
|
||||
} else {
|
||||
caldata = 0;
|
||||
}
|
||||
|
||||
cache.put(cacheKey,
|
||||
new ResourceReference(cacheKey, (Object) caldata, referenceQueue));
|
||||
}
|
||||
|
||||
return caldata;
|
||||
}
|
||||
|
||||
public String getCollationData() {
|
||||
String key = "Rule";
|
||||
String coldata = "";
|
||||
|
||||
removeEmptyReferences();
|
||||
ResourceReference data = cache.get(COLLATION_DATA_CACHEKEY);
|
||||
if (data == null || ((coldata = (String) data.get()) == null)) {
|
||||
ResourceBundle rb = localeData.getCollationData(locale);
|
||||
if (rb.containsKey(key)) {
|
||||
coldata = rb.getString(key);
|
||||
}
|
||||
cache.put(COLLATION_DATA_CACHEKEY,
|
||||
new ResourceReference(COLLATION_DATA_CACHEKEY, (Object) coldata, referenceQueue));
|
||||
}
|
||||
|
||||
return coldata;
|
||||
}
|
||||
|
||||
public Object[] getDecimalFormatSymbolsData() {
|
||||
Object[] dfsdata;
|
||||
|
||||
removeEmptyReferences();
|
||||
ResourceReference data = cache.get(DECIMAL_FORMAT_SYMBOLS_DATA_CACHEKEY);
|
||||
if (data == null || ((dfsdata = (Object[]) data.get()) == null)) {
|
||||
// Note that only dfsdata[0] is prepared here in this method. Other
|
||||
// elements are provided by the caller, yet they are cached here.
|
||||
ResourceBundle rb = localeData.getNumberFormatData(locale);
|
||||
dfsdata = new Object[3];
|
||||
|
||||
// NumberElements look up. First, try the Unicode extension
|
||||
String numElemKey;
|
||||
String numberType = locale.getUnicodeLocaleType("nu");
|
||||
if (numberType != null) {
|
||||
numElemKey = numberType + ".NumberElements";
|
||||
if (rb.containsKey(numElemKey)) {
|
||||
dfsdata[0] = rb.getStringArray(numElemKey);
|
||||
}
|
||||
}
|
||||
|
||||
// Next, try DefaultNumberingSystem value
|
||||
if (dfsdata[0] == null && rb.containsKey("DefaultNumberingSystem")) {
|
||||
numElemKey = rb.getString("DefaultNumberingSystem") + ".NumberElements";
|
||||
if (rb.containsKey(numElemKey)) {
|
||||
dfsdata[0] = rb.getStringArray(numElemKey);
|
||||
}
|
||||
}
|
||||
|
||||
// Last resort. No need to check the availability.
|
||||
// Just let it throw MissingResourceException when needed.
|
||||
if (dfsdata[0] == null) {
|
||||
dfsdata[0] = rb.getStringArray("NumberElements");
|
||||
}
|
||||
|
||||
cache.put(DECIMAL_FORMAT_SYMBOLS_DATA_CACHEKEY,
|
||||
new ResourceReference(DECIMAL_FORMAT_SYMBOLS_DATA_CACHEKEY, (Object) dfsdata, referenceQueue));
|
||||
}
|
||||
|
||||
return dfsdata;
|
||||
}
|
||||
|
||||
public String getCurrencyName(String key) {
|
||||
Object currencyName = null;
|
||||
String cacheKey = CURRENCY_NAMES + key;
|
||||
|
||||
removeEmptyReferences();
|
||||
ResourceReference data = cache.get(cacheKey);
|
||||
|
||||
if (data != null && ((currencyName = data.get()) != null)) {
|
||||
if (currencyName.equals(NULLOBJECT)) {
|
||||
currencyName = null;
|
||||
}
|
||||
|
||||
return (String) currencyName;
|
||||
}
|
||||
|
||||
OpenListResourceBundle olrb = localeData.getCurrencyNames(locale);
|
||||
|
||||
if (olrb.containsKey(key)) {
|
||||
currencyName = olrb.getObject(key);
|
||||
cache.put(cacheKey,
|
||||
new ResourceReference(cacheKey, currencyName, referenceQueue));
|
||||
}
|
||||
|
||||
return (String) currencyName;
|
||||
}
|
||||
|
||||
public String getLocaleName(String key) {
|
||||
Object localeName = null;
|
||||
String cacheKey = LOCALE_NAMES + key;
|
||||
|
||||
removeEmptyReferences();
|
||||
ResourceReference data = cache.get(cacheKey);
|
||||
|
||||
if (data != null && ((localeName = data.get()) != null)) {
|
||||
if (localeName.equals(NULLOBJECT)) {
|
||||
localeName = null;
|
||||
}
|
||||
|
||||
return (String) localeName;
|
||||
}
|
||||
|
||||
OpenListResourceBundle olrb = localeData.getLocaleNames(locale);
|
||||
|
||||
if (olrb.containsKey(key)) {
|
||||
localeName = olrb.getObject(key);
|
||||
cache.put(cacheKey,
|
||||
new ResourceReference(cacheKey, localeName, referenceQueue));
|
||||
}
|
||||
|
||||
return (String) localeName;
|
||||
}
|
||||
|
||||
String[] getTimeZoneNames(String key) {
|
||||
String[] names = null;
|
||||
String cacheKey = TIME_ZONE_NAMES + '.' + key;
|
||||
|
||||
removeEmptyReferences();
|
||||
ResourceReference data = cache.get(cacheKey);
|
||||
|
||||
if (Objects.isNull(data) || Objects.isNull((names = (String[]) data.get()))) {
|
||||
TimeZoneNamesBundle tznb = localeData.getTimeZoneNames(locale);
|
||||
if (tznb.containsKey(key)) {
|
||||
names = tznb.getStringArray(key);
|
||||
cache.put(cacheKey,
|
||||
new ResourceReference(cacheKey, (Object) names, referenceQueue));
|
||||
}
|
||||
}
|
||||
|
||||
return names;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Set<String> getZoneIDs() {
|
||||
Set<String> zoneIDs = null;
|
||||
|
||||
removeEmptyReferences();
|
||||
ResourceReference data = cache.get(ZONE_IDS_CACHEKEY);
|
||||
if (data == null || ((zoneIDs = (Set<String>) data.get()) == null)) {
|
||||
TimeZoneNamesBundle rb = localeData.getTimeZoneNames(locale);
|
||||
zoneIDs = rb.keySet();
|
||||
cache.put(ZONE_IDS_CACHEKEY,
|
||||
new ResourceReference(ZONE_IDS_CACHEKEY, (Object) zoneIDs, referenceQueue));
|
||||
}
|
||||
|
||||
return zoneIDs;
|
||||
}
|
||||
|
||||
// zoneStrings are cached separately in TimeZoneNameUtility.
|
||||
String[][] getZoneStrings() {
|
||||
TimeZoneNamesBundle rb = localeData.getTimeZoneNames(locale);
|
||||
Set<String> keyset = getZoneIDs();
|
||||
// Use a LinkedHashSet to preseve the order
|
||||
Set<String[]> value = new LinkedHashSet<>();
|
||||
for (String key : keyset) {
|
||||
value.add(rb.getStringArray(key));
|
||||
}
|
||||
|
||||
// Add aliases data for CLDR
|
||||
if (type == LocaleProviderAdapter.Type.CLDR) {
|
||||
// Note: TimeZoneNamesBundle creates a String[] on each getStringArray call.
|
||||
Map<String, String> aliases = ZoneInfo.getAliasTable();
|
||||
for (String alias : aliases.keySet()) {
|
||||
if (!keyset.contains(alias)) {
|
||||
String tzid = aliases.get(alias);
|
||||
if (keyset.contains(tzid)) {
|
||||
String[] val = rb.getStringArray(tzid);
|
||||
val[0] = alias;
|
||||
value.add(val);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return value.toArray(new String[0][]);
|
||||
}
|
||||
|
||||
String[] getCalendarNames(String key) {
|
||||
String[] names = null;
|
||||
String cacheKey = CALENDAR_NAMES + key;
|
||||
|
||||
removeEmptyReferences();
|
||||
ResourceReference data = cache.get(cacheKey);
|
||||
|
||||
if (data == null || ((names = (String[]) data.get()) == null)) {
|
||||
ResourceBundle rb = localeData.getDateFormatData(locale);
|
||||
if (rb.containsKey(key)) {
|
||||
names = rb.getStringArray(key);
|
||||
cache.put(cacheKey,
|
||||
new ResourceReference(cacheKey, (Object) names, referenceQueue));
|
||||
}
|
||||
}
|
||||
|
||||
return names;
|
||||
}
|
||||
|
||||
String[] getJavaTimeNames(String key) {
|
||||
String[] names = null;
|
||||
String cacheKey = CALENDAR_NAMES + key;
|
||||
|
||||
removeEmptyReferences();
|
||||
ResourceReference data = cache.get(cacheKey);
|
||||
|
||||
if (data == null || ((names = (String[]) data.get()) == null)) {
|
||||
ResourceBundle rb = getJavaTimeFormatData();
|
||||
if (rb.containsKey(key)) {
|
||||
names = rb.getStringArray(key);
|
||||
cache.put(cacheKey,
|
||||
new ResourceReference(cacheKey, (Object) names, referenceQueue));
|
||||
}
|
||||
}
|
||||
|
||||
return names;
|
||||
}
|
||||
|
||||
public String getDateTimePattern(int timeStyle, int dateStyle, Calendar cal) {
|
||||
if (cal == null) {
|
||||
cal = Calendar.getInstance(locale);
|
||||
}
|
||||
return getDateTimePattern(null, timeStyle, dateStyle, cal.getCalendarType());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a date-time format pattern
|
||||
* @param timeStyle style of time; one of FULL, LONG, MEDIUM, SHORT in DateFormat,
|
||||
* or -1 if not required
|
||||
* @param dateStyle style of time; one of FULL, LONG, MEDIUM, SHORT in DateFormat,
|
||||
* or -1 if not required
|
||||
* @param calType the calendar type for the pattern
|
||||
* @return the pattern string
|
||||
*/
|
||||
public String getJavaTimeDateTimePattern(int timeStyle, int dateStyle, String calType) {
|
||||
calType = CalendarDataUtility.normalizeCalendarType(calType);
|
||||
String pattern;
|
||||
pattern = getDateTimePattern("java.time.", timeStyle, dateStyle, calType);
|
||||
if (pattern == null) {
|
||||
pattern = getDateTimePattern(null, timeStyle, dateStyle, calType);
|
||||
}
|
||||
return pattern;
|
||||
}
|
||||
|
||||
private String getDateTimePattern(String prefix, int timeStyle, int dateStyle, String calType) {
|
||||
String pattern;
|
||||
String timePattern = null;
|
||||
String datePattern = null;
|
||||
|
||||
if (timeStyle >= 0) {
|
||||
if (prefix != null) {
|
||||
timePattern = getDateTimePattern(prefix, "TimePatterns", timeStyle, calType);
|
||||
}
|
||||
if (timePattern == null) {
|
||||
timePattern = getDateTimePattern(null, "TimePatterns", timeStyle, calType);
|
||||
}
|
||||
}
|
||||
if (dateStyle >= 0) {
|
||||
if (prefix != null) {
|
||||
datePattern = getDateTimePattern(prefix, "DatePatterns", dateStyle, calType);
|
||||
}
|
||||
if (datePattern == null) {
|
||||
datePattern = getDateTimePattern(null, "DatePatterns", dateStyle, calType);
|
||||
}
|
||||
}
|
||||
if (timeStyle >= 0) {
|
||||
if (dateStyle >= 0) {
|
||||
String dateTimePattern = null;
|
||||
if (prefix != null) {
|
||||
dateTimePattern = getDateTimePattern(prefix, "DateTimePatterns", 0, calType);
|
||||
}
|
||||
if (dateTimePattern == null) {
|
||||
dateTimePattern = getDateTimePattern(null, "DateTimePatterns", 0, calType);
|
||||
}
|
||||
switch (dateTimePattern) {
|
||||
case "{1} {0}":
|
||||
pattern = datePattern + " " + timePattern;
|
||||
break;
|
||||
case "{0} {1}":
|
||||
pattern = timePattern + " " + datePattern;
|
||||
break;
|
||||
default:
|
||||
pattern = MessageFormat.format(dateTimePattern, timePattern, datePattern);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
pattern = timePattern;
|
||||
}
|
||||
} else if (dateStyle >= 0) {
|
||||
pattern = datePattern;
|
||||
} else {
|
||||
throw new IllegalArgumentException("No date or time style specified");
|
||||
}
|
||||
return pattern;
|
||||
}
|
||||
|
||||
public String[] getNumberPatterns() {
|
||||
String[] numberPatterns = null;
|
||||
|
||||
removeEmptyReferences();
|
||||
ResourceReference data = cache.get(NUMBER_PATTERNS_CACHEKEY);
|
||||
|
||||
if (data == null || ((numberPatterns = (String[]) data.get()) == null)) {
|
||||
ResourceBundle resource = localeData.getNumberFormatData(locale);
|
||||
numberPatterns = resource.getStringArray("NumberPatterns");
|
||||
cache.put(NUMBER_PATTERNS_CACHEKEY,
|
||||
new ResourceReference(NUMBER_PATTERNS_CACHEKEY, (Object) numberPatterns, referenceQueue));
|
||||
}
|
||||
|
||||
return numberPatterns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the FormatData resource bundle of this LocaleResources.
|
||||
* The FormatData should be used only for accessing extra
|
||||
* resources required by JSR 310.
|
||||
*/
|
||||
public ResourceBundle getJavaTimeFormatData() {
|
||||
ResourceBundle rb = localeData.getDateFormatData(locale);
|
||||
if (rb instanceof ParallelListResourceBundle) {
|
||||
localeData.setSupplementary((ParallelListResourceBundle) rb);
|
||||
}
|
||||
return rb;
|
||||
}
|
||||
|
||||
private String getDateTimePattern(String prefix, String key, int styleIndex, String calendarType) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (prefix != null) {
|
||||
sb.append(prefix);
|
||||
}
|
||||
if (!"gregory".equals(calendarType)) {
|
||||
sb.append(calendarType).append('.');
|
||||
}
|
||||
sb.append(key);
|
||||
String resourceKey = sb.toString();
|
||||
String cacheKey = sb.insert(0, DATE_TIME_PATTERN).toString();
|
||||
|
||||
removeEmptyReferences();
|
||||
ResourceReference data = cache.get(cacheKey);
|
||||
Object value = NULLOBJECT;
|
||||
|
||||
if (data == null || ((value = data.get()) == null)) {
|
||||
ResourceBundle r = (prefix != null) ? getJavaTimeFormatData() : localeData.getDateFormatData(locale);
|
||||
if (r.containsKey(resourceKey)) {
|
||||
value = r.getStringArray(resourceKey);
|
||||
} else {
|
||||
assert !resourceKey.equals(key);
|
||||
if (r.containsKey(key)) {
|
||||
value = r.getStringArray(key);
|
||||
}
|
||||
}
|
||||
cache.put(cacheKey,
|
||||
new ResourceReference(cacheKey, value, referenceQueue));
|
||||
}
|
||||
if (value == NULLOBJECT) {
|
||||
assert prefix != null;
|
||||
return null;
|
||||
}
|
||||
return ((String[])value)[styleIndex];
|
||||
}
|
||||
|
||||
private static class ResourceReference extends SoftReference<Object> {
|
||||
private final String cacheKey;
|
||||
|
||||
ResourceReference(String cacheKey, Object o, ReferenceQueue<Object> q) {
|
||||
super(o, q);
|
||||
this.cacheKey = cacheKey;
|
||||
}
|
||||
|
||||
String getCacheKey() {
|
||||
return cacheKey;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,419 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.util.locale.provider;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.IllformedLocaleException;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Locale.Builder;
|
||||
import java.util.ResourceBundle.Control;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.spi.LocaleServiceProvider;
|
||||
import sun.util.logging.PlatformLogger;
|
||||
|
||||
/**
|
||||
* An instance of this class holds a set of the third party implementations of a particular
|
||||
* locale sensitive service, such as {@link java.util.spi.LocaleNameProvider}.
|
||||
*
|
||||
* @author Naoto Sato
|
||||
* @author Masayoshi Okutsu
|
||||
*/
|
||||
public final class LocaleServiceProviderPool {
|
||||
|
||||
/**
|
||||
* A Map that holds singleton instances of this class. Each instance holds a
|
||||
* set of provider implementations of a particular locale sensitive service.
|
||||
*/
|
||||
private static ConcurrentMap<Class<? extends LocaleServiceProvider>, LocaleServiceProviderPool> poolOfPools =
|
||||
new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* A Map containing locale service providers that implement the
|
||||
* specified provider SPI, keyed by a LocaleProviderAdapter.Type
|
||||
*/
|
||||
private ConcurrentMap<LocaleProviderAdapter.Type, LocaleServiceProvider> providers =
|
||||
new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* A Map that retains Locale->provider mapping
|
||||
*/
|
||||
private ConcurrentMap<Locale, List<LocaleProviderAdapter.Type>> providersCache =
|
||||
new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* Available locales for this locale sensitive service. This also contains
|
||||
* JRE's available locales
|
||||
*/
|
||||
private Set<Locale> availableLocales = null;
|
||||
|
||||
/**
|
||||
* Provider class
|
||||
*/
|
||||
private Class<? extends LocaleServiceProvider> providerClass;
|
||||
|
||||
/**
|
||||
* Array of all Locale Sensitive SPI classes.
|
||||
*
|
||||
* We know "spiClasses" contains classes that extends LocaleServiceProvider,
|
||||
* but generic array creation is not allowed, thus the "unchecked" warning
|
||||
* is suppressed here.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
static final Class<LocaleServiceProvider>[] spiClasses =
|
||||
(Class<LocaleServiceProvider>[]) new Class<?>[] {
|
||||
java.text.spi.BreakIteratorProvider.class,
|
||||
java.text.spi.CollatorProvider.class,
|
||||
java.text.spi.DateFormatProvider.class,
|
||||
java.text.spi.DateFormatSymbolsProvider.class,
|
||||
java.text.spi.DecimalFormatSymbolsProvider.class,
|
||||
java.text.spi.NumberFormatProvider.class,
|
||||
java.util.spi.CurrencyNameProvider.class,
|
||||
java.util.spi.LocaleNameProvider.class,
|
||||
java.util.spi.TimeZoneNameProvider.class,
|
||||
java.util.spi.CalendarDataProvider.class
|
||||
};
|
||||
|
||||
/**
|
||||
* A factory method that returns a singleton instance
|
||||
*/
|
||||
public static LocaleServiceProviderPool getPool(Class<? extends LocaleServiceProvider> providerClass) {
|
||||
LocaleServiceProviderPool pool = poolOfPools.get(providerClass);
|
||||
if (pool == null) {
|
||||
LocaleServiceProviderPool newPool =
|
||||
new LocaleServiceProviderPool(providerClass);
|
||||
pool = poolOfPools.putIfAbsent(providerClass, newPool);
|
||||
if (pool == null) {
|
||||
pool = newPool;
|
||||
}
|
||||
}
|
||||
|
||||
return pool;
|
||||
}
|
||||
|
||||
/**
|
||||
* The sole constructor.
|
||||
*
|
||||
* @param c class of the locale sensitive service
|
||||
*/
|
||||
private LocaleServiceProviderPool (final Class<? extends LocaleServiceProvider> c) {
|
||||
providerClass = c;
|
||||
|
||||
for (LocaleProviderAdapter.Type type : LocaleProviderAdapter.getAdapterPreference()) {
|
||||
LocaleProviderAdapter lda = LocaleProviderAdapter.forType(type);
|
||||
if (lda != null) {
|
||||
LocaleServiceProvider provider = lda.getLocaleServiceProvider(c);
|
||||
if (provider != null) {
|
||||
providers.putIfAbsent(type, provider);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void config(Class<? extends Object> caller, String message) {
|
||||
PlatformLogger logger = PlatformLogger.getLogger(caller.getCanonicalName());
|
||||
logger.config(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lazy loaded set of available locales.
|
||||
* Loading all locales is a very long operation.
|
||||
*/
|
||||
private static class AllAvailableLocales {
|
||||
/**
|
||||
* Available locales for all locale sensitive services.
|
||||
* This also contains JRE's available locales
|
||||
*/
|
||||
static final Locale[] allAvailableLocales;
|
||||
|
||||
static {
|
||||
Set<Locale> all = new HashSet<>();
|
||||
for (Class<? extends LocaleServiceProvider> c : spiClasses) {
|
||||
LocaleServiceProviderPool pool =
|
||||
LocaleServiceProviderPool.getPool(c);
|
||||
all.addAll(pool.getAvailableLocaleSet());
|
||||
}
|
||||
|
||||
allAvailableLocales = all.toArray(new Locale[0]);
|
||||
}
|
||||
|
||||
// No instantiation
|
||||
private AllAvailableLocales() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of available locales for all the provider classes.
|
||||
* This array is a merged array of all the locales that are provided by each
|
||||
* provider, including the JRE.
|
||||
*
|
||||
* @return an array of the available locales for all provider classes
|
||||
*/
|
||||
public static Locale[] getAllAvailableLocales() {
|
||||
return AllAvailableLocales.allAvailableLocales.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of available locales. This array is a
|
||||
* merged array of all the locales that are provided by each
|
||||
* provider, including the JRE.
|
||||
*
|
||||
* @return an array of the available locales
|
||||
*/
|
||||
public Locale[] getAvailableLocales() {
|
||||
Set<Locale> locList = new HashSet<>();
|
||||
locList.addAll(getAvailableLocaleSet());
|
||||
// Make sure it all contains JRE's locales for compatibility.
|
||||
locList.addAll(Arrays.asList(LocaleProviderAdapter.forJRE().getAvailableLocales()));
|
||||
Locale[] tmp = new Locale[locList.size()];
|
||||
locList.toArray(tmp);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the union of locale sets that are available from
|
||||
* each service provider. This method does NOT return the
|
||||
* defensive copy.
|
||||
*
|
||||
* @return a set of available locales
|
||||
*/
|
||||
private synchronized Set<Locale> getAvailableLocaleSet() {
|
||||
if (availableLocales == null) {
|
||||
availableLocales = new HashSet<>();
|
||||
for (LocaleServiceProvider lsp : providers.values()) {
|
||||
Locale[] locales = lsp.getAvailableLocales();
|
||||
for (Locale locale: locales) {
|
||||
availableLocales.add(getLookupLocale(locale));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return availableLocales;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether any provider for this locale sensitive
|
||||
* service is available or not, excluding JRE's one.
|
||||
*
|
||||
* @return true if any provider (other than JRE) is available
|
||||
*/
|
||||
boolean hasProviders() {
|
||||
return providers.size() != 1 ||
|
||||
(providers.get(LocaleProviderAdapter.Type.JRE) == null &&
|
||||
providers.get(LocaleProviderAdapter.Type.FALLBACK) == null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the provider's localized object for the specified
|
||||
* locale.
|
||||
*
|
||||
* @param getter an object on which getObject() method
|
||||
* is called to obtain the provider's instance.
|
||||
* @param locale the given locale that is used as the starting one
|
||||
* @param params provider specific parameters
|
||||
* @return provider's instance, or null.
|
||||
*/
|
||||
public <P extends LocaleServiceProvider, S> S getLocalizedObject(LocalizedObjectGetter<P, S> getter,
|
||||
Locale locale,
|
||||
Object... params) {
|
||||
return getLocalizedObjectImpl(getter, locale, true, null, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the provider's localized name for the specified
|
||||
* locale.
|
||||
*
|
||||
* @param getter an object on which getObject() method
|
||||
* is called to obtain the provider's instance.
|
||||
* @param locale the given locale that is used as the starting one
|
||||
* @param key the key string for name providers
|
||||
* @param params provider specific parameters
|
||||
* @return provider's instance, or null.
|
||||
*/
|
||||
public <P extends LocaleServiceProvider, S> S getLocalizedObject(LocalizedObjectGetter<P, S> getter,
|
||||
Locale locale,
|
||||
String key,
|
||||
Object... params) {
|
||||
return getLocalizedObjectImpl(getter, locale, false, key, params);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <P extends LocaleServiceProvider, S> S getLocalizedObjectImpl(LocalizedObjectGetter<P, S> getter,
|
||||
Locale locale,
|
||||
boolean isObjectProvider,
|
||||
String key,
|
||||
Object... params) {
|
||||
if (locale == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
|
||||
// Check whether JRE is the sole locale data provider or not,
|
||||
// and directly call it if it is.
|
||||
if (!hasProviders()) {
|
||||
return getter.getObject((P)providers.get(LocaleProviderAdapter.defaultLocaleProviderAdapter),
|
||||
locale, key, params);
|
||||
}
|
||||
|
||||
List<Locale> lookupLocales = getLookupLocales(locale);
|
||||
|
||||
Set<Locale> available = getAvailableLocaleSet();
|
||||
for (Locale current : lookupLocales) {
|
||||
if (available.contains(current)) {
|
||||
S providersObj;
|
||||
|
||||
for (LocaleProviderAdapter.Type type: findProviders(current)) {
|
||||
LocaleServiceProvider lsp = providers.get(type);
|
||||
providersObj = getter.getObject((P)lsp, locale, key, params);
|
||||
if (providersObj != null) {
|
||||
return providersObj;
|
||||
} else if (isObjectProvider) {
|
||||
config(LocaleServiceProviderPool.class,
|
||||
"A locale sensitive service provider returned null for a localized objects, which should not happen. provider: "
|
||||
+ lsp + " locale: " + locale);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// not found.
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of locale service provider instances that support
|
||||
* the specified locale.
|
||||
*
|
||||
* @param locale the given locale
|
||||
* @return the list of locale data adapter types
|
||||
*/
|
||||
private List<LocaleProviderAdapter.Type> findProviders(Locale locale) {
|
||||
List<LocaleProviderAdapter.Type> providersList = providersCache.get(locale);
|
||||
if (providersList == null) {
|
||||
for (LocaleProviderAdapter.Type type : LocaleProviderAdapter.getAdapterPreference()) {
|
||||
LocaleServiceProvider lsp = providers.get(type);
|
||||
if (lsp != null) {
|
||||
if (lsp.isSupportedLocale(locale)) {
|
||||
if (providersList == null) {
|
||||
providersList = new ArrayList<>(2);
|
||||
}
|
||||
providersList.add(type);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
if (providersList == null) {
|
||||
providersList = NULL_LIST;
|
||||
}
|
||||
List<LocaleProviderAdapter.Type> val = providersCache.putIfAbsent(locale, providersList);
|
||||
if (val != null) {
|
||||
providersList = val;
|
||||
}
|
||||
}
|
||||
return providersList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of candidate locales for service look up.
|
||||
* @param locale the input locale
|
||||
* @return the list of candidate locales for the given locale
|
||||
*/
|
||||
static List<Locale> getLookupLocales(Locale locale) {
|
||||
// Note: We currently use the default implementation of
|
||||
// ResourceBundle.Control.getCandidateLocales. The result
|
||||
// returned by getCandidateLocales are already normalized
|
||||
// (no extensions) for service look up.
|
||||
List<Locale> lookupLocales = Control.getNoFallbackControl(Control.FORMAT_DEFAULT)
|
||||
.getCandidateLocales("", locale);
|
||||
return lookupLocales;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an instance of Locale used for service look up.
|
||||
* The result Locale has no extensions except for ja_JP_JP
|
||||
* and th_TH_TH
|
||||
*
|
||||
* @param locale the locale
|
||||
* @return the locale used for service look up
|
||||
*/
|
||||
static Locale getLookupLocale(Locale locale) {
|
||||
Locale lookupLocale = locale;
|
||||
if (locale.hasExtensions()
|
||||
&& !locale.equals(JRELocaleConstants.JA_JP_JP)
|
||||
&& !locale.equals(JRELocaleConstants.TH_TH_TH)) {
|
||||
// remove extensions
|
||||
Builder locbld = new Builder();
|
||||
try {
|
||||
locbld.setLocale(locale);
|
||||
locbld.clearExtensions();
|
||||
lookupLocale = locbld.build();
|
||||
} catch (IllformedLocaleException e) {
|
||||
// A Locale with non-empty extensions
|
||||
// should have well-formed fields except
|
||||
// for ja_JP_JP and th_TH_TH. Therefore,
|
||||
// it should never enter in this catch clause.
|
||||
config(LocaleServiceProviderPool.class,
|
||||
"A locale(" + locale + ") has non-empty extensions, but has illformed fields.");
|
||||
|
||||
// Fallback - script field will be lost.
|
||||
lookupLocale = new Locale(locale.getLanguage(), locale.getCountry(), locale.getVariant());
|
||||
}
|
||||
}
|
||||
return lookupLocale;
|
||||
}
|
||||
|
||||
/**
|
||||
* A dummy locale service provider list that indicates there is no
|
||||
* provider available
|
||||
*/
|
||||
private static List<LocaleProviderAdapter.Type> NULL_LIST =
|
||||
Collections.emptyList();
|
||||
|
||||
/**
|
||||
* An interface to get a localized object for each locale sensitive
|
||||
* service class.
|
||||
*/
|
||||
public interface LocalizedObjectGetter<P extends LocaleServiceProvider, S> {
|
||||
/**
|
||||
* Returns an object from the provider
|
||||
*
|
||||
* @param lsp the provider
|
||||
* @param locale the locale
|
||||
* @param key key string to localize, or null if the provider is not
|
||||
* a name provider
|
||||
* @param params provider specific params
|
||||
* @return localized object from the provider
|
||||
*/
|
||||
public S getObject(P lsp,
|
||||
Locale locale,
|
||||
String key,
|
||||
Object... params);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,227 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
* (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
|
||||
* (C) Copyright IBM Corp. 1996 - 2002 - All Rights Reserved
|
||||
*
|
||||
* The original version of this source code and documentation
|
||||
* is copyrighted and owned by Taligent, Inc., a wholly-owned
|
||||
* subsidiary of IBM. These materials are provided under terms
|
||||
* of a License Agreement between Taligent and Sun. This technology
|
||||
* is protected by multiple US and International patents.
|
||||
*
|
||||
* This notice and attribution to Taligent may not be removed.
|
||||
* Taligent is a registered trademark of Taligent, Inc.
|
||||
*/
|
||||
|
||||
package sun.util.locale.provider;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
import java.text.DecimalFormatSymbols;
|
||||
import java.text.NumberFormat;
|
||||
import java.text.spi.NumberFormatProvider;
|
||||
import java.util.Currency;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Concrete implementation of the {@link java.text.spi.NumberFormatProvider
|
||||
* NumberFormatProvider} class for the JRE LocaleProviderAdapter.
|
||||
*
|
||||
* @author Naoto Sato
|
||||
* @author Masayoshi Okutsu
|
||||
*/
|
||||
public class NumberFormatProviderImpl extends NumberFormatProvider implements AvailableLanguageTags {
|
||||
|
||||
// Constants used by factory methods to specify a style of format.
|
||||
private static final int NUMBERSTYLE = 0;
|
||||
private static final int CURRENCYSTYLE = 1;
|
||||
private static final int PERCENTSTYLE = 2;
|
||||
private static final int SCIENTIFICSTYLE = 3;
|
||||
private static final int INTEGERSTYLE = 4;
|
||||
|
||||
private final LocaleProviderAdapter.Type type;
|
||||
private final Set<String> langtags;
|
||||
|
||||
public NumberFormatProviderImpl(LocaleProviderAdapter.Type type, Set<String> langtags) {
|
||||
this.type = type;
|
||||
this.langtags = langtags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of all locales for which this locale service provider
|
||||
* can provide localized objects or names.
|
||||
*
|
||||
* @return An array of all locales for which this locale service provider
|
||||
* can provide localized objects or names.
|
||||
*/
|
||||
@Override
|
||||
public Locale[] getAvailableLocales() {
|
||||
return LocaleProviderAdapter.forType(type).getAvailableLocales();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupportedLocale(Locale locale) {
|
||||
return LocaleProviderAdapter.isSupportedLocale(locale, type, langtags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new <code>NumberFormat</code> instance which formats
|
||||
* monetary values for the specified locale.
|
||||
*
|
||||
* @param locale the desired locale.
|
||||
* @exception NullPointerException if <code>locale</code> is null
|
||||
* @exception IllegalArgumentException if <code>locale</code> isn't
|
||||
* one of the locales returned from
|
||||
* {@link java.util.spi.LocaleServiceProvider#getAvailableLocales()
|
||||
* getAvailableLocales()}.
|
||||
* @return a currency formatter
|
||||
* @see java.text.NumberFormat#getCurrencyInstance(java.util.Locale)
|
||||
*/
|
||||
@Override
|
||||
public NumberFormat getCurrencyInstance(Locale locale) {
|
||||
return getInstance(locale, CURRENCYSTYLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new <code>NumberFormat</code> instance which formats
|
||||
* integer values for the specified locale.
|
||||
* The returned number format is configured to
|
||||
* round floating point numbers to the nearest integer using
|
||||
* half-even rounding (see {@link java.math.RoundingMode#HALF_EVEN HALF_EVEN})
|
||||
* for formatting, and to parse only the integer part of
|
||||
* an input string (see {@link
|
||||
* java.text.NumberFormat#isParseIntegerOnly isParseIntegerOnly}).
|
||||
*
|
||||
* @param locale the desired locale
|
||||
* @exception NullPointerException if <code>locale</code> is null
|
||||
* @exception IllegalArgumentException if <code>locale</code> isn't
|
||||
* one of the locales returned from
|
||||
* {@link java.util.spi.LocaleServiceProvider#getAvailableLocales()
|
||||
* getAvailableLocales()}.
|
||||
* @return a number format for integer values
|
||||
* @see java.text.NumberFormat#getIntegerInstance(java.util.Locale)
|
||||
*/
|
||||
@Override
|
||||
public NumberFormat getIntegerInstance(Locale locale) {
|
||||
return getInstance(locale, INTEGERSTYLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new general-purpose <code>NumberFormat</code> instance for
|
||||
* the specified locale.
|
||||
*
|
||||
* @param locale the desired locale
|
||||
* @exception NullPointerException if <code>locale</code> is null
|
||||
* @exception IllegalArgumentException if <code>locale</code> isn't
|
||||
* one of the locales returned from
|
||||
* {@link java.util.spi.LocaleServiceProvider#getAvailableLocales()
|
||||
* getAvailableLocales()}.
|
||||
* @return a general-purpose number formatter
|
||||
* @see java.text.NumberFormat#getNumberInstance(java.util.Locale)
|
||||
*/
|
||||
@Override
|
||||
public NumberFormat getNumberInstance(Locale locale) {
|
||||
return getInstance(locale, NUMBERSTYLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new <code>NumberFormat</code> instance which formats
|
||||
* percentage values for the specified locale.
|
||||
*
|
||||
* @param locale the desired locale
|
||||
* @exception NullPointerException if <code>locale</code> is null
|
||||
* @exception IllegalArgumentException if <code>locale</code> isn't
|
||||
* one of the locales returned from
|
||||
* {@link java.util.spi.LocaleServiceProvider#getAvailableLocales()
|
||||
* getAvailableLocales()}.
|
||||
* @return a percent formatter
|
||||
* @see java.text.NumberFormat#getPercentInstance(java.util.Locale)
|
||||
*/
|
||||
@Override
|
||||
public NumberFormat getPercentInstance(Locale locale) {
|
||||
return getInstance(locale, PERCENTSTYLE);
|
||||
}
|
||||
|
||||
private NumberFormat getInstance(Locale locale,
|
||||
int choice) {
|
||||
if (locale == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
|
||||
LocaleProviderAdapter adapter = LocaleProviderAdapter.forType(type);
|
||||
String[] numberPatterns = adapter.getLocaleResources(locale).getNumberPatterns();
|
||||
DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance(locale);
|
||||
int entry = (choice == INTEGERSTYLE) ? NUMBERSTYLE : choice;
|
||||
DecimalFormat format = new DecimalFormat(numberPatterns[entry], symbols);
|
||||
|
||||
if (choice == INTEGERSTYLE) {
|
||||
format.setMaximumFractionDigits(0);
|
||||
format.setDecimalSeparatorAlwaysShown(false);
|
||||
format.setParseIntegerOnly(true);
|
||||
} else if (choice == CURRENCYSTYLE) {
|
||||
adjustForCurrencyDefaultFractionDigits(format, symbols);
|
||||
}
|
||||
|
||||
return format;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjusts the minimum and maximum fraction digits to values that
|
||||
* are reasonable for the currency's default fraction digits.
|
||||
*/
|
||||
private static void adjustForCurrencyDefaultFractionDigits(
|
||||
DecimalFormat format, DecimalFormatSymbols symbols) {
|
||||
Currency currency = symbols.getCurrency();
|
||||
if (currency == null) {
|
||||
try {
|
||||
currency = Currency.getInstance(symbols.getInternationalCurrencySymbol());
|
||||
} catch (IllegalArgumentException e) {
|
||||
}
|
||||
}
|
||||
if (currency != null) {
|
||||
int digits = currency.getDefaultFractionDigits();
|
||||
if (digits != -1) {
|
||||
int oldMinDigits = format.getMinimumFractionDigits();
|
||||
// Common patterns are "#.##", "#.00", "#".
|
||||
// Try to adjust all of them in a reasonable way.
|
||||
if (oldMinDigits == format.getMaximumFractionDigits()) {
|
||||
format.setMinimumFractionDigits(digits);
|
||||
format.setMaximumFractionDigits(digits);
|
||||
} else {
|
||||
format.setMinimumFractionDigits(Math.min(digits, oldMinDigits));
|
||||
format.setMaximumFractionDigits(digits);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getAvailableLanguageTags() {
|
||||
return langtags;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.util.locale.provider;
|
||||
|
||||
import sun.util.resources.LocaleData;
|
||||
|
||||
/**
|
||||
* Accessor for LocaleData
|
||||
*
|
||||
* @author Naoto Sato
|
||||
*/
|
||||
public interface ResourceBundleBasedAdapter {
|
||||
public LocaleData getLocaleData();
|
||||
}
|
||||
1195
jdkSrc/jdk8/sun/util/locale/provider/RuleBasedBreakIterator.java
Normal file
1195
jdkSrc/jdk8/sun/util/locale/provider/RuleBasedBreakIterator.java
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,615 @@
|
||||
/*
|
||||
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.util.locale.provider;
|
||||
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedActionException;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
import java.text.BreakIterator;
|
||||
import java.text.Collator;
|
||||
import java.text.DateFormat;
|
||||
import java.text.DateFormatSymbols;
|
||||
import java.text.DecimalFormatSymbols;
|
||||
import java.text.NumberFormat;
|
||||
import java.text.spi.BreakIteratorProvider;
|
||||
import java.text.spi.CollatorProvider;
|
||||
import java.text.spi.DateFormatProvider;
|
||||
import java.text.spi.DateFormatSymbolsProvider;
|
||||
import java.text.spi.DecimalFormatSymbolsProvider;
|
||||
import java.text.spi.NumberFormatProvider;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.ServiceLoader;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.spi.CalendarDataProvider;
|
||||
import java.util.spi.CalendarNameProvider;
|
||||
import java.util.spi.CurrencyNameProvider;
|
||||
import java.util.spi.LocaleNameProvider;
|
||||
import java.util.spi.LocaleServiceProvider;
|
||||
import java.util.spi.TimeZoneNameProvider;
|
||||
|
||||
/**
|
||||
* LocaleProviderAdapter implementation for the installed SPI implementations.
|
||||
*
|
||||
* @author Naoto Sato
|
||||
* @author Masayoshi Okutsu
|
||||
*/
|
||||
public class SPILocaleProviderAdapter extends AuxLocaleProviderAdapter {
|
||||
|
||||
/**
|
||||
* Returns the type of this LocaleProviderAdapter
|
||||
*/
|
||||
@Override
|
||||
public LocaleProviderAdapter.Type getAdapterType() {
|
||||
return LocaleProviderAdapter.Type.SPI;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <P extends LocaleServiceProvider> P findInstalledProvider(final Class<P> c) {
|
||||
try {
|
||||
return AccessController.doPrivileged(new PrivilegedExceptionAction<P>() {
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public P run() {
|
||||
P delegate = null;
|
||||
|
||||
for (LocaleServiceProvider provider : ServiceLoader.loadInstalled(c)) {
|
||||
if (delegate == null) {
|
||||
try {
|
||||
delegate =
|
||||
(P) Class.forName(SPILocaleProviderAdapter.class.getCanonicalName() +
|
||||
"$" +
|
||||
c.getSimpleName() +
|
||||
"Delegate")
|
||||
.newInstance();
|
||||
} catch (ClassNotFoundException |
|
||||
InstantiationException |
|
||||
IllegalAccessException e) {
|
||||
LocaleServiceProviderPool.config(SPILocaleProviderAdapter.class, e.toString());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
((Delegate)delegate).addImpl(provider);
|
||||
}
|
||||
return delegate;
|
||||
}
|
||||
});
|
||||
} catch (PrivilegedActionException e) {
|
||||
LocaleServiceProviderPool.config(SPILocaleProviderAdapter.class, e.toString());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* Delegate interface. All the implementations have to have the class name
|
||||
* following "<provider class name>Delegate" convention.
|
||||
*/
|
||||
interface Delegate<P extends LocaleServiceProvider> {
|
||||
public void addImpl(P impl);
|
||||
public P getImpl(Locale locale);
|
||||
}
|
||||
|
||||
/*
|
||||
* Obtain the real SPI implementation, using locale fallback
|
||||
*/
|
||||
private static <P extends LocaleServiceProvider> P getImpl(Map<Locale, P> map, Locale locale) {
|
||||
for (Locale l : LocaleServiceProviderPool.getLookupLocales(locale)) {
|
||||
P ret = map.get(l);
|
||||
if (ret != null) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* Delegates for the actual SPI implementations.
|
||||
*/
|
||||
static class BreakIteratorProviderDelegate extends BreakIteratorProvider
|
||||
implements Delegate<BreakIteratorProvider> {
|
||||
private ConcurrentMap<Locale, BreakIteratorProvider> map = new ConcurrentHashMap<>();
|
||||
|
||||
@Override
|
||||
public void addImpl(BreakIteratorProvider impl) {
|
||||
for (Locale l : impl.getAvailableLocales()) {
|
||||
map.putIfAbsent(l, impl);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public BreakIteratorProvider getImpl(Locale locale) {
|
||||
return SPILocaleProviderAdapter.getImpl(map, locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Locale[] getAvailableLocales() {
|
||||
return map.keySet().toArray(new Locale[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupportedLocale(Locale locale) {
|
||||
return map.containsKey(locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BreakIterator getWordInstance(Locale locale) {
|
||||
BreakIteratorProvider bip = getImpl(locale);
|
||||
assert bip != null;
|
||||
return bip.getWordInstance(locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BreakIterator getLineInstance(Locale locale) {
|
||||
BreakIteratorProvider bip = getImpl(locale);
|
||||
assert bip != null;
|
||||
return bip.getLineInstance(locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BreakIterator getCharacterInstance(Locale locale) {
|
||||
BreakIteratorProvider bip = getImpl(locale);
|
||||
assert bip != null;
|
||||
return bip.getCharacterInstance(locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BreakIterator getSentenceInstance(Locale locale) {
|
||||
BreakIteratorProvider bip = getImpl(locale);
|
||||
assert bip != null;
|
||||
return bip.getSentenceInstance(locale);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class CollatorProviderDelegate extends CollatorProvider implements Delegate<CollatorProvider> {
|
||||
private ConcurrentMap<Locale, CollatorProvider> map = new ConcurrentHashMap<>();
|
||||
|
||||
@Override
|
||||
public void addImpl(CollatorProvider impl) {
|
||||
for (Locale l : impl.getAvailableLocales()) {
|
||||
map.putIfAbsent(l, impl);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CollatorProvider getImpl(Locale locale) {
|
||||
return SPILocaleProviderAdapter.getImpl(map, locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Locale[] getAvailableLocales() {
|
||||
return map.keySet().toArray(new Locale[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupportedLocale(Locale locale) {
|
||||
return map.containsKey(locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collator getInstance(Locale locale) {
|
||||
CollatorProvider cp = getImpl(locale);
|
||||
assert cp != null;
|
||||
return cp.getInstance(locale);
|
||||
}
|
||||
}
|
||||
|
||||
static class DateFormatProviderDelegate extends DateFormatProvider
|
||||
implements Delegate<DateFormatProvider> {
|
||||
private ConcurrentMap<Locale, DateFormatProvider> map = new ConcurrentHashMap<>();
|
||||
|
||||
@Override
|
||||
public void addImpl(DateFormatProvider impl) {
|
||||
for (Locale l : impl.getAvailableLocales()) {
|
||||
map.putIfAbsent(l, impl);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public DateFormatProvider getImpl(Locale locale) {
|
||||
return SPILocaleProviderAdapter.getImpl(map, locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Locale[] getAvailableLocales() {
|
||||
return map.keySet().toArray(new Locale[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupportedLocale(Locale locale) {
|
||||
return map.containsKey(locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DateFormat getTimeInstance(int style, Locale locale) {
|
||||
DateFormatProvider dfp = getImpl(locale);
|
||||
assert dfp != null;
|
||||
return dfp.getTimeInstance(style, locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DateFormat getDateInstance(int style, Locale locale) {
|
||||
DateFormatProvider dfp = getImpl(locale);
|
||||
assert dfp != null;
|
||||
return dfp.getDateInstance(style, locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DateFormat getDateTimeInstance(int dateStyle, int timeStyle, Locale locale) {
|
||||
DateFormatProvider dfp = getImpl(locale);
|
||||
assert dfp != null;
|
||||
return dfp.getDateTimeInstance(dateStyle, timeStyle, locale);
|
||||
}
|
||||
}
|
||||
|
||||
static class DateFormatSymbolsProviderDelegate extends DateFormatSymbolsProvider
|
||||
implements Delegate<DateFormatSymbolsProvider> {
|
||||
private ConcurrentMap<Locale, DateFormatSymbolsProvider> map = new ConcurrentHashMap<>();
|
||||
|
||||
@Override
|
||||
public void addImpl(DateFormatSymbolsProvider impl) {
|
||||
for (Locale l : impl.getAvailableLocales()) {
|
||||
map.putIfAbsent(l, impl);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public DateFormatSymbolsProvider getImpl(Locale locale) {
|
||||
return SPILocaleProviderAdapter.getImpl(map, locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Locale[] getAvailableLocales() {
|
||||
return map.keySet().toArray(new Locale[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupportedLocale(Locale locale) {
|
||||
return map.containsKey(locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DateFormatSymbols getInstance(Locale locale) {
|
||||
DateFormatSymbolsProvider dfsp = getImpl(locale);
|
||||
assert dfsp != null;
|
||||
return dfsp.getInstance(locale);
|
||||
}
|
||||
}
|
||||
|
||||
static class DecimalFormatSymbolsProviderDelegate extends DecimalFormatSymbolsProvider
|
||||
implements Delegate<DecimalFormatSymbolsProvider> {
|
||||
private ConcurrentMap<Locale, DecimalFormatSymbolsProvider> map = new ConcurrentHashMap<>();
|
||||
|
||||
@Override
|
||||
public void addImpl(DecimalFormatSymbolsProvider impl) {
|
||||
for (Locale l : impl.getAvailableLocales()) {
|
||||
map.putIfAbsent(l, impl);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public DecimalFormatSymbolsProvider getImpl(Locale locale) {
|
||||
return SPILocaleProviderAdapter.getImpl(map, locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Locale[] getAvailableLocales() {
|
||||
return map.keySet().toArray(new Locale[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupportedLocale(Locale locale) {
|
||||
return map.containsKey(locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DecimalFormatSymbols getInstance(Locale locale) {
|
||||
DecimalFormatSymbolsProvider dfsp = getImpl(locale);
|
||||
assert dfsp != null;
|
||||
return dfsp.getInstance(locale);
|
||||
}
|
||||
}
|
||||
|
||||
static class NumberFormatProviderDelegate extends NumberFormatProvider
|
||||
implements Delegate<NumberFormatProvider> {
|
||||
private ConcurrentMap<Locale, NumberFormatProvider> map = new ConcurrentHashMap<>();
|
||||
|
||||
@Override
|
||||
public void addImpl(NumberFormatProvider impl) {
|
||||
for (Locale l : impl.getAvailableLocales()) {
|
||||
map.putIfAbsent(l, impl);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public NumberFormatProvider getImpl(Locale locale) {
|
||||
return SPILocaleProviderAdapter.getImpl(map, locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Locale[] getAvailableLocales() {
|
||||
return map.keySet().toArray(new Locale[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupportedLocale(Locale locale) {
|
||||
return map.containsKey(locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NumberFormat getCurrencyInstance(Locale locale) {
|
||||
NumberFormatProvider nfp = getImpl(locale);
|
||||
assert nfp != null;
|
||||
return nfp.getCurrencyInstance(locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NumberFormat getIntegerInstance(Locale locale) {
|
||||
NumberFormatProvider nfp = getImpl(locale);
|
||||
assert nfp != null;
|
||||
return nfp.getIntegerInstance(locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NumberFormat getNumberInstance(Locale locale) {
|
||||
NumberFormatProvider nfp = getImpl(locale);
|
||||
assert nfp != null;
|
||||
return nfp.getNumberInstance(locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NumberFormat getPercentInstance(Locale locale) {
|
||||
NumberFormatProvider nfp = getImpl(locale);
|
||||
assert nfp != null;
|
||||
return nfp.getPercentInstance(locale);
|
||||
}
|
||||
}
|
||||
|
||||
static class CalendarDataProviderDelegate extends CalendarDataProvider
|
||||
implements Delegate<CalendarDataProvider> {
|
||||
private ConcurrentMap<Locale, CalendarDataProvider> map = new ConcurrentHashMap<>();
|
||||
|
||||
@Override
|
||||
public void addImpl(CalendarDataProvider impl) {
|
||||
for (Locale l : impl.getAvailableLocales()) {
|
||||
map.putIfAbsent(l, impl);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CalendarDataProvider getImpl(Locale locale) {
|
||||
return SPILocaleProviderAdapter.getImpl(map, locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Locale[] getAvailableLocales() {
|
||||
return map.keySet().toArray(new Locale[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupportedLocale(Locale locale) {
|
||||
return map.containsKey(locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFirstDayOfWeek(Locale locale) {
|
||||
CalendarDataProvider cdp = getImpl(locale);
|
||||
assert cdp != null;
|
||||
return cdp.getFirstDayOfWeek(locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinimalDaysInFirstWeek(Locale locale) {
|
||||
CalendarDataProvider cdp = getImpl(locale);
|
||||
assert cdp != null;
|
||||
return cdp.getMinimalDaysInFirstWeek(locale);
|
||||
}
|
||||
}
|
||||
|
||||
static class CalendarNameProviderDelegate extends CalendarNameProvider
|
||||
implements Delegate<CalendarNameProvider> {
|
||||
private ConcurrentMap<Locale, CalendarNameProvider> map = new ConcurrentHashMap<>();
|
||||
|
||||
@Override
|
||||
public void addImpl(CalendarNameProvider impl) {
|
||||
for (Locale l : impl.getAvailableLocales()) {
|
||||
map.putIfAbsent(l, impl);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CalendarNameProvider getImpl(Locale locale) {
|
||||
return SPILocaleProviderAdapter.getImpl(map, locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Locale[] getAvailableLocales() {
|
||||
return map.keySet().toArray(new Locale[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupportedLocale(Locale locale) {
|
||||
return map.containsKey(locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayName(String calendarType,
|
||||
int field, int value,
|
||||
int style, Locale locale) {
|
||||
CalendarNameProvider cdp = getImpl(locale);
|
||||
assert cdp != null;
|
||||
return cdp.getDisplayName(calendarType, field, value, style, locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Integer> getDisplayNames(String calendarType,
|
||||
int field, int style,
|
||||
Locale locale) {
|
||||
CalendarNameProvider cdp = getImpl(locale);
|
||||
assert cdp != null;
|
||||
return cdp.getDisplayNames(calendarType, field, style, locale);
|
||||
}
|
||||
}
|
||||
|
||||
static class CurrencyNameProviderDelegate extends CurrencyNameProvider
|
||||
implements Delegate<CurrencyNameProvider> {
|
||||
private ConcurrentMap<Locale, CurrencyNameProvider> map = new ConcurrentHashMap<>();
|
||||
|
||||
@Override
|
||||
public void addImpl(CurrencyNameProvider impl) {
|
||||
for (Locale l : impl.getAvailableLocales()) {
|
||||
map.putIfAbsent(l, impl);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CurrencyNameProvider getImpl(Locale locale) {
|
||||
return SPILocaleProviderAdapter.getImpl(map, locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Locale[] getAvailableLocales() {
|
||||
return map.keySet().toArray(new Locale[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupportedLocale(Locale locale) {
|
||||
return map.containsKey(locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSymbol(String currencyCode, Locale locale) {
|
||||
CurrencyNameProvider cnp = getImpl(locale);
|
||||
assert cnp != null;
|
||||
return cnp.getSymbol(currencyCode, locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayName(String currencyCode, Locale locale) {
|
||||
CurrencyNameProvider cnp = getImpl(locale);
|
||||
assert cnp != null;
|
||||
return cnp.getDisplayName(currencyCode, locale);
|
||||
}
|
||||
}
|
||||
|
||||
static class LocaleNameProviderDelegate extends LocaleNameProvider
|
||||
implements Delegate<LocaleNameProvider> {
|
||||
private ConcurrentMap<Locale, LocaleNameProvider> map = new ConcurrentHashMap<>();
|
||||
|
||||
@Override
|
||||
public void addImpl(LocaleNameProvider impl) {
|
||||
for (Locale l : impl.getAvailableLocales()) {
|
||||
map.putIfAbsent(l, impl);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocaleNameProvider getImpl(Locale locale) {
|
||||
return SPILocaleProviderAdapter.getImpl(map, locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Locale[] getAvailableLocales() {
|
||||
return map.keySet().toArray(new Locale[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupportedLocale(Locale locale) {
|
||||
return map.containsKey(locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayLanguage(String languageCode, Locale locale) {
|
||||
LocaleNameProvider lnp = getImpl(locale);
|
||||
assert lnp != null;
|
||||
return lnp.getDisplayLanguage(languageCode, locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayScript(String scriptCode, Locale locale) {
|
||||
LocaleNameProvider lnp = getImpl(locale);
|
||||
assert lnp != null;
|
||||
return lnp.getDisplayScript(scriptCode, locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayCountry(String countryCode, Locale locale) {
|
||||
LocaleNameProvider lnp = getImpl(locale);
|
||||
assert lnp != null;
|
||||
return lnp.getDisplayCountry(countryCode, locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayVariant(String variant, Locale locale) {
|
||||
LocaleNameProvider lnp = getImpl(locale);
|
||||
assert lnp != null;
|
||||
return lnp.getDisplayVariant(variant, locale);
|
||||
}
|
||||
}
|
||||
|
||||
static class TimeZoneNameProviderDelegate extends TimeZoneNameProvider
|
||||
implements Delegate<TimeZoneNameProvider> {
|
||||
private ConcurrentMap<Locale, TimeZoneNameProvider> map = new ConcurrentHashMap<>();
|
||||
|
||||
@Override
|
||||
public void addImpl(TimeZoneNameProvider impl) {
|
||||
for (Locale l : impl.getAvailableLocales()) {
|
||||
map.putIfAbsent(l, impl);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TimeZoneNameProvider getImpl(Locale locale) {
|
||||
return SPILocaleProviderAdapter.getImpl(map, locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Locale[] getAvailableLocales() {
|
||||
return map.keySet().toArray(new Locale[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupportedLocale(Locale locale) {
|
||||
return map.containsKey(locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayName(String ID, boolean daylight, int style, Locale locale) {
|
||||
TimeZoneNameProvider tznp = getImpl(locale);
|
||||
assert tznp != null;
|
||||
return tznp.getDisplayName(ID, daylight, style, locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGenericDisplayName(String ID, int style, Locale locale) {
|
||||
TimeZoneNameProvider tznp = getImpl(locale);
|
||||
assert tznp != null;
|
||||
return tznp.getGenericDisplayName(ID, style, locale);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.util.locale.provider;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.TimeZone;
|
||||
import java.util.spi.TimeZoneNameProvider;
|
||||
|
||||
/**
|
||||
* Concrete implementation of the
|
||||
* {@link java.util.spi.TimeZoneNameProvider TimeZoneNameProvider} class
|
||||
* for the JRE LocaleProviderAdapter.
|
||||
*
|
||||
* @author Naoto Sato
|
||||
* @author Masayoshi Okutsu
|
||||
*/
|
||||
public class TimeZoneNameProviderImpl extends TimeZoneNameProvider {
|
||||
private final LocaleProviderAdapter.Type type;
|
||||
private final Set<String> langtags;
|
||||
|
||||
TimeZoneNameProviderImpl(LocaleProviderAdapter.Type type, Set<String> langtags) {
|
||||
this.type = type;
|
||||
this.langtags = langtags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of all locales for which this locale service provider
|
||||
* can provide localized objects or names.
|
||||
*
|
||||
* @return An array of all locales for which this locale service provider
|
||||
* can provide localized objects or names.
|
||||
*/
|
||||
@Override
|
||||
public Locale[] getAvailableLocales() {
|
||||
return LocaleProviderAdapter.toLocaleArray(langtags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupportedLocale(Locale locale) {
|
||||
return LocaleProviderAdapter.isSupportedLocale(locale, type, langtags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a name for the given time zone ID that's suitable for
|
||||
* presentation to the user in the specified locale. The given time
|
||||
* zone ID is "GMT" or one of the names defined using "Zone" entries
|
||||
* in the "tz database", a public domain time zone database at
|
||||
* <a href="ftp://elsie.nci.nih.gov/pub/">ftp://elsie.nci.nih.gov/pub/</a>.
|
||||
* The data of this database is contained in a file whose name starts with
|
||||
* "tzdata", and the specification of the data format is part of the zic.8
|
||||
* man page, which is contained in a file whose name starts with "tzcode".
|
||||
* <p>
|
||||
* If <code>daylight</code> is true, the method should return a name
|
||||
* appropriate for daylight saving time even if the specified time zone
|
||||
* has not observed daylight saving time in the past.
|
||||
*
|
||||
* @param ID a time zone ID string
|
||||
* @param daylight if true, return the daylight saving name.
|
||||
* @param style either {@link java.util.TimeZone#LONG TimeZone.LONG} or
|
||||
* {@link java.util.TimeZone#SHORT TimeZone.SHORT}
|
||||
* @param locale the desired locale
|
||||
* @return the human-readable name of the given time zone in the
|
||||
* given locale, or null if it's not available.
|
||||
* @exception IllegalArgumentException if <code>style</code> is invalid,
|
||||
* or <code>locale</code> isn't one of the locales returned from
|
||||
* {@link java.util.spi.LocaleServiceProvider#getAvailableLocales()
|
||||
* getAvailableLocales()}.
|
||||
* @exception NullPointerException if <code>ID</code> or <code>locale</code>
|
||||
* is null
|
||||
* @see java.util.TimeZone#getDisplayName(boolean, int, java.util.Locale)
|
||||
*/
|
||||
@Override
|
||||
public String getDisplayName(String id, boolean daylight, int style, Locale locale) {
|
||||
String[] names = getDisplayNameArray(id, locale);
|
||||
if (Objects.nonNull(names)) {
|
||||
assert names.length >= 7;
|
||||
int index = daylight ? 3 : 1;
|
||||
if (style == TimeZone.SHORT) {
|
||||
index++;
|
||||
}
|
||||
return names[index];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGenericDisplayName(String id, int style, Locale locale) {
|
||||
String[] names = getDisplayNameArray(id, locale);
|
||||
if (Objects.nonNull(names)) {
|
||||
assert names.length >= 7;
|
||||
return names[(style == TimeZone.LONG) ? 5 : 6];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private String[] getDisplayNameArray(String id, Locale locale) {
|
||||
Objects.requireNonNull(id);
|
||||
Objects.requireNonNull(locale);
|
||||
return LocaleProviderAdapter.forType(type).getLocaleResources(locale).getTimeZoneNames(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a String[][] as the DateFormatSymbols.getZoneStrings() value for
|
||||
* the given locale. This method is package private.
|
||||
*
|
||||
* @param locale a Locale for time zone names
|
||||
* @return an array of time zone names arrays
|
||||
*/
|
||||
String[][] getZoneStrings(Locale locale) {
|
||||
return LocaleProviderAdapter.forType(type).getLocaleResources(locale).getZoneStrings();
|
||||
}
|
||||
}
|
||||
256
jdkSrc/jdk8/sun/util/locale/provider/TimeZoneNameUtility.java
Normal file
256
jdkSrc/jdk8/sun/util/locale/provider/TimeZoneNameUtility.java
Normal file
@@ -0,0 +1,256 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.util.locale.provider;
|
||||
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.spi.TimeZoneNameProvider;
|
||||
import sun.util.calendar.ZoneInfo;
|
||||
|
||||
/**
|
||||
* Utility class that deals with the localized time zone names
|
||||
*
|
||||
* @author Naoto Sato
|
||||
* @author Masayoshi Okutsu
|
||||
*/
|
||||
public final class TimeZoneNameUtility {
|
||||
|
||||
/**
|
||||
* cache to hold time zone localized strings. Keyed by Locale
|
||||
*/
|
||||
private static ConcurrentHashMap<Locale, SoftReference<String[][]>> cachedZoneData =
|
||||
new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* Cache for managing display names per timezone per locale
|
||||
* The structure is:
|
||||
* Map(key=id, value=SoftReference(Map(key=locale, value=displaynames)))
|
||||
*/
|
||||
private static final Map<String, SoftReference<Map<Locale, String[]>>> cachedDisplayNames =
|
||||
new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* get time zone localized strings. Enumerate all keys.
|
||||
*/
|
||||
public static String[][] getZoneStrings(Locale locale) {
|
||||
String[][] zones;
|
||||
SoftReference<String[][]> data = cachedZoneData.get(locale);
|
||||
|
||||
if (data == null || ((zones = data.get()) == null)) {
|
||||
zones = loadZoneStrings(locale);
|
||||
data = new SoftReference<>(zones);
|
||||
cachedZoneData.put(locale, data);
|
||||
}
|
||||
|
||||
return zones;
|
||||
}
|
||||
|
||||
private static String[][] loadZoneStrings(Locale locale) {
|
||||
// If the provider is a TimeZoneNameProviderImpl, call its getZoneStrings
|
||||
// in order to avoid per-ID retrieval.
|
||||
LocaleProviderAdapter adapter = LocaleProviderAdapter.getAdapter(TimeZoneNameProvider.class, locale);
|
||||
TimeZoneNameProvider provider = adapter.getTimeZoneNameProvider();
|
||||
if (provider instanceof TimeZoneNameProviderImpl) {
|
||||
return ((TimeZoneNameProviderImpl)provider).getZoneStrings(locale);
|
||||
}
|
||||
|
||||
// Performs per-ID retrieval.
|
||||
Set<String> zoneIDs = LocaleProviderAdapter.forJRE().getLocaleResources(locale).getZoneIDs();
|
||||
List<String[]> zones = new LinkedList<>();
|
||||
for (String key : zoneIDs) {
|
||||
String[] names = retrieveDisplayNamesImpl(key, locale);
|
||||
if (names != null) {
|
||||
zones.add(names);
|
||||
}
|
||||
}
|
||||
|
||||
String[][] zonesArray = new String[zones.size()][];
|
||||
return zones.toArray(zonesArray);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve display names for a time zone ID.
|
||||
*/
|
||||
public static String[] retrieveDisplayNames(String id, Locale locale) {
|
||||
Objects.requireNonNull(id);
|
||||
Objects.requireNonNull(locale);
|
||||
|
||||
return retrieveDisplayNamesImpl(id, locale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a generic time zone display name for a time zone ID.
|
||||
*
|
||||
* @param id time zone ID
|
||||
* @param style TimeZone.LONG or TimeZone.SHORT
|
||||
* @param locale desired Locale
|
||||
* @return the requested generic time zone display name, or null if not found.
|
||||
*/
|
||||
public static String retrieveGenericDisplayName(String id, int style, Locale locale) {
|
||||
String[] names = retrieveDisplayNamesImpl(id, locale);
|
||||
if (Objects.nonNull(names)) {
|
||||
return names[6 - style];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a standard or daylight-saving time name for the given time zone ID.
|
||||
*
|
||||
* @param id time zone ID
|
||||
* @param daylight true for a daylight saving time name, or false for a standard time name
|
||||
* @param style TimeZone.LONG or TimeZone.SHORT
|
||||
* @param locale desired Locale
|
||||
* @return the requested time zone name, or null if not found.
|
||||
*/
|
||||
public static String retrieveDisplayName(String id, boolean daylight, int style, Locale locale) {
|
||||
String[] names = retrieveDisplayNamesImpl(id, locale);
|
||||
if (Objects.nonNull(names)) {
|
||||
return names[(daylight ? 4 : 2) - style];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static String[] retrieveDisplayNamesImpl(String id, Locale locale) {
|
||||
LocaleServiceProviderPool pool =
|
||||
LocaleServiceProviderPool.getPool(TimeZoneNameProvider.class);
|
||||
String[] names;
|
||||
Map<Locale, String[]> perLocale = null;
|
||||
|
||||
SoftReference<Map<Locale, String[]>> ref = cachedDisplayNames.get(id);
|
||||
if (Objects.nonNull(ref)) {
|
||||
perLocale = ref.get();
|
||||
if (Objects.nonNull(perLocale)) {
|
||||
names = perLocale.get(locale);
|
||||
if (Objects.nonNull(names)) {
|
||||
return names;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// build names array
|
||||
names = new String[7];
|
||||
names[0] = id;
|
||||
for (int i = 1; i <= 6; i ++) {
|
||||
names[i] = pool.getLocalizedObject(TimeZoneNameGetter.INSTANCE, locale,
|
||||
i<5 ? (i<3 ? "std" : "dst") : "generic", i%2, id);
|
||||
}
|
||||
|
||||
if (Objects.isNull(perLocale)) {
|
||||
perLocale = new ConcurrentHashMap<>();
|
||||
}
|
||||
perLocale.put(locale, names);
|
||||
ref = new SoftReference<>(perLocale);
|
||||
cachedDisplayNames.put(id, ref);
|
||||
return names;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Obtains a localized time zone strings from a TimeZoneNameProvider
|
||||
* implementation.
|
||||
*/
|
||||
private static class TimeZoneNameGetter
|
||||
implements LocaleServiceProviderPool.LocalizedObjectGetter<TimeZoneNameProvider,
|
||||
String> {
|
||||
private static final TimeZoneNameGetter INSTANCE =
|
||||
new TimeZoneNameGetter();
|
||||
|
||||
@Override
|
||||
public String getObject(TimeZoneNameProvider timeZoneNameProvider,
|
||||
Locale locale,
|
||||
String requestID,
|
||||
Object... params) {
|
||||
assert params.length == 2;
|
||||
int style = (int) params[0];
|
||||
String tzid = (String) params[1];
|
||||
String value = getName(timeZoneNameProvider, locale, requestID, style, tzid);
|
||||
if (value == null) {
|
||||
Map<String, String> aliases = ZoneInfo.getAliasTable();
|
||||
if (aliases != null) {
|
||||
String canonicalID = aliases.get(tzid);
|
||||
if (canonicalID != null) {
|
||||
value = getName(timeZoneNameProvider, locale, requestID, style, canonicalID);
|
||||
}
|
||||
if (value == null) {
|
||||
value = examineAliases(timeZoneNameProvider, locale, requestID,
|
||||
canonicalID != null ? canonicalID : tzid, style, aliases);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
private static String examineAliases(TimeZoneNameProvider tznp, Locale locale,
|
||||
String requestID, String tzid, int style,
|
||||
Map<String, String> aliases) {
|
||||
for (Map.Entry<String, String> entry : aliases.entrySet()) {
|
||||
if (entry.getValue().equals(tzid)) {
|
||||
String alias = entry.getKey();
|
||||
String name = getName(tznp, locale, requestID, style, alias);
|
||||
if (name != null) {
|
||||
return name;
|
||||
}
|
||||
name = examineAliases(tznp, locale, requestID, alias, style, aliases);
|
||||
if (name != null) {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static String getName(TimeZoneNameProvider timeZoneNameProvider,
|
||||
Locale locale, String requestID, int style, String tzid) {
|
||||
String value = null;
|
||||
switch (requestID) {
|
||||
case "std":
|
||||
value = timeZoneNameProvider.getDisplayName(tzid, false, style, locale);
|
||||
break;
|
||||
case "dst":
|
||||
value = timeZoneNameProvider.getDisplayName(tzid, true, style, locale);
|
||||
break;
|
||||
case "generic":
|
||||
value = timeZoneNameProvider.getGenericDisplayName(tzid, style, locale);
|
||||
break;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
// No instantiation
|
||||
private TimeZoneNameUtility() {
|
||||
}
|
||||
}
|
||||
68
jdkSrc/jdk8/sun/util/logging/LoggingProxy.java
Normal file
68
jdkSrc/jdk8/sun/util/logging/LoggingProxy.java
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
|
||||
package sun.util.logging;
|
||||
|
||||
/**
|
||||
* A proxy interface for the java.util.logging support.
|
||||
*
|
||||
* @see sun.util.logging.LoggingSupport
|
||||
*/
|
||||
public interface LoggingProxy {
|
||||
// Methods to bridge java.util.logging.Logger methods
|
||||
public Object getLogger(String name);
|
||||
|
||||
public Object getLevel(Object logger);
|
||||
|
||||
public void setLevel(Object logger, Object newLevel);
|
||||
|
||||
public boolean isLoggable(Object logger, Object level);
|
||||
|
||||
public void log(Object logger, Object level, String msg);
|
||||
|
||||
public void log(Object logger, Object level, String msg, Throwable t);
|
||||
|
||||
public void log(Object logger, Object level, String msg, Object... params);
|
||||
|
||||
// Methods to bridge java.util.logging.LoggingMXBean methods
|
||||
public java.util.List<String> getLoggerNames();
|
||||
|
||||
public String getLoggerLevel(String loggerName);
|
||||
|
||||
public void setLoggerLevel(String loggerName, String levelName);
|
||||
|
||||
public String getParentLoggerName(String loggerName);
|
||||
|
||||
// Methods to bridge Level.parse() and Level.getName() method
|
||||
public Object parseLevel(String levelName);
|
||||
|
||||
public String getLevelName(Object level);
|
||||
|
||||
public int getLevelValue(Object level);
|
||||
|
||||
// return the logging property
|
||||
public String getProperty(String key);
|
||||
}
|
||||
185
jdkSrc/jdk8/sun/util/logging/LoggingSupport.java
Normal file
185
jdkSrc/jdk8/sun/util/logging/LoggingSupport.java
Normal file
@@ -0,0 +1,185 @@
|
||||
/*
|
||||
* Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
|
||||
package sun.util.logging;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* Internal API to support JRE implementation to detect if the java.util.logging
|
||||
* support is available but with no dependency on the java.util.logging
|
||||
* classes. This LoggingSupport class provides several static methods to
|
||||
* access the java.util.logging functionality that requires the caller
|
||||
* to ensure that the logging support is {@linkplain #isAvailable available}
|
||||
* before invoking it.
|
||||
*
|
||||
* @see sun.util.logging.PlatformLogger if you want to log messages even
|
||||
* if the logging support is not available
|
||||
*/
|
||||
public class LoggingSupport {
|
||||
private LoggingSupport() { }
|
||||
|
||||
private static final LoggingProxy proxy =
|
||||
AccessController.doPrivileged(new PrivilegedAction<LoggingProxy>() {
|
||||
public LoggingProxy run() {
|
||||
try {
|
||||
// create a LoggingProxyImpl instance when
|
||||
// java.util.logging classes exist
|
||||
Class<?> c = Class.forName("java.util.logging.LoggingProxyImpl", true, null);
|
||||
Field f = c.getDeclaredField("INSTANCE");
|
||||
f.setAccessible(true);
|
||||
return (LoggingProxy) f.get(null);
|
||||
} catch (ClassNotFoundException cnf) {
|
||||
return null;
|
||||
} catch (NoSuchFieldException e) {
|
||||
throw new AssertionError(e);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}});
|
||||
|
||||
/**
|
||||
* Returns true if java.util.logging support is available.
|
||||
*/
|
||||
public static boolean isAvailable() {
|
||||
return proxy != null;
|
||||
}
|
||||
|
||||
private static void ensureAvailable() {
|
||||
if (proxy == null)
|
||||
throw new AssertionError("Should not here");
|
||||
}
|
||||
|
||||
public static java.util.List<String> getLoggerNames() {
|
||||
ensureAvailable();
|
||||
return proxy.getLoggerNames();
|
||||
}
|
||||
public static String getLoggerLevel(String loggerName) {
|
||||
ensureAvailable();
|
||||
return proxy.getLoggerLevel(loggerName);
|
||||
}
|
||||
|
||||
public static void setLoggerLevel(String loggerName, String levelName) {
|
||||
ensureAvailable();
|
||||
proxy.setLoggerLevel(loggerName, levelName);
|
||||
}
|
||||
|
||||
public static String getParentLoggerName(String loggerName) {
|
||||
ensureAvailable();
|
||||
return proxy.getParentLoggerName(loggerName);
|
||||
}
|
||||
|
||||
public static Object getLogger(String name) {
|
||||
ensureAvailable();
|
||||
return proxy.getLogger(name);
|
||||
}
|
||||
|
||||
public static Object getLevel(Object logger) {
|
||||
ensureAvailable();
|
||||
return proxy.getLevel(logger);
|
||||
}
|
||||
|
||||
public static void setLevel(Object logger, Object newLevel) {
|
||||
ensureAvailable();
|
||||
proxy.setLevel(logger, newLevel);
|
||||
}
|
||||
|
||||
public static boolean isLoggable(Object logger, Object level) {
|
||||
ensureAvailable();
|
||||
return proxy.isLoggable(logger,level);
|
||||
}
|
||||
|
||||
public static void log(Object logger, Object level, String msg) {
|
||||
ensureAvailable();
|
||||
proxy.log(logger, level, msg);
|
||||
}
|
||||
|
||||
public static void log(Object logger, Object level, String msg, Throwable t) {
|
||||
ensureAvailable();
|
||||
proxy.log(logger, level, msg, t);
|
||||
}
|
||||
|
||||
public static void log(Object logger, Object level, String msg, Object... params) {
|
||||
ensureAvailable();
|
||||
proxy.log(logger, level, msg, params);
|
||||
}
|
||||
|
||||
public static Object parseLevel(String levelName) {
|
||||
ensureAvailable();
|
||||
return proxy.parseLevel(levelName);
|
||||
}
|
||||
|
||||
public static String getLevelName(Object level) {
|
||||
ensureAvailable();
|
||||
return proxy.getLevelName(level);
|
||||
}
|
||||
|
||||
public static int getLevelValue(Object level) {
|
||||
ensureAvailable();
|
||||
return proxy.getLevelValue(level);
|
||||
}
|
||||
|
||||
private static final String DEFAULT_FORMAT =
|
||||
"%1$tb %1$td, %1$tY %1$tl:%1$tM:%1$tS %1$Tp %2$s%n%4$s: %5$s%6$s%n";
|
||||
|
||||
private static final String FORMAT_PROP_KEY = "java.util.logging.SimpleFormatter.format";
|
||||
public static String getSimpleFormat() {
|
||||
return getSimpleFormat(true);
|
||||
}
|
||||
|
||||
// useProxy if true will cause initialization of
|
||||
// java.util.logging and read its configuration
|
||||
static String getSimpleFormat(boolean useProxy) {
|
||||
String format =
|
||||
AccessController.doPrivileged(
|
||||
new PrivilegedAction<String>() {
|
||||
public String run() {
|
||||
return System.getProperty(FORMAT_PROP_KEY);
|
||||
}
|
||||
});
|
||||
|
||||
if (useProxy && proxy != null && format == null) {
|
||||
format = proxy.getProperty(FORMAT_PROP_KEY);
|
||||
}
|
||||
|
||||
if (format != null) {
|
||||
try {
|
||||
// validate the user-defined format string
|
||||
String.format(format, new Date(), "", "", "", "", "");
|
||||
} catch (IllegalArgumentException e) {
|
||||
// illegal syntax; fall back to the default format
|
||||
format = DEFAULT_FORMAT;
|
||||
}
|
||||
} else {
|
||||
format = DEFAULT_FORMAT;
|
||||
}
|
||||
return format;
|
||||
}
|
||||
|
||||
}
|
||||
659
jdkSrc/jdk8/sun/util/logging/PlatformLogger.java
Normal file
659
jdkSrc/jdk8/sun/util/logging/PlatformLogger.java
Normal file
@@ -0,0 +1,659 @@
|
||||
/*
|
||||
* Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
|
||||
package sun.util.logging;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.io.PrintStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import sun.misc.JavaLangAccess;
|
||||
import sun.misc.SharedSecrets;
|
||||
|
||||
/**
|
||||
* Platform logger provides an API for the JRE components to log
|
||||
* messages. This enables the runtime components to eliminate the
|
||||
* static dependency of the logging facility and also defers the
|
||||
* java.util.logging initialization until it is enabled.
|
||||
* In addition, the PlatformLogger API can be used if the logging
|
||||
* module does not exist.
|
||||
*
|
||||
* If the logging facility is not enabled, the platform loggers
|
||||
* will output log messages per the default logging configuration
|
||||
* (see below). In this implementation, it does not log the
|
||||
* the stack frame information issuing the log message.
|
||||
*
|
||||
* When the logging facility is enabled (at startup or runtime),
|
||||
* the java.util.logging.Logger will be created for each platform
|
||||
* logger and all log messages will be forwarded to the Logger
|
||||
* to handle.
|
||||
*
|
||||
* Logging facility is "enabled" when one of the following
|
||||
* conditions is met:
|
||||
* 1) a system property "java.util.logging.config.class" or
|
||||
* "java.util.logging.config.file" is set
|
||||
* 2) java.util.logging.LogManager or java.util.logging.Logger
|
||||
* is referenced that will trigger the logging initialization.
|
||||
*
|
||||
* Default logging configuration:
|
||||
* global logging level = INFO
|
||||
* handlers = java.util.logging.ConsoleHandler
|
||||
* java.util.logging.ConsoleHandler.level = INFO
|
||||
* java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
|
||||
*
|
||||
* Limitation:
|
||||
* <JAVA_HOME>/lib/logging.properties is the system-wide logging
|
||||
* configuration defined in the specification and read in the
|
||||
* default case to configure any java.util.logging.Logger instances.
|
||||
* Platform loggers will not detect if <JAVA_HOME>/lib/logging.properties
|
||||
* is modified. In other words, unless the java.util.logging API
|
||||
* is used at runtime or the logging system properties is set,
|
||||
* the platform loggers will use the default setting described above.
|
||||
* The platform loggers are designed for JDK developers use and
|
||||
* this limitation can be workaround with setting
|
||||
* -Djava.util.logging.config.file system property.
|
||||
*
|
||||
* @since 1.7
|
||||
*/
|
||||
public class PlatformLogger {
|
||||
|
||||
// The integer values must match that of {@code java.util.logging.Level}
|
||||
// objects.
|
||||
private static final int OFF = Integer.MAX_VALUE;
|
||||
private static final int SEVERE = 1000;
|
||||
private static final int WARNING = 900;
|
||||
private static final int INFO = 800;
|
||||
private static final int CONFIG = 700;
|
||||
private static final int FINE = 500;
|
||||
private static final int FINER = 400;
|
||||
private static final int FINEST = 300;
|
||||
private static final int ALL = Integer.MIN_VALUE;
|
||||
|
||||
/**
|
||||
* PlatformLogger logging levels.
|
||||
*/
|
||||
public static enum Level {
|
||||
// The name and value must match that of {@code java.util.logging.Level}s.
|
||||
// Declare in ascending order of the given value for binary search.
|
||||
ALL,
|
||||
FINEST,
|
||||
FINER,
|
||||
FINE,
|
||||
CONFIG,
|
||||
INFO,
|
||||
WARNING,
|
||||
SEVERE,
|
||||
OFF;
|
||||
|
||||
/**
|
||||
* Associated java.util.logging.Level lazily initialized in
|
||||
* JavaLoggerProxy's static initializer only once
|
||||
* when java.util.logging is available and enabled.
|
||||
* Only accessed by JavaLoggerProxy.
|
||||
*/
|
||||
/* java.util.logging.Level */ Object javaLevel;
|
||||
|
||||
// ascending order for binary search matching the list of enum constants
|
||||
private static final int[] LEVEL_VALUES = new int[] {
|
||||
PlatformLogger.ALL, PlatformLogger.FINEST, PlatformLogger.FINER,
|
||||
PlatformLogger.FINE, PlatformLogger.CONFIG, PlatformLogger.INFO,
|
||||
PlatformLogger.WARNING, PlatformLogger.SEVERE, PlatformLogger.OFF
|
||||
};
|
||||
|
||||
public int intValue() {
|
||||
return LEVEL_VALUES[this.ordinal()];
|
||||
}
|
||||
|
||||
static Level valueOf(int level) {
|
||||
switch (level) {
|
||||
// ordering per the highest occurrences in the jdk source
|
||||
// finest, fine, finer, info first
|
||||
case PlatformLogger.FINEST : return Level.FINEST;
|
||||
case PlatformLogger.FINE : return Level.FINE;
|
||||
case PlatformLogger.FINER : return Level.FINER;
|
||||
case PlatformLogger.INFO : return Level.INFO;
|
||||
case PlatformLogger.WARNING : return Level.WARNING;
|
||||
case PlatformLogger.CONFIG : return Level.CONFIG;
|
||||
case PlatformLogger.SEVERE : return Level.SEVERE;
|
||||
case PlatformLogger.OFF : return Level.OFF;
|
||||
case PlatformLogger.ALL : return Level.ALL;
|
||||
}
|
||||
// return the nearest Level value >= the given level,
|
||||
// for level > SEVERE, return SEVERE and exclude OFF
|
||||
int i = Arrays.binarySearch(LEVEL_VALUES, 0, LEVEL_VALUES.length-2, level);
|
||||
return values()[i >= 0 ? i : (-i-1)];
|
||||
}
|
||||
}
|
||||
|
||||
private static final Level DEFAULT_LEVEL = Level.INFO;
|
||||
private static boolean loggingEnabled;
|
||||
static {
|
||||
loggingEnabled = AccessController.doPrivileged(
|
||||
new PrivilegedAction<Boolean>() {
|
||||
public Boolean run() {
|
||||
String cname = System.getProperty("java.util.logging.config.class");
|
||||
String fname = System.getProperty("java.util.logging.config.file");
|
||||
return (cname != null || fname != null);
|
||||
}
|
||||
});
|
||||
|
||||
// force loading of all JavaLoggerProxy (sub)classes to make JIT de-optimizations
|
||||
// less probable. Don't initialize JavaLoggerProxy class since
|
||||
// java.util.logging may not be enabled.
|
||||
try {
|
||||
Class.forName("sun.util.logging.PlatformLogger$DefaultLoggerProxy",
|
||||
false,
|
||||
PlatformLogger.class.getClassLoader());
|
||||
Class.forName("sun.util.logging.PlatformLogger$JavaLoggerProxy",
|
||||
false, // do not invoke class initializer
|
||||
PlatformLogger.class.getClassLoader());
|
||||
} catch (ClassNotFoundException ex) {
|
||||
throw new InternalError(ex);
|
||||
}
|
||||
}
|
||||
|
||||
// Table of known loggers. Maps names to PlatformLoggers.
|
||||
private static Map<String,WeakReference<PlatformLogger>> loggers =
|
||||
new HashMap<>();
|
||||
|
||||
/**
|
||||
* Returns a PlatformLogger of a given name.
|
||||
*/
|
||||
public static synchronized PlatformLogger getLogger(String name) {
|
||||
PlatformLogger log = null;
|
||||
WeakReference<PlatformLogger> ref = loggers.get(name);
|
||||
if (ref != null) {
|
||||
log = ref.get();
|
||||
}
|
||||
if (log == null) {
|
||||
log = new PlatformLogger(name);
|
||||
loggers.put(name, new WeakReference<>(log));
|
||||
}
|
||||
return log;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize java.util.logging.Logger objects for all platform loggers.
|
||||
* This method is called from LogManager.readPrimordialConfiguration().
|
||||
*/
|
||||
public static synchronized void redirectPlatformLoggers() {
|
||||
if (loggingEnabled || !LoggingSupport.isAvailable()) return;
|
||||
|
||||
loggingEnabled = true;
|
||||
for (Map.Entry<String, WeakReference<PlatformLogger>> entry : loggers.entrySet()) {
|
||||
WeakReference<PlatformLogger> ref = entry.getValue();
|
||||
PlatformLogger plog = ref.get();
|
||||
if (plog != null) {
|
||||
plog.redirectToJavaLoggerProxy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new JavaLoggerProxy and redirects the platform logger to it
|
||||
*/
|
||||
private void redirectToJavaLoggerProxy() {
|
||||
DefaultLoggerProxy lp = DefaultLoggerProxy.class.cast(this.loggerProxy);
|
||||
JavaLoggerProxy jlp = new JavaLoggerProxy(lp.name, lp.level);
|
||||
// the order of assignments is important
|
||||
this.javaLoggerProxy = jlp; // isLoggable checks javaLoggerProxy if set
|
||||
this.loggerProxy = jlp;
|
||||
}
|
||||
|
||||
// DefaultLoggerProxy may be replaced with a JavaLoggerProxy object
|
||||
// when the java.util.logging facility is enabled
|
||||
private volatile LoggerProxy loggerProxy;
|
||||
// javaLoggerProxy is only set when the java.util.logging facility is enabled
|
||||
private volatile JavaLoggerProxy javaLoggerProxy;
|
||||
private PlatformLogger(String name) {
|
||||
if (loggingEnabled) {
|
||||
this.loggerProxy = this.javaLoggerProxy = new JavaLoggerProxy(name);
|
||||
} else {
|
||||
this.loggerProxy = new DefaultLoggerProxy(name);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A convenience method to test if the logger is turned off.
|
||||
* (i.e. its level is OFF).
|
||||
*/
|
||||
public boolean isEnabled() {
|
||||
return loggerProxy.isEnabled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name for this platform logger.
|
||||
*/
|
||||
public String getName() {
|
||||
return loggerProxy.name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if a message of the given level would actually
|
||||
* be logged by this logger.
|
||||
*/
|
||||
public boolean isLoggable(Level level) {
|
||||
if (level == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
// performance-sensitive method: use two monomorphic call-sites
|
||||
JavaLoggerProxy jlp = javaLoggerProxy;
|
||||
return jlp != null ? jlp.isLoggable(level) : loggerProxy.isLoggable(level);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the log level that has been specified for this PlatformLogger.
|
||||
* The result may be null, which means that this logger's
|
||||
* effective level will be inherited from its parent.
|
||||
*
|
||||
* @return this PlatformLogger's level
|
||||
*/
|
||||
public Level level() {
|
||||
return loggerProxy.getLevel();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the log level specifying which message levels will be
|
||||
* logged by this logger. Message levels lower than this
|
||||
* value will be discarded. The level value {@link #OFF}
|
||||
* can be used to turn off logging.
|
||||
* <p>
|
||||
* If the new level is null, it means that this node should
|
||||
* inherit its level from its nearest ancestor with a specific
|
||||
* (non-null) level value.
|
||||
*
|
||||
* @param newLevel the new value for the log level (may be null)
|
||||
*/
|
||||
public void setLevel(Level newLevel) {
|
||||
loggerProxy.setLevel(newLevel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a SEVERE message.
|
||||
*/
|
||||
public void severe(String msg) {
|
||||
loggerProxy.doLog(Level.SEVERE, msg);
|
||||
}
|
||||
|
||||
public void severe(String msg, Throwable t) {
|
||||
loggerProxy.doLog(Level.SEVERE, msg, t);
|
||||
}
|
||||
|
||||
public void severe(String msg, Object... params) {
|
||||
loggerProxy.doLog(Level.SEVERE, msg, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a WARNING message.
|
||||
*/
|
||||
public void warning(String msg) {
|
||||
loggerProxy.doLog(Level.WARNING, msg);
|
||||
}
|
||||
|
||||
public void warning(String msg, Throwable t) {
|
||||
loggerProxy.doLog(Level.WARNING, msg, t);
|
||||
}
|
||||
|
||||
public void warning(String msg, Object... params) {
|
||||
loggerProxy.doLog(Level.WARNING, msg, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs an INFO message.
|
||||
*/
|
||||
public void info(String msg) {
|
||||
loggerProxy.doLog(Level.INFO, msg);
|
||||
}
|
||||
|
||||
public void info(String msg, Throwable t) {
|
||||
loggerProxy.doLog(Level.INFO, msg, t);
|
||||
}
|
||||
|
||||
public void info(String msg, Object... params) {
|
||||
loggerProxy.doLog(Level.INFO, msg, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a CONFIG message.
|
||||
*/
|
||||
public void config(String msg) {
|
||||
loggerProxy.doLog(Level.CONFIG, msg);
|
||||
}
|
||||
|
||||
public void config(String msg, Throwable t) {
|
||||
loggerProxy.doLog(Level.CONFIG, msg, t);
|
||||
}
|
||||
|
||||
public void config(String msg, Object... params) {
|
||||
loggerProxy.doLog(Level.CONFIG, msg, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a FINE message.
|
||||
*/
|
||||
public void fine(String msg) {
|
||||
loggerProxy.doLog(Level.FINE, msg);
|
||||
}
|
||||
|
||||
public void fine(String msg, Throwable t) {
|
||||
loggerProxy.doLog(Level.FINE, msg, t);
|
||||
}
|
||||
|
||||
public void fine(String msg, Object... params) {
|
||||
loggerProxy.doLog(Level.FINE, msg, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a FINER message.
|
||||
*/
|
||||
public void finer(String msg) {
|
||||
loggerProxy.doLog(Level.FINER, msg);
|
||||
}
|
||||
|
||||
public void finer(String msg, Throwable t) {
|
||||
loggerProxy.doLog(Level.FINER, msg, t);
|
||||
}
|
||||
|
||||
public void finer(String msg, Object... params) {
|
||||
loggerProxy.doLog(Level.FINER, msg, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a FINEST message.
|
||||
*/
|
||||
public void finest(String msg) {
|
||||
loggerProxy.doLog(Level.FINEST, msg);
|
||||
}
|
||||
|
||||
public void finest(String msg, Throwable t) {
|
||||
loggerProxy.doLog(Level.FINEST, msg, t);
|
||||
}
|
||||
|
||||
public void finest(String msg, Object... params) {
|
||||
loggerProxy.doLog(Level.FINEST, msg, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Abstract base class for logging support, defining the API and common field.
|
||||
*/
|
||||
private static abstract class LoggerProxy {
|
||||
final String name;
|
||||
|
||||
protected LoggerProxy(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
abstract boolean isEnabled();
|
||||
|
||||
abstract Level getLevel();
|
||||
abstract void setLevel(Level newLevel);
|
||||
|
||||
abstract void doLog(Level level, String msg);
|
||||
abstract void doLog(Level level, String msg, Throwable thrown);
|
||||
abstract void doLog(Level level, String msg, Object... params);
|
||||
|
||||
abstract boolean isLoggable(Level level);
|
||||
}
|
||||
|
||||
|
||||
private static final class DefaultLoggerProxy extends LoggerProxy {
|
||||
/**
|
||||
* Default platform logging support - output messages to System.err -
|
||||
* equivalent to ConsoleHandler with SimpleFormatter.
|
||||
*/
|
||||
private static PrintStream outputStream() {
|
||||
return System.err;
|
||||
}
|
||||
|
||||
volatile Level effectiveLevel; // effective level (never null)
|
||||
volatile Level level; // current level set for this node (may be null)
|
||||
|
||||
DefaultLoggerProxy(String name) {
|
||||
super(name);
|
||||
this.effectiveLevel = deriveEffectiveLevel(null);
|
||||
this.level = null;
|
||||
}
|
||||
|
||||
boolean isEnabled() {
|
||||
return effectiveLevel != Level.OFF;
|
||||
}
|
||||
|
||||
Level getLevel() {
|
||||
return level;
|
||||
}
|
||||
|
||||
void setLevel(Level newLevel) {
|
||||
Level oldLevel = level;
|
||||
if (oldLevel != newLevel) {
|
||||
level = newLevel;
|
||||
effectiveLevel = deriveEffectiveLevel(newLevel);
|
||||
}
|
||||
}
|
||||
|
||||
void doLog(Level level, String msg) {
|
||||
if (isLoggable(level)) {
|
||||
outputStream().print(format(level, msg, null));
|
||||
}
|
||||
}
|
||||
|
||||
void doLog(Level level, String msg, Throwable thrown) {
|
||||
if (isLoggable(level)) {
|
||||
outputStream().print(format(level, msg, thrown));
|
||||
}
|
||||
}
|
||||
|
||||
void doLog(Level level, String msg, Object... params) {
|
||||
if (isLoggable(level)) {
|
||||
String newMsg = formatMessage(msg, params);
|
||||
outputStream().print(format(level, newMsg, null));
|
||||
}
|
||||
}
|
||||
|
||||
boolean isLoggable(Level level) {
|
||||
Level effectiveLevel = this.effectiveLevel;
|
||||
return level.intValue() >= effectiveLevel.intValue() && effectiveLevel != Level.OFF;
|
||||
}
|
||||
|
||||
// derive effective level (could do inheritance search like j.u.l.Logger)
|
||||
private Level deriveEffectiveLevel(Level level) {
|
||||
return level == null ? DEFAULT_LEVEL : level;
|
||||
}
|
||||
|
||||
// Copied from java.util.logging.Formatter.formatMessage
|
||||
private String formatMessage(String format, Object... parameters) {
|
||||
// Do the formatting.
|
||||
try {
|
||||
if (parameters == null || parameters.length == 0) {
|
||||
// No parameters. Just return format string.
|
||||
return format;
|
||||
}
|
||||
// Is it a java.text style format?
|
||||
// Ideally we could match with
|
||||
// Pattern.compile("\\{\\d").matcher(format).find())
|
||||
// However the cost is 14% higher, so we cheaply check for
|
||||
// 1 of the first 4 parameters
|
||||
if (format.indexOf("{0") >= 0 || format.indexOf("{1") >=0 ||
|
||||
format.indexOf("{2") >=0|| format.indexOf("{3") >=0) {
|
||||
return java.text.MessageFormat.format(format, parameters);
|
||||
}
|
||||
return format;
|
||||
} catch (Exception ex) {
|
||||
// Formatting failed: use format string.
|
||||
return format;
|
||||
}
|
||||
}
|
||||
|
||||
private static final String formatString =
|
||||
LoggingSupport.getSimpleFormat(false); // don't check logging.properties
|
||||
|
||||
// minimize memory allocation
|
||||
private Date date = new Date();
|
||||
private synchronized String format(Level level, String msg, Throwable thrown) {
|
||||
date.setTime(System.currentTimeMillis());
|
||||
String throwable = "";
|
||||
if (thrown != null) {
|
||||
StringWriter sw = new StringWriter();
|
||||
PrintWriter pw = new PrintWriter(sw);
|
||||
pw.println();
|
||||
thrown.printStackTrace(pw);
|
||||
pw.close();
|
||||
throwable = sw.toString();
|
||||
}
|
||||
|
||||
return String.format(formatString,
|
||||
date,
|
||||
getCallerInfo(),
|
||||
name,
|
||||
level.name(),
|
||||
msg,
|
||||
throwable);
|
||||
}
|
||||
|
||||
// Returns the caller's class and method's name; best effort
|
||||
// if cannot infer, return the logger's name.
|
||||
private String getCallerInfo() {
|
||||
String sourceClassName = null;
|
||||
String sourceMethodName = null;
|
||||
|
||||
JavaLangAccess access = SharedSecrets.getJavaLangAccess();
|
||||
Throwable throwable = new Throwable();
|
||||
int depth = access.getStackTraceDepth(throwable);
|
||||
|
||||
String logClassName = "sun.util.logging.PlatformLogger";
|
||||
boolean lookingForLogger = true;
|
||||
for (int ix = 0; ix < depth; ix++) {
|
||||
// Calling getStackTraceElement directly prevents the VM
|
||||
// from paying the cost of building the entire stack frame.
|
||||
StackTraceElement frame =
|
||||
access.getStackTraceElement(throwable, ix);
|
||||
String cname = frame.getClassName();
|
||||
if (lookingForLogger) {
|
||||
// Skip all frames until we have found the first logger frame.
|
||||
if (cname.equals(logClassName)) {
|
||||
lookingForLogger = false;
|
||||
}
|
||||
} else {
|
||||
if (!cname.equals(logClassName)) {
|
||||
// We've found the relevant frame.
|
||||
sourceClassName = cname;
|
||||
sourceMethodName = frame.getMethodName();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (sourceClassName != null) {
|
||||
return sourceClassName + " " + sourceMethodName;
|
||||
} else {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* JavaLoggerProxy forwards all the calls to its corresponding
|
||||
* java.util.logging.Logger object.
|
||||
*/
|
||||
private static final class JavaLoggerProxy extends LoggerProxy {
|
||||
// initialize javaLevel fields for mapping from Level enum -> j.u.l.Level object
|
||||
static {
|
||||
for (Level level : Level.values()) {
|
||||
level.javaLevel = LoggingSupport.parseLevel(level.name());
|
||||
}
|
||||
}
|
||||
|
||||
private final /* java.util.logging.Logger */ Object javaLogger;
|
||||
|
||||
JavaLoggerProxy(String name) {
|
||||
this(name, null);
|
||||
}
|
||||
|
||||
JavaLoggerProxy(String name, Level level) {
|
||||
super(name);
|
||||
this.javaLogger = LoggingSupport.getLogger(name);
|
||||
if (level != null) {
|
||||
// level has been updated and so set the Logger's level
|
||||
LoggingSupport.setLevel(javaLogger, level.javaLevel);
|
||||
}
|
||||
}
|
||||
|
||||
void doLog(Level level, String msg) {
|
||||
LoggingSupport.log(javaLogger, level.javaLevel, msg);
|
||||
}
|
||||
|
||||
void doLog(Level level, String msg, Throwable t) {
|
||||
LoggingSupport.log(javaLogger, level.javaLevel, msg, t);
|
||||
}
|
||||
|
||||
void doLog(Level level, String msg, Object... params) {
|
||||
if (!isLoggable(level)) {
|
||||
return;
|
||||
}
|
||||
// only pass String objects to the j.u.l.Logger which may
|
||||
// be created by untrusted code
|
||||
int len = (params != null) ? params.length : 0;
|
||||
Object[] sparams = new String[len];
|
||||
for (int i = 0; i < len; i++) {
|
||||
sparams [i] = String.valueOf(params[i]);
|
||||
}
|
||||
LoggingSupport.log(javaLogger, level.javaLevel, msg, sparams);
|
||||
}
|
||||
|
||||
boolean isEnabled() {
|
||||
return LoggingSupport.isLoggable(javaLogger, Level.OFF.javaLevel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the PlatformLogger.Level mapped from j.u.l.Level
|
||||
* set in the logger. If the j.u.l.Logger is set to a custom Level,
|
||||
* this method will return the nearest Level.
|
||||
*/
|
||||
Level getLevel() {
|
||||
Object javaLevel = LoggingSupport.getLevel(javaLogger);
|
||||
if (javaLevel == null) return null;
|
||||
|
||||
try {
|
||||
return Level.valueOf(LoggingSupport.getLevelName(javaLevel));
|
||||
} catch (IllegalArgumentException e) {
|
||||
return Level.valueOf(LoggingSupport.getLevelValue(javaLevel));
|
||||
}
|
||||
}
|
||||
|
||||
void setLevel(Level level) {
|
||||
LoggingSupport.setLevel(javaLogger, level == null ? null : level.javaLevel);
|
||||
}
|
||||
|
||||
boolean isLoggable(Level level) {
|
||||
return LoggingSupport.isLoggable(javaLogger, level.javaLevel);
|
||||
}
|
||||
}
|
||||
}
|
||||
19
jdkSrc/jdk8/sun/util/logging/resources/logging.java
Normal file
19
jdkSrc/jdk8/sun/util/logging/resources/logging.java
Normal file
@@ -0,0 +1,19 @@
|
||||
package sun.util.logging.resources;
|
||||
|
||||
import java.util.ListResourceBundle;
|
||||
|
||||
public final class logging extends ListResourceBundle {
|
||||
protected final Object[][] getContents() {
|
||||
return new Object[][] {
|
||||
{ "ALL", "All" },
|
||||
{ "CONFIG", "Config" },
|
||||
{ "FINE", "Fine" },
|
||||
{ "FINER", "Finer" },
|
||||
{ "FINEST", "Finest" },
|
||||
{ "INFO", "Info" },
|
||||
{ "OFF", "Off" },
|
||||
{ "SEVERE", "Severe" },
|
||||
{ "WARNING", "Warning" },
|
||||
};
|
||||
}
|
||||
}
|
||||
19
jdkSrc/jdk8/sun/util/logging/resources/logging_de.java
Normal file
19
jdkSrc/jdk8/sun/util/logging/resources/logging_de.java
Normal file
@@ -0,0 +1,19 @@
|
||||
package sun.util.logging.resources;
|
||||
|
||||
import java.util.ListResourceBundle;
|
||||
|
||||
public final class logging_de extends ListResourceBundle {
|
||||
protected final Object[][] getContents() {
|
||||
return new Object[][] {
|
||||
{ "ALL", "Alle" },
|
||||
{ "CONFIG", "Konfiguration" },
|
||||
{ "FINE", "Fein" },
|
||||
{ "FINER", "Feiner" },
|
||||
{ "FINEST", "Am feinsten" },
|
||||
{ "INFO", "Information" },
|
||||
{ "OFF", "Deaktiviert" },
|
||||
{ "SEVERE", "Schwerwiegend" },
|
||||
{ "WARNING", "Warnung" },
|
||||
};
|
||||
}
|
||||
}
|
||||
19
jdkSrc/jdk8/sun/util/logging/resources/logging_es.java
Normal file
19
jdkSrc/jdk8/sun/util/logging/resources/logging_es.java
Normal file
@@ -0,0 +1,19 @@
|
||||
package sun.util.logging.resources;
|
||||
|
||||
import java.util.ListResourceBundle;
|
||||
|
||||
public final class logging_es extends ListResourceBundle {
|
||||
protected final Object[][] getContents() {
|
||||
return new Object[][] {
|
||||
{ "ALL", "Todo" },
|
||||
{ "CONFIG", "Configurar" },
|
||||
{ "FINE", "Detallado" },
|
||||
{ "FINER", "Muy Detallado" },
|
||||
{ "FINEST", "M\u00E1s Detallado" },
|
||||
{ "INFO", "Informaci\u00F3n" },
|
||||
{ "OFF", "Desactivado" },
|
||||
{ "SEVERE", "Grave" },
|
||||
{ "WARNING", "Advertencia" },
|
||||
};
|
||||
}
|
||||
}
|
||||
19
jdkSrc/jdk8/sun/util/logging/resources/logging_fr.java
Normal file
19
jdkSrc/jdk8/sun/util/logging/resources/logging_fr.java
Normal file
@@ -0,0 +1,19 @@
|
||||
package sun.util.logging.resources;
|
||||
|
||||
import java.util.ListResourceBundle;
|
||||
|
||||
public final class logging_fr extends ListResourceBundle {
|
||||
protected final Object[][] getContents() {
|
||||
return new Object[][] {
|
||||
{ "ALL", "Tout" },
|
||||
{ "CONFIG", "Config" },
|
||||
{ "FINE", "Pr\u00E9cis" },
|
||||
{ "FINER", "Plus pr\u00E9cis" },
|
||||
{ "FINEST", "Le plus pr\u00E9cis" },
|
||||
{ "INFO", "Infos" },
|
||||
{ "OFF", "D\u00E9sactiv\u00E9" },
|
||||
{ "SEVERE", "Grave" },
|
||||
{ "WARNING", "Avertissement" },
|
||||
};
|
||||
}
|
||||
}
|
||||
19
jdkSrc/jdk8/sun/util/logging/resources/logging_it.java
Normal file
19
jdkSrc/jdk8/sun/util/logging/resources/logging_it.java
Normal file
@@ -0,0 +1,19 @@
|
||||
package sun.util.logging.resources;
|
||||
|
||||
import java.util.ListResourceBundle;
|
||||
|
||||
public final class logging_it extends ListResourceBundle {
|
||||
protected final Object[][] getContents() {
|
||||
return new Object[][] {
|
||||
{ "ALL", "Tutto" },
|
||||
{ "CONFIG", "Configurazione" },
|
||||
{ "FINE", "Buono" },
|
||||
{ "FINER", "Migliore" },
|
||||
{ "FINEST", "Ottimale" },
|
||||
{ "INFO", "Informazioni" },
|
||||
{ "OFF", "Non attivo" },
|
||||
{ "SEVERE", "Grave" },
|
||||
{ "WARNING", "Avvertenza" },
|
||||
};
|
||||
}
|
||||
}
|
||||
19
jdkSrc/jdk8/sun/util/logging/resources/logging_ja.java
Normal file
19
jdkSrc/jdk8/sun/util/logging/resources/logging_ja.java
Normal file
@@ -0,0 +1,19 @@
|
||||
package sun.util.logging.resources;
|
||||
|
||||
import java.util.ListResourceBundle;
|
||||
|
||||
public final class logging_ja extends ListResourceBundle {
|
||||
protected final Object[][] getContents() {
|
||||
return new Object[][] {
|
||||
{ "ALL", "\u3059\u3079\u3066" },
|
||||
{ "CONFIG", "\u69CB\u6210" },
|
||||
{ "FINE", "\u666E\u901A" },
|
||||
{ "FINER", "\u8A73\u7D30" },
|
||||
{ "FINEST", "\u6700\u3082\u8A73\u7D30" },
|
||||
{ "INFO", "\u60C5\u5831" },
|
||||
{ "OFF", "\u30AA\u30D5" },
|
||||
{ "SEVERE", "\u91CD\u5927" },
|
||||
{ "WARNING", "\u8B66\u544A" },
|
||||
};
|
||||
}
|
||||
}
|
||||
19
jdkSrc/jdk8/sun/util/logging/resources/logging_ko.java
Normal file
19
jdkSrc/jdk8/sun/util/logging/resources/logging_ko.java
Normal file
@@ -0,0 +1,19 @@
|
||||
package sun.util.logging.resources;
|
||||
|
||||
import java.util.ListResourceBundle;
|
||||
|
||||
public final class logging_ko extends ListResourceBundle {
|
||||
protected final Object[][] getContents() {
|
||||
return new Object[][] {
|
||||
{ "ALL", "\uBAA8\uB450" },
|
||||
{ "CONFIG", "\uAD6C\uC131" },
|
||||
{ "FINE", "\uBBF8\uC138" },
|
||||
{ "FINER", "\uBCF4\uB2E4 \uBBF8\uC138" },
|
||||
{ "FINEST", "\uAC00\uC7A5 \uBBF8\uC138" },
|
||||
{ "INFO", "\uC815\uBCF4" },
|
||||
{ "OFF", "\uD574\uC81C" },
|
||||
{ "SEVERE", "\uC2EC\uAC01" },
|
||||
{ "WARNING", "\uACBD\uACE0" },
|
||||
};
|
||||
}
|
||||
}
|
||||
19
jdkSrc/jdk8/sun/util/logging/resources/logging_pt_BR.java
Normal file
19
jdkSrc/jdk8/sun/util/logging/resources/logging_pt_BR.java
Normal file
@@ -0,0 +1,19 @@
|
||||
package sun.util.logging.resources;
|
||||
|
||||
import java.util.ListResourceBundle;
|
||||
|
||||
public final class logging_pt_BR extends ListResourceBundle {
|
||||
protected final Object[][] getContents() {
|
||||
return new Object[][] {
|
||||
{ "ALL", "Tudo" },
|
||||
{ "CONFIG", "Configura\u00E7\u00E3o" },
|
||||
{ "FINE", "Detalhado" },
|
||||
{ "FINER", "Mais Detalhado" },
|
||||
{ "FINEST", "O Mais Detalhado" },
|
||||
{ "INFO", "Informa\u00E7\u00F5es" },
|
||||
{ "OFF", "Desativado" },
|
||||
{ "SEVERE", "Grave" },
|
||||
{ "WARNING", "Advert\u00EAncia" },
|
||||
};
|
||||
}
|
||||
}
|
||||
19
jdkSrc/jdk8/sun/util/logging/resources/logging_sv.java
Normal file
19
jdkSrc/jdk8/sun/util/logging/resources/logging_sv.java
Normal file
@@ -0,0 +1,19 @@
|
||||
package sun.util.logging.resources;
|
||||
|
||||
import java.util.ListResourceBundle;
|
||||
|
||||
public final class logging_sv extends ListResourceBundle {
|
||||
protected final Object[][] getContents() {
|
||||
return new Object[][] {
|
||||
{ "ALL", "Alla" },
|
||||
{ "CONFIG", "Konfig" },
|
||||
{ "FINE", "Fin" },
|
||||
{ "FINER", "Finare" },
|
||||
{ "FINEST", "Finaste" },
|
||||
{ "INFO", "Info" },
|
||||
{ "OFF", "Av" },
|
||||
{ "SEVERE", "Allvarlig" },
|
||||
{ "WARNING", "Varning" },
|
||||
};
|
||||
}
|
||||
}
|
||||
19
jdkSrc/jdk8/sun/util/logging/resources/logging_zh_CN.java
Normal file
19
jdkSrc/jdk8/sun/util/logging/resources/logging_zh_CN.java
Normal file
@@ -0,0 +1,19 @@
|
||||
package sun.util.logging.resources;
|
||||
|
||||
import java.util.ListResourceBundle;
|
||||
|
||||
public final class logging_zh_CN extends ListResourceBundle {
|
||||
protected final Object[][] getContents() {
|
||||
return new Object[][] {
|
||||
{ "ALL", "\u5168\u90E8" },
|
||||
{ "CONFIG", "\u914D\u7F6E" },
|
||||
{ "FINE", "\u8BE6\u7EC6" },
|
||||
{ "FINER", "\u8F83\u8BE6\u7EC6" },
|
||||
{ "FINEST", "\u975E\u5E38\u8BE6\u7EC6" },
|
||||
{ "INFO", "\u4FE1\u606F" },
|
||||
{ "OFF", "\u7981\u7528" },
|
||||
{ "SEVERE", "\u4E25\u91CD" },
|
||||
{ "WARNING", "\u8B66\u544A" },
|
||||
};
|
||||
}
|
||||
}
|
||||
19
jdkSrc/jdk8/sun/util/logging/resources/logging_zh_HK.java
Normal file
19
jdkSrc/jdk8/sun/util/logging/resources/logging_zh_HK.java
Normal file
@@ -0,0 +1,19 @@
|
||||
package sun.util.logging.resources;
|
||||
|
||||
import java.util.ListResourceBundle;
|
||||
|
||||
public final class logging_zh_HK extends ListResourceBundle {
|
||||
protected final Object[][] getContents() {
|
||||
return new Object[][] {
|
||||
{ "ALL", "\u6240\u6709" },
|
||||
{ "CONFIG", "\u7D44\u614B" },
|
||||
{ "FINE", "\u8A73\u7D30" },
|
||||
{ "FINER", "\u8F03\u8A73\u7D30" },
|
||||
{ "FINEST", "\u6700\u8A73\u7D30" },
|
||||
{ "INFO", "\u8CC7\u8A0A" },
|
||||
{ "OFF", "\u95DC\u9589" },
|
||||
{ "SEVERE", "\u56B4\u91CD" },
|
||||
{ "WARNING", "\u8B66\u544A" },
|
||||
};
|
||||
}
|
||||
}
|
||||
19
jdkSrc/jdk8/sun/util/logging/resources/logging_zh_TW.java
Normal file
19
jdkSrc/jdk8/sun/util/logging/resources/logging_zh_TW.java
Normal file
@@ -0,0 +1,19 @@
|
||||
package sun.util.logging.resources;
|
||||
|
||||
import java.util.ListResourceBundle;
|
||||
|
||||
public final class logging_zh_TW extends ListResourceBundle {
|
||||
protected final Object[][] getContents() {
|
||||
return new Object[][] {
|
||||
{ "ALL", "\u6240\u6709" },
|
||||
{ "CONFIG", "\u7D44\u614B" },
|
||||
{ "FINE", "\u8A73\u7D30" },
|
||||
{ "FINER", "\u8F03\u8A73\u7D30" },
|
||||
{ "FINEST", "\u6700\u8A73\u7D30" },
|
||||
{ "INFO", "\u8CC7\u8A0A" },
|
||||
{ "OFF", "\u95DC\u9589" },
|
||||
{ "SEVERE", "\u56B4\u91CD" },
|
||||
{ "WARNING", "\u8B66\u544A" },
|
||||
};
|
||||
}
|
||||
}
|
||||
12
jdkSrc/jdk8/sun/util/resources/CalendarData.java
Normal file
12
jdkSrc/jdk8/sun/util/resources/CalendarData.java
Normal file
@@ -0,0 +1,12 @@
|
||||
package sun.util.resources;
|
||||
|
||||
import java.util.ListResourceBundle;
|
||||
|
||||
public final class CalendarData extends sun.util.resources.LocaleNamesBundle {
|
||||
protected final Object[][] getContents() {
|
||||
return new Object[][] {
|
||||
{ "firstDayOfWeek", "1" },
|
||||
{ "minimalDaysInFirstWeek", "1" },
|
||||
};
|
||||
}
|
||||
}
|
||||
465
jdkSrc/jdk8/sun/util/resources/CurrencyNames.java
Normal file
465
jdkSrc/jdk8/sun/util/resources/CurrencyNames.java
Normal file
@@ -0,0 +1,465 @@
|
||||
package sun.util.resources;
|
||||
|
||||
import java.util.ListResourceBundle;
|
||||
|
||||
public final class CurrencyNames extends sun.util.resources.LocaleNamesBundle {
|
||||
protected final Object[][] getContents() {
|
||||
return new Object[][] {
|
||||
{ "ADP", "ADP" },
|
||||
{ "AED", "AED" },
|
||||
{ "AFA", "AFA" },
|
||||
{ "AFN", "AFN" },
|
||||
{ "ALL", "ALL" },
|
||||
{ "AMD", "AMD" },
|
||||
{ "ANG", "ANG" },
|
||||
{ "AOA", "AOA" },
|
||||
{ "ARS", "ARS" },
|
||||
{ "ATS", "ATS" },
|
||||
{ "AUD", "AUD" },
|
||||
{ "AWG", "AWG" },
|
||||
{ "AYM", "AYM" },
|
||||
{ "AZM", "AZM" },
|
||||
{ "AZN", "AZN" },
|
||||
{ "BAM", "BAM" },
|
||||
{ "BBD", "BBD" },
|
||||
{ "BDT", "BDT" },
|
||||
{ "BEF", "BEF" },
|
||||
{ "BGL", "BGL" },
|
||||
{ "BGN", "BGN" },
|
||||
{ "BHD", "BHD" },
|
||||
{ "BIF", "BIF" },
|
||||
{ "BMD", "BMD" },
|
||||
{ "BND", "BND" },
|
||||
{ "BOB", "BOB" },
|
||||
{ "BOV", "BOV" },
|
||||
{ "BRL", "BRL" },
|
||||
{ "BSD", "BSD" },
|
||||
{ "BTN", "BTN" },
|
||||
{ "BWP", "BWP" },
|
||||
{ "BYB", "BYB" },
|
||||
{ "BYN", "BYN" },
|
||||
{ "BYR", "BYR" },
|
||||
{ "BZD", "BZD" },
|
||||
{ "CAD", "CAD" },
|
||||
{ "CDF", "CDF" },
|
||||
{ "CHF", "CHF" },
|
||||
{ "CLF", "CLF" },
|
||||
{ "CLP", "CLP" },
|
||||
{ "CNY", "CNY" },
|
||||
{ "COP", "COP" },
|
||||
{ "CRC", "CRC" },
|
||||
{ "CSD", "CSD" },
|
||||
{ "CUC", "CUC" },
|
||||
{ "CUP", "CUP" },
|
||||
{ "CVE", "CVE" },
|
||||
{ "CYP", "CYP" },
|
||||
{ "CZK", "CZK" },
|
||||
{ "DEM", "DEM" },
|
||||
{ "DJF", "DJF" },
|
||||
{ "DKK", "DKK" },
|
||||
{ "DOP", "DOP" },
|
||||
{ "DZD", "DZD" },
|
||||
{ "EEK", "EEK" },
|
||||
{ "EGP", "EGP" },
|
||||
{ "ERN", "ERN" },
|
||||
{ "ESP", "ESP" },
|
||||
{ "ETB", "ETB" },
|
||||
{ "EUR", "EUR" },
|
||||
{ "FIM", "FIM" },
|
||||
{ "FJD", "FJD" },
|
||||
{ "FKP", "FKP" },
|
||||
{ "FRF", "FRF" },
|
||||
{ "GBP", "GBP" },
|
||||
{ "GEL", "GEL" },
|
||||
{ "GHC", "GHC" },
|
||||
{ "GHS", "GHS" },
|
||||
{ "GIP", "GIP" },
|
||||
{ "GMD", "GMD" },
|
||||
{ "GNF", "GNF" },
|
||||
{ "GRD", "GRD" },
|
||||
{ "GTQ", "GTQ" },
|
||||
{ "GWP", "GWP" },
|
||||
{ "GYD", "GYD" },
|
||||
{ "HKD", "HKD" },
|
||||
{ "HNL", "HNL" },
|
||||
{ "HRK", "HRK" },
|
||||
{ "HTG", "HTG" },
|
||||
{ "HUF", "HUF" },
|
||||
{ "IDR", "IDR" },
|
||||
{ "IEP", "IEP" },
|
||||
{ "ILS", "ILS" },
|
||||
{ "INR", "INR" },
|
||||
{ "IQD", "IQD" },
|
||||
{ "IRR", "IRR" },
|
||||
{ "ISK", "ISK" },
|
||||
{ "ITL", "ITL" },
|
||||
{ "JMD", "JMD" },
|
||||
{ "JOD", "JOD" },
|
||||
{ "JPY", "JPY" },
|
||||
{ "KES", "KES" },
|
||||
{ "KGS", "KGS" },
|
||||
{ "KHR", "KHR" },
|
||||
{ "KMF", "KMF" },
|
||||
{ "KPW", "KPW" },
|
||||
{ "KRW", "KRW" },
|
||||
{ "KWD", "KWD" },
|
||||
{ "KYD", "KYD" },
|
||||
{ "KZT", "KZT" },
|
||||
{ "LAK", "LAK" },
|
||||
{ "LBP", "LBP" },
|
||||
{ "LKR", "LKR" },
|
||||
{ "LRD", "LRD" },
|
||||
{ "LSL", "LSL" },
|
||||
{ "LTL", "LTL" },
|
||||
{ "LUF", "LUF" },
|
||||
{ "LVL", "LVL" },
|
||||
{ "LYD", "LYD" },
|
||||
{ "MAD", "MAD" },
|
||||
{ "MDL", "MDL" },
|
||||
{ "MGA", "MGA" },
|
||||
{ "MGF", "MGF" },
|
||||
{ "MKD", "MKD" },
|
||||
{ "MMK", "MMK" },
|
||||
{ "MNT", "MNT" },
|
||||
{ "MOP", "MOP" },
|
||||
{ "MRO", "MRO" },
|
||||
{ "MRU", "MRU" },
|
||||
{ "MTL", "MTL" },
|
||||
{ "MUR", "MUR" },
|
||||
{ "MVR", "MVR" },
|
||||
{ "MWK", "MWK" },
|
||||
{ "MXN", "MXN" },
|
||||
{ "MXV", "MXV" },
|
||||
{ "MYR", "MYR" },
|
||||
{ "MZM", "MZM" },
|
||||
{ "MZN", "MZN" },
|
||||
{ "NAD", "NAD" },
|
||||
{ "NGN", "NGN" },
|
||||
{ "NIO", "NIO" },
|
||||
{ "NLG", "NLG" },
|
||||
{ "NOK", "NOK" },
|
||||
{ "NPR", "NPR" },
|
||||
{ "NZD", "NZD" },
|
||||
{ "OMR", "OMR" },
|
||||
{ "PAB", "PAB" },
|
||||
{ "PEN", "PEN" },
|
||||
{ "PGK", "PGK" },
|
||||
{ "PHP", "PHP" },
|
||||
{ "PKR", "PKR" },
|
||||
{ "PLN", "PLN" },
|
||||
{ "PTE", "PTE" },
|
||||
{ "PYG", "PYG" },
|
||||
{ "QAR", "QAR" },
|
||||
{ "ROL", "ROL" },
|
||||
{ "RON", "RON" },
|
||||
{ "RSD", "RSD" },
|
||||
{ "RUB", "RUB" },
|
||||
{ "RUR", "RUR" },
|
||||
{ "RWF", "RWF" },
|
||||
{ "SAR", "SAR" },
|
||||
{ "SBD", "SBD" },
|
||||
{ "SCR", "SCR" },
|
||||
{ "SDD", "SDD" },
|
||||
{ "SDG", "SDG" },
|
||||
{ "SEK", "SEK" },
|
||||
{ "SGD", "SGD" },
|
||||
{ "SHP", "SHP" },
|
||||
{ "SIT", "SIT" },
|
||||
{ "SKK", "SKK" },
|
||||
{ "SLE", "SLE" },
|
||||
{ "SLL", "SLL" },
|
||||
{ "SOS", "SOS" },
|
||||
{ "SRD", "SRD" },
|
||||
{ "SRG", "SRG" },
|
||||
{ "SSP", "SSP" },
|
||||
{ "STD", "STD" },
|
||||
{ "STN", "STN" },
|
||||
{ "SVC", "SVC" },
|
||||
{ "SYP", "SYP" },
|
||||
{ "SZL", "SZL" },
|
||||
{ "THB", "THB" },
|
||||
{ "TJS", "TJS" },
|
||||
{ "TMM", "TMM" },
|
||||
{ "TMT", "TMT" },
|
||||
{ "TND", "TND" },
|
||||
{ "TOP", "TOP" },
|
||||
{ "TPE", "TPE" },
|
||||
{ "TRL", "TRL" },
|
||||
{ "TRY", "TRY" },
|
||||
{ "TTD", "TTD" },
|
||||
{ "TWD", "TWD" },
|
||||
{ "TZS", "TZS" },
|
||||
{ "UAH", "UAH" },
|
||||
{ "UGX", "UGX" },
|
||||
{ "USD", "USD" },
|
||||
{ "USN", "USN" },
|
||||
{ "USS", "USS" },
|
||||
{ "UYU", "UYU" },
|
||||
{ "UZS", "UZS" },
|
||||
{ "VEB", "VEB" },
|
||||
{ "VED", "VED" },
|
||||
{ "VEF", "VEF" },
|
||||
{ "VES", "VES" },
|
||||
{ "VND", "VND" },
|
||||
{ "VUV", "VUV" },
|
||||
{ "WST", "WST" },
|
||||
{ "XAD", "XAD" },
|
||||
{ "XAF", "XAF" },
|
||||
{ "XAG", "XAG" },
|
||||
{ "XAU", "XAU" },
|
||||
{ "XBA", "XBA" },
|
||||
{ "XBB", "XBB" },
|
||||
{ "XBC", "XBC" },
|
||||
{ "XBD", "XBD" },
|
||||
{ "XCD", "XCD" },
|
||||
{ "XCG", "XCG" },
|
||||
{ "XDR", "XDR" },
|
||||
{ "XFO", "XFO" },
|
||||
{ "XFU", "XFU" },
|
||||
{ "XOF", "XOF" },
|
||||
{ "XPD", "XPD" },
|
||||
{ "XPF", "XPF" },
|
||||
{ "XPT", "XPT" },
|
||||
{ "XSU", "XSU" },
|
||||
{ "XTS", "XTS" },
|
||||
{ "XUA", "XUA" },
|
||||
{ "XXX", "XXX" },
|
||||
{ "YER", "YER" },
|
||||
{ "YUM", "YUM" },
|
||||
{ "ZAR", "ZAR" },
|
||||
{ "ZMK", "ZMK" },
|
||||
{ "ZMW", "ZMW" },
|
||||
{ "ZWD", "ZWD" },
|
||||
{ "ZWG", "ZWG" },
|
||||
{ "ZWL", "ZWL" },
|
||||
{ "ZWN", "ZWN" },
|
||||
{ "ZWR", "ZWR" },
|
||||
{ "adp", "Andorran Peseta" },
|
||||
{ "aed", "United Arab Emirates Dirham" },
|
||||
{ "afa", "Afghan Afghani (1927-2002)" },
|
||||
{ "afn", "Afghan Afghani" },
|
||||
{ "all", "Albanian Lek" },
|
||||
{ "amd", "Armenian Dram" },
|
||||
{ "ang", "Netherlands Antillean Guilder" },
|
||||
{ "aoa", "Angolan Kwanza" },
|
||||
{ "ars", "Argentine Peso" },
|
||||
{ "ats", "Austrian Schilling" },
|
||||
{ "aud", "Australian Dollar" },
|
||||
{ "awg", "Aruban Florin" },
|
||||
{ "azm", "Azerbaijani Manat (1993-2006)" },
|
||||
{ "azn", "Azerbaijan Manat" },
|
||||
{ "bam", "Bosnia-Herzegovina Convertible Mark" },
|
||||
{ "bbd", "Barbadian Dollar" },
|
||||
{ "bdt", "Bangladeshi Taka" },
|
||||
{ "bef", "Belgian Franc" },
|
||||
{ "bgl", "Bulgarian Hard Lev" },
|
||||
{ "bgn", "Bulgarian Lev" },
|
||||
{ "bhd", "Bahraini Dinar" },
|
||||
{ "bif", "Burundian Franc" },
|
||||
{ "bmd", "Bermudan Dollar" },
|
||||
{ "bnd", "Brunei Dollar" },
|
||||
{ "bob", "Bolivian Boliviano" },
|
||||
{ "bov", "Bolivian Mvdol" },
|
||||
{ "brl", "Brazilian Real" },
|
||||
{ "bsd", "Bahamian Dollar" },
|
||||
{ "btn", "Bhutanese Ngultrum" },
|
||||
{ "bwp", "Botswanan Pula" },
|
||||
{ "byb", "Belarusian Ruble (1994-1999)" },
|
||||
{ "byn", "Belarusian Ruble" },
|
||||
{ "byr", "Belarusian Ruble (2000-2016)" },
|
||||
{ "bzd", "Belize Dollar" },
|
||||
{ "cad", "Canadian Dollar" },
|
||||
{ "cdf", "Congolese Franc" },
|
||||
{ "chf", "Swiss Franc" },
|
||||
{ "clf", "Chilean Unit of Account (UF)" },
|
||||
{ "clp", "Chilean Peso" },
|
||||
{ "cny", "Chinese Yuan" },
|
||||
{ "cop", "Colombian Peso" },
|
||||
{ "crc", "Costa Rican Col\u00F3n" },
|
||||
{ "csd", "Serbian Dinar (2002-2006)" },
|
||||
{ "cuc", "Cuban Convertible Peso" },
|
||||
{ "cup", "Cuban Peso" },
|
||||
{ "cve", "Cape Verdean Escudo" },
|
||||
{ "cyp", "Cypriot Pound" },
|
||||
{ "czk", "Czech Republic Koruna" },
|
||||
{ "dem", "German Mark" },
|
||||
{ "djf", "Djiboutian Franc" },
|
||||
{ "dkk", "Danish Krone" },
|
||||
{ "dop", "Dominican Peso" },
|
||||
{ "dzd", "Algerian Dinar" },
|
||||
{ "eek", "Estonian Kroon" },
|
||||
{ "egp", "Egyptian Pound" },
|
||||
{ "ern", "Eritrean Nakfa" },
|
||||
{ "esp", "Spanish Peseta" },
|
||||
{ "etb", "Ethiopian Birr" },
|
||||
{ "eur", "Euro" },
|
||||
{ "fim", "Finnish Markka" },
|
||||
{ "fjd", "Fijian Dollar" },
|
||||
{ "fkp", "Falkland Islands Pound" },
|
||||
{ "frf", "French Franc" },
|
||||
{ "gbp", "British Pound Sterling" },
|
||||
{ "gel", "Georgian Lari" },
|
||||
{ "ghc", "Ghanaian Cedi (1979-2007)" },
|
||||
{ "ghs", "Ghanaian Cedi" },
|
||||
{ "gip", "Gibraltar Pound" },
|
||||
{ "gmd", "Gambian Dalasi" },
|
||||
{ "gnf", "Guinean Franc" },
|
||||
{ "grd", "Greek Drachma" },
|
||||
{ "gtq", "Guatemalan Quetzal" },
|
||||
{ "gwp", "Guinea-Bissau Peso" },
|
||||
{ "gyd", "Guyanaese Dollar" },
|
||||
{ "hkd", "Hong Kong Dollar" },
|
||||
{ "hnl", "Honduran Lempira" },
|
||||
{ "hrk", "Kuna" },
|
||||
{ "htg", "Haitian Gourde" },
|
||||
{ "huf", "Hungarian Forint" },
|
||||
{ "idr", "Indonesian Rupiah" },
|
||||
{ "iep", "Irish Pound" },
|
||||
{ "ils", "Israeli New Sheqel" },
|
||||
{ "inr", "Indian Rupee" },
|
||||
{ "iqd", "Iraqi Dinar" },
|
||||
{ "irr", "Iranian Rial" },
|
||||
{ "isk", "Icelandic Kr\u00F3na" },
|
||||
{ "itl", "Italian Lira" },
|
||||
{ "jmd", "Jamaican Dollar" },
|
||||
{ "jod", "Jordanian Dinar" },
|
||||
{ "jpy", "Japanese Yen" },
|
||||
{ "kes", "Kenyan Shilling" },
|
||||
{ "kgs", "Kyrgystani Som" },
|
||||
{ "khr", "Cambodian Riel" },
|
||||
{ "kmf", "Comorian Franc" },
|
||||
{ "kpw", "North Korean Won" },
|
||||
{ "krw", "South Korean Won" },
|
||||
{ "kwd", "Kuwaiti Dinar" },
|
||||
{ "kyd", "Cayman Islands Dollar" },
|
||||
{ "kzt", "Kazakhstani Tenge" },
|
||||
{ "lak", "Lao Kip" },
|
||||
{ "lbp", "Lebanese Pound" },
|
||||
{ "lkr", "Sri Lankan Rupee" },
|
||||
{ "lrd", "Liberian Dollar" },
|
||||
{ "lsl", "Lesotho Loti" },
|
||||
{ "ltl", "Lithuanian Litas" },
|
||||
{ "luf", "Luxembourgian Franc" },
|
||||
{ "lvl", "Latvian Lats" },
|
||||
{ "lyd", "Libyan Dinar" },
|
||||
{ "mad", "Moroccan Dirham" },
|
||||
{ "mdl", "Moldovan Leu" },
|
||||
{ "mga", "Malagasy Ariary" },
|
||||
{ "mgf", "Malagasy Franc" },
|
||||
{ "mkd", "Macedonian Denar" },
|
||||
{ "mmk", "Myanma Kyat" },
|
||||
{ "mnt", "Mongolian Tugrik" },
|
||||
{ "mop", "Macanese Pataca" },
|
||||
{ "mro", "Mauritanian Ouguiya" },
|
||||
{ "mru", "Mauritanian Ouguiya" },
|
||||
{ "mtl", "Maltese Lira" },
|
||||
{ "mur", "Mauritian Rupee" },
|
||||
{ "mvr", "Maldivian Rufiyaa" },
|
||||
{ "mwk", "Malawian Malawi Kwacha" },
|
||||
{ "mxn", "Mexican Peso" },
|
||||
{ "mxv", "Mexican Investment Unit" },
|
||||
{ "myr", "Malaysian Ringgit" },
|
||||
{ "mzm", "Mozambican Metical (1980-2006)" },
|
||||
{ "mzn", "Mozambican Metical" },
|
||||
{ "nad", "Namibian Dollar" },
|
||||
{ "ngn", "Nigerian Naira" },
|
||||
{ "nio", "Nicaraguan C\u00F3rdoba" },
|
||||
{ "nlg", "Dutch Guilder" },
|
||||
{ "nok", "Norwegian Krone" },
|
||||
{ "npr", "Nepalese Rupee" },
|
||||
{ "nzd", "New Zealand Dollar" },
|
||||
{ "omr", "Omani Rial" },
|
||||
{ "pab", "Panamanian Balboa" },
|
||||
{ "pen", "Peruvian Sol" },
|
||||
{ "pgk", "Papua New Guinean Kina" },
|
||||
{ "php", "Philippine Peso" },
|
||||
{ "pkr", "Pakistani Rupee" },
|
||||
{ "pln", "Polish Zloty" },
|
||||
{ "pte", "Portuguese Escudo" },
|
||||
{ "pyg", "Paraguayan Guarani" },
|
||||
{ "qar", "Qatari Rial" },
|
||||
{ "rol", "Romanian Leu (1952-2006)" },
|
||||
{ "ron", "Romanian Leu" },
|
||||
{ "rsd", "Serbian Dinar" },
|
||||
{ "rub", "Russian Ruble" },
|
||||
{ "rur", "Russian Ruble (1991-1998)" },
|
||||
{ "rwf", "Rwandan Franc" },
|
||||
{ "sar", "Saudi Riyal" },
|
||||
{ "sbd", "Solomon Islands Dollar" },
|
||||
{ "scr", "Seychellois Rupee" },
|
||||
{ "sdd", "Sudanese Dinar (1992-2007)" },
|
||||
{ "sdg", "Sudanese Pound" },
|
||||
{ "sek", "Swedish Krona" },
|
||||
{ "sgd", "Singapore Dollar" },
|
||||
{ "shp", "Saint Helena Pound" },
|
||||
{ "sit", "Slovenian Tolar" },
|
||||
{ "skk", "Slovak Koruna" },
|
||||
{ "sle", "Sierra Leonean Leone" },
|
||||
{ "sll", "Sierra Leonean Leone" },
|
||||
{ "sos", "Somali Shilling" },
|
||||
{ "srd", "Surinamese Dollar" },
|
||||
{ "srg", "Surinamese Guilder" },
|
||||
{ "ssp", "South Sudanese Pound" },
|
||||
{ "std", "S\u00E3o Tom\u00E9 and Pr\u00EDncipe Dobra" },
|
||||
{ "stn", "S\u00E3o Tom\u00E9 and Pr\u00EDncipe Dobra" },
|
||||
{ "svc", "Salvadoran Col\u00F3n" },
|
||||
{ "syp", "Syrian Pound" },
|
||||
{ "szl", "Swazi Lilangeni" },
|
||||
{ "thb", "Thai Baht" },
|
||||
{ "tjs", "Tajikistani Somoni" },
|
||||
{ "tmm", "Turkmenistani Manat (1993-2009)" },
|
||||
{ "tmt", "Turkmenistani Manat" },
|
||||
{ "tnd", "Tunisian Dinar" },
|
||||
{ "top", "Tongan Pa\u02BBanga" },
|
||||
{ "tpe", "Timorese Escudo" },
|
||||
{ "trl", "Turkish Lira (1922-2005)" },
|
||||
{ "try", "Turkish Lira" },
|
||||
{ "ttd", "Trinidad and Tobago Dollar" },
|
||||
{ "twd", "New Taiwan Dollar" },
|
||||
{ "tzs", "Tanzanian Shilling" },
|
||||
{ "uah", "Ukrainian Hryvnia" },
|
||||
{ "ugx", "Ugandan Shilling" },
|
||||
{ "usd", "US Dollar" },
|
||||
{ "usn", "US Dollar (Next day)" },
|
||||
{ "uss", "US Dollar (Same day)" },
|
||||
{ "uyu", "Uruguayan Peso" },
|
||||
{ "uzs", "Uzbekistan Som" },
|
||||
{ "veb", "Venezuelan Bol\u00EDvar (1871-2008)" },
|
||||
{ "ved", "Venezuelan Bol\u00EDvar Soberano" },
|
||||
{ "vef", "Venezuelan Bol\u00EDvar" },
|
||||
{ "ves", "Venezuelan Bol\u00EDvar Soberano" },
|
||||
{ "vnd", "Vietnamese Dong" },
|
||||
{ "vuv", "Vanuatu Vatu" },
|
||||
{ "wst", "Samoan Tala" },
|
||||
{ "xad", "Arab Accounting Dinar" },
|
||||
{ "xaf", "CFA Franc BEAC" },
|
||||
{ "xag", "Silver" },
|
||||
{ "xau", "Gold" },
|
||||
{ "xba", "European Composite Unit" },
|
||||
{ "xbb", "European Monetary Unit" },
|
||||
{ "xbc", "European Unit of Account (XBC)" },
|
||||
{ "xbd", "European Unit of Account (XBD)" },
|
||||
{ "xcd", "East Caribbean Dollar" },
|
||||
{ "xcg", "Caribbean Guilder" },
|
||||
{ "xdr", "Special Drawing Rights" },
|
||||
{ "xfo", "French Gold Franc" },
|
||||
{ "xfu", "French UIC-Franc" },
|
||||
{ "xof", "CFA Franc BCEAO" },
|
||||
{ "xpd", "Palladium" },
|
||||
{ "xpf", "CFP Franc" },
|
||||
{ "xpt", "Platinum" },
|
||||
{ "xsu", "Sucre" },
|
||||
{ "xts", "Testing Currency Code" },
|
||||
{ "xua", "ADB Unit of Account" },
|
||||
{ "xxx", "Unknown Currency" },
|
||||
{ "yer", "Yemeni Rial" },
|
||||
{ "yum", "Yugoslavian New Dinar (1994-2002)" },
|
||||
{ "zar", "South African Rand" },
|
||||
{ "zmk", "Zambian Kwacha" },
|
||||
{ "zwd", "Zimbabwean Dollar (1980-2008)" },
|
||||
{ "zwg", "Zimbabwe Gold" },
|
||||
{ "zwl", "Zimbabwean Dollar (2009)" },
|
||||
{ "zwr", "Zimbabwean Dollar (2008)" },
|
||||
};
|
||||
}
|
||||
}
|
||||
299
jdkSrc/jdk8/sun/util/resources/LocaleData.java
Normal file
299
jdkSrc/jdk8/sun/util/resources/LocaleData.java
Normal file
@@ -0,0 +1,299 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
|
||||
* (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved
|
||||
*
|
||||
* The original version of this source code and documentation
|
||||
* is copyrighted and owned by Taligent, Inc., a wholly-owned
|
||||
* subsidiary of IBM. These materials are provided under terms
|
||||
* of a License Agreement between Taligent and Sun. This technology
|
||||
* is protected by multiple US and International patents.
|
||||
*
|
||||
* This notice and attribution to Taligent may not be removed.
|
||||
* Taligent is a registered trademark of Taligent, Inc.
|
||||
*
|
||||
*/
|
||||
|
||||
package sun.util.resources;
|
||||
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.MissingResourceException;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.Set;
|
||||
import sun.util.locale.provider.JRELocaleProviderAdapter;
|
||||
import sun.util.locale.provider.LocaleDataMetaInfo;
|
||||
import sun.util.locale.provider.LocaleProviderAdapter;
|
||||
import static sun.util.locale.provider.LocaleProviderAdapter.Type.CLDR;
|
||||
import static sun.util.locale.provider.LocaleProviderAdapter.Type.JRE;
|
||||
|
||||
/**
|
||||
* Provides information about and access to resource bundles in the
|
||||
* sun.text.resources and sun.util.resources packages or in their corresponding
|
||||
* packages for CLDR.
|
||||
*
|
||||
* @author Asmus Freytag
|
||||
* @author Mark Davis
|
||||
*/
|
||||
|
||||
public class LocaleData {
|
||||
private final LocaleProviderAdapter.Type type;
|
||||
|
||||
public LocaleData(LocaleProviderAdapter.Type type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a calendar data resource bundle, using privileges
|
||||
* to allow accessing a sun.* package.
|
||||
*/
|
||||
public ResourceBundle getCalendarData(Locale locale) {
|
||||
return getBundle(type.getUtilResourcesPackage() + ".CalendarData", locale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a currency names resource bundle, using privileges
|
||||
* to allow accessing a sun.* package.
|
||||
*/
|
||||
public OpenListResourceBundle getCurrencyNames(Locale locale) {
|
||||
return (OpenListResourceBundle) getBundle(type.getUtilResourcesPackage() + ".CurrencyNames", locale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a locale names resource bundle, using privileges
|
||||
* to allow accessing a sun.* package.
|
||||
*/
|
||||
public OpenListResourceBundle getLocaleNames(Locale locale) {
|
||||
return (OpenListResourceBundle) getBundle(type.getUtilResourcesPackage() + ".LocaleNames", locale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a time zone names resource bundle, using privileges
|
||||
* to allow accessing a sun.* package.
|
||||
*/
|
||||
public TimeZoneNamesBundle getTimeZoneNames(Locale locale) {
|
||||
return (TimeZoneNamesBundle) getBundle(type.getUtilResourcesPackage() + ".TimeZoneNames", locale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a break iterator info resource bundle, using privileges
|
||||
* to allow accessing a sun.* package.
|
||||
*/
|
||||
public ResourceBundle getBreakIteratorInfo(Locale locale) {
|
||||
return getBundle(type.getTextResourcesPackage() + ".BreakIteratorInfo", locale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a collation data resource bundle, using privileges
|
||||
* to allow accessing a sun.* package.
|
||||
*/
|
||||
public ResourceBundle getCollationData(Locale locale) {
|
||||
return getBundle(type.getTextResourcesPackage() + ".CollationData", locale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a date format data resource bundle, using privileges
|
||||
* to allow accessing a sun.* package.
|
||||
*/
|
||||
public ResourceBundle getDateFormatData(Locale locale) {
|
||||
return getBundle(type.getTextResourcesPackage() + ".FormatData", locale);
|
||||
}
|
||||
|
||||
public void setSupplementary(ParallelListResourceBundle formatData) {
|
||||
if (!formatData.areParallelContentsComplete()) {
|
||||
String suppName = type.getTextResourcesPackage() + ".JavaTimeSupplementary";
|
||||
setSupplementary(suppName, formatData);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean setSupplementary(String suppName, ParallelListResourceBundle formatData) {
|
||||
ParallelListResourceBundle parent = (ParallelListResourceBundle) formatData.getParent();
|
||||
boolean resetKeySet = false;
|
||||
if (parent != null) {
|
||||
resetKeySet = setSupplementary(suppName, parent);
|
||||
}
|
||||
OpenListResourceBundle supp = getSupplementary(suppName, formatData.getLocale());
|
||||
formatData.setParallelContents(supp);
|
||||
resetKeySet |= supp != null;
|
||||
// If any parents or this bundle has parallel data, reset keyset to create
|
||||
// a new keyset with the data.
|
||||
if (resetKeySet) {
|
||||
formatData.resetKeySet();
|
||||
}
|
||||
return resetKeySet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a number format data resource bundle, using privileges
|
||||
* to allow accessing a sun.* package.
|
||||
*/
|
||||
public ResourceBundle getNumberFormatData(Locale locale) {
|
||||
return getBundle(type.getTextResourcesPackage() + ".FormatData", locale);
|
||||
}
|
||||
|
||||
public static ResourceBundle getBundle(final String baseName, final Locale locale) {
|
||||
return AccessController.doPrivileged(new PrivilegedAction<ResourceBundle>() {
|
||||
@Override
|
||||
public ResourceBundle run() {
|
||||
return ResourceBundle
|
||||
.getBundle(baseName, locale, LocaleDataResourceBundleControl.INSTANCE);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static OpenListResourceBundle getSupplementary(final String baseName, final Locale locale) {
|
||||
return AccessController.doPrivileged(new PrivilegedAction<OpenListResourceBundle>() {
|
||||
@Override
|
||||
public OpenListResourceBundle run() {
|
||||
OpenListResourceBundle rb = null;
|
||||
try {
|
||||
rb = (OpenListResourceBundle) ResourceBundle.getBundle(baseName,
|
||||
locale, SupplementaryResourceBundleControl.INSTANCE);
|
||||
|
||||
} catch (MissingResourceException e) {
|
||||
// return null if no supplementary is available
|
||||
}
|
||||
return rb;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static class LocaleDataResourceBundleControl extends ResourceBundle.Control {
|
||||
/* Singlton instance of ResourceBundle.Control. */
|
||||
private static final LocaleDataResourceBundleControl INSTANCE =
|
||||
new LocaleDataResourceBundleControl();
|
||||
|
||||
private LocaleDataResourceBundleControl() {
|
||||
}
|
||||
|
||||
/*
|
||||
* This method overrides the default implementation to search
|
||||
* from a prebaked locale string list to determin the candidate
|
||||
* locale list.
|
||||
*
|
||||
* @param baseName the resource bundle base name.
|
||||
* locale the requested locale for the resource bundle.
|
||||
* @returns a list of candidate locales to search from.
|
||||
* @exception NullPointerException if baseName or locale is null.
|
||||
*/
|
||||
@Override
|
||||
public List<Locale> getCandidateLocales(String baseName, Locale locale) {
|
||||
List<Locale> candidates = super.getCandidateLocales(baseName, locale);
|
||||
// Weed out Locales which are known to have no resource bundles
|
||||
int lastDot = baseName.lastIndexOf('.');
|
||||
String category = (lastDot >= 0) ? baseName.substring(lastDot + 1) : baseName;
|
||||
LocaleProviderAdapter.Type type = baseName.contains(DOTCLDR) ? CLDR : JRE;
|
||||
LocaleProviderAdapter adapter = LocaleProviderAdapter.forType(type);
|
||||
Set<String> langtags = ((JRELocaleProviderAdapter)adapter).getLanguageTagSet(category);
|
||||
if (!langtags.isEmpty()) {
|
||||
for (Iterator<Locale> itr = candidates.iterator(); itr.hasNext();) {
|
||||
if (!LocaleProviderAdapter.isSupportedLocale(itr.next(), type, langtags)) {
|
||||
itr.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Force fallback to Locale.ENGLISH for CLDR time zone names support
|
||||
if (locale.getLanguage() != "en"
|
||||
&& type == CLDR && category.equals("TimeZoneNames")) {
|
||||
candidates.add(candidates.size() - 1, Locale.ENGLISH);
|
||||
}
|
||||
return candidates;
|
||||
}
|
||||
|
||||
/*
|
||||
* Overrides "getFallbackLocale" to return null so
|
||||
* that the fallback locale will be null.
|
||||
* @param baseName the resource bundle base name.
|
||||
* locale the requested locale for the resource bundle.
|
||||
* @return null for the fallback locale.
|
||||
* @exception NullPointerException if baseName or locale is null.
|
||||
*/
|
||||
@Override
|
||||
public Locale getFallbackLocale(String baseName, Locale locale) {
|
||||
if (baseName == null || locale == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static final String DOTCLDR = ".cldr";
|
||||
|
||||
/**
|
||||
* Changes baseName to its per-language package name and
|
||||
* calls the super class implementation. For example,
|
||||
* if the baseName is "sun.text.resources.FormatData" and locale is ja_JP,
|
||||
* the baseName is changed to "sun.text.resources.ja.FormatData". If
|
||||
* baseName contains "cldr", such as "sun.text.resources.cldr.FormatData",
|
||||
* the name is changed to "sun.text.resources.cldr.jp.FormatData".
|
||||
*/
|
||||
@Override
|
||||
public String toBundleName(String baseName, Locale locale) {
|
||||
String newBaseName = baseName;
|
||||
String lang = locale.getLanguage();
|
||||
if (lang.length() > 0) {
|
||||
if (baseName.startsWith(JRE.getUtilResourcesPackage())
|
||||
|| baseName.startsWith(JRE.getTextResourcesPackage())) {
|
||||
// Assume the lengths are the same.
|
||||
assert JRE.getUtilResourcesPackage().length()
|
||||
== JRE.getTextResourcesPackage().length();
|
||||
int index = JRE.getUtilResourcesPackage().length();
|
||||
if (baseName.indexOf(DOTCLDR, index) > 0) {
|
||||
index += DOTCLDR.length();
|
||||
}
|
||||
newBaseName = baseName.substring(0, index + 1) + lang
|
||||
+ baseName.substring(index);
|
||||
}
|
||||
}
|
||||
return super.toBundleName(newBaseName, locale);
|
||||
}
|
||||
}
|
||||
|
||||
private static class SupplementaryResourceBundleControl extends LocaleDataResourceBundleControl {
|
||||
private static final SupplementaryResourceBundleControl INSTANCE =
|
||||
new SupplementaryResourceBundleControl();
|
||||
|
||||
private SupplementaryResourceBundleControl() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Locale> getCandidateLocales(String baseName, Locale locale) {
|
||||
// Specifiy only the given locale
|
||||
return Arrays.asList(locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getTimeToLive(String baseName, Locale locale) {
|
||||
assert baseName.contains("JavaTimeSupplementary");
|
||||
return TTL_DONT_CACHE;
|
||||
}
|
||||
}
|
||||
}
|
||||
1116
jdkSrc/jdk8/sun/util/resources/LocaleNames.java
Normal file
1116
jdkSrc/jdk8/sun/util/resources/LocaleNames.java
Normal file
File diff suppressed because it is too large
Load Diff
40
jdkSrc/jdk8/sun/util/resources/LocaleNamesBundle.java
Normal file
40
jdkSrc/jdk8/sun/util/resources/LocaleNamesBundle.java
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.util.resources;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.MissingResourceException;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
/**
|
||||
* Implements ResourceBundle for LocaleNames bundles that don't provide
|
||||
* the complete set of locale names.
|
||||
*/
|
||||
public abstract class LocaleNamesBundle extends OpenListResourceBundle {
|
||||
|
||||
protected LocaleNamesBundle() {
|
||||
}
|
||||
}
|
||||
169
jdkSrc/jdk8/sun/util/resources/OpenListResourceBundle.java
Normal file
169
jdkSrc/jdk8/sun/util/resources/OpenListResourceBundle.java
Normal file
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
|
||||
* (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved
|
||||
*
|
||||
* The original version of this source code and documentation
|
||||
* is copyrighted and owned by Taligent, Inc., a wholly-owned
|
||||
* subsidiary of IBM. These materials are provided under terms
|
||||
* of a License Agreement between Taligent and Sun. This technology
|
||||
* is protected by multiple US and International patents.
|
||||
*
|
||||
* This notice and attribution to Taligent may not be removed.
|
||||
* Taligent is a registered trademark of Taligent, Inc.
|
||||
*
|
||||
*/
|
||||
|
||||
package sun.util.resources;
|
||||
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.Set;
|
||||
import sun.util.ResourceBundleEnumeration;
|
||||
|
||||
/**
|
||||
* Subclass of <code>ResourceBundle</code> which mimics
|
||||
* <code>ListResourceBundle</code>, but provides more hooks
|
||||
* for specialized subclass behavior. For general description,
|
||||
* see {@link java.util.ListResourceBundle}.
|
||||
* <p>
|
||||
* This class leaves handleGetObject non-final, and
|
||||
* adds a method createMap which allows subclasses to
|
||||
* use specialized Map implementations.
|
||||
*/
|
||||
public abstract class OpenListResourceBundle extends ResourceBundle {
|
||||
/**
|
||||
* Sole constructor. (For invocation by subclass constructors, typically
|
||||
* implicit.)
|
||||
*/
|
||||
protected OpenListResourceBundle() {
|
||||
}
|
||||
|
||||
// Implements java.util.ResourceBundle.handleGetObject; inherits javadoc specification.
|
||||
@Override
|
||||
protected Object handleGetObject(String key) {
|
||||
if (key == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
|
||||
loadLookupTablesIfNecessary();
|
||||
return lookup.get(key); // this class ignores locales
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of ResourceBundle.getKeys.
|
||||
*/
|
||||
@Override
|
||||
public Enumeration<String> getKeys() {
|
||||
ResourceBundle parentBundle = this.parent;
|
||||
return new ResourceBundleEnumeration(handleKeySet(),
|
||||
(parentBundle != null) ? parentBundle.getKeys() : null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a set of keys provided in this resource bundle,
|
||||
* including no parents.
|
||||
*/
|
||||
@Override
|
||||
protected Set<String> handleKeySet() {
|
||||
loadLookupTablesIfNecessary();
|
||||
return lookup.keySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> keySet() {
|
||||
if (keyset != null) {
|
||||
return keyset;
|
||||
}
|
||||
Set<String> ks = createSet();
|
||||
ks.addAll(handleKeySet());
|
||||
if (parent != null) {
|
||||
ks.addAll(parent.keySet());
|
||||
}
|
||||
synchronized (this) {
|
||||
if (keyset == null) {
|
||||
keyset = ks;
|
||||
}
|
||||
}
|
||||
return keyset;
|
||||
}
|
||||
|
||||
/**
|
||||
* See ListResourceBundle class description.
|
||||
*/
|
||||
abstract protected Object[][] getContents();
|
||||
|
||||
/**
|
||||
* Load lookup tables if they haven't been loaded already.
|
||||
*/
|
||||
void loadLookupTablesIfNecessary() {
|
||||
if (lookup == null) {
|
||||
loadLookup();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* We lazily load the lookup hashtable. This function does the
|
||||
* loading.
|
||||
*/
|
||||
private void loadLookup() {
|
||||
Object[][] contents = getContents();
|
||||
Map<String, Object> temp = createMap(contents.length);
|
||||
for (int i = 0; i < contents.length; ++i) {
|
||||
// key must be non-null String, value must be non-null
|
||||
String key = (String) contents[i][0];
|
||||
Object value = contents[i][1];
|
||||
if (key == null || value == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
temp.put(key, value);
|
||||
}
|
||||
synchronized (this) {
|
||||
if (lookup == null) {
|
||||
lookup = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Lets subclasses provide specialized Map implementations.
|
||||
* Default uses HashMap.
|
||||
*/
|
||||
protected <K, V> Map<K, V> createMap(int size) {
|
||||
return new HashMap<>(size);
|
||||
}
|
||||
|
||||
protected <E> Set<E> createSet() {
|
||||
return new HashSet<>();
|
||||
}
|
||||
|
||||
private volatile Map<String, Object> lookup = null;
|
||||
private volatile Set<String> keyset;
|
||||
}
|
||||
259
jdkSrc/jdk8/sun/util/resources/ParallelListResourceBundle.java
Normal file
259
jdkSrc/jdk8/sun/util/resources/ParallelListResourceBundle.java
Normal file
@@ -0,0 +1,259 @@
|
||||
/*
|
||||
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.util.resources;
|
||||
|
||||
import java.util.AbstractSet;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.atomic.AtomicMarkableReference;
|
||||
|
||||
/**
|
||||
* ParallelListResourceBundle is another variant of ListResourceBundle
|
||||
* supporting "parallel" contents provided by another resource bundle
|
||||
* (OpenListResourceBundle). Parallel contents, if any, are added into this
|
||||
* bundle on demand.
|
||||
*
|
||||
* @author Masayoshi Okutsu
|
||||
*/
|
||||
public abstract class ParallelListResourceBundle extends ResourceBundle {
|
||||
private volatile ConcurrentMap<String, Object> lookup;
|
||||
private volatile Set<String> keyset;
|
||||
private final AtomicMarkableReference<Object[][]> parallelContents
|
||||
= new AtomicMarkableReference<>(null, false);
|
||||
|
||||
/**
|
||||
* Sole constructor. (For invocation by subclass constructors, typically
|
||||
* implicit.)
|
||||
*/
|
||||
protected ParallelListResourceBundle() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array in which each item is a pair of objects in an
|
||||
* Object array. The first element of each pair is the key, which
|
||||
* must be a String, and the second element is the value
|
||||
* associated with that key. See the class description for
|
||||
* details.
|
||||
*
|
||||
* @return an array of an Object array representing a key-value pair.
|
||||
*/
|
||||
protected abstract Object[][] getContents();
|
||||
|
||||
/**
|
||||
* Returns the parent of this resource bundle or null if there's no parent.
|
||||
*
|
||||
* @return the parent or null if no parent
|
||||
*/
|
||||
ResourceBundle getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the parallel contents to the data given by rb. If rb is null, this
|
||||
* bundle will be marked as `complete'.
|
||||
*
|
||||
* @param rb an OpenResourceBundle for parallel contents, or null indicating
|
||||
* there are no parallel contents for this bundle
|
||||
*/
|
||||
public void setParallelContents(OpenListResourceBundle rb) {
|
||||
if (rb == null) {
|
||||
parallelContents.compareAndSet(null, null, false, true);
|
||||
} else {
|
||||
parallelContents.compareAndSet(null, rb.getContents(), false, false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if any parallel contents have been set or if this bundle is
|
||||
* marked as complete.
|
||||
*
|
||||
* @return true if any parallel contents have been processed
|
||||
*/
|
||||
boolean areParallelContentsComplete() {
|
||||
// Quick check for `complete'
|
||||
if (parallelContents.isMarked()) {
|
||||
return true;
|
||||
}
|
||||
boolean[] done = new boolean[1];
|
||||
Object[][] data = parallelContents.get(done);
|
||||
return data != null || done[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object handleGetObject(String key) {
|
||||
if (key == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
|
||||
loadLookupTablesIfNecessary();
|
||||
return lookup.get(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration<String> getKeys() {
|
||||
return Collections.enumeration(keySet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsKey(String key) {
|
||||
return keySet().contains(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Set<String> handleKeySet() {
|
||||
loadLookupTablesIfNecessary();
|
||||
return lookup.keySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("UnusedAssignment")
|
||||
public Set<String> keySet() {
|
||||
Set<String> ks;
|
||||
while ((ks = keyset) == null) {
|
||||
ks = new KeySet(handleKeySet(), parent);
|
||||
synchronized (this) {
|
||||
if (keyset == null) {
|
||||
keyset = ks;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Discards any cached keyset value. This method is called from
|
||||
* LocaleData for re-creating a KeySet.
|
||||
*/
|
||||
synchronized void resetKeySet() {
|
||||
keyset = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the lookup table if they haven't been loaded already.
|
||||
*/
|
||||
void loadLookupTablesIfNecessary() {
|
||||
ConcurrentMap<String, Object> map = lookup;
|
||||
if (map == null) {
|
||||
map = new ConcurrentHashMap<>();
|
||||
for (Object[] item : getContents()) {
|
||||
map.put((String) item[0], item[1]);
|
||||
}
|
||||
}
|
||||
|
||||
// If there's any parallel contents data, merge the data into map.
|
||||
Object[][] data = parallelContents.getReference();
|
||||
if (data != null) {
|
||||
for (Object[] item : data) {
|
||||
map.putIfAbsent((String) item[0], item[1]);
|
||||
}
|
||||
parallelContents.set(null, true);
|
||||
}
|
||||
if (lookup == null) {
|
||||
synchronized (this) {
|
||||
if (lookup == null) {
|
||||
lookup = map;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This class implements the Set interface for
|
||||
* ParallelListResourceBundle methods.
|
||||
*/
|
||||
private static class KeySet extends AbstractSet<String> {
|
||||
private final Set<String> set;
|
||||
private final ResourceBundle parent;
|
||||
|
||||
private KeySet(Set<String> set, ResourceBundle parent) {
|
||||
this.set = set;
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(Object o) {
|
||||
if (set.contains(o)) {
|
||||
return true;
|
||||
}
|
||||
return (parent != null) ? parent.containsKey((String) o) : false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<String> iterator() {
|
||||
if (parent == null) {
|
||||
return set.iterator();
|
||||
}
|
||||
return new Iterator<String>() {
|
||||
private Iterator<String> itr = set.iterator();
|
||||
private boolean usingParent;
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
if (itr.hasNext()) {
|
||||
return true;
|
||||
}
|
||||
if (!usingParent) {
|
||||
Set<String> nextset = new HashSet<>(parent.keySet());
|
||||
nextset.removeAll(set);
|
||||
itr = nextset.iterator();
|
||||
usingParent = true;
|
||||
}
|
||||
return itr.hasNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String next() {
|
||||
if (hasNext()) {
|
||||
return itr.next();
|
||||
}
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
if (parent == null) {
|
||||
return set.size();
|
||||
}
|
||||
Set<String> allset = new HashSet<>(set);
|
||||
allset.addAll(parent.keySet());
|
||||
return allset.size();
|
||||
}
|
||||
}
|
||||
}
|
||||
1053
jdkSrc/jdk8/sun/util/resources/TimeZoneNames.java
Normal file
1053
jdkSrc/jdk8/sun/util/resources/TimeZoneNames.java
Normal file
File diff suppressed because it is too large
Load Diff
128
jdkSrc/jdk8/sun/util/resources/TimeZoneNamesBundle.java
Normal file
128
jdkSrc/jdk8/sun/util/resources/TimeZoneNamesBundle.java
Normal file
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
|
||||
* (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved
|
||||
*
|
||||
* The original version of this source code and documentation
|
||||
* is copyrighted and owned by Taligent, Inc., a wholly-owned
|
||||
* subsidiary of IBM. These materials are provided under terms
|
||||
* of a License Agreement between Taligent and Sun. This technology
|
||||
* is protected by multiple US and International patents.
|
||||
*
|
||||
* This notice and attribution to Taligent may not be removed.
|
||||
* Taligent is a registered trademark of Taligent, Inc.
|
||||
*
|
||||
*/
|
||||
|
||||
package sun.util.resources;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.MissingResourceException;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Subclass of <code>ResourceBundle</code> with special
|
||||
* functionality for time zone names. The additional functionality:
|
||||
* <ul>
|
||||
* <li>Preserves the order of entries in the <code>getContents</code>
|
||||
* array for the enumeration returned by <code>getKeys</code>.
|
||||
* <li>Inserts the time zone ID (the key of the bundle entries) into
|
||||
* the string arrays returned by <code>handleGetObject</code>.
|
||||
* <ul>
|
||||
* All <code>TimeZoneNames</code> resource bundles must extend this
|
||||
* class and implement the <code>getContents</code> method.
|
||||
*/
|
||||
public abstract class TimeZoneNamesBundle extends OpenListResourceBundle {
|
||||
|
||||
/**
|
||||
* Maps time zone IDs to locale-specific names.
|
||||
* The value returned is an array of five strings:
|
||||
* <ul>
|
||||
* <li>The time zone ID (same as the key, not localized).
|
||||
* <li>The long name of the time zone in standard time (localized).
|
||||
* <li>The short name of the time zone in standard time (localized).
|
||||
* <li>The long name of the time zone in daylight savings time (localized).
|
||||
* <li>The short name of the time zone in daylight savings time (localized).
|
||||
* <li>The long name of the time zone in generic form (localized).
|
||||
* <li>The short name of the time zone in generic form (localized).
|
||||
* </ul>
|
||||
* The localized names come from the subclasses's
|
||||
* <code>getContents</code> implementations, while the time zone
|
||||
* ID is inserted into the returned array by this method.
|
||||
*/
|
||||
@Override
|
||||
public Object handleGetObject(String key) {
|
||||
String[] contents = (String[]) super.handleGetObject(key);
|
||||
if (Objects.isNull(contents)) {
|
||||
return null;
|
||||
}
|
||||
int clen = contents.length;
|
||||
String[] tmpobj = new String[7];
|
||||
tmpobj[0] = key;
|
||||
System.arraycopy(contents, 0, tmpobj, 1, clen);
|
||||
return tmpobj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use LinkedHashMap to preserve the order of bundle entries.
|
||||
*/
|
||||
@Override
|
||||
protected <K, V> Map<K, V> createMap(int size) {
|
||||
return new LinkedHashMap<>(size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use LinkedHashSet to preserve the key order.
|
||||
* @param <E> the type of elements
|
||||
* @return a Set
|
||||
*/
|
||||
@Override
|
||||
protected <E> Set<E> createSet() {
|
||||
return new LinkedHashSet<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides key/value mappings for a specific
|
||||
* resource bundle. Each entry of the array
|
||||
* returned must be an array with two elements:
|
||||
* <ul>
|
||||
* <li>The key, which must be a string.
|
||||
* <li>The value, which must be an array of
|
||||
* four strings:
|
||||
* <ul>
|
||||
* <li>The long name of the time zone in standard time.
|
||||
* <li>The short name of the time zone in standard time.
|
||||
* <li>The long name of the time zone in daylight savings time.
|
||||
* <li>The short name of the time zone in daylight savings time.
|
||||
* </ul>
|
||||
* </ul>
|
||||
*/
|
||||
protected abstract Object[][] getContents();
|
||||
}
|
||||
12
jdkSrc/jdk8/sun/util/resources/ar/CalendarData_ar.java
Normal file
12
jdkSrc/jdk8/sun/util/resources/ar/CalendarData_ar.java
Normal file
@@ -0,0 +1,12 @@
|
||||
package sun.util.resources.ar;
|
||||
|
||||
import java.util.ListResourceBundle;
|
||||
|
||||
public final class CalendarData_ar extends sun.util.resources.LocaleNamesBundle {
|
||||
protected final Object[][] getContents() {
|
||||
return new Object[][] {
|
||||
{ "firstDayOfWeek", "7" },
|
||||
{ "minimalDaysInFirstWeek", "1" },
|
||||
};
|
||||
}
|
||||
}
|
||||
11
jdkSrc/jdk8/sun/util/resources/ar/CurrencyNames_ar_AE.java
Normal file
11
jdkSrc/jdk8/sun/util/resources/ar/CurrencyNames_ar_AE.java
Normal file
@@ -0,0 +1,11 @@
|
||||
package sun.util.resources.ar;
|
||||
|
||||
import java.util.ListResourceBundle;
|
||||
|
||||
public final class CurrencyNames_ar_AE extends sun.util.resources.LocaleNamesBundle {
|
||||
protected final Object[][] getContents() {
|
||||
return new Object[][] {
|
||||
{ "AED", "\u062F.\u0625.\u200F" },
|
||||
};
|
||||
}
|
||||
}
|
||||
11
jdkSrc/jdk8/sun/util/resources/ar/CurrencyNames_ar_BH.java
Normal file
11
jdkSrc/jdk8/sun/util/resources/ar/CurrencyNames_ar_BH.java
Normal file
@@ -0,0 +1,11 @@
|
||||
package sun.util.resources.ar;
|
||||
|
||||
import java.util.ListResourceBundle;
|
||||
|
||||
public final class CurrencyNames_ar_BH extends sun.util.resources.LocaleNamesBundle {
|
||||
protected final Object[][] getContents() {
|
||||
return new Object[][] {
|
||||
{ "BHD", "\u062F.\u0628.\u200F" },
|
||||
};
|
||||
}
|
||||
}
|
||||
11
jdkSrc/jdk8/sun/util/resources/ar/CurrencyNames_ar_DZ.java
Normal file
11
jdkSrc/jdk8/sun/util/resources/ar/CurrencyNames_ar_DZ.java
Normal file
@@ -0,0 +1,11 @@
|
||||
package sun.util.resources.ar;
|
||||
|
||||
import java.util.ListResourceBundle;
|
||||
|
||||
public final class CurrencyNames_ar_DZ extends sun.util.resources.LocaleNamesBundle {
|
||||
protected final Object[][] getContents() {
|
||||
return new Object[][] {
|
||||
{ "DZD", "\u062F.\u062C.\u200F" },
|
||||
};
|
||||
}
|
||||
}
|
||||
11
jdkSrc/jdk8/sun/util/resources/ar/CurrencyNames_ar_EG.java
Normal file
11
jdkSrc/jdk8/sun/util/resources/ar/CurrencyNames_ar_EG.java
Normal file
@@ -0,0 +1,11 @@
|
||||
package sun.util.resources.ar;
|
||||
|
||||
import java.util.ListResourceBundle;
|
||||
|
||||
public final class CurrencyNames_ar_EG extends sun.util.resources.LocaleNamesBundle {
|
||||
protected final Object[][] getContents() {
|
||||
return new Object[][] {
|
||||
{ "EGP", "\u062C.\u0645.\u200F" },
|
||||
};
|
||||
}
|
||||
}
|
||||
11
jdkSrc/jdk8/sun/util/resources/ar/CurrencyNames_ar_IQ.java
Normal file
11
jdkSrc/jdk8/sun/util/resources/ar/CurrencyNames_ar_IQ.java
Normal file
@@ -0,0 +1,11 @@
|
||||
package sun.util.resources.ar;
|
||||
|
||||
import java.util.ListResourceBundle;
|
||||
|
||||
public final class CurrencyNames_ar_IQ extends sun.util.resources.LocaleNamesBundle {
|
||||
protected final Object[][] getContents() {
|
||||
return new Object[][] {
|
||||
{ "IQD", "\u062F.\u0639.\u200F" },
|
||||
};
|
||||
}
|
||||
}
|
||||
11
jdkSrc/jdk8/sun/util/resources/ar/CurrencyNames_ar_JO.java
Normal file
11
jdkSrc/jdk8/sun/util/resources/ar/CurrencyNames_ar_JO.java
Normal file
@@ -0,0 +1,11 @@
|
||||
package sun.util.resources.ar;
|
||||
|
||||
import java.util.ListResourceBundle;
|
||||
|
||||
public final class CurrencyNames_ar_JO extends sun.util.resources.LocaleNamesBundle {
|
||||
protected final Object[][] getContents() {
|
||||
return new Object[][] {
|
||||
{ "JOD", "\u062F.\u0623.\u200F" },
|
||||
};
|
||||
}
|
||||
}
|
||||
11
jdkSrc/jdk8/sun/util/resources/ar/CurrencyNames_ar_KW.java
Normal file
11
jdkSrc/jdk8/sun/util/resources/ar/CurrencyNames_ar_KW.java
Normal file
@@ -0,0 +1,11 @@
|
||||
package sun.util.resources.ar;
|
||||
|
||||
import java.util.ListResourceBundle;
|
||||
|
||||
public final class CurrencyNames_ar_KW extends sun.util.resources.LocaleNamesBundle {
|
||||
protected final Object[][] getContents() {
|
||||
return new Object[][] {
|
||||
{ "KWD", "\u062F.\u0643.\u200F" },
|
||||
};
|
||||
}
|
||||
}
|
||||
11
jdkSrc/jdk8/sun/util/resources/ar/CurrencyNames_ar_LB.java
Normal file
11
jdkSrc/jdk8/sun/util/resources/ar/CurrencyNames_ar_LB.java
Normal file
@@ -0,0 +1,11 @@
|
||||
package sun.util.resources.ar;
|
||||
|
||||
import java.util.ListResourceBundle;
|
||||
|
||||
public final class CurrencyNames_ar_LB extends sun.util.resources.LocaleNamesBundle {
|
||||
protected final Object[][] getContents() {
|
||||
return new Object[][] {
|
||||
{ "LBP", "\u0644.\u0644.\u200F" },
|
||||
};
|
||||
}
|
||||
}
|
||||
11
jdkSrc/jdk8/sun/util/resources/ar/CurrencyNames_ar_LY.java
Normal file
11
jdkSrc/jdk8/sun/util/resources/ar/CurrencyNames_ar_LY.java
Normal file
@@ -0,0 +1,11 @@
|
||||
package sun.util.resources.ar;
|
||||
|
||||
import java.util.ListResourceBundle;
|
||||
|
||||
public final class CurrencyNames_ar_LY extends sun.util.resources.LocaleNamesBundle {
|
||||
protected final Object[][] getContents() {
|
||||
return new Object[][] {
|
||||
{ "LYD", "\u062F.\u0644.\u200F" },
|
||||
};
|
||||
}
|
||||
}
|
||||
11
jdkSrc/jdk8/sun/util/resources/ar/CurrencyNames_ar_MA.java
Normal file
11
jdkSrc/jdk8/sun/util/resources/ar/CurrencyNames_ar_MA.java
Normal file
@@ -0,0 +1,11 @@
|
||||
package sun.util.resources.ar;
|
||||
|
||||
import java.util.ListResourceBundle;
|
||||
|
||||
public final class CurrencyNames_ar_MA extends sun.util.resources.LocaleNamesBundle {
|
||||
protected final Object[][] getContents() {
|
||||
return new Object[][] {
|
||||
{ "MAD", "\u062F.\u0645.\u200F" },
|
||||
};
|
||||
}
|
||||
}
|
||||
11
jdkSrc/jdk8/sun/util/resources/ar/CurrencyNames_ar_OM.java
Normal file
11
jdkSrc/jdk8/sun/util/resources/ar/CurrencyNames_ar_OM.java
Normal file
@@ -0,0 +1,11 @@
|
||||
package sun.util.resources.ar;
|
||||
|
||||
import java.util.ListResourceBundle;
|
||||
|
||||
public final class CurrencyNames_ar_OM extends sun.util.resources.LocaleNamesBundle {
|
||||
protected final Object[][] getContents() {
|
||||
return new Object[][] {
|
||||
{ "OMR", "\u0631.\u0639.\u200F" },
|
||||
};
|
||||
}
|
||||
}
|
||||
11
jdkSrc/jdk8/sun/util/resources/ar/CurrencyNames_ar_QA.java
Normal file
11
jdkSrc/jdk8/sun/util/resources/ar/CurrencyNames_ar_QA.java
Normal file
@@ -0,0 +1,11 @@
|
||||
package sun.util.resources.ar;
|
||||
|
||||
import java.util.ListResourceBundle;
|
||||
|
||||
public final class CurrencyNames_ar_QA extends sun.util.resources.LocaleNamesBundle {
|
||||
protected final Object[][] getContents() {
|
||||
return new Object[][] {
|
||||
{ "QAR", "\u0631.\u0642.\u200F" },
|
||||
};
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user