1 /*******************************************************************************
2 * Copyright (c) 2007, 2018 Association for Decentralized Information Management
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
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.diagram.adapter;
14 import java.util.ArrayList;
15 import java.util.Collection;
17 import java.util.concurrent.atomic.AtomicInteger;
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;
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;
43 * @author Tuukka Lehtonen
45 public class DiagramContentRequest extends BaseRequest<Resource, DiagramContents> {
47 private static final Logger LOGGER = LoggerFactory.getLogger(DiagramContentRequest.class);
49 int previousElementCount = 32;
50 ErrorHandler errorHandler;
52 public DiagramContentRequest(ICanvasContext canvas, Resource resource, ErrorHandler errorHandler) {
53 super(canvas, resource);
54 this.errorHandler = errorHandler;
58 public DiagramContents perform(ReadGraph g) throws DatabaseException {
60 final DiagramResource DIA = DiagramResource.getInstance(g);
62 // These help loading result.elements in the correct order.
63 final AtomicInteger index = new AtomicInteger();
64 final TIntArrayList unrecognizedElementIndices = new TIntArrayList();
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
70 Collection<Resource> components = OrderedSetUtils.toList(g, data);
71 DiagramContents res = g.syncRequest((AsyncRead<DiagramContents>)(graph, procedure) -> {
73 DiagramContents result = new DiagramContents();
74 procedure.execute(graph, result);
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>();
86 result.partToConnection = new THashMap<Object, Resource>();
88 for (Resource component : components) {
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);
95 graph.asyncRequest(new org.simantics.db.common.primitiverequest.Types(component), new ProcedureAdapter<Set<Resource>>() {
98 public void execute(Set<Resource> types) {
100 if (types.contains(DIA.Connection)) {
101 if (types.contains(DIA.RouteGraphConnection)) {
103 new RouteGraphConnectionPartRequest(errorHandler, DIA, component),
104 new ProcedureAdapter<RouteGraphConnectionPartData>() {
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);
113 for (Resource line : partData.routeLines) {
114 result.routeLines.add(line);
115 result.connectionToParts.add(component, line);
116 result.partToConnection.put(line, component);
118 for (Resource point : partData.routePoints) {
119 result.routePoints.add(point);
120 result.connectionToParts.add(component, point);
121 result.partToConnection.put(point, component);
127 synchronized (result.routeGraphConnectionSet) {
128 result.routeGraphConnectionSet.add(component);
132 new ConnectionPartRequest(errorHandler, DIA, component),
133 new ProcedureAdapter<ConnectionPartData>() {
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);
142 for (Resource bp : partData.branchPoints) {
143 result.branchPoints.add(bp);
144 result.connectionToParts.add(component, bp);
145 result.partToConnection.put(bp, component);
151 synchronized (result.connectionSet) {
152 result.connectionSet.add(component);
156 else if (types.contains(DIA.Element)) {
157 synchronized (result.nodeSet) {
158 result.nodeSet.add(component);
162 synchronized (unrecognizedElementIndices) {
163 // Unrecognized element, mark it to be
164 // removed after everything is processed.
165 unrecognizedElementIndices.add(elementIndex);
173 // Remove elements that were not recognized in descending order.
174 unrecognizedElementIndices.sort();
175 unrecognizedElementIndices.forEachDescending(new TIntProcedure() {
177 public boolean execute(int index) {
178 res.elements.remove(index);
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();