[binding] Added nullness annotations (#1165)

* Added nullness annotations to o.o.c.binding.xml
* Use local variables
* Removed unuused import

Signed-off-by: Christoph Weitkamp <github@christophweitkamp.de>
pull/1168/head
Christoph Weitkamp 2019-10-28 08:14:10 +01:00 committed by Kai Kreuzer
parent d7e3297466
commit 8351a2f8d4
14 changed files with 181 additions and 128 deletions

View File

@ -12,6 +12,8 @@
*/ */
package org.eclipse.smarthome.core.binding.xml.internal; package org.eclipse.smarthome.core.binding.xml.internal;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.smarthome.config.core.ConfigDescription; import org.eclipse.smarthome.config.core.ConfigDescription;
import org.eclipse.smarthome.config.xml.AbstractXmlConfigDescriptionProvider; import org.eclipse.smarthome.config.xml.AbstractXmlConfigDescriptionProvider;
import org.eclipse.smarthome.config.xml.osgi.XmlDocumentProvider; import org.eclipse.smarthome.config.xml.osgi.XmlDocumentProvider;
@ -36,14 +38,15 @@ import org.slf4j.LoggerFactory;
* *
* @see BindingInfoXmlProviderFactory * @see BindingInfoXmlProviderFactory
*/ */
@NonNullByDefault
public class BindingInfoXmlProvider implements XmlDocumentProvider<BindingInfoXmlResult> { public class BindingInfoXmlProvider implements XmlDocumentProvider<BindingInfoXmlResult> {
private Logger logger = LoggerFactory.getLogger(BindingInfoXmlProvider.class); private Logger logger = LoggerFactory.getLogger(BindingInfoXmlProvider.class);
private Bundle bundle; private final Bundle bundle;
private XmlBindingInfoProvider bindingInfoProvider; private final XmlBindingInfoProvider bindingInfoProvider;
private AbstractXmlConfigDescriptionProvider configDescriptionProvider; private final AbstractXmlConfigDescriptionProvider configDescriptionProvider;
public BindingInfoXmlProvider(Bundle bundle, XmlBindingInfoProvider bindingInfoProvider, public BindingInfoXmlProvider(Bundle bundle, XmlBindingInfoProvider bindingInfoProvider,
AbstractXmlConfigDescriptionProvider configDescriptionProvider) throws IllegalArgumentException { AbstractXmlConfigDescriptionProvider configDescriptionProvider) throws IllegalArgumentException {
@ -60,26 +63,24 @@ public class BindingInfoXmlProvider implements XmlDocumentProvider<BindingInfoXm
} }
this.bundle = bundle; this.bundle = bundle;
this.bindingInfoProvider = bindingInfoProvider; this.bindingInfoProvider = bindingInfoProvider;
this.configDescriptionProvider = configDescriptionProvider; this.configDescriptionProvider = configDescriptionProvider;
} }
@Override @Override
public synchronized void addingObject(BindingInfoXmlResult bindingInfoXmlResult) { public synchronized void addingObject(@Nullable BindingInfoXmlResult bindingInfoXmlResult) {
if (bindingInfoXmlResult != null) { if (bindingInfoXmlResult != null) {
ConfigDescription configDescription = bindingInfoXmlResult.getConfigDescription(); ConfigDescription configDescription = bindingInfoXmlResult.getConfigDescription();
if (configDescription != null) { if (configDescription != null) {
try { try {
this.configDescriptionProvider.add(this.bundle, configDescription); configDescriptionProvider.add(bundle, configDescription);
} catch (Exception ex) { } catch (Exception ex) {
this.logger.error("Could not register ConfigDescription!", ex); logger.error("Could not register ConfigDescription!", ex);
} }
} }
BindingInfo bindingInfo = bindingInfoXmlResult.getBindingInfo(); bindingInfoProvider.add(bundle, bindingInfoXmlResult.getBindingInfo());
this.bindingInfoProvider.add(bundle, bindingInfo);
} }
} }
@ -93,5 +94,4 @@ public class BindingInfoXmlProvider implements XmlDocumentProvider<BindingInfoXm
this.bindingInfoProvider.removeAll(bundle); this.bindingInfoProvider.removeAll(bundle);
this.configDescriptionProvider.removeAll(bundle); this.configDescriptionProvider.removeAll(bundle);
} }
} }

View File

