/* ******************************************************************************* * Copyright (C) 2009, International Business Machines Corporation and * * others. All Rights Reserved. * ******************************************************************************* */ package com.ibm.icu.impl.locale; import java.util.Collections; import java.util.Set; import java.util.SortedMap; import java.util.TreeMap; import java.util.Map.Entry; import com.ibm.icu.impl.locale.LanguageTag.ParseStatus; public class LocaleExtensions { private SortedMap _map = EMPTY_MAP; private String _id = ""; private static final SortedMap EMPTY_MAP = Collections.unmodifiableSortedMap(new TreeMap()); private static final LocaleObjectCache LOCALEEXTENSIONS_CACHE = new LocaleObjectCache(); public static LocaleExtensions EMPTY_EXTENSIONS = new LocaleExtensions(); public static final LocaleExtensions CALENDAR_JAPANESE; public static final LocaleExtensions NUMBER_THAI; static { CALENDAR_JAPANESE = new LocaleExtensions(); CALENDAR_JAPANESE._id = UnicodeLocaleExtension.CA_JAPANESE.getID(); CALENDAR_JAPANESE._map = new TreeMap(); CALENDAR_JAPANESE._map.put(Character.valueOf(UnicodeLocaleExtension.CA_JAPANESE.getKey()), UnicodeLocaleExtension.CA_JAPANESE); LOCALEEXTENSIONS_CACHE.put(CALENDAR_JAPANESE._id, CALENDAR_JAPANESE); NUMBER_THAI = new LocaleExtensions(); NUMBER_THAI._id = UnicodeLocaleExtension.NU_THAI.getID(); NUMBER_THAI._map = new TreeMap(); NUMBER_THAI._map.put(Character.valueOf(UnicodeLocaleExtension.NU_THAI.getKey()), UnicodeLocaleExtension.NU_THAI); LOCALEEXTENSIONS_CACHE.put(NUMBER_THAI._id, NUMBER_THAI); } private LocaleExtensions() { } public static LocaleExtensions getInstance(String str) throws LocaleSyntaxException { if (str == null || str.length() == 0) { return EMPTY_EXTENSIONS; } LocaleExtensions exts = LOCALEEXTENSIONS_CACHE.get(str); if (exts == null) { StringTokenIterator itr = new StringTokenIterator(str, LanguageTag.SEP); ParseStatus sts = new ParseStatus(); TreeMap map = new TreeMap(); while (!itr.isDone()) { int startOffset = itr.currentEnd(); Extension ext = Extension.create(itr, sts); if (sts.isError()) { throw new LocaleSyntaxException(sts.errorMsg, sts.errorIndex); } if (ext == null) { throw new LocaleSyntaxException("Invalid extension subtag: " + itr.current(), startOffset); } Character keyChar = Character.valueOf(ext.getKey()); if (map.containsKey(keyChar)) { throw new LocaleSyntaxException("Duplicated extension: " + keyChar, startOffset); } map.put(keyChar, ext); } String id = toID(map); // check the cache with canonicalized ID exts = LOCALEEXTENSIONS_CACHE.get(id); if (exts == null) { exts = new LocaleExtensions(); exts._map = map; exts._id = id; exts = LOCALEEXTENSIONS_CACHE.put(id, exts); } } return exts; } static LocaleExtensions getInstance(SortedMap map) { if (map == null || map.isEmpty()) { return EMPTY_EXTENSIONS; } String id = toID(map); LocaleExtensions exts = LOCALEEXTENSIONS_CACHE.get(id); if (exts == null) { exts = new LocaleExtensions(); exts._map = new TreeMap(map); exts._id = id; exts = LOCALEEXTENSIONS_CACHE.put(id, exts); } return exts; } private static String toID(SortedMap map) { StringBuilder buf = new StringBuilder(); Extension privuse = null; if (map != null && !map.isEmpty()) { Set> entries = map.entrySet(); for (Entry entry : entries) { Character key = entry.getKey(); if (key.charValue() == LanguageTag.PRIVATEUSE.charAt(0)) { privuse = entry.getValue(); continue; } if (buf.length() > 0) { buf.append(LanguageTag.SEP); } buf.append(entry.getKey()); buf.append(LanguageTag.SEP); buf.append(entry.getValue().getValue()); } } if (privuse != null) { if (buf.length() > 0) { buf.append(LanguageTag.SEP); } buf.append(LanguageTag.PRIVATEUSE); buf.append(LanguageTag.SEP); buf.append(privuse.getValue()); } return buf.toString(); } public Set getKeys() { return Collections.unmodifiableSet(_map.keySet()); } public Extension getExtension(Character key) { return _map.get(key); } public String getExtensionValue(Character key) { Extension ext = _map.get(key); if (ext == null) { return ""; } return ext.getValue(); } public Set getUnicodeLocaleKeys() { Extension ext = _map.get(Character.valueOf(UnicodeLocaleExtension.SINGLETON)); if (ext == null) { return Collections.emptySet(); } assert (ext instanceof UnicodeLocaleExtension); return ((UnicodeLocaleExtension)ext).getKeys(); } public String getUnicodeLocaleType(String unicodeLocaleKey) { Extension ext = _map.get(Character.valueOf(UnicodeLocaleExtension.SINGLETON)); if (ext == null) { return ""; } assert (ext instanceof UnicodeLocaleExtension); return ((UnicodeLocaleExtension)ext).getType(unicodeLocaleKey); } public String toString() { return _id; } public String getID() { return _id; } public int hashCode() { return _id.hashCode(); } public static boolean isValidKey(String key) { return LanguageTag.isExtensionSingleton(key) || LanguageTag.isPrivateuseSingleton(key); } }