com.ibm.icu.impl.ValidIdentifiers Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of icu4j Show documentation
Show all versions of icu4j Show documentation
International Component for Unicode for Java (ICU4J) is a mature, widely used Java library
providing Unicode and Globalization support
// © 2016 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html
/*
*******************************************************************************
* Copyright (C) 2015-2016, International Business Machines Corporation and
* others. All Rights Reserved.
*******************************************************************************
*/
package com.ibm.icu.impl;
import java.util.Collections;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import com.ibm.icu.impl.locale.AsciiUtil;
import com.ibm.icu.util.UResourceBundle;
import com.ibm.icu.util.UResourceBundleIterator;
/**
* @author markdavis
*
*/
public class ValidIdentifiers {
public enum Datatype {
currency,
language,
region,
script,
subdivision,
unit,
variant,
u,
t,
x,
illegal
}
public enum Datasubtype {
deprecated,
private_use,
regular,
special,
unknown,
macroregion,
reserved,
}
public static class ValiditySet {
public final Set regularData;
public final Map> subdivisionData;
public ValiditySet(Set plainData, boolean makeMap) {
if (makeMap) {
HashMap> _subdivisionData = new HashMap>();
for (String s : plainData) {
int pos = s.indexOf('-'); // read v28 data also
int pos2 = pos+1;
if (pos < 0) {
pos2 = pos = s.charAt(0) < 'A' ? 3 : 2;
}
final String key = s.substring(0, pos);
final String subdivision = s.substring(pos2);
Set oldSet = _subdivisionData.get(key);
if (oldSet == null) {
_subdivisionData.put(key, oldSet = new HashSet());
}
oldSet.add(subdivision);
}
this.regularData = null;
HashMap> _subdivisionData2 = new HashMap>();
// protect the sets
for (Entry> e : _subdivisionData.entrySet()) {
Set value = e.getValue();
// optimize a bit by using singleton
Set set = value.size() == 1 ? Collections.singleton(value.iterator().next())
: Collections.unmodifiableSet(value);
_subdivisionData2.put(e.getKey(), set);
}
this.subdivisionData = Collections.unmodifiableMap(_subdivisionData2);
} else {
this.regularData = Collections.unmodifiableSet(plainData);
this.subdivisionData = null;
}
}
public boolean contains(String code) {
if (regularData != null) {
return regularData.contains(code);
} else {
int pos = code.indexOf('-');
String key = code.substring(0,pos);
final String value = code.substring(pos+1);
return contains(key, value);
}
}
public boolean contains(String key, String value) {
Set oldSet = subdivisionData.get(key);
return oldSet != null && oldSet.contains(value);
}
@Override
public String toString() {
if (regularData != null) {
return regularData.toString();
} else {
return subdivisionData.toString();
}
}
}
private static class ValidityData {
static final Map> data;
static {
Map> _data = new EnumMap>(Datatype.class);
UResourceBundle suppData = UResourceBundle.getBundleInstance(
ICUData.ICU_BASE_NAME,
"supplementalData",
ICUResourceBundle.ICU_DATA_CLASS_LOADER);
UResourceBundle validityInfo = suppData.get("idValidity");
for(UResourceBundleIterator datatypeIterator = validityInfo.getIterator();
datatypeIterator.hasNext();) {
UResourceBundle datatype = datatypeIterator.next();
String rawKey = datatype.getKey();
Datatype key = Datatype.valueOf(rawKey);
Map values = new EnumMap(Datasubtype.class);
for(UResourceBundleIterator datasubtypeIterator = datatype.getIterator();
datasubtypeIterator.hasNext();) {
UResourceBundle datasubtype = datasubtypeIterator.next();
String rawsubkey = datasubtype.getKey();
Datasubtype subkey = Datasubtype.valueOf(rawsubkey);
// handle single value specially
Set subvalues = new HashSet();
if (datasubtype.getType() == UResourceBundle.STRING) {
addRange(datasubtype.getString(), subvalues);
} else {
for (String string : datasubtype.getStringArray()) {
addRange(string, subvalues);
}
}
values.put(subkey, new ValiditySet(subvalues, key == Datatype.subdivision));
}
_data.put(key, Collections.unmodifiableMap(values));
}
data = Collections.unmodifiableMap(_data);
}
private static void addRange(String string, Set subvalues) {
string = AsciiUtil.toLowerString(string);
int pos = string.indexOf('~');
if (pos < 0) {
subvalues.add(string);
} else {
StringRange.expand(string.substring(0,pos), string.substring(pos+1), false, subvalues);
}
}
}
public static Map> getData() {
return ValidityData.data;
}
/**
* Returns the Datasubtype containing the code, or null if there is none.
*/
public static Datasubtype isValid(Datatype datatype, Set datasubtypes, String code) {
Map subtable = ValidityData.data.get(datatype);
if (subtable != null) {
for (Datasubtype datasubtype : datasubtypes) {
ValiditySet validitySet = subtable.get(datasubtype);
if (validitySet != null) {
if (validitySet.contains(AsciiUtil.toLowerString(code))) {
return datasubtype;
}
}
}
}
return null;
}
public static Datasubtype isValid(Datatype datatype, Set datasubtypes, String code, String value) {
Map subtable = ValidityData.data.get(datatype);
if (subtable != null) {
code = AsciiUtil.toLowerString(code);
value = AsciiUtil.toLowerString(value);
for (Datasubtype datasubtype : datasubtypes) {
ValiditySet validitySet = subtable.get(datasubtype);
if (validitySet != null) {
if (validitySet.contains(code, value)) {
return datasubtype;
}
}
}
}
return null;
}
}