Updated data for Andorra/Russia, new label for Russia, small formatting fixes (Java).

git-svn-id: http://libaddressinput.googlecode.com/svn/trunk@301 38ededc0-08b8-5190-f2ac-b31f878777ad
diff --git a/cpp/res/messages.grdp b/cpp/res/messages.grdp
index 1e1bcf2..c04449a 100644
--- a/cpp/res/messages.grdp
+++ b/cpp/res/messages.grdp
@@ -85,6 +85,12 @@
     Island
   </message>
   <message
+      name="IDS_LIBADDRESSINPUT_OBLAST"
+      desc="Administrative Area for certain countries (e.g., Russia's
+            Leningrad).">
+    Oblast
+  </message>
+  <message
       name="IDS_LIBADDRESSINPUT_PARISH"
       desc="Administrative Area for certain countries (e.g., Andorra's
             Canillo).">
diff --git a/cpp/src/region_data_constants.cc b/cpp/src/region_data_constants.cc
index d12bafc..8c552d3 100644
--- a/cpp/src/region_data_constants.cc
+++ b/cpp/src/region_data_constants.cc
@@ -43,9 +43,8 @@
       "\"languages\":\"en\""
       "}"));
   region_data.insert(std::make_pair("AD", "{"
-      "\"fmt\":\"%N%n%O%n%A%n%Z %S\","
-      "\"require\":\"AS\","
-      "\"state_name_type\":\"parish\","
+      "\"fmt\":\"%N%n%O%n%A%n%Z %C\","
+      "\"require\":\"A\","
       "\"zipex\":\"AD100,AD501,AD700\","
       "\"posturl\":\"http://www.correos.es/comun/CodigosPostales/1010_s-CodPostal.asp\?Provincia=\","
       "\"languages\":\"ca\""
@@ -1062,8 +1061,9 @@
       "\"languages\":\"sr-Cyrl~sr-Latn\""
       "}"));
   region_data.insert(std::make_pair("RU", "{"
-      "\"fmt\":\"%Z %C  %n%A%n%O%n%N\","
+      "\"fmt\":\"%N%n%O%n%A%n%C%n%S%n%Z\","
       "\"require\":\"ACZ\","
+      "\"state_name_type\":\"oblast\","
       "\"zipex\":\"125075,247112,103375\","
       "\"posturl\":\"http://info.russianpost.ru/servlet/department\","
       "\"languages\":\"ru\""
diff --git a/cpp/src/rule.cc b/cpp/src/rule.cc
index e25142f..b4d03ca 100644
--- a/cpp/src/rule.cc
+++ b/cpp/src/rule.cc
@@ -73,6 +73,8 @@
   message_ids.insert(std::make_pair(
       "island", IDS_LIBADDRESSINPUT_ISLAND));
   message_ids.insert(std::make_pair(
+      "oblast", IDS_LIBADDRESSINPUT_OBLAST));
+  message_ids.insert(std::make_pair(
       "parish", IDS_LIBADDRESSINPUT_PARISH));
   message_ids.insert(std::make_pair(
       "prefecture", IDS_LIBADDRESSINPUT_PREFECTURE));
diff --git a/java/res/values/address_strings.xml b/java/res/values/address_strings.xml
index 57b34c4..f12247a 100644
--- a/java/res/values/address_strings.xml
+++ b/java/res/values/address_strings.xml
@@ -80,6 +80,9 @@
     <!-- Administrative Area for certain countries (e.g., Bahama's Cat Island) [CHAR LIMIT=30] -->
     <string name="i18n_island">Island</string>
 
+    <!-- Administrative Area for certain countries (e.g., Russia's Leningrad) [CHAR LIMIT=30] -->
+    <string name="i18n_oblast">Oblast</string>
+
     <!-- Administrative Area for certain countries (e.g., Andorra's Canillo) [CHAR LIMIT=30] -->
     <string name="i18n_parish">Parish</string>
 
@@ -140,6 +143,10 @@
          (e.g., Bahama) is entered incorrectly by the user [CHAR LIMIT=30] -->
     <string name="invalid_island">Invalid island</string>
 
+    <!-- Message to be shown when the administrative area (oblast) for certain countries
+         (e.g., Russia) is entered incorrectly by the user [CHAR LIMIT=30] -->
+    <string name="invalid_oblast">Invalid oblast</string>
+
     <!-- Message to be shown when the administrative area (parish) for certain countries
          (e.g., Andorra) is entered incorrectly by the user [CHAR LIMIT=30] -->
     <string name="invalid_parish">Invalid parish</string>
diff --git a/java/src/com/android/i18n/addressinput/AddressWidget.java b/java/src/com/android/i18n/addressinput/AddressWidget.java
index 76cd12a..c377e2c 100644
--- a/java/src/com/android/i18n/addressinput/AddressWidget.java
+++ b/java/src/com/android/i18n/addressinput/AddressWidget.java
@@ -112,6 +112,7 @@
         adminLabelMap.put("do_si", R.string.i18n_do_si);
         adminLabelMap.put("emirate", R.string.i18n_emirate);
         adminLabelMap.put("island", R.string.i18n_island);
+        adminLabelMap.put("oblast", R.string.i18n_oblast);
         adminLabelMap.put("parish", R.string.i18n_parish);
         adminLabelMap.put("prefecture", R.string.i18n_prefecture);
         adminLabelMap.put("province", R.string.i18n_province);
@@ -131,6 +132,7 @@
         adminErrorMap.put("do_si", R.string.invalid_do_si);
         adminErrorMap.put("emirate", R.string.invalid_emirate);
         adminErrorMap.put("island", R.string.invalid_island);
+        adminErrorMap.put("oblast", R.string.invalid_oblast);
         adminErrorMap.put("parish", R.string.invalid_parish);
         adminErrorMap.put("prefecture", R.string.invalid_prefecture);
         adminErrorMap.put("province", R.string.invalid_province);
diff --git a/java/src/com/android/i18n/addressinput/FormatInterpreter.java b/java/src/com/android/i18n/addressinput/FormatInterpreter.java
index ffd19b1..ed7b2ac 100644
--- a/java/src/com/android/i18n/addressinput/FormatInterpreter.java
+++ b/java/src/com/android/i18n/addressinput/FormatInterpreter.java
@@ -155,15 +155,16 @@
 
         List<String> lines = new ArrayList<String>();
         StringBuilder currentLine = new StringBuilder();
-        for (String substr : getFormatSubStrings(scriptType, regionCode)) {
-            if (substr.equals(NEW_LINE)) {
-                String normalizedStr = removeAllRedundantSpaces(currentLine.toString());
+        for (String formatSymbol : getFormatSubStrings(scriptType, regionCode)) {
+            if (formatSymbol.equals(NEW_LINE)) {
+                String normalizedStr =
+                        removeRedundantSpacesAndLeadingPunctuation(currentLine.toString());
                 if (normalizedStr.length() > 0) {
                     lines.add(normalizedStr);
                     currentLine.setLength(0);
                 }
-            } else if (substr.startsWith("%")) {
-                char c = substr.charAt(1);
+            } else if (formatSymbol.startsWith("%")) {
+                char c = formatSymbol.charAt(1);
                 AddressField field = AddressField.of(c);
                 Util.checkNotNull(field, "null address field for character " + c);
 
@@ -203,10 +204,10 @@
                     currentLine.append(value);
                 }
             } else {
-                currentLine.append(substr);
+                currentLine.append(formatSymbol);
             }
         }
-        String normalizedStr = removeAllRedundantSpaces(currentLine.toString());
+        String normalizedStr = removeRedundantSpacesAndLeadingPunctuation(currentLine.toString());
         if (normalizedStr.length() > 0) {
             lines.add(normalizedStr);
         }
@@ -242,13 +243,16 @@
         return parts;
     }
 
-    private String removeAllRedundantSpaces(String str) {
+    private static String removeRedundantSpacesAndLeadingPunctuation(String str) {
+        // Remove leading commas and other punctuation that might have been added by the formatter
+        // in the case of missing data.
+        str = str.replaceFirst("^[-,\\s]+", "");
         str = str.trim();
         str = str.replaceAll(" +", " ");
         return str;
     }
 
-    private String getFormatString(ScriptType scriptType, String regionCode) {
+    private static String getFormatString(ScriptType scriptType, String regionCode) {
         String format = (scriptType == ScriptType.LOCAL)
                 ? getJsonValue(regionCode, AddressDataKey.FMT)
                 : getJsonValue(regionCode, AddressDataKey.LFMT);
@@ -258,7 +262,7 @@
         return format;
     }
 
-    private String getJsonValue(String regionCode, AddressDataKey key) {
+    private static String getJsonValue(String regionCode, AddressDataKey key) {
         Util.checkNotNull(regionCode);
         String jsonString = RegionDataConstants.getCountryFormatMap().get(regionCode);
         Util.checkNotNull(jsonString, "no json data for region code " + regionCode);
diff --git a/java/src/com/android/i18n/addressinput/RegionDataConstants.java b/java/src/com/android/i18n/addressinput/RegionDataConstants.java
index 946fc24..18b1fd8 100644
--- a/java/src/com/android/i18n/addressinput/RegionDataConstants.java
+++ b/java/src/com/android/i18n/addressinput/RegionDataConstants.java
@@ -41,10 +41,8 @@
                 "name", "ANDORRA",
                 "lang", "ca",
                 "languages", "ca",
-                "fmt", "%N%n%O%n%A%n%Z %S",
-                "require", "AS",
-                "upper", "S",
-                "state_name_type", "parish",
+                "fmt", "%N%n%O%n%A%n%Z %C",
+                "require", "A",
         }),
         AE(new String[]{
                 "name", "UNITED ARAB EMIRATES",
@@ -977,8 +975,9 @@
         }),
         RU(new String[]{
                 "name", "RUSSIAN FEDERATION",
-                "fmt", "%Z %C  %n%A%n%O%n%N",
+                "fmt", "%N%n%O%n%A%n%C%n%S%n%Z",
                 "require", "ACZ",
+                "state_name_type", "oblast",
                 "upper", "AC",
         }),
         RW(new String[]{
@@ -1168,7 +1167,7 @@
                 "name", "UNITED STATES",
                 "lang", "en",
                 "languages", "en",
-                "fmt", "%N%n%O%n%A%n%C %S %Z",
+                "fmt", "%N%n%O%n%A%n%C, %S %Z",
                 "require", "ACSZ",
                 "upper", "CS",
                 "zip_name_type", "zip",
diff --git a/java/test/com/android/i18n/addressinput/ClientDataTest.java b/java/test/com/android/i18n/addressinput/ClientDataTest.java
index 570434e..b18d726 100644
--- a/java/test/com/android/i18n/addressinput/ClientDataTest.java
+++ b/java/test/com/android/i18n/addressinput/ClientDataTest.java
@@ -78,6 +78,6 @@
         // data from there.
         assertNotNull(data);
         String unitedStatesFormatInfo = data.get(AddressDataKey.FMT);
-        assertEquals("%N%n%O%n%A%n%C %S %Z", unitedStatesFormatInfo);
+        assertEquals("%N%n%O%n%A%n%C, %S %Z", unitedStatesFormatInfo);
     }
 }
diff --git a/java/test/com/android/i18n/addressinput/FormatInterpreterTest.java b/java/test/com/android/i18n/addressinput/FormatInterpreterTest.java
index 50372ed..f5bac79 100644
--- a/java/test/com/android/i18n/addressinput/FormatInterpreterTest.java
+++ b/java/test/com/android/i18n/addressinput/FormatInterpreterTest.java
@@ -147,7 +147,7 @@
     public void testUsEnvelopeAddress() {
         List<String> expected = new ArrayList<String>();
         expected.add("1098 Alta Ave");
-        expected.add("Mt View CA 94043");
+        expected.add("Mt View, CA 94043");
 
         List<String> real = formatInterpreter.getEnvelopeAddress(US_CA_ADDRESS);
 
@@ -189,4 +189,44 @@
         List<String> real = formatInterpreter.getEnvelopeAddress(address);
         assertEquals(expected, real);
     }
+
+  public void testEnvelopeAddressLeadingPostPrefix() {
+      List<String> expected = new ArrayList<String>();
+      expected.add("CH-8047 Herrliberg");
+      AddressData address = new AddressData.Builder().setCountry("CH")
+              .setPostalCode("8047")
+              .setLocality("Herrliberg")
+              .build();
+
+      List<String> real = formatInterpreter.getEnvelopeAddress(address);
+      assertEquals(expected, real);
+  }
+
+  public void testSvAddress() {
+      final AddressData svAddress = new AddressData.Builder().setCountry("SV")
+              .setAdminArea("Ahuachapán")
+              .setLocality("Ahuachapán")
+              .setAddressLine1("Some Street 12")
+              .build();
+
+      List<String> expected = new ArrayList<String>();
+      expected.add("Some Street 12");
+      expected.add("Ahuachapán");
+      expected.add("Ahuachapán");
+
+      List<String> real = formatInterpreter.getEnvelopeAddress(svAddress);
+      assertEquals(expected, real);
+
+      final AddressData svAddressWithPostCode = new AddressData.Builder(svAddress)
+              .setPostalCode("CP 2101")
+              .build();
+
+      expected = new ArrayList<String>();
+      expected.add("Some Street 12");
+      expected.add("CP 2101-Ahuachapán");
+      expected.add("Ahuachapán");
+
+      real = formatInterpreter.getEnvelopeAddress(svAddressWithPostCode);
+      assertEquals(expected, real);
+  }
 }