Issue
Task
I am trying to set an alias name on a UOM ProductUnit
to allow the unit to be displayed in a human-friendly name in JSON/my frontend. The unit in question is "kg/h", so a mass-flow rate derived from the SI basic units "kg" and "s".
However, while setting the alias via the SimpleUnitFormat
method
public abstract void alias(Unit<?> unit, String alias);
returns no error, the alias name is disregarded. I am not sure where I go wrong, as code comments on SimpleUnitFormat
say "Attaches a system-wide alias to this unit".
Problem
I expect to be able to parse the string "kg/s" into a Indrya unit and if serializing that unit, get back "kg/s". What I instead get back is "(kg/s)*3600"
The code in form of a unit-test:
public class UnitsTest {
private static final SimpleUnitFormat fs;
private static final Unit<MassFlowRate> KILOGRAM_PER_HOUR;
static {
fs = SimpleUnitFormat.getInstance();
// KILOGRAM_PER_SECOND is defined in si.uom.SI
KILOGRAM_PER_HOUR = KILOGRAM_PER_SECOND.multiply(3600);
fs.alias(KILOGRAM_PER_SECOND.multiply(3600), "kg/h");
}
@Test
void testFlowRate() {
String unitName = "kg/h";
Unit<? extends Quantity<?>> rate = fs.parse(unitName);
Assertions.assertEquals(unitName, rate.toString()); //<-- fails
Assertions.assertEquals(rate, KILOGRAM_PER_HOUR);
}
}
And the assertEquals()
fails with the following:
org.opentest4j.AssertionFailedError:
Expected :kg/h
Actual :(kg/s)*3600
As you can see, the String-representation of the derived unit ("(kg/s)*3600") is physically correct, but not what my end-users would want to see.
What I tried
Replacing rate.toString()
with rate.getName()
doesn't work either, it just yields null
. Replacing rate.toString()
with rate.getSymbol()
doesn't work either, it also yields null
.
Another attempt with using the alternate()
method instead of an alias like this:
KILOGRAM_PER_SECOND.multiply(3600).alternate("kg/h");
fails with
java.lang.IllegalArgumentException: The parent unit: (kg/s)*3600 is not an unscaled SI unit
at tech.units.indriya.unit.AlternateUnit.<init>(AlternateUnit.java:91)
at tech.units.indriya.AbstractUnit.alternate(AbstractUnit.java:336)
Based on this old answer, I tried switching to EBNFUnitFormat
but that doesn't allow aliases.
I am sure I am misunderstanding the whole UoM/Indrya library here, but IDK how.
Environment
The problem comes up both on Windows and Linux. I am using Java 13 and here's the relevant parts of my POM:
<dependencies>
<dependency>
<groupId>tech.units</groupId>
<artifactId>indriya</artifactId>
<version>2.1.3</version>
</dependency>
<dependency>
<groupId>si.uom</groupId>
<artifactId>si-units</artifactId>
<version>2.1</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.9.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.9.0</version>
<scope>test</scope>
</dependency>
</dependencies>
Solution
In the end, it was easy:
fs.label(KILOGRAM_PER_HOUR, "kg/h");
This way, the unit gets serialized to kg/h
in toString()
Answered By - Johannes Jander
Answer Checked By - Senaida (JavaFixing Volunteer)