/**
* Copyright (c) 2014-2017 by the respective copyright holders.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.smarthome.config.core.status;
import java.util.Collection;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService;
import org.eclipse.smarthome.config.core.status.events.ConfigStatusInfoEvent;
import org.eclipse.smarthome.core.common.ThreadPoolManager;
import org.eclipse.smarthome.core.events.EventPublisher;
import org.eclipse.smarthome.core.i18n.I18nProvider;
import org.eclipse.smarthome.core.i18n.LocaleProvider;
import org.osgi.framework.Bundle;
import org.osgi.framework.FrameworkUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The {@link ConfigStatusService} provides the {@link ConfigStatusInfo} for a specific entity. For this purpose
* it loops over all registered {@link ConfigStatusProvider}s and returns the {@link ConfigStatusInfo} for the matching
* {@link ConfigStatusProvider}.
*
* @author Thomas Höfer - Initial contribution
* @author Chris Jackson - Allow null messages
* @author Markus Rathgeb - Add locale provider support
*/
public final class ConfigStatusService implements ConfigStatusCallback {
private final Logger logger = LoggerFactory.getLogger(ConfigStatusService.class);
private final List<ConfigStatusProvider> configStatusProviders = new CopyOnWriteArrayList<>();
private EventPublisher eventPublisher;
private LocaleProvider localeProvider;
private I18nProvider i18nProvider;
private final ExecutorService executorService = ThreadPoolManager
.getPool(ConfigStatusService.class.getSimpleName());
/**
* Retrieves the {@link ConfigStatusInfo} of the entity by using the registered
* {@link ConfigStatusProvider} that supports the given entity.
*
* @param entityId the id of the entity whose configuration status information is to be retrieved (must not
* be null or empty)
* @param locale the locale to be used for the corresponding configuration status messages; if null then the
* default local will be used
*
* @return the {@link ConfigStatusInfo} or null if there is no {@link ConfigStatusProvider} registered that
* supports the given entity
*
* @throws IllegalArgumentException if given entityId is null or empty
*/
public ConfigStatusInfo getConfigStatus(String entityId, final Locale locale) {
if (entityId == null || entityId.equals("")) {
throw new IllegalArgumentException("EntityId must not be null or empty");
}
final Locale loc = locale != null ? locale : localeProvider.getLocale();
for (ConfigStatusProvider configStatusProvider : configStatusProviders) {
if (configStatusProvider.supportsEntity(entityId)) {
return getConfigStatus(configStatusProvider, entityId, loc);
}
}
logger.debug("There is no config status provider for entity {} available.", entityId);
return null;
}
@Override
public void configUpdated(final ConfigStatusSource configStatusSource) {
executorService.submit(new Runnable() {
@Override
public void run() {
final ConfigStatusInfo info = getConfigStatus(configStatusSource.entityId, null);
if (info != null) {
if (eventPublisher != null) {
eventPublisher.post(new ConfigStatusInfoEvent(configStatusSource.getTopic(), info));
} else {
logger.warn("EventPublisher not available. Cannot post new config status for entity "
+ configStatusSource.entityId);
}
}
}
});
}
private ConfigStatusInfo getConfigStatus(ConfigStatusProvider configStatusProvider, String entityId,
Locale locale) {
Collection<ConfigStatusMessage> configStatus = configStatusProvider.getConfigStatus();
if (configStatus == null) {
logger.debug("Cannot provide config status for entity {} because its config status provider returned null.",
entityId);
return null;
}
Bundle bundle = FrameworkUtil.getBundle(configStatusProvider.getClass());
ConfigStatusInfo info = new ConfigStatusInfo();
for (ConfigStatusMessage configStatusMessage : configStatus) {
String message = null;
if (configStatusMessage.messageKey != null) {
message = i18nProvider.getText(bundle, configStatusMessage.messageKey, null, locale,
configStatusMessage.arguments);
if (message == null) {
logger.warn(
"No translation found for key {} and config status provider {}. Will ignore the config status message.",
configStatusMessage.messageKey, configStatusProvider.getClass().getSimpleName());
continue;
}
}
info.add(new ConfigStatusMessage(configStatusMessage.parameterName, configStatusMessage.type, message,
configStatusMessage.statusCode));
}
return info;
}
protected void addConfigStatusProvider(ConfigStatusProvider configStatusProvider) {
configStatusProvider.setConfigStatusCallback(this);
configStatusProviders.add(configStatusProvider);
}
protected void removeConfigStatusProvider(ConfigStatusProvider configStatusProvider) {
configStatusProvider.setConfigStatusCallback(null);
configStatusProviders.remove(configStatusProvider);
}
protected void setEventPublisher(EventPublisher eventPublisher) {
this.eventPublisher = eventPublisher;
}
protected void unsetEventPublisher(EventPublisher eventPublisher) {
this.eventPublisher = null;
}
protected void setLocaleProvider(LocaleProvider localeProvider) {
this.localeProvider = localeProvider;
}
protected void unsetLocaleProvider(LocaleProvider localeProvider) {
this.localeProvider = null;
}
protected void setI18nProvider(I18nProvider i18nProvider) {
this.i18nProvider = i18nProvider;
}
protected void unsetI18nProvider(I18nProvider i18nProvider) {
this.i18nProvider = null;
}
}