@ -12,6 +12,8 @@
*/ */
package org.eclipse.smarthome.core.binding.xml.internal; package org.eclipse.smarthome.core.binding.xml.internal;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.smarthome.config.core.ConfigDescription; import org.eclipse.smarthome.config.core.ConfigDescription;
import org.eclipse.smarthome.config.core.ConfigDescriptionProvider; import org.eclipse.smarthome.config.core.ConfigDescriptionProvider;
import org.eclipse.smarthome.core.binding.BindingInfo; import org.eclipse.smarthome.core.binding.BindingInfo;
@ -24,12 +26,13 @@ import org.eclipse.smarthome.core.binding.BindingInfo;
* *
* @author Michael Grammling - Initial contribution * @author Michael Grammling - Initial contribution
*/ */
@NonNullByDefault
public class BindingInfoXmlResult { public class BindingInfoXmlResult {
private BindingInfo bindingInfo; private BindingInfo bindingInfo;
private ConfigDescription configDescription; private @Nullable ConfigDescription configDescription;
public BindingInfoXmlResult(BindingInfo bindingInfo, ConfigDescription configDescription) public BindingInfoXmlResult(BindingInfo bindingInfo, @Nullable ConfigDescription configDescription)
throws IllegalArgumentException { throws IllegalArgumentException {
if (bindingInfo == null) { if (bindingInfo == null) {
throw new IllegalArgumentException("The BindingInfo must not be null!"); throw new IllegalArgumentException("The BindingInfo must not be null!");
@ -40,16 +43,15 @@ public class BindingInfoXmlResult {
} }
public BindingInfo getBindingInfo() { public BindingInfo getBindingInfo() {
return this.bindingInfo; return bindingInfo;
} }
public ConfigDescription getConfigDescription() { public @Nullable ConfigDescription getConfigDescription() {
return this.configDescription; return configDescription;
} }
@Override @Override
public String toString() { public String toString() {
return "BindingInfoXmlResult [bindingInfo=" + bindingInfo + ", configDescription=" + configDescription + "]"; return "BindingInfoXmlResult [bindingInfo=" + bindingInfo + ", configDescription=" + configDescription + "]";
} }
} }

View File

@ -12,10 +12,12 @@
*/ */
package org.eclipse.smarthome.core.binding.xml.internal; package org.eclipse.smarthome.core.binding.xml.internal;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.smarthome.config.core.ConfigDescription; import org.eclipse.smarthome.config.core.ConfigDescription;
import org.eclipse.smarthome.config.core.ConfigDescriptionProvider; import org.eclipse.smarthome.config.core.ConfigDescriptionProvider;
import org.eclipse.smarthome.config.core.i18n.ConfigI18nLocalizationService; import org.eclipse.smarthome.config.core.i18n.ConfigI18nLocalizationService;
import org.eclipse.smarthome.config.xml.AbstractXmlConfigDescriptionProvider; import org.eclipse.smarthome.config.xml.AbstractXmlConfigDescriptionProvider;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference; import org.osgi.service.component.annotations.Reference;
@ -25,22 +27,18 @@ import org.osgi.service.component.annotations.Reference;
* @author Simon Kaufmann - Initial contribution * @author Simon Kaufmann - Initial contribution
*/ */
@Component(service = ConfigDescriptionProvider.class, immediate = true, property = { "esh.scope=core.xml.binding" }) @Component(service = ConfigDescriptionProvider.class, immediate = true, property = { "esh.scope=core.xml.binding" })
@NonNullByDefault
public class BindingXmlConfigDescriptionProvider extends AbstractXmlConfigDescriptionProvider { public class BindingXmlConfigDescriptionProvider extends AbstractXmlConfigDescriptionProvider {
private ConfigI18nLocalizationService configI18nLocalizerService; private final ConfigI18nLocalizationService configI18nService;
@Reference @Activate
public void setConfigI18nLocalizerService(ConfigI18nLocalizationService configI18nLocalizerService) { public BindingXmlConfigDescriptionProvider(final @Reference ConfigI18nLocalizationService configI18nService) {
this.configI18nLocalizerService = configI18nLocalizerService; this.configI18nService = configI18nService;
}
public void unsetConfigI18nLocalizerService(ConfigI18nLocalizationService configI18nLocalizerService) {
this.configI18nLocalizerService = null;
} }
@Override @Override
protected ConfigI18nLocalizationService getConfigI18nLocalizerService() { protected ConfigI18nLocalizationService getConfigI18nLocalizerService() {
return configI18nLocalizerService; return configI18nService;
} }
} }

View File

@ -18,6 +18,7 @@ import java.util.Set;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledExecutorService;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.smarthome.config.core.ConfigDescriptionProvider; import org.eclipse.smarthome.config.core.ConfigDescriptionProvider;
import org.eclipse.smarthome.config.xml.AbstractXmlBasedProvider; import org.eclipse.smarthome.config.xml.AbstractXmlBasedProvider;
import org.eclipse.smarthome.config.xml.AbstractXmlConfigDescriptionProvider; import org.eclipse.smarthome.config.xml.AbstractXmlConfigDescriptionProvider;
@ -27,9 +28,8 @@ import org.eclipse.smarthome.config.xml.osgi.XmlDocumentProviderFactory;
import org.eclipse.smarthome.config.xml.util.XmlDocumentReader; import org.eclipse.smarthome.config.xml.util.XmlDocumentReader;
import org.eclipse.smarthome.core.binding.BindingInfo; import org.eclipse.smarthome.core.binding.BindingInfo;
import org.eclipse.smarthome.core.binding.BindingInfoProvider; import org.eclipse.smarthome.core.binding.BindingInfoProvider;
import org.eclipse.smarthome.core.binding.i18n.BindingI18nLocalizationService;
import org.eclipse.smarthome.core.common.ThreadPoolManager; import org.eclipse.smarthome.core.common.ThreadPoolManager;
import org.eclipse.smarthome.core.i18n.BindingI18nUtil;
import org.eclipse.smarthome.core.i18n.TranslationProvider;
import org.eclipse.smarthome.core.service.ReadyService; import org.eclipse.smarthome.core.service.ReadyService;
import org.osgi.framework.Bundle; import org.osgi.framework.Bundle;
import org.osgi.service.component.ComponentContext; import org.osgi.service.component.ComponentContext;
@ -55,19 +55,24 @@ public class XmlBindingInfoProvider extends AbstractXmlBasedProvider<String, Bin
private static final String XML_DIRECTORY = "/ESH-INF/binding/"; private static final String XML_DIRECTORY = "/ESH-INF/binding/";
public static final String READY_MARKER = "esh.xmlBindingInfo"; public static final String READY_MARKER = "esh.xmlBindingInfo";
private BindingI18nUtil bindingI18nUtil; private final BindingI18nLocalizationService bindingI18nService;
private AbstractXmlConfigDescriptionProvider configDescriptionProvider; private AbstractXmlConfigDescriptionProvider configDescriptionProvider;
private XmlDocumentBundleTracker<BindingInfoXmlResult> bindingInfoTracker; private @Nullable XmlDocumentBundleTracker<BindingInfoXmlResult> bindingInfoTracker;
private ReadyService readyService; private final ReadyService readyService;
private final ScheduledExecutorService scheduler = ThreadPoolManager
private ScheduledExecutorService scheduler = ThreadPoolManager
.getScheduledPool(XmlDocumentBundleTracker.THREAD_POOL_NAME); .getScheduledPool(XmlDocumentBundleTracker.THREAD_POOL_NAME);
private Future<?> trackerJob; private @Nullable Future<?> trackerJob;
@Activate
public XmlBindingInfoProvider(final @Reference BindingI18nLocalizationService bindingI18nService,
final @Reference ReadyService readyService) {
this.bindingI18nService = bindingI18nService;
this.readyService = readyService;
}
@Activate @Activate
public void activate(ComponentContext componentContext) { public void activate(ComponentContext componentContext) {
XmlDocumentReader<BindingInfoXmlResult> bindingInfoReader = new BindingInfoReader(); XmlDocumentReader<BindingInfoXmlResult> bindingInfoReader = new BindingInfoReader();
bindingInfoTracker = new XmlDocumentBundleTracker<>(componentContext.getBundleContext(), XML_DIRECTORY, bindingInfoTracker = new XmlDocumentBundleTracker<>(componentContext.getBundleContext(), XML_DIRECTORY,
bindingInfoReader, this, READY_MARKER, readyService); bindingInfoReader, this, READY_MARKER, readyService);
trackerJob = scheduler.submit(() -> { trackerJob = scheduler.submit(() -> {
@ -77,33 +82,28 @@ public class XmlBindingInfoProvider extends AbstractXmlBasedProvider<String, Bin
@Deactivate @Deactivate
public void deactivate(ComponentContext componentContext) { public void deactivate(ComponentContext componentContext) {
if (trackerJob != null && !trackerJob.isDone()) { Future<?> localTrackerJob = trackerJob;
trackerJob.cancel(true); if (localTrackerJob != null && !localTrackerJob.isDone()) {
localTrackerJob.cancel(true);
trackerJob = null; trackerJob = null;
} }
bindingInfoTracker.close(); XmlDocumentBundleTracker<BindingInfoXmlResult> localBindingInfoTracker = bindingInfoTracker;
bindingInfoTracker = null; if (localBindingInfoTracker != null) {
localBindingInfoTracker.close();
bindingInfoTracker = null;
}
} }
@Override @Override
public synchronized BindingInfo getBindingInfo(String id, Locale locale) { public synchronized @Nullable BindingInfo getBindingInfo(@Nullable String id, @Nullable Locale locale) {
return get(id, locale); return id == null ? null : get(id, locale);
} }
@Override @Override
public synchronized Set<BindingInfo> getBindingInfos(Locale locale) { public synchronized Set<BindingInfo> getBindingInfos(@Nullable Locale locale) {
return new HashSet<>(getAll(locale)); return new HashSet<>(getAll(locale));
} }
@Reference
public void setTranslationProvider(TranslationProvider i18nProvider) {
this.bindingI18nUtil = new BindingI18nUtil(i18nProvider);
}
public void unsetTranslationProvider(TranslationProvider i18nProvider) {
this.bindingI18nUtil = null;
}
@Reference(target = "(esh.scope=core.xml.binding)") @Reference(target = "(esh.scope=core.xml.binding)")
public void setConfigDescriptionProvider(ConfigDescriptionProvider configDescriptionProvider) { public void setConfigDescriptionProvider(ConfigDescriptionProvider configDescriptionProvider) {
this.configDescriptionProvider = (AbstractXmlConfigDescriptionProvider) configDescriptionProvider; this.configDescriptionProvider = (AbstractXmlConfigDescriptionProvider) configDescriptionProvider;
@ -113,32 +113,13 @@ public class XmlBindingInfoProvider extends AbstractXmlBasedProvider<String, Bin
this.configDescriptionProvider = null; this.configDescriptionProvider = null;
} }
@Reference
public void setReadyService(ReadyService readyService) {
this.readyService = readyService;
}
public void unsetReadyService(ReadyService readyService) {
this.readyService = null;
}
@Override @Override
protected BindingInfo localize(Bundle bundle, BindingInfo bindingInfo, Locale locale) { protected @Nullable BindingInfo localize(Bundle bundle, BindingInfo bindingInfo, @Nullable Locale locale) {
if (this.bindingI18nUtil == null) { return bindingI18nService.createLocalizedBindingInfo(bundle, bindingInfo, locale);
return null;
}
String name = this.bindingI18nUtil.getName(bundle, bindingInfo.getUID(), bindingInfo.getName(), locale);
String description = this.bindingI18nUtil.getDescription(bundle, bindingInfo.getUID(),
bindingInfo.getDescription(), locale);
return new BindingInfo(bindingInfo.getUID(), name, description, bindingInfo.getAuthor(),
bindingInfo.getServiceId(), bindingInfo.getConfigDescriptionURI());
} }
@Override @Override
public XmlDocumentProvider<BindingInfoXmlResult> createDocumentProvider(Bundle bundle) { public XmlDocumentProvider<BindingInfoXmlResult> createDocumentProvider(Bundle bundle) {
return new BindingInfoXmlProvider(bundle, this, configDescriptionProvider); return new BindingInfoXmlProvider(bundle, this, configDescriptionProvider);
} }
} }

View File

@ -23,6 +23,7 @@ import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.smarthome.core.common.registry.Identifiable; import org.eclipse.smarthome.core.common.registry.Identifiable;
import org.eclipse.smarthome.core.i18n.LocalizedKey; import org.eclipse.smarthome.core.i18n.LocalizedKey;
import org.osgi.framework.Bundle; import org.osgi.framework.Bundle;
@ -48,7 +49,7 @@ public abstract class AbstractXmlBasedProvider<T_ID, T_OBJECT extends Identifiab
* @param locale the target locale * @param locale the target locale
* @return a translated copy of the given object or <code>null</code> if translation was not possible. * @return a translated copy of the given object or <code>null</code> if translation was not possible.
*/ */
protected abstract T_OBJECT localize(Bundle bundle, T_OBJECT object, Locale locale); protected abstract @Nullable T_OBJECT localize(Bundle bundle, T_OBJECT object, @Nullable Locale locale);
/** /**
* Adds an object to the internal list associated with the specified module. * Adds an object to the internal list associated with the specified module.
@ -104,7 +105,7 @@ public abstract class AbstractXmlBasedProvider<T_ID, T_OBJECT extends Identifiab
* @param locale the locale * @param locale the locale
* @return the object if found, <code>null</code> otherwise * @return the object if found, <code>null</code> otherwise
*/ */
protected final T_OBJECT get(T_ID key, Locale locale) { protected final @Nullable T_OBJECT get(T_ID key, @Nullable Locale locale) {
for (Entry<Bundle, List<T_OBJECT>> objects : bundleObjectMap.entrySet()) { for (Entry<Bundle, List<T_OBJECT>> objects : bundleObjectMap.entrySet()) {
for (T_OBJECT object : objects.getValue()) { for (T_OBJECT object : objects.getValue()) {
if (key.equals(object.getUID())) { if (key.equals(object.getUID())) {
@ -121,7 +122,7 @@ public abstract class AbstractXmlBasedProvider<T_ID, T_OBJECT extends Identifiab
* @param locale the locale * @param locale the locale
* @return a collection containing all available objects. Never <code>null</code> * @return a collection containing all available objects. Never <code>null</code>
*/ */
protected final synchronized Collection<T_OBJECT> getAll(Locale locale) { protected final synchronized Collection<T_OBJECT> getAll(@Nullable Locale locale) {
List<T_OBJECT> ret = new LinkedList<>(); List<T_OBJECT> ret = new LinkedList<>();
Collection<Entry<Bundle, List<T_OBJECT>>> objectList = bundleObjectMap.entrySet(); Collection<Entry<Bundle, List<T_OBJECT>>> objectList = bundleObjectMap.entrySet();
for (Entry<Bundle, List<T_OBJECT>> objects : objectList) { for (Entry<Bundle, List<T_OBJECT>> objects : objectList) {
@ -164,7 +165,7 @@ public abstract class AbstractXmlBasedProvider<T_ID, T_OBJECT extends Identifiab
} }
} }
private T_OBJECT acquireLocalizedObject(Bundle bundle, T_OBJECT object, Locale locale) { private T_OBJECT acquireLocalizedObject(Bundle bundle, T_OBJECT object, @Nullable Locale locale) {
final LocalizedKey localizedKey = getLocalizedKey(object, locale); final LocalizedKey localizedKey = getLocalizedKey(object, locale);
final T_OBJECT cacheEntry = localizedObjectCache.get(localizedKey); final T_OBJECT cacheEntry = localizedObjectCache.get(localizedKey);
@ -181,7 +182,7 @@ public abstract class AbstractXmlBasedProvider<T_ID, T_OBJECT extends Identifiab
} }
} }
private LocalizedKey getLocalizedKey(T_OBJECT object, Locale locale) { private LocalizedKey getLocalizedKey(T_OBJECT object, @Nullable Locale locale) {
return new LocalizedKey(object.getUID(), locale != null ? locale.toLanguageTag() : null); return new LocalizedKey(object.getUID(), locale != null ? locale.toLanguageTag() : null);
} }

View File

@ -16,6 +16,7 @@ import java.net.URI;
import java.util.Collection; import java.util.Collection;
import java.util.Locale; import java.util.Locale;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.smarthome.config.core.ConfigDescription; import org.eclipse.smarthome.config.core.ConfigDescription;
import org.eclipse.smarthome.config.core.ConfigDescriptionProvider; import org.eclipse.smarthome.config.core.ConfigDescriptionProvider;
import org.eclipse.smarthome.config.core.i18n.ConfigI18nLocalizationService; import org.eclipse.smarthome.config.core.i18n.ConfigI18nLocalizationService;
@ -41,21 +42,19 @@ public abstract class AbstractXmlConfigDescriptionProvider extends AbstractXmlBa
implements ConfigDescriptionProvider { implements ConfigDescriptionProvider {
@Override @Override
public synchronized Collection<ConfigDescription> getConfigDescriptions(Locale locale) { public synchronized Collection<ConfigDescription> getConfigDescriptions(@Nullable Locale locale) {
return getAll(locale); return getAll(locale);
} }
@Override @Override
public synchronized ConfigDescription getConfigDescription(URI uri, Locale locale) { public synchronized @Nullable ConfigDescription getConfigDescription(URI uri, @Nullable Locale locale) {
return get(uri, locale); return get(uri, locale);
} }
@Override @Override
protected ConfigDescription localize(Bundle bundle, ConfigDescription configDescription, Locale locale) { protected @Nullable ConfigDescription localize(Bundle bundle, ConfigDescription configDescription,
@Nullable Locale locale) {
ConfigI18nLocalizationService configI18nLocalizerService = getConfigI18nLocalizerService(); ConfigI18nLocalizationService configI18nLocalizerService = getConfigI18nLocalizerService();
if (configI18nLocalizerService == null) {
return null;
}
return configI18nLocalizerService.getLocalizedConfigDescription(bundle, configDescription, locale); return configI18nLocalizerService.getLocalizedConfigDescription(bundle, configDescription, locale);
} }

View File

@ -12,6 +12,8 @@
*/ */
package org.eclipse.smarthome.config.xml.osgi; package org.eclipse.smarthome.config.xml.osgi;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.smarthome.config.xml.internal.ConfigDescriptionReader; import org.eclipse.smarthome.config.xml.internal.ConfigDescriptionReader;
/** /**
@ -24,6 +26,7 @@ import org.eclipse.smarthome.config.xml.internal.ConfigDescriptionReader;
* *
* @param <T> the result type of the conversion * @param <T> the result type of the conversion
*/ */
@NonNullByDefault
public interface XmlDocumentProvider<T> { public interface XmlDocumentProvider<T> {
/** /**
@ -31,7 +34,7 @@ public interface XmlDocumentProvider<T> {
* *
* @param object the result object to be processed (could be null) * @param object the result object to be processed (could be null)
*/ */
void addingObject(T object); void addingObject(@Nullable T object);
/** /**
* Signals that all available result objects from the XML processing of the * Signals that all available result objects from the XML processing of the
@ -43,5 +46,4 @@ public interface XmlDocumentProvider<T> {
* Releases any added result objects from the XML processing. * Releases any added result objects from the XML processing.
*/ */
void release(); void release();
} }

View File

@ -12,6 +12,7 @@
*/ */
package org.eclipse.smarthome.config.xml.osgi; package org.eclipse.smarthome.config.xml.osgi;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.osgi.framework.Bundle; import org.osgi.framework.Bundle;
/** /**
@ -27,6 +28,7 @@ import org.osgi.framework.Bundle;
* @param <T> the result type of the conversion * @param <T> the result type of the conversion
* @see XmlDocumentProvider * @see XmlDocumentProvider
*/ */
@NonNullByDefault
public interface XmlDocumentProviderFactory<T> { public interface XmlDocumentProviderFactory<T> {
/** /**
@ -37,5 +39,4 @@ public interface XmlDocumentProviderFactory<T> {
* @return the created provider for the specified module (must not be null) * @return the created provider for the specified module (must not be null)
*/ */
XmlDocumentProvider<T> createDocumentProvider(Bundle bundle); XmlDocumentProvider<T> createDocumentProvider(Bundle bundle);
} }

View File

@ -14,6 +14,8 @@ package org.eclipse.smarthome.core.binding;
import java.net.URI; import java.net.URI;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.smarthome.core.common.registry.Identifiable; import org.eclipse.smarthome.core.common.registry.Identifiable;
/** /**
@ -27,17 +29,19 @@ import org.eclipse.smarthome.core.common.registry.Identifiable;
* @author Michael Grammling - Initial contribution * @author Michael Grammling - Initial contribution
* @author Andre Fuechsel - Made author tag optional * @author Andre Fuechsel - Made author tag optional
*/ */
@NonNullByDefault
public class BindingInfo implements Identifiable<String> { public class BindingInfo implements Identifiable<String> {
/** /**
* The default service ID prefix. * The default service ID prefix.
*/ */
public static final String DEFAULT_SERVICE_ID_PREFIX = "binding."; public static final String DEFAULT_SERVICE_ID_PREFIX = "binding.";
private String id; private String id;
private String name; private String name;
private String description; private @Nullable String description;
private String author; private @Nullable String author;
private URI configDescriptionURI; private @Nullable URI configDescriptionURI;
private String serviceId; private String serviceId;
/** /**
@ -46,13 +50,13 @@ public class BindingInfo implements Identifiable<String> {
* @param id the identifier for the binding (must neither be null, nor empty) * @param id the identifier for the binding (must neither be null, nor empty)
* @param name a human readable name for the binding (must neither be null, nor empty) * @param name a human readable name for the binding (must neither be null, nor empty)
* @param description a human readable description for the binding (could be null or empty) * @param description a human readable description for the binding (could be null or empty)
* @param author the author of the binding (must neither be null, nor empty) * @param author the author of the binding (could be null or empty)
* @param serviceId the service id of the main service of the binding (can be null) * @param serviceId the service id of the main service of the binding (can be null)
* @param configDescriptionURI the link to a concrete ConfigDescription (could be null) * @param configDescriptionURI the link to a concrete ConfigDescription (could be null)
* @throws IllegalArgumentException if the identifier, the name or the author is null or empty * @throws IllegalArgumentException if the identifier or the name are null or empty
*/ */
public BindingInfo(String id, String name, String description, String author, String serviceId, public BindingInfo(String id, String name, @Nullable String description, @Nullable String author,
URI configDescriptionURI) throws IllegalArgumentException { @Nullable String serviceId, @Nullable URI configDescriptionURI) throws IllegalArgumentException {
if ((id == null) || (id.isEmpty())) { if ((id == null) || (id.isEmpty())) {
throw new IllegalArgumentException("The ID must neither be null nor empty!"); throw new IllegalArgumentException("The ID must neither be null nor empty!");
} }
@ -76,7 +80,7 @@ public class BindingInfo implements Identifiable<String> {
*/ */
@Override @Override
public String getUID() { public String getUID() {
return this.id; return id;
} }
/** /**
@ -85,7 +89,7 @@ public class BindingInfo implements Identifiable<String> {
* @return a human readable name for the binding (neither null, nor empty) * @return a human readable name for the binding (neither null, nor empty)
*/ */
public String getName() { public String getName() {
return this.name; return name;
} }
/** /**
@ -94,8 +98,8 @@ public class BindingInfo implements Identifiable<String> {
* *
* @return a human readable description for the binding (could be null or empty) * @return a human readable description for the binding (could be null or empty)
*/ */
public String getDescription() { public @Nullable String getDescription() {
return this.description; return description;
} }
/** /**
@ -103,14 +107,14 @@ public class BindingInfo implements Identifiable<String> {
* *
* @return the author of the binding (could be null or empty) * @return the author of the binding (could be null or empty)
*/ */
public String getAuthor() { public @Nullable String getAuthor() {
return this.author; return author;
} }
/** /**
* Returns the service ID of the bindings main service, that can be configured. * Returns the service ID of the bindings main service, that can be configured.
* *
* @return service ID or null if no service is configured * @return service ID
*/ */
public String getServiceId() { public String getServiceId() {
return serviceId; return serviceId;
@ -121,14 +125,13 @@ public class BindingInfo implements Identifiable<String> {
* *
* @return the link to a concrete ConfigDescription (could be null) * @return the link to a concrete ConfigDescription (could be null)
*/ */
public URI getConfigDescriptionURI() { public @Nullable URI getConfigDescriptionURI() {
return this.configDescriptionURI; return configDescriptionURI;
} }
@Override @Override
public String toString() { public String toString() {
return "BindingInfoImpl [id=" + id + ", name=" + name + ", description=" + description + ", author=" + author return "BindingInfo [id=" + id + ", name=" + name + ", description=" + description + ", author=" + author
+ ", configDescriptionURI=" + configDescriptionURI + "]"; + ", configDescriptionURI=" + configDescriptionURI + "]";
} }
} }

View File

@ -15,6 +15,9 @@ package org.eclipse.smarthome.core.binding;
import java.util.Locale; import java.util.Locale;
import java.util.Set; import java.util.Set;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
/** /**
* The {@link BindingInfoProvider} is a service interface providing {@link BindingInfo} objects. All registered * The {@link BindingInfoProvider} is a service interface providing {@link BindingInfo} objects. All registered
* {@link BindingInfoProvider} services are tracked by the {@link BindingInfoRegistry} and provided as one common * {@link BindingInfoProvider} services are tracked by the {@link BindingInfoRegistry} and provided as one common
@ -24,6 +27,7 @@ import java.util.Set;
* *
* @see BindingInfoRegistry * @see BindingInfoRegistry
*/ */
@NonNullByDefault
public interface BindingInfoProvider { public interface BindingInfoProvider {
/** /**
@ -34,15 +38,15 @@ public interface BindingInfoProvider {
* @param locale the locale to be used for the binding information (could be null) * @param locale the locale to be used for the binding information (could be null)
* @return a localized binding information object (could be null) * @return a localized binding information object (could be null)
*/ */
BindingInfo getBindingInfo(String id, Locale locale); @Nullable
BindingInfo getBindingInfo(@Nullable String id, @Nullable Locale locale);
/** /**
* Returns all binding information in the specified locale (language) this provider contains. * Returns all binding information in the specified locale (language) this provider contains.
* *
* @param locale the locale to be used for the binding information (could be null) * @param locale the locale to be used for the binding information (could be null)
* @return a localized set of all binding information this provider contains * @return a localized set of all binding information this provider contains
* (not null, could be empty) * (could be empty)
*/ */
Set<BindingInfo> getBindingInfos(Locale locale); Set<BindingInfo> getBindingInfos(@Nullable Locale locale);
} }

View File

@ -19,6 +19,8 @@ import java.util.Locale;
import java.util.Set; import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference; import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality; import org.osgi.service.component.annotations.ReferenceCardinality;
@ -32,6 +34,7 @@ import org.osgi.service.component.annotations.ReferencePolicy;
* @author Michael Grammling - Initial contribution, added locale support * @author Michael Grammling - Initial contribution, added locale support
*/ */
@Component(immediate = true, service = BindingInfoRegistry.class) @Component(immediate = true, service = BindingInfoRegistry.class)
@NonNullByDefault
public class BindingInfoRegistry { public class BindingInfoRegistry {
private final Collection<BindingInfoProvider> bindingInfoProviders = new CopyOnWriteArrayList<>(); private final Collection<BindingInfoProvider> bindingInfoProviders = new CopyOnWriteArrayList<>();
@ -39,13 +42,13 @@ public class BindingInfoRegistry {
@Reference(cardinality = ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC) @Reference(cardinality = ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC)
protected void addBindingInfoProvider(BindingInfoProvider bindingInfoProvider) { protected void addBindingInfoProvider(BindingInfoProvider bindingInfoProvider) {
if (bindingInfoProvider != null) { if (bindingInfoProvider != null) {
this.bindingInfoProviders.add(bindingInfoProvider); bindingInfoProviders.add(bindingInfoProvider);
} }
} }
protected void removeBindingInfoProvider(BindingInfoProvider bindingInfoProvider) { protected void removeBindingInfoProvider(BindingInfoProvider bindingInfoProvider) {
if (bindingInfoProvider != null) { if (bindingInfoProvider != null) {
this.bindingInfoProviders.remove(bindingInfoProvider); bindingInfoProviders.remove(bindingInfoProvider);
} }
} }
@ -56,7 +59,7 @@ public class BindingInfoRegistry {
* @param id the ID to be looked for (could be null or empty) * @param id the ID to be looked for (could be null or empty)
* @return a binding information object (could be null) * @return a binding information object (could be null)
*/ */
public BindingInfo getBindingInfo(String id) { public @Nullable BindingInfo getBindingInfo(@Nullable String id) {
return getBindingInfo(id, null); return getBindingInfo(id, null);
} }
@ -68,15 +71,13 @@ public class BindingInfoRegistry {
* @param locale the locale to be used for the binding information (could be null) * @param locale the locale to be used for the binding information (could be null)
* @return a localized binding information object (could be null) * @return a localized binding information object (could be null)
*/ */
public BindingInfo getBindingInfo(String id, Locale locale) { public @Nullable BindingInfo getBindingInfo(@Nullable String id, @Nullable Locale locale) {
for (BindingInfoProvider bindingInfoProvider : this.bindingInfoProviders) { for (BindingInfoProvider bindingInfoProvider : bindingInfoProviders) {
BindingInfo bindingInfo = bindingInfoProvider.getBindingInfo(id, locale); BindingInfo bindingInfo = bindingInfoProvider.getBindingInfo(id, locale);
if (bindingInfo != null) { if (bindingInfo != null) {
return bindingInfo; return bindingInfo;
} }
} }
return null; return null;
} }
@ -96,15 +97,12 @@ public class BindingInfoRegistry {
* @return a localized set of all binding information this registry contains * @return a localized set of all binding information this registry contains
* (not null, could be empty) * (not null, could be empty)
*/ */
public Set<BindingInfo> getBindingInfos(Locale locale) { public Set<BindingInfo> getBindingInfos(@Nullable Locale locale) {
Set<BindingInfo> allBindingInfos = new LinkedHashSet<>(10); Set<BindingInfo> allBindingInfos = new LinkedHashSet<>(bindingInfoProviders.size());
for (BindingInfoProvider bindingInfoProvider : bindingInfoProviders) {
for (BindingInfoProvider bindingInfoProvider : this.bindingInfoProviders) {
Set<BindingInfo> bindingInfos = bindingInfoProvider.getBindingInfos(locale); Set<BindingInfo> bindingInfos = bindingInfoProvider.getBindingInfos(locale);
allBindingInfos.addAll(bindingInfos); allBindingInfos.addAll(bindingInfos);
} }
return Collections.unmodifiableSet(allBindingInfos); return Collections.unmodifiableSet(allBindingInfos);
} }
} }

View File

@ -35,5 +35,4 @@ public class BindingInfoDTO {
this.description = description; this.description = description;
this.configDescriptionURI = configDescriptionURI; this.configDescriptionURI = configDescriptionURI;
} }
} }

View File

@ -0,0 +1,62 @@
/**
* Copyright (c) 2010-2019 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.eclipse.smarthome.core.binding.i18n;
import java.util.Locale;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.smarthome.core.binding.BindingInfo;
import org.eclipse.smarthome.core.binding.internal.i18n.BindingI18nUtil;
import org.eclipse.smarthome.core.i18n.TranslationProvider;
import org.osgi.framework.Bundle;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
/**
* This OSGi service could be used to localize the binding info using the I18N mechanism of the openHAB
* framework.
*
* @author Christoph Weitkamp - Initial contribution
*/
@Component(immediate = true, service = { BindingI18nLocalizationService.class })
@NonNullByDefault
public class BindingI18nLocalizationService {
private final BindingI18nUtil bindingI18nUtil;
@Activate
public BindingI18nLocalizationService(final @Reference TranslationProvider i18nProvider) {
this.bindingI18nUtil = new BindingI18nUtil(i18nProvider);
}
/**
* Localizes a binding info.
*
* @param bundle the bundle the i18n resources are located
* @param bindingInfo the binding info that should be localized
* @param locale the locale it should be localized to
* @return a localized binding info on success, a non-localized one on error (e.g. no translation is found).
*/
public BindingInfo createLocalizedBindingInfo(Bundle bundle, BindingInfo bindingInfo, @Nullable Locale locale) {
String bindingInfoUID = bindingInfo.getUID();
String name = bindingI18nUtil.getName(bundle, bindingInfoUID, bindingInfo.getName(), locale);
String description = bindingI18nUtil.getDescription(bundle, bindingInfoUID, bindingInfo.getDescription(),
locale);
return new BindingInfo(bindingInfoUID, name == null ? bindingInfo.getName() : name,
description == null ? bindingInfo.getDescription() : description, bindingInfo.getAuthor(),
bindingInfo.getServiceId(), bindingInfo.getConfigDescriptionURI());
}
}

View File

@ -10,10 +10,14 @@
* *
* SPDX-License-Identifier: EPL-2.0 * SPDX-License-Identifier: EPL-2.0
*/ */
package org.eclipse.smarthome.core.i18n; package org.eclipse.smarthome.core.binding.internal.i18n;
import java.util.Locale; import java.util.Locale;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.smarthome.core.i18n.I18nUtil;
import org.eclipse.smarthome.core.i18n.TranslationProvider;
import org.osgi.framework.Bundle; import org.osgi.framework.Bundle;
/** /**
@ -23,6 +27,7 @@ import org.osgi.framework.Bundle;
* *
* @author Dennis Nobel - Initial contribution * @author Dennis Nobel - Initial contribution
*/ */
@NonNullByDefault
public class BindingI18nUtil { public class BindingI18nUtil {
private final TranslationProvider i18nProvider; private final TranslationProvider i18nProvider;
@ -31,20 +36,18 @@ public class BindingI18nUtil {
this.i18nProvider = i18nProvider; this.i18nProvider = i18nProvider;
} }
public String getDescription(Bundle bundle, String bindingId, String defaultDescription, Locale locale) { public @Nullable String getDescription(Bundle bundle, String bindingId, @Nullable String defaultDescription,
@Nullable Locale locale) {
String key = I18nUtil.stripConstantOr(defaultDescription, () -> inferKey(bindingId, "description")); String key = I18nUtil.stripConstantOr(defaultDescription, () -> inferKey(bindingId, "description"));
return i18nProvider.getText(bundle, key, defaultDescription, locale); return i18nProvider.getText(bundle, key, defaultDescription, locale);
} }
public String getName(Bundle bundle, String bindingId, String defaultLabel, Locale locale) { public @Nullable String getName(Bundle bundle, String bindingId, String defaultLabel, @Nullable Locale locale) {
String key = I18nUtil.stripConstantOr(defaultLabel, () -> inferKey(bindingId, "name")); String key = I18nUtil.stripConstantOr(defaultLabel, () -> inferKey(bindingId, "name"));
return i18nProvider.getText(bundle, key, defaultLabel, locale); return i18nProvider.getText(bundle, key, defaultLabel, locale);
} }
private String inferKey(String bindingId, String lastSegment) { private String inferKey(String bindingId, String lastSegment) {
return "binding." + bindingId + "." + lastSegment; return "binding." + bindingId + "." + lastSegment;
} }
} }