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