]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.diagram/src/org/simantics/diagram/adapter/DiagramContentRequest.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.diagram / src / org / simantics / diagram / adapter / DiagramContentRequest.java
1 /*******************************************************************************\r
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
3  * in Industry THTH ry.\r
4  * All rights reserved. This program and the accompanying materials\r
5  * are made available under the terms of the Eclipse Public License v1.0\r
6  * which accompanies this distribution, and is available at\r
7  * http://www.eclipse.org/legal/epl-v10.html\r
8  *\r
9  * Contributors:\r
10  *     VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.simantics.diagram.adapter;\r
13 \r
14 import gnu.trove.list.array.TIntArrayList;\r
15 import gnu.trove.map.hash.THashMap;\r
16 import gnu.trove.procedure.TIntProcedure;\r
17 import gnu.trove.set.hash.THashSet;\r
18 \r
19 import java.util.ArrayList;\r
20 import java.util.Set;\r
21 import java.util.concurrent.atomic.AtomicInteger;\r
22 \r
23 import org.simantics.db.AsyncReadGraph;\r
24 import org.simantics.db.ReadGraph;\r
25 import org.simantics.db.Resource;\r
26 import org.simantics.db.common.procedure.adapter.ProcedureAdapter;\r
27 import org.simantics.db.exception.DatabaseException;\r
28 import org.simantics.db.procedure.AsyncMultiProcedure;\r
29 import org.simantics.db.procedure.AsyncProcedure;\r
30 import org.simantics.diagram.content.ConnectionPartData;\r
31 import org.simantics.diagram.content.ConnectionPartRequest;\r
32 import org.simantics.diagram.content.DiagramContents;\r
33 import org.simantics.diagram.content.EdgeResource;\r
34 import org.simantics.diagram.content.RouteGraphConnectionPartData;\r
35 import org.simantics.diagram.content.RouteGraphConnectionPartRequest;\r
36 import org.simantics.diagram.stubs.DiagramResource;\r
37 import org.simantics.diagram.synchronization.ErrorHandler;\r
38 import org.simantics.g2d.canvas.ICanvasContext;\r
39 \r
40 /**\r
41  * @author Tuukka Lehtonen\r
42  */\r
43 public class DiagramContentRequest extends BaseRequest<Resource, DiagramContents> {\r
44 \r
45     int previousElementCount = 32;\r
46     ErrorHandler errorHandler;\r
47 \r
48     public DiagramContentRequest(ICanvasContext canvas, Resource resource, ErrorHandler errorHandler) {\r
49         super(canvas, resource);\r
50         this.errorHandler = errorHandler;\r
51     }\r
52 \r
53     @Override\r
54     public DiagramContents perform(ReadGraph g) throws DatabaseException {\r
55 \r
56         final DiagramResource DIA = DiagramResource.getInstance(g);\r
57         final DiagramContents result = new DiagramContents();\r
58 \r
59         result.elements =   new ArrayList<Resource>(previousElementCount);\r
60         result.nodeSet = new THashSet<Resource>();\r
61         result.connectionSet = new THashSet<Resource>();\r
62         result.connectionSegments = new THashSet<EdgeResource>();\r
63         result.branchPoints = new THashSet<Resource>();\r
64         result.routeGraphConnectionSet = new THashSet<Resource>();\r
65         result.routeLinks = new THashSet<EdgeResource>();\r
66         result.routeLines = new THashSet<Resource>();\r
67         result.routePoints = new THashSet<Resource>();\r
68 \r
69         result.partToConnection = new THashMap<Object, Resource>();\r
70 \r
71         // These help loading result.elements in the correct order.\r
72         final AtomicInteger index = new AtomicInteger();\r
73         final TIntArrayList unrecognizedElementIndices = new TIntArrayList();\r
74 \r
75         g.forOrderedSet(data, new AsyncMultiProcedure<Resource>() {\r
76 \r
77             @Override\r
78             public void execute(AsyncReadGraph graph, final Resource component) {\r
79 \r
80                 // Must add the elements to the result set here in order to\r
81                 // keep their order the same as in the ordered set.\r
82                 final int elementIndex = index.getAndIncrement();\r
83                 result.elements.add(component);\r
84 \r
85                 graph.forTypes(component, new AsyncProcedure<Set<Resource>>() {\r
86 \r
87                     @Override\r
88                     public void exception(AsyncReadGraph graph, Throwable t) {\r
89                         if (errorHandler != null)\r
90                             errorHandler.error(t.getMessage(), t);\r
91                     }\r
92 \r
93                     @Override\r
94                     public void execute(AsyncReadGraph graph, Set<Resource> types) {\r
95                         if (types.contains(DIA.Connection)) {\r
96                             if (types.contains(DIA.RouteGraphConnection)) {\r
97                                 graph.asyncRequest(new RouteGraphConnectionPartRequest(errorHandler, DIA, component),\r
98                                         new ProcedureAdapter<RouteGraphConnectionPartData>() {\r
99                                     @Override\r
100                                     public void execute(RouteGraphConnectionPartData partData) {\r
101                                         synchronized (result) {\r
102                                             for (EdgeResource link : partData.links) {\r
103                                                 result.routeLinks.add(link);\r
104                                                 result.partToConnection.put(link, component);\r
105                                                 result.connectionToParts.add(component, link);\r
106                                             }\r
107                                             for (Resource line : partData.routeLines) {\r
108                                                 result.routeLines.add(line);\r
109                                                 result.connectionToParts.add(component, line);\r
110                                                 result.partToConnection.put(line, component);\r
111                                             }\r
112                                             for (Resource point : partData.routePoints) {\r
113                                                 result.routePoints.add(point);\r
114                                                 result.connectionToParts.add(component, point);\r
115                                                 result.partToConnection.put(point, component);\r
116                                             }\r
117                                         }\r
118                                     }\r
119                                 });\r
120 \r
121                                 synchronized (result.routeGraphConnectionSet) {\r
122                                     result.routeGraphConnectionSet.add(component);\r
123                                 }\r
124                             } else {\r
125                                 graph.asyncRequest(new ConnectionPartRequest(errorHandler, DIA, component),\r
126                                         new ProcedureAdapter<ConnectionPartData>() {\r
127                                     @Override\r
128                                     public void execute(ConnectionPartData partData) {\r
129                                         synchronized (result) {\r
130                                             for (EdgeResource er : partData.edges) {\r
131                                                 result.connectionSegments.add(er);\r
132                                                 result.partToConnection.put(er, component);\r
133                                                 result.connectionToParts.add(component, er);\r
134                                             }\r
135                                             for (Resource bp : partData.branchPoints) {\r
136                                                 result.branchPoints.add(bp);\r
137                                                 result.connectionToParts.add(component, bp);\r
138                                                 result.partToConnection.put(bp, component);\r
139                                             }\r
140                                         }\r
141                                     }\r
142                                 });\r
143 \r
144                                 synchronized (result.connectionSet) {\r
145                                     result.connectionSet.add(component);\r
146                                 }\r
147                             }\r
148                         }\r
149                         else if (types.contains(DIA.Element)) {\r
150                             synchronized (result.nodeSet) {\r
151                                 result.nodeSet.add(component);\r
152                             }\r
153                         }\r
154                         else {\r
155                             synchronized (unrecognizedElementIndices) {\r
156                                 // Unrecognized element, mark it to be\r
157                                 // removed after everything is processed.\r
158                                 unrecognizedElementIndices.add(elementIndex);\r
159                             }\r
160                         }\r
161                     }\r
162 \r
163                 });\r
164 \r
165             }\r
166 \r
167             @Override\r
168             public void finished(AsyncReadGraph graph) {\r
169                 // Remove elements that were not recognized in descending order.\r
170                 unrecognizedElementIndices.sort();\r
171                 unrecognizedElementIndices.forEachDescending(new TIntProcedure() {\r
172                     @Override\r
173                     public boolean execute(int index) {\r
174                         result.elements.remove(index);\r
175                         return true;\r
176                     }\r
177                 });\r
178 \r
179                 // Help successive request executions by remembering the previous\r
180                 // element count. This will relieve some ArrayList reallocation\r
181                 // strain down the road.\r
182                 previousElementCount = result.elements.size();\r
183             }\r
184 \r
185             @Override\r
186             public void exception(AsyncReadGraph graph, Throwable t) {\r
187                 if (errorHandler != null)\r
188                     errorHandler.error(t.getMessage(), t);\r
189             }\r
190         });\r
191 \r
192         return result;\r
193     }\r
194 }