[rest] Added support for default values containing a list of configuration options (#1031)

* Added support for default values containing a list of configuration options

Signed-off-by: Christoph Weitkamp <github@christophweitkamp.de>
This commit is contained in:
Christoph Weitkamp 2019-10-14 12:51:22 +02:00 committed by Kai Kreuzer
parent b337e31621
commit d8a0225b48
5 changed files with 230 additions and 12 deletions

View File

@ -46,7 +46,7 @@ public class ConfigDescriptionDTOMapper {
return new ConfigDescriptionDTO(toDecodedString(configDescription.getUID()), parameters, parameterGroups);
}
private static String toDecodedString(URI uri) {
protected static String toDecodedString(URI uri) {
// combine these partials because URI.toString() does not decode
return uri.getScheme() + ":" + uri.getSchemeSpecificPart();
}
@ -139,7 +139,7 @@ public class ConfigDescriptionDTOMapper {
return parameterGroupBeans;
}
private static List<FilterCriteriaDTO> mapFilterCriteria(List<FilterCriteria> filterCriteria) {
protected static List<FilterCriteriaDTO> mapFilterCriteria(List<FilterCriteria> filterCriteria) {
if (filterCriteria == null) {
return null;
}
@ -150,7 +150,7 @@ public class ConfigDescriptionDTOMapper {
return result;
}
private static List<ParameterOptionDTO> mapOptions(List<ParameterOption> options) {
protected static List<ParameterOptionDTO> mapOptions(List<ParameterOption> options) {
if (options == null) {
return null;
}

View File

@ -0,0 +1,77 @@
/**
* Copyright (c) 2010-2019 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.eclipse.smarthome.io.rest.core.config;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.smarthome.config.core.ConfigDescription;
import org.eclipse.smarthome.config.core.ConfigDescriptionParameter;
import org.eclipse.smarthome.config.core.dto.ConfigDescriptionDTO;
import org.eclipse.smarthome.config.core.dto.ConfigDescriptionDTOMapper;
import org.eclipse.smarthome.config.core.dto.ConfigDescriptionParameterDTO;
import org.eclipse.smarthome.config.core.dto.ConfigDescriptionParameterGroupDTO;
/**
* The {@link EnrichedConfigDescriptionDTOMapper} is a utility class to map {@link ConfigDescription}s to config
* descriptions data transform objects {@link ConfigDescriptionDTO} containing
* {@link EnrichedConfigDescriptionParameterDTO}.
*
* @author Christoph Weitkamp - Initial contribution
*/
@NonNullByDefault
public class EnrichedConfigDescriptionDTOMapper extends ConfigDescriptionDTOMapper {
/**
* Maps configuration description into configuration description DTO object.
*
* @param configDescription the configuration description (not null)
* @return enriched configuration description DTO object
*/
public static ConfigDescriptionDTO map(ConfigDescription configDescription) {
List<ConfigDescriptionParameterGroupDTO> parameterGroups = mapParameterGroups(
configDescription.getParameterGroups());
List<ConfigDescriptionParameterDTO> parameters = mapEnrichedParameters(configDescription.getParameters());
return new ConfigDescriptionDTO(toDecodedString(configDescription.getUID()), parameters, parameterGroups);
}
/**
* Maps configuration description parameters into enriched DTO objects.
*
* @param parameters the configuration description parameters (not null)
* @return the parameter enriched DTO objects
*/
public static List<ConfigDescriptionParameterDTO> mapEnrichedParameters(
List<ConfigDescriptionParameter> parameters) {
List<ConfigDescriptionParameterDTO> configDescriptionParameterBeans = new ArrayList<>(parameters.size());
for (ConfigDescriptionParameter configDescriptionParameter : parameters) {
ConfigDescriptionParameterDTO configDescriptionParameterBean = new EnrichedConfigDescriptionParameterDTO(
configDescriptionParameter.getName(), configDescriptionParameter.getType(),
configDescriptionParameter.getMinimum(), configDescriptionParameter.getMaximum(),
configDescriptionParameter.getStepSize(), configDescriptionParameter.getPattern(),
configDescriptionParameter.isRequired(), configDescriptionParameter.isReadOnly(),
configDescriptionParameter.isMultiple(), configDescriptionParameter.getContext(),
configDescriptionParameter.getDefault(), configDescriptionParameter.getLabel(),
configDescriptionParameter.getDescription(), mapOptions(configDescriptionParameter.getOptions()),
mapFilterCriteria(configDescriptionParameter.getFilterCriteria()),
configDescriptionParameter.getGroupName(), configDescriptionParameter.isAdvanced(),
configDescriptionParameter.getLimitToOptions(), configDescriptionParameter.getMultipleLimit(),
configDescriptionParameter.getUnit(), configDescriptionParameter.getUnitLabel(),
configDescriptionParameter.isVerifyable());
configDescriptionParameterBeans.add(configDescriptionParameterBean);
}
return configDescriptionParameterBeans;
}
}

View File

@ -0,0 +1,61 @@
/**
* Copyright (c) 2010-2019 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.eclipse.smarthome.io.rest.core.config;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.smarthome.config.core.ConfigDescriptionParameter.Type;
import org.eclipse.smarthome.config.core.dto.ConfigDescriptionParameterDTO;
import org.eclipse.smarthome.config.core.dto.FilterCriteriaDTO;
import org.eclipse.smarthome.config.core.dto.ParameterOptionDTO;
/**
* This is an enriched data transfer object that is used to serialize config descriptions parameters with a list of
* default values if a configuration description defines <code>multiple="true"</code>.
*
* @author Christoph Weitkamp - Initial contribution
*/
@NonNullByDefault
public class EnrichedConfigDescriptionParameterDTO extends ConfigDescriptionParameterDTO {
private static final String DEFAULT_LIST_DELIMITER = ",";
public @Nullable Collection<String> defaultValues;
public EnrichedConfigDescriptionParameterDTO(String name, Type type, BigDecimal minimum, BigDecimal maximum,
BigDecimal stepsize, String pattern, Boolean required, Boolean readOnly, Boolean multiple, String context,
String defaultValue, String label, String description, List<ParameterOptionDTO> options,
List<FilterCriteriaDTO> filterCriteria, String groupName, Boolean advanced, Boolean limitToOptions,
Integer multipleLimit, String unit, String unitLabel, Boolean verify) {
super(name, type, minimum, maximum, stepsize, pattern, required, readOnly, multiple, context, defaultValue,
label, description, options, filterCriteria, groupName, advanced, limitToOptions, multipleLimit, unit,
unitLabel, verify);
if (multiple) {
if (defaultValue.contains(DEFAULT_LIST_DELIMITER)) {
defaultValues = Arrays.asList(defaultValue.split(DEFAULT_LIST_DELIMITER)).stream().map(v -> v.trim())
.filter(v -> !v.isEmpty()).collect(Collectors.toList());
} else {
defaultValues = Collections.singleton(defaultValue);
}
}
}
}

View File

@ -28,16 +28,17 @@ import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.UriBuilder;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.smarthome.config.core.ConfigDescription;
import org.eclipse.smarthome.config.core.ConfigDescriptionRegistry;
import org.eclipse.smarthome.config.core.dto.ConfigDescriptionDTO;
import org.eclipse.smarthome.config.core.dto.ConfigDescriptionDTOMapper;
import org.eclipse.smarthome.core.auth.Role;
import org.eclipse.smarthome.io.rest.JSONResponse;
import org.eclipse.smarthome.io.rest.LocaleService;
import org.eclipse.smarthome.io.rest.RESTResource;
import org.eclipse.smarthome.io.rest.Stream2JSONInputStream;
import org.eclipse.smarthome.io.rest.core.config.EnrichedConfigDescriptionDTOMapper;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
@ -60,14 +61,15 @@ import io.swagger.annotations.ApiResponses;
@RolesAllowed({ Role.ADMIN })
@Api(value = ConfigDescriptionResource.PATH_CONFIG_DESCRIPTIONS)
@Component
@NonNullByDefault
public class ConfigDescriptionResource implements RESTResource {
/** The URI path to this resource */
public static final String PATH_CONFIG_DESCRIPTIONS = "config-descriptions";
private ConfigDescriptionRegistry configDescriptionRegistry;
private @NonNullByDefault({}) ConfigDescriptionRegistry configDescriptionRegistry;
private LocaleService localeService;
private @NonNullByDefault({}) LocaleService localeService;
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
protected void setLocaleService(LocaleService localeService) {
@ -82,14 +84,14 @@ public class ConfigDescriptionResource implements RESTResource {
@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") String language, //
public Response getAll(
@HeaderParam("Accept-Language") @ApiParam(value = "Accept-Language") @Nullable String language, //
@QueryParam("scheme") @ApiParam(value = "scheme filter", required = false) @Nullable String scheme) {
Locale locale = localeService.getLocale(language);
Collection<ConfigDescription> configDescriptions = configDescriptionRegistry.getConfigDescriptions(locale);
return Response.ok(new Stream2JSONInputStream(configDescriptions.stream().filter(configDescription -> {
return scheme == null || scheme.equals(configDescription.getUID().getScheme());
}).map(ConfigDescriptionDTOMapper::map))).build();
}).map(EnrichedConfigDescriptionDTOMapper::map))).build();
}
@GET
@ -98,12 +100,14 @@ 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") String language,
public Response getByURI(
@HeaderParam("Accept-Language") @ApiParam(value = "Accept-Language") @Nullable String language,
@PathParam("uri") @ApiParam(value = "uri") String uri) {
Locale locale = localeService.getLocale(language);
URI uriObject = UriBuilder.fromPath(uri).build();
ConfigDescription configDescription = this.configDescriptionRegistry.getConfigDescription(uriObject, locale);
return configDescription != null ? Response.ok(ConfigDescriptionDTOMapper.map(configDescription)).build()
ConfigDescription configDescription = configDescriptionRegistry.getConfigDescription(uriObject, locale);
return configDescription != null
? Response.ok(EnrichedConfigDescriptionDTOMapper.map(configDescription)).build()
: JSONResponse.createErrorResponse(Status.NOT_FOUND, "Configuration not found: " + uri);
}

View File

@ -0,0 +1,76 @@
/**
* Copyright (c) 2010-2019 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.eclipse.smarthome.io.rest.core.config;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.assertThat;
import java.net.URI;
import java.util.Arrays;
import org.eclipse.smarthome.config.core.ConfigDescription;
import org.eclipse.smarthome.config.core.ConfigDescriptionParameter;
import org.eclipse.smarthome.config.core.ConfigDescriptionParameter.Type;
import org.eclipse.smarthome.config.core.ConfigDescriptionParameterBuilder;
import org.eclipse.smarthome.config.core.dto.ConfigDescriptionDTO;
import org.eclipse.smarthome.config.core.dto.ConfigDescriptionParameterDTO;
import org.junit.Test;
/**
* @author Christoph Weitkamp - Initial contribution
*/
public class EnrichedConfigDescriptionDTOMapperTest {
private static final URI CONFIG_URI = URI.create("system:ephemeris");
private static final String CONFIG_PARAMETER_NAME = "test";
private static final String CONFIG_PARAMETER_DEFAULT_VALUE = "first value,second value,third value";
@Test
public void testThatDefaultValueIsNotAList() {
ConfigDescriptionParameter configDescriptionParameter = ConfigDescriptionParameterBuilder
.create(CONFIG_PARAMETER_NAME, Type.TEXT).withDefault(CONFIG_PARAMETER_DEFAULT_VALUE).build();
ConfigDescription configDescription = new ConfigDescription(CONFIG_URI,
Arrays.asList(configDescriptionParameter));
ConfigDescriptionDTO cddto = EnrichedConfigDescriptionDTOMapper.map(configDescription);
assertThat(cddto.parameters.size(), is(1));
ConfigDescriptionParameterDTO cdpdto = cddto.parameters.get(0);
assertThat(cdpdto, instanceOf(EnrichedConfigDescriptionParameterDTO.class));
assertThat(cdpdto.defaultValue, is(CONFIG_PARAMETER_DEFAULT_VALUE));
EnrichedConfigDescriptionParameterDTO ecdpdto = (EnrichedConfigDescriptionParameterDTO) cdpdto;
assertThat(ecdpdto.defaultValues, is(nullValue()));
}
@SuppressWarnings("null")
@Test
public void testThatDefaultValuesAreAList() {
ConfigDescriptionParameter configDescriptionParameter = ConfigDescriptionParameterBuilder
.create(CONFIG_PARAMETER_NAME, Type.TEXT).withDefault(CONFIG_PARAMETER_DEFAULT_VALUE).withMultiple(true)
.build();
ConfigDescription configDescription = new ConfigDescription(CONFIG_URI,
Arrays.asList(configDescriptionParameter));
ConfigDescriptionDTO cddto = EnrichedConfigDescriptionDTOMapper.map(configDescription);
assertThat(cddto.parameters.size(), is(1));
ConfigDescriptionParameterDTO cdpdto = cddto.parameters.get(0);
assertThat(cdpdto, instanceOf(EnrichedConfigDescriptionParameterDTO.class));
assertThat(cdpdto.defaultValue, is(CONFIG_PARAMETER_DEFAULT_VALUE));
EnrichedConfigDescriptionParameterDTO ecdpdto = (EnrichedConfigDescriptionParameterDTO) cdpdto;
assertThat(ecdpdto.defaultValues, is(notNullValue()));
assertThat(ecdpdto.defaultValues.size(), is(3));
assertThat(ecdpdto.defaultValues, is(equalTo(Arrays.asList("first value", "second value", "third value"))));
}
}