Introduce metadata for all add-ons (#3050)

* Introduce addon.xml

Signed-off-by: Jan N. Klug <github@klug.nrw>
This commit is contained in:
J-N-K
2023-01-15 15:31:42 +01:00
committed by GitHub
parent dd584779db
commit 3d54ee54d2
81 changed files with 1250 additions and 1356 deletions
+1 -1
View File
@@ -51,7 +51,7 @@
</dependency>
<dependency>
<groupId>org.openhab.core.bundles</groupId>
<artifactId>org.openhab.core.binding.xml</artifactId>
<artifactId>org.openhab.core.addon.xml</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
@@ -19,7 +19,7 @@ import java.util.Optional;
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 @@ import com.google.gson.JsonObject;
@NonNullByDefault
public class BundleInfo {
private String bindingId = "";
private @Nullable BindingInfoXmlResult bindingInfoXml;
private String addonId = "";
private @Nullable AddonInfoXmlResult addonInfoXml;
private List<ConfigDescription> configDescriptions = new ArrayList<>(5);
private List<ChannelGroupTypeXmlResult> channelGroupTypesXml = new ArrayList<>(5);
private List<ChannelTypeXmlResult> channelTypesXml = new ArrayList<>(5);
@@ -44,20 +44,20 @@ public class BundleInfo {
private List<JsonObject> moduleTypesJson = new ArrayList<>(5);
private List<JsonObject> 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<ConfigDescription> getConfigDescriptions() {
@@ -25,8 +25,8 @@ import java.util.stream.StreamSupport;
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 class BundleInfoReader {
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 @@ public class BundleInfoReader {
: Stream.of();
}
private void readBindingInfo(Path ohinfPath, BundleInfo bundleInfo) throws IOException {
BindingInfoReader reader = new BindingInfoReader();
try (Stream<Path> xmlPathStream = xmlPathStream(ohinfPath, "binding")) {
private void readAddonInfo(Path ohinfPath, BundleInfo bundleInfo) throws IOException {
AddonInfoReader reader = new AddonInfoReader();
try (Stream<Path> 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 @@ public class BundleInfoReader {
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());
}
}
}
@@ -86,7 +86,7 @@ public class GenerateDefaultTranslationsMojo extends AbstractI18nMojo {
}
private String propertiesFileName(BundleInfo bundleInfo) {
String name = bundleInfo.getBindingId();
String name = bundleInfo.getAddonId();
if (name.isEmpty()) {
Optional<ConfigDescription> optional = bundleInfo.getConfigDescriptions().stream().findFirst();
if (optional.isPresent()) {
@@ -25,8 +25,8 @@ import java.util.stream.Stream;
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 @@ public class XmlToTranslationsConverter {
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 @@ public class XmlToTranslationsConverter {
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 @@ public class XmlToTranslationsConverter {
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 @@ public class XmlToTranslationsConverter {
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();
@@ -21,7 +21,7 @@ import java.nio.file.Path;
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 class BundleInfoReaderTest {
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 class BundleInfoReaderTest {
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 class BundleInfoReaderTest {
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));
@@ -123,7 +123,7 @@ public class GenerateDefaultTranslationsMojoTest {
}
@Test
public void addMissingBindingTranslationsWithoutI18nPath() throws IOException, MojoFailureException {
public void addMissingAddonTranslationsWithoutI18nPath() throws IOException, MojoFailureException {
copyPath(WEATHER_RESOURCES_PATH, tempPath);
deleteTempI18nPath();
@@ -134,7 +134,7 @@ public class GenerateDefaultTranslationsMojoTest {
}
@Test
public void addMissingBindingTranslationsNoChanges() throws IOException, MojoFailureException {
public void addMissingAddonTranslationsNoChanges() throws IOException, MojoFailureException {
copyPath(WEATHER_RESOURCES_PATH, tempPath);
mojo.setGenerationMode(ADD_MISSING_TRANSLATIONS);
@@ -42,10 +42,10 @@ public class PropertiesToTranslationsConverterTest {
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(
@@ -45,10 +45,10 @@ public class XmlToTranslationsConverterTest {
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(
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<addon:addon id="acmeweather" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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">
<type>binding</type>
<name>ACME Weather Binding</name>
<description>ACME Weather - Current weather and forecasts in your city.</description>
</addon:addon>
@@ -1,9 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<binding:binding id="acmeweather" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:binding="https://openhab.org/schemas/binding/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/binding/v1.0.0 https://openhab.org/schemas/binding-1.0.0.xsd">
<name>ACME Weather Binding</name>
<description>ACME Weather - Current weather and forecasts in your city.</description>
</binding:binding>
@@ -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
@@ -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
@@ -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