diff --git a/vortex-api/src/main/java/mil/army/usace/hec/vortex/convert/DataConverter.java b/vortex-api/src/main/java/mil/army/usace/hec/vortex/convert/DataConverter.java index fc65104c..ed725d61 100644 --- a/vortex-api/src/main/java/mil/army/usace/hec/vortex/convert/DataConverter.java +++ b/vortex-api/src/main/java/mil/army/usace/hec/vortex/convert/DataConverter.java @@ -40,7 +40,7 @@ public static List convert(List vortexGrids) { public static VortexGrid convert(VortexGrid vortexGrid) { VortexVariable variable = VortexVariable.fromGrid(vortexGrid); - Unit units = UnitUtil.getUnits(vortexGrid.units()); + Unit units = UnitUtil.parse(vortexGrid.units()); if (units == null) return vortexGrid; diff --git a/vortex-api/src/main/java/mil/army/usace/hec/vortex/io/GridDatasetReader.java b/vortex-api/src/main/java/mil/army/usace/hec/vortex/io/GridDatasetReader.java index 5094c4f0..4afe80d2 100644 --- a/vortex-api/src/main/java/mil/army/usace/hec/vortex/io/GridDatasetReader.java +++ b/vortex-api/src/main/java/mil/army/usace/hec/vortex/io/GridDatasetReader.java @@ -303,7 +303,7 @@ private static Grid getGridDefinition(GridCoordSystem coordinateSystem) { .build()); String xAxisUnits = Objects.requireNonNull(xAxis).getUnitsString(); - Unit cellUnits = UnitUtil.getUnits(xAxisUnits.toLowerCase()); + Unit cellUnits = UnitUtil.parse(xAxisUnits.toLowerCase()); Unit csUnits = ReferenceUtils.getLinearUnits(wkt); // This will scale the grid if cellUnits and csUnits do not align diff --git a/vortex-api/src/main/java/mil/army/usace/hec/vortex/io/VariableDsReader.java b/vortex-api/src/main/java/mil/army/usace/hec/vortex/io/VariableDsReader.java index 787496bf..dfe48f04 100644 --- a/vortex-api/src/main/java/mil/army/usace/hec/vortex/io/VariableDsReader.java +++ b/vortex-api/src/main/java/mil/army/usace/hec/vortex/io/VariableDsReader.java @@ -290,7 +290,7 @@ private static Grid getGridDefinition(NetcdfDataset ncd, CoordinateSystem coordi .build(); String xAxisUnits = Objects.requireNonNull(xAxis).getUnitsString(); - Unit cellUnits = UnitUtil.getUnits(xAxisUnits.toLowerCase()); + Unit cellUnits = UnitUtil.parse(xAxisUnits.toLowerCase()); Unit csUnits = ReferenceUtils.getLinearUnits(wkt); if (cellUnits.isCompatible(csUnits) && !cellUnits.equals(csUnits)) { diff --git a/vortex-api/src/main/java/mil/army/usace/hec/vortex/util/DssUtil.java b/vortex-api/src/main/java/mil/army/usace/hec/vortex/util/DssUtil.java index e376b193..00726fbd 100644 --- a/vortex-api/src/main/java/mil/army/usace/hec/vortex/util/DssUtil.java +++ b/vortex-api/src/main/java/mil/army/usace/hec/vortex/util/DssUtil.java @@ -107,7 +107,7 @@ public static GridInfo getGridInfo(VortexGrid grid) { gridInfo.setCellInfo(minX, minY, grid.nx(), grid.ny(), cellSize); - Unit units = UnitUtil.getUnits(grid.units()); + Unit units = UnitUtil.parse(grid.units()); String unitsString = getUnitsString(units); gridInfo.setDataUnits(unitsString); diff --git a/vortex-api/src/main/java/mil/army/usace/hec/vortex/util/UnitUtil.java b/vortex-api/src/main/java/mil/army/usace/hec/vortex/util/UnitUtil.java index e48efb1d..e2260703 100644 --- a/vortex-api/src/main/java/mil/army/usace/hec/vortex/util/UnitUtil.java +++ b/vortex-api/src/main/java/mil/army/usace/hec/vortex/util/UnitUtil.java @@ -1,29 +1,47 @@ package mil.army.usace.hec.vortex.util; import systems.uom.common.USCustomary; +import tech.units.indriya.format.SimpleUnitFormat; import javax.measure.Unit; +import javax.measure.format.MeasurementParseException; +import javax.measure.format.UnitFormat; import java.util.Optional; import static javax.measure.MetricPrefix.*; -import static systems.uom.common.USCustomary.FAHRENHEIT; -import static systems.uom.common.USCustomary.INCH; +import static systems.uom.common.USCustomary.*; import static tech.units.indriya.AbstractUnit.ONE; +import static tech.units.indriya.unit.Units.HOUR; +import static tech.units.indriya.unit.Units.MINUTE; import static tech.units.indriya.unit.Units.*; public class UnitUtil { - public static Unit getUnits(String units) { + static { + USCustomary.getInstance(); + } + + private UnitUtil() { + // Utility Class + } + + public static Unit parse(String units) { + if (units == null) { + return ONE; + } + return switch (units.toLowerCase()) { case "kg.m-2.s-1", "kg m-2 s-1", "kg/m2s", "mm/s", "mm s-1" -> MILLI(METRE).divide(SECOND); case "mm hr^-1", "mm/hr" -> MILLI(METRE).divide(HOUR); case "mm/day", "mm/d" -> MILLI(METRE).divide(DAY); - case "kg.m-2", "kg/m^2", "kg m^-2", "kg m-2", "mm", "millimeters h20", "millimeters snow thickness" -> - MILLI(METRE); + case "kg.m-2", "kg/m^2", "kg m^-2", "kg m-2", "mm", "millimeter", "millimeters", "millimeters h20", + "millimeters snow thickness" -> MILLI(METRE); case "in", "inch", "inches" -> INCH; - case "1/1000 in" -> ONE.divide(INCH.multiply(1000)); + case "ft", "foot", "feet" -> FOOT; + case "1/1000 in" -> INCH.divide(1000); + case "in/hr" -> INCH.divide(HOUR); case "celsius", "degrees c", "deg c", "deg_c", "degc", "c" -> CELSIUS; case "degc-d" -> CELSIUS.multiply(DAY); - case "degf-d" -> FAHRENHEIT.multiply(DAY); + case "degf-d" -> FAHRENHEIT.multiply(DAY); case "fahrenheit", "deg f", "deg_f", "degf", "f" -> FAHRENHEIT; case "kelvin", "k" -> KELVIN; case "watt/m2", "w m-2" -> WATT.divide(SQUARE_METRE); @@ -34,11 +52,14 @@ public static Unit getUnits(String units) { case "hpa" -> HECTO(PASCAL); case "kpa" -> KILO(PASCAL); case "pa" -> PASCAL; - case "m", "meter", "metre" -> METRE; + case "m", "meter", "metre", "meters" -> METRE; case "min" -> MINUTE; case "km" -> KILO(METRE); case "degrees", "degrees_east", "degrees_north" -> USCustomary.DEGREE_ANGLE; - default -> ONE; + case "hr" -> HOUR; + case "ac", "acre" -> ACRE; + case "sqft", "ft2" -> SQUARE_FOOT; + default -> parseSimpleUnitFormat(units); }; } @@ -47,4 +68,17 @@ public static boolean equals(String units1, String units2) { .map(u -> u.equalsIgnoreCase(units2)) .orElse(units2 == null); } + + private static Unit parseSimpleUnitFormat(String units) { + if (units == null || units.isBlank()) { + return ONE; + } + + try { + UnitFormat format = SimpleUnitFormat.getInstance(); + return format.parse(units); + } catch (MeasurementParseException mpe) { + return ONE; + } + } } diff --git a/vortex-api/src/test/java/mil/army/usace/hec/vortex/util/UnitUtilTest.java b/vortex-api/src/test/java/mil/army/usace/hec/vortex/util/UnitUtilTest.java new file mode 100644 index 00000000..761bcde7 --- /dev/null +++ b/vortex-api/src/test/java/mil/army/usace/hec/vortex/util/UnitUtilTest.java @@ -0,0 +1,34 @@ +package mil.army.usace.hec.vortex.util; + +import org.junit.jupiter.api.Test; +import tech.units.indriya.unit.TransformedUnit; + +import javax.measure.Unit; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static systems.uom.common.USCustomary.INCH; +import static systems.uom.common.USCustomary.SQUARE_FOOT; + +class UnitUtilTest { + + @Test + void unit1divide1000inches() { + String str = "1/1000 in"; + + Unit units = INCH.divide(1000); + Unit parsed = TransformedUnit.parse("in/1000"); + + Unit retrieved = UnitUtil.parse(str); + assertEquals(units, retrieved); + assertEquals(units, parsed); + } + + @Test + void unitSquareFeet() { + String ft2 = "ft2"; + assertEquals(SQUARE_FOOT, UnitUtil.parse(ft2)); + + String sqft = "sqft"; + assertEquals(SQUARE_FOOT, UnitUtil.parse(sqft)); + } +} \ No newline at end of file