attributes = attributeMapValidator.readValidatedAttributes(reader);
+
+ String id = requireNonEmpty(attributes.get("id"), "Add-on id attribute is null or empty");
+
+ // set automatically extracted URI for a possible 'config-description' section
+ context.put("config-description.uri", CONFIG_DESCRIPTION_URI_PLACEHOLDER);
+
+ // read values
+ List> nodes = (List>) context.convertAnother(context, List.class);
+ NodeIterator nodeIterator = new NodeIterator(nodes);
+
+ String type = requireNonEmpty((String) nodeIterator.nextValue("type", true), "Add-on type is null or empty");
+
+ String name = requireNonEmpty((String) nodeIterator.nextValue("name", true),
+ "Add-on name attribute is null or empty");
+ String description = requireNonEmpty((String) nodeIterator.nextValue("description", true),
+ "Add-on description is null or empty");
+
+ AddonInfo.Builder addonInfo = AddonInfo.builder(id, type).withName(name).withDescription(description);
+ addonInfo.withAuthor((String) nodeIterator.nextValue("author", false));
+ addonInfo.withConnection((String) nodeIterator.nextValue("connection", false));
+
+ addonInfo.withServiceId((String) nodeIterator.nextValue("service-id", false));
+
+ String configDescriptionURI = nodeIterator.nextAttribute("config-description-ref", "uri", false);
+ ConfigDescription configDescription = null;
+ if (configDescriptionURI == null) {
+ configDescription = readConfigDescription(nodeIterator);
+ if (configDescription != null) {
+ configDescriptionURI = configDescription.getUID().toString();
+ // if config description is missing the URI, recreate it with correct URI
+ if (CONFIG_DESCRIPTION_URI_PLACEHOLDER.equals(configDescriptionURI)) {
+ configDescriptionURI = type + ":" + id;
+ configDescription = ConfigDescriptionBuilder.create(URI.create(configDescriptionURI))
+ .withParameterGroups(configDescription.getParameterGroups())
+ .withParameters(configDescription.getParameters()).build();
+ }
+ }
+ }
+ addonInfo.withConfigDescriptionURI(configDescriptionURI);
+
+ nodeIterator.assertEndOfType();
+
+ // create object
+ return new AddonInfoXmlResult(addonInfo.build(), configDescription);
+ }
+}
diff --git a/bundles/org.openhab.core.binding.xml/src/main/java/org/openhab/core/binding/xml/internal/BindingInfoReader.java b/bundles/org.openhab.core.addon.xml/src/main/java/org/openhab/core/addon/xml/internal/AddonInfoReader.java
similarity index 83%
rename from bundles/org.openhab.core.binding.xml/src/main/java/org/openhab/core/binding/xml/internal/BindingInfoReader.java
rename to bundles/org.openhab.core.addon.xml/src/main/java/org/openhab/core/addon/xml/internal/AddonInfoReader.java
index 0cd1e1559..334a275d9 100644
--- a/bundles/org.openhab.core.binding.xml/src/main/java/org/openhab/core/binding/xml/internal/BindingInfoReader.java
+++ b/bundles/org.openhab.core.addon.xml/src/main/java/org/openhab/core/addon/xml/internal/AddonInfoReader.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.core.binding.xml.internal;
+package org.openhab.core.addon.xml.internal;
import java.util.List;
@@ -33,23 +33,24 @@ import org.openhab.core.config.xml.util.XmlDocumentReader;
import com.thoughtworks.xstream.XStream;
/**
- * The {@link BindingInfoReader} reads XML documents, which contain the {@code binding} XML tag,
- * and converts them to {@link BindingInfoXmlResult} objects.
+ * The {@link AddonInfoReader} reads XML documents, which contain the {@code binding} XML tag,
+ * and converts them to {@link AddonInfoXmlResult} objects.
*
* This reader uses {@code XStream} and {@code StAX} to parse and convert the XML document.
*
* @author Michael Grammling - Initial contribution
* @author Alex Tugarev - Extended by options and filter criteria
* @author Chris Jackson - Add parameter groups
+ * @author Jan N. Klug - Refactored to cover all add-ons
*/
@NonNullByDefault
-public class BindingInfoReader extends XmlDocumentReader {
+public class AddonInfoReader extends XmlDocumentReader {
/**
* The default constructor of this class.
*/
- public BindingInfoReader() {
- ClassLoader classLoader = BindingInfoReader.class.getClassLoader();
+ public AddonInfoReader() {
+ ClassLoader classLoader = AddonInfoReader.class.getClassLoader();
if (classLoader != null) {
super.setClassLoader(classLoader);
}
@@ -59,7 +60,7 @@ public class BindingInfoReader extends XmlDocumentReader {
protected void registerConverters(XStream xstream) {
xstream.registerConverter(new NodeAttributesConverter());
xstream.registerConverter(new NodeValueConverter());
- xstream.registerConverter(new BindingInfoConverter());
+ xstream.registerConverter(new AddonInfoConverter());
xstream.registerConverter(new ConfigDescriptionConverter());
xstream.registerConverter(new ConfigDescriptionParameterConverter());
xstream.registerConverter(new ConfigDescriptionParameterGroupConverter());
@@ -68,11 +69,11 @@ public class BindingInfoReader extends XmlDocumentReader {
@Override
protected void registerAliases(XStream xstream) {
- xstream.alias("binding", BindingInfoXmlResult.class);
+ xstream.alias("addon", AddonInfoXmlResult.class);
xstream.alias("name", NodeValue.class);
xstream.alias("description", NodeValue.class);
xstream.alias("author", NodeValue.class);
- xstream.alias("service-id", NodeValue.class);
+ xstream.alias("type", NodeValue.class);
xstream.alias("config-description", ConfigDescription.class);
xstream.alias("config-description-ref", NodeAttributes.class);
xstream.alias("parameter", ConfigDescriptionParameter.class);
@@ -81,5 +82,6 @@ public class BindingInfoReader extends XmlDocumentReader {
xstream.alias("option", NodeValue.class);
xstream.alias("filter", List.class);
xstream.alias("criteria", FilterCriteria.class);
+ xstream.alias("service-id", NodeValue.class);
}
}
diff --git a/bundles/org.openhab.core.binding.xml/src/main/java/org/openhab/core/binding/xml/internal/BindingInfoXmlProvider.java b/bundles/org.openhab.core.addon.xml/src/main/java/org/openhab/core/addon/xml/internal/AddonInfoXmlProvider.java
similarity index 59%
rename from bundles/org.openhab.core.binding.xml/src/main/java/org/openhab/core/binding/xml/internal/BindingInfoXmlProvider.java
rename to bundles/org.openhab.core.addon.xml/src/main/java/org/openhab/core/addon/xml/internal/AddonInfoXmlProvider.java
index 5da7384ff..93bac7bdf 100644
--- a/bundles/org.openhab.core.binding.xml/src/main/java/org/openhab/core/binding/xml/internal/BindingInfoXmlProvider.java
+++ b/bundles/org.openhab.core.addon.xml/src/main/java/org/openhab/core/addon/xml/internal/AddonInfoXmlProvider.java
@@ -10,11 +10,9 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.core.binding.xml.internal;
+package org.openhab.core.addon.xml.internal;
import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.openhab.core.binding.BindingInfo;
-import org.openhab.core.binding.BindingInfoProvider;
import org.openhab.core.config.core.ConfigDescription;
import org.openhab.core.config.xml.AbstractXmlConfigDescriptionProvider;
import org.openhab.core.config.xml.osgi.XmlDocumentProvider;
@@ -23,38 +21,37 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
- * The {@link BindingInfoXmlProvider} is responsible managing any created
- * objects by a {@link BindingInfoReader} for a certain bundle.
+ * The {@link AddonInfoXmlProvider} is responsible managing any created
+ * objects by a {@link AddonInfoReader} for a certain bundle.
*
- * This implementation registers each {@link BindingInfo} object at the {@link XmlBindingInfoProvider} which is itself
- * registered as {@link BindingInfoProvider} service at the OSGi service registry.
+ * This implementation registers each {@link AddonInfo} object at the {@link XmlAddonInfoProvider} which is itself
+ * registered as {@link AddonInfoProvider} service at the OSGi service registry.
*
- * If there is a {@link ConfigDescription} object within the {@link BindingInfoXmlResult} object, it is added to the
+ * If there is a {@link ConfigDescription} object within the {@link AddonInfoXmlResult} object, it is added to the
* {@link AbstractXmlConfigDescriptionProvider} which is itself registered as OSGi service at the service
* registry.
*
* @author Michael Grammling - Initial contribution
- *
- * @see BindingInfoXmlProviderFactory
+ * @author Jan N. Klug - Refactored to cover all add-ons
*/
@NonNullByDefault
-public class BindingInfoXmlProvider implements XmlDocumentProvider {
+public class AddonInfoXmlProvider implements XmlDocumentProvider {
- private Logger logger = LoggerFactory.getLogger(BindingInfoXmlProvider.class);
+ private Logger logger = LoggerFactory.getLogger(AddonInfoXmlProvider.class);
private final Bundle bundle;
- private final XmlBindingInfoProvider bindingInfoProvider;
+ private final XmlAddonInfoProvider addonInfoProvider;
private final AbstractXmlConfigDescriptionProvider configDescriptionProvider;
- public BindingInfoXmlProvider(Bundle bundle, XmlBindingInfoProvider bindingInfoProvider,
+ public AddonInfoXmlProvider(Bundle bundle, XmlAddonInfoProvider addonInfoProvider,
AbstractXmlConfigDescriptionProvider configDescriptionProvider) throws IllegalArgumentException {
if (bundle == null) {
throw new IllegalArgumentException("The Bundle must not be null!");
}
- if (bindingInfoProvider == null) {
- throw new IllegalArgumentException("The XmlBindingInfoProvider must not be null!");
+ if (addonInfoProvider == null) {
+ throw new IllegalArgumentException("The XmlAddonInfoProvider must not be null!");
}
if (configDescriptionProvider == null) {
@@ -62,13 +59,13 @@ public class BindingInfoXmlProvider implements XmlDocumentProvider
+ * If a {@link ConfigDescription} object exists, it must be added to the according {@link ConfigDescriptionProvider}.
+ *
+ * @author Jan N. Klug - Initial contribution
+ */
+@NonNullByDefault
+public record AddonInfoXmlResult(AddonInfo addonInfo, @Nullable ConfigDescription configDescription) {
+}
diff --git a/bundles/org.openhab.core.binding.xml/src/main/java/org/openhab/core/binding/xml/internal/BindingXmlConfigDescriptionProvider.java b/bundles/org.openhab.core.addon.xml/src/main/java/org/openhab/core/addon/xml/internal/AddonXmlConfigDescriptionProvider.java
similarity index 78%
rename from bundles/org.openhab.core.binding.xml/src/main/java/org/openhab/core/binding/xml/internal/BindingXmlConfigDescriptionProvider.java
rename to bundles/org.openhab.core.addon.xml/src/main/java/org/openhab/core/addon/xml/internal/AddonXmlConfigDescriptionProvider.java
index cbb0bb5a7..f21cb22b9 100644
--- a/bundles/org.openhab.core.binding.xml/src/main/java/org/openhab/core/binding/xml/internal/BindingXmlConfigDescriptionProvider.java
+++ b/bundles/org.openhab.core.addon.xml/src/main/java/org/openhab/core/addon/xml/internal/AddonXmlConfigDescriptionProvider.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.core.binding.xml.internal;
+package org.openhab.core.addon.xml.internal;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.core.config.core.ConfigDescription;
@@ -25,15 +25,16 @@ import org.osgi.service.component.annotations.Reference;
* Provides {@link ConfigDescription}s for bindings which are read from XML files.
*
* @author Simon Kaufmann - Initial contribution
+ * @author Jan N. Klug - Refactored to cover all add-ons
*/
-@Component(service = ConfigDescriptionProvider.class, immediate = true, property = { "openhab.scope=core.xml.binding" })
+@Component(service = ConfigDescriptionProvider.class, immediate = true, property = { "openhab.scope=core.xml.addon" })
@NonNullByDefault
-public class BindingXmlConfigDescriptionProvider extends AbstractXmlConfigDescriptionProvider {
+public class AddonXmlConfigDescriptionProvider extends AbstractXmlConfigDescriptionProvider {
private final ConfigI18nLocalizationService configI18nService;
@Activate
- public BindingXmlConfigDescriptionProvider(final @Reference ConfigI18nLocalizationService configI18nService) {
+ public AddonXmlConfigDescriptionProvider(final @Reference ConfigI18nLocalizationService configI18nService) {
this.configI18nService = configI18nService;
}
diff --git a/bundles/org.openhab.core.addon.xml/src/main/java/org/openhab/core/addon/xml/internal/XmlAddonInfoProvider.java b/bundles/org.openhab.core.addon.xml/src/main/java/org/openhab/core/addon/xml/internal/XmlAddonInfoProvider.java
new file mode 100644
index 000000000..52d7ce047
--- /dev/null
+++ b/bundles/org.openhab.core.addon.xml/src/main/java/org/openhab/core/addon/xml/internal/XmlAddonInfoProvider.java
@@ -0,0 +1,107 @@
+/**
+ * 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.addon.xml.internal;
+
+import java.util.HashSet;
+import java.util.Locale;
+import java.util.Set;
+import java.util.concurrent.Future;
+import java.util.concurrent.ScheduledExecutorService;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.openhab.core.addon.AddonI18nLocalizationService;
+import org.openhab.core.addon.AddonInfo;
+import org.openhab.core.addon.AddonInfoProvider;
+import org.openhab.core.common.ThreadPoolManager;
+import org.openhab.core.config.core.ConfigDescriptionProvider;
+import org.openhab.core.config.xml.AbstractXmlBasedProvider;
+import org.openhab.core.config.xml.AbstractXmlConfigDescriptionProvider;
+import org.openhab.core.config.xml.osgi.XmlDocumentBundleTracker;
+import org.openhab.core.config.xml.osgi.XmlDocumentProvider;
+import org.openhab.core.config.xml.osgi.XmlDocumentProviderFactory;
+import org.openhab.core.config.xml.util.XmlDocumentReader;
+import org.openhab.core.service.ReadyService;
+import org.osgi.framework.Bundle;
+import org.osgi.service.component.ComponentContext;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Deactivate;
+import org.osgi.service.component.annotations.Reference;
+
+/**
+ * The {@link XmlAddonInfoProvider} is a concrete implementation of the {@link AddonInfoProvider} service interface.
+ *
+ * This implementation manages any {@link AddonInfo} objects associated to specific modules. If a specific module
+ * disappears, any registered {@link AddonInfo} objects associated with that module are released.
+ *
+ * @author Michael Grammling - Initial contribution
+ * @author Michael Grammling - Refactoring: Provider/Registry pattern is used, added locale support
+ * @author Simon Kaufmann - factored out common aspects into {@link AbstractXmlBasedProvider}
+ * @author Jan N. Klug - Refactored to cover all add-ons
+ */
+@NonNullByDefault
+@Component
+public class XmlAddonInfoProvider extends AbstractXmlBasedProvider
+ implements AddonInfoProvider, XmlDocumentProviderFactory {
+
+ private static final String XML_DIRECTORY = "/OH-INF/addon/";
+ public static final String READY_MARKER = "openhab.xmlAddonInfo";
+
+ private final AddonI18nLocalizationService addonI18nService;
+ private final AbstractXmlConfigDescriptionProvider configDescriptionProvider;
+ private final XmlDocumentBundleTracker addonInfoTracker;
+ private final Future> trackerJob;
+
+ @Activate
+ public XmlAddonInfoProvider(final @Reference AddonI18nLocalizationService addonI18nService,
+ final @Reference(target = "(openhab.scope=core.xml.addon)") ConfigDescriptionProvider configDescriptionProvider,
+ final @Reference ReadyService readyService, ComponentContext componentContext) {
+ this.addonI18nService = addonI18nService;
+ this.configDescriptionProvider = (AbstractXmlConfigDescriptionProvider) configDescriptionProvider;
+
+ XmlDocumentReader addonInfoReader = new AddonInfoReader();
+ addonInfoTracker = new XmlDocumentBundleTracker<>(componentContext.getBundleContext(), XML_DIRECTORY,
+ addonInfoReader, this, READY_MARKER, readyService);
+
+ ScheduledExecutorService scheduler = ThreadPoolManager
+ .getScheduledPool(XmlDocumentBundleTracker.THREAD_POOL_NAME);
+ trackerJob = scheduler.submit(addonInfoTracker::open);
+ }
+
+ @Deactivate
+ public void deactivate() {
+ trackerJob.cancel(true);
+ addonInfoTracker.close();
+ }
+
+ @Override
+ public synchronized @Nullable AddonInfo getAddonInfo(@Nullable String id, @Nullable Locale locale) {
+ return id == null ? null : get(id, locale);
+ }
+
+ @Override
+ public synchronized Set getAddonInfos(@Nullable Locale locale) {
+ return new HashSet<>(getAll(locale));
+ }
+
+ @Override
+ protected @Nullable AddonInfo localize(Bundle bundle, AddonInfo bindingInfo, @Nullable Locale locale) {
+ return addonI18nService.createLocalizedAddonInfo(bundle, bindingInfo, locale);
+ }
+
+ @Override
+ public XmlDocumentProvider createDocumentProvider(Bundle bundle) {
+ return new AddonInfoXmlProvider(bundle, this, configDescriptionProvider);
+ }
+}
diff --git a/bundles/org.openhab.core.binding.xml/binding-1.0.0.xsd b/bundles/org.openhab.core.binding.xml/binding-1.0.0.xsd
deleted file mode 100644
index fb11dbb77..000000000
--- a/bundles/org.openhab.core.binding.xml/binding-1.0.0.xsd
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/bundles/org.openhab.core.binding.xml/src/main/java/org/openhab/core/binding/xml/internal/BindingInfoConverter.java b/bundles/org.openhab.core.binding.xml/src/main/java/org/openhab/core/binding/xml/internal/BindingInfoConverter.java
deleted file mode 100644
index ed6cf6a23..000000000
--- a/bundles/org.openhab.core.binding.xml/src/main/java/org/openhab/core/binding/xml/internal/BindingInfoConverter.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/**
- * 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.binding.xml.internal;
-
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.List;
-import java.util.Map;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.eclipse.jdt.annotation.Nullable;
-import org.openhab.core.binding.BindingInfo;
-import org.openhab.core.config.core.ConfigDescription;
-import org.openhab.core.config.xml.util.ConverterAttributeMapValidator;
-import org.openhab.core.config.xml.util.GenericUnmarshaller;
-import org.openhab.core.config.xml.util.NodeIterator;
-
-import com.thoughtworks.xstream.converters.ConversionException;
-import com.thoughtworks.xstream.converters.Converter;
-import com.thoughtworks.xstream.converters.UnmarshallingContext;
-import com.thoughtworks.xstream.io.HierarchicalStreamReader;
-
-/**
- * The {@link BindingInfoConverter} is a concrete implementation of the {@code XStream} {@link Converter} interface used
- * to convert binding information within an XML document
- * into a {@link BindingInfoXmlResult} object.
- *
- * This converter converts {@code binding} XML tags.
- *
- * @author Michael Grammling - Initial contribution
- * @author Andre Fuechsel - Made author tag optional
- */
-@NonNullByDefault
-public class BindingInfoConverter extends GenericUnmarshaller {
-
- private ConverterAttributeMapValidator attributeMapValidator;
-
- public BindingInfoConverter() {
- super(BindingInfoXmlResult.class);
-
- attributeMapValidator = new ConverterAttributeMapValidator(
- new String[][] { { "id", "true" }, { "schemaLocation", "false" } });
- }
-
- private @Nullable URI readConfigDescriptionURI(NodeIterator nodeIterator) throws ConversionException {
- String uriText = nodeIterator.nextAttribute("config-description-ref", "uri", false);
-
- if (uriText != null) {
- try {
- return new URI(uriText);
- } catch (URISyntaxException ex) {
- throw new ConversionException(
- "The URI '" + uriText + "' in node " + "'config-description-ref' is invalid!", ex);
- }
- }
-
- return null;
- }
-
- private @Nullable ConfigDescription readConfigDescription(NodeIterator nodeIterator) {
- Object nextNode = nodeIterator.next();
-
- if (nextNode != null) {
- if (nextNode instanceof ConfigDescription) {
- return (ConfigDescription) nextNode;
- }
-
- nodeIterator.revert();
- }
-
- return null;
- }
-
- @Override
- public @Nullable Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
- // read attributes
- Map attributes = attributeMapValidator.readValidatedAttributes(reader);
-
- String id = requireNonEmpty(attributes.get("id"), "Binding id attribute is null or empty");
-
- // set automatically extracted URI for a possible 'config-description' section
- context.put("config-description.uri", "binding:" + id);
-
- // read values
- List> nodes = (List>) context.convertAnother(context, List.class);
- NodeIterator nodeIterator = new NodeIterator(nodes);
-
- String name = requireNonEmpty((String) nodeIterator.nextValue("name", true),
- "Binding name attribute is null or empty");
- String description = (String) nodeIterator.nextValue("description", false);
- String author = (String) nodeIterator.nextValue("author", false);
- String serviceId = (String) nodeIterator.nextValue("service-id", false);
-
- URI configDescriptionURI = readConfigDescriptionURI(nodeIterator);
- ConfigDescription configDescription = null;
- if (configDescriptionURI == null) {
- configDescription = readConfigDescription(nodeIterator);
- if (configDescription != null) {
- configDescriptionURI = configDescription.getUID();
- }
- }
-
- nodeIterator.assertEndOfType();
-
- // create object
- BindingInfo bindingInfo = new BindingInfo(id, name, description, author, serviceId, configDescriptionURI);
- return new BindingInfoXmlResult(bindingInfo, configDescription);
- }
-}
diff --git a/bundles/org.openhab.core.binding.xml/src/main/java/org/openhab/core/binding/xml/internal/BindingInfoXmlResult.java b/bundles/org.openhab.core.binding.xml/src/main/java/org/openhab/core/binding/xml/internal/BindingInfoXmlResult.java
deleted file mode 100644
index d1b2dff45..000000000
--- a/bundles/org.openhab.core.binding.xml/src/main/java/org/openhab/core/binding/xml/internal/BindingInfoXmlResult.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/**
- * 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.binding.xml.internal;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.eclipse.jdt.annotation.Nullable;
-import org.openhab.core.binding.BindingInfo;
-import org.openhab.core.config.core.ConfigDescription;
-import org.openhab.core.config.core.ConfigDescriptionProvider;
-
-/**
- * The {@link BindingInfoXmlResult} is an intermediate XML conversion result object which
- * contains a mandatory {@link BindingInfo} and an optional {@link ConfigDescription} object.
- *
- * If a {@link ConfigDescription} object exists, it must be added to the according {@link ConfigDescriptionProvider}.
- *
- * @author Michael Grammling - Initial contribution
- */
-@NonNullByDefault
-public class BindingInfoXmlResult {
-
- private BindingInfo bindingInfo;
- private @Nullable ConfigDescription configDescription;
-
- public BindingInfoXmlResult(BindingInfo bindingInfo, @Nullable ConfigDescription configDescription) {
- this.bindingInfo = bindingInfo;
- this.configDescription = configDescription;
- }
-
- public BindingInfo getBindingInfo() {
- return bindingInfo;
- }
-
- public @Nullable ConfigDescription getConfigDescription() {
- return configDescription;
- }
-
- @Override
- public String toString() {
- return "BindingInfoXmlResult [bindingInfo=" + bindingInfo + ", configDescription=" + configDescription + "]";
- }
-}
diff --git a/bundles/org.openhab.core.binding.xml/src/main/java/org/openhab/core/binding/xml/internal/XmlBindingInfoProvider.java b/bundles/org.openhab.core.binding.xml/src/main/java/org/openhab/core/binding/xml/internal/XmlBindingInfoProvider.java
deleted file mode 100644
index 562c52b67..000000000
--- a/bundles/org.openhab.core.binding.xml/src/main/java/org/openhab/core/binding/xml/internal/XmlBindingInfoProvider.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/**
- * 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.binding.xml.internal;
-
-import java.util.HashSet;
-import java.util.Locale;
-import java.util.Set;
-import java.util.concurrent.Future;
-import java.util.concurrent.ScheduledExecutorService;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.eclipse.jdt.annotation.Nullable;
-import org.openhab.core.binding.BindingInfo;
-import org.openhab.core.binding.BindingInfoProvider;
-import org.openhab.core.binding.i18n.BindingI18nLocalizationService;
-import org.openhab.core.common.ThreadPoolManager;
-import org.openhab.core.config.core.ConfigDescriptionProvider;
-import org.openhab.core.config.xml.AbstractXmlBasedProvider;
-import org.openhab.core.config.xml.AbstractXmlConfigDescriptionProvider;
-import org.openhab.core.config.xml.osgi.XmlDocumentBundleTracker;
-import org.openhab.core.config.xml.osgi.XmlDocumentProvider;
-import org.openhab.core.config.xml.osgi.XmlDocumentProviderFactory;
-import org.openhab.core.config.xml.util.XmlDocumentReader;
-import org.openhab.core.service.ReadyService;
-import org.osgi.framework.Bundle;
-import org.osgi.service.component.ComponentContext;
-import org.osgi.service.component.annotations.Activate;
-import org.osgi.service.component.annotations.Component;
-import org.osgi.service.component.annotations.Deactivate;
-import org.osgi.service.component.annotations.Reference;
-
-/**
- * The {@link XmlBindingInfoProvider} is a concrete implementation of the {@link BindingInfoProvider} service interface.
- *
- * This implementation manages any {@link BindingInfo} objects associated to specific modules. If a specific module
- * disappears, any registered {@link BindingInfo} objects associated with that module are released.
- *
- * @author Michael Grammling - Initial contribution
- * @author Michael Grammling - Refactoring: Provider/Registry pattern is used, added locale support
- * @author Simon Kaufmann - factored out common aspects into {@link AbstractXmlBasedProvider}
- */
-@NonNullByDefault
-@Component
-public class XmlBindingInfoProvider extends AbstractXmlBasedProvider
- implements BindingInfoProvider, XmlDocumentProviderFactory {
-
- private static final String XML_DIRECTORY = "/OH-INF/binding/";
- public static final String READY_MARKER = "openhab.xmlBindingInfo";
-
- private final BindingI18nLocalizationService bindingI18nService;
- private AbstractXmlConfigDescriptionProvider configDescriptionProvider;
- private @Nullable XmlDocumentBundleTracker bindingInfoTracker;
- private final ReadyService readyService;
- private final ScheduledExecutorService scheduler = ThreadPoolManager
- .getScheduledPool(XmlDocumentBundleTracker.THREAD_POOL_NAME);
- private @Nullable Future> trackerJob;
-
- @Activate
- public XmlBindingInfoProvider(final @Reference BindingI18nLocalizationService bindingI18nService,
- final @Reference(target = "(openhab.scope=core.xml.binding)") ConfigDescriptionProvider configDescriptionProvider,
- final @Reference ReadyService readyService) {
- this.bindingI18nService = bindingI18nService;
- this.configDescriptionProvider = (AbstractXmlConfigDescriptionProvider) configDescriptionProvider;
- this.readyService = readyService;
- }
-
- @Activate
- public void activate(ComponentContext componentContext) {
- XmlDocumentReader bindingInfoReader = new BindingInfoReader();
- bindingInfoTracker = new XmlDocumentBundleTracker<>(componentContext.getBundleContext(), XML_DIRECTORY,
- bindingInfoReader, this, READY_MARKER, readyService);
- trackerJob = scheduler.submit(() -> {
- bindingInfoTracker.open();
- });
- }
-
- @Deactivate
- public void deactivate(ComponentContext componentContext) {
- Future> localTrackerJob = trackerJob;
- if (localTrackerJob != null && !localTrackerJob.isDone()) {
- localTrackerJob.cancel(true);
- trackerJob = null;
- }
- XmlDocumentBundleTracker localBindingInfoTracker = bindingInfoTracker;
- if (localBindingInfoTracker != null) {
- localBindingInfoTracker.close();
- bindingInfoTracker = null;
- }
- }
-
- @Override
- public synchronized @Nullable BindingInfo getBindingInfo(@Nullable String id, @Nullable Locale locale) {
- return id == null ? null : get(id, locale);
- }
-
- @Override
- public synchronized Set getBindingInfos(@Nullable Locale locale) {
- return new HashSet<>(getAll(locale));
- }
-
- @Override
- protected @Nullable BindingInfo localize(Bundle bundle, BindingInfo bindingInfo, @Nullable Locale locale) {
- return bindingI18nService.createLocalizedBindingInfo(bundle, bindingInfo, locale);
- }
-
- @Override
- public XmlDocumentProvider createDocumentProvider(Bundle bundle) {
- return new BindingInfoXmlProvider(bundle, this, configDescriptionProvider);
- }
-}
diff --git a/bundles/org.openhab.core.io.rest.core/src/main/java/org/openhab/core/io/rest/core/internal/addons/AddonResource.java b/bundles/org.openhab.core.io.rest.core/src/main/java/org/openhab/core/io/rest/core/internal/addons/AddonResource.java
index 951270796..0b50c7f0f 100644
--- a/bundles/org.openhab.core.io.rest.core/src/main/java/org/openhab/core/io/rest/core/internal/addons/AddonResource.java
+++ b/bundles/org.openhab.core.io.rest.core/src/main/java/org/openhab/core/io/rest/core/internal/addons/AddonResource.java
@@ -12,20 +12,25 @@
*/
package org.openhab.core.io.rest.core.internal.addons;
+import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.text.Collator;
import java.util.Comparator;
+import java.util.List;
import java.util.Locale;
+import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.stream.Stream;
import javax.annotation.security.RolesAllowed;
+import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
@@ -41,10 +46,16 @@ import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.jetty.http.HttpStatus;
import org.openhab.core.addon.Addon;
import org.openhab.core.addon.AddonEventFactory;
+import org.openhab.core.addon.AddonInfo;
+import org.openhab.core.addon.AddonInfoRegistry;
import org.openhab.core.addon.AddonService;
import org.openhab.core.addon.AddonType;
import org.openhab.core.auth.Role;
import org.openhab.core.common.ThreadPoolManager;
+import org.openhab.core.config.core.ConfigDescription;
+import org.openhab.core.config.core.ConfigDescriptionRegistry;
+import org.openhab.core.config.core.ConfigUtil;
+import org.openhab.core.config.core.Configuration;
import org.openhab.core.events.Event;
import org.openhab.core.events.EventPublisher;
import org.openhab.core.io.rest.JSONResponse;
@@ -52,6 +63,7 @@ import org.openhab.core.io.rest.LocaleService;
import org.openhab.core.io.rest.RESTConstants;
import org.openhab.core.io.rest.RESTResource;
import org.openhab.core.io.rest.Stream2JSONInputStream;
+import org.openhab.core.io.rest.core.config.ConfigurationService;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
@@ -105,13 +117,22 @@ public class AddonResource implements RESTResource {
private final Set addonServices = new CopyOnWriteArraySet<>();
private final EventPublisher eventPublisher;
private final LocaleService localeService;
+ private final ConfigurationService configurationService;
+ private final AddonInfoRegistry addonInfoRegistry;
+ private final ConfigDescriptionRegistry configDescriptionRegistry;
private @Context @NonNullByDefault({}) UriInfo uriInfo;
@Activate
- public AddonResource(final @Reference EventPublisher eventPublisher, final @Reference LocaleService localeService) {
+ public AddonResource(final @Reference EventPublisher eventPublisher, final @Reference LocaleService localeService,
+ final @Reference ConfigurationService configurationService,
+ final @Reference AddonInfoRegistry addonInfoRegistry,
+ final @Reference ConfigDescriptionRegistry configDescriptionRegistry) {
this.eventPublisher = eventPublisher;
this.localeService = localeService;
+ this.configurationService = configurationService;
+ this.addonInfoRegistry = addonInfoRegistry;
+ this.configDescriptionRegistry = configDescriptionRegistry;
}
@Reference(cardinality = ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC)
@@ -270,6 +291,80 @@ public class AddonResource implements RESTResource {
return Response.ok(null, MediaType.TEXT_PLAIN).build();
}
+ @GET
+ @Path("/{addonId: [a-zA-Z_0-9-:]+}/config")
+ @Produces({ MediaType.APPLICATION_JSON })
+ @Operation(operationId = "getAddonConfiguration", summary = "Get add-on configuration for given add-on ID.", responses = {
+ @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = String.class))),
+ @ApiResponse(responseCode = "404", description = "Add-on does not exist"),
+ @ApiResponse(responseCode = "500", description = "Configuration can not be read due to internal error") })
+ public Response getConfiguration(final @PathParam("addonId") @Parameter(description = "addon ID") String addonId,
+ @QueryParam("serviceId") @Parameter(description = "service ID") @Nullable String serviceId) {
+ try {
+ AddonInfo addonInfo = addonInfoRegistry.getAddonInfo(addonId);
+ if (addonInfo == null) {
+ return Response.status(Status.NOT_FOUND).build();
+ }
+ Configuration configuration = configurationService.get(addonInfo.getServiceId());
+ return configuration != null ? Response.ok(configuration.getProperties()).build()
+ : Response.ok(Map.of()).build();
+ } catch (IOException e) {
+ logger.error("Cannot get configuration for service {}: {}", addonId, e.getMessage(), e);
+ return Response.status(Status.INTERNAL_SERVER_ERROR).build();
+ }
+ }
+
+ @PUT
+ @Path("/{addonId: [a-zA-Z_0-9-:]+}/config")
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces({ MediaType.APPLICATION_JSON })
+ @Operation(operationId = "updateAddonConfiguration", summary = "Updates an add-on configuration for given ID and returns the old configuration.", responses = {
+ @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = String.class))),
+ @ApiResponse(responseCode = "204", description = "No old configuration"),
+ @ApiResponse(responseCode = "404", description = "Add-on does not exist"),
+ @ApiResponse(responseCode = "500", description = "Configuration can not be updated due to internal error") })
+ public Response updateConfiguration(@PathParam("addonId") @Parameter(description = "Add-on id") String addonId,
+ @QueryParam("serviceId") @Parameter(description = "service ID") @Nullable String serviceId,
+ @Nullable Map configuration) {
+ try {
+ AddonInfo addonInfo = addonInfoRegistry.getAddonInfo(addonId);
+ if (addonInfo == null) {
+ return Response.status(Status.NOT_FOUND).build();
+ }
+ Configuration oldConfiguration = configurationService.get(addonInfo.getServiceId());
+ configurationService.update(addonInfo.getServiceId(),
+ new Configuration(normalizeConfiguration(configuration, addonId)));
+ return oldConfiguration != null ? Response.ok(oldConfiguration.getProperties()).build()
+ : Response.noContent().build();
+ } catch (IOException ex) {
+ logger.error("Cannot update configuration for service {}: {}", addonId, ex.getMessage(), ex);
+ return Response.status(Status.INTERNAL_SERVER_ERROR).build();
+ }
+ }
+
+ private @Nullable Map normalizeConfiguration(@Nullable Map properties,
+ String addonId) {
+ if (properties == null || properties.isEmpty()) {
+ return properties;
+ }
+ AddonInfo addonInfo = addonInfoRegistry.getAddonInfo(addonId);
+
+ if (addonInfo == null || addonInfo.getConfigDescriptionURI() == null) {
+ return properties;
+ }
+
+ String configDescriptionURI = addonInfo.getConfigDescriptionURI();
+ if (configDescriptionURI != null) {
+ ConfigDescription configDesc = configDescriptionRegistry
+ .getConfigDescription(URI.create(configDescriptionURI));
+ if (configDesc != null) {
+ return ConfigUtil.normalizeTypes(properties, List.of(configDesc));
+ }
+ }
+
+ return properties;
+ }
+
private void postFailureEvent(String addonId, @Nullable String msg) {
Event event = AddonEventFactory.createAddonFailureEvent(addonId, msg);
eventPublisher.post(event);
@@ -302,12 +397,7 @@ public class AddonResource implements RESTResource {
private Set getAddonTypesForService(AddonService addonService, Locale locale) {
final Collator coll = Collator.getInstance(locale);
coll.setStrength(Collator.PRIMARY);
- Set ret = new TreeSet<>(new Comparator() {
- @Override
- public int compare(AddonType o1, AddonType o2) {
- return coll.compare(o1.getLabel(), o2.getLabel());
- }
- });
+ Set ret = new TreeSet<>((o1, o2) -> coll.compare(o1.getLabel(), o2.getLabel()));
ret.addAll(addonService.getTypes(locale));
return ret;
}
diff --git a/bundles/org.openhab.core.io.rest.core/src/main/java/org/openhab/core/io/rest/core/internal/binding/BindingResource.java b/bundles/org.openhab.core.io.rest.core/src/main/java/org/openhab/core/io/rest/core/internal/binding/BindingResource.java
deleted file mode 100644
index 449f3877e..000000000
--- a/bundles/org.openhab.core.io.rest.core/src/main/java/org/openhab/core/io/rest/core/internal/binding/BindingResource.java
+++ /dev/null
@@ -1,216 +0,0 @@
-/**
- * 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.io.rest.core.internal.binding;
-
-import java.io.IOException;
-import java.net.URI;
-import java.util.Collections;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Set;
-
-import javax.annotation.security.RolesAllowed;
-import javax.ws.rs.Consumes;
-import javax.ws.rs.GET;
-import javax.ws.rs.HeaderParam;
-import javax.ws.rs.PUT;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.HttpHeaders;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.Response.Status;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.eclipse.jdt.annotation.Nullable;
-import org.openhab.core.auth.Role;
-import org.openhab.core.binding.BindingInfo;
-import org.openhab.core.binding.BindingInfoRegistry;
-import org.openhab.core.binding.dto.BindingInfoDTO;
-import org.openhab.core.config.core.ConfigDescription;
-import org.openhab.core.config.core.ConfigDescriptionRegistry;
-import org.openhab.core.config.core.ConfigUtil;
-import org.openhab.core.config.core.Configuration;
-import org.openhab.core.io.rest.LocaleService;
-import org.openhab.core.io.rest.RESTConstants;
-import org.openhab.core.io.rest.RESTResource;
-import org.openhab.core.io.rest.Stream2JSONInputStream;
-import org.openhab.core.io.rest.core.config.ConfigurationService;
-import org.osgi.service.component.annotations.Activate;
-import org.osgi.service.component.annotations.Component;
-import org.osgi.service.component.annotations.Reference;
-import org.osgi.service.jaxrs.whiteboard.JaxrsWhiteboardConstants;
-import org.osgi.service.jaxrs.whiteboard.propertytypes.JSONRequired;
-import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsApplicationSelect;
-import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsName;
-import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsResource;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.Parameter;
-import io.swagger.v3.oas.annotations.media.ArraySchema;
-import io.swagger.v3.oas.annotations.media.Content;
-import io.swagger.v3.oas.annotations.media.Schema;
-import io.swagger.v3.oas.annotations.responses.ApiResponse;
-import io.swagger.v3.oas.annotations.security.SecurityRequirement;
-import io.swagger.v3.oas.annotations.tags.Tag;
-
-/**
- * This class acts as a REST resource for bindings and is registered with the
- * Jersey servlet.
- *
- * @author Dennis Nobel - Initial contribution
- * @author Kai Kreuzer - refactored for using the OSGi JAX-RS connector
- * @author Yordan Zhelev - Added Swagger annotations
- * @author Franck Dechavanne - Added DTOs to ApiResponses
- * @author Markus Rathgeb - Migrated to JAX-RS Whiteboard Specification
- * @author Wouter Born - Migrated to OpenAPI annotations
- */
-@Component
-@JaxrsResource
-@JaxrsName(BindingResource.PATH_BINDINGS)
-@JaxrsApplicationSelect("(" + JaxrsWhiteboardConstants.JAX_RS_NAME + "=" + RESTConstants.JAX_RS_NAME + ")")
-@JSONRequired
-@Path(BindingResource.PATH_BINDINGS)
-@RolesAllowed({ Role.ADMIN })
-@SecurityRequirement(name = "oauth2", scopes = { "admin" })
-@Tag(name = BindingResource.PATH_BINDINGS)
-@NonNullByDefault
-public class BindingResource implements RESTResource {
-
- /** The URI path to this resource */
- public static final String PATH_BINDINGS = "bindings";
-
- private final Logger logger = LoggerFactory.getLogger(BindingResource.class);
-
- private final BindingInfoRegistry bindingInfoRegistry;
- private final ConfigurationService configurationService;
- private final ConfigDescriptionRegistry configDescRegistry;
- private final LocaleService localeService;
-
- @Activate
- public BindingResource( //
- final @Reference BindingInfoRegistry bindingInfoRegistry,
- final @Reference ConfigurationService configurationService,
- final @Reference ConfigDescriptionRegistry configDescRegistry,
- final @Reference LocaleService localeService) {
- this.bindingInfoRegistry = bindingInfoRegistry;
- this.configurationService = configurationService;
- this.configDescRegistry = configDescRegistry;
- this.localeService = localeService;
- }
-
- @GET
- @Produces(MediaType.APPLICATION_JSON)
- @Operation(operationId = "getBindings", summary = "Get all bindings.", responses = {
- @ApiResponse(responseCode = "200", description = "OK", content = @Content(array = @ArraySchema(schema = @Schema(implementation = BindingInfoDTO.class), uniqueItems = true))) })
- public Response getAll(
- @HeaderParam(HttpHeaders.ACCEPT_LANGUAGE) @Parameter(description = "language") @Nullable String language) {
- final Locale locale = localeService.getLocale(language);
- Set bindingInfos = bindingInfoRegistry.getBindingInfos(locale);
-
- return Response.ok(new Stream2JSONInputStream(bindingInfos.stream().map(b -> map(b, locale)))).build();
- }
-
- @GET
- @Path("/{bindingId}/config")
- @Produces({ MediaType.APPLICATION_JSON })
- @Operation(operationId = "getBindingConfiguration", summary = "Get binding configuration for given binding ID.", responses = {
- @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = String.class))),
- @ApiResponse(responseCode = "404", description = "Binding does not exist"),
- @ApiResponse(responseCode = "500", description = "Configuration can not be read due to internal error") })
- public Response getConfiguration(@PathParam("bindingId") @Parameter(description = "service ID") String bindingId) {
- try {
- String configId = getConfigId(bindingId);
- if (configId == null) {
- logger.warn("Cannot get config id for binding id '{}', probably because binding does not exist.",
- bindingId);
- return Response.status(404).build();
- }
- Configuration configuration = configurationService.get(configId);
- return configuration != null ? Response.ok(configuration.getProperties()).build()
- : Response.ok(Collections.emptyMap()).build();
- } catch (IOException ex) {
- logger.error("Cannot get configuration for service {}: {}", bindingId, ex.getMessage(), ex);
- return Response.status(Status.INTERNAL_SERVER_ERROR).build();
- }
- }
-
- @PUT
- @Path("/{bindingId}/config")
- @Consumes(MediaType.APPLICATION_JSON)
- @Produces({ MediaType.APPLICATION_JSON })
- @Operation(operationId = "updateBindingConfiguration", summary = "Updates a binding configuration for given binding ID and returns the old configuration.", responses = {
- @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = String.class))),
- @ApiResponse(responseCode = "204", description = "No old configuration"),
- @ApiResponse(responseCode = "404", description = "Binding does not exist"),
- @ApiResponse(responseCode = "500", description = "Configuration can not be updated due to internal error") })
- public Response updateConfiguration(@PathParam("bindingId") @Parameter(description = "service ID") String bindingId,
- @Nullable Map configuration) {
- try {
- String configId = getConfigId(bindingId);
- if (configId == null) {
- logger.warn("Cannot get config id for binding id '{}', probably because binding does not exist.",
- bindingId);
- return Response.status(404).build();
- }
- Configuration oldConfiguration = configurationService.get(configId);
- configurationService.update(configId, new Configuration(normalizeConfiguration(configuration, bindingId)));
- return oldConfiguration != null ? Response.ok(oldConfiguration.getProperties()).build()
- : Response.noContent().build();
- } catch (IOException ex) {
- logger.error("Cannot update configuration for service {}: {}", bindingId, ex.getMessage(), ex);
- return Response.status(Status.INTERNAL_SERVER_ERROR).build();
- }
- }
-
- private @Nullable Map normalizeConfiguration(@Nullable Map properties,
- String bindingId) {
- if (properties == null || properties.isEmpty()) {
- return properties;
- }
-
- BindingInfo bindingInfo = this.bindingInfoRegistry.getBindingInfo(bindingId);
- if (bindingInfo == null || bindingInfo.getConfigDescriptionURI() == null) {
- return properties;
- }
-
- URI descURI = bindingInfo.getConfigDescriptionURI();
- if (descURI != null) {
- ConfigDescription configDesc = configDescRegistry.getConfigDescription(descURI);
- if (configDesc != null) {
- return ConfigUtil.normalizeTypes(properties, List.of(configDesc));
- }
- }
-
- return properties;
- }
-
- private @Nullable String getConfigId(String bindingId) {
- BindingInfo bindingInfo = this.bindingInfoRegistry.getBindingInfo(bindingId);
- if (bindingInfo != null) {
- return bindingInfo.getServiceId();
- } else {
- return null;
- }
- }
-
- private BindingInfoDTO map(BindingInfo bindingInfo, Locale locale) {
- URI configDescriptionURI = bindingInfo.getConfigDescriptionURI();
- return new BindingInfoDTO(bindingInfo.getUID(), bindingInfo.getName(), bindingInfo.getAuthor(),
- bindingInfo.getDescription(), configDescriptionURI != null ? configDescriptionURI.toString() : null);
- }
-}
diff --git a/bundles/org.openhab.core.karaf/src/main/java/org/openhab/core/karaf/internal/FeatureInstaller.java b/bundles/org.openhab.core.karaf/src/main/java/org/openhab/core/karaf/internal/FeatureInstaller.java
index baac35eaa..a6fc3b7b2 100644
--- a/bundles/org.openhab.core.karaf/src/main/java/org/openhab/core/karaf/internal/FeatureInstaller.java
+++ b/bundles/org.openhab.core.karaf/src/main/java/org/openhab/core/karaf/internal/FeatureInstaller.java
@@ -88,17 +88,14 @@ public class FeatureInstaller implements ConfigurationListener {
public static final String EXTENSION_TYPE_TRANSFORMATION = "transformation";
public static final String EXTENSION_TYPE_UI = "ui";
public static final String EXTENSION_TYPE_VOICE = "voice";
- public static final List EXTENSION_TYPES = List.of(EXTENSION_TYPE_AUTOMATION, EXTENSION_TYPE_BINDING,
+ public static final Set EXTENSION_TYPES = Set.of(EXTENSION_TYPE_AUTOMATION, EXTENSION_TYPE_BINDING,
EXTENSION_TYPE_MISC, EXTENSION_TYPE_PERSISTENCE, EXTENSION_TYPE_TRANSFORMATION, EXTENSION_TYPE_UI,
EXTENSION_TYPE_VOICE);
public static final String PREFIX = "openhab-";
public static final String PREFIX_PACKAGE = "package-";
- public static final String SIMPLE_PACKAGE = "simple";
public static final String MINIMAL_PACKAGE = "minimal";
- public static final String STANDARD_PACKAGE = "standard";
-
private static final String CFG_REMOTE = "remote";
private static final String PAX_URL_PID = "org.ops4j.pax.url.mvn";
private static final String ADDONS_PID = "org.openhab.addons";
@@ -121,8 +118,6 @@ public class FeatureInstaller implements ConfigurationListener {
// configuration as this must be waited for before trying to add feature repos
private @Nullable Map configMapCache;
- private @Nullable String currentPackage = null;
-
@Activate
public FeatureInstaller(final @Reference ConfigurationAdmin configurationAdmin,
final @Reference FeaturesService featuresService, final @Reference KarService karService,
@@ -226,11 +221,6 @@ public class FeatureInstaller implements ConfigurationListener {
}
}
- @Nullable
- String getCurrentPackage() {
- return currentPackage;
- }
-
public void addAddon(String type, String id) {
try {
changeAddonConfig(type, id, Collection::add);
@@ -267,10 +257,11 @@ public class FeatureInstaller implements ConfigurationListener {
Dictionary felixProperties = configurations[0].getProperties();
String addonsDirectory = (String) felixProperties.get("felix.fileinstall.dir");
if (addonsDirectory != null) {
- return Files.list(Path.of(addonsDirectory)).map(Path::getFileName).map(Path::toString)
- .filter(file -> file.endsWith(".kar"))
- .map(karFileName -> karFileName.substring(0, karFileName.lastIndexOf(".")))
- .allMatch(karRepos::contains);
+ try (Stream files = Files.list(Path.of(addonsDirectory))) {
+ return files.map(Path::getFileName).map(Path::toString).filter(file -> file.endsWith(".kar"))
+ .map(karFileName -> karFileName.substring(0, karFileName.lastIndexOf(".")))
+ .allMatch(karRepos::contains);
+ }
}
}
} catch (Exception ignored) {
@@ -399,11 +390,11 @@ public class FeatureInstaller implements ConfigurationListener {
for (String type : EXTENSION_TYPES) {
Object configValue = config.get(type);
- if (configValue instanceof String) {
+ if (configValue instanceof String addonString) {
try {
Feature[] features = featuresService.listInstalledFeatures();
String typePrefix = PREFIX + type + "-";
- Set configFeatureNames = Arrays.stream(((String) configValue).split(",")) //
+ Set configFeatureNames = Arrays.stream(addonString.split(",")) //
.map(String::strip) //
.filter(not(String::isEmpty)) //
.map(addon -> typePrefix + addon) //
@@ -531,9 +522,8 @@ public class FeatureInstaller implements ConfigurationListener {
private boolean installPackage(final Map config) {
boolean configChanged = false;
Object packageName = config.get(OpenHAB.CFG_PACKAGE);
- if (packageName instanceof String) {
- currentPackage = (String) packageName;
- String fullName = PREFIX + PREFIX_PACKAGE + ((String) packageName).strip();
+ if (packageName instanceof String currentPackage) {
+ String fullName = PREFIX + PREFIX_PACKAGE + currentPackage.strip();
if (!MINIMAL_PACKAGE.equals(currentPackage)) {
configChanged = installFeature(fullName);
}
diff --git a/bundles/org.openhab.core.karaf/src/main/java/org/openhab/core/karaf/internal/KarafAddonService.java b/bundles/org.openhab.core.karaf/src/main/java/org/openhab/core/karaf/internal/KarafAddonService.java
index ad04d5024..a0b495559 100644
--- a/bundles/org.openhab.core.karaf/src/main/java/org/openhab/core/karaf/internal/KarafAddonService.java
+++ b/bundles/org.openhab.core.karaf/src/main/java/org/openhab/core/karaf/internal/KarafAddonService.java
@@ -13,20 +13,20 @@
package org.openhab.core.karaf.internal;
import java.net.URI;
-import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Locale;
-import java.util.stream.Collectors;
import org.apache.karaf.features.Feature;
import org.apache.karaf.features.FeaturesService;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.addon.Addon;
+import org.openhab.core.addon.AddonInfo;
+import org.openhab.core.addon.AddonInfoRegistry;
import org.openhab.core.addon.AddonService;
import org.openhab.core.addon.AddonType;
-import org.openhab.core.binding.BindingInfo;
-import org.openhab.core.binding.BindingInfoRegistry;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
@@ -40,34 +40,32 @@ import org.slf4j.LoggerFactory;
* @author Kai Kreuzer - Initial contribution
*/
@Component(name = "org.openhab.core.karafaddons")
+@NonNullByDefault
public class KarafAddonService implements AddonService {
- private static final String ADDONS_CONTENTTYPE = "application/vnd.openhab.feature;type=karaf";
+ private static final String ADDONS_CONTENT_TYPE = "application/vnd.openhab.feature;type=karaf";
private static final String ADDONS_AUTHOR = "openHAB";
+ private static final List ADDON_TYPES = List.of( //
+ new AddonType(FeatureInstaller.EXTENSION_TYPE_AUTOMATION, "Automation"), //
+ new AddonType(FeatureInstaller.EXTENSION_TYPE_BINDING, "Bindings"), //
+ new AddonType(FeatureInstaller.EXTENSION_TYPE_MISC, "Misc"), //
+ new AddonType(FeatureInstaller.EXTENSION_TYPE_VOICE, "Voice"), //
+ new AddonType(FeatureInstaller.EXTENSION_TYPE_PERSISTENCE, "Persistence"), //
+ new AddonType(FeatureInstaller.EXTENSION_TYPE_TRANSFORMATION, "Transformations"), //
+ new AddonType(FeatureInstaller.EXTENSION_TYPE_UI, "User Interfaces"));
private final Logger logger = LoggerFactory.getLogger(KarafAddonService.class);
- private final List typeList = new ArrayList<>(FeatureInstaller.EXTENSION_TYPES.size());
-
private final FeaturesService featuresService;
private final FeatureInstaller featureInstaller;
- private final BindingInfoRegistry bindingInfoRegistry;
+
+ private final AddonInfoRegistry addonInfoRegistry;
@Activate
public KarafAddonService(final @Reference FeatureInstaller featureInstaller,
- final @Reference FeaturesService featuresService,
- final @Reference BindingInfoRegistry bindingInfoRegistry) {
+ final @Reference FeaturesService featuresService, @Reference AddonInfoRegistry addonInfoRegistry) {
this.featureInstaller = featureInstaller;
this.featuresService = featuresService;
- this.bindingInfoRegistry = bindingInfoRegistry;
- typeList.add(new AddonType(FeatureInstaller.EXTENSION_TYPE_AUTOMATION, "Automation"));
- typeList.add(new AddonType(FeatureInstaller.EXTENSION_TYPE_BINDING, "Bindings"));
- typeList.add(new AddonType(FeatureInstaller.EXTENSION_TYPE_MISC, "Misc"));
- typeList.add(new AddonType(FeatureInstaller.EXTENSION_TYPE_VOICE, "Voice"));
- if (!FeatureInstaller.SIMPLE_PACKAGE.equals(featureInstaller.getCurrentPackage())) {
- typeList.add(new AddonType(FeatureInstaller.EXTENSION_TYPE_PERSISTENCE, "Persistence"));
- typeList.add(new AddonType(FeatureInstaller.EXTENSION_TYPE_TRANSFORMATION, "Transformations"));
- typeList.add(new AddonType(FeatureInstaller.EXTENSION_TYPE_UI, "User Interfaces"));
- }
+ this.addonInfoRegistry = addonInfoRegistry;
}
@Override
@@ -85,10 +83,10 @@ public class KarafAddonService implements AddonService {
}
@Override
- public List getAddons(Locale locale) {
+ public List getAddons(@Nullable Locale locale) {
try {
return Arrays.stream(featuresService.listFeatures()).filter(this::isAddon).map(this::getAddon)
- .sorted(Comparator.comparing(Addon::getLabel)).collect(Collectors.toList());
+ .sorted(Comparator.comparing(Addon::getLabel)).toList();
} catch (Exception e) {
logger.error("Exception while retrieving features: {}", e.getMessage());
return List.of();
@@ -101,7 +99,7 @@ public class KarafAddonService implements AddonService {
}
@Override
- public Addon getAddon(String id, Locale locale) {
+ public @Nullable Addon getAddon(String id, @Nullable Locale locale) {
Feature feature;
try {
feature = featuresService.getFeature(FeatureInstaller.PREFIX + id);
@@ -112,62 +110,46 @@ public class KarafAddonService implements AddonService {
}
}
+ private @Nullable String getDefaultDocumentationLink(String type, String name) {
+ return switch (type) {
+ case FeatureInstaller.EXTENSION_TYPE_AUTOMATION -> "https://www.openhab.org/addons/automation/" + name
+ + "/";
+ case FeatureInstaller.EXTENSION_TYPE_BINDING -> "https://www.openhab.org/addons/bindings/" + name + "/";
+ case FeatureInstaller.EXTENSION_TYPE_PERSISTENCE -> "https://www.openhab.org/addons/persistence/" + name
+ + "/";
+ case FeatureInstaller.EXTENSION_TYPE_TRANSFORMATION -> "https://www.openhab.org/addons/transformations/"
+ + name + "/";
+ case FeatureInstaller.EXTENSION_TYPE_VOICE -> "https://www.openhab.org/addons/voice/" + name + "/";
+ default -> null;
+ };
+ }
+
private Addon getAddon(Feature feature) {
String name = getName(feature.getName());
String type = getType(feature.getName());
- String link = null;
- String configDescriptionURI = "";
- switch (type) {
- case FeatureInstaller.EXTENSION_TYPE_AUTOMATION:
- link = "https://www.openhab.org/addons/automation/" + name + "/";
- break;
- case FeatureInstaller.EXTENSION_TYPE_BINDING:
- link = "https://www.openhab.org/addons/bindings/" + name + "/";
- BindingInfo bindingInfo = bindingInfoRegistry.getBindingInfo(name);
- if (bindingInfo != null) {
- URI uri = bindingInfo.getConfigDescriptionURI();
- if (uri != null) {
- configDescriptionURI = uri.toString();
- }
- }
- break;
- case FeatureInstaller.EXTENSION_TYPE_MISC:
- // Not possible to define URL
- break;
- case FeatureInstaller.EXTENSION_TYPE_PERSISTENCE:
- link = "https://www.openhab.org/addons/persistence/" + name + "/";
- break;
- case FeatureInstaller.EXTENSION_TYPE_TRANSFORMATION:
- link = "https://www.openhab.org/addons/transformations/" + name + "/";
- break;
- case FeatureInstaller.EXTENSION_TYPE_UI:
- // Not possible to define URL
- break;
- case FeatureInstaller.EXTENSION_TYPE_VOICE:
- link = "https://www.openhab.org/addons/voice/" + name + "/";
- break;
- default:
- break;
+ String id = type + Addon.ADDON_SEPARATOR + name;
+ boolean isInstalled = featuresService.isInstalled(feature);
+
+ Addon.Builder addon = Addon.create(id).withContentType(ADDONS_CONTENT_TYPE).withType(type)
+ .withVersion(feature.getVersion()).withAuthor(ADDONS_AUTHOR, true).withInstalled(isInstalled);
+
+ AddonInfo addonInfo = addonInfoRegistry.getAddonInfo(id);
+
+ if (isInstalled && addonInfo != null) {
+ // only enrich if this add-on is installed, otherwise wrong data might be added
+ addon = addon.withLabel(addonInfo.getName()).withDescription(addonInfo.getDescription())
+ .withCountries(addonInfo.getCountries()).withLink(getDefaultDocumentationLink(type, name))
+ .withConfigDescriptionURI(addonInfo.getConfigDescriptionURI());
+ } else {
+ addon = addon.withLabel(feature.getDescription()).withLink(getDefaultDocumentationLink(type, name));
}
- // for openHAB add-on bundles the package is the same as the bundle name
- List packages = feature.getBundles().stream().filter(bundle -> !bundle.isDependency()).map(bundle -> {
- String location = bundle.getLocation();
- location = location.substring(0, location.lastIndexOf("/")); // strip version
- location = location.substring(location.lastIndexOf("/") + 1); // strip groupId and protocol
- return location;
- }).collect(Collectors.toList());
-
- return Addon.create(type + "-" + name).withType(type).withLabel(feature.getDescription())
- .withVersion(feature.getVersion()).withContentType(ADDONS_CONTENTTYPE).withLink(link)
- .withLoggerPackages(packages).withAuthor(ADDONS_AUTHOR, true)
- .withConfigDescriptionURI(configDescriptionURI).withInstalled(featuresService.isInstalled(feature))
- .build();
+ return addon.build();
}
@Override
- public List getTypes(Locale locale) {
- return typeList;
+ public List getTypes(@Nullable Locale locale) {
+ return ADDON_TYPES;
}
@Override
@@ -181,29 +163,19 @@ public class KarafAddonService implements AddonService {
}
@Override
- public String getAddonId(URI addonURI) {
+ public @Nullable String getAddonId(URI addonURI) {
return null;
}
- private String substringAfter(String str, String separator) {
- int index = str.indexOf(separator);
- return index == -1 ? "" : str.substring(index + separator.length());
- }
-
- private String substringBefore(String str, String separator) {
- int index = str.indexOf(separator);
+ private String getType(String name) {
+ String str = name.startsWith(FeatureInstaller.PREFIX) ? name.substring(FeatureInstaller.PREFIX.length()) : name;
+ int index = str.indexOf(Addon.ADDON_SEPARATOR);
return index == -1 ? str : str.substring(0, index);
}
- private String getType(String name) {
- return substringBefore(
- name.startsWith(FeatureInstaller.PREFIX) ? name.substring(FeatureInstaller.PREFIX.length()) : name,
- "-");
- }
-
private String getName(String name) {
- return substringAfter(
- name.startsWith(FeatureInstaller.PREFIX) ? name.substring(FeatureInstaller.PREFIX.length()) : name,
- "-");
+ String str = name.startsWith(FeatureInstaller.PREFIX) ? name.substring(FeatureInstaller.PREFIX.length()) : name;
+ int index = str.indexOf(Addon.ADDON_SEPARATOR);
+ return index == -1 ? "" : str.substring(index + Addon.ADDON_SEPARATOR.length());
}
}
diff --git a/bundles/org.openhab.core.test.magic/src/main/resources/OH-INF/addon/addon.xml b/bundles/org.openhab.core.test.magic/src/main/resources/OH-INF/addon/addon.xml
new file mode 100644
index 000000000..b6e8268cf
--- /dev/null
+++ b/bundles/org.openhab.core.test.magic/src/main/resources/OH-INF/addon/addon.xml
@@ -0,0 +1,10 @@
+
+
+
+ binding
+ Magic Binding
+ This is the Magic binding for openHAB.
+
+
diff --git a/bundles/org.openhab.core.test.magic/src/main/resources/OH-INF/binding/binding.xml b/bundles/org.openhab.core.test.magic/src/main/resources/OH-INF/binding/binding.xml
deleted file mode 100644
index 209d57a6e..000000000
--- a/bundles/org.openhab.core.test.magic/src/main/resources/OH-INF/binding/binding.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
- Magic Binding
- This is the Magic binding for openHAB.
-
-
diff --git a/bundles/org.openhab.core/src/main/java/org/openhab/core/addon/Addon.java b/bundles/org.openhab.core/src/main/java/org/openhab/core/addon/Addon.java
index 7c29ee403..b6158f681 100644
--- a/bundles/org.openhab.core/src/main/java/org/openhab/core/addon/Addon.java
+++ b/bundles/org.openhab.core/src/main/java/org/openhab/core/addon/Addon.java
@@ -27,12 +27,13 @@ import org.eclipse.jdt.annotation.Nullable;
*/
public class Addon {
public static final Set CODE_MATURITY_LEVELS = Set.of("alpha", "beta", "mature", "stable");
+ public static final String ADDON_SEPARATOR = "-";
private final String id;
private final String label;
private final String version;
private final @Nullable String maturity;
- private boolean compatible;
+ private final boolean compatible;
private final String contentType;
private final @Nullable String link;
private final String author;
@@ -43,7 +44,7 @@ public class Addon {
private final @Nullable String detailedDescription;
private final String configDescriptionURI;
private final String keywords;
- private final String countries;
+ private final List countries;
private final @Nullable String license;
private final String connection;
private final @Nullable String backgroundColor;
@@ -69,7 +70,7 @@ public class Addon {
* @param detailedDescription the detailed description of the add-on (may be null)
* @param configDescriptionURI the URI to the configuration description for this add-on
* @param keywords the keywords for this add-on
- * @param countries a comma-separated list of ISO 3166 codes relevant to this add-on
+ * @param countries a list of ISO 3166 codes relevant to this add-on
* @param license the SPDX license identifier
* @param connection a string describing the type of connection (local or cloud, push or pull...) this add-on uses,
* if applicable.
@@ -81,7 +82,7 @@ public class Addon {
private Addon(String id, String type, String label, String version, @Nullable String maturity, boolean compatible,
String contentType, @Nullable String link, String author, boolean verifiedAuthor, boolean installed,
@Nullable String description, @Nullable String detailedDescription, String configDescriptionURI,
- String keywords, String countries, @Nullable String license, String connection,
+ String keywords, List countries, @Nullable String license, String connection,
@Nullable String backgroundColor, @Nullable String imageLink, @Nullable Map properties,
List loggerPackages) {
this.id = id;
@@ -122,6 +123,10 @@ public class Addon {
return id;
}
+ public String getUID() {
+ return type + ADDON_SEPARATOR + id;
+ }
+
/**
* The label of the add-on
*/
@@ -207,9 +212,9 @@ public class Addon {
}
/**
- * A comma-separated list of ISO 3166 codes relevant to this add-on
+ * A list of ISO 3166 codes relevant to this add-on
*/
- public String getCountries() {
+ public List getCountries() {
return countries;
}
@@ -221,7 +226,7 @@ public class Addon {
}
/**
- * A string describing the type of connection (local or cloud, push or pull...) this add-on uses, if applicable.
+ * A string describing the type of connection (local, cloud, cloudDiscovery) this add-on uses, if applicable.
*/
public String getConnection() {
return connection;
@@ -289,7 +294,7 @@ public class Addon {
private @Nullable String detailedDescription;
private String configDescriptionURI = "";
private String keywords = "";
- private String countries = "";
+ private List countries = List.of();
private @Nullable String license;
private String connection = "";
private @Nullable String backgroundColor;
@@ -372,7 +377,7 @@ public class Addon {
return this;
}
- public Builder withCountries(String countries) {
+ public Builder withCountries(List countries) {
this.countries = countries;
return this;
}
diff --git a/bundles/org.openhab.core/src/main/java/org/openhab/core/addon/AddonI18nLocalizationService.java b/bundles/org.openhab.core/src/main/java/org/openhab/core/addon/AddonI18nLocalizationService.java
new file mode 100644
index 000000000..6f3d8f27d
--- /dev/null
+++ b/bundles/org.openhab.core/src/main/java/org/openhab/core/addon/AddonI18nLocalizationService.java
@@ -0,0 +1,58 @@
+/**
+ * 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.addon;
+
+import java.util.Locale;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.openhab.core.i18n.TranslationProvider;
+import org.openhab.core.internal.addon.AddonI18nUtil;
+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 add-on info using the I18N mechanism of the openHAB
+ * framework.
+ *
+ * @author Christoph Weitkamp - Initial contribution
+ */
+@Component(immediate = true, service = { AddonI18nLocalizationService.class })
+@NonNullByDefault
+public class AddonI18nLocalizationService {
+
+ private final AddonI18nUtil addonI18NUtil;
+
+ @Activate
+ public AddonI18nLocalizationService(final @Reference TranslationProvider i18nProvider) {
+ this.addonI18NUtil = new AddonI18nUtil(i18nProvider);
+ }
+
+ /**
+ * Localizes an add-on info.
+ *
+ * @param bundle the bundle the i18n resources are located
+ * @param addonInfo the add-on info that should be localized
+ * @param locale the locale it should be localized to
+ * @return a localized add-on info on success, a non-localized one on error (e.g. no translation is found).
+ */
+ public AddonInfo createLocalizedAddonInfo(Bundle bundle, AddonInfo addonInfo, @Nullable Locale locale) {
+ String addonInfoUID = addonInfo.getId();
+ String name = addonI18NUtil.getName(bundle, addonInfoUID, addonInfo.getName(), locale);
+ String description = addonI18NUtil.getDescription(bundle, addonInfoUID, addonInfo.getDescription(), locale);
+
+ return AddonInfo.builder(addonInfo).withName(name).withDescription(description).build();
+ }
+}
diff --git a/bundles/org.openhab.core/src/main/java/org/openhab/core/addon/AddonInfo.java b/bundles/org.openhab.core/src/main/java/org/openhab/core/addon/AddonInfo.java
new file mode 100644
index 000000000..c12b29ede
--- /dev/null
+++ b/bundles/org.openhab.core/src/main/java/org/openhab/core/addon/AddonInfo.java
@@ -0,0 +1,234 @@
+/**
+ * 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.addon;
+
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.openhab.core.common.registry.Identifiable;
+
+/**
+ * The {@link AddonInfo} class contains general information about an add-on.
+ *
+ * Any add-on information is provided by a {@link AddonInfoProvider} and can also be retrieved through the
+ * {@link AddonInfoRegistry}.
+ *
+ * @author Michael Grammling - Initial contribution
+ * @author Andre Fuechsel - Made author tag optional
+ * @author Jan N. Klug - Refactored to cover all add-ons
+ */
+@NonNullByDefault
+public class AddonInfo implements Identifiable {
+ private static final Set SUPPORTED_ADDON_TYPES = Set.of("automation", "binding", "misc", "persistence",
+ "transformation", "ui", "voice");
+
+ private final String id;
+ private final String type;
+ private final String name;
+ private final String description;
+ private final @Nullable String author;
+ private final @Nullable String connection;
+ private final List countries;
+ private final @Nullable String configDescriptionURI;
+ private final String serviceId;
+
+ private AddonInfo(String id, String type, String name, String description, @Nullable String author,
+ @Nullable String connection, List countries, @Nullable String configDescriptionURI,
+ @Nullable String serviceId) throws IllegalArgumentException {
+ // mandatory fields
+ if (id.isBlank()) {
+ throw new IllegalArgumentException("The ID must neither be null nor empty!");
+ }
+ if (!SUPPORTED_ADDON_TYPES.contains(type)) {
+ throw new IllegalArgumentException(
+ "The type must be one of [" + String.join(", ", SUPPORTED_ADDON_TYPES) + "]");
+ }
+ if (name.isBlank()) {
+ throw new IllegalArgumentException("The name must neither be null nor empty!");
+ }
+ if (description.isBlank()) {
+ throw new IllegalArgumentException("The description must neither be null nor empty!");
+ }
+ this.id = id;
+ this.type = type;
+ this.name = name;
+ this.description = description;
+
+ // optional fields
+ this.author = author;
+ this.connection = connection;
+ this.countries = countries;
+ this.configDescriptionURI = configDescriptionURI;
+ this.serviceId = Objects.requireNonNullElse(serviceId, type + "." + id);
+ }
+
+ /**
+ * Returns an unique identifier for the add-on (e.g. "binding-hue").
+ *
+ * @return an identifier for the add-on
+ */
+ @Override
+ public String getUID() {
+ return type + Addon.ADDON_SEPARATOR + id;
+ }
+
+ /**
+ * Returns the id part of the UID
+ *
+ * @return the identifier
+ */
+ public String getId() {
+ return id;
+ }
+
+ /**
+ * Returns a human-readable name for the add-on (e.g. "HUE Binding").
+ *
+ * @return a human-readable name for the add-on (neither null, nor empty)
+ */
+ public String getName() {
+ return name;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public String getServiceId() {
+ return serviceId;
+ }
+
+ /**
+ * Returns a human-readable description for the add-on
+ * (e.g. "Discovers and controls HUE bulbs").
+ *
+ * @return a human-readable description for the add-on
+ */
+ public String getDescription() {
+ return description;
+ }
+
+ /**
+ * Returns the author of the add-on (e.g. "Max Mustermann").
+ *
+ * @return the author of the add-on (could be null or empty)
+ */
+ public @Nullable String getAuthor() {
+ return author;
+ }
+
+ /**
+ * Returns the link to a concrete {@link org.openhab.core.config.core.ConfigDescription}.
+ *
+ * @return the link to a concrete ConfigDescription (could be null
>)
+ */
+ public @Nullable String getConfigDescriptionURI() {
+ return configDescriptionURI;
+ }
+
+ public List getCountries() {
+ return countries;
+ }
+
+ public static Builder builder(String id, String type) {
+ return new Builder(id, type);
+ }
+
+ public static Builder builder(AddonInfo addonInfo) {
+ return new Builder(addonInfo);
+ }
+
+ public static class Builder {
+
+ private final String id;
+ private final String type;
+ private String name = "";
+ private String description = "";
+ private @Nullable String author;
+ private @Nullable String connection;
+ private List countries = List.of();
+ private @Nullable String configDescriptionURI = "";
+ private @Nullable String serviceId;
+
+ private Builder(String id, String type) {
+ this.id = id;
+ this.type = type;
+ }
+
+ private Builder(AddonInfo addonInfo) {
+ this.id = addonInfo.id;
+ this.type = addonInfo.type;
+ this.name = addonInfo.name;
+ this.description = addonInfo.description;
+ this.author = addonInfo.author;
+ this.connection = addonInfo.connection;
+ this.countries = addonInfo.countries;
+ this.configDescriptionURI = addonInfo.configDescriptionURI;
+ this.serviceId = addonInfo.serviceId;
+ }
+
+ public Builder withName(String name) {
+ this.name = name;
+ return this;
+ }
+
+ public Builder withDescription(String description) {
+ this.description = description;
+ return this;
+ }
+
+ public Builder withAuthor(@Nullable String author) {
+ this.author = author;
+ return this;
+ }
+
+ public Builder withConnection(@Nullable String connection) {
+ this.connection = connection;
+ return this;
+ }
+
+ public Builder withCountries(@Nullable String countries) {
+ this.countries = List.of(Objects.requireNonNull(countries, "").split(","));
+ return this;
+ }
+
+ public Builder withCountries(List countries) {
+ this.countries = countries;
+ return this;
+ }
+
+ public Builder withConfigDescriptionURI(@Nullable String configDescriptionURI) {
+ this.configDescriptionURI = configDescriptionURI;
+ return this;
+ }
+
+ public Builder withServiceId(@Nullable String serviceId) {
+ this.serviceId = serviceId;
+ return this;
+ }
+
+ /**
+ * Build an {@link AddonInfo} from this builder
+ *
+ * @return the add-on info object
+ * @throws IllegalArgumentException if any of the information in this builder is invalid
+ */
+ public AddonInfo build() throws IllegalArgumentException {
+ return new AddonInfo(id, type, name, description, author, connection, countries, configDescriptionURI,
+ serviceId);
+ }
+ }
+}
diff --git a/bundles/org.openhab.core/src/main/java/org/openhab/core/binding/BindingInfoProvider.java b/bundles/org.openhab.core/src/main/java/org/openhab/core/addon/AddonInfoProvider.java
similarity index 74%
rename from bundles/org.openhab.core/src/main/java/org/openhab/core/binding/BindingInfoProvider.java
rename to bundles/org.openhab.core/src/main/java/org/openhab/core/addon/AddonInfoProvider.java
index 15c973a80..edd8b0958 100644
--- a/bundles/org.openhab.core/src/main/java/org/openhab/core/binding/BindingInfoProvider.java
+++ b/bundles/org.openhab.core/src/main/java/org/openhab/core/addon/AddonInfoProvider.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.core.binding;
+package org.openhab.core.addon;
import java.util.Locale;
import java.util.Set;
@@ -19,16 +19,16 @@ 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
- * {@link BindingInfoProvider} services are tracked by the {@link BindingInfoRegistry} and provided as one common
+ * The {@link AddonInfoProvider} is a service interface providing {@link AddonInfo} objects. All registered
+ * {@link AddonInfoProvider} services are tracked by the {@link AddonInfoRegistry} and provided as one common
* collection.
*
* @author Michael Grammling - Initial contribution
*
- * @see BindingInfoRegistry
+ * @see AddonInfoRegistry
*/
@NonNullByDefault
-public interface BindingInfoProvider {
+public interface AddonInfoProvider {
/**
* Returns the binding information for the specified binding ID and locale (language),
@@ -39,7 +39,7 @@ public interface BindingInfoProvider {
* @return a localized binding information object (could be null)
*/
@Nullable
- BindingInfo getBindingInfo(@Nullable String id, @Nullable Locale locale);
+ AddonInfo getAddonInfo(@Nullable String id, @Nullable Locale locale);
/**
* Returns all binding information in the specified locale (language) this provider contains.
@@ -48,5 +48,5 @@ public interface BindingInfoProvider {
* @return a localized set of all binding information this provider contains
* (could be empty)
*/
- Set getBindingInfos(@Nullable Locale locale);
+ Set getAddonInfos(@Nullable Locale locale);
}
diff --git a/bundles/org.openhab.core/src/main/java/org/openhab/core/addon/AddonInfoRegistry.java b/bundles/org.openhab.core/src/main/java/org/openhab/core/addon/AddonInfoRegistry.java
new file mode 100644
index 000000000..678c329ca
--- /dev/null
+++ b/bundles/org.openhab.core/src/main/java/org/openhab/core/addon/AddonInfoRegistry.java
@@ -0,0 +1,95 @@
+/**
+ * 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.addon;
+
+import java.util.Collection;
+import java.util.Locale;
+import java.util.Objects;
+import java.util.Set;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.stream.Collectors;
+
+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.Reference;
+import org.osgi.service.component.annotations.ReferenceCardinality;
+import org.osgi.service.component.annotations.ReferencePolicy;
+
+/**
+ * The {@link AddonInfoRegistry} provides access to {@link AddonInfo} objects.
+ * It tracks {@link AddonInfoProvider} OSGi services to collect all {@link AddonInfo} objects.
+ *
+ * @author Dennis Nobel - Initial contribution
+ * @author Michael Grammling - Initial contribution, added locale support
+ */
+@Component(immediate = true, service = AddonInfoRegistry.class)
+@NonNullByDefault
+public class AddonInfoRegistry {
+
+ private final Collection addonInfoProviders = new CopyOnWriteArrayList<>();
+
+ @Reference(cardinality = ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC)
+ protected void addAddonInfoProvider(AddonInfoProvider addonInfoProvider) {
+ addonInfoProviders.add(addonInfoProvider);
+ }
+
+ protected void removeAddonInfoProvider(AddonInfoProvider addonInfoProvider) {
+ addonInfoProviders.remove(addonInfoProvider);
+ }
+
+ /**
+ * Returns the add-on information for the specified add-on ID, or {@code null} if no add-on information could be
+ * found.
+ *
+ * @param id the ID to be looked
+ * @return a add-on information object (could be null)
+ */
+ public @Nullable AddonInfo getAddonInfo(String id) {
+ return getAddonInfo(id, null);
+ }
+
+ /**
+ * Returns the add-on information for the specified add-on ID and locale (language),
+ * or {@code null} if no add-on information could be found.
+ *
+ * @param id the ID to be looked for
+ * @param locale the locale to be used for the add-on information (could be null)
+ * @return a localized add-on information object (could be null)
+ */
+ public @Nullable AddonInfo getAddonInfo(String id, @Nullable Locale locale) {
+ return addonInfoProviders.stream().map(p -> p.getAddonInfo(id, locale)).filter(Objects::nonNull).findAny()
+ .orElse(null);
+ }
+
+ /**
+ * Returns all add-on information this registry contains.
+ *
+ * @return a set of all add-on information this registry contains (not null, could be empty)
+ */
+ public Set getAddonInfos() {
+ return getAddonInfos(null);
+ }
+
+ /**
+ * Returns all add-on information in the specified locale (language) this registry contains.
+ *
+ * @param locale the locale to be used for the add-on information (could be null)
+ * @return a localized set of all add-on information this registry contains
+ * (not null, could be empty)
+ */
+ public Set getAddonInfos(@Nullable Locale locale) {
+ return addonInfoProviders.stream().map(provider -> provider.getAddonInfos(locale)).flatMap(Set::stream)
+ .collect(Collectors.toUnmodifiableSet());
+ }
+}
diff --git a/bundles/org.openhab.core/src/main/java/org/openhab/core/addon/AddonType.java b/bundles/org.openhab.core/src/main/java/org/openhab/core/addon/AddonType.java
index b3ae1f572..1b1cc139c 100644
--- a/bundles/org.openhab.core/src/main/java/org/openhab/core/addon/AddonType.java
+++ b/bundles/org.openhab.core/src/main/java/org/openhab/core/addon/AddonType.java
@@ -55,7 +55,7 @@ public class AddonType {
public int hashCode() {
final int prime = 31;
int result = 1;
- result = prime * result + ((id == null) ? 0 : id.hashCode());
+ result = prime * result + id.hashCode();
return result;
}
@@ -70,14 +70,6 @@ public class AddonType {
if (getClass() != obj.getClass()) {
return false;
}
- AddonType other = (AddonType) obj;
- if (id == null) {
- if (other.id != null) {
- return false;
- }
- } else if (!id.equals(other.id)) {
- return false;
- }
- return true;
+ return id.equals(((AddonType) obj).id);
}
}
diff --git a/bundles/org.openhab.core/src/main/java/org/openhab/core/binding/BindingInfo.java b/bundles/org.openhab.core/src/main/java/org/openhab/core/binding/BindingInfo.java
deleted file mode 100644
index 24fe0ebcc..000000000
--- a/bundles/org.openhab.core/src/main/java/org/openhab/core/binding/BindingInfo.java
+++ /dev/null
@@ -1,137 +0,0 @@
-/**
- * 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.binding;
-
-import java.net.URI;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.eclipse.jdt.annotation.Nullable;
-import org.openhab.core.common.registry.Identifiable;
-
-/**
- * The {@link BindingInfo} class contains general information about a binding.
- *
- * Any binding information are provided by a {@link BindingInfoProvider} and can also be retrieved through the
- * {@link BindingInfoRegistry}.
- *
- * Hint: This class is immutable.
- *
- * @author Michael Grammling - Initial contribution
- * @author Andre Fuechsel - Made author tag optional
- */
-@NonNullByDefault
-public class BindingInfo implements Identifiable {
-
- /**
- * The default service ID prefix.
- */
- public static final String DEFAULT_SERVICE_ID_PREFIX = "binding.";
-
- private String id;
- private String name;
- private @Nullable String description;
- private @Nullable String author;
- private @Nullable URI configDescriptionURI;
- private String serviceId;
-
- /**
- * Creates a new instance of this class with the specified parameters.
- *
- * @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 description a human readable description for the binding (could be null or 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 configDescriptionURI the link to a concrete ConfigDescription (could be null)
- * @throws IllegalArgumentException if the identifier or the name are null or empty
- */
- public BindingInfo(String id, String name, @Nullable String description, @Nullable String author,
- @Nullable String serviceId, @Nullable URI configDescriptionURI) throws IllegalArgumentException {
- if ((id == null) || (id.isEmpty())) {
- throw new IllegalArgumentException("The ID must neither be null nor empty!");
- }
-
- if ((name == null) || (name.isEmpty())) {
- throw new IllegalArgumentException("The name must neither be null nor empty!");
- }
-
- this.id = id;
- this.name = name;
- this.description = description;
- this.author = author;
- this.serviceId = serviceId != null ? serviceId : DEFAULT_SERVICE_ID_PREFIX + id;
- this.configDescriptionURI = configDescriptionURI;
- }
-
- /**
- * Returns an identifier for the binding (e.g. "hue").
- *
- * @return an identifier for the binding (neither null, nor empty)
- */
- @Override
- public String getUID() {
- return id;
- }
-
- /**
- * Returns a human readable name for the binding (e.g. "HUE Binding").
- *
- * @return a human readable name for the binding (neither null, nor empty)
- */
- public String getName() {
- return name;
- }
-
- /**
- * Returns a human readable description for the binding
- * (e.g. "Discovers and controls HUE bulbs").
- *
- * @return a human readable description for the binding (could be null or empty)
- */
- public @Nullable String getDescription() {
- return description;
- }
-
- /**
- * Returns the author of the binding (e.g. "Max Mustermann").
- *
- * @return the author of the binding (could be null or empty)
- */
- public @Nullable String getAuthor() {
- return author;
- }
-
- /**
- * Returns the service ID of the bindings main service, that can be configured.
- *
- * @return service ID
- */
- public String getServiceId() {
- return serviceId;
- }
-
- /**
- * Returns the link to a concrete {@link ConfigDescription}.
- *
- * @return the link to a concrete ConfigDescription (could be null)
- */
- public @Nullable URI getConfigDescriptionURI() {
- return configDescriptionURI;
- }
-
- @Override
- public String toString() {
- return "BindingInfo [id=" + id + ", name=" + name + ", description=" + description + ", author=" + author
- + ", configDescriptionURI=" + configDescriptionURI + "]";
- }
-}
diff --git a/bundles/org.openhab.core/src/main/java/org/openhab/core/binding/BindingInfoRegistry.java b/bundles/org.openhab.core/src/main/java/org/openhab/core/binding/BindingInfoRegistry.java
deleted file mode 100644
index e5380a22e..000000000
--- a/bundles/org.openhab.core/src/main/java/org/openhab/core/binding/BindingInfoRegistry.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/**
- * 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.binding;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.LinkedHashSet;
-import java.util.Locale;
-import java.util.Set;
-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.Reference;
-import org.osgi.service.component.annotations.ReferenceCardinality;
-import org.osgi.service.component.annotations.ReferencePolicy;
-
-/**
- * The {@link BindingInfoRegistry} provides access to {@link BindingInfo} objects.
- * It tracks {@link BindingInfoProvider} OSGi services to collect all {@link BindingInfo} objects.
- *
- * @author Dennis Nobel - Initial contribution
- * @author Michael Grammling - Initial contribution, added locale support
- */
-@Component(immediate = true, service = BindingInfoRegistry.class)
-@NonNullByDefault
-public class BindingInfoRegistry {
-
- private final Collection bindingInfoProviders = new CopyOnWriteArrayList<>();
-
- @Reference(cardinality = ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC)
- protected void addBindingInfoProvider(BindingInfoProvider bindingInfoProvider) {
- if (bindingInfoProvider != null) {
- bindingInfoProviders.add(bindingInfoProvider);
- }
- }
-
- protected void removeBindingInfoProvider(BindingInfoProvider bindingInfoProvider) {
- if (bindingInfoProvider != null) {
- bindingInfoProviders.remove(bindingInfoProvider);
- }
- }
-
- /**
- * Returns the binding information for the specified binding ID, or {@code null} if no binding information could be
- * found.
- *
- * @param id the ID to be looked for (could be null or empty)
- * @return a binding information object (could be null)
- */
- public @Nullable BindingInfo getBindingInfo(@Nullable String id) {
- return getBindingInfo(id, null);
- }
-
- /**
- * Returns the binding information for the specified binding ID and locale (language),
- * or {@code null} if no binding information could be found.
- *
- * @param id the ID to be looked for (could be null or empty)
- * @param locale the locale to be used for the binding information (could be null)
- * @return a localized binding information object (could be null)
- */
- public @Nullable BindingInfo getBindingInfo(@Nullable String id, @Nullable Locale locale) {
- for (BindingInfoProvider bindingInfoProvider : bindingInfoProviders) {
- BindingInfo bindingInfo = bindingInfoProvider.getBindingInfo(id, locale);
- if (bindingInfo != null) {
- return bindingInfo;
- }
- }
- return null;
- }
-
- /**
- * Returns all binding information this registry contains.
- *
- * @return a set of all binding information this registry contains (not null, could be empty)
- */
- public Set getBindingInfos() {
- return getBindingInfos(null);
- }
-
- /**
- * Returns all binding information in the specified locale (language) this registry contains.
- *
- * @param locale the locale to be used for the binding information (could be null)
- * @return a localized set of all binding information this registry contains
- * (not null, could be empty)
- */
- public Set getBindingInfos(@Nullable Locale locale) {
- Set allBindingInfos = new LinkedHashSet<>(bindingInfoProviders.size());
- for (BindingInfoProvider bindingInfoProvider : bindingInfoProviders) {
- Set bindingInfos = bindingInfoProvider.getBindingInfos(locale);
- allBindingInfos.addAll(bindingInfos);
- }
- return Collections.unmodifiableSet(allBindingInfos);
- }
-}
diff --git a/bundles/org.openhab.core/src/main/java/org/openhab/core/binding/dto/BindingInfoDTO.java b/bundles/org.openhab.core/src/main/java/org/openhab/core/binding/dto/BindingInfoDTO.java
deleted file mode 100644
index 931c53dc7..000000000
--- a/bundles/org.openhab.core/src/main/java/org/openhab/core/binding/dto/BindingInfoDTO.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/**
- * 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.binding.dto;
-
-/**
- * This is a data transfer object that is used to serialize binding info objects.
- *
- * @author Dennis Nobel - Initial contribution
- */
-public class BindingInfoDTO {
-
- public String author;
- public String description;
- public String id;
- public String name;
- public String configDescriptionURI;
-
- public BindingInfoDTO() {
- }
-
- public BindingInfoDTO(String id, String name, String author, String description, String configDescriptionURI) {
- this.id = id;
- this.name = name;
- this.author = author;
- this.description = description;
- this.configDescriptionURI = configDescriptionURI;
- }
-}
diff --git a/bundles/org.openhab.core/src/main/java/org/openhab/core/binding/i18n/BindingI18nLocalizationService.java b/bundles/org.openhab.core/src/main/java/org/openhab/core/binding/i18n/BindingI18nLocalizationService.java
deleted file mode 100644
index 96b80a0d3..000000000
--- a/bundles/org.openhab.core/src/main/java/org/openhab/core/binding/i18n/BindingI18nLocalizationService.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/**
- * 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.binding.i18n;
-
-import java.util.Locale;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.eclipse.jdt.annotation.Nullable;
-import org.openhab.core.binding.BindingInfo;
-import org.openhab.core.binding.internal.i18n.BindingI18nUtil;
-import org.openhab.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());
- }
-}
diff --git a/bundles/org.openhab.core/src/main/java/org/openhab/core/binding/internal/i18n/BindingI18nUtil.java b/bundles/org.openhab.core/src/main/java/org/openhab/core/internal/addon/AddonI18nUtil.java
similarity index 88%
rename from bundles/org.openhab.core/src/main/java/org/openhab/core/binding/internal/i18n/BindingI18nUtil.java
rename to bundles/org.openhab.core/src/main/java/org/openhab/core/internal/addon/AddonI18nUtil.java
index faac67cd4..30c5d9cfd 100644
--- a/bundles/org.openhab.core/src/main/java/org/openhab/core/binding/internal/i18n/BindingI18nUtil.java
+++ b/bundles/org.openhab.core/src/main/java/org/openhab/core/internal/addon/AddonI18nUtil.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.core.binding.internal.i18n;
+package org.openhab.core.internal.addon;
import java.util.Locale;
@@ -21,18 +21,18 @@ import org.openhab.core.i18n.TranslationProvider;
import org.osgi.framework.Bundle;
/**
- * The {@link BindingI18nUtil} uses the {@link TranslationProvider} to resolve the
+ * The {@link AddonI18nUtil} uses the {@link TranslationProvider} to resolve the
* localized texts. It automatically infers the key if the default text is not a
* constant.
*
* @author Dennis Nobel - Initial contribution
*/
@NonNullByDefault
-public class BindingI18nUtil {
+public class AddonI18nUtil {
private final TranslationProvider i18nProvider;
- public BindingI18nUtil(TranslationProvider i18nProvider) {
+ public AddonI18nUtil(TranslationProvider i18nProvider) {
this.i18nProvider = i18nProvider;
}
diff --git a/bundles/pom.xml b/bundles/pom.xml
index eca213a28..8e1bc0503 100644
--- a/bundles/pom.xml
+++ b/bundles/pom.xml
@@ -19,6 +19,7 @@
org.openhab.core.addon.marketplace
org.openhab.core.addon.marketplace.karaf
+ org.openhab.core.addon.xml
org.openhab.core.auth.jaas
org.openhab.core.auth.oauth2client
org.openhab.core.automation
@@ -38,7 +39,6 @@
org.openhab.core.config.xml
org.openhab.core
org.openhab.core.audio
- org.openhab.core.binding.xml
org.openhab.core.ephemeris
org.openhab.core.addon.sample
org.openhab.core.id
diff --git a/features/karaf/openhab-core/src/main/feature/feature.xml b/features/karaf/openhab-core/src/main/feature/feature.xml
index 2e66b033b..b60919acc 100644
--- a/features/karaf/openhab-core/src/main/feature/feature.xml
+++ b/features/karaf/openhab-core/src/main/feature/feature.xml
@@ -47,7 +47,7 @@
mvn:org.openhab.core.bundles/org.openhab.core.config.xml/${project.version}
mvn:org.openhab.core.bundles/org.openhab.core/${project.version}
openhab-core-storage-json
- mvn:org.openhab.core.bundles/org.openhab.core.binding.xml/${project.version}
+ mvn:org.openhab.core.bundles/org.openhab.core.addon.xml/${project.version}
mvn:org.openhab.core.bundles/org.openhab.core.ephemeris/${project.version}
mvn:org.openhab.core.bundles/org.openhab.core.id/${project.version}
mvn:org.openhab.core.bundles/org.openhab.core.persistence/${project.version}
diff --git a/itests/org.openhab.core.binding.xml.tests/.classpath b/itests/org.openhab.core.addon.xml.tests/.classpath
similarity index 100%
rename from itests/org.openhab.core.binding.xml.tests/.classpath
rename to itests/org.openhab.core.addon.xml.tests/.classpath
diff --git a/itests/org.openhab.core.binding.xml.tests/.project b/itests/org.openhab.core.addon.xml.tests/.project
similarity index 91%
rename from itests/org.openhab.core.binding.xml.tests/.project
rename to itests/org.openhab.core.addon.xml.tests/.project
index c078a2c09..55dda464e 100644
--- a/itests/org.openhab.core.binding.xml.tests/.project
+++ b/itests/org.openhab.core.addon.xml.tests/.project
@@ -1,6 +1,6 @@
- org.openhab.core.binding.xml.tests
+ org.openhab.core.addon.xml.tests
diff --git a/itests/org.openhab.core.binding.xml.tests/NOTICE b/itests/org.openhab.core.addon.xml.tests/NOTICE
similarity index 100%
rename from itests/org.openhab.core.binding.xml.tests/NOTICE
rename to itests/org.openhab.core.addon.xml.tests/NOTICE
diff --git a/itests/org.openhab.core.binding.xml.tests/itest.bndrun b/itests/org.openhab.core.addon.xml.tests/itest.bndrun
similarity index 88%
rename from itests/org.openhab.core.binding.xml.tests/itest.bndrun
rename to itests/org.openhab.core.addon.xml.tests/itest.bndrun
index dd3644044..9739940ed 100644
--- a/itests/org.openhab.core.binding.xml.tests/itest.bndrun
+++ b/itests/org.openhab.core.addon.xml.tests/itest.bndrun
@@ -1,13 +1,13 @@
-include: ../itest-common.bndrun
Bundle-SymbolicName: ${project.artifactId}
-Fragment-Host: org.openhab.core.binding.xml
+Fragment-Host: org.openhab.core.addon.xml
-runblacklist: \
bnd.identity;id='org.osgi.service.cm'
-runrequires: \
- bnd.identity;id='org.openhab.core.binding.xml.tests'
+ bnd.identity;id='org.openhab.core.addon.xml.tests'
#
# done
@@ -52,10 +52,10 @@ Fragment-Host: org.openhab.core.binding.xml
ch.qos.logback.classic;version='[1.2.11,1.2.12)',\
ch.qos.logback.core;version='[1.2.11,1.2.12)',\
biz.aQute.tester.junit-platform;version='[6.4.0,6.4.1)',\
+ com.google.gson;version='[2.9.1,2.9.2)',\
org.openhab.core;version='[4.0.0,4.0.1)',\
- org.openhab.core.binding.xml;version='[4.0.0,4.0.1)',\
- org.openhab.core.binding.xml.tests;version='[4.0.0,4.0.1)',\
+ org.openhab.core.addon.xml;version='[4.0.0,4.0.1)',\
+ org.openhab.core.addon.xml.tests;version='[4.0.0,4.0.1)',\
org.openhab.core.config.core;version='[4.0.0,4.0.1)',\
org.openhab.core.config.xml;version='[4.0.0,4.0.1)',\
- org.openhab.core.test;version='[4.0.0,4.0.1)',\
- com.google.gson;version='[2.9.1,2.9.2)'
+ org.openhab.core.test;version='[4.0.0,4.0.1)'
diff --git a/itests/org.openhab.core.binding.xml.tests/pom.xml b/itests/org.openhab.core.addon.xml.tests/pom.xml
similarity index 78%
rename from itests/org.openhab.core.binding.xml.tests/pom.xml
rename to itests/org.openhab.core.addon.xml.tests/pom.xml
index 583002f08..077be84c2 100644
--- a/itests/org.openhab.core.binding.xml.tests/pom.xml
+++ b/itests/org.openhab.core.addon.xml.tests/pom.xml
@@ -9,8 +9,8 @@
4.0.0-SNAPSHOT
- org.openhab.core.binding.xml.tests
+ org.openhab.core.addon.xml.tests
- openHAB Core :: Integration Tests :: Binding XML Tests
+ openHAB Core :: Integration Tests :: Add-on XML Tests
diff --git a/itests/org.openhab.core.binding.xml.tests/src/main/java/org/openhab/core/binding/xml/test/BindingInfoI18nTest.java b/itests/org.openhab.core.addon.xml.tests/src/main/java/org/openhab/core/addon/xml/test/AddonInfoI18nTest.java
similarity index 65%
rename from itests/org.openhab.core.binding.xml.tests/src/main/java/org/openhab/core/binding/xml/test/BindingInfoI18nTest.java
rename to itests/org.openhab.core.addon.xml.tests/src/main/java/org/openhab/core/addon/xml/test/AddonInfoI18nTest.java
index 948516c6c..a0127836b 100644
--- a/itests/org.openhab.core.binding.xml.tests/src/main/java/org/openhab/core/binding/xml/test/BindingInfoI18nTest.java
+++ b/itests/org.openhab.core.addon.xml.tests/src/main/java/org/openhab/core/addon/xml/test/AddonInfoI18nTest.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.core.binding.xml.test;
+package org.openhab.core.addon.xml.test;
import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.MatcherAssert.assertThat;
@@ -23,8 +23,8 @@ import java.util.Set;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
-import org.openhab.core.binding.BindingInfo;
-import org.openhab.core.binding.BindingInfoRegistry;
+import org.openhab.core.addon.AddonInfo;
+import org.openhab.core.addon.AddonInfoRegistry;
import org.openhab.core.i18n.LocaleProvider;
import org.openhab.core.internal.i18n.I18nProviderImpl;
import org.openhab.core.test.java.JavaOSGiTest;
@@ -35,38 +35,38 @@ import org.osgi.service.cm.ConfigurationAdmin;
* @author Dennis Nobel - Initial contribution
*/
@NonNullByDefault
-public class BindingInfoI18nTest extends JavaOSGiTest {
+public class AddonInfoI18nTest extends JavaOSGiTest {
private static final String TEST_BUNDLE_NAME = "acmeweather.bundle";
- private @NonNullByDefault({}) BindingInfoRegistry bindingInfoRegistry;
- private @NonNullByDefault({}) BindingInstaller bindingInstaller;
+ private @NonNullByDefault({}) AddonInfoRegistry addonInfoRegistry;
+ private @NonNullByDefault({}) AddonInstaller addonInstaller;
@BeforeEach
public void setUp() {
- bindingInfoRegistry = getService(BindingInfoRegistry.class);
- assertThat(bindingInfoRegistry, is(notNullValue()));
- bindingInstaller = new BindingInstaller(this::waitForAssert, bindingInfoRegistry, bundleContext);
+ addonInfoRegistry = getService(AddonInfoRegistry.class);
+ assertThat(addonInfoRegistry, is(notNullValue()));
+ addonInstaller = new AddonInstaller(this::waitForAssert, addonInfoRegistry, bundleContext);
}
@Test
- public void assertBindingInfosWereLocalizedInGerman() throws Exception {
- bindingInstaller.exec(TEST_BUNDLE_NAME, () -> {
- Set bindingInfos = bindingInfoRegistry.getBindingInfos(Locale.GERMAN);
- BindingInfo bindingInfo = bindingInfos.iterator().next();
+ public void assertAddonInfosWereLocalizedInGerman() throws Exception {
+ addonInstaller.exec(TEST_BUNDLE_NAME, () -> {
+ Set addonInfos = addonInfoRegistry.getAddonInfos(Locale.GERMAN);
+ AddonInfo addonInfo = addonInfos.iterator().next();
- assertThat(bindingInfo, is(notNullValue()));
- assertThat(bindingInfo.getName(), is("ACME Wetter Binding"));
- assertThat(bindingInfo.getDescription(), is(
+ assertThat(addonInfo, is(notNullValue()));
+ assertThat(addonInfo.getName(), is("ACME Wetter Binding"));
+ assertThat(addonInfo.getDescription(), is(
"Das ACME Wetter Binding stellt verschiedene Wetterdaten wie die Temperatur, die Luftfeuchtigkeit und den Luftdruck für konfigurierbare Orte vom ACME Wetterdienst bereit"));
});
}
@Test
- public void assertBindingInfosWereLocalizedInDutch() throws Exception {
- bindingInstaller.exec(TEST_BUNDLE_NAME, () -> {
- Set bindingInfos = bindingInfoRegistry.getBindingInfos(new Locale("nl"));
- BindingInfo bindingInfo = bindingInfos.iterator().next();
+ public void assertAddonInfosWereLocalizedInDutch() throws Exception {
+ addonInstaller.exec(TEST_BUNDLE_NAME, () -> {
+ Set bindingInfos = addonInfoRegistry.getAddonInfos(new Locale("nl"));
+ AddonInfo bindingInfo = bindingInfos.iterator().next();
assertThat(bindingInfo, is(notNullValue()));
assertThat(bindingInfo.getName(), is("ACME Weer Binding"));
@@ -76,10 +76,10 @@ public class BindingInfoI18nTest extends JavaOSGiTest {
}
@Test
- public void assertUsingOriginalBindingInfosIfProvidedLocaleIsNotSupported() throws Exception {
- bindingInstaller.exec(TEST_BUNDLE_NAME, () -> {
- Set bindingInfos = bindingInfoRegistry.getBindingInfos(Locale.FRENCH);
- BindingInfo bindingInfo = bindingInfos.iterator().next();
+ public void assertUsingOriginalAddonInfosIfProvidedLocaleIsNotSupported() throws Exception {
+ addonInstaller.exec(TEST_BUNDLE_NAME, () -> {
+ Set bindingInfos = addonInfoRegistry.getAddonInfos(Locale.FRENCH);
+ AddonInfo bindingInfo = bindingInfos.iterator().next();
assertThat(bindingInfo, is(notNullValue()));
assertThat(bindingInfo.getName(), is("ACME Weather Binding"));
@@ -113,10 +113,10 @@ public class BindingInfoI18nTest extends JavaOSGiTest {
waitForAssert(() -> assertThat(localeProvider.getLocale().toString(), is("de_DE")));
- bindingInstaller.exec(TEST_BUNDLE_NAME, () -> {
+ addonInstaller.exec(TEST_BUNDLE_NAME, () -> {
// use default locale
- Set bindingInfos = bindingInfoRegistry.getBindingInfos(null);
- BindingInfo bindingInfo = bindingInfos.iterator().next();
+ Set bindingInfos = addonInfoRegistry.getAddonInfos(null);
+ AddonInfo bindingInfo = bindingInfos.iterator().next();
assertThat(bindingInfo, is(notNullValue()));
assertThat(bindingInfo.getName(), is("ACME Wetter Binding"));
assertThat(bindingInfo.getDescription(), is(
diff --git a/itests/org.openhab.core.binding.xml.tests/src/main/java/org/openhab/core/binding/xml/test/BindingInfoTest.java b/itests/org.openhab.core.addon.xml.tests/src/main/java/org/openhab/core/addon/xml/test/AddonInfoTest.java
similarity index 59%
rename from itests/org.openhab.core.binding.xml.tests/src/main/java/org/openhab/core/binding/xml/test/BindingInfoTest.java
rename to itests/org.openhab.core.addon.xml.tests/src/main/java/org/openhab/core/addon/xml/test/AddonInfoTest.java
index 972649029..48dc4fa65 100644
--- a/itests/org.openhab.core.binding.xml.tests/src/main/java/org/openhab/core/binding/xml/test/BindingInfoTest.java
+++ b/itests/org.openhab.core.addon.xml.tests/src/main/java/org/openhab/core/addon/xml/test/AddonInfoTest.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.core.binding.xml.test;
+package org.openhab.core.addon.xml.test;
import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.MatcherAssert.assertThat;
@@ -24,8 +24,8 @@ import java.util.stream.Collectors;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
-import org.openhab.core.binding.BindingInfo;
-import org.openhab.core.binding.BindingInfoRegistry;
+import org.openhab.core.addon.AddonInfo;
+import org.openhab.core.addon.AddonInfoRegistry;
import org.openhab.core.config.core.ConfigDescription;
import org.openhab.core.config.core.ConfigDescriptionParameter;
import org.openhab.core.config.core.ConfigDescriptionRegistry;
@@ -36,60 +36,63 @@ import org.openhab.core.test.java.JavaOSGiTest;
* @author Wouter Born - Migrate tests from Groovy to Java
*/
@NonNullByDefault
-public class BindingInfoTest extends JavaOSGiTest {
+public class AddonInfoTest extends JavaOSGiTest {
private static final String TEST_BUNDLE_NAME = "BundleInfoTest.bundle";
private static final String TEST_BUNDLE_NAME2 = "BundleInfoTestNoAuthor.bundle";
- private @NonNullByDefault({}) BindingInfoRegistry bindingInfoRegistry;
+ private @NonNullByDefault({}) AddonInfoRegistry addonInfoRegistry;
private @NonNullByDefault({}) ConfigDescriptionRegistry configDescriptionRegistry;
- private @NonNullByDefault({}) BindingInstaller bindingInstaller;
+ private @NonNullByDefault({}) AddonInstaller addonInstaller;
@BeforeEach
public void setUp() {
- bindingInfoRegistry = getService(BindingInfoRegistry.class);
- assertThat(bindingInfoRegistry, is(notNullValue()));
+ addonInfoRegistry = getService(AddonInfoRegistry.class);
+ assertThat(addonInfoRegistry, is(notNullValue()));
configDescriptionRegistry = getService(ConfigDescriptionRegistry.class);
assertThat(configDescriptionRegistry, is(notNullValue()));
- bindingInstaller = new BindingInstaller(this::waitForAssert, bindingInfoRegistry, bundleContext);
+ addonInstaller = new AddonInstaller(this::waitForAssert, addonInfoRegistry, bundleContext);
}
@Test
- public void assertThatBindingInfoIsReadProperly() throws Exception {
- bindingInstaller.exec(TEST_BUNDLE_NAME, () -> {
- Set bindingInfos = bindingInfoRegistry.getBindingInfos();
- BindingInfo bindingInfo = bindingInfos.iterator().next();
- assertThat(bindingInfo.getUID(), is("hue"));
- assertThat(bindingInfo.getConfigDescriptionURI(), is(URI.create("binding:hue")));
- assertThat(bindingInfo.getDescription(),
+ public void assertThatAddonInfoIsReadProperly() throws Exception {
+ addonInstaller.exec(TEST_BUNDLE_NAME, () -> {
+ Set addonInfos = addonInfoRegistry.getAddonInfos();
+ AddonInfo addonInfo = addonInfos.iterator().next();
+ assertThat(addonInfo.getId(), is("hue"));
+ assertThat(addonInfo.getUID(), is("binding-hue"));
+ assertThat(addonInfo.getConfigDescriptionURI(), is("binding:hue"));
+ assertThat(addonInfo.getDescription(),
is("The hue Binding integrates the Philips hue system. It allows to control hue lights."));
- assertThat(bindingInfo.getName(), is("hue Binding"));
- assertThat(bindingInfo.getAuthor(), is("Deutsche Telekom AG"));
+ assertThat(addonInfo.getName(), is("hue Binding"));
+ assertThat(addonInfo.getAuthor(), is("Deutsche Telekom AG"));
});
}
@Test
- public void assertThatBindingInfoWithoutAuthorIsReadProperly() throws Exception {
- bindingInstaller.exec(TEST_BUNDLE_NAME2, () -> {
- Set bindingInfos = bindingInfoRegistry.getBindingInfos();
- BindingInfo bindingInfo = bindingInfos.iterator().next();
- assertThat(bindingInfo.getUID(), is("hue"));
- assertThat(bindingInfo.getConfigDescriptionURI(), is(URI.create("binding:hue")));
- assertThat(bindingInfo.getDescription(),
+ public void assertThatAddonInfoWithoutAuthorIsReadProperly() throws Exception {
+ addonInstaller.exec(TEST_BUNDLE_NAME2, () -> {
+ Set addonInfos = addonInfoRegistry.getAddonInfos();
+ AddonInfo addonInfo = addonInfos.iterator().next();
+ assertThat(addonInfo.getId(), is("hue"));
+ assertThat(addonInfo.getUID(), is("binding-hue"));
+ assertThat(addonInfo.getConfigDescriptionURI(), is("foo:bar"));
+ assertThat(addonInfo.getDescription(),
is("The hue Binding integrates the Philips hue system. It allows to control hue lights."));
- assertThat(bindingInfo.getName(), is("hue Binding"));
- assertThat(bindingInfo.getAuthor(), is((String) null));
+ assertThat(addonInfo.getName(), is("hue Binding"));
+ assertThat(addonInfo.getAuthor(), is((String) null));
});
}
@Test
public void assertThatConfigWithOptionsAndFilterAreProperlyRead() throws Exception {
- bindingInstaller.exec(TEST_BUNDLE_NAME, () -> {
- Set bindingInfos = bindingInfoRegistry.getBindingInfos();
- BindingInfo bindingInfo = bindingInfos.iterator().next();
+ addonInstaller.exec(TEST_BUNDLE_NAME, () -> {
+ Set bindingInfos = addonInfoRegistry.getAddonInfos();
+ AddonInfo bindingInfo = bindingInfos.iterator().next();
- URI configDescriptionURI = Objects.requireNonNull(bindingInfo.getConfigDescriptionURI());
- ConfigDescription configDescription = configDescriptionRegistry.getConfigDescription(configDescriptionURI);
+ String configDescriptionURI = Objects.requireNonNull(bindingInfo.getConfigDescriptionURI());
+ ConfigDescription configDescription = configDescriptionRegistry
+ .getConfigDescription(URI.create(configDescriptionURI));
List parameters = configDescription.getParameters();
assertThat(parameters.size(), is(2));
diff --git a/itests/org.openhab.core.binding.xml.tests/src/main/java/org/openhab/core/binding/xml/test/BindingInstaller.java b/itests/org.openhab.core.addon.xml.tests/src/main/java/org/openhab/core/addon/xml/test/AddonInstaller.java
similarity index 65%
rename from itests/org.openhab.core.binding.xml.tests/src/main/java/org/openhab/core/binding/xml/test/BindingInstaller.java
rename to itests/org.openhab.core.addon.xml.tests/src/main/java/org/openhab/core/addon/xml/test/AddonInstaller.java
index 1c1f59b88..1191916bd 100644
--- a/itests/org.openhab.core.binding.xml.tests/src/main/java/org/openhab/core/binding/xml/test/BindingInstaller.java
+++ b/itests/org.openhab.core.addon.xml.tests/src/main/java/org/openhab/core/addon/xml/test/AddonInstaller.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.core.binding.xml.test;
+package org.openhab.core.addon.xml.test;
import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.MatcherAssert.assertThat;
@@ -18,7 +18,7 @@ import static org.hamcrest.MatcherAssert.assertThat;
import java.util.function.Consumer;
import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.openhab.core.binding.BindingInfoRegistry;
+import org.openhab.core.addon.AddonInfoRegistry;
import org.openhab.core.test.BundleCloseable;
import org.openhab.core.test.SyntheticBundleInstaller;
import org.osgi.framework.BundleContext;
@@ -27,36 +27,35 @@ import org.osgi.framework.BundleContext;
* @author Markus Rathgeb - Initial contribution
*/
@NonNullByDefault
-public class BindingInstaller {
+public class AddonInstaller {
private final Consumer waitForAssert;
- private final BindingInfoRegistry bindingInfoRegistry;
+ private final AddonInfoRegistry addonInfoRegistry;
private final BundleContext bc;
- public BindingInstaller(Consumer waitForAssert, BindingInfoRegistry bindingInfoRegistry,
- BundleContext bc) {
+ public AddonInstaller(Consumer waitForAssert, AddonInfoRegistry addonInfoRegistry, BundleContext bc) {
this.waitForAssert = waitForAssert;
- this.bindingInfoRegistry = bindingInfoRegistry;
+ this.addonInfoRegistry = addonInfoRegistry;
this.bc = bc;
}
public void exec(final String bundleName, final Runnable func) throws Exception {
// Save the number of currently installed bundles.
- final int initialNumberOfBindingInfos = bindingInfoRegistry.getBindingInfos().size();
+ final int initialNumberOfBindingInfos = addonInfoRegistry.getAddonInfos().size();
// install test bundle
try (BundleCloseable bundle = new BundleCloseable(SyntheticBundleInstaller.install(bc, bundleName))) {
assertThat(bundle, is(notNullValue()));
// Wait for correctly installed bundle.
- waitForAssert.accept(() -> assertThat(bindingInfoRegistry.getBindingInfos().size(),
- is(initialNumberOfBindingInfos + 1)));
+ waitForAssert.accept(
+ () -> assertThat(addonInfoRegistry.getAddonInfos().size(), is(initialNumberOfBindingInfos + 1)));
func.run();
}
// Wait for correctly uninstalled bundle.
- waitForAssert.accept(
- () -> assertThat(bindingInfoRegistry.getBindingInfos().size(), is(initialNumberOfBindingInfos)));
+ waitForAssert
+ .accept(() -> assertThat(addonInfoRegistry.getAddonInfos().size(), is(initialNumberOfBindingInfos)));
}
}
diff --git a/itests/org.openhab.core.binding.xml.tests/src/main/resources/test-bundle-pool/BundleInfoTest.bundle/OH-INF/binding/binding.xml b/itests/org.openhab.core.addon.xml.tests/src/main/resources/test-bundle-pool/BundleInfoTest.bundle/OH-INF/addon/addon.xml
similarity index 73%
rename from itests/org.openhab.core.binding.xml.tests/src/main/resources/test-bundle-pool/BundleInfoTest.bundle/OH-INF/binding/binding.xml
rename to itests/org.openhab.core.addon.xml.tests/src/main/resources/test-bundle-pool/BundleInfoTest.bundle/OH-INF/addon/addon.xml
index 6940e76f9..1b1a3696d 100644
--- a/itests/org.openhab.core.binding.xml.tests/src/main/resources/test-bundle-pool/BundleInfoTest.bundle/OH-INF/binding/binding.xml
+++ b/itests/org.openhab.core.addon.xml.tests/src/main/resources/test-bundle-pool/BundleInfoTest.bundle/OH-INF/addon/addon.xml
@@ -1,8 +1,9 @@
-
+
+ binding
hue Binding
The hue Binding integrates the Philips hue system. It
allows to control hue lights.
@@ -29,4 +30,4 @@
-
+
diff --git a/itests/org.openhab.core.binding.xml.tests/src/main/resources/test-bundle-pool/BundleInfoTest.bundle/OH-INF/thing/thing-types.xml b/itests/org.openhab.core.addon.xml.tests/src/main/resources/test-bundle-pool/BundleInfoTest.bundle/OH-INF/thing/thing-types.xml
similarity index 100%
rename from itests/org.openhab.core.binding.xml.tests/src/main/resources/test-bundle-pool/BundleInfoTest.bundle/OH-INF/thing/thing-types.xml
rename to itests/org.openhab.core.addon.xml.tests/src/main/resources/test-bundle-pool/BundleInfoTest.bundle/OH-INF/thing/thing-types.xml
diff --git a/itests/org.openhab.core.binding.xml.tests/src/main/resources/test-bundle-pool/BundleInfoTestNoAuthor.bundle/OH-INF/binding/binding.xml b/itests/org.openhab.core.addon.xml.tests/src/main/resources/test-bundle-pool/BundleInfoTestNoAuthor.bundle/OH-INF/addon/addon.xml
similarity index 69%
rename from itests/org.openhab.core.binding.xml.tests/src/main/resources/test-bundle-pool/BundleInfoTestNoAuthor.bundle/OH-INF/binding/binding.xml
rename to itests/org.openhab.core.addon.xml.tests/src/main/resources/test-bundle-pool/BundleInfoTestNoAuthor.bundle/OH-INF/addon/addon.xml
index c56096372..7a7260c91 100644
--- a/itests/org.openhab.core.binding.xml.tests/src/main/resources/test-bundle-pool/BundleInfoTestNoAuthor.bundle/OH-INF/binding/binding.xml
+++ b/itests/org.openhab.core.addon.xml.tests/src/main/resources/test-bundle-pool/BundleInfoTestNoAuthor.bundle/OH-INF/addon/addon.xml
@@ -1,15 +1,16 @@
-
+
+ binding
hue Binding
The hue Binding integrates the Philips hue system. It
allows to control hue lights.
-
+
@@ -29,4 +30,4 @@
-
+
diff --git a/itests/org.openhab.core.binding.xml.tests/src/main/resources/test-bundle-pool/BundleInfoTestNoAuthor.bundle/OH-INF/thing/thing-types.xml b/itests/org.openhab.core.addon.xml.tests/src/main/resources/test-bundle-pool/BundleInfoTestNoAuthor.bundle/OH-INF/thing/thing-types.xml
similarity index 100%
rename from itests/org.openhab.core.binding.xml.tests/src/main/resources/test-bundle-pool/BundleInfoTestNoAuthor.bundle/OH-INF/thing/thing-types.xml
rename to itests/org.openhab.core.addon.xml.tests/src/main/resources/test-bundle-pool/BundleInfoTestNoAuthor.bundle/OH-INF/thing/thing-types.xml
diff --git a/itests/org.openhab.core.addon.xml.tests/src/main/resources/test-bundle-pool/acmeweather.bundle/OH-INF/addon/addon.xml b/itests/org.openhab.core.addon.xml.tests/src/main/resources/test-bundle-pool/acmeweather.bundle/OH-INF/addon/addon.xml
new file mode 100644
index 000000000..1fd540c81
--- /dev/null
+++ b/itests/org.openhab.core.addon.xml.tests/src/main/resources/test-bundle-pool/acmeweather.bundle/OH-INF/addon/addon.xml
@@ -0,0 +1,11 @@
+
+
+
+ binding
+ ACME Weather Binding
+ The ACME Weather Binding requests the ACME Weather Service to show the current temperature, humidity and
+ pressure.
+
+
diff --git a/itests/org.openhab.core.binding.xml.tests/src/main/resources/test-bundle-pool/acmeweather.bundle/OH-INF/i18n/acmeweather_de.properties b/itests/org.openhab.core.addon.xml.tests/src/main/resources/test-bundle-pool/acmeweather.bundle/OH-INF/i18n/acmeweather_de.properties
similarity index 100%
rename from itests/org.openhab.core.binding.xml.tests/src/main/resources/test-bundle-pool/acmeweather.bundle/OH-INF/i18n/acmeweather_de.properties
rename to itests/org.openhab.core.addon.xml.tests/src/main/resources/test-bundle-pool/acmeweather.bundle/OH-INF/i18n/acmeweather_de.properties
diff --git a/itests/org.openhab.core.binding.xml.tests/src/main/resources/test-bundle-pool/acmeweather.bundle/OH-INF/i18n/acmeweather_nl.properties b/itests/org.openhab.core.addon.xml.tests/src/main/resources/test-bundle-pool/acmeweather.bundle/OH-INF/i18n/acmeweather_nl.properties
similarity index 100%
rename from itests/org.openhab.core.binding.xml.tests/src/main/resources/test-bundle-pool/acmeweather.bundle/OH-INF/i18n/acmeweather_nl.properties
rename to itests/org.openhab.core.addon.xml.tests/src/main/resources/test-bundle-pool/acmeweather.bundle/OH-INF/i18n/acmeweather_nl.properties
diff --git a/itests/org.openhab.core.auth.oauth2client.tests/itest.bndrun b/itests/org.openhab.core.auth.oauth2client.tests/itest.bndrun
index c14419841..74bcd2865 100644
--- a/itests/org.openhab.core.auth.oauth2client.tests/itest.bndrun
+++ b/itests/org.openhab.core.auth.oauth2client.tests/itest.bndrun
@@ -56,10 +56,10 @@ Fragment-Host: org.openhab.core.auth.oauth2client
ch.qos.logback.core;version='[1.2.11,1.2.12)',\
org.osgi.service.cm;version='[1.6.0,1.6.1)',\
biz.aQute.tester.junit-platform;version='[6.4.0,6.4.1)',\
+ com.google.gson;version='[2.9.1,2.9.2)',\
org.openhab.core;version='[4.0.0,4.0.1)',\
org.openhab.core.auth.oauth2client;version='[4.0.0,4.0.1)',\
org.openhab.core.auth.oauth2client.tests;version='[4.0.0,4.0.1)',\
org.openhab.core.io.console;version='[4.0.0,4.0.1)',\
org.openhab.core.io.net;version='[4.0.0,4.0.1)',\
- org.openhab.core.test;version='[4.0.0,4.0.1)',\
- com.google.gson;version='[2.9.1,2.9.2)'
+ org.openhab.core.test;version='[4.0.0,4.0.1)'
diff --git a/itests/org.openhab.core.binding.xml.tests/src/main/resources/test-bundle-pool/acmeweather.bundle/OH-INF/binding/binding.xml b/itests/org.openhab.core.binding.xml.tests/src/main/resources/test-bundle-pool/acmeweather.bundle/OH-INF/binding/binding.xml
deleted file mode 100644
index 2e6dce5f0..000000000
--- a/itests/org.openhab.core.binding.xml.tests/src/main/resources/test-bundle-pool/acmeweather.bundle/OH-INF/binding/binding.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
- ACME Weather Binding
- The ACME Weather Binding requests the ACME Weather Service to show the current temperature, humidity and
- pressure.
-
-
diff --git a/itests/org.openhab.core.config.discovery.mdns.tests/itest.bndrun b/itests/org.openhab.core.config.discovery.mdns.tests/itest.bndrun
index 4a0488185..7bf217cab 100644
--- a/itests/org.openhab.core.config.discovery.mdns.tests/itest.bndrun
+++ b/itests/org.openhab.core.config.discovery.mdns.tests/itest.bndrun
@@ -53,6 +53,7 @@ Fragment-Host: org.openhab.core.config.discovery.mdns
javax.jmdns;version='[3.5.8,3.5.9)',\
org.osgi.service.cm;version='[1.6.0,1.6.1)',\
biz.aQute.tester.junit-platform;version='[6.4.0,6.4.1)',\
+ com.google.gson;version='[2.9.1,2.9.2)',\
org.openhab.core;version='[4.0.0,4.0.1)',\
org.openhab.core.config.core;version='[4.0.0,4.0.1)',\
org.openhab.core.config.discovery;version='[4.0.0,4.0.1)',\
@@ -61,5 +62,4 @@ Fragment-Host: org.openhab.core.config.discovery.mdns
org.openhab.core.io.console;version='[4.0.0,4.0.1)',\
org.openhab.core.io.transport.mdns;version='[4.0.0,4.0.1)',\
org.openhab.core.test;version='[4.0.0,4.0.1)',\
- org.openhab.core.thing;version='[4.0.0,4.0.1)',\
- com.google.gson;version='[2.9.1,2.9.2)'
+ org.openhab.core.thing;version='[4.0.0,4.0.1)'
diff --git a/itests/org.openhab.core.config.discovery.tests/itest.bndrun b/itests/org.openhab.core.config.discovery.tests/itest.bndrun
index ffeee45ee..3e4696ae3 100644
--- a/itests/org.openhab.core.config.discovery.tests/itest.bndrun
+++ b/itests/org.openhab.core.config.discovery.tests/itest.bndrun
@@ -56,6 +56,7 @@ Fragment-Host: org.openhab.core.config.discovery
ch.qos.logback.core;version='[1.2.11,1.2.12)',\
org.osgi.service.cm;version='[1.6.0,1.6.1)',\
biz.aQute.tester.junit-platform;version='[6.4.0,6.4.1)',\
+ com.google.gson;version='[2.9.1,2.9.2)',\
org.openhab.core;version='[4.0.0,4.0.1)',\
org.openhab.core.config.core;version='[4.0.0,4.0.1)',\
org.openhab.core.config.discovery;version='[4.0.0,4.0.1)',\
@@ -64,5 +65,4 @@ Fragment-Host: org.openhab.core.config.discovery
org.openhab.core.io.console;version='[4.0.0,4.0.1)',\
org.openhab.core.test;version='[4.0.0,4.0.1)',\
org.openhab.core.thing;version='[4.0.0,4.0.1)',\
- org.openhab.core.thing.xml;version='[4.0.0,4.0.1)',\
- com.google.gson;version='[2.9.1,2.9.2)'
+ org.openhab.core.thing.xml;version='[4.0.0,4.0.1)'
diff --git a/itests/org.openhab.core.config.discovery.usbserial.linuxsysfs.tests/itest.bndrun b/itests/org.openhab.core.config.discovery.usbserial.linuxsysfs.tests/itest.bndrun
index a13125417..8855441cb 100644
--- a/itests/org.openhab.core.config.discovery.usbserial.linuxsysfs.tests/itest.bndrun
+++ b/itests/org.openhab.core.config.discovery.usbserial.linuxsysfs.tests/itest.bndrun
@@ -53,6 +53,7 @@ Fragment-Host: org.openhab.core.config.discovery.usbserial.linuxsysfs
ch.qos.logback.core;version='[1.2.11,1.2.12)',\
org.osgi.service.cm;version='[1.6.0,1.6.1)',\
biz.aQute.tester.junit-platform;version='[6.4.0,6.4.1)',\
+ com.google.gson;version='[2.9.1,2.9.2)',\
org.openhab.core;version='[4.0.0,4.0.1)',\
org.openhab.core.config.core;version='[4.0.0,4.0.1)',\
org.openhab.core.config.discovery;version='[4.0.0,4.0.1)',\
@@ -61,5 +62,4 @@ Fragment-Host: org.openhab.core.config.discovery.usbserial.linuxsysfs
org.openhab.core.config.discovery.usbserial.linuxsysfs.tests;version='[4.0.0,4.0.1)',\
org.openhab.core.io.console;version='[4.0.0,4.0.1)',\
org.openhab.core.test;version='[4.0.0,4.0.1)',\
- org.openhab.core.thing;version='[4.0.0,4.0.1)',\
- com.google.gson;version='[2.9.1,2.9.2)'
+ org.openhab.core.thing;version='[4.0.0,4.0.1)'
diff --git a/itests/org.openhab.core.config.discovery.usbserial.tests/itest.bndrun b/itests/org.openhab.core.config.discovery.usbserial.tests/itest.bndrun
index 1767a82c1..0b72b3e93 100644
--- a/itests/org.openhab.core.config.discovery.usbserial.tests/itest.bndrun
+++ b/itests/org.openhab.core.config.discovery.usbserial.tests/itest.bndrun
@@ -62,6 +62,7 @@ Provide-Capability: \
ch.qos.logback.core;version='[1.2.11,1.2.12)',\
org.osgi.service.cm;version='[1.6.0,1.6.1)',\
biz.aQute.tester.junit-platform;version='[6.4.0,6.4.1)',\
+ com.google.gson;version='[2.9.1,2.9.2)',\
org.openhab.core;version='[4.0.0,4.0.1)',\
org.openhab.core.config.core;version='[4.0.0,4.0.1)',\
org.openhab.core.config.discovery;version='[4.0.0,4.0.1)',\
@@ -69,5 +70,4 @@ Provide-Capability: \
org.openhab.core.config.discovery.usbserial.tests;version='[4.0.0,4.0.1)',\
org.openhab.core.io.console;version='[4.0.0,4.0.1)',\
org.openhab.core.test;version='[4.0.0,4.0.1)',\
- org.openhab.core.thing;version='[4.0.0,4.0.1)',\
- com.google.gson;version='[2.9.1,2.9.2)'
+ org.openhab.core.thing;version='[4.0.0,4.0.1)'
diff --git a/itests/org.openhab.core.config.dispatch.tests/itest.bndrun b/itests/org.openhab.core.config.dispatch.tests/itest.bndrun
index 0e1d8a106..34f9e0dd0 100644
--- a/itests/org.openhab.core.config.dispatch.tests/itest.bndrun
+++ b/itests/org.openhab.core.config.dispatch.tests/itest.bndrun
@@ -48,8 +48,8 @@ Fragment-Host: org.openhab.core.config.dispatch
ch.qos.logback.core;version='[1.2.11,1.2.12)',\
org.osgi.service.cm;version='[1.6.0,1.6.1)',\
biz.aQute.tester.junit-platform;version='[6.4.0,6.4.1)',\
+ com.google.gson;version='[2.9.1,2.9.2)',\
org.openhab.core;version='[4.0.0,4.0.1)',\
org.openhab.core.config.dispatch;version='[4.0.0,4.0.1)',\
org.openhab.core.config.dispatch.tests;version='[4.0.0,4.0.1)',\
- org.openhab.core.test;version='[4.0.0,4.0.1)',\
- com.google.gson;version='[2.9.1,2.9.2)'
+ org.openhab.core.test;version='[4.0.0,4.0.1)'
diff --git a/itests/org.openhab.core.io.rest.core.tests/itest.bndrun b/itests/org.openhab.core.io.rest.core.tests/itest.bndrun
index 0e5def6cf..b1d832b93 100644
--- a/itests/org.openhab.core.io.rest.core.tests/itest.bndrun
+++ b/itests/org.openhab.core.io.rest.core.tests/itest.bndrun
@@ -45,6 +45,7 @@ Fragment-Host: org.openhab.core.io.rest.core
org.glassfish.hk2.external.javax.inject;version='[2.4.0,2.4.1)',\
tech.units.indriya;version='[2.1.2,2.1.3)',\
uom-lib-common;version='[2.1.0,2.1.1)',\
+ com.fasterxml.woodstox.woodstox-core;version='[6.2.6,6.2.7)',\
org.apache.cxf.cxf-core;version='[3.4.5,3.4.6)',\
org.apache.cxf.cxf-rt-frontend-jaxrs;version='[3.4.5,3.4.6)',\
org.apache.cxf.cxf-rt-rs-client;version='[3.4.5,3.4.6)',\
@@ -84,9 +85,11 @@ Fragment-Host: org.openhab.core.io.rest.core
org.ops4j.pax.web.pax-web-spi;version='[7.3.25,7.3.26)',\
ch.qos.logback.classic;version='[1.2.11,1.2.12)',\
ch.qos.logback.core;version='[1.2.11,1.2.12)',\
- junit-jupiter-params;version='[5.8.1,5.8.2)',\
org.osgi.service.cm;version='[1.6.0,1.6.1)',\
biz.aQute.tester.junit-platform;version='[6.4.0,6.4.1)',\
+ com.google.gson;version='[2.9.1,2.9.2)',\
+ junit-jupiter-params;version='[5.8.1,5.8.2)',\
+ org.objectweb.asm;version='[9.4.0,9.4.1)',\
org.openhab.core;version='[4.0.0,4.0.1)',\
org.openhab.core.config.core;version='[4.0.0,4.0.1)',\
org.openhab.core.config.discovery;version='[4.0.0,4.0.1)',\
@@ -98,7 +101,4 @@ Fragment-Host: org.openhab.core.io.rest.core
org.openhab.core.semantics;version='[4.0.0,4.0.1)',\
org.openhab.core.test;version='[4.0.0,4.0.1)',\
org.openhab.core.thing;version='[4.0.0,4.0.1)',\
- org.openhab.core.transform;version='[4.0.0,4.0.1)',\
- com.google.gson;version='[2.9.1,2.9.2)',\
- org.objectweb.asm;version='[9.4.0,9.4.1)',\
- com.fasterxml.woodstox.woodstox-core;version='[6.4.0,6.4.1)'
+ org.openhab.core.transform;version='[4.0.0,4.0.1)'
diff --git a/itests/org.openhab.core.model.core.tests/itest.bndrun b/itests/org.openhab.core.model.core.tests/itest.bndrun
index d1028e509..0dd9e71b7 100644
--- a/itests/org.openhab.core.model.core.tests/itest.bndrun
+++ b/itests/org.openhab.core.model.core.tests/itest.bndrun
@@ -75,6 +75,18 @@ Fragment-Host: org.openhab.core.model.core
ch.qos.logback.classic;version='[1.2.11,1.2.12)',\
ch.qos.logback.core;version='[1.2.11,1.2.12)',\
biz.aQute.tester.junit-platform;version='[6.4.0,6.4.1)',\
+ com.google.gson;version='[2.9.1,2.9.2)',\
+ io.github.classgraph;version='[4.8.149,4.8.150)',\
+ org.apache.log4j;version='[1.2.19,1.2.20)',\
+ org.eclipse.equinox.common;version='[3.16.200,3.16.201)',\
+ org.eclipse.xtend.lib;version='[2.29.0,2.29.1)',\
+ org.eclipse.xtend.lib.macro;version='[2.29.0,2.29.1)',\
+ org.eclipse.xtext;version='[2.29.0,2.29.1)',\
+ org.eclipse.xtext.common.types;version='[2.29.0,2.29.1)',\
+ org.eclipse.xtext.util;version='[2.29.0,2.29.1)',\
+ org.eclipse.xtext.xbase;version='[2.29.0,2.29.1)',\
+ org.eclipse.xtext.xbase.lib;version='[2.29.0,2.29.1)',\
+ org.objectweb.asm;version='[9.4.0,9.4.1)',\
org.openhab.core;version='[4.0.0,4.0.1)',\
org.openhab.core.audio;version='[4.0.0,4.0.1)',\
org.openhab.core.automation;version='[4.0.0,4.0.1)',\
@@ -99,15 +111,4 @@ Fragment-Host: org.openhab.core.model.core
org.openhab.core.test;version='[4.0.0,4.0.1)',\
org.openhab.core.thing;version='[4.0.0,4.0.1)',\
org.openhab.core.transform;version='[4.0.0,4.0.1)',\
- org.openhab.core.voice;version='[4.0.0,4.0.1)',\
- com.google.gson;version='[2.9.1,2.9.2)',\
- io.github.classgraph;version='[4.8.149,4.8.150)',\
- org.eclipse.equinox.common;version='[3.16.200,3.16.201)',\
- org.eclipse.xtend.lib;version='[2.29.0,2.29.1)',\
- org.eclipse.xtend.lib.macro;version='[2.29.0,2.29.1)',\
- org.eclipse.xtext;version='[2.29.0,2.29.1)',\
- org.eclipse.xtext.common.types;version='[2.29.0,2.29.1)',\
- org.eclipse.xtext.util;version='[2.29.0,2.29.1)',\
- org.eclipse.xtext.xbase;version='[2.29.0,2.29.1)',\
- org.eclipse.xtext.xbase.lib;version='[2.29.0,2.29.1)',\
- org.objectweb.asm;version='[9.4.0,9.4.1)'
+ org.openhab.core.voice;version='[4.0.0,4.0.1)'
diff --git a/itests/org.openhab.core.model.item.tests/itest.bndrun b/itests/org.openhab.core.model.item.tests/itest.bndrun
index f8662cbd7..45214d266 100644
--- a/itests/org.openhab.core.model.item.tests/itest.bndrun
+++ b/itests/org.openhab.core.model.item.tests/itest.bndrun
@@ -72,6 +72,18 @@ Fragment-Host: org.openhab.core.model.item
ch.qos.logback.classic;version='[1.2.11,1.2.12)',\
ch.qos.logback.core;version='[1.2.11,1.2.12)',\
biz.aQute.tester.junit-platform;version='[6.4.0,6.4.1)',\
+ com.google.gson;version='[2.9.1,2.9.2)',\
+ io.github.classgraph;version='[4.8.149,4.8.150)',\
+ org.apache.log4j;version='[1.2.19,1.2.20)',\
+ org.eclipse.equinox.common;version='[3.16.200,3.16.201)',\
+ org.eclipse.xtend.lib;version='[2.29.0,2.29.1)',\
+ org.eclipse.xtend.lib.macro;version='[2.29.0,2.29.1)',\
+ org.eclipse.xtext;version='[2.29.0,2.29.1)',\
+ org.eclipse.xtext.common.types;version='[2.29.0,2.29.1)',\
+ org.eclipse.xtext.util;version='[2.29.0,2.29.1)',\
+ org.eclipse.xtext.xbase;version='[2.29.0,2.29.1)',\
+ org.eclipse.xtext.xbase.lib;version='[2.29.0,2.29.1)',\
+ org.objectweb.asm;version='[9.4.0,9.4.1)',\
org.openhab.core;version='[4.0.0,4.0.1)',\
org.openhab.core.audio;version='[4.0.0,4.0.1)',\
org.openhab.core.automation;version='[4.0.0,4.0.1)',\
@@ -97,15 +109,4 @@ Fragment-Host: org.openhab.core.model.item
org.openhab.core.test;version='[4.0.0,4.0.1)',\
org.openhab.core.thing;version='[4.0.0,4.0.1)',\
org.openhab.core.transform;version='[4.0.0,4.0.1)',\
- org.openhab.core.voice;version='[4.0.0,4.0.1)',\
- com.google.gson;version='[2.9.1,2.9.2)',\
- io.github.classgraph;version='[4.8.149,4.8.150)',\
- org.eclipse.equinox.common;version='[3.16.200,3.16.201)',\
- org.eclipse.xtend.lib;version='[2.29.0,2.29.1)',\
- org.eclipse.xtend.lib.macro;version='[2.29.0,2.29.1)',\
- org.eclipse.xtext;version='[2.29.0,2.29.1)',\
- org.eclipse.xtext.common.types;version='[2.29.0,2.29.1)',\
- org.eclipse.xtext.util;version='[2.29.0,2.29.1)',\
- org.eclipse.xtext.xbase;version='[2.29.0,2.29.1)',\
- org.eclipse.xtext.xbase.lib;version='[2.29.0,2.29.1)',\
- org.objectweb.asm;version='[9.4.0,9.4.1)'
+ org.openhab.core.voice;version='[4.0.0,4.0.1)'
diff --git a/itests/org.openhab.core.model.rule.tests/itest.bndrun b/itests/org.openhab.core.model.rule.tests/itest.bndrun
index a1eaa70cf..4f107073f 100644
--- a/itests/org.openhab.core.model.rule.tests/itest.bndrun
+++ b/itests/org.openhab.core.model.rule.tests/itest.bndrun
@@ -73,6 +73,18 @@ Fragment-Host: org.openhab.core.model.rule.runtime
ch.qos.logback.classic;version='[1.2.11,1.2.12)',\
ch.qos.logback.core;version='[1.2.11,1.2.12)',\
biz.aQute.tester.junit-platform;version='[6.4.0,6.4.1)',\
+ com.google.gson;version='[2.9.1,2.9.2)',\
+ io.github.classgraph;version='[4.8.149,4.8.150)',\
+ org.apache.log4j;version='[1.2.19,1.2.20)',\
+ org.eclipse.equinox.common;version='[3.16.200,3.16.201)',\
+ org.eclipse.xtend.lib;version='[2.29.0,2.29.1)',\
+ org.eclipse.xtend.lib.macro;version='[2.29.0,2.29.1)',\
+ org.eclipse.xtext;version='[2.29.0,2.29.1)',\
+ org.eclipse.xtext.common.types;version='[2.29.0,2.29.1)',\
+ org.eclipse.xtext.util;version='[2.29.0,2.29.1)',\
+ org.eclipse.xtext.xbase;version='[2.29.0,2.29.1)',\
+ org.eclipse.xtext.xbase.lib;version='[2.29.0,2.29.1)',\
+ org.objectweb.asm;version='[9.4.0,9.4.1)',\
org.openhab.core;version='[4.0.0,4.0.1)',\
org.openhab.core.audio;version='[4.0.0,4.0.1)',\
org.openhab.core.automation;version='[4.0.0,4.0.1)',\
@@ -98,16 +110,5 @@ Fragment-Host: org.openhab.core.model.rule.runtime
org.openhab.core.test;version='[4.0.0,4.0.1)',\
org.openhab.core.thing;version='[4.0.0,4.0.1)',\
org.openhab.core.transform;version='[4.0.0,4.0.1)',\
- org.openhab.core.voice;version='[4.0.0,4.0.1)',\
- com.google.gson;version='[2.9.1,2.9.2)',\
- io.github.classgraph;version='[4.8.149,4.8.150)',\
- org.eclipse.equinox.common;version='[3.16.200,3.16.201)',\
- org.eclipse.xtend.lib;version='[2.29.0,2.29.1)',\
- org.eclipse.xtend.lib.macro;version='[2.29.0,2.29.1)',\
- org.eclipse.xtext;version='[2.29.0,2.29.1)',\
- org.eclipse.xtext.common.types;version='[2.29.0,2.29.1)',\
- org.eclipse.xtext.util;version='[2.29.0,2.29.1)',\
- org.eclipse.xtext.xbase;version='[2.29.0,2.29.1)',\
- org.eclipse.xtext.xbase.lib;version='[2.29.0,2.29.1)',\
- org.objectweb.asm;version='[9.4.0,9.4.1)'
+ org.openhab.core.voice;version='[4.0.0,4.0.1)'
-runblacklist: bnd.identity;id='jakarta.activation-api'
diff --git a/itests/org.openhab.core.model.script.tests/itest.bndrun b/itests/org.openhab.core.model.script.tests/itest.bndrun
index 4c4db2a39..82e445df3 100644
--- a/itests/org.openhab.core.model.script.tests/itest.bndrun
+++ b/itests/org.openhab.core.model.script.tests/itest.bndrun
@@ -75,6 +75,18 @@ Fragment-Host: org.openhab.core.model.script
ch.qos.logback.classic;version='[1.2.11,1.2.12)',\
ch.qos.logback.core;version='[1.2.11,1.2.12)',\
biz.aQute.tester.junit-platform;version='[6.4.0,6.4.1)',\
+ com.google.gson;version='[2.9.1,2.9.2)',\
+ io.github.classgraph;version='[4.8.149,4.8.150)',\
+ org.apache.log4j;version='[1.2.19,1.2.20)',\
+ org.eclipse.equinox.common;version='[3.16.200,3.16.201)',\
+ org.eclipse.xtend.lib;version='[2.29.0,2.29.1)',\
+ org.eclipse.xtend.lib.macro;version='[2.29.0,2.29.1)',\
+ org.eclipse.xtext;version='[2.29.0,2.29.1)',\
+ org.eclipse.xtext.common.types;version='[2.29.0,2.29.1)',\
+ org.eclipse.xtext.util;version='[2.29.0,2.29.1)',\
+ org.eclipse.xtext.xbase;version='[2.29.0,2.29.1)',\
+ org.eclipse.xtext.xbase.lib;version='[2.29.0,2.29.1)',\
+ org.objectweb.asm;version='[9.4.0,9.4.1)',\
org.openhab.core;version='[4.0.0,4.0.1)',\
org.openhab.core.audio;version='[4.0.0,4.0.1)',\
org.openhab.core.automation;version='[4.0.0,4.0.1)',\
@@ -99,15 +111,4 @@ Fragment-Host: org.openhab.core.model.script
org.openhab.core.test;version='[4.0.0,4.0.1)',\
org.openhab.core.thing;version='[4.0.0,4.0.1)',\
org.openhab.core.transform;version='[4.0.0,4.0.1)',\
- org.openhab.core.voice;version='[4.0.0,4.0.1)',\
- com.google.gson;version='[2.9.1,2.9.2)',\
- io.github.classgraph;version='[4.8.149,4.8.150)',\
- org.eclipse.equinox.common;version='[3.16.200,3.16.201)',\
- org.eclipse.xtend.lib;version='[2.29.0,2.29.1)',\
- org.eclipse.xtend.lib.macro;version='[2.29.0,2.29.1)',\
- org.eclipse.xtext;version='[2.29.0,2.29.1)',\
- org.eclipse.xtext.common.types;version='[2.29.0,2.29.1)',\
- org.eclipse.xtext.util;version='[2.29.0,2.29.1)',\
- org.eclipse.xtext.xbase;version='[2.29.0,2.29.1)',\
- org.eclipse.xtext.xbase.lib;version='[2.29.0,2.29.1)',\
- org.objectweb.asm;version='[9.4.0,9.4.1)'
+ org.openhab.core.voice;version='[4.0.0,4.0.1)'
diff --git a/itests/org.openhab.core.model.thing.tests/itest.bndrun b/itests/org.openhab.core.model.thing.tests/itest.bndrun
index 36b7c226b..f28f44830 100644
--- a/itests/org.openhab.core.model.thing.tests/itest.bndrun
+++ b/itests/org.openhab.core.model.thing.tests/itest.bndrun
@@ -81,6 +81,18 @@ Fragment-Host: org.openhab.core.model.thing
ch.qos.logback.classic;version='[1.2.11,1.2.12)',\
ch.qos.logback.core;version='[1.2.11,1.2.12)',\
biz.aQute.tester.junit-platform;version='[6.4.0,6.4.1)',\
+ com.google.gson;version='[2.9.1,2.9.2)',\
+ io.github.classgraph;version='[4.8.149,4.8.150)',\
+ org.apache.log4j;version='[1.2.19,1.2.20)',\
+ org.eclipse.equinox.common;version='[3.16.200,3.16.201)',\
+ org.eclipse.xtend.lib;version='[2.29.0,2.29.1)',\
+ org.eclipse.xtend.lib.macro;version='[2.29.0,2.29.1)',\
+ org.eclipse.xtext;version='[2.29.0,2.29.1)',\
+ org.eclipse.xtext.common.types;version='[2.29.0,2.29.1)',\
+ org.eclipse.xtext.util;version='[2.29.0,2.29.1)',\
+ org.eclipse.xtext.xbase;version='[2.29.0,2.29.1)',\
+ org.eclipse.xtext.xbase.lib;version='[2.29.0,2.29.1)',\
+ org.objectweb.asm;version='[9.4.0,9.4.1)',\
org.openhab.core;version='[4.0.0,4.0.1)',\
org.openhab.core.audio;version='[4.0.0,4.0.1)',\
org.openhab.core.automation;version='[4.0.0,4.0.1)',\
@@ -110,15 +122,4 @@ Fragment-Host: org.openhab.core.model.thing
org.openhab.core.thing;version='[4.0.0,4.0.1)',\
org.openhab.core.thing.xml;version='[4.0.0,4.0.1)',\
org.openhab.core.transform;version='[4.0.0,4.0.1)',\
- org.openhab.core.voice;version='[4.0.0,4.0.1)',\
- com.google.gson;version='[2.9.1,2.9.2)',\
- io.github.classgraph;version='[4.8.149,4.8.150)',\
- org.eclipse.equinox.common;version='[3.16.200,3.16.201)',\
- org.eclipse.xtend.lib;version='[2.29.0,2.29.1)',\
- org.eclipse.xtend.lib.macro;version='[2.29.0,2.29.1)',\
- org.eclipse.xtext;version='[2.29.0,2.29.1)',\
- org.eclipse.xtext.common.types;version='[2.29.0,2.29.1)',\
- org.eclipse.xtext.util;version='[2.29.0,2.29.1)',\
- org.eclipse.xtext.xbase;version='[2.29.0,2.29.1)',\
- org.eclipse.xtext.xbase.lib;version='[2.29.0,2.29.1)',\
- org.objectweb.asm;version='[9.4.0,9.4.1)'
+ org.openhab.core.voice;version='[4.0.0,4.0.1)'
diff --git a/itests/org.openhab.core.thing.xml.tests/itest.bndrun b/itests/org.openhab.core.thing.xml.tests/itest.bndrun
index ef4e1a05b..c58811161 100644
--- a/itests/org.openhab.core.thing.xml.tests/itest.bndrun
+++ b/itests/org.openhab.core.thing.xml.tests/itest.bndrun
@@ -5,7 +5,7 @@ Fragment-Host: org.openhab.core.thing.xml
-runrequires: \
bnd.identity;id='org.openhab.core.thing.xml.tests',\
- bnd.identity;id='org.openhab.core.binding.xml'
+ bnd.identity;id='org.openhab.core.addon.xml'
#
# done
@@ -49,13 +49,13 @@ Fragment-Host: org.openhab.core.thing.xml
ch.qos.logback.classic;version='[1.2.11,1.2.12)',\
ch.qos.logback.core;version='[1.2.11,1.2.12)',\
biz.aQute.tester.junit-platform;version='[6.4.0,6.4.1)',\
+ com.google.gson;version='[2.9.1,2.9.2)',\
org.openhab.core;version='[4.0.0,4.0.1)',\
- org.openhab.core.binding.xml;version='[4.0.0,4.0.1)',\
+ org.openhab.core.addon.xml;version='[4.0.0,4.0.1)',\
org.openhab.core.config.core;version='[4.0.0,4.0.1)',\
org.openhab.core.config.xml;version='[4.0.0,4.0.1)',\
org.openhab.core.io.console;version='[4.0.0,4.0.1)',\
org.openhab.core.test;version='[4.0.0,4.0.1)',\
org.openhab.core.thing;version='[4.0.0,4.0.1)',\
org.openhab.core.thing.xml;version='[4.0.0,4.0.1)',\
- org.openhab.core.thing.xml.tests;version='[4.0.0,4.0.1)',\
- com.google.gson;version='[2.9.1,2.9.2)'
+ org.openhab.core.thing.xml.tests;version='[4.0.0,4.0.1)'
diff --git a/itests/pom.xml b/itests/pom.xml
index 89d9d28b0..e2f28f2dc 100644
--- a/itests/pom.xml
+++ b/itests/pom.xml
@@ -24,7 +24,7 @@
org.openhab.core.automation.module.timer.tests
org.openhab.core.automation.module.script.tests
org.openhab.core.automation.integration.tests
- org.openhab.core.binding.xml.tests
+ org.openhab.core.addon.xml.tests
org.openhab.core.config.core.tests
org.openhab.core.config.discovery.mdns.tests
org.openhab.core.config.discovery.tests
diff --git a/tools/archetype/binding/src/main/resources/archetype-resources/src/main/resources/OH-INF/addon/addon.xml b/tools/archetype/binding/src/main/resources/archetype-resources/src/main/resources/OH-INF/addon/addon.xml
new file mode 100644
index 000000000..2f07c8d19
--- /dev/null
+++ b/tools/archetype/binding/src/main/resources/archetype-resources/src/main/resources/OH-INF/addon/addon.xml
@@ -0,0 +1,10 @@
+
+
+
+ binding
+ ${bindingIdCamelCase} Binding
+ This is the binding for ${bindingIdCamelCase}.
+
+
diff --git a/tools/archetype/binding/src/main/resources/archetype-resources/src/main/resources/OH-INF/binding/binding.xml b/tools/archetype/binding/src/main/resources/archetype-resources/src/main/resources/OH-INF/binding/binding.xml
deleted file mode 100644
index 8fad179c6..000000000
--- a/tools/archetype/binding/src/main/resources/archetype-resources/src/main/resources/OH-INF/binding/binding.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
- ${bindingIdCamelCase} Binding
- This is the binding for ${bindingIdCamelCase}.
-
-
diff --git a/tools/i18n-plugin/pom.xml b/tools/i18n-plugin/pom.xml
index aa543af71..6cbe6e1b4 100644
--- a/tools/i18n-plugin/pom.xml
+++ b/tools/i18n-plugin/pom.xml
@@ -51,7 +51,7 @@