Skip to content
This repository has been archived by the owner on May 7, 2020. It is now read-only.

Commit

Permalink
Improving scale transformation service (#4439)
Browse files Browse the repository at this point in the history
to ensure that they match in the same order than the scale definition file as discussed
in openhab/openhab-docs#486.

Signed-off-by: Gaël L'hopital <glhopital@gmail.com>
  • Loading branch information
clinique authored and sjsf committed Oct 19, 2017
1 parent e1133a1 commit a5330c0
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 37 deletions.
@@ -0,0 +1,3 @@
]..15[=first
[10..17[=second
[15..[=last
Expand Up @@ -45,7 +45,6 @@ public void testTransformByScale() throws TransformationException {
source = "10";
transformedResponse = processor.transform(existingscale, source);
Assert.assertEquals("middle", transformedResponse);

}

@Test
Expand Down Expand Up @@ -78,7 +77,6 @@ public void testTransformByScaleUndef() throws TransformationException {
String source = "-";
String transformedResponse = processor.transform(existingscale, source);
Assert.assertEquals("", transformedResponse);

}

@Test
Expand All @@ -95,7 +93,17 @@ public void testTransformByScaleErrorInBounds() throws TransformationException {
} catch (TransformationException e) {
// awaited result
}
}

@Test
public void testEvaluationOrder() throws TransformationException {
// Ensures that only first matching scale as presented in the file is taken in account
String evaluationOrder = "scale/evaluationorder.scale";
// This value matches two lines of the scale file
String source = "12";

String transformedResponse = processor.transform(evaluationOrder, source);
Assert.assertEquals("first", transformedResponse);
}

}
Expand Up @@ -10,10 +10,14 @@
import java.io.FileReader;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

Expand All @@ -37,31 +41,57 @@ public class ScaleTransformationService extends AbstractFileTransformationServic
/** RegEx to extract a scale definition */
private static final Pattern LIMITS_PATTERN = Pattern.compile("(\\[|\\])(.*)\\.\\.(.*)(\\[|\\])");

/**
* The implementation of {@link OrderedProperties} that let access
* properties in the same order than presented in the source file
* by using the orderedKeys function.
*
* This implementation is limited to the sole purpose of the class
* (e.g. it does not handle removing elements)
*
* @author Gaël L'hopital
*/
static class OrderedProperties extends Properties {
private static final long serialVersionUID = 3860553217028220119L;
private final HashSet<Object> keys = new LinkedHashSet<>();

Set<Object> orderedKeys() {
return keys;
}

@Override
public Enumeration<Object> keys() {
return Collections.<Object> enumeration(keys);
}

@Override
public Object put(Object key, Object value) {
keys.add(key);
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
*
*
*/
@Override
protected String internalTransform(Map<Range, String> data, String source) throws TransformationException {

try {
final BigDecimal value = new BigDecimal(source);

for (final Range range : data.keySet()) {
if (range.contains(value)) {
return data.get(range);
}
}
return data.entrySet().stream().filter(e -> e.getKey().contains(value)).findFirst().map(Map.Entry::getValue)
.orElseThrow(() -> new TransformationException("No matching range for '" + source + "'"));

throw new TransformationException("No matching range for '" + source + "'");
} catch (NumberFormatException e) {
throw new TransformationException("Scale can only be used with numeric inputs");
}
Expand All @@ -70,14 +100,14 @@ protected String internalTransform(Map<Range, String> data, String source) throw
@Override
protected Map<Range, String> internalLoadTransform(String filename) throws TransformationException {
try (FileReader reader = new FileReader(filename)) {
final Properties properties = new Properties();
final Map<Range, String> data = new LinkedHashMap<>();
final OrderedProperties properties = new OrderedProperties();
properties.load(reader);
final Map<Range, String> data = new HashMap<>();

for (Entry<Object, Object> f : properties.entrySet()) {
final String key = (String) f.getKey();
final String value = properties.getProperty(key);
final Matcher matcher = LIMITS_PATTERN.matcher(key);
for (Object orderedKey : properties.orderedKeys()) {
final String entry = (String) orderedKey;
final String value = properties.getProperty(entry);
final Matcher matcher = LIMITS_PATTERN.matcher(entry);
if (matcher.matches() && (matcher.groupCount() == 4)) {

final boolean lowerInclusive = matcher.group(1).equals("]") ? false : true;
Expand All @@ -86,32 +116,23 @@ protected Map<Range, String> internalLoadTransform(String filename) throws Trans
final String lowLimit = matcher.group(2);
final String highLimit = matcher.group(3);

final BigDecimal lowValue;
final BigDecimal highValue;

try {
if (lowLimit.isEmpty()) {
lowValue = null;
} else {
lowValue = new BigDecimal(lowLimit);
}
if (highLimit.isEmpty()) {
highValue = null;
} else {
highValue = new BigDecimal(highLimit);
}
} catch (final NumberFormatException ex) {
throw new TransformationException("Error parsing bounds: " + lowLimit + ".." + highLimit);
}
final BigDecimal lowValue = lowLimit.isEmpty() ? null : new BigDecimal(lowLimit);
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 {
logger.warn("Scale transform entry does not comply with syntax : '{}', '{}'", key, value);
logger.warn("Scale transform file '{}' does not comply with syntax for entry : '{}', '{}'",
filename, entry, value);
}
}

return data;
} catch (final IOException ex) {
throw new TransformationException("An error occurred while opening file.", ex);
Expand Down

0 comments on commit a5330c0

Please sign in to comment.