]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/variable/NodeValueRequest.java
NodeStructureRequest and NodeValueRequest fire ExternalRead twice
[simantics/platform.git] / bundles / org.simantics.db.layer0 / src / org / simantics / db / layer0 / variable / NodeValueRequest.java
index dcc5a6f9c3d862acb67ca45dcee79651b43724aa..b44f16b30eeedc3ca7ee15fd9d023e0505703a9b 100644 (file)
-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.exception.DatabaseException;
+import org.simantics.db.procedure.Listener;
+import org.simantics.simulator.variable.NodeManager;
+import org.simantics.simulator.variable.exceptions.NodeIsNotValidAnymoreException;
+import org.simantics.simulator.variable.exceptions.NodeManagerException;
+import org.simantics.utils.datastructures.Pair;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@SuppressWarnings("rawtypes")
+class NodeValueRequest extends ParametrizedPrimitiveRead<Pair<VariableNode,Binding>, Variant> implements VariableNodeReadRunnable {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(NodeValueRequest.class);
+
+    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) {
+                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 if(NodeManager.PENDING_NODE_VALUE == raw)
+                return NodeManager.PENDING_NODE_VALUE;
+            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.error("Error while computing node value", 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