Adding Scale transformation service, without Localizable source file for scale and map

Signed-off-by: Gaël L'hopital <glhopital@gmail.com>

My own code review

Signed-off-by: Gaël L'hopital <glhopital@gmail.com>

Corrections after CR

Signed-off-by: Gaël L'hopital <glhopital@gmail.com>

Removing test launch files

Signed-off-by: Gaël L'hopital <glhopital@gmail.com>
This commit is contained in:
Gaël L'hopital 2015-06-19 12:51:35 +02:00
Родитель 93676abed4
Коммит fe0ae37189
42 изменённых файлов: 999 добавлений и 107 удалений

Просмотреть файл

@ -7,7 +7,9 @@ Bundle-Version: 0.8.0.qualifier
Bundle-Activator: org.eclipse.smarthome.core.transform.internal.TransformationActivator
Bundle-ManifestVersion: 2
Bundle-License: http://www.eclipse.org/legal/epl-v10.html
Import-Package: org.eclipse.smarthome.core.scriptengine.action;resolution:=optional,
Import-Package: org.apache.commons.io,
org.eclipse.smarthome.config.core,
org.eclipse.smarthome.core.scriptengine.action;resolution:=optional,
org.osgi.framework,
org.slf4j
Bundle-SymbolicName: org.eclipse.smarthome.core.transform

Просмотреть файл

