diff options
Diffstat (limited to 'java/src/com/android/i18n/addressinput/ClientData.java')
-rw-r--r-- | java/src/com/android/i18n/addressinput/ClientData.java | 450 |
1 files changed, 225 insertions, 225 deletions
diff --git a/java/src/com/android/i18n/addressinput/ClientData.java b/java/src/com/android/i18n/addressinput/ClientData.java index f0b2fc0..8e23f3a 100644 --- a/java/src/com/android/i18n/addressinput/ClientData.java +++ b/java/src/com/android/i18n/addressinput/ClientData.java @@ -35,264 +35,264 @@ import java.util.Set; */ public class ClientData implements DataSource { - private static final String TAG = "ClientData"; - - /** - * Data to bootstrap the process. The data are all regional (country level) - * data. Keys are like "data/US/CA" - */ - private final Map<String, JsoMap> mBootstrapMap = new HashMap<String, JsoMap>(); - - private CacheData mCacheData; - - public ClientData(CacheData cacheData) { - this.mCacheData = cacheData; - buildRegionalData(); + private static final String TAG = "ClientData"; + + /** + * Data to bootstrap the process. The data are all regional (country level) + * data. Keys are like "data/US/CA" + */ + private final Map<String, JsoMap> bootstrapMap = new HashMap<String, JsoMap>(); + + private CacheData cacheData; + + public ClientData(CacheData cacheData) { + this.cacheData = cacheData; + buildRegionalData(); + } + + @Override + public AddressVerificationNodeData get(String key) { + JsoMap jso = cacheData.getObj(key); + if (jso == null) { // Not cached. + fetchDataIfNotAvailable(key); + jso = cacheData.getObj(key); } - - @Override - public AddressVerificationNodeData get(String key) { - JsoMap jso = mCacheData.getObj(key); - if (jso == null) { // Not cached. - fetchDataIfNotAvailable(key); - jso = mCacheData.getObj(key); - } - if (jso != null && isValidDataKey(key)) { - return createNodeData(jso); - } - return null; + if (jso != null && isValidDataKey(key)) { + return createNodeData(jso); + } + return null; + } + + @Override + public AddressVerificationNodeData getDefaultData(String key) { + // root data + if (key.split("/").length == 1) { + JsoMap jso = bootstrapMap.get(key); + if (jso == null || !isValidDataKey(key)) { + throw new RuntimeException("key " + key + " does not have bootstrap data"); + } + return createNodeData(jso); } - @Override - public AddressVerificationNodeData getDefaultData(String key) { - // root data - if (key.split("/").length == 1) { - JsoMap jso = mBootstrapMap.get(key); - if (jso == null || !isValidDataKey(key)) { - throw new RuntimeException("key " + key + " does not have bootstrap data"); - } - return createNodeData(jso); - } + key = getCountryKey(key); + JsoMap jso = bootstrapMap.get(key); + if (jso == null || !isValidDataKey(key)) { + throw new RuntimeException("key " + key + " does not have bootstrap data"); + } + return createNodeData(jso); + } - key = getCountryKey(key); - JsoMap jso = mBootstrapMap.get(key); - if (jso == null || !isValidDataKey(key)) { - throw new RuntimeException("key " + key + " does not have bootstrap data"); - } - return createNodeData(jso); + private String getCountryKey(String hierarchyKey) { + if (hierarchyKey.split("/").length <= 1) { + throw new RuntimeException("Cannot get country key with key '" + hierarchyKey + "'"); + } + if (isCountryKey(hierarchyKey)) { + return hierarchyKey; } - private String getCountryKey(String hierarchyKey) { - if (hierarchyKey.split("/").length <= 1) { - throw new RuntimeException("Cannot get country key with key '" + hierarchyKey + "'"); - } - if (isCountryKey(hierarchyKey)) { - return hierarchyKey; - } + String[] parts = hierarchyKey.split("/"); - String[] parts = hierarchyKey.split("/"); + return new StringBuilder().append(parts[0]) + .append("/") + .append(parts[1]) + .toString(); + } - return new StringBuilder().append(parts[0]) - .append("/") - .append(parts[1]) - .toString(); - } + private boolean isCountryKey(String hierarchyKey) { + Util.checkNotNull(hierarchyKey, "Cannot use null as a key"); + return hierarchyKey.split("/").length == 2; + } - private boolean isCountryKey(String hierarchyKey) { - Util.checkNotNull(hierarchyKey, "Cannot use null as a key"); - return hierarchyKey.split("/").length == 2; - } + /** + * Returns the contents of the JSON-format string as a map. + */ + protected AddressVerificationNodeData createNodeData(JsoMap jso) { + Map<AddressDataKey, String> map = + new EnumMap<AddressDataKey, String>(AddressDataKey.class); - /** - * Returns the contents of the JSON-format string as a map. - */ - protected AddressVerificationNodeData createNodeData(JsoMap jso) { - Map<AddressDataKey, String> map = - new EnumMap<AddressDataKey, String>(AddressDataKey.class); - - JSONArray arr = jso.getKeys(); - for (int i = 0; i < arr.length(); i++) { - try { - AddressDataKey key = AddressDataKey.get(arr.getString(i)); - - if (key == null) { - // Not all keys are supported by Android, so we continue if we encounter one - // that is not used. - continue; - } - - String value = jso.get(key.toString().toLowerCase()); - map.put(key, value); - } catch (JSONException e) { - // This should not happen - we should not be fetching a key from outside the bounds - // of the array. - } + JSONArray arr = jso.getKeys(); + for (int i = 0; i < arr.length(); i++) { + try { + AddressDataKey key = AddressDataKey.get(arr.getString(i)); + + if (key == null) { + // Not all keys are supported by Android, so we continue if we encounter one + // that is not used. + continue; } - return new AddressVerificationNodeData(map); + String value = jso.get(key.toString().toLowerCase()); + map.put(key, value); + } catch (JSONException e) { + // This should not happen - we should not be fetching a key from outside the bounds + // of the array. + } } - /** - * We can be initialized with the full set of address information, but validation only uses info - * prefixed with "data" (in particular, no info prefixed with "examples"). - */ - private boolean isValidDataKey(String key) { - return key.startsWith("data"); + return new AddressVerificationNodeData(map); + } + + /** + * We can be initialized with the full set of address information, but validation only uses info + * prefixed with "data" (in particular, no info prefixed with "examples"). + */ + private boolean isValidDataKey(String key) { + return key.startsWith("data"); + } + + /** + * Initializes regionalData structure based on property file. + */ + private void buildRegionalData() { + StringBuilder countries = new StringBuilder(); + + for (String countryCode : RegionDataConstants.getCountryFormatMap().keySet()) { + countries.append(countryCode + "~"); + String json = RegionDataConstants.getCountryFormatMap().get(countryCode); + JsoMap jso = null; + try { + jso = JsoMap.buildJsoMap(json); + } catch (JSONException e) { + // Ignore. + } + + AddressData data = new AddressData.Builder().setCountry(countryCode).build(); + LookupKey key = new LookupKey.Builder(KeyType.DATA).setAddressData(data).build(); + bootstrapMap.put(key.toString(), jso); } + countries.setLength(countries.length() - 1); - /** - * Initializes regionalData structure based on property file. + // TODO: this is messy. do we have better ways to do it? + /* Creates verification data for key="data". This will be used for the + * root FieldVerifier. */ - private void buildRegionalData() { - StringBuilder countries = new StringBuilder(); - - for (String countryCode : RegionDataConstants.getCountryFormatMap().keySet()) { - countries.append(countryCode + "~"); - String json = RegionDataConstants.getCountryFormatMap().get(countryCode); - JsoMap jso = null; - try { - jso = JsoMap.buildJsoMap(json); - } catch (JSONException e) { - // Ignore. - } - - AddressData data = new AddressData.Builder().setCountry(countryCode).build(); - LookupKey key = new LookupKey.Builder(KeyType.DATA).setAddressData(data).build(); - mBootstrapMap.put(key.toString(), jso); - } - countries.setLength(countries.length() - 1); - - // TODO: this is messy. do we have better ways to do it? - /* Creates verification data for key="data". This will be used for the - * root FieldVerifier. - */ - String str = "{\"id\":\"data\",\"" + - AddressDataKey.COUNTRIES.toString().toLowerCase() + - "\": \"" + countries.toString() + "\"}"; - JsoMap jsoData = null; - try { - jsoData = JsoMap.buildJsoMap(str); - } catch (JSONException e) { - // Ignore. - } - mBootstrapMap.put("data", jsoData); + String str = "{\"id\":\"data\",\"" + + AddressDataKey.COUNTRIES.toString().toLowerCase() + + "\": \"" + countries.toString() + "\"}"; + JsoMap jsoData = null; + try { + jsoData = JsoMap.buildJsoMap(str); + } catch (JSONException e) { + // Ignore. } - - /** - * Fetches data from remote server if it is not cached yet. - * - * @param key The key for data that being requested. Key can be either a data key (starts with - * "data") or example key (starts with "examples") - */ - private void fetchDataIfNotAvailable(String key) { - JsoMap jso = mCacheData.getObj(key); - if (jso == null) { - // If there is bootstrap data for the key, pass the data to fetchDynamicData - JsoMap regionalData = mBootstrapMap.get(key); - NotifyingListener listener = new NotifyingListener(this); - // If the key was invalid, we don't want to attempt to fetch it. - if (LookupKey.hasValidKeyPrefix(key)) { - LookupKey lookupKey = new LookupKey.Builder(key).build(); - mCacheData.fetchDynamicData(lookupKey, regionalData, listener); - try { - listener.waitLoadingEnd(); - // Check to see if there is data for this key now. - if (mCacheData.getObj(key) == null && isCountryKey(key)) { - // If not, see if there is data in RegionDataConstants. - Log.i(TAG, "Server failure: looking up key in region data constants."); - mCacheData.getFromRegionDataConstants(lookupKey); - } - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - } + bootstrapMap.put("data", jsoData); + } + + /** + * Fetches data from remote server if it is not cached yet. + * + * @param key The key for data that being requested. Key can be either a data key (starts with + * "data") or example key (starts with "examples") + */ + private void fetchDataIfNotAvailable(String key) { + JsoMap jso = cacheData.getObj(key); + if (jso == null) { + // If there is bootstrap data for the key, pass the data to fetchDynamicData + JsoMap regionalData = bootstrapMap.get(key); + NotifyingListener listener = new NotifyingListener(this); + // If the key was invalid, we don't want to attempt to fetch it. + if (LookupKey.hasValidKeyPrefix(key)) { + LookupKey lookupKey = new LookupKey.Builder(key).build(); + cacheData.fetchDynamicData(lookupKey, regionalData, listener); + try { + listener.waitLoadingEnd(); + // Check to see if there is data for this key now. + if (cacheData.getObj(key) == null && isCountryKey(key)) { + // If not, see if there is data in RegionDataConstants. + Log.i(TAG, "Server failure: looking up key in region data constants."); + cacheData.getFromRegionDataConstants(lookupKey); + } + } catch (InterruptedException e) { + throw new RuntimeException(e); } + } } - - public void requestData(LookupKey key, DataLoadListener listener) { - Util.checkNotNull(key, "Null lookup key not allowed"); - JsoMap regionalData = mBootstrapMap.get(key.toString()); - mCacheData.fetchDynamicData(key, regionalData, listener); + } + + public void requestData(LookupKey key, DataLoadListener listener) { + Util.checkNotNull(key, "Null lookup key not allowed"); + JsoMap regionalData = bootstrapMap.get(key.toString()); + cacheData.fetchDynamicData(key, regionalData, listener); + } + + /** + * Fetches all data for the specified country from the remote server. + */ + public void prefetchCountry(String country, DataLoadListener listener) { + String key = "data/" + country; + Set<RecursiveLoader> loaders = new HashSet<RecursiveLoader>(); + listener.dataLoadingBegin(); + cacheData.fetchDynamicData( + new LookupKey.Builder(key).build(), + null, + new RecursiveLoader(key, loaders, listener)); + } + + /** + * A helper class to recursively load all sub keys using fetchDynamicData(). + */ + private class RecursiveLoader implements DataLoadListener { + + private final String key; + + private final Set<RecursiveLoader> loaders; + + private final DataLoadListener listener; + + public RecursiveLoader(String key, Set<RecursiveLoader> loaders, + DataLoadListener listener) { + this.key = key; + this.loaders = loaders; + this.listener = listener; + + synchronized (loaders) { + loaders.add(this); + } } - /** - * Fetches all data for the specified country from the remote server. - */ - public void prefetchCountry(String country, DataLoadListener listener) { - String key = "data/" + country; - Set<RecursiveLoader> loaders = new HashSet<RecursiveLoader>(); - listener.dataLoadingBegin(); - mCacheData.fetchDynamicData( - new LookupKey.Builder(key).build(), - null, - new RecursiveLoader(key, loaders, listener)); + @Override + public void dataLoadingBegin() { } - /** - * A helper class to recursively load all sub keys using fetchDynamicData(). - */ - private class RecursiveLoader implements DataLoadListener { - - private final String key; + @Override + public void dataLoadingEnd() { + final String subKeys = AddressDataKey.SUB_KEYS.name().toLowerCase(); + final String subMores = AddressDataKey.SUB_MORES.name().toLowerCase(); - private final Set<RecursiveLoader> loaders; + JsoMap map = cacheData.getObj(key); - private final DataLoadListener listener; + if (map.containsKey(subMores)) { + // This key could have sub keys. + String[] mores = map.get(subMores).split("~"); + String[] keys = {}; - public RecursiveLoader(String key, Set<RecursiveLoader> loaders, - DataLoadListener listener) { - this.key = key; - this.loaders = loaders; - this.listener = listener; + if (map.containsKey(subKeys)) { + keys = map.get(subKeys).split("~"); + } - synchronized (loaders) { - loaders.add(this); - } + if (mores.length != keys.length) { // This should never happen. + throw new IndexOutOfBoundsException("mores.length != keys.length"); } - @Override - public void dataLoadingBegin() { + for (int i = 0; i < mores.length; i++) { + if (mores[i].equalsIgnoreCase("true")) { + // This key should have sub keys. + String subKey = key + "/" + keys[i]; + cacheData.fetchDynamicData( + new LookupKey.Builder(subKey).build(), + null, + new RecursiveLoader(subKey, loaders, listener)); + } } + } - @Override - public void dataLoadingEnd() { - final String subKeys = AddressDataKey.SUB_KEYS.name().toLowerCase(); - final String subMores = AddressDataKey.SUB_MORES.name().toLowerCase(); - - JsoMap map = mCacheData.getObj(key); - - if (map.containsKey(subMores)) { - // This key could have sub keys. - String[] mores = map.get(subMores).split("~"); - String[] keys = {}; - - if (map.containsKey(subKeys)) { - keys = map.get(subKeys).split("~"); - } - - if (mores.length != keys.length) { // This should never happen. - throw new IndexOutOfBoundsException("mores.length != keys.length"); - } - - for (int i = 0; i < mores.length; i++) { - if (mores[i].equalsIgnoreCase("true")) { - // This key should have sub keys. - String subKey = key + "/" + keys[i]; - mCacheData.fetchDynamicData( - new LookupKey.Builder(subKey).build(), - null, - new RecursiveLoader(subKey, loaders, listener)); - } - } - } - - synchronized (loaders) { - loaders.remove(this); - if (loaders.isEmpty()) { - listener.dataLoadingEnd(); - } - } + synchronized (loaders) { + loaders.remove(this); + if (loaders.isEmpty()) { + listener.dataLoadingEnd(); } + } } + } } |