blob: c8b81007702c18befe6e33260635e815506c7653 [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.mapper;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.unicode.cldr.api.CldrData.PathOrder.NESTED_GROUPING;
import org.unicode.cldr.api.CldrDataSupplier;
import org.unicode.cldr.api.CldrDataType;
import org.unicode.cldr.api.CldrValue;
import org.unicode.icu.tool.cldrtoicu.IcuData;
import org.unicode.icu.tool.cldrtoicu.PathMatcher;
import org.unicode.icu.tool.cldrtoicu.PathValueTransformer;
import org.unicode.icu.tool.cldrtoicu.PathValueTransformer.Result;
import org.unicode.icu.tool.cldrtoicu.RbPath;
/**
* Generate supplemental {@link IcuData} by transforming {@link CldrDataType#SUPPLEMENTAL
* SUPPLEMENTAL} data using a {@link PathValueTransformer}.
*
* <p>This is currently driven by the {@code ldml2icu_supplemental.txt} configuration file via a
* {@code RegexTransformer}, but could use any {@link PathValueTransformer} implementation.
*/
public final class SupplementalMapper extends AbstractPathValueMapper {
private static final RbPath RB_FIFO = RbPath.of("<FIFO>");
/**
* Processes a subset of supplemental data from the given supplier.
*
* @param src the CLDR data supplier to process.
* @param transformer the transformer to match and transform each CLDR path/value pair.
* @param icuName the name for the generated IcuData.
* @param paths a matcher to select the CLDR paths to be transformed.
* @return An IcuData instance containing the specified subset of supplemental data with the
* given ICU name.
*/
// TODO: Improve external data splitting and remove need for a PathMatcher here.
public static IcuData process(
CldrDataSupplier src, PathValueTransformer transformer, String icuName, PathMatcher paths) {
return new SupplementalMapper(src, transformer, paths).generateIcuData(icuName, false);
}
private final PathMatcher paths;
private int fifoCounter = 0;
private SupplementalMapper(
CldrDataSupplier src, PathValueTransformer transformer, PathMatcher pathFilter) {
super(src.getDataForType(CldrDataType.SUPPLEMENTAL), transformer);
this.paths = checkNotNull(pathFilter);
}
@Override
void addResults() {
// DTD and NESTED_GROUPING order differ because of how the magic <FIFO> label works (it
// basically enforces "encounter order" onto things in unlabeled sequences, which matches
// the old behaviour). If it wouldn't break anything, it might be worth moving to DTD order
// to remove any lingering implicit dependencies on the CLDR data behaviour.
getCldrData().accept(NESTED_GROUPING, this::visit);
}
private void visit(CldrValue value) {
if (paths.matchesPrefixOf(value.getPath())) {
transformValue(value).forEach(this::collectResult);
fifoCounter++;
}
}
// <FIFO> hidden labels could be supported in the abstract mapper, but would need a "bulk" add
// method for results (since the counter is updated once per batch, which corresponds to once
// per rule). Having the same FIFO counter value for the same group of values is essential
// since it serves to group them.
//
// TODO: Improve this and push this up into the abstract class (so it works with LocaleMapper).
private void collectResult(Result r) {
RbPath rbPath = r.getKey();
if (rbPath.contains(RB_FIFO)) {
// The fifo counter needs to be formatted with leading zeros for sorting.
rbPath = rbPath.mapSegments(
s -> s.equals("<FIFO>") ? String.format("<%04d>", fifoCounter) : s);
}
addResult(rbPath, r);
}
}