Updating MeasureUnit with new CLDR data
Contents
This document explains how to update the C++ and Java version of the MeasureUnit
class with new CLDR data.
This document applies to ICU 77 and later. For older versions see updating-measure-unit-old.md
Make sure DRAFT_VERSION_SET
at top of ./icu4j/main/common_tests/src/test/java/com/ibm/icu/dev/test/format/MeasureUnitGeneratorTest.java
is set correctly.
These are the ICU versions that have draft methods.
The code is generated by running MeasureUnitGeneratorTest.java
unit tests, which writes generated code to various file.
- With maven (command line):
- Change folder to
{icuRoot}/icu4j
- run
mvn install -DskipTests -DskipITs
- run
mvn install -q -Dtest=MeasureUnitGeneratorTest -DgenerateMeasureUnitUpdate -f main/common_tests
- Change folder to
- Within Eclipse:
- Open
MeasureUnitGeneratorTest.java
, find thegenerateUnitTestsUpdate
methods and run it by clicking on the green play button on menu bar.
Choose “JUnit Test” if asked.
This will not generate the update, but it will run the test and create a “Run Configuration”.
Open it (Main menu – “Run” – “Run Configurations”), select the one namedMeasureUnitGeneratorTest.generateUnitTestsUpdate
, go to the “Arguments” tab and add-DgenerateMeasureUnitUpdate
to the “VM Arguments” text area.
- Open
Both methods will generate files with in icu4j/main/common_tests/target/
folder.
The file names and the logging to the standard output will guide you.
It currently looks something like this:
Copy the generated code fragments from / to
/some/absolute/path/icu4j/main/common_tests/target/MeasureUnit.java \
/some/absolute/path/icu4j/main/core/src/main/java/com/ibm/icu/util/MeasureUnit.java
Copy the generated code fragments from / to
/some/absolute/path/icu4j/main/common_tests/target/MeasureUnitCompatibilityTest.java \
/some/absolute/path/icu4j/main/common_tests/src/test/java/com/ibm/icu/dev/test/format/MeasureUnitCompatibilityTest.java
Copy the generated code fragments from / to
/some/absolute/path/icu4j/main/common_tests/target/measunit.h \
/some/absolute/path/icu4c/source/i18n/unicode/measunit.h
Copy the generated code fragments from / to
/some/absolute/path/icu4j/main/common_tests/target/measunit.cpp \
/some/absolute/path/icu4c/source/i18n/measunit.cpp
Copy the generated code fragments from / to
/some/absolute/path/icu4j/main/common_tests/target/measfmttest.cpp \
/some/absolute/path/icu4c/source/test/intltest/measfmttest.cpp
Copy the generated code fragments from / to
/some/absolute/path/icu4j/main/common_tests/target/MeasureUnitGeneratorTest.java \
/some/absolute/path/icu4j/main/common_tests/src/test/java/com/ibm/icu/dev/test/format/MeasureUnitGeneratorTest.java
Some kind of diff tool or editor (for example vi -d
) work nicely.
Look for line containing // Start generated ...
and // End generated ...
These lines exist in both the original files, and the generated one.
Replace all the generated code in between with the contents of the clipboard.
If the generated code has no // Start
… // End ...
pair then the new code should be appended at some fixed place (details below).
MeasureUnit.java
: replace range.MeasureUnitCompatibilityTest.java
: append the new generated method at the end.
It is named something likeTestCompatible<version>()
.
Don’t add it if it already exists.measunit.h
: replace range.measunit.cpp
: replace range.measfmttest.cpp
: append the new generated method after the lastMeasureFormatTest::TestCompatible<version>()
method.
Don’t add it if it already exists.
WARNING: here you should add the method in two places. The method proper, with code, as generated, and the declaration in the class definition.MeasureUnitGeneratorTest.java
: append the new pairs of measure + version at the end of theJAVA_VERSIONS
structure.
Don’t add them if they already exist.
Run tests for both icu4c
and icu4j
Updating units.txt
and unitConstants
The standard ldml2icu
process is used to update ICU’s resource files (see cldr-icu-readme.txt
). CLDR’s units.xml defines conversion rates in terms of some constants defined in unitConstants
.
For efficiency and simplicity, ICU does not read unitConstants
from the resource file. If any new constants are added, some code changes would be needed. This would be caught by testUnitConstantFreshness
unit test in units_test.cpp
.
They are hard-coded:
- Java:
UnitConverter.java
has the constant names inUnitConverter.Factor.addEntity()
and constant values inUnitConverter.Factor.getConversionRate()
. - C++:
units_converter.cpp
has the constant names inaddSingleFactorConstant()
, with the constant values indouble constantsValues[]
in theunits_converter.h
header file.