]> granicus.if.org Git - icu/commitdiff
ICU-21935 Add DisplayOptions to NumberFormatterSettings
authorYounies Mahmoud <younies@chromium.org>
Thu, 26 May 2022 17:59:10 +0000 (17:59 +0000)
committerYounies Mahmoud <younies@chromium.org>
Tue, 31 May 2022 20:02:01 +0000 (13:02 -0700)
See #2099

icu4c/source/i18n/number_fluent.cpp
icu4c/source/i18n/unicode/numberformatter.h
icu4c/source/test/intltest/numbertest_api.cpp
icu4j/main/classes/core/src/com/ibm/icu/number/NumberFormatterSettings.java
icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/NumberFormatterApiTest.java

index fd486afb5122498b084ecd93a28de030f473731b..8a968d922c29126c094365cd0d02b5ac3c0250b0 100644 (file)
@@ -288,6 +288,34 @@ Derived NumberFormatterSettings<Derived>::usage(const StringPiece usage)&& {
     return move;
 }
 
+template <typename Derived>
+Derived NumberFormatterSettings<Derived>::displayOptions(const DisplayOptions &displayOptions) const & {
+    Derived copy(*this);
+    // `displayCase` does not recognise the `undefined`
+    if (displayOptions.getGrammaticalCase() == UDISPOPT_GRAMMATICAL_CASE_UNDEFINED) {
+        copy.fMacros.unitDisplayCase.set(nullptr);
+        return copy;
+    }
+
+    copy.fMacros.unitDisplayCase.set(
+        udispopt_getGrammaticalCaseIdentifier(displayOptions.getGrammaticalCase()));
+    return copy;
+}
+
+template <typename Derived>
+Derived NumberFormatterSettings<Derived>::displayOptions(const DisplayOptions &displayOptions) && {
+    Derived move(std::move(*this));
+    // `displayCase` does not recognise the `undefined`
+    if (displayOptions.getGrammaticalCase() == UDISPOPT_GRAMMATICAL_CASE_UNDEFINED) {
+        move.fMacros.unitDisplayCase.set(nullptr);
+        return move;
+    }
+
+    move.fMacros.unitDisplayCase.set(
+        udispopt_getGrammaticalCaseIdentifier(displayOptions.getGrammaticalCase()));
+    return move;
+}
+
 template<typename Derived>
 Derived NumberFormatterSettings<Derived>::unitDisplayCase(const StringPiece unitDisplayCase) const& {
     Derived copy(*this);
index 09bbdb8c3b0a3bf2fc74029b9ec04b4caa4660e0..339a6098cc669f2cb3e325f4a98a79e74d5cc68d 100644 (file)
@@ -14,6 +14,7 @@
 #include "unicode/bytestream.h"
 #include "unicode/currunit.h"
 #include "unicode/dcfmtsym.h"
+#include "unicode/displayoptions.h"
 #include "unicode/fieldpos.h"
 #include "unicode/formattedvalue.h"
 #include "unicode/fpositer.h"
@@ -2254,23 +2255,44 @@ class U_I18N_API NumberFormatterSettings {
     Derived usage(StringPiece usage) &&;
 
 #ifndef U_HIDE_DRAFT_API
-#ifndef U_HIDE_INTERNAL_API
     /**
+     * Specifies the DisplayOptions. For example, UDisplayOptionsGrammaticalCase specifies
+     * the desired case for a unit formatter's output (e.g. accusative, dative, genitive).
+     *
+     * @param displayOptions
+     * @return The fluent chain.
+     * @draft ICU 72
+     */
+    Derived displayOptions(const DisplayOptions &displayOptions) const &;
+
+    /**
+     * Overload of displayOptions() for use on an rvalue reference.
+     *
+     * @param displayOptions
+     * @return The fluent chain.
+     * @draft ICU 72
+     */
+    Derived displayOptions(const DisplayOptions &displayOptions) &&;
+#endif // U_HIDE_DRAFT_API
+
+#ifndef U_HIDE_DEPRECATED_API
+    /**
+     * NOTE: This function is deprecated, use `displayOptions` instead.
+     *
      * Specifies the desired case for a unit formatter's output (e.g.
      * accusative, dative, genitive).
      *
-     * @internal ICU 69 technology preview
+     * @deprecated ICU 72
      */
     Derived unitDisplayCase(StringPiece unitDisplayCase) const &;
 
     /**
      * Overload of unitDisplayCase() for use on an rvalue reference.
      *
-     * @internal ICU 69 technology preview
+     * @deprecated ICU 72
      */
     Derived unitDisplayCase(StringPiece unitDisplayCase) &&;
-#endif // U_HIDE_INTERNAL_API
-#endif // U_HIDE_DRAFT_API
+#endif // U_HIDE_DEPRECATED_API
 
 #ifndef U_HIDE_INTERNAL_API
 
index 674250abaebc1838b66424dc391703be25f60cf8..3bd993a7453f83d03c7906ba55e2856125542603 100644 (file)
@@ -5,19 +5,22 @@
 
 #if !UCONFIG_NO_FORMATTING
 
-#include "charstr.h"
-#include <cstdarg>
 #include <cmath>
+#include <cstdarg>
 #include <memory>
-#include "unicode/unum.h"
+
+#include "unicode/displayoptions.h"
 #include "unicode/numberformatter.h"
 #include "unicode/testlog.h"
+#include "unicode/unum.h"
 #include "unicode/utypes.h"
+
+#include "charstr.h"
 #include "number_asformat.h"
+#include "number_microprops.h"
 #include "number_types.h"
 #include "number_utils.h"
 #include "number_utypes.h"
-#include "number_microprops.h"
 #include "numbertest.h"
 
 using number::impl::UFormattedNumberData;
@@ -2312,6 +2315,39 @@ void NumberFormatterApiTest::runUnitInflectionsTestCases(UnlocalizedNumberFormat
                            skel, skel, unf, Locale(t.locale), t.value, t.expected);
         status.assertSuccess();
     }
+
+    for (int32_t i = 0; i < numCases; i++) {
+        UnitInflectionTestCase t = cases[i];
+        status.assertSuccess();
+        MeasureUnit mu = MeasureUnit::forIdentifier(t.unitIdentifier, status);
+        if (status.errIfFailureAndReset("MeasureUnit::forIdentifier(\"%s\", ...) failed",
+                                        t.unitIdentifier)) {
+            continue;
+        };
+
+        UnicodeString skelString = UnicodeString("unit/") + t.unitIdentifier + u" " + skeleton;
+        const UChar *skel;
+        auto displayOptionsBuilder = DisplayOptions::builder();
+        if (t.unitDisplayCase == nullptr || t.unitDisplayCase[0] == 0) {
+            auto displayoptions = displayOptionsBuilder.build();
+            unf = unf.unit(mu).displayOptions(displayoptions);
+            skel = skelString.getTerminatedBuffer();
+        } else {
+            auto displayoptions =
+                displayOptionsBuilder
+                    .setGrammaticalCase(udispopt_fromGrammaticalCaseIdentifier(t.unitDisplayCase))
+                    .build();
+            unf = unf.unit(mu).displayOptions(displayoptions);
+            // No skeleton support for unitDisplayCase yet.
+            skel = nullptr;
+        }
+        assertFormatSingle((UnicodeString("Unit: \"") + t.unitIdentifier + ("\", \"") + skeleton +
+                            u"\", locale=\"" + t.locale + u"\", case=\"" +
+                            (t.unitDisplayCase ? t.unitDisplayCase : "") + u"\", value=" + t.value)
+                               .getTerminatedBuffer(),
+                           skel, skel, unf, Locale(t.locale), t.value, t.expected);
+        status.assertSuccess();
+    }
 }
 
 void NumberFormatterApiTest::unitInflections() {
index 800048792ff11ababd2b0b9536037c81a59fd363..c820a823ea1ec22c49b236323ea0870dcb803faa 100644 (file)
@@ -2,6 +2,8 @@
 // License & terms of use: http://www.unicode.org/copyright.html
 package com.ibm.icu.number;
 
+import com.ibm.icu.text.DisplayOptions;
+import com.ibm.icu.text.DisplayOptions.GrammaticalCase;
 import java.math.RoundingMode;
 
 import com.ibm.icu.impl.number.MacroProps;
@@ -552,6 +554,22 @@ public abstract class NumberFormatterSettings<T extends NumberFormatterSettings<
         return create(KEY_USAGE, usage);
     }
 