@ -0,0 +1,229 @@
/**
* Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.smarthome.core.transform;
import static java.nio.file.StandardWatchEventKinds.ENTRY_DELETE;
import static java.nio.file.StandardWatchEventKinds.ENTRY_MODIFY;
import static java.nio.file.StandardWatchEventKinds.OVERFLOW;
import java.io.File;
import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.commons.io.FilenameUtils;
import org.eclipse.smarthome.config.core.ConfigConstants;
import org.eclipse.smarthome.core.transform.TransformationException;
import org.eclipse.smarthome.core.transform.TransformationService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Base class for cacheable and localizable file based transformation
* {@link TransformationService}.
* It expects the transformation to be applied to be read from a file stored
* under the 'transform' folder within the configuration path. To organize the various
* transformations one might use subfolders.
*
* @author Gaël L'hopital - Initial contribution
* @author Kai Kreuzer - File caching mechanism
*/
public abstract class AbstractFileTransformationService<T> implements TransformationService {
private WatchService watchService = null;
protected final Map<String, T> cachedFiles = new ConcurrentHashMap<>();
protected final List<String> watchedDirectories = new ArrayList<String>();
private final Logger logger = LoggerFactory.getLogger(AbstractFileTransformationService.class);
private final String language = Locale.getDefault().getLanguage();
/**
* <p>
* Transforms the input <code>source</code> by the according method defined in subclass to another string.
* It expects the transformation to be read from a file which is stored
* under the 'configurations/transform'
* </p>
*
* @param filename
* the name of the file which contains the transformation definition.
* The name may contain subfoldernames
* as well
* @param source
* the input to transform
*
* @{inheritDoc
*
*/
@Override
public String transform(String filename, String source) throws TransformationException {
if (filename == null || source == null) {
throw new TransformationException("the given parameters 'filename' and 'source' must not be null");
}
if (watchService == null) {
initializeWatchService();
} else {
processFolderEvents();
}
String transformFile = getLocalizedProposedFilename(filename);
T transform = cachedFiles.get(transformFile);
if (transform == null) {
transform = internalLoadTransform(transformFile);
cachedFiles.put(transformFile, transform);
}
String result = internalTransform(transform, source);
if (result == null) {
logger.warn("Could not transform '{}' with the file '{}'.", source, filename);
result = source;
}
return result;
}
/**
* <p>
* Abstract method defined by subclasses to effectively operate the
* transformation according to its rules
* </p>
*
* @param transform
* transformation held by the file provided to <code>transform</code> method
*
* @param source
* the input to transform
*
* @return the transformed result or null if the
* transformation couldn't be completed for any reason.
*
*/
protected abstract String internalTransform(T transform, String source) throws TransformationException;
/**
* <p>
* Abstract method defined by subclasses to effectively read the transformation
* source file according to their own needs.
* </p>
*
* @param filename
* Name of the file to be read. This filename may have been transposed
* to a localized one
*
* @return
* An object containing the source file
*
* @throws TransformationException
* file couldn't be read for any reason
*/
protected abstract T internalLoadTransform(String filename) throws TransformationException;
private void initializeWatchService() {
try {
watchService = FileSystems.getDefault().newWatchService();
watchSubDirectory("");
} catch (IOException e) {
logger.error("Unable to start transformation directory monitoring");
}
}
private void watchSubDirectory(String subDirectory) {
if (watchedDirectories.indexOf(subDirectory) == -1) {
String watchedDirectory = getSourcePath() + subDirectory;
Path transformFilePath = Paths.get(watchedDirectory);
try {
transformFilePath.register(watchService, ENTRY_DELETE, ENTRY_MODIFY);
watchedDirectories.add(subDirectory);
} catch (IOException e) {
logger.warn("Unable to watch transformation directory : {}", watchedDirectory);
cachedFiles.clear();
}
}
}
/**
* Ensures that a modified or deleted cached files does not stay in the cache
*/
private void processFolderEvents() {
WatchKey key = watchService.poll();
if (key != null) {
for (WatchEvent<?> e : key.pollEvents()) {
if (e.kind() == OVERFLOW) {
continue;
}
// Context for directory entry event is the file name of entry
@SuppressWarnings("unchecked")
WatchEvent<Path> ev = (WatchEvent<Path>) e;
Path path = ev.context();
logger.debug("Refreshing transformation file '{}'", path);
for (String fileEntry : cachedFiles.keySet()) {
if (fileEntry.endsWith(path.toString())) {
cachedFiles.remove(fileEntry);
}
}
}
key.reset();
}
}
/**
* Returns the name of the localized transformation file
* if it actually exists, keeps the original in the other case
*
* @param filename name of the requested transformation file
* @return original or localized transformation file to use
*/
protected String getLocalizedProposedFilename(String filename) {
String extension = FilenameUtils.getExtension(filename);
String prefix = FilenameUtils.getPath(filename);
String result = filename;
if (!prefix.isEmpty()) {
watchSubDirectory(prefix);
}
// the filename may already contain locale information
if (!filename.matches(".*_[a-z]{2}." + extension +"$")) {
String basename = FilenameUtils.getBaseName(filename);
String alternateName = prefix + basename + "_" + language + "." + extension;
String alternatePath = getSourcePath() + alternateName;
File f = new File(alternatePath);
if (f.exists()) {
result = alternateName;
}
}
result = getSourcePath() + result;
return result;
}
/**
* Returns the path to the root of the transformation folder
*/
private String getSourcePath() {
return ConfigConstants.getConfigFolder() + File.separator + TransformationService.TRANSFORM_FOLDER_NAME + File.separator;
}
}

Просмотреть файл

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="src" path="src/test/java"/>
<classpathentry kind="output" path="target/test-classes"/>
</classpath>

Просмотреть файл

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>org.eclipse.smarthome.transform.map.test</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.ManifestBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.SchemaBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.pde.PluginNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

Просмотреть файл

@ -0,0 +1,7 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
org.eclipse.jdt.core.compiler.compliance=1.7
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.7

Просмотреть файл

@ -0,0 +1,9 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Tests for the Map Transformation Service
Bundle-SymbolicName: org.eclipse.smarthome.transform.map.test
Bundle-Version: 0.8.0.qualifier
Bundle-Vendor: Eclipse.org/SmartHome
Fragment-Host: org.eclipse.smarthome.transform.map
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
Require-Bundle: org.junit;bundle-version="4.8.1"

Просмотреть файл

