Merge pull request #168 from googlei18n/opensource_update_3447

(AUTOMATIC) opensource update

C++: Correctly format multiline address line that precedes a literal.
Java: Metadata update + other small fixes
diff --git a/android/src/main/java/com/android/i18n/addressinput/AddressWidget.java b/android/src/main/java/com/android/i18n/addressinput/AddressWidget.java
index 2416669..0ce8c82 100644
--- a/android/src/main/java/com/android/i18n/addressinput/AddressWidget.java
+++ b/android/src/main/java/com/android/i18n/addressinput/AddressWidget.java
@@ -79,7 +79,7 @@
   private ClientData clientData;
 
   // A map for all address fields.
-  // TODO(user): Fix this to avoid needing to map specific address lines.
+  // TODO(dbeaumont): Fix this to avoid needing to map specific address lines.
   private final EnumMap<AddressField, AddressUiComponent> inputWidgets =
       new EnumMap<AddressField, AddressUiComponent>(AddressField.class);
 
diff --git a/common/src/main/java/com/google/i18n/addressinput/common/CacheData.java b/common/src/main/java/com/google/i18n/addressinput/common/CacheData.java
index 24f5c83..12c36b6 100644
--- a/common/src/main/java/com/google/i18n/addressinput/common/CacheData.java
+++ b/common/src/main/java/com/google/i18n/addressinput/common/CacheData.java
@@ -79,7 +79,7 @@
    * Creates an instance of CacheData with an empty cache, and uses no caching that is external
    * to the AddressWidget.
    */
-  // TODO(user): Remove this method (avoid needless dependency on SimpleClientCacheManager).
+  // TODO(dbeaumont): Remove this method (avoid needless dependency on SimpleClientCacheManager).
   public CacheData(AsyncRequestApi asyncRequestApi) {
     this(new SimpleClientCacheManager(), asyncRequestApi);
   }
@@ -115,7 +115,7 @@
    *
    * @param jsonString cached data from last time the class was used
    */
