1 /*******************************************************************************
\r
2 * Copyright (c) 2011 Association for Decentralized Information Management in
\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.synchronization.graph;
\r
14 import gnu.trove.map.hash.TObjectIntHashMap;
\r
15 import gnu.trove.procedure.TObjectIntProcedure;
\r
16 import gnu.trove.set.hash.THashSet;
\r
18 import java.util.ArrayList;
\r
19 import java.util.HashMap;
\r
20 import java.util.HashSet;
\r
21 import java.util.Iterator;
\r
22 import java.util.List;
\r
23 import java.util.Map;
\r
24 import java.util.Set;
\r
26 import org.simantics.db.ReadGraph;
\r
27 import org.simantics.db.Resource;
\r
28 import org.simantics.db.ServiceLocator;
\r
29 import org.simantics.db.Statement;
\r
30 import org.simantics.db.WriteGraph;
\r
31 import org.simantics.db.common.CommandMetadata;
\r
32 import org.simantics.db.common.CommentMetadata;
\r
33 import org.simantics.db.common.request.IndexRoot;
\r
34 import org.simantics.db.common.request.WriteRequest;
\r
35 import org.simantics.db.common.utils.NameUtils;
\r
36 import org.simantics.db.exception.DatabaseException;
\r
37 import org.simantics.db.request.Write;
\r
38 import org.simantics.db.service.SerialisationSupport;
\r
39 import org.simantics.diagram.connection.RouteGraph;
\r
40 import org.simantics.diagram.connection.RouteLine;
\r
41 import org.simantics.diagram.connection.RouteLink;
\r
42 import org.simantics.diagram.connection.RouteNode;
\r
43 import org.simantics.diagram.connection.RoutePoint;
\r
44 import org.simantics.diagram.connection.RouteTerminal;
\r
45 import org.simantics.diagram.connection.delta.RouteGraphDelta;
\r
46 import org.simantics.diagram.connection.delta.RouteGraphDelta.RouteLinePair;
\r
47 import org.simantics.diagram.connection.delta.RouteGraphDelta.RouteTerminalPair;
\r
48 import org.simantics.diagram.content.ConnectionUtil;
\r
49 import org.simantics.diagram.stubs.DiagramResource;
\r
50 import org.simantics.layer0.Layer0;
\r
51 import org.simantics.modeling.ModelingResources;
\r
52 import org.simantics.scenegraph.g2d.nodes.connection.RouteGraphChangeEvent;
\r
53 import org.simantics.scl.commands.Commands;
\r
54 import org.simantics.scl.compiler.top.ValueNotFound;
\r
55 import org.simantics.scl.osgi.SCLOsgi;
\r
56 import org.simantics.scl.runtime.SCLContext;
\r
57 import org.simantics.scl.runtime.function.Function;
\r
58 import org.simantics.structural.stubs.StructuralResource2;
\r
59 import org.simantics.utils.datastructures.Pair;
\r
62 * FIXME: Adding new route lines does not reconnect the new route lines to existing terminals/other route lines
\r
64 * @author Tuukka Lehtonen
\r
66 @SuppressWarnings("rawtypes")
\r
67 public class RouteGraphConnection {
\r
69 private static final boolean DEBUG_SYNC = false;
\r
70 private static final boolean USE_COMMAND_BASED_SYNCHRONIZATION = true;
\r
72 public static Write synchronizer(final Resource connection, final RouteGraphChangeEvent event) {
\r
73 return new WriteRequest() {
\r
75 public void perform(WriteGraph graph) throws DatabaseException {
\r
76 RouteGraphConnection rgc = new RouteGraphConnection(graph, connection);
\r
77 rgc.synchronize(graph, event.before, event.after, event.delta);
\r
78 CommentMetadata cm = graph.getMetadata(CommentMetadata.class);
\r
79 graph.addMetadata(cm.add("Modified connection route"));
\r
80 graph.markUndoPoint();
\r
86 private DiagramResource DIA;
\r
87 private ConnectionUtil cu;
\r
88 private Resource connection;
\r
90 public RouteGraphConnection(WriteGraph graph, Resource connection) {
\r
91 this.L0 = Layer0.getInstance(graph);
\r
92 this.DIA = DiagramResource.getInstance(graph);
\r
93 this.cu = new ConnectionUtil(graph);
\r
94 this.connection = connection;
\r
97 private static Function ConnectionPoint;
\r
98 private static Function Element;
\r
99 private static Function RouteGraphStructure;
\r
100 private static Function UpdateLine;
\r
101 private static Function RemoveNode;
\r
102 private static Function RemoveLink;
\r
103 private static Function CreateLine;
\r
104 private static Function CreateLink;
\r
106 private static boolean initialized = false;
\r
107 private static void initialize(ReadGraph graph) {
\r
109 Object oldGraph = SCLContext.getCurrent().put("graph", graph);
\r
111 ConnectionPoint = (Function)SCLOsgi.MODULE_REPOSITORY.getValue("Simantics/RouteGraph/ConnectionPoint");
\r
112 Element = (Function)SCLOsgi.MODULE_REPOSITORY.getValue("Simantics/RouteGraph/Element");
\r
113 RouteGraphStructure = (Function)SCLOsgi.MODULE_REPOSITORY.getValue("Simantics/RouteGraph/RouteGraphStructure");
\r
114 UpdateLine = (Function)SCLOsgi.MODULE_REPOSITORY.getValue("Simantics/RouteGraph/UpdateLine");
\r
115 RemoveNode = (Function)SCLOsgi.MODULE_REPOSITORY.getValue("Simantics/RouteGraph/RemoveNode");
\r
116 RemoveLink = (Function)SCLOsgi.MODULE_REPOSITORY.getValue("Simantics/RouteGraph/RemoveLink");
\r
117 CreateLine = (Function)SCLOsgi.MODULE_REPOSITORY.getValue("Simantics/RouteGraph/CreateLine");
\r
118 CreateLink = (Function)SCLOsgi.MODULE_REPOSITORY.getValue("Simantics/RouteGraph/CreateLink");
\r
119 initialized = true;
\r
120 } catch(ValueNotFound e) {
\r
121 e.printStackTrace();
\r
123 SCLContext.getCurrent().put("graph", oldGraph);
\r
128 @SuppressWarnings("unchecked")
\r
129 private static Object getConnectorIdentifier(ReadGraph graph, Resource connector) throws DatabaseException {
\r
130 Layer0 L0 = Layer0.getInstance(graph);
\r
131 DiagramResource DIA = DiagramResource.getInstance(graph);
\r
132 StructuralResource2 STR = StructuralResource2.getInstance(graph);
\r
133 ModelingResources MOD = ModelingResources.getInstance(graph);
\r
134 for(Statement stat : graph.getStatements(connector, STR.Connects)) {
\r
135 Resource pred = stat.getPredicate();
\r
136 Resource element = stat.getObject();
\r
137 if(!graph.isSubrelationOf(pred, DIA.IsConnectorOf)) {
\r
138 Resource component = graph.getPossibleObject(element, MOD.ElementToComponent);
\r
139 if(component != null) {
\r
140 String componentName = graph.getRelatedValue(component, L0.HasName);
\r
141 String relationName = graph.getRelatedValue(graph.getInverse(pred), L0.HasName);
\r
142 return ConnectionPoint.apply(componentName, relationName);
\r
144 else /* element is flag or reference element */ {
\r
145 String elementName = graph.getRelatedValue(element, L0.HasName);
\r
146 return Element.apply(elementName);
\r
150 throw new DatabaseException("Didn't find indentification for " + connector + ".");
\r
153 @SuppressWarnings("unchecked")
\r
154 public void synchronize(
\r
158 RouteGraphDelta delta) throws DatabaseException {
\r
163 if(USE_COMMAND_BASED_SYNCHRONIZATION) {
\r
164 initialize(graph);
\r
166 Layer0 L0 = Layer0.getInstance(graph);
\r
167 ModelingResources MOD = ModelingResources.getInstance(graph);
\r
169 Resource diagram = graph.getSingleObject(connection, L0.PartOf);
\r
170 Resource composite = graph.getSingleObject(diagram, MOD.DiagramToComposite);
\r
174 TObjectIntHashMap<RouteNode> routeNodeMap = new TObjectIntHashMap<RouteNode>() {
\r
176 protected int hash(Object notnull) {
\r
177 RouteNode node = (RouteNode)notnull;
\r
178 Object data = node.getData();
\r
180 return data.hashCode();
\r
182 return node.hashCode();
\r
186 protected boolean equals(Object notnull, Object two) {
\r
187 RouteNode node1 = (RouteNode)notnull;
\r
188 RouteNode node2 = (RouteNode)two;
\r
189 Object data1 = node1.getData();
\r
191 return node1 == node2;
\r
192 Object data2 = node2.getData();
\r
193 return data1.equals(data2);
\r
198 ArrayList<Object> connectorIdentifiers = new ArrayList<Object>();
\r
200 for(RouteTerminal terminal : before.getTerminals()) {
\r
201 Resource connector = deserialize(graph, terminal.getData());
\r
202 connectorIdentifiers.add(getConnectorIdentifier(graph, connector));
\r
203 routeNodeMap.put(terminal, routeNodeMap.size());
\r
206 ArrayList<Integer> routeLinks;
\r
207 if(before.isSimpleConnection()) {
\r
208 routeLinks = new ArrayList<Integer>(2);
\r
213 THashSet<RouteLink> linkSet = new THashSet<RouteLink>();
\r
214 for(RouteLine line : before.getLines()) {
\r
215 int id = routeNodeMap.size();
\r
216 routeNodeMap.put(line, id);
\r
217 for(RoutePoint rp : line.getPoints())
\r
218 if(rp instanceof RouteLink) {
\r
219 RouteLink link = (RouteLink)rp;
\r
220 if(!link.getA().isTransient() &&
\r
221 !link.getB().isTransient())
\r
226 routeLinks = new ArrayList<Integer>(linkSet.size()*2+before.getTerminals().size());
\r
227 for(RouteTerminal terminal : before.getTerminals()) {
\r
228 routeLinks.add(routeNodeMap.get(terminal));
\r
229 routeLinks.add(routeNodeMap.get(terminal.getLine()));
\r
231 for(RouteLink link : linkSet) {
\r
232 routeLinks.add(routeNodeMap.get(link.getA()));
\r
233 routeLinks.add(routeNodeMap.get(link.getB()));
\r
237 structure = RouteGraphStructure.apply(composite,
\r
238 connectorIdentifiers, routeNodeMap.size()-connectorIdentifiers.size(),
\r
243 // Process modifications
\r
244 ArrayList<Object> modifications = new ArrayList<Object>();
\r
245 ArrayList<Pair<RouteLine,Integer>> newRouteLines = new ArrayList<Pair<RouteLine,Integer>>();
\r
247 // Make direct changes to connection components
\r
248 for (RouteLinePair pair : delta.getLinesThatDiffer())
\r
249 modifications.add(UpdateLine.apply(routeNodeMap.get(pair.left),
\r
250 pair.right.getPosition(), pair.right.isHorizontal()));
\r
252 // Write new components into connection
\r
253 for (RouteLine added : delta.getLinesOnlyInRight()) {
\r
254 modifications.add(CreateLine.apply(added.getPosition(), added.isHorizontal()));
\r
255 newRouteLines.add(Pair.make(added, routeNodeMap.size()));
\r
256 routeNodeMap.put(added, routeNodeMap.size());
\r
259 // Remove all removed links from connection
\r
260 for (RouteLink removed : delta.getLinksOnlyInLeft())
\r
261 modifications.add(RemoveLink.apply(
\r
262 routeNodeMap.get(removed.getA()),
\r
263 routeNodeMap.get(removed.getB())));
\r
265 // Write modifications to connectivity between terminals and interior
\r
267 for (RouteLink added : delta.getLinksOnlyInRight())
\r
268 modifications.add(CreateLink.apply(
\r
269 routeNodeMap.get(added.getA()),
\r
270 routeNodeMap.get(added.getB())));
\r
272 // Update modifications to terminals
\r
273 if(before.isSimpleConnection()) {
\r
274 if(!after.isSimpleConnection()) {
\r
275 modifications.add(RemoveLink.apply(0, 1));
\r
276 for(RouteTerminal terminal : after.getTerminals())
\r
277 modifications.add(CreateLink.apply(
\r
278 routeNodeMap.get(terminal),
\r
279 routeNodeMap.get(terminal.getLine())
\r
283 else if(after.isSimpleConnection()) {
\r
284 for(RouteTerminal terminal : before.getTerminals())
\r
285 modifications.add(RemoveLink.apply(
\r
286 routeNodeMap.get(terminal),
\r
287 routeNodeMap.get(terminal.getLine())
\r
289 modifications.add(CreateLink.apply(0, 1));
\r
291 for (RouteTerminalPair pair : delta.getTerminalsThatDiffer()) {
\r
292 // If terminals are connected to different route lines,
\r
293 // disconnect left terminal connector from its connected counterpart
\r
294 // and connect the same terminal connector to the connected counterpart
\r
295 // listed in the right terminal.
\r
297 int terminalId = routeNodeMap.get(pair.left);
\r
298 int leftLine = routeNodeMap.get(pair.left.getLine());
\r
299 int rightLine = routeNodeMap.get(pair.right.getLine());
\r
301 if(leftLine != rightLine) {
\r
302 modifications.add(RemoveLink.apply(terminalId, leftLine));
\r
303 modifications.add(CreateLink.apply(terminalId, rightLine));
\r
308 // Disconnect and remove removed terminal connectors
\r
309 for(RouteTerminal removedTerminal : delta.getTerminalsOnlyInLeft())
\r
310 modifications.add(RemoveNode.apply(routeNodeMap.get(removedTerminal)));
\r
312 // Finally delete removed route lines
\r
313 for(RouteLine removed : delta.getLinesOnlyInLeft())
\r
314 modifications.add(RemoveNode.apply(routeNodeMap.get(removed)));
\r
318 if(!modifications.isEmpty()) {
\r
319 /*System.out.println("--");
\r
320 System.out.println(structure);
\r
321 System.out.println(modifications);*/
\r
322 final List<Resource> allRouteNodes = (List<Resource>)
\r
323 Commands.get(graph, "Simantics/RouteGraph/modifyRouteGraph")
\r
324 .execute(graph, graph.syncRequest(new IndexRoot(connection)),
\r
325 structure, modifications);
\r
326 for(Pair<RouteLine,Integer> pair : newRouteLines)
\r
327 pair.first.setData(allRouteNodes.get(pair.second).getResourceId());
\r
332 Map<RouteNode, Resource> newComponents = new HashMap<RouteNode, Resource>();
\r
334 CommentMetadata comments = graph.getMetadata(CommentMetadata.class);
\r
335 comments.add("Modified connection " + NameUtils.getSafeLabel(graph, connection));
\r
337 writeCommandMetadata(graph, before, delta, after);
\r
339 // Make direct changes to connection components
\r
340 for (RouteLinePair pair : delta.getLinesThatDiffer()) {
\r
341 Resource line = deserialize(graph, pair.right.getData());
\r
343 System.out.print("synchronizing existing route line: " + NameUtils.getSafeLabel(graph, line) + " - ");
\r
344 pair.right.print(System.out);
\r
346 writeLine(graph, line, pair.right);
\r
347 comments.add("Synchronized existing route line: " + NameUtils.getSafeLabel(graph, line));
\r
350 // Write new components into connection
\r
351 for (RouteLine added : delta.getLinesOnlyInRight()) {
\r
352 Resource line = tryDeserialize(graph, added.getData());
\r
354 System.out.print("adding new route line (" + line + "): ");
\r
355 added.print(System.out);
\r
357 newComponents.put( added, line = writeLine(graph, line, added) );
\r
359 comments.add("Added new route line " + NameUtils.getSafeLabel(graph, line));
\r
362 // Remove all removed links from connection
\r
363 for (RouteLink removed : delta.getLinksOnlyInLeft()) {
\r
364 Resource a = deserialize(graph, removed.getA().getData());
\r
365 Resource b = deserialize(graph, removed.getB().getData());
\r
367 System.out.println("removing link: " + NameUtils.getSafeLabel(graph, a) + " <> " + NameUtils.getSafeLabel(graph, b));
\r
368 cu.disconnect(a, b);
\r
369 comments.add("Removed link: " + NameUtils.getSafeLabel(graph, a) + " <> " + NameUtils.getSafeLabel(graph, b));
\r
372 // Write modifications to connectivity between terminals and interior
\r
374 for (RouteLink added : delta.getLinksOnlyInRight()) {
\r
376 System.out.println("processing added link:");
\r
377 added.getA().print(System.out);
\r
378 added.getB().print(System.out);
\r
380 Resource a = deserialize(graph, added.getA().getData());
\r
381 Resource b = deserialize(graph, added.getB().getData());
\r
383 System.out.println("adding link between "
\r
384 + NameUtils.getSafeLabel(graph, a) + " <> "
\r
385 + NameUtils.getSafeLabel(graph, b));
\r
387 comments.add("Added link between "
\r
388 + NameUtils.getSafeLabel(graph, a) + " <> "
\r
389 + NameUtils.getSafeLabel(graph, b));
\r
392 Set<Resource> looseConnectors = new HashSet<Resource>();
\r
394 // Handle terminals that differ
\r
395 for (RouteTerminalPair pair : delta.getTerminalsThatDiffer()) {
\r
397 System.out.println("processing differing terminal:");
\r
398 pair.left.print(System.out);
\r
399 pair.right.print(System.out);
\r
402 // If terminals are connected to different route lines,
\r
403 // disconnect left terminal connector from its connected counterpart
\r
404 // and connect the same terminal connector to the connected counterpart
\r
405 // listed in the right terminal.
\r
407 if (pair.left.getLine() != pair.right.getLine()) {
\r
408 Resource connector = deserialize( graph, pair.left.getData() );
\r
411 // - two terminals connected directly to each other.
\r
412 // - terminals moved so that a transient route line is added but
\r
413 // nothing should be written into the graph.
\r
414 // Case recognition logic:
\r
415 // left.line == null
\r
416 // && right.line != null
\r
417 // && right.line.data == null
\r
418 if (pair.left.getLine() == null
\r
419 && pair.right.getLine() != null
\r
420 && pair.right.getLine().getData() == null)
\r
424 // - terminal previously connected to either another terminal or a persistent route line
\r
426 // - terminal previously connected to another terminal through a transient route line
\r
428 // - terminal previously connected to another terminal
\r
429 if (pair.left.getLine() != null && pair.left.getLine().getData() != null) {
\r
430 Resource line = deserialize(graph, pair.left.getLine().getData());
\r
433 System.out.println("removing link between terminal "
\r
434 + NameUtils.getSafeLabel(graph, connector) + " and route line "
\r
435 + NameUtils.getSafeLabel(graph, line));
\r
436 cu.disconnect(connector, line);
\r
437 comments.add("Removed link between terminal "
\r
438 + NameUtils.getSafeLabel(graph, connector) + " and route line "
\r
439 + NameUtils.getSafeLabel(graph, line));
\r
443 System.out.println("removing link between terminal "
\r
444 + NameUtils.getSafeLabel(graph, connector) + " and other terminals ");
\r
445 cu.disconnectFromAllRouteNodes(connector);
\r
446 comments.add("Removed link between terminal "
\r
447 + NameUtils.getSafeLabel(graph, connector) + " and other terminals ");
\r
451 // - terminal is now connected to a persistent route line
\r
453 // - terminal is now connected to another terminal
\r
454 if (pair.right.getLine() != null && pair.right.getLine().getData() != null) {
\r
456 Resource line = deserialize(graph, pair.right.getLine().getData());
\r
458 System.out.println("adding link between terminal "
\r
459 + NameUtils.getSafeLabel(graph, connector) + " and route line "
\r
460 + NameUtils.getSafeLabel(graph, line));
\r
461 cu.connect(connector, line);
\r
462 comments.add("Added link between terminal "
\r
463 + NameUtils.getSafeLabel(graph, connector) + " and route line "
\r
464 + NameUtils.getSafeLabel(graph, line));
\r
467 // Connector was disconnected from route line.
\r
468 // This can currently only mean one thing:
\r
469 // there are no more route lines in the connection.
\r
470 // If there are still connectors in the connection, the
\r
471 // only possible assumption is that there are two
\r
472 // connectors and they need to be connected together
\r
473 looseConnectors.add(connector);
\r
477 if (looseConnectors.size() == 2) {
\r
478 Resource[] cns = looseConnectors.toArray(Resource.NONE);
\r
480 System.out.println("linking two loose terminal connectors "
\r
481 + NameUtils.getSafeLabel(graph, cns[0]) + " and "
\r
482 + NameUtils.getSafeLabel(graph, cns[1]));
\r
483 cu.connect(cns[0], cns[1]);
\r
484 comments.add("Linking two loose terminal connectors "
\r
485 + NameUtils.getSafeLabel(graph, cns[0]) + " and "
\r
486 + NameUtils.getSafeLabel(graph, cns[1]));
\r
487 } else if (!looseConnectors.isEmpty()) {
\r
488 System.err.println("BUG: there can only be 0 or 2 loose terminal connectors in any connection. Found " + looseConnectors.size() + ":");
\r
489 for (Resource cn : looseConnectors)
\r
490 System.err.println(NameUtils.getSafeLabel(graph, cn));
\r
491 System.err.flush();
\r
494 // Disconnect and remove removed terminal connectors
\r
495 for (RouteTerminal removedTerminal : delta.getTerminalsOnlyInLeft()) {
\r
496 Resource connector = deserialize(graph, removedTerminal.getData());
\r
498 System.out.println("removing route terminal: " + NameUtils.getSafeLabel(graph, connector));
\r
499 cu.removeConnectionPart(connector);
\r
500 comments.add("Removed route terminal " + NameUtils.getSafeLabel(graph, connector));
\r
503 // Finally delete removed route lines
\r
504 for (RouteLine removed : delta.getLinesOnlyInLeft()) {
\r
505 Resource line = deserialize(graph, removed.getData());
\r
507 System.out.println("removing route line: " + NameUtils.getSafeLabel(graph, line));
\r
508 cu.removeConnectionPart(line);
\r
509 comments.add("Removed route line " + NameUtils.getSafeLabel(graph, line));
\r
512 graph.addMetadata(comments);
\r
516 private void writeCommandMetadata(WriteGraph graph, RouteGraph left, RouteGraphDelta delta, RouteGraph right) {
\r
518 if(!delta.getTerminalsOnlyInLeft().isEmpty() || !delta.getTerminalsOnlyInRight().isEmpty())
\r
519 return; // These are not changes layout organizer may do.
\r
521 RouteGraphModification proxy = new RouteGraphModification(graph.getService(SerialisationSupport.class), left);
\r
522 TObjectIntHashMap<RouteNode> idMap = proxy.getIdMap();
\r
523 TObjectIntHashMap<RouteNode> rightIdMap = new TObjectIntHashMap<RouteNode>();
\r
525 final TObjectIntHashMap<Object> keyToId = new TObjectIntHashMap<Object>();
\r
526 idMap.forEachEntry(new TObjectIntProcedure<RouteNode>() {
\r
528 public boolean execute(RouteNode a, int b) {
\r
529 Object data = a.getData();
\r
531 keyToId.put(data, b);
\r
535 for(RouteLine line : right.getLines()) {
\r
536 Object data = line.getData();
\r
537 if(keyToId.containsKey(data))
\r
538 rightIdMap.put(line, keyToId.get(data));
\r
540 for(RouteTerminal terminal : right.getTerminals()) {
\r
541 Object data = terminal.getData();
\r
542 if(keyToId.containsKey(data))
\r
543 rightIdMap.put(terminal, keyToId.get(data));
\r
546 int id = idMap.size();
\r
547 for(RouteLink link : delta.getLinksOnlyInLeft()) {
\r
548 proxy.addModi(new RouteGraphModification.RemoveLink(idMap.get(link.getA()), idMap.get(link.getB())));
\r
550 for(RouteLine line : delta.getLinesOnlyInLeft()) {
\r
551 proxy.addModi(new RouteGraphModification.RemoveLine(idMap.get(line)));
\r
553 for(RouteLinePair pair : delta.getLinesThatDiffer()) {
\r
554 proxy.addModi(new RouteGraphModification.UpdateLine(idMap.get(pair.left), pair.right.getPosition(), pair.right.isHorizontal()));
\r
556 for(RouteLine line : delta.getLinesOnlyInRight()) {
\r
557 rightIdMap.put(line, id++);
\r
558 proxy.addModi(new RouteGraphModification.CreateLine(line.getPosition(), line.isHorizontal()));
\r
560 if(left.isSimpleConnection() && !right.isSimpleConnection())
\r
561 proxy.addModi(new RouteGraphModification.RemoveLink(0, 1));
\r
562 for(RouteTerminalPair pair : delta.getTerminalsThatDiffer())
\r
563 if(pair.left.getLine() != pair.right.getLine()) {
\r
564 if(pair.left.getLine() != null)
\r
565 proxy.addModi(new RouteGraphModification.RemoveLink(idMap.get(pair.left), idMap.get(pair.left.getLine())));
\r
566 if(pair.right.getLine() != null)
\r
567 proxy.addModi(new RouteGraphModification.CreateLink(idMap.get(pair.left), rightIdMap.get(pair.right.getLine())));
\r
569 if(!left.isSimpleConnection() && right.isSimpleConnection() && right.getTerminals().size() == 2) {
\r
570 Iterator<RouteTerminal> it = right.getTerminals().iterator();
\r
571 proxy.addModi(new RouteGraphModification.CreateLink(
\r
572 rightIdMap.get(it.next()), rightIdMap.get(it.next())));
\r
574 for(RouteLink link : delta.getLinksOnlyInRight()) {
\r
575 proxy.addModi(new RouteGraphModification.CreateLink(rightIdMap.get(link.getA()), rightIdMap.get(link.getB())));
\r
577 Resource model = proxy.findTerminalIdentifiers(graph);
\r
578 StringBuilder b = new StringBuilder();
\r
579 b.append("modifyConnection \"");
\r
583 CommandMetadata.add(graph, model.getResourceId(), b.toString());
\r
584 } catch(DatabaseException e) {
\r
585 // Failure in command writing must not cancel the write transaction
\r
586 e.printStackTrace();
\r
587 } catch(NullPointerException e) {
\r
588 // Failure in command writing must not cancel the write transaction
\r
589 e.printStackTrace();
\r
593 public Resource writeLine(WriteGraph graph, Resource line, RouteLine routeLine) throws DatabaseException {
\r
594 if (line == null) {
\r
595 line = graph.newResource();
\r
596 graph.claim(line, L0.InstanceOf, null, DIA.RouteLine);
\r
597 graph.claim(connection, DIA.HasInteriorRouteNode, line);
\r
599 graph.claimLiteral(line, DIA.IsHorizontal, routeLine.isHorizontal());
\r
600 graph.claimLiteral(line, DIA.HasPosition, routeLine.getPosition());
\r
601 routeLine.setData( serialize(graph, line) );
\r
603 System.out.print("wrote route line: ");
\r
604 routeLine.print(System.out);
\r
609 public static Object serialize(ServiceLocator locator, Resource r) throws DatabaseException {
\r
610 SerialisationSupport ss = locator.getService(SerialisationSupport.class);
\r
611 return ss.getRandomAccessId(r);
\r
614 public static Resource deserialize(ServiceLocator locator, Object o) throws DatabaseException {
\r
615 Resource r = tryDeserialize(locator, o);
\r
618 throw new IllegalArgumentException("unrecognized object: " + o);
\r
621 public static Resource tryDeserialize(ServiceLocator locator, Object o) throws DatabaseException {
\r
622 if (o instanceof Long)
\r
623 return locator.getService(SerialisationSupport.class).getResource((Long) o);
\r