17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package build.tools.cldrconverter;
27
28 import java.util.ArrayList;
29 import java.util.Arrays;
30 import java.util.EnumSet;
31 import java.util.HashMap;
32 import java.util.Iterator;
33 import java.util.List;
34 import java.util.Map;
35 import java.util.Objects;
36 import java.util.Optional;
37
38 class Bundle {
39 static enum Type {
40 LOCALENAMES, CURRENCYNAMES, TIMEZONENAMES, CALENDARDATA, FORMATDATA;
41
42 static EnumSet<Type> ALL_TYPES = EnumSet.of(LOCALENAMES,
43 CURRENCYNAMES,
44 TIMEZONENAMES,
45 CALENDARDATA,
46 FORMATDATA);
47 }
48
49 private final static Map<String, Bundle> bundles = new HashMap<>();
50
51 private final static String[] NUMBER_PATTERN_KEYS = {
52 "NumberPatterns/decimal",
53 "NumberPatterns/currency",
54 "NumberPatterns/percent",
55 "NumberPatterns/accounting"
56 };
57
58 private final static String[] COMPACT_NUMBER_PATTERN_KEYS = {
59 "short.CompactNumberPatterns",
60 "long.CompactNumberPatterns"};
61
62 private final static String[] NUMBER_ELEMENT_KEYS = {
63 "NumberElements/decimal",
64 "NumberElements/group",
65 "NumberElements/list",
66 "NumberElements/percent",
67 "NumberElements/zero",
68 "NumberElements/pattern",
69 "NumberElements/minus",
70 "NumberElements/exponential",
71 "NumberElements/permille",
72 "NumberElements/infinity",
73 "NumberElements/nan"
74 };
75
76 private final static String[] TIME_PATTERN_KEYS = {
77 "DateTimePatterns/full-time",
78 "DateTimePatterns/long-time",
79 "DateTimePatterns/medium-time",
80 "DateTimePatterns/short-time",
175 return currencies;
176 }
177
178 /**
179 * Generate a map that contains all the data that should be
180 * visible for the bundle's locale
181 */
182 Map<String, Object> getTargetMap() throws Exception {
183 if (targetMap != null) {
184 return targetMap;
185 }
186
187 String[] cldrBundles = getCLDRPath().split(",");
188
189 // myMap contains resources for id.
190 Map<String, Object> myMap = new HashMap<>();
191 int index;
192 for (index = 0; index < cldrBundles.length; index++) {
193 if (cldrBundles[index].equals(id)) {
194 myMap.putAll(CLDRConverter.getCLDRBundle(cldrBundles[index]));
195 CLDRConverter.handleAliases(myMap);
196 break;
197 }
198 }
199
200 // parentsMap contains resources from id's parents.
201 Map<String, Object> parentsMap = new HashMap<>();
202 for (int i = cldrBundles.length - 1; i > index; i--) {
203 if (!("no".equals(cldrBundles[i]) || cldrBundles[i].startsWith("no_"))) {
204 parentsMap.putAll(CLDRConverter.getCLDRBundle(cldrBundles[i]));
205 CLDRConverter.handleAliases(parentsMap);
206 }
207 }
208 // Duplicate myMap as parentsMap for "root" so that the
209 // fallback works. This is a hack, though.
210 if ("root".equals(cldrBundles[0])) {
211 assert parentsMap.isEmpty();
212 parentsMap.putAll(myMap);
213 }
214
215 // merge individual strings into arrays
216
217 // if myMap has any of the NumberPatterns/NumberElements members, create a
218 // complete array of patterns/elements.
219 @SuppressWarnings("unchecked")
220 List<String> scripts = (List<String>) myMap.get("numberingScripts");
221 if (scripts != null) {
222 for (String script : scripts) {
223 myMap.put(script + ".NumberPatterns",
224 createNumberArray(myMap, parentsMap, NUMBER_PATTERN_KEYS, script));
225 myMap.put(script + ".NumberElements",
226 createNumberArray(myMap, parentsMap, NUMBER_ELEMENT_KEYS, script));
227 }
228 }
229
230 for (String k : COMPACT_NUMBER_PATTERN_KEYS) {
231 List<String> patterns = (List<String>) myMap.remove(k);
232 if (patterns != null) {
233 // Replace any null entry with empty strings.
234 String[] arrPatterns = patterns.stream()
235 .map(s -> s == null ? "" : s).toArray(String[]::new);
236 myMap.put(k, arrPatterns);
237 }
238 }
239
240 // another hack: parentsMap is not used for date-time resources.
241 if ("root".equals(id)) {
242 parentsMap = null;
243 }
244
245 for (CalendarType calendarType : CalendarType.values()) {
246 String calendarPrefix = calendarType.keyElementName();
247 // handle multiple inheritance for month and day names
248 handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "MonthNames");
249 handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "MonthAbbreviations");
250 handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "MonthNarrows");
251 handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "DayNames");
252 handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "DayAbbreviations");
253 handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "DayNarrows");
254 handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "AmPmMarkers");
255 handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "narrow.AmPmMarkers");
256 handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "abbreviated.AmPmMarkers");
257 handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "QuarterNames");
258 handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "QuarterAbbreviations");
259 handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "QuarterNarrows");
|
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package build.tools.cldrconverter;
27
28 import java.util.ArrayList;
29 import java.util.Arrays;
30 import java.util.EnumSet;
31 import java.util.HashMap;
32 import java.util.Iterator;
33 import java.util.List;
34 import java.util.Map;
35 import java.util.Objects;
36 import java.util.Optional;
37 import java.util.stream.IntStream;
38
39 class Bundle {
40 static enum Type {
41 LOCALENAMES, CURRENCYNAMES, TIMEZONENAMES, CALENDARDATA, FORMATDATA;
42
43 static EnumSet<Type> ALL_TYPES = EnumSet.of(LOCALENAMES,
44 CURRENCYNAMES,
45 TIMEZONENAMES,
46 CALENDARDATA,
47 FORMATDATA);
48 }
49
50 private final static Map<String, Bundle> bundles = new HashMap<>();
51
52 private final static String[] NUMBER_PATTERN_KEYS = {
53 "NumberPatterns/decimal",
54 "NumberPatterns/currency",
55 "NumberPatterns/percent",
56 "NumberPatterns/accounting"
57 };
58
59 private final static String[] COMPACT_NUMBER_PATTERN_KEYS = {
60 "short.CompactNumberPatterns",
61 "long.CompactNumberPatterns"
62 };
63
64 private final static String[] NUMBER_ELEMENT_KEYS = {
65 "NumberElements/decimal",
66 "NumberElements/group",
67 "NumberElements/list",
68 "NumberElements/percent",
69 "NumberElements/zero",
70 "NumberElements/pattern",
71 "NumberElements/minus",
72 "NumberElements/exponential",
73 "NumberElements/permille",
74 "NumberElements/infinity",
75 "NumberElements/nan"
76 };
77
78 private final static String[] TIME_PATTERN_KEYS = {
79 "DateTimePatterns/full-time",
80 "DateTimePatterns/long-time",
81 "DateTimePatterns/medium-time",
82 "DateTimePatterns/short-time",
177 return currencies;
178 }
179
180 /**
181 * Generate a map that contains all the data that should be
182 * visible for the bundle's locale
183 */
184 Map<String, Object> getTargetMap() throws Exception {
185 if (targetMap != null) {
186 return targetMap;
187 }
188
189 String[] cldrBundles = getCLDRPath().split(",");
190
191 // myMap contains resources for id.
192 Map<String, Object> myMap = new HashMap<>();
193 int index;
194 for (index = 0; index < cldrBundles.length; index++) {
195 if (cldrBundles[index].equals(id)) {
196 myMap.putAll(CLDRConverter.getCLDRBundle(cldrBundles[index]));
197 break;
198 }
199 }
200
201 // parentsMap contains resources from id's parents.
202 Map<String, Object> parentsMap = new HashMap<>();
203 for (int i = cldrBundles.length - 1; i > index; i--) {
204 if (!("no".equals(cldrBundles[i]) || cldrBundles[i].startsWith("no_"))) {
205 parentsMap.putAll(CLDRConverter.getCLDRBundle(cldrBundles[i]));
206 }
207 }
208 // Duplicate myMap as parentsMap for "root" so that the
209 // fallback works. This is a hack, though.
210 if ("root".equals(cldrBundles[0])) {
211 assert parentsMap.isEmpty();
212 parentsMap.putAll(myMap);
213 }
214
215 // merge individual strings into arrays
216
217 // if myMap has any of the NumberPatterns/NumberElements members, create a
218 // complete array of patterns/elements.
219 @SuppressWarnings("unchecked")
220 List<String> scripts = (List<String>) myMap.get("numberingScripts");
221 if (scripts != null) {
222 for (String script : scripts) {
223 myMap.put(script + ".NumberPatterns",
224 createNumberArray(myMap, parentsMap, NUMBER_PATTERN_KEYS, script));
225 myMap.put(script + ".NumberElements",
226 createNumberArray(myMap, parentsMap, NUMBER_ELEMENT_KEYS, script));
227 }
228 }
229
230 for (String k : COMPACT_NUMBER_PATTERN_KEYS) {
231 List<String> patterns = (List<String>) myMap.remove(k);
232 if (patterns != null) {
233 // Convert the map value from List<String> to String[], replacing any missing
234 // entry from the parents map, if any.
235 final List<String> pList = (List<String>)parentsMap.get(k);
236 int size = patterns.size();
237 int psize = pList != null ? pList.size() : 0;
238 String[] arrPatterns = IntStream.range(0, Math.max(size, psize))
239 .mapToObj(i -> {
240 String pattern;
241 // first try itself.
242 if (i < size) {
243 pattern = patterns.get(i);
244 if (!pattern.isEmpty()) {
245 return pattern;
246 }
247 }
248 // if not found, try parent
249 if (i < psize) {
250 pattern = pList.get(i);
251 if (!pattern.isEmpty()) {
252 return pattern;
253 }
254 }
255 // bail out with empty string
256 return "";
257 })
258 .toArray(String[]::new);
259 myMap.put(k, arrPatterns);
260 }
261 }
262
263 // Processes aliases here
264 CLDRConverter.handleAliases(myMap);
265
266 // another hack: parentsMap is not used for date-time resources.
267 if ("root".equals(id)) {
268 parentsMap = null;
269 }
270
271 for (CalendarType calendarType : CalendarType.values()) {
272 String calendarPrefix = calendarType.keyElementName();
273 // handle multiple inheritance for month and day names
274 handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "MonthNames");
275 handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "MonthAbbreviations");
276 handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "MonthNarrows");
277 handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "DayNames");
278 handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "DayAbbreviations");
279 handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "DayNarrows");
280 handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "AmPmMarkers");
281 handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "narrow.AmPmMarkers");
282 handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "abbreviated.AmPmMarkers");
283 handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "QuarterNames");
284 handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "QuarterAbbreviations");
285 handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "QuarterNarrows");
|