blob: 6a0022b2ad5a04d871f03adb18dd7e24416a3927 [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 org.unicode.icu.tool.cldrtoicu.mapper.DayPeriodsMapperTest.RuleType.AFTERNOON1;
import static org.unicode.icu.tool.cldrtoicu.mapper.DayPeriodsMapperTest.RuleType.EVENING1;
import static org.unicode.icu.tool.cldrtoicu.mapper.DayPeriodsMapperTest.RuleType.MIDNIGHT;
import static org.unicode.icu.tool.cldrtoicu.mapper.DayPeriodsMapperTest.RuleType.MORNING1;
import static org.unicode.icu.tool.cldrtoicu.mapper.DayPeriodsMapperTest.RuleType.NIGHT1;
import static org.unicode.icu.tool.cldrtoicu.mapper.DayPeriodsMapperTest.RuleType.NOON;
import static org.unicode.icu.tool.cldrtoicu.testing.IcuDataSubjectFactory.assertThat;
import java.util.Arrays;
import java.util.Map;
import java.util.Set;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.unicode.cldr.api.CldrData;
import org.unicode.cldr.api.CldrDataSupplier;
import org.unicode.cldr.api.CldrValue;
import org.unicode.icu.tool.cldrtoicu.IcuData;
import com.google.common.base.Ascii;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
@RunWith(JUnit4.class)
public class DayPeriodsMapperTest {
// A subset of rule types for testing.
enum RuleType {
MORNING1, NOON, AFTERNOON1, EVENING1, NIGHT1, MIDNIGHT;
@Override public String toString() {
return Ascii.toLowerCase(name());
}
}
// Possible rule names (these are the value attributes).
enum RuleName {
AT, BEFORE, FROM;
@Override public String toString() {
return Ascii.toLowerCase(name());
}
}
@Test
public void testSimple() {
Set<String> locales = ImmutableSet.of("en_GB", "en_AU", "en_NZ");
CldrData cldrData = cldrData(
dayPeriodRule(locales, MORNING1, isBetween("04:00", "12:00")),
dayPeriodRule(locales, NOON, isAt("12:00")),
dayPeriodRule(locales, AFTERNOON1, isBetween("12:00", "18:00")),
dayPeriodRule(locales, EVENING1, isBetween("18:00", "21:00")),
dayPeriodRule(locales, NIGHT1, isBetween("21:00", "04:00")),
dayPeriodRule(locales, MIDNIGHT, isAt("00:00")));
IcuData icuData = DayPeriodsMapper.process(cldrData);
assertThat(icuData).hasName("dayPeriods");
assertThat(icuData).hasFallback(false);
assertThat(icuData).hasValuesFor("/locales/en_AU", "set1");
assertThat(icuData).hasValuesFor("/locales/en_GB", "set1");
assertThat(icuData).hasValuesFor("/locales/en_NZ", "set1");
assertThat(icuData).hasValuesFor("/rules/set1/morning1/from", "04:00");
assertThat(icuData).hasValuesFor("/rules/set1/morning1/before", "12:00");
assertThat(icuData).hasValuesFor("/rules/set1/noon/at", "12:00");
assertThat(icuData).hasValuesFor("/rules/set1/afternoon1/from", "12:00");
assertThat(icuData).hasValuesFor("/rules/set1/afternoon1/before", "18:00");
assertThat(icuData).hasValuesFor("/rules/set1/evening1/from", "18:00");
assertThat(icuData).hasValuesFor("/rules/set1/evening1/before", "21:00");
assertThat(icuData).hasValuesFor("/rules/set1/night1/from", "21:00");
assertThat(icuData).hasValuesFor("/rules/set1/night1/before", "04:00");
assertThat(icuData).hasValuesFor("/rules/set1/midnight/at", "00:00");
}
@Test
public void testMultipleRuleSets() {
Set<String> locales1 = ImmutableSet.of("en_GB");
Set<String> locales2 = ImmutableSet.of("en_AU", "en_NZ");
CldrData cldrData = cldrData(
dayPeriodRule(locales1, MORNING1, isBetween("04:00", "12:00")),
dayPeriodRule(locales1, NOON, isAt("12:00")),
dayPeriodRule(locales2, MORNING1, isBetween("06:00", "13:00")),
dayPeriodRule(locales2, NOON, isAt("13:00")));
IcuData icuData = DayPeriodsMapper.process(cldrData);
// This reversal of the set ordering (as compared to the order of the input paths) is
// because visitation requires nested path ordering, which is achieved by lexicographical
// ordering of path strings ("en_AU" < "en_GB"). This is an implementation detail however
// and might one day change. If this were switched to use DTD order, then it would be
// stable (but also affect the ordering of paths in the released ICU data).
assertThat(icuData).hasValuesFor("/locales/en_AU", "set1");
assertThat(icuData).hasValuesFor("/locales/en_NZ", "set1");
assertThat(icuData).hasValuesFor("/rules/set1/morning1/from", "06:00");
assertThat(icuData).hasValuesFor("/rules/set1/morning1/before", "13:00");
assertThat(icuData).hasValuesFor("/rules/set1/noon/at", "13:00");
assertThat(icuData).hasValuesFor("/locales/en_GB", "set2");
assertThat(icuData).hasValuesFor("/rules/set2/morning1/from", "04:00");
assertThat(icuData).hasValuesFor("/rules/set2/morning1/before", "12:00");
assertThat(icuData).hasValuesFor("/rules/set2/noon/at", "12:00");
}
@Test
public void testRulesetLabels() {
Set<String> locales = ImmutableSet.of("en_GB");
// Note that there's an implicit assumption in the mapper that the ruleset label is the
// same for all of the rules of any given locale (since it comes from the parent element).
CldrData cldrData = cldrData(
dayPeriodRule(locales, MORNING1, isBetween("04:00", "12:00"), "foo"),
dayPeriodRule(locales, NOON, isAt("12:00"), "foo"));
IcuData icuData = DayPeriodsMapper.process(cldrData);
assertThat(icuData).hasValuesFor("/locales_foo/en_GB", "set1");
assertThat(icuData).hasValuesFor("/rules/set1/morning1/from", "04:00");
assertThat(icuData).hasValuesFor("/rules/set1/morning1/before", "12:00");
assertThat(icuData).hasValuesFor("/rules/set1/noon/at", "12:00");
}
// Just demonstrating that the mapper does no data validation.
@Test
public void testNoDataValidation() {
Set<String> locales = ImmutableSet.of("foo", "bar");
CldrData cldrData = cldrData(
dayPeriodRule(locales, MORNING1, isBetween("start", "end")),
dayPeriodRule(locales, NOON, isAt("moment")));
IcuData icuData = DayPeriodsMapper.process(cldrData);
// This reversal of the set ordering (as compared to the order of the input paths) is
// because visitation requires nested path ordering, which is achieved by lexicographical
// ordering of path strings. This is an implementation detail however and might one day
// change. If this were switched to use DTD order, then it would be stable (but also
// affect the ordering of paths in the released ICU data).
assertThat(icuData).hasValuesFor("/locales/foo", "set1");
assertThat(icuData).hasValuesFor("/locales/bar", "set1");
assertThat(icuData).hasValuesFor("/rules/set1/morning1/from", "start");
assertThat(icuData).hasValuesFor("/rules/set1/morning1/before", "end");
assertThat(icuData).hasValuesFor("/rules/set1/noon/at", "moment");
}
private static CldrData cldrData(CldrValue... values) {
return CldrDataSupplier.forValues(Arrays.asList(values));
}
private static CldrValue dayPeriodRule(
Set<String> locales, RuleType type, Map<RuleName, String> rules) {
return dayPeriodRule(locales, type, rules, null);
}
private static CldrValue dayPeriodRule(
Set<String> locales, RuleType type, Map<RuleName, String> rules, String label) {
StringBuilder cldrPath = new StringBuilder("//supplementalData/dayPeriodRuleSet");
if (label != null) {
appendAttribute(cldrPath, "type", label);
}
appendAttribute(cldrPath.append("/dayPeriodRules"), "locales", Joiner.on(' ').join(locales));
appendAttribute(cldrPath.append("/dayPeriodRule"), "type", type);
rules.forEach((k, v) -> cldrPath.append(String.format("[@%s=\"%s\"]", k, v)));
return CldrValue.parseValue(cldrPath.toString(), "");
}
private static Map<RuleName, String> isAt(String time) {
return ImmutableMap.of(RuleName.AT, time);
}
private static Map<RuleName, String> isBetween(String from, String to) {
return ImmutableMap.of(RuleName.FROM, from, RuleName.BEFORE, to);
}
private static void appendAttribute(StringBuilder out, String k, Object v) {
out.append(String.format("[@%s=\"%s\"]", k, v));
}
}