Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / libaddressinput / src / java / src / com / android / i18n / addressinput / AddressVerificationData.java
1 /*
2  * Copyright (C) 2010 Google Inc.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 package com.android.i18n.addressinput;
18
19 import java.util.Collections;
20 import java.util.EnumMap;
21 import java.util.HashSet;
22 import java.util.Map;
23 import java.util.Set;
24 import java.util.regex.Matcher;
25 import java.util.regex.Pattern;
26
27 /**
28  * Wraps a Map of address property data to provide the AddressVerificationData API.
29  */
30 class AddressVerificationData implements DataSource {
31
32   private final Map<String, String> propertiesMap;
33
34   private static final Pattern KEY_VALUES_PATTERN = Pattern.compile("\"([^\"]+)\":\"([^\"]*)\"");
35
36   private static final Pattern SEPARATOR_PATTERN = Pattern.compile("\",\"");
37
38   /**
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.
41    */
42   AddressVerificationData(Map<String, String> propertiesMap) {
43     this.propertiesMap = propertiesMap;
44   }
45
46   @Override
47   public AddressVerificationNodeData get(String key) {
48     String json = propertiesMap.get(key);
49     if (json != null && isValidKey(key)) {
50       return createNodeData(json);
51     }
52     return null;
53   }
54
55   /**
56    * Returns a set of the keys for which verification data is provided.  The returned set is
57    * immutable.
58    */
59   Set<String> keys() {
60     Set<String> result = new HashSet<String>();
61     for (String key : propertiesMap.keySet()) {
62       if (isValidKey(key)) {
63         result.add(key);
64       }
65     }
66     return Collections.unmodifiableSet(result);
67   }
68
69   /**
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").
72    */
73   private boolean isValidKey(String key) {
74     return key.startsWith("data");
75   }
76
77   /**
78    * Returns the contents of the JSON-format string as a map.
79    */
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);
85
86     // our objects are very simple so we parse manually
87     // - no double quotes within strings
88     // - no extra spaces
89     // can't use split "," since some data has commas in it.
90     Matcher sm = SEPARATOR_PATTERN.matcher(json);
91     int pos = 0;
92     while (pos < json.length()) {
93       String pair;
94       if (sm.find()) {
95         pair = json.substring(pos, sm.start() + 1);
96         pos = sm.start() + 2;
97       } else {
98         pair = json.substring(pos);
99         pos = json.length();
100       }
101
102       Matcher m = KEY_VALUES_PATTERN.matcher(pair);
103       if (m.matches()) {
104         String value = m.group(2);
105
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,
111         // apparently.
112         if (value.length() > 0) {
113           char[] linechars = m.group(2).toCharArray();
114           int w = 1;
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;
119               continue;
120             }
121             linechars[w++] = c;
122           }
123           value = new String(linechars, 0, w);
124         }
125
126         AddressDataKey df = AddressDataKey.get(m.group(1));
127         if (df == null) {
128           // Skip this data - it isn't used in the Android version.
129         } else {
130           map.put(df, value);
131         }
132       } else {
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 + "'");
137       }
138     }
139
140     return new AddressVerificationNodeData(map);
141   }
142
143   @Override
144   public AddressVerificationNodeData getDefaultData(String key) {
145     // gets country key
146     if (key.split("/").length > 1) {
147       String[] parts = key.split("/");
148       key = parts[0] + "/" + parts[1];
149     }
150
151     AddressVerificationNodeData data = get(key);
152     if (data == null) {
153       throw new RuntimeException("failed to get default data with key " + key);
154     }
155     return data;
156   }
157 }