Skip to content

Commit

Permalink
[rest] Added support for default values containing a list of configur…
Browse files Browse the repository at this point in the history
…ation options (#1031)

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

Signed-off-by: Christoph Weitkamp <github@christophweitkamp.de>
  • Loading branch information
cweitkamp authored and kaikreuzer committed Oct 14, 2019
1 parent b337e31 commit d8a0225
Show file tree
Hide file tree
Showing 5 changed files with 230 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public static ConfigDescriptionDTO map(ConfigDescription configDescription) {
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();
}
Expand Down Expand Up @@ -139,7 +139,7 @@ public static List<ConfigDescriptionParameterGroupDTO> mapParameterGroups(
return parameterGroupBeans;
}

private static List<FilterCriteriaDTO> mapFilterCriteria(List<FilterCriteria> filterCriteria) {
protected static List<FilterCriteriaDTO> mapFilterCriteria(List<FilterCriteria> filterCriteria) {
if (filterCriteria == null) {
return null;
}
Expand All @@ -150,7 +150,7 @@ private static List<FilterCriteriaDTO> mapFilterCriteria(List<FilterCriteria> fi
return result;
}

private static List<ParameterOptionDTO> mapOptions(List<ParameterOption> options) {
protected static List<ParameterOptionDTO> mapOptions(List<ParameterOption> options) {
if (options == null) {
return null;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
}

}
Original file line number Diff line number Diff line change
@@ -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);
}
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,17 @@
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;
Expand All @@ -60,14 +61,15 @@
@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) {
Expand All @@ -82,14 +84,14 @@ protected void unsetLocaleService(LocaleService localeService) {
@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
Expand All @@ -98,12 +100,14 @@ public Response getAll(@HeaderParam("Accept-Language") @ApiParam(value = "Accept
@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);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -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"))));
}

}

0 comments on commit d8a0225

Please sign in to comment.