-  // TODO(user): Remove this method (if callers need to build from json string, do it first).
+  // TODO(dbeaumont): Remove this method (if callers need to build from json string, do it first).
   public CacheData(String jsonString, AsyncRequestApi asyncRequestApi) {
     clientCacheManager = new SimpleClientCacheManager();
     setUrl(clientCacheManager.getAddressServerUrl());
diff --git a/common/src/main/java/com/google/i18n/addressinput/common/FieldVerifier.java b/common/src/main/java/com/google/i18n/addressinput/common/FieldVerifier.java
index a8d9763..7ee0151 100644
--- a/common/src/main/java/com/google/i18n/addressinput/common/FieldVerifier.java
+++ b/common/src/main/java/com/google/i18n/addressinput/common/FieldVerifier.java
@@ -257,6 +257,11 @@
     // alternative for the region, for which we have data. If not, we drop it from the data key.
     String[] parts = sublevel.split(LOCALE_DELIMITER);
 
+    if (parts.length == 0){
+      // May only contains the LOCALE_DELIMITER.
+      return new FieldVerifier(this, null);
+    }
+
     // Makes the new key - the old key, plus the new data, minus the language code.
     String currentFullKey = id + KEY_NODE_DELIMITER + parts[0];
 
diff --git a/common/src/main/java/com/google/i18n/addressinput/common/RegionDataConstants.java b/common/src/main/java/com/google/i18n/addressinput/common/RegionDataConstants.java
index 5d0784f..fce8747 100644
--- a/common/src/main/java/com/google/i18n/addressinput/common/RegionDataConstants.java
+++ b/common/src/main/java/com/google/i18n/addressinput/common/RegionDataConstants.java
@@ -78,7 +78,7 @@
     map.put("CN", "{\"name\":\"CHINA\",\"lang\":\"zh\",\"languages\":\"zh\",\"lfmt\":\"%N%n%O%n%A%n%D%n%C%n%S, %Z\",\"fmt\":\"%Z%n%S%C%D%n%A%n%O%n%N\",\"require\":\"ACSZ\",\"upper\":\"S\",\"sublocality_name_type\":\"district\",\"width_overrides\":\"%S:S%C:S%D:S\",\"label_overrides\":[{\"field\":\"C\",\"label\":\"市/自治州/地区/盟\",\"lang\":\"zh\"},{\"field\":\"S\",\"label\":\"省/自治区/直辖市\",\"lang\":\"zh\"},{\"field\":\"D\",\"label\":\"区/县/旗\",\"lang\":\"zh\"}]}");
     map.put("CO", "{\"name\":\"COLOMBIA\",\"fmt\":\"%N%n%O%n%A%n%C, %S, %Z\",\"require\":\"AS\",\"state_name_type\":\"department\",\"label_overrides\":[{\"field\":\"LL\",\"label\":\"Vereda\"},{\"field\":\"A3\",\"label\":\"Corregimiento\"},{\"field\":\"A2\",\"label\":\"Municipio\"}]}");
     map.put("CR", "{\"name\":\"COSTA RICA\",\"fmt\":\"%N%n%O%n%A%n%S, %C%n%Z\",\"require\":\"ACS\"}");
-    map.put("CU", "{\"name\":\"CUBA\",\"fmt\":\"%N%n%O%n%A%n%S%C%n%Z\"}");
+    map.put("CU", "{\"name\":\"CUBA\",\"lang\":\"es\",\"languages\":\"es\",\"fmt\":\"%N%n%O%n%A%n%C %S%n%Z\"}");
     map.put("CV", "{\"name\":\"CAPE VERDE\",\"lang\":\"pt\",\"languages\":\"pt\",\"fmt\":\"%N%n%O%n%A%n%Z %C%n%S\",\"state_name_type\":\"island\"}");
     map.put("CW", "{\"name\":\"CURACAO\"}");
     map.put("CX", "{\"name\":\"CHRISTMAS ISLAND\",\"fmt\":\"%O%n%N%n%A%n%C %S %Z\",\"upper\":\"CS\"}");
@@ -201,7 +201,7 @@
     map.put("NZ", "{\"name\":\"NEW ZEALAND\",\"fmt\":\"%N%n%O%n%A%n%D%n%C %Z\",\"require\":\"ACZ\"}");
     map.put("OM", "{\"name\":\"OMAN\",\"fmt\":\"%N%n%O%n%A%n%Z%n%C\"}");
     map.put("PA", "{\"name\":\"PANAMA (REP.)\",\"fmt\":\"%N%n%O%n%A%n%C%n%S\",\"upper\":\"CS\"}");
-    map.put("PE", "{\"name\":\"PERU\",\"lang\":\"es\",\"languages\":\"es\",\"fmt\":\"%N%n%O%n%A%n%C %Z%n%S\"}");
+    map.put("PE", "{\"name\":\"PERU\",\"lang\":\"es\",\"languages\":\"es\",\"fmt\":\"%N%n%O%n%A%n%C %Z%n%S\",\"locality_name_type\":\"district\"}");
     map.put("PF", "{\"name\":\"FRENCH POLYNESIA\",\"fmt\":\"%N%n%O%n%A%n%Z %C %S\",\"require\":\"ACSZ\",\"upper\":\"CS\",\"state_name_type\":\"island\"}");
     map.put("PG", "{\"name\":\"PAPUA NEW GUINEA\",\"fmt\":\"%N%n%O%n%A%n%C %Z %S\",\"require\":\"ACS\"}");
     map.put("PH", "{\"name\":\"PHILIPPINES\",\"lang\":\"en\",\"languages\":\"en\",\"fmt\":\"%N%n%O%n%A%n%D, %C%n%Z %S\"}");
diff --git a/common/src/test/java/com/google/i18n/addressinput/common/FieldVerifierTest.java b/common/src/test/java/com/google/i18n/addressinput/common/FieldVerifierTest.java
index 57e86d8..0c2d150 100644
--- a/common/src/test/java/com/google/i18n/addressinput/common/FieldVerifierTest.java
+++ b/common/src/test/java/com/google/i18n/addressinput/common/FieldVerifierTest.java
@@ -553,6 +553,19 @@
     assertTrue(problems.isEmpty());
   }
 
