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 java.io.PrintWriter; 6 import java.io.StringWriter; 7 import java.util.Arrays; 8 import java.util.Collections; 9 import java.util.List; 10 import java.util.NavigableSet; 11 import java.util.Set; 12 import java.util.TreeSet; 13 14 import com.google.common.collect.ArrayListMultimap; 15 import com.google.common.collect.ImmutableList; 16 import com.google.common.collect.ListMultimap; 17 18 /** 19 * Mutable ICU data, represented as a mapping from resource bundle paths to a sequence of values. 20 */ 21 public final class IcuData { 22 private static final RbPath RB_VERSION = RbPath.of("Version"); 23 24 private final String name; 25 private final boolean hasFallback; 26 private final NavigableSet<RbPath> paths = new TreeSet<>(); 27 private final ListMultimap<RbPath, RbValue> rbPathToValues = ArrayListMultimap.create(); 28 private ImmutableList<String> commentLines = ImmutableList.of(); 29 30 /** 31 * IcuData constructor. 32 * 33 * @param name The name of the IcuData object, used as the name of the root node in the output file 34 * @param hasFallback true if the output file has another ICU file as a fallback. 35 */ IcuData(String name, boolean hasFallback)36 public IcuData(String name, boolean hasFallback) { 37 this.hasFallback = hasFallback; 38 this.name = name; 39 } 40 41 /** @return whether data should fallback on data in other ICU files. */ hasFallback()42 public boolean hasFallback() { 43 return hasFallback; 44 } 45 46 /** 47 * @return the name of this ICU data instance. Used in the output filename, and in comments. 48 */ getName()49 public String getName() { 50 return name; 51 } 52 53 /** Sets additional comment lines for the top of the file. */ setFileComment(String... commentLines)54 public void setFileComment(String... commentLines) { 55 setFileComment(Arrays.asList(commentLines)); 56 } 57 setFileComment(Iterable<String> commentLines)58 public void setFileComment(Iterable<String> commentLines) { 59 this.commentLines = ImmutableList.copyOf(commentLines); 60 } 61 getFileComment()62 public List<String> getFileComment() { 63 return commentLines; 64 } 65 66 /** Adds a singleton resource bundle value for a given path. */ add(RbPath rbPath, String element)67 public void add(RbPath rbPath, String element) { 68 add(rbPath, RbValue.of(element)); 69 } 70 71 /** Adds a single resource bundle value for a given path. */ add(RbPath rbPath, RbValue rbValue)72 public void add(RbPath rbPath, RbValue rbValue) { 73 rbPathToValues.put(rbPath, rbValue); 74 paths.add(rbPath); 75 } 76 77 /** Adds a sequence of resource bundle values for a given path. */ add(RbPath rbPath, Iterable<RbValue> rbValues)78 public void add(RbPath rbPath, Iterable<RbValue> rbValues) { 79 rbValues.forEach(v -> rbPathToValues.put(rbPath, v)); 80 paths.add(rbPath); 81 } 82 83 /** Replaces all resource bundle values for a given path with the specified singleton value. */ replace(RbPath rbPath, String element)84 public void replace(RbPath rbPath, String element) { 85 rbPathToValues.removeAll(rbPath); 86 rbPathToValues.put(rbPath, RbValue.of(element)); 87 paths.add(rbPath); 88 } 89 90 /** Replaces all resource bundle values for a given path with the specified value. */ replace(RbPath rbPath, RbValue rbValue)91 public void replace(RbPath rbPath, RbValue rbValue) { 92 rbPathToValues.removeAll(rbPath); 93 add(rbPath, rbValue); 94 } 95 96 /** 97 * Sets the value of the "/Version" path to be the given string, replacing any previous value. 98 */ setVersion(String versionString)99 public void setVersion(String versionString) { 100 replace(RB_VERSION, versionString); 101 } 102 103 /** 104 * Returns the mutable list of values associated with the given path (or null if there are no 105 * associated values). 106 */ get(RbPath rbPath)107 public List<RbValue> get(RbPath rbPath) { 108 return paths.contains(rbPath) ? rbPathToValues.get(rbPath) : null; 109 } 110 111 /** Returns an unmodifiable view of the set of paths in this instance. */ getPaths()112 public Set<RbPath> getPaths() { 113 return Collections.unmodifiableSet(paths); 114 } 115 toString()116 @Override public String toString() { 117 StringWriter out = new StringWriter(); 118 PrintWriter w = new PrintWriter(out); 119 w.format("IcuData{ name=%s, fallback=%s\n", name, hasFallback); 120 commentLines.forEach(c -> w.format(" # %s\n", c)); 121 paths.forEach(p -> { 122 w.format(" %s:\n", p); 123 rbPathToValues.get(p).forEach(v -> w.format(" %s\n", v)); 124 }); 125 w.format("}\n"); 126 w.flush(); 127 return out.toString(); 128 } 129 } 130