]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.diagram/src/org/simantics/diagram/adapter/DiagramContentRequest.java
8f5afab1ac5faee7115d3164827014c3bbd100fe
[simantics/platform.git] / bundles / org.simantics.diagram / src / org / simantics / diagram / adapter / DiagramContentRequest.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2018 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.ReadGraph;
20 import org.simantics.db.Resource;
21 import org.simantics.db.common.procedure.adapter.ProcedureAdapter;
22 import org.simantics.db.common.utils.OrderedSetUtils;
23 import org.simantics.db.exception.DatabaseException;
24 import org.simantics.db.request.AsyncRead;
25 import org.simantics.diagram.content.ConnectionPartData;
26 import org.simantics.diagram.content.ConnectionPartRequest;
27 import org.simantics.diagram.content.DiagramContents;
28 import org.simantics.diagram.content.EdgeResource;
29 import org.simantics.diagram.content.RouteGraphConnectionPartData;
30 import org.simantics.diagram.content.RouteGraphConnectionPartRequest;
31 import org.simantics.diagram.stubs.DiagramResource;
32 import org.simantics.diagram.synchronization.ErrorHandler;
33 import org.simantics.g2d.canvas.ICanvasContext;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
36
37 import gnu.trove.list.array.TIntArrayList;
38 import gnu.trove.map.hash.THashMap;
39 import gnu.trove.procedure.TIntProcedure;
40 import gnu.trove.set.hash.THashSet;
41
42 /**
43  * @author Tuukka Lehtonen
44  */
45 public class DiagramContentRequest extends BaseRequest<Resource, DiagramContents> {
46
47     private static final Logger LOGGER = LoggerFactory.getLogger(DiagramContentRequest.class);
48
49     int previousElementCount = 32;
50     ErrorHandler errorHandler;
51
52     public DiagramContentRequest(ICanvasContext canvas, Resource resource, ErrorHandler errorHandler) {
53         super(canvas, resource);
54         this.errorHandler = errorHandler;
55     }
56
57     @Override
58     public DiagramContents perform(ReadGraph g) throws DatabaseException {
59
60         final DiagramResource DIA = DiagramResource.getInstance(g);
61
62         // These help loading result.elements in the correct order.
63         final AtomicInteger index = new AtomicInteger();
64         final TIntArrayList unrecognizedElementIndices = new TIntArrayList();
65         
66         if (!g.hasStatement(data)) {
67             LOGGER.warn("Most likely diagram is being removed and therefore ordered list can not be found for {}", data);
68             return new DiagramContents(); // or null, I don't know
69         }
70         Collection<Resource> components = OrderedSetUtils.toList(g, data);
71         DiagramContents res = g.syncRequest((AsyncRead<DiagramContents>)(graph, procedure) -> {
72
73             DiagramContents result = new DiagramContents();
74             procedure.execute(graph, result);
75
76             result.elements =   new ArrayList<Resource>(previousElementCount);
77             result.nodeSet = new THashSet<Resource>();
78             result.connectionSet = new THashSet<Resource>();
79             result.connectionSegments = new THashSet<EdgeResource>();
80             result.branchPoints = new THashSet<Resource>();
81             result.routeGraphConnectionSet = new THashSet<Resource>();
82             result.routeLinks = new THashSet<EdgeResource>();
83             result.routeLines = new THashSet<Resource>();
84             result.routePoints = new THashSet<Resource>();
85
86             result.partToConnection = new THashMap<Object, Resource>();
87
88             for (Resource component : components) {
89
90                 // Must add the elements to the result set here in order to
91                 // keep their order the same as in the ordered set.
92                 final int elementIndex = index.getAndIncrement();
93                 result.elements.add(component);
94
95                 graph.forTypes(component, new ProcedureAdapter<Set<Resource>>() {
96
97                     @Override
98                     public void execute(Set<Resource> types) {
99
100                         if (types.contains(DIA.Connection)) {
101                             if (types.contains(DIA.RouteGraphConnection)) {
102                                 graph.asyncRequest(
103                                         new RouteGraphConnectionPartRequest(errorHandler, DIA, component),
104                                         new ProcedureAdapter<RouteGraphConnectionPartData>() {
105                                             @Override
106                                             public void execute(RouteGraphConnectionPartData partData) {
107                                                 synchronized (result) {
108                                                     for (EdgeResource link : partData.links) {
109                                                         result.routeLinks.add(link);
110                                                         result.partToConnection.put(link, component);
111                                                         result.connectionToParts.add(component, link);
112                                                     }
113                                                     for (Resource line : partData.routeLines) {
114                                                         result.routeLines.add(line);
115                                                         result.connectionToParts.add(component, line);
116                                                         result.partToConnection.put(line, component);
117                                                     }
118                                                     for (Resource point : partData.routePoints) {
119                                                         result.routePoints.add(point);
120                                                         result.connectionToParts.add(component, point);
121                                                         result.partToConnection.put(point, component);
122                                                     }
123                                                 }
124                                             }
125                                         });
126
127                                 synchronized (result.routeGraphConnectionSet) {
128                                     result.routeGraphConnectionSet.add(component);
129                                 }
130                             } else {
131                                 graph.asyncRequest(
132                                         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         // Remove elements that were not recognized in descending order.
174         unrecognizedElementIndices.sort();
175         unrecognizedElementIndices.forEachDescending(new TIntProcedure() {
176             @Override
177             public boolean execute(int index) {
178                 res.elements.remove(index);
179                 return true;
180             }
181         });
182
183         // Help successive request executions by remembering the previous
184         // element count. This will relieve some ArrayList reallocation
185         // strain down the road.
186         previousElementCount = res.elements.size();
187
188         return res;
189     }
190 }