diff --git a/src/main/java/org/icatproject/utils/IcatUnits.java b/src/main/java/org/icatproject/utils/IcatUnits.java new file mode 100644 index 0000000..285cc0b --- /dev/null +++ b/src/main/java/org/icatproject/utils/IcatUnits.java @@ -0,0 +1,77 @@ +package org.icatproject.utils; + +import javax.measure.IncommensurableException; +import javax.measure.UnconvertibleException; +import javax.measure.Unit; +import javax.measure.UnitConverter; +import javax.measure.format.MeasurementParseException; + +import tech.units.indriya.format.SimpleUnitFormat; + +/** + * Utility to perform conversions to SI (System) units. + */ +public class IcatUnits { + + /** + * Holds the SI units and value for a quantity. If the units provided at construction could not be parsed, then these will be null. + */ + public class SystemValue { + public String units = null; + public Double value = null; + + /** + * Converts value units into an SI quantity. + * + * @param value Quantity in (potentially) non-SI units. + * @param units Units of the provided value. + */ + public SystemValue(Double value, String units) { + try { + Unit unit = unitFormat.parse(units); + Unit systemUnit = unit.getSystemUnit(); + this.units = systemUnit.getName(); + if (value == null) { + return; + } + UnitConverter converter = unit.getConverterToAny(systemUnit); + this.value = converter.convert(value.doubleValue()); + } catch (MeasurementParseException | UnconvertibleException | IncommensurableException e) { + // If the units can't be parsed, or the value converted, then just return + return; + } + } + } + + private static final SimpleUnitFormat unitFormat = SimpleUnitFormat.getInstance(); + + /** + * Creates instance with any aliasing. + */ + public IcatUnits() { + } + + /** + * In addition to the standard names and prefixes, allows aliasing other terms + * for a unit. Note that Unit should be refered to by the symbol specified in + * the + * Indriya + * documentation, but the aliases can be any string. However, OoM prefixes + * will not be applied to aliases. For example, "mK" would be understood as + * 0.001K, but if "Kelvin" is aliased than "mKelvin" will not be understood. + * + * @param aliasOptions String with the format ": , + * : ..." + */ + public IcatUnits(String aliasOptions) { + for (String unitAliases : aliasOptions.split(",")) { + String[] splitUnitAliases = unitAliases.split(":"); + Unit unit = unitFormat.parse(splitUnitAliases[0].trim()); + for (String alias : splitUnitAliases[1].trim().split("\\s+")) { + unitFormat.alias(unit, alias); + } + } + } + +} \ No newline at end of file diff --git a/src/test/java/org/icatproject/utils/TestIcatUnits.java b/src/test/java/org/icatproject/utils/TestIcatUnits.java new file mode 100644 index 0000000..fa2705e --- /dev/null +++ b/src/test/java/org/icatproject/utils/TestIcatUnits.java @@ -0,0 +1,45 @@ +package org.icatproject.utils; + +import static org.junit.Assert.assertEquals; +import org.icatproject.utils.IcatUnits.SystemValue; +import org.junit.Test; + +public class TestIcatUnits { + @Test + public void testArguments() { + // Both null + IcatUnits icatUnits = new IcatUnits(); + SystemValue systemValue = icatUnits.new SystemValue(null, "impossible to parse"); + assertEquals(null, systemValue.units); + assertEquals(null, systemValue.value); + + // Unit parsed, value null + systemValue = icatUnits.new SystemValue(null, "K"); + assertEquals("Kelvin", systemValue.units); + assertEquals(null, systemValue.value); + + // Unit parsed, value converted + systemValue = icatUnits.new SystemValue(1., "GK"); + assertEquals("Kelvin", systemValue.units); + assertEquals(new Double(1e9), systemValue.value); + } + + @Test + public void testAliasing() { + IcatUnits icatUnits = new IcatUnits(); + SystemValue systemValue = icatUnits.new SystemValue(null, "celsius"); + assertEquals(null, systemValue.units); + systemValue = icatUnits.new SystemValue(null, "degC"); + assertEquals(null, systemValue.units); + systemValue = icatUnits.new SystemValue(null, "kelvin"); + assertEquals(null, systemValue.units); + + icatUnits = new IcatUnits("\u2103: celsius degC, K: kelvin"); + systemValue = icatUnits.new SystemValue(null, "celsius"); + assertEquals("Kelvin", systemValue.units); + systemValue = icatUnits.new SystemValue(null, "degC"); + assertEquals("Kelvin", systemValue.units); + systemValue = icatUnits.new SystemValue(null, "kelvin"); + assertEquals("Kelvin", systemValue.units); + } +} \ No newline at end of file