-package org.simantics.db.layer0.variable;\r
-\r
-import org.simantics.databoard.binding.Binding;\r
-import org.simantics.databoard.binding.error.BindingException;\r
-import org.simantics.databoard.binding.mutable.Variant;\r
-import org.simantics.databoard.util.ObjectUtils;\r
-import org.simantics.db.ReadGraph;\r
-import org.simantics.db.common.request.ParametrizedPrimitiveRead;\r
-import org.simantics.db.common.utils.Logger;\r
-import org.simantics.db.exception.DatabaseException;\r
-import org.simantics.db.procedure.Listener;\r
-import org.simantics.simulator.variable.exceptions.NodeIsNotValidAnymoreException;\r
-import org.simantics.simulator.variable.exceptions.NodeManagerException;\r
-import org.simantics.utils.datastructures.Pair;\r
-\r
-@SuppressWarnings("rawtypes")\r
-class NodeValueRequest extends ParametrizedPrimitiveRead<Pair<VariableNode,Binding>, Variant> implements VariableNodeReadRunnable {\r
-\r
- private Listener<Variant> listener = null;\r
- private Variant value = Variables.PENDING_NODE_VALUE;\r
- private boolean wasRun = false;\r
-\r
- static class Probe implements Runnable {\r
-\r
- private Pair<VariableNode,Binding> parameter;\r
- public Variant result;\r
- \r
- public Probe(Pair<VariableNode,Binding> parameter) {\r
- this.parameter = parameter;\r
- }\r
- \r
- @SuppressWarnings("unchecked")\r
- @Override\r
- public void run() {\r
- try {\r
- result = NodeValueRequest.get(parameter);\r
- parameter.first.support.valueCache.put(parameter.first.node, result, 1000000000L);\r
- } catch (NodeManagerException e) {\r
- e.printStackTrace();\r
- } catch (BindingException e) {\r
- e.printStackTrace();\r
- }\r
- }\r
- \r
- }\r
- \r
- public NodeValueRequest(VariableNode node) {\r
- super(Pair.<VariableNode, Binding>make(node, null));\r
- }\r
-\r
- public NodeValueRequest(VariableNode node, Binding binding) {\r
- super(Pair.<VariableNode, Binding>make(node, binding));\r
- }\r
-\r
- @SuppressWarnings("unchecked")\r
- @Override\r
- public void register(ReadGraph graph, final Listener<Variant> procedure) {\r
- \r
- VariableNode node = parameter.first;\r
-\r
- if(procedure.isDisposed()) {\r
- \r
- // We are not listening\r
- Variant result = (Variant)node.support.valueCache.get(node.node);\r
-\r
- if(result != null) {\r
- // Return cached value immediately\r
- procedure.execute(result);\r
- } else {\r
-\r
-// \r
-// listener = procedure;\r
-// \r
-// if(graph.getSynchronous()) {\r
-// try {\r
-// parameter.support.manager.getRealm().syncExec(this);\r
-// } catch (InterruptedException e) {\r
-// if (!wasRun) procedure.exception(e);\r
-// } catch (Throwable e) {\r
-// if (!wasRun) procedure.exception(e);\r
-// }\r
-// } else {\r
-// parameter.support.manager.getRealm().asyncExec(this);\r
-// \r
-// if(value == Variables.PENDING_NODE_VALUE) {\r
-// procedure.execute(Variables.PENDING_NODE_VALUE);\r
-// }\r
-// }\r
-// return;\r
- \r
- NodeValueRequest.Probe probe = new Probe(parameter);\r
- node.support.manager.getRealm().asyncExec(probe);\r
- if(probe.result != null) {\r
- procedure.execute(probe.result);\r
- } else {\r
- procedure.execute(Variables.PENDING_NODE_VALUE);\r
- }\r
-\r
- }\r
-\r
- return; \r
- }\r
- \r
- // We need to listen\r
- listener = procedure;\r
- // Register listening\r
- node.support.manager.addNodeListener(node.node, this);\r
- synchronized(this) {\r
- if(wasRun) {\r
- procedure.execute(value);\r
- } else {\r
- Variant result = (Variant)node.support.valueCache.get(node.node);\r
- if(result != null) {\r
- procedure.execute(result);\r
- } else {\r
- procedure.execute(Variables.PENDING_NODE_VALUE);\r
- }\r
- }\r
- }\r
- \r
-// if(listener != null) {\r
-// throw new UnsupportedOperationException();\r
-// }\r
-// listener = procedure;\r
-// if(graph.getSynchronous()) {\r
-// try {\r
-// parameter.support.manager.getRealm().syncExec(new VariableNodeReadRunnable() {\r
-// @Override\r
-// public void run() {\r
-// parameter.support.manager.addNodeListener(parameter.node, NodeValueRequest.this);\r
-// }\r
-// @Override\r
-// public String toString() {\r
-// return "NodeValueRequest.register.sync.addNodeListener @ " + System.identityHashCode(NodeValueRequest.this);\r
-// }\r
-// });\r
-// \r
-// if (!wasRun) procedure.exception(new InternalException("No invocation of listener from node manager " + parameter.support.manager.getClass().getName()));\r
-// } catch (InterruptedException e) {\r
-// if (!wasRun) procedure.exception(e);\r
-// } catch (Throwable e) {\r
-// if (!wasRun) procedure.exception(e);\r
-// }\r
-// } else {\r
-// parameter.support.manager.addNodeListener(parameter.node, this);\r
-// if(value == Variables.PENDING_NODE_VALUE) procedure.execute(Variables.PENDING_NODE_VALUE);\r
-// }\r
- \r
- }\r
- \r
- static class NodeListener implements VariableNodeReadRunnable {\r
- \r
- private VariableNode node;\r
- private NodeValueRequest request;\r
- \r
- public NodeListener(VariableNode node, NodeValueRequest request) {\r
- this.node = node;\r
- this.request = request;\r
- }\r
-\r
- @SuppressWarnings("unchecked")\r
- @Override\r
- public void run() {\r
- node.support.manager.addNodeListener(node.node, request);\r
- }\r
- \r
- }\r
-\r
-\r
- @SuppressWarnings("unchecked")\r
- @Override\r
- public void unregistered() {\r
- VariableNode node = parameter.first;\r
- node.support.manager.removeNodeListener(node.node, this);\r
- node.support.valueCache.removeListening(node.node);\r
- listener = null;\r
- }\r
- \r
- @SuppressWarnings("unchecked")\r
- public static Variant get(Pair<VariableNode,Binding> parameter) throws NodeManagerException, BindingException {\r
-\r
- VariableNode node = parameter.first;\r
- Binding binding = parameter.second;\r
- \r
- if (binding != null) {\r
- Object raw = node.support.manager.getValue(node.node, binding);\r
- if(raw == null) return null;\r
- else return new Variant(binding, raw);\r
- } else {\r
- return node.support.manager.getValue(node.node);\r
- }\r
- \r
- }\r
- \r
- @SuppressWarnings("unchecked")\r
- @Override\r
- public synchronized void run() {\r
- \r
- VariableNode node = parameter.first;\r
- \r
- try {\r
- Variant newValue = get(parameter);\r
- if (wasRun && ObjectUtils.objectEquals(value, newValue)) {\r
- //System.out.println("CACHE VALUE MATCH (" + newValue + ") for " + node.node);\r
- return;\r
- }\r
- value = newValue;\r
- node.support.valueCache.put(node.node, value);\r
- } catch (Throwable e) {\r
- // Must catch everything to prevent DB client from getting stuck.\r
- if(!(e instanceof NodeIsNotValidAnymoreException))\r
- Logger.defaultLogError(e);\r
- // Invoke the exception method of the listener\r
- Listener<Variant> listener = this.listener;\r
- if (listener != null) listener.exception(new DatabaseException("External data access error", e));\r
- wasRun = true;\r
- return;\r
- }\r
- // Must always invoke an existing listener, regardless of earlier errors.\r
- Listener<Variant> listener = this.listener;\r
- if (listener != null) {\r
- //System.out.println("LISTENER " + listener + " invoked with value " + value);\r
- listener.execute(value);\r
- }\r
- wasRun = true;\r
- }\r
-\r
- @Override\r
- public String toString() {\r
- return "NodeValueRequest.run " + parameter.first.node + " " + parameter.first.support.manager + " " + System.identityHashCode(this);\r
- }\r
-\r
+package org.simantics.db.layer0.variable;
+
+import org.simantics.databoard.binding.Binding;
+import org.simantics.databoard.binding.error.BindingException;
+import org.simantics.databoard.binding.mutable.Variant;
+import org.simantics.databoard.util.ObjectUtils;
+import org.simantics.db.ReadGraph;
+import org.simantics.db.common.request.ParametrizedPrimitiveRead;
+import org.simantics.db.common.utils.Logger;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.procedure.Listener;
+import org.simantics.simulator.variable.exceptions.NodeIsNotValidAnymoreException;
+import org.simantics.simulator.variable.exceptions.NodeManagerException;
+import org.simantics.utils.datastructures.Pair;
+
+@SuppressWarnings("rawtypes")
+class NodeValueRequest extends ParametrizedPrimitiveRead<Pair<VariableNode,Binding>, Variant> implements VariableNodeReadRunnable {
+
+ private Listener<Variant> listener = null;
+ private Variant value = Variables.PENDING_NODE_VALUE;
+ private boolean wasRun = false;
+
+ static class Probe implements Runnable {
+
+ private Pair<VariableNode,Binding> parameter;
+ public Variant result;
+
+ public Probe(Pair<VariableNode,Binding> parameter) {
+ this.parameter = parameter;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public void run() {
+ try {
+ result = NodeValueRequest.get(parameter);
+ parameter.first.support.valueCache.put(parameter.first.node, result, 1000000000L);
+ } catch (NodeManagerException e) {
+ e.printStackTrace();
+ } catch (BindingException e) {
+ e.printStackTrace();
+ }
+ }
+
+ }
+
+ public NodeValueRequest(VariableNode node) {
+ super(Pair.<VariableNode, Binding>make(node, null));
+ }
+
+ public NodeValueRequest(VariableNode node, Binding binding) {
+ super(Pair.<VariableNode, Binding>make(node, binding));
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public void register(ReadGraph graph, final Listener<Variant> procedure) {
+
+ VariableNode node = parameter.first;
+
+ if(procedure.isDisposed()) {
+
+ // We are not listening
+ Variant result = (Variant)node.support.valueCache.get(node.node);
+
+ if(result != null) {
+ // Return cached value immediately
+ procedure.execute(result);
+ } else {
+
+//
+// listener = procedure;
+//
+// if(graph.getSynchronous()) {
+// try {
+// parameter.support.manager.getRealm().syncExec(this);
+// } catch (InterruptedException e) {
+// if (!wasRun) procedure.exception(e);
+// } catch (Throwable e) {
+// if (!wasRun) procedure.exception(e);
+// }
+// } else {
+// parameter.support.manager.getRealm().asyncExec(this);
+//
+// if(value == Variables.PENDING_NODE_VALUE) {
+// procedure.execute(Variables.PENDING_NODE_VALUE);
+// }
+// }
+// return;
+
+ NodeValueRequest.Probe probe = new Probe(parameter);
+ node.support.manager.getRealm().asyncExec(probe);
+ if(probe.result != null) {
+ procedure.execute(probe.result);
+ } else {
+ procedure.execute(Variables.PENDING_NODE_VALUE);
+ }
+
+ }
+
+ return;
+ }
+
+ // We need to listen
+ listener = procedure;
+ // Register listening
+ node.support.manager.addNodeListener(node.node, this);
+ synchronized(this) {
+ if(wasRun) {
+ procedure.execute(value);
+ } else {
+ Variant result = (Variant)node.support.valueCache.get(node.node);
+ if(result != null) {
+ procedure.execute(result);
+ } else {
+ procedure.execute(Variables.PENDING_NODE_VALUE);
+ }
+ }
+ }
+
+// if(listener != null) {
+// throw new UnsupportedOperationException();
+// }
+// listener = procedure;
+// if(graph.getSynchronous()) {
+// try {
+// parameter.support.manager.getRealm().syncExec(new VariableNodeReadRunnable() {
+// @Override
+// public void run() {
+// parameter.support.manager.addNodeListener(parameter.node, NodeValueRequest.this);
+// }
+// @Override
+// public String toString() {
+// return "NodeValueRequest.register.sync.addNodeListener @ " + System.identityHashCode(NodeValueRequest.this);
+// }
+// });
+//
+// if (!wasRun) procedure.exception(new InternalException("No invocation of listener from node manager " + parameter.support.manager.getClass().getName()));
+// } catch (InterruptedException e) {
+// if (!wasRun) procedure.exception(e);
+// } catch (Throwable e) {
+// if (!wasRun) procedure.exception(e);
+// }
+// } else {
+// parameter.support.manager.addNodeListener(parameter.node, this);
+// if(value == Variables.PENDING_NODE_VALUE) procedure.execute(Variables.PENDING_NODE_VALUE);
+// }
+
+ }
+
+ static class NodeListener implements VariableNodeReadRunnable {
+
+ private VariableNode node;
+ private NodeValueRequest request;
+
+ public NodeListener(VariableNode node, NodeValueRequest request) {
+ this.node = node;
+ this.request = request;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public void run() {
+ node.support.manager.addNodeListener(node.node, request);
+ }
+
+ }
+
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public void unregistered() {
+ VariableNode node = parameter.first;
+ node.support.manager.removeNodeListener(node.node, this);
+ node.support.valueCache.removeListening(node.node);
+ listener = null;
+ }
+
+ @SuppressWarnings("unchecked")
+ public static Variant get(Pair<VariableNode,Binding> parameter) throws NodeManagerException, BindingException {
+
+ VariableNode node = parameter.first;
+ Binding binding = parameter.second;
+
+ if (binding != null) {
+ Object raw = node.support.manager.getValue(node.node, binding);
+ if(raw == null) return null;
+ else return new Variant(binding, raw);
+ } else {
+ return node.support.manager.getValue(node.node);
+ }
+
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public synchronized void run() {
+
+ VariableNode node = parameter.first;
+
+ try {
+ Variant newValue = get(parameter);
+ if (wasRun && ObjectUtils.objectEquals(value, newValue)) {
+ //System.out.println("CACHE VALUE MATCH (" + newValue + ") for " + node.node);
+ return;
+ }
+ value = newValue;
+ node.support.valueCache.put(node.node, value);
+ } catch (Throwable e) {
+ // Must catch everything to prevent DB client from getting stuck.
+ if(!(e instanceof NodeIsNotValidAnymoreException))
+ Logger.defaultLogError(e);
+ // Invoke the exception method of the listener
+ Listener<Variant> listener = this.listener;
+ if (listener != null) listener.exception(new DatabaseException("External data access error", e));
+ wasRun = true;
+ return;
+ }
+ // Must always invoke an existing listener, regardless of earlier errors.
+ Listener<Variant> listener = this.listener;
+ if (listener != null) {
+ //System.out.println("LISTENER " + listener + " invoked with value " + value);
+ listener.execute(value);
+ }
+ wasRun = true;
+ }
+
+ @Override
+ public String toString() {
+ return "NodeValueRequest.run " + parameter.first.node + " " + parameter.first.support.manager + " " + System.identityHashCode(this);
+ }
+
}
\ No newline at end of file