blob: 2efc0eebf7ca7c82e7cc4e9df7368475942a4855 [file] [log] [blame]
// © 2019 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html
package org.unicode.icu.tool.cldrtoicu;
import static com.google.common.base.Preconditions.checkNotNull;
import static java.util.stream.Collectors.joining;
import java.io.PrintWriter;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
/**
* Stores any explicit locale relationships for a single directory (e.g. "lang" or "coll").
* This class just reflects a concise version of the "%%Parent and %%ALIAS" paths set in files and
* allows them to be written to the dependency graph files in each ICU data directory.
*/
final class DependencyGraph {
private final String cldrVersion;
private final Map<String, String> parentMap = new TreeMap<>();
private final Map<String, String> aliasMap = new TreeMap<>();
public DependencyGraph(String cldrVersion) {
this.cldrVersion = checkNotNull(cldrVersion);
}
void addParent(String localeId, String parentId) {
// Aliases take priority (since they can be forced and will replace empty files). Note
// however that this only happens in a tiny number of places due to the somewhat "hacky"
// forced aliases, and in future it's perfectly possibly that there would never be an
// overlap, and this code could just prohibit overlap between alias and parent mappings.
if (!aliasMap.containsKey(localeId)) {
parentMap.put(localeId, parentId);
}
}
void addAlias(String sourceId, String targetId) {
parentMap.remove(sourceId);
aliasMap.put(sourceId, targetId);
}
/**
* Outputs a JSON dictionary containing the parent and alias mappings to the given writer. The
* output contains non-JSON line comments and is of the form:
* <pre>{@code
* // <copyright message>
* {
* "cldrVersion": "<version>"
* "aliases": {
* "<source>": "<target>"
* ...
* }
* "parents": {
* "<id>": "<parent>"
* ...
* }
* }
* }</pre>
* where all values (other than the version) are locale IDs.
*
* <p>Anything reading the produced files must strip the line comments prior to processing the
* JSON data. Line comments only appear as a contiguous block in the header, so comment
* processing can stop at the first non-comment line (i.e. the first bare '{').
*/
void writeJsonTo(PrintWriter out, List<String> fileHeader) {
fileHeader.forEach(s -> out.println("// " + s));
out.println();
out.format("{\n \"cldrVersion\": \"%s\"", cldrVersion);
writeMap(out, "aliases", aliasMap);
writeMap(out, "parents", parentMap);
out.append("\n}\n");
out.close();
}
private static void writeMap(PrintWriter out, String name, Map<String, String> map) {
if (!map.isEmpty()) {
out.append(
map.entrySet().stream()
.map(e -> String.format("\n \"%s\": \"%s\"", e.getKey(), e.getValue()))
.collect(joining(",", ",\n \"" + name + "\": {", "\n }")));
}
}
}