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
10 * VTT Technical Research Centre of Finland - initial API and implementation
\r
11 *******************************************************************************/
\r
12 package org.simantics.diagram.adapter;
\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
19 import java.util.ArrayList;
\r
20 import java.util.Set;
\r
21 import java.util.concurrent.atomic.AtomicInteger;
\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
41 * @author Tuukka Lehtonen
\r
43 public class DiagramContentRequest extends BaseRequest<Resource, DiagramContents> {
\r
45 int previousElementCount = 32;
\r
46 ErrorHandler errorHandler;
\r
48 public DiagramContentRequest(ICanvasContext canvas, Resource resource, ErrorHandler errorHandler) {
\r
49 super(canvas, resource);
\r
50 this.errorHandler = errorHandler;
\r
54 public DiagramContents perform(ReadGraph g) throws DatabaseException {
\r
56 final DiagramResource DIA = DiagramResource.getInstance(g);
\r
57 final DiagramContents result = new DiagramContents();
\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
69 result.partToConnection = new THashMap<Object, Resource>();
\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
75 g.forOrderedSet(data, new AsyncMultiProcedure<Resource>() {
\r
78 public void execute(AsyncReadGraph graph, final Resource component) {
\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
85 graph.forTypes(component, new AsyncProcedure<Set<Resource>>() {
\r
88 public void exception(AsyncReadGraph graph, Throwable t) {
\r
89 if (errorHandler != null)
\r
90 errorHandler.error(t.getMessage(), t);
\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
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
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
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
121 synchronized (result.routeGraphConnectionSet) {
\r
122 result.routeGraphConnectionSet.add(component);
\r
125 graph.asyncRequest(new ConnectionPartRequest(errorHandler, DIA, component),
\r
126 new ProcedureAdapter<ConnectionPartData>() {
\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
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
144 synchronized (result.connectionSet) {
\r
145 result.connectionSet.add(component);
\r
149 else if (types.contains(DIA.Element)) {
\r
150 synchronized (result.nodeSet) {
\r
151 result.nodeSet.add(component);
\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
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
173 public boolean execute(int index) {
\r
174 result.elements.remove(index);
\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
186 public void exception(AsyncReadGraph graph, Throwable t) {
\r
187 if (errorHandler != null)
\r
188 errorHandler.error(t.getMessage(), t);
\r