From ace610baa94d47c45f17eb8a3cbdc3e7ed21ab39 Mon Sep 17 00:00:00 2001 From: "Jan N. Klug" Date: Thu, 2 Jun 2022 00:31:14 +0200 Subject: [PATCH 1/8] Introduce addon.xml Signed-off-by: Jan N. Klug --- bom/openhab-core/pom.xml | 2 +- .../.classpath | 0 .../.project | 0 .../NOTICE | 0 .../addon-1.0.0.xsd | 70 ++++++ .../pom.xml | 4 +- .../xml/internal/AddonInfoConverter.java | 115 +++++++++ .../addon/xml/internal/AddonInfoReader.java} | 20 +- .../xml/internal/AddonInfoXmlProvider.java} | 39 ++- .../xml/internal/AddonInfoXmlResult.java | 31 +++ .../AddonXmlConfigDescriptionProvider.java} | 9 +- .../xml/internal/XmlAddonInfoProvider.java | 107 ++++++++ .../binding-1.0.0.xsd | 26 -- .../xml/internal/BindingInfoConverter.java | 119 --------- .../xml/internal/BindingInfoXmlResult.java | 52 ---- .../xml/internal/XmlBindingInfoProvider.java | 120 --------- .../core/internal/addons/AddonResource.java | 104 +++++++- .../internal/binding/BindingResource.java | 216 ---------------- .../core/karaf/internal/FeatureInstaller.java | 21 +- .../karaf/internal/KarafAddonService.java | 130 +++++----- .../src/main/resources/OH-INF/addon/addon.xml | 10 + .../java/org/openhab/core/addon/Addon.java | 23 +- .../AddonI18nLocalizationService.java} | 30 +-- .../org/openhab/core/addon/AddonInfo.java | 234 ++++++++++++++++++ .../AddonInfoProvider.java} | 14 +- .../openhab/core/addon/AddonInfoRegistry.java | 95 +++++++ .../org/openhab/core/addon/AddonType.java | 12 +- .../org/openhab/core/binding/BindingInfo.java | 137 ---------- .../core/binding/BindingInfoRegistry.java | 108 -------- .../core/binding/dto/BindingInfoDTO.java | 38 --- .../addon/AddonI18nUtil.java} | 8 +- bundles/pom.xml | 2 +- .../openhab-core/src/main/feature/feature.xml | 2 +- .../.classpath | 0 .../.project | 0 .../NOTICE | 0 .../itest.bndrun | 12 +- .../pom.xml | 4 +- .../addon/xml/test/AddonInfoI18nTest.java} | 56 ++--- .../core/addon/xml/test/AddonInfoTest.java} | 67 ++--- .../core/addon/xml/test/AddonInstaller.java} | 23 +- .../OH-INF/addon/addon.xml} | 9 +- .../OH-INF/thing/thing-types.xml | 0 .../OH-INF/addon/addon.xml} | 11 +- .../OH-INF/thing/thing-types.xml | 0 .../acmeweather.bundle/OH-INF/addon/addon.xml | 11 + .../OH-INF/i18n/acmeweather_de.properties | 0 .../OH-INF/i18n/acmeweather_nl.properties | 0 .../itest.bndrun | 4 +- .../OH-INF/binding/binding.xml | 10 - .../itest.bndrun | 4 +- .../itest.bndrun | 4 +- .../itest.bndrun | 4 +- .../itest.bndrun | 4 +- .../itest.bndrun | 4 +- .../itest.bndrun | 10 +- .../itest.bndrun | 25 +- .../itest.bndrun | 25 +- .../itest.bndrun | 25 +- .../itest.bndrun | 25 +- .../itest.bndrun | 25 +- .../itest.bndrun | 8 +- itests/pom.xml | 2 +- .../src/main/resources/OH-INF/addon/addon.xml | 10 + .../main/resources/OH-INF/binding/binding.xml | 9 - tools/i18n-plugin/pom.xml | 2 +- .../core/tools/i18n/plugin/BundleInfo.java | 22 +- .../tools/i18n/plugin/BundleInfoReader.java | 30 +-- .../GenerateDefaultTranslationsMojo.java | 2 +- .../plugin/XmlToTranslationsConverter.java | 58 ++--- .../i18n/plugin/BundleInfoReaderTest.java | 22 +- .../GenerateDefaultTranslationsMojoTest.java | 4 +- ...PropertiesToTranslationsConverterTest.java | 6 +- .../XmlToTranslationsConverterTest.java | 6 +- .../acmeweather.bundle/OH-INF/addon/addon.xml | 10 + .../OH-INF/binding/binding.xml | 9 - .../i18n/acmeweather.generated.properties | 6 +- .../OH-INF/i18n/acmeweather.properties | 6 +- .../OH-INF/i18n/acmeweather_de.properties | 6 +- 79 files changed, 1195 insertions(+), 1283 deletions(-) rename bundles/{org.openhab.core.binding.xml => org.openhab.core.addon.xml}/.classpath (100%) rename bundles/{org.openhab.core.binding.xml => org.openhab.core.addon.xml}/.project (100%) rename bundles/{org.openhab.core.binding.xml => org.openhab.core.addon.xml}/NOTICE (100%) create mode 100644 bundles/org.openhab.core.addon.xml/addon-1.0.0.xsd rename bundles/{org.openhab.core.binding.xml => org.openhab.core.addon.xml}/pom.xml (86%) create mode 100644 bundles/org.openhab.core.addon.xml/src/main/java/org/openhab/core/addon/xml/internal/AddonInfoConverter.java rename bundles/{org.openhab.core.binding.xml/src/main/java/org/openhab/core/binding/xml/internal/BindingInfoReader.java => org.openhab.core.addon.xml/src/main/java/org/openhab/core/addon/xml/internal/AddonInfoReader.java} (82%) rename bundles/{org.openhab.core.binding.xml/src/main/java/org/openhab/core/binding/xml/internal/BindingInfoXmlProvider.java => org.openhab.core.addon.xml/src/main/java/org/openhab/core/addon/xml/internal/AddonInfoXmlProvider.java} (59%) create mode 100644 bundles/org.openhab.core.addon.xml/src/main/java/org/openhab/core/addon/xml/internal/AddonInfoXmlResult.java rename bundles/{org.openhab.core.binding.xml/src/main/java/org/openhab/core/binding/xml/internal/BindingXmlConfigDescriptionProvider.java => org.openhab.core.addon.xml/src/main/java/org/openhab/core/addon/xml/internal/AddonXmlConfigDescriptionProvider.java} (78%) create mode 100644 bundles/org.openhab.core.addon.xml/src/main/java/org/openhab/core/addon/xml/internal/XmlAddonInfoProvider.java delete mode 100644 bundles/org.openhab.core.binding.xml/binding-1.0.0.xsd delete mode 100644 bundles/org.openhab.core.binding.xml/src/main/java/org/openhab/core/binding/xml/internal/BindingInfoConverter.java delete mode 100644 bundles/org.openhab.core.binding.xml/src/main/java/org/openhab/core/binding/xml/internal/BindingInfoXmlResult.java delete mode 100644 bundles/org.openhab.core.binding.xml/src/main/java/org/openhab/core/binding/xml/internal/XmlBindingInfoProvider.java delete mode 100644 bundles/org.openhab.core.io.rest.core/src/main/java/org/openhab/core/io/rest/core/internal/binding/BindingResource.java create mode 100644 bundles/org.openhab.core.test.magic/src/main/resources/OH-INF/addon/addon.xml rename bundles/org.openhab.core/src/main/java/org/openhab/core/{binding/i18n/BindingI18nLocalizationService.java => addon/AddonI18nLocalizationService.java} (50%) create mode 100644 bundles/org.openhab.core/src/main/java/org/openhab/core/addon/AddonInfo.java rename bundles/org.openhab.core/src/main/java/org/openhab/core/{binding/BindingInfoProvider.java => addon/AddonInfoProvider.java} (74%) create mode 100644 bundles/org.openhab.core/src/main/java/org/openhab/core/addon/AddonInfoRegistry.java delete mode 100644 bundles/org.openhab.core/src/main/java/org/openhab/core/binding/BindingInfo.java delete mode 100644 bundles/org.openhab.core/src/main/java/org/openhab/core/binding/BindingInfoRegistry.java delete mode 100644 bundles/org.openhab.core/src/main/java/org/openhab/core/binding/dto/BindingInfoDTO.java rename bundles/org.openhab.core/src/main/java/org/openhab/core/{binding/internal/i18n/BindingI18nUtil.java => internal/addon/AddonI18nUtil.java} (88%) rename itests/{org.openhab.core.binding.xml.tests => org.openhab.core.addon.xml.tests}/.classpath (100%) rename itests/{org.openhab.core.binding.xml.tests => org.openhab.core.addon.xml.tests}/.project (100%) rename itests/{org.openhab.core.binding.xml.tests => org.openhab.core.addon.xml.tests}/NOTICE (100%) rename itests/{org.openhab.core.binding.xml.tests => org.openhab.core.addon.xml.tests}/itest.bndrun (88%) rename itests/{org.openhab.core.binding.xml.tests => org.openhab.core.addon.xml.tests}/pom.xml (78%) rename itests/{org.openhab.core.binding.xml.tests/src/main/java/org/openhab/core/binding/xml/test/BindingInfoI18nTest.java => org.openhab.core.addon.xml.tests/src/main/java/org/openhab/core/addon/xml/test/AddonInfoI18nTest.java} (65%) rename itests/{org.openhab.core.binding.xml.tests/src/main/java/org/openhab/core/binding/xml/test/BindingInfoTest.java => org.openhab.core.addon.xml.tests/src/main/java/org/openhab/core/addon/xml/test/AddonInfoTest.java} (59%) rename itests/{org.openhab.core.binding.xml.tests/src/main/java/org/openhab/core/binding/xml/test/BindingInstaller.java => org.openhab.core.addon.xml.tests/src/main/java/org/openhab/core/addon/xml/test/AddonInstaller.java} (65%) rename itests/{org.openhab.core.binding.xml.tests/src/main/resources/test-bundle-pool/BundleInfoTest.bundle/OH-INF/binding/binding.xml => org.openhab.core.addon.xml.tests/src/main/resources/test-bundle-pool/BundleInfoTest.bundle/OH-INF/addon/addon.xml} (73%) rename itests/{org.openhab.core.binding.xml.tests => org.openhab.core.addon.xml.tests}/src/main/resources/test-bundle-pool/BundleInfoTest.bundle/OH-INF/thing/thing-types.xml (100%) rename itests/{org.openhab.core.binding.xml.tests/src/main/resources/test-bundle-pool/BundleInfoTestNoAuthor.bundle/OH-INF/binding/binding.xml => org.openhab.core.addon.xml.tests/src/main/resources/test-bundle-pool/BundleInfoTestNoAuthor.bundle/OH-INF/addon/addon.xml} (69%) rename itests/{org.openhab.core.binding.xml.tests => org.openhab.core.addon.xml.tests}/src/main/resources/test-bundle-pool/BundleInfoTestNoAuthor.bundle/OH-INF/thing/thing-types.xml (100%) create mode 100644 itests/org.openhab.core.addon.xml.tests/src/main/resources/test-bundle-pool/acmeweather.bundle/OH-INF/addon/addon.xml rename itests/{org.openhab.core.binding.xml.tests => org.openhab.core.addon.xml.tests}/src/main/resources/test-bundle-pool/acmeweather.bundle/OH-INF/i18n/acmeweather_de.properties (100%) rename itests/{org.openhab.core.binding.xml.tests => org.openhab.core.addon.xml.tests}/src/main/resources/test-bundle-pool/acmeweather.bundle/OH-INF/i18n/acmeweather_nl.properties (100%) delete mode 100644 itests/org.openhab.core.binding.xml.tests/src/main/resources/test-bundle-pool/acmeweather.bundle/OH-INF/binding/binding.xml create mode 100644 tools/archetype/binding/src/main/resources/archetype-resources/src/main/resources/OH-INF/addon/addon.xml delete mode 100644 tools/archetype/binding/src/main/resources/archetype-resources/src/main/resources/OH-INF/binding/binding.xml create mode 100644 tools/i18n-plugin/src/test/resources/acmeweather.bundle/OH-INF/addon/addon.xml delete mode 100644 tools/i18n-plugin/src/test/resources/acmeweather.bundle/OH-INF/binding/binding.xml diff --git a/bom/openhab-core/pom.xml b/bom/openhab-core/pom.xml index 85a48752fbd..abbed4f491c 100644 --- a/bom/openhab-core/pom.xml +++ b/bom/openhab-core/pom.xml @@ -66,7 +66,7 @@ org.openhab.core.bundles - org.openhab.core.binding.xml + org.openhab.core.addon.xml ${project.version} compile diff --git a/bundles/org.openhab.core.binding.xml/.classpath b/bundles/org.openhab.core.addon.xml/.classpath similarity index 100% rename from bundles/org.openhab.core.binding.xml/.classpath rename to bundles/org.openhab.core.addon.xml/.classpath diff --git a/bundles/org.openhab.core.binding.xml/.project b/bundles/org.openhab.core.addon.xml/.project similarity index 100% rename from bundles/org.openhab.core.binding.xml/.project rename to bundles/org.openhab.core.addon.xml/.project diff --git a/bundles/org.openhab.core.binding.xml/NOTICE b/bundles/org.openhab.core.addon.xml/NOTICE similarity index 100% rename from bundles/org.openhab.core.binding.xml/NOTICE rename to bundles/org.openhab.core.addon.xml/NOTICE diff --git a/bundles/org.openhab.core.addon.xml/addon-1.0.0.xsd b/bundles/org.openhab.core.addon.xml/addon-1.0.0.xsd new file mode 100644 index 00000000000..af9336341b0 --- /dev/null +++ b/bundles/org.openhab.core.addon.xml/addon-1.0.0.xsd @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + The organization maintaining the add-on (e.g. openHAB). Individual developer names should be avoided. + + + + + + Comma-separated list of two-letter ISO country codes. + + + + + The ID (service.pid or component.name) of the main add-on service, which can be configured through OSGi configuration admin service. Should only be used in combination with a config description definition. The default value is <type>.<name> + + + + + + + + + + The id is used to construct the UID of this add-on to <type>-<name> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bundles/org.openhab.core.binding.xml/pom.xml b/bundles/org.openhab.core.addon.xml/pom.xml similarity index 86% rename from bundles/org.openhab.core.binding.xml/pom.xml rename to bundles/org.openhab.core.addon.xml/pom.xml index c5cdb62835a..de04645697a 100644 --- a/bundles/org.openhab.core.binding.xml/pom.xml +++ b/bundles/org.openhab.core.addon.xml/pom.xml @@ -10,9 +10,9 @@ 4.0.0-SNAPSHOT - org.openhab.core.binding.xml + org.openhab.core.addon.xml - openHAB Core :: Bundles :: Binding XML + openHAB Core :: Bundles :: Add-on XML diff --git a/bundles/org.openhab.core.addon.xml/src/main/java/org/openhab/core/addon/xml/internal/AddonInfoConverter.java b/bundles/org.openhab.core.addon.xml/src/main/java/org/openhab/core/addon/xml/internal/AddonInfoConverter.java new file mode 100644 index 00000000000..f2af9fe5c9c --- /dev/null +++ b/bundles/org.openhab.core.addon.xml/src/main/java/org/openhab/core/addon/xml/internal/AddonInfoConverter.java @@ -0,0 +1,115 @@ +/** + * Copyright (c) 2010-2022 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.net.URI; +import java.util.List; +import java.util.Map; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.openhab.core.addon.AddonInfo; +import org.openhab.core.config.core.ConfigDescription; +import org.openhab.core.config.core.ConfigDescriptionBuilder; +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.Converter; +import com.thoughtworks.xstream.converters.UnmarshallingContext; +import com.thoughtworks.xstream.io.HierarchicalStreamReader; + +/** + * The {@link AddonInfoConverter} is a concrete implementation of the {@code XStream} {@link Converter} interface used + * to convert binding information within an XML document into a {@link AddonInfoXmlResult} object. + * This converter converts {@code addon} XML tags. + * + * @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 AddonInfoConverter extends GenericUnmarshaller { + private static final String CONFIG_DESCRIPTION_URI_PLACEHOLDER = "addonInfoConverter:placeHolder"; + private final ConverterAttributeMapValidator attributeMapValidator; + + public AddonInfoConverter() { + super(AddonInfoXmlResult.class); + + attributeMapValidator = new ConverterAttributeMapValidator(Map.of("id", true, "schemaLocation", false)); + } + + private @Nullable ConfigDescription readConfigDescription(NodeIterator nodeIterator) { + Object nextNode = nodeIterator.next(); + + if (nextNode != null) { + if (nextNode instanceof ConfigDescription configDescription) { + return configDescription; + } + + 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", 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 82% 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 0cd1e155933..42b2eae0bbd 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 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 BindingInfoReader() { 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 @@ protected void registerConverters(XStream xstream) { @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 @@ protected void registerAliases(XStream xstream) { xstream.alias("option", NodeValue.class); xstream.alias("filter", List.class); xstream.alias("criteria", FilterCriteria.class); + xstream.alias("config-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 5da7384ff9b..93bac7bdfc4 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.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 BindingInfoXmlProvider(Bundle bundle, XmlBindingInfoProvider bindingInfoP } this.bundle = bundle; - this.bindingInfoProvider = bindingInfoProvider; + this.addonInfoProvider = addonInfoProvider; this.configDescriptionProvider = configDescriptionProvider; } @Override - public synchronized void addingObject(BindingInfoXmlResult bindingInfoXmlResult) { - ConfigDescription configDescription = bindingInfoXmlResult.getConfigDescription(); + public synchronized void addingObject(AddonInfoXmlResult addonInfoXmlResult) { + ConfigDescription configDescription = addonInfoXmlResult.configDescription(); if (configDescription != null) { try { @@ -78,7 +75,7 @@ public synchronized void addingObject(BindingInfoXmlResult bindingInfoXmlResult) } } - bindingInfoProvider.add(bundle, bindingInfoXmlResult.getBindingInfo()); + addonInfoProvider.add(bundle, addonInfoXmlResult.addonInfo()); } @Override @@ -88,7 +85,7 @@ public void addingFinished() { @Override public synchronized void release() { - this.bindingInfoProvider.removeAll(bundle); + this.addonInfoProvider.removeAll(bundle); this.configDescriptionProvider.removeAll(bundle); } } diff --git a/bundles/org.openhab.core.addon.xml/src/main/java/org/openhab/core/addon/xml/internal/AddonInfoXmlResult.java b/bundles/org.openhab.core.addon.xml/src/main/java/org/openhab/core/addon/xml/internal/AddonInfoXmlResult.java new file mode 100644 index 00000000000..f618a67c3a3 --- /dev/null +++ b/bundles/org.openhab.core.addon.xml/src/main/java/org/openhab/core/addon/xml/internal/AddonInfoXmlResult.java @@ -0,0 +1,31 @@ +/** + * Copyright (c) 2010-2022 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 org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.openhab.core.addon.AddonInfo; +import org.openhab.core.config.core.ConfigDescription; +import org.openhab.core.config.core.ConfigDescriptionProvider; + +/** + * The {@link AddonInfoXmlResult} is an intermediate XML conversion result object which + * contains a mandatory {@link AddonInfo} and an optional {@link ConfigDescription} object. + *

+ * 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 cbb0bb5a7c8..f21cb22b919 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 @@ * 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 00000000000..0d2af9c5e31 --- /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-2022 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 fb11dbb77e2..00000000000 --- 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 ed6cf6a2373..00000000000 --- 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 d1b2dff4548..00000000000 --- 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 562c52b67a8..00000000000 --- 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 951270796cd..d760f2a3616 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.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.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 Response uninstallAddon(final @PathParam("addonId") @Parameter(descriptio 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-onconfiguration for given binding 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 int compare(AddonType o1, AddonType o2) { 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 449f3877e71..00000000000 --- 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 baac35eaa3a..09b275bc4fa 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 @@ private synchronized void processConfigQueue() { } } - @Nullable - String getCurrentPackage() { - return currentPackage; - } - public void addAddon(String type, String id) { try { changeAddonConfig(type, id, Collection::add); @@ -399,11 +389,11 @@ private boolean installAddons(final Map config) { 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 +521,8 @@ private void uninstallFeature(String name) { 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 ad04d5024c1..7279095fa58 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 @@ * @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 void refreshSource() { } @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 @@ private boolean isAddon(Feature feature) { } @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 Addon getAddon(String id, Locale locale) { } } + 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); - // 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()); + 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)); + } - 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,7 +163,7 @@ public void uninstall(String id) { } @Override - public String getAddonId(URI addonURI) { + public @Nullable String getAddonId(URI addonURI) { return null; } @@ -198,12 +180,12 @@ private String substringBefore(String str, String separator) { private String getType(String name) { return substringBefore( name.startsWith(FeatureInstaller.PREFIX) ? name.substring(FeatureInstaller.PREFIX.length()) : name, - "-"); + Addon.ADDON_SEPARATOR); } private String getName(String name) { return substringAfter( name.startsWith(FeatureInstaller.PREFIX) ? name.substring(FeatureInstaller.PREFIX.length()) : name, - "-"); + Addon.ADDON_SEPARATOR); } } 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 00000000000..9e65ce333dc --- /dev/null +++ b/bundles/org.openhab.core.test.magic/src/main/resources/OH-INF/addon/addon.xml @@ -0,0 +1,10 @@ + + + + core + 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 7c29ee40308..b6158f681f3 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 @@ */ 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 String getId() { return id; } + public String getUID() { + return type + ADDON_SEPARATOR + id; + } + /** * The label of the add-on */ @@ -207,9 +212,9 @@ public String getKeywords() { } /** - * 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 String getCountries() { } /** - * 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 static class Builder { 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 Builder withKeywords(String keywords) { 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/binding/i18n/BindingI18nLocalizationService.java b/bundles/org.openhab.core/src/main/java/org/openhab/core/addon/AddonI18nLocalizationService.java similarity index 50% rename from bundles/org.openhab.core/src/main/java/org/openhab/core/binding/i18n/BindingI18nLocalizationService.java rename to bundles/org.openhab.core/src/main/java/org/openhab/core/addon/AddonI18nLocalizationService.java index 96b80a0d39d..869ede8feff 100644 --- 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/addon/AddonI18nLocalizationService.java @@ -10,15 +10,14 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.openhab.core.binding.i18n; +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.binding.BindingInfo; -import org.openhab.core.binding.internal.i18n.BindingI18nUtil; 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; @@ -30,33 +29,30 @@ * * @author Christoph Weitkamp - Initial contribution */ -@Component(immediate = true, service = { BindingI18nLocalizationService.class }) +@Component(immediate = true, service = { AddonI18nLocalizationService.class }) @NonNullByDefault -public class BindingI18nLocalizationService { +public class AddonI18nLocalizationService { - private final BindingI18nUtil bindingI18nUtil; + private final AddonI18nUtil addonI18NUtil; @Activate - public BindingI18nLocalizationService(final @Reference TranslationProvider i18nProvider) { - this.bindingI18nUtil = new BindingI18nUtil(i18nProvider); + public AddonI18nLocalizationService(final @Reference TranslationProvider i18nProvider) { + this.addonI18NUtil = new AddonI18nUtil(i18nProvider); } /** * Localizes a binding info. * * @param bundle the bundle the i18n resources are located - * @param bindingInfo the binding info that should be localized + * @param addonInfo 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); + 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 new BindingInfo(bindingInfoUID, name == null ? bindingInfo.getName() : name, - description == null ? bindingInfo.getDescription() : description, bindingInfo.getAuthor(), - bindingInfo.getServiceId(), bindingInfo.getConfigDescriptionURI()); + 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 00000000000..0b3eccb50c2 --- /dev/null +++ b/bundles/org.openhab.core/src/main/java/org/openhab/core/addon/AddonInfo.java @@ -0,0 +1,234 @@ +/** + * Copyright (c) 2010-2022 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 binding (e.g. "HUE Binding"). + * + * @return a human-readable name for the binding (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 binding + * (e.g. "Discovers and controls HUE bulbs"). + * + * @return a human-readable description for the binding + */ + public 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 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 15c973a80f0..edd8b095883 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.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 00000000000..a6768cf861e --- /dev/null +++ b/bundles/org.openhab.core/src/main/java/org/openhab/core/addon/AddonInfoRegistry.java @@ -0,0 +1,95 @@ +/** + * Copyright (c) 2010-2022 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 b3ae1f572d7..1b1cc139cd6 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 String getLabel() { 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 boolean equals(@Nullable Object obj) { 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 24fe0ebccce..00000000000 --- 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 e5380a22e82..00000000000 --- 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 931c53dc74d..00000000000 --- 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/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 faac67cd4f8..30c5d9cfd25 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.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 eca213a2826..8e1bc050341 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 2e66b033b6d..b60919acc62 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 100% rename from itests/org.openhab.core.binding.xml.tests/.project rename to itests/org.openhab.core.addon.xml.tests/.project 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 dd36440443b..9739940edaa 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 583002f080a..077be84c2e5 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 948516c6cf3..a0127836bc7 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 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 @@ * @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(); - - assertThat(bindingInfo, is(notNullValue())); - assertThat(bindingInfo.getName(), is("ACME Wetter Binding")); - assertThat(bindingInfo.getDescription(), is( + public void assertAddonInfosWereLocalizedInGerman() throws Exception { + addonInstaller.exec(TEST_BUNDLE_NAME, () -> { + Set addonInfos = addonInfoRegistry.getAddonInfos(Locale.GERMAN); + AddonInfo addonInfo = addonInfos.iterator().next(); + + 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 void assertBindingInfosWereLocalizedInDutch() throws Exception { } @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 void assertUsingDefaultLocale() throws Exception { 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 97264902900..48dc4fa65e2 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 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 @@ * @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 1c1f59b888c..1191916bdb7 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 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 @@ * @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 6940e76f952..1b1a3696de9 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 c56096372cb..7a7260c91be 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 00000000000..1fd540c81aa --- /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 c1441984103..74bcd28658b 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 2e6dce5f0d3..00000000000 --- 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 4a048818589..7bf217cabe2 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 ffeee45ee31..3e4696ae33e 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 a1312541761..8855441cbfb 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 1767a82c1f6..0b72b3e931e 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 0e1d8a106d3..34f9e0dd014 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 0e5def6cf24..b1d832b9362 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 d1028e5099a..0dd9e71b735 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 f8662cbd777..45214d26624 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 a1eaa70cffd..4f107073fd7 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 4c4db2a3975..82e445df389 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 36b7c226bc4..f28f44830f0 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 ef4e1a05ba1..c588111615c 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 89d9d28b00e..e2f28f2dc70 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 00000000000..2f07c8d19b4 --- /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 8fad179c6fb..00000000000 --- 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 aa543af718a..6cbe6e1b4ba 100644 --- a/tools/i18n-plugin/pom.xml +++ b/tools/i18n-plugin/pom.xml @@ -51,7 +51,7 @@ org.openhab.core.bundles - org.openhab.core.binding.xml + org.openhab.core.addon.xml ${project.version} diff --git a/tools/i18n-plugin/src/main/java/org/openhab/core/tools/i18n/plugin/BundleInfo.java b/tools/i18n-plugin/src/main/java/org/openhab/core/tools/i18n/plugin/BundleInfo.java index c7214758667..c36cf61895f 100644 --- a/tools/i18n-plugin/src/main/java/org/openhab/core/tools/i18n/plugin/BundleInfo.java +++ b/tools/i18n-plugin/src/main/java/org/openhab/core/tools/i18n/plugin/BundleInfo.java @@ -19,7 +19,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; -import org.openhab.core.binding.xml.internal.BindingInfoXmlResult; +import org.openhab.core.addon.xml.internal.AddonInfoXmlResult; import org.openhab.core.config.core.ConfigDescription; import org.openhab.core.thing.xml.internal.ChannelGroupTypeXmlResult; import org.openhab.core.thing.xml.internal.ChannelTypeXmlResult; @@ -35,8 +35,8 @@ @NonNullByDefault public class BundleInfo { - private String bindingId = ""; - private @Nullable BindingInfoXmlResult bindingInfoXml; + private String addonId = ""; + private @Nullable AddonInfoXmlResult addonInfoXml; private List configDescriptions = new ArrayList<>(5); private List channelGroupTypesXml = new ArrayList<>(5); private List channelTypesXml = new ArrayList<>(5); @@ -44,20 +44,20 @@ public class BundleInfo { private List moduleTypesJson = new ArrayList<>(5); private List ruleTemplateJson = new ArrayList<>(5); - public String getBindingId() { - return bindingId; + public String getAddonId() { + return addonId; } - public void setBindingId(String bindingId) { - this.bindingId = bindingId; + public void setAddonId(String addonId) { + this.addonId = addonId; } - public @Nullable BindingInfoXmlResult getBindingInfoXml() { - return bindingInfoXml; + public @Nullable AddonInfoXmlResult getAddonInfoXml() { + return addonInfoXml; } - public void setBindingInfoXml(BindingInfoXmlResult bindingInfo) { - this.bindingInfoXml = bindingInfo; + public void setAddonInfoXml(AddonInfoXmlResult addonInfo) { + this.addonInfoXml = addonInfo; } public List getConfigDescriptions() { diff --git a/tools/i18n-plugin/src/main/java/org/openhab/core/tools/i18n/plugin/BundleInfoReader.java b/tools/i18n-plugin/src/main/java/org/openhab/core/tools/i18n/plugin/BundleInfoReader.java index 4ce8f77a4e7..76ef82a2058 100644 --- a/tools/i18n-plugin/src/main/java/org/openhab/core/tools/i18n/plugin/BundleInfoReader.java +++ b/tools/i18n-plugin/src/main/java/org/openhab/core/tools/i18n/plugin/BundleInfoReader.java @@ -25,8 +25,8 @@ import org.apache.maven.plugin.logging.Log; import org.eclipse.jdt.annotation.NonNullByDefault; -import org.openhab.core.binding.xml.internal.BindingInfoReader; -import org.openhab.core.binding.xml.internal.BindingInfoXmlResult; +import org.openhab.core.addon.xml.internal.AddonInfoReader; +import org.openhab.core.addon.xml.internal.AddonInfoXmlResult; import org.openhab.core.config.core.ConfigDescription; import org.openhab.core.config.xml.internal.ConfigDescriptionReader; import org.openhab.core.thing.xml.internal.ChannelGroupTypeXmlResult; @@ -58,7 +58,7 @@ public BundleInfoReader(Log log) { public BundleInfo readBundleInfo(Path ohinfPath) throws IOException { BundleInfo bundleInfo = new BundleInfo(); - readBindingInfo(ohinfPath, bundleInfo); + readAddonInfo(ohinfPath, bundleInfo); readConfigInfo(ohinfPath, bundleInfo); readThingInfo(ohinfPath, bundleInfo); readModuleTypeInfo(ohinfPath, bundleInfo); @@ -73,16 +73,16 @@ private Stream xmlPathStream(Path ohinfPath, String directory) throws IOEx : Stream.of(); } - private void readBindingInfo(Path ohinfPath, BundleInfo bundleInfo) throws IOException { - BindingInfoReader reader = new BindingInfoReader(); - try (Stream xmlPathStream = xmlPathStream(ohinfPath, "binding")) { + private void readAddonInfo(Path ohinfPath, BundleInfo bundleInfo) throws IOException { + AddonInfoReader reader = new AddonInfoReader(); + try (Stream xmlPathStream = xmlPathStream(ohinfPath, "addon")) { xmlPathStream.forEach(path -> { log.info("Reading: " + path); try { - BindingInfoXmlResult bindingInfoXml = reader.readFromXML(path.toUri().toURL()); + AddonInfoXmlResult bindingInfoXml = reader.readFromXML(path.toUri().toURL()); if (bindingInfoXml != null) { - bundleInfo.setBindingId(bindingInfoXml.getBindingInfo().getUID()); - bundleInfo.setBindingInfoXml(bindingInfoXml); + bundleInfo.setAddonId(bindingInfoXml.addonInfo().getId()); + bundleInfo.setAddonInfoXml(bindingInfoXml); } } catch (ConversionException | MalformedURLException e) { log.warn("Exception while reading binding info from: " + path, e); @@ -119,20 +119,20 @@ private void readThingInfo(Path ohinfPath, BundleInfo bundleInfo) throws IOExcep if (type instanceof ThingTypeXmlResult) { ThingTypeXmlResult result = (ThingTypeXmlResult) type; bundleInfo.getThingTypesXml().add(result); - if (bundleInfo.getBindingId().isBlank()) { - bundleInfo.setBindingId(result.getUID().getBindingId()); + if (bundleInfo.getAddonId().isBlank()) { + bundleInfo.setAddonId(result.getUID().getBindingId()); } } else if (type instanceof ChannelGroupTypeXmlResult) { ChannelGroupTypeXmlResult result = (ChannelGroupTypeXmlResult) type; bundleInfo.getChannelGroupTypesXml().add(result); - if (bundleInfo.getBindingId().isBlank()) { - bundleInfo.setBindingId(result.getUID().getBindingId()); + if (bundleInfo.getAddonId().isBlank()) { + bundleInfo.setAddonId(result.getUID().getBindingId()); } } else if (type instanceof ChannelTypeXmlResult) { ChannelTypeXmlResult result = (ChannelTypeXmlResult) type; bundleInfo.getChannelTypesXml().add(result); - if (bundleInfo.getBindingId().isBlank()) { - bundleInfo.setBindingId(result.toChannelType().getUID().getBindingId()); + if (bundleInfo.getAddonId().isBlank()) { + bundleInfo.setAddonId(result.toChannelType().getUID().getBindingId()); } } } diff --git a/tools/i18n-plugin/src/main/java/org/openhab/core/tools/i18n/plugin/GenerateDefaultTranslationsMojo.java b/tools/i18n-plugin/src/main/java/org/openhab/core/tools/i18n/plugin/GenerateDefaultTranslationsMojo.java index f68c5f36a17..5089ba00ac2 100644 --- a/tools/i18n-plugin/src/main/java/org/openhab/core/tools/i18n/plugin/GenerateDefaultTranslationsMojo.java +++ b/tools/i18n-plugin/src/main/java/org/openhab/core/tools/i18n/plugin/GenerateDefaultTranslationsMojo.java @@ -86,7 +86,7 @@ public void execute() throws MojoFailureException { } private String propertiesFileName(BundleInfo bundleInfo) { - String name = bundleInfo.getBindingId(); + String name = bundleInfo.getAddonId(); if (name.isEmpty()) { Optional optional = bundleInfo.getConfigDescriptions().stream().findFirst(); if (optional.isPresent()) { diff --git a/tools/i18n-plugin/src/main/java/org/openhab/core/tools/i18n/plugin/XmlToTranslationsConverter.java b/tools/i18n-plugin/src/main/java/org/openhab/core/tools/i18n/plugin/XmlToTranslationsConverter.java index 5d47d7625cb..2f38f4ddee2 100644 --- a/tools/i18n-plugin/src/main/java/org/openhab/core/tools/i18n/plugin/XmlToTranslationsConverter.java +++ b/tools/i18n-plugin/src/main/java/org/openhab/core/tools/i18n/plugin/XmlToTranslationsConverter.java @@ -25,8 +25,8 @@ import java.util.stream.Stream.Builder; import org.eclipse.jdt.annotation.NonNullByDefault; -import org.openhab.core.binding.BindingInfo; -import org.openhab.core.binding.xml.internal.BindingInfoXmlResult; +import org.openhab.core.addon.AddonInfo; +import org.openhab.core.addon.xml.internal.AddonInfoXmlResult; import org.openhab.core.config.core.ConfigDescription; import org.openhab.core.config.core.ConfigDescriptionParameter; import org.openhab.core.config.core.ConfigDescriptionParameterGroup; @@ -54,14 +54,14 @@ public class XmlToTranslationsConverter { private static final Pattern OPTION_ESCAPE_PATTERN = Pattern.compile("([ :=])"); public Translations convert(BundleInfo bundleInfo) { - String bindingId = bundleInfo.getBindingId(); - return bindingId.isBlank() ? configTranslations(bundleInfo) : bindingTranslations(bundleInfo); + String addonId = bundleInfo.getAddonId(); + return addonId.isBlank() ? configTranslations(bundleInfo) : addonTranslations(bundleInfo); } - private Translations bindingTranslations(BundleInfo bundleInfo) { + private Translations addonTranslations(BundleInfo bundleInfo) { return Translations.translations( // - bindingSection(bundleInfo), // - bindingConfigSection(bundleInfo), // + addonSection(bundleInfo), // + addonConfigSection(bundleInfo), // thingTypesSection(bundleInfo), // thingTypesConfigSection(bundleInfo), // channelGroupTypesSection(bundleInfo), // @@ -85,39 +85,39 @@ private Translations configTranslations(BundleInfo bundleInfo) { return Translations.translations(section(groupsBuilder.build())); } - private TranslationsSection bindingSection(BundleInfo bundleInfo) { - String header = "binding"; - BindingInfoXmlResult bindingInfoXml = bundleInfo.getBindingInfoXml(); - if (bindingInfoXml == null) { + private TranslationsSection addonSection(BundleInfo bundleInfo) { + String header = "add-on"; + AddonInfoXmlResult addonInfoXml = bundleInfo.getAddonInfoXml(); + if (addonInfoXml == null) { return section(header); } - BindingInfo bindingInfo = bindingInfoXml.getBindingInfo(); - String bindingId = bundleInfo.getBindingId(); + AddonInfo addonInfo = addonInfoXml.addonInfo(); + String addonId = bundleInfo.getAddonId(); - String keyPrefix = String.format("binding.%s", bindingId); + String keyPrefix = String.format("addon.%s", addonId); return section(header, group( // - entry(String.format("%s.name", keyPrefix), bindingInfo.getName()), - entry(String.format("%s.description", keyPrefix), bindingInfo.getDescription()) // + entry(String.format("%s.name", keyPrefix), addonInfo.getName()), + entry(String.format("%s.description", keyPrefix), addonInfo.getDescription()) // )); } - private TranslationsSection bindingConfigSection(BundleInfo bundleInfo) { - String header = "binding config"; - BindingInfoXmlResult bindingInfoXml = bundleInfo.getBindingInfoXml(); - if (bindingInfoXml == null) { + private TranslationsSection addonConfigSection(BundleInfo bundleInfo) { + String header = "add-on config"; + AddonInfoXmlResult addonInfoXml = bundleInfo.getAddonInfoXml(); + if (addonInfoXml == null) { return section(header); } - ConfigDescription bindingConfig = bindingInfoXml.getConfigDescription(); - if (bindingConfig == null) { + ConfigDescription addonConfig = addonInfoXml.configDescription(); + if (addonConfig == null) { return section(header); } - String keyPrefix = String.format("binding.config.%s", bundleInfo.getBindingId()); + String keyPrefix = String.format("addon.config.%s", bundleInfo.getAddonId()); return section(header, - Stream.concat(configDescriptionGroupParameters(keyPrefix, bindingConfig.getParameterGroups()), - configDescriptionParameters(keyPrefix, bindingConfig.getParameters()))); + Stream.concat(configDescriptionGroupParameters(keyPrefix, addonConfig.getParameterGroups()), + configDescriptionParameters(keyPrefix, addonConfig.getParameters()))); } private TranslationsSection thingTypesSection(BundleInfo bundleInfo) { @@ -127,8 +127,8 @@ private TranslationsSection thingTypesSection(BundleInfo bundleInfo) { return section(header); } - String bindingId = bundleInfo.getBindingId(); - String keyPrefix = String.format("thing-type.%s", bindingId); + String addonId = bundleInfo.getAddonId(); + String keyPrefix = String.format("thing-type.%s", addonId); return section(header, thingTypesXml.stream().map(thingTypeXml -> { ThingType thingType = thingTypeXml.toThingType(); @@ -216,7 +216,7 @@ private TranslationsSection channelGroupTypesSection(BundleInfo bundleInfo) { return section(header); } - String keyPrefix = String.format("channel-group-type.%s", bundleInfo.getBindingId()); + String keyPrefix = String.format("channel-group-type.%s", bundleInfo.getAddonId()); return section(header, channelGroupTypesXml.stream().map(ChannelGroupTypeXmlResult::toChannelGroupType) .map(channelGroupType -> { @@ -258,7 +258,7 @@ private TranslationsSection channelTypesSection(BundleInfo bundleInfo) { return section(header); } - String keyPrefix = String.format("channel-type.%s", bundleInfo.getBindingId()); + String keyPrefix = String.format("channel-type.%s", bundleInfo.getAddonId()); return section(header, channelTypesXml.stream().map(channelTypeXml -> { ChannelType channelType = channelTypeXml.toChannelType(); diff --git a/tools/i18n-plugin/src/test/java/org/openhab/core/tools/i18n/plugin/BundleInfoReaderTest.java b/tools/i18n-plugin/src/test/java/org/openhab/core/tools/i18n/plugin/BundleInfoReaderTest.java index 4f17330550f..7e74b0de50f 100644 --- a/tools/i18n-plugin/src/test/java/org/openhab/core/tools/i18n/plugin/BundleInfoReaderTest.java +++ b/tools/i18n-plugin/src/test/java/org/openhab/core/tools/i18n/plugin/BundleInfoReaderTest.java @@ -21,7 +21,7 @@ import org.apache.maven.plugin.logging.SystemStreamLog; import org.eclipse.jdt.annotation.NonNullByDefault; import org.junit.jupiter.api.Test; -import org.openhab.core.binding.xml.internal.BindingInfoXmlResult; +import org.openhab.core.addon.xml.internal.AddonInfoXmlResult; /** * Tests {@link BundleInfoReader}. @@ -36,15 +36,15 @@ public void readBindingInfo() throws IOException { BundleInfoReader reader = new BundleInfoReader(new SystemStreamLog()); BundleInfo bundleInfo = reader.readBundleInfo(Path.of("src/test/resources/acmeweather.bundle/OH-INF")); - BindingInfoXmlResult bindingInfoXml = bundleInfo.getBindingInfoXml(); - assertThat(bindingInfoXml, is(notNullValue())); - if (bindingInfoXml != null) { - assertThat(bindingInfoXml.getBindingInfo().getName(), is("ACME Weather Binding")); - assertThat(bindingInfoXml.getBindingInfo().getDescription(), + AddonInfoXmlResult addonInfoXml = bundleInfo.getAddonInfoXml(); + assertThat(addonInfoXml, is(notNullValue())); + if (addonInfoXml != null) { + assertThat(addonInfoXml.addonInfo().getName(), is("ACME Weather Binding")); + assertThat(addonInfoXml.addonInfo().getDescription(), is("ACME Weather - Current weather and forecasts in your city.")); } - assertThat(bundleInfo.getBindingId(), is("acmeweather")); + assertThat(bundleInfo.getAddonId(), is("acmeweather")); assertThat(bundleInfo.getChannelGroupTypesXml().size(), is(1)); assertThat(bundleInfo.getChannelTypesXml().size(), is(2)); assertThat(bundleInfo.getConfigDescriptions().size(), is(1)); @@ -58,8 +58,8 @@ public void readGenericBundleInfo() throws IOException { BundleInfoReader reader = new BundleInfoReader(new SystemStreamLog()); BundleInfo bundleInfo = reader.readBundleInfo(Path.of("src/test/resources/acmetts.bundle/OH-INF")); - assertThat(bundleInfo.getBindingInfoXml(), is(nullValue())); - assertThat(bundleInfo.getBindingId(), is("")); + assertThat(bundleInfo.getAddonInfoXml(), is(nullValue())); + assertThat(bundleInfo.getAddonId(), is("")); assertThat(bundleInfo.getChannelGroupTypesXml().size(), is(0)); assertThat(bundleInfo.getChannelTypesXml().size(), is(0)); assertThat(bundleInfo.getConfigDescriptions().size(), is(1)); @@ -73,8 +73,8 @@ public void readPathWithoutAnyInfo() throws IOException { BundleInfoReader reader = new BundleInfoReader(new SystemStreamLog()); BundleInfo bundleInfo = reader.readBundleInfo(Path.of("src/test/resources/infoless.bundle/OH-INF")); - assertThat(bundleInfo.getBindingInfoXml(), is(nullValue())); - assertThat(bundleInfo.getBindingId(), is("")); + assertThat(bundleInfo.getAddonInfoXml(), is(nullValue())); + assertThat(bundleInfo.getAddonId(), is("")); assertThat(bundleInfo.getChannelGroupTypesXml().size(), is(0)); assertThat(bundleInfo.getChannelTypesXml().size(), is(0)); assertThat(bundleInfo.getConfigDescriptions().size(), is(0)); diff --git a/tools/i18n-plugin/src/test/java/org/openhab/core/tools/i18n/plugin/GenerateDefaultTranslationsMojoTest.java b/tools/i18n-plugin/src/test/java/org/openhab/core/tools/i18n/plugin/GenerateDefaultTranslationsMojoTest.java index 2b0a7805530..f37fa411d73 100644 --- a/tools/i18n-plugin/src/test/java/org/openhab/core/tools/i18n/plugin/GenerateDefaultTranslationsMojoTest.java +++ b/tools/i18n-plugin/src/test/java/org/openhab/core/tools/i18n/plugin/GenerateDefaultTranslationsMojoTest.java @@ -123,7 +123,7 @@ private void assertSameProperties(Path expectedPath, Path actualPath) throws IOE } @Test - public void addMissingBindingTranslationsWithoutI18nPath() throws IOException, MojoFailureException { + public void addMissingAddonTranslationsWithoutI18nPath() throws IOException, MojoFailureException { copyPath(WEATHER_RESOURCES_PATH, tempPath); deleteTempI18nPath(); @@ -134,7 +134,7 @@ public void addMissingBindingTranslationsWithoutI18nPath() throws IOException, M } @Test - public void addMissingBindingTranslationsNoChanges() throws IOException, MojoFailureException { + public void addMissingAddonTranslationsNoChanges() throws IOException, MojoFailureException { copyPath(WEATHER_RESOURCES_PATH, tempPath); mojo.setGenerationMode(ADD_MISSING_TRANSLATIONS); diff --git a/tools/i18n-plugin/src/test/java/org/openhab/core/tools/i18n/plugin/PropertiesToTranslationsConverterTest.java b/tools/i18n-plugin/src/test/java/org/openhab/core/tools/i18n/plugin/PropertiesToTranslationsConverterTest.java index ef70bb56168..e6782f88377 100644 --- a/tools/i18n-plugin/src/test/java/org/openhab/core/tools/i18n/plugin/PropertiesToTranslationsConverterTest.java +++ b/tools/i18n-plugin/src/test/java/org/openhab/core/tools/i18n/plugin/PropertiesToTranslationsConverterTest.java @@ -42,10 +42,10 @@ public void readBindingInfo() { assertThat(translations.keysStream().count(), is(44L)); String lines = translations.linesStream().collect(Collectors.joining(System.lineSeparator())); - assertThat(lines, containsString("# binding")); - assertThat(lines, containsString("binding.acmeweather.name = ACME Weather Binding")); + assertThat(lines, containsString("# add-on")); + assertThat(lines, containsString("addon.acmeweather.name = ACME Weather Binding")); assertThat(lines, containsString( - "binding.acmeweather.description = ACME Weather - Current weather and forecasts in your city.")); + "addon.acmeweather.description = ACME Weather - Current weather and forecasts in your city.")); assertThat(lines, containsString( "channel-group-type.acmeweather.forecast.channel.minTemperature.description = Minimum forecasted temperature in degrees Celsius (metric) or Fahrenheit (imperial).")); assertThat(lines, containsString( diff --git a/tools/i18n-plugin/src/test/java/org/openhab/core/tools/i18n/plugin/XmlToTranslationsConverterTest.java b/tools/i18n-plugin/src/test/java/org/openhab/core/tools/i18n/plugin/XmlToTranslationsConverterTest.java index 71378985f2b..6fc4e6b7a63 100644 --- a/tools/i18n-plugin/src/test/java/org/openhab/core/tools/i18n/plugin/XmlToTranslationsConverterTest.java +++ b/tools/i18n-plugin/src/test/java/org/openhab/core/tools/i18n/plugin/XmlToTranslationsConverterTest.java @@ -45,10 +45,10 @@ public void convertBindingInfo() throws IOException { assertThat(translations.keysStream().count(), is(34L)); String lines = translations.linesStream().collect(Collectors.joining(System.lineSeparator())); - assertThat(lines, containsString("# binding")); - assertThat(lines, containsString("binding.acmeweather.name = ACME Weather Binding")); + assertThat(lines, containsString("# add-on")); + assertThat(lines, containsString("addon.acmeweather.name = ACME Weather Binding")); assertThat(lines, containsString( - "binding.acmeweather.description = ACME Weather - Current weather and forecasts in your city.")); + "addon.acmeweather.description = ACME Weather - Current weather and forecasts in your city.")); assertThat(lines, containsString( "channel-group-type.acmeweather.forecast.channel.minTemperature.description = Minimum forecasted temperature in degrees Celsius (metric) or Fahrenheit (imperial).")); assertThat(lines, containsString( diff --git a/tools/i18n-plugin/src/test/resources/acmeweather.bundle/OH-INF/addon/addon.xml b/tools/i18n-plugin/src/test/resources/acmeweather.bundle/OH-INF/addon/addon.xml new file mode 100644 index 00000000000..15a82ff0b05 --- /dev/null +++ b/tools/i18n-plugin/src/test/resources/acmeweather.bundle/OH-INF/addon/addon.xml @@ -0,0 +1,10 @@ + + + + binding + ACME Weather Binding + ACME Weather - Current weather and forecasts in your city. + + diff --git a/tools/i18n-plugin/src/test/resources/acmeweather.bundle/OH-INF/binding/binding.xml b/tools/i18n-plugin/src/test/resources/acmeweather.bundle/OH-INF/binding/binding.xml deleted file mode 100644 index 97266803f7a..00000000000 --- a/tools/i18n-plugin/src/test/resources/acmeweather.bundle/OH-INF/binding/binding.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - ACME Weather Binding - ACME Weather - Current weather and forecasts in your city. - - diff --git a/tools/i18n-plugin/src/test/resources/acmeweather.bundle/OH-INF/i18n/acmeweather.generated.properties b/tools/i18n-plugin/src/test/resources/acmeweather.bundle/OH-INF/i18n/acmeweather.generated.properties index 4266719f1ef..9496f5ca23f 100644 --- a/tools/i18n-plugin/src/test/resources/acmeweather.bundle/OH-INF/i18n/acmeweather.generated.properties +++ b/tools/i18n-plugin/src/test/resources/acmeweather.bundle/OH-INF/i18n/acmeweather.generated.properties @@ -1,7 +1,7 @@ -# binding +# add-on -binding.acmeweather.name = ACME Weather Binding -binding.acmeweather.description = ACME Weather - Current weather and forecasts in your city. +addon.acmeweather.name = ACME Weather Binding +addon.acmeweather.description = ACME Weather - Current weather and forecasts in your city. # thing types diff --git a/tools/i18n-plugin/src/test/resources/acmeweather.bundle/OH-INF/i18n/acmeweather.properties b/tools/i18n-plugin/src/test/resources/acmeweather.bundle/OH-INF/i18n/acmeweather.properties index e2516dd187f..e3dd79ba48e 100644 --- a/tools/i18n-plugin/src/test/resources/acmeweather.bundle/OH-INF/i18n/acmeweather.properties +++ b/tools/i18n-plugin/src/test/resources/acmeweather.bundle/OH-INF/i18n/acmeweather.properties @@ -1,7 +1,7 @@ -# binding +# add-on -binding.acmeweather.name = ACME Weather Binding -binding.acmeweather.description = ACME Weather - Current weather and forecasts in your city. +addon.acmeweather.name = ACME Weather Binding +addon.acmeweather.description = ACME Weather - Current weather and forecasts in your city. # thing types diff --git a/tools/i18n-plugin/src/test/resources/acmeweather.bundle/OH-INF/i18n/acmeweather_de.properties b/tools/i18n-plugin/src/test/resources/acmeweather.bundle/OH-INF/i18n/acmeweather_de.properties index 5d0396171a6..b6944f64919 100644 --- a/tools/i18n-plugin/src/test/resources/acmeweather.bundle/OH-INF/i18n/acmeweather_de.properties +++ b/tools/i18n-plugin/src/test/resources/acmeweather.bundle/OH-INF/i18n/acmeweather_de.properties @@ -1,7 +1,7 @@ -# binding +# add-on -binding.acmeweather.name = ACME Wetter Binding -binding.acmeweather.description = ACME Wetter - Aktuelles Wetter und Prognosen in Ihrer Stadt. +addon.acmeweather.name = ACME Wetter Binding +addon.acmeweather.description = ACME Wetter - Aktuelles Wetter und Prognosen in Ihrer Stadt. # thing types From 46b1425cce55d75d58ccbe5d73330b4cdb0076ff Mon Sep 17 00:00:00 2001 From: "Jan N. Klug" Date: Tue, 3 Jan 2023 20:17:13 +0100 Subject: [PATCH 2/8] license header Signed-off-by: Jan N. Klug --- .../org/openhab/core/addon/xml/internal/AddonInfoConverter.java | 2 +- .../org/openhab/core/addon/xml/internal/AddonInfoXmlResult.java | 2 +- .../openhab/core/addon/xml/internal/XmlAddonInfoProvider.java | 2 +- .../src/main/java/org/openhab/core/addon/AddonInfo.java | 2 +- .../src/main/java/org/openhab/core/addon/AddonInfoRegistry.java | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/bundles/org.openhab.core.addon.xml/src/main/java/org/openhab/core/addon/xml/internal/AddonInfoConverter.java b/bundles/org.openhab.core.addon.xml/src/main/java/org/openhab/core/addon/xml/internal/AddonInfoConverter.java index f2af9fe5c9c..c43d27dea8e 100644 --- a/bundles/org.openhab.core.addon.xml/src/main/java/org/openhab/core/addon/xml/internal/AddonInfoConverter.java +++ b/bundles/org.openhab.core.addon.xml/src/main/java/org/openhab/core/addon/xml/internal/AddonInfoConverter.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2022 Contributors to the openHAB project + * Copyright (c) 2010-2023 Contributors to the openHAB project * * See the NOTICE file(s) distributed with this work for additional * information. diff --git a/bundles/org.openhab.core.addon.xml/src/main/java/org/openhab/core/addon/xml/internal/AddonInfoXmlResult.java b/bundles/org.openhab.core.addon.xml/src/main/java/org/openhab/core/addon/xml/internal/AddonInfoXmlResult.java index f618a67c3a3..ff7b0fe3b12 100644 --- a/bundles/org.openhab.core.addon.xml/src/main/java/org/openhab/core/addon/xml/internal/AddonInfoXmlResult.java +++ b/bundles/org.openhab.core.addon.xml/src/main/java/org/openhab/core/addon/xml/internal/AddonInfoXmlResult.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2022 Contributors to the openHAB project + * Copyright (c) 2010-2023 Contributors to the openHAB project * * See the NOTICE file(s) distributed with this work for additional * information. 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 index 0d2af9c5e31..52d7ce047c7 100644 --- 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 @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2022 Contributors to the openHAB project + * Copyright (c) 2010-2023 Contributors to the openHAB project * * See the NOTICE file(s) distributed with this work for additional * information. 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 index 0b3eccb50c2..5f936a239c7 100644 --- 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 @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2022 Contributors to the openHAB project + * Copyright (c) 2010-2023 Contributors to the openHAB project * * See the NOTICE file(s) distributed with this work for additional * information. 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 index a6768cf861e..678c329ca2d 100644 --- 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 @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2022 Contributors to the openHAB project + * Copyright (c) 2010-2023 Contributors to the openHAB project * * See the NOTICE file(s) distributed with this work for additional * information. From 52fb698dc6b529b5f7c87bde714c0946d2394500 Mon Sep 17 00:00:00 2001 From: "Jan N. Klug" Date: Sat, 14 Jan 2023 21:26:55 +0100 Subject: [PATCH 3/8] code improvements Signed-off-by: Jan N. Klug --- .../core/karaf/internal/FeatureInstaller.java | 8 +++---- .../karaf/internal/KarafAddonService.java | 22 +++++-------------- 2 files changed, 10 insertions(+), 20 deletions(-) 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 09b275bc4fa..67033030c70 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 @@ -257,10 +257,10 @@ private boolean allKarsInstalled() { 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) { 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 7279095fa58..a0b495559a7 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 @@ -167,25 +167,15 @@ public void uninstall(String id) { 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); - 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, - Addon.ADDON_SEPARATOR); + 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 getName(String name) { - return substringAfter( - name.startsWith(FeatureInstaller.PREFIX) ? name.substring(FeatureInstaller.PREFIX.length()) : name, - Addon.ADDON_SEPARATOR); + 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()); } } From 687709445cf2a47a2f9597f67d9c1d1a937594d7 Mon Sep 17 00:00:00 2001 From: "Jan N. Klug" Date: Sat, 14 Jan 2023 22:07:21 +0100 Subject: [PATCH 4/8] spotless Signed-off-by: Jan N. Klug --- .../java/org/openhab/core/karaf/internal/FeatureInstaller.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 67033030c70..a6fc3b7b2c3 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 @@ -258,7 +258,8 @@ private boolean allKarsInstalled() { String addonsDirectory = (String) felixProperties.get("felix.fileinstall.dir"); if (addonsDirectory != null) { 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("."))) + return files.map(Path::getFileName).map(Path::toString).filter(file -> file.endsWith(".kar")) + .map(karFileName -> karFileName.substring(0, karFileName.lastIndexOf("."))) .allMatch(karRepos::contains); } } From 071f7930fb14f14ad1eaa86c3d213641f349558c Mon Sep 17 00:00:00 2001 From: "Jan N. Klug" Date: Sat, 14 Jan 2023 23:53:16 +0100 Subject: [PATCH 5/8] fix .project Signed-off-by: Jan N. Klug --- bundles/org.openhab.core.addon.xml/.project | 2 +- itests/org.openhab.core.addon.xml.tests/.project | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bundles/org.openhab.core.addon.xml/.project b/bundles/org.openhab.core.addon.xml/.project index 08933b3a05f..9e3910de1c7 100644 --- a/bundles/org.openhab.core.addon.xml/.project +++ b/bundles/org.openhab.core.addon.xml/.project @@ -1,6 +1,6 @@ - org.openhab.core.binding.xml + org.openhab.core.addon.xml diff --git a/itests/org.openhab.core.addon.xml.tests/.project b/itests/org.openhab.core.addon.xml.tests/.project index c078a2c09a3..55dda464e6a 100644 --- a/itests/org.openhab.core.addon.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 From 50e8ce3a689e3bbc89387b3d850335a6aaf54b32 Mon Sep 17 00:00:00 2001 From: "Jan N. Klug" Date: Sun, 15 Jan 2023 00:52:57 +0100 Subject: [PATCH 6/8] address review comments Signed-off-by: Jan N. Klug --- .../core/addon/xml/internal/AddonInfoConverter.java | 4 ++-- .../core/io/rest/core/internal/addons/AddonResource.java | 2 +- .../src/main/resources/OH-INF/addon/addon.xml | 2 +- .../src/main/resources/OH-INF/binding/binding.xml | 9 --------- .../openhab/core/addon/AddonI18nLocalizationService.java | 8 ++++---- 5 files changed, 8 insertions(+), 17 deletions(-) delete mode 100644 bundles/org.openhab.core.test.magic/src/main/resources/OH-INF/binding/binding.xml diff --git a/bundles/org.openhab.core.addon.xml/src/main/java/org/openhab/core/addon/xml/internal/AddonInfoConverter.java b/bundles/org.openhab.core.addon.xml/src/main/java/org/openhab/core/addon/xml/internal/AddonInfoConverter.java index c43d27dea8e..d20abfb3317 100644 --- a/bundles/org.openhab.core.addon.xml/src/main/java/org/openhab/core/addon/xml/internal/AddonInfoConverter.java +++ b/bundles/org.openhab.core.addon.xml/src/main/java/org/openhab/core/addon/xml/internal/AddonInfoConverter.java @@ -31,7 +31,7 @@ /** * The {@link AddonInfoConverter} is a concrete implementation of the {@code XStream} {@link Converter} interface used - * to convert binding information within an XML document into a {@link AddonInfoXmlResult} object. + * to convert add-on information within an XML document into a {@link AddonInfoXmlResult} object. * This converter converts {@code addon} XML tags. * * @author Michael Grammling - Initial contribution @@ -68,7 +68,7 @@ public AddonInfoConverter() { // read attributes Map attributes = attributeMapValidator.readValidatedAttributes(reader); - String id = requireNonEmpty(attributes.get("id"), "Binding id attribute is null or empty"); + 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); 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 d760f2a3616..0b50c7f0fce 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 @@ -294,7 +294,7 @@ public Response uninstallAddon(final @PathParam("addonId") @Parameter(descriptio @GET @Path("/{addonId: [a-zA-Z_0-9-:]+}/config") @Produces({ MediaType.APPLICATION_JSON }) - @Operation(operationId = "getAddonConfiguration", summary = "Get add-onconfiguration for given binding ID.", responses = { + @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") }) 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 index 9e65ce333dc..b6e8268cf11 100644 --- 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 @@ -3,7 +3,7 @@ xmlns:addon="https://openhab.org/schemas/addon/v1.0.0" xsi:schemaLocation="https://openhab.org/schemas/addon/v1.0.0 https://openhab.org/schemas/addon-1.0.0.xsd"> - core + 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 209d57a6ed7..00000000000 --- 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/AddonI18nLocalizationService.java b/bundles/org.openhab.core/src/main/java/org/openhab/core/addon/AddonI18nLocalizationService.java index 869ede8feff..6f3d8f27db6 100644 --- 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 @@ -24,7 +24,7 @@ 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 + * 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 @@ -41,12 +41,12 @@ public AddonI18nLocalizationService(final @Reference TranslationProvider i18nPro } /** - * Localizes a binding info. + * Localizes an add-on info. * * @param bundle the bundle the i18n resources are located - * @param addonInfo the binding info that should be localized + * @param addonInfo the add-on 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). + * @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(); From 1194a4cd8cae0837631b75e7223b93e6d83d9016 Mon Sep 17 00:00:00 2001 From: "Jan N. Klug" Date: Sun, 15 Jan 2023 01:00:13 +0100 Subject: [PATCH 7/8] fix Signed-off-by: Jan N. Klug --- .../org/openhab/core/addon/xml/internal/AddonInfoReader.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundles/org.openhab.core.addon.xml/src/main/java/org/openhab/core/addon/xml/internal/AddonInfoReader.java b/bundles/org.openhab.core.addon.xml/src/main/java/org/openhab/core/addon/xml/internal/AddonInfoReader.java index 42b2eae0bbd..334a275d94f 100644 --- a/bundles/org.openhab.core.addon.xml/src/main/java/org/openhab/core/addon/xml/internal/AddonInfoReader.java +++ b/bundles/org.openhab.core.addon.xml/src/main/java/org/openhab/core/addon/xml/internal/AddonInfoReader.java @@ -82,6 +82,6 @@ protected void registerAliases(XStream xstream) { xstream.alias("option", NodeValue.class); xstream.alias("filter", List.class); xstream.alias("criteria", FilterCriteria.class); - xstream.alias("config-id", NodeValue.class); + xstream.alias("service-id", NodeValue.class); } } From 2417225c40cb1a6dc74b79cb2befe7930c72d27b Mon Sep 17 00:00:00 2001 From: "Jan N. Klug" Date: Sun, 15 Jan 2023 12:32:23 +0100 Subject: [PATCH 8/8] address more review comments Signed-off-by: Jan N. Klug --- .../main/java/org/openhab/core/addon/AddonInfo.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) 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 index 5f936a239c7..c12b29ede25 100644 --- 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 @@ -95,9 +95,9 @@ public String getId() { } /** - * Returns a human-readable name for the binding (e.g. "HUE Binding"). + * Returns a human-readable name for the add-on (e.g. "HUE Binding"). * - * @return a human-readable name for the binding (neither null, nor empty) + * @return a human-readable name for the add-on (neither null, nor empty) */ public String getName() { return name; @@ -112,19 +112,19 @@ public String getServiceId() { } /** - * Returns a human-readable description for the binding + * Returns a human-readable description for the add-on * (e.g. "Discovers and controls HUE bulbs"). * - * @return a human-readable description for the binding + * @return a human-readable description for the add-on */ public String getDescription() { return description; } /** - * Returns the author of the binding (e.g. "Max Mustermann"). + * Returns the author of the add-on (e.g. "Max Mustermann"). * - * @return the author of the binding (could be null or empty) + * @return the author of the add-on (could be null or empty) */ public @Nullable String getAuthor() { return author;