+    /**
+     * Specifies the {@code DisplayOptions}. For example, {@code GrammaticalCase} specifies
+     * the desired case for a unit formatter's output (e.g. accusative, dative, genitive).
+     *
+     * @return The fluent chain.
+     * @draft ICU 72
+     */
+    public T displayOptions(DisplayOptions displayOptions) {
+        // `displayCase` does not recognise the `undefined`
+        if (displayOptions.getGrammaticalCase() == GrammaticalCase.UNDEFINED) {
+            return create(KEY_UNIT_DISPLAY_CASE, null);
+        }
+
+        return create(KEY_UNIT_DISPLAY_CASE, displayOptions.getGrammaticalCase().getIdentifier());
+    }
+
     /**
      * Specifies the desired case for a unit formatter's output (e.g.
      * accusative, dative, genitive).
index 671121e3c43775aa9fd1949f867d69ddb4d3ad91..e2baab1be718f9815c67e20c838d292e441d2fe9 100644 (file)
@@ -2,6 +2,7 @@
 // License & terms of use: http://www.unicode.org/copyright.html
 package com.ibm.icu.dev.test.number;
 
+
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.math.BigDecimal;
@@ -18,6 +19,8 @@ import org.junit.Assert;
 import org.junit.Ignore;
 import org.junit.Test;
 
+import com.ibm.icu.text.DisplayOptions;
+import com.ibm.icu.text.DisplayOptions.GrammaticalCase;
 import com.ibm.icu.dev.test.TestFmwk;
 import com.ibm.icu.dev.test.format.FormattedValueTest;
 import com.ibm.icu.dev.test.serializable.SerializableTestUtility;
@@ -2276,6 +2279,28 @@ public class NumberFormatterApiTest extends TestFmwk {
                                    "\", value=" + this.value,
                                skel, skel, unf, new ULocale(this.locale), this.value, this.expected);
         }
+
+        public void runTestWithDisplayOptions(UnlocalizedNumberFormatter unf, String skeleton) {
+            MeasureUnit mu = MeasureUnit.forIdentifier(unitIdentifier);
+            String skel;
+
+            DisplayOptions.Builder displayOptionsBuilder = DisplayOptions.builder();
+            if (this.unitDisplayCase == null || this.unitDisplayCase.isEmpty()) {
+                DisplayOptions displayOptions = displayOptionsBuilder.build();
+                unf = unf.unit(mu).displayOptions(displayOptions);
+                skel = "unit/" + unitIdentifier + " " + skeleton;
+            } else {
+                DisplayOptions displayOptions = displayOptionsBuilder.setGrammaticalCase(
+                    GrammaticalCase.fromIdentifier(this.unitDisplayCase)).build();
+                unf = unf.unit(mu).displayOptions(displayOptions);
+                // No skeleton support for unitDisplayCase yet.
+                skel = null;
+            }
+            assertFormatSingle("\"" + skeleton + "\", locale=\"" + this.locale + "\", case=\"" +
+                    (this.unitDisplayCase != null ? this.unitDisplayCase : "") +
+                    "\", value=" + this.value,
+                skel, skel, unf, new ULocale(this.locale), this.value, this.expected);
+        }
     }
 
     @Test
@@ -2298,6 +2323,7 @@ public class NumberFormatterApiTest extends TestFmwk {
             };
             for (UnitInflectionTestCase t : percentCases) {
                 t.runTest(unf, skeleton);
+                t.runTestWithDisplayOptions(unf, skeleton);
             }
         }
         {
@@ -2393,6 +2419,7 @@ public class NumberFormatterApiTest extends TestFmwk {
             };
             for (UnitInflectionTestCase t : testCases) {
                 t.runTest(unf, skeleton);
+                t.runTestWithDisplayOptions(unf, skeleton);
             }
         }
         {
@@ -2422,6 +2449,7 @@ public class NumberFormatterApiTest extends TestFmwk {
             };
             for (UnitInflectionTestCase t : meterPerDayCases) {
                 t.runTest(unf, skeleton);
+                t.runTestWithDisplayOptions(unf, skeleton);
             }
         }
         // TODO: add a usage case that selects between preferences with different