Refactor scale transformation to configuration registry (#12862)
Signed-off-by: Jan N. Klug <github@klug.nrw>
This commit is contained in:
parent
44a0dfb132
commit
0bbd276a24
|
@ -12,8 +12,8 @@
|
||||||
*/
|
*/
|
||||||
package org.openhab.transform.scale.internal;
|
package org.openhab.transform.scale.internal;
|
||||||
|
|
||||||
import java.io.FileReader;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.StringReader;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
@ -26,19 +26,25 @@ import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.eclipse.jdt.annotation.NonNull;
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
import org.eclipse.jdt.annotation.Nullable;
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
|
import org.openhab.core.common.registry.RegistryChangeListener;
|
||||||
import org.openhab.core.config.core.ConfigOptionProvider;
|
import org.openhab.core.config.core.ConfigOptionProvider;
|
||||||
import org.openhab.core.config.core.ParameterOption;
|
import org.openhab.core.config.core.ParameterOption;
|
||||||
import org.openhab.core.library.types.QuantityType;
|
import org.openhab.core.library.types.QuantityType;
|
||||||
import org.openhab.core.transform.AbstractFileTransformationService;
|
import org.openhab.core.transform.TransformationConfiguration;
|
||||||
|
import org.openhab.core.transform.TransformationConfigurationRegistry;
|
||||||
import org.openhab.core.transform.TransformationException;
|
import org.openhab.core.transform.TransformationException;
|
||||||
import org.openhab.core.transform.TransformationService;
|
import org.openhab.core.transform.TransformationService;
|
||||||
|
import org.osgi.service.component.annotations.Activate;
|
||||||
import org.osgi.service.component.annotations.Component;
|
import org.osgi.service.component.annotations.Component;
|
||||||
|
import org.osgi.service.component.annotations.Deactivate;
|
||||||
|
import org.osgi.service.component.annotations.Reference;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
@ -51,17 +57,18 @@ import org.slf4j.LoggerFactory;
|
||||||
*/
|
*/
|
||||||
@Component(service = { TransformationService.class, ConfigOptionProvider.class }, property = {
|
@Component(service = { TransformationService.class, ConfigOptionProvider.class }, property = {
|
||||||
"openhab.transform=SCALE" })
|
"openhab.transform=SCALE" })
|
||||||
public class ScaleTransformationService extends AbstractFileTransformationService<Map<Range, String>>
|
@NonNullByDefault
|
||||||
implements ConfigOptionProvider {
|
public class ScaleTransformationService
|
||||||
|
implements TransformationService, ConfigOptionProvider, RegistryChangeListener<TransformationConfiguration> {
|
||||||
|
|
||||||
private final Logger logger = LoggerFactory.getLogger(ScaleTransformationService.class);
|
private final Logger logger = LoggerFactory.getLogger(ScaleTransformationService.class);
|
||||||
|
|
||||||
private static final String PROFILE_CONFIG_URI = "profile:transform:SCALE";
|
private static final String PROFILE_CONFIG_URI = "profile:transform:SCALE";
|
||||||
private static final String CONFIG_PARAM_FUNCTION = "function";
|
private static final String CONFIG_PARAM_FUNCTION = "function";
|
||||||
private static final String[] FILE_NAME_EXTENSIONS = { "scale" };
|
private static final Set<String> SUPPORTED_CONFIGURATION_TYPES = Set.of("scale");
|
||||||
|
|
||||||
/** RegEx to extract a scale definition */
|
/** RegEx to extract a scale definition */
|
||||||
private static final Pattern LIMITS_PATTERN = Pattern.compile("(\\[|\\])(.*)\\.\\.(.*)(\\[|\\])");
|
private static final Pattern LIMITS_PATTERN = Pattern.compile("(\\[|])(.*)\\.\\.(.*)(\\[|])");
|
||||||
|
|
||||||
private static final String NON_NUMBER = "NaN";
|
private static final String NON_NUMBER = "NaN";
|
||||||
private static final String FORMAT = "format";
|
private static final String FORMAT = "format";
|
||||||
|
@ -70,6 +77,39 @@ public class ScaleTransformationService extends AbstractFileTransformationServic
|
||||||
|
|
||||||
/** Inaccessible range used to store presentation format ]0..0[ */
|
/** Inaccessible range used to store presentation format ]0..0[ */
|
||||||
private static final Range FORMAT_RANGE = Range.range(BigDecimal.ZERO, false, BigDecimal.ZERO, false);
|
private static final Range FORMAT_RANGE = Range.range(BigDecimal.ZERO, false, BigDecimal.ZERO, false);
|
||||||
|
private final TransformationConfigurationRegistry transformationConfigurationRegistry;
|
||||||
|
|
||||||
|
private final Map<String, Map<@Nullable Range, String>> cachedTransformations = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
@Activate
|
||||||
|
public ScaleTransformationService(
|
||||||
|
@Reference TransformationConfigurationRegistry transformationConfigurationRegistry) {
|
||||||
|
this.transformationConfigurationRegistry = transformationConfigurationRegistry;
|
||||||
|
transformationConfigurationRegistry.addRegistryChangeListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deactivate
|
||||||
|
public void deactivate() {
|
||||||
|
transformationConfigurationRegistry.removeRegistryChangeListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void added(TransformationConfiguration element) {
|
||||||
|
// do nothing, configurations are added to cache if needed
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removed(TransformationConfiguration element) {
|
||||||
|
cachedTransformations.remove(element.getUID());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updated(TransformationConfiguration oldElement, TransformationConfiguration element) {
|
||||||
|
if (cachedTransformations.remove(oldElement.getUID()) != null) {
|
||||||
|
// import only if it was present before
|
||||||
|
importConfiguration(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The implementation of {@link OrderedProperties} that let access
|
* The implementation of {@link OrderedProperties} that let access
|
||||||
|
@ -83,125 +123,129 @@ public class ScaleTransformationService extends AbstractFileTransformationServic
|
||||||
*/
|
*/
|
||||||
static class OrderedProperties extends Properties {
|
static class OrderedProperties extends Properties {
|
||||||
private static final long serialVersionUID = 3860553217028220119L;
|
private static final long serialVersionUID = 3860553217028220119L;
|
||||||
private final HashSet<Object> keys = new LinkedHashSet<>();
|
private final HashSet<@Nullable Object> keys = new LinkedHashSet<>();
|
||||||
|
|
||||||
Set<Object> orderedKeys() {
|
Set<@Nullable Object> orderedKeys() {
|
||||||
return keys;
|
return keys;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Enumeration<Object> keys() {
|
public @NonNullByDefault({}) Enumeration<Object> keys() {
|
||||||
return Collections.<Object> enumeration(keys);
|
return Collections.enumeration(keys);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object put(Object key, Object value) {
|
public @Nullable Object put(@Nullable Object key, @Nullable Object value) {
|
||||||
keys.add(key);
|
keys.add(key);
|
||||||
return super.put(key, value);
|
return super.put(key, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Performs transformation of the input <code>source</code>
|
|
||||||
*
|
|
||||||
* The method transforms the input <code>source</code> by matching searching
|
|
||||||
* the range where it fits i.e. [min..max]=value or ]min..max]=value
|
|
||||||
*
|
|
||||||
* @param properties the list of properties defining all the available ranges
|
|
||||||
* @param source the input to transform
|
|
||||||
* @return the transformed result or null if the transformation couldn't be completed for any reason.
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
protected @Nullable String internalTransform(Map<Range, String> data, String source)
|
public @Nullable String transform(String function, String source) throws TransformationException {
|
||||||
throws TransformationException {
|
// always get a configuration from the registry to account for changed system locale
|
||||||
try {
|
TransformationConfiguration transformationConfiguration = transformationConfigurationRegistry.get(function,
|
||||||
final BigDecimal value = new BigDecimal(source);
|
null);
|
||||||
return formatResult(data, source, value);
|
|
||||||
} catch (NumberFormatException e) {
|
if (transformationConfiguration != null) {
|
||||||
// Scale can only be used with numeric inputs, so lets try to see if ever its a valid quantity type
|
if (!cachedTransformations.containsKey(transformationConfiguration.getUID())) {
|
||||||
try {
|
importConfiguration(transformationConfiguration);
|
||||||
final QuantityType<?> quantity = new QuantityType<>(source);
|
}
|
||||||
return formatResult(data, source, quantity.toBigDecimal());
|
Map<@Nullable Range, String> data = cachedTransformations.get(function);
|
||||||
} catch (IllegalArgumentException e2) {
|
|
||||||
String nonNumeric = data.get(null);
|
if (data != null) {
|
||||||
if (nonNumeric != null) {
|
String target;
|
||||||
return nonNumeric;
|
|
||||||
} else {
|
try {
|
||||||
throw new TransformationException(
|
final BigDecimal value = new BigDecimal(source);
|
||||||
"Scale must be used with numeric inputs, valid quantity types or a 'NaN' entry.");
|
target = formatResult(data, source, value);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
// Scale can only be used with numeric inputs, so lets try to see if ever its a valid quantity type
|
||||||
|
try {
|
||||||
|
final QuantityType<?> quantity = new QuantityType<>(source);
|
||||||
|
return formatResult(data, source, quantity.toBigDecimal());
|
||||||
|
} catch (IllegalArgumentException e2) {
|
||||||
|
String nonNumeric = data.get(null);
|
||||||
|
if (nonNumeric != null) {
|
||||||
|
target = nonNumeric;
|
||||||
|
} else {
|
||||||
|
throw new TransformationException(
|
||||||
|
"Scale must be used with numeric inputs, valid quantity types or a 'NaN' entry.");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
logger.debug("Transformation resulted in '{}'", target);
|
||||||
|
return target;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
throw new TransformationException("Could not find configuration '" + function + "' or failed to parse it.");
|
||||||
}
|
}
|
||||||
|
|
||||||
private String formatResult(Map<Range, String> data, String source, final BigDecimal value)
|
private String formatResult(Map<@Nullable Range, String> data, String source, final BigDecimal value)
|
||||||
throws TransformationException {
|
throws TransformationException {
|
||||||
String format = data.get(FORMAT_RANGE);
|
String format = data.get(FORMAT_RANGE);
|
||||||
String result = getScaleResult(data, source, value);
|
String result = getScaleResult(data, source, value);
|
||||||
return format.replaceAll(FORMAT_VALUE, source).replaceAll(FORMAT_LABEL, result);
|
return format.replaceAll(FORMAT_VALUE, source).replaceAll(FORMAT_LABEL, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getScaleResult(Map<Range, String> data, String source, final BigDecimal value)
|
private String getScaleResult(Map<@Nullable Range, String> data, String source, final BigDecimal value)
|
||||||
throws TransformationException {
|
throws TransformationException {
|
||||||
return data.entrySet().stream().filter(entry -> entry.getKey() != null && entry.getKey().contains(value))
|
return data.entrySet().stream().filter(entry -> entry.getKey() != null && entry.getKey().contains(value))
|
||||||
.findFirst().map(Map.Entry::getValue)
|
.findFirst().map(Map.Entry::getValue)
|
||||||
.orElseThrow(() -> new TransformationException("No matching range for '" + source + "'"));
|
.orElseThrow(() -> new TransformationException("No matching range for '" + source + "'"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private void importConfiguration(@Nullable TransformationConfiguration configuration) {
|
||||||
protected Map<Range, String> internalLoadTransform(String filename) throws TransformationException {
|
if (configuration != null) {
|
||||||
try (FileReader reader = new FileReader(filename)) {
|
try {
|
||||||
final Map<Range, String> data = new LinkedHashMap<>();
|
final Map<@Nullable Range, String> data = new LinkedHashMap<>();
|
||||||
data.put(FORMAT_RANGE, FORMAT_LABEL);
|
data.put(FORMAT_RANGE, FORMAT_LABEL);
|
||||||
final OrderedProperties properties = new OrderedProperties();
|
final OrderedProperties properties = new OrderedProperties();
|
||||||
properties.load(reader);
|
properties.load(new StringReader(configuration.getContent()));
|
||||||
|
|
||||||
for (Object orderedKey : properties.orderedKeys()) {
|
for (Object orderedKey : properties.orderedKeys()) {
|
||||||
final String entry = (String) orderedKey;
|
final String entry = (String) orderedKey;
|
||||||
final String value = properties.getProperty(entry);
|
final String value = properties.getProperty(entry);
|
||||||
final Matcher matcher = LIMITS_PATTERN.matcher(entry);
|
final Matcher matcher = LIMITS_PATTERN.matcher(entry);
|
||||||
if (matcher.matches() && (matcher.groupCount() == 4)) {
|
if (matcher.matches() && (matcher.groupCount() == 4)) {
|
||||||
final boolean lowerInclusive = matcher.group(1).equals("[");
|
final boolean lowerInclusive = matcher.group(1).equals("[");
|
||||||
final boolean upperInclusive = matcher.group(4).equals("]");
|
final boolean upperInclusive = matcher.group(4).equals("]");
|
||||||
|
|
||||||
final String lowLimit = matcher.group(2);
|
final String lowLimit = matcher.group(2);
|
||||||
final String highLimit = matcher.group(3);
|
final String highLimit = matcher.group(3);
|
||||||
|
|
||||||
try {
|
|
||||||
final BigDecimal lowValue = lowLimit.isEmpty() ? null : new BigDecimal(lowLimit);
|
final BigDecimal lowValue = lowLimit.isEmpty() ? null : new BigDecimal(lowLimit);
|
||||||
final BigDecimal highValue = highLimit.isEmpty() ? null : new BigDecimal(highLimit);
|
final BigDecimal highValue = highLimit.isEmpty() ? null : new BigDecimal(highLimit);
|
||||||
final Range range = Range.range(lowValue, lowerInclusive, highValue, upperInclusive);
|
final Range range = Range.range(lowValue, lowerInclusive, highValue, upperInclusive);
|
||||||
|
|
||||||
data.put(range, value);
|
data.put(range, value);
|
||||||
} catch (NumberFormatException ex) {
|
|
||||||
throw new TransformationException("Error parsing bounds: " + lowLimit + ".." + highLimit);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (NON_NUMBER.equals(entry)) {
|
|
||||||
data.put(null, value);
|
|
||||||
} else if (FORMAT.equals(entry)) {
|
|
||||||
data.put(FORMAT_RANGE, value);
|
|
||||||
} else {
|
} else {
|
||||||
logger.warn("Scale transform file '{}' does not comply with syntax for entry : '{}', '{}'",
|
if (NON_NUMBER.equals(entry)) {
|
||||||
filename, entry, value);
|
data.put(null, value);
|
||||||
|
} else if (FORMAT.equals(entry)) {
|
||||||
|
data.put(FORMAT_RANGE, value);
|
||||||
|
} else {
|
||||||
|
logger.warn(
|
||||||
|
"Scale transformation configuration '{}' does not comply with syntax for entry : '{}', '{}'",
|
||||||
|
configuration.getUID(), entry, value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return data;
|
cachedTransformations.put(configuration.getUID(), data);
|
||||||
} catch (final IOException ex) {
|
} catch (IOException | NumberFormatException ignored) {
|
||||||
throw new TransformationException("An error occurred while opening file.", ex);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @Nullable Collection<@NonNull ParameterOption> getParameterOptions(URI uri, String param,
|
public @Nullable Collection<ParameterOption> getParameterOptions(URI uri, String param, @Nullable String context,
|
||||||
@Nullable String context, @Nullable Locale locale) {
|
@Nullable Locale locale) {
|
||||||
if (PROFILE_CONFIG_URI.equals(uri.toString())) {
|
if (PROFILE_CONFIG_URI.equals(uri.toString())) {
|
||||||
switch (param) {
|
if (CONFIG_PARAM_FUNCTION.equals(param)) {
|
||||||
case CONFIG_PARAM_FUNCTION:
|
return transformationConfigurationRegistry.getConfigurations(SUPPORTED_CONFIGURATION_TYPES).stream()
|
||||||
return getFilenames(FILE_NAME_EXTENSIONS).stream().map(f -> new ParameterOption(f, f))
|
.map(c -> new ParameterOption(c.getUID(), c.getLabel())).collect(Collectors.toList());
|
||||||
.collect(Collectors.toList());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -13,30 +13,68 @@
|
||||||
package org.openhab.transform.scale.internal;
|
package org.openhab.transform.scale.internal;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyString;
|
||||||
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
|
|
||||||
import java.util.Locale;
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import javax.measure.quantity.Dimensionless;
|
import javax.measure.quantity.Dimensionless;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.Mockito;
|
||||||
|
import org.mockito.junit.jupiter.MockitoExtension;
|
||||||
|
import org.mockito.junit.jupiter.MockitoSettings;
|
||||||
|
import org.mockito.quality.Strictness;
|
||||||
|
import org.mockito.stubbing.Answer;
|
||||||
import org.openhab.core.library.types.QuantityType;
|
import org.openhab.core.library.types.QuantityType;
|
||||||
|
import org.openhab.core.transform.TransformationConfiguration;
|
||||||
|
import org.openhab.core.transform.TransformationConfigurationRegistry;
|
||||||
import org.openhab.core.transform.TransformationException;
|
import org.openhab.core.transform.TransformationException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Gaël L'hopital - Initial contribution
|
* @author Gaël L'hopital - Initial contribution
|
||||||
*/
|
*/
|
||||||
|
@ExtendWith(MockitoExtension.class)
|
||||||
|
@MockitoSettings(strictness = Strictness.LENIENT)
|
||||||
|
@NonNullByDefault
|
||||||
public class ScaleTransformServiceTest {
|
public class ScaleTransformServiceTest {
|
||||||
private ScaleTransformationService processor;
|
private static final String SRC_FOLDER = "conf" + File.separator + "transform";
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private @NonNullByDefault({}) TransformationConfigurationRegistry transformationConfigurationRegistry;
|
||||||
|
private final Map<String, TransformationConfiguration> configurationMap = new HashMap<>();
|
||||||
|
private @NonNullByDefault({}) ScaleTransformationService processor;
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
public void init() {
|
public void init() throws IOException {
|
||||||
processor = new ScaleTransformationService() {
|
configurationMap.clear();
|
||||||
@Override
|
Files.walk(Path.of(SRC_FOLDER)).filter(Files::isRegularFile).forEach(file -> {
|
||||||
protected Locale getLocale() {
|
try {
|
||||||
return Locale.US;
|
String content = new String(Files.readAllBytes(file), StandardCharsets.UTF_8);
|
||||||
|
String uid = Path.of(SRC_FOLDER).relativize(file).toString();
|
||||||
|
TransformationConfiguration transformationConfiguration = new TransformationConfiguration(uid, uid,
|
||||||
|
"scale", null, content);
|
||||||
|
configurationMap.put(uid, transformationConfiguration);
|
||||||
|
} catch (IOException ignored) {
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
|
|
||||||
|
Mockito.when(transformationConfigurationRegistry.get(anyString(), eq(null)))
|
||||||
|
.thenAnswer((Answer<TransformationConfiguration>) invocation -> {
|
||||||
|
Object[] args = invocation.getArguments();
|
||||||
|
return configurationMap.get(args[0]);
|
||||||
|
});
|
||||||
|
processor = new ScaleTransformationService(transformationConfigurationRegistry);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -80,8 +118,7 @@ public class ScaleTransformServiceTest {
|
||||||
// Issue #1107
|
// Issue #1107
|
||||||
String existingscale = "scale/humidex_fr.scale";
|
String existingscale = "scale/humidex_fr.scale";
|
||||||
String source = "-";
|
String source = "-";
|
||||||
String transformedResponse = processor.transform(existingscale, source);
|
assertThrows(TransformationException.class, () -> processor.transform(existingscale, source));
|
||||||
assertEquals("", transformedResponse);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -104,8 +141,7 @@ public class ScaleTransformServiceTest {
|
||||||
// checks that an error is raised when trying to scale an erroneous value
|
// checks that an error is raised when trying to scale an erroneous value
|
||||||
String existingscale = "scale/evaluationorder.scale";
|
String existingscale = "scale/evaluationorder.scale";
|
||||||
String source = "azerty";
|
String source = "azerty";
|
||||||
String transformedResponse = processor.transform(existingscale, source);
|
assertThrows(TransformationException.class, () -> processor.transform(existingscale, source));
|
||||||
assertEquals("", transformedResponse);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -150,7 +186,6 @@ public class ScaleTransformServiceTest {
|
||||||
public void testValueExceedsRange() throws TransformationException {
|
public void testValueExceedsRange() throws TransformationException {
|
||||||
String existingscale = "scale/humidex.scale";
|
String existingscale = "scale/humidex.scale";
|
||||||
String source = "200";
|
String source = "200";
|
||||||
String transformedResponse = processor.transform(existingscale, source);
|
assertThrows(TransformationException.class, () -> processor.transform(existingscale, source));
|
||||||
assertEquals("", transformedResponse);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue