• 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.checkArgument;
6 import static com.google.common.base.Preconditions.checkNotNull;
7 import static java.util.stream.Collectors.joining;
8 
9 import java.nio.file.Files;
10 import java.nio.file.Path;
11 import java.nio.file.Paths;
12 import java.util.Arrays;
13 import java.util.Optional;
14 import java.util.Set;
15 
16 import org.unicode.cldr.api.CldrDataSupplier;
17 import org.unicode.cldr.api.CldrDraftStatus;
18 import org.unicode.icu.tool.cldrtoicu.LdmlConverter.OutputType;
19 
20 import com.google.common.collect.ImmutableMap;
21 import com.google.common.collect.ImmutableSet;
22 import com.google.common.collect.ImmutableSetMultimap;
23 import com.google.common.collect.ImmutableTable;
24 import com.google.common.collect.SetMultimap;
25 import com.google.common.collect.Sets;
26 import com.google.common.collect.Table;
27 import com.google.common.collect.TreeBasedTable;
28 import com.google.common.collect.TreeMultimap;
29 
30 /**
31  * The converter config intended to generate the standard ICU data files. This used to be something
32  * that was configured by text files such as "icu-locale-deprecates.xml" and "icu-config.
33  */
34 public final class IcuConverterConfig implements LdmlConverterConfig {
35     private static final Optional<Path> DEFAULT_ICU_DIR =
36         Optional.ofNullable(System.getProperty("ICU_DIR", null))
37             .map(d -> Paths.get(d).toAbsolutePath());
38 
39     /** The builder with which to specify configuration for the {@link LdmlConverter}. */
40     @SuppressWarnings("UnusedReturnValue")
41     public static final class Builder {
42         private Path outputDir =
43             DEFAULT_ICU_DIR.map(d -> d.resolve("icu4c/source/data")).orElse(null);
44         private Path specialsDir =
45             DEFAULT_ICU_DIR.map(d -> d.resolve("icu4c/source/data/xml")).orElse(null);
46         private ImmutableSet<OutputType> outputTypes = OutputType.ALL;
47         private Optional<String> icuVersion = Optional.empty();
48         private Optional<String> icuDataVersion = Optional.empty();
49         private Optional<String> cldrVersion = Optional.empty();
50         private CldrDraftStatus minimumDraftStatus = CldrDraftStatus.CONTRIBUTED;
51         private boolean emitReport = false;
52         private final SetMultimap<IcuLocaleDir, String> localeIdsMap = TreeMultimap.create();
53         private final Table<IcuLocaleDir, String, String> forcedAliases = TreeBasedTable.create();
54         private final Table<IcuLocaleDir, String, String> forcedParents = TreeBasedTable.create();
55 
56         /**
57          * Sets the output directory in which the ICU data directories and files will go. This is
58          * optional if the {@code ICU_DIR} system property is set, which will be used to generate
59          * the path instead (i.e. {@code "icu4c/source/data"} inside the ICU release directory).
60          */
setOutputDir(Path outputDir)61         public Builder setOutputDir(Path outputDir) {
62             this.outputDir = checkNotNull(outputDir);
63             return this;
64         }
65 
66         /**
67          * Sets the "specials" directory containing additional ICU specific data to be processed.
68          * This is optional if the {@code ICU_DIR} system property is set, which will be used to
69          * generate the path instead (i.e. {@code "icu4c/source/data/xml"} inside the ICU release
70          * directory).
71          */
setSpecialsDir(Path specialsDir)72         public Builder setSpecialsDir(Path specialsDir) {
73             this.specialsDir = checkNotNull(specialsDir);
74             return this;
75         }
76 
77         /**
78          * Sets the output types which will be converted. This is optional and defaults to {@link
79          * OutputType#ALL}.
80          */
setOutputTypes(Iterable<OutputType> types)81         public Builder setOutputTypes(Iterable<OutputType> types) {
82             this.outputTypes = ImmutableSet.copyOf(types);
83             return this;
84         }
85 
setIcuVersion(String version)86         public Builder setIcuVersion(String version) {
87             if (!version.isEmpty()) {
88                 this.icuVersion = Optional.of(version);
89             }
90             return this;
91         }
92 
setIcuDataVersion(String version)93         public Builder setIcuDataVersion(String version) {
94             if (!version.isEmpty()) {
95                 this.icuDataVersion = Optional.of(version);
96             }
97             return this;
98         }
99 
setCldrVersion(String version)100         public Builder setCldrVersion(String version) {
101             if (!version.isEmpty()) {
102                 this.cldrVersion = Optional.of(version);
103             }
104             return this;
105         }
106 
setMinimumDraftStatus(CldrDraftStatus minimumDraftStatus)107         public void setMinimumDraftStatus(CldrDraftStatus minimumDraftStatus) {
108             this.minimumDraftStatus = checkNotNull(minimumDraftStatus);
109         }
110 
setEmitReport(boolean emitReport)111         public Builder setEmitReport(boolean emitReport) {
112             this.emitReport = emitReport;
113             return this;
114         }
115 
addLocaleIds(IcuLocaleDir dir, Iterable<String> localeIds)116         public Builder addLocaleIds(IcuLocaleDir dir, Iterable<String> localeIds) {
117             localeIdsMap.putAll(dir, localeIds);
118             return this;
119         }
120 
addForcedAlias(IcuLocaleDir dir, String source, String target)121         public Builder addForcedAlias(IcuLocaleDir dir, String source, String target) {
122             forcedAliases.put(dir, source, target);
123             return this;
124         }
125 
addForcedParent(IcuLocaleDir dir, String localeId, String parent)126         public Builder addForcedParent(IcuLocaleDir dir, String localeId, String parent) {
127             forcedParents.put(dir, localeId, parent);
128             return this;
129         }
130 
131         /** Returns a converter config from the current builder state. */
build()132         public LdmlConverterConfig build() {
133             return new IcuConverterConfig(this);
134         }
135     }
136 
137     private final Path outputDir;
138     private final Path specialsDir;
139     private final ImmutableSet<OutputType> outputTypes;
140     private final IcuVersionInfo versionInfo;
141     private final CldrDraftStatus minimumDraftStatus;
142     private final boolean emitReport;
143     private final ImmutableSet<String> allLocaleIds;
144     private final ImmutableSetMultimap<IcuLocaleDir, String> localeIdsMap;
145     private final ImmutableTable<IcuLocaleDir, String, String> forcedAliases;
146     private final ImmutableTable<IcuLocaleDir, String, String> forcedParents;
147 
IcuConverterConfig(Builder builder)148     private IcuConverterConfig(Builder builder) {
149         this.outputDir = checkNotNull(builder.outputDir);
150         checkArgument(!Files.isRegularFile(outputDir),
151             "specified output directory if not a directory: %s", outputDir);
152         this.specialsDir = checkNotNull(builder.specialsDir,
153             "must specify a 'specials' XML directory");
154         checkArgument(Files.isDirectory(specialsDir),
155             "specified specials directory does not exist: %s", specialsDir);
156         this.outputTypes = builder.outputTypes;
157         checkArgument(!this.outputTypes.isEmpty(),
158             "must specify at least one output type to be generated (possible values are: %s)",
159             Arrays.asList(OutputType.values()));
160         this.versionInfo = new IcuVersionInfo(
161             builder.icuVersion.orElseThrow(() -> new IllegalStateException("missing ICU version")),
162             builder.icuDataVersion.orElseThrow(() -> new IllegalStateException("missing ICU data version")),
163             builder.cldrVersion.orElse(CldrDataSupplier.getCldrVersionString()));
164         this.minimumDraftStatus = checkNotNull(builder.minimumDraftStatus);
165         this.emitReport = builder.emitReport;
166         // getAllLocaleIds() returns the union of all the specified IDs in the map.
167         this.allLocaleIds = ImmutableSet.copyOf(builder.localeIdsMap.values());
168         this.localeIdsMap = ImmutableSetMultimap.copyOf(builder.localeIdsMap);
169         this.forcedAliases = ImmutableTable.copyOf(builder.forcedAliases);
170         this.forcedParents = ImmutableTable.copyOf(builder.forcedParents);
171     }
172 
builder()173     public static Builder builder() {
174         return new Builder();
175     }
176 
177     @Override
getOutputDir()178     public Path getOutputDir() {
179         return outputDir;
180     }
181 
182     @Override
getOutputTypes()183     public Set<OutputType> getOutputTypes() {
184         return outputTypes;
185     }
186 
187     @Override
getSpecialsDir()188     public Path getSpecialsDir() {
189         return specialsDir;
190     }
191 
192     @Override
getVersionInfo()193     public IcuVersionInfo getVersionInfo() {
194         return versionInfo;
195     }
196 
197     @Override
getMinimumDraftStatus()198     public CldrDraftStatus getMinimumDraftStatus() {
199         return minimumDraftStatus;
200     }
201 
202     @Override
emitReport()203     public boolean emitReport() {
204         return emitReport;
205     }
206 
207     @Override
getForcedAliases(IcuLocaleDir dir)208     public ImmutableMap<String, String> getForcedAliases(IcuLocaleDir dir) {
209         return forcedAliases.row(dir);
210     }
211 
212     @Override
getForcedParents(IcuLocaleDir dir)213     public ImmutableMap<String, String> getForcedParents(IcuLocaleDir dir) {
214         return forcedParents.row(dir);
215     }
216 
getAllLocaleIds()217     @Override public ImmutableSet<String> getAllLocaleIds() {
218         return allLocaleIds;
219     }
220 
getTargetLocaleIds(IcuLocaleDir dir)221     @Override public ImmutableSet<String> getTargetLocaleIds(IcuLocaleDir dir) {
222         return localeIdsMap.get(dir);
223     }
224 }
225