@ -0,0 +1,28 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
<title>About</title>
</head>
<body lang="EN-US">
<h2>About This Content</h2>
<p>June 5, 2006</p>
<h3>License</h3>
<p>The Eclipse Foundation makes available all content in this plug-in (&quot;Content&quot;). Unless otherwise
indicated below, the Content is provided to you under the terms and conditions of the
Eclipse Public License Version 1.0 (&quot;EPL&quot;). A copy of the EPL is available
at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is
being redistributed by another party (&quot;Redistributor&quot;) and different terms and conditions may
apply to your use of any object code in the Content. Check the Redistributor's license that was
provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise
indicated below, the terms and conditions of the EPL still apply to any source code in the Content
and such source code may be obtained at <a href="http://www.eclipse.org/">http://www.eclipse.org</a>.</p>
</body>
</html>

Просмотреть файл

@ -0,0 +1,5 @@
source.. = src/test/java/
output.. = target/test-classes/
bin.includes = META-INF/,\
.,\
about.html

Просмотреть файл

@ -0,0 +1,6 @@
#
#Fri Jun 19 12:42:17 CEST 2015
OPEN=offen
-=-
undefined=undefiniert
CLOSED=zu

Просмотреть файл

@ -0,0 +1,4 @@
CLOSED=closed
OPEN=open
undefined=unknown
-=-

Просмотреть файл

@ -0,0 +1,4 @@
CLOSED=fermé
OPEN=ouvert
undefined=inconnu
-=-

Просмотреть файл

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<groupId>org.eclipse.smarthome.transform</groupId>
<artifactId>pom</artifactId>
<version>0.8.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.smarthome.transform</groupId>
<artifactId>org.eclipse.smarthome.transform.map.test</artifactId>
<name>Eclipse SmartHome Map Transformation Service Tests</name>
<packaging>eclipse-test-plugin</packaging>
<build>
<plugins>
<plugin>
<groupId>org.eclipse.tycho</groupId>
<artifactId>tycho-surefire-plugin</artifactId>
<version>${tycho-version}</version>
</plugin>
</plugins>
</build>
</project>

Просмотреть файл

