2 * Copyright (C) 2010 Google Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package com.android.i18n.addressinput;
19 import java.util.Collections;
20 import java.util.EnumMap;
21 import java.util.HashSet;
24 import java.util.regex.Matcher;
25 import java.util.regex.Pattern;
28 * Wraps a Map of address property data to provide the AddressVerificationData API.
30 class AddressVerificationData implements DataSource {
32 private final Map<String, String> propertiesMap;
34 private static final Pattern KEY_VALUES_PATTERN = Pattern.compile("\"([^\"]+)\":\"([^\"]*)\"");
36 private static final Pattern SEPARATOR_PATTERN = Pattern.compile("\",\"");
39 * Constructs from a map of address property data. This keeps a reference to the map. This
40 * does not mutate the map. The map should not be mutated subsequent to this call.
42 AddressVerificationData(Map<String, String> propertiesMap) {
43 this.propertiesMap = propertiesMap;
47 public AddressVerificationNodeData get(String key) {
48 String json = propertiesMap.get(key);
49 if (json != null && isValidKey(key)) {
50 return createNodeData(json);
56 * Returns a set of the keys for which verification data is provided. The returned set is
60 Set<String> result = new HashSet<String>();
61 for (String key : propertiesMap.keySet()) {
62 if (isValidKey(key)) {
66 return Collections.unmodifiableSet(result);
70 * We can be initialized with the full set of address information, but validation only uses
71 * info prefixed with "data" (in particular, no info prefixed with "examples").
73 private boolean isValidKey(String key) {
74 return key.startsWith("data");
78 * Returns the contents of the JSON-format string as a map.
80 AddressVerificationNodeData createNodeData(String json) {
81 // Remove leading and trailing { and }.
82 json = json.substring(1, json.length() - 1);
83 Map<AddressDataKey, String> map =
84 new EnumMap<AddressDataKey, String>(AddressDataKey.class);
86 // our objects are very simple so we parse manually
87 // - no double quotes within strings
89 // can't use split "," since some data has commas in it.
90 Matcher sm = SEPARATOR_PATTERN.matcher(json);
92 while (pos < json.length()) {
95 pair = json.substring(pos, sm.start() + 1);
98 pair = json.substring(pos);
102 Matcher m = KEY_VALUES_PATTERN.matcher(pair);
104 String value = m.group(2);
106 // Remove escaped backslashes.
107 // Java regex doesn't handle a replacement String consisting of
108 // a single backslash, and treats a replacement String consisting of
109 // two backslashes as two backslashes instead of one. So there's
110 // no way to use regex to replace a match with a single backslash,
112 if (value.length() > 0) {
113 char[] linechars = m.group(2).toCharArray();
115 for (int r = w; r < linechars.length; ++r) {
116 char c = linechars[r];
117 if (c == '\\' && linechars[w - 1] == '\\') {
118 // don't increment w;
123 value = new String(linechars, 0, w);
126 AddressDataKey df = AddressDataKey.get(m.group(1));
128 // Skip this data - it isn't used in the Android version.
133 // This is a runtime data sanity check. The data should be
134 // checked when the data is built. The JSON data string should
135 // be parsable into string pairs using SEP_PAT.
136 throw new RuntimeException("could not match '" + pair + "' in '" + json + "'");
140 return new AddressVerificationNodeData(map);
144 public AddressVerificationNodeData getDefaultData(String key) {
146 if (key.split("/").length > 1) {
147 String[] parts = key.split("/");
148 key = parts[0] + "/" + parts[1];
151 AddressVerificationNodeData data = get(key);
153 throw new RuntimeException("failed to get default data with key " + key);