Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AddonInfo extensions #3865

Merged
merged 11 commits into from
Dec 5, 2023
8 changes: 4 additions & 4 deletions bundles/org.openhab.core.addon/.classpath
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,16 @@
<attribute name="annotationpath" value="target/dependency"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happened here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Umm. Not sure. I think Eclipse did it automagically when I wrote a new JUnit test.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you simply revert the changes so that this PR leaves the file untouched?

<classpathentry excluding="**" kind="src" output="target/classes" path="src/generated">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry excluding="**" kind="src" output="target/classes" path="src/generated">
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="target/classes"/>
Expand Down
82 changes: 55 additions & 27 deletions bundles/org.openhab.core.addon/schema/addon-1.0.0.xsd
Original file line number Diff line number Diff line change
Expand Up @@ -7,35 +7,36 @@
<xs:import namespace="https://openhab.org/schemas/config-description/v1.0.0"
schemaLocation="https://openhab.org/schemas/config-description-1.0.0.xsd"/>

<xs:element name="addon">
<xs:complexType>
<xs:sequence>
<xs:element name="type" type="addon:addonType"/>
<xs:element name="name" type="xs:string"/>
<xs:element name="description" type="xs:string"/>
<xs:element name="connection" type="addon:connectionType" minOccurs="0"/>
<xs:element name="countries" type="addon:countryType" minOccurs="0">
<xs:annotation>
<xs:documentation>Comma-separated list of two-letter ISO country codes.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="service-id" type="xs:string" minOccurs="0">
<xs:annotation>
<xs:documentation>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 &lt;type&gt;.&lt;name&gt;</xs:documentation>
</xs:annotation>
</xs:element>
<xs:choice minOccurs="0">
<xs:element name="config-description" type="config-description:configDescription"/>
<xs:element name="config-description-ref" type="config-description:configDescriptionRef"/>
</xs:choice>
</xs:sequence>
<xs:attribute name="id" type="config-description:idRestrictionPattern" use="required">
<xs:element name="addon" type="addon:addonInfo"/>

<xs:complexType name="addonInfo">
<xs:sequence>
<xs:element name="type" type="addon:addonType"/>
<xs:element name="name" type="xs:string"/>
<xs:element name="description" type="xs:string"/>
<xs:element name="connection" type="addon:connectionType" minOccurs="0"/>
<xs:element name="countries" type="addon:countryType" minOccurs="0">
<xs:annotation>
<xs:documentation>Comma-separated list of two-letter ISO country codes.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="service-id" type="xs:string" minOccurs="0">
<xs:annotation>
<xs:documentation>The id is used to construct the UID of this add-on to &lt;type&gt;-&lt;name&gt;</xs:documentation>
<xs:documentation>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 &lt;type&gt;.&lt;name&gt;</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:element>
<xs:choice minOccurs="0">
<xs:element name="config-description" type="config-description:configDescription"/>
<xs:element name="config-description-ref" type="config-description:configDescriptionRef"/>
</xs:choice>
<xs:element name="discovery-methods" type="addon:discoveryMethodsType" minOccurs="0"/>
</xs:sequence>
<xs:attribute name="id" type="config-description:idRestrictionPattern" use="required">
<xs:annotation>
<xs:documentation>The id is used to construct the UID of this add-on to &lt;type&gt;-&lt;name&gt;</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>

<xs:simpleType name="addonType">
<xs:restriction base="xs:string">
Expand Down Expand Up @@ -80,4 +81,31 @@
</xs:restriction>
</xs:simpleType>

<xs:complexType name="discoveryMethodsType">
<xs:sequence>
<xs:element type="addon:discoveryMethodType" name="discovery-method" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>

<xs:complexType name="discoveryMethodType">
<xs:sequence>
<xs:element type="xs:string" name="service-type"/>
<xs:element type="xs:string" name="mdns-service-type" minOccurs="0"/>
<xs:element type="addon:matchPropertiesType" name="match-properties" minOccurs="0"/>
</xs:sequence>
</xs:complexType>