@ -0,0 +1,97 @@
/**
* Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.smarthome.transform.map.internal;
import static org.junit.Assert.*;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Properties;
import org.eclipse.smarthome.core.transform.TransformationException;
import org.eclipse.smarthome.transform.map.internal.MapTransformationService;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
/**
* @author Gaël L'hopital
*/
public class MapTransformationServiceTest {
private MapTransformationService processor;
@Before
public void init() {
processor = new MapTransformationService();
}
@Test
public void testTransformByMap() throws TransformationException {
String existingGermanFilename = "map/doorstatus_de.map";
String shouldBeLocalizedFilename = "map/doorstatus.map";
String inexistingFilename = "map/de.map";
// Test that we find a translation in an existing file
String source = "CLOSED";
String transformedResponse = processor.transform(existingGermanFilename, source);
Assert.assertEquals("zu", transformedResponse);
String usedfile = "conf/transform/" + existingGermanFilename;
Properties properties = new Properties();
try {
properties.load(new FileReader(usedfile));
properties.setProperty(source, "changevalue");
properties.store(new FileWriter(usedfile), "");
// This tests that the requested transformation file has been removed from
// the cache
transformedResponse = processor.transform(existingGermanFilename, source);
Assert.assertEquals("changevalue", transformedResponse);
properties.setProperty(source, "zu");
properties.store(new FileWriter(usedfile), "");
transformedResponse = processor.transform(existingGermanFilename, source);
Assert.assertEquals("zu", transformedResponse);
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
// Test that an unknown input in an existing file give the expected behaviour
// transformed response shall be the same as source if not found in the file
source = "UNKNOWN";
transformedResponse = processor.transform(existingGermanFilename, source);
Assert.assertEquals(source, transformedResponse);
// Test that an inexisting file raises correct exception as expected
source = "CLOSED";
try {
transformedResponse = processor.transform(inexistingFilename, source);
fail();
} catch (Exception e) {
// That's what we expect.
}
// Test that we find a localized version of desired file
source = "CLOSED";
transformedResponse = processor.transform(shouldBeLocalizedFilename, source);
// as we don't know the real locale at the moment the
// test is run, we test that the string has actually been transformed
Assert.assertNotEquals(source, transformedResponse);
transformedResponse = processor.transform(shouldBeLocalizedFilename, source);
Assert.assertNotEquals(source, transformedResponse);
}
}

Просмотреть файл

@ -4,8 +4,7 @@ Bundle-Vendor: Eclipse.org/SmartHome
Bundle-Version: 0.8.0.qualifier
Bundle-ManifestVersion: 2
Bundle-License: http://www.eclipse.org/legal/epl-v10.html
Import-Package: org.eclipse.smarthome.config.core,
org.eclipse.smarthome.core.transform,
Import-Package: org.eclipse.smarthome.core.transform,
org.slf4j
Bundle-SymbolicName: org.eclipse.smarthome.transform.map
Bundle-RequiredExecutionEnvironment: JavaSE-1.7

Просмотреть файл

@ -7,27 +7,13 @@
*/
package org.eclipse.smarthome.transform.map.internal;
import static java.nio.file.StandardWatchEventKinds.ENTRY_DELETE;
import static java.nio.file.StandardWatchEventKinds.ENTRY_MODIFY;
import static java.nio.file.StandardWatchEventKinds.OVERFLOW;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
import org.eclipse.smarthome.config.core.ConfigConstants;
import org.eclipse.smarthome.core.transform.TransformationException;
import org.eclipse.smarthome.core.transform.TransformationService;
import org.eclipse.smarthome.core.transform.AbstractFileTransformationService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -35,29 +21,14 @@ import org.slf4j.LoggerFactory;
* <p>
* The implementation of {@link TransformationService} which simply maps strings to other strings
* </p>
*
*
* @author Kai Kreuzer - Initial contribution and API
* @author Gaël L'hopital - Make it localizable
*/
public class MapTransformationService implements TransformationService {
public class MapTransformationService extends AbstractFileTransformationService<Properties> {
private final Logger logger = LoggerFactory.getLogger(MapTransformationService.class);
protected WatchService watchService = null;
protected final Map<String, Properties> cachedProperties = new ConcurrentHashMap<>();
protected void deactivate() {
cachedProperties.clear();
if (watchService != null) {
try {
watchService.close();
} catch (IOException e) {
logger.debug("Cannot cancel watch service for folder '{}'", getSourcePath());
}
watchService = null;
}
}
/**
* <p>
* Transforms the input <code>source</code> by mapping it to another string. It expects the mappings to be read from
@ -65,83 +36,32 @@ public class MapTransformationService implements TransformationService {
* simple lines with "key=value" pairs. To organize the various transformations one might use subfolders.
* </p>
*
* @param filename
* the name of the file which contains the key value pairs for the mapping. The name may contain
* subfoldernames
* as well
* @param properties
* the list of properties which contains the key value pairs for the mapping.
* @param source
* the input to transform
*
* @{inheritDoc
*
*/
*/
@Override
public String transform(String filename, String source) throws TransformationException {
if (filename == null || source == null) {
throw new TransformationException("the given parameters 'filename' and 'source' must not be null");
}
if (watchService == null) {
try {
initializeWatchService();
} catch (IOException e) {
// we cannot watch the folder, so let's at least clear the cache
cachedProperties.clear();
}
} else {
processFolderEvents();
}
Properties properties = cachedProperties.get(filename);
if (properties == null) {
String path = getSourcePath() + File.separator + filename;
try (Reader reader = new FileReader(path)) {
properties = new Properties();
properties.load(reader);
cachedProperties.put(filename, properties);
} catch (IOException e) {
String message = "opening file '" + filename + "' throws exception";
logger.error(message, e);
throw new TransformationException(message, e);
}
}
protected String internalTransform(Properties properties, String source) throws TransformationException {
String target = properties.getProperty(source);
if (target != null) {
logger.debug("transformation resulted in '{}'", target);
return target;
} else {
logger.warn("Could not find a mapping for '{}' in the file '{}'.", source, filename);
return "";
logger.debug("transformation resulted in '{}'", target);
}
return target;
}
private void processFolderEvents() {
WatchKey key = watchService.poll();
if (key != null) {
for (WatchEvent<?> e : key.pollEvents()) {
if (e.kind() == OVERFLOW) {
continue;
}
// Context for directory entry event is the file name of entry
@SuppressWarnings("unchecked")
WatchEvent<Path> ev = (WatchEvent<Path>) e;
Path path = ev.context();
logger.debug("Refreshing transformation file '{}'", path);
cachedProperties.remove(path.getFileName().toString());
}
key.reset();
@Override
protected Properties internalLoadTransform(String filename) throws TransformationException {
try {
Properties result = new Properties();
result.load(new FileReader(filename));
return result;
} catch (IOException e) {
throw new TransformationException("An error occured while opening file.", e);
}
}
private void initializeWatchService() throws IOException {
watchService = FileSystems.getDefault().newWatchService();
Path transformFilePath = Paths.get(getSourcePath());
transformFilePath.register(watchService, ENTRY_DELETE, ENTRY_MODIFY);
}
protected String getSourcePath() {
return ConfigConstants.getConfigFolder() + File.separator + TransformationService.TRANSFORM_FOLDER_NAME;
}
}

Просмотреть файл

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="src" path="src/test/java"/>
<classpathentry kind="output" path="target/test-classes"/>
</classpath>

Просмотреть файл

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>org.eclipse.smarthome.transform.scale.test</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.ManifestBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.SchemaBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.pde.PluginNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

Просмотреть файл

@ -0,0 +1,7 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
org.eclipse.jdt.core.compiler.compliance=1.7
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.7

Просмотреть файл

@ -0,0 +1,9 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Tests for the Scale Transformation Service
Bundle-SymbolicName: org.eclipse.smarthome.transform.scale.test
Bundle-Version: 0.8.0.qualifier
Bundle-Vendor: Eclipse.org/SmartHome
Fragment-Host: org.eclipse.smarthome.transform.scale
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
Require-Bundle: org.junit;bundle-version="4.8.1"

Просмотреть файл

@ -0,0 +1,28 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
<title>About</title>
</head>
<body lang="EN-US">
<h2>About This Content</h2>
<p>June 5, 2006</p>
<h3>License</h3>
<p>The Eclipse Foundation makes available all content in this plug-in (&quot;Content&quot;). Unless otherwise
indicated below, the Content is provided to you under the terms and conditions of the
Eclipse Public License Version 1.0 (&quot;EPL&quot;). A copy of the EPL is available
at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is
being redistributed by another party (&quot;Redistributor&quot;) and different terms and conditions may
apply to your use of any object code in the Content. Check the Redistributor's license that was
provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise
indicated below, the terms and conditions of the EPL still apply to any source code in the Content
and such source code may be obtained at <a href="http://www.eclipse.org/">http://www.eclipse.org</a>.</p>
</body>
</html>

Просмотреть файл

@ -0,0 +1,5 @@
source.. = src/test/java/
output.. = target/test-classes/
bin.includes = META-INF/,\
.,\
about.html

Просмотреть файл

@ -0,0 +1,5 @@
]..10[=low
[10..20[=middle
[20..300[=high
[300..]=extreme
[..]=catchall

Просмотреть файл

@ -0,0 +1,4 @@
]..10[=low
[1O..20[=middle
[20..300[=high
[300..]=extreme

Просмотреть файл

@ -0,0 +1,6 @@
[-40..20]=no significant
[20..29]=comfortable
[29..38]=some discomfort
[38..45]=avoid exertion
[45..54]=dangerous
[54..100]=heat stroke imminent

Просмотреть файл

@ -0,0 +1,6 @@
[-40..20]=nicht wesentlich
[20..29]=komfortabel
[29..38]=etwas unannehmlich
[38..45]=Anstrengung vermeiden
[45..54]=gefährlich
[54..100]=Hitzschlag bevorstehend

Просмотреть файл

@ -0,0 +1,6 @@
[-40..20]=non significatif
[20..29]=confortable
[29..38]=quelque inconfort
[38..45]=éviter de s'exposer
[45..54]=dangereux
[54..100]=coup de soleil imminent

Просмотреть файл

@ -0,0 +1,4 @@
]..10[=low
[10..20[=middle
[20..300[=high
[300..]=extreme

Просмотреть файл

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<groupId>org.eclipse.smarthome.transform</groupId>
<artifactId>pom</artifactId>
<version>0.8.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.smarthome.transform</groupId>
<artifactId>org.eclipse.smarthome.transform.scale.test</artifactId>
<name>Eclipse SmartHome Scale Transformation Service Tests</name>
<packaging>eclipse-test-plugin</packaging>
<build>
<plugins>
<plugin>
<groupId>org.eclipse.tycho</groupId>
<artifactId>tycho-surefire-plugin</artifactId>
<version>${tycho-version}</version>
</plugin>
</plugins>
</build>
</project>

Просмотреть файл

@ -0,0 +1,94 @@
/**
* Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.smarthome.transform.scale.internal;
import static org.junit.Assert.*;
import org.eclipse.smarthome.core.transform.TransformationException;
import org.eclipse.smarthome.transform.scale.internal.ScaleTransformationService;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
/**
* @author Gaël L'hopital
*/
public class ScaleTransformServiceTest {
private ScaleTransformationService processor;
@Before
public void init() {
processor = new ScaleTransformationService();
}
@Test
public void testTransformByScale() throws TransformationException {
// need to be sur we'll have the german version
String existingscale = "scale/humidex_de.scale";
String source="10";
String transformedResponse = processor.transform(existingscale, source);
Assert.assertEquals("nicht wesentlich", transformedResponse);
existingscale = "scale/limits.scale";
source="10";
transformedResponse = processor.transform(existingscale, source);
Assert.assertEquals("middle", transformedResponse);
}
@Test
public void testTransformByScaleLimits() throws TransformationException {
String existingscale = "scale/limits.scale";
// Testing upper bound opened range
String source="500";
String transformedResponse = processor.transform(existingscale, source);
Assert.assertEquals("extreme", transformedResponse);
// Testing lower bound opened range
source="-10";
transformedResponse = processor.transform(existingscale, source);
Assert.assertEquals("low", transformedResponse);
// Testing unfinite up and down range
existingscale = "scale/catchall.scale";
source="-10";
transformedResponse = processor.transform(existingscale, source);
Assert.assertEquals("catchall", transformedResponse);
}
@Test
public void testTransformByScaleUndef() throws TransformationException {
// check that for undefined/non numeric value we return the original value
String existingscale = "scale/humidex_fr.scale";
String source="-";
String transformedResponse = processor.transform(existingscale, source);
Assert.assertEquals("-", transformedResponse);
}
@Test
public void testTransformByScaleErrorInBounds() throws TransformationException {
// the tested file contains inputs that generate a conversion error of the bounds
// of range
String existingscale = "scale/erroneous.scale";
String source="15";
try {
@SuppressWarnings("unused")
String transformedResponse = processor.transform(existingscale, source);
fail();
} catch (TransformationException e) {
// awaited result
}
}
}

Просмотреть файл

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="src" output="target/classes" path="src/main/java"/>
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources"/>
<classpathentry kind="output" path="target/classes"/>
</classpath>

Просмотреть файл

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>org.eclipse.smarthome.transform.scale</name>
<comment>This is the transformation bundle containing the Scale Transformation Service</comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.ManifestBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.SchemaBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.ds.core.builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.pde.PluginNature</nature>
</natures>
</projectDescription>

Просмотреть файл

@ -0,0 +1,8 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
org.eclipse.jdt.core.compiler.compliance=1.7
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.source=1.7

Просмотреть файл

@ -0,0 +1,9 @@
#Fri Feb 19 20:28:11 CET 2010
activeProfiles=
eclipse.preferences.version=1
fullBuildGoals=process-test-resources
includeModules=false
resolveWorkspaceProjects=true
resourceFilterGoals=process-resources resources\:testResources
skipCompilerPlugin=true
version=1

Просмотреть файл

@ -0,0 +1,14 @@
Manifest-Version: 1.0
Bundle-Name: Eclipse SmartHome Scale Transformation Service
Bundle-Vendor: Eclipse.org/SmartHome
Bundle-Version: 0.8.0.qualifier
Bundle-ManifestVersion: 2
Bundle-License: http://www.eclipse.org/legal/epl-v10.html
Import-Package: com.google.common.collect,
org.eclipse.smarthome.core.transform,
org.slf4j
Bundle-SymbolicName: org.eclipse.smarthome.transform.scale
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
Service-Component: OSGI-INF/scaleservice.xml
Bundle-ClassPath: .

Просмотреть файл

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others.
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
which accompanies this distribution, and is available at
http://www.eclipse.org/legal/epl-v10.html
-->
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" immediate="true" name="org.eclipse.smarthome.transform.processor.scale">
<implementation class="org.eclipse.smarthome.transform.scale.internal.ScaleTransformationService"/>
<service>
<provide interface="org.eclipse.smarthome.core.transform.TransformationService"/>
</service>
<property name="smarthome.transform" type="String" value="SCALE"/>
</scr:component>

Просмотреть файл

@ -0,0 +1,28 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
<title>About</title>
</head>
<body lang="EN-US">
<h2>About This Content</h2>
<p>June 5, 2006</p>
<h3>License</h3>
<p>The Eclipse Foundation makes available all content in this plug-in (&quot;Content&quot;). Unless otherwise
indicated below, the Content is provided to you under the terms and conditions of the
Eclipse Public License Version 1.0 (&quot;EPL&quot;). A copy of the EPL is available
at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is
being redistributed by another party (&quot;Redistributor&quot;) and different terms and conditions may
apply to your use of any object code in the Content. Check the Redistributor's license that was
provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise
indicated below, the terms and conditions of the EPL still apply to any source code in the Content
and such source code may be obtained at <a href="http://www.eclipse.org/">http://www.eclipse.org</a>.</p>
</body>
</html>

Просмотреть файл

@ -0,0 +1,7 @@
output.. = target/classes/
bin.includes = META-INF/,\
.,\
OSGI-INF/,\
about.html
source.. = src/main/java/,\
src/main/resources/

Просмотреть файл

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.eclipse.smarthome.transform</groupId>
<artifactId>pom</artifactId>
<version>0.8.0-SNAPSHOT</version>
</parent>
<groupId>org.eclipse.smarthome.transform</groupId>
<artifactId>org.eclipse.smarthome.transform.sale</artifactId>
<name>Eclipse SmartHome Scale Transform Service</name>
<packaging>eclipse-plugin</packaging>
</project>

Просмотреть файл

@ -0,0 +1,127 @@
/**
* Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.smarthome.transform.scale.internal;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.smarthome.core.transform.TransformationException;
import org.eclipse.smarthome.core.transform.TransformationService;
import org.eclipse.smarthome.core.transform.AbstractFileTransformationService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.collect.BoundType;
import com.google.common.collect.Range;
import com.google.common.collect.Ranges;
/**
* The implementation of {@link TransformationService} which transforms the
* input by matching it between limits of ranges in a scale file
*
* @author Gaël L'hopital
*/
public class ScaleTransformationService extends AbstractFileTransformationService<Map<Range<Double>, String>> {
private final Logger logger = LoggerFactory.getLogger(ScaleTransformationService.class);
/** RegEx to extract a scale definition */
private static final Pattern limits_pattern = Pattern.compile("(\\[|\\])(.*)\\.\\.(.*)(\\[|\\])");
/**
* <p>
* Transforms the input <code>source</code> by matching searching the range where it fits
* i.e. [min..max]=value or ]min..max]=value
* </p>
*
* @param properties
* the list of properties defining all the available ranges
* @param source
* the input to transform
*
* @{inheritDoc
*
*/
@Override
protected String internalTransform(Map<Range<Double>, String> data, String source) throws TransformationException {
Double value = null;
try {
value = new Double(source);
for (Range<Double> range : data.keySet()) {
if (range.contains(value)) {
return data.get(range);
}
}
logger.debug("No matching range for '{}'", source);
} catch (NumberFormatException e) {
logger.debug("Scale can not work with non numeric input");
}
return null;
}
@Override
protected Map<Range<Double>, String> internalLoadTransform(String filename) throws TransformationException {
try {
Properties properties = new Properties();
properties.load(new FileReader(filename));
Map<Range<Double>,String> data = new HashMap<Range<Double>,String>();
for (Entry<Object, Object> f : properties.entrySet()) {
String key = (String) f.getKey();
String value = properties.getProperty(key);
Matcher matcher = limits_pattern.matcher(key);
if (matcher.matches() && (matcher.groupCount() == 4)) {
BoundType lowBoundType = matcher.group(1).equals("]") ? BoundType.OPEN : BoundType.CLOSED;
BoundType highBoundType = matcher.group(4).equals("[") ? BoundType.OPEN : BoundType.CLOSED;
String lowLimit = matcher.group(2);
String highLimit = matcher.group(3);
Range<Double> range = null;
Double lowValue = null;
Double highValue = null;
try {
if (!lowLimit.isEmpty()) lowValue = new Double(lowLimit);
if (!highLimit.isEmpty()) highValue = new Double(highLimit);
} catch (NumberFormatException e) {
throw new TransformationException("Error parsing bounds : "+lowLimit+".."+highLimit);
}
if (lowValue == null && highValue == null) {
range = Ranges.all();
} else if (lowValue == null) {
range = Ranges.upTo(highValue, highBoundType);
} else if (highValue == null) {
range = Ranges.downTo(lowValue, lowBoundType);
} else {
range = Ranges.range(lowValue, lowBoundType, highValue, highBoundType);
}
data.put(range, value);
} else {
logger.warn("Scale transform entry does not comply with syntax : '{}', '{}'",key,value);
}
}
return data;
} catch (IOException e) {
throw new TransformationException("An error occured while opening file.", e);
}
}
}

Просмотреть файл

@ -0,0 +1 @@
Bundle resources go in here!

Просмотреть файл

@ -19,6 +19,9 @@
<module>org.eclipse.smarthome.transform.exec</module>
<module>org.eclipse.smarthome.transform.javascript</module>
<module>org.eclipse.smarthome.transform.map</module>
<module>org.eclipse.smarthome.transform.map.test</module>
<module>org.eclipse.smarthome.transform.scale</module>
<module>org.eclipse.smarthome.transform.scale.test</module>
<module>org.eclipse.smarthome.transform.regex</module>
<module>org.eclipse.smarthome.transform.regex.test</module>
<module>org.eclipse.smarthome.transform.xpath</module>

Просмотреть файл

@ -67,42 +67,42 @@
install-size="0"
version="0.0.0"
unpack="false"/>
<plugin
id="org.eclipse.smarthome.transform.exec"
download-size="0"
install-size="0"
version="0.0.0"
unpack="false"/>
<plugin
id="org.eclipse.smarthome.transform.javascript"
download-size="0"
install-size="0"
version="0.0.0"
unpack="false"/>
<plugin
id="org.eclipse.smarthome.transform.map"
download-size="0"
install-size="0"
version="0.0.0"
unpack="false"/>
<plugin
id="org.eclipse.smarthome.transform.regex"
download-size="0"
install-size="0"
version="0.0.0"
unpack="false"/>
<plugin
id="org.eclipse.smarthome.transform.xpath"
download-size="0"
install-size="0"
version="0.0.0"
unpack="false"/>
<plugin
id="org.eclipse.smarthome.transform.xslt"
download-size="0"
@ -215,4 +215,11 @@
version="0.0.0"
unpack="false"/>
<plugin
id="org.eclipse.smarthome.transform.scale"
download-size="0"
install-size="0"
version="0.0.0"
unpack="false"/>
</feature>