diff --git a/icu4j/main/common_tests/src/test/java/com/ibm/icu/dev/test/format/MeasureUnitTest.java b/icu4j/main/common_tests/src/test/java/com/ibm/icu/dev/test/format/MeasureUnitTest.java index bc64d401d23c..a45d6d169e9e 100644 --- a/icu4j/main/common_tests/src/test/java/com/ibm/icu/dev/test/format/MeasureUnitTest.java +++ b/icu4j/main/common_tests/src/test/java/com/ibm/icu/dev/test/format/MeasureUnitTest.java @@ -1334,6 +1334,7 @@ class ConstantDenominatorTestCase { new ConstantDenominatorTestCase("second-per-1000-minute", 1000), new ConstantDenominatorTestCase("gram-per-1000-kilogram", 1000), new ConstantDenominatorTestCase("meter-per-100", 100), + // Test for constant denominators that are powers of 10 new ConstantDenominatorTestCase("portion-per-1", 1), new ConstantDenominatorTestCase("portion-per-10", 10), new ConstantDenominatorTestCase("portion-per-100", 100), @@ -1353,6 +1354,8 @@ class ConstantDenominatorTestCase { new ConstantDenominatorTestCase("portion-per-10000000000000000", 10000000000000000L), new ConstantDenominatorTestCase("portion-per-100000000000000000", 100000000000000000L), new ConstantDenominatorTestCase("portion-per-1000000000000000000", 1000000000000000000L), + // Test for constant denominators that are represented as scientific notation + // numbers. new ConstantDenominatorTestCase("portion-per-1e9", 1000000000L), new ConstantDenominatorTestCase("portion-per-1E9", 1000000000L), new ConstantDenominatorTestCase("portion-per-10e9", 10000000000L), @@ -1360,9 +1363,14 @@ class ConstantDenominatorTestCase { new ConstantDenominatorTestCase("portion-per-1e10", 10000000000L), new ConstantDenominatorTestCase("portion-per-1E10", 10000000000L), new ConstantDenominatorTestCase("portion-per-1e3-kilometer", 1000), + // Test for constant denominators that are randomely selected. new ConstantDenominatorTestCase("liter-per-12345-kilometer", 12345), new ConstantDenominatorTestCase("per-1000-kilometer", 1000), new ConstantDenominatorTestCase("liter-per-1000-kiloliter", 1000), + // Test for constant denominators that gives 0. + new ConstantDenominatorTestCase("meter", 0), + new ConstantDenominatorTestCase("meter-per-second", 0), + new ConstantDenominatorTestCase("meter-per-square-second", 0), // NOTE: The following constant denominator should be 0. However, since // `100-kilometer` is treated as a unit in CLDR, // the unit does not have a constant denominator. @@ -1379,7 +1387,35 @@ class ConstantDenominatorTestCase { MeasureUnit unit = MeasureUnit.forIdentifier(testCase.identifier); assertEquals("Constant denominator for " + testCase.identifier, testCase.expectedConstantDenominator, unit.getConstantDenominator()); - assertEquals("Complexity for " + testCase.identifier, Complexity.COMPOUND, unit.getComplexity()); + assertTrue("Complexity for " + testCase.identifier, + unit.getComplexity() == Complexity.COMPOUND || unit.getComplexity() == Complexity.SINGLE); + } + } + + @Test + public void TestNonAcceptableConstantDenominator() { + class NonAcceptableConstantDenominatorTestCase { + String identifier; + + NonAcceptableConstantDenominatorTestCase(String identifier) { + this.identifier = identifier; + } + } + + List testCases = Arrays.asList( + new NonAcceptableConstantDenominatorTestCase("meter-and-second"), + new NonAcceptableConstantDenominatorTestCase("meter-per--20--second"), + new NonAcceptableConstantDenominatorTestCase("meter-per-1000-1e9-second"), + new NonAcceptableConstantDenominatorTestCase("meter-per-1e20-second")); + + for (NonAcceptableConstantDenominatorTestCase testCase : testCases) { + try { + MeasureUnit unit = MeasureUnit.forIdentifier(testCase.identifier); + unit.getConstantDenominator(); + Assert.fail("An IllegalArgumentException must be thrown"); + } catch (Exception e) { + continue; + } } } diff --git a/icu4j/main/core/src/main/java/com/ibm/icu/util/MeasureUnit.java b/icu4j/main/core/src/main/java/com/ibm/icu/util/MeasureUnit.java index 066a2f6fb90f..4c8272d88b1f 100644 --- a/icu4j/main/core/src/main/java/com/ibm/icu/util/MeasureUnit.java +++ b/icu4j/main/core/src/main/java/com/ibm/icu/util/MeasureUnit.java @@ -555,7 +555,7 @@ public MeasurePrefix getPrefix() { * @draft ICU 77 */ public MeasureUnit withConstantDenominator(long denominator) { - if (this.getComplexity() == Complexity.MIXED) { + if (this.getComplexity() != Complexity.COMPOUND && this.getComplexity() != Complexity.SINGLE) { throw new UnsupportedOperationException( "Constant denominator can only be applied to COMPOUND & SINGLE units"); } @@ -581,7 +581,7 @@ public MeasureUnit withConstantDenominator(long denominator) { * zero. * *

- * This method is applicable only to COMPOUND units. If invoked on a SINGLE or + * This method is applicable only to COMPOUND & SINGLE units. If invoked on a * MIXED unit, an exception will be thrown. * For further details, refer to {@link Complexity}. *

@@ -593,8 +593,9 @@ public MeasureUnit withConstantDenominator(long denominator) { * @draft ICU 77 */ public long getConstantDenominator() { - if (this.getComplexity() != Complexity.COMPOUND) { - throw new UnsupportedOperationException("Constant denominator is only supported for COMPOUND units"); + if (this.getComplexity() != Complexity.COMPOUND && this.getComplexity() != Complexity.SINGLE) { + throw new UnsupportedOperationException( + "Constant denominator is only supported for COMPOUND & SINGLE units"); } if (this.measureUnitImpl == null) {