Skip to content

Commit

Permalink
further work
Browse files Browse the repository at this point in the history
Signed-off-by: Jan N. Klug <github@klug.nrw>
  • Loading branch information
J-N-K committed Aug 28, 2023
1 parent c722303 commit 461a17e
Show file tree
Hide file tree
Showing 13 changed files with 352 additions and 73 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/**
* Copyright (c) 2010-2023 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.core.config.core;

import java.net.URI;
import java.util.Collection;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.CopyOnWriteArrayList;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.library.unit.CurrencyProvider;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.osgi.service.component.annotations.ReferencePolicy;

/**
* The {@link CurrencyServiceConfigOptionProvider} is an implementation of {@link ConfigOptionProvider} for the
* available currency providers.
*
* @author Jan N. Klug - Initial contribution
*/
@Component(service = ConfigOptionProvider.class)
@NonNullByDefault
public class CurrencyServiceConfigOptionProvider implements ConfigOptionProvider {

private final List<CurrencyProvider> currencyProviders = new CopyOnWriteArrayList<>();

@Reference(cardinality = ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC)
public void addCurrencyProvider(CurrencyProvider currencyProvider) {
currencyProviders.add(currencyProvider);
}

public void removeCurrencyProvider(CurrencyProvider currencyProvider) {
currencyProviders.remove(currencyProvider);
}

@Override
public @Nullable Collection<ParameterOption> getParameterOptions(URI uri, String param, @Nullable String context,
@Nullable Locale locale) {
if ("system:units".equals(uri.toString()) && param.equals("currencyProvider")) {
return currencyProviders.stream().map(this::mapProvider).toList();
}
return null;
}

private ParameterOption mapProvider(CurrencyProvider currencyProvider) {
String providerName = currencyProvider.getName();
int lastDot = providerName.lastIndexOf(".");
String providerDescription = lastDot > -1 ? providerName.substring(lastDot + 1) : providerName;
return new ParameterOption(providerName, providerDescription);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
import org.osgi.service.component.annotations.Component;

/**
* {@link ConfigOptionProvider} that provides a list of
* A {@link ConfigOptionProvider} that provides a list of config options for the i18n service
*
* @author Simon Kaufmann - Initial contribution
* @author Erdoan Hadzhiyusein - Added time zone
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@

import static org.openhab.core.library.unit.MetricPrefix.HECTO;

import java.math.BigDecimal;
import java.text.MessageFormat;
import java.time.DateTimeException;
import java.time.ZoneId;
Expand All @@ -25,7 +24,6 @@
import java.util.Objects;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.function.Function;

import javax.measure.Quantity;
import javax.measure.Unit;
Expand Down Expand Up @@ -82,8 +80,6 @@
import org.openhab.core.library.dimension.RadiationSpecificActivity;
import org.openhab.core.library.dimension.VolumetricFlowRate;
import org.openhab.core.library.types.PointType;
import org.openhab.core.library.unit.CurrencyProvider;
import org.openhab.core.library.unit.CurrencyUnit;
import org.openhab.core.library.unit.CurrencyUnits;
import org.openhab.core.library.unit.ImperialUnits;
import org.openhab.core.library.unit.SIUnits;
Expand Down Expand Up @@ -124,16 +120,15 @@
"service.config.category=system", //
"service.config.description.uri=system:i18n" })
@NonNullByDefault
public class I18nProviderImpl implements TranslationProvider, LocaleProvider, LocationProvider, TimeZoneProvider,
UnitProvider, CurrencyProvider {
public class I18nProviderImpl
implements TranslationProvider, LocaleProvider, LocationProvider, TimeZoneProvider, UnitProvider {

private final Logger logger = LoggerFactory.getLogger(I18nProviderImpl.class);

public static final String CONFIGURATION_PID = "org.openhab.i18n";

// LocaleProvider
public static final String LANGUAGE = "language";
public static final String BASE_CURRENCY = "baseCurrency";
public static final String SCRIPT = "script";
public static final String REGION = "region";
public static final String VARIANT = "variant";
Expand Down Expand Up @@ -174,7 +169,6 @@ protected void deactivate() {
@Modified
protected synchronized void modified(Map<String, Object> config) {
final String language = toStringOrNull(config.get(LANGUAGE));
this.currencyCode = toStringOrNull(config.get(BASE_CURRENCY));
final String script = toStringOrNull(config.get(SCRIPT));
final String region = toStringOrNull(config.get(REGION));
final String variant = toStringOrNull(config.get(VARIANT));
Expand Down Expand Up @@ -457,29 +451,4 @@ private static <T extends Quantity<T>> void addDefaultUnit(
Class<T> dimension, Unit<T> unit) {
dimensionMap.put(dimension, Map.of(SIUnits.getInstance(), unit, ImperialUnits.getInstance(), unit));
}

@Override
public Unit<Currency> getBaseCurrency() {
String currencyCode = this.currencyCode;
if (currencyCode == null && locale != null) {
currencyCode = java.util.Currency.getInstance(locale).getCurrencyCode();
}
if (currencyCode != null) {
// either the currency was set or determined from the locale
String symbol = java.util.Currency.getInstance(currencyCode).getSymbol();
return new CurrencyUnit(currencyCode, symbol);
} else {
return new CurrencyUnit("DEF", null);
}
}

@Override
public Collection<Unit<Currency>> getCurrencies() {
return Set.of();
}

@Override
public Function<Unit<Currency>, @Nullable BigDecimal> getExchangeRateFunction() {
return unit -> null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,11 @@
import static org.openhab.core.library.unit.CurrencyUnits.BASE_CURRENCY;

import java.math.BigDecimal;
import java.util.Collection;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;

import javax.measure.Unit;
Expand All @@ -30,57 +33,110 @@
import org.osgi.framework.Constants;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Modified;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.osgi.service.component.annotations.ReferencePolicy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import tech.units.indriya.format.SimpleUnitFormat;

/**
* The {@link CurrencyService} is allows to register and switch {@link CurrencyProvider}s and provides exchange rates
* The {@link CurrencyService} allows to register and switch {@link CurrencyProvider}s and provides exchange rates
* for currencies
*
* @author Jan N. Klug - Initial contribution
*/
@Component
@Component(service = CurrencyService.class, immediate = true, configurationPid = CurrencyService.CONFIGURATION_PID, property = {
Constants.SERVICE_PID + "=org.openhab.units", //
"service.config.label=Unit Settings", //
"service.config.category=system", //
"service.config.description.uri=system:units" })
@NonNullByDefault
public class CurrencyService {
public static final String CONFIGURATION_PID = "org.openhab.units";
public static final String CONFIG_OPTION_CURRENCY_PROVIDER = "currencyProvider";
private final Logger logger = LoggerFactory.getLogger(CurrencyService.class);

public static Function<Unit<Currency>, @Nullable BigDecimal> FACTOR_FCN = unit -> null;

private final Set<CurrencyProvider> currencyProviders = new CopyOnWriteArraySet<>();
private final Map<String, CurrencyProvider> currencyProviders = new ConcurrentHashMap<>();

private CurrencyProvider enabledCurrencyProvider = DefaultCurrencyProvider.getInstance();
private String configuredCurrencyProvider = DefaultCurrencyProvider.getInstance().getName();

@Activate
public CurrencyService(
@Reference(target = "(" + Constants.SERVICE_PID + "=org.openhab.i18n)") CurrencyProvider currencyProvider) {
currencyProviders.add(currencyProvider);
public CurrencyService(Map<String, Object> config) {
modified(config);
}

@Modified
public void modified(Map<String, Object> config) {
String configOption = (String) config.get(CONFIG_OPTION_CURRENCY_PROVIDER);
configuredCurrencyProvider = Objects.requireNonNullElse(configOption,
DefaultCurrencyProvider.getInstance().getName());
CurrencyProvider currencyProvider = currencyProviders.getOrDefault(configuredCurrencyProvider,
DefaultCurrencyProvider.getInstance());
enableProvider(currencyProvider);
}

@Reference(cardinality = ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC)
public void addCurrencyProvider(CurrencyProvider currencyProvider) {
currencyProviders.add(currencyProvider);
logger.error("Added {}", currencyProvider.getName());
currencyProviders.put(currencyProvider.getName(), currencyProvider);
if (configuredCurrencyProvider.equals(currencyProvider.getName())) {
enableProvider(currencyProvider);
}
}

public void removeCurrencyProvider(CurrencyProvider currencyProvider) {
currencyProviders.remove(currencyProvider);
if (currencyProvider.equals(enabledCurrencyProvider)) {
logger.warn("The currently activated currency provider is being removed. Enabling default.");
enableProvider(DefaultCurrencyProvider.getInstance());
}
currencyProviders.remove(currencyProvider.getName());
}

private synchronized void enableProvider(CurrencyProvider currencyProvider) {
SimpleUnitFormat unitFormatter = SimpleUnitFormat.getInstance();
// remove units from old provider
enabledCurrencyProvider.getAdditionalCurrencies().forEach(CurrencyUnits::removeUnit);
unitFormatter.removeLabel(enabledCurrencyProvider.getBaseCurrency());

// add new units
FACTOR_FCN = currencyProvider.getExchangeRateFunction();
((CurrencyUnit) BASE_CURRENCY).setSymbol(currencyProvider.getBaseCurrency().getSymbol());
((CurrencyUnit) BASE_CURRENCY).setName(currencyProvider.getBaseCurrency().getName());
SimpleUnitFormat.getInstance().label(BASE_CURRENCY, currencyProvider.getBaseCurrency().getSymbol());
currencyProvider.getCurrencies().forEach(CurrencyUnits::addUnit);
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()));

currencyProvider.getAdditionalCurrencies().forEach(CurrencyUnits::addUnit);

this.enabledCurrencyProvider = currencyProvider;
}

/**
* Get the exchange rate for a given currency to the system's base unit
*
* @param currency the currency
* @return the exchange rate
*/
public static @Nullable BigDecimal getExchangeRate(Unit<Currency> currency) {
return FACTOR_FCN.apply(currency);
private static class DefaultCurrencyProvider implements CurrencyProvider {
private static final CurrencyProvider INSTANCE = new DefaultCurrencyProvider();

@Override
public Unit<Currency> getBaseCurrency() {
return new CurrencyUnit("DEF", null);
}

@Override
public Collection<Unit<Currency>> getAdditionalCurrencies() {
return Set.of();
}

@Override
public Function<Unit<Currency>, @Nullable BigDecimal> getExchangeRateFunction() {
return unit -> null;
}

public static CurrencyProvider getInstance() {
return INSTANCE;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/**
* Copyright (c) 2010-2023 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.core.internal.library.unit;

import java.math.BigDecimal;
import java.util.Collection;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Function;

import javax.measure.Unit;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.library.dimension.Currency;
import org.openhab.core.library.unit.CurrencyProvider;
import org.openhab.core.library.unit.CurrencyUnit;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Modified;

/**
* The {@link FixedCurrencyProvider} is an implementation of {@link CurrencyProvider} that provides only a single
* (configurable) currency.
*
* @author Jan N. Klug - Initial contribution
*/
@Component(service = CurrencyProvider.class, configurationPid = CurrencyService.CONFIGURATION_PID)
@NonNullByDefault
public class FixedCurrencyProvider implements CurrencyProvider {
public static final String CONFIG_OPTION_BASE_CURRENCY = "fixedBaseCurrency";
private String currencyCode = "DEF";

@Activate
public FixedCurrencyProvider(Map<String, Object> config) {
modified(config);
}

@Modified
public void modified(Map<String, Object> config) {
String code = (String) config.get(CONFIG_OPTION_BASE_CURRENCY);
currencyCode = Objects.requireNonNullElse(code, "DEF");
}

@Override
public Unit<Currency> getBaseCurrency() {
String symbol = null;
try {
symbol = java.util.Currency.getInstance(currencyCode).getSymbol();
} catch (IllegalArgumentException ignored) {
}

return new CurrencyUnit(currencyCode, symbol);
}

@Override
public Collection<Unit<Currency>> getAdditionalCurrencies() {
return Set.of();
}

@Override
public Function<Unit<Currency>, @Nullable BigDecimal> getExchangeRateFunction() {
return unit -> null;
}
}
Loading

0 comments on commit 461a17e

Please sign in to comment.