Commit cb5e1e6b authored by Nico Mack's avatar Nico Mack

Added additional Trace logging. Improved handling of notification

suspension. Moved variable value class variable into Variable class
parent 53ed2271
......@@ -48,7 +48,7 @@ public class InputEvent extends EventObject {
* @param tick
* The turn index the event was triggered at.
*/
public InputEvent(Variable source, long tick) {
public InputEvent(Variable<?> source, long tick) {
super(source);
this.tick = tick;
}
......@@ -59,7 +59,7 @@ public class InputEvent extends EventObject {
* @param source
* The source of the event.
*/
public InputEvent(Variable source) {
public InputEvent(Variable<?> source) {
super(source);
this.tick = -1;
}
......@@ -72,4 +72,9 @@ public class InputEvent extends EventObject {
public long getTick() {
return tick;
}
@Override
public Variable<?> getSource() {
return (Variable<?>) this.source;
}
}
\ No newline at end of file
......@@ -46,10 +46,10 @@ import javax.script.ScriptEngine;
*/
@NonNullByDefault
public class Equation {
private String name;
private Mapping mapping;
private Mapping lockedMapping;
@Nullable
// private ScriptEngine scriptEngine;
private Executor scriptExecutor;
private String script;
......@@ -65,7 +65,8 @@ public class Equation {
* the variables in the script must coincide with the names of the variables in the
* mapping.
*/
public Equation(Mapping mapping, String script) {
public Equation(String name, Mapping mapping, String script) {
this.name = name;
this.mapping = mapping;
this.lockedMapping = mapping;
this.script = script;
......@@ -85,14 +86,6 @@ public class Equation {
* mapping.
*/
public void evaluate() {
// Preconditions.checkState(scriptEngine != null);
// try {
// mapping.getDependentVariable().setValue(scriptEngine.eval(replaceVariables()));
// } catch (ScriptException e) {
// Logger.getLogger(Equation.class.getSimpleName()).log(Level.SEVERE, "Exception while
// executing script!", e); //$NON-NLS-1$
// }
LinkedHashSet<Variable<?>> dependentVariables;
String evaluationErrors;
......@@ -117,7 +110,7 @@ public class Equation {
consolidatedListeners = new HashMap<>();
for (Variable<?> variable : dependentVariables) {
variable.setConsolidated(consolidated);
variable.suspendListenerNotification(consolidated);
if (consolidated)
consolidatedListeners = variable.consolidateListeners(consolidatedListeners);
try {
......@@ -125,7 +118,7 @@ public class Equation {
} catch (Exception exception) {
LOGGER.error("Error while retrieving variable {}", variable.getName(), exception); //$NON-NLS-1$
}
variable.setConsolidated(false);
variable.suspendListenerNotification(false);
}
if (consolidated && consolidatedListeners != null) {
......@@ -147,35 +140,6 @@ public class Equation {
}
}
/**
* Method used to replace variables with their actual values in the formula.
*
* @return The formula with variables replaced by their values, ready for evaluation.
*/
// private String replaceVariables() {
// String result = new String(script);
//
// for (Variable variable : lockedMapping.getIndependentVariables()) {
// result = result.replaceAll(variable.getName(), variable.getValue().toString());
// }
//
// for (Variable variable : lockedMapping.getDependentVariables()) {
// result = result.replaceAll(variable.getName(), variable.getValue().toString());
// }
//
// assert result != null;
// return result;
// }
/**
* Method for setting the script engine to use.
*
* @param engine
* The {@link ScriptEngine} instance to use for evaluating the scripted formulas.
*/
// public void setScriptEngine(ScriptEngine engine) {
// scriptEngine = engine;
// }
/**
* Method for setting the script engine to use.
*
......@@ -207,17 +171,8 @@ public class Equation {
lockedMapping = mapping.lock();
}
// /**
// * Method used to update the mapping with a variable, that is, to update the reference to a
// * variable so that the mapping will correctly map all changes of the variable. <br>
// * <br>
// * <u>Note:</u> This method depends on the equality of variables being by name and unit.
// *
// * @param variable
// * The variable to update the reference for.
// * @see Variable#equals(Object)
// */
// public void updateMapping(Variable variable) {
// mapping.updateVariableReference(variable);
// }
@Override
public String toString() {
return this.name;
}
}
\ No newline at end of file
......@@ -635,7 +635,7 @@ public class EquationSystemBuilder {
Mapping variableMapping = new Mapping(equationInputs, equationOutputs);
final LinearEquationSystem equationSystem = new LinearEquationSystem(lockToNesting);
Equation newEquation = new Equation(variableMapping, script);
Equation newEquation = new Equation(equationName, variableMapping, script);
newEquation.setExecutor(executors.get(executor));
equationSystem.addEquation(newEquation);
......
......@@ -22,10 +22,12 @@ package lu.list.itis.dkd.tui.cps.system;
import lu.list.itis.dkd.dbc.annotation.NonNullByDefault;
import lu.list.itis.dkd.tui.cps.InputEvent;
import lu.list.itis.dkd.tui.cps.variable.Variable;
import com.google.common.base.Preconditions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.ConcurrentHashMap;
/**
......@@ -42,6 +44,8 @@ public class LinearEquationSystem extends System {
private ConcurrentHashMap<Mapping, Equation> equations;
// private ScriptEngine scriptEngine;
private static final Logger LOGGER = LoggerFactory.getLogger(LinearEquationSystem.class.getSimpleName());
/**
* Constructor issuing a super call and initialising the map of equations.
*
......@@ -76,6 +80,9 @@ public class LinearEquationSystem extends System {
@Override
public synchronized void clockTicked(long tick) {
super.clockTicked(tick);
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Clock tick at {}...", tick); //$NON-NLS-1$
}
for (Equation equation : equations.values()) {
equation.evaluate();
......@@ -92,7 +99,10 @@ public class LinearEquationSystem extends System {
super.inputChanged(input);
for (Equation equation : equations.values()) {
if (equation.catersTo((Variable<?>) input.getSource())) {
if (equation.catersTo(input.getSource())) {
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Equation {} triggered by variable {}...", equation.toString(), input.getSource().getName()); //$NON-NLS-1$
}
equation.evaluate();
}
}
......
......@@ -63,7 +63,7 @@ public class PythonExecutor extends Executor {
}
engine.set(variable.getName(), array);
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Parameter {} = {}", variable.getName(), list.toString()); //$NON-NLS-1$
LOGGER.trace("Parameter -> {} = {}", variable.getName(), list.toString()); //$NON-NLS-1$
}
}
} else {
......@@ -71,7 +71,7 @@ public class PythonExecutor extends Executor {
Double numericValue = Double.valueOf(variable.getValue().toString());
engine.set(variable.getName(), new PyFloat(numericValue));
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Parameter {} = {}", variable.getName(), variable.getValue()); //$NON-NLS-1$
LOGGER.trace("Parameter -> {} = {}", variable.getName(), variable.getValue()); //$NON-NLS-1$
}
}
}
......@@ -82,7 +82,7 @@ public class PythonExecutor extends Executor {
engine.exec(script);
elapsed = System.currentTimeMillis() - elapsed;
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Eval => {} | took {} ms!", script, elapsed); //$NON-NLS-1$
LOGGER.trace("Eval took {} ms | {}", elapsed, script); //$NON-NLS-1$
}
return true;
}
......@@ -97,13 +97,13 @@ public class PythonExecutor extends Executor {
PyTuple tuple = (PyTuple) engine.get(tupleMatcher.group(1));
result = tuple.__getattr__(tupleMatcher.group(2));
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Result {} = {}.{} = {}", variable.getName(), tupleMatcher.group(1), tupleMatcher.group(2), result); //$NON-NLS-1$
LOGGER.trace("Result <- {} = {}.{} = {}", variable.getName(), tupleMatcher.group(1), tupleMatcher.group(2), result); //$NON-NLS-1$
}
}
} else {
result = engine.get(variable.getName());
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Result {} = {}", variable.getName(), result); //$NON-NLS-1$
LOGGER.trace("Result <- {} = {}", variable.getName(), result); //$NON-NLS-1$
}
}
......
......@@ -293,7 +293,7 @@ public class SqlExecutor extends Executor {
public void set(Variable<?> variable) {
parameters.put(variable.getName(), variable.getValue());
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Parameter {} = {}", variable.getName(), variable.getValue()); //$NON-NLS-1$
LOGGER.trace("Parameter -> {} = {}", variable.getName(), variable.getValue()); //$NON-NLS-1$
}
}
......@@ -302,6 +302,7 @@ public class SqlExecutor extends Executor {
/** {@inheritDoc} */
@Override
public boolean eval(String script) {
long elapsed = System.currentTimeMillis();
Connection connection = this.getConnectionFromPool();
List<String> variables = new ArrayList<String>();
String queryString = this.interpolate(script, variables, false);
......@@ -318,6 +319,11 @@ public class SqlExecutor extends Executor {
columnNames = this.getColumnNames(rows);
columnTypes = this.getColumnTypes(rows);
columnValues = this.convertResults(rows);
elapsed = System.currentTimeMillis() - elapsed;
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Eval took {} ms | {}", elapsed, script); //$NON-NLS-1$
}
} catch (SQLException e) {
LOGGER.error("Failed to execute query!", e); //$NON-NLS-1$
success = false;
......@@ -366,10 +372,13 @@ public class SqlExecutor extends Executor {
if (variable instanceof VectorVariable) {
VectorVariable<?> vector = (VectorVariable<?>) variable;
// Suspend notification of input change listeners while populating vector
variable.suspendListenerNotification(true);
for (Object[] values : columnValues) {
Object value = values[index];
vector.add(value);
}
variable.suspendListenerNotification(false);
vector.notifyInputChangeListeners();
} else {
LOGGER.warn("Query returned multiple rows but specified variable {} is scalar!", variable.getName()); //$NON-NLS-1$
......@@ -380,6 +389,9 @@ public class SqlExecutor extends Executor {
variable.setValueFromObject(values[index]);
}
}
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Result <- {} = {}", variable.getName(), variable.getValue()); //$NON-NLS-1$
}
return variable;
}
......
......@@ -20,7 +20,6 @@
*/
package lu.list.itis.dkd.tui.cps.variable;
import lu.list.itis.dkd.tui.cps.InputEvent;
import lu.list.itis.dkd.tui.cps.utility.Externalization;
import org.slf4j.Logger;
......@@ -35,8 +34,6 @@ import java.util.Vector;
*/
public class BooleanVariable extends Variable<Boolean> {
protected boolean value;
/**
* @param name
* @param value
......@@ -49,19 +46,6 @@ public class BooleanVariable extends Variable<Boolean> {
this.value = value;
}
/** {@inheritDoc} */
@Override
public Boolean getValue() {
return value;
}
/** {@inheritDoc} */
@Override
public void setValue(Boolean newValue) {
this.value = newValue;
this.notifyInputChangeListeners(new InputEvent(this));
}
/** {@inheritDoc} */
@Override
public void setValueFromObject(Object object) {
......
......@@ -22,7 +22,6 @@ package lu.list.itis.dkd.tui.cps.variable;
import lu.list.itis.dkd.dbc.annotation.NonNullByDefault;
import lu.list.itis.dkd.dbc.annotation.Nullable;
import lu.list.itis.dkd.tui.cps.InputEvent;
import lu.list.itis.dkd.tui.cps.utility.Externalization;
import org.slf4j.Logger;
......@@ -41,7 +40,6 @@ import java.util.Vector;
*/
@NonNullByDefault
public class NumericalVariable extends Variable<Double> {
protected double value;
protected double minValue;
protected double maxValue;
protected double scale;
......@@ -151,13 +149,11 @@ public class NumericalVariable extends Variable<Double> {
// Double newValue;
// newValue = (Double) this.valueFromString(value.toString());
if (newValue < this.minValue)
this.value = this.minValue;
newValue = this.minValue;
else if (newValue > this.maxValue)
this.value = this.maxValue;
else
this.value = newValue;
newValue = this.maxValue;
this.notifyInputChangeListeners(new InputEvent(this));
super.setValue(newValue);
}
/** {@inheritDoc} */
......
......@@ -14,7 +14,6 @@
package lu.list.itis.dkd.tui.cps.variable;
import lu.list.itis.dkd.dbc.annotation.Nullable;
import lu.list.itis.dkd.tui.cps.InputEvent;
import lu.list.itis.dkd.tui.cps.utility.Externalization;
import lu.list.itis.dkd.tui.utility.Point;
......@@ -32,8 +31,6 @@ import java.util.regex.Pattern;
*/
public class SpatialVariable extends Variable<Point> {
private Point point;
private static final Logger LOGGER = LoggerFactory.getLogger(SpatialVariable.class.getSimpleName());
private static final Pattern SPATIAL_STRING_PATTERN = Pattern.compile("([0-9]+\\.?[0-9]*)\\s*,\\s*([0-9]+\\.?[0-9]*)(\\s*,\\s*([0-9]+\\.?[0-9]*))?", Pattern.CASE_INSENSITIVE); //$NON-NLS-1$
......@@ -45,7 +42,7 @@ public class SpatialVariable extends Variable<Point> {
*/
public SpatialVariable(String name, String unit, Point value) {
super(Externalization.SPATIAL_TYPE, name, unit);
this.point = value;
this.value = value;
}
/**
......@@ -56,7 +53,7 @@ public class SpatialVariable extends Variable<Point> {
*/
@Override
public int hashCode() {
return this.point.hashCode();
return this.value.hashCode();
}
/**
......@@ -75,25 +72,13 @@ public class SpatialVariable extends Variable<Point> {
if (object instanceof SpatialVariable) {
SpatialVariable variable = (SpatialVariable) object;
if (name.equals(variable.getName()) && unit.equals(variable.getUnit()) && variable.getValue().equals(point)) {
if (name.equals(variable.getName()) && unit.equals(variable.getUnit()) && variable.getValue().equals(value)) {
return true;
}
}
return false;
}
/** {@inheritDoc} */
@Override
public Point getValue() {
return this.point;
}
/** {@inheritDoc} */
@Override
public void setValue(Point value) {
this.point = value;
this.notifyInputChangeListeners(new InputEvent(this));
}
/** {@inheritDoc} */
@Override
......@@ -104,7 +89,7 @@ public class SpatialVariable extends Variable<Point> {
/** {@inheritDoc} */
@Override
public Variable<Point> clone() {
SpatialVariable variable = new SpatialVariable(name, unit, point);
SpatialVariable variable = new SpatialVariable(name, unit, value);
variable.listeners = new Vector<>(listeners);
return variable;
}
......
......@@ -22,7 +22,6 @@ package lu.list.itis.dkd.tui.cps.variable;
import lu.list.itis.dkd.dbc.annotation.NonNullByDefault;
import lu.list.itis.dkd.dbc.annotation.Nullable;
import lu.list.itis.dkd.tui.cps.InputEvent;
import lu.list.itis.dkd.tui.cps.utility.Externalization;
import org.slf4j.Logger;
......@@ -40,7 +39,6 @@ import java.util.Vector;
*/
@NonNullByDefault
public class TextVariable extends Variable<String> {
protected String value;
private static final Logger logger = LoggerFactory.getLogger(TextVariable.class.getSimpleName());
......@@ -106,12 +104,6 @@ public class TextVariable extends Variable<String> {
return false;
}
/** {@inheritDoc} */
@Override
public void setValue(String newValue) {
this.value = newValue;
this.notifyInputChangeListeners(new InputEvent(this));
}
/** {@inheritDoc} */
@Override
......@@ -119,13 +111,6 @@ public class TextVariable extends Variable<String> {
this.setValue(this.valueFromObject(object));
}
/** {@inheritDoc} */
@Override
public String getValue() {
return this.value;
}
/** {@inheritDoc} */
@Override
public TextVariable clone() {
......
......@@ -25,6 +25,9 @@ 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 org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.HashMap;
import java.util.Vector;
......@@ -49,10 +52,14 @@ public abstract class Variable<V> implements Cloneable {
/** The listeners to notify when the variable changes value. */
protected Vector<InputChangeListener> listeners;
protected boolean listenersConsolidated = false;
protected V value;
protected int suspendNotificationSemaphore = 0;
public static final String NO_UNIT = ""; //$NON-NLS-1$
private static final Logger LOGGER = LoggerFactory.getLogger(Variable.class.getSimpleName());
/**
* Constructor initialising the name and unit fields.
*
......@@ -95,12 +102,19 @@ public abstract class Variable<V> implements Cloneable {
return unit;
}
@SuppressWarnings("unchecked")
public V getContentClass() {
return (V) value.getClass();
}
/**
* Simple getter method for the value held by the {@link Variable} instance.
*
* @return The value held by the {@link Variable} instance.
*/
public abstract V getValue();
public V getValue() {
return value;
}
/**
* Method used to set the value held by the variable.
......@@ -108,7 +122,10 @@ public abstract class Variable<V> implements Cloneable {
* @param value
* The new value the variable should have.
*/
public abstract void setValue(V value);
public void setValue(V newValue) {
this.value = newValue;
this.notifyInputChangeListeners(new InputEvent(this));
}
/**
* Method used to set the value held by the variable from an object.
......@@ -183,16 +200,24 @@ public abstract class Variable<V> implements Cloneable {
}
/**
* Sets the consolidated flag for InputChangeListeners. When consolidated, InputChangeListeners
* will not be notified on value changes.
* Sets the suspendNotification flag for InputChangeListeners. When suspend,
* InputChangeListeners will not be notified on value changes.
*
* @param consolidate
* specify <code>true</true> to switch variable in consolidated mode, <code>false</code>
* to enable notification of InputChangeListerners on value change.
* @param suspend
* specify <code>true</true> to suspend listener notification, <code>false</code> to
* enable notification of InputChangeListerners on value change.
* @see #consolidateListeners
*/
public void setConsolidated(boolean consolidate) {
listenersConsolidated = consolidate;
public synchronized void suspendListenerNotification(boolean suspend) {
if (suspend) {
suspendNotificationSemaphore++;
if (LOGGER.isTraceEnabled())
LOGGER.trace("Suspend Notification Semaphore of Variable {} raised to {}!", this.name, suspendNotificationSemaphore); //$NON-NLS-1$
} else if (suspendNotificationSemaphore > 0) {
suspendNotificationSemaphore--;
if (LOGGER.isTraceEnabled())
LOGGER.trace("Suspend Notification Semaphore of Variable {} lowered to {}!", this.name, suspendNotificationSemaphore); //$NON-NLS-1$
}
}
/**
......@@ -220,8 +245,13 @@ public abstract class Variable<V> implements Cloneable {
* specifies the event to be passed to each listeners inputChanged method.
*/
protected void notifyInputChangeListeners(InputEvent event) {
if (listenersConsolidated)
if (suspendNotificationSemaphore > 0) {
// if (LOGGER.isTraceEnabled())
// LOGGER.trace("Notification suspend for Variable {}! Semaphore was {}!", this.name,
// suspendNotificationSemaphore); //$NON-NLS-1$
return;
}
for (InputChangeListener listener : listeners) {
listener.inputChanged(event);
}
......
......@@ -30,24 +30,22 @@ import java.util.Vector;
*/
public class VectorVariable<B> extends Variable<List<B>> implements Collection<B> {
private List<B> values;
public VectorVariable(String name, String unit) {
super(Externalization.VECTOR_TYPE, name, unit);
values = new ArrayList<B>();
value = new ArrayList<B>();
}
/** {@inheritDoc} */
@Override
public List<B> getValue() {
return values;
return value;
}
/** {@inheritDoc} */
@Override
public void setValue(List<B> values) {
this.values.clear();
this.values.addAll(values);
this.value.clear();
this.value.addAll(values);
this.notifyInputChangeListeners(new InputEvent(this));
}
......@@ -56,87 +54,93 @@ public class VectorVariable<B> extends Variable<List<B>> implements Collection<B
public Variable<List<B>> clone() {
VectorVariable<B> variable = new VectorVariable<>(name, unit);
variable.listeners = new Vector<>(listeners);
variable.values = new ArrayList<B>(values);
variable.value = new ArrayList<B>(value);
return variable;
}
/** {@inheritDoc} */
@Override
public int size() {
return values.size();
return value.size();
}
/** {@inheritDoc} */
@Override
public boolean isEmpty() {
return values.isEmpty();
return value.isEmpty();
}
/** {@inheritDoc} */
@Override
public boolean contains(Object o) {
return values.contains(o);
return value.contains(o);
}
/** {@inheritDoc} */
@Override
public Iterator<B> iterator() {
return values.iterator();
return value.iterator();
}
/** {@inheritDoc} */
@Override
public Object[] toArray() {
return values.toArray();
return value.toArray();
}
/** {@inheritDoc} */
@Override
public <T> T[] toArray(T[] a) {
return values.toArray(a);
return value.toArray(a);
}
/** {@inheritDoc} */
@SuppressWarnings("unchecked")
@Override
public boolean add(Object e) {
return values.add((B) e);
boolean hasChanged = value.add((B) e);
if (hasChanged)
this.notifyInputChangeListeners();
return hasChanged;
}
/** {@inheritDoc} */
@Override
public boolean remove(Object o) {
return values.remove(o);
boolean hasChanged = value.remove(o);
if (hasChanged)
this.notifyInputChangeListeners();
return hasChanged;
}
/** {@inheritDoc} */
@Override
public boolean containsAll(Collection<?> c) {
return values.containsAll(c);
return value.containsAll(c);
}
/** {@inheritDoc} */
@Override
public boolean addAll(Collection<? extends B> c) {
return values.addAll(c);
return value.addAll(c);
}
/** {@inheritDoc} */
@Override
public boolean removeAll(Collection<?> c) {
return values.removeAll(c);
return value.removeAll(c);
}
/** {@inheritDoc} */
@Override
public boolean retainAll(Collection<?> c) {
return values.retainAll(c);
return value.retainAll(c);
}
/** {@inheritDoc} */
@Override
public void clear() {
values.clear();
value.clear();
}
/** {@inheritDoc} */
......
......@@ -49,11 +49,14 @@ public abstract class BaseConditionalCoronaBuilder<B extends BaseConditionalCoro
/** All variables that will be needed to evaluate the trigger condition. */
public LinkedHashSet<Variable<?>> variables = new LinkedHashSet<>();
/** Variable used to easily gather the output from the trigger equation. */
public BooleanVariable tri