blob: aa39c3f01f4ce339c7cb6ca217e304a10a32be78 [file] [log] [blame]
/*
*******************************************************************************
* Copyright (C) 2009, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*/
package com.ibm.icu.impl.locale;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import com.ibm.icu.impl.Utility;
public final class InternalLocaleBuilder {
private String _language = "";
private String _script = "";
private String _region = "";
private String _variant = "";
private FieldHandler _handler = FieldHandler.DEFAULT;
private TreeMap/*<String,String>*/ _extensions;
private TreeMap/*<String,String>*/ _keywords;
private String _privateuse = "";
private static final char PRIVUSE = 'x';
private static final char LOCALESINGLETON = 'u';
private static final String LANGTAGSEP = "-";
private static final String LOCALESEP = "_";
public InternalLocaleBuilder() {
}
public InternalLocaleBuilder(FieldHandler handler) {
_handler = handler;
}
public String setLanguage(String language) {
if (language == null || language.length() == 0) {
_language = "";
} else {
String newval = _handler.process(FieldType.LANGUAGE, language);
if (newval == null) {
return null;
}
_language = newval;
}
return _language;
}
public String setScript(String script) {
if (script == null || script.length() == 0) {
_script = "";
} else {
String newval = _handler.process(FieldType.SCRIPT, script);
if (newval == null) {
return null;
}
_script = newval;
}
return _script;
}
public String setRegion(String region) {
if (region == null || region.length() == 0) {
_region = "";
} else {
String newval = _handler.process(FieldType.REGION, region);
if (newval == null) {
return null;
}
_region = newval;
}
return _region;
}
public String setVariant(String variant) {
if (variant == null || variant.length() == 0) {
_variant = "";
} else {
String newval = _handler.process(FieldType.VARIANT, variant);
if (newval == null) {
return null;
}
_variant = newval;
}
return _variant;
}
public boolean setLocaleKeyword(String key, String type) {
if (key == null || key.length() == 0) {
throw new IllegalArgumentException("The specified key is null or empty");
}
if (type == null || type.length() == 0) {
if (_keywords != null) {
_keywords.remove(key);
}
return true;
}
key = _handler.process(FieldType.LOCALEKEY, key);
type = _handler.process(FieldType.LOCALETYPE, type);
if (key == null || type == null) {
return false;
}
if (_keywords == null) {
_keywords = new TreeMap/*<String,String>*/();
}
_keywords.put(key, type);
return true;
}
public boolean setExtension(char singleton, String value) {
if (!AsciiUtil.isAlphaNumeric(singleton)) {
throw new IllegalArgumentException("Letter '" + singleton
+ "' cannot be used for the singleton extensions.");
}
// singleton char to lower case
singleton = AsciiUtil.toLower(singleton);
if (singleton == PRIVUSE) {
throw new IllegalArgumentException("Letter '" + singleton
+ "' is reserved for the private use.");
}
//value = value.replaceAll(LANGTAGSEP, LOCALESEP);
value = Utility.replaceAll(value, LANGTAGSEP, LOCALESEP);
if (singleton == LOCALESINGLETON) {
// keep locale keywords maintained in _keywords
Map/*<String,String>*/ kwds = LocaleExtension.parseKeywordSubtags(value, LOCALESEP);
Set/*<Map.Entry<String,String>>*/ entries = kwds.entrySet();
// check if all key/type pairs are valid, so we can put the set of key/type
// pairs atomically.
Map/*<String,String>*/ validkwds = new HashMap/*<String,String>*/(kwds.size());
Iterator itr = entries.iterator();
//for (Map.Entry<String,String> entry : entries) {
while (itr.hasNext()) {
Map.Entry entry = (Map.Entry)itr.next();
String kwkey = _handler.process(FieldType.LOCALEKEY, (String)entry.getKey());
String kwtype = _handler.process(FieldType.LOCALETYPE, (String)entry.getValue());
if (kwkey == null || kwtype == null) {
return false;
}
validkwds.put(kwkey, kwtype);
}
// put the validated key/type pairs in _keywords
Set/*<Map.Entry<String,String>>*/ newentries = validkwds.entrySet();
Iterator itrn = newentries.iterator();
//for (Map.Entry<String,String> newentry : newentries) {
while (itrn.hasNext()) {
Map.Entry newentry = (Map.Entry)itrn.next();
_keywords.put(newentry.getKey(), newentry.getValue());
}
} else {
if (value == null || value.length() == 0) {
if (_extensions != null) {
_extensions.remove(String.valueOf(singleton));
}
} else {
value = _handler.process(FieldType.EXTENSION, value);
if (value == null) {
return false;
}
if (_extensions == null) {
_extensions = new TreeMap/*<String,String>*/();
}
_extensions.put(String.valueOf(singleton).intern(), value);
}
}
return true;
}
public String setPrivateUse(String privuse) {
if (privuse == null || privuse.length() == 0) {
_privateuse = "";
} else {
//String newval = _handler.process(FieldType.PRIVATEUSE, privuse.replaceAll(LANGTAGSEP, LOCALESEP));
String newval = _handler.process(FieldType.PRIVATEUSE, Utility.replaceAll(privuse, LANGTAGSEP, LOCALESEP));
if (newval == null) {
return null;
}
_privateuse = newval;
}
return _privateuse;
}
public InternalLocaleBuilder removeLocaleExtension() {
_keywords = null;
_extensions = null;
_privateuse = "";
return this;
}
public BaseLocale getBaseLocale() {
return BaseLocale.get(_language, _script, _region, _variant);
}
public LocaleExtension getLocaleExtension() {
TreeMap/*<String,String>*/ map = null;
if (_extensions != null || _keywords != null) {
// Create a new map
map = new TreeMap/*<String,String>*/();
if (_extensions != null) {
map.putAll(_extensions);
}
if (_keywords != null) {
// Add keywords as an extension
StringBuffer buf = new StringBuffer();
String lockwd = LocaleExtension.mapToLocaleExtensionString(_keywords, buf);
map.put(String.valueOf(LOCALESINGLETON), lockwd);
}
}
return LocaleExtension.get(map, _privateuse);
}
// protected enum FieldType {
// LANGUAGE,
// SCRIPT,
// REGION,
// VARIANT,
// LOCALEKEY,
// LOCALETYPE,
// EXTENSION,
// PRIVATEUSE
// }
protected static interface FieldType {
public static final int LANGUAGE = 0;
public static final int SCRIPT = 1;
public static final int REGION = 2;
public static final int VARIANT = 3;
public static final int LOCALEKEY = 4;
public static final int LOCALETYPE = 5;
public static final int EXTENSION = 6;
public static final int PRIVATEUSE = 7;
}
public static class FieldHandler {
public static final int LANGUAGE = FieldType.LANGUAGE;
public static final int SCRIPT = FieldType.SCRIPT;
public static final int REGION = FieldType.REGION;
public static final int VARIANT = FieldType.VARIANT;
public static final int LOCALEKEY = FieldType.LOCALEKEY;
public static final int LOCALETYPE = FieldType.LOCALETYPE;
public static final int EXTENSION = FieldType.EXTENSION;
public static final int PRIVATEUSE = FieldType.PRIVATEUSE;
public static FieldHandler DEFAULT = new FieldHandler();
protected FieldHandler() {
}
//public String process(FieldType type, String value) {
public String process(int type, String value) {
value = map(type, value);
if (!validate(type, value)) {
return null;
}
return value.intern();
}
//protected String map(FieldType type, String value) {
protected String map(int type, String value) {
switch (type) {
case LANGUAGE:
value = LanguageCode.getShortest(AsciiUtil.toLowerString(value));
break;
case SCRIPT:
//TODO
break;
case REGION:
value = AsciiUtil.toLowerString(value);
break;
case VARIANT:
// Java variant is case sensitive
break;
case LOCALEKEY:
case LOCALETYPE:
case EXTENSION:
case PRIVATEUSE:
value = AsciiUtil.toLowerString(value);
break;
}
return value;
}
//protected boolean validate(FieldType type, String value) {
protected boolean validate(int type, String value) {
boolean isValid = false;
String[] subtags;
switch (type) {
case LANGUAGE:
isValid = LanguageTag.isLanguageSubtag(value);
break;
case SCRIPT:
isValid = LanguageTag.isScriptSubtag(value);
break;
case REGION:
isValid = LanguageTag.isRegionSubtag(value);
break;
case VARIANT:
isValid = LanguageTag.isVariantSubtag(value);
break;
case LOCALEKEY:
isValid = LanguageTag.isExtensionSubtag(value);
break;
case LOCALETYPE:
isValid = LanguageTag.isExtensionSubtag(value);
break;
case EXTENSION:
//subtags = value.split(LOCALESEP);
subtags = Utility.split(value, LOCALESEP.charAt(0));
//for (String subtag : subtags) {
for (int i = 0; i < subtags.length; i++) {
String subtag = subtags[i];
isValid = LanguageTag.isExtensionSubtag(subtag);
}
break;
case PRIVATEUSE:
//subtags = value.split(LOCALESEP);
subtags = Utility.split(value, LOCALESEP.charAt(0));
//for (String subtag : subtags) {
for (int i = 0; i < subtags.length; i++) {
String subtag = subtags[i];
isValid = LanguageTag.isPrivateuseValueSubtag(subtag);
}
break;
}
return isValid;
}
}
}