/**
* Copyright (c) 2014-2017 by the respective copyright holders.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.smarthome.io.rest.core.discovery;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import javax.annotation.security.RolesAllowed;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.UriInfo;
import org.eclipse.smarthome.config.discovery.DiscoveryResult;
import org.eclipse.smarthome.config.discovery.DiscoveryResultFlag;
import org.eclipse.smarthome.config.discovery.dto.DiscoveryResultDTO;
import org.eclipse.smarthome.config.discovery.dto.DiscoveryResultDTOMapper;
import org.eclipse.smarthome.config.discovery.inbox.Inbox;
import org.eclipse.smarthome.core.auth.Role;
import org.eclipse.smarthome.core.thing.Thing;
import org.eclipse.smarthome.core.thing.ThingUID;
import org.eclipse.smarthome.io.rest.JSONResponse;
import org.eclipse.smarthome.io.rest.SatisfiableRESTResource;
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;
/**
* This class acts as a REST resource for the inbox and is registered with the
* Jersey servlet.
*
* @author Dennis Nobel - Initial contribution
* @author Kai Kreuzer - refactored for using the OSGi JAX-RS connector and removed ThingSetupManager
* @author Yordan Zhelev - Added Swagger annotations
* @author Chris Jackson - Updated to use JSONResponse. Fixed null response from approve.
* @author Franck Dechavanne - Added DTOs to ApiResponses
*/
@Path(InboxResource.PATH_INBOX)
@RolesAllowed({ Role.ADMIN })
@Api(value = InboxResource.PATH_INBOX)
public class InboxResource implements SatisfiableRESTResource {
/** The URI path to this resource */
public static final String PATH_INBOX = "inbox";
private Inbox inbox;
protected void setInbox(Inbox inbox) {
this.inbox = inbox;
}
protected void unsetInbox(Inbox inbox) {
this.inbox = null;
}
@Context
private UriInfo uriInfo;
@POST
@Path("/{thingUID}/approve")
@Consumes(MediaType.TEXT_PLAIN)
@ApiOperation(value = "Approves the discovery result by adding the thing to the registry.")
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK"),
@ApiResponse(code = 404, message = "Thing not found in the inbox."),
@ApiResponse(code = 409, message = "No binding found that supports this thing.") })
public Response approve(@HeaderParam(HttpHeaders.ACCEPT_LANGUAGE) @ApiParam(value = "language") String language,
@PathParam("thingUID") @ApiParam(value = "thingUID", required = true) String thingUID,
@ApiParam(value = "thing label") String label) {
ThingUID thingUIDObject = new ThingUID(thingUID);
String notEmptyLabel = label != null && !label.isEmpty() ? label : null;
Thing thing = null;
try {
thing = inbox.approve(thingUIDObject, notEmptyLabel);
} catch (IllegalArgumentException e) {
return JSONResponse.createErrorResponse(Status.NOT_FOUND, "Thing not found in inbox");
}
// inbox.approve returns null if no handler is found that supports this thing
if (thing == null) {
return JSONResponse.createErrorResponse(Status.CONFLICT, "No binding found that can create the thing");
}
return Response.ok().build();
}
@DELETE
@Path("/{thingUID}")
@ApiOperation(value = "Removes the discovery result from the inbox.")
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK"),
@ApiResponse(code = 404, message = "Discovery result not found in the inbox.") })
public Response delete(@PathParam("thingUID") @ApiParam(value = "thingUID", required = true) String thingUID) {
if (inbox.remove(new ThingUID(thingUID))) {
return Response.ok().build();
} else {
return JSONResponse.createErrorResponse(Status.NOT_FOUND, "Thing not found in inbox");
}
}
@GET
@Produces({ MediaType.WILDCARD })
@ApiOperation(value = "Get all discovered things.")
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = DiscoveryResultDTO.class) })
public Response getAll() {
List<DiscoveryResult> discoveryResults = inbox.getAll();
Set<DiscoveryResultDTO> discoveryResultBeans = convertToListBean(discoveryResults);
return Response.ok(discoveryResultBeans).build();
}
@POST
@Path("/{thingUID}/ignore")
@ApiOperation(value = "Flags a discovery result as ignored for further processing.")
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK") })
public Response ignore(@PathParam("thingUID") @ApiParam(value = "thingUID", required = true) String thingUID) {
inbox.setFlag(new ThingUID(thingUID), DiscoveryResultFlag.IGNORED);
return Response.ok().build();
}
@POST
@Path("/{thingUID}/unignore")
@ApiOperation(value = "Removes ignore flag from a discovery result.")
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK") })
public Response unignore(@PathParam("thingUID") @ApiParam(value = "thingUID", required = true) String thingUID) {
inbox.setFlag(new ThingUID(thingUID), DiscoveryResultFlag.NEW);
return Response.ok().build();
}
private Set<DiscoveryResultDTO> convertToListBean(List<DiscoveryResult> discoveryResults) {
Set<DiscoveryResultDTO> discoveryResultBeans = new LinkedHashSet<>();
for (DiscoveryResult discoveryResult : discoveryResults) {
discoveryResultBeans.add(DiscoveryResultDTOMapper.map(discoveryResult));
}
return discoveryResultBeans;
}
@Override
public boolean isSatisfied() {
return inbox != null;
}
}