Skip to content

Commit b7b23db

Browse files
authored
YAML configuration: add support for things (openhab#4691)
Related to openhab#3666 Signed-off-by: Laurent Garnier <lg.hc@free.fr>
1 parent 1c955f3 commit b7b23db

File tree

16 files changed

+1790
-41
lines changed

16 files changed

+1790
-41
lines changed

bundles/org.openhab.core.io.rest.core/src/main/java/org/openhab/core/io/rest/core/internal/fileformat/FileFormatResource.java

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@
9494
* This resource is registered with the Jersey servlet.
9595
*
9696
* @author Laurent Garnier - Initial contribution
97+
* @author Laurent Garnier - Add YAML output for things
9798
*/
9899
@Component
99100
@JaxrsResource
@@ -108,6 +109,15 @@ public class FileFormatResource implements RESTResource {
108109
/** The URI path to this resource */
109110
public static final String PATH_FILE_FORMAT = "file-format";
110111

112+
private static final String DSL_THINGS_EXAMPLE = "Bridge binding:typeBridge:idBridge \"Label brigde\" @ \"Location bridge\" [stringParam=\"my value\"] {" //
113+
+ "\n Thing type id \"Label thing\" @ \"Location thing\" [booleanParam=true, decimalParam=2.5]\n}";
114+
private static final String DSL_THING_EXAMPLE = "Thing binding:type:idBridge:id \"Label thing\" @ \"Location thing\" (binding:typeBridge:idBridge) [stringParam=\"my value\", booleanParam=true, decimalParam=2.5]";
115+
private static final String YAML_THINGS_EXAMPLE = "version: 2\nthings:\n" //
116+
+ " binding:typeBridge:idBridge:\n isBridge: true\n label: Label bridge\n location: Location bridge\n config:\n stringParam: my value\n"
117+
+ " binding:type:idBridge:id:\n bridge: binding:typeBridge:idBridge\n label: Label thing\n location: Location thing\n config:\n booleanParam: true\n decimalParam: 2.5";
118+
private static final String YAML_THING_EXAMPLE = "version: 2\nthings:\n" //
119+
+ " binding:type:idBridge:id:\n bridge: binding:typeBridge:idBridge\n label: Label thing\n location: Location thing\n config:\n stringParam: my value\n booleanParam: true\n decimalParam: 2.5";
120+
111121
private final Logger logger = LoggerFactory.getLogger(FileFormatResource.class);
112122

113123
private final ItemRegistry itemRegistry;
@@ -216,16 +226,28 @@ public Response createFileFormatForItem(final @Context HttpHeaders httpHeaders,
216226
@GET
217227
@RolesAllowed({ Role.ADMIN })
218228
@Path("/things")
219-
@Produces("text/vnd.openhab.dsl.thing")
229+
@Produces({ "text/vnd.openhab.dsl.thing", "application/yaml" })
220230
@Operation(operationId = "createFileFormatForAllThings", summary = "Create file format for all existing things in registry.", security = {
221231
@SecurityRequirement(name = "oauth2", scopes = { "admin" }) }, responses = {
222-
@ApiResponse(responseCode = "200", description = "OK", content = @Content(mediaType = "text/vnd.openhab.dsl.thing", schema = @Schema(example = "Bridge binding:typeBridge:idBridge \"Label\" @ \"Location\" [stringParam=\"my value\"] {\n Thing type id \"Label\" @ \"Location\" [booleanParam=true, decimalParam=2.5]\n}"))),
232+
@ApiResponse(responseCode = "200", description = "OK", content = {
233+
@Content(mediaType = "text/vnd.openhab.dsl.thing", schema = @Schema(example = DSL_THINGS_EXAMPLE)),
234+
@Content(mediaType = "application/yaml", schema = @Schema(example = YAML_THINGS_EXAMPLE)) }),
223235
@ApiResponse(responseCode = "415", description = "Unsupported media type.") })
224236
public Response createFileFormatForAllThings(final @Context HttpHeaders httpHeaders,
225237
@DefaultValue("true") @QueryParam("hideDefaultParameters") @Parameter(description = "hide the configuration parameters having the default value") boolean hideDefaultParameters) {
226238
String acceptHeader = httpHeaders.getHeaderString(HttpHeaders.ACCEPT);
227-
String format = "text/vnd.openhab.dsl.thing".equals(acceptHeader) ? "DSL" : null;
228-
ThingFileGenerator generator = format == null ? null : thingFileGenerators.get(format);
239+
ThingFileGenerator generator;
240+
switch (acceptHeader) {
241+
case "text/vnd.openhab.dsl.thing":
242+
generator = thingFileGenerators.get("DSL");
243+
break;
244+
case "application/yaml":
245+
generator = thingFileGenerators.get("YAML");
246+
break;
247+
default:
248+
generator = null;
249+
break;
250+
}
229251
if (generator == null) {
230252
return Response.status(Response.Status.UNSUPPORTED_MEDIA_TYPE)
231253
.entity("Unsupported media type '" + acceptHeader + "'!").build();
@@ -238,18 +260,30 @@ public Response createFileFormatForAllThings(final @Context HttpHeaders httpHead
238260
@GET
239261
@RolesAllowed({ Role.ADMIN })
240262
@Path("/things/{thingUID}")
241-
@Produces("text/vnd.openhab.dsl.thing")
263+
@Produces({ "text/vnd.openhab.dsl.thing", "application/yaml" })
242264
@Operation(operationId = "createFileFormatForThing", summary = "Create file format for an existing thing in things or discovery registry.", security = {
243265
@SecurityRequirement(name = "oauth2", scopes = { "admin" }) }, responses = {
244-
@ApiResponse(responseCode = "200", description = "OK", content = @Content(mediaType = "text/vnd.openhab.dsl.thing", schema = @Schema(example = "Thing binding:type:idBridge:id \"Label\" @ \"Location\" (binding:typeBridge:idBridge) [stringParam=\"my value\", booleanParam=true, decimalParam=2.5]"))),
266+
@ApiResponse(responseCode = "200", description = "OK", content = {
267+
@Content(mediaType = "text/vnd.openhab.dsl.thing", schema = @Schema(example = DSL_THING_EXAMPLE)),
268+
@Content(mediaType = "application/yaml", schema = @Schema(example = YAML_THING_EXAMPLE)) }),
245269
@ApiResponse(responseCode = "404", description = "Thing not found in things or discovery registry or thing type not found."),
246270
@ApiResponse(responseCode = "415", description = "Unsupported media type.") })
247271
public Response createFileFormatForThing(final @Context HttpHeaders httpHeaders,
248272
@DefaultValue("true") @QueryParam("hideDefaultParameters") @Parameter(description = "hide the configuration parameters having the default value") boolean hideDefaultParameters,
249273
@PathParam("thingUID") @Parameter(description = "thingUID") String thingUID) {
250274
String acceptHeader = httpHeaders.getHeaderString(HttpHeaders.ACCEPT);
251-
String format = "text/vnd.openhab.dsl.thing".equals(acceptHeader) ? "DSL" : null;
252-
ThingFileGenerator generator = format == null ? null : thingFileGenerators.get(format);
275+
ThingFileGenerator generator;
276+
switch (acceptHeader) {
277+
case "text/vnd.openhab.dsl.thing":
278+
generator = thingFileGenerators.get("DSL");
279+
break;
280+
case "application/yaml":
281+
generator = thingFileGenerators.get("YAML");
282+
break;
283+
default:
284+
generator = null;
285+
break;
286+
}
253287
if (generator == null) {
254288
return Response.status(Response.Status.UNSUPPORTED_MEDIA_TYPE)
255289
.entity("Unsupported media type '" + acceptHeader + "'!").build();

bundles/org.openhab.core.model.yaml/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,10 @@
2525
<artifactId>org.openhab.core.semantics</artifactId>
2626
<version>${project.version}</version>
2727
</dependency>
28+
<dependency>
29+
<groupId>org.openhab.core.bundles</groupId>
30+
<artifactId>org.openhab.core.thing</artifactId>
31+
<version>${project.version}</version>
32+
</dependency>
2833
</dependencies>
2934
</project>

bundles/org.openhab.core.model.yaml/src/main/java/org/openhab/core/model/yaml/YamlElement.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,10 @@
1212
*/
1313
package org.openhab.core.model.yaml;
1414

15+
import java.util.List;
16+
1517
import org.eclipse.jdt.annotation.NonNull;
18+
import org.eclipse.jdt.annotation.Nullable;
1619
import org.openhab.core.model.yaml.internal.YamlModelRepositoryImpl;
1720

1821
/**
@@ -30,6 +33,7 @@
3033
* @author Laurent Garnier - Initial contribution
3134
* @author Jan N. Klug - Refactoring and improvements to JavaDoc
3235
* @author Laurent Garnier - Added methods setId and cloneWithoutId
36+
* @author Laurent Garnier - Added parameters to method isValid
3337
*/
3438
public interface YamlElement {
3539

@@ -74,7 +78,10 @@ public interface YamlElement {
7478
* <li>MAY perform additional checks</li>
7579
* </ul>
7680
*
81+
* @param errors a list of error messages to fill with fatal invalid controls; can be null to ignore messages
82+
* @param warnings a list of warning messages to fill with non-fatal invalid controls; can be null to ignore
83+
* messages
7784
* @return {@code true} if all the checks are completed successfully
7885
*/
79-
boolean isValid();
86+
boolean isValid(@Nullable List<@NonNull String> errors, @Nullable List<@NonNull String> warnings);
8087
}

bundles/org.openhab.core.model.yaml/src/main/java/org/openhab/core/model/yaml/YamlModelRepository.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,16 @@
1212
*/
1313
package org.openhab.core.model.yaml;
1414

15+
import java.io.OutputStream;
16+
import java.util.List;
17+
1518
import org.eclipse.jdt.annotation.NonNullByDefault;
1619

1720
/**
1821
* The {@link YamlModelRepository} defines methods to update elements in a YAML model.
1922
*
2023
* @author Jan N. Klug - Initial contribution
24+
* @author Laurent Garnier - Added methods refreshModelElements and generateSyntaxFromElements
2125
*/
2226
@NonNullByDefault
2327
public interface YamlModelRepository {
@@ -26,4 +30,20 @@ public interface YamlModelRepository {
2630
void removeElementFromModel(String modelName, YamlElement element);
2731

2832
void updateElementInModel(String modelName, YamlElement element);
33+
34+
/**
35+
* Triggers the refresh of a certain type of elements in a given model.
36+
*
37+
* @param modelName the model name
38+
* @param elementName the type of elements to refresh
39+
*/
40+
void refreshModelElements(String modelName, String elementName);
41+
42+
/**
43+
* Generate the YAML syntax from a provided list of elements.
44+
*
45+
* @param out the output stream to write the generated syntax to
46+
* @param elements the list of elements to includ
47+
*/
48+
void generateSyntaxFromElements(OutputStream out, List<YamlElement> elements);
2949
}

0 commit comments

Comments
 (0)