mirror of
https://github.com/danieldemus/openhab-core.git
synced 2025-01-10 21:31:53 +01:00
parent
8e7d5d880c
commit
36cafd765f
@ -12,8 +12,10 @@
|
||||
*/
|
||||
package org.openhab.core.internal.library.unit;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.MathContext;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import javax.measure.UnitConverter;
|
||||
@ -22,6 +24,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
import tech.units.indriya.function.AbstractConverter;
|
||||
import tech.units.indriya.function.Calculus;
|
||||
|
||||
/**
|
||||
* The {@link CurrencyConverter} implements an {@link UnitConverter} for
|
||||
@ -82,4 +85,28 @@ public class CurrencyConverter extends AbstractConverter {
|
||||
public boolean isLinear() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is currently necessary because conversion of {@link tech.units.indriya.unit.ProductUnit}s requires a
|
||||
* converter that is properly registered. This is currently not possible. We can't use the registered providers,
|
||||
* because they only have package-private constructors.
|
||||
*
|
||||
* {@see https://github.com/unitsofmeasurement/indriya/issues/402}
|
||||
*/
|
||||
static {
|
||||
// call to ensure map is initialized
|
||||
Map<Class<? extends AbstractConverter>, Integer> normalFormOrder = (Map<Class<? extends AbstractConverter>, Integer>) Calculus
|
||||
.getNormalFormOrder();
|
||||
try {
|
||||
Field field = Calculus.class.getDeclaredField("normalFormOrder");
|
||||
field.setAccessible(true);
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<Class<? extends AbstractConverter>, Integer> original = (Map<Class<? extends AbstractConverter>, Integer>) field
|
||||
.get(null);
|
||||
original.put(CurrencyConverter.class, 1000);
|
||||
} catch (NoSuchFieldException | IllegalAccessException e) {
|
||||
throw new IllegalStateException("Could not add currency converter", e);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -108,8 +108,10 @@ public class CurrencyService {
|
||||
Unit<Currency> baseCurrency = currencyProvider.getBaseCurrency();
|
||||
((CurrencyUnit) BASE_CURRENCY).setSymbol(baseCurrency.getSymbol());
|
||||
((CurrencyUnit) BASE_CURRENCY).setName(baseCurrency.getName());
|
||||
unitFormatter.label(BASE_CURRENCY,
|
||||
Objects.requireNonNullElse(baseCurrency.getSymbol(), baseCurrency.getName()));
|
||||
unitFormatter.label(BASE_CURRENCY, baseCurrency.getName());
|
||||
if (baseCurrency.getSymbol() != null) {
|
||||
unitFormatter.alias(BASE_CURRENCY, baseCurrency.getSymbol());
|
||||
}
|
||||
|
||||
currencyProvider.getAdditionalCurrencies().forEach(CurrencyUnits::addUnit);
|
||||
|
||||
|
@ -19,16 +19,13 @@ import static org.eclipse.jdt.annotation.DefaultLocation.TYPE_BOUND;
|
||||
import static org.openhab.core.library.unit.CurrencyUnits.BASE_CURRENCY;
|
||||
import static tech.units.indriya.AbstractUnit.ONE;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.MathContext;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import javax.measure.Dimension;
|
||||
import javax.measure.IncommensurableException;
|
||||
import javax.measure.Prefix;
|
||||
import javax.measure.Quantity;
|
||||
import javax.measure.UnconvertibleException;
|
||||
import javax.measure.Unit;
|
||||
import javax.measure.UnitConverter;
|
||||
@ -39,18 +36,11 @@ import org.openhab.core.internal.library.unit.CurrencyConverter;
|
||||
import org.openhab.core.internal.library.unit.CurrencyService;
|
||||
import org.openhab.core.library.dimension.Currency;
|
||||
|
||||
import tech.units.indriya.AbstractUnit;
|
||||
import tech.units.indriya.function.AbstractConverter;
|
||||
import tech.units.indriya.function.AddConverter;
|
||||
import tech.units.indriya.function.Calculus;
|
||||
import tech.units.indriya.function.MultiplyConverter;
|
||||
import tech.units.indriya.function.RationalNumber;
|
||||
import tech.units.indriya.unit.AlternateUnit;
|
||||
import tech.units.indriya.unit.ProductUnit;
|
||||
import tech.units.indriya.unit.TransformedUnit;
|
||||
import tech.units.indriya.unit.UnitDimension;
|
||||
import tech.uom.lib.common.function.Nameable;
|
||||
import tech.uom.lib.common.function.PrefixOperator;
|
||||
import tech.uom.lib.common.function.SymbolSupplier;
|
||||
|
||||
/**
|
||||
* The {@link CurrencyUnit} is a UoM compatible unit for currencies.
|
||||
@ -58,8 +48,7 @@ import tech.uom.lib.common.function.SymbolSupplier;
|
||||
* @author Jan N. Klug - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault({ PARAMETER, RETURN_TYPE, FIELD, TYPE_BOUND })
|
||||
public final class CurrencyUnit implements Unit<Currency>, Comparable<Unit<Currency>>, PrefixOperator<Currency>,
|
||||
Nameable, Serializable, SymbolSupplier {
|
||||
public final class CurrencyUnit extends AbstractUnit<Currency> {
|
||||
|
||||
private static final long serialVersionUID = -1L;
|
||||
private static final Dimension DIMENSION = UnitDimension.parse('$');
|
||||
@ -82,7 +71,12 @@ public final class CurrencyUnit implements Unit<Currency>, Comparable<Unit<Curre
|
||||
}
|
||||
|
||||
public UnitConverter getSystemConverter() {
|
||||
return AbstractConverter.IDENTITY;
|
||||
return internalGetConverterTo(getSystemUnit());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Unit<Currency> toSystemUnit() {
|
||||
return BASE_CURRENCY;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -90,26 +84,6 @@ public final class CurrencyUnit implements Unit<Currency>, Comparable<Unit<Curre
|
||||
return getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Unit<Currency> getSystemUnit() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCompatible(@NonNullByDefault({}) Unit<?> that) {
|
||||
return DIMENSION.equals(that.getDimension());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public @NonNullByDefault({}) <T extends Quantity<T>> Unit<T> asType(@NonNullByDefault({}) Class<T> type) {
|
||||
Dimension typeDimension = UnitDimension.of(type);
|
||||
if (typeDimension != null && !typeDimension.equals(this.getDimension())) {
|
||||
throw new ClassCastException("The unit: " + this + " is not compatible with quantities of type " + type);
|
||||
}
|
||||
return (Unit<T>) this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNullByDefault({}) Map<? extends Unit<?>, Integer> getBaseUnits() {
|
||||
return Map.of();
|
||||
@ -120,7 +94,7 @@ public final class CurrencyUnit implements Unit<Currency>, Comparable<Unit<Curre
|
||||
return DIMENSION;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
public void setName(@NonNullByDefault({}) String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@ -138,41 +112,6 @@ public final class CurrencyUnit implements Unit<Currency>, Comparable<Unit<Curre
|
||||
this.symbol = s;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final UnitConverter getConverterTo(@NonNullByDefault({}) Unit<Currency> that) throws UnconvertibleException {
|
||||
return internalGetConverterTo(that);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public final @NonNullByDefault({}) UnitConverter getConverterToAny(@NonNullByDefault({}) Unit<?> that)
|
||||
throws IncommensurableException, UnconvertibleException {
|
||||
if (!isCompatible(that)) {
|
||||
throw new IncommensurableException(this + " is not compatible with " + that);
|
||||
}
|
||||
return internalGetConverterTo((Unit<Currency>) that);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Unit<Currency> alternate(@NonNullByDefault({}) String newSymbol) {
|
||||
return new AlternateUnit<>(this, newSymbol);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Unit<Currency> transform(@NonNullByDefault({}) UnitConverter operation) {
|
||||
return operation.isIdentity() ? this : new TransformedUnit<>(null, this, this, operation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Unit<Currency> shift(@NonNullByDefault({}) Number offset) {
|
||||
return Calculus.currentNumberSystem().isZero(offset) ? this : transform(new AddConverter(offset));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Unit<Currency> multiply(@NonNullByDefault({}) Number factor) {
|
||||
return Calculus.currentNumberSystem().isOne(factor) ? this : transform(MultiplyConverter.of(factor));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Unit<Currency> shift(double offset) {
|
||||
return shift(RationalNumber.of(offset));
|
||||
@ -214,42 +153,6 @@ public final class CurrencyUnit implements Unit<Currency>, Comparable<Unit<Curre
|
||||
"Could not get factor for converting " + this.getName() + " to " + that.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Unit<?> multiply(@NonNullByDefault({}) Unit<?> that) {
|
||||
return that.equals(ONE) ? this : ProductUnit.ofProduct(this, that);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Unit<?> inverse() {
|
||||
return ProductUnit.ofQuotient(ONE, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Unit<Currency> divide(@NonNullByDefault({}) Number divisor) {
|
||||
if (Calculus.currentNumberSystem().isOne(divisor)) {
|
||||
return this;
|
||||
}
|
||||
BigDecimal factor = BigDecimal.ONE.divide(new BigDecimal(divisor.toString()), MathContext.DECIMAL128);
|
||||
return transform(MultiplyConverter.of(factor));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Unit<?> divide(@NonNullByDefault({}) Unit<?> that) {
|
||||
return this.multiply(that.inverse());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Unit<?> root(int n) {
|
||||
if (n > 0) {
|
||||
return ProductUnit.ofRoot(this, n);
|
||||
} else if (n == 0) {
|
||||
throw new ArithmeticException("Root's order of zero");
|
||||
} else {
|
||||
// n < 0
|
||||
return ONE.divide(this.root(-n));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Unit<?> pow(int n) {
|
||||
if (n > 0) {
|
||||
|
@ -33,6 +33,7 @@ import org.openhab.core.internal.library.unit.CurrencyService;
|
||||
import org.openhab.core.library.dimension.Currency;
|
||||
import org.openhab.core.library.dimension.EnergyPrice;
|
||||
import org.openhab.core.library.types.QuantityType;
|
||||
import org.openhab.core.types.util.UnitUtils;
|
||||
|
||||
/**
|
||||
* The {@link CurrencyUnitTest} contains tests for the currency units
|
||||
@ -97,6 +98,16 @@ public class CurrencyUnitTest {
|
||||
assertThat(price.doubleValue(), closeTo(1.25, 1E-4));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEnergyPriceConversion() {
|
||||
QuantityType<EnergyPrice> price = new QuantityType<>("0.25 EUR/kWh");
|
||||
QuantityType<EnergyPrice> convertedPrice = price.toUnit("DKK/kWh");
|
||||
|
||||
assertThat(convertedPrice, is(notNullValue()));
|
||||
assertThat(convertedPrice.getUnit(), is(UnitUtils.parseUnit("DKK/kWh")));
|
||||
assertThat(convertedPrice.doubleValue(), closeTo(1.8625, 1e-4));
|
||||
}
|
||||
|
||||
private static class TestCurrencyProvider implements CurrencyProvider {
|
||||
public static final Unit<Currency> EUR = new CurrencyUnit("EUR", "€");
|
||||
public static final Unit<Currency> DKK = new CurrencyUnit("DKK", null);
|
||||
|
Loading…
Reference in New Issue
Block a user