+  @Test public void testLocalityWithDelimiterOnly() {
+    AddressProblems problems = new AddressProblems();
+    AddressData address = AddressData.builder()
+        .setAddress("dummy")
+        .setLocality("--")
+        .setAdminArea("Haryana")
+        .setCountry("IN")
+        .setPostalCode("136118")
+        .build();
+    VERIFIER.verify(address, problems);
+    assertTrue(problems.isEmpty());
+  }
+
   @Test public void testFieldVerifierUsesRegionDataConstantsForFmtAndRequire() {
     Map<AddressDataKey, String> map = new EnumMap<AddressDataKey, String>(AddressDataKey.class);
     // Values for format and require are deliberately different from RegionDataConstants so that we
diff --git a/cpp/src/address_formatter.cc b/cpp/src/address_formatter.cc
index 97d90f1..dadc064 100644
--- a/cpp/src/address_formatter.cc
+++ b/cpp/src/address_formatter.cc
@@ -191,9 +191,12 @@
           if (address_data.address_line.size() > 1U) {
             lines->push_back(line);
             line.clear();
-            lines->insert(lines->end(),
-                          address_data.address_line.begin() + 1,
-                          address_data.address_line.end());
+            const auto last_element_iterator =
+                address_data.address_line.begin() +
+                address_data.address_line.size() - 1;
+            lines->insert(lines->end(), address_data.address_line.begin() + 1,
+                          last_element_iterator);
+            line.append(*last_element_iterator);
           }
         }
       } else {
diff --git a/cpp/src/region_data_constants.cc b/cpp/src/region_data_constants.cc
index 14a5744..647d05f 100644
--- a/cpp/src/region_data_constants.cc
+++ b/cpp/src/region_data_constants.cc
@@ -307,7 +307,7 @@
       u8R"("languages":"es")"
       "}"},
   {"CU", "{"
-      u8R"("fmt":"%N%n%O%n%A%n%S%C%n%Z",)"
+      u8R"("fmt":"%N%n%O%n%A%n%C %S%n%Z",)"
       u8R"("zipex":"10700",)"
       u8R"("languages":"es")"
       "}"},
@@ -1009,6 +1009,7 @@
       "}"},
   {"PE", "{"
       u8R"("fmt":"%N%n%O%n%A%n%C %Z%n%S",)"
+      u8R"("locality_name_type":"district",)"
       u8R"("zipex":"LIMA 23,LIMA 42,CALLAO 2,02001",)"
       u8R"("posturl":"http://www.serpost.com.pe/cpostal/codigo",)"
       u8R"("languages":"es")"
diff --git a/cpp/test/address_formatter_test.cc b/cpp/test/address_formatter_test.cc
index 7f62952..ec269f4 100644
--- a/cpp/test/address_formatter_test.cc
+++ b/cpp/test/address_formatter_test.cc
@@ -327,6 +327,35 @@
 }
 
 TEST(AddressFormatterTest,
+     GetFormattedNationalAddress_LiteralBeforeOneAddressLine) {
+  AddressData address;
+  address.region_code = "JP";
+  address.language_code = "ja_Latn";
+  address.administrative_area = "Tokyo";
+  address.address_line = {"Roppongi Hills"};
+  std::vector<std::string> expected;
+  expected.emplace_back("Roppongi Hills, Tokyo");
+  std::vector<std::string> lines;
+  GetFormattedNationalAddress(address, &lines);
+  EXPECT_EQ(expected, lines);
+}
+
+TEST(AddressFormatterTest,
+     GetFormattedNationalAddress_LiteralBeforeTwoAddressLines) {
+  AddressData address;
+  address.region_code = "JP";
+  address.language_code = "ja_Latn";
+  address.administrative_area = "Tokyo";
+  address.address_line = {"Roppongi Hills", "Mori Tower"};
+  std::vector<std::string> expected;
+  expected.emplace_back("Roppongi Hills");
+  expected.emplace_back("Mori Tower, Tokyo");
+  std::vector<std::string> lines;
+  GetFormattedNationalAddress(address, &lines);
+  EXPECT_EQ(expected, lines);
+}
+
+TEST(AddressFormatterTest,
      GetFormattedNationalAddressMissingFields_DuplicateField) {
   AddressData address;
   address.region_code = "CI";