mirror of
https://github.com/danieldemus/openhab-core.git
synced 2025-01-25 11:45:49 +01:00
[rest] Add summary option to rules, things, UI components resources (#1827)
The /things, /rules, /ui/components endpoints retrieve all objects in their entirety, which can become very big, i.e. channels, config parameters, script rule modules or trees of UI components can quickly add up to the size. When the UI simply displays a list of those objects it retrieves all this extra information but does nothing with it. This introduces an optional ?summary=true query parameter for the above resources to limit the output to pre-defined fields which are deemed most relevant for displaying these lists, omitting the rest. When the option is not set, the behavior remains unchanged so this change is not API breaking. The API version has therefore not been incremented. The client is responsible for adding the option to retrieve summarized collections instead of the entire objects. Signed-off-by: Yannick Schaus <github@schaus.net>
This commit is contained in:
parent
5330de0473
commit
065177b730
@ -21,7 +21,7 @@ import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import javax.annotation.security.RolesAllowed;
|
||||
import javax.ws.rs.Consumes;
|
||||
@ -65,9 +65,11 @@ import org.openhab.core.automation.util.ModuleBuilder;
|
||||
import org.openhab.core.automation.util.RuleBuilder;
|
||||
import org.openhab.core.config.core.ConfigUtil;
|
||||
import org.openhab.core.config.core.Configuration;
|
||||
import org.openhab.core.io.rest.DTOMapper;
|
||||
import org.openhab.core.io.rest.JSONResponse;
|
||||
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;
|
||||
@ -114,6 +116,7 @@ public class RuleResource implements RESTResource {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(RuleResource.class);
|
||||
|
||||
private final DTOMapper dtoMapper;
|
||||
private final RuleManager ruleManager;
|
||||
private final RuleRegistry ruleRegistry;
|
||||
private final ManagedRuleProvider managedRuleProvider;
|
||||
@ -122,9 +125,11 @@ public class RuleResource implements RESTResource {
|
||||
|
||||
@Activate
|
||||
public RuleResource( //
|
||||
final @Reference DTOMapper dtoMapper, //
|
||||
final @Reference RuleManager ruleManager, //
|
||||
final @Reference RuleRegistry ruleRegistry, //
|
||||
final @Reference ManagedRuleProvider managedRuleProvider) {
|
||||
this.dtoMapper = dtoMapper;
|
||||
this.ruleManager = ruleManager;
|
||||
this.ruleRegistry = ruleRegistry;
|
||||
this.managedRuleProvider = managedRuleProvider;
|
||||
@ -135,7 +140,8 @@ public class RuleResource implements RESTResource {
|
||||
@Operation(summary = "Get available rules, optionally filtered by tags and/or prefix.", responses = {
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(array = @ArraySchema(schema = @Schema(implementation = EnrichedRuleDTO.class)))) })
|
||||
public Response get(@QueryParam("prefix") final @Nullable String prefix,
|
||||
@QueryParam("tags") final @Nullable List<String> tags) {
|
||||
@QueryParam("tags") final @Nullable List<String> tags,
|
||||
@QueryParam("summary") @Parameter(description = "summary fields only") @Nullable Boolean summary) {
|
||||
// match all
|
||||
Predicate<Rule> p = r -> true;
|
||||
|
||||
@ -149,10 +155,13 @@ public class RuleResource implements RESTResource {
|
||||
// if tags is null or empty list returns all rules
|
||||
p = p.and(hasAllTags(tags));
|
||||
|
||||
final Collection<EnrichedRuleDTO> rules = ruleRegistry.stream().filter(p) // filter according to Predicates
|
||||
.map(rule -> EnrichedRuleDTOMapper.map(rule, ruleManager, managedRuleProvider)) // map matching rules
|
||||
.collect(Collectors.toList());
|
||||
return Response.ok(rules).build();
|
||||
Stream<EnrichedRuleDTO> rules = ruleRegistry.stream().filter(p) // filter according to Predicates
|
||||
.map(rule -> EnrichedRuleDTOMapper.map(rule, ruleManager, managedRuleProvider)); // map matching rules
|
||||
if (summary != null && summary == true) {
|
||||
rules = dtoMapper.limitToFields(rules, "uid,templateUID,name,visibility,description,status,tags,editable");
|
||||
}
|
||||
|
||||
return Response.ok(new Stream2JSONInputStream(rules)).build();
|
||||
}
|
||||
|
||||
@POST
|
||||
|
@ -56,6 +56,7 @@ import org.openhab.core.config.core.Configuration;
|
||||
import org.openhab.core.config.core.status.ConfigStatusInfo;
|
||||
import org.openhab.core.config.core.status.ConfigStatusService;
|
||||
import org.openhab.core.config.core.validation.ConfigValidationException;
|
||||
import org.openhab.core.io.rest.DTOMapper;
|
||||
import org.openhab.core.io.rest.JSONResponse;
|
||||
import org.openhab.core.io.rest.LocaleService;
|
||||
import org.openhab.core.io.rest.RESTConstants;
|
||||
@ -148,6 +149,7 @@ public class ThingResource implements RESTResource {
|
||||
/** The URI path to this resource */
|
||||
public static final String PATH_THINGS = "things";
|
||||
|
||||
private final DTOMapper dtoMapper;
|
||||
private final ChannelTypeRegistry channelTypeRegistry;
|
||||
private final ConfigStatusService configStatusService;
|
||||
private final ConfigDescriptionRegistry configDescRegistry;
|
||||
@ -169,7 +171,7 @@ public class ThingResource implements RESTResource {
|
||||
|
||||
@Activate
|
||||
public ThingResource( //
|
||||
final @Reference ChannelTypeRegistry channelTypeRegistry,
|
||||
final @Reference DTOMapper dtoMapper, final @Reference ChannelTypeRegistry channelTypeRegistry,
|
||||
final @Reference ConfigStatusService configStatusService,
|
||||
final @Reference ConfigDescriptionRegistry configDescRegistry,
|
||||
final @Reference FirmwareRegistry firmwareRegistry,
|
||||
@ -185,6 +187,7 @@ public class ThingResource implements RESTResource {
|
||||
final @Reference ThingRegistry thingRegistry,
|
||||
final @Reference ThingStatusInfoI18nLocalizationService thingStatusInfoI18nLocalizationService,
|
||||
final @Reference ThingTypeRegistry thingTypeRegistry) {
|
||||
this.dtoMapper = dtoMapper;
|
||||
this.channelTypeRegistry = channelTypeRegistry;
|
||||
this.configStatusService = configStatusService;
|
||||
this.configDescRegistry = configDescRegistry;
|
||||
@ -294,11 +297,16 @@ public class ThingResource implements RESTResource {
|
||||
@Operation(summary = "Get all available things.", responses = {
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(array = @ArraySchema(schema = @Schema(implementation = EnrichedThingDTO.class), uniqueItems = true))) })
|
||||
public Response getAll(
|
||||
@HeaderParam(HttpHeaders.ACCEPT_LANGUAGE) @Parameter(description = "language") @Nullable String language) {
|
||||
@HeaderParam(HttpHeaders.ACCEPT_LANGUAGE) @Parameter(description = "language") @Nullable String language,
|
||||
@QueryParam("summary") @Parameter(description = "summary fields only") @Nullable Boolean summary) {
|
||||
final Locale locale = localeService.getLocale(language);
|
||||
|
||||
Stream<EnrichedThingDTO> thingStream = thingRegistry.stream().map(t -> convertToEnrichedThingDTO(t, locale))
|
||||
.distinct();
|
||||
if (summary != null && summary == true) {
|
||||
thingStream = dtoMapper.limitToFields(thingStream,
|
||||
"UID,label,bridgeUID,thingTypeUID,statusInfo,location,editable");
|
||||
}
|
||||
return Response.ok(new Stream2JSONInputStream(thingStream)).build();
|
||||
}
|
||||
|
||||
|
@ -13,6 +13,8 @@
|
||||
package org.openhab.core.io.rest.ui.internal;
|
||||
|
||||
import java.security.InvalidParameterException;
|
||||
import java.util.Date;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import javax.annotation.security.RolesAllowed;
|
||||
@ -23,11 +25,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.QueryParam;
|
||||
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.io.rest.RESTConstants;
|
||||
import org.openhab.core.io.rest.RESTResource;
|
||||
@ -48,6 +52,7 @@ import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsName;
|
||||
import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsResource;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.media.ArraySchema;
|
||||
import io.swagger.v3.oas.annotations.media.Content;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
@ -101,9 +106,26 @@ public class UIResource implements RESTResource {
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Get all registered UI components in the specified namespace.", responses = {
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(array = @ArraySchema(schema = @Schema(implementation = RootUIComponent.class)))) })
|
||||
public Response getAllComponents(@PathParam("namespace") String namespace) {
|
||||
public Response getAllComponents(@PathParam("namespace") String namespace,
|
||||
@QueryParam("summary") @Parameter(description = "summary fields only") @Nullable Boolean summary) {
|
||||
UIComponentRegistry registry = componentRegistryFactory.getRegistry(namespace);
|
||||
Stream<RootUIComponent> components = registry.getAll().stream();
|
||||
if (summary != null && summary == true) {
|
||||
components = components.map(c -> {
|
||||
RootUIComponent component = new RootUIComponent(c.getUID(), c.getType());
|
||||
@Nullable
|
||||
Set<String> tags = c.getTags();
|
||||
if (tags != null) {
|
||||
component.addTags(c.getTags());
|
||||
}
|
||||
@Nullable
|
||||
Date timestamp = c.getTimestamp();
|
||||
if (timestamp != null) {
|
||||
component.setTimestamp(timestamp);
|
||||
}
|
||||
return component;
|
||||
});
|
||||
}
|
||||
return Response.ok(new Stream2JSONInputStream(components)).build();
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user