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);
+                }
+            }
+        }
+
     }
 }