diff --git a/bundles/org.openhab.core/src/main/java/org/openhab/core/internal/i18n/I18nProviderImpl.java b/bundles/org.openhab.core/src/main/java/org/openhab/core/internal/i18n/I18nProviderImpl.java index 71a605882..e308aae44 100644 --- a/bundles/org.openhab.core/src/main/java/org/openhab/core/internal/i18n/I18nProviderImpl.java +++ b/bundles/org.openhab.core/src/main/java/org/openhab/core/internal/i18n/I18nProviderImpl.java @@ -25,12 +25,39 @@ import java.util.ResourceBundle; import javax.measure.Quantity; import javax.measure.Unit; +import javax.measure.quantity.Acceleration; +import javax.measure.quantity.AmountOfSubstance; import javax.measure.quantity.Angle; +import javax.measure.quantity.Area; +import javax.measure.quantity.CatalyticActivity; import javax.measure.quantity.Dimensionless; +import javax.measure.quantity.ElectricCapacitance; +import javax.measure.quantity.ElectricCharge; +import javax.measure.quantity.ElectricConductance; +import javax.measure.quantity.ElectricCurrent; +import javax.measure.quantity.ElectricInductance; +import javax.measure.quantity.ElectricPotential; +import javax.measure.quantity.ElectricResistance; +import javax.measure.quantity.Energy; +import javax.measure.quantity.Force; +import javax.measure.quantity.Frequency; +import javax.measure.quantity.Illuminance; import javax.measure.quantity.Length; +import javax.measure.quantity.LuminousFlux; +import javax.measure.quantity.LuminousIntensity; +import javax.measure.quantity.MagneticFlux; +import javax.measure.quantity.MagneticFluxDensity; +import javax.measure.quantity.Mass; +import javax.measure.quantity.Power; import javax.measure.quantity.Pressure; +import javax.measure.quantity.RadiationDoseAbsorbed; +import javax.measure.quantity.RadiationDoseEffective; +import javax.measure.quantity.Radioactivity; +import javax.measure.quantity.SolidAngle; import javax.measure.quantity.Speed; import javax.measure.quantity.Temperature; +import javax.measure.quantity.Time; +import javax.measure.quantity.Volume; import javax.measure.spi.SystemOfUnits; import org.eclipse.jdt.annotation.NonNullByDefault; @@ -40,7 +67,13 @@ import org.openhab.core.i18n.LocationProvider; import org.openhab.core.i18n.TimeZoneProvider; import org.openhab.core.i18n.TranslationProvider; import org.openhab.core.i18n.UnitProvider; +import org.openhab.core.library.dimension.ArealDensity; +import org.openhab.core.library.dimension.DataAmount; +import org.openhab.core.library.dimension.DataTransferRate; +import org.openhab.core.library.dimension.Density; +import org.openhab.core.library.dimension.ElectricConductivity; import org.openhab.core.library.dimension.Intensity; +import org.openhab.core.library.dimension.VolumetricFlowRate; import org.openhab.core.library.types.PointType; import org.openhab.core.library.unit.ImperialUnits; import org.openhab.core.library.unit.SIUnits; @@ -107,7 +140,7 @@ public class I18nProviderImpl private @Nullable ZoneId timeZone; // UnitProvider - private static final String MEASUREMENT_SYSTEM = "measurementSystem"; + static final String MEASUREMENT_SYSTEM = "measurementSystem"; private @Nullable SystemOfUnits measurementSystem; private final Map>, Map>>> dimensionMap = new HashMap<>(); @@ -122,7 +155,7 @@ public class I18nProviderImpl } @Deactivate - protected void deactivate(ComponentContext componentContext) { + protected void deactivate() { this.resourceBundleTracker.close(); } @@ -319,8 +352,8 @@ public class I18nProviderImpl return text; } - @SuppressWarnings("unchecked") @Override + @SuppressWarnings("unchecked") public > @Nullable Unit getUnit(@Nullable Class dimension) { Map>> map = dimensionMap.get(dimension); if (map == null) { @@ -344,39 +377,53 @@ public class I18nProviderImpl } private void initDimensionMap() { - Map>> temperatureMap = new HashMap<>(); - temperatureMap.put(SIUnits.getInstance(), SIUnits.CELSIUS); - temperatureMap.put(ImperialUnits.getInstance(), ImperialUnits.FAHRENHEIT); - dimensionMap.put(Temperature.class, temperatureMap); + addDefaultUnit(Acceleration.class, Units.METRE_PER_SQUARE_SECOND); + addDefaultUnit(AmountOfSubstance.class, Units.MOLE); + addDefaultUnit(Angle.class, Units.DEGREE_ANGLE, Units.DEGREE_ANGLE); + addDefaultUnit(Area.class, SIUnits.SQUARE_METRE, ImperialUnits.SQUARE_FOOT); + addDefaultUnit(ArealDensity.class, Units.DOBSON_UNIT); + addDefaultUnit(CatalyticActivity.class, Units.KATAL); + addDefaultUnit(DataAmount.class, Units.BYTE); + addDefaultUnit(DataTransferRate.class, Units.MEGABIT_PER_SECOND); + addDefaultUnit(Density.class, Units.KILOGRAM_PER_CUBICMETRE); + addDefaultUnit(Dimensionless.class, Units.ONE); + addDefaultUnit(ElectricCapacitance.class, Units.FARAD); + addDefaultUnit(ElectricCharge.class, Units.COULOMB); + addDefaultUnit(ElectricConductance.class, Units.SIEMENS); + addDefaultUnit(ElectricConductivity.class, Units.SIEMENS_PER_METRE); + addDefaultUnit(ElectricCurrent.class, Units.AMPERE); + addDefaultUnit(ElectricInductance.class, Units.HENRY); + addDefaultUnit(ElectricPotential.class, Units.VOLT); + addDefaultUnit(ElectricResistance.class, Units.OHM); + addDefaultUnit(Energy.class, Units.JOULE); + addDefaultUnit(Force.class, Units.NEWTON); + addDefaultUnit(Frequency.class, Units.HERTZ); + addDefaultUnit(Illuminance.class, Units.LUX); + addDefaultUnit(Intensity.class, Units.IRRADIANCE); + addDefaultUnit(Length.class, SIUnits.METRE, ImperialUnits.FOOT); + addDefaultUnit(LuminousFlux.class, Units.LUMEN); + addDefaultUnit(LuminousIntensity.class, Units.CANDELA); + addDefaultUnit(MagneticFlux.class, Units.WEBER); + addDefaultUnit(MagneticFluxDensity.class, Units.TESLA); + addDefaultUnit(Mass.class, SIUnits.KILOGRAM, ImperialUnits.POUND); + addDefaultUnit(Power.class, Units.WATT); + addDefaultUnit(Pressure.class, HECTO(SIUnits.PASCAL), ImperialUnits.INCH_OF_MERCURY); + addDefaultUnit(RadiationDoseAbsorbed.class, Units.GRAY); + addDefaultUnit(RadiationDoseEffective.class, Units.SIEVERT); + addDefaultUnit(Radioactivity.class, Units.BECQUEREL); + addDefaultUnit(SolidAngle.class, Units.STERADIAN); + addDefaultUnit(Speed.class, SIUnits.KILOMETRE_PER_HOUR, ImperialUnits.MILES_PER_HOUR); + addDefaultUnit(Temperature.class, SIUnits.CELSIUS, ImperialUnits.FAHRENHEIT); + addDefaultUnit(Time.class, Units.SECOND); + addDefaultUnit(Volume.class, SIUnits.CUBIC_METRE, ImperialUnits.GALLON_LIQUID_US); + addDefaultUnit(VolumetricFlowRate.class, Units.LITRE_PER_MINUTE, ImperialUnits.GALLON_PER_MINUTE); + } - Map>> pressureMap = new HashMap<>(); - pressureMap.put(SIUnits.getInstance(), HECTO(SIUnits.PASCAL)); - pressureMap.put(ImperialUnits.getInstance(), ImperialUnits.INCH_OF_MERCURY); - dimensionMap.put(Pressure.class, pressureMap); + private > void addDefaultUnit(Class dimension, Unit siUnit, Unit imperialUnit) { + dimensionMap.put(dimension, Map.of(SIUnits.getInstance(), siUnit, ImperialUnits.getInstance(), imperialUnit)); + } - Map>> speedMap = new HashMap<>(); - speedMap.put(SIUnits.getInstance(), SIUnits.KILOMETRE_PER_HOUR); - speedMap.put(ImperialUnits.getInstance(), ImperialUnits.MILES_PER_HOUR); - dimensionMap.put(Speed.class, speedMap); - - Map>> lengthMap = new HashMap<>(); - lengthMap.put(SIUnits.getInstance(), SIUnits.METRE); - lengthMap.put(ImperialUnits.getInstance(), ImperialUnits.INCH); - dimensionMap.put(Length.class, lengthMap); - - Map>> intensityMap = new HashMap<>(); - intensityMap.put(SIUnits.getInstance(), Units.IRRADIANCE); - intensityMap.put(ImperialUnits.getInstance(), Units.IRRADIANCE); - dimensionMap.put(Intensity.class, intensityMap); - - Map>> percentMap = new HashMap<>(); - percentMap.put(SIUnits.getInstance(), Units.ONE); - percentMap.put(ImperialUnits.getInstance(), Units.ONE); - dimensionMap.put(Dimensionless.class, percentMap); - - Map>> angleMap = new HashMap<>(); - angleMap.put(SIUnits.getInstance(), Units.DEGREE_ANGLE); - angleMap.put(ImperialUnits.getInstance(), Units.DEGREE_ANGLE); - dimensionMap.put(Angle.class, angleMap); + private > void addDefaultUnit(Class dimension, Unit unit) { + dimensionMap.put(dimension, Map.of(SIUnits.getInstance(), unit, ImperialUnits.getInstance(), unit)); } } diff --git a/bundles/org.openhab.core/src/main/java/org/openhab/core/library/unit/ImperialUnits.java b/bundles/org.openhab.core/src/main/java/org/openhab/core/library/unit/ImperialUnits.java index 6d75cc7bd..29e9922f9 100644 --- a/bundles/org.openhab.core/src/main/java/org/openhab/core/library/unit/ImperialUnits.java +++ b/bundles/org.openhab.core/src/main/java/org/openhab/core/library/unit/ImperialUnits.java @@ -17,6 +17,7 @@ import java.math.BigInteger; import javax.measure.Unit; import javax.measure.quantity.Area; import javax.measure.quantity.Length; +import javax.measure.quantity.Mass; import javax.measure.quantity.Pressure; import javax.measure.quantity.Speed; import javax.measure.quantity.Temperature; @@ -45,6 +46,8 @@ public final class ImperialUnits extends CustomUnits { private static final ImperialUnits INSTANCE = new ImperialUnits(); + public static final Unit POUND = addUnit(new TransformedUnit<>("lb", Units.GRAM, + MultiplyConverter.ofRational(BigInteger.valueOf(45359237), BigInteger.valueOf(100000)))); /** Additionally defined units to be used in openHAB **/ public static final Unit INCH_OF_MERCURY = addUnit(new TransformedUnit<>("inHg", Units.PASCAL, MultiplyConverter.ofRational(BigInteger.valueOf(3386388), BigInteger.valueOf(1000)))); diff --git a/bundles/org.openhab.core/src/test/java/org/openhab/core/internal/i18n/I18nProviderImplTest.java b/bundles/org.openhab.core/src/test/java/org/openhab/core/internal/i18n/I18nProviderImplTest.java index c136c0a35..6591eb15d 100644 --- a/bundles/org.openhab.core/src/test/java/org/openhab/core/internal/i18n/I18nProviderImplTest.java +++ b/bundles/org.openhab.core/src/test/java/org/openhab/core/internal/i18n/I18nProviderImplTest.java @@ -14,23 +14,37 @@ package org.openhab.core.internal.i18n; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.notNullValue; import static org.junit.jupiter.api.Assertions.assertNull; import static org.mockito.Mockito.when; import static org.openhab.core.internal.i18n.I18nProviderImpl.*; import java.time.ZoneId; +import java.util.Collection; import java.util.Dictionary; import java.util.Hashtable; import java.util.Locale; import java.util.Map; +import java.util.Objects; +import java.util.stream.Stream; + +import javax.measure.Quantity; +import javax.measure.Unit; +import javax.measure.spi.SystemOfUnits; import org.eclipse.jdt.annotation.NonNullByDefault; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.openhab.core.library.types.PointType; +import org.openhab.core.library.unit.ImperialUnits; +import org.openhab.core.library.unit.SIUnits; +import org.openhab.core.library.unit.Units; +import org.openhab.core.types.util.UnitUtils; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.service.component.ComponentContext; @@ -158,6 +172,23 @@ public class I18nProviderImplTest { assertThat(setLocale.getVariant(), is(VARIANT_RU)); } + @ParameterizedTest + @MethodSource("getAllDimensions") + @SuppressWarnings("unchecked") + public > void assertThatUnitProviderIsComplete(String dimensionName) { + Class> dimension = UnitUtils.parseDimension(dimensionName); + assertThat(dimension, is(notNullValue())); + + Unit defaultUnit = i18nProviderImpl.getUnit((Class) dimension); + assertThat(dimensionName + " has no default unit", defaultUnit, notNullValue()); + } + + private static Stream getAllDimensions() { + return Stream.of(SIUnits.getInstance(), Units.getInstance(), ImperialUnits.getInstance()) + .map(SystemOfUnits::getUnits).flatMap(Collection::stream) // + .map(UnitUtils::getDimensionName).filter(Objects::nonNull).map(Objects::requireNonNull).distinct(); + } + private Dictionary buildInitialConfig() { Dictionary conf = new Hashtable<>(); conf.put(LOCATION, LOCATION_ZERO); diff --git a/bundles/org.openhab.core/src/test/java/org/openhab/core/library/unit/UnitsTest.java b/bundles/org.openhab.core/src/test/java/org/openhab/core/library/unit/UnitsTest.java index 46afff0ae..cadb7db3d 100644 --- a/bundles/org.openhab.core/src/test/java/org/openhab/core/library/unit/UnitsTest.java +++ b/bundles/org.openhab.core/src/test/java/org/openhab/core/library/unit/UnitsTest.java @@ -23,6 +23,7 @@ import javax.measure.Quantity; import javax.measure.quantity.Dimensionless; import javax.measure.quantity.Energy; import javax.measure.quantity.Length; +import javax.measure.quantity.Mass; import javax.measure.quantity.Power; import javax.measure.quantity.Pressure; import javax.measure.quantity.Speed; @@ -54,6 +55,14 @@ public class UnitsTest { return new QuantityEquals(quantity); } + @Test + public void pound2KilogramConversion() { + Quantity lb = Quantities.getQuantity(BigDecimal.ONE, ImperialUnits.POUND); + + assertThat(lb.to(SIUnits.GRAM), + isQuantityEquals(Quantities.getQuantity(new BigDecimal("453.59237"), SIUnits.GRAM))); + } + @Test public void testInHg2PascalConversion() { Quantity inHg = Quantities.getQuantity(BigDecimal.ONE, ImperialUnits.INCH_OF_MERCURY);