/*
* Copyright 2001-2009 Stephen Colebourne
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.joda.time.chrono;
import java.lang.ref.WeakReference;
import java.text.DateFormatSymbols;
import java.util.Locale;
import java.util.TreeMap;
import java.util.WeakHashMap;
import org.joda.time.DateTimeFieldType;
import org.joda.time.DateTimeUtils;
import org.joda.time.IllegalFieldValueException;
/**
* Utility class used by a few of the GJDateTimeFields.
*
* @author Brian S O'Neill
* @since 1.0
*/
class GJLocaleSymbols {
private static final int FAST_CACHE_SIZE = 64;
private static final GJLocaleSymbols[] cFastCache = new GJLocaleSymbols[FAST_CACHE_SIZE];
private static WeakHashMap<Locale, GJLocaleSymbols> cCache = new WeakHashMap<Locale, GJLocaleSymbols>();
public static GJLocaleSymbols forLocale(Locale locale) {
if (locale == null) {
locale = Locale.getDefault();
}
int index = System.identityHashCode(locale) & (FAST_CACHE_SIZE - 1);
GJLocaleSymbols symbols = cFastCache[index];
if (symbols != null && symbols.iLocale.get() == locale) {
return symbols;
}
synchronized (cCache) {
symbols = cCache.get(locale);
if (symbols == null) {
symbols = new GJLocaleSymbols(locale);
cCache.put(locale, symbols);
}
}
cFastCache[index] = symbols;
return symbols;
}
private static String[] realignMonths(String[] months) {
String[] a = new String[13];
for (int i=1; i<13; i++) {
a[i] = months[i - 1];
}
return a;
}
private static String[] realignDaysOfWeek(String[] daysOfWeek) {
String[] a = new String[8];
for (int i=1; i<8; i++) {
a[i] = daysOfWeek[(i < 7) ? i + 1 : 1];
}
return a;
}
private static void addSymbols(TreeMap<String, Integer> map, String[] symbols, Integer[] integers) {
for (int i=symbols.length; --i>=0; ) {
String symbol = symbols[i];
if (symbol != null) {
map.put(symbol, integers[i]);
}
}
}
private static void addNumerals(TreeMap<String, Integer> map, int start, int end, Integer[] integers) {
for (int i=start; i<=end; i++) {
map.put(String.valueOf(i).intern(), integers[i]);
}
}
private static int maxLength(String[] a) {
int max = 0;
for (int i=a.length; --i>=0; ) {
String s = a[i];
if (s != null) {
int len = s.length();
if (len > max) {
max = len;
}
}
}
return max;
}
private final WeakReference<Locale> iLocale;
private final String[] iEras;
private final String[] iDaysOfWeek;
private final String[] iShortDaysOfWeek;
private final String[] iMonths;
private final String[] iShortMonths;
private final String[] iHalfday;
private final TreeMap<String, Integer> iParseEras;
private final TreeMap<String, Integer> iParseDaysOfWeek;
private final TreeMap<String, Integer> iParseMonths;
private final int iMaxEraLength;
private final int iMaxDayOfWeekLength;
private final int iMaxShortDayOfWeekLength;
private final int iMaxMonthLength;
private final int iMaxShortMonthLength;
private final int iMaxHalfdayLength;
/**
* @param locale must not be null
*/
private GJLocaleSymbols(Locale locale) {
iLocale = new WeakReference<Locale>(locale);
DateFormatSymbols dfs = DateTimeUtils.getDateFormatSymbols(locale);
iEras = dfs.getEras();
iDaysOfWeek = realignDaysOfWeek(dfs.getWeekdays());
iShortDaysOfWeek = realignDaysOfWeek(dfs.getShortWeekdays());
iMonths = realignMonths(dfs.getMonths());
iShortMonths = realignMonths(dfs.getShortMonths());
iHalfday = dfs.getAmPmStrings();
Integer[] integers = new Integer[13];
for (int i=0; i<13; i++) {
integers[i] = Integer.valueOf(i);
}
iParseEras = new TreeMap<String, Integer>(String.CASE_INSENSITIVE_ORDER);
addSymbols(iParseEras, iEras, integers);
if ("en".equals(locale.getLanguage())) {
// Include support for parsing "BCE" and "CE" if the language is
// English. At some point Joda-Time will need an independent set of
// localized symbols and not depend on java.text.DateFormatSymbols.
iParseEras.put("BCE", integers[0]);
iParseEras.put("CE", integers[1]);
}
iParseDaysOfWeek = new TreeMap<String, Integer>(String.CASE_INSENSITIVE_ORDER);
addSymbols(iParseDaysOfWeek, iDaysOfWeek, integers);
addSymbols(iParseDaysOfWeek, iShortDaysOfWeek, integers);
addNumerals(iParseDaysOfWeek, 1, 7, integers);
iParseMonths = new TreeMap<String, Integer>(String.CASE_INSENSITIVE_ORDER);
addSymbols(iParseMonths, iMonths, integers);
addSymbols(iParseMonths, iShortMonths, integers);
addNumerals(iParseMonths, 1, 12, integers);
iMaxEraLength = maxLength(iEras);
iMaxDayOfWeekLength = maxLength(iDaysOfWeek);
iMaxShortDayOfWeekLength = maxLength(iShortDaysOfWeek);
iMaxMonthLength = maxLength(iMonths);
iMaxShortMonthLength = maxLength(iShortMonths);
iMaxHalfdayLength = maxLength(iHalfday);
}
public String eraValueToText(int value) {
return iEras[value];
}
public int eraTextToValue(String text) {
Integer era = iParseEras.get(text);
if (era != null) {
return era.intValue();
}
throw new IllegalFieldValueException(DateTimeFieldType.era(), text);
}
public int getEraMaxTextLength() {
return iMaxEraLength;
}
public String monthOfYearValueToText(int value) {
return iMonths[value];
}
public String monthOfYearValueToShortText(int value) {
return iShortMonths[value];
}
public int monthOfYearTextToValue(String text) {
Integer month = iParseMonths.get(text);
if (month != null) {
return month.intValue();
}
throw new IllegalFieldValueException(DateTimeFieldType.monthOfYear(), text);
}
public int getMonthMaxTextLength() {
return iMaxMonthLength;
}
public int getMonthMaxShortTextLength() {
return iMaxShortMonthLength;
}
public String dayOfWeekValueToText(int value) {
return iDaysOfWeek[value];
}
public String dayOfWeekValueToShortText(int value) {
return iShortDaysOfWeek[value];
}
public int dayOfWeekTextToValue(String text) {
Integer day = iParseDaysOfWeek.get(text);
if (day != null) {
return day.intValue();
}
throw new IllegalFieldValueException(DateTimeFieldType.dayOfWeek(), text);
}
public int getDayOfWeekMaxTextLength() {
return iMaxDayOfWeekLength;
}
public int getDayOfWeekMaxShortTextLength() {
return iMaxShortDayOfWeekLength;
}
public String halfdayValueToText(int value) {
return iHalfday[value];
}
public int halfdayTextToValue(String text) {
String[] halfday = iHalfday;
for (int i = halfday.length; --i>=0; ) {
if (halfday[i].equalsIgnoreCase(text)) {
return i;
}
}
throw new IllegalFieldValueException(DateTimeFieldType.halfdayOfDay(), text);
}
public int getHalfdayMaxTextLength() {
return iMaxHalfdayLength;
}
}