mirror of
https://github.com/danieldemus/openhab-core.git
synced 2025-01-25 19:55:48 +01:00
[config] Add config validator for parameter options (#2691)
Signed-off-by: Christoph Weitkamp <github@christophweitkamp.de>
This commit is contained in:
parent
9b438d7e12
commit
9cda2c8de8
@ -62,4 +62,13 @@ public final class ConfigDescriptionParameterValidatorFactory {
|
||||
public static ConfigDescriptionParameterValidator createPatternValidator() {
|
||||
return new PatternValidator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new validator for the parameter options of a config description parameter.
|
||||
*
|
||||
* @return a new validator for the parameter options of a config description parameter
|
||||
*/
|
||||
public static ConfigDescriptionParameterValidator createOptionsValidator() {
|
||||
return new OptionsValidator();
|
||||
}
|
||||
}
|
||||
|
@ -53,7 +53,8 @@ public final class ConfigDescriptionValidatorImpl implements ConfigDescriptionVa
|
||||
ConfigDescriptionParameterValidatorFactory.createRequiredValidator(), //
|
||||
ConfigDescriptionParameterValidatorFactory.createTypeValidator(), //
|
||||
ConfigDescriptionParameterValidatorFactory.createMinMaxValidator(), //
|
||||
ConfigDescriptionParameterValidatorFactory.createPatternValidator() //
|
||||
ConfigDescriptionParameterValidatorFactory.createPatternValidator(), //
|
||||
ConfigDescriptionParameterValidatorFactory.createOptionsValidator() //
|
||||
);
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(ConfigDescriptionValidatorImpl.class);
|
||||
|
@ -41,6 +41,9 @@ final class MessageKey {
|
||||
static final MessageKey PATTERN_VIOLATED = new MessageKey("pattern_violated",
|
||||
"The value {0} does not match the pattern {1}.");
|
||||
|
||||
static final MessageKey OPTIONS_VIOLATED = new MessageKey("options_violated",
|
||||
"The value {0} does not match allowed parameter options. Allowed options are: {1}");
|
||||
|
||||
static final MessageKey MULTIPLE_LIMIT_VIOLATED = new MessageKey("multiple_limit_violated",
|
||||
"Only {0} elements are allowed but {1} are provided.");
|
||||
/** The key to be used for internationalization. */
|
||||
|
@ -18,7 +18,6 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.core.config.core.ConfigDescriptionParameter;
|
||||
import org.openhab.core.config.core.ConfigDescriptionParameter.Type;
|
||||
import org.openhab.core.config.core.ParameterOption;
|
||||
import org.openhab.core.config.core.internal.validation.TypeIntrospections.TypeIntrospection;
|
||||
import org.openhab.core.config.core.validation.ConfigValidationMessage;
|
||||
|
||||
@ -39,15 +38,12 @@ final class MinMaxValidator implements ConfigDescriptionParameterValidator {
|
||||
}
|
||||
|
||||
// Allow specified options to be outside of the min/max value
|
||||
for (ParameterOption option : parameter.getOptions()) {
|
||||
// Option values are a string, so we can do a simple compare
|
||||
if (option.getValue().equals(value.toString())) {
|
||||
return null;
|
||||
}
|
||||
// Option values are a string, so we can do a simple compare
|
||||
if (parameter.getOptions().stream().map(o -> o.getValue()).anyMatch(v -> v.equals(value.toString()))) {
|
||||
return null;
|
||||
}
|
||||
|
||||
TypeIntrospection typeIntrospection = TypeIntrospections.get(parameter.getType());
|
||||
|
||||
if (parameter.getMinimum() != null) {
|
||||
BigDecimal min = parameter.getMinimum();
|
||||
if (typeIntrospection.isMinViolated(value, min)) {
|
||||
@ -55,7 +51,6 @@ final class MinMaxValidator implements ConfigDescriptionParameterValidator {
|
||||
min);
|
||||
}
|
||||
}
|
||||
|
||||
if (parameter.getMaximum() != null) {
|
||||
BigDecimal max = parameter.getMaximum();
|
||||
if (typeIntrospection.isMaxViolated(value, max)) {
|
||||
|
@ -0,0 +1,42 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2022 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.config.core.internal.validation;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.core.config.core.ConfigDescriptionParameter;
|
||||
import org.openhab.core.config.core.validation.ConfigValidationMessage;
|
||||
|
||||
/**
|
||||
* The {@link ConfigDescriptionParameterValidator} for the options of a {@link ConfigDescriptionParameter}.
|
||||
*
|
||||
* @author Christoph Weitkamp - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
final class OptionsValidator implements ConfigDescriptionParameterValidator {
|
||||
|
||||
@Override
|
||||
public @Nullable ConfigValidationMessage validate(ConfigDescriptionParameter param, @Nullable Object value) {
|
||||
if (value == null || !param.getLimitToOptions() || param.getOptions().isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Option values are a string, so we can do a simple compare
|
||||
if (param.getOptions().stream().map(o -> o.getValue()).noneMatch(v -> v.equals(value.toString()))) {
|
||||
MessageKey messageKey = MessageKey.OPTIONS_VIOLATED;
|
||||
return new ConfigValidationMessage(param.getName(), messageKey.defaultMessage, messageKey.key,
|
||||
param.getOptions());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -9,4 +9,5 @@ min_value_txt_violated=The value must not consist of less than {0} characters.
|
||||
min_value_numeric_violated=The value must not be less than {0}.
|
||||
|
||||
pattern_violated=The value {0} does not match the pattern {1}.
|
||||
options_violated=The value {0} does not match allowed parameter options. Allowed options are: {1}
|
||||
multiple_limit_violated=Only {0} elements are allowed but {1} are provided.
|
||||
|
@ -25,6 +25,8 @@ import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@ -35,6 +37,7 @@ 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.ConfigDescriptionRegistry;
|
||||
import org.openhab.core.config.core.ParameterOption;
|
||||
import org.openhab.core.config.core.validation.ConfigDescriptionValidator;
|
||||
import org.openhab.core.config.core.validation.ConfigValidationException;
|
||||
import org.openhab.core.config.core.validation.ConfigValidationMessage;
|
||||
@ -48,12 +51,13 @@ import org.osgi.framework.BundleContext;
|
||||
* @author Thomas Höfer - Initial contribution
|
||||
* @author Wouter Born - Migrate tests from Groovy to Java
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class ConfigDescriptionValidatorTest {
|
||||
|
||||
private static final int MIN_VIOLATED = 1;
|
||||
private static final int MAX_VIOLATED = 1234;
|
||||
|
||||
private static final BigDecimal DECIMAL_MIN_VIOLATED = new BigDecimal("1");
|
||||
private static final BigDecimal DECIMAL_MIN_VIOLATED = BigDecimal.ONE;
|
||||
private static final BigDecimal DECIMAL_MAX_VIOLATED = new BigDecimal("3.5");
|
||||
|
||||
private static final BigDecimal MIN = BigDecimal.valueOf(2);
|
||||
@ -76,6 +80,8 @@ public class ConfigDescriptionValidatorTest {
|
||||
private static final String TXT_MAX_PARAM_NAME = "txt-max-name";
|
||||
private static final String TXT_PATTERN_PARAM_NAME = "txt-pattern-name";
|
||||
private static final String TXT_MAX_PATTERN_PARAM_NAME = "txt-max-pattern-name";
|
||||
private static final String TXT_PARAM_WITH_LIMITED_OPTIONS_NAME = "txt-param-with-limited-options-name";
|
||||
private static final String TXT_PARAM_WITH_UNLIMITED_OPTIONS_NAME = "txt-param-with-unlimited-options-name";
|
||||
private static final String TXT_MULTIPLE_LIMIT_PARAM_NAME = "txt-multiple-limit-name";
|
||||
|
||||
private static final String INT_PARAM_NAME = "int-param";
|
||||
@ -88,6 +94,11 @@ public class ConfigDescriptionValidatorTest {
|
||||
private static final String DECIMAL_MIN_PARAM_NAME = "decimal-min-name";
|
||||
private static final String DECIMAL_MAX_PARAM_NAME = "decimal-max-name";
|
||||
|
||||
private static final List<ParameterOption> PARAMETER_OPTIONS = List.of( //
|
||||
new ParameterOption("http", "HTTP"), //
|
||||
new ParameterOption("https", "HTTPS") //
|
||||
);
|
||||
|
||||
private static final ConfigDescriptionParameter BOOL_PARAM = ConfigDescriptionParameterBuilder
|
||||
.create(BOOL_PARAM_NAME, ConfigDescriptionParameter.Type.BOOLEAN).build();
|
||||
private static final ConfigDescriptionParameter BOOL_REQUIRED_PARAM = ConfigDescriptionParameterBuilder
|
||||
@ -106,6 +117,12 @@ public class ConfigDescriptionValidatorTest {
|
||||
private static final ConfigDescriptionParameter TXT_MAX_PATTERN_PARAM = ConfigDescriptionParameterBuilder
|
||||
.create(TXT_MAX_PATTERN_PARAM_NAME, ConfigDescriptionParameter.Type.TEXT).withMaximum(MAX)
|
||||
.withPattern(PATTERN).build();
|
||||
private static final ConfigDescriptionParameter TXT_PARAM_WITH_LIMITED_OPTIONS = ConfigDescriptionParameterBuilder
|
||||
.create(TXT_PARAM_WITH_LIMITED_OPTIONS_NAME, ConfigDescriptionParameter.Type.TEXT)
|
||||
.withOptions(PARAMETER_OPTIONS).build();
|
||||
private static final ConfigDescriptionParameter TXT_PARAM_WITH_UNLIMITED_OPTIONS = ConfigDescriptionParameterBuilder
|
||||
.create(TXT_PARAM_WITH_UNLIMITED_OPTIONS_NAME, ConfigDescriptionParameter.Type.TEXT)
|
||||
.withOptions(PARAMETER_OPTIONS).withLimitToOptions(false).build();
|
||||
private static final ConfigDescriptionParameter TXT_MULTIPLE_LIMIT_PARAM = ConfigDescriptionParameterBuilder
|
||||
.create(TXT_MULTIPLE_LIMIT_PARAM_NAME, Type.TEXT).withMultiple(true).withMultipleLimit(2).build();
|
||||
|
||||
@ -139,13 +156,14 @@ public class ConfigDescriptionValidatorTest {
|
||||
|
||||
private static final ConfigDescription CONFIG_DESCRIPTION = ConfigDescriptionBuilder.create(CONFIG_DESCRIPTION_URI)
|
||||
.withParameters(List.of(BOOL_PARAM, BOOL_REQUIRED_PARAM, TXT_PARAM, TXT_REQUIRED_PARAM, TXT_MIN_PARAM,
|
||||
TXT_MAX_PARAM, TXT_PATTERN_PARAM, TXT_MAX_PATTERN_PARAM, TXT_MULTIPLE_LIMIT_PARAM, INT_PARAM,
|
||||
INT_REQUIRED_PARAM, INT_MIN_PARAM, INT_MAX_PARAM, DECIMAL_PARAM, DECIMAL_REQUIRED_PARAM,
|
||||
DECIMAL_MIN_PARAM, DECIMAL_MAX_PARAM))
|
||||
TXT_MAX_PARAM, TXT_PATTERN_PARAM, TXT_MAX_PATTERN_PARAM, TXT_PARAM_WITH_LIMITED_OPTIONS,
|
||||
TXT_PARAM_WITH_UNLIMITED_OPTIONS, TXT_MULTIPLE_LIMIT_PARAM, INT_PARAM, INT_REQUIRED_PARAM,
|
||||
INT_MIN_PARAM, INT_MAX_PARAM, DECIMAL_PARAM, DECIMAL_REQUIRED_PARAM, DECIMAL_MIN_PARAM,
|
||||
DECIMAL_MAX_PARAM))
|
||||
.build();
|
||||
|
||||
private Map<String, Object> params;
|
||||
private ConfigDescriptionValidatorImpl configDescriptionValidator;
|
||||
private @NonNullByDefault({}) Map<String, Object> params;
|
||||
private @NonNullByDefault({}) ConfigDescriptionValidatorImpl configDescriptionValidator;
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
@ -171,6 +189,7 @@ public class ConfigDescriptionValidatorTest {
|
||||
params.put(TXT_MAX_PARAM_NAME, String.valueOf(MIN_VIOLATED));
|
||||
params.put(TXT_PATTERN_PARAM_NAME, "abbbc");
|
||||
params.put(TXT_MAX_PATTERN_PARAM_NAME, "abc");
|
||||
params.put(TXT_PARAM_WITH_LIMITED_OPTIONS_NAME, "http");
|
||||
params.put(TXT_MULTIPLE_LIMIT_PARAM_NAME, List.of("1", "2"));
|
||||
params.put(INT_PARAM_NAME, null);
|
||||
params.put(INT_REQUIRED_PARAM_NAME, 0);
|
||||
@ -408,6 +427,27 @@ public class ConfigDescriptionValidatorTest {
|
||||
assertThat(getConfigValidationMessages(exception), is(expected));
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
// PARAMETER OPTION VALIDATIONS
|
||||
// ===========================================================================
|
||||
|
||||
@Test
|
||||
public void assertValidationThrowsExceptionForNotAllowedLimitedParameterOption() {
|
||||
List<ConfigValidationMessage> expected = List.of(new ConfigValidationMessage(
|
||||
TXT_PARAM_WITH_LIMITED_OPTIONS_NAME, MessageKey.OPTIONS_VIOLATED.defaultMessage,
|
||||
MessageKey.OPTIONS_VIOLATED.key, PARAMETER_OPTIONS));
|
||||
params.put(TXT_PARAM_WITH_LIMITED_OPTIONS_NAME, "ftp");
|
||||
ConfigValidationException exception = Assertions.assertThrows(ConfigValidationException.class,
|
||||
() -> configDescriptionValidator.validate(params, CONFIG_DESCRIPTION_URI));
|
||||
assertThat(getConfigValidationMessages(exception), is(expected));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void assertValidationThrowsNoExceptionForAllowedUnlimitedParameterOption() {
|
||||
params.put(TXT_PARAM_WITH_UNLIMITED_OPTIONS_NAME, "ftp");
|
||||
Assertions.assertDoesNotThrow(() -> configDescriptionValidator.validate(params, CONFIG_DESCRIPTION_URI));
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
// MISC VALIDATIONS
|
||||
// ===========================================================================
|
||||
@ -484,7 +524,7 @@ public class ConfigDescriptionValidatorTest {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static List<ConfigValidationMessage> getConfigValidationMessages(ConfigValidationException cve) {
|
||||
private static @Nullable List<ConfigValidationMessage> getConfigValidationMessages(ConfigValidationException cve) {
|
||||
try {
|
||||
Field field = cve.getClass().getDeclaredField("configValidationMessages");
|
||||
field.setAccessible(true);
|
||||
|
Loading…
Reference in New Issue
Block a user