Commit 2c465577 authored by Nico Mack's avatar Nico Mack

Numerous fixes and improvements to handling of complex variable types

such as Vectors and Maps
parent b8827db6
......@@ -56,6 +56,7 @@ public class PythonExecutor extends Executor {
TYPE_MAPPING.put(PyBoolean.TYPE, Boolean.class);
TYPE_MAPPING.put(PyString.TYPE, String.class);
TYPE_MAPPING.put(PyUnicode.TYPE, String.class);
TYPE_MAPPING.put(PyDictionary.TYPE, Map.class);
}
private static final String SCRIPT_ENGINE_WORKING_DIR = "python.workingDir"; //$NON-NLS-1$
......@@ -90,122 +91,6 @@ public class PythonExecutor extends Executor {
// ***************************************************************************
// ---------------------------------------------------------------------------
// ============================================================================
// = Low level conversion for scalars from Java to Python and back again
// ============================================================================
// ---------------------------------------------------------------------------
/**
* Converts a java double value into a python double.
*
* @param value
* specifies the java double value to convert
* @return a python double initialized to the same value as the specified java double.
*/
// ---------------------------------------------------------------------------
private PyObject pythonizeDouble(Double value) {
return (value != null) ? new PyFloat(value) : Py.None;
}
// ---------------------------------------------------------------------------
/**
* Converts a python double value into a java double.
*
* @param value
* specifies the python double value to convert
* @return a java double initialized to the same value as the specified python double.
*/
// ---------------------------------------------------------------------------
private Double depythonizeDouble(PyObject object) {
return (object != null) ? (Double) object.__tojava__(Double.class) : null;
}
// ---------------------------------------------------------------------------
/**
* Converts a java integer value into a python integer.
*
* @param value
* specifies the java integer value to convert
* @return a python integer initialized to the same value as the specified java integer.
*/
// ---------------------------------------------------------------------------
private PyObject pythonizeInteger(Integer value) {
return (value != null) ? new PyInteger(value) : Py.None;
}
// ---------------------------------------------------------------------------
/**
* Converts a python integer value into a java integer.
*
* @param value
* specifies the python integer value to convert
* @return a java integer initialized to the same value as the specified python integer.
*/
// ---------------------------------------------------------------------------
private Integer depythonizeInteger(PyObject object) {
return (object != null) ? (Integer) object.__tojava__(Integer.class) : null;
}
// ---------------------------------------------------------------------------
/**
* Converts a java boolean value into a python boolean.
*
* @param value
* specifies the java boolean value to convert
* @return a python boolean initialized to the same value as the specified java boolean.
*/
// ---------------------------------------------------------------------------
private PyObject pythonizeBoolean(Boolean value) {
return (value != null) ? new PyBoolean(value) : Py.None;
}
// ---------------------------------------------------------------------------
/**
* Converts a python boolean value into a java boolean.
*
* @param value
* specifies the python boolean value to convert
* @return a java boolean initialized to the same value as the specified python boolean.
*/
// ---------------------------------------------------------------------------
private Boolean depythonizeBoolean(PyObject object) {
return (object != null) ? (Boolean) object.__tojava__(Boolean.class) : null;
}
// ---------------------------------------------------------------------------
/**
* Converts a java boolean value into a python boolean.
*
* @param value
* specifies the java boolean value to convert
* @return a python boolean initialized to the same value as the specified java boolean.
*/
// ---------------------------------------------------------------------------
private PyObject pythonizeObject(Object value) {
return (value != null) ? Py.java2py(value) : Py.None;
}
// ---------------------------------------------------------------------------
/**
* Converts a python boolean value into a java boolean.
*
* @param value
* specifies the python boolean value to convert
* @return a java boolean initialized to the same value as the specified python boolean.
*/
// ---------------------------------------------------------------------------
private Object depythonizeObject(PyObject object) {
return (object != null) ? object.__tojava__(Object.class) : null;
}
// ---------------------------------------------------------------------------
// ============================================================================
// = Low level conversion for vectors from Java to Python and back again
......@@ -221,50 +106,6 @@ public class PythonExecutor extends Executor {
return array;
}
// ---------------------------------------------------------------------------
// private PyArray pythonizeDoubleVector(List<Double> doubles) {
// PyArray array = new PyArray(Double.class, doubles.size());
// int index = 0;
// for (Double value : doubles) {
// array.set(index++, pythonizeDouble(value));
// }
// return array;
// }
// ---------------------------------------------------------------------------
// private PyArray pythonizeIntegerVector(List<Integer> integers) {
// PyArray array = new PyArray(Integer.class, integers.size());
// int index = 0;
// for (Integer value : integers) {
// array.set(index++, pythonizeInteger(value));
// }
// return array;
// }
// ---------------------------------------------------------------------------
// private PyArray pythonizeBooleanVector(List<Boolean> booleans) {
// PyArray array = new PyArray(Boolean.class, booleans.size());
// int index = 0;
// for (Boolean value : booleans) {
// array.set(index++, pythonizeBoolean(value));
// }
// return array;
// }
// ---------------------------------------------------------------------------
// private PyArray pythonizeObjectVector(List<Object> objects) {
// PyArray array = new PyArray(Object.class, objects.size());
// int index = 0;
// for (Object value : objects) {
// array.set(index++, pythonizeObject(value));
// }
// return array;
// }
// ---------------------------------------------------------------------------
// ============================================================================
// = High level conversion for complex variables from Java to Python and back again
......@@ -329,10 +170,10 @@ public class PythonExecutor extends Executor {
MapVariable<?, ?> map = (MapVariable<?, ?>) declaration.getVariable();
String field = declaration.getField();
PyDictionary dictionary = new PyDictionary();
if (!map.isEmpty()) {
if (Strings.isNullOrEmpty(field)) {
PyDictionary dictionary = new PyDictionary();
for (Entry<?, ?> entry : map.entrySet()) {
if (entry.getValue() instanceof List) {
List<?> list = (List<?>) entry.getValue();
......@@ -346,6 +187,8 @@ public class PythonExecutor extends Executor {
} else {
pythonized = Py.java2py(map.get(field));
}
} else {
pythonized = dictionary;
}
return pythonized;
}
......@@ -380,6 +223,7 @@ public class PythonExecutor extends Executor {
}
}
map.suspendListenerNotification(false);
map.notifyInputChangeListeners();
} else {
PyObject value = dictionary.__finditem__(Py.java2py(field));
Class<?> clazz = TYPE_MAPPING.get(value.getType());
......@@ -400,17 +244,6 @@ public class PythonExecutor extends Executor {
String identifier = entry.getKey().intern();
Method getter = entry.getValue();
pythonized.__setitem__(identifier, Py.java2py(Variable.invokeVariableMethod(getter, structured, null)));
// if (Double.class.isAssignableFrom(getter.getReturnType())) {
// pythonized.__setitem__(identifier, pythonizeDouble((Double) Variable.invokeVariableMethod(getter,
// structured, null)));
// } else if (Integer.class.isAssignableFrom(getter.getReturnType())) {
// pythonized.__setitem__(identifier, pythonizeInteger((Integer)
// Variable.invokeVariableMethod(getter, structured, null)));
// } else if (Boolean.class.isAssignableFrom(getter.getReturnType())) {
// pythonized.__setitem__(identifier, pythonizeBoolean((Boolean)
// Variable.invokeVariableMethod(getter, structured, null)));
// }
}
} else {
LOGGER.warn("Failed to determine getters for structured variable {}", structured.getName()); //$NON-NLS-1$
......@@ -433,20 +266,6 @@ public class PythonExecutor extends Executor {
PyObject object = dictionary.__finditem__(identifier);
parameters.add(object.__tojava__(clazz));
Variable.invokeVariableMethod(setter, structured, parameters.toArray());
// if (Double.class.isAssignableFrom((setter.getParameters())[0].getType())) {
// ArrayList<Double> doubles = new ArrayList<>();
// doubles.add(this.depythonizeDouble(dictionary.__finditem__(identifier)));
// Variable.invokeVariableMethod(setter, structured, doubles.toArray());
// } else if (Integer.class.isAssignableFrom((setter.getParameters())[0].getType())) {
// ArrayList<Integer> integers = new ArrayList<>();
// integers.add(this.depythonizeInteger(dictionary.__finditem__(identifier)));
// Variable.invokeVariableMethod(setter, structured, integers.toArray());
// } else if (Boolean.class.isAssignableFrom((setter.getParameters())[0].getType())) {
// ArrayList<Boolean> booleans = new ArrayList<>();
// booleans.add(this.depythonizeBoolean(dictionary.__finditem__(identifier)));
// Variable.invokeVariableMethod(setter, structured, booleans.toArray());
// }
}
} else {
LOGGER.warn("Failed to determine setters for structured variable {}", structured.getName()); //$NON-NLS-1$
......
......@@ -521,6 +521,17 @@ public class SqlExecutor extends Executor {
variable.setValueFromObject(values[index]);
} else {
LOGGER.info("Query returned no results!"); //$NON-NLS-1$
if (variable instanceof VectorVariable) {
VectorVariable<?> vector = (VectorVariable<?>) variable;
vector.clear();
vector.notifyInputChangeListeners();
} else if (variable instanceof MapVariable) {
MapVariable<?, ?> map = (MapVariable<?, ?>) variable;
map.clear();
map.notifyInputChangeListeners();
} else {
variable.setValue(null);
}
}
}
}
......
......@@ -168,7 +168,12 @@ public class MapVariable<K, V> extends Variable<Map<K, V>> implements Map<K, V>
@Override
public void setValueFromObject(Object object) {
this.value = this.valueFromObject(object);
if (this.value != null) {
this.value.clear();
} else {
this.value = new ConcurrentHashMap<K, V>();
}
this.value.putAll(this.valueFromObject(object));
}
// ---------------------------------------------------------------------------
......@@ -186,6 +191,21 @@ public class MapVariable<K, V> extends Variable<Map<K, V>> implements Map<K, V>
/** {@inheritDoc} */
// ---------------------------------------------------------------------------
@Override
public String toString() {
StringBuilder renderer = new StringBuilder(name);
if (value != null) {
renderer.append(value);
} else {
renderer.append("null"); //$NON-NLS-1$
}
return renderer.toString();
}
// ---------------------------------------------------------------------------
/** {@inheritDoc} */
// ---------------------------------------------------------------------------
@Override
public Map<K, V> valueFromString(String stringValue) {
// TODO Auto-generated method stub
......
......@@ -451,10 +451,13 @@ public class NumericalVariable extends Variable<Double> {
@Override
public NumericalVariable clone() {
NumericalVariable variable = new NumericalVariable(name, unit, value);
variable.displayName = displayName;
variable.format = format;
variable.minValue = minValue;
variable.maxValue = maxValue;
variable.scale = scale;
variable.roundingFactor = roundingFactor;
variable.epsilon = epsilon;
variable.listeners = new Vector<>(listeners);
return variable;
}
......
......@@ -361,7 +361,9 @@ public abstract class Variable<V> implements Cloneable {
public HashMap<InputChangeListener, Variable<?>> consolidateListeners(HashMap<InputChangeListener, Variable<?>> consolidated) {
for (InputChangeListener listener : listeners) {
consolidated.put(listener, this);
if (!consolidated.containsKey(listener)) {
consolidated.put(listener, this);
}
}
return consolidated;
}
......
......@@ -274,8 +274,9 @@ public class VectorVariable<B> extends Variable<List<B>> implements List<B> {
if (objectValue instanceof List) {
return (List<B>) objectValue;
}
return new ArrayList<>();
List<B> list = new ArrayList<>();
list.add((B) objectValue);
return list;
}
......
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