ICU-21349 Add extra UnitsRouter constructor that takes only CLDR unit…

See #1579
This commit is contained in:
Younies Mahmoud 2021-02-23 15:09:01 +00:00 committed by Younies Mahmoud
parent c825da1d29
commit 2138ac8a0e
5 changed files with 81 additions and 9 deletions

View file

@ -43,8 +43,23 @@ Precision UnitsRouter::parseSkeletonToPrecision(icu::UnicodeString precisionSkel
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);

View file

@ -120,7 +120,9 @@ namespace units {
*/
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 @@ class U_I18N_API UnitsRouter {
static number::Precision parseSkeletonToPrecision(icu::UnicodeString precisionSkeleton,
UErrorCode &status);
void init(const MeasureUnit &inputUnit, StringPiece locale, StringPiece usage, UErrorCode &status);
};
} // namespace units

View file

@ -964,6 +964,35 @@ void unitPreferencesTestDataLineFn(void *context, char *fields[][2], int32_t fie
}
// 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);
}
/**

View file

@ -47,13 +47,16 @@ public class UnitsRouter {
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 @@ public class UnitsRouter {
}
outputUnits_.add(complexTargetUnitImpl.build());
converterPreferences_.add(new ConverterPreference(inputUnitImpl, complexTargetUnitImpl,
converterPreferences_.add(new ConverterPreference(inputUnit, complexTargetUnitImpl,
preference.getGeq(), precision,
data.getConversionRates()));
}

View file

@ -646,8 +646,7 @@ public class UnitsTest {
}
}
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 @@ public class UnitsTest {
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);
}
}
}
}
}