Commit b3aa8423 authored by Nico Mack's avatar Nico Mack

Integrated support for SpatialVariables in PythonExecutor

parent 37e3695e
......@@ -5,6 +5,11 @@
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.python.pydev.PyDevBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
......@@ -19,5 +24,6 @@
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
<nature>org.python.pydev.pythonNature</nature>
</natures>
</projectDescription>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?eclipse-pydev version="1.0"?><pydev_project>
<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Default</pydev_property>
<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.7</pydev_property>
<pydev_pathproperty name="org.python.pydev.PROJECT_SOURCE_PATH">
<path>/${PROJECT_DIR_NAME}/python</path>
</pydev_pathproperty>
</pydev_project>
'''
Created on Aug 16, 2017
@author: mack
'''
def AddPoints (A, B):
C = {}
C['x'] = A['x'] + B['x']
C['y'] = A['y'] + B['y']
C['a'] = A['a'] + B['a']
return C
\ No newline at end of file
......@@ -52,7 +52,7 @@ public class DisplayWidgetBootstrapper implements BootstrapCallback {
// * Constants *
// ***************************************************************************
private static Logger LOGGER = LoggerFactory.getLogger(DisplayWidgetBootstrapper.class.getName());
private static final Logger LOGGER = LoggerFactory.getLogger(DisplayWidgetBootstrapper.class.getName());
// ---------------------------------------------------------------------------
// ***************************************************************************
......
......@@ -54,7 +54,7 @@ public class Equation {
private String script;
private boolean isolated;
private static Logger LOGGER = LoggerFactory.getLogger(Equation.class.getSimpleName());
private static final Logger LOGGER = LoggerFactory.getLogger(Equation.class.getSimpleName());
/**
* Constructor
......
......@@ -165,11 +165,11 @@ public class NumericalVariable extends Variable<Double> {
this.setValue(this.valueFromObject(object));
}
/** {@inheritDoc} */
@Override
public Double getValue() {
return this.value;
}
// /** {@inheritDoc} */
// @Override
// public Double getValue() {
// return super.getValue();
// }
/**
*
......
......@@ -135,42 +135,42 @@ public class SpatialVariable extends Variable<Point> {
}
@ExecutorScope(identifier = "x")
public double getX() {
return (this.value != null) ? this.value.getX() : 0;
public Double getX() {
return (this.value != null) ? Double.valueOf(this.value.x) : 0;
}
@ExecutorScope(identifier = "x")
public void setX(double value) {
public void setX(Double value) {
if (this.value == null) {
this.value = new Point();
}
this.value.x = (float) value;
this.value.x = (value != null) ? value.floatValue() : 0f;
}
@ExecutorScope(identifier = "y")
public double getY() {
return (this.value != null) ? this.value.getY() : 0;
public Double getY() {
return (this.value != null) ? Double.valueOf(this.value.y) : 0;
}
@ExecutorScope(identifier = "y")
public void setY(double value) {
public void setY(Double value) {
if (this.value == null) {
this.value = new Point();
}
this.value.y = (float) value;
this.value.y = (value != null) ? value.floatValue() : 0f;
}
@ExecutorScope(identifier = "a")
public double getA() {
return (this.value != null) ? this.value.getAngle() : 0;
public Double getAngle() {
return (this.value != null) ? Double.valueOf(this.value.getAngle()) : 0;
}
@ExecutorScope(identifier = "a")
public void setAngle(double value) {
public void setAngle(Double value) {
if (this.value == null) {
this.value = new Point();
}
this.value.setAngle((float) value);
this.value.setAngle((value != null) ? value.floatValue() : 0f);
}
}
......@@ -24,11 +24,19 @@ import lu.list.itis.dkd.dbc.annotation.NonNullByDefault;
import lu.list.itis.dkd.dbc.annotation.Nullable;
import lu.list.itis.dkd.tui.cps.InputChangeListener;
import lu.list.itis.dkd.tui.cps.InputEvent;
import lu.list.itis.dkd.tui.cps.utility.ExecutorScope;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.Vector;
/**
......@@ -56,6 +64,8 @@ public abstract class Variable<V> implements Cloneable {
protected V value;
protected boolean modified = true;
protected int suspendNotificationSemaphore = 0;
public static final String NO_UNIT = ""; //$NON-NLS-1$
......@@ -136,14 +146,27 @@ public abstract class Variable<V> implements Cloneable {
/**
* Simple getter method for the value held by the {@link Variable} instance.
* Simple getter method for the value held by the {@link Variable} instance. Reading the value
* will reset the modified flag.
*
* @return The value held by the {@link Variable} instance.
*/
public V getValue() {
this.modified = false;
return value;
}
/**
* checks whether this variable was modified since it was read for the last time. *
*
* @return <code>true</code> if variable was modified since last read, <code>false</code>
* otherwise.
*/
public boolean wasModified() {
return this.modified;
}
/**
* Method used to set the value held by the variable.
*
......@@ -151,6 +174,8 @@ public abstract class Variable<V> implements Cloneable {
* The new value the variable should have.
*/
public void setValue(V newValue) {
this.modified = ((newValue != null) && (!newValue.equals(this.value)));
this.value = newValue;
this.notifyInputChangeListeners(new InputEvent(this));
}
......@@ -216,6 +241,76 @@ public abstract class Variable<V> implements Cloneable {
return false;
}
/**
*
* @param clazz
* @return
*/
public static Map<String, Method> getValueGetters(Class<?> clazz) {
Map<String, Method> getters = new HashMap<>();
try {
BeanInfo classDetails = Introspector.getBeanInfo(clazz);
PropertyDescriptor[] properties = classDetails.getPropertyDescriptors();
for (Method method : clazz.getDeclaredMethods()) {
ExecutorScope scope = method.getAnnotation(ExecutorScope.class);
if (scope != null) {
String identifier = scope.identifier();
for (PropertyDescriptor descriptor : properties) {
if (method.equals(descriptor.getReadMethod())) {
getters.put(identifier, method);
}
}
}
}
} catch (IntrospectionException e) {
LOGGER.error("Failed to lookup value Getters for variable class {}!", clazz.getSimpleName()); //$NON-NLS-1$
}
return getters;
}
/**
*
* @param clazz
* @return
*/
public static Map<String, Method> getValueSetters(Class<?> clazz) {
Map<String, Method> setters = new HashMap<>();
try {
BeanInfo classDetails = Introspector.getBeanInfo(clazz);
PropertyDescriptor[] properties = classDetails.getPropertyDescriptors();
for (Method method : clazz.getDeclaredMethods()) {
ExecutorScope scope = method.getAnnotation(ExecutorScope.class);
if (scope != null) {
String identifier = scope.identifier();
for (PropertyDescriptor descriptor : properties) {
if (method.equals(descriptor.getWriteMethod())) {
setters.put(identifier, method);
}
}
}
}
} catch (IntrospectionException e) {
LOGGER.error("Failed to lookup value Setters for variable class {}!", clazz.getSimpleName()); //$NON-NLS-1$
}
return setters;
}
public static Object invokeVariableMethod(Method method, Variable<?> variable, Object[] parameters) {
Object result = null;
try {
result = method.invoke(variable, parameters);
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
LOGGER.error("Failed to invoke method {} on variable {}!", method.getName(), variable.getName(), e); //$NON-NLS-1$
}
return result;
}
/**
* Method invoked to add a {@link InputChangeListener} to the {@link Vector} of listeners to
* notify on tick.
......
/**
* Copyright Luxembourg Institute of Science and Technology, 2017. All rights reserved. If you wish
* to use this code for any purpose, please contact the author(s).
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
* WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package lu.list.itis.dkd.tui.utility;
import lu.list.itis.dkd.tui.cps.variable.Variable;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
/**
* @author Nico Mack [nico.mack@list.lu]
* @since 2.5
* @version 2.5.0
*/
// ***************************************************************************
// * Class Definition and Members *
// ***************************************************************************
public class VariableManager {
private HashMap<String, Variable<?>> variables;
// ---------------------------------------------------------------------------
// ***************************************************************************
// * Constructor(s) *
// ***************************************************************************
// ---------------------------------------------------------------------------
public VariableManager() {
variables = new HashMap<>();
}
// ---------------------------------------------------------------------------
public VariableManager(Collection<Variable<?>> variables) {
this.variables = new HashMap<>();
for (Variable<?> variable : variables) {
this.variables.put(variable.getName(), variable);
}
}
// ---------------------------------------------------------------------------
// ***************************************************************************
// * Primitives *
// ***************************************************************************
// ---------------------------------------------------------------------------
private boolean connect(Variable<?> local, Map<String, Variable<?>> globals) {
boolean connected = false;
if ((globals != null) && globals.containsKey(local.getName())) {
Variable<?> global = globals.get(local.getName());
if (globals.getClass().isAssignableFrom(global.getClass())) {
this.variables.put(local.getName(), global);
connected = true;
}
}
return connected;
}
// ---------------------------------------------------------------------------
// ***************************************************************************
// * Class Body *
// ***************************************************************************
// ---------------------------------------------------------------------------
public void connectWithGlobals(Map<String, Variable<?>> globals) {
for (Variable<?> local : variables.values()) {
connect(local, globals);
}
}
// ---------------------------------------------------------------------------
// ***************************************************************************
// * End of class *
// ***************************************************************************
// ---------------------------------------------------------------------------
}
......@@ -33,7 +33,7 @@ public class GaugeWidget extends TetherableWidget implements InputChangeListener
// * Constants *
// ***************************************************************************
private static Logger LOGGER = LoggerFactory.getLogger(GaugeWidget.class.getSimpleName());
private static final Logger LOGGER = LoggerFactory.getLogger(GaugeWidget.class.getSimpleName());
// ---------------------------------------------------------------------------
// ***************************************************************************
......@@ -86,7 +86,7 @@ public class GaugeWidget extends TetherableWidget implements InputChangeListener
@Override
public void setInformation(Double information) {
getCoronas(Gauge.class).forEach(corona -> ((InformationReceiver<Double>) corona).setInformation(information));
getCoronas(Gauge.class).forEach(corona -> (corona).setInformation(information));
}
// ---------------------------------------------------------------------------
......
......@@ -30,8 +30,7 @@ public class SelectorWidget extends ValueWidget {
// * Constants *
// ***************************************************************************
public static int NONE = -1;
private static double TWO_PI = 2 * Math.PI;
public static final int NONE = -1;
// ---------------------------------------------------------------------------
// ***************************************************************************
......@@ -56,6 +55,26 @@ public class SelectorWidget extends ValueWidget {
}
}
// ---------------------------------------------------------------------------
/**
* Copy constructor to clone widget.
*
* @param original
* specifies the original widget to create an exact copy from.
*/
// ---------------------------------------------------------------------------
public SelectorWidget(SelectorWidget original) {
super(original);
this.numberOfPositions = original.numberOfPositions;
this.presetPosition = original.presetPosition;
if (presetPosition != NONE) {
this.selectPosition(presetPosition);
}
}
// ---------------------------------------------------------------------------
// ***************************************************************************
// * Primitives *
......@@ -79,7 +98,7 @@ public class SelectorWidget extends ValueWidget {
@Override
protected void updateFromRotation(double angle) {
// Empty to disable features implemented in inherited class
}
// ---------------------------------------------------------------------------
......@@ -174,10 +193,8 @@ public class SelectorWidget extends ValueWidget {
autoFading.forEach(corona -> corona.fadeIn());
}
if (manager.isRotating()) {
if (position != currentPosition) {
this.selectPosition(position);
}
if (manager.isRotating() && (position != currentPosition)) {
this.selectPosition(position);
}
}
......@@ -221,6 +238,12 @@ public class SelectorWidget extends ValueWidget {
}
}
// ---------------------------------------------------------------------------
@Override
public SelectorWidget clone() {
return new SelectorWidget(this);
}
// ---------------------------------------------------------------------------
// ***************************************************************************
// * End of Class *
......
......@@ -153,7 +153,6 @@ public class ArcGraph extends ValueCorona {
face.subtract(inner);
outer.subtract(inner);
if (this.labelShape != null) {
AffineTransform originTranslator = new AffineTransform();
......
......@@ -29,7 +29,7 @@ public class ValueCorona extends Corona implements InformationReceiver<Object> {
// ***************************************************************************
// ---------------------------------------------------------------------------
public ValueCorona(ValueCoronaBuilder builder) {
public ValueCorona(ValueCoronaBuilder<?> builder) {
super(builder);
this.variable = builder.variable;
this.selected = false;
......
/**
* Copyright Luxembourg Institute of Science and Technology, 2017. All rights reserved. If you wish
* to use this code for any purpose, please contact the author(s).
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
* WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package lu.list.itis.dkd.tui.cps.system.executor;
import static org.junit.Assert.assertEquals;
import lu.list.itis.dkd.tui.cps.system.Import;
import lu.list.itis.dkd.tui.cps.variable.SpatialVariable;
import lu.list.itis.dkd.tui.utility.Point;
import lu.list.itis.dkd.tui.utility.PropertiesFetcher;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
/**
* @author mack
* @since [major].[minor]
* @version [major].[minor].[micro]
*/
public class PythonExecutorTest {
private Properties properties;
/**
* @throws java.lang.Exception
*/
@Before
public void setUp() throws Exception {
this.properties = PropertiesFetcher.fetchProperties("test_properties.properties");
}
/**
* @throws java.lang.Exception
*/
@After
public void tearDown() throws Exception {}
@Test
public void setSpatialVariableTest() {
SpatialVariable pointA = new SpatialVariable("PointA", "n/a", null); //$NON-NLS-2$
pointA.setValue(pointA.valueFromString("49.6111 , 45, 3.14")); //$NON-NLS-1$
SpatialVariable pointB = new SpatialVariable("PointB", "n/a", null); //$NON-NLS-2$
pointB.setValue(pointB.valueFromString("10.5 , 14.10, 3.14")); //$NON-NLS-1$
SpatialVariable pointC = new SpatialVariable("PointC", "n/a", null); //$NON-NLS-2$
pointC.setValue(pointC.valueFromString("0,0,0")); //$NON-NLS-1$
List<Import> imports = new ArrayList<>();
Import funtion = new Import("AddPoints", "Spatial"); //$NON-NLS-1$ //$NON-NLS-2$
imports.add(funtion);
PythonExecutor executor = new PythonExecutor(this.properties);
executor.resolve(imports);
executor.set(pointA);
executor.set(pointB);
executor.eval("PointC = AddPoints(PointA,PointB)"); //$NON-NLS-1$
executor.get(pointC);
Point coordinates = pointC.getValue();
assertEquals(60.111d, coordinates.x, 0.0001);
assertEquals(59.10d, coordinates.y, 0.0001);
assertEquals(6.28d, coordinates.getAngle(), 0.0001);
}
}
......@@ -21,6 +21,9 @@ import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.lang.reflect.Method;
import java.util.Map;
/**
* @author mack
* @since [major].[minor]
......@@ -49,4 +52,10 @@ public class SpatialVariableTest {
assertEquals(0, fromString.getAngle(), 0.0001);
}
@Test
public void testExecutorScope() {
Map<String, Method> getters = Variable.getValueGetters(SpatialVariable.class);
Map<String, Method> setters = Variable.getValueSetters(SpatialVariable.class);
}
}
# Properties for the equation system
executor.class = lu.list.itis.dkd.tui.cps.system.executor.PythonExecutor
numeric.variable.class = lu.list.itis.dkd.tui.cps.variable.tangible.TangibleNumericalVariable
text.variable.class = lu.list.itis.dkd.tui.cps.variable.TextVariable
spatial.variable.class = lu.list.itis.dkd.tui.cps.variable.SpatialVariable
vector.variable.class = lu.list.itis.dkd.tui.cps.variable.VectorVariable
#octave.executable=/opt/local/bin/octave
#octave.workingDir=model/octave
python.workingDir=python
equation.system=ColosseumScenario4.xml
sql.connection.url=jdbc:postgresql://10.122.10.89:5432/gtui
sql.driver.class=org.postgresql.Driver
sql.user.name=gtui
sql.user.password=PW4gtui
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment