ICU-21349 Add extra UnitsRouter constructor that takes only CLDR unit…
See #1579
diff --git a/icu4c/source/i18n/units_router.cpp b/icu4c/source/i18n/units_router.cpp
index 9fc389d4..51f66bf 100644
--- a/icu4c/source/i18n/units_router.cpp
+++ b/icu4c/source/i18n/units_router.cpp
@@ -43,8 +43,23 @@
return result;
}
-UnitsRouter::UnitsRouter(MeasureUnit inputUnit, StringPiece region, StringPiece usage,
+UnitsRouter::UnitsRouter(StringPiece inputUnitIdentifier, StringPiece region, StringPiece usage,
UErrorCode &status) {
+ this->init(MeasureUnit::forIdentifier(inputUnitIdentifier, status), region, usage, status);
+}
+
+UnitsRouter::UnitsRouter(const MeasureUnit &inputUnit, StringPiece region, StringPiece usage,
+ UErrorCode &status) {
+ this->init(std::move(inputUnit), region, usage, status);
+}
+
+void UnitsRouter::init(const MeasureUnit &inputUnit, StringPiece region, StringPiece usage,
+ UErrorCode &status) {
+
+ if (U_FAILURE(status)) {
+ return;
+ }
+
// TODO: do we want to pass in ConversionRates and UnitPreferences instead
// of loading in each UnitsRouter instance? (Or make global?)
ConversionRates conversionRates(status);
diff --git a/icu4c/source/i18n/units_router.h b/icu4c/source/i18n/units_router.h
index bd7a93d..c6e4e4f 100644
--- a/icu4c/source/i18n/units_router.h
+++ b/icu4c/source/i18n/units_router.h
@@ -120,7 +120,9 @@
*/
class U_I18N_API UnitsRouter {
public:
- UnitsRouter(MeasureUnit inputUnit, StringPiece locale, StringPiece usage, UErrorCode &status);
+ UnitsRouter(StringPiece inputUnitIdentifier, StringPiece locale, StringPiece usage,
+ UErrorCode &status);
+ UnitsRouter(const MeasureUnit &inputUnit, StringPiece locale, StringPiece usage, UErrorCode &status);
/**
* Performs locale and usage sensitive unit conversion.
@@ -152,6 +154,8 @@
static number::Precision parseSkeletonToPrecision(icu::UnicodeString precisionSkeleton,
UErrorCode &status);
+
+ void init(const MeasureUnit &inputUnit, StringPiece locale, StringPiece usage, UErrorCode &status);
};
} // namespace units
diff --git a/icu4c/source/test/intltest/units_test.cpp b/icu4c/source/test/intltest/units_test.cpp
index 8e9bfbc..87cd16d 100644
--- a/icu4c/source/test/intltest/units_test.cpp
+++ b/icu4c/source/test/intltest/units_test.cpp
@@ -964,6 +964,35 @@
}
// TODO: revisit this experimentally chosen precision:
checkOutput(unitsTest, msg.data(), expected, routeResult.measures, 0.0000000001);
+
+ // Test UnitsRouter created with CLDR units identifiers.
+ CharString inputUnitIdentifier(inputUnit, status);
+ UnitsRouter router2(inputUnitIdentifier.data(), region, usage, status);
+ if (status.errIfFailureAndReset("UnitsRouter2(<%s>, \"%.*s\", \"%.*s\", status)",
+ inputUnitIdentifier.data(), region.length(), region.data(),
+ usage.length(), usage.data())) {
+ return;
+ }
+
+ CharString msg2(quantity, status);
+ msg2.append(" ", status);
+ msg2.append(usage, status);
+ msg2.append(" ", status);
+ msg2.append(region, status);
+ msg2.append(" ", status);
+ msg2.append(inputD, status);
+ msg2.append(" ", status);
+ msg2.append(inputUnitIdentifier.data(), status);
+ if (status.errIfFailureAndReset("Failure before router2.route")) {
+ return;
+ }
+
+ RouteResult routeResult2 = router2.route(inputAmount, nullptr, status);
+ if (status.errIfFailureAndReset("router2.route(inputAmount, ...)")) {
+ return;
+ }
+ // TODO: revisit this experimentally chosen precision:
+ checkOutput(unitsTest, msg2.data(), expected, routeResult.measures, 0.0000000001);
}
/**
diff --git a/icu4j/main/classes/core/src/com/ibm/icu/impl/units/UnitsRouter.java b/icu4j/main/classes/core/src/com/ibm/icu/impl/units/UnitsRouter.java
index b7c925c..cfb6fa0 100644
--- a/icu4j/main/classes/core/src/com/ibm/icu/impl/units/UnitsRouter.java
+++ b/icu4j/main/classes/core/src/com/ibm/icu/impl/units/UnitsRouter.java
@@ -47,13 +47,16 @@
private ArrayList<MeasureUnit> outputUnits_ = new ArrayList<>();
private ArrayList<ConverterPreference> converterPreferences_ = new ArrayList<>();
- public UnitsRouter(MeasureUnitImpl inputUnitImpl, String region, String usage) {
+ public UnitsRouter(String inputUnitIdentifier, String region, String usage) {
+ this(MeasureUnitImpl.forIdentifier(inputUnitIdentifier), region, usage);
+ }
+
+ public UnitsRouter(MeasureUnitImpl inputUnit, String region, String usage) {
// TODO: do we want to pass in ConversionRates and UnitPreferences instead?
// of loading in each UnitsRouter instance? (Or make global?)
UnitsData data = new UnitsData();
- //MeasureUnitImpl inputUnitImpl = MeasureUnitImpl.forMeasureUnitMaybeCopy(inputUnit);
- String category = data.getCategory(inputUnitImpl);
+ String category = data.getCategory(inputUnit);
UnitPreferences.UnitPreference[] unitPreferences = data.getPreferencesFor(category, usage, region);
for (int i = 0; i < unitPreferences.length; ++i) {
@@ -74,7 +77,7 @@
}
outputUnits_.add(complexTargetUnitImpl.build());
- converterPreferences_.add(new ConverterPreference(inputUnitImpl, complexTargetUnitImpl,
+ converterPreferences_.add(new ConverterPreference(inputUnit, complexTargetUnitImpl,
preference.getGeq(), precision,
data.getConversionRates()));
}
diff --git a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/impl/UnitsTest.java b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/impl/UnitsTest.java
index 107503a..927ff58 100644
--- a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/impl/UnitsTest.java
+++ b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/impl/UnitsTest.java
@@ -646,8 +646,7 @@
}
}
- for (TestCase testCase :
- tests) {
+ for (TestCase testCase : tests) {
UnitsRouter router = new UnitsRouter(testCase.inputUnit.second, testCase.region, testCase.usage);
List<Measure> measures = router.route(testCase.input, null).complexConverterResult.measures;
@@ -661,10 +660,32 @@
if (!UnitsTest
.compareTwoBigDecimal(testCase.expectedInOrder.get(i),
BigDecimal.valueOf(measures.get(i).getNumber().doubleValue()),
- BigDecimal.valueOf(0.00001))) {
+ BigDecimal.valueOf(0.0000000001))) {
fail("Test failed: " + testCase + "; Got unexpected result: " + measures);
}
}
}
+
+ // Test UnitsRouter created with CLDR units identifiers.
+ for (TestCase testCase : tests) {
+ UnitsRouter router = new UnitsRouter(testCase.inputUnit.first, testCase.region, testCase.usage);
+ List<Measure> measures = router.route(testCase.input, null).complexConverterResult.measures;
+
+ assertEquals("Measures size must be the same as expected units",
+ measures.size(), testCase.expectedInOrder.size());
+ assertEquals("Measures size must be the same as output units",
+ measures.size(), testCase.outputUnitInOrder.size());
+
+
+ for (int i = 0; i < measures.size(); i++) {
+ if (!UnitsTest
+ .compareTwoBigDecimal(testCase.expectedInOrder.get(i),
+ BigDecimal.valueOf(measures.get(i).getNumber().doubleValue()),
+ BigDecimal.valueOf(0.0000000001))) {
+ fail("Test failed: " + testCase + "; Got unexpected result: " + measures);
+ }
+ }
+ }
+
}
}