Fixed multiple issues causing dangling references to discarded queries
[simantics/platform.git] / bundles / org.simantics.document.server / src / org / simantics / document / server / request / NodesRequest.java
index 99526368e8cc3e21e1b92451f4dd915db45d40ba..133264e29b09321e399831600106ce0227ba0a04 100644 (file)
@@ -2,11 +2,12 @@ package org.simantics.document.server.request;
 
 import java.util.Collection;
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.Set;
 
 import org.simantics.db.AsyncReadGraph;
 import org.simantics.db.ReadGraph;
-import org.simantics.db.common.request.AsyncReadRequest;
+import org.simantics.db.common.request.UnaryAsyncRead;
 import org.simantics.db.exception.DatabaseException;
 import org.simantics.db.layer0.request.VariableChildren;
 import org.simantics.db.layer0.request.VariableRead;
@@ -16,52 +17,57 @@ import org.simantics.structural.stubs.StructuralResource2;
 import org.simantics.utils.threads.logger.ITask;
 import org.simantics.utils.threads.logger.ThreadLogger;
 
-import gnu.trove.set.hash.THashSet;
-
 public class NodesRequest extends VariableRead<Set<Variable>> {
 
     public NodesRequest(Variable var) {
         super(var);
     }
 
-    @Override
-    public Set<Variable> perform(ReadGraph graph) throws DatabaseException {
+    static class CollectNodesRequest2 extends UnaryAsyncRead<Collection<Variable>, Set<Variable>> {
 
-        ITask task = DocumentRequest.PROFILE ? ThreadLogger.task(this) : null;
+        public CollectNodesRequest2(Collection<Variable> nodes) {
+            super(nodes);
+        }
 
-        StructuralResource2.getInstance(graph);
-        if(variable == null)
-            return Collections.emptySet();
+        @Override
+        public void perform(AsyncReadGraph graph, AsyncProcedure<Set<Variable>> procedure) {
+            HashSet<Variable> rs = new HashSet<Variable>(); // result
 
-        Set<Variable> nodes = new THashSet<Variable>();
+            for(Variable node : parameter) {
+                graph.asyncRequest(new NodesRequest2(node), new AsyncProcedure<Set<Variable>> () {
 
-        Collection<Variable> children = graph.syncRequest(new VariableChildren(variable));
+                    @Override
+                    public void execute(AsyncReadGraph graph, Set<Variable> result) {
+                        synchronized(rs) {
+                            rs.addAll(result);
+                        }
+                    }
 
-        graph.syncRequest(new AsyncReadRequest() {
+                    @Override
+                    public void exception(AsyncReadGraph graph, Throwable throwable) {
+                    }
 
-            @Override
-            public void run(AsyncReadGraph graph) throws DatabaseException {
+                });
 
-                for(Variable child : children) {
-                    graph.asyncRequest(new NodesRequest2(child), new AsyncProcedure<Set<Variable>>() {
+            }
+            procedure.execute(graph, rs);
 
-                        @Override
-                        public void execute(AsyncReadGraph graph, Set<Variable> result) {
-                            synchronized(nodes) {
-                                nodes.addAll(result);
-                            }
-                        }
+        }
 
-                        @Override
-                        public void exception(AsyncReadGraph graph, Throwable throwable) {
-                        }
-                        
-                    });
-                }
+    }
 
-            }
+    @Override
+    public Set<Variable> perform(ReadGraph graph) throws DatabaseException {
+
+        ITask task = DocumentRequest.PROFILE ? ThreadLogger.task(this) : null;
+
+        StructuralResource2.getInstance(graph);
+        if(variable == null)
+            return Collections.emptySet();
+
+        Collection<Variable> children = graph.syncRequest(new VariableChildren(variable));
 
-        });
+        Set<Variable> nodes = graph.syncRequest(new CollectNodesRequest2(children));
 
         if(DocumentRequest.PROFILE) task.finish();