Migrate to OpenAPI 3 annotations (#299)

Signed-off-by: Wouter Born <github@maindrain.net>
pull/300/head
Wouter Born 2020-08-02 16:14:55 +02:00 committed by GitHub
parent 3c597f5ed7
commit 7453955770
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 270 additions and 240 deletions

View File

@ -71,10 +71,9 @@ import org.rrd4j.core.Util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
/**
* handles requests for chart series data from the CometVisu client
@ -82,6 +81,7 @@ import io.swagger.annotations.ApiResponses;
*
* @author Tobias Bräutigam - Initial contribution
* @author Wouter Born - Migrated to JAX-RS Whiteboard Specification
* @author Wouter Born - Migrated to OpenAPI annotations
*/
@Component
@JaxrsResource
@ -89,7 +89,7 @@ import io.swagger.annotations.ApiResponses;
@JaxrsApplicationSelect("(" + JaxrsWhiteboardConstants.JAX_RS_NAME + "=" + RESTConstants.JAX_RS_NAME + ")")
@JSONRequired
@Path(Config.COMETVISU_BACKEND_ALIAS + "/" + Config.COMETVISU_BACKEND_CHART_ALIAS)
@Api(Config.COMETVISU_BACKEND_ALIAS + "/" + Config.COMETVISU_BACKEND_CHART_ALIAS)
@Tag(name = Config.COMETVISU_BACKEND_ALIAS + "/" + Config.COMETVISU_BACKEND_CHART_ALIAS)
@NonNullByDefault
public class ChartResource implements RESTResource {
private final Logger logger = LoggerFactory.getLogger(ChartResource.class);
@ -135,9 +135,9 @@ public class ChartResource implements RESTResource {
@GET
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value = "returns chart data from persistence service for an item")
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK"),
@ApiResponse(code = 500, message = "Server error") })
@Operation(summary = "returns chart data from persistence service for an item", responses = {
@ApiResponse(responseCode = "200", description = "OK"),
@ApiResponse(responseCode = "500", description = "Server error") })
public Response getChartSeries(@Context HttpHeaders headers, @QueryParam("rrd") String itemName,
@QueryParam("ds") String consFunction, @QueryParam("start") String start, @QueryParam("end") String end,
@QueryParam("res") long resolution) {

View File

@ -15,6 +15,7 @@ package org.openhab.ui.cometvisu.internal.backend.rest;
import java.io.File;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
@ -35,16 +36,18 @@ import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsApplicationSelect;
import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsName;
import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsResource;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
/**
* Check filesystem backend for the cometvisu manager.
*
* @author Tobias Bräutigam - Initial contribution
* @author Wouter Born - Migrated to JAX-RS Whiteboard Specification
* @author Wouter Born - Migrated to OpenAPI annotations
*/
@Component
@JaxrsResource
@ -52,7 +55,7 @@ import io.swagger.annotations.ApiResponses;
@JaxrsApplicationSelect("(" + JaxrsWhiteboardConstants.JAX_RS_NAME + "=" + RESTConstants.JAX_RS_NAME + ")")
@JSONRequired
@Path(Config.COMETVISU_BACKEND_ALIAS + "/fs/check")
@Api(Config.COMETVISU_BACKEND_ALIAS + "/fs/check")
@Tag(name = Config.COMETVISU_BACKEND_ALIAS + "/fs/check")
@NonNullByDefault
public class CheckResource implements RESTResource {
@ -63,12 +66,12 @@ public class CheckResource implements RESTResource {
*/
@GET
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value = "Check filesystem environment (access rights, etc)")
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = CheckResponse.class) })
@Operation(summary = "Check filesystem environment (access rights, etc)", responses = {
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = CheckResponse.class))) })
public CheckResponse checkEnvironment() {
CheckResponse res = new CheckResponse();
File configFolder = ManagerSettings.getInstance().getConfigFolder();
ArrayList<File> filesToCheck = new ArrayList<File>();
List<File> filesToCheck = new ArrayList<>();
filesToCheck.add(configFolder);
filesToCheck.add(new File(configFolder.getAbsoluteFile() + File.separator + "media"));
filesToCheck.add(new File(configFolder.getAbsoluteFile() + File.separator + "backup"));

View File

@ -33,17 +33,17 @@ import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsResource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
/**
* Allows certain actions to configure the CometVisu backend through the REST api.
*
* @author Tobias Bräutigam - Initial contribution
* @author Wouter Born - Migrated to JAX-RS Whiteboard Specification
* @author Wouter Born - Migrated to OpenAPI annotations
*/
@Component
@JaxrsResource
@ -51,7 +51,7 @@ import io.swagger.annotations.ApiResponses;
@JaxrsApplicationSelect("(" + JaxrsWhiteboardConstants.JAX_RS_NAME + "=" + RESTConstants.JAX_RS_NAME + ")")
@JSONRequired
@Path(Config.COMETVISU_BACKEND_ALIAS + "/" + Config.COMETVISU_BACKEND_CONFIG_ALIAS)
@Api(Config.COMETVISU_BACKEND_ALIAS + "/" + Config.COMETVISU_BACKEND_CONFIG_ALIAS)
@Tag(name = Config.COMETVISU_BACKEND_ALIAS + "/" + Config.COMETVISU_BACKEND_CONFIG_ALIAS)
@NonNullByDefault
public class ConfigResource implements RESTResource {
@ -60,10 +60,10 @@ public class ConfigResource implements RESTResource {
@GET
@Path("/{actionName}")
@Produces({ MediaType.TEXT_PLAIN })
@ApiOperation(value = "starts defined actions e.g. downloading the CometVisu client")
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK") })
@Operation(summary = "starts defined actions e.g. downloading the CometVisu client", responses = {
@ApiResponse(responseCode = "200", description = "OK") })
public Response getValue(
@ApiParam(value = "name of the action, currently only 'download-client' is implemented") @PathParam("actionName") String actionName) {
@Parameter(description = "name of the action, currently only 'download-client' is implemented") @PathParam("actionName") String actionName) {
if ("download-client".equalsIgnoreCase(actionName)) {
logger.debug("calling installation checker with config overriding");
ClientInstaller.getInstance().check(true);

View File

@ -54,16 +54,19 @@ import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsResource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.ArraySchema;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
/**
* DataProvider backend for the cometvisu manager.
*
* @author Tobias Bräutigam - Initial contribution
* @author Wouter Born - Migrated to JAX-RS Whiteboard Specification
* @author Wouter Born - Migrated to OpenAPI annotations
*/
@Component
@JaxrsResource
@ -71,7 +74,7 @@ import io.swagger.annotations.ApiResponses;
@JaxrsApplicationSelect("(" + JaxrsWhiteboardConstants.JAX_RS_NAME + "=" + RESTConstants.JAX_RS_NAME + ")")
@JSONRequired
@Path(Config.COMETVISU_BACKEND_ALIAS + "/data")
@Api(Config.COMETVISU_BACKEND_ALIAS + "/data")
@Tag(name = Config.COMETVISU_BACKEND_ALIAS + "/data")
@NonNullByDefault
public class DataProviderResource implements RESTResource {
private final Logger logger = LoggerFactory.getLogger(DataProviderResource.class);
@ -98,8 +101,8 @@ public class DataProviderResource implements RESTResource {
@GET
@Path("/addresses")
@Produces({ MediaType.APPLICATION_JSON })
@ApiOperation(value = "Returns the list of available addresses.")
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = Map.class) })
@Operation(summary = "Returns the list of available addresses.", responses = {
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = Map.class))) })
public Response getAddresses() {
// collect all available transform types
List<String> transformTypes = new ArrayList<>();
@ -144,8 +147,8 @@ public class DataProviderResource implements RESTResource {
@GET
@Path("/designs")
@Produces({ MediaType.APPLICATION_JSON })
@ApiOperation(value = "Returns the list of available designs.")
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = List.class) })
@Operation(summary = "Returns the list of available designs.", responses = {
@ApiResponse(responseCode = "200", description = "OK", content = @Content(array = @ArraySchema(schema = @Schema(implementation = String.class)))) })
public List<String> getDesigns() {
// all designs
File designDir = ManagerSettings.getInstance().getDesignFolder();
@ -165,8 +168,8 @@ public class DataProviderResource implements RESTResource {
@GET
@Path("/influxdbfields")
@Produces({ MediaType.APPLICATION_JSON })
@ApiOperation(value = "Returns the list of available influx database tags.")
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK") })
@Operation(summary = "Returns the list of available influx database tags.", responses = {
@ApiResponse(responseCode = "200", description = "OK") })
public Response getInfluxDBFields(@QueryParam("auth") String auth, @QueryParam("measurement") String measurement) {
// this is not supported by the openHAB backend
return Response.ok().build();
@ -175,8 +178,8 @@ public class DataProviderResource implements RESTResource {
@GET
@Path("/influxdbtags")
@Produces({ MediaType.APPLICATION_JSON })
@ApiOperation(value = "Returns the list of available influx database fields.")
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK") })
@Operation(summary = "Returns the list of available influx database fields.", responses = {
@ApiResponse(responseCode = "200", description = "OK") })
public Response getInfluxDBTags(@QueryParam("auth") String auth, @QueryParam("measurement") String measurement) {
// this is not supported by the openHAB backend
return Response.ok().build();
@ -185,8 +188,8 @@ public class DataProviderResource implements RESTResource {
@GET
@Path("/influxdbs")
@Produces({ MediaType.APPLICATION_JSON })
@ApiOperation(value = "Returns the list of available influx databases.")
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK") })
@Operation(summary = "Returns the list of available influx databases.", responses = {
@ApiResponse(responseCode = "200", description = "OK") })
public Response getInfluxDBs(@QueryParam("auth") String auth) {
// this is not supported by the openHAB backend
return Response.ok().build();
@ -195,8 +198,8 @@ public class DataProviderResource implements RESTResource {
@GET
@Path("/rrds")
@Produces({ MediaType.APPLICATION_JSON })
@ApiOperation(value = "Returns the list of available RRDs.")
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = DataProviderResponse.class) })
@Operation(summary = "Returns the list of available RRDs.", responses = {
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = DataProviderResponse.class))) })
public Response getRRDs() {
DataProviderResponse res = new DataProviderResponse();
for (final QueryablePersistenceService service : persistenceServices.values()) {

View File

@ -53,17 +53,19 @@ import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsResource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
/**
* Filesystem backend for the cometvisu manager.
*
* @author Tobias Bräutigam - Initial contribution
* @author Wouter Born - Migrated to JAX-RS Whiteboard Specification
* @author Wouter Born - Migrated to OpenAPI annotations
*/
@Component
@JaxrsResource
@ -71,7 +73,7 @@ import io.swagger.annotations.ApiResponses;
@JaxrsApplicationSelect("(" + JaxrsWhiteboardConstants.JAX_RS_NAME + "=" + RESTConstants.JAX_RS_NAME + ")")
@JSONRequired
@Path(Config.COMETVISU_BACKEND_ALIAS + "/fs")
@Api(Config.COMETVISU_BACKEND_ALIAS + "/fs")
@Tag(name = Config.COMETVISU_BACKEND_ALIAS + "/fs")
@NonNullByDefault
public class FsResource implements RESTResource {
private final Logger logger = LoggerFactory.getLogger(FsResource.class);
@ -79,11 +81,11 @@ public class FsResource implements RESTResource {
@POST
@Consumes("text/*")
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value = "Create a text file")
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK"), @ApiResponse(code = 403, message = "not allowed"),
@ApiResponse(code = 406, message = "File already exists") })
@Operation(summary = "Create a text file", responses = { @ApiResponse(responseCode = "200", description = "OK"),
@ApiResponse(responseCode = "403", description = "not allowed"),
@ApiResponse(responseCode = "406", description = "File already exists") })
public Response create(@QueryParam("path") String path, @QueryParam("type") String type,
@QueryParam("hash") String hash, @ApiParam(value = "file content") String body,
@QueryParam("hash") String hash, @Parameter(description = "file content") String body,
@DefaultValue("false") @QueryParam("force") Boolean force) {
MountedFile file;
try {
@ -113,15 +115,15 @@ public class FsResource implements RESTResource {
@POST
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value = "Create a binary file")
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK"), @ApiResponse(code = 403, message = "not allowed"),
@ApiResponse(code = 406, message = "File already exists") })
@Operation(summary = "Create a binary file", responses = { @ApiResponse(responseCode = "200", description = "OK"),
@ApiResponse(responseCode = "403", description = "not allowed"),
@ApiResponse(responseCode = "406", description = "File already exists") })
public Response createBinary(@Context HttpServletRequest request,
@ApiParam(value = "Relative path inside the config folder", required = true) @QueryParam("path") String path,
@Parameter(description = "Relative path inside the config folder", required = true) @QueryParam("path") String path,
@QueryParam("type") String type,
@ApiParam(value = "CRC32 hash of the file content") @QueryParam("hash") String hash,
@ApiParam(value = "force overriding existing file") @DefaultValue("false") @FormParam("force") Boolean force,
@ApiParam(value = "file content") @FormParam("file") Object fileParam) {
@Parameter(description = "CRC32 hash of the file content") @QueryParam("hash") String hash,
@Parameter(description = "force overriding existing file") @DefaultValue("false") @FormParam("force") Boolean force,
@Parameter(description = "file content") @FormParam("file") Object fileParam) {
MountedFile target;
try {
MultipartRequestMap map = new MultipartRequestMap(request);
@ -151,13 +153,13 @@ public class FsResource implements RESTResource {
@DELETE
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value = "Deletes a file/folder")
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK"), @ApiResponse(code = 403, message = "not allowed"),
@ApiResponse(code = 404, message = "File/Folder not found"),
@ApiResponse(code = 406, message = "Folder not empty") })
@Operation(summary = "Deletes a file/folder", responses = { @ApiResponse(responseCode = "200", description = "OK"),
@ApiResponse(responseCode = "403", description = "not allowed"),
@ApiResponse(responseCode = "404", description = "File/Folder not found"),
@ApiResponse(responseCode = "406", description = "Folder not empty") })
public Response delete(
@ApiParam(value = "Relative path inside the config folder", required = true) @QueryParam("path") String path,
@ApiParam(value = "force deletion of non empty folders") @QueryParam("force") Boolean force) {
@Parameter(description = "Relative path inside the config folder", required = true) @QueryParam("path") String path,
@Parameter(description = "force deletion of non empty folders") @QueryParam("force") Boolean force) {
MountedFile file;
try {
file = new MountedFile(path);
@ -200,14 +202,14 @@ public class FsResource implements RESTResource {
@GET
@Produces({ MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN, MediaType.APPLICATION_OCTET_STREAM })
@ApiOperation(value = "Return directory listing or file content")
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK"), @ApiResponse(code = 403, message = "not allowed"),
@ApiResponse(code = 404, message = "File/Folder not found") })
@Operation(summary = "Return directory listing or file content", responses = {
@ApiResponse(responseCode = "200", description = "OK"),
@ApiResponse(responseCode = "403", description = "not allowed"),
@ApiResponse(responseCode = "404", description = "File/Folder not found") })
public Response read(
@ApiParam(value = "Relative path inside the config folder", required = true, defaultValue = "") @QueryParam("path") String path,
@ApiParam(value = "should the file be downloaded?", defaultValue = "false") @DefaultValue("false") @QueryParam("download") Boolean download,
@ApiParam(value = "also include all sub-folders in the directory listing", defaultValue = "false") @DefaultValue("false") @QueryParam("recursive") Boolean recursive) {
@Parameter(description = "Relative path inside the config folder", required = true, content = @Content(schema = @Schema(implementation = String.class, defaultValue = ""))) @QueryParam("path") String path,
@Parameter(description = "should the file be downloaded?", content = @Content(schema = @Schema(implementation = Boolean.class, defaultValue = "false"))) @DefaultValue("false") @QueryParam("download") Boolean download,
@Parameter(description = "also include all sub-folders in the directory listing", content = @Content(schema = @Schema(implementation = Boolean.class, defaultValue = "false"))) @DefaultValue("false") @QueryParam("recursive") Boolean recursive) {
try {
MountedFile file = new MountedFile(path);
logger.debug("read request for: {}", file.getAbsolutePath());
@ -244,13 +246,14 @@ public class FsResource implements RESTResource {
@PUT
@Produces(MediaType.APPLICATION_JSON)
@Consumes({ MediaType.TEXT_PLAIN, MediaType.TEXT_XML })
@ApiOperation(value = "Update an existing file")
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK"), @ApiResponse(code = 403, message = "not allowed"),
@ApiResponse(code = 404, message = "File does not exist") })
@Operation(summary = "Update an existing file", responses = {
@ApiResponse(responseCode = "200", description = "OK"),
@ApiResponse(responseCode = "403", description = "not allowed"),
@ApiResponse(responseCode = "404", description = "File does not exist") })
public Response update(
@ApiParam(value = "Relative path inside the config folder", required = true) @QueryParam("path") String path,
@ApiParam(value = "file content") String body,
@ApiParam(value = "CRC32 hash value of the file content", defaultValue = "ignore") @DefaultValue("ignore") @QueryParam("hash") String hash) {
@Parameter(description = "Relative path inside the config folder", required = true) @QueryParam("path") String path,
@Parameter(description = "file content") String body,
@Parameter(description = "CRC32 hash value of the file content", content = @Content(schema = @Schema(implementation = String.class, defaultValue = "ignore"))) @DefaultValue("ignore") @QueryParam("hash") String hash) {
File target = new File(
ManagerSettings.getInstance().getConfigFolder().getAbsolutePath() + File.separator + path);
if (target.exists()) {

View File

@ -50,17 +50,17 @@ import org.slf4j.LoggerFactory;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
/**
* Hidden configuration backend for the cometvisu manager.
*
* @author Tobias Bräutigam - Initial contribution
* @author Wouter Born - Migrated to JAX-RS Whiteboard Specification
* @author Wouter Born - Migrated to OpenAPI annotations
*/
@Component
@JaxrsResource
@ -68,7 +68,7 @@ import io.swagger.annotations.ApiResponses;
@JaxrsApplicationSelect("(" + JaxrsWhiteboardConstants.JAX_RS_NAME + "=" + RESTConstants.JAX_RS_NAME + ")")
@JSONRequired
@Path(Config.COMETVISU_BACKEND_ALIAS + "/config")
@Api(Config.COMETVISU_BACKEND_ALIAS + "/config")
@Tag(name = Config.COMETVISU_BACKEND_ALIAS + "/config")
@NonNullByDefault
public class HiddenConfigResource implements RESTResource {
private final Logger logger = LoggerFactory.getLogger(HiddenConfigResource.class);
@ -79,14 +79,15 @@ public class HiddenConfigResource implements RESTResource {
@POST
@Path("/hidden/{section}/{key}")
@Consumes(MediaType.TEXT_PLAIN)
@ApiOperation(value = "Creates a new config option")
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK"), @ApiResponse(code = 403, message = "not allowed"),
@ApiResponse(code = 404, message = "section not found"),
@ApiResponse(code = 406, message = "config option exists") })
@Operation(summary = "Creates a new config option", responses = {
@ApiResponse(responseCode = "200", description = "OK"),
@ApiResponse(responseCode = "403", description = "not allowed"),
@ApiResponse(responseCode = "404", description = "section not found"),
@ApiResponse(responseCode = "406", description = "config option exists") })
public Response createHiddenConfig(
@ApiParam(value = "Section of the config option") @PathParam("section") String section,
@ApiParam(value = "Key (ID) of the config option in the section, ('*' for all options)") @PathParam("key") String key,
@ApiParam(value = "value of the option", required = true) String body) {
@Parameter(description = "Section of the config option") @PathParam("section") String section,
@Parameter(description = "Key (ID) of the config option in the section, ('*' for all options)") @PathParam("key") String key,
@Parameter(description = "value of the option", required = true) String body) {
if (section.equals("*") || key.equals("*")) {
return FsUtil.createErrorResponse(Status.NOT_ACCEPTABLE, "wildcard not allowed");
}
@ -110,12 +111,12 @@ public class HiddenConfigResource implements RESTResource {
@DELETE
@Path("/hidden/{section}/{key}")
@ApiOperation(value = "Delete config option")
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK"), @ApiResponse(code = 403, message = "not allowed"),
@ApiResponse(code = 404, message = "config option does not exist") })
@Operation(summary = "Delete config option", responses = { @ApiResponse(responseCode = "200", description = "OK"),
@ApiResponse(responseCode = "403", description = "not allowed"),
@ApiResponse(responseCode = "404", description = "config option does not exist") })
public Response deleteHiddenConfig(
@ApiParam(value = "Section of the config option, ('*' for all sections)") @PathParam("section") String section,
@ApiParam(value = "Key (ID) of the config option in the section, ('*' for all options)") @PathParam("key") String key) {
@Parameter(description = "Section of the config option, ('*' for all sections)") @PathParam("section") String section,
@Parameter(description = "Key (ID) of the config option in the section, ('*' for all options)") @PathParam("key") String key) {
HiddenConfig config = this.loadHiddenConfig();
if (section.equals("*")) {
config.clear();
@ -143,12 +144,13 @@ public class HiddenConfigResource implements RESTResource {
@GET
@Path("/hidden/{section}/{key}")
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value = "Provides the value of a config option")
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK"), @ApiResponse(code = 403, message = "not allowed"),
@ApiResponse(code = 404, message = "config option does not exist") })
@Operation(summary = "Provides the value of a config option", responses = {
@ApiResponse(responseCode = "200", description = "OK"),
@ApiResponse(responseCode = "403", description = "not allowed"),
@ApiResponse(responseCode = "404", description = "config option does not exist") })
public Response getHiddenConfig(
@ApiParam(value = "Section of the config option, ('*' for all sections)") @PathParam("section") String sectionKey,
@ApiParam(value = "Key (ID) of the config option in the section, ('*' for all options)") @PathParam("key") String key) {
@Parameter(description = "Section of the config option, ('*' for all sections)") @PathParam("section") String sectionKey,
@Parameter(description = "Key (ID) of the config option in the section, ('*' for all options)") @PathParam("key") String key) {
HiddenConfig config = this.loadHiddenConfig();
if (sectionKey.contentEquals("*")) {
if (key.contentEquals("*")) {
@ -179,11 +181,11 @@ public class HiddenConfigResource implements RESTResource {
@PUT
@Path("/hidden")
@Consumes(MediaType.APPLICATION_JSON)
@ApiOperation(value = "Save the hidden config")
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK"), @ApiResponse(code = 403, message = "not allowed"),
@ApiResponse(code = 500, message = "error saving hidden config") })
@Operation(summary = "Save the hidden config", responses = { @ApiResponse(responseCode = "200", description = "OK"),
@ApiResponse(responseCode = "403", description = "not allowed"),
@ApiResponse(responseCode = "500", description = "error saving hidden config") })
public Response saveHiddenConfig(
@ApiParam(value = "Complete config content", required = true) HiddenConfig config) {
@Parameter(description = "Complete config content", required = true) HiddenConfig config) {
try {
this.writeHiddenConfig(config);
return Response.ok().build();
@ -196,15 +198,16 @@ public class HiddenConfigResource implements RESTResource {
@PUT
@Path("/hidden/{section}/{key}")
@Consumes(MediaType.TEXT_PLAIN)
@ApiOperation(value = "Changes the value of an existing config option")
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK"), @ApiResponse(code = 403, message = "not allowed"),
@ApiResponse(code = 404, message = "config option does not exist"),
@ApiResponse(code = 406, message = "wildcard not allowed"),
@ApiResponse(code = 500, message = "error saving hidden config") })
@Operation(summary = "Changes the value of an existing config option", responses = {
@ApiResponse(responseCode = "200", description = "OK"),
@ApiResponse(responseCode = "403", description = "not allowed"),
@ApiResponse(responseCode = "404", description = "config option does not exist"),
@ApiResponse(responseCode = "406", description = "wildcard not allowed"),
@ApiResponse(responseCode = "500", description = "error saving hidden config") })
public Response updateHiddenConfig(
@ApiParam(value = "Section of the config option") @PathParam("section") String section,
@ApiParam(value = "Key (ID) of the config option in the section") @PathParam("key") String key,
@ApiParam(value = "value of the option", required = true) String body) {
@Parameter(description = "Section of the config option") @PathParam("section") String section,
@Parameter(description = "Key (ID) of the config option in the section") @PathParam("key") String key,
@Parameter(description = "value of the option", required = true) String body) {
if (section.equals("*") || key.equals("*")) {
return FsUtil.createErrorResponse(Status.NOT_ACCEPTABLE, "wildcard not allowed");
}

View File

@ -36,10 +36,11 @@ import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsApplicationSelect;
import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsName;
import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsResource;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
/**
* handles login request from the CometVisu client
@ -47,6 +48,7 @@ import io.swagger.annotations.ApiResponses;
*
* @author Tobias Bräutigam - Initial contribution
* @author Wouter Born - Migrated to JAX-RS Whiteboard Specification
* @author Wouter Born - Migrated to OpenAPI annotations
*/
@Component
@JaxrsResource
@ -54,13 +56,13 @@ import io.swagger.annotations.ApiResponses;
@JaxrsApplicationSelect("(" + JaxrsWhiteboardConstants.JAX_RS_NAME + "=" + RESTConstants.JAX_RS_NAME + ")")
@JSONRequired
@Path(Config.COMETVISU_BACKEND_ALIAS + "/" + Config.COMETVISU_BACKEND_LOGIN_ALIAS)
@Api(Config.COMETVISU_BACKEND_ALIAS + "/" + Config.COMETVISU_BACKEND_LOGIN_ALIAS)
@Tag(name = Config.COMETVISU_BACKEND_ALIAS + "/" + Config.COMETVISU_BACKEND_LOGIN_ALIAS)
@NonNullByDefault
public class LoginResource implements RESTResource {
@GET
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value = "returns the login response with backend configuration information")
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = LoginBean.class) })
@Operation(summary = "returns the login response with backend configuration information", responses = {
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = LoginBean.class))) })
public Response getLogin(@Context UriInfo uriInfo, @Context HttpHeaders headers, @QueryParam("u") String user,
@QueryParam("p") String password, @QueryParam("d") String device) {
LoginBean bean = new LoginBean();

View File

@ -39,17 +39,17 @@ import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsResource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
/**
* Move/renames files for the CometVisu manager.
*
* @author Tobias Bräutigam - Initial contribution
* @author Wouter Born - Migrated to JAX-RS Whiteboard Specification
* @author Wouter Born - Migrated to OpenAPI annotations
*/
@Component
@JaxrsResource
@ -57,20 +57,22 @@ import io.swagger.annotations.ApiResponses;
@JaxrsApplicationSelect("(" + JaxrsWhiteboardConstants.JAX_RS_NAME + "=" + RESTConstants.JAX_RS_NAME + ")")
@JSONRequired
@Path(Config.COMETVISU_BACKEND_ALIAS + "/fs/move")
@Api(Config.COMETVISU_BACKEND_ALIAS + "/fs/move")
@Tag(name = Config.COMETVISU_BACKEND_ALIAS + "/fs/move")
@NonNullByDefault
public class MoveResource implements RESTResource {
private final Logger logger = LoggerFactory.getLogger(MoveResource.class);
@PUT
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value = "Move folder or file to a new place")
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK"), @ApiResponse(code = 403, message = "forbidden"),
@ApiResponse(code = 404, message = "not found"), @ApiResponse(code = 406, message = "target exists"),
@ApiResponse(code = 500, message = "rename/move failed") })
@Operation(summary = "Move folder or file to a new place", responses = {
@ApiResponse(responseCode = "200", description = "OK"),
@ApiResponse(responseCode = "403", description = "forbidden"),
@ApiResponse(responseCode = "404", description = "not found"),
@ApiResponse(responseCode = "406", description = "target exists"),
@ApiResponse(responseCode = "500", description = "rename/move failed") })
public Response move(
@ApiParam(value = "current path of the filesystem entry", required = true) @QueryParam("src") String src,
@ApiParam(value = " new path of the filesystem entry", required = true) @QueryParam("target") String target) {
@Parameter(description = "current path of the filesystem entry", required = true) @QueryParam("src") String src,
@Parameter(description = " new path of the filesystem entry", required = true) @QueryParam("target") String target) {
MountedFile sourceFile;
MountedFile targetFile;
try {

View File

@ -58,10 +58,9 @@ import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsResource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
/**
* handles read request from the CometVisu client every request initializes a
@ -69,6 +68,7 @@ import io.swagger.annotations.ApiResponses;
*
* @author Tobias Bräutigam - Initial contribution
* @author Wouter Born - Migrated to JAX-RS Whiteboard Specification
* @author Wouter Born - Migrated to OpenAPI annotations
*/
@Component(immediate = true)
@JaxrsResource
@ -76,7 +76,7 @@ import io.swagger.annotations.ApiResponses;
@JaxrsApplicationSelect("(" + JaxrsWhiteboardConstants.JAX_RS_NAME + "=" + RESTConstants.JAX_RS_NAME + ")")
@JSONRequired
@Path(Config.COMETVISU_BACKEND_ALIAS + "/" + Config.COMETVISU_BACKEND_READ_ALIAS)
@Api(Config.COMETVISU_BACKEND_ALIAS + "/" + Config.COMETVISU_BACKEND_READ_ALIAS)
@Tag(name = Config.COMETVISU_BACKEND_ALIAS + "/" + Config.COMETVISU_BACKEND_READ_ALIAS)
@NonNullByDefault
public class ReadResource implements EventBroadcaster, RESTResource {
private final Logger logger = LoggerFactory.getLogger(ReadResource.class);
@ -131,8 +131,8 @@ public class ReadResource implements EventBroadcaster, RESTResource {
*/
@GET
@Produces(MediaType.SERVER_SENT_EVENTS)
@ApiOperation(value = "Creates the SSE stream for item states, sends all requested states once and then only changes states")
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK") })
@Operation(summary = "Creates the SSE stream for item states, sends all requested states once and then only changes states", responses = {
@ApiResponse(responseCode = "200", description = "OK") })
public void getStates(@Context final SseEventSink sseEventSink, @QueryParam("a") List<String> itemNames,
@QueryParam("i") long index, @QueryParam("t") long time) throws IOException, InterruptedException {

View File

@ -46,17 +46,17 @@ import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsResource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
/**
* handles state updates send by the CometVisu client and forwars them to the EventPublisher
*
* @author Tobias Bräutigam - Initial contribution
* @author Wouter Born - Migrated to JAX-RS Whiteboard Specification
* @author Wouter Born - Migrated to OpenAPI annotations
*/
@Component
@JaxrsResource
@ -64,7 +64,7 @@ import io.swagger.annotations.ApiResponses;
@JaxrsApplicationSelect("(" + JaxrsWhiteboardConstants.JAX_RS_NAME + "=" + RESTConstants.JAX_RS_NAME + ")")
@JSONRequired
@Path(Config.COMETVISU_BACKEND_ALIAS + "/" + Config.COMETVISU_BACKEND_WRITE_ALIAS)
@Api(Config.COMETVISU_BACKEND_ALIAS + "/" + Config.COMETVISU_BACKEND_WRITE_ALIAS)
@Tag(name = Config.COMETVISU_BACKEND_ALIAS + "/" + Config.COMETVISU_BACKEND_WRITE_ALIAS)
@NonNullByDefault
public class WriteResource implements RESTResource {
private final Logger logger = LoggerFactory.getLogger(WriteResource.class);
@ -82,13 +82,13 @@ public class WriteResource implements RESTResource {
@GET
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value = "starts defined actions e.g. downloading the CometVisu client")
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK"),
@ApiResponse(code = 404, message = "Item not found") })
@Operation(summary = "starts defined actions e.g. downloading the CometVisu client", responses = {
@ApiResponse(responseCode = "200", description = "OK"),
@ApiResponse(responseCode = "404", description = "Item not found") })
public Response setState(@Context HttpHeaders headers,
@ApiParam(value = "Item name", required = true) @QueryParam("a") String itemName,
@ApiParam(value = "Item value", required = true) @QueryParam("v") String value,
@ApiParam(value = "timestamp") @QueryParam("ts") long timestamp) {
@Parameter(description = "Item name", required = true) @QueryParam("a") String itemName,
@Parameter(description = "Item value", required = true) @QueryParam("v") String value,
@Parameter(description = "timestamp") @QueryParam("ts") long timestamp) {
if (logger.isDebugEnabled()) {
logger.debug("Received CV write request at '{}' for item '{}' with value '{}'.", uriInfo.getPath(),
itemName, value);

View File

@ -62,17 +62,20 @@ import org.slf4j.LoggerFactory;
import com.google.gson.Gson;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.ArraySchema;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
/**
* This class describes the /habot resource of the REST API.
*
* @author Yannick Schaus - Initial contribution
* @author Wouter Born - Migrated to JAX-RS Whiteboard Specification
* @author Wouter Born - Migrated to OpenAPI annotations
*/
@Component
@JaxrsResource
@ -81,7 +84,7 @@ import io.swagger.annotations.ApiResponses;
@JSONRequired
@RolesAllowed({ Role.USER, Role.ADMIN })
@Path(HABotResource.PATH_HABOT)
@Api(HABotResource.PATH_HABOT)
@Tag(name = HABotResource.PATH_HABOT)
@NonNullByDefault
public class HABotResource implements RESTResource {
@ -116,9 +119,9 @@ public class HABotResource implements RESTResource {
@RolesAllowed({ Role.USER, Role.ADMIN })
@Path("/greet")
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value = "Retrieves a first greeting message from the bot in the specified or configured language.")
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = ChatReply.class),
@ApiResponse(code = 500, message = "There is no support for the configured language") })
@Operation(summary = "Retrieves a first greeting message from the bot in the specified or configured language.", responses = {
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = ChatReply.class))),
@ApiResponse(responseCode = "500", description = "There is no support for the configured language") })
public Response greet() {
final Locale locale = localeService.getLocale(null);
@ -136,10 +139,11 @@ public class HABotResource implements RESTResource {
@Path("/chat")
@Consumes(MediaType.TEXT_PLAIN)
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value = "Send a query to HABot to interpret.")
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = ChatReply.class),
@ApiResponse(code = 500, message = "An interpretation error occurred") })
public Response chat(@ApiParam(value = "human language query", required = true) String query) throws Exception {
@Operation(summary = "Send a query to HABot to interpret.", responses = {
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = ChatReply.class))),
@ApiResponse(responseCode = "500", description = "An interpretation error occurred") })
public Response chat(@Parameter(description = "human language query", required = true) String query)
throws Exception {
final Locale locale = localeService.getLocale(null);
// interpret
@ -157,9 +161,9 @@ public class HABotResource implements RESTResource {
@Path("/attributes")
@Consumes(MediaType.TEXT_PLAIN)
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value = "Gets all item named attributes.")
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = ChatReply.class),
@ApiResponse(code = 500, message = "An error occurred") })
@Operation(summary = "Gets all item named attributes.", responses = {
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = ChatReply.class))),
@ApiResponse(responseCode = "500", description = "An error occurred") })
public Response getAttributes() throws Exception {
final Locale locale = localeService.getLocale(null);
@ -175,9 +179,9 @@ public class HABotResource implements RESTResource {
@Path("/notifications/subscribe")
// TEXT_PLAIN to work around https://github.com/openhab/openhab-cloud/issues/31
@Consumes(MediaType.TEXT_PLAIN) // @Consumes(MediaType.APPLICATION_JSON)
@ApiOperation(value = "Subscribes a new client for push notifications.")
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK"),
@ApiResponse(code = 500, message = "An error occured") })
@Operation(summary = "Subscribes a new client for push notifications.", responses = {
@ApiResponse(responseCode = "200", description = "OK"),
@ApiResponse(responseCode = "500", description = "An error occured") })
public Response webPushSubscribe(String subscriptionJson) throws Exception {
Gson gson = new Gson();
Subscription subscription = gson.fromJson(subscriptionJson, Subscription.class);
@ -197,9 +201,9 @@ public class HABotResource implements RESTResource {
@GET
@Path("/notifications/vapid")
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value = "Gets or generates the public VAPID key used for push notifications.")
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK"),
@ApiResponse(code = 500, message = "An error occured") })
@Operation(summary = "Gets or generates the public VAPID key used for push notifications.", responses = {
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = String.class))),
@ApiResponse(responseCode = "500", description = "An error occured") })
public Response webPushConfig() throws Exception {
String publicVAPIDKey = notificationService.getVAPIDPublicKey();
@ -209,9 +213,9 @@ public class HABotResource implements RESTResource {
@GET
@Path("/cards")
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value = "Gets all cards of the card deck.", response = Card.class, responseContainer = "List")
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK"),
@ApiResponse(code = 500, message = "An error occured") })
@Operation(summary = "Gets all cards of the card deck.", responses = {
@ApiResponse(responseCode = "200", description = "OK", content = @Content(array = @ArraySchema(schema = @Schema(implementation = Card.class)))),
@ApiResponse(responseCode = "500", description = "An error occured") })
public Response getAllCards() {
Collection<Card> cards = cardRegistry.getNonEphemeral();
@ -221,11 +225,11 @@ public class HABotResource implements RESTResource {
@GET
@Path("/cards/{cardUID}")
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value = "Gets a card from the card deck by its UID.", response = Card.class)
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK"),
@ApiResponse(code = 404, message = "The card with the provided UID doesn't exist"),
@ApiResponse(code = 500, message = "An error occured") })
public Response getCardByUid(@PathParam("cardUID") @ApiParam(value = "cardUID") String cardUID) {
@Operation(summary = "Gets a card from the card deck by its UID.", responses = {
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = Card.class))),
@ApiResponse(responseCode = "404", description = "The card with the provided UID doesn't exist"),
@ApiResponse(responseCode = "500", description = "An error occured") })
public Response getCardByUid(@PathParam("cardUID") @Parameter(description = "cardUID") String cardUID) {
Card card = cardRegistry.get(cardUID);
if (card == null) {
return Response.status(Status.NOT_FOUND).build();
@ -237,10 +241,10 @@ public class HABotResource implements RESTResource {
@POST
@Path("/cards")
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value = "Creates a new card in the card deck.")
@ApiResponses(value = { @ApiResponse(code = 200, message = "The card was created"),
@ApiResponse(code = 500, message = "An error occured") })
public Response createCard(@ApiParam(value = "card", required = true) Card card) {
@Operation(summary = "Creates a new card in the card deck.", responses = {
@ApiResponse(responseCode = "200", description = "The card was created", content = @Content(schema = @Schema(implementation = Card.class))),
@ApiResponse(responseCode = "500", description = "An error occured") })
public Response createCard(@Parameter(description = "card", required = true) Card card) {
card.updateTimestamp();
card.setEphemeral(false);
Card existingCard = cardRegistry.get(card.getUID());
@ -255,9 +259,11 @@ public class HABotResource implements RESTResource {
@PUT
@Path("/cards/{cardUID}")
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value = "Updates a card in the card deck.")
public Response updateCard(@PathParam("cardUID") @ApiParam(value = "cardUID") String cardUID,
@ApiParam(value = "card", required = true) Card card) {
@Operation(summary = "Updates a card in the card deck.", responses = {
@ApiResponse(responseCode = "200", description = "The card was updated", content = @Content(schema = @Schema(implementation = Card.class))),
@ApiResponse(responseCode = "500", description = "An error occured") })
public Response updateCard(@PathParam("cardUID") @Parameter(description = "cardUID") String cardUID,
@Parameter(description = "card", required = true) Card card) {
if (!card.getUID().equals(cardUID)) {
throw new InvalidParameterException(
"The card UID in the body of the request should match the UID in the URL");
@ -271,8 +277,10 @@ public class HABotResource implements RESTResource {
@DELETE
@Path("/cards/{cardUID}")
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value = "Deletes a card from the card deck.")
public Response deleteCard(@PathParam("cardUID") @ApiParam(value = "cardUID") String cardUID) {
@Operation(summary = "Deletes a card from the card deck.", responses = {
@ApiResponse(responseCode = "200", description = "The card was deleted"),
@ApiResponse(responseCode = "500", description = "An error occured") })
public Response deleteCard(@PathParam("cardUID") @Parameter(description = "cardUID") String cardUID) {
cardRegistry.remove(cardUID);
return Response.ok().build();
@ -280,11 +288,11 @@ public class HABotResource implements RESTResource {
@PUT
@Path("/cards/{cardUID}/bookmark")
@ApiOperation(value = "Sets a bookmark on a card.")
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK"),
@ApiResponse(code = 404, message = "The card with the provided UID doesn't exist"),
@ApiResponse(code = 500, message = "An error occured") })
public Response setCardBookmark(@PathParam("cardUID") @ApiParam(value = "cardUID") String cardUID) {
@Operation(summary = "Sets a bookmark on a card.", responses = {
@ApiResponse(responseCode = "200", description = "OK"),
@ApiResponse(responseCode = "404", description = "The card with the provided UID doesn't exist"),
@ApiResponse(responseCode = "500", description = "An error occured") })
public Response setCardBookmark(@PathParam("cardUID") @Parameter(description = "cardUID") String cardUID) {
Card card = cardRegistry.get(cardUID);
if (card == null) {
return Response.status(Status.NOT_FOUND).build();
@ -298,10 +306,10 @@ public class HABotResource implements RESTResource {
@GET
@Path("/cards/recent")
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value = "Creates a new card in the card deck.")
@ApiResponses(value = { @ApiResponse(code = 200, message = "The card was created"),
@ApiResponse(code = 500, message = "An error occured") })
public Response createCard(@QueryParam(value = "skip") int skip, @QueryParam(value = "count") int count) {
@Operation(summary = "Gets the most recent cards from the card deck", responses = {
@ApiResponse(responseCode = "200", description = "The most recent cards", content = @Content(array = @ArraySchema(schema = @Schema(implementation = Card.class)))),
@ApiResponse(responseCode = "500", description = "An error occured") })
public Response recentCards(@QueryParam(value = "skip") int skip, @QueryParam(value = "count") int count) {
Collection<Card> cards = cardRegistry.getRecent(skip, count);
return Response.ok(cards).build();
@ -309,11 +317,11 @@ public class HABotResource implements RESTResource {
@DELETE
@Path("/cards/{cardUID}/bookmark")
@ApiOperation(value = "Removes the bookmark on a card.")
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK"),
@ApiResponse(code = 404, message = "The card with the provided UID doesn't exist"),
@ApiResponse(code = 500, message = "An error occured") })
public Response unsetCardBookmark(@PathParam("cardUID") @ApiParam(value = "cardUID") String cardUID) {
@Operation(summary = "Removes the bookmark on a card.", responses = {
@ApiResponse(responseCode = "200", description = "OK"),
@ApiResponse(responseCode = "404", description = "The card with the provided UID doesn't exist"),
@ApiResponse(responseCode = "500", description = "An error occured") })
public Response unsetCardBookmark(@PathParam("cardUID") @Parameter(description = "cardUID") String cardUID) {
Card card = cardRegistry.get(cardUID);
if (card == null) {
return Response.status(Status.NOT_FOUND).build();
@ -326,11 +334,11 @@ public class HABotResource implements RESTResource {
@PUT
@Path("/cards/{cardUID}/timestamp")
@ApiOperation(value = "Updates the timestamp on a card to the current time")
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK"),
@ApiResponse(code = 404, message = "The card with the provided UID doesn't exist"),
@ApiResponse(code = 500, message = "An error occured") })
public Response updateCardTimestamp(@PathParam("cardUID") @ApiParam(value = "cardUID") String cardUID) {
@Operation(summary = "Updates the timestamp on a card to the current time", responses = {
@ApiResponse(responseCode = "200", description = "OK"),
@ApiResponse(responseCode = "404", description = "The card with the provided UID doesn't exist"),
@ApiResponse(responseCode = "500", description = "An error occured") })
public Response updateCardTimestamp(@PathParam("cardUID") @Parameter(description = "cardUID") String cardUID) {
Card card = cardRegistry.get(cardUID);
if (card == null) {
return Response.status(Status.NOT_FOUND).build();
@ -349,10 +357,10 @@ public class HABotResource implements RESTResource {
@Path("/compat/cards")
@Consumes(MediaType.TEXT_PLAIN)
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value = "Creates a new card in the card deck (compatibility endpoint).")
@ApiResponses(value = { @ApiResponse(code = 200, message = "The card was created"),
@ApiResponse(code = 500, message = "An error occured") })
public Response createCard(@ApiParam(value = "card", required = true) String card) {
@Operation(summary = "Creates a new card in the card deck (compatibility endpoint).", responses = {
@ApiResponse(responseCode = "200", description = "The card was created", content = @Content(schema = @Schema(implementation = Card.class))),
@ApiResponse(responseCode = "500", description = "An error occured") })
public Response createCard(@Parameter(description = "card", required = true) String card) {
Gson gson = new Gson();
return createCard(gson.fromJson(card, Card.class));
}
@ -361,9 +369,11 @@ public class HABotResource implements RESTResource {
@Path("/compat/cards/{cardUID}")
@Consumes(MediaType.TEXT_PLAIN)
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value = "Updates a card in the card deck (compatibility endpoint).")
public Response updateCard(@PathParam("cardUID") @ApiParam(value = "cardUID") String cardUID,
@ApiParam(value = "card", required = true) String card) {
@Operation(summary = "Updates a card in the card deck (compatibility endpoint).", responses = {
@ApiResponse(responseCode = "200", description = "The card was updated", content = @Content(schema = @Schema(implementation = Card.class))),
@ApiResponse(responseCode = "500", description = "An error occured") })
public Response updateCard(@PathParam("cardUID") @Parameter(description = "cardUID") String cardUID,
@Parameter(description = "card", required = true) String card) {
Gson gson = new Gson();
return updateCard(cardUID, gson.fromJson(card, Card.class));
}
@ -371,18 +381,20 @@ public class HABotResource implements RESTResource {
@POST
@Path("/compat/cards/{cardUID}/delete")
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value = "Deletes a card from the card deck (compatibility endpoint).")
public Response deleteCardPost(@PathParam("cardUID") @ApiParam(value = "cardUID") String cardUID) {
@Operation(summary = "Deletes a card from the card deck (compatibility endpoint).", responses = {
@ApiResponse(responseCode = "200", description = "The card was updated", content = @Content(schema = @Schema(implementation = Card.class))),
@ApiResponse(responseCode = "500", description = "An error occured") })
public Response deleteCardPost(@PathParam("cardUID") @Parameter(description = "cardUID") String cardUID) {
return deleteCard(cardUID);
}
@POST
@Path("/compat/cards/{cardUID}/unbookmark")
@ApiOperation(value = "Removes the bookmark on a card (compatibility endpoint).")
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK"),
@ApiResponse(code = 404, message = "The card with the provided UID doesn't exist"),
@ApiResponse(code = 500, message = "An error occured") })
public Response unsetCardBookmarkCompat(@PathParam("cardUID") @ApiParam(value = "cardUID") String cardUID) {
@Operation(summary = "Removes the bookmark on a card (compatibility endpoint).", responses = {
@ApiResponse(responseCode = "200", description = "OK"),
@ApiResponse(responseCode = "404", description = "The card with the provided UID doesn't exist"),
@ApiResponse(responseCode = "500", description = "An error occured") })
public Response unsetCardBookmarkCompat(@PathParam("cardUID") @Parameter(description = "cardUID") String cardUID) {
return unsetCardBookmark(cardUID);
}
}

View File

@ -39,25 +39,27 @@ import org.osgi.service.jaxrs.whiteboard.propertytypes.JSONRequired;
import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsApplicationSelect;
import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsName;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.ArraySchema;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
/**
* This class describes the /habpanel resource of the REST API, currently holding facilities for browsing widget
* galleries.
*
* @author Yannick Schaus - Initial contribution
*
* @author Wouter Born - Migrated to OpenAPI annotations
*/
@Component
@JaxrsName(HABPanelResource.PATH_HABPANEL)
@JaxrsApplicationSelect("(" + JaxrsWhiteboardConstants.JAX_RS_NAME + "=" + RESTConstants.JAX_RS_NAME + ")")
@JSONRequired
@Path(HABPanelResource.PATH_HABPANEL)
@Api(HABPanelResource.PATH_HABPANEL)
@Tag(name = HABPanelResource.PATH_HABPANEL)
@NonNullByDefault
public class HABPanelResource implements RESTResource {
@ -67,11 +69,11 @@ public class HABPanelResource implements RESTResource {
@RolesAllowed({ Role.USER, Role.ADMIN })
@Path("/gallery/{galleryName: [a-zA-Z_0-9]*}/widgets")
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value = "Gets the list of widget gallery items.")
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = String.class),
@ApiResponse(code = 404, message = "Unknown gallery") })
@Operation(summary = "Gets the list of widget gallery items.", responses = {
@ApiResponse(responseCode = "200", description = "OK", content = @Content(array = @ArraySchema(schema = @Schema(implementation = GalleryWidgetsListItem.class)))),
@ApiResponse(responseCode = "404", description = "Unknown gallery") })
public Response getGalleryWidgetList(
@PathParam("galleryName") @ApiParam(value = "gallery name e.g. 'community'") String galleryName)
@PathParam("galleryName") @Parameter(description = "gallery name e.g. 'community'") String galleryName)
throws Exception {
GalleryWidgetProvider galleryProvider = GalleryProviderFactory.getWidgetGalleryProvider(galleryName);
@ -88,12 +90,12 @@ public class HABPanelResource implements RESTResource {
@RolesAllowed({ Role.USER, Role.ADMIN })
@Path("/gallery/{galleryName: [a-zA-Z_0-9]*}/widgets/{id: [a-zA-Z_0-9]*}")
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value = "Gets the details about a widget gallery item.")
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = String.class),
@ApiResponse(code = 404, message = "Unknown gallery or gallery item not found") })
@Operation(summary = "Gets the details about a widget gallery item.", responses = {
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = GalleryItem.class))),
@ApiResponse(responseCode = "404", description = "Unknown gallery or gallery item not found") })
public Response getGalleryWidgetsItem(
@PathParam("galleryName") @ApiParam(value = "gallery name e.g. 'community'") String galleryName,
@PathParam("id") @ApiParam(value = "id within the gallery") String id) throws Exception {
@PathParam("galleryName") @Parameter(description = "gallery name e.g. 'community'") String galleryName,
@PathParam("id") @Parameter(description = "id within the gallery") String id) throws Exception {
GalleryWidgetProvider galleryProvider = GalleryProviderFactory.getWidgetGalleryProvider(galleryName);
if (galleryProvider == null) {

View File

@ -88,7 +88,7 @@
<bnd><![CDATA[Bundle-SymbolicName: ${project.artifactId}
Automatic-Module-Name: ${def;bsn}
Import-Package: \\
io.swagger.annotations.*;resolution:=optional,\\
io.swagger.v3.oas.annotations.*;resolution:=optional,\\
javax.annotation.security.*;resolution:=optional,\\
org.eclipse.jdt.annotation.*;resolution:=optional,\\
org.openhab.core.automation.annotation.*;resolution:=optional;version=!,\\