mirror of
https://github.com/danieldemus/openhab-core.git
synced 2026-07-29 12:34:22 +02:00
Allow multiple default values to contain an escaped comma (#4657)
* Allow multiple default values to contain an escaped comma An comma character can be a part of the value when escaped with a backslash. The backslash will be removed, i.e. `\,` -> `,` To have an actual backslash and comma, add an extra backslash, i.e. `\\,` -> `\,` Signed-off-by: Jimmy Tanagra <jcode@tanagra.id.au>
This commit is contained in:
+26
-30
@@ -23,6 +23,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Objects;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
@@ -51,7 +52,7 @@ import org.slf4j.LoggerFactory;
|
||||
@NonNullByDefault
|
||||
public class ConfigUtil {
|
||||
|
||||
private static final String DEFAULT_LIST_DELIMITER = ",";
|
||||
private static final Pattern DEFAULT_LIST_SPLITTER = Pattern.compile("(?<!\\\\),");
|
||||
|
||||
/**
|
||||
* Maps the provided (default) value of the given {@link ConfigDescriptionParameter} to the corresponding Java type.
|
||||
@@ -61,10 +62,29 @@ public class ConfigUtil {
|
||||
*
|
||||
* @param parameter the {@link ConfigDescriptionParameter} which default value should be normalized (must not be
|
||||
* null)
|
||||
* @return the given value as the corresponding Java type or <code>null</code> if the value could not be converted
|
||||
* @return the default value as the corresponding Java type, or
|
||||
* a <code>List</code> of the corresponding Java type if the parameter contains multiple values.
|
||||
* Returns <code>null</code> if the value could not be converted.
|
||||
*/
|
||||
public static @Nullable Object getDefaultValueAsCorrectType(ConfigDescriptionParameter parameter) {
|
||||
return getDefaultValueAsCorrectType(parameter.getName(), parameter.getType(), parameter.getDefault());
|
||||
if (parameter.isMultiple()) {
|
||||
List<Object> defaultValues = Stream.of(DEFAULT_LIST_SPLITTER.split(parameter.getDefault())) //
|
||||
.map(value -> value.trim().replace("\\,", ",")) //
|
||||
.filter(not(String::isEmpty)) //
|
||||
.map(value -> getDefaultValueAsCorrectType(parameter.getName(), parameter.getType(), value)) //
|
||||
.filter(Objects::nonNull) //
|
||||
.toList();
|
||||
|
||||
Integer multipleLimit = parameter.getMultipleLimit();
|
||||
if (multipleLimit != null && defaultValues.size() > multipleLimit.intValue()) {
|
||||
LoggerFactory.getLogger(ConfigUtil.class).warn(
|
||||
"Number of default values ({}) for parameter '{}' is greater than multiple limit ({})",
|
||||
defaultValues.size(), parameter.getName(), multipleLimit);
|
||||
}
|
||||
return defaultValues;
|
||||
} else {
|
||||
return getDefaultValueAsCorrectType(parameter.getName(), parameter.getType(), parameter.getDefault());
|
||||
}
|
||||
}
|
||||
|
||||
static @Nullable Object getDefaultValueAsCorrectType(String parameterName, Type parameterType,
|
||||
@@ -117,33 +137,9 @@ public class ConfigUtil {
|
||||
for (ConfigDescriptionParameter parameter : configDescription.getParameters()) {
|
||||
String defaultValue = parameter.getDefault();
|
||||
if (defaultValue != null && configuration.get(parameter.getName()) == null) {
|
||||
if (parameter.isMultiple()) {
|
||||
if (defaultValue.contains(DEFAULT_LIST_DELIMITER)) {
|
||||
List<Object> values = (List<Object>) Stream.of(defaultValue.split(DEFAULT_LIST_DELIMITER))
|
||||
.map(String::trim) //
|
||||
.filter(not(String::isEmpty)) //
|
||||
.map(value -> ConfigUtil.getDefaultValueAsCorrectType(parameter.getName(),
|
||||
parameter.getType(), value)) //
|
||||
.filter(Objects::nonNull) //
|
||||
.toList();
|
||||
Integer multipleLimit = parameter.getMultipleLimit();
|
||||
if (multipleLimit != null && values.size() > multipleLimit.intValue()) {
|
||||
LoggerFactory.getLogger(ConfigUtil.class).warn(
|
||||
"Number of default values ({}) for parameter '{}' is greater than multiple limit ({})",
|
||||
values.size(), parameter.getName(), multipleLimit);
|
||||
}
|
||||
configuration.put(parameter.getName(), values);
|
||||
} else {
|
||||
Object value = ConfigUtil.getDefaultValueAsCorrectType(parameter);
|
||||
if (value != null) {
|
||||
configuration.put(parameter.getName(), List.of(value));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Object value = ConfigUtil.getDefaultValueAsCorrectType(parameter);
|
||||
if (value != null) {
|
||||
configuration.put(parameter.getName(), value);
|
||||
}
|
||||
Object value = ConfigUtil.getDefaultValueAsCorrectType(parameter);
|
||||
if (value != null) {
|
||||
configuration.put(parameter.getName(), value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+12
-9
@@ -15,10 +15,11 @@ package org.openhab.core.io.rest.core.config;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.openhab.core.config.core.ConfigDescriptionParameter;
|
||||
import org.openhab.core.config.core.ConfigDescriptionParameter.Type;
|
||||
import org.openhab.core.config.core.ConfigDescriptionParameterBuilder;
|
||||
import org.openhab.core.config.core.ConfigUtil;
|
||||
import org.openhab.core.config.core.dto.ConfigDescriptionParameterDTO;
|
||||
import org.openhab.core.config.core.dto.FilterCriteriaDTO;
|
||||
import org.openhab.core.config.core.dto.ParameterOptionDTO;
|
||||
@@ -26,15 +27,18 @@ import org.openhab.core.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>.
|
||||
*
|
||||
* The default values are split by a comma. Individual values that contain a comma
|
||||
* must be escaped with a backslash character. The backslash character will be
|
||||
* removed from the value.
|
||||
*
|
||||
* @author Christoph Weitkamp - Initial contribution
|
||||
*/
|
||||
public class EnrichedConfigDescriptionParameterDTO extends ConfigDescriptionParameterDTO {
|
||||
|
||||
private static final String DEFAULT_LIST_DELIMITER = ",";
|
||||
|
||||
public Collection<String> defaultValues;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
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,
|
||||
@@ -45,11 +49,10 @@ public class EnrichedConfigDescriptionParameterDTO extends ConfigDescriptionPara
|
||||
unitLabel, verify);
|
||||
|
||||
if (multiple && defaultValue != null) {
|
||||
if (defaultValue.contains(DEFAULT_LIST_DELIMITER)) {
|
||||
defaultValues = Stream.of(defaultValue.split(DEFAULT_LIST_DELIMITER)).map(String::trim)
|
||||
.filter(v -> !v.isEmpty()).toList();
|
||||
} else {
|
||||
defaultValues = Set.of(defaultValue);
|
||||
ConfigDescriptionParameter parameter = ConfigDescriptionParameterBuilder.create(name, type)
|
||||
.withMultiple(multiple).withDefault(defaultValue).withMultipleLimit(multipleLimit).build();
|
||||
if (ConfigUtil.getDefaultValueAsCorrectType(parameter) instanceof List defaultValues) {
|
||||
this.defaultValues = (Collection<String>) defaultValues;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+21
@@ -92,4 +92,25 @@ public class EnrichedConfigDescriptionDTOMapperTest {
|
||||
assertThat(ecdpdto.defaultValues, hasSize(3));
|
||||
assertThat(ecdpdto.defaultValues, is(equalTo(List.of("first value", "second value", "third value"))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThatDefaultValuesDontSplitEscapedCommas() {
|
||||
final String CONFIG_PARAMETER_DEFAULT_VALUE = "Me\\, myself\\, and I,You \\\\,";
|
||||
ConfigDescriptionParameter configDescriptionParameter = ConfigDescriptionParameterBuilder
|
||||
.create(CONFIG_PARAMETER_NAME, Type.TEXT).withDefault(CONFIG_PARAMETER_DEFAULT_VALUE).withMultiple(true)
|
||||
.build();
|
||||
ConfigDescription configDescription = ConfigDescriptionBuilder.create(CONFIG_URI)
|
||||
.withParameter(configDescriptionParameter).build();
|
||||
|
||||
ConfigDescriptionDTO cddto = EnrichedConfigDescriptionDTOMapper.map(configDescription);
|
||||
assertThat(cddto.parameters, hasSize(1));
|
||||
|
||||
ConfigDescriptionParameterDTO cdpdto = cddto.parameters.getFirst();
|
||||
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, hasSize(2));
|
||||
assertThat(ecdpdto.defaultValues, is(equalTo(List.of("Me, myself, and I", "You \\,"))));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user