]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/variable/NodeStructureRequest.java
Add isDisposed checking to avoid unexpected NPE
[simantics/platform.git] / bundles / org.simantics.db.layer0 / src / org / simantics / db / layer0 / variable / NodeStructureRequest.java
index a87a2042a9452cbe8e187b352f47da116b8f9d8c..5d21ca56bdf5ab3a0d0ba9aa7cd7a11542379920 100644 (file)
-package org.simantics.db.layer0.variable;\r
-\r
-import java.util.Collections;\r
-import java.util.List;\r
-import java.util.Map;\r
-\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.layer0.variable.Variables.NodeStructure;\r
-import org.simantics.db.procedure.Listener;\r
-import org.simantics.simulator.variable.exceptions.NodeManagerException;\r
-\r
-import gnu.trove.map.hash.THashMap;\r
-\r
-@SuppressWarnings("rawtypes")\r
-class NodeStructureRequest extends ParametrizedPrimitiveRead<VariableNode, NodeStructure> implements VariableNodeReadRunnable {\r
-\r
-       private Listener<NodeStructure> listener = null;\r
-       private NodeStructure value = Variables.PENDING_NODE_STRUCTURE;\r
-       private boolean wasRun = false;\r
-\r
-       static class Probe implements Runnable {\r
-\r
-               private VariableNode node;\r
-               public NodeStructure result;\r
-\r
-               public Probe(VariableNode node) {\r
-                       this.node = node;\r
-               }\r
-\r
-               @SuppressWarnings("unchecked")\r
-               @Override\r
-               public void run() {\r
-                       try {\r
-                               result = NodeStructureRequest.get(node);\r
-                               node.support.structureCache.put(node.node, result, 1000000000L);\r
-                       } catch (NodeManagerException e) {\r
-                               e.printStackTrace();\r
-                       }\r
-               }\r
-\r
-       }\r
-\r
-       public NodeStructureRequest(VariableNode node) {\r
-               super(node);\r
-       }\r
-\r
-       @SuppressWarnings("unchecked")\r
-       @Override\r
-       public void register(ReadGraph graph, final Listener<NodeStructure> procedure) {\r
-\r
-               if(procedure.isDisposed()) {\r
-\r
-                       // We are not listening\r
-                       NodeStructure result = (NodeStructure)parameter.support.structureCache.get(parameter.node);\r
-\r
-                       if(result != null) {\r
-                               // Return cached value immediately\r
-                               procedure.execute(result);\r
-                       } else {\r
-                               NodeStructureRequest.Probe probe = new Probe(parameter);\r
-                               parameter.support.manager.getRealm().asyncExec(probe);\r
-                               if(probe.result != null) {\r
-                                       procedure.execute(probe.result);\r
-                               } else {\r
-                                       procedure.execute(Variables.PENDING_NODE_STRUCTURE);\r
-                               }\r
-                       }\r
-\r
-                       return;\r
-\r
-               }\r
-\r
-               // We need to listen\r
-               listener = procedure;\r
-               // Register listening\r
-               parameter.support.manager.addNodeListener(parameter.node, this);\r
-               synchronized(this) {\r
-                       if(wasRun) {\r
-                               procedure.execute(value);\r
-                       } else {\r
-                               NodeStructure result = (NodeStructure)parameter.support.structureCache.get(parameter.node);\r
-                               if(result != null) {\r
-                                       procedure.execute(result);\r
-                               } else {\r
-                                       procedure.execute(Variables.PENDING_NODE_STRUCTURE);\r
-                               }\r
-                       }\r
-               }\r
-\r
-       }\r
-\r
-       static class NodeListener implements VariableNodeReadRunnable {\r
-\r
-               private VariableNode node;\r
-               private NodeStructureRequest request;\r
-\r
-               public NodeListener(VariableNode node, NodeStructureRequest 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
-       @SuppressWarnings("unchecked")\r
-       @Override\r
-       public void unregistered() {\r
-               parameter.support.manager.removeNodeListener(parameter.node, this);\r
-               parameter.support.structureCache.removeListening(parameter.node);\r
-               listener = null;\r
-       }\r
-\r
-       @SuppressWarnings("unchecked")\r
-       public static NodeStructure get(VariableNode parameter) throws NodeManagerException {\r
-               List<?> children = parameter.support.manager.getChildren(parameter.node);\r
-               List<?> properties = parameter.support.manager.getProperties(parameter.node);\r
-               Map<String, Object> childMap = Collections.emptyMap();\r
-               Map<String, Object> propertyMap = childMap;\r
-               if(!children.isEmpty()) {\r
-                       childMap = new THashMap<>(children.size());\r
-                       for(Object o : children) {\r
-                               String name = parameter.support.manager.getName(o);\r
-                               childMap.put(name, o);\r
-                       }\r
-               }\r
-               if(!properties.isEmpty()) {\r
-                       propertyMap = new THashMap<>(properties.size());\r
-                       for(Object o : properties) {\r
-                               String name = parameter.support.manager.getName(o);\r
-                               propertyMap.put(name, o);\r
-                       }\r
-               }\r
-               return new NodeStructure(childMap, propertyMap);\r
-       }\r
-\r
-       @SuppressWarnings("unchecked")\r
-       @Override\r
-       public synchronized void run() {\r
-               try {\r
-                       // Cache this value with infinite cache time since we are listening\r
-                       NodeStructure 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
-                       parameter.support.structureCache.put(parameter.node, value);\r
-               } catch (Throwable e) {\r
-                       // Must catch everything to prevent DB client from getting stuck.\r
-                       Logger.defaultLogError(e);\r
-                       // Invoke the exception method of the listener\r
-                       Listener<NodeStructure> listener = this.listener;\r
-                       if (listener != null) listener.exception(new DatabaseException("External data access error", e));\r
-                       wasRun = true;\r
-                       return;\r
-               }\r
-\r
-               // Must always invoke an existing listener, regardless of earlier errors.\r
-               Listener<NodeStructure> listener = this.listener;\r
-               if (listener != null) {\r
-                       listener.execute(value);\r
-               }\r
-               wasRun = true;\r
-       }\r
-\r
-       @Override\r
-       public String toString() {\r
-               return "NodeStructureRequest.run @ " + System.identityHashCode(this);\r
-       }\r
-\r
+package org.simantics.db.layer0.variable;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+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.layer0.variable.Variables.NodeStructure;
+import org.simantics.db.procedure.Listener;
+import org.simantics.simulator.variable.exceptions.NodeManagerException;
+
+import gnu.trove.map.hash.THashMap;
+
+@SuppressWarnings("rawtypes")
+class NodeStructureRequest extends ParametrizedPrimitiveRead<VariableNode, NodeStructure> implements VariableNodeReadRunnable {
+
+       private Listener<NodeStructure> listener = null;
+       private NodeStructure value = Variables.PENDING_NODE_STRUCTURE;
+       private boolean wasRun = false;
+
+       static class Probe implements Runnable {
+
+               private VariableNode node;
+               public NodeStructure result;
+
+               public Probe(VariableNode node) {
+                       this.node = node;
+               }
+
+               @SuppressWarnings("unchecked")
+               @Override
+               public void run() {
+                       try {
+                               result = NodeStructureRequest.get(node);
+                               node.support.structureCache.put(node.node, result, 1000000000L);
+                       } catch (NodeManagerException e) {
+                               e.printStackTrace();
+                       }
+               }
+
+       }
+
+       public NodeStructureRequest(VariableNode node) {
+               super(node);
+       }
+
+       @SuppressWarnings("unchecked")
+       @Override
+       public void register(ReadGraph graph, final Listener<NodeStructure> procedure) {
+
+               if(procedure.isDisposed()) {
+
+                       // We are not listening
+                       NodeStructure result = (NodeStructure)parameter.support.structureCache.get(parameter.node);
+
+                       if(result != null) {
+                               // Return cached value immediately
+                               procedure.execute(result);
+                       } else {
+                               NodeStructureRequest.Probe probe = new Probe(parameter);
+                               parameter.support.manager.getRealm().asyncExec(probe);
+                               if(probe.result != null) {
+                                       procedure.execute(probe.result);
+                               } else {
+                                       procedure.execute(Variables.PENDING_NODE_STRUCTURE);
+                               }
+                       }
+
+                       return;
+
+               }
+
+               // We need to listen
+               listener = procedure;
+               // Register listening
+               parameter.support.manager.addNodeListener(parameter.node, this);
+               synchronized(this) {
+                       if(wasRun) {
+                               procedure.execute(value);
+                       } else {
+                               NodeStructure result = (NodeStructure)parameter.support.structureCache.get(parameter.node);
+                               if(result != null) {
+                                       procedure.execute(result);
+                               } else {
+                                       procedure.execute(Variables.PENDING_NODE_STRUCTURE);
+                               }
+                       }
+               }
+
+       }
+
+       static class NodeListener implements VariableNodeReadRunnable {
+
+               private VariableNode node;
+               private NodeStructureRequest request;
+
+               public NodeListener(VariableNode node, NodeStructureRequest 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() {
+               parameter.support.manager.removeNodeListener(parameter.node, this);
+               parameter.support.structureCache.removeListening(parameter.node);
+               listener = null;
+       }
+
+       @SuppressWarnings("unchecked")
+       public static NodeStructure get(VariableNode parameter) throws NodeManagerException {
+               List<?> children = parameter.support.manager.getChildren(parameter.node);
+               List<?> properties = parameter.support.manager.getProperties(parameter.node);
+               Map<String, Object> childMap = Collections.emptyMap();
+               Map<String, Object> propertyMap = childMap;
+               if(!children.isEmpty()) {
+                       childMap = new THashMap<>(children.size());
+                       for(Object o : children) {
+                               String name = parameter.support.manager.getName(o);
+                               childMap.put(name, o);
+                       }
+               }
+               if(!properties.isEmpty()) {
+                       propertyMap = new THashMap<>(properties.size());
+                       for(Object o : properties) {
+                               String name = parameter.support.manager.getName(o);
+                               propertyMap.put(name, o);
+                       }
+               }
+               return new NodeStructure(childMap, propertyMap);
+       }
+
+       @SuppressWarnings("unchecked")
+       @Override
+       public synchronized void run() {
+               try {
+                       // Cache this value with infinite cache time since we are listening
+                       NodeStructure newValue = get(parameter);
+                       if (wasRun && ObjectUtils.objectEquals(value, newValue)) {
+                               //System.out.println("CACHE VALUE MATCH (" + newValue + ") for " + node.node);
+                               return;
+                       }
+                       value = newValue;
+                       parameter.support.structureCache.put(parameter.node, value);
+               } catch (Throwable e) {
+                       // Must catch everything to prevent DB client from getting stuck.
+                       Logger.defaultLogError(e);
+                       // Invoke the exception method of the listener
+                       Listener<NodeStructure> 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<NodeStructure> listener = this.listener;
+               if (listener != null) {
+                       listener.execute(value);
+               }
+               wasRun = true;
+       }
+
+       @Override
+       public String toString() {
+               return "NodeStructureRequest.run @ " + System.identityHashCode(this);
+       }
+
 }
\ No newline at end of file