mirror of
https://github.com/danieldemus/openhab-core.git
synced 2025-01-10 21:31:53 +01:00
Add null annotations to REST resources (#1475)
Signed-off-by: Wouter Born <github@maindrain.net>
This commit is contained in:
parent
054ad6c48e
commit
84d9438737
@ -22,11 +22,9 @@ import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.QueryParam;
|
||||
import javax.ws.rs.core.Context;
|
||||
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.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
@ -45,10 +43,9 @@ import org.openhab.core.automation.type.TriggerType;
|
||||
import org.openhab.core.io.rest.LocaleService;
|
||||
import org.openhab.core.io.rest.RESTConstants;
|
||||
import org.openhab.core.io.rest.RESTResource;
|
||||
import org.osgi.service.component.annotations.Activate;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Reference;
|
||||
import org.osgi.service.component.annotations.ReferenceCardinality;
|
||||
import org.osgi.service.component.annotations.ReferencePolicy;
|
||||
import org.osgi.service.jaxrs.whiteboard.JaxrsWhiteboardConstants;
|
||||
import org.osgi.service.jaxrs.whiteboard.propertytypes.JSONRequired;
|
||||
import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsApplicationSelect;
|
||||
@ -82,28 +79,15 @@ public class ModuleTypeResource implements RESTResource {
|
||||
/** The URI path to this resource */
|
||||
public static final String PATH_MODULE_TYPES = "module-types";
|
||||
|
||||
private @NonNullByDefault({}) ModuleTypeRegistry moduleTypeRegistry;
|
||||
private @NonNullByDefault({}) LocaleService localeService;
|
||||
private final LocaleService localeService;
|
||||
private final ModuleTypeRegistry moduleTypeRegistry;
|
||||
|
||||
@Context
|
||||
private @NonNullByDefault({}) UriInfo uriInfo;
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
|
||||
protected void setModuleTypeRegistry(ModuleTypeRegistry moduleTypeRegistry) {
|
||||
this.moduleTypeRegistry = moduleTypeRegistry;
|
||||
}
|
||||
|
||||
protected void unsetModuleTypeRegistry(ModuleTypeRegistry moduleTypeRegistry) {
|
||||
this.moduleTypeRegistry = null;
|
||||
}
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
|
||||
protected void setLocaleService(LocaleService localeService) {
|
||||
@Activate
|
||||
public ModuleTypeResource( //
|
||||
final @Reference LocaleService localeService, //
|
||||
final @Reference ModuleTypeRegistry moduleTypeRegistry) {
|
||||
this.localeService = localeService;
|
||||
}
|
||||
|
||||
protected void unsetLocaleService(LocaleService localeService) {
|
||||
this.localeService = null;
|
||||
this.moduleTypeRegistry = moduleTypeRegistry;
|
||||
}
|
||||
|
||||
@GET
|
||||
@ -112,8 +96,8 @@ public class ModuleTypeResource implements RESTResource {
|
||||
@ApiResponses(value = {
|
||||
@ApiResponse(code = 200, message = "OK", response = ModuleTypeDTO.class, responseContainer = "List") })
|
||||
public Response getAll(@HeaderParam("Accept-Language") @ApiParam(value = "language") @Nullable String language,
|
||||
@QueryParam("tags") @ApiParam(value = "tags for filtering", required = false) @Nullable String tagList,
|
||||
@QueryParam("type") @ApiParam(value = "filtering by action, condition or trigger", required = false) @Nullable String type) {
|
||||
@QueryParam("tags") @ApiParam(value = "tags for filtering") @Nullable String tagList,
|
||||
@QueryParam("type") @ApiParam(value = "filtering by action, condition or trigger") @Nullable String type) {
|
||||
final Locale locale = localeService.getLocale(language);
|
||||
final String[] tags = tagList != null ? tagList.split(",") : new String[0];
|
||||
final List<ModuleTypeDTO> modules = new ArrayList<>();
|
||||
@ -137,7 +121,7 @@ public class ModuleTypeResource implements RESTResource {
|
||||
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = ModuleTypeDTO.class),
|
||||
@ApiResponse(code = 404, message = "Module Type corresponding to the given UID does not found.") })
|
||||
public Response getByUID(@HeaderParam("Accept-Language") @ApiParam(value = "language") @Nullable String language,
|
||||
@PathParam("moduleTypeUID") @ApiParam(value = "moduleTypeUID", required = true) String moduleTypeUID) {
|
||||
@PathParam("moduleTypeUID") @ApiParam(value = "moduleTypeUID") String moduleTypeUID) {
|
||||
Locale locale = localeService.getLocale(language);
|
||||
final ModuleType moduleType = moduleTypeRegistry.get(moduleTypeUID, locale);
|
||||
if (moduleType != null) {
|
||||
@ -168,9 +152,4 @@ public class ModuleTypeResource implements RESTResource {
|
||||
String.format("Cannot handle given module type class (%s)", moduleType.getClass()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSatisfied() {
|
||||
return moduleTypeRegistry != null && localeService != null;
|
||||
}
|
||||
}
|
||||
|
@ -38,6 +38,8 @@ import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.Response.Status;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.core.auth.Role;
|
||||
import org.openhab.core.automation.Action;
|
||||
import org.openhab.core.automation.Condition;
|
||||
@ -64,10 +66,9 @@ import org.openhab.core.config.core.Configuration;
|
||||
import org.openhab.core.io.rest.JSONResponse;
|
||||
import org.openhab.core.io.rest.RESTConstants;
|
||||
import org.openhab.core.io.rest.RESTResource;
|
||||
import org.osgi.service.component.annotations.Activate;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Reference;
|
||||
import org.osgi.service.component.annotations.ReferenceCardinality;
|
||||
import org.osgi.service.component.annotations.ReferencePolicy;
|
||||
import org.osgi.service.jaxrs.whiteboard.JaxrsWhiteboardConstants;
|
||||
import org.osgi.service.jaxrs.whiteboard.propertytypes.JSONRequired;
|
||||
import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsApplicationSelect;
|
||||
@ -98,6 +99,7 @@ import io.swagger.annotations.ResponseHeader;
|
||||
@Path(RuleResource.PATH_RULES)
|
||||
@Api(RuleResource.PATH_RULES)
|
||||
@RolesAllowed({ Role.ADMIN })
|
||||
@NonNullByDefault
|
||||
public class RuleResource implements RESTResource {
|
||||
|
||||
/** The URI path to this resource */
|
||||
@ -105,28 +107,17 @@ public class RuleResource implements RESTResource {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(RuleResource.class);
|
||||
|
||||
private RuleRegistry ruleRegistry;
|
||||
private RuleManager ruleManager;
|
||||
private final RuleManager ruleManager;
|
||||
private final RuleRegistry ruleRegistry;
|
||||
|
||||
@Context
|
||||
private UriInfo uriInfo;
|
||||
private @Context @NonNullByDefault({}) UriInfo uriInfo;
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
|
||||
protected void setRuleRegistry(RuleRegistry ruleRegistry) {
|
||||
this.ruleRegistry = ruleRegistry;
|
||||
}
|
||||
|
||||
protected void unsetRuleRegistry(RuleRegistry ruleRegistry) {
|
||||
this.ruleRegistry = null;
|
||||
}
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
|
||||
protected void setRuleManager(RuleManager ruleManager) {
|
||||
@Activate
|
||||
public RuleResource( //
|
||||
final @Reference RuleManager ruleManager, //
|
||||
final @Reference RuleRegistry ruleRegistry) {
|
||||
this.ruleManager = ruleManager;
|
||||
}
|
||||
|
||||
protected void unsetRuleManager(RuleManager ruleManager) {
|
||||
this.ruleManager = null;
|
||||
this.ruleRegistry = ruleRegistry;
|
||||
}
|
||||
|
||||
@GET
|
||||
@ -134,12 +125,13 @@ public class RuleResource implements RESTResource {
|
||||
@ApiOperation(value = "Get available rules, optionally filtered by tags and/or prefix.", response = EnrichedRuleDTO.class, responseContainer = "Collection")
|
||||
@ApiResponses(value = {
|
||||
@ApiResponse(code = 200, message = "OK", response = EnrichedRuleDTO.class, responseContainer = "Collection") })
|
||||
public Response get(@QueryParam("prefix") final String prefix, @QueryParam("tags") final List<String> tags) {
|
||||
public Response get(@QueryParam("prefix") final @Nullable String prefix,
|
||||
@QueryParam("tags") final @Nullable List<String> tags) {
|
||||
// match all
|
||||
Predicate<Rule> p = r -> true;
|
||||
|
||||
// prefix parameter has been used
|
||||
if (null != prefix) {
|
||||
if (prefix != null) {
|
||||
// works also for null prefix
|
||||
// (empty prefix used if searching for rules without prefix)
|
||||
p = p.and(hasPrefix(prefix));
|
||||
@ -185,7 +177,7 @@ public class RuleResource implements RESTResource {
|
||||
@ApiOperation(value = "Gets the rule corresponding to the given UID.", response = EnrichedRuleDTO.class)
|
||||
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = EnrichedRuleDTO.class),
|
||||
@ApiResponse(code = 404, message = "Rule not found") })
|
||||
public Response getByUID(@PathParam("ruleUID") @ApiParam(value = "ruleUID", required = true) String ruleUID) {
|
||||
public Response getByUID(@PathParam("ruleUID") @ApiParam(value = "ruleUID") String ruleUID) {
|
||||
Rule rule = ruleRegistry.get(ruleUID);
|
||||
if (rule != null) {
|
||||
return Response.ok(EnrichedRuleDTOMapper.map(rule, ruleManager)).build();
|
||||
@ -200,7 +192,7 @@ public class RuleResource implements RESTResource {
|
||||
@ApiOperation(value = "Removes an existing rule corresponding to the given UID.")
|
||||
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = String.class),
|
||||
@ApiResponse(code = 404, message = "Rule corresponding to the given UID does not found.") })
|
||||
public Response remove(@PathParam("ruleUID") @ApiParam(value = "ruleUID", required = true) String ruleUID) {
|
||||
public Response remove(@PathParam("ruleUID") @ApiParam(value = "ruleUID") String ruleUID) {
|
||||
Rule removedRule = ruleRegistry.remove(ruleUID);
|
||||
if (removedRule == null) {
|
||||
logger.info("Received HTTP DELETE request at '{}' for the unknown rule '{}'.", uriInfo.getPath(), ruleUID);
|
||||
@ -216,7 +208,7 @@ public class RuleResource implements RESTResource {
|
||||
@ApiOperation(value = "Updates an existing rule corresponding to the given UID.")
|
||||
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK"),
|
||||
@ApiResponse(code = 404, message = "Rule corresponding to the given UID does not found.") })
|
||||
public Response update(@PathParam("ruleUID") @ApiParam(value = "ruleUID", required = true) String ruleUID,
|
||||
public Response update(@PathParam("ruleUID") @ApiParam(value = "ruleUID") String ruleUID,
|
||||
@ApiParam(value = "rule data", required = true) RuleDTO rule) throws IOException {
|
||||
rule.uid = ruleUID;
|
||||
final Rule oldRule = ruleRegistry.update(RuleDTOMapper.map(rule));
|
||||
@ -235,7 +227,7 @@ public class RuleResource implements RESTResource {
|
||||
@ApiOperation(value = "Gets the rule configuration values.")
|
||||
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = String.class),
|
||||
@ApiResponse(code = 404, message = "Rule corresponding to the given UID does not found.") })
|
||||
public Response getConfiguration(@PathParam("ruleUID") @ApiParam(value = "ruleUID", required = true) String ruleUID)
|
||||
public Response getConfiguration(@PathParam("ruleUID") @ApiParam(value = "ruleUID") String ruleUID)
|
||||
throws IOException {
|
||||
Rule rule = ruleRegistry.get(ruleUID);
|
||||
if (rule == null) {
|
||||
@ -253,8 +245,7 @@ public class RuleResource implements RESTResource {
|
||||
@ApiOperation(value = "Sets the rule configuration values.")
|
||||
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK"),
|
||||
@ApiResponse(code = 404, message = "Rule corresponding to the given UID does not found.") })
|
||||
public Response updateConfiguration(
|
||||
@PathParam("ruleUID") @ApiParam(value = "ruleUID", required = true) String ruleUID,
|
||||
public Response updateConfiguration(@PathParam("ruleUID") @ApiParam(value = "ruleUID") String ruleUID,
|
||||
@ApiParam(value = "config") Map<String, Object> configurationParameters) throws IOException {
|
||||
Map<String, Object> config = ConfigUtil.normalizeTypes(configurationParameters);
|
||||
Rule rule = ruleRegistry.get(ruleUID);
|
||||
@ -275,7 +266,7 @@ public class RuleResource implements RESTResource {
|
||||
@ApiOperation(value = "Sets the rule enabled status.")
|
||||
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK"),
|
||||
@ApiResponse(code = 404, message = "Rule corresponding to the given UID does not found.") })
|
||||
public Response enableRule(@PathParam("ruleUID") @ApiParam(value = "ruleUID", required = true) String ruleUID,
|
||||
public Response enableRule(@PathParam("ruleUID") @ApiParam(value = "ruleUID") String ruleUID,
|
||||
@ApiParam(value = "enable", required = true) String enabled) throws IOException {
|
||||
Rule rule = ruleRegistry.get(ruleUID);
|
||||
if (rule == null) {
|
||||
@ -295,8 +286,7 @@ public class RuleResource implements RESTResource {
|
||||
@ApiOperation(value = "Executes actions of the rule.")
|
||||
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK"),
|
||||
@ApiResponse(code = 404, message = "Rule corresponding to the given UID does not found.") })
|
||||
public Response runNow(@PathParam("ruleUID") @ApiParam(value = "ruleUID", required = true) String ruleUID)
|
||||
throws IOException {
|
||||
public Response runNow(@PathParam("ruleUID") @ApiParam(value = "ruleUID") String ruleUID) throws IOException {
|
||||
Rule rule = ruleRegistry.get(ruleUID);
|
||||
if (rule == null) {
|
||||
logger.info("Received HTTP PUT request for run now at '{}' for the unknown rule '{}'.", uriInfo.getPath(),
|
||||
@ -315,7 +305,7 @@ public class RuleResource implements RESTResource {
|
||||
@ApiResponses(value = {
|
||||
@ApiResponse(code = 200, message = "OK", response = TriggerDTO.class, responseContainer = "List"),
|
||||
@ApiResponse(code = 404, message = "Rule corresponding to the given UID does not found.") })
|
||||
public Response getTriggers(@PathParam("ruleUID") @ApiParam(value = "ruleUID", required = true) String ruleUID) {
|
||||
public Response getTriggers(@PathParam("ruleUID") @ApiParam(value = "ruleUID") String ruleUID) {
|
||||
Rule rule = ruleRegistry.get(ruleUID);
|
||||
if (rule != null) {
|
||||
return Response.ok(TriggerDTOMapper.map(rule.getTriggers())).build();
|
||||
@ -331,7 +321,7 @@ public class RuleResource implements RESTResource {
|
||||
@ApiResponses(value = {
|
||||
@ApiResponse(code = 200, message = "OK", response = ConditionDTO.class, responseContainer = "List"),
|
||||
@ApiResponse(code = 404, message = "Rule corresponding to the given UID does not found.") })
|
||||
public Response getConditions(@PathParam("ruleUID") @ApiParam(value = "ruleUID", required = true) String ruleUID) {
|
||||
public Response getConditions(@PathParam("ruleUID") @ApiParam(value = "ruleUID") String ruleUID) {
|
||||
Rule rule = ruleRegistry.get(ruleUID);
|
||||
if (rule != null) {
|
||||
return Response.ok(ConditionDTOMapper.map(rule.getConditions())).build();
|
||||
@ -347,7 +337,7 @@ public class RuleResource implements RESTResource {
|
||||
@ApiResponses(value = {
|
||||
@ApiResponse(code = 200, message = "OK", response = ActionDTO.class, responseContainer = "List"),
|
||||
@ApiResponse(code = 404, message = "Rule corresponding to the given UID does not found.") })
|
||||
public Response getActions(@PathParam("ruleUID") @ApiParam(value = "ruleUID", required = true) String ruleUID) {
|
||||
public Response getActions(@PathParam("ruleUID") @ApiParam(value = "ruleUID") String ruleUID) {
|
||||
Rule rule = ruleRegistry.get(ruleUID);
|
||||
if (rule != null) {
|
||||
return Response.ok(ActionDTOMapper.map(rule.getActions())).build();
|
||||
@ -362,9 +352,9 @@ public class RuleResource implements RESTResource {
|
||||
@ApiOperation(value = "Gets the rule's module corresponding to the given Category and ID.", response = ModuleDTO.class)
|
||||
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = ModuleDTO.class),
|
||||
@ApiResponse(code = 404, message = "Rule corresponding to the given UID does not found or does not have a module with such Category and ID.") })
|
||||
public Response getModuleById(@PathParam("ruleUID") @ApiParam(value = "ruleUID", required = true) String ruleUID,
|
||||
@PathParam("moduleCategory") @ApiParam(value = "moduleCategory", required = true) String moduleCategory,
|
||||
@PathParam("id") @ApiParam(value = "id", required = true) String id) {
|
||||
public Response getModuleById(@PathParam("ruleUID") @ApiParam(value = "ruleUID") String ruleUID,
|
||||
@PathParam("moduleCategory") @ApiParam(value = "moduleCategory") String moduleCategory,
|
||||
@PathParam("id") @ApiParam(value = "id") String id) {
|
||||
Rule rule = ruleRegistry.get(ruleUID);
|
||||
if (rule != null) {
|
||||
final ModuleDTO dto = getModuleDTO(rule, moduleCategory, id);
|
||||
@ -381,9 +371,9 @@ public class RuleResource implements RESTResource {
|
||||
@ApiOperation(value = "Gets the module's configuration.")
|
||||
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = String.class),
|
||||
@ApiResponse(code = 404, message = "Rule corresponding to the given UID does not found or does not have a module with such Category and ID.") })
|
||||
public Response getModuleConfig(@PathParam("ruleUID") @ApiParam(value = "ruleUID", required = true) String ruleUID,
|
||||
@PathParam("moduleCategory") @ApiParam(value = "moduleCategory", required = true) String moduleCategory,
|
||||
@PathParam("id") @ApiParam(value = "id", required = true) String id) {
|
||||
public Response getModuleConfig(@PathParam("ruleUID") @ApiParam(value = "ruleUID") String ruleUID,
|
||||
@PathParam("moduleCategory") @ApiParam(value = "moduleCategory") String moduleCategory,
|
||||
@PathParam("id") @ApiParam(value = "id") String id) {
|
||||
Rule rule = ruleRegistry.get(ruleUID);
|
||||
if (rule != null) {
|
||||
Module module = getModule(rule, moduleCategory, id);
|
||||
@ -400,11 +390,10 @@ public class RuleResource implements RESTResource {
|
||||
@ApiOperation(value = "Gets the module's configuration parameter.", response = String.class)
|
||||
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = String.class),
|
||||
@ApiResponse(code = 404, message = "Rule corresponding to the given UID does not found or does not have a module with such Category and ID.") })
|
||||
public Response getModuleConfigParam(
|
||||
@PathParam("ruleUID") @ApiParam(value = "ruleUID", required = true) String ruleUID,
|
||||
@PathParam("moduleCategory") @ApiParam(value = "moduleCategory", required = true) String moduleCategory,
|
||||
@PathParam("id") @ApiParam(value = "id", required = true) String id,
|
||||
@PathParam("param") @ApiParam(value = "param", required = true) String param) {
|
||||
public Response getModuleConfigParam(@PathParam("ruleUID") @ApiParam(value = "ruleUID") String ruleUID,
|
||||
@PathParam("moduleCategory") @ApiParam(value = "moduleCategory") String moduleCategory,
|
||||
@PathParam("id") @ApiParam(value = "id") String id,
|
||||
@PathParam("param") @ApiParam(value = "param") String param) {
|
||||
Rule rule = ruleRegistry.get(ruleUID);
|
||||
if (rule != null) {
|
||||
Module module = getModule(rule, moduleCategory, id);
|
||||
@ -421,11 +410,10 @@ public class RuleResource implements RESTResource {
|
||||
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK"),
|
||||
@ApiResponse(code = 404, message = "Rule corresponding to the given UID does not found or does not have a module with such Category and ID.") })
|
||||
@Consumes(MediaType.TEXT_PLAIN)
|
||||
public Response setModuleConfigParam(
|
||||
@PathParam("ruleUID") @ApiParam(value = "ruleUID", required = true) String ruleUID,
|
||||
@PathParam("moduleCategory") @ApiParam(value = "moduleCategory", required = true) String moduleCategory,
|
||||
@PathParam("id") @ApiParam(value = "id", required = true) String id,
|
||||
@PathParam("param") @ApiParam(value = "param", required = true) String param,
|
||||
public Response setModuleConfigParam(@PathParam("ruleUID") @ApiParam(value = "ruleUID") String ruleUID,
|
||||
@PathParam("moduleCategory") @ApiParam(value = "moduleCategory") String moduleCategory,
|
||||
@PathParam("id") @ApiParam(value = "id") String id,
|
||||
@PathParam("param") @ApiParam(value = "param") String param,
|
||||
@ApiParam(value = "value", required = true) String value) {
|
||||
Rule rule = ruleRegistry.get(ruleUID);
|
||||
if (rule != null) {
|
||||
@ -441,10 +429,7 @@ public class RuleResource implements RESTResource {
|
||||
return Response.status(Status.NOT_FOUND).build();
|
||||
}
|
||||
|
||||
protected <T extends Module> T getModuleById(final Collection<T> coll, final String id) {
|
||||
if (coll == null) {
|
||||
return null;
|
||||
}
|
||||
protected <T extends Module> @Nullable T getModuleById(final Collection<T> coll, final String id) {
|
||||
for (final T module : coll) {
|
||||
if (module.getId().equals(id)) {
|
||||
return module;
|
||||
@ -453,19 +438,19 @@ public class RuleResource implements RESTResource {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected Trigger getTrigger(Rule rule, String id) {
|
||||
protected @Nullable Trigger getTrigger(Rule rule, String id) {
|
||||
return getModuleById(rule.getTriggers(), id);
|
||||
}
|
||||
|
||||
protected Condition getCondition(Rule rule, String id) {
|
||||
protected @Nullable Condition getCondition(Rule rule, String id) {
|
||||
return getModuleById(rule.getConditions(), id);
|
||||
}
|
||||
|
||||
protected Action getAction(Rule rule, String id) {
|
||||
protected @Nullable Action getAction(Rule rule, String id) {
|
||||
return getModuleById(rule.getActions(), id);
|
||||
}
|
||||
|
||||
protected Module getModule(Rule rule, String moduleCategory, String id) {
|
||||
protected @Nullable Module getModule(Rule rule, String moduleCategory, String id) {
|
||||
if ("triggers".equals(moduleCategory)) {
|
||||
return getTrigger(rule, id);
|
||||
} else if ("conditions".equals(moduleCategory)) {
|
||||
@ -477,7 +462,7 @@ public class RuleResource implements RESTResource {
|
||||
}
|
||||
}
|
||||
|
||||
protected ModuleDTO getModuleDTO(Rule rule, String moduleCategory, String id) {
|
||||
protected @Nullable ModuleDTO getModuleDTO(Rule rule, String moduleCategory, String id) {
|
||||
if ("triggers".equals(moduleCategory)) {
|
||||
final Trigger trigger = getTrigger(rule, id);
|
||||
return trigger == null ? null : TriggerDTOMapper.map(trigger);
|
||||
@ -491,9 +476,4 @@ public class RuleResource implements RESTResource {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSatisfied() {
|
||||
return ruleRegistry != null && ruleManager != null;
|
||||
}
|
||||
}
|
||||
|
@ -21,14 +21,13 @@ import javax.ws.rs.HeaderParam;
|
||||
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.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.Response.Status;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.core.automation.dto.RuleTemplateDTO;
|
||||
import org.openhab.core.automation.dto.RuleTemplateDTOMapper;
|
||||
import org.openhab.core.automation.template.RuleTemplate;
|
||||
@ -37,10 +36,9 @@ import org.openhab.core.automation.template.TemplateRegistry;
|
||||
import org.openhab.core.io.rest.LocaleService;
|
||||
import org.openhab.core.io.rest.RESTConstants;
|
||||
import org.openhab.core.io.rest.RESTResource;
|
||||
import org.osgi.service.component.annotations.Activate;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Reference;
|
||||
import org.osgi.service.component.annotations.ReferenceCardinality;
|
||||
import org.osgi.service.component.annotations.ReferencePolicy;
|
||||
import org.osgi.service.jaxrs.whiteboard.JaxrsWhiteboardConstants;
|
||||
import org.osgi.service.jaxrs.whiteboard.propertytypes.JSONRequired;
|
||||
import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsApplicationSelect;
|
||||
@ -72,28 +70,15 @@ public class TemplateResource implements RESTResource {
|
||||
/** The URI path to this resource */
|
||||
public static final String PATH_TEMPLATES = "templates";
|
||||
|
||||
private @NonNullByDefault({}) TemplateRegistry<@NonNull RuleTemplate> templateRegistry;
|
||||
private @NonNullByDefault({}) LocaleService localeService;
|
||||
private final LocaleService localeService;
|
||||
private final TemplateRegistry<@NonNull RuleTemplate> templateRegistry;
|
||||
|
||||
@Context
|
||||
private @NonNullByDefault({}) UriInfo uriInfo;
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
|
||||
protected void setTemplateRegistry(TemplateRegistry<RuleTemplate> templateRegistry) {
|
||||
this.templateRegistry = templateRegistry;
|
||||
}
|
||||
|
||||
protected void unsetTemplateRegistry(TemplateRegistry<RuleTemplate> templateRegistry) {
|
||||
this.templateRegistry = null;
|
||||
}
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
|
||||
protected void setLocaleService(LocaleService localeService) {
|
||||
@Activate
|
||||
public TemplateResource( //
|
||||
final @Reference LocaleService localeService,
|
||||
final @Reference TemplateRegistry<@NonNull RuleTemplate> templateRegistry) {
|
||||
this.localeService = localeService;
|
||||
}
|
||||
|
||||
protected void unsetLocaleService(LocaleService localeService) {
|
||||
this.localeService = null;
|
||||
this.templateRegistry = templateRegistry;
|
||||
}
|
||||
|
||||
@GET
|
||||
@ -101,7 +86,7 @@ public class TemplateResource implements RESTResource {
|
||||
@ApiOperation(value = "Get all available templates.", response = Template.class, responseContainer = "Collection")
|
||||
@ApiResponses(value = {
|
||||
@ApiResponse(code = 200, message = "OK", response = Template.class, responseContainer = "Collection") })
|
||||
public Response getAll(@HeaderParam("Accept-Language") @ApiParam(value = "language") String language) {
|
||||
public Response getAll(@HeaderParam("Accept-Language") @ApiParam(value = "language") @Nullable String language) {
|
||||
Locale locale = localeService.getLocale(language);
|
||||
Collection<RuleTemplateDTO> result = templateRegistry.getAll(locale).stream()
|
||||
.map(template -> RuleTemplateDTOMapper.map(template)).collect(Collectors.toList());
|
||||
@ -114,8 +99,8 @@ public class TemplateResource implements RESTResource {
|
||||
@ApiOperation(value = "Gets a template corresponding to the given UID.", response = Template.class)
|
||||
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = Template.class),
|
||||
@ApiResponse(code = 404, message = "Template corresponding to the given UID does not found.") })
|
||||
public Response getByUID(@HeaderParam("Accept-Language") @ApiParam(value = "language") String language,
|
||||
@PathParam("templateUID") @ApiParam(value = "templateUID", required = true) String templateUID) {
|
||||
public Response getByUID(@HeaderParam("Accept-Language") @ApiParam(value = "language") @Nullable String language,
|
||||
@PathParam("templateUID") @ApiParam(value = "templateUID") String templateUID) {
|
||||
Locale locale = localeService.getLocale(language);
|
||||
RuleTemplate template = templateRegistry.get(templateUID, locale);
|
||||
if (template != null) {
|
||||
@ -124,9 +109,4 @@ public class TemplateResource implements RESTResource {
|
||||
return Response.status(Status.NOT_FOUND).build();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSatisfied() {
|
||||
return templateRegistry != null && localeService != null;
|
||||
}
|
||||
}
|
||||
|
@ -12,6 +12,7 @@
|
||||
*/
|
||||
package org.openhab.core.automation.dto;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.core.automation.template.RuleTemplate;
|
||||
import org.openhab.core.config.core.dto.ConfigDescriptionDTOMapper;
|
||||
|
||||
@ -20,6 +21,7 @@ import org.openhab.core.config.core.dto.ConfigDescriptionDTOMapper;
|
||||
*
|
||||
* @author Ana Dimova - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class RuleTemplateDTOMapper {
|
||||
|
||||
public static RuleTemplateDTO map(final RuleTemplate template) {
|
||||
|
@ -61,7 +61,7 @@ public class Configuration {
|
||||
*
|
||||
* @param properties the properties the configuration should be filled. If null, an empty configuration is created.
|
||||
*/
|
||||
public Configuration(Map<String, Object> properties) {
|
||||
public Configuration(@Nullable Map<String, Object> properties) {
|
||||
this(properties == null ? emptyMap() : properties, false);
|
||||
}
|
||||
|
||||
@ -103,7 +103,7 @@ public class Configuration {
|
||||
return properties.get(key);
|
||||
}
|
||||
|
||||
public Object put(String key, Object value) {
|
||||
public Object put(String key, @Nullable Object value) {
|
||||
return properties.put(key, ConfigUtil.normalizeType(value, null));
|
||||
}
|
||||
|
||||
@ -150,7 +150,7 @@ public class Configuration {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
return (obj instanceof Configuration) && this.properties.equals(((Configuration) obj).properties);
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,7 @@ import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.core.auth.Role;
|
||||
import org.openhab.core.id.InstanceUUID;
|
||||
import org.openhab.core.io.rest.RESTConstants;
|
||||
@ -47,6 +48,7 @@ import io.swagger.annotations.ApiResponses;
|
||||
@Path(UUIDResource.PATH_UUID)
|
||||
@Api(UUIDResource.PATH_UUID)
|
||||
@RolesAllowed({ Role.ADMIN })
|
||||
@NonNullByDefault
|
||||
public class UUIDResource implements RESTResource {
|
||||
|
||||
public static final String PATH_UUID = "uuid";
|
||||
|
@ -37,10 +37,9 @@ import org.openhab.core.io.rest.JSONResponse;
|
||||
import org.openhab.core.io.rest.LocaleService;
|
||||
import org.openhab.core.io.rest.RESTConstants;
|
||||
import org.openhab.core.io.rest.RESTResource;
|
||||
import org.osgi.service.component.annotations.Activate;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Reference;
|
||||
import org.osgi.service.component.annotations.ReferenceCardinality;
|
||||
import org.osgi.service.component.annotations.ReferencePolicy;
|
||||
import org.osgi.service.jaxrs.whiteboard.JaxrsWhiteboardConstants;
|
||||
import org.osgi.service.jaxrs.whiteboard.propertytypes.JSONRequired;
|
||||
import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsApplicationSelect;
|
||||
@ -70,29 +69,20 @@ import io.swagger.annotations.ApiResponses;
|
||||
@NonNullByDefault
|
||||
public class AudioResource implements RESTResource {
|
||||
|
||||
static final String PATH_AUDIO = "audio";
|
||||
/** The URI path to this resource */
|
||||
public static final String PATH_AUDIO = "audio";
|
||||
|
||||
private @Nullable AudioManager audioManager;
|
||||
private @Nullable LocaleService localeService;
|
||||
private final AudioManager audioManager;
|
||||
private final LocaleService localeService;
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
|
||||
public void setAudioManager(AudioManager audioManager) {
|
||||
@Activate
|
||||
public AudioResource( //
|
||||
final @Reference AudioManager audioManager, //
|
||||
final @Reference LocaleService localeService) {
|
||||
this.audioManager = audioManager;
|
||||
}
|
||||
|
||||
public void unsetAudioManager(AudioManager audioManager) {
|
||||
this.audioManager = null;
|
||||
}
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
|
||||
protected void setLocaleService(LocaleService localeService) {
|
||||
this.localeService = localeService;
|
||||
}
|
||||
|
||||
protected void unsetLocaleService(LocaleService localeService) {
|
||||
this.localeService = null;
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("/sources")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@ -158,9 +148,4 @@ public class AudioResource implements RESTResource {
|
||||
return JSONResponse.createErrorResponse(Status.NOT_FOUND, "Sink not found");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSatisfied() {
|
||||
return audioManager != null && localeService != null;
|
||||
}
|
||||
}
|
||||
|
@ -40,6 +40,7 @@ import javax.ws.rs.core.Response.Status;
|
||||
import javax.ws.rs.core.SecurityContext;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.jose4j.base64url.Base64Url;
|
||||
import org.openhab.core.auth.ManagedUser;
|
||||
import org.openhab.core.auth.PendingToken;
|
||||
@ -79,6 +80,7 @@ import io.swagger.annotations.ApiResponses;
|
||||
@JSONRequired
|
||||
@Path(TokenResource.PATH_AUTH)
|
||||
@Api(TokenResource.PATH_AUTH)
|
||||
@NonNullByDefault
|
||||
public class TokenResource implements RESTResource {
|
||||
private final Logger logger = LoggerFactory.getLogger(TokenResource.class);
|
||||
|
||||
@ -91,11 +93,10 @@ public class TokenResource implements RESTResource {
|
||||
/** The default lifetime of tokens in minutes before they expire */
|
||||
public static final int TOKEN_LIFETIME = 60;
|
||||
|
||||
@Context
|
||||
private UriInfo uriInfo;
|
||||
private @Context @NonNullByDefault({}) UriInfo uriInfo;
|
||||
|
||||
private UserRegistry userRegistry;
|
||||
private JwtHelper jwtHelper;
|
||||
private final UserRegistry userRegistry;
|
||||
private final JwtHelper jwtHelper;
|
||||
|
||||
@Activate
|
||||
public TokenResource(final @Reference UserRegistry userRegistry, final @Reference JwtHelper jwtHelper) {
|
||||
|
@ -22,6 +22,7 @@ import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.core.config.core.ConfigConstants;
|
||||
import org.openhab.core.config.core.Configuration;
|
||||
import org.osgi.framework.Constants;
|
||||
@ -52,7 +53,7 @@ public class ConfigurationService {
|
||||
* @return config or null if no config with the given config id exists
|
||||
* @throws IOException if configuration can not be read
|
||||
*/
|
||||
public Configuration get(String configId) throws IOException {
|
||||
public @Nullable Configuration get(String configId) throws IOException {
|
||||
org.osgi.service.cm.Configuration configuration = configurationAdmin.getConfiguration(configId, null);
|
||||
Dictionary<String, Object> properties = configuration.getProperties();
|
||||
return toConfiguration(properties);
|
||||
@ -161,7 +162,7 @@ public class ConfigurationService {
|
||||
return oldConfiguration;
|
||||
}
|
||||
|
||||
private Configuration toConfiguration(Dictionary<String, Object> dictionary) {
|
||||
private @Nullable Configuration toConfiguration(Dictionary<String, Object> dictionary) {
|
||||
if (dictionary == null) {
|
||||
return null;
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsExtension;
|
||||
/**
|
||||
* Trap exceptions.
|
||||
*
|
||||
* @author Markus Rathgeb - Migrated to JAX-RS Whiteboard Specification
|
||||
* @author Markus Rathgeb - Initial contribution
|
||||
*/
|
||||
@Component
|
||||
@JaxrsExtension
|
||||
|
@ -27,13 +27,13 @@ import javax.ws.rs.PUT;
|
||||
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.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.core.auth.Role;
|
||||
import org.openhab.core.binding.BindingInfo;
|
||||
import org.openhab.core.binding.BindingInfoRegistry;
|
||||
@ -47,10 +47,9 @@ import org.openhab.core.io.rest.RESTConstants;
|
||||
import org.openhab.core.io.rest.RESTResource;
|
||||
import org.openhab.core.io.rest.Stream2JSONInputStream;
|
||||
import org.openhab.core.io.rest.core.config.ConfigurationService;
|
||||
import org.osgi.service.component.annotations.Activate;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Reference;
|
||||
import org.osgi.service.component.annotations.ReferenceCardinality;
|
||||
import org.osgi.service.component.annotations.ReferencePolicy;
|
||||
import org.osgi.service.jaxrs.whiteboard.JaxrsWhiteboardConstants;
|
||||
import org.osgi.service.jaxrs.whiteboard.propertytypes.JSONRequired;
|
||||
import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsApplicationSelect;
|
||||
@ -83,6 +82,7 @@ import io.swagger.annotations.ApiResponses;
|
||||
@Path(BindingResource.PATH_BINDINGS)
|
||||
@RolesAllowed({ Role.ADMIN })
|
||||
@Api(BindingResource.PATH_BINDINGS)
|
||||
@NonNullByDefault
|
||||
public class BindingResource implements RESTResource {
|
||||
|
||||
/** The URI path to this resource */
|
||||
@ -90,40 +90,30 @@ public class BindingResource implements RESTResource {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(BindingResource.class);
|
||||
|
||||
private ConfigurationService configurationService;
|
||||
private ConfigDescriptionRegistry configDescRegistry;
|
||||
private final BindingInfoRegistry bindingInfoRegistry;
|
||||
private final ConfigurationService configurationService;
|
||||
private final ConfigDescriptionRegistry configDescRegistry;
|
||||
private final LocaleService localeService;
|
||||
|
||||
private BindingInfoRegistry bindingInfoRegistry;
|
||||
|
||||
private LocaleService localeService;
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
|
||||
protected void setBindingInfoRegistry(BindingInfoRegistry bindingInfoRegistry) {
|
||||
@Activate
|
||||
public BindingResource( //
|
||||
final @Reference BindingInfoRegistry bindingInfoRegistry,
|
||||
final @Reference ConfigurationService configurationService,
|
||||
final @Reference ConfigDescriptionRegistry configDescRegistry,
|
||||
final @Reference LocaleService localeService) {
|
||||
this.bindingInfoRegistry = bindingInfoRegistry;
|
||||
}
|
||||
|
||||
protected void unsetBindingInfoRegistry(BindingInfoRegistry bindingInfoRegistry) {
|
||||
this.bindingInfoRegistry = null;
|
||||
}
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
|
||||
protected void setLocaleService(LocaleService localeService) {
|
||||
this.configurationService = configurationService;
|
||||
this.configDescRegistry = configDescRegistry;
|
||||
this.localeService = localeService;
|
||||
}
|
||||
|
||||
protected void unsetLocaleService(LocaleService localeService) {
|
||||
this.localeService = null;
|
||||
}
|
||||
|
||||
@Context
|
||||
UriInfo uriInfo;
|
||||
|
||||
@GET
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@ApiOperation(value = "Get all bindings.", response = BindingInfoDTO.class, responseContainer = "Set")
|
||||
@ApiResponses(value = {
|
||||
@ApiResponse(code = 200, message = "OK", response = BindingInfoDTO.class, responseContainer = "Set") })
|
||||
public Response getAll(@HeaderParam(HttpHeaders.ACCEPT_LANGUAGE) @ApiParam(value = "language") String language) {
|
||||
public Response getAll(
|
||||
@HeaderParam(HttpHeaders.ACCEPT_LANGUAGE) @ApiParam(value = "language") @Nullable String language) {
|
||||
final Locale locale = localeService.getLocale(language);
|
||||
Set<BindingInfo> bindingInfos = bindingInfoRegistry.getBindingInfos(locale);
|
||||
|
||||
@ -137,8 +127,7 @@ public class BindingResource implements RESTResource {
|
||||
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = String.class),
|
||||
@ApiResponse(code = 404, message = "Binding does not exist"),
|
||||
@ApiResponse(code = 500, message = "Configuration can not be read due to internal error") })
|
||||
public Response getConfiguration(
|
||||
@PathParam("bindingId") @ApiParam(value = "service ID", required = true) String bindingId) {
|
||||
public Response getConfiguration(@PathParam("bindingId") @ApiParam(value = "service ID") String bindingId) {
|
||||
try {
|
||||
String configId = getConfigId(bindingId);
|
||||
if (configId == null) {
|
||||
@ -164,9 +153,8 @@ public class BindingResource implements RESTResource {
|
||||
@ApiResponse(code = 204, message = "No old configuration"),
|
||||
@ApiResponse(code = 404, message = "Binding does not exist"),
|
||||
@ApiResponse(code = 500, message = "Configuration can not be updated due to internal error") })
|
||||
public Response updateConfiguration(
|
||||
@PathParam("bindingId") @ApiParam(value = "service ID", required = true) String bindingId,
|
||||
Map<String, Object> configuration) {
|
||||
public Response updateConfiguration(@PathParam("bindingId") @ApiParam(value = "service ID") String bindingId,
|
||||
@Nullable Map<String, Object> configuration) {
|
||||
try {
|
||||
String configId = getConfigId(bindingId);
|
||||
if (configId == null) {
|
||||
@ -184,7 +172,8 @@ public class BindingResource implements RESTResource {
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, Object> normalizeConfiguration(Map<String, Object> properties, String bindingId) {
|
||||
private @Nullable Map<String, Object> normalizeConfiguration(@Nullable Map<String, Object> properties,
|
||||
String bindingId) {
|
||||
if (properties == null || properties.isEmpty()) {
|
||||
return properties;
|
||||
}
|
||||
@ -202,7 +191,7 @@ public class BindingResource implements RESTResource {
|
||||
return ConfigUtil.normalizeTypes(properties, Collections.singletonList(configDesc));
|
||||
}
|
||||
|
||||
private String getConfigId(String bindingId) {
|
||||
private @Nullable String getConfigId(String bindingId) {
|
||||
BindingInfo bindingInfo = this.bindingInfoRegistry.getBindingInfo(bindingId);
|
||||
if (bindingInfo != null) {
|
||||
return bindingInfo.getServiceId();
|
||||
@ -216,28 +205,4 @@ public class BindingResource implements RESTResource {
|
||||
return new BindingInfoDTO(bindingInfo.getUID(), bindingInfo.getName(), bindingInfo.getAuthor(),
|
||||
bindingInfo.getDescription(), configDescriptionURI != null ? configDescriptionURI.toString() : null);
|
||||
}
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
|
||||
protected void setConfigurationService(ConfigurationService configurationService) {
|
||||
this.configurationService = configurationService;
|
||||
}
|
||||
|
||||
protected void unsetConfigurationService(ConfigurationService configurationService) {
|
||||
this.configurationService = null;
|
||||
}
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
|
||||
protected void setConfigDescriptionRegistry(ConfigDescriptionRegistry configDescriptionRegistry) {
|
||||
this.configDescRegistry = configDescriptionRegistry;
|
||||
}
|
||||
|
||||
protected void unsetConfigDescriptionRegistry(ConfigDescriptionRegistry configDescriptionRegistry) {
|
||||
this.configDescRegistry = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSatisfied() {
|
||||
return configurationService != null && configDescRegistry != null && bindingInfoRegistry != null
|
||||
&& localeService != null;
|
||||
}
|
||||
}
|
||||
|
@ -32,6 +32,7 @@ import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.Response.Status;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.core.auth.Role;
|
||||
import org.openhab.core.config.core.ConfigDescription;
|
||||
@ -52,10 +53,9 @@ import org.openhab.core.thing.type.ChannelKind;
|
||||
import org.openhab.core.thing.type.ChannelType;
|
||||
import org.openhab.core.thing.type.ChannelTypeRegistry;
|
||||
import org.openhab.core.thing.type.ChannelTypeUID;
|
||||
import org.osgi.service.component.annotations.Activate;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Reference;
|
||||
import org.osgi.service.component.annotations.ReferenceCardinality;
|
||||
import org.osgi.service.component.annotations.ReferencePolicy;
|
||||
import org.osgi.service.jaxrs.whiteboard.JaxrsWhiteboardConstants;
|
||||
import org.osgi.service.jaxrs.whiteboard.propertytypes.JSONRequired;
|
||||
import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsApplicationSelect;
|
||||
@ -84,52 +84,27 @@ import io.swagger.annotations.ApiResponses;
|
||||
@Path(ChannelTypeResource.PATH_CHANNEL_TYPES)
|
||||
@RolesAllowed({ Role.ADMIN })
|
||||
@Api(ChannelTypeResource.PATH_CHANNEL_TYPES)
|
||||
@NonNullByDefault
|
||||
public class ChannelTypeResource implements RESTResource {
|
||||
|
||||
/** The URI path to this resource */
|
||||
public static final String PATH_CHANNEL_TYPES = "channel-types";
|
||||
|
||||
private ChannelTypeRegistry channelTypeRegistry;
|
||||
private ConfigDescriptionRegistry configDescriptionRegistry;
|
||||
private final ChannelTypeRegistry channelTypeRegistry;
|
||||
private final ConfigDescriptionRegistry configDescriptionRegistry;
|
||||
private final LocaleService localeService;
|
||||
private final ProfileTypeRegistry profileTypeRegistry;
|
||||
|
||||
private ProfileTypeRegistry profileTypeRegistry;
|
||||
|
||||
private LocaleService localeService;
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
|
||||
protected void setChannelTypeRegistry(ChannelTypeRegistry channelTypeRegistry) {
|
||||
@Activate
|
||||
public ChannelTypeResource( //
|
||||
final @Reference ChannelTypeRegistry channelTypeRegistry,
|
||||
final @Reference ConfigDescriptionRegistry configDescriptionRegistry,
|
||||
final @Reference LocaleService localeService, //
|
||||
final @Reference ProfileTypeRegistry profileTypeRegistry) {
|
||||
this.channelTypeRegistry = channelTypeRegistry;
|
||||
}
|
||||
|
||||
protected void unsetChannelTypeRegistry(ChannelTypeRegistry channelTypeRegistry) {
|
||||
this.channelTypeRegistry = null;
|
||||
}
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
|
||||
protected void setConfigDescriptionRegistry(ConfigDescriptionRegistry configDescriptionRegistry) {
|
||||
this.configDescriptionRegistry = configDescriptionRegistry;
|
||||
}
|
||||
|
||||
protected void unsetConfigDescriptionRegistry(ConfigDescriptionRegistry configDescriptionRegistry) {
|
||||
this.configDescriptionRegistry = null;
|
||||
}
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
|
||||
protected void setProfileTypeRegistry(ProfileTypeRegistry profileTypeRegistry) {
|
||||
this.profileTypeRegistry = profileTypeRegistry;
|
||||
}
|
||||
|
||||
protected void unsetProfileTypeRegistry(ProfileTypeRegistry profileTypeRegistry) {
|
||||
this.profileTypeRegistry = null;
|
||||
}
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
|
||||
protected void setLocaleService(LocaleService localeService) {
|
||||
this.localeService = localeService;
|
||||
}
|
||||
|
||||
protected void unsetLocaleService(LocaleService localeService) {
|
||||
this.localeService = null;
|
||||
this.profileTypeRegistry = profileTypeRegistry;
|
||||
}
|
||||
|
||||
@GET
|
||||
@ -137,8 +112,8 @@ public class ChannelTypeResource implements RESTResource {
|
||||
@ApiOperation(value = "Gets all available channel types.", response = ChannelTypeDTO.class, responseContainer = "Set")
|
||||
@ApiResponses(value = @ApiResponse(code = 200, message = "OK", response = ChannelTypeDTO.class, responseContainer = "Set"))
|
||||
public Response getAll(
|
||||
@HeaderParam(HttpHeaders.ACCEPT_LANGUAGE) @ApiParam(value = HttpHeaders.ACCEPT_LANGUAGE) String language,
|
||||
@QueryParam("prefixes") @ApiParam(value = "filter UIDs by prefix (multiple comma-separated prefixes allowed, for example: 'system,mqtt')", required = false) @Nullable String prefixes) {
|
||||
@HeaderParam(HttpHeaders.ACCEPT_LANGUAGE) @ApiParam(value = "language") @Nullable String language,
|
||||
@QueryParam("prefixes") @ApiParam(value = "filter UIDs by prefix (multiple comma-separated prefixes allowed, for example: 'system,mqtt')") @Nullable String prefixes) {
|
||||
Locale locale = localeService.getLocale(language);
|
||||
|
||||
Stream<ChannelTypeDTO> channelStream = channelTypeRegistry.getChannelTypes(locale).stream()
|
||||
@ -163,7 +138,7 @@ public class ChannelTypeResource implements RESTResource {
|
||||
@ApiResponse(code = 200, message = "Channel type with provided channelTypeUID does not exist.", response = ChannelTypeDTO.class),
|
||||
@ApiResponse(code = 404, message = "No content") })
|
||||
public Response getByUID(@PathParam("channelTypeUID") @ApiParam(value = "channelTypeUID") String channelTypeUID,
|
||||
@HeaderParam(HttpHeaders.ACCEPT_LANGUAGE) @ApiParam(value = HttpHeaders.ACCEPT_LANGUAGE) String language) {
|
||||
@HeaderParam(HttpHeaders.ACCEPT_LANGUAGE) @ApiParam(value = "language") @Nullable String language) {
|
||||
Locale locale = localeService.getLocale(language);
|
||||
ChannelType channelType = channelTypeRegistry.getChannelType(new ChannelTypeUID(channelTypeUID), locale);
|
||||
if (channelType != null) {
|
||||
@ -235,10 +210,4 @@ public class ChannelTypeResource implements RESTResource {
|
||||
parameterGroups, channelType.getState(), channelType.getTags(), channelType.isAdvanced(),
|
||||
channelType.getCommandDescription());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSatisfied() {
|
||||
return channelTypeRegistry != null && configDescriptionRegistry != null && profileTypeRegistry != null
|
||||
&& localeService != null;
|
||||
}
|
||||
}
|
||||
|
@ -40,10 +40,9 @@ import org.openhab.core.io.rest.RESTConstants;
|
||||
import org.openhab.core.io.rest.RESTResource;
|
||||
import org.openhab.core.io.rest.Stream2JSONInputStream;
|
||||
import org.openhab.core.io.rest.core.config.EnrichedConfigDescriptionDTOMapper;
|
||||
import org.osgi.service.component.annotations.Activate;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Reference;
|
||||
import org.osgi.service.component.annotations.ReferenceCardinality;
|
||||
import org.osgi.service.component.annotations.ReferencePolicy;
|
||||
import org.osgi.service.jaxrs.whiteboard.JaxrsWhiteboardConstants;
|
||||
import org.osgi.service.jaxrs.whiteboard.propertytypes.JSONRequired;
|
||||
import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsApplicationSelect;
|
||||
@ -78,26 +77,23 @@ public class ConfigDescriptionResource implements RESTResource {
|
||||
/** The URI path to this resource */
|
||||
public static final String PATH_CONFIG_DESCRIPTIONS = "config-descriptions";
|
||||
|
||||
private @NonNullByDefault({}) ConfigDescriptionRegistry configDescriptionRegistry;
|
||||
private final ConfigDescriptionRegistry configDescriptionRegistry;
|
||||
private final LocaleService localeService;
|
||||
|
||||
private @NonNullByDefault({}) LocaleService localeService;
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
|
||||
protected void setLocaleService(LocaleService localeService) {
|
||||
@Activate
|
||||
public ConfigDescriptionResource( //
|
||||
final @Reference ConfigDescriptionRegistry configDescriptionRegistry,
|
||||
final @Reference LocaleService localeService) {
|
||||
this.configDescriptionRegistry = configDescriptionRegistry;
|
||||
this.localeService = localeService;
|
||||
}
|
||||
|
||||
protected void unsetLocaleService(LocaleService localeService) {
|
||||
this.localeService = null;
|
||||
}
|
||||
|
||||
@GET
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@ApiOperation(value = "Gets all available config descriptions.", response = ConfigDescriptionDTO.class, responseContainer = "List")
|
||||
@ApiResponses(value = @ApiResponse(code = 200, message = "OK", response = ConfigDescriptionDTO.class, responseContainer = "List"))
|
||||
public Response getAll(
|
||||
@HeaderParam("Accept-Language") @ApiParam(value = "Accept-Language") @Nullable String language, //
|
||||
@QueryParam("scheme") @ApiParam(value = "scheme filter", required = false) @Nullable String scheme) {
|
||||
public Response getAll(@HeaderParam("Accept-Language") @ApiParam(value = "language") @Nullable String language, //
|
||||
@QueryParam("scheme") @ApiParam(value = "scheme filter") @Nullable String scheme) {
|
||||
Locale locale = localeService.getLocale(language);
|
||||
Collection<ConfigDescription> configDescriptions = configDescriptionRegistry.getConfigDescriptions(locale);
|
||||
return Response.ok(new Stream2JSONInputStream(configDescriptions.stream().filter(configDescription -> {
|
||||
@ -111,8 +107,7 @@ public class ConfigDescriptionResource implements RESTResource {
|
||||
@ApiOperation(value = "Gets a config description by URI.", response = ConfigDescriptionDTO.class)
|
||||
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = ConfigDescriptionDTO.class),
|
||||
@ApiResponse(code = 400, message = "Invalid URI syntax"), @ApiResponse(code = 404, message = "Not found") })
|
||||
public Response getByURI(
|
||||
@HeaderParam("Accept-Language") @ApiParam(value = "Accept-Language") @Nullable String language,
|
||||
public Response getByURI(@HeaderParam("Accept-Language") @ApiParam(value = "language") @Nullable String language,
|
||||
@PathParam("uri") @ApiParam(value = "uri") String uri) {
|
||||
Locale locale = localeService.getLocale(language);
|
||||
URI uriObject = UriBuilder.fromPath(uri).build();
|
||||
@ -121,18 +116,4 @@ public class ConfigDescriptionResource implements RESTResource {
|
||||
? Response.ok(EnrichedConfigDescriptionDTOMapper.map(configDescription)).build()
|
||||
: JSONResponse.createErrorResponse(Status.NOT_FOUND, "Configuration not found: " + uri);
|
||||
}
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
|
||||
protected void setConfigDescriptionRegistry(ConfigDescriptionRegistry configDescriptionRegistry) {
|
||||
this.configDescriptionRegistry = configDescriptionRegistry;
|
||||
}
|
||||
|
||||
protected void unsetConfigDescriptionRegistry(ConfigDescriptionRegistry configDescriptionRegistry) {
|
||||
this.configDescriptionRegistry = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSatisfied() {
|
||||
return configDescriptionRegistry != null && localeService != null;
|
||||
}
|
||||
}
|
||||
|
@ -21,20 +21,19 @@ 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.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.core.auth.Role;
|
||||
import org.openhab.core.config.discovery.DiscoveryServiceRegistry;
|
||||
import org.openhab.core.config.discovery.ScanListener;
|
||||
import org.openhab.core.io.rest.RESTConstants;
|
||||
import org.openhab.core.io.rest.RESTResource;
|
||||
import org.osgi.service.component.annotations.Activate;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Reference;
|
||||
import org.osgi.service.component.annotations.ReferenceCardinality;
|
||||
import org.osgi.service.component.annotations.ReferencePolicy;
|
||||
import org.osgi.service.jaxrs.whiteboard.JaxrsWhiteboardConstants;
|
||||
import org.osgi.service.jaxrs.whiteboard.propertytypes.JSONRequired;
|
||||
import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsApplicationSelect;
|
||||
@ -68,6 +67,7 @@ import io.swagger.annotations.ApiResponses;
|
||||
@Path(DiscoveryResource.PATH_DISCOVERY)
|
||||
@RolesAllowed({ Role.ADMIN })
|
||||
@Api(DiscoveryResource.PATH_DISCOVERY)
|
||||
@NonNullByDefault
|
||||
public class DiscoveryResource implements RESTResource {
|
||||
|
||||
/** The URI path to this resource */
|
||||
@ -75,20 +75,13 @@ public class DiscoveryResource implements RESTResource {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(DiscoveryResource.class);
|
||||
|
||||
private DiscoveryServiceRegistry discoveryServiceRegistry;
|
||||
private final DiscoveryServiceRegistry discoveryServiceRegistry;
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
|
||||
protected void setDiscoveryServiceRegistry(DiscoveryServiceRegistry discoveryServiceRegistry) {
|
||||
@Activate
|
||||
public DiscoveryResource(final @Reference DiscoveryServiceRegistry discoveryServiceRegistry) {
|
||||
this.discoveryServiceRegistry = discoveryServiceRegistry;
|
||||
}
|
||||
|
||||
protected void unsetDiscoveryServiceRegistry(DiscoveryServiceRegistry discoveryServiceRegistry) {
|
||||
this.discoveryServiceRegistry = null;
|
||||
}
|
||||
|
||||
@Context
|
||||
private UriInfo uriInfo;
|
||||
|
||||
@GET
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@ApiOperation(value = "Gets all bindings that support discovery.", response = String.class, responseContainer = "Set")
|
||||
@ -107,9 +100,8 @@ public class DiscoveryResource implements RESTResource {
|
||||
public Response scan(@PathParam("bindingId") @ApiParam(value = "bindingId") final String bindingId) {
|
||||
discoveryServiceRegistry.startScan(bindingId, new ScanListener() {
|
||||
@Override
|
||||
public void onErrorOccurred(Exception exception) {
|
||||
logger.error("Error occurred while scanning for binding '{}': {}", bindingId, exception.getMessage(),
|
||||
exception);
|
||||
public void onErrorOccurred(@Nullable Exception exception) {
|
||||
logger.error("Error occurred while scanning for binding '{}'", bindingId, exception);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -120,9 +112,4 @@ public class DiscoveryResource implements RESTResource {
|
||||
|
||||
return Response.ok(discoveryServiceRegistry.getMaxScanTimeout(bindingId)).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSatisfied() {
|
||||
return discoveryServiceRegistry != null;
|
||||
}
|
||||
}
|
||||
|
@ -23,13 +23,13 @@ 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.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.core.auth.Role;
|
||||
import org.openhab.core.config.discovery.DiscoveryResultFlag;
|
||||
import org.openhab.core.config.discovery.dto.DiscoveryResultDTO;
|
||||
@ -41,10 +41,9 @@ import org.openhab.core.io.rest.RESTResource;
|
||||
import org.openhab.core.io.rest.Stream2JSONInputStream;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingUID;
|
||||
import org.osgi.service.component.annotations.Activate;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Reference;
|
||||
import org.osgi.service.component.annotations.ReferenceCardinality;
|
||||
import org.osgi.service.component.annotations.ReferencePolicy;
|
||||
import org.osgi.service.jaxrs.whiteboard.JaxrsWhiteboardConstants;
|
||||
import org.osgi.service.jaxrs.whiteboard.propertytypes.JSONRequired;
|
||||
import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsApplicationSelect;
|
||||
@ -78,26 +77,20 @@ import io.swagger.annotations.ApiResponses;
|
||||
@Path(InboxResource.PATH_INBOX)
|
||||
@RolesAllowed({ Role.ADMIN })
|
||||
@Api(InboxResource.PATH_INBOX)
|
||||
@NonNullByDefault
|
||||
public class InboxResource implements RESTResource {
|
||||
private final Logger logger = LoggerFactory.getLogger(InboxResource.class);
|
||||
|
||||
/** The URI path to this resource */
|
||||
public static final String PATH_INBOX = "inbox";
|
||||
|
||||
private Inbox inbox;
|
||||
private final Inbox inbox;
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
|
||||
protected void setInbox(Inbox inbox) {
|
||||
@Activate
|
||||
public InboxResource(final @Reference 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)
|
||||
@ -105,9 +98,10 @@ public class InboxResource implements RESTResource {
|
||||
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK"),
|
||||
@ApiResponse(code = 404, message = "Thing unable to be approved."),
|
||||
@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) {
|
||||
public Response approve(
|
||||
@HeaderParam(HttpHeaders.ACCEPT_LANGUAGE) @ApiParam(value = "language") @Nullable String language,
|
||||
@PathParam("thingUID") @ApiParam(value = "thingUID") String thingUID,
|
||||
@ApiParam(value = "thing label") @Nullable String label) {
|
||||
ThingUID thingUIDObject = new ThingUID(thingUID);
|
||||
String notEmptyLabel = label != null && !label.isEmpty() ? label : null;
|
||||
Thing thing = null;
|
||||
@ -131,7 +125,7 @@ public class InboxResource implements RESTResource {
|
||||
@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) {
|
||||
public Response delete(@PathParam("thingUID") @ApiParam(value = "thingUID") String thingUID) {
|
||||
if (inbox.remove(new ThingUID(thingUID))) {
|
||||
return Response.ok(null, MediaType.TEXT_PLAIN).build();
|
||||
} else {
|
||||
@ -152,7 +146,7 @@ public class InboxResource implements RESTResource {
|
||||
@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) {
|
||||
public Response ignore(@PathParam("thingUID") @ApiParam(value = "thingUID") String thingUID) {
|
||||
inbox.setFlag(new ThingUID(thingUID), DiscoveryResultFlag.IGNORED);
|
||||
return Response.ok(null, MediaType.TEXT_PLAIN).build();
|
||||
}
|
||||
@ -161,13 +155,8 @@ public class InboxResource implements RESTResource {
|
||||
@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) {
|
||||
public Response unignore(@PathParam("thingUID") @ApiParam(value = "thingUID") String thingUID) {
|
||||
inbox.setFlag(new ThingUID(thingUID), DiscoveryResultFlag.NEW);
|
||||
return Response.ok(null, MediaType.TEXT_PLAIN).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSatisfied() {
|
||||
return inbox != null;
|
||||
}
|
||||
}
|
||||
|
@ -35,6 +35,8 @@ import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.Response.Status;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.core.auth.Role;
|
||||
import org.openhab.core.common.ThreadPoolManager;
|
||||
import org.openhab.core.events.Event;
|
||||
@ -48,6 +50,7 @@ import org.openhab.core.io.rest.LocaleService;
|
||||
import org.openhab.core.io.rest.RESTConstants;
|
||||
import org.openhab.core.io.rest.RESTResource;
|
||||
import org.openhab.core.io.rest.Stream2JSONInputStream;
|
||||
import org.osgi.service.component.annotations.Activate;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Reference;
|
||||
import org.osgi.service.component.annotations.ReferenceCardinality;
|
||||
@ -81,6 +84,7 @@ import io.swagger.annotations.ApiResponses;
|
||||
@Path(ExtensionResource.PATH_EXTENSIONS)
|
||||
@RolesAllowed({ Role.ADMIN })
|
||||
@Api(ExtensionResource.PATH_EXTENSIONS)
|
||||
@NonNullByDefault
|
||||
public class ExtensionResource implements RESTResource {
|
||||
|
||||
private static final String THREAD_POOL_NAME = "extensionService";
|
||||
@ -88,12 +92,18 @@ public class ExtensionResource implements RESTResource {
|
||||
public static final String PATH_EXTENSIONS = "extensions";
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(ExtensionResource.class);
|
||||
|
||||
private final Set<ExtensionService> extensionServices = new CopyOnWriteArraySet<>();
|
||||
private final EventPublisher eventPublisher;
|
||||
private final LocaleService localeService;
|
||||
|
||||
private EventPublisher eventPublisher;
|
||||
private @Context @NonNullByDefault({}) UriInfo uriInfo;
|
||||
|
||||
private LocaleService localeService;
|
||||
@Activate
|
||||
public ExtensionResource(final @Reference EventPublisher eventPublisher,
|
||||
final @Reference LocaleService localeService) {
|
||||
this.eventPublisher = eventPublisher;
|
||||
this.localeService = localeService;
|
||||
}
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC)
|
||||
protected void addExtensionService(ExtensionService featureService) {
|
||||
@ -104,32 +114,12 @@ public class ExtensionResource implements RESTResource {
|
||||
this.extensionServices.remove(featureService);
|
||||
}
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
|
||||
protected void setEventPublisher(EventPublisher eventPublisher) {
|
||||
this.eventPublisher = eventPublisher;
|
||||
}
|
||||
|
||||
protected void unsetEventPublisher(EventPublisher eventPublisher) {
|
||||
this.eventPublisher = null;
|
||||
}
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
|
||||
protected void setLocaleService(LocaleService localeService) {
|
||||
this.localeService = localeService;
|
||||
}
|
||||
|
||||
protected void unsetLocaleService(LocaleService localeService) {
|
||||
this.localeService = null;
|
||||
}
|
||||
|
||||
@Context
|
||||
UriInfo uriInfo;
|
||||
|
||||
@GET
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@ApiOperation(value = "Get all extensions.")
|
||||
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = String.class) })
|
||||
public Response getExtensions(@HeaderParam("Accept-Language") @ApiParam(value = "language") String language) {
|
||||
public Response getExtensions(
|
||||
@HeaderParam("Accept-Language") @ApiParam(value = "language") @Nullable String language) {
|
||||
logger.debug("Received HTTP GET request at '{}'", uriInfo.getPath());
|
||||
Locale locale = localeService.getLocale(language);
|
||||
return Response.ok(new Stream2JSONInputStream(getAllExtensions(locale))).build();
|
||||
@ -140,7 +130,7 @@ public class ExtensionResource implements RESTResource {
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@ApiOperation(value = "Get all extension types.")
|
||||
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = String.class) })
|
||||
public Response getTypes(@HeaderParam("Accept-Language") @ApiParam(value = "language") String language) {
|
||||
public Response getTypes(@HeaderParam("Accept-Language") @ApiParam(value = "language") @Nullable String language) {
|
||||
logger.debug("Received HTTP GET request at '{}'", uriInfo.getPath());
|
||||
Locale locale = localeService.getLocale(language);
|
||||
Stream<ExtensionType> extensionTypeStream = getAllExtensionTypes(locale).stream().distinct();
|
||||
@ -153,8 +143,8 @@ public class ExtensionResource implements RESTResource {
|
||||
@ApiOperation(value = "Get extension with given ID.")
|
||||
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = String.class),
|
||||
@ApiResponse(code = 404, message = "Not found") })
|
||||
public Response getById(@HeaderParam("Accept-Language") @ApiParam(value = "language") String language,
|
||||
@PathParam("extensionId") @ApiParam(value = "extension ID", required = true) String extensionId) {
|
||||
public Response getById(@HeaderParam("Accept-Language") @ApiParam(value = "language") @Nullable String language,
|
||||
@PathParam("extensionId") @ApiParam(value = "extension ID") String extensionId) {
|
||||
logger.debug("Received HTTP GET request at '{}'.", uriInfo.getPath());
|
||||
Locale locale = localeService.getLocale(language);
|
||||
ExtensionService extensionService = getExtensionService(extensionId);
|
||||
@ -171,7 +161,7 @@ public class ExtensionResource implements RESTResource {
|
||||
@ApiOperation(value = "Installs the extension with the given ID.")
|
||||
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK") })
|
||||
public Response installExtension(
|
||||
final @PathParam("extensionId") @ApiParam(value = "extension ID", required = true) String extensionId) {
|
||||
final @PathParam("extensionId") @ApiParam(value = "extension ID") String extensionId) {
|
||||
ThreadPoolManager.getPool(THREAD_POOL_NAME).submit(() -> {
|
||||
try {
|
||||
ExtensionService extensionService = getExtensionService(extensionId);
|
||||
@ -190,7 +180,7 @@ public class ExtensionResource implements RESTResource {
|
||||
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK"),
|
||||
@ApiResponse(code = 400, message = "The given URL is malformed or not valid.") })
|
||||
public Response installExtensionByURL(
|
||||
final @PathParam("url") @ApiParam(value = "extension install URL", required = true) String url) {
|
||||
final @PathParam("url") @ApiParam(value = "extension install URL") String url) {
|
||||
try {
|
||||
URI extensionURI = new URI(url);
|
||||
String extensionId = getExtensionId(extensionURI);
|
||||
@ -208,7 +198,7 @@ public class ExtensionResource implements RESTResource {
|
||||
@ApiOperation(value = "Uninstalls the extension with the given ID.")
|
||||
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK") })
|
||||
public Response uninstallExtension(
|
||||
final @PathParam("extensionId") @ApiParam(value = "extension ID", required = true) String extensionId) {
|
||||
final @PathParam("extensionId") @ApiParam(value = "extension ID") String extensionId) {
|
||||
ThreadPoolManager.getPool(THREAD_POOL_NAME).submit(() -> {
|
||||
try {
|
||||
ExtensionService extensionService = getExtensionService(extensionId);
|
||||
@ -222,16 +212,9 @@ public class ExtensionResource implements RESTResource {
|
||||
}
|
||||
|
||||
private void postFailureEvent(String extensionId, String msg) {
|
||||
if (eventPublisher != null) {
|
||||
Event event = ExtensionEventFactory.createExtensionFailureEvent(extensionId, msg);
|
||||
eventPublisher.post(event);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSatisfied() {
|
||||
return !extensionServices.isEmpty() && localeService != null;
|
||||
}
|
||||
|
||||
private Stream<Extension> getAllExtensions(Locale locale) {
|
||||
return extensionServices.stream().map(s -> s.getExtensions(locale)).flatMap(l -> l.stream());
|
||||
|
@ -79,10 +79,9 @@ import org.openhab.core.library.types.UpDownType;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.State;
|
||||
import org.openhab.core.types.TypeParser;
|
||||
import org.osgi.service.component.annotations.Activate;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Reference;
|
||||
import org.osgi.service.component.annotations.ReferenceCardinality;
|
||||
import org.osgi.service.component.annotations.ReferencePolicy;
|
||||
import org.osgi.service.jaxrs.whiteboard.JaxrsWhiteboardConstants;
|
||||
import org.osgi.service.jaxrs.whiteboard.propertytypes.JSONRequired;
|
||||
import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsApplicationSelect;
|
||||
@ -153,85 +152,33 @@ public class ItemResource implements RESTResource {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(ItemResource.class);
|
||||
|
||||
private @NonNullByDefault({}) ItemRegistry itemRegistry;
|
||||
private @NonNullByDefault({}) MetadataRegistry metadataRegistry;
|
||||
private @NonNullByDefault({}) EventPublisher eventPublisher;
|
||||
private @NonNullByDefault({}) ManagedItemProvider managedItemProvider;
|
||||
private @NonNullByDefault({}) DTOMapper dtoMapper;
|
||||
private @NonNullByDefault({}) MetadataSelectorMatcher metadataSelectorMatcher;
|
||||
private @NonNullByDefault({}) ItemBuilderFactory itemBuilderFactory;
|
||||
private @NonNullByDefault({}) LocaleService localeService;
|
||||
private final DTOMapper dtoMapper;
|
||||
private final EventPublisher eventPublisher;
|
||||
private final ItemBuilderFactory itemBuilderFactory;
|
||||
private final ItemRegistry itemRegistry;
|
||||
private final LocaleService localeService;
|
||||
private final ManagedItemProvider managedItemProvider;
|
||||
private final MetadataRegistry metadataRegistry;
|
||||
private final MetadataSelectorMatcher metadataSelectorMatcher;
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
|
||||
protected void setItemRegistry(ItemRegistry itemRegistry) {
|
||||
this.itemRegistry = itemRegistry;
|
||||
}
|
||||
|
||||
protected void unsetItemRegistry(ItemRegistry itemRegistry) {
|
||||
this.itemRegistry = null;
|
||||
}
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
|
||||
protected void setMetadataRegistry(MetadataRegistry metadataRegistry) {
|
||||
this.metadataRegistry = metadataRegistry;
|
||||
}
|
||||
|
||||
protected void unsetMetadataRegistry(MetadataRegistry metadataRegistry) {
|
||||
this.metadataRegistry = null;
|
||||
}
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
|
||||
protected void setEventPublisher(EventPublisher eventPublisher) {
|
||||
@Activate
|
||||
public ItemResource(//
|
||||
final @Reference DTOMapper dtoMapper, //
|
||||
final @Reference EventPublisher eventPublisher, //
|
||||
final @Reference ItemBuilderFactory itemBuilderFactory, //
|
||||
final @Reference ItemRegistry itemRegistry, //
|
||||
final @Reference LocaleService localeService, //
|
||||
final @Reference ManagedItemProvider managedItemProvider,
|
||||
final @Reference MetadataRegistry metadataRegistry,
|
||||
final @Reference MetadataSelectorMatcher metadataSelectorMatcher) {
|
||||
this.dtoMapper = dtoMapper;
|
||||
this.eventPublisher = eventPublisher;
|
||||
}
|
||||
|
||||
protected void unsetEventPublisher(EventPublisher eventPublisher) {
|
||||
this.eventPublisher = null;
|
||||
}
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
|
||||
protected void setManagedItemProvider(ManagedItemProvider managedItemProvider) {
|
||||
this.managedItemProvider = managedItemProvider;
|
||||
}
|
||||
|
||||
protected void unsetManagedItemProvider(ManagedItemProvider managedItemProvider) {
|
||||
this.managedItemProvider = null;
|
||||
}
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
|
||||
protected void setDTOMapper(DTOMapper dtoMapper) {
|
||||
this.dtoMapper = dtoMapper;
|
||||
}
|
||||
|
||||
protected void unsetDTOMapper(DTOMapper dtoMapper) {
|
||||
this.dtoMapper = dtoMapper;
|
||||
}
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
|
||||
protected void setLocaleService(LocaleService localeService) {
|
||||
this.localeService = localeService;
|
||||
}
|
||||
|
||||
protected void unsetLocaleService(LocaleService localeService) {
|
||||
this.localeService = null;
|
||||
}
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
|
||||
protected void setMetadataSelectorMatcher(MetadataSelectorMatcher metadataSelectorMatcher) {
|
||||
this.metadataSelectorMatcher = metadataSelectorMatcher;
|
||||
}
|
||||
|
||||
protected void unsetMetadataSelectorMatcher(MetadataSelectorMatcher metadataSelectorMatcher) {
|
||||
this.metadataSelectorMatcher = null;
|
||||
}
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
|
||||
public void setItemBuilderFactory(ItemBuilderFactory itemBuilderFactory) {
|
||||
this.itemBuilderFactory = itemBuilderFactory;
|
||||
}
|
||||
|
||||
public void unsetItemBuilderFactory(ItemBuilderFactory itemBuilderFactory) {
|
||||
this.itemBuilderFactory = null;
|
||||
this.itemRegistry = itemRegistry;
|
||||
this.localeService = localeService;
|
||||
this.managedItemProvider = managedItemProvider;
|
||||
this.metadataRegistry = metadataRegistry;
|
||||
this.metadataSelectorMatcher = metadataSelectorMatcher;
|
||||
}
|
||||
|
||||
private UriBuilder uriBuilder(final UriInfo uriInfo, final HttpHeaders httpHeaders) {
|
||||
@ -249,11 +196,11 @@ public class ItemResource implements RESTResource {
|
||||
@ApiResponse(code = 200, message = "OK", response = EnrichedItemDTO.class, responseContainer = "List") })
|
||||
public Response getItems(final @Context UriInfo uriInfo, final @Context HttpHeaders httpHeaders,
|
||||
@HeaderParam(HttpHeaders.ACCEPT_LANGUAGE) @ApiParam(value = "language") @Nullable String language,
|
||||
@QueryParam("type") @ApiParam(value = "item type filter", required = false) @Nullable String type,
|
||||
@QueryParam("tags") @ApiParam(value = "item tag filter", required = false) @Nullable String tags,
|
||||
@QueryParam("metadata") @ApiParam(value = "metadata selector", required = false) @Nullable String namespaceSelector,
|
||||
@DefaultValue("false") @QueryParam("recursive") @ApiParam(value = "get member items recursively", required = false) boolean recursive,
|
||||
@QueryParam("fields") @ApiParam(value = "limit output to the given fields (comma separated)", required = false) @Nullable String fields) {
|
||||
@QueryParam("type") @ApiParam(value = "item type filter") @Nullable String type,
|
||||
@QueryParam("tags") @ApiParam(value = "item tag filter") @Nullable String tags,
|
||||
@QueryParam("metadata") @ApiParam(value = "metadata selector") @Nullable String namespaceSelector,
|
||||
@DefaultValue("false") @QueryParam("recursive") @ApiParam(value = "get member items recursively") boolean recursive,
|
||||
@QueryParam("fields") @ApiParam(value = "limit output to the given fields (comma separated)") @Nullable String fields) {
|
||||
final Locale locale = localeService.getLocale(language);
|
||||
final Set<String> namespaces = splitAndFilterNamespaces(namespaceSelector, locale);
|
||||
|
||||
@ -276,8 +223,8 @@ public class ItemResource implements RESTResource {
|
||||
@ApiResponse(code = 404, message = "Item not found") })
|
||||
public Response getItemData(final @Context UriInfo uriInfo, final @Context HttpHeaders httpHeaders,
|
||||
@HeaderParam(HttpHeaders.ACCEPT_LANGUAGE) @ApiParam(value = "language") @Nullable String language,
|
||||
@QueryParam("metadata") @ApiParam(value = "metadata selector", required = false) @Nullable String namespaceSelector,
|
||||
@PathParam("itemname") @ApiParam(value = "item name", required = true) String itemname) {
|
||||
@QueryParam("metadata") @ApiParam(value = "metadata selector") @Nullable String namespaceSelector,
|
||||
@PathParam("itemname") @ApiParam(value = "item name") String itemname) {
|
||||
final Locale locale = localeService.getLocale(language);
|
||||
final Set<String> namespaces = splitAndFilterNamespaces(namespaceSelector, locale);
|
||||
|
||||
@ -311,8 +258,7 @@ public class ItemResource implements RESTResource {
|
||||
@ApiOperation(value = "Gets the state of an item.")
|
||||
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = String.class),
|
||||
@ApiResponse(code = 404, message = "Item not found") })
|
||||
public Response getPlainItemState(
|
||||
@PathParam("itemname") @ApiParam(value = "item name", required = true) String itemname) {
|
||||
public Response getPlainItemState(@PathParam("itemname") @ApiParam(value = "item name") String itemname) {
|
||||
// get item
|
||||
Item item = getItem(itemname);
|
||||
|
||||
@ -335,8 +281,8 @@ public class ItemResource implements RESTResource {
|
||||
@ApiResponse(code = 404, message = "Item not found"),
|
||||
@ApiResponse(code = 400, message = "Item state null") })
|
||||
public Response putItemState(
|
||||
@HeaderParam(HttpHeaders.ACCEPT_LANGUAGE) @ApiParam(value = "language") String language,
|
||||
@PathParam("itemname") @ApiParam(value = "item name", required = true) String itemname,
|
||||
@HeaderParam(HttpHeaders.ACCEPT_LANGUAGE) @ApiParam(value = "language") @Nullable String language,
|
||||
@PathParam("itemname") @ApiParam(value = "item name") String itemname,
|
||||
@ApiParam(value = "valid item state (e.g. ON, OFF)", required = true) String value) {
|
||||
final Locale locale = localeService.getLocale(language);
|
||||
|
||||
@ -370,8 +316,7 @@ public class ItemResource implements RESTResource {
|
||||
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK"),
|
||||
@ApiResponse(code = 404, message = "Item not found"),
|
||||
@ApiResponse(code = 400, message = "Item command null") })
|
||||
public Response postItemCommand(
|
||||
@PathParam("itemname") @ApiParam(value = "item name", required = true) String itemname,
|
||||
public Response postItemCommand(@PathParam("itemname") @ApiParam(value = "item name") String itemname,
|
||||
@ApiParam(value = "valid item command (e.g. ON, OFF, UP, DOWN, REFRESH)", required = true) String value) {
|
||||
Item item = getItem(itemname);
|
||||
Command command = null;
|
||||
@ -412,8 +357,8 @@ public class ItemResource implements RESTResource {
|
||||
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK"),
|
||||
@ApiResponse(code = 404, message = "Item or member item not found or item is not of type group item."),
|
||||
@ApiResponse(code = 405, message = "Member item is not editable.") })
|
||||
public Response addMember(@PathParam("itemName") @ApiParam(value = "item name", required = true) String itemName,
|
||||
@PathParam("memberItemName") @ApiParam(value = "member item name", required = true) String memberItemName) {
|
||||
public Response addMember(@PathParam("itemName") @ApiParam(value = "item name") String itemName,
|
||||
@PathParam("memberItemName") @ApiParam(value = "member item name") String memberItemName) {
|
||||
try {
|
||||
Item item = itemRegistry.getItem(itemName);
|
||||
|
||||
@ -450,8 +395,8 @@ public class ItemResource implements RESTResource {
|
||||
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK"),
|
||||
@ApiResponse(code = 404, message = "Item or member item not found or item is not of type group item."),
|
||||
@ApiResponse(code = 405, message = "Member item is not editable.") })
|
||||
public Response removeMember(@PathParam("itemName") @ApiParam(value = "item name", required = true) String itemName,
|
||||
@PathParam("memberItemName") @ApiParam(value = "member item name", required = true) String memberItemName) {
|
||||
public Response removeMember(@PathParam("itemName") @ApiParam(value = "item name") String itemName,
|
||||
@PathParam("memberItemName") @ApiParam(value = "member item name") String memberItemName) {
|
||||
try {
|
||||
Item item = itemRegistry.getItem(itemName);
|
||||
|
||||
@ -487,7 +432,7 @@ public class ItemResource implements RESTResource {
|
||||
@ApiOperation(value = "Removes an item from the registry.")
|
||||
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK"),
|
||||
@ApiResponse(code = 404, message = "Item not found or item is not editable.") })
|
||||
public Response removeItem(@PathParam("itemname") @ApiParam(value = "item name", required = true) String itemname) {
|
||||
public Response removeItem(@PathParam("itemname") @ApiParam(value = "item name") String itemname) {
|
||||
if (managedItemProvider.remove(itemname) == null) {
|
||||
return Response.status(Status.NOT_FOUND).build();
|
||||
}
|
||||
@ -501,8 +446,8 @@ public class ItemResource implements RESTResource {
|
||||
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK"),
|
||||
@ApiResponse(code = 404, message = "Item not found."),
|
||||
@ApiResponse(code = 405, message = "Item not editable.") })
|
||||
public Response addTag(@PathParam("itemname") @ApiParam(value = "item name", required = true) String itemname,
|
||||
@PathParam("tag") @ApiParam(value = "tag", required = true) String tag) {
|
||||
public Response addTag(@PathParam("itemname") @ApiParam(value = "item name") String itemname,
|
||||
@PathParam("tag") @ApiParam(value = "tag") String tag) {
|
||||
Item item = getItem(itemname);
|
||||
|
||||
if (item == null) {
|
||||
@ -526,8 +471,8 @@ public class ItemResource implements RESTResource {
|
||||
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK"),
|
||||
@ApiResponse(code = 404, message = "Item not found."),
|
||||
@ApiResponse(code = 405, message = "Item not editable.") })
|
||||
public Response removeTag(@PathParam("itemname") @ApiParam(value = "item name", required = true) String itemname,
|
||||
@PathParam("tag") @ApiParam(value = "tag", required = true) String tag) {
|
||||
public Response removeTag(@PathParam("itemname") @ApiParam(value = "item name") String itemname,
|
||||
@PathParam("tag") @ApiParam(value = "tag") String tag) {
|
||||
Item item = getItem(itemname);
|
||||
|
||||
if (item == null) {
|
||||
@ -555,8 +500,8 @@ public class ItemResource implements RESTResource {
|
||||
@ApiResponse(code = 400, message = "Metadata value empty."), //
|
||||
@ApiResponse(code = 404, message = "Item not found."), //
|
||||
@ApiResponse(code = 405, message = "Metadata not editable.") })
|
||||
public Response addMetadata(@PathParam("itemname") @ApiParam(value = "item name", required = true) String itemname,
|
||||
@PathParam("namespace") @ApiParam(value = "namespace", required = true) String namespace,
|
||||
public Response addMetadata(@PathParam("itemname") @ApiParam(value = "item name") String itemname,
|
||||
@PathParam("namespace") @ApiParam(value = "namespace") String namespace,
|
||||
@ApiParam(value = "metadata", required = true) MetadataDTO metadata) {
|
||||
Item item = getItem(itemname);
|
||||
|
||||
@ -587,9 +532,8 @@ public class ItemResource implements RESTResource {
|
||||
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK"),
|
||||
@ApiResponse(code = 404, message = "Item not found."),
|
||||
@ApiResponse(code = 405, message = "Meta data not editable.") })
|
||||
public Response removeMetadata(
|
||||
@PathParam("itemname") @ApiParam(value = "item name", required = true) String itemname,
|
||||
@PathParam("namespace") @ApiParam(value = "namespace", required = true) String namespace) {
|
||||
public Response removeMetadata(@PathParam("itemname") @ApiParam(value = "item name") String itemname,
|
||||
@PathParam("namespace") @ApiParam(value = "namespace") String namespace) {
|
||||
Item item = getItem(itemname);
|
||||
|
||||
if (item == null) {
|
||||
@ -625,8 +569,8 @@ public class ItemResource implements RESTResource {
|
||||
@ApiResponse(code = 404, message = "Item not found."),
|
||||
@ApiResponse(code = 405, message = "Item not editable.") })
|
||||
public Response createOrUpdateItem(final @Context UriInfo uriInfo, final @Context HttpHeaders httpHeaders,
|
||||
@HeaderParam(HttpHeaders.ACCEPT_LANGUAGE) @ApiParam(value = "language") String language,
|
||||
@PathParam("itemname") @ApiParam(value = "item name", required = true) String itemname,
|
||||
@HeaderParam(HttpHeaders.ACCEPT_LANGUAGE) @ApiParam(value = "language") @Nullable String language,
|
||||
@PathParam("itemname") @ApiParam(value = "item name") String itemname,
|
||||
@ApiParam(value = "item data", required = true) @Nullable GroupItemDTO item) {
|
||||
final Locale locale = localeService.getLocale(language);
|
||||
|
||||
@ -826,11 +770,4 @@ public class ItemResource implements RESTResource {
|
||||
private boolean isEditable(String itemName) {
|
||||
return managedItemProvider.get(itemName) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSatisfied() {
|
||||
return itemRegistry != null && managedItemProvider != null && eventPublisher != null
|
||||
&& itemBuilderFactory != null && dtoMapper != null && metadataRegistry != null
|
||||
&& metadataSelectorMatcher != null && localeService != null;
|
||||
}
|
||||
}
|
||||
|
@ -24,12 +24,11 @@ import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.QueryParam;
|
||||
import javax.ws.rs.core.Context;
|
||||
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.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.core.auth.Role;
|
||||
import org.openhab.core.config.core.Configuration;
|
||||
@ -42,10 +41,9 @@ import org.openhab.core.thing.link.AbstractLink;
|
||||
import org.openhab.core.thing.link.ItemChannelLink;
|
||||
import org.openhab.core.thing.link.ItemChannelLinkRegistry;
|
||||
import org.openhab.core.thing.link.dto.ItemChannelLinkDTO;
|
||||
import org.osgi.service.component.annotations.Activate;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Reference;
|
||||
import org.osgi.service.component.annotations.ReferenceCardinality;
|
||||
import org.osgi.service.component.annotations.ReferencePolicy;
|
||||
import org.osgi.service.jaxrs.whiteboard.JaxrsWhiteboardConstants;
|
||||
import org.osgi.service.jaxrs.whiteboard.propertytypes.JSONRequired;
|
||||
import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsApplicationSelect;
|
||||
@ -76,15 +74,18 @@ import io.swagger.annotations.ApiResponses;
|
||||
@Path(ItemChannelLinkResource.PATH_LINKS)
|
||||
@RolesAllowed({ Role.ADMIN })
|
||||
@Api(ItemChannelLinkResource.PATH_LINKS)
|
||||
@NonNullByDefault
|
||||
public class ItemChannelLinkResource implements RESTResource {
|
||||
|
||||
/** The URI path to this resource */
|
||||
public static final String PATH_LINKS = "links";
|
||||
|
||||
private ItemChannelLinkRegistry itemChannelLinkRegistry;
|
||||
private final ItemChannelLinkRegistry itemChannelLinkRegistry;
|
||||
|
||||
@Context
|
||||
UriInfo uriInfo;
|
||||
@Activate
|
||||
public ItemChannelLinkResource(final @Reference ItemChannelLinkRegistry itemChannelLinkRegistry) {
|
||||
this.itemChannelLinkRegistry = itemChannelLinkRegistry;
|
||||
}
|
||||
|
||||
@GET
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@ -92,8 +93,8 @@ public class ItemChannelLinkResource implements RESTResource {
|
||||
@ApiResponses(value = {
|
||||
@ApiResponse(code = 200, message = "OK", response = ItemChannelLinkDTO.class, responseContainer = "Collection") })
|
||||
public Response getAll(
|
||||
@QueryParam("channelUID") @ApiParam(value = "filter by channel UID", required = false) @Nullable String channelUID,
|
||||
@QueryParam("itemName") @ApiParam(value = "filter by item name", required = false) @Nullable String itemName) {
|
||||
@QueryParam("channelUID") @ApiParam(value = "filter by channel UID") @Nullable String channelUID,
|
||||
@QueryParam("itemName") @ApiParam(value = "filter by item name") @Nullable String itemName) {
|
||||
Stream<ItemChannelLinkDTO> linkStream = itemChannelLinkRegistry.getAll().stream().map(this::toBeans);
|
||||
|
||||
if (channelUID != null) {
|
||||
@ -134,7 +135,7 @@ public class ItemChannelLinkResource implements RESTResource {
|
||||
@ApiResponse(code = 405, message = "Link is not editable") })
|
||||
public Response link(@PathParam("itemName") @ApiParam(value = "itemName") String itemName,
|
||||
@PathParam("channelUID") @ApiParam(value = "channelUID") String channelUid,
|
||||
@ApiParam(value = "link data", required = false) ItemChannelLinkDTO bean) {
|
||||
@ApiParam(value = "link data") @Nullable ItemChannelLinkDTO bean) {
|
||||
ItemChannelLink link;
|
||||
if (bean == null) {
|
||||
link = new ItemChannelLink(itemName, new ChannelUID(channelUid), new Configuration());
|
||||
@ -182,22 +183,8 @@ public class ItemChannelLinkResource implements RESTResource {
|
||||
}
|
||||
}
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
|
||||
protected void setItemChannelLinkRegistry(ItemChannelLinkRegistry itemChannelLinkRegistry) {
|
||||
this.itemChannelLinkRegistry = itemChannelLinkRegistry;
|
||||
}
|
||||
|
||||
protected void unsetItemChannelLinkRegistry(ItemChannelLinkRegistry itemChannelLinkRegistry) {
|
||||
this.itemChannelLinkRegistry = null;
|
||||
}
|
||||
|
||||
private ItemChannelLinkDTO toBeans(ItemChannelLink link) {
|
||||
return new ItemChannelLinkDTO(link.getItemName(), link.getLinkedUID().toString(),
|
||||
link.getConfiguration().getProperties());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSatisfied() {
|
||||
return itemChannelLinkRegistry != null;
|
||||
}
|
||||
}
|
||||
|
@ -35,6 +35,8 @@ import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.Response.Status;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.core.auth.Role;
|
||||
import org.openhab.core.i18n.TimeZoneProvider;
|
||||
import org.openhab.core.io.rest.JSONResponse;
|
||||
@ -58,10 +60,9 @@ import org.openhab.core.persistence.dto.ItemHistoryDTO;
|
||||
import org.openhab.core.persistence.dto.PersistenceServiceDTO;
|
||||
import org.openhab.core.types.State;
|
||||
import org.openhab.core.types.TypeParser;
|
||||
import org.osgi.service.component.annotations.Activate;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Reference;
|
||||
import org.osgi.service.component.annotations.ReferenceCardinality;
|
||||
import org.osgi.service.component.annotations.ReferencePolicy;
|
||||
import org.osgi.service.jaxrs.whiteboard.JaxrsWhiteboardConstants;
|
||||
import org.osgi.service.jaxrs.whiteboard.propertytypes.JSONRequired;
|
||||
import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsApplicationSelect;
|
||||
@ -94,57 +95,33 @@ import io.swagger.annotations.ApiResponses;
|
||||
@JSONRequired
|
||||
@Path(PersistenceResource.PATH_PERSISTENCE)
|
||||
@Api(PersistenceResource.PATH_PERSISTENCE)
|
||||
@NonNullByDefault
|
||||
public class PersistenceResource implements RESTResource {
|
||||
|
||||
// The URI path to this resource
|
||||
public static final String PATH_PERSISTENCE = "persistence";
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(PersistenceResource.class);
|
||||
|
||||
private static final String MODIFYABLE = "Modifiable";
|
||||
private static final String QUERYABLE = "Queryable";
|
||||
private static final String STANDARD = "Standard";
|
||||
|
||||
// The URI path to this resource
|
||||
public static final String PATH_PERSISTENCE = "persistence";
|
||||
private final ItemRegistry itemRegistry;
|
||||
private final LocaleService localeService;
|
||||
private final PersistenceServiceRegistry persistenceServiceRegistry;
|
||||
private final TimeZoneProvider timeZoneProvider;
|
||||
|
||||
private ItemRegistry itemRegistry;
|
||||
private PersistenceServiceRegistry persistenceServiceRegistry;
|
||||
private TimeZoneProvider timeZoneProvider;
|
||||
|
||||
private LocaleService localeService;
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
|
||||
protected void setPersistenceServiceRegistry(PersistenceServiceRegistry persistenceServiceRegistry) {
|
||||
this.persistenceServiceRegistry = persistenceServiceRegistry;
|
||||
}
|
||||
|
||||
protected void unsetPersistenceServiceRegistry(PersistenceServiceRegistry persistenceServiceRegistry) {
|
||||
this.persistenceServiceRegistry = null;
|
||||
}
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
|
||||
protected void setTimeZoneProvider(TimeZoneProvider timeZoneProvider) {
|
||||
this.timeZoneProvider = timeZoneProvider;
|
||||
}
|
||||
|
||||
protected void unsetTimeZoneProvider(TimeZoneProvider timeZoneProvider) {
|
||||
this.timeZoneProvider = null;
|
||||
}
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
|
||||
protected void setItemRegistry(ItemRegistry itemRegistry) {
|
||||
@Activate
|
||||
public PersistenceResource( //
|
||||
final @Reference ItemRegistry itemRegistry, //
|
||||
final @Reference LocaleService localeService,
|
||||
final @Reference PersistenceServiceRegistry persistenceServiceRegistry,
|
||||
final @Reference TimeZoneProvider timeZoneProvider) {
|
||||
this.itemRegistry = itemRegistry;
|
||||
}
|
||||
|
||||
protected void unsetItemRegistry(ItemRegistry itemRegistry) {
|
||||
this.itemRegistry = null;
|
||||
}
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
|
||||
protected void setLocaleService(LocaleService localeService) {
|
||||
this.localeService = localeService;
|
||||
}
|
||||
|
||||
protected void unsetLocaleService(LocaleService localeService) {
|
||||
this.localeService = null;
|
||||
this.persistenceServiceRegistry = persistenceServiceRegistry;
|
||||
this.timeZoneProvider = timeZoneProvider;
|
||||
}
|
||||
|
||||
@GET
|
||||
@ -153,7 +130,7 @@ public class PersistenceResource implements RESTResource {
|
||||
@ApiOperation(value = "Gets a list of persistence services.", response = String.class, responseContainer = "List")
|
||||
@ApiResponses(value = @ApiResponse(code = 200, message = "OK", response = String.class, responseContainer = "List"))
|
||||
public Response httpGetPersistenceServices(@Context HttpHeaders headers,
|
||||
@HeaderParam(HttpHeaders.ACCEPT_LANGUAGE) @ApiParam(value = HttpHeaders.ACCEPT_LANGUAGE) String language) {
|
||||
@HeaderParam(HttpHeaders.ACCEPT_LANGUAGE) @ApiParam(value = "language") @Nullable String language) {
|
||||
Locale locale = localeService.getLocale(language);
|
||||
|
||||
Object responseObject = getPersistenceServiceList(locale);
|
||||
@ -167,7 +144,7 @@ public class PersistenceResource implements RESTResource {
|
||||
@ApiOperation(value = "Gets a list of items available via a specific persistence service.", response = String.class, responseContainer = "List")
|
||||
@ApiResponses(value = @ApiResponse(code = 200, message = "OK", response = String.class, responseContainer = "List"))
|
||||
public Response httpGetPersistenceServiceItems(@Context HttpHeaders headers,
|
||||
@ApiParam(value = "Id of the persistence service. If not provided the default service will be used", required = false) @QueryParam("serviceId") String serviceId) {
|
||||
@ApiParam(value = "Id of the persistence service. If not provided the default service will be used") @QueryParam("serviceId") @Nullable String serviceId) {
|
||||
return getServiceItemList(serviceId);
|
||||
}
|
||||
|
||||
@ -179,17 +156,16 @@ public class PersistenceResource implements RESTResource {
|
||||
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = ItemHistoryDTO.class),
|
||||
@ApiResponse(code = 404, message = "Unknown Item or persistence service") })
|
||||
public Response httpGetPersistenceItemData(@Context HttpHeaders headers,
|
||||
@ApiParam(value = "Id of the persistence service. If not provided the default service will be used", required = false) @QueryParam("serviceId") String serviceId,
|
||||
@ApiParam(value = "The item name", required = true) @PathParam("itemname") String itemName,
|
||||
@ApiParam(value = "Id of the persistence service. If not provided the default service will be used") @QueryParam("serviceId") @Nullable String serviceId,
|
||||
@ApiParam(value = "The item name") @PathParam("itemname") String itemName,
|
||||
@ApiParam(value = "Start time of the data to return. Will default to 1 day before endtime. ["
|
||||
+ DateTimeType.DATE_PATTERN_WITH_TZ_AND_MS
|
||||
+ "]", required = false) @QueryParam("starttime") String startTime,
|
||||
+ "]") @QueryParam("starttime") @Nullable String startTime,
|
||||
@ApiParam(value = "End time of the data to return. Will default to current time. ["
|
||||
+ DateTimeType.DATE_PATTERN_WITH_TZ_AND_MS
|
||||
+ "]", required = false) @QueryParam("endtime") String endTime,
|
||||
@ApiParam(value = "Page number of data to return. This parameter will enable paging.", required = false) @QueryParam("page") int pageNumber,
|
||||
@ApiParam(value = "The length of each page.", required = false) @QueryParam("pagelength") int pageLength,
|
||||
@ApiParam(value = "Gets one value before and after the requested period.", required = false) @QueryParam("boundary") boolean boundary) {
|
||||
+ DateTimeType.DATE_PATTERN_WITH_TZ_AND_MS + "]") @QueryParam("endtime") @Nullable String endTime,
|
||||
@ApiParam(value = "Page number of data to return. This parameter will enable paging.") @QueryParam("page") int pageNumber,
|
||||
@ApiParam(value = "The length of each page.") @QueryParam("pagelength") int pageLength,
|
||||
@ApiParam(value = "Gets one value before and after the requested period.") @QueryParam("boundary") boolean boundary) {
|
||||
return getItemHistoryDTO(serviceId, itemName, startTime, endTime, pageNumber, pageLength, boundary);
|
||||
}
|
||||
|
||||
@ -204,7 +180,7 @@ public class PersistenceResource implements RESTResource {
|
||||
@ApiResponse(code = 404, message = "Unknown persistence service") })
|
||||
public Response httpDeletePersistenceServiceItem(@Context HttpHeaders headers,
|
||||
@ApiParam(value = "Id of the persistence service.", required = true) @QueryParam("serviceId") String serviceId,
|
||||
@ApiParam(value = "The item name.", required = true) @PathParam("itemname") String itemName,
|
||||
@ApiParam(value = "The item name.") @PathParam("itemname") String itemName,
|
||||
@ApiParam(value = "Start time of the data to return. [" + DateTimeType.DATE_PATTERN_WITH_TZ_AND_MS
|
||||
+ "]", required = true) @QueryParam("starttime") String startTime,
|
||||
@ApiParam(value = "End time of the data to return. [" + DateTimeType.DATE_PATTERN_WITH_TZ_AND_MS
|
||||
@ -220,8 +196,8 @@ public class PersistenceResource implements RESTResource {
|
||||
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = ItemHistoryDTO.class),
|
||||
@ApiResponse(code = 404, message = "Unknown Item or persistence service") })
|
||||
public Response httpPutPersistenceItemData(@Context HttpHeaders headers,
|
||||
@ApiParam(value = "Id of the persistence service. If not provided the default service will be used", required = false) @QueryParam("serviceId") String serviceId,
|
||||
@ApiParam(value = "The item name.", required = true) @PathParam("itemname") String itemName,
|
||||
@ApiParam(value = "Id of the persistence service. If not provided the default service will be used") @QueryParam("serviceId") @Nullable String serviceId,
|
||||
@ApiParam(value = "The item name.") @PathParam("itemname") String itemName,
|
||||
@ApiParam(value = "Time of the data to be stored. Will default to current time. ["
|
||||
+ DateTimeType.DATE_PATTERN_WITH_TZ_AND_MS + "]", required = true) @QueryParam("time") String time,
|
||||
@ApiParam(value = "The state to store.", required = true) @QueryParam("state") String value) {
|
||||
@ -233,22 +209,26 @@ public class PersistenceResource implements RESTResource {
|
||||
return dateTime.getZonedDateTime();
|
||||
}
|
||||
|
||||
private Response getItemHistoryDTO(String serviceId, String itemName, String timeBegin, String timeEnd,
|
||||
int pageNumber, int pageLength, boolean boundary) {
|
||||
private Response getItemHistoryDTO(@Nullable String serviceId, String itemName, @Nullable String timeBegin,
|
||||
@Nullable String timeEnd, int pageNumber, int pageLength, boolean boundary) {
|
||||
// Benchmarking timer...
|
||||
long timerStart = System.currentTimeMillis();
|
||||
|
||||
@Nullable
|
||||
ItemHistoryDTO dto = createDTO(serviceId, itemName, timeBegin, timeEnd, pageNumber, pageLength, boundary);
|
||||
|
||||
if (dto == null) {
|
||||
JSONResponse.createErrorResponse(Status.BAD_REQUEST, "Persistence service not queryable: " + serviceId);
|
||||
return JSONResponse.createErrorResponse(Status.BAD_REQUEST,
|
||||
"Persistence service not queryable: " + serviceId);
|
||||
}
|
||||
|
||||
logger.debug("Persistence returned {} rows in {}ms", dto.datapoints, System.currentTimeMillis() - timerStart);
|
||||
|
||||
return JSONResponse.createResponse(Status.OK, dto, "");
|
||||
}
|
||||
|
||||
protected ItemHistoryDTO createDTO(String serviceId, String itemName, String timeBegin, String timeEnd,
|
||||
int pageNumber, int pageLength, boolean boundary) {
|
||||
protected @Nullable ItemHistoryDTO createDTO(@Nullable String serviceId, String itemName,
|
||||
@Nullable String timeBegin, @Nullable String timeEnd, int pageNumber, int pageLength, boolean boundary) {
|
||||
// If serviceId is null, then use the default service
|
||||
PersistenceService service = null;
|
||||
String effectiveServiceId = serviceId != null ? serviceId : persistenceServiceRegistry.getDefaultId();
|
||||
@ -315,7 +295,7 @@ public class PersistenceResource implements RESTResource {
|
||||
filter.setPageSize(1);
|
||||
filter.setOrdering(Ordering.DESCENDING);
|
||||
result = qService.query(filter);
|
||||
if (result != null && result.iterator().hasNext()) {
|
||||
if (result.iterator().hasNext()) {
|
||||
dto.addData(dateTimeBegin.toInstant().toEpochMilli(), result.iterator().next().getState());
|
||||
quantity++;
|
||||
}
|
||||
@ -334,7 +314,6 @@ public class PersistenceResource implements RESTResource {
|
||||
filter.setOrdering(Ordering.ASCENDING);
|
||||
|
||||
result = qService.query(filter);
|
||||
if (result != null) {
|
||||
Iterator<HistoricItem> it = result.iterator();
|
||||
|
||||
// Iterate through the data
|
||||
@ -356,7 +335,6 @@ public class PersistenceResource implements RESTResource {
|
||||
quantity++;
|
||||
lastItem = historicItem;
|
||||
}
|
||||
}
|
||||
|
||||
if (boundary) {
|
||||
// Get the value after the end time.
|
||||
@ -364,7 +342,7 @@ public class PersistenceResource implements RESTResource {
|
||||
filter.setPageSize(1);
|
||||
filter.setOrdering(Ordering.ASCENDING);
|
||||
result = qService.query(filter);
|
||||
if (result != null && result.iterator().hasNext()) {
|
||||
if (result.iterator().hasNext()) {
|
||||
dto.addData(dateTimeEnd.toInstant().toEpochMilli(), result.iterator().next().getState());
|
||||
quantity++;
|
||||
}
|
||||
@ -401,7 +379,7 @@ public class PersistenceResource implements RESTResource {
|
||||
return dtoList;
|
||||
}
|
||||
|
||||
private Response getServiceItemList(String serviceId) {
|
||||
private Response getServiceItemList(@Nullable String serviceId) {
|
||||
// If serviceId is null, then use the default service
|
||||
PersistenceService service = null;
|
||||
if (serviceId == null) {
|
||||
@ -426,7 +404,8 @@ public class PersistenceResource implements RESTResource {
|
||||
return JSONResponse.createResponse(Status.OK, qService.getItemInfo(), "");
|
||||
}
|
||||
|
||||
private Response deletePersistenceItemData(String serviceId, String itemName, String timeBegin, String timeEnd) {
|
||||
private Response deletePersistenceItemData(@Nullable String serviceId, String itemName, @Nullable String timeBegin,
|
||||
@Nullable String timeEnd) {
|
||||
// For deleting, we must specify a service id - don't use the default service
|
||||
if (serviceId == null || serviceId.length() == 0) {
|
||||
logger.debug("Persistence service must be specified for delete operations.");
|
||||
@ -448,7 +427,7 @@ public class PersistenceResource implements RESTResource {
|
||||
|
||||
ModifiablePersistenceService mService = (ModifiablePersistenceService) service;
|
||||
|
||||
if (timeBegin == null | timeEnd == null) {
|
||||
if (timeBegin == null || timeEnd == null) {
|
||||
return JSONResponse.createErrorResponse(Status.BAD_REQUEST, "The start and end time must be set");
|
||||
}
|
||||
|
||||
@ -476,11 +455,10 @@ public class PersistenceResource implements RESTResource {
|
||||
return Response.status(Status.OK).build();
|
||||
}
|
||||
|
||||
private Response putItemState(String serviceId, String itemName, String value, String time) {
|
||||
private Response putItemState(@Nullable String serviceId, String itemName, String value, @Nullable String time) {
|
||||
// If serviceId is null, then use the default service
|
||||
PersistenceService service = null;
|
||||
String effectiveServiceId = serviceId != null ? serviceId : persistenceServiceRegistry.getDefaultId();
|
||||
service = persistenceServiceRegistry.get(effectiveServiceId);
|
||||
PersistenceService service = persistenceServiceRegistry.get(effectiveServiceId);
|
||||
|
||||
if (service == null) {
|
||||
logger.warn("Persistence service not found '{}'.", effectiveServiceId);
|
||||
@ -490,10 +468,6 @@ public class PersistenceResource implements RESTResource {
|
||||
|
||||
Item item;
|
||||
try {
|
||||
if (itemRegistry == null) {
|
||||
logger.warn("Item registry not set.");
|
||||
return JSONResponse.createErrorResponse(Status.CONFLICT, "Item registry not set.");
|
||||
}
|
||||
item = itemRegistry.getItem(itemName);
|
||||
} catch (ItemNotFoundException e) {
|
||||
logger.warn("Item not found '{}'.", itemName);
|
||||
@ -528,10 +502,4 @@ public class PersistenceResource implements RESTResource {
|
||||
mService.store(item, Date.from(dateTime.toInstant()), state);
|
||||
return Response.status(Status.OK).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSatisfied() {
|
||||
return itemRegistry != null && persistenceServiceRegistry != null && timeZoneProvider != null
|
||||
&& localeService != null;
|
||||
}
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ import javax.ws.rs.core.HttpHeaders;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.core.auth.Role;
|
||||
import org.openhab.core.io.rest.LocaleService;
|
||||
@ -43,17 +44,14 @@ import org.openhab.core.thing.profiles.dto.ProfileTypeDTOMapper;
|
||||
import org.openhab.core.thing.type.ChannelType;
|
||||
import org.openhab.core.thing.type.ChannelTypeRegistry;
|
||||
import org.openhab.core.thing.type.ChannelTypeUID;
|
||||
import org.osgi.service.component.annotations.Activate;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Reference;
|
||||
import org.osgi.service.component.annotations.ReferenceCardinality;
|
||||
import org.osgi.service.component.annotations.ReferencePolicy;
|
||||
import org.osgi.service.jaxrs.whiteboard.JaxrsWhiteboardConstants;
|
||||
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 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;
|
||||
@ -75,16 +73,25 @@ import io.swagger.annotations.ApiResponses;
|
||||
@Path(ProfileTypeResource.PATH_PROFILE_TYPES)
|
||||
@RolesAllowed({ Role.ADMIN })
|
||||
@Api(ProfileTypeResource.PATH_PROFILE_TYPES)
|
||||
@NonNullByDefault
|
||||
public class ProfileTypeResource implements RESTResource {
|
||||
|
||||
/** The URI path to this resource */
|
||||
public static final String PATH_PROFILE_TYPES = "profile-types";
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(ProfileTypeResource.class);
|
||||
private final ChannelTypeRegistry channelTypeRegistry;
|
||||
private final LocaleService localeService;
|
||||
private final ProfileTypeRegistry profileTypeRegistry;
|
||||
|
||||
private ProfileTypeRegistry profileTypeRegistry;
|
||||
private ChannelTypeRegistry channelTypeRegistry;
|
||||
private LocaleService localeService;
|
||||
@Activate
|
||||
public ProfileTypeResource( //
|
||||
final @Reference ChannelTypeRegistry channelTypeRegistry, //
|
||||
final @Reference LocaleService localeService, //
|
||||
final @Reference ProfileTypeRegistry profileTypeRegistry) {
|
||||
this.channelTypeRegistry = channelTypeRegistry;
|
||||
this.localeService = localeService;
|
||||
this.profileTypeRegistry = profileTypeRegistry;
|
||||
}
|
||||
|
||||
@GET
|
||||
@RolesAllowed({ Role.USER })
|
||||
@ -92,19 +99,20 @@ public class ProfileTypeResource implements RESTResource {
|
||||
@ApiOperation(value = "Gets all available profile types.", response = ProfileTypeDTO.class, responseContainer = "Set")
|
||||
@ApiResponses(value = @ApiResponse(code = 200, message = "OK", response = ProfileTypeDTO.class, responseContainer = "Set"))
|
||||
public Response getAll(
|
||||
@HeaderParam(HttpHeaders.ACCEPT_LANGUAGE) @ApiParam(value = HttpHeaders.ACCEPT_LANGUAGE) String language,
|
||||
@QueryParam("channelTypeUID") @ApiParam(value = "channel type filter", required = false) @Nullable String channelTypeUID,
|
||||
@QueryParam("itemType") @ApiParam(value = "item type filter", required = false) @Nullable String itemType) {
|
||||
@HeaderParam(HttpHeaders.ACCEPT_LANGUAGE) @ApiParam(value = "language") @Nullable String language,
|
||||
@QueryParam("channelTypeUID") @ApiParam(value = "channel type filter") @Nullable String channelTypeUID,
|
||||
@QueryParam("itemType") @ApiParam(value = "item type filter") @Nullable String itemType) {
|
||||
Locale locale = localeService.getLocale(language);
|
||||
return Response.ok(new Stream2JSONInputStream(getProfileTypes(locale, channelTypeUID, itemType))).build();
|
||||
}
|
||||
|
||||
protected Stream<ProfileTypeDTO> getProfileTypes(Locale locale, String channelTypeUID, String itemType) {
|
||||
protected Stream<ProfileTypeDTO> getProfileTypes(@Nullable Locale locale, @Nullable String channelTypeUID,
|
||||
@Nullable String itemType) {
|
||||
return profileTypeRegistry.getProfileTypes(locale).stream().filter(matchesChannelUID(channelTypeUID, locale))
|
||||
.filter(matchesItemType(itemType)).map(t -> convertToProfileTypeDTO(t, locale));
|
||||
.filter(matchesItemType(itemType)).map(profileType -> ProfileTypeDTOMapper.map(profileType));
|
||||
}
|
||||
|
||||
private Predicate<ProfileType> matchesChannelUID(String channelTypeUID, Locale locale) {
|
||||
private Predicate<ProfileType> matchesChannelUID(@Nullable String channelTypeUID, @Nullable Locale locale) {
|
||||
if (channelTypeUID == null) {
|
||||
return t -> true;
|
||||
}
|
||||
@ -122,7 +130,7 @@ public class ProfileTypeResource implements RESTResource {
|
||||
return t -> false;
|
||||
}
|
||||
|
||||
private Predicate<ProfileType> matchesItemType(String itemType) {
|
||||
private Predicate<ProfileType> matchesItemType(@Nullable String itemType) {
|
||||
if (itemType == null) {
|
||||
return t -> true;
|
||||
}
|
||||
@ -171,47 +179,4 @@ public class ProfileTypeResource implements RESTResource {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private ProfileTypeDTO convertToProfileTypeDTO(ProfileType profileType, Locale locale) {
|
||||
final ProfileTypeDTO profileTypeDTO = ProfileTypeDTOMapper.map(profileType);
|
||||
if (profileTypeDTO != null) {
|
||||
return profileTypeDTO;
|
||||
} else {
|
||||
logger.warn("Cannot create DTO for profileType '{}'. Skipping it.", profileTypeDTO);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSatisfied() {
|
||||
return (this.profileTypeRegistry != null && channelTypeRegistry != null);
|
||||
}
|
||||
|
||||
@Reference
|
||||
protected void setLocaleService(LocaleService localeService) {
|
||||
this.localeService = localeService;
|
||||
}
|
||||
|
||||
protected void unsetLocaleService(LocaleService localeService) {
|
||||
this.localeService = null;
|
||||
}
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
|
||||
protected void setProfileTypeRegistry(ProfileTypeRegistry registry) {
|
||||
this.profileTypeRegistry = registry;
|
||||
}
|
||||
|
||||
protected void unsetProfileTypeRegistry(ProfileTypeRegistry registry) {
|
||||
this.profileTypeRegistry = null;
|
||||
}
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
|
||||
protected void setChannelTypeRegistry(ChannelTypeRegistry registry) {
|
||||
this.channelTypeRegistry = registry;
|
||||
}
|
||||
|
||||
protected void unsetChannelTypeRegistry(ChannelTypeRegistry registry) {
|
||||
this.channelTypeRegistry = null;
|
||||
}
|
||||
}
|
||||
|
@ -35,6 +35,8 @@ import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.Response.Status;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.core.auth.Role;
|
||||
import org.openhab.core.config.core.ConfigConstants;
|
||||
import org.openhab.core.config.core.ConfigDescription;
|
||||
@ -55,8 +57,6 @@ import org.osgi.service.component.ComponentConstants;
|
||||
import org.osgi.service.component.annotations.Activate;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Reference;
|
||||
import org.osgi.service.component.annotations.ReferenceCardinality;
|
||||
import org.osgi.service.component.annotations.ReferencePolicy;
|
||||
import org.osgi.service.jaxrs.whiteboard.JaxrsWhiteboardConstants;
|
||||
import org.osgi.service.jaxrs.whiteboard.propertytypes.JSONRequired;
|
||||
import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsApplicationSelect;
|
||||
@ -87,6 +87,7 @@ import io.swagger.annotations.ApiResponses;
|
||||
@Path(ConfigurableServiceResource.PATH_SERVICES)
|
||||
@RolesAllowed({ Role.ADMIN })
|
||||
@Api(ConfigurableServiceResource.PATH_SERVICES)
|
||||
@NonNullByDefault
|
||||
public class ConfigurableServiceResource implements RESTResource {
|
||||
|
||||
/** The URI path to this resource */
|
||||
@ -104,13 +105,17 @@ public class ConfigurableServiceResource implements RESTResource {
|
||||
private final Logger logger = LoggerFactory.getLogger(ConfigurableServiceResource.class);
|
||||
|
||||
private final BundleContext bundleContext;
|
||||
|
||||
private ConfigurationService configurationService;
|
||||
private ConfigDescriptionRegistry configDescRegistry;
|
||||
private final ConfigDescriptionRegistry configDescRegistry;
|
||||
private final ConfigurationService configurationService;
|
||||
|
||||
@Activate
|
||||
public ConfigurableServiceResource(final BundleContext bundleContext) {
|
||||
public ConfigurableServiceResource( //
|
||||
final BundleContext bundleContext, //
|
||||
final @Reference ConfigurationService configurationService,
|
||||
final @Reference ConfigDescriptionRegistry configDescRegistry) {
|
||||
this.bundleContext = bundleContext;
|
||||
this.configDescRegistry = configDescRegistry;
|
||||
this.configurationService = configurationService;
|
||||
}
|
||||
|
||||
@GET
|
||||
@ -129,7 +134,7 @@ public class ConfigurableServiceResource implements RESTResource {
|
||||
@ApiOperation(value = "Get configurable service for given service ID.")
|
||||
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = ConfigurableServiceDTO.class),
|
||||
@ApiResponse(code = 404, message = "Not found") })
|
||||
public Response getById(@PathParam("serviceId") @ApiParam(value = "service ID", required = true) String serviceId) {
|
||||
public Response getById(@PathParam("serviceId") @ApiParam(value = "service ID") String serviceId) {
|
||||
ConfigurableServiceDTO configurableService = getServiceById(serviceId);
|
||||
if (configurableService != null) {
|
||||
return Response.ok(configurableService).build();
|
||||
@ -138,7 +143,7 @@ public class ConfigurableServiceResource implements RESTResource {
|
||||
}
|
||||
}
|
||||
|
||||
private ConfigurableServiceDTO getServiceById(String serviceId) {
|
||||
private @Nullable ConfigurableServiceDTO getServiceById(String serviceId) {
|
||||
ConfigurableServiceDTO multiService = getMultiConfigServiceById(serviceId);
|
||||
if (multiService != null) {
|
||||
return multiService;
|
||||
@ -153,7 +158,7 @@ public class ConfigurableServiceResource implements RESTResource {
|
||||
return null;
|
||||
}
|
||||
|
||||
private ConfigurableServiceDTO getMultiConfigServiceById(String serviceId) {
|
||||
private @Nullable ConfigurableServiceDTO getMultiConfigServiceById(String serviceId) {
|
||||
String filter = "(&(" + Constants.SERVICE_PID + "=" + serviceId + ")(" + ConfigurationAdmin.SERVICE_FACTORYPID
|
||||
+ "=*))";
|
||||
List<ConfigurableServiceDTO> services = getServicesByFilter(filter);
|
||||
@ -170,7 +175,7 @@ public class ConfigurableServiceResource implements RESTResource {
|
||||
@ApiResponses(value = {
|
||||
@ApiResponse(code = 200, message = "OK", response = ConfigurableServiceDTO.class, responseContainer = "List") })
|
||||
public List<ConfigurableServiceDTO> getMultiConfigServicesByFactoryPid(
|
||||
@PathParam("serviceId") @ApiParam(value = "service ID", required = true) String serviceId) {
|
||||
@PathParam("serviceId") @ApiParam(value = "service ID") String serviceId) {
|
||||
List<ConfigurableServiceDTO> services = collectServicesById(serviceId);
|
||||
return services;
|
||||
}
|
||||
@ -186,8 +191,7 @@ public class ConfigurableServiceResource implements RESTResource {
|
||||
@ApiOperation(value = "Get service configuration for given service ID.")
|
||||
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = String.class),
|
||||
@ApiResponse(code = 500, message = "Configuration can not be read due to internal error") })
|
||||
public Response getConfiguration(
|
||||
@PathParam("serviceId") @ApiParam(value = "service ID", required = true) String serviceId) {
|
||||
public Response getConfiguration(@PathParam("serviceId") @ApiParam(value = "service ID") String serviceId) {
|
||||
try {
|
||||
Configuration configuration = configurationService.get(serviceId);
|
||||
return configuration != null ? Response.ok(configuration.getProperties()).build()
|
||||
@ -206,9 +210,8 @@ public class ConfigurableServiceResource implements RESTResource {
|
||||
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = String.class),
|
||||
@ApiResponse(code = 204, message = "No old configuration"),
|
||||
@ApiResponse(code = 500, message = "Configuration can not be updated due to internal error") })
|
||||
public Response updateConfiguration(
|
||||
@PathParam("serviceId") @ApiParam(value = "service ID", required = true) String serviceId,
|
||||
Map<String, Object> configuration) {
|
||||
public Response updateConfiguration(@PathParam("serviceId") @ApiParam(value = "service ID") String serviceId,
|
||||
@Nullable Map<String, Object> configuration) {
|
||||
try {
|
||||
Configuration oldConfiguration = configurationService.get(serviceId);
|
||||
configurationService.update(serviceId, new Configuration(normalizeConfiguration(configuration, serviceId)));
|
||||
@ -220,7 +223,8 @@ public class ConfigurableServiceResource implements RESTResource {
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, Object> normalizeConfiguration(Map<String, Object> properties, String serviceId) {
|
||||
private @Nullable Map<String, Object> normalizeConfiguration(@Nullable Map<String, Object> properties,
|
||||
String serviceId) {
|
||||
if (properties == null || properties.isEmpty()) {
|
||||
return properties;
|
||||
}
|
||||
@ -253,8 +257,7 @@ public class ConfigurableServiceResource implements RESTResource {
|
||||
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = String.class),
|
||||
@ApiResponse(code = 204, message = "No old configuration"),
|
||||
@ApiResponse(code = 500, message = "Configuration can not be deleted due to internal error") })
|
||||
public Response deleteConfiguration(
|
||||
@PathParam("serviceId") @ApiParam(value = "service ID", required = true) String serviceId) {
|
||||
public Response deleteConfiguration(@PathParam("serviceId") @ApiParam(value = "service ID") String serviceId) {
|
||||
try {
|
||||
Configuration oldConfiguration = configurationService.get(serviceId);
|
||||
configurationService.delete(serviceId);
|
||||
@ -300,7 +303,7 @@ public class ConfigurableServiceResource implements RESTResource {
|
||||
return services;
|
||||
}
|
||||
|
||||
private String getConfigDescriptionByFactoryPid(String factoryPid) {
|
||||
private @Nullable String getConfigDescriptionByFactoryPid(String factoryPid) {
|
||||
String configDescriptionURI = null;
|
||||
|
||||
String filter = "(" + Constants.SERVICE_PID + "=" + factoryPid + ")";
|
||||
@ -379,27 +382,4 @@ public class ConfigurableServiceResource implements RESTResource {
|
||||
return first;
|
||||
}
|
||||
}
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
|
||||
protected void setConfigurationService(ConfigurationService configurationService) {
|
||||
this.configurationService = configurationService;
|
||||
}
|
||||
|
||||
protected void unsetConfigurationService(ConfigurationService configurationService) {
|
||||
this.configurationService = null;
|
||||
}
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
|
||||
protected void setConfigDescriptionRegistry(ConfigDescriptionRegistry configDescriptionRegistry) {
|
||||
this.configDescRegistry = configDescriptionRegistry;
|
||||
}
|
||||
|
||||
protected void unsetConfigDescriptionRegistry(ConfigDescriptionRegistry configDescriptionRegistry) {
|
||||
this.configDescRegistry = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSatisfied() {
|
||||
return configurationService != null && configDescRegistry != null;
|
||||
}
|
||||
}
|
||||
|
@ -46,6 +46,8 @@ import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.Response.Status;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.core.auth.Role;
|
||||
import org.openhab.core.config.core.ConfigDescription;
|
||||
import org.openhab.core.config.core.ConfigDescriptionRegistry;
|
||||
@ -94,10 +96,9 @@ import org.openhab.core.thing.type.ChannelTypeUID;
|
||||
import org.openhab.core.thing.type.ThingType;
|
||||
import org.openhab.core.thing.type.ThingTypeRegistry;
|
||||
import org.openhab.core.thing.util.ThingHelper;
|
||||
import org.osgi.service.component.annotations.Activate;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Reference;
|
||||
import org.osgi.service.component.annotations.ReferenceCardinality;
|
||||
import org.osgi.service.component.annotations.ReferencePolicy;
|
||||
import org.osgi.service.jaxrs.whiteboard.JaxrsWhiteboardConstants;
|
||||
import org.osgi.service.jaxrs.whiteboard.propertytypes.JSONRequired;
|
||||
import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsApplicationSelect;
|
||||
@ -136,6 +137,7 @@ import io.swagger.annotations.ApiResponses;
|
||||
@JSONRequired
|
||||
@Path(ThingResource.PATH_THINGS)
|
||||
@Api(ThingResource.PATH_THINGS)
|
||||
@NonNullByDefault
|
||||
public class ThingResource implements RESTResource {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(ThingResource.class);
|
||||
@ -143,34 +145,59 @@ public class ThingResource implements RESTResource {
|
||||
/** The URI path to this resource */
|
||||
public static final String PATH_THINGS = "things";
|
||||
|
||||
private ItemChannelLinkRegistry itemChannelLinkRegistry;
|
||||
private ItemFactory itemFactory;
|
||||
private ItemRegistry itemRegistry;
|
||||
private ManagedItemChannelLinkProvider managedItemChannelLinkProvider;
|
||||
private ManagedItemProvider managedItemProvider;
|
||||
private ManagedThingProvider managedThingProvider;
|
||||
private ThingRegistry thingRegistry;
|
||||
private ConfigStatusService configStatusService;
|
||||
private ConfigDescriptionRegistry configDescRegistry;
|
||||
private ThingTypeRegistry thingTypeRegistry;
|
||||
private ChannelTypeRegistry channelTypeRegistry;
|
||||
private ThingStatusInfoI18nLocalizationService thingStatusInfoI18nLocalizationService;
|
||||
private FirmwareUpdateService firmwareUpdateService;
|
||||
private FirmwareRegistry firmwareRegistry;
|
||||
private ThingManager thingManager;
|
||||
private final ChannelTypeRegistry channelTypeRegistry;
|
||||
private final ConfigStatusService configStatusService;
|
||||
private final ConfigDescriptionRegistry configDescRegistry;
|
||||
private final FirmwareRegistry firmwareRegistry;
|
||||
private final FirmwareUpdateService firmwareUpdateService;
|
||||
private final ItemChannelLinkRegistry itemChannelLinkRegistry;
|
||||
private final ItemFactory itemFactory;
|
||||
private final ItemRegistry itemRegistry;
|
||||
private final LocaleService localeService;
|
||||
private final ManagedItemChannelLinkProvider managedItemChannelLinkProvider;
|
||||
private final ManagedItemProvider managedItemProvider;
|
||||
private final ManagedThingProvider managedThingProvider;
|
||||
private final ThingManager thingManager;
|
||||
private final ThingRegistry thingRegistry;
|
||||
private final ThingStatusInfoI18nLocalizationService thingStatusInfoI18nLocalizationService;
|
||||
private final ThingTypeRegistry thingTypeRegistry;
|
||||
|
||||
private LocaleService localeService;
|
||||
private @Context @NonNullByDefault({}) UriInfo uriInfo;
|
||||
|
||||
@Context
|
||||
private UriInfo uriInfo;
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
|
||||
protected void setLocaleService(LocaleService localeService) {
|
||||
@Activate
|
||||
public ThingResource( //
|
||||
final @Reference ChannelTypeRegistry channelTypeRegistry,
|
||||
final @Reference ConfigStatusService configStatusService,
|
||||
final @Reference ConfigDescriptionRegistry configDescRegistry,
|
||||
final @Reference FirmwareRegistry firmwareRegistry,
|
||||
final @Reference FirmwareUpdateService firmwareUpdateService,
|
||||
final @Reference ItemChannelLinkRegistry itemChannelLinkRegistry, //
|
||||
final @Reference ItemFactory itemFactory, //
|
||||
final @Reference ItemRegistry itemRegistry, //
|
||||
final @Reference LocaleService localeService,
|
||||
final @Reference ManagedItemChannelLinkProvider managedItemChannelLinkProvider,
|
||||
final @Reference ManagedItemProvider managedItemProvider,
|
||||
final @Reference ManagedThingProvider managedThingProvider, //
|
||||
final @Reference ThingManager thingManager, //
|
||||
final @Reference ThingRegistry thingRegistry,
|
||||
final @Reference ThingStatusInfoI18nLocalizationService thingStatusInfoI18nLocalizationService,
|
||||
final @Reference ThingTypeRegistry thingTypeRegistry) {
|
||||
this.channelTypeRegistry = channelTypeRegistry;
|
||||
this.configStatusService = configStatusService;
|
||||
this.configDescRegistry = configDescRegistry;
|
||||
this.firmwareRegistry = firmwareRegistry;
|
||||
this.firmwareUpdateService = firmwareUpdateService;
|
||||
this.itemChannelLinkRegistry = itemChannelLinkRegistry;
|
||||
this.itemFactory = itemFactory;
|
||||
this.itemRegistry = itemRegistry;
|
||||
this.localeService = localeService;
|
||||
}
|
||||
|
||||
protected void unsetLocaleService(LocaleService localeService) {
|
||||
this.localeService = null;
|
||||
this.managedItemChannelLinkProvider = managedItemChannelLinkProvider;
|
||||
this.managedItemProvider = managedItemProvider;
|
||||
this.managedThingProvider = managedThingProvider;
|
||||
this.thingManager = thingManager;
|
||||
this.thingRegistry = thingRegistry;
|
||||
this.thingStatusInfoI18nLocalizationService = thingStatusInfoI18nLocalizationService;
|
||||
this.thingTypeRegistry = thingTypeRegistry;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -186,7 +213,8 @@ public class ThingResource implements RESTResource {
|
||||
@ApiResponses(value = { @ApiResponse(code = 201, message = "Created", response = String.class),
|
||||
@ApiResponse(code = 400, message = "A uid must be provided, if no binding can create a thing of this type."),
|
||||
@ApiResponse(code = 409, message = "A thing with the same uid already exists.") })
|
||||
public Response create(@HeaderParam(HttpHeaders.ACCEPT_LANGUAGE) @ApiParam(value = "language") String language,
|
||||
public Response create(
|
||||
@HeaderParam(HttpHeaders.ACCEPT_LANGUAGE) @ApiParam(value = "language") @Nullable String language,
|
||||
@ApiParam(value = "thing data", required = true) ThingDTO thingBean) {
|
||||
final Locale locale = localeService.getLocale(language);
|
||||
|
||||
@ -212,7 +240,9 @@ public class ThingResource implements RESTResource {
|
||||
// turn the ThingDTO's configuration into a Configuration
|
||||
Configuration configuration = new Configuration(
|
||||
normalizeConfiguration(thingBean.configuration, thingTypeUID, thingUID));
|
||||
if (thingUID != null) {
|
||||
normalizeChannels(thingBean, thingUID);
|
||||
}
|
||||
|
||||
Thing thing = thingRegistry.createThingOfType(thingTypeUID, thingUID, bridgeUID, thingBean.label,
|
||||
configuration);
|
||||
@ -254,7 +284,8 @@ public class ThingResource implements RESTResource {
|
||||
@ApiOperation(value = "Get all available things.", response = EnrichedThingDTO.class, responseContainer = "Set")
|
||||
@ApiResponses(value = {
|
||||
@ApiResponse(code = 200, message = "OK", response = EnrichedThingDTO.class, responseContainer = "Set") })
|
||||
public Response getAll(@HeaderParam(HttpHeaders.ACCEPT_LANGUAGE) @ApiParam(value = "language") String language) {
|
||||
public Response getAll(
|
||||
@HeaderParam(HttpHeaders.ACCEPT_LANGUAGE) @ApiParam(value = "language") @Nullable String language) {
|
||||
final Locale locale = localeService.getLocale(language);
|
||||
|
||||
Stream<EnrichedThingDTO> thingStream = thingRegistry.stream().map(t -> convertToEnrichedThingDTO(t, locale))
|
||||
@ -269,7 +300,8 @@ public class ThingResource implements RESTResource {
|
||||
@ApiOperation(value = "Gets thing by UID.")
|
||||
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = ThingDTO.class),
|
||||
@ApiResponse(code = 404, message = "Thing not found.") })
|
||||
public Response getByUID(@HeaderParam(HttpHeaders.ACCEPT_LANGUAGE) @ApiParam(value = "language") String language,
|
||||
public Response getByUID(
|
||||
@HeaderParam(HttpHeaders.ACCEPT_LANGUAGE) @ApiParam(value = "language") @Nullable String language,
|
||||
@PathParam("thingUID") @ApiParam(value = "thingUID") String thingUID) {
|
||||
final Locale locale = localeService.getLocale(language);
|
||||
|
||||
@ -300,7 +332,8 @@ public class ThingResource implements RESTResource {
|
||||
@ApiResponse(code = 202, message = "ACCEPTED for asynchronous deletion."),
|
||||
@ApiResponse(code = 404, message = "Thing not found."),
|
||||
@ApiResponse(code = 409, message = "Thing could not be deleted because it's not editable.") })
|
||||
public Response remove(@HeaderParam(HttpHeaders.ACCEPT_LANGUAGE) @ApiParam(value = "language") String language,
|
||||
public Response remove(
|
||||
@HeaderParam(HttpHeaders.ACCEPT_LANGUAGE) @ApiParam(value = "language") @Nullable String language,
|
||||
@PathParam("thingUID") @ApiParam(value = "thingUID") String thingUID,
|
||||
@DefaultValue("false") @QueryParam("force") @ApiParam(value = "force") boolean force) {
|
||||
final Locale locale = localeService.getLocale(language);
|
||||
@ -318,7 +351,7 @@ public class ThingResource implements RESTResource {
|
||||
// ask whether the Thing exists as a managed thing, so it can get
|
||||
// updated, 409 otherwise
|
||||
Thing managed = managedThingProvider.get(thingUIDObject);
|
||||
if (null == managed) {
|
||||
if (managed == null) {
|
||||
logger.info("Received HTTP DELETE request for update at '{}' for an unmanaged thing '{}'.",
|
||||
uriInfo.getPath(), thingUID);
|
||||
return getThingResponse(Status.CONFLICT, thing, locale,
|
||||
@ -327,12 +360,12 @@ public class ThingResource implements RESTResource {
|
||||
|
||||
// only move on if Thing is known to be managed, so it can get updated
|
||||
if (force) {
|
||||
if (null == thingRegistry.forceRemove(thingUIDObject)) {
|
||||
if (thingRegistry.forceRemove(thingUIDObject) == null) {
|
||||
return getThingResponse(Status.INTERNAL_SERVER_ERROR, thing, locale,
|
||||
"Cannot delete Thing " + thingUID + " for unknown reasons.");
|
||||
}
|
||||
} else {
|
||||
if (null != thingRegistry.remove(thingUIDObject)) {
|
||||
if (thingRegistry.remove(thingUIDObject) != null) {
|
||||
return getThingResponse(Status.ACCEPTED, thing, locale, null);
|
||||
}
|
||||
}
|
||||
@ -356,7 +389,8 @@ public class ThingResource implements RESTResource {
|
||||
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = ThingDTO.class),
|
||||
@ApiResponse(code = 404, message = "Thing not found."),
|
||||
@ApiResponse(code = 409, message = "Thing could not be updated as it is not editable.") })
|
||||
public Response update(@HeaderParam(HttpHeaders.ACCEPT_LANGUAGE) @ApiParam(value = "language") String language,
|
||||
public Response update(
|
||||
@HeaderParam(HttpHeaders.ACCEPT_LANGUAGE) @ApiParam(value = "language") @Nullable String language,
|
||||
@PathParam("thingUID") @ApiParam(value = "thingUID") String thingUID,
|
||||
@ApiParam(value = "thing", required = true) ThingDTO thingBean) throws IOException {
|
||||
final Locale locale = localeService.getLocale(language);
|
||||
@ -365,7 +399,7 @@ public class ThingResource implements RESTResource {
|
||||
|
||||
// ask whether the Thing exists at all, 404 otherwise
|
||||
Thing thing = thingRegistry.get(thingUIDObject);
|
||||
if (null == thing) {
|
||||
if (thing == null) {
|
||||
logger.info("Received HTTP PUT request for update at '{}' for the unknown thing '{}'.", uriInfo.getPath(),
|
||||
thingUID);
|
||||
return getThingNotFoundResponse(thingUID);
|
||||
@ -374,7 +408,7 @@ public class ThingResource implements RESTResource {
|
||||
// ask whether the Thing exists as a managed thing, so it can get
|
||||
// updated, 409 otherwise
|
||||
Thing managed = managedThingProvider.get(thingUIDObject);
|
||||
if (null == managed) {
|
||||
if (managed == null) {
|
||||
logger.info("Received HTTP PUT request for update at '{}' for an unmanaged thing '{}'.", uriInfo.getPath(),
|
||||
thingUID);
|
||||
return getThingResponse(Status.CONFLICT, thing, locale,
|
||||
@ -390,7 +424,7 @@ public class ThingResource implements RESTResource {
|
||||
|
||||
// update, returns null in case Thing cannot be found
|
||||
Thing oldthing = managedThingProvider.update(thing);
|
||||
if (null == oldthing) {
|
||||
if (oldthing == null) {
|
||||
return getThingNotFoundResponse(thingUID);
|
||||
}
|
||||
|
||||
@ -415,9 +449,10 @@ public class ThingResource implements RESTResource {
|
||||
@ApiResponse(code = 400, message = "Configuration of the thing is not valid."),
|
||||
@ApiResponse(code = 404, message = "Thing not found"),
|
||||
@ApiResponse(code = 409, message = "Thing could not be updated as it is not editable.") })
|
||||
public Response updateConfiguration(@HeaderParam(HttpHeaders.ACCEPT_LANGUAGE) String language,
|
||||
public Response updateConfiguration(
|
||||
@HeaderParam(HttpHeaders.ACCEPT_LANGUAGE) @ApiParam(value = "language") @Nullable String language,
|
||||
@PathParam("thingUID") @ApiParam(value = "thing") String thingUID,
|
||||
@ApiParam(value = "configuration parameters") Map<String, Object> configurationParameters)
|
||||
@ApiParam(value = "configuration parameters") @Nullable Map<String, Object> configurationParameters)
|
||||
throws IOException {
|
||||
final Locale locale = localeService.getLocale(language);
|
||||
|
||||
@ -425,7 +460,7 @@ public class ThingResource implements RESTResource {
|
||||
|
||||
// ask whether the Thing exists at all, 404 otherwise
|
||||
Thing thing = thingRegistry.get(thingUIDObject);
|
||||
if (null == thing) {
|
||||
if (thing == null) {
|
||||
logger.info("Received HTTP PUT request for update configuration at '{}' for the unknown thing '{}'.",
|
||||
uriInfo.getPath(), thingUID);
|
||||
return getThingNotFoundResponse(thingUID);
|
||||
@ -434,7 +469,7 @@ public class ThingResource implements RESTResource {
|
||||
// ask whether the Thing exists as a managed thing, so it can get
|
||||
// updated, 409 otherwise
|
||||
Thing managed = managedThingProvider.get(thingUIDObject);
|
||||
if (null == managed) {
|
||||
if (managed == null) {
|
||||
logger.info("Received HTTP PUT request for update configuration at '{}' for an unmanaged thing '{}'.",
|
||||
uriInfo.getPath(), thingUID);
|
||||
return getThingResponse(Status.CONFLICT, thing, locale,
|
||||
@ -468,13 +503,14 @@ public class ThingResource implements RESTResource {
|
||||
@ApiOperation(value = "Gets thing's status.")
|
||||
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = String.class),
|
||||
@ApiResponse(code = 404, message = "Thing not found.") })
|
||||
public Response getStatus(@HeaderParam(HttpHeaders.ACCEPT_LANGUAGE) String language,
|
||||
public Response getStatus(
|
||||
@HeaderParam(HttpHeaders.ACCEPT_LANGUAGE) @ApiParam(value = "language") @Nullable String language,
|
||||
@PathParam("thingUID") @ApiParam(value = "thing") String thingUID) throws IOException {
|
||||
ThingUID thingUIDObject = new ThingUID(thingUID);
|
||||
|
||||
// Check if the Thing exists, 404 if not
|
||||
Thing thing = thingRegistry.get(thingUIDObject);
|
||||
if (null == thing) {
|
||||
if (thing == null) {
|
||||
logger.info("Received HTTP GET request for thing config status at '{}' for the unknown thing '{}'.",
|
||||
uriInfo.getPath(), thingUID);
|
||||
return getThingNotFoundResponse(thingUID);
|
||||
@ -491,7 +527,8 @@ public class ThingResource implements RESTResource {
|
||||
@ApiOperation(value = "Sets the thing enabled status.")
|
||||
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = String.class),
|
||||
@ApiResponse(code = 404, message = "Thing not found.") })
|
||||
public Response setEnabled(@HeaderParam(HttpHeaders.ACCEPT_LANGUAGE) String language,
|
||||
public Response setEnabled(
|
||||
@HeaderParam(HttpHeaders.ACCEPT_LANGUAGE) @ApiParam(value = "language") @Nullable String language,
|
||||
@PathParam("thingUID") @ApiParam(value = "thing") String thingUID,
|
||||
@ApiParam(value = "enabled") String enabled) throws IOException {
|
||||
final Locale locale = localeService.getLocale(language);
|
||||
@ -500,7 +537,7 @@ public class ThingResource implements RESTResource {
|
||||
|
||||
// Check if the Thing exists, 404 if not
|
||||
Thing thing = thingRegistry.get(thingUIDObject);
|
||||
if (null == thing) {
|
||||
if (thing == null) {
|
||||
logger.info("Received HTTP PUT request for set enabled at '{}' for the unknown thing '{}'.",
|
||||
uriInfo.getPath(), thingUID);
|
||||
return getThingNotFoundResponse(thingUID);
|
||||
@ -519,13 +556,14 @@ public class ThingResource implements RESTResource {
|
||||
@ApiOperation(value = "Gets thing's config status.")
|
||||
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = String.class),
|
||||
@ApiResponse(code = 404, message = "Thing not found.") })
|
||||
public Response getConfigStatus(@HeaderParam(HttpHeaders.ACCEPT_LANGUAGE) String language,
|
||||
public Response getConfigStatus(
|
||||
@HeaderParam(HttpHeaders.ACCEPT_LANGUAGE) @ApiParam(value = "language") String language,
|
||||
@PathParam("thingUID") @ApiParam(value = "thing") String thingUID) throws IOException {
|
||||
ThingUID thingUIDObject = new ThingUID(thingUID);
|
||||
|
||||
// Check if the Thing exists, 404 if not
|
||||
Thing thing = thingRegistry.get(thingUIDObject);
|
||||
if (null == thing) {
|
||||
if (thing == null) {
|
||||
logger.info("Received HTTP GET request for thing config status at '{}' for the unknown thing '{}'.",
|
||||
uriInfo.getPath(), thingUID);
|
||||
return getThingNotFoundResponse(thingUID);
|
||||
@ -546,7 +584,7 @@ public class ThingResource implements RESTResource {
|
||||
@ApiResponse(code = 400, message = "Firmware update preconditions not satisfied."),
|
||||
@ApiResponse(code = 404, message = "Thing not found.") })
|
||||
public Response updateFirmware(
|
||||
@HeaderParam(HttpHeaders.ACCEPT_LANGUAGE) @ApiParam(value = "language") String language,
|
||||
@HeaderParam(HttpHeaders.ACCEPT_LANGUAGE) @ApiParam(value = "language") @Nullable String language,
|
||||
@PathParam("thingUID") @ApiParam(value = "thing") String thingUID,
|
||||
@PathParam("firmwareVersion") @ApiParam(value = "version") String firmwareVersion) throws IOException {
|
||||
Thing thing = thingRegistry.get(new ThingUID(thingUID));
|
||||
@ -556,16 +594,15 @@ public class ThingResource implements RESTResource {
|
||||
return getThingNotFoundResponse(thingUID);
|
||||
}
|
||||
|
||||
if (firmwareVersion == null || firmwareVersion.isEmpty()) {
|
||||
if (firmwareVersion.isEmpty()) {
|
||||
logger.info(
|
||||
"Received HTTP PUT request for firmware update at '{}' for thing '{}' with unknown firmware version '{}'.",
|
||||
uriInfo.getPath(), thingUID, firmwareVersion);
|
||||
return JSONResponse.createResponse(Status.BAD_REQUEST, null, "Firmware version is empty");
|
||||
}
|
||||
|
||||
ThingUID uid = thing.getUID();
|
||||
try {
|
||||
firmwareUpdateService.updateFirmware(uid, firmwareVersion, localeService.getLocale(language));
|
||||
firmwareUpdateService.updateFirmware(thing.getUID(), firmwareVersion, localeService.getLocale(language));
|
||||
} catch (IllegalArgumentException | IllegalStateException ex) {
|
||||
return JSONResponse.createResponse(Status.BAD_REQUEST, null,
|
||||
"Firmware update preconditions not satisfied.");
|
||||
@ -579,7 +616,8 @@ public class ThingResource implements RESTResource {
|
||||
@ApiOperation(value = "Gets thing's firmware status.")
|
||||
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK"),
|
||||
@ApiResponse(code = 204, message = "No firmware status provided by this Thing.") })
|
||||
public Response getFirmwareStatus(@HeaderParam(HttpHeaders.ACCEPT_LANGUAGE) String language,
|
||||
public Response getFirmwareStatus(
|
||||
@HeaderParam(HttpHeaders.ACCEPT_LANGUAGE) @ApiParam(value = "language") @Nullable String language,
|
||||
@PathParam("thingUID") @ApiParam(value = "thing") String thingUID) throws IOException {
|
||||
ThingUID thingUIDObject = new ThingUID(thingUID);
|
||||
FirmwareStatusDTO firmwareStatusDto = getThingFirmwareStatusInfo(thingUIDObject);
|
||||
@ -597,10 +635,10 @@ public class ThingResource implements RESTResource {
|
||||
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK"),
|
||||
@ApiResponse(code = 204, message = "No firmwares found.") })
|
||||
public Response getFirmwares(@PathParam("thingUID") @ApiParam(value = "thingUID") String thingUID,
|
||||
@HeaderParam(HttpHeaders.ACCEPT_LANGUAGE) @ApiParam(value = HttpHeaders.ACCEPT_LANGUAGE) String language) {
|
||||
@HeaderParam(HttpHeaders.ACCEPT_LANGUAGE) @ApiParam(value = "language") @Nullable String language) {
|
||||
ThingUID aThingUID = new ThingUID(thingUID);
|
||||
Thing thing = thingRegistry.get(aThingUID);
|
||||
if (null == thing) {
|
||||
if (thing == null) {
|
||||
logger.info(
|
||||
"Received HTTP GET request for listing available firmwares at {} for unknown thing with UID '{}'",
|
||||
uriInfo.getPath(), thingUID);
|
||||
@ -622,7 +660,7 @@ public class ThingResource implements RESTResource {
|
||||
firmware.getPrerequisiteVersion(), firmware.getChangelog());
|
||||
}
|
||||
|
||||
private FirmwareStatusDTO getThingFirmwareStatusInfo(ThingUID thingUID) {
|
||||
private @Nullable FirmwareStatusDTO getThingFirmwareStatusInfo(ThingUID thingUID) {
|
||||
FirmwareStatusInfo info = firmwareUpdateService.getFirmwareStatusInfo(thingUID);
|
||||
if (info != null) {
|
||||
return buildFirmwareStatusDTO(info);
|
||||
@ -654,10 +692,11 @@ public class ThingResource implements RESTResource {
|
||||
* @param errormessage an optional error message (may be null), ignored if the status family is successful
|
||||
* @return Response
|
||||
*/
|
||||
private Response getThingResponse(Status status, Thing thing, Locale locale, String errormessage) {
|
||||
private Response getThingResponse(Status status, @Nullable Thing thing, Locale locale,
|
||||
@Nullable String errormessage) {
|
||||
ThingStatusInfo thingStatusInfo = thingStatusInfoI18nLocalizationService.getLocalizedThingStatusInfo(thing,
|
||||
locale);
|
||||
boolean managed = managedThingProvider.get(thing.getUID()) != null;
|
||||
boolean managed = thing != null && managedThingProvider.get(thing.getUID()) != null;
|
||||
EnrichedThingDTO enrichedThingDTO = thing != null
|
||||
? EnrichedThingDTOMapper.map(thing, thingStatusInfo, this.getThingFirmwareStatusInfo(thing.getUID()),
|
||||
getLinkedItemsMap(thing), managed)
|
||||
@ -666,89 +705,6 @@ public class ThingResource implements RESTResource {
|
||||
return JSONResponse.createResponse(status, enrichedThingDTO, errormessage);
|
||||
}
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
|
||||
protected void setItemChannelLinkRegistry(ItemChannelLinkRegistry itemChannelLinkRegistry) {
|
||||
this.itemChannelLinkRegistry = itemChannelLinkRegistry;
|
||||
}
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
|
||||
protected void setItemFactory(ItemFactory itemFactory) {
|
||||
this.itemFactory = itemFactory;
|
||||
}
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
|
||||
protected void setItemRegistry(ItemRegistry itemRegistry) {
|
||||
this.itemRegistry = itemRegistry;
|
||||
}
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
|
||||
protected void setManagedItemChannelLinkProvider(ManagedItemChannelLinkProvider managedItemChannelLinkProvider) {
|
||||
this.managedItemChannelLinkProvider = managedItemChannelLinkProvider;
|
||||
}
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
|
||||
protected void setManagedItemProvider(ManagedItemProvider managedItemProvider) {
|
||||
this.managedItemProvider = managedItemProvider;
|
||||
}
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
|
||||
protected void setManagedThingProvider(ManagedThingProvider managedThingProvider) {
|
||||
this.managedThingProvider = managedThingProvider;
|
||||
}
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
|
||||
protected void setThingRegistry(ThingRegistry thingRegistry) {
|
||||
this.thingRegistry = thingRegistry;
|
||||
}
|
||||
|
||||
protected void unsetItemChannelLinkRegistry(ItemChannelLinkRegistry itemChannelLinkRegistry) {
|
||||
this.itemChannelLinkRegistry = null;
|
||||
}
|
||||
|
||||
protected void unsetItemFactory(ItemFactory itemFactory) {
|
||||
this.itemFactory = null;
|
||||
}
|
||||
|
||||
protected void unsetItemRegistry(ItemRegistry itemRegistry) {
|
||||
this.itemRegistry = null;
|
||||
}
|
||||
|
||||
protected void unsetManagedItemChannelLinkProvider(ManagedItemChannelLinkProvider managedItemChannelLinkProvider) {
|
||||
this.managedItemChannelLinkProvider = null;
|
||||
}
|
||||
|
||||
protected void unsetManagedItemProvider(ManagedItemProvider managedItemProvider) {
|
||||
this.managedItemProvider = null;
|
||||
}
|
||||
|
||||
protected void unsetManagedThingProvider(ManagedThingProvider managedThingProvider) {
|
||||
this.managedThingProvider = null;
|
||||
}
|
||||
|
||||
protected void unsetThingRegistry(ThingRegistry thingRegistry) {
|
||||
this.thingRegistry = null;
|
||||
}
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
|
||||
protected void setConfigStatusService(ConfigStatusService configStatusService) {
|
||||
this.configStatusService = configStatusService;
|
||||
}
|
||||
|
||||
protected void unsetConfigStatusService(ConfigStatusService configStatusService) {
|
||||
this.configStatusService = null;
|
||||
}
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
|
||||
protected void setThingStatusInfoI18nLocalizationService(
|
||||
ThingStatusInfoI18nLocalizationService thingStatusInfoI18nLocalizationService) {
|
||||
this.thingStatusInfoI18nLocalizationService = thingStatusInfoI18nLocalizationService;
|
||||
}
|
||||
|
||||
protected void unsetThingStatusInfoI18nLocalizationService(
|
||||
ThingStatusInfoI18nLocalizationService thingStatusInfoI18nLocalizationService) {
|
||||
this.thingStatusInfoI18nLocalizationService = null;
|
||||
}
|
||||
|
||||
private EnrichedThingDTO convertToEnrichedThingDTO(Thing thing, Locale locale) {
|
||||
boolean managed = managedThingProvider.get(thing.getUID()) != null;
|
||||
ThingStatusInfo thingStatusInfo = thingStatusInfoI18nLocalizationService.getLocalizedThingStatusInfo(thing,
|
||||
@ -772,62 +728,8 @@ public class ThingResource implements RESTResource {
|
||||
}
|
||||
}
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
|
||||
protected void setConfigDescriptionRegistry(ConfigDescriptionRegistry configDescriptionRegistry) {
|
||||
this.configDescRegistry = configDescriptionRegistry;
|
||||
}
|
||||
|
||||
protected void unsetConfigDescriptionRegistry(ConfigDescriptionRegistry configDescriptionRegistry) {
|
||||
this.configDescRegistry = null;
|
||||
}
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
|
||||
protected void setThingTypeRegistry(ThingTypeRegistry thingTypeRegistry) {
|
||||
this.thingTypeRegistry = thingTypeRegistry;
|
||||
}
|
||||
|
||||
protected void unsetThingTypeRegistry(ThingTypeRegistry thingTypeRegistry) {
|
||||
this.thingTypeRegistry = null;
|
||||
}
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
|
||||
protected void setChannelTypeRegistry(ChannelTypeRegistry channelTypeRegistry) {
|
||||
this.channelTypeRegistry = channelTypeRegistry;
|
||||
}
|
||||
|
||||
protected void unsetChannelTypeRegistry(ChannelTypeRegistry channelTypeRegistry) {
|
||||
this.channelTypeRegistry = null;
|
||||
}
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
|
||||
protected void setFirmwareUpdateService(FirmwareUpdateService firmwareUpdateService) {
|
||||
this.firmwareUpdateService = firmwareUpdateService;
|
||||
}
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
|
||||
protected void setFirmwareRegistry(FirmwareRegistry firmwareRegistry) {
|
||||
this.firmwareRegistry = firmwareRegistry;
|
||||
}
|
||||
|
||||
protected void unsetFirmwareRegistry(FirmwareRegistry firmwareRegistry) {
|
||||
this.firmwareRegistry = null;
|
||||
}
|
||||
|
||||
protected void unsetFirmwareUpdateService(FirmwareUpdateService firmwareUpdateService) {
|
||||
this.firmwareUpdateService = null;
|
||||
}
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
|
||||
protected void setThingManager(ThingManager thingManager) {
|
||||
this.thingManager = thingManager;
|
||||
}
|
||||
|
||||
protected void unsetThingManager(ThingManager thingManager) {
|
||||
this.thingManager = null;
|
||||
}
|
||||
|
||||
private Map<String, Object> normalizeConfiguration(Map<String, Object> properties, ThingTypeUID thingTypeUID,
|
||||
ThingUID thingUID) {
|
||||
private @Nullable Map<String, Object> normalizeConfiguration(@Nullable Map<String, Object> properties,
|
||||
ThingTypeUID thingTypeUID, @Nullable ThingUID thingUID) {
|
||||
if (properties == null || properties.isEmpty()) {
|
||||
return properties;
|
||||
}
|
||||
@ -845,7 +747,7 @@ public class ThingResource implements RESTResource {
|
||||
configDescriptions.add(typeConfigDesc);
|
||||
}
|
||||
}
|
||||
if (getConfigDescriptionURI(thingUID) != null) {
|
||||
if (thingUID != null) {
|
||||
ConfigDescription thingConfigDesc = configDescRegistry
|
||||
.getConfigDescription(getConfigDescriptionURI(thingUID));
|
||||
if (thingConfigDesc != null) {
|
||||
@ -860,8 +762,8 @@ public class ThingResource implements RESTResource {
|
||||
return ConfigUtil.normalizeTypes(properties, configDescriptions);
|
||||
}
|
||||
|
||||
private Map<String, Object> normalizeConfiguration(Map<String, Object> properties, ChannelTypeUID channelTypeUID,
|
||||
ChannelUID channelUID) {
|
||||
private @Nullable Map<String, Object> normalizeConfiguration(Map<String, Object> properties,
|
||||
ChannelTypeUID channelTypeUID, ChannelUID channelUID) {
|
||||
if (properties == null || properties.isEmpty()) {
|
||||
return properties;
|
||||
}
|
||||
@ -922,14 +824,4 @@ public class ThingResource implements RESTResource {
|
||||
throw new BadRequestException("Invalid URI syntax: " + uriString);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSatisfied() {
|
||||
return itemChannelLinkRegistry != null && itemFactory != null && itemRegistry != null
|
||||
&& managedItemChannelLinkProvider != null && managedItemProvider != null && managedThingProvider != null
|
||||
&& thingRegistry != null && configStatusService != null && configDescRegistry != null
|
||||
&& thingTypeRegistry != null && channelTypeRegistry != null && firmwareUpdateService != null
|
||||
&& thingStatusInfoI18nLocalizationService != null && firmwareRegistry != null && localeService != null
|
||||
&& thingManager != null;
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
package org.openhab.core.io.rest.core.internal.thing;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.stream.Stream;
|
||||
@ -28,6 +29,7 @@ import javax.ws.rs.core.HttpHeaders;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.core.auth.Role;
|
||||
import org.openhab.core.config.core.ConfigDescription;
|
||||
@ -55,10 +57,9 @@ import org.openhab.core.thing.type.ChannelType;
|
||||
import org.openhab.core.thing.type.ChannelTypeRegistry;
|
||||
import org.openhab.core.thing.type.ThingType;
|
||||
import org.openhab.core.thing.type.ThingTypeRegistry;
|
||||
import org.osgi.service.component.annotations.Activate;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Reference;
|
||||
import org.osgi.service.component.annotations.ReferenceCardinality;
|
||||
import org.osgi.service.component.annotations.ReferencePolicy;
|
||||
import org.osgi.service.jaxrs.whiteboard.JaxrsWhiteboardConstants;
|
||||
import org.osgi.service.jaxrs.whiteboard.propertytypes.JSONRequired;
|
||||
import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsApplicationSelect;
|
||||
@ -94,6 +95,7 @@ import io.swagger.annotations.ApiResponses;
|
||||
@JSONRequired
|
||||
@Path(ThingTypeResource.PATH_THING_TYPES)
|
||||
@Api(ThingTypeResource.PATH_THING_TYPES)
|
||||
@NonNullByDefault
|
||||
public class ThingTypeResource implements RESTResource {
|
||||
|
||||
/** The URI path to this resource */
|
||||
@ -101,56 +103,24 @@ public class ThingTypeResource implements RESTResource {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(ThingTypeResource.class);
|
||||
|
||||
private ThingTypeRegistry thingTypeRegistry;
|
||||
private ConfigDescriptionRegistry configDescriptionRegistry;
|
||||
private ChannelTypeRegistry channelTypeRegistry;
|
||||
private ChannelGroupTypeRegistry channelGroupTypeRegistry;
|
||||
private final ChannelTypeRegistry channelTypeRegistry;
|
||||
private final ChannelGroupTypeRegistry channelGroupTypeRegistry;
|
||||
private final ConfigDescriptionRegistry configDescriptionRegistry;
|
||||
private final LocaleService localeService;
|
||||
private final ThingTypeRegistry thingTypeRegistry;
|
||||
|
||||
private LocaleService localeService;
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
|
||||
protected void setThingTypeRegistry(ThingTypeRegistry thingTypeRegistry) {
|
||||
this.thingTypeRegistry = thingTypeRegistry;
|
||||
}
|
||||
|
||||
protected void unsetThingTypeRegistry(ThingTypeRegistry thingTypeRegistry) {
|
||||
this.thingTypeRegistry = null;
|
||||
}
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
|
||||
protected void setConfigDescriptionRegistry(ConfigDescriptionRegistry configDescriptionRegistry) {
|
||||
this.configDescriptionRegistry = configDescriptionRegistry;
|
||||
}
|
||||
|
||||
protected void unsetConfigDescriptionRegistry(ConfigDescriptionRegistry configDescriptionRegistry) {
|
||||
this.configDescriptionRegistry = null;
|
||||
}
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
|
||||
protected void setChannelTypeRegistry(ChannelTypeRegistry channelTypeRegistry) {
|
||||
@Activate
|
||||
public ThingTypeResource( //
|
||||
final @Reference ChannelTypeRegistry channelTypeRegistry,
|
||||
final @Reference ChannelGroupTypeRegistry channelGroupTypeRegistry,
|
||||
final @Reference ConfigDescriptionRegistry configDescriptionRegistry,
|
||||
final @Reference LocaleService localeService, //
|
||||
final @Reference ThingTypeRegistry thingTypeRegistry) {
|
||||
this.channelTypeRegistry = channelTypeRegistry;
|
||||
}
|
||||
|
||||
protected void unsetChannelTypeRegistry(ChannelTypeRegistry channelTypeRegistry) {
|
||||
this.channelTypeRegistry = null;
|
||||
}
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
|
||||
protected void setChannelGroupTypeRegistry(ChannelGroupTypeRegistry channelGroupTypeRegistry) {
|
||||
this.channelGroupTypeRegistry = channelGroupTypeRegistry;
|
||||
}
|
||||
|
||||
protected void unsetChannelGroupTypeRegistry(ChannelGroupTypeRegistry channelGroupTypeRegistry) {
|
||||
this.channelGroupTypeRegistry = null;
|
||||
}
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
|
||||
protected void setLocaleService(LocaleService localeService) {
|
||||
this.configDescriptionRegistry = configDescriptionRegistry;
|
||||
this.localeService = localeService;
|
||||
}
|
||||
|
||||
protected void unsetLocaleService(LocaleService localeService) {
|
||||
this.localeService = null;
|
||||
this.thingTypeRegistry = thingTypeRegistry;
|
||||
}
|
||||
|
||||
@GET
|
||||
@ -159,11 +129,11 @@ public class ThingTypeResource implements RESTResource {
|
||||
@ApiOperation(value = "Gets all available thing types without config description, channels and properties.", response = StrippedThingTypeDTO.class, responseContainer = "Set")
|
||||
@ApiResponses(value = @ApiResponse(code = 200, message = "OK", response = StrippedThingTypeDTO.class, responseContainer = "Set"))
|
||||
public Response getAll(
|
||||
@HeaderParam(HttpHeaders.ACCEPT_LANGUAGE) @ApiParam(value = HttpHeaders.ACCEPT_LANGUAGE) String language,
|
||||
@QueryParam("bindingId") @ApiParam(value = "filter by binding Id", required = false) @Nullable String bindingId) {
|
||||
@HeaderParam(HttpHeaders.ACCEPT_LANGUAGE) @ApiParam(value = "language") @Nullable String language,
|
||||
@QueryParam("bindingId") @ApiParam(value = "filter by binding Id") @Nullable String bindingId) {
|
||||
Locale locale = localeService.getLocale(language);
|
||||
Stream<StrippedThingTypeDTO> typeStream = thingTypeRegistry.getThingTypes(locale).stream()
|
||||
.map(t -> convertToStrippedThingTypeDTO(t, locale));
|
||||
.map(thingType -> StrippedThingTypeDTOMapper.map(thingType, locale));
|
||||
|
||||
if (bindingId != null) {
|
||||
typeStream = typeStream.filter(type -> type.UID.startsWith(bindingId + ':'));
|
||||
@ -181,7 +151,7 @@ public class ThingTypeResource implements RESTResource {
|
||||
@ApiResponse(code = 200, message = "Thing type with provided thingTypeUID does not exist.", response = ThingTypeDTO.class),
|
||||
@ApiResponse(code = 404, message = "No content") })
|
||||
public Response getByUID(@PathParam("thingTypeUID") @ApiParam(value = "thingTypeUID") String thingTypeUID,
|
||||
@HeaderParam(HttpHeaders.ACCEPT_LANGUAGE) @ApiParam(value = HttpHeaders.ACCEPT_LANGUAGE) String language) {
|
||||
@HeaderParam(HttpHeaders.ACCEPT_LANGUAGE) @ApiParam(value = "language") @Nullable String language) {
|
||||
Locale locale = localeService.getLocale(language);
|
||||
ThingType thingType = thingTypeRegistry.getThingType(new ThingTypeUID(thingTypeUID), locale);
|
||||
if (thingType != null) {
|
||||
@ -191,7 +161,7 @@ public class ThingTypeResource implements RESTResource {
|
||||
}
|
||||
}
|
||||
|
||||
private ThingTypeDTO convertToThingTypeDTO(ThingType thingType, Locale locale) {
|
||||
private @Nullable ThingTypeDTO convertToThingTypeDTO(ThingType thingType, Locale locale) {
|
||||
final ConfigDescription configDescription;
|
||||
if (thingType.getConfigDescriptionURI() != null) {
|
||||
configDescription = this.configDescriptionRegistry.getConfigDescription(thingType.getConfigDescriptionURI(),
|
||||
@ -233,21 +203,21 @@ public class ThingTypeResource implements RESTResource {
|
||||
ChannelGroupType channelGroupType = channelGroupTypeRegistry
|
||||
.getChannelGroupType(channelGroupDefinition.getTypeUID(), locale);
|
||||
|
||||
// Default to the channelGroupDefinition label to override the
|
||||
// channelGroupType
|
||||
// Default to the channelGroupDefinition label/description to override the channelGroupType
|
||||
String label = channelGroupDefinition.getLabel();
|
||||
String description = channelGroupDefinition.getDescription();
|
||||
List<ChannelDefinition> channelDefinitions = Collections.emptyList();
|
||||
|
||||
if (channelGroupType != null) {
|
||||
if (label == null) {
|
||||
label = channelGroupType.getLabel();
|
||||
}
|
||||
|
||||
// Default to the channelGroupDefinition description to override the
|
||||
// channelGroupType
|
||||
String description = channelGroupDefinition.getDescription();
|
||||
if (description == null) {
|
||||
description = channelGroupType.getDescription();
|
||||
}
|
||||
channelDefinitions = channelGroupType.getChannelDefinitions();
|
||||
}
|
||||
|
||||
List<ChannelDefinition> channelDefinitions = channelGroupType.getChannelDefinitions();
|
||||
List<ChannelDefinitionDTO> channelDefinitionDTOs = convertToChannelDefinitionDTOs(channelDefinitions,
|
||||
locale);
|
||||
|
||||
@ -257,8 +227,8 @@ public class ThingTypeResource implements RESTResource {
|
||||
return channelGroupDefinitionDTOs;
|
||||
}
|
||||
|
||||
private List<ChannelDefinitionDTO> convertToChannelDefinitionDTOs(List<ChannelDefinition> channelDefinitions,
|
||||
Locale locale) {
|
||||
private @Nullable List<ChannelDefinitionDTO> convertToChannelDefinitionDTOs(
|
||||
List<ChannelDefinition> channelDefinitions, Locale locale) {
|
||||
List<ChannelDefinitionDTO> channelDefinitionDTOs = new ArrayList<>();
|
||||
for (ChannelDefinition channelDefinition : channelDefinitions) {
|
||||
ChannelType channelType = channelTypeRegistry.getChannelType(channelDefinition.getChannelTypeUID(), locale);
|
||||
@ -289,21 +259,4 @@ public class ThingTypeResource implements RESTResource {
|
||||
}
|
||||
return channelDefinitionDTOs;
|
||||
}
|
||||
|
||||
private StrippedThingTypeDTO convertToStrippedThingTypeDTO(ThingType thingType, Locale locale) {
|
||||
final StrippedThingTypeDTO strippedThingTypeDTO = StrippedThingTypeDTOMapper.map(thingType, locale);
|
||||
if (strippedThingTypeDTO != null) {
|
||||
return strippedThingTypeDTO;
|
||||
} else {
|
||||
logger.warn("Cannot create DTO for thingType '{}'. Skip it.", thingType);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSatisfied() {
|
||||
return thingTypeRegistry != null && configDescriptionRegistry != null && channelTypeRegistry != null
|
||||
&& channelGroupTypeRegistry != null && localeService != null;
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,6 @@ package org.openhab.core.io.rest.core.internal.channel;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.mockito.MockitoAnnotations.initMocks;
|
||||
|
||||
@ -30,6 +29,7 @@ import org.hamcrest.core.IsCollectionContaining;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mock;
|
||||
import org.openhab.core.config.core.ConfigDescriptionRegistry;
|
||||
import org.openhab.core.io.rest.LocaleServiceImpl;
|
||||
import org.openhab.core.thing.profiles.ProfileTypeRegistry;
|
||||
import org.openhab.core.thing.profiles.ProfileTypeUID;
|
||||
@ -46,25 +46,23 @@ public class ChannelTypeResourceTest {
|
||||
|
||||
private ChannelTypeResource channelTypeResource;
|
||||
|
||||
@Mock
|
||||
private ChannelTypeRegistry channelTypeRegistry;
|
||||
|
||||
@Mock
|
||||
private ProfileTypeRegistry profileTypeRegistry;
|
||||
private @Mock ChannelTypeRegistry channelTypeRegistry;
|
||||
private @Mock ConfigDescriptionRegistry configDescriptionRegistry;
|
||||
private @Mock LocaleServiceImpl localeService;
|
||||
private @Mock ProfileTypeRegistry profileTypeRegistry;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
initMocks(this);
|
||||
channelTypeResource = new ChannelTypeResource();
|
||||
channelTypeResource.setLocaleService(new LocaleServiceImpl());
|
||||
channelTypeResource.setChannelTypeRegistry(channelTypeRegistry);
|
||||
channelTypeResource.setProfileTypeRegistry(profileTypeRegistry);
|
||||
channelTypeResource = new ChannelTypeResource(channelTypeRegistry, configDescriptionRegistry, localeService,
|
||||
profileTypeRegistry);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAllShouldRetrieveAllChannelTypes() throws Exception {
|
||||
when(localeService.getLocale(null)).thenReturn(Locale.ENGLISH);
|
||||
channelTypeResource.getAll(null, null);
|
||||
verify(channelTypeRegistry).getChannelTypes(any(Locale.class));
|
||||
verify(channelTypeRegistry).getChannelTypes(Locale.ENGLISH);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
@ -32,6 +32,8 @@ import javax.ws.rs.QueryParam;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.core.io.rest.RESTConstants;
|
||||
import org.openhab.core.io.rest.RESTResource;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
@ -62,6 +64,7 @@ import io.swagger.annotations.ApiResponses;
|
||||
@Path(LogHandler.PATH_LOG)
|
||||
@Api(LogHandler.PATH_LOG)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@NonNullByDefault
|
||||
public class LogHandler implements RESTResource {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(LogHandler.class);
|
||||
@ -80,9 +83,9 @@ public class LogHandler implements RESTResource {
|
||||
*/
|
||||
public class LogMessage {
|
||||
public long timestamp;
|
||||
public String severity;
|
||||
public URL url;
|
||||
public String message;
|
||||
public @Nullable String severity;
|
||||
public @Nullable URL url;
|
||||
public @Nullable String message;
|
||||
}
|
||||
|
||||
@GET
|
||||
@ -96,7 +99,8 @@ public class LogHandler implements RESTResource {
|
||||
@ApiOperation(value = "Returns the last logged frontend messages. The amount is limited to the "
|
||||
+ LogConstants.LOG_BUFFER_LIMIT + " last entries.")
|
||||
@ApiParam(name = "limit", allowableValues = "range[1, " + LogConstants.LOG_BUFFER_LIMIT + "]")
|
||||
public Response getLastLogs(@DefaultValue(LogConstants.LOG_BUFFER_LIMIT + "") @QueryParam("limit") Integer limit) {
|
||||
public Response getLastLogs(
|
||||
@DefaultValue(LogConstants.LOG_BUFFER_LIMIT + "") @QueryParam("limit") @Nullable Integer limit) {
|
||||
if (logBuffer.isEmpty()) {
|
||||
return Response.ok("[]").build();
|
||||
}
|
||||
@ -127,7 +131,7 @@ public class LogHandler implements RESTResource {
|
||||
@ApiParam(name = "logMessage", value = "Severity is required and can be one of error, warn, info or debug, depending on activated severities which you can GET at /logLevels.", example = "{\"severity\": \"error\", \"url\": \"http://example.org\", \"message\": \"Error message\"}")
|
||||
@ApiResponses({ @ApiResponse(code = 200, message = "OK"),
|
||||
@ApiResponse(code = 403, message = LogConstants.LOG_SEVERITY_IS_NOT_SUPPORTED) })
|
||||
public Response log(final LogMessage logMessage) {
|
||||
public Response log(final @Nullable LogMessage logMessage) {
|
||||
if (logMessage == null) {
|
||||
logger.debug("Received null log message model!");
|
||||
return Response.status(500)
|
||||
@ -155,7 +159,9 @@ public class LogHandler implements RESTResource {
|
||||
* @return Falls if severity is not supported, true if successfully logged.
|
||||
*/
|
||||
private boolean doLog(LogMessage logMessage) {
|
||||
switch (logMessage.severity.toLowerCase()) {
|
||||
String severity = logMessage.severity;
|
||||
severity = severity != null ? severity.toLowerCase() : "";
|
||||
switch (severity) {
|
||||
case "error":
|
||||
logger.error(LogConstants.FRONTEND_LOG_PATTERN, logMessage.url, logMessage.message);
|
||||
break;
|
||||
|
@ -24,6 +24,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.eclipse.emf.common.util.BasicEList;
|
||||
import org.eclipse.emf.common.util.EList;
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.core.events.Event;
|
||||
import org.openhab.core.events.EventFilter;
|
||||
@ -62,6 +63,7 @@ import org.slf4j.LoggerFactory;
|
||||
*/
|
||||
@Component(service = { SitemapSubscriptionService.class,
|
||||
EventSubscriber.class }, configurationPid = "org.openhab.sitemapsubscription")
|
||||
@NonNullByDefault
|
||||
public class SitemapSubscriptionService implements ModelRepositoryChangeListener, EventSubscriber {
|
||||
|
||||
private static final String SITEMAP_PAGE_SEPARATOR = "#";
|
||||
@ -77,7 +79,8 @@ public class SitemapSubscriptionService implements ModelRepositoryChangeListener
|
||||
void onRelease(String subscriptionId);
|
||||
}
|
||||
|
||||
private ItemUIRegistry itemUIRegistry;
|
||||
private final ItemUIRegistry itemUIRegistry;
|
||||
|
||||
private final List<SitemapProvider> sitemapProviders = new ArrayList<>();
|
||||
|
||||
/* subscription id -> sitemap+page */
|
||||
@ -95,12 +98,10 @@ public class SitemapSubscriptionService implements ModelRepositoryChangeListener
|
||||
/* Max number of subscriptions at the same time */
|
||||
private int maxSubscriptions = DEFAULT_MAX_SUBSCRIPTIONS;
|
||||
|
||||
public SitemapSubscriptionService() {
|
||||
}
|
||||
|
||||
@Activate
|
||||
protected void activate(Map<String, Object> config) {
|
||||
public SitemapSubscriptionService(Map<String, Object> config, final @Reference ItemUIRegistry itemUIRegistry) {
|
||||
applyConfig(config);
|
||||
this.itemUIRegistry = itemUIRegistry;
|
||||
}
|
||||
|
||||
@Deactivate
|
||||
@ -132,15 +133,6 @@ public class SitemapSubscriptionService implements ModelRepositoryChangeListener
|
||||
}
|
||||
}
|
||||
|
||||
@Reference
|
||||
protected void setItemUIRegistry(ItemUIRegistry itemUIRegistry) {
|
||||
this.itemUIRegistry = itemUIRegistry;
|
||||
}
|
||||
|
||||
protected void unsetItemUIRegistry(ItemUIRegistry itemUIRegistry) {
|
||||
this.itemUIRegistry = null;
|
||||
}
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC)
|
||||
protected void addSitemapProvider(SitemapProvider provider) {
|
||||
sitemapProviders.add(provider);
|
||||
@ -158,7 +150,7 @@ public class SitemapSubscriptionService implements ModelRepositoryChangeListener
|
||||
* @param callback an instance that should receive the events
|
||||
* @returns a unique id that identifies the subscription or null if the limit of subscriptions is already reached
|
||||
*/
|
||||
public String createSubscription(SitemapSubscriptionCallback callback) {
|
||||
public @Nullable String createSubscription(SitemapSubscriptionCallback callback) {
|
||||
if (maxSubscriptions >= 0 && callbacks.size() >= maxSubscriptions) {
|
||||
logger.debug("No new subscription delivered as limit ({}) is already reached", maxSubscriptions);
|
||||
return null;
|
||||
@ -206,7 +198,7 @@ public class SitemapSubscriptionService implements ModelRepositoryChangeListener
|
||||
* @param subscriptionId the subscription to get the page id for
|
||||
* @return the id of the currently active page or null if no page is currently set for the subscription
|
||||
*/
|
||||
public String getPageId(String subscriptionId) {
|
||||
public @Nullable String getPageId(String subscriptionId) {
|
||||
String sitemapWithPageId = pageOfSubscription.get(subscriptionId);
|
||||
return (sitemapWithPageId == null) ? null : extractPageId(sitemapWithPageId);
|
||||
}
|
||||
@ -217,7 +209,7 @@ public class SitemapSubscriptionService implements ModelRepositoryChangeListener
|
||||
* @param subscriptionId the subscription to get the sitemap name for
|
||||
* @return the name of the current sitemap or null if no sitemap is currently set for the subscription
|
||||
*/
|
||||
public String getSitemapName(String subscriptionId) {
|
||||
public @Nullable String getSitemapName(String subscriptionId) {
|
||||
String sitemapWithPageId = pageOfSubscription.get(subscriptionId);
|
||||
return (sitemapWithPageId == null) ? null : extractSitemapName(sitemapWithPageId);
|
||||
}
|
||||
@ -260,8 +252,7 @@ public class SitemapSubscriptionService implements ModelRepositoryChangeListener
|
||||
// there is no listener for this page yet, so let's try to create one
|
||||
listener = new PageChangeListener(sitemapName, pageId, itemUIRegistry, collectWidgets(sitemapName, pageId));
|
||||
pageChangeListeners.put(getValue(sitemapName, pageId), listener);
|
||||
}
|
||||
if (listener != null) {
|
||||
} else {
|
||||
listener.addCallback(callback);
|
||||
}
|
||||
}
|
||||
@ -301,7 +292,7 @@ public class SitemapSubscriptionService implements ModelRepositoryChangeListener
|
||||
return sitemapName + SITEMAP_PAGE_SEPARATOR + pageId;
|
||||
}
|
||||
|
||||
private Sitemap getSitemap(String sitemapName) {
|
||||
private @Nullable Sitemap getSitemap(String sitemapName) {
|
||||
for (SitemapProvider provider : sitemapProviders) {
|
||||
Sitemap sitemap = provider.getSitemap(sitemapName);
|
||||
if (sitemap != null) {
|
||||
|
@ -53,6 +53,7 @@ import org.eclipse.emf.common.util.EList;
|
||||
import org.eclipse.emf.ecore.EObject;
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.core.auth.Role;
|
||||
import org.openhab.core.common.ThreadPoolManager;
|
||||
import org.openhab.core.io.rest.JSONResponse;
|
||||
@ -128,6 +129,7 @@ import io.swagger.annotations.ApiResponses;
|
||||
@Path(SitemapResource.PATH_SITEMAPS)
|
||||
@RolesAllowed({ Role.USER, Role.ADMIN })
|
||||
@Api(SitemapResource.PATH_SITEMAPS)
|
||||
@NonNullByDefault
|
||||
public class SitemapResource
|
||||
implements RESTResource, SitemapSubscriptionCallback, SseBroadcaster.Listener<SseSinkInfo> {
|
||||
|
||||
@ -139,24 +141,27 @@ public class SitemapResource
|
||||
|
||||
private static final long TIMEOUT_IN_MS = 30000;
|
||||
|
||||
private @NonNullByDefault({}) Sse sse;
|
||||
|
||||
private SseBroadcaster<@NonNull SseSinkInfo> broadcaster;
|
||||
|
||||
@Context
|
||||
@NonNullByDefault({})
|
||||
UriInfo uriInfo;
|
||||
|
||||
@Context
|
||||
@NonNullByDefault({})
|
||||
HttpServletRequest request;
|
||||
|
||||
@Context
|
||||
private HttpServletResponse response;
|
||||
@NonNullByDefault({})
|
||||
HttpServletResponse response;
|
||||
|
||||
private ItemUIRegistry itemUIRegistry;
|
||||
@Context
|
||||
@NonNullByDefault({})
|
||||
Sse sse;
|
||||
|
||||
private SitemapSubscriptionService subscriptions;
|
||||
|
||||
private LocaleService localeService;
|
||||
private final ItemUIRegistry itemUIRegistry;
|
||||
private final SitemapSubscriptionService subscriptions;
|
||||
private final LocaleService localeService;
|
||||
|
||||
private final java.util.List<SitemapProvider> sitemapProviders = new ArrayList<>();
|
||||
|
||||
@ -165,10 +170,17 @@ public class SitemapResource
|
||||
private final ScheduledExecutorService scheduler = ThreadPoolManager
|
||||
.getScheduledPool(ThreadPoolManager.THREAD_POOL_NAME_COMMON);
|
||||
|
||||
private ScheduledFuture<?> cleanSubscriptionsJob;
|
||||
private @Nullable ScheduledFuture<?> cleanSubscriptionsJob;
|
||||
|
||||
@Activate
|
||||
protected void activate() {
|
||||
public SitemapResource( //
|
||||
final @Reference ItemUIRegistry itemUIRegistry, //
|
||||
final @Reference LocaleService localeService, //
|
||||
final @Reference SitemapSubscriptionService subscriptions) {
|
||||
this.itemUIRegistry = itemUIRegistry;
|
||||
this.localeService = localeService;
|
||||
this.subscriptions = subscriptions;
|
||||
|
||||
broadcaster = new SseBroadcaster<>();
|
||||
|
||||
// The clean SSE subscriptions job sends an ALIVE event to all subscribers. This will trigger
|
||||
@ -179,45 +191,21 @@ public class SitemapResource
|
||||
// The clean SSE subscriptions job is run every 5 minutes.
|
||||
cleanSubscriptionsJob = scheduler.scheduleAtFixedRate(() -> {
|
||||
logger.debug("Run clean SSE subscriptions job");
|
||||
if (subscriptions != null) {
|
||||
subscriptions.checkAliveClients();
|
||||
}
|
||||
}, 1, 5, TimeUnit.MINUTES);
|
||||
}
|
||||
|
||||
@Deactivate
|
||||
protected void deactivate() {
|
||||
if (cleanSubscriptionsJob != null && !cleanSubscriptionsJob.isCancelled()) {
|
||||
ScheduledFuture<?> job = cleanSubscriptionsJob;
|
||||
if (job != null && !job.isCancelled()) {
|
||||
logger.debug("Cancel clean SSE subscriptions job");
|
||||
cleanSubscriptionsJob.cancel(true);
|
||||
job.cancel(true);
|
||||
cleanSubscriptionsJob = null;
|
||||
}
|
||||
broadcaster.close();
|
||||
}
|
||||
|
||||
@Context
|
||||
public void setSse(final Sse sse) {
|
||||
this.sse = sse;
|
||||
}
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
|
||||
public void setItemUIRegistry(ItemUIRegistry itemUIRegistry) {
|
||||
this.itemUIRegistry = itemUIRegistry;
|
||||
}
|
||||
|
||||
public void unsetItemUIRegistry(ItemUIRegistry itemUIRegistry) {
|
||||
this.itemUIRegistry = null;
|
||||
}
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
|
||||
public void setSitemapSubscriptionService(SitemapSubscriptionService subscriptions) {
|
||||
this.subscriptions = subscriptions;
|
||||
}
|
||||
|
||||
public void unsetSitemapSubscriptionService(SitemapSubscriptionService subscriptions) {
|
||||
this.subscriptions = null;
|
||||
}
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC)
|
||||
public void addSitemapProvider(SitemapProvider provider) {
|
||||
sitemapProviders.add(provider);
|
||||
@ -227,15 +215,6 @@ public class SitemapResource
|
||||
sitemapProviders.remove(provider);
|
||||
}
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
|
||||
protected void setLocaleService(LocaleService localeService) {
|
||||
this.localeService = localeService;
|
||||
}
|
||||
|
||||
protected void unsetLocaleService(LocaleService localeService) {
|
||||
this.localeService = null;
|
||||
}
|
||||
|
||||
@GET
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@ApiOperation(value = "Get all available sitemaps.", response = SitemapDTO.class, responseContainer = "Collection")
|
||||
@ -252,10 +231,10 @@ public class SitemapResource
|
||||
@ApiOperation(value = "Get sitemap by name.", response = SitemapDTO.class)
|
||||
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK") })
|
||||
public Response getSitemapData(@Context HttpHeaders headers,
|
||||
@HeaderParam(HttpHeaders.ACCEPT_LANGUAGE) @ApiParam(value = "language") String language,
|
||||
@HeaderParam(HttpHeaders.ACCEPT_LANGUAGE) @ApiParam(value = "language") @Nullable String language,
|
||||
@PathParam("sitemapname") @ApiParam(value = "sitemap name") String sitemapname,
|
||||
@QueryParam("type") String type, @QueryParam("jsoncallback") @DefaultValue("callback") String callback,
|
||||
@QueryParam("includeHidden") @ApiParam(value = "include hidden widgets", required = false) boolean includeHiddenWidgets) {
|
||||
@QueryParam("includeHidden") @ApiParam(value = "include hidden widgets") boolean includeHiddenWidgets) {
|
||||
final Locale locale = localeService.getLocale(language);
|
||||
logger.debug("Received HTTP GET request from IP {} at '{}' for media type '{}'.", request.getRemoteAddr(),
|
||||
uriInfo.getPath(), type);
|
||||
@ -272,11 +251,11 @@ public class SitemapResource
|
||||
@ApiResponse(code = 404, message = "Sitemap with requested name does not exist or page does not exist, or page refers to a non-linkable widget"),
|
||||
@ApiResponse(code = 400, message = "Invalid subscription id has been provided.") })
|
||||
public Response getPageData(@Context HttpHeaders headers,
|
||||
@HeaderParam(HttpHeaders.ACCEPT_LANGUAGE) @ApiParam(value = "language") String language,
|
||||
@HeaderParam(HttpHeaders.ACCEPT_LANGUAGE) @ApiParam(value = "language") @Nullable String language,
|
||||
@PathParam("sitemapname") @ApiParam(value = "sitemap name") String sitemapname,
|
||||
@PathParam("pageid") @ApiParam(value = "page id") String pageId,
|
||||
@QueryParam("subscriptionid") @ApiParam(value = "subscriptionid", required = false) String subscriptionId,
|
||||
@QueryParam("includeHidden") @ApiParam(value = "include hidden widgets", required = false) boolean includeHiddenWidgets) {
|
||||
@QueryParam("subscriptionid") @ApiParam(value = "subscriptionid") @Nullable String subscriptionId,
|
||||
@QueryParam("includeHidden") @ApiParam(value = "include hidden widgets") boolean includeHiddenWidgets) {
|
||||
final Locale locale = localeService.getLocale(language);
|
||||
logger.debug("Received HTTP GET request from IP {} at '{}'", request.getRemoteAddr(), uriInfo.getPath());
|
||||
|
||||
@ -345,8 +324,8 @@ public class SitemapResource
|
||||
@ApiResponse(code = 404, message = "Subscription not found.") })
|
||||
public void getSitemapEvents(@Context final SseEventSink sseEventSink, @Context final HttpServletResponse response,
|
||||
@PathParam("subscriptionid") @ApiParam(value = "subscription id") String subscriptionId,
|
||||
@QueryParam("sitemap") @ApiParam(value = "sitemap name", required = false) String sitemapname,
|
||||
@QueryParam("pageid") @ApiParam(value = "page id", required = false) String pageId) {
|
||||
@QueryParam("sitemap") @ApiParam(value = "sitemap name") @Nullable String sitemapname,
|
||||
@QueryParam("pageid") @ApiParam(value = "page id") @Nullable String pageId) {
|
||||
final SseSinkInfo sinkInfo = knownSubscriptions.get(subscriptionId);
|
||||
if (sinkInfo == null) {
|
||||
logger.debug("Subscription id {} does not exist.", subscriptionId);
|
||||
@ -475,8 +454,9 @@ public class SitemapResource
|
||||
return bean;
|
||||
}
|
||||
|
||||
private PageDTO createPageBean(String sitemapName, String title, String icon, String pageId, EList<Widget> children,
|
||||
boolean drillDown, boolean isLeaf, URI uri, Locale locale, boolean timeout, boolean includeHiddenWidgets) {
|
||||
private PageDTO createPageBean(String sitemapName, @Nullable String title, @Nullable String icon, String pageId,
|
||||
@Nullable EList<Widget> children, boolean drillDown, boolean isLeaf, URI uri, Locale locale,
|
||||
boolean timeout, boolean includeHiddenWidgets) {
|
||||
PageDTO bean = new PageDTO();
|
||||
bean.timeout = timeout;
|
||||
bean.id = pageId;
|
||||
@ -499,8 +479,8 @@ public class SitemapResource
|
||||
return bean;
|
||||
}
|
||||
|
||||
private WidgetDTO createWidgetBean(String sitemapName, Widget widget, boolean drillDown, URI uri, String widgetId,
|
||||
Locale locale, boolean evenIfHidden) {
|
||||
private @Nullable WidgetDTO createWidgetBean(String sitemapName, Widget widget, boolean drillDown, URI uri,
|
||||
String widgetId, Locale locale, boolean evenIfHidden) {
|
||||
// Test visibility
|
||||
if (!evenIfHidden && !itemUIRegistry.getVisiblity(widget)) {
|
||||
return null;
|
||||
@ -653,7 +633,7 @@ public class SitemapResource
|
||||
return true;
|
||||
}
|
||||
|
||||
private Sitemap getSitemap(String sitemapname) {
|
||||
private @Nullable Sitemap getSitemap(String sitemapname) {
|
||||
for (SitemapProvider provider : sitemapProviders) {
|
||||
Sitemap sitemap = provider.getSitemap(sitemapname);
|
||||
if (sitemap != null) {
|
||||
@ -723,7 +703,6 @@ public class SitemapResource
|
||||
*/
|
||||
private Set<GenericItem> getAllItems(EList<Widget> widgets) {
|
||||
Set<GenericItem> items = new HashSet<>();
|
||||
if (itemUIRegistry != null) {
|
||||
for (Widget widget : widgets) {
|
||||
// We skip the chart widgets having a refresh argument
|
||||
boolean skipWidget = false;
|
||||
@ -751,7 +730,6 @@ public class SitemapResource
|
||||
items.addAll(getItemsInColorCond(widget.getLabelColor()));
|
||||
items.addAll(getItemsInColorCond(widget.getValueColor()));
|
||||
}
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
@ -858,11 +836,6 @@ public class SitemapResource
|
||||
knownSubscriptions.remove(subscriptionId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSatisfied() {
|
||||
return itemUIRegistry != null && subscriptions != null && localeService != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sseEventSinkRemoved(SseEventSink sink, SseSinkInfo info) {
|
||||
logger.debug("SSE connection for subscription {} has been closed.", info.subscriptionId);
|
||||
|
@ -38,6 +38,7 @@ import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mock;
|
||||
import org.openhab.core.io.rest.LocaleService;
|
||||
import org.openhab.core.io.rest.sitemap.SitemapSubscriptionService;
|
||||
import org.openhab.core.items.GenericItem;
|
||||
import org.openhab.core.items.ItemNotFoundException;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
@ -79,23 +80,14 @@ public class SitemapResourceTest extends JavaTest {
|
||||
|
||||
private SitemapResource sitemapResource;
|
||||
|
||||
@Mock
|
||||
private UriInfo uriInfo;
|
||||
|
||||
@Mock
|
||||
private HttpServletRequest request;
|
||||
|
||||
@Mock
|
||||
private SitemapProvider sitemapProvider;
|
||||
|
||||
@Mock
|
||||
private Sitemap defaultSitemap;
|
||||
|
||||
@Mock
|
||||
private ItemUIRegistry itemUIRegistry;
|
||||
|
||||
@Mock
|
||||
private HttpHeaders headers;
|
||||
private @Mock HttpHeaders headers;
|
||||
private @Mock Sitemap defaultSitemap;
|
||||
private @Mock ItemUIRegistry itemUIRegistry;
|
||||
private @Mock LocaleService localeService;
|
||||
private @Mock HttpServletRequest request;
|
||||
private @Mock SitemapProvider sitemapProvider;
|
||||
private @Mock SitemapSubscriptionService subscriptions;
|
||||
private @Mock UriInfo uriInfo;
|
||||
|
||||
private GenericItem item;
|
||||
private GenericItem visibilityRuleItem;
|
||||
@ -107,7 +99,8 @@ public class SitemapResourceTest extends JavaTest {
|
||||
@Before
|
||||
public void setup() throws Exception {
|
||||
initMocks(this);
|
||||
sitemapResource = new SitemapResource();
|
||||
|
||||
sitemapResource = new SitemapResource(itemUIRegistry, localeService, subscriptions);
|
||||
|
||||
when(uriInfo.getAbsolutePathBuilder()).thenReturn(UriBuilder.fromPath(SITEMAP_PATH));
|
||||
when(uriInfo.getBaseUriBuilder()).thenReturn(UriBuilder.fromPath(SITEMAP_PATH));
|
||||
@ -121,9 +114,7 @@ public class SitemapResourceTest extends JavaTest {
|
||||
labelColorItem = new TestItem(LABEL_COLOR_ITEM_NAME);
|
||||
valueColorItem = new TestItem(VALUE_COLOR_ITEM_NAME);
|
||||
|
||||
LocaleService localeService = mock(LocaleService.class);
|
||||
when(localeService.getLocale(null)).thenReturn(Locale.US);
|
||||
sitemapResource.setLocaleService(localeService);
|
||||
|
||||
configureSitemapProviderMock();
|
||||
configureSitemapMock();
|
||||
@ -131,7 +122,6 @@ public class SitemapResourceTest extends JavaTest {
|
||||
|
||||
widgets = initSitemapWidgets();
|
||||
configureItemUIRegistry(PercentType.HUNDRED, OnOffType.ON);
|
||||
sitemapResource.setItemUIRegistry(itemUIRegistry);
|
||||
|
||||
// Disable long polling
|
||||
when(headers.getRequestHeader(HTTP_HEADER_X_ATMOSPHERE_TRANSPORT)).thenReturn(null);
|
||||
|
@ -95,7 +95,7 @@ public class SseResource implements SsePublisher {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(SseResource.class);
|
||||
|
||||
private @NonNullByDefault({}) Sse sse;
|
||||
private @Context @NonNullByDefault({}) Sse sse;
|
||||
|
||||
private final SseBroadcaster<SseSinkItemInfo> itemStatesBroadcaster = new SseBroadcaster<>();
|
||||
private final SseItemStatesEventBuilder itemStatesEventBuilder;
|
||||
@ -103,11 +103,6 @@ public class SseResource implements SsePublisher {
|
||||
|
||||
private ExecutorService executorService;
|
||||
|
||||
@Context
|
||||
public void setSse(final Sse sse) {
|
||||
this.sse = sse;
|
||||
}
|
||||
|
||||
@Activate
|
||||
public SseResource(@Reference SseItemStatesEventBuilder itemStatesEventBuilder) {
|
||||
this.executorService = Executors.newSingleThreadExecutor();
|
||||
|
@ -23,12 +23,11 @@ import javax.ws.rs.PUT;
|
||||
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.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.Response.Status;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.core.auth.Role;
|
||||
import org.openhab.core.io.rest.RESTConstants;
|
||||
import org.openhab.core.io.rest.RESTResource;
|
||||
@ -39,10 +38,9 @@ import org.openhab.core.ui.components.UIComponentRegistry;
|
||||
import org.openhab.core.ui.components.UIComponentRegistryFactory;
|
||||
import org.openhab.core.ui.tiles.Tile;
|
||||
import org.openhab.core.ui.tiles.TileProvider;
|
||||
import org.osgi.service.component.annotations.Activate;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Reference;
|
||||
import org.osgi.service.component.annotations.ReferenceCardinality;
|
||||
import org.osgi.service.component.annotations.ReferencePolicy;
|
||||
import org.osgi.service.jaxrs.whiteboard.JaxrsWhiteboardConstants;
|
||||
import org.osgi.service.jaxrs.whiteboard.propertytypes.JSONRequired;
|
||||
import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsApplicationSelect;
|
||||
@ -67,16 +65,22 @@ import io.swagger.annotations.ApiResponses;
|
||||
@JSONRequired
|
||||
@Path(UIResource.PATH_UI)
|
||||
@Api(UIResource.PATH_UI)
|
||||
@NonNullByDefault
|
||||
public class UIResource implements RESTResource {
|
||||
|
||||
/** The URI path to this resource */
|
||||
public static final String PATH_UI = "ui";
|
||||
|
||||
@Context
|
||||
private UriInfo uriInfo;
|
||||
private final UIComponentRegistryFactory componentRegistryFactory;
|
||||
private final TileProvider tileProvider;
|
||||
|
||||
private TileProvider tileProvider;
|
||||
private UIComponentRegistryFactory componentRegistryFactory;
|
||||
@Activate
|
||||
public UIResource( //
|
||||
final @Reference UIComponentRegistryFactory componentRegistryFactory,
|
||||
final @Reference TileProvider tileProvider) {
|
||||
this.componentRegistryFactory = componentRegistryFactory;
|
||||
this.tileProvider = tileProvider;
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("/tiles")
|
||||
@ -169,29 +173,6 @@ public class UIResource implements RESTResource {
|
||||
return Response.ok().build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSatisfied() {
|
||||
return tileProvider != null && componentRegistryFactory != null;
|
||||
}
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
|
||||
protected void setTileProvider(TileProvider tileProvider) {
|
||||
this.tileProvider = tileProvider;
|
||||
}
|
||||
|
||||
protected void unsetTileProvider(TileProvider tileProvider) {
|
||||
this.tileProvider = null;
|
||||
}
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
|
||||
protected void setComponentRegistryFactory(UIComponentRegistryFactory componentRegistryFactory) {
|
||||
this.componentRegistryFactory = componentRegistryFactory;
|
||||
}
|
||||
|
||||
protected void unsetComponentRegistryFactory(UIComponentRegistryFactory componentRegistryFactory) {
|
||||
this.componentRegistryFactory = null;
|
||||
}
|
||||
|
||||
private TileDTO toTileDTO(Tile tile) {
|
||||
return new TileDTO(tile.getName(), tile.getUrl(), tile.getOverlay(), tile.getImageUrl());
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ import java.util.HashSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.core.voice.text.HumanLanguageInterpreter;
|
||||
|
||||
/**
|
||||
@ -23,6 +24,7 @@ import org.openhab.core.voice.text.HumanLanguageInterpreter;
|
||||
*
|
||||
* @author Kai Kreuzer - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class HLIMapper {
|
||||
|
||||
/**
|
||||
|
@ -12,6 +12,7 @@
|
||||
*/
|
||||
package org.openhab.core.io.rest.voice.internal;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.core.voice.Voice;
|
||||
|
||||
/**
|
||||
@ -19,6 +20,7 @@ import org.openhab.core.voice.Voice;
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class VoiceMapper {
|
||||
|
||||
/**
|
||||
|
@ -12,10 +12,9 @@
|
||||
*/
|
||||
package org.openhab.core.io.rest.voice.internal;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.annotation.security.RolesAllowed;
|
||||
import javax.ws.rs.Consumes;
|
||||
@ -26,13 +25,13 @@ import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.QueryParam;
|
||||
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.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.core.auth.Role;
|
||||
import org.openhab.core.io.rest.JSONResponse;
|
||||
import org.openhab.core.io.rest.LocaleService;
|
||||
@ -42,10 +41,9 @@ import org.openhab.core.voice.Voice;
|
||||
import org.openhab.core.voice.VoiceManager;
|
||||
import org.openhab.core.voice.text.HumanLanguageInterpreter;
|
||||
import org.openhab.core.voice.text.InterpretationException;
|
||||
import org.osgi.service.component.annotations.Activate;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Reference;
|
||||
import org.osgi.service.component.annotations.ReferenceCardinality;
|
||||
import org.osgi.service.component.annotations.ReferencePolicy;
|
||||
import org.osgi.service.jaxrs.whiteboard.JaxrsWhiteboardConstants;
|
||||
import org.osgi.service.jaxrs.whiteboard.propertytypes.JSONRequired;
|
||||
import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsApplicationSelect;
|
||||
@ -73,32 +71,21 @@ import io.swagger.annotations.ApiResponses;
|
||||
@Path(VoiceResource.PATH_VOICE)
|
||||
@RolesAllowed({ Role.USER, Role.ADMIN })
|
||||
@Api(VoiceResource.PATH_VOICE)
|
||||
@NonNullByDefault
|
||||
public class VoiceResource implements RESTResource {
|
||||
|
||||
static final String PATH_VOICE = "voice";
|
||||
/** The URI path to this resource */
|
||||
public static final String PATH_VOICE = "voice";
|
||||
|
||||
@Context
|
||||
UriInfo uriInfo;
|
||||
private final LocaleService localeService;
|
||||
private final VoiceManager voiceManager;
|
||||
|
||||
private VoiceManager voiceManager;
|
||||
private LocaleService localeService;
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
|
||||
public void setVoiceManager(VoiceManager voiceManager) {
|
||||
this.voiceManager = voiceManager;
|
||||
}
|
||||
|
||||
public void unsetVoiceManager(VoiceManager voiceManager) {
|
||||
this.voiceManager = null;
|
||||
}
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
|
||||
protected void setLocaleService(LocaleService localeService) {
|
||||
@Activate
|
||||
public VoiceResource( //
|
||||
final @Reference LocaleService localeService, //
|
||||
final @Reference VoiceManager voiceManager) {
|
||||
this.localeService = localeService;
|
||||
}
|
||||
|
||||
protected void unsetLocaleService(LocaleService localeService) {
|
||||
this.localeService = null;
|
||||
this.voiceManager = voiceManager;
|
||||
}
|
||||
|
||||
@GET
|
||||
@ -107,13 +94,10 @@ public class VoiceResource implements RESTResource {
|
||||
@ApiOperation(value = "Get the list of all interpreters.", response = HumanLanguageInterpreterDTO.class, responseContainer = "List")
|
||||
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK") })
|
||||
public Response getInterpreters(
|
||||
@HeaderParam(HttpHeaders.ACCEPT_LANGUAGE) @ApiParam(value = "language") String language) {
|
||||
@HeaderParam(HttpHeaders.ACCEPT_LANGUAGE) @ApiParam(value = "language") @Nullable String language) {
|
||||
final Locale locale = localeService.getLocale(language);
|
||||
Collection<HumanLanguageInterpreter> hlis = voiceManager.getHLIs();
|
||||
List<HumanLanguageInterpreterDTO> dtos = new ArrayList<>(hlis.size());
|
||||
for (HumanLanguageInterpreter hli : hlis) {
|
||||
dtos.add(HLIMapper.map(hli, locale));
|
||||
}
|
||||
List<HumanLanguageInterpreterDTO> dtos = voiceManager.getHLIs().stream().map(hli -> HLIMapper.map(hli, locale))
|
||||
.collect(Collectors.toList());
|
||||
return Response.ok(dtos).build();
|
||||
}
|
||||
|
||||
@ -124,16 +108,16 @@ public class VoiceResource implements RESTResource {
|
||||
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK"),
|
||||
@ApiResponse(code = 404, message = "Interpreter not found") })
|
||||
public Response getInterpreter(
|
||||
@HeaderParam(HttpHeaders.ACCEPT_LANGUAGE) @ApiParam(value = "language") String language,
|
||||
@PathParam("id") @ApiParam(value = "interpreter id", required = true) String id) {
|
||||
@HeaderParam(HttpHeaders.ACCEPT_LANGUAGE) @ApiParam(value = "language") @Nullable String language,
|
||||
@PathParam("id") @ApiParam(value = "interpreter id") String id) {
|
||||
final Locale locale = localeService.getLocale(language);
|
||||
HumanLanguageInterpreter hli = voiceManager.getHLI(id);
|
||||
if (hli != null) {
|
||||
if (hli == null) {
|
||||
return JSONResponse.createErrorResponse(Status.NOT_FOUND, "No interpreter found");
|
||||
}
|
||||
|
||||
HumanLanguageInterpreterDTO dto = HLIMapper.map(hli, locale);
|
||||
return Response.ok(dto).build();
|
||||
} else {
|
||||
return JSONResponse.createErrorResponse(Status.NOT_FOUND, "Interpreter not found");
|
||||
}
|
||||
}
|
||||
|
||||
@POST
|
||||
@ -143,21 +127,22 @@ public class VoiceResource implements RESTResource {
|
||||
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK"),
|
||||
@ApiResponse(code = 404, message = "No human language interpreter was found."),
|
||||
@ApiResponse(code = 400, message = "interpretation exception occurs") })
|
||||
public Response interpret(@HeaderParam(HttpHeaders.ACCEPT_LANGUAGE) @ApiParam(value = "language") String language,
|
||||
public Response interpret(
|
||||
@HeaderParam(HttpHeaders.ACCEPT_LANGUAGE) @ApiParam(value = "language") @Nullable String language,
|
||||
@ApiParam(value = "text to interpret", required = true) String text,
|
||||
@PathParam("id") @ApiParam(value = "interpreter id", required = true) String id) {
|
||||
@PathParam("id") @ApiParam(value = "interpreter id") String id) {
|
||||
final Locale locale = localeService.getLocale(language);
|
||||
HumanLanguageInterpreter hli = voiceManager.getHLI(id);
|
||||
if (hli != null) {
|
||||
if (hli == null) {
|
||||
return JSONResponse.createErrorResponse(Status.NOT_FOUND, "No interpreter found");
|
||||
}
|
||||
|
||||
try {
|
||||
hli.interpret(locale, text);
|
||||
return Response.ok(null, MediaType.TEXT_PLAIN).build();
|
||||
} catch (InterpretationException e) {
|
||||
return JSONResponse.createErrorResponse(Status.BAD_REQUEST, e.getMessage());
|
||||
}
|
||||
} else {
|
||||
return JSONResponse.createErrorResponse(Status.NOT_FOUND, "Interpreter not found");
|
||||
}
|
||||
}
|
||||
|
||||
@POST
|
||||
@ -167,20 +152,21 @@ public class VoiceResource implements RESTResource {
|
||||
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK"),
|
||||
@ApiResponse(code = 404, message = "No human language interpreter was found."),
|
||||
@ApiResponse(code = 400, message = "interpretation exception occurs") })
|
||||
public Response interpret(@HeaderParam(HttpHeaders.ACCEPT_LANGUAGE) @ApiParam(value = "language") String language,
|
||||
public Response interpret(
|
||||
@HeaderParam(HttpHeaders.ACCEPT_LANGUAGE) @ApiParam(value = "language") @Nullable String language,
|
||||
@ApiParam(value = "text to interpret", required = true) String text) {
|
||||
final Locale locale = localeService.getLocale(language);
|
||||
HumanLanguageInterpreter hli = voiceManager.getHLI();
|
||||
if (hli != null) {
|
||||
if (hli == null) {
|
||||
return JSONResponse.createErrorResponse(Status.NOT_FOUND, "No interpreter found");
|
||||
}
|
||||
|
||||
try {
|
||||
hli.interpret(locale, text);
|
||||
return Response.ok(null, MediaType.TEXT_PLAIN).build();
|
||||
} catch (InterpretationException e) {
|
||||
return JSONResponse.createErrorResponse(Status.BAD_REQUEST, e.getMessage());
|
||||
}
|
||||
} else {
|
||||
return JSONResponse.createErrorResponse(Status.NOT_FOUND, "No interpreter found");
|
||||
}
|
||||
}
|
||||
|
||||
@GET
|
||||
@ -189,11 +175,7 @@ public class VoiceResource implements RESTResource {
|
||||
@ApiOperation(value = "Get the list of all voices.", response = VoiceDTO.class, responseContainer = "List")
|
||||
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK") })
|
||||
public Response getVoices() {
|
||||
Collection<Voice> voices = voiceManager.getAllVoices();
|
||||
List<VoiceDTO> dtos = new ArrayList<>(voices.size());
|
||||
for (Voice voice : voices) {
|
||||
dtos.add(VoiceMapper.map(voice));
|
||||
}
|
||||
List<VoiceDTO> dtos = voiceManager.getAllVoices().stream().map(VoiceMapper::map).collect(Collectors.toList());
|
||||
return Response.ok(dtos).build();
|
||||
}
|
||||
|
||||
@ -205,12 +187,12 @@ public class VoiceResource implements RESTResource {
|
||||
@ApiResponse(code = 404, message = "No default voice was found.") })
|
||||
public Response getDefaultVoice() {
|
||||
Voice voice = voiceManager.getDefaultVoice();
|
||||
if (voice != null) {
|
||||
VoiceDTO dto = VoiceMapper.map(voice);
|
||||
return Response.ok(dto).build();
|
||||
} else {
|
||||
if (voice == null) {
|
||||
return JSONResponse.createErrorResponse(Status.NOT_FOUND, "Default voice not found");
|
||||
}
|
||||
|
||||
VoiceDTO dto = VoiceMapper.map(voice);
|
||||
return Response.ok(dto).build();
|
||||
}
|
||||
|
||||
@POST
|
||||
@ -219,14 +201,9 @@ public class VoiceResource implements RESTResource {
|
||||
@ApiOperation(value = "Speaks a given text with a given voice through the given audio sink.")
|
||||
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK") })
|
||||
public Response say(@ApiParam(value = "text to speak", required = true) String text,
|
||||
@ApiParam(value = "voice id", required = false) @QueryParam("voiceid") String voiceId,
|
||||
@ApiParam(value = "audio sink id", required = false) @QueryParam("sinkid") String sinkId) {
|
||||
@QueryParam("voiceid") @ApiParam(value = "voice id") @Nullable String voiceId,
|
||||
@QueryParam("sinkid") @ApiParam(value = "audio sink id") @Nullable String sinkId) {
|
||||
voiceManager.say(text, voiceId, sinkId);
|
||||
return Response.ok(null, MediaType.TEXT_PLAIN).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSatisfied() {
|
||||
return voiceManager != null && localeService != null;
|
||||
}
|
||||
}
|
||||
|
@ -12,20 +12,15 @@
|
||||
*/
|
||||
package org.openhab.core.io.rest;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* This is a marker interface for REST resource implementations
|
||||
*
|
||||
* @author Kai Kreuzer - Initial contribution
|
||||
* @author Stefan Triller - Added default implementation for isSatisfied
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public interface RESTResource {
|
||||
|
||||
/**
|
||||
* Method used to determine availability of a RESTResource
|
||||
*
|
||||
* @return true if this RESTResource is ready to process requests, false otherwise.
|
||||
*/
|
||||
default boolean isSatisfied() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -1,62 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.io.rest.internal.filter;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import javax.ws.rs.container.ContainerRequestContext;
|
||||
import javax.ws.rs.container.ContainerRequestFilter;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.Response.Status;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
|
||||
import org.openhab.core.io.rest.RESTConstants;
|
||||
import org.openhab.core.io.rest.RESTResource;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.jaxrs.whiteboard.JaxrsWhiteboardConstants;
|
||||
import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsApplicationSelect;
|
||||
import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsExtension;
|
||||
|
||||
/**
|
||||
* A filter that only affects resources implementing the {@link SatisfiableRESTResource} interface.
|
||||
* If the current request is going to be fulfilled by a Resource implementing this interface and the
|
||||
* {@link SatisfiableRESTResource#isSatisfied()} returns false then the request will be aborted with HTTP Status Code
|
||||
* 503 - Service Unavailable.
|
||||
*
|
||||
* @author Ivan Iliev - Initial contribution
|
||||
* @author Markus Rathgeb - Migrated to JAX-RS Whiteboard Specification
|
||||
*/
|
||||
@Component
|
||||
@JaxrsExtension
|
||||
@JaxrsApplicationSelect("(" + JaxrsWhiteboardConstants.JAX_RS_NAME + "=" + RESTConstants.JAX_RS_NAME + ")")
|
||||
public class SatisfiableResourceFilter implements ContainerRequestFilter {
|
||||
|
||||
@Override
|
||||
public void filter(ContainerRequestContext ctx) throws IOException {
|
||||
UriInfo uriInfo = ctx.getUriInfo();
|
||||
|
||||
if (uriInfo != null) {
|
||||
List<Object> matchedResources = uriInfo.getMatchedResources();
|
||||
|
||||
if (matchedResources != null && !matchedResources.isEmpty()) {
|
||||
// current resource is always first as per documentation
|
||||
Object matchedResource = matchedResources.get(0);
|
||||
|
||||
if (matchedResource instanceof RESTResource && !((RESTResource) matchedResource).isSatisfied()) {
|
||||
ctx.abortWith(Response.status(Status.SERVICE_UNAVAILABLE).build());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,93 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.io.rest.internal.filter;
|
||||
|
||||
import static java.util.Collections.singletonList;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.ArgumentMatchers.isA;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.ws.rs.container.ContainerRequestContext;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.Response.Status;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnit;
|
||||
import org.mockito.junit.MockitoRule;
|
||||
import org.openhab.core.io.rest.RESTResource;
|
||||
|
||||
/**
|
||||
* Test for {@link SatisfiableResourceFilter}
|
||||
*
|
||||
* @author Ivan Iliev - Initial contribution
|
||||
* @author Wouter Born - Migrate tests from Groovy to Java and use Mockito
|
||||
*/
|
||||
public class SatisfiableResourceFilterTest {
|
||||
|
||||
private @Mock ContainerRequestContext context;
|
||||
private @Mock UriInfo uriInfo;
|
||||
private @Mock RESTResource resource;
|
||||
|
||||
public @Rule MockitoRule mockitoRule = MockitoJUnit.rule();
|
||||
|
||||
private SatisfiableResourceFilter filter = new SatisfiableResourceFilter();
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
when(context.getUriInfo()).thenReturn(uriInfo);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithBasicRESTResource() throws IOException {
|
||||
when(uriInfo.getMatchedResources()).thenReturn(singletonList(new RESTResource() {
|
||||
}));
|
||||
|
||||
filter.filter(context);
|
||||
|
||||
verify(context, never()).abortWith(isA(Response.class));
|
||||
verify(uriInfo).getMatchedResources();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithSatisfiableRESTResourceSatisfied() throws IOException {
|
||||
when(uriInfo.getMatchedResources()).thenReturn(singletonList(resource));
|
||||
when(resource.isSatisfied()).thenReturn(true);
|
||||
|
||||
filter.filter(context);
|
||||
|
||||
verify(context, never()).abortWith(isA(Response.class));
|
||||
verify(uriInfo).getMatchedResources();
|
||||
verify(resource, atLeastOnce()).isSatisfied();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithSatisfiableRESTResourceNOTSatisfied() throws IOException {
|
||||
when(uriInfo.getMatchedResources()).thenReturn(singletonList(resource));
|
||||
when(resource.isSatisfied()).thenReturn(false);
|
||||
|
||||
filter.filter(context);
|
||||
|
||||
ArgumentCaptor<Response> captor = ArgumentCaptor.forClass(Response.class);
|
||||
verify(context, times(1)).abortWith(captor.capture());
|
||||
assertEquals(Status.SERVICE_UNAVAILABLE.getStatusCode(), captor.getValue().getStatus());
|
||||
verify(uriInfo).getMatchedResources();
|
||||
verify(resource, atLeastOnce()).isSatisfied();
|
||||
}
|
||||
}
|
@ -12,6 +12,7 @@
|
||||
*/
|
||||
package org.openhab.core.thing.profiles.dto;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.core.thing.profiles.ProfileType;
|
||||
import org.openhab.core.thing.profiles.TriggerProfileType;
|
||||
|
||||
@ -21,6 +22,7 @@ import org.openhab.core.thing.profiles.TriggerProfileType;
|
||||
*
|
||||
* @author Stefan Triller - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class ProfileTypeDTOMapper {
|
||||
|
||||
/**
|
||||
|
@ -20,16 +20,17 @@ import javax.ws.rs.GET;
|
||||
import javax.ws.rs.HeaderParam;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.core.io.rest.LocaleService;
|
||||
import org.openhab.core.io.rest.RESTConstants;
|
||||
import org.openhab.core.io.rest.RESTResource;
|
||||
import org.openhab.core.ui.icon.IconProvider;
|
||||
import org.openhab.core.ui.icon.IconSet;
|
||||
import org.osgi.service.component.annotations.Activate;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Reference;
|
||||
import org.osgi.service.component.annotations.ReferenceCardinality;
|
||||
@ -42,6 +43,7 @@ import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsResource;
|
||||
|
||||
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;
|
||||
|
||||
@ -58,14 +60,20 @@ import io.swagger.annotations.ApiResponses;
|
||||
@JSONRequired
|
||||
@Path(IconSetResource.PATH_ICONSETS)
|
||||
@Api(IconSetResource.PATH_ICONSETS)
|
||||
@NonNullByDefault
|
||||
public class IconSetResource implements RESTResource {
|
||||
|
||||
/** The URI path to this resource */
|
||||
public static final String PATH_ICONSETS = "iconsets";
|
||||
|
||||
private List<IconProvider> iconProviders = new ArrayList<>(5);
|
||||
private final List<IconProvider> iconProviders = new ArrayList<>(5);
|
||||
|
||||
private LocaleService localeService;
|
||||
private final LocaleService localeService;
|
||||
|
||||
@Activate
|
||||
public IconSetResource(final @Reference LocaleService localeService) {
|
||||
this.localeService = localeService;
|
||||
}
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC)
|
||||
protected void addIconProvider(IconProvider iconProvider) {
|
||||
@ -76,23 +84,11 @@ public class IconSetResource implements RESTResource {
|
||||
this.iconProviders.remove(iconProvider);
|
||||
}
|
||||
|
||||
@Reference
|
||||
protected void setLocaleService(LocaleService localeService) {
|
||||
this.localeService = localeService;
|
||||
}
|
||||
|
||||
protected void unsetLocaleService(LocaleService localeService) {
|
||||
this.localeService = null;
|
||||
}
|
||||
|
||||
@Context
|
||||
UriInfo uriInfo;
|
||||
|
||||
@GET
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@ApiOperation(value = "Gets all icon sets.")
|
||||
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK") })
|
||||
public Response getAll(@HeaderParam("Accept-Language") String language) {
|
||||
public Response getAll(@HeaderParam("Accept-Language") @ApiParam(value = "language") @Nullable String language) {
|
||||
Locale locale = localeService.getLocale(language);
|
||||
|
||||
List<IconSet> iconSets = new ArrayList<>(iconProviders.size());
|
||||
|
@ -14,13 +14,15 @@ package org.openhab.core.io.rest.core.internal.discovery;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.mockito.MockitoAnnotations.initMocks;
|
||||
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.Response.Status;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mock;
|
||||
import org.openhab.core.config.core.ConfigDescriptionRegistry;
|
||||
import org.openhab.core.config.discovery.inbox.Inbox;
|
||||
import org.openhab.core.test.java.JavaOSGiTest;
|
||||
@ -41,32 +43,32 @@ public class InboxResourceOSGITest extends JavaOSGiTest {
|
||||
private final Thing testThing = ThingBuilder.create(testTypeUID, testUID).build();
|
||||
private final String testThingLabel = "dummy_thing";
|
||||
|
||||
private @Mock Inbox inbox;
|
||||
|
||||
@Before
|
||||
public void setup() throws Exception {
|
||||
ConfigDescriptionRegistry configDescRegistry = getService(ConfigDescriptionRegistry.class);
|
||||
assertFalse(configDescRegistry == null);
|
||||
initMocks(this);
|
||||
|
||||
registerService(new InboxResource(), InboxResource.class.getName());
|
||||
ConfigDescriptionRegistry configDescRegistry = getService(ConfigDescriptionRegistry.class);
|
||||
assertNotNull(configDescRegistry);
|
||||
|
||||
registerService(new InboxResource(inbox), InboxResource.class.getName());
|
||||
resource = getService(InboxResource.class);
|
||||
assertFalse(resource == null);
|
||||
assertNotNull(resource);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void assertThatApproveApprovesThingsWhichAreInTheInbox() {
|
||||
Inbox inbox = mock(Inbox.class);
|
||||
when(inbox.approve(any(), any())).thenReturn(testThing);
|
||||
|
||||
resource.setInbox(inbox);
|
||||
Response reponse = resource.approve(null, testThing.getUID().toString(), testThingLabel);
|
||||
assertTrue(reponse.getStatusInfo().getStatusCode() == Status.OK.getStatusCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void assertThatApproveDoesntApproveThingsWhichAreNotInTheInbox() {
|
||||
Inbox inbox = mock(Inbox.class);
|
||||
when(inbox.approve(any(), any())).thenThrow(new IllegalArgumentException());
|
||||
|
||||
resource.setInbox(inbox);
|
||||
Response reponse = resource.approve(null, testThing.getUID().toString(), testThingLabel);
|
||||
assertTrue(reponse.getStatusInfo().getStatusCode() == Status.NOT_FOUND.getStatusCode());
|
||||
}
|
||||
|
@ -51,6 +51,7 @@ import org.openhab.core.library.items.DimmerItem;
|
||||
import org.openhab.core.library.items.StringItem;
|
||||
import org.openhab.core.library.items.SwitchItem;
|
||||
import org.openhab.core.test.java.JavaOSGiTest;
|
||||
import org.openhab.core.test.storage.VolatileStorageService;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonParser;
|
||||
@ -72,8 +73,7 @@ public class ItemResourceOSGiTest extends JavaOSGiTest {
|
||||
private GenericItem item3;
|
||||
private GenericItem item4;
|
||||
|
||||
@Mock
|
||||
private ItemProvider itemProvider;
|
||||
private @Mock ItemProvider itemProvider;
|
||||
|
||||
private UriInfo uriInfo;
|
||||
private HttpHeaders httpHeaders;
|
||||
@ -85,6 +85,8 @@ public class ItemResourceOSGiTest extends JavaOSGiTest {
|
||||
public void setup() {
|
||||
initMocks(this);
|
||||
|
||||
registerService(new VolatileStorageService());
|
||||
|
||||
itemResource = getService(RESTResource.class, ItemResource.class);
|
||||
assertNotNull(itemResource);
|
||||
|
||||
|
@ -15,6 +15,7 @@ package org.openhab.core.io.rest.core.internal.persistence;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.mockito.MockitoAnnotations.initMocks;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
@ -23,7 +24,10 @@ import java.util.TimeZone;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mock;
|
||||
import org.openhab.core.i18n.TimeZoneProvider;
|
||||
import org.openhab.core.io.rest.LocaleService;
|
||||
import org.openhab.core.items.ItemRegistry;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.persistence.HistoricItem;
|
||||
import org.openhab.core.persistence.PersistenceServiceRegistry;
|
||||
@ -44,9 +48,16 @@ public class PersistenceResourceTest {
|
||||
private PersistenceResource pResource;
|
||||
private List<HistoricItem> items;
|
||||
|
||||
private @Mock ItemRegistry itemRegistry;
|
||||
private @Mock LocaleService localeService;
|
||||
private @Mock PersistenceServiceRegistry persistenceServiceRegistry;
|
||||
private @Mock TimeZoneProvider timeZoneProvider;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
pResource = new PersistenceResource();
|
||||
initMocks(this);
|
||||
|
||||
pResource = new PersistenceResource(itemRegistry, localeService, persistenceServiceRegistry, timeZoneProvider);
|
||||
|
||||
int startValue = 2016;
|
||||
int endValue = 2018;
|
||||
@ -78,20 +89,12 @@ public class PersistenceResourceTest {
|
||||
QueryablePersistenceService pService = mock(QueryablePersistenceService.class);
|
||||
when(pService.query(any())).thenReturn(items);
|
||||
|
||||
TimeZoneProvider timeZoneProvider = mock(TimeZoneProvider.class);
|
||||
when(persistenceServiceRegistry.get(PERSISTENCE_SERVICE_ID)).thenReturn(pService);
|
||||
when(timeZoneProvider.getTimeZone()).thenReturn(TimeZone.getDefault().toZoneId());
|
||||
|
||||
PersistenceServiceRegistry pServiceRegistry = mock(PersistenceServiceRegistry.class);
|
||||
when(pServiceRegistry.get(PERSISTENCE_SERVICE_ID)).thenReturn(pService);
|
||||
|
||||
pResource.setPersistenceServiceRegistry(pServiceRegistry);
|
||||
pResource.setTimeZoneProvider(timeZoneProvider);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetPersistenceItemData() {
|
||||
// pResource.httpGetPersistenceItemData(headers, serviceId, itemName, startTime, endTime, pageNumber,
|
||||
// pageLength, boundary)
|
||||
ItemHistoryDTO dto = pResource.createDTO(PERSISTENCE_SERVICE_ID, "testItem", null, null, 1, 5, false);
|
||||
|
||||
assertEquals(5, Integer.parseInt(dto.datapoints));
|
||||
|
@ -15,7 +15,8 @@ package org.openhab.core.io.rest.core.internal.profile;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.mockito.MockitoAnnotations.initMocks;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@ -24,6 +25,8 @@ import java.util.stream.Stream;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mock;
|
||||
import org.openhab.core.io.rest.LocaleService;
|
||||
import org.openhab.core.test.java.JavaTest;
|
||||
import org.openhab.core.thing.profiles.ProfileType;
|
||||
import org.openhab.core.thing.profiles.ProfileTypeBuilder;
|
||||
@ -42,7 +45,7 @@ import org.openhab.core.thing.type.ChannelTypeUID;
|
||||
*/
|
||||
public class ProfileTypeResourceTest extends JavaTest {
|
||||
|
||||
private ProfileTypeResource ressource;
|
||||
private ProfileTypeResource resource;
|
||||
|
||||
// UIDs for state profile types
|
||||
private final ProfileTypeUID stateProfileTypeUID1 = new ProfileTypeUID("my:stateProfile1");
|
||||
@ -67,12 +70,15 @@ public class ProfileTypeResourceTest extends JavaTest {
|
||||
private final ChannelType otherTriggerChannelType = ChannelTypeBuilder
|
||||
.trigger(otherTriggerChannelTypeUID, "channel1").build();
|
||||
|
||||
private @Mock ChannelTypeRegistry channelTypeRegistry;
|
||||
private @Mock LocaleService localeService;
|
||||
private @Mock ProfileTypeRegistry profileTypeRegistry;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
ressource = new ProfileTypeResource();
|
||||
initMocks(this);
|
||||
|
||||
ChannelTypeRegistry ctRegistry = mock(ChannelTypeRegistry.class);
|
||||
ProfileTypeRegistry ptRegistry = mock(ProfileTypeRegistry.class);
|
||||
resource = new ProfileTypeResource(channelTypeRegistry, localeService, profileTypeRegistry);
|
||||
|
||||
List<ProfileType> profileTypes = new ArrayList<>();
|
||||
ProfileType pt1 = ProfileTypeBuilder.newState(stateProfileTypeUID1, "profile1")
|
||||
@ -87,20 +93,17 @@ public class ProfileTypeResourceTest extends JavaTest {
|
||||
profileTypes.add(pt3);
|
||||
profileTypes.add(pt4);
|
||||
|
||||
when(ptRegistry.getProfileTypes(any())).thenReturn(profileTypes);
|
||||
when(ctRegistry.getChannelType(pt1ChannelType1UID, null)).thenReturn(pt1ChannelType1);
|
||||
when(ctRegistry.getChannelType(pt3ChannelType1UID, null)).thenReturn(pt3ChannelType1);
|
||||
when(profileTypeRegistry.getProfileTypes(any())).thenReturn(profileTypes);
|
||||
when(channelTypeRegistry.getChannelType(pt1ChannelType1UID, null)).thenReturn(pt1ChannelType1);
|
||||
when(channelTypeRegistry.getChannelType(pt3ChannelType1UID, null)).thenReturn(pt3ChannelType1);
|
||||
|
||||
when(ctRegistry.getChannelType(otherStateChannelTypeUID, null)).thenReturn(otherStateChannelType);
|
||||
when(ctRegistry.getChannelType(otherTriggerChannelTypeUID, null)).thenReturn(otherTriggerChannelType);
|
||||
|
||||
ressource.setChannelTypeRegistry(ctRegistry);
|
||||
ressource.setProfileTypeRegistry(ptRegistry);
|
||||
when(channelTypeRegistry.getChannelType(otherStateChannelTypeUID, null)).thenReturn(otherStateChannelType);
|
||||
when(channelTypeRegistry.getChannelType(otherTriggerChannelTypeUID, null)).thenReturn(otherTriggerChannelType);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAll() {
|
||||
Stream<ProfileTypeDTO> result = ressource.getProfileTypes(null, null, null);
|
||||
Stream<ProfileTypeDTO> result = resource.getProfileTypes(null, null, null);
|
||||
|
||||
List<ProfileTypeDTO> list = result.collect(Collectors.toList());
|
||||
assertThat(list.size(), is(4));
|
||||
@ -108,7 +111,7 @@ public class ProfileTypeResourceTest extends JavaTest {
|
||||
|
||||
@Test
|
||||
public void testGetProfileTypesForStateChannel1() {
|
||||
Stream<ProfileTypeDTO> result = ressource.getProfileTypes(null, pt1ChannelType1UID.toString(), null);
|
||||
Stream<ProfileTypeDTO> result = resource.getProfileTypes(null, pt1ChannelType1UID.toString(), null);
|
||||
List<ProfileTypeDTO> list = result.collect(Collectors.toList());
|
||||
|
||||
// should be both state profiles because the second state profile supports ALL item types on the channel side
|
||||
@ -121,7 +124,7 @@ public class ProfileTypeResourceTest extends JavaTest {
|
||||
|
||||
@Test
|
||||
public void testGetProfileTypesForOtherChannel() {
|
||||
Stream<ProfileTypeDTO> result = ressource.getProfileTypes(null, otherStateChannelTypeUID.toString(), null);
|
||||
Stream<ProfileTypeDTO> result = resource.getProfileTypes(null, otherStateChannelTypeUID.toString(), null);
|
||||
List<ProfileTypeDTO> list = result.collect(Collectors.toList());
|
||||
|
||||
// should be only the second state profile because the first one is restricted to another item type on the
|
||||
@ -136,7 +139,7 @@ public class ProfileTypeResourceTest extends JavaTest {
|
||||
|
||||
@Test
|
||||
public void testGetProfileTypesForTriggerChannel1() {
|
||||
Stream<ProfileTypeDTO> result = ressource.getProfileTypes(null, pt3ChannelType1UID.toString(), null);
|
||||
Stream<ProfileTypeDTO> result = resource.getProfileTypes(null, pt3ChannelType1UID.toString(), null);
|
||||
List<ProfileTypeDTO> list = result.collect(Collectors.toList());
|
||||
|
||||
// should be both trigger profiles because the second trigger profile supports ALL channel types
|
||||
@ -149,7 +152,7 @@ public class ProfileTypeResourceTest extends JavaTest {
|
||||
|
||||
@Test
|
||||
public void testGetProfileTypesForTriggerChannel2() {
|
||||
Stream<ProfileTypeDTO> result = ressource.getProfileTypes(null, otherTriggerChannelTypeUID.toString(), null);
|
||||
Stream<ProfileTypeDTO> result = resource.getProfileTypes(null, otherTriggerChannelTypeUID.toString(), null);
|
||||
List<ProfileTypeDTO> list = result.collect(Collectors.toList());
|
||||
|
||||
// should be only the second trigger profile because the first one is restricted to another channel type UID
|
||||
|
Loading…
Reference in New Issue
Block a user