• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // © 2019 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 package org.unicode.icu.tool.cldrtoicu;
4 
5 import static com.google.common.base.Preconditions.checkNotNull;
6 import static java.util.stream.Collectors.joining;
7 
8 import java.io.PrintWriter;
9 import java.util.List;
10 import java.util.Map;
11 import java.util.TreeMap;
12 
13 /**
14  * Stores any explicit locale relationships for a single directory (e.g. "lang" or "coll").
15  * This class just reflects a concise version of the "%%Parent and %%ALIAS" paths set in files and
16  * allows them to be written to the dependency graph files in each ICU data directory.
17  */
18 final class DependencyGraph {
19     private final String cldrVersion;
20     private final Map<String, String> parentMap = new TreeMap<>();
21     private final Map<String, String> aliasMap = new TreeMap<>();
22 
DependencyGraph(String cldrVersion)23     public DependencyGraph(String cldrVersion) {
24         this.cldrVersion = checkNotNull(cldrVersion);
25     }
26 
addParent(String localeId, String parentId)27     void addParent(String localeId, String parentId) {
28         // Aliases take priority (since they can be forced and will replace empty files). Note
29         // however that this only happens in a tiny number of places due to the somewhat "hacky"
30         // forced aliases, and in future it's perfectly possibly that there would never be an
31         // overlap, and this code could just prohibit overlap between alias and parent mappings.
32         if (!aliasMap.containsKey(localeId)) {
33             parentMap.put(localeId, parentId);
34         }
35     }
36 
addAlias(String sourceId, String targetId)37     void addAlias(String sourceId, String targetId) {
38         parentMap.remove(sourceId);
39         aliasMap.put(sourceId, targetId);
40     }
41 
42     /**
43      * Outputs a JSON dictionary containing the parent and alias mappings to the given writer. The
44      * output contains non-JSON line comments and is of the form:
45      * <pre>{@code
46      * // <copyright message>
47      * {
48      *     "cldrVersion": "<version>"
49      *     "aliases": {
50      *         "<source>": "<target>"
51      *         ...
52      *     }
53      *     "parents": {
54      *         "<id>": "<parent>"
55      *         ...
56      *     }
57      * }
58      * }</pre>
59      * where all values (other than the version) are locale IDs.
60      *
61      * <p>Anything reading the produced files must strip the line comments prior to processing the
62      * JSON data. Line comments only appear as a contiguous block in the header, so comment
63      * processing can stop at the first non-comment line (i.e. the first bare '{').
64      */
writeJsonTo(PrintWriter out, List<String> fileHeader)65     void writeJsonTo(PrintWriter out, List<String> fileHeader) {
66         fileHeader.forEach(s -> out.println("// " + s));
67         out.println();
68         out.format("{\n    \"cldrVersion\": \"%s\"", cldrVersion);
69         writeMap(out, "aliases", aliasMap);
70         writeMap(out, "parents", parentMap);
71         out.append("\n}\n");
72         out.close();
73     }
74 
writeMap(PrintWriter out, String name, Map<String, String> map)75     private static void writeMap(PrintWriter out, String name, Map<String, String> map) {
76         if (!map.isEmpty()) {
77             out.append(
78                 map.entrySet().stream()
79                     .map(e -> String.format("\n        \"%s\": \"%s\"", e.getKey(), e.getValue()))
80                     .collect(joining(",", ",\n    \"" + name + "\": {", "\n    }")));
81         }
82     }
83 }
84