-
-
Notifications
You must be signed in to change notification settings - Fork 428
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add a YAML file provider for semantic tags
Files in folder conf/tags are loaded by this provider. Related to #3619 Signed-off-by: Laurent Garnier <[email protected]>
- Loading branch information
Showing
9 changed files
with
586 additions
and
0 deletions.
There are no files selected for viewing
61 changes: 61 additions & 0 deletions
61
...antics/src/main/java/org/openhab/core/semantics/internal/config/yaml/YamlSemanticTag.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
/** | ||
* 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.semantics.internal.config.yaml; | ||
|
||
import java.util.List; | ||
import java.util.Objects; | ||
|
||
import org.eclipse.jdt.annotation.Nullable; | ||
import org.openhab.core.semantics.model.yaml.YamlElement; | ||
import org.openhab.core.semantics.model.yaml.YamlParseException; | ||
|
||
/** | ||
* The {@link YamlSemanticTag} is a data transfer object used to serialize a semantic tag | ||
* in a YAML configuration file. | ||
* | ||
* @author Laurent Garnier - Initial contribution | ||
*/ | ||
public class YamlSemanticTag implements YamlElement { | ||
|
||
public String uid; | ||
public String label; | ||
public String description; | ||
public List<String> synonyms; | ||
|
||
public YamlSemanticTag() { | ||
} | ||
|
||
@Override | ||
public String getId() { | ||
return uid; | ||
} | ||
|
||
@Override | ||
public void checkValidity() throws YamlParseException { | ||
if (uid == null) { | ||
throw new YamlParseException("uid missing"); | ||
} | ||
} | ||
|
||
@Override | ||
public boolean equals(@Nullable Object obj) { | ||
if (this == obj) { | ||
return true; | ||
} else if (obj == null || getClass() != obj.getClass()) { | ||
return false; | ||
} | ||
YamlSemanticTag that = (YamlSemanticTag) obj; | ||
return Objects.equals(uid, that.uid) && Objects.equals(label, that.label) | ||
&& Objects.equals(description, that.description) && Objects.equals(synonyms, that.synonyms); | ||
} | ||
} |
125 changes: 125 additions & 0 deletions
125
...rc/main/java/org/openhab/core/semantics/internal/config/yaml/YamlSemanticTagProvider.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
/** | ||
* 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.semantics.internal.config.yaml; | ||
|
||
import java.util.ArrayList; | ||
import java.util.Collection; | ||
import java.util.Comparator; | ||
import java.util.List; | ||
|
||
import org.eclipse.jdt.annotation.NonNullByDefault; | ||
import org.openhab.core.common.registry.AbstractProvider; | ||
import org.openhab.core.semantics.SemanticTag; | ||
import org.openhab.core.semantics.SemanticTagImpl; | ||
import org.openhab.core.semantics.SemanticTagProvider; | ||
import org.openhab.core.semantics.SemanticTagRegistry; | ||
import org.openhab.core.semantics.model.yaml.YamlElement; | ||
import org.openhab.core.semantics.model.yaml.YamlFile; | ||
import org.openhab.core.semantics.model.yaml.YamlModelListener; | ||
import org.osgi.service.component.annotations.Activate; | ||
import org.osgi.service.component.annotations.Component; | ||
import org.osgi.service.component.annotations.Deactivate; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
/** | ||
* {@link YamlSemanticTagProvider} is an OSGi service, that allows to define semantic tags | ||
* in YAML configuration files in folder conf/tags. | ||
* Files can be added, updated or removed at runtime. | ||
* These semantic tags are automatically exposed to the {@link SemanticTagRegistry}. | ||
* | ||
* @author Laurent Garnier - Initial contribution | ||
*/ | ||
@NonNullByDefault | ||
@Component(immediate = true, service = { SemanticTagProvider.class, YamlSemanticTagProvider.class, | ||
YamlModelListener.class }) | ||
public class YamlSemanticTagProvider extends AbstractProvider<SemanticTag> | ||
implements SemanticTagProvider, YamlModelListener<YamlSemanticTag> { | ||
|
||
private final Logger logger = LoggerFactory.getLogger(YamlSemanticTagProvider.class); | ||
|
||
private final List<SemanticTag> tags = new ArrayList<>(); | ||
|
||
@Activate | ||
public YamlSemanticTagProvider() { | ||
} | ||
|
||
@Deactivate | ||
public void deactivate() { | ||
tags.clear(); | ||
} | ||
|
||
@Override | ||
public Collection<SemanticTag> getAll() { | ||
return tags.stream().sorted(Comparator.comparing(SemanticTag::getUID)).toList(); | ||
} | ||
|
||
@Override | ||
public String getRootName() { | ||
return "tags"; | ||
} | ||
|
||
@Override | ||
public Class<? extends YamlFile> getFileClass() { | ||
return YamlSemanticTags.class; | ||
} | ||
|
||
@Override | ||
public Class<YamlSemanticTag> getElementClass() { | ||
return YamlSemanticTag.class; | ||
} | ||
|
||
@Override | ||
public void addedModel(String modelName, List<? extends YamlElement> elements) { | ||
List<SemanticTag> added = elements.stream().map(e -> mapSemanticTag((YamlSemanticTag) e)) | ||
.sorted(Comparator.comparing(SemanticTag::getUID)).toList(); | ||
tags.addAll(added); | ||
added.forEach(t -> { | ||
logger.debug("model {} added tag {}", modelName, t.getUID()); | ||
notifyListenersAboutAddedElement(t); | ||
}); | ||
} | ||
|
||
@Override | ||
public void updatedModel(String modelName, List<? extends YamlElement> elements) { | ||
List<SemanticTag> updated = elements.stream().map(e -> mapSemanticTag((YamlSemanticTag) e)).toList(); | ||
updated.forEach(t -> { | ||
tags.stream().filter(tag -> tag.getUID().equals(t.getUID())).findFirst().ifPresentOrElse(oldTag -> { | ||
tags.remove(oldTag); | ||
tags.add(t); | ||
logger.debug("model {} updated tag {}", modelName, t.getUID()); | ||
notifyListenersAboutUpdatedElement(oldTag, t); | ||
}, () -> logger.debug("model {} tag {} not found", modelName, t.getUID())); | ||
}); | ||
} | ||
|
||
@Override | ||
public void removedModel(String modelName, List<? extends YamlElement> elements) { | ||
List<SemanticTag> removed = elements.stream().map(e -> mapSemanticTag((YamlSemanticTag) e)) | ||
.sorted(Comparator.comparing(SemanticTag::getUID).reversed()).toList(); | ||
removed.forEach(t -> { | ||
tags.stream().filter(tag -> tag.getUID().equals(t.getUID())).findFirst().ifPresentOrElse(oldTag -> { | ||
tags.remove(oldTag); | ||
logger.debug("model {} removed tag {}", modelName, t.getUID()); | ||
notifyListenersAboutRemovedElement(oldTag); | ||
}, () -> logger.debug("model {} tag {} not found", modelName, t.getUID())); | ||
}); | ||
} | ||
|
||
private SemanticTag mapSemanticTag(YamlSemanticTag tagDTO) { | ||
if (tagDTO.uid == null) { | ||
throw new IllegalArgumentException("The argument 'tagDTO.uid' must not be null."); | ||
} | ||
return new SemanticTagImpl(tagDTO.uid, tagDTO.label, tagDTO.description, tagDTO.synonyms); | ||
} | ||
} |
44 changes: 44 additions & 0 deletions
44
...ntics/src/main/java/org/openhab/core/semantics/internal/config/yaml/YamlSemanticTags.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
/** | ||
* 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.semantics.internal.config.yaml; | ||
|
||
import java.util.List; | ||
|
||
import org.eclipse.jdt.annotation.NonNullByDefault; | ||
import org.openhab.core.semantics.model.yaml.YamlElement; | ||
import org.openhab.core.semantics.model.yaml.YamlFile; | ||
import org.openhab.core.semantics.model.yaml.YamlParseException; | ||
|
||
/** | ||
* The {@link YamlSemanticTags} is a data transfer object used to serialize a list of semantic tags | ||
* in a YAML configuration file. | ||
* | ||
* @author Laurent Garnier - Initial contribution | ||
*/ | ||
@NonNullByDefault | ||
public class YamlSemanticTags extends YamlFile { | ||
|
||
public List<YamlSemanticTag> tags = List.of(); | ||
|
||
@Override | ||
public List<? extends YamlElement> getElements() { | ||
return tags; | ||
} | ||
|
||
@Override | ||
protected void checkVersion() throws YamlParseException { | ||
if (version != 1) { | ||
throw new YamlParseException("Version 1 required; please convert your file"); | ||
} | ||
} | ||
} |
25 changes: 25 additions & 0 deletions
25
...enhab.core.semantics/src/main/java/org/openhab/core/semantics/model/yaml/YamlElement.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
/** | ||
* 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.semantics.model.yaml; | ||
|
||
/** | ||
* The {@link YamlElement} interface offers an identifier to any element defined in a YAML configuration file. | ||
* | ||
* @author Laurent Garnier - Initial contribution | ||
*/ | ||
public interface YamlElement { | ||
|
||
String getId(); | ||
|
||
void checkValidity() throws YamlParseException; | ||
} |
50 changes: 50 additions & 0 deletions
50
....openhab.core.semantics/src/main/java/org/openhab/core/semantics/model/yaml/YamlFile.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
/** | ||
* 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.semantics.model.yaml; | ||
|
||
import java.util.List; | ||
|
||
import org.eclipse.jdt.annotation.NonNullByDefault; | ||
|
||
/** | ||
* The {@link YamlFile} is the DTO base class used to map a YAML configuration file. | ||
* | ||
* A YAML configuration file consists of a version and a list of elements. | ||
* | ||
* @author Laurent Garnier - Initial contribution | ||
*/ | ||
@NonNullByDefault | ||
public abstract class YamlFile { | ||
|
||
public int version; | ||
|
||
public abstract List<? extends YamlElement> getElements(); | ||
|
||
protected abstract void checkVersion() throws YamlParseException; | ||
|
||
public void checkValidity() throws YamlParseException { | ||
checkVersion(); | ||
List<? extends YamlElement> elts = getElements(); | ||
long nbDistinctIds = elts.stream().map(YamlElement::getId).distinct().count(); | ||
if (nbDistinctIds < elts.size()) { | ||
throw new YamlParseException((elts.size() - nbDistinctIds + 1) + " elements with same ids"); | ||
} | ||
for (int i = 0; i < elts.size(); i++) { | ||
try { | ||
elts.get(i).checkValidity(); | ||
} catch (YamlParseException e) { | ||
throw new YamlParseException("Error in element " + (i + 1) + ": " + e.getMessage()); | ||
} | ||
} | ||
} | ||
} |
39 changes: 39 additions & 0 deletions
39
...core.semantics/src/main/java/org/openhab/core/semantics/model/yaml/YamlModelListener.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
/** | ||
* 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.semantics.model.yaml; | ||
|
||
import java.util.List; | ||
|
||
import org.eclipse.jdt.annotation.NonNullByDefault; | ||
|
||
/** | ||
* The {@link YamlModelListener} interface is responsible for managing a particular model | ||
* with data processed from YAML configuration files. | ||
* | ||
* @author Laurent Garnier - Initial contribution | ||
*/ | ||
@NonNullByDefault | ||
public interface YamlModelListener<T extends YamlElement> { | ||
|
||
void addedModel(String modelName, List<? extends YamlElement> elements); | ||
|
||
void updatedModel(String modelName, List<? extends YamlElement> elements); | ||
|
||
void removedModel(String modelName, List<? extends YamlElement> elements); | ||
|
||
String getRootName(); | ||
|
||
Class<? extends YamlFile> getFileClass(); | ||
|
||
Class<T> getElementClass(); | ||
} |
Oops, something went wrong.