Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / libaddressinput / src / java / src / com / android / i18n / addressinput / FormController.java
index c8c5953..63c69ab 100644 (file)
@@ -29,306 +29,305 @@ import java.util.Queue;
  * values for the next level down in the address hierarchy, if these are known.
  */
 class FormController {
-    // For address hierarchy in lookup key.
-    private static final String SLASH_DELIM = "/";
-    // For joined values.
-    private static final String TILDE_DELIM = "~";
-    // For language code info in lookup key (E.g., data/CA--fr).
-    private static final String DASH_DELIM = "--";
-    private static final LookupKey ROOT_KEY = FormController.getDataKeyForRoot();
-    private static final String DEFAULT_REGION_CODE = "ZZ";
-    private static final AddressField[] ADDRESS_HIERARCHY = {
-            AddressField.COUNTRY,
-            AddressField.ADMIN_AREA,
-            AddressField.LOCALITY,
-            AddressField.DEPENDENT_LOCALITY
-    };
-
-    // Current user language.
-    private String mLanguageCode;
-    private ClientData mIntegratedData;
-    private String mCurrentCountry;
-
-    /**
-     * Constructor that populates this with data. languageCode should be a BCP language code (such
-     * as "en" or "zh-Hant") and currentCountry should be an ISO 2-letter region code (such as "GB"
-     * or "US").
-     */
-    FormController(ClientData integratedData, String languageCode, String currentCountry) {
-        Util.checkNotNull(integratedData, "null data not allowed");
-        mLanguageCode = languageCode;
-        this.mCurrentCountry = currentCountry;
-
-        AddressData address = new AddressData.Builder().setCountry(DEFAULT_REGION_CODE).build();
-        LookupKey defaultCountryKey = getDataKeyFor(address);
-
-        AddressVerificationNodeData defaultCountryData =
-            integratedData.getDefaultData(defaultCountryKey.toString());
-        Util.checkNotNull(defaultCountryData,
-                "require data for default country key: " + defaultCountryKey);
-        this.mIntegratedData = integratedData;
+  // For address hierarchy in lookup key.
+  private static final String SLASH_DELIM = "/";
+  // For joined values.
+  private static final String TILDE_DELIM = "~";
+  // For language code info in lookup key (E.g., data/CA--fr).
+  private static final String DASH_DELIM = "--";
+  private static final LookupKey ROOT_KEY = FormController.getDataKeyForRoot();
+  private static final String DEFAULT_REGION_CODE = "ZZ";
+  private static final AddressField[] ADDRESS_HIERARCHY = {
+    AddressField.COUNTRY,
+    AddressField.ADMIN_AREA,
+    AddressField.LOCALITY,
+    AddressField.DEPENDENT_LOCALITY
+  };
+
+  // Current user language.
+  private String languageCode;
+  private ClientData integratedData;
+  private String currentCountry;
+
+  /**
+   * Constructor that populates this with data. languageCode should be a BCP language code (such
+   * as "en" or "zh-Hant") and currentCountry should be an ISO 2-letter region code (such as "GB"
+   * or "US").
+   */
+  FormController(ClientData integratedData, String languageCode, String currentCountry) {
+    Util.checkNotNull(integratedData, "null data not allowed");
+    this.languageCode = languageCode;
+    this.currentCountry = currentCountry;
+
+    AddressData address = new AddressData.Builder().setCountry(DEFAULT_REGION_CODE).build();
+    LookupKey defaultCountryKey = getDataKeyFor(address);
+
+    AddressVerificationNodeData defaultCountryData =
+        integratedData.getDefaultData(defaultCountryKey.toString());
+    Util.checkNotNull(defaultCountryData,
+        "require data for default country key: " + defaultCountryKey);
+    this.integratedData = integratedData;
+  }
+
+  void setLanguageCode(String languageCode) {
+    this.languageCode = languageCode;
+  }
+
+  void setCurrentCountry(String currentCountry) {
+    this.currentCountry = currentCountry;
+  }
+
+  private ScriptType getScriptType() {
+    if (languageCode != null && Util.isExplicitLatinScript(languageCode)) {
+      return ScriptType.LATIN;
     }
-
-    void setLanguageCode(String languageCode) {
-        mLanguageCode = languageCode;
-    }
-
-    void setCurrentCountry(String currentCountry) {
-        mCurrentCountry = currentCountry;
+    return ScriptType.LOCAL;
+  }
+
+  private static LookupKey getDataKeyForRoot() {
+    AddressData address = new AddressData.Builder().build();
+    return new LookupKey.Builder(KeyType.DATA).setAddressData(address).build();
+  }
+
+  LookupKey getDataKeyFor(AddressData address) {
+    return new LookupKey.Builder(KeyType.DATA).setAddressData(address).build();
+  }
+
+  /**
+   * Requests data for the input address. This method chains multiple requests together. For
+   * example, an address for Mt View, California needs data from "data/US", "data/US/CA", and
+   * "data/US/CA/Mt View" to support it. This method will request them one by one (from top level
+   * key down to the most granular) and evokes {@link DataLoadListener#dataLoadingEnd} method when
+   * all data is collected. If the address is invalid, it will request the first valid child key
+   * instead. For example, a request for "data/US/Foo" will end up requesting data for "data/US",
+   * "data/US/AL".
+   *
+   * @param address  the current address.
+   * @param listener triggered when requested data for the address is returned.
+   */
+  void requestDataForAddress(AddressData address, DataLoadListener listener) {
+    Util.checkNotNull(address.getPostalCountry(), "null country not allowed");
+
+    // Gets the key for deepest available node.
+    Queue<String> subkeys = new LinkedList<String>();
+
+    for (AddressField field : ADDRESS_HIERARCHY) {
+      String value = address.getFieldValue(field);
+      if (value == null) {
+        break;
+      }
+      subkeys.add(value);
     }
-
-    private ScriptType getScriptType() {
-        if (mLanguageCode != null && Util.isExplicitLatinScript(mLanguageCode)) {
-            return ScriptType.LATIN;
-        }
-        return ScriptType.LOCAL;
+    if (subkeys.size() == 0) {
+      throw new RuntimeException("Need at least country level info");
     }
 
-    private static LookupKey getDataKeyForRoot() {
-        AddressData address = new AddressData.Builder().build();
-        return new LookupKey.Builder(KeyType.DATA).setAddressData(address).build();
+    if (listener != null) {
+      listener.dataLoadingBegin();
     }
-
-    LookupKey getDataKeyFor(AddressData address) {
-        return new LookupKey.Builder(KeyType.DATA).setAddressData(address).build();
-    }
-
-    /**
-     * Requests data for the input address. This method chains multiple requests together. For
-     * example, an address for Mt View, California needs data from "data/US", "data/US/CA", and
-     * "data/US/CA/Mt View" to support it. This method will request them one by one (from top level
-     * key down to the most granular) and evokes {@link DataLoadListener#dataLoadingEnd} method when
-     * all data is collected. If the address is invalid, it will request the first valid child key
-     * instead. For example, a request for "data/US/Foo" will end up requesting data for "data/US",
-     * "data/US/AL".
-     *
-     * @param address  the current address.
-     * @param listener triggered when requested data for the address is returned.
-     */
-    void requestDataForAddress(AddressData address, DataLoadListener listener) {
-        Util.checkNotNull(address.getPostalCountry(), "null country not allowed");
-
-        // Gets the key for deepest available node.
-        Queue<String> subkeys = new LinkedList<String>();
-
-        for (AddressField field : ADDRESS_HIERARCHY) {
-            String value = address.getFieldValue(field);
-            if (value == null) {
-                break;
+    requestDataRecursively(ROOT_KEY, subkeys, listener);
+  }
+
+  private void requestDataRecursively(final LookupKey key,
+      final Queue<String> subkeys, final DataLoadListener listener) {
+    Util.checkNotNull(key, "Null key not allowed");
+    Util.checkNotNull(subkeys, "Null subkeys not allowed");
+
+    integratedData.requestData(key, new DataLoadListener() {
+      @Override
+      public void dataLoadingBegin() {
+      }
+
+      @Override
+      public void dataLoadingEnd() {
+        List<RegionData> subregions = getRegionData(key);
+        if (subregions.isEmpty()) {
+          if (listener != null) {
+            listener.dataLoadingEnd();
+          }
+          // TODO: Should update the selectors here.
+          return;
+        } else if (subkeys.size() > 0) {
+          String subkey = subkeys.remove();
+          for (RegionData subregion : subregions) {
+            if (subregion.isValidName(subkey)) {
+              LookupKey nextKey = buildDataLookupKey(key, subregion.getKey());
+              requestDataRecursively(nextKey, subkeys, listener);
+              return;
             }
-            subkeys.add(value);
-        }
-        if (subkeys.size() == 0) {
-            throw new RuntimeException("Need at least country level info");
+          }
         }
 
-        if (listener != null) {
-            listener.dataLoadingBegin();
-        }
-        requestDataRecursively(ROOT_KEY, subkeys, listener);
+        // Current value in the field is not valid, use the first valid subkey
+        // to request more data instead.
+        String firstSubkey = subregions.get(0).getKey();
+        LookupKey nextKey = buildDataLookupKey(key, firstSubkey);
+        Queue<String> emptyList = new LinkedList<String>();
+        requestDataRecursively(nextKey, emptyList, listener);
+      }
+    });
+  }
+
+  private LookupKey buildDataLookupKey(LookupKey lookupKey, String subKey) {
+    String[] subKeys = lookupKey.toString().split(SLASH_DELIM);
+    String languageCodeSubTag =
+        (languageCode == null) ? null : Util.getLanguageSubtag(languageCode);
+    String key = lookupKey.toString() + SLASH_DELIM + subKey;
+
+    // Country level key
+    if (subKeys.length == 1 &&
+        languageCodeSubTag != null && !isDefaultLanguage(languageCodeSubTag)) {
+      key += DASH_DELIM + languageCodeSubTag.toString();
     }
-
-    private void requestDataRecursively(final LookupKey key,
-            final Queue<String> subkeys, final DataLoadListener listener) {
-        Util.checkNotNull(key, "Null key not allowed");
-        Util.checkNotNull(subkeys, "Null subkeys not allowed");
-
-        mIntegratedData.requestData(key, new DataLoadListener() {
-            @Override
-            public void dataLoadingBegin() {
-            }
-
-            @Override
-            public void dataLoadingEnd() {
-                List<RegionData> subregions = getRegionData(key);
-                if (subregions.isEmpty()) {
-                    if (listener != null) {
-                        listener.dataLoadingEnd();
-                    }
-                    // TODO: Should update the selectors here.
-                    return;
-                } else if (subkeys.size() > 0) {
-                    String subkey = subkeys.remove();
-                    for (RegionData subregion : subregions) {
-                        if (subregion.isValidName(subkey)) {
-                            LookupKey nextKey = buildDataLookupKey(key, subregion.getKey());
-                            requestDataRecursively(nextKey, subkeys, listener);
-                            return;
-                        }
-                    }
-                }
-
-                // Current value in the field is not valid, use the first valid subkey
-                // to request more data instead.
-                String firstSubkey = subregions.get(0).getKey();
-                LookupKey nextKey = buildDataLookupKey(key, firstSubkey);
-                Queue<String> emptyList = new LinkedList<String>();
-                requestDataRecursively(nextKey, emptyList, listener);
-            }
-        });
+    return new LookupKey.Builder(key).build();
+  }
+
+  /**
+   * Compares the language subtags of input {@code languageCode} and default language code. For
+   * example, "zh-Hant" and "zh" are viewed as identical.
+   */
+  boolean isDefaultLanguage(String languageCode) {
+    if (languageCode == null) {
+      return true;
     }
-
-    private LookupKey buildDataLookupKey(LookupKey lookupKey, String subKey) {
-        String[] subKeys = lookupKey.toString().split(SLASH_DELIM);
-        String languageCodeSubTag =
-                (mLanguageCode == null) ? null : Util.getLanguageSubtag(mLanguageCode);
-        String key = lookupKey.toString() + SLASH_DELIM + subKey;
-
-        // Country level key
-        if (subKeys.length == 1 &&
-                languageCodeSubTag != null && !isDefaultLanguage(languageCodeSubTag)) {
-            key += DASH_DELIM + languageCodeSubTag.toString();
-        }
-        return new LookupKey.Builder(key).build();
+    AddressData addr = new AddressData.Builder().setCountry(currentCountry).build();
+    LookupKey lookupKey = getDataKeyFor(addr);
+    AddressVerificationNodeData data =
+        integratedData.getDefaultData(lookupKey.toString());
+    String defaultLanguage = data.get(AddressDataKey.LANG);
+
+    // Current language is not the default language for the country.
+    if (Util.trimToNull(defaultLanguage) != null &&
+        !Util.getLanguageSubtag(languageCode).equals(Util.getLanguageSubtag(languageCode))) {
+      return false;
     }
-
-    /**
-     * Compares the language subtags of input {@code languageCode} and default language code. For
-     * example, "zh-Hant" and "zh" are viewed as identical.
-     */
-    boolean isDefaultLanguage(String languageCode) {
-        if (languageCode == null) {
-            return true;
-        }
-        AddressData addr = new AddressData.Builder().setCountry(mCurrentCountry).build();
-        LookupKey lookupKey = getDataKeyFor(addr);
-        AddressVerificationNodeData data =
-                mIntegratedData.getDefaultData(lookupKey.toString());
-        String defaultLanguage = data.get(AddressDataKey.LANG);
-
-        // Current language is not the default language for the country.
-        if (Util.trimToNull(defaultLanguage) != null &&
-            !Util.getLanguageSubtag(languageCode).equals(Util.getLanguageSubtag(languageCode))) {
-            return false;
-        }
-        return true;
+    return true;
+  }
+
+  /**
+   * Gets a list of {@link RegionData} for sub-regions for a given key. For example, sub regions
+   * for "data/US" are AL/Alabama, AK/Alaska, etc.
+   *
+   * <p> TODO: It seems more straight forward to return a list of pairs instead of RegionData.
+   * Actually, we can remove RegionData since it does not contain anything more than key/value
+   * pairs now.
+   *
+   * @return A list of sub-regions, each sub-region represented by a {@link RegionData}.
+   */
+  List<RegionData> getRegionData(LookupKey key) {
+    if (key.getKeyType() == KeyType.EXAMPLES) {
+      throw new RuntimeException("example key not allowed for getting region data");
     }
-
-    /**
-     * Gets a list of {@link RegionData} for sub-regions for a given key. For example, sub regions
-     * for "data/US" are AL/Alabama, AK/Alaska, etc.
-     *
-     * <p> TODO: It seems more straight forward to return a list of pairs instead of RegionData.
-     * Actually, we can remove RegionData since it does not contain anything more than key/value
-     * pairs now.
-     *
-     * @return A list of sub-regions, each sub-region represented by a {@link RegionData}.
-     */
-    List<RegionData> getRegionData(LookupKey key) {
-        if (key.getKeyType() == KeyType.EXAMPLES) {
-            throw new RuntimeException("example key not allowed for getting region data");
-        }
-        Util.checkNotNull(key, "null regionKey not allowed");
-        LookupKey normalizedKey = normalizeLookupKey(key);
-        List<RegionData> results = new ArrayList<RegionData>();
-
-        // Root key.
-        if (normalizedKey.equals(ROOT_KEY)) {
-            AddressVerificationNodeData data =
-                    mIntegratedData.getDefaultData(normalizedKey.toString());
-            String[] countries = splitData(data.get(AddressDataKey.COUNTRIES));
-            for (int i = 0; i < countries.length; i++) {
-                RegionData rd = new RegionData.Builder()
-                        .setKey(countries[i])
-                        .setName(countries[i])
-                        .build();
-                results.add(rd);
-            }
-            return results;
-        }
-
-        AddressVerificationNodeData data =
-                mIntegratedData.get(normalizedKey.toString());
-        if (data != null) {
-            String[] keys = splitData(data.get(AddressDataKey.SUB_KEYS));
-            String[] names = (getScriptType() == ScriptType.LOCAL)
-                    ? splitData(data.get(AddressDataKey.SUB_NAMES))
-                    : splitData(data.get(AddressDataKey.SUB_LNAMES));
-
-            for (int i = 0; i < keys.length; i++) {
-                RegionData rd =
-                        new RegionData.Builder()
-                                .setKey(keys[i])
-                                .setName((i < names.length) ? names[i] : keys[i])
-                                .build();
-                results.add(rd);
-            }
-        }
-        return results;
+    Util.checkNotNull(key, "null regionKey not allowed");
+    LookupKey normalizedKey = normalizeLookupKey(key);
+    List<RegionData> results = new ArrayList<RegionData>();
+
+    // Root key.
+    if (normalizedKey.equals(ROOT_KEY)) {
+      AddressVerificationNodeData data =
+          integratedData.getDefaultData(normalizedKey.toString());
+      String[] countries = splitData(data.get(AddressDataKey.COUNTRIES));
+      for (int i = 0; i < countries.length; i++) {
+        RegionData rd = new RegionData.Builder()
+            .setKey(countries[i])
+            .setName(countries[i])
+            .build();
+        results.add(rd);
+      }
+      return results;
     }
 
-    /**
-     * Split a '~' delimited string into an array of strings. This method is null tolerant and
-     * considers an empty string to contain no elements.
-     *
-     * @param raw The data to split
-     * @return an array of strings
-     */
-    private String[] splitData(String raw) {
-        if (raw == null || raw.length() == 0) {
-            return new String[]{};
-        }
-        return raw.split(TILDE_DELIM);
+    AddressVerificationNodeData data =
+        integratedData.get(normalizedKey.toString());
+    if (data != null) {
+      String[] keys = splitData(data.get(AddressDataKey.SUB_KEYS));
+      String[] names = (getScriptType() == ScriptType.LOCAL)
+          ? splitData(data.get(AddressDataKey.SUB_NAMES))
+          : splitData(data.get(AddressDataKey.SUB_LNAMES));
+
+      for (int i = 0; i < keys.length; i++) {
+        RegionData rd = new RegionData.Builder()
+            .setKey(keys[i])
+            .setName((i < names.length) ? names[i] : keys[i])
+            .build();
+        results.add(rd);
+      }
     }
-
-    private String getSubKey(LookupKey parentKey, String name) {
-        for (RegionData subRegion : getRegionData(parentKey)) {
-            if (subRegion.isValidName(name)) {
-                return subRegion.getKey();
-            }
-        }
-        return null;
+    return results;
+  }
+
+  /**
+   * Split a '~' delimited string into an array of strings. This method is null tolerant and
+   * considers an empty string to contain no elements.
+   *
+   * @param raw The data to split
+   * @return an array of strings
+   */
+  private String[] splitData(String raw) {
+    if (raw == null || raw.length() == 0) {
+      return new String[]{};
+    }
+    return raw.split(TILDE_DELIM);
+  }
+
+  private String getSubKey(LookupKey parentKey, String name) {
+    for (RegionData subRegion : getRegionData(parentKey)) {
+      if (subRegion.isValidName(name)) {
+        return subRegion.getKey();
+      }
+    }
+    return null;
+  }
+
+  /**
+   * Normalizes {@code key} by replacing field values with sub-keys. For example, California is
+   * replaced with CA. The normalization goes from top (country) to bottom (dependent locality)
+   * and if any field value is empty, unknown, or invalid, it will stop and return whatever it
+   * gets. For example, a key "data/US/California/foobar/kar" will be normalized into
+   * "data/US/CA/foobar/kar" since "foobar" is unknown. This method supports only key of
+   * {@link KeyType#DATA} type.
+   *
+   * @return normalized {@link LookupKey}.
+   */
+  private LookupKey normalizeLookupKey(LookupKey key) {
+    Util.checkNotNull(key);
+    if (key.getKeyType() != KeyType.DATA) {
+      throw new RuntimeException("Only DATA keyType is supported");
     }
 
-    /**
-     * Normalizes {@code key} by replacing field values with sub-keys. For example, California is
-     * replaced with CA. The normalization goes from top (country) to bottom (dependent locality)
-     * and if any field value is empty, unknown, or invalid, it will stop and return whatever it
-     * gets. For example, a key "data/US/California/foobar/kar" will be normalized into
-     * "data/US/CA/foobar/kar" since "foobar" is unknown. This method supports only key of
-     * {@link KeyType#DATA} type.
-     *
-     * @return normalized {@link LookupKey}.
-     */
-    private LookupKey normalizeLookupKey(LookupKey key) {
-        Util.checkNotNull(key);
-        if (key.getKeyType() != KeyType.DATA) {
-            throw new RuntimeException("Only DATA keyType is supported");
-        }
-
-        String subStr[] = key.toString().split(SLASH_DELIM);
-
-        // Root key does not need to be normalized.
-        if (subStr.length < 2) {
-            return key;
-        }
-
-        StringBuilder sb = new StringBuilder(subStr[0]);
-        for (int i = 1; i < subStr.length; ++i) {
-            // Strips the language code if contained.
-            String languageCode = null;
-            if (i == 1 && subStr[i].contains(DASH_DELIM)) {
-                String[] s = subStr[i].split(DASH_DELIM);
-                subStr[i] = s[0];
-                languageCode = s[1];
-            }
+    String subStr[] = key.toString().split(SLASH_DELIM);
 
-            String normalizedSubKey = getSubKey(new LookupKey.Builder(sb.toString()).build(),
-                    subStr[i]);
+    // Root key does not need to be normalized.
+    if (subStr.length < 2) {
+      return key;
+    }
 
-            // Can't find normalized sub-key; assembles the lookup key with the
-            // remaining sub-keys and returns it.
-            if (normalizedSubKey == null) {
-                for (; i < subStr.length; ++i) {
-                    sb.append(SLASH_DELIM).append(subStr[i]);
-                }
-                break;
-            }
-            sb.append(SLASH_DELIM).append(normalizedSubKey);
-            if (languageCode != null) {
-                sb.append(DASH_DELIM).append(languageCode);
-            }
+    StringBuilder sb = new StringBuilder(subStr[0]);
+    for (int i = 1; i < subStr.length; ++i) {
+      // Strips the language code if contained.
+      String languageCode = null;
+      if (i == 1 && subStr[i].contains(DASH_DELIM)) {
+        String[] s = subStr[i].split(DASH_DELIM);
+        subStr[i] = s[0];
+        languageCode = s[1];
+      }
+
+      String normalizedSubKey = getSubKey(new LookupKey.Builder(sb.toString()).build(),
+          subStr[i]);
+
+      // Can't find normalized sub-key; assembles the lookup key with the
+      // remaining sub-keys and returns it.
+      if (normalizedSubKey == null) {
+        for (; i < subStr.length; ++i) {
+          sb.append(SLASH_DELIM).append(subStr[i]);
         }
-        return new LookupKey.Builder(sb.toString()).build();
+        break;
+      }
+      sb.append(SLASH_DELIM).append(normalizedSubKey);
+      if (languageCode != null) {
+        sb.append(DASH_DELIM).append(languageCode);
+      }
     }
+    return new LookupKey.Builder(sb.toString()).build();
+  }
 }