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

Modified finder discovery schema to make future finders easier to create #3924

Merged
merged 6 commits into from
Dec 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion bundles/org.openhab.core.addon/schema/addon-1.0.0.xsd
Original file line number Diff line number Diff line change
Expand Up @@ -90,11 +90,24 @@
<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:ParametersType" name="discovery-parameters" minOccurs="0"/>
<xs:element type="addon:matchPropertiesType" name="match-properties" minOccurs="0"/>
</xs:sequence>
</xs:complexType>

<xs:complexType name="ParametersType">
<xs:sequence>
<xs:element type="addon:parameterType" name="discovery-parameter" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>

<xs:complexType name="parameterType">
<xs:sequence>
<xs:element type="xs:string" name="name"/>
<xs:element type="xs:string" name="value"/>
</xs:sequence>
</xs:complexType>

<xs:complexType name="matchPropertiesType">
<xs:sequence>
<xs:element type="addon:matchPropertyType" name="match-property" maxOccurs="unbounded"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,16 @@
@NonNullByDefault
public class AddonDiscoveryMethod {
private @NonNullByDefault({}) String serviceType;
private @Nullable String mdnsServiceType;
private @Nullable List<AddonParameter> parameters;
private @Nullable List<AddonMatchProperty> matchProperties;

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

public String getMdnsServiceType() {
String mdnsServiceType = this.mdnsServiceType;
return mdnsServiceType != null ? mdnsServiceType : "";
public List<AddonParameter> getParameters() {
List<AddonParameter> parameters = this.parameters;
return parameters != null ? parameters : List.of();
}

public List<AddonMatchProperty> getMatchProperties() {
Expand All @@ -48,8 +48,8 @@ public AddonDiscoveryMethod setServiceType(String serviceType) {
return this;
}

public AddonDiscoveryMethod setMdnsServiceType(@Nullable String mdnsServiceType) {
this.mdnsServiceType = mdnsServiceType;
public AddonDiscoveryMethod setParameters(@Nullable List<AddonParameter> parameters) {
this.parameters = parameters;
return this;
}

Expand All @@ -60,7 +60,7 @@ public AddonDiscoveryMethod setMatchProperties(@Nullable List<AddonMatchProperty

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

@Override
Expand All @@ -75,7 +75,7 @@ public boolean equals(@Nullable Object obj) {
return false;
}
AddonDiscoveryMethod other = (AddonDiscoveryMethod) obj;
return Objects.equals(serviceType, other.serviceType) && Objects.equals(mdnsServiceType, other.mdnsServiceType)
return Objects.equals(serviceType, other.serviceType) && Objects.equals(parameters, other.parameters)
&& Objects.equals(matchProperties, other.matchProperties);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/**
* 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.Objects;

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

/**
* DTO for serialization of a add-on discovery parameter.
*
* @author Mark Herwege - Initial contribution
*/
@NonNullByDefault
public class AddonParameter {
private @NonNullByDefault({}) String name;
private @NonNullByDefault({}) String value;

public AddonParameter(String name, String value) {
this.name = name;
this.value = value;
}

public String getName() {
return name;
}

public String getValue() {
return value;
}

@Override
public int hashCode() {
return Objects.hash(name, value);
}

@Override
public boolean equals(@Nullable Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
AddonParameter other = (AddonParameter) obj;
return Objects.equals(name, other.name) && Objects.equals(value, other.value);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.addon.AddonDiscoveryMethod;
import org.openhab.core.addon.AddonMatchProperty;
import org.openhab.core.addon.AddonParameter;
import org.openhab.core.config.core.xml.util.GenericUnmarshaller;
import org.openhab.core.config.core.xml.util.NodeIterator;

Expand Down Expand Up @@ -46,16 +47,18 @@ public AddonDiscoveryMethodConverter() {
String serviceType = requireNonEmpty((String) nodeIterator.nextValue("service-type", true),
"Service type is null or empty");

String mdnsServiceType = (String) nodeIterator.nextValue("mdns-service-type", false);
Object paramObject = nodeIterator.nextList("discovery-parameters", false);
List<AddonParameter> parameters = !(paramObject instanceof List<?> list) ? null
: list.stream().filter(e -> (e instanceof AddonParameter)).map(e -> ((AddonParameter) e)).toList();

Object object = nodeIterator.nextList("match-properties", false);
List<AddonMatchProperty> matchProperties = !(object instanceof List<?> list) ? null
Object matchPropObject = nodeIterator.nextList("match-properties", false);
List<AddonMatchProperty> matchProperties = !(matchPropObject instanceof List<?> list) ? null
: list.stream().filter(e -> (e instanceof AddonMatchProperty)).map(e -> ((AddonMatchProperty) e))
.toList();

nodeIterator.assertEndOfType();

return new AddonDiscoveryMethod().setServiceType(serviceType).setMdnsServiceType(mdnsServiceType)
return new AddonDiscoveryMethod().setServiceType(serviceType).setParameters(parameters)
.setMatchProperties(matchProperties);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import org.openhab.core.addon.AddonDiscoveryMethod;
import org.openhab.core.addon.AddonInfoList;
import org.openhab.core.addon.AddonMatchProperty;
import org.openhab.core.addon.AddonParameter;
import org.openhab.core.config.core.ConfigDescription;
import org.openhab.core.config.core.ConfigDescriptionParameter;
import org.openhab.core.config.core.ConfigDescriptionParameterGroup;
Expand Down Expand Up @@ -69,6 +70,7 @@ protected void registerConverters(XStream xstream) {
xstream.registerConverter(new ConfigDescriptionParameterGroupConverter());
xstream.registerConverter(new FilterCriteriaConverter());
xstream.registerConverter(new AddonDiscoveryMethodConverter());
xstream.registerConverter(new AddonParameterConverter());
xstream.registerConverter(new AddonMatchPropertyConverter());
}

Expand All @@ -94,9 +96,11 @@ protected void registerAliases(XStream xstream) {
xstream.alias("discovery-methods", NodeList.class);
xstream.alias("discovery-method", AddonDiscoveryMethod.class);
xstream.alias("service-type", NodeValue.class);
xstream.alias("mdns-service-type", NodeValue.class);
xstream.alias("discovery-parameters", NodeList.class);
xstream.alias("discovery-parameter", AddonParameter.class);
xstream.alias("match-properties", NodeList.class);
xstream.alias("match-property", AddonMatchProperty.class);
xstream.alias("value", NodeValue.class);
xstream.alias("regex", NodeValue.class);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.core.addon.AddonDiscoveryMethod;
import org.openhab.core.addon.AddonMatchProperty;
import org.openhab.core.addon.AddonParameter;
import org.openhab.core.config.core.ConfigDescription;
import org.openhab.core.config.core.ConfigDescriptionParameter;
import org.openhab.core.config.core.ConfigDescriptionParameterGroup;
Expand Down Expand Up @@ -70,6 +71,7 @@ protected void registerConverters(XStream xstream) {
xstream.registerConverter(new ConfigDescriptionParameterGroupConverter());
xstream.registerConverter(new FilterCriteriaConverter());
xstream.registerConverter(new AddonDiscoveryMethodConverter());
xstream.registerConverter(new AddonParameterConverter());
xstream.registerConverter(new AddonMatchPropertyConverter());
}

Expand All @@ -93,9 +95,11 @@ protected void registerAliases(XStream xstream) {
xstream.alias("discovery-methods", NodeList.class);
xstream.alias("discovery-method", AddonDiscoveryMethod.class);
xstream.alias("service-type", NodeValue.class);
xstream.alias("mdns-service-type", NodeValue.class);
xstream.alias("discovery-parameters", NodeList.class);
xstream.alias("discovery-parameter", AddonParameter.class);
xstream.alias("match-properties", NodeList.class);
xstream.alias("match-property", AddonMatchProperty.class);
xstream.alias("value", NodeValue.class);
xstream.alias("regex", NodeValue.class);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/**
* 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.internal.xml;

import java.util.List;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.addon.AddonMatchProperty;
import org.openhab.core.addon.AddonParameter;
import org.openhab.core.config.core.xml.util.GenericUnmarshaller;
import org.openhab.core.config.core.xml.util.NodeIterator;

import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;

/**
* The {@link AddonParameterConverter} is a concrete implementation of the {@code XStream} {@link Converter}
* interface used to convert add-on discovery method parameter information within an XML document into a
* {@link AddonMatchProperty} object.
*
* @author Mark Herwege - Initial contribution
*/
@NonNullByDefault
public class AddonParameterConverter extends GenericUnmarshaller<AddonParameter> {

public AddonParameterConverter() {
super(AddonParameter.class);
}

@Override
public @Nullable Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
List<?> nodes = (List<?>) context.convertAnother(context, List.class);
NodeIterator nodeIterator = new NodeIterator(nodes);

String name = requireNonEmpty((String) nodeIterator.nextValue("name", true), "Name is null or empty");
String value = requireNonEmpty((String) nodeIterator.nextValue("value", true), "Value is null or empty");

nodeIterator.assertEndOfType();

return new AddonParameter(name, value);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,7 @@
*/
package org.openhab.core.addon;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
import static org.junit.jupiter.api.Assertions.*;

import java.util.List;

Expand Down Expand Up @@ -44,7 +41,12 @@ class AddonInfoListReaderTest {
+ " <discovery-methods>"
+ " <discovery-method>"
+ " <service-type>mdns</service-type>"
+ " <mdns-service-type>_printer._tcp.local.</mdns-service-type>"
+ " <discovery-parameters>"
+ " <discovery-parameter>"
+ " <name>mdnsServiceType</name>"
+ " <value>_printer._tcp.local.</value>"
+ " </discovery-parameter>"
+ " </discovery-parameters>"
+ " <match-properties>"
+ " <match-property>"
+ " <name>rp</name>"
Expand Down Expand Up @@ -91,7 +93,13 @@ void testAddonInfoListReader() {
AddonDiscoveryMethod method = discoveryMethods.get(0);
assertNotNull(method);
assertEquals("mdns", method.getServiceType());
assertEquals("_printer._tcp.local.", method.getMdnsServiceType());
List<AddonParameter> parameters = method.getParameters();
assertNotNull(parameters);
assertEquals(1, parameters.size());
AddonParameter parameter = parameters.get(0);
assertNotNull(parameter);
assertEquals("mdnsServiceType", parameter.getName());
Copy link
Contributor

Choose a reason for hiding this comment

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

"mdnsServiceType" should be a constant

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Left as is, as this would also require a local constant and the exact name of the parameter is not relevant for the test.

assertEquals("_printer._tcp.local.", parameter.getValue());
List<AddonMatchProperty> matchProperties = method.getMatchProperties();
assertNotNull(matchProperties);
assertEquals(2, matchProperties.size());
Expand All @@ -104,7 +112,9 @@ void testAddonInfoListReader() {
method = discoveryMethods.get(1);
assertNotNull(method);
assertEquals("upnp", method.getServiceType());
assertEquals("", method.getMdnsServiceType());
parameters = method.getParameters();
assertNotNull(parameters);
assertEquals(0, parameters.size());
matchProperties = method.getMatchProperties();
assertNotNull(matchProperties);
assertEquals(1, matchProperties.size());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,9 @@
*/
package org.openhab.core.addon;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;

import java.util.List;
import java.util.Locale;
Expand Down Expand Up @@ -67,7 +60,7 @@ private AddonInfoProvider createAddonInfoProvider0() {

private AddonInfoProvider createAddonInfoProvider1() {
AddonDiscoveryMethod discoveryMethod = new AddonDiscoveryMethod().setServiceType("mdns")
.setMdnsServiceType("_hue._tcp.local.");
.setParameters(List.of(new AddonParameter("mdnsServiceType", "_hue._tcp.local.")));
Copy link
Contributor

Choose a reason for hiding this comment

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

"mdnsServiceType" should be a constant

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Left as is, as this would also require a local constant and the exact name of the parameter is not relevant for the test.

AddonInfo addonInfo = AddonInfo.builder("hue", "binding").withName("name-one")
.withDescription("description-one").withCountries("GB,NL").withConnection("local")
.withDiscoveryMethods(List.of(discoveryMethod)).build();
Expand Down
Loading