--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.diagram.adapter;\r
+\r
+import gnu.trove.list.array.TIntArrayList;\r
+import gnu.trove.map.hash.THashMap;\r
+import gnu.trove.procedure.TIntProcedure;\r
+import gnu.trove.set.hash.THashSet;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Set;\r
+import java.util.concurrent.atomic.AtomicInteger;\r
+\r
+import org.simantics.db.AsyncReadGraph;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.common.procedure.adapter.ProcedureAdapter;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.procedure.AsyncMultiProcedure;\r
+import org.simantics.db.procedure.AsyncProcedure;\r
+import org.simantics.diagram.content.ConnectionPartData;\r
+import org.simantics.diagram.content.ConnectionPartRequest;\r
+import org.simantics.diagram.content.DiagramContents;\r
+import org.simantics.diagram.content.EdgeResource;\r
+import org.simantics.diagram.content.RouteGraphConnectionPartData;\r
+import org.simantics.diagram.content.RouteGraphConnectionPartRequest;\r
+import org.simantics.diagram.stubs.DiagramResource;\r
+import org.simantics.diagram.synchronization.ErrorHandler;\r
+import org.simantics.g2d.canvas.ICanvasContext;\r
+\r
+/**\r
+ * @author Tuukka Lehtonen\r
+ */\r
+public class DiagramContentRequest extends BaseRequest<Resource, DiagramContents> {\r
+\r
+ int previousElementCount = 32;\r
+ ErrorHandler errorHandler;\r
+\r
+ public DiagramContentRequest(ICanvasContext canvas, Resource resource, ErrorHandler errorHandler) {\r
+ super(canvas, resource);\r
+ this.errorHandler = errorHandler;\r
+ }\r
+\r
+ @Override\r
+ public DiagramContents perform(ReadGraph g) throws DatabaseException {\r
+\r
+ final DiagramResource DIA = DiagramResource.getInstance(g);\r
+ final DiagramContents result = new DiagramContents();\r
+\r
+ result.elements = new ArrayList<Resource>(previousElementCount);\r
+ result.nodeSet = new THashSet<Resource>();\r
+ result.connectionSet = new THashSet<Resource>();\r
+ result.connectionSegments = new THashSet<EdgeResource>();\r
+ result.branchPoints = new THashSet<Resource>();\r
+ result.routeGraphConnectionSet = new THashSet<Resource>();\r
+ result.routeLinks = new THashSet<EdgeResource>();\r
+ result.routeLines = new THashSet<Resource>();\r
+ result.routePoints = new THashSet<Resource>();\r
+\r
+ result.partToConnection = new THashMap<Object, Resource>();\r
+\r
+ // These help loading result.elements in the correct order.\r
+ final AtomicInteger index = new AtomicInteger();\r
+ final TIntArrayList unrecognizedElementIndices = new TIntArrayList();\r
+\r
+ g.forOrderedSet(data, new AsyncMultiProcedure<Resource>() {\r
+\r
+ @Override\r
+ public void execute(AsyncReadGraph graph, final Resource component) {\r
+\r
+ // Must add the elements to the result set here in order to\r
+ // keep their order the same as in the ordered set.\r
+ final int elementIndex = index.getAndIncrement();\r
+ result.elements.add(component);\r
+\r
+ graph.forTypes(component, new AsyncProcedure<Set<Resource>>() {\r
+\r
+ @Override\r
+ public void exception(AsyncReadGraph graph, Throwable t) {\r
+ if (errorHandler != null)\r
+ errorHandler.error(t.getMessage(), t);\r
+ }\r
+\r
+ @Override\r
+ public void execute(AsyncReadGraph graph, Set<Resource> types) {\r
+ if (types.contains(DIA.Connection)) {\r
+ if (types.contains(DIA.RouteGraphConnection)) {\r
+ graph.asyncRequest(new RouteGraphConnectionPartRequest(errorHandler, DIA, component),\r
+ new ProcedureAdapter<RouteGraphConnectionPartData>() {\r
+ @Override\r
+ public void execute(RouteGraphConnectionPartData partData) {\r
+ synchronized (result) {\r
+ for (EdgeResource link : partData.links) {\r
+ result.routeLinks.add(link);\r
+ result.partToConnection.put(link, component);\r
+ result.connectionToParts.add(component, link);\r
+ }\r
+ for (Resource line : partData.routeLines) {\r
+ result.routeLines.add(line);\r
+ result.connectionToParts.add(component, line);\r
+ result.partToConnection.put(line, component);\r
+ }\r
+ for (Resource point : partData.routePoints) {\r
+ result.routePoints.add(point);\r
+ result.connectionToParts.add(component, point);\r
+ result.partToConnection.put(point, component);\r
+ }\r
+ }\r
+ }\r
+ });\r
+\r
+ synchronized (result.routeGraphConnectionSet) {\r
+ result.routeGraphConnectionSet.add(component);\r
+ }\r
+ } else {\r
+ graph.asyncRequest(new ConnectionPartRequest(errorHandler, DIA, component),\r
+ new ProcedureAdapter<ConnectionPartData>() {\r
+ @Override\r
+ public void execute(ConnectionPartData partData) {\r
+ synchronized (result) {\r
+ for (EdgeResource er : partData.edges) {\r
+ result.connectionSegments.add(er);\r
+ result.partToConnection.put(er, component);\r
+ result.connectionToParts.add(component, er);\r
+ }\r
+ for (Resource bp : partData.branchPoints) {\r
+ result.branchPoints.add(bp);\r
+ result.connectionToParts.add(component, bp);\r
+ result.partToConnection.put(bp, component);\r
+ }\r
+ }\r
+ }\r
+ });\r
+\r
+ synchronized (result.connectionSet) {\r
+ result.connectionSet.add(component);\r
+ }\r
+ }\r
+ }\r
+ else if (types.contains(DIA.Element)) {\r
+ synchronized (result.nodeSet) {\r
+ result.nodeSet.add(component);\r
+ }\r
+ }\r
+ else {\r
+ synchronized (unrecognizedElementIndices) {\r
+ // Unrecognized element, mark it to be\r
+ // removed after everything is processed.\r
+ unrecognizedElementIndices.add(elementIndex);\r
+ }\r
+ }\r
+ }\r
+\r
+ });\r
+\r
+ }\r
+\r
+ @Override\r
+ public void finished(AsyncReadGraph graph) {\r
+ // Remove elements that were not recognized in descending order.\r
+ unrecognizedElementIndices.sort();\r
+ unrecognizedElementIndices.forEachDescending(new TIntProcedure() {\r
+ @Override\r
+ public boolean execute(int index) {\r
+ result.elements.remove(index);\r
+ return true;\r
+ }\r
+ });\r
+\r
+ // Help successive request executions by remembering the previous\r
+ // element count. This will relieve some ArrayList reallocation\r
+ // strain down the road.\r
+ previousElementCount = result.elements.size();\r
+ }\r
+\r
+ @Override\r
+ public void exception(AsyncReadGraph graph, Throwable t) {\r
+ if (errorHandler != null)\r
+ errorHandler.error(t.getMessage(), t);\r
+ }\r
+ });\r
+\r
+ return result;\r
+ }\r
+}
\ No newline at end of file