<xs:complexType name="matchPropertiesType">
<xs:sequence>
<xs:element type="addon:matchPropertyType" name="match-property" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>

<xs:complexType name="matchPropertyType">
<xs:sequence>
<xs:element type="xs:string" name="name"/>
<xs:element type="xs:string" name="regex"/>
</xs:sequence>
</xs:complexType>

</xs:schema>
23 changes: 23 additions & 0 deletions bundles/org.openhab.core.addon/schema/addon-info-list-1.0.0.xsd
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:addon="https://openhab.org/schemas/addon/v1.0.0"
xmlns:addon-info-list="https://openhab.org/schemas/addon-info-list/v1.0.0"
targetNamespace="https://openhab.org/schemas/addon-info-list/v1.0.0">

<xs:import namespace="https://openhab.org/schemas/addon/v1.0.0" schemaLocation="addon-1.0.0.xsd"/>

<xs:element name="addon-info-list">
<xs:complexType>
<xs:sequence>
<xs:element name="addons" type="addon-info-list:addons"/>
</xs:sequence>
</xs:complexType>
</xs:element>

<xs:complexType name="addons">
<xs:sequence>
<xs:element name="addon" type="addon:addonInfo" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>

</xs:schema>
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/**
* Copyright (c) 2010-2023 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.core.addon;

import java.util.List;
import java.util.Objects;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;

/**
* DTO for serialization of a suggested addon discovery method.
*
* @author Andrew Fiddian-Green - Initial contribution
*/
@NonNullByDefault
public class AddonDiscoveryMethod {
private @NonNullByDefault({}) String serviceType;
private @Nullable String mdnsServiceType;
private @Nullable List<AddonMatchProperty> matchProperties;

public String getServiceType() {
return serviceType.toLowerCase();
}

public String getMdnsServiceType() {
String mdnsServiceType = this.mdnsServiceType;
return mdnsServiceType != null ? mdnsServiceType : "";
}

public List<AddonMatchProperty> getMatchProperties() {
List<AddonMatchProperty> matchProperties = this.matchProperties;
return matchProperties != null ? matchProperties : List.of();
}

public AddonDiscoveryMethod setServiceType(String serviceType) {
this.serviceType = serviceType.toLowerCase();
return this;
}

public AddonDiscoveryMethod setMdnsServiceType(@Nullable String mdnsServiceType) {
this.mdnsServiceType = mdnsServiceType;
return this;
}

public AddonDiscoveryMethod setMatchProperties(@Nullable List<AddonMatchProperty> matchProperties) {
this.matchProperties = matchProperties;
return this;
}

@Override
public int hashCode() {
return Objects.hash(serviceType, mdnsServiceType, matchProperties);
}

@Override
public boolean equals(@Nullable Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
AddonDiscoveryMethod other = (AddonDiscoveryMethod) obj;
return Objects.equals(serviceType, other.serviceType) && Objects.equals(mdnsServiceType, other.mdnsServiceType)
&& Objects.equals(matchProperties, other.matchProperties);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,20 @@ public class AddonInfo implements Identifiable<String> {

private final String id;
private final String type;
private final String uid;
private final String name;
private final String description;
private final @Nullable String connection;
private final List<String> countries;
private final @Nullable String configDescriptionURI;
private final String serviceId;
private @Nullable String sourceBundle;
private @Nullable List<AddonDiscoveryMethod> discoveryMethods;

private AddonInfo(String id, String type, String name, String description, @Nullable String connection,
List<String> countries, @Nullable String configDescriptionURI, @Nullable String serviceId,
@Nullable String sourceBundle) throws IllegalArgumentException {
private AddonInfo(String id, String type, @Nullable String uid, String name, String description,
@Nullable String connection, List<String> countries, @Nullable String configDescriptionURI,
@Nullable String serviceId, @Nullable String sourceBundle,
@Nullable List<AddonDiscoveryMethod> discoveryMethods) throws IllegalArgumentException {
// mandatory fields
if (id.isBlank()) {
throw new IllegalArgumentException("The ID must neither be null nor empty!");
Expand All @@ -64,6 +67,7 @@ private AddonInfo(String id, String type, String name, String description, @Null
}
this.id = id;
this.type = type;
this.uid = uid != null ? uid : type + Addon.ADDON_SEPARATOR + id;
this.name = name;
this.description = description;

Expand All @@ -73,6 +77,7 @@ private AddonInfo(String id, String type, String name, String description, @Null
this.configDescriptionURI = configDescriptionURI;
this.serviceId = Objects.requireNonNullElse(serviceId, type + "." + id);
this.sourceBundle = sourceBundle;
this.discoveryMethods = discoveryMethods;
}

/**
Expand All @@ -82,7 +87,7 @@ private AddonInfo(String id, String type, String name, String description, @Null
*/
@Override
public String getUID() {
return type + Addon.ADDON_SEPARATOR + id;
return uid;
}

/**
Expand Down Expand Up @@ -142,6 +147,11 @@ public List<String> getCountries() {
return countries;
}

public List<AddonDiscoveryMethod> getDiscoveryMethods() {
List<AddonDiscoveryMethod> discoveryMethods = this.discoveryMethods;
return discoveryMethods != null ? discoveryMethods : List.of();
}

public static Builder builder(String id, String type) {
return new Builder(id, type);
}
Expand All @@ -154,13 +164,15 @@ public static class Builder {

private final String id;
private final String type;
private @Nullable String uid;
private String name = "";
private String description = "";
private @Nullable String connection;
private List<String> countries = List.of();
private @Nullable String configDescriptionURI = "";
private @Nullable String serviceId;
private @Nullable String sourceBundle;
private @Nullable List<AddonDiscoveryMethod> discoveryMethods;

private Builder(String id, String type) {
this.id = id;
Expand All @@ -170,13 +182,20 @@ private Builder(String id, String type) {
private Builder(AddonInfo addonInfo) {
this.id = addonInfo.id;
this.type = addonInfo.type;
this.uid = addonInfo.uid;
this.name = addonInfo.name;
this.description = addonInfo.description;
this.connection = addonInfo.connection;
this.countries = addonInfo.countries;
this.configDescriptionURI = addonInfo.configDescriptionURI;
this.serviceId = addonInfo.serviceId;
this.sourceBundle = addonInfo.sourceBundle;
this.discoveryMethods = addonInfo.discoveryMethods;
}

public Builder withUID(@Nullable String uid) {
this.uid = uid;
return this;
}

public Builder withName(String name) {
Expand Down Expand Up @@ -219,15 +238,20 @@ public Builder withSourceBundle(@Nullable String sourceBundle) {
return this;
}

public Builder withDiscoveryMethods(@Nullable List<AddonDiscoveryMethod> discoveryMethods) {
this.discoveryMethods = discoveryMethods;
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, connection, countries, configDescriptionURI, serviceId,
sourceBundle);
return new AddonInfo(id, type, uid, name, description, connection, countries, configDescriptionURI,
serviceId, sourceBundle, discoveryMethods);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/**
* Copyright (c) 2010-2023 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.core.addon;

import java.util.List;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;

/**
* DTO containing a list of {@code AddonInfo}
*
* @author Andrew Fiddian-Green - Initial contribution
*/
@NonNullByDefault
public class AddonInfoList {
protected @Nullable List<AddonInfo> addons;

public List<AddonInfo> getAddons() {
List<AddonInfo> addons = this.addons;
return addons != null ? addons : List.of();
}

public AddonInfoList setAddons(@Nullable List<AddonInfo> addons) {
this.addons = addons;
return this;
}
}
Loading