X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics.diagram%2Fsrc%2Forg%2Fsimantics%2Fdiagram%2Fadapter%2FGraphToDiagramSynchronizer.java;h=37471eb3a1186fa8dc1c993e7d0f267f178a5f91;hb=617b9475710b80a125597f222f9777224972ce72;hp=dd6c9b7d10f7e7e916264a30bc3f24af71180627;hpb=0ae2b770234dfc3cbb18bd38f324125cf0faca07;p=simantics%2Fplatform.git diff --git a/bundles/org.simantics.diagram/src/org/simantics/diagram/adapter/GraphToDiagramSynchronizer.java b/bundles/org.simantics.diagram/src/org/simantics/diagram/adapter/GraphToDiagramSynchronizer.java index dd6c9b7d1..37471eb3a 100644 --- a/bundles/org.simantics.diagram/src/org/simantics/diagram/adapter/GraphToDiagramSynchronizer.java +++ b/bundles/org.simantics.diagram/src/org/simantics/diagram/adapter/GraphToDiagramSynchronizer.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2010 Association for Decentralized Information Management + * Copyright (c) 2007, 2018 Association for Decentralized Information Management * in Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -11,9 +11,6 @@ *******************************************************************************/ package org.simantics.diagram.adapter; -import gnu.trove.map.hash.TObjectIntHashMap; -import gnu.trove.set.hash.THashSet; - import java.awt.geom.AffineTransform; import java.lang.reflect.InvocationTargetException; import java.util.ArrayDeque; @@ -49,6 +46,7 @@ import org.simantics.db.common.procedure.adapter.AsyncProcedureAdapter; import org.simantics.db.common.procedure.adapter.CacheListener; import org.simantics.db.common.procedure.adapter.ListenerSupport; import org.simantics.db.common.procedure.adapter.ProcedureAdapter; +import org.simantics.db.common.procedure.adapter.TransientCacheAsyncListener; import org.simantics.db.common.request.AsyncReadRequest; import org.simantics.db.common.request.ReadRequest; import org.simantics.db.common.session.SessionEventListenerAdapter; @@ -140,6 +138,7 @@ import org.simantics.scenegraph.INode; import org.simantics.scenegraph.profile.DataNodeConstants; import org.simantics.scenegraph.profile.DataNodeMap; import org.simantics.scenegraph.profile.common.ProfileObserver; +import org.simantics.scl.runtime.tuple.Tuple3; import org.simantics.structural2.modelingRules.IModelingRules; import org.simantics.utils.datastructures.ArrayMap; import org.simantics.utils.datastructures.MapSet; @@ -157,6 +156,11 @@ import org.simantics.utils.strings.EString; import org.simantics.utils.threads.ThreadUtils; import org.simantics.utils.threads.logger.ITask; import org.simantics.utils.threads.logger.ThreadLogger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import gnu.trove.map.hash.TObjectIntHashMap; +import gnu.trove.set.hash.THashSet; /** * This class loads a diagram contained in the graph database into the runtime @@ -249,6 +253,8 @@ import org.simantics.utils.threads.logger.ThreadLogger; */ public class GraphToDiagramSynchronizer extends AbstractDisposable implements IDiagramLoader, IModifiableSynchronizationContext { + private static final Logger LOGGER = LoggerFactory.getLogger(GraphToDiagramSynchronizer.class); + /** * Controls whether the class adds hint listeners to each diagram element * that try to perform basic sanity checks on changes happening in element @@ -611,6 +617,17 @@ public class GraphToDiagramSynchronizer extends AbstractDisposable implements ID */ ConcurrentMap dataConnection = new ConcurrentHashMap(); + + void mapElementIfNew(final Object data, final IElement element) { + IElement mapped = getMappedElement(data); + if(mapped == null) { + mapElement(data, element); + currentUpdater.addedElements.add(element); + currentUpdater.addedElementMap.put(data, element); + } + } + + /** * @param data * @param element @@ -762,7 +779,7 @@ public class GraphToDiagramSynchronizer extends AbstractDisposable implements ID else result.add(eh); } - return ElementClass.compile(result).setId(ec.getId()); + return ElementClass.compile(result, false).setId(ec.getId()); } } @@ -1110,7 +1127,7 @@ public class GraphToDiagramSynchronizer extends AbstractDisposable implements ID } } catch (InterruptedException e) { // Shouldn't happen. - e.printStackTrace(); + LOGGER.error("Dispose interrupted!", e); } finally { detachSessionListener(); @@ -1301,7 +1318,8 @@ public class GraphToDiagramSynchronizer extends AbstractDisposable implements ID task4.finish(); // ITask task5 = ThreadLogger.getInstance().begin("DiagramContentRequest2"); ITask task42 = ThreadLogger.getInstance().begin("DiagramContentRequest2"); - DiagramContents contents = g.syncRequest(query); + DiagramContents contents = g.syncRequest(query, TransientCacheAsyncListener.instance()); + //System.err.println("contents: " + contents); task42.finish(); // task5.finish(); monitor.worked(10); @@ -1338,7 +1356,16 @@ public class GraphToDiagramSynchronizer extends AbstractDisposable implements ID ArrayMap.keys(ProfileKeys.DIAGRAM, ProfileKeys.CANVAS, ProfileKeys.NODE_MAP).values(GraphToDiagramSynchronizer.this.diagram, canvas, dn), new CanvasNotification(canvas)); - profileObserver.listen(g, GraphToDiagramSynchronizer.this); + g.getSession().asyncRequest(new AsyncReadRequest() { + @Override + public void run(AsyncReadGraph graph) { + ProfileObserver po = profileObserver; + if (po != null) + po.listen(graph, GraphToDiagramSynchronizer.this); + else + LOGGER.info("profileObserver has been disposed already!"); + } + }); return d; @@ -1603,11 +1630,11 @@ public class GraphToDiagramSynchronizer extends AbstractDisposable implements ID } public void clear() { - // Prevent DiagramContents leakage through DisposableListeners. - lastContent = null; - content = null; - changes = null; - + // Prevent DiagramContents leakage through DisposableListeners. + lastContent = null; + content = null; + changes = null; + this.addedElements.clear(); this.removedElements.clear(); this.addedConnectionSegments.clear(); @@ -1623,7 +1650,91 @@ public class GraphToDiagramSynchronizer extends AbstractDisposable implements ID this.removedRouteGraphConnections.clear(); } - void processNodes(AsyncReadGraph graph) { + class LoadNodeListener extends DisposableListener { + + final Resource element; + public IElement lastLoaded; + + public LoadNodeListener(ListenerSupport support, Resource element) { + super(support); + this.element = element; + } + + @Override + public String toString() { + return "Node load listener for " + element; + } + + public void applyFirst(IElement loaded) { + + Object data = loaded.getHint(ElementHints.KEY_OBJECT); + + if (addedElementMap.containsKey(data)) { + // This element was just loaded, in + // which case its hints need to + // uploaded to the real mapped + // element immediately. + IElement mappedElement = getMappedElement(data); + if (DebugPolicy.DEBUG_NODE_LISTENER) + System.out.println("LOADED ADDED ELEMENT, currently mapped element: " + mappedElement); + if (mappedElement != null && (mappedElement instanceof Element)) { + if (DebugPolicy.DEBUG_NODE_LISTENER) { + System.out.println(" mapped hints: " + mappedElement.getHints()); + System.out.println(" loaded hints: " + loaded.getHints()); + } + updateMappedElement((Element) mappedElement, loaded); + } + } + + } + + @Override + public void execute(IElement loaded) { + + // Invoked when the element has been loaded. + if (DebugPolicy.DEBUG_NODE_LISTENER) + System.out.println("NODE LoadListener for " + loaded); + + if (loaded == null) { + disposeListener(); + return; + } + + + boolean first = lastLoaded == null; + + lastLoaded = loaded; + + /* + * The first invocation is postponed + */ + if(first) { + applyFirst(loaded); + return; + } + + Object data = loaded.getHint(ElementHints.KEY_OBJECT); + + // Logic for disposing listener + if (!previousContent.nodeSet.contains(data)) { + if (DebugPolicy.DEBUG_NODE_LISTENER) + System.out.println("NODE LoadListener, node not in current content: " + data + ". Disposing."); + disposeListener(); + return; + } + + // This element was already loaded. + // Just schedule an update some time + // in the future. + if (DebugPolicy.DEBUG_NODE_LISTENER) + System.out.println("PREVIOUSLY LOADED NODE UPDATED, scheduling update into the future"); + offerGraphUpdate( nodeUpdater(element, loaded) ); + + } + + } + + void processNodes(AsyncReadGraph graph) throws DatabaseException { for (Map.Entry entry : changes.elements.entrySet()) { @@ -1635,7 +1746,7 @@ public class GraphToDiagramSynchronizer extends AbstractDisposable implements ID IElement mappedElement = getMappedElement(element); if (mappedElement == null) { if (DebugPolicy.DEBUG_NODE_LOAD) - graph.asyncRequest(new ReadRequest() { + graph.syncRequest(new ReadRequest() { @Override public void run(ReadGraph graph) throws DatabaseException { System.out.println(" EXTERNALLY ADDED ELEMENT: " @@ -1648,10 +1759,13 @@ public class GraphToDiagramSynchronizer extends AbstractDisposable implements ID // TODO: Connection loading has no listening, changes :Connection will not be noticed by this code! Listener loadListener = new DisposableListener(canvasListenerSupport) { - @Override - public String toString() { - return "Connection load listener for " + element; - } + + boolean firstTime = true; + + @Override + public String toString() { + return "Connection load listener for " + element; + } @Override public void execute(IElement loaded) { // Invoked when the element has been loaded. @@ -1663,6 +1777,19 @@ public class GraphToDiagramSynchronizer extends AbstractDisposable implements ID return; } + if (firstTime) { + + mapElement(element, loaded); + synchronized (GraphToDiagramUpdater.this) { + addedElements.add(loaded); + addedElementMap.put(element, loaded); + addedConnectionMap.put(element, loaded); + } + + firstTime = false; + + } + Object data = loaded.getHint(ElementHints.KEY_OBJECT); // Logic for disposing listener @@ -1702,10 +1829,7 @@ public class GraphToDiagramSynchronizer extends AbstractDisposable implements ID graph.asyncRequest(new ConnectionRequest(canvas, diagram, element, errorHandler, loadListener), new AsyncProcedure() { @Override public void execute(AsyncReadGraph graph, final IElement e) { - if (e == null) - return; - //System.out.println("ConnectionRequestProcedure " + e); mapElement(element, e); synchronized (GraphToDiagramUpdater.this) { addedElements.add(e); @@ -1723,13 +1847,20 @@ public class GraphToDiagramSynchronizer extends AbstractDisposable implements ID @Override public void execute(Resource connectionType) { synchronized (GraphToDiagramUpdater.this) { + IElement mapped = getMappedElement(element); + assert(mapped != null); + + if (DebugPolicy.DEBUG_CONNECTION_LISTENER) + System.out.println("CONNECTION ENTITY CREATED " + e + " " + element); + //System.out.println("new connection entity " + e); - ConnectionEntityImpl entity = new ConnectionEntityImpl(element, connectionType, e); - e.setHint(ElementHints.KEY_CONNECTION_ENTITY, entity); + ConnectionEntityImpl entity = new ConnectionEntityImpl(element, connectionType, mapped); + mapped.setHint(ElementHints.KEY_CONNECTION_ENTITY, entity); addedConnectionEntities.put(element, entity); } } }); + } @Override @@ -1739,65 +1870,19 @@ public class GraphToDiagramSynchronizer extends AbstractDisposable implements ID }); } else if (content.nodeSet.contains(element)) { - Listener loadListener = new DisposableListener(canvasListenerSupport) { - @Override - public String toString() { - return "Node load listener for " + element; - } - @Override - public void execute(IElement loaded) { - // Invoked when the element has been loaded. - if (DebugPolicy.DEBUG_NODE_LISTENER) - System.out.println("NODE LoadListener for " + loaded); - - if (loaded == null) { - disposeListener(); - return; - } - - Object data = loaded.getHint(ElementHints.KEY_OBJECT); - - // Logic for disposing listener - if (!previousContent.nodeSet.contains(data)) { - if (DebugPolicy.DEBUG_NODE_LISTENER) - System.out.println("NODE LoadListener, node not in current content: " + data + ". Disposing."); - disposeListener(); - return; - } - - if (addedElementMap.containsKey(data)) { - // This element was just loaded, in - // which case its hints need to - // uploaded to the real mapped - // element immediately. - IElement mappedElement = getMappedElement(data); - if (DebugPolicy.DEBUG_NODE_LISTENER) - System.out.println("LOADED ADDED ELEMENT, currently mapped element: " + mappedElement); - if (mappedElement != null && (mappedElement instanceof Element)) { - if (DebugPolicy.DEBUG_NODE_LISTENER) { - System.out.println(" mapped hints: " + mappedElement.getHints()); - System.out.println(" loaded hints: " + loaded.getHints()); - } - updateMappedElement((Element) mappedElement, loaded); - } - } else { - // This element was already loaded. - // Just schedule an update some time - // in the future. - if (DebugPolicy.DEBUG_NODE_LISTENER) - System.out.println("PREVIOUSLY LOADED NODE UPDATED, scheduling update into the future"); - offerGraphUpdate( nodeUpdater(element, loaded) ); - } - } - }; + graph.asyncRequest(new ReadRequest() { - //System.out.println("NODE REQUEST: " + element); - graph.asyncRequest(new NodeRequest(canvas, diagram, element, loadListener), new AsyncProcedure() { @Override - public void execute(AsyncReadGraph graph, IElement e) { + public void run(ReadGraph graph) throws DatabaseException { + + LoadNodeListener loadListener = new LoadNodeListener(canvasListenerSupport, element); + Tuple3 t = graph.syncRequest(new NodeRequest2(canvas, diagram, element)); + IElement e = (IElement)t.c0; + ElementClass ec = (ElementClass)t.c1; + org.simantics.diagram.adapter.ElementFactory ef = (org.simantics.diagram.adapter.ElementFactory)t.c2; if (e == null) return; - + // This is invoked before the element is actually loaded. //System.out.println("NodeRequestProcedure " + e); if (DebugPolicy.DEBUG_NODE_LOAD) @@ -1807,12 +1892,11 @@ public class GraphToDiagramSynchronizer extends AbstractDisposable implements ID addedElements.add(e); addedElementMap.put(element, e); } - } - @Override - public void exception(AsyncReadGraph graph, Throwable throwable) { - error(throwable); + graph.syncRequest(new LoadRequest(canvas, diagram, ef, ec, element), loadListener); + } + }); } else { @@ -1826,7 +1910,7 @@ public class GraphToDiagramSynchronizer extends AbstractDisposable implements ID case REMOVED: { IElement e = getMappedElement(element); if (DebugPolicy.DEBUG_NODE_LOAD) - graph.asyncRequest(new ReadRequest() { + graph.syncRequest(new ReadRequest() { @Override public void run(ReadGraph graph) throws DatabaseException { System.out.println(" EXTERNALLY REMOVED ELEMENT: " @@ -1839,6 +1923,7 @@ public class GraphToDiagramSynchronizer extends AbstractDisposable implements ID } break; } + default: } } } @@ -1872,6 +1957,7 @@ public class GraphToDiagramSynchronizer extends AbstractDisposable implements ID } break; } + default: } } } @@ -1915,6 +2001,7 @@ public class GraphToDiagramSynchronizer extends AbstractDisposable implements ID case REMOVED: { removedConnectionEntities.add(ce); } + default: } } @@ -1931,8 +2018,121 @@ public class GraphToDiagramSynchronizer extends AbstractDisposable implements ID } } } + + class LoadRouteGraphConnectionListener extends DisposableListener { + + final Resource connection; + public IElement lastLoaded; + + public LoadRouteGraphConnectionListener(ListenerSupport support, Resource connection) { + super(support); + this.connection = connection; + } - void processRouteGraphConnections(AsyncReadGraph graph) { + @Override + public String toString() { + return "processRouteGraphConnections " + connection; + } + + public void applyFirst(IElement loaded) { + + Object data = loaded.getHint(ElementHints.KEY_OBJECT); + if (addedElementMap.containsKey(data)) { + // This element was just loaded, in + // which case its hints need to + // uploaded to the real mapped + // element immediately. + IElement mappedElement = getMappedElement(data); + if (DebugPolicy.DEBUG_CONNECTION_LISTENER) + System.out.println("LOADED ADDED ROUTE GRAPH CONNECTION, currently mapped connection: " + mappedElement); + if (mappedElement instanceof Element) { + if (DebugPolicy.DEBUG_CONNECTION_LISTENER) { + System.out.println(" mapped hints: " + mappedElement.getHints()); + System.out.println(" loaded hints: " + loaded.getHints()); + } + updateMappedElement((Element) mappedElement, loaded); + } + } + + } + + @Override + public void execute(IElement loaded) { + + // Invoked when the element has been loaded. + if (DebugPolicy.DEBUG_CONNECTION_LISTENER) + System.out.println("ROUTE GRAPH CONNECTION LoadListener for " + loaded); + + if (loaded == null) { + disposeListener(); + return; + } + + boolean first = lastLoaded == null; + + lastLoaded = loaded; + + /* + * The first invocation is postponed + */ + if(first) { + applyFirst(loaded); + return; + } + + Object data = loaded.getHint(ElementHints.KEY_OBJECT); + + // Logic for disposing listener + if (!previousContent.routeGraphConnectionSet.contains(data)) { + if (DebugPolicy.DEBUG_CONNECTION_LISTENER) + System.out.println("ROUTE GRAPH CONNECTION LoadListener, connection not in current content: " + data + ". Disposing."); + disposeListener(); + return; + } + + if (addedElementMap.containsKey(data)) { + // This element was just loaded, in + // which case its hints need to + // uploaded to the real mapped + // element immediately. + IElement mappedElement = getMappedElement(data); + if (DebugPolicy.DEBUG_CONNECTION_LISTENER) + System.out.println("LOADED ADDED ROUTE GRAPH CONNECTION, currently mapped connection: " + mappedElement); + if (mappedElement instanceof Element) { + if (DebugPolicy.DEBUG_CONNECTION_LISTENER) { + System.out.println(" mapped hints: " + mappedElement.getHints()); + System.out.println(" loaded hints: " + loaded.getHints()); + } + updateMappedElement((Element) mappedElement, loaded); + } + } else { + // This element was already loaded. + // Just schedule an update some time + // in the future. + if (DebugPolicy.DEBUG_CONNECTION_LISTENER) + System.out.println("PREVIOUSLY LOADED ROUTE GRAPH CONNECTION UPDATED, scheduling update into the future: " + connection); + + Set dirtyNodes = new THashSet(4); + IElement mappedElement = getMappedElement(connection); + ConnectionEntity ce = mappedElement.getHint(ElementHints.KEY_CONNECTION_ENTITY); + if (ce != null) { + for (Connection conn : ce.getTerminalConnections(null)) { + Object o = conn.node.getHint(ElementHints.KEY_OBJECT); + if (o != null) { + dirtyNodes.add(o); + if (DebugPolicy.DEBUG_CONNECTION_LISTENER) + System.out.println("Marked connectivity dirty for node: " + conn.node); + } + } + } + + offerGraphUpdate( routeGraphConnectionUpdater(connection, loaded, dirtyNodes) ); + } + } + }; + + + void processRouteGraphConnections(AsyncReadGraph graph) throws DatabaseException { for (Map.Entry entry : changes.routeGraphConnections.entrySet()) { final Resource connection = entry.getKey(); @@ -1943,76 +2143,19 @@ public class GraphToDiagramSynchronizer extends AbstractDisposable implements ID if (mappedElement != null) continue; - Listener loadListener = new DisposableListener(canvasListenerSupport) { - @Override - public String toString() { - return "processRouteGraphConnections " + connection; - } - @Override - public void execute(IElement loaded) { - // Invoked when the element has been loaded. - if (DebugPolicy.DEBUG_CONNECTION_LISTENER) - System.out.println("ROUTE GRAPH CONNECTION LoadListener for " + loaded); - - if (loaded == null) { - disposeListener(); - return; - } + + graph.asyncRequest(new ReadRequest() { - Object data = loaded.getHint(ElementHints.KEY_OBJECT); + @Override + public void run(ReadGraph graph) throws DatabaseException { - // Logic for disposing listener - if (!previousContent.routeGraphConnectionSet.contains(data)) { - if (DebugPolicy.DEBUG_CONNECTION_LISTENER) - System.out.println("ROUTE GRAPH CONNECTION LoadListener, connection not in current content: " + data + ". Disposing."); - disposeListener(); - return; - } + LoadRouteGraphConnectionListener loadListener = new LoadRouteGraphConnectionListener(canvasListenerSupport, connection); - if (addedElementMap.containsKey(data)) { - // This element was just loaded, in - // which case its hints need to - // uploaded to the real mapped - // element immediately. - IElement mappedElement = getMappedElement(data); - if (DebugPolicy.DEBUG_CONNECTION_LISTENER) - System.out.println("LOADED ADDED ROUTE GRAPH CONNECTION, currently mapped connection: " + mappedElement); - if (mappedElement instanceof Element) { - if (DebugPolicy.DEBUG_CONNECTION_LISTENER) { - System.out.println(" mapped hints: " + mappedElement.getHints()); - System.out.println(" loaded hints: " + loaded.getHints()); - } - updateMappedElement((Element) mappedElement, loaded); - } - } else { - // This element was already loaded. - // Just schedule an update some time - // in the future. - if (DebugPolicy.DEBUG_CONNECTION_LISTENER) - System.out.println("PREVIOUSLY LOADED ROUTE GRAPH CONNECTION UPDATED, scheduling update into the future: " + connection); - - Set dirtyNodes = new THashSet(4); - IElement mappedElement = getMappedElement(connection); - ConnectionEntity ce = mappedElement.getHint(ElementHints.KEY_CONNECTION_ENTITY); - if (ce != null) { - for (Connection conn : ce.getTerminalConnections(null)) { - Object o = conn.node.getHint(ElementHints.KEY_OBJECT); - if (o != null) { - dirtyNodes.add(o); - if (DebugPolicy.DEBUG_CONNECTION_LISTENER) - System.out.println("Marked connectivity dirty for node: " + conn.node); - } - } - } + Tuple3 t = graph.syncRequest(new ConnectionRequest2(canvas, diagram, connection, errorHandler)); + IElement e = (IElement)t.c0; + ElementClass ec = (ElementClass)t.c1; + org.simantics.diagram.adapter.ElementFactory ef = (org.simantics.diagram.adapter.ElementFactory)t.c2; - offerGraphUpdate( routeGraphConnectionUpdater(connection, loaded, dirtyNodes) ); - } - } - }; - - graph.asyncRequest(new ConnectionRequest(canvas, diagram, connection, errorHandler, loadListener), new Procedure() { - @Override - public void execute(final IElement e) { if (e == null) return; @@ -2025,12 +2168,14 @@ public class GraphToDiagramSynchronizer extends AbstractDisposable implements ID addedElementMap.put(connection, e); addedRouteGraphConnectionMap.put(connection, e); } + + graph.syncRequest(new LoadRequest(canvas, diagram, ef, ec, connection), loadListener); + } - @Override - public void exception(Throwable throwable) { - error(throwable); - } + }); + + break; } case REMOVED: { @@ -2039,6 +2184,7 @@ public class GraphToDiagramSynchronizer extends AbstractDisposable implements ID removedRouteGraphConnections.add(e); break; } + default: } } } @@ -2052,7 +2198,7 @@ public class GraphToDiagramSynchronizer extends AbstractDisposable implements ID return assertMappedConnection(connection); } - void processBranchPoints(AsyncReadGraph graph) { + void processBranchPoints(AsyncReadGraph graph) throws DatabaseException { for (Map.Entry entry : changes.branchPoints.entrySet()) { final Resource element = entry.getKey(); @@ -2073,10 +2219,11 @@ public class GraphToDiagramSynchronizer extends AbstractDisposable implements ID }); Listener loadListener = new DisposableListener(canvasListenerSupport) { - @Override - public String toString() { - return "processBranchPoints for " + element; - } + + @Override + public String toString() { + return "processBranchPoints for " + element; + } @Override public void execute(IElement loaded) { // Invoked when the element has been loaded. @@ -2118,16 +2265,6 @@ public class GraphToDiagramSynchronizer extends AbstractDisposable implements ID graph.asyncRequest(new NodeRequest(canvas, diagram, element, loadListener), new AsyncProcedure() { @Override public void execute(AsyncReadGraph graph, IElement e) { - if (e != null) { - mapElement(element, e); - synchronized (GraphToDiagramUpdater.this) { - addedBranchPoints.add(e); - addedElementMap.put(element, e); - ConnectionEntityImpl ce = getConnectionEntity(element); - e.setHint(ElementHints.KEY_CONNECTION_ENTITY, ce); - e.setHint(ElementHints.KEY_PARENT_ELEMENT, ce.getConnectionElement()); - } - } } @Override @@ -2141,7 +2278,7 @@ public class GraphToDiagramSynchronizer extends AbstractDisposable implements ID case REMOVED: { IElement e = getMappedElement(element); if (DebugPolicy.DEBUG_NODE_LOAD) - graph.asyncRequest(new ReadRequest() { + graph.syncRequest(new ReadRequest() { @Override public void run(ReadGraph graph) throws DatabaseException { System.out.println(" EXTERNALLY REMOVED BRANCH POINT: " @@ -2154,11 +2291,12 @@ public class GraphToDiagramSynchronizer extends AbstractDisposable implements ID } break; } + default: } } } - void processConnectionSegments(AsyncReadGraph graph) { + void processConnectionSegments(AsyncReadGraph graph) throws DatabaseException { ConnectionSegmentAdapter adapter = connectionSegmentAdapter; for (Map.Entry entry : changes.connectionSegments.entrySet()) { @@ -2178,13 +2316,13 @@ public class GraphToDiagramSynchronizer extends AbstractDisposable implements ID } }); - graph.asyncRequest(new EdgeRequest(canvas, errorHandler, canvasListenerSupport, diagram, adapter, seg), new AsyncProcedure() { + graph.asyncRequest(new EdgeRequest(GraphToDiagramSynchronizer.this, canvas, errorHandler, canvasListenerSupport, diagram, adapter, seg), new AsyncProcedure() { @Override public void execute(AsyncReadGraph graph, IElement e) { if (DebugPolicy.DEBUG_EDGE_LOAD) - System.out.println("ADDED EDGE LOADED: " + e); + System.out.println("ADDED EDGE LOADED: " + e + " " + seg); + if (e != null) { - mapElement(seg, e); synchronized (GraphToDiagramUpdater.this) { addedConnectionSegments.add(e); addedElementMap.put(seg, e); @@ -2218,6 +2356,7 @@ public class GraphToDiagramSynchronizer extends AbstractDisposable implements ID } break; } + default: } } } @@ -2256,13 +2395,15 @@ public class GraphToDiagramSynchronizer extends AbstractDisposable implements ID if (changes.isEmpty()) return; + ITask threadLog = ThreadLogger.task("processNodes"); + // NOTE: This order is important. Object task = Timing.BEGIN("processNodesConnections"); //System.out.println("---- PROCESS NODES & CONNECTIONS BEGIN"); if (!changes.elements.isEmpty()) { graph.syncRequest(new AsyncReadRequest() { @Override - public void run(AsyncReadGraph graph) { + public void run(AsyncReadGraph graph) throws DatabaseException { processNodes(graph); } @Override @@ -2273,13 +2414,21 @@ public class GraphToDiagramSynchronizer extends AbstractDisposable implements ID } //System.out.println("---- PROCESS NODES & CONNECTIONS END"); + threadLog.finish(); + + threadLog = ThreadLogger.task("processConnections"); + processConnections(); + threadLog.finish(); + + threadLog = ThreadLogger.task("processBranchPoints"); + //System.out.println("---- PROCESS BRANCH POINTS BEGIN"); if (!changes.branchPoints.isEmpty()) { graph.syncRequest(new AsyncReadRequest() { @Override - public void run(AsyncReadGraph graph) { + public void run(AsyncReadGraph graph) throws DatabaseException { processBranchPoints(graph); } @Override @@ -2287,17 +2436,23 @@ public class GraphToDiagramSynchronizer extends AbstractDisposable implements ID return "processBranchPoints"; } }); + } //System.out.println("---- PROCESS BRANCH POINTS END"); + threadLog.finish(); + Timing.END(task); + + threadLog = ThreadLogger.task("processConnectionSegments"); + task = Timing.BEGIN("processConnectionSegments"); //System.out.println("---- PROCESS CONNECTION SEGMENTS BEGIN"); if (!changes.connectionSegments.isEmpty()) { graph.syncRequest(new AsyncReadRequest() { @Override - public void run(AsyncReadGraph graph) { + public void run(AsyncReadGraph graph) throws DatabaseException { processConnectionSegments(graph); } @Override @@ -2308,13 +2463,17 @@ public class GraphToDiagramSynchronizer extends AbstractDisposable implements ID } //System.out.println("---- PROCESS CONNECTION SEGMENTS END"); + threadLog.finish(); + Timing.END(task); + threadLog = ThreadLogger.task("processRouteGraphConnections"); + task = Timing.BEGIN("processRouteGraphConnections"); if (!changes.routeGraphConnections.isEmpty()) { graph.syncRequest(new AsyncReadRequest() { @Override - public void run(AsyncReadGraph graph) { + public void run(AsyncReadGraph graph) throws DatabaseException { processRouteGraphConnections(graph); } @Override @@ -2325,6 +2484,8 @@ public class GraphToDiagramSynchronizer extends AbstractDisposable implements ID } Timing.END(task); + threadLog.finish(); + //System.out.println("---- AFTER LOADING"); //for (IElement e : addedElements) // System.out.println(" ADDED ELEMENT: " + e); @@ -2332,7 +2493,12 @@ public class GraphToDiagramSynchronizer extends AbstractDisposable implements ID // System.out.println(" ADDED BRANCH POINTS: " + e); task = Timing.BEGIN("executeDeferredLoaders"); + threadLog = ThreadLogger.task("executeDeferredLoaders"); + executeDeferredLoaders(graph); + + threadLog.finish(); + Timing.END(task); } @@ -2373,17 +2539,15 @@ public class GraphToDiagramSynchronizer extends AbstractDisposable implements ID return "defaultConnectionSegmentAdapter"; } }, new DisposableListener(listenerSupport) { - - @Override - public String toString() { - return "DefaultConnectionSegmentAdapter listener for " + edge; - } - + + @Override + public String toString() { + return "DefaultConnectionSegmentAdapter listener for " + edge; + } + @Override public void execute(IElement loaded) { // Invoked when the element has been loaded. - if (DebugPolicy.DEBUG_EDGE_LISTENER) - System.out.println("EDGE LoadListener for " + loaded); if (loaded == null) { disposeListener(); @@ -2391,6 +2555,10 @@ public class GraphToDiagramSynchronizer extends AbstractDisposable implements ID } Object data = loaded.getHint(ElementHints.KEY_OBJECT); + + if (DebugPolicy.DEBUG_EDGE_LISTENER) + System.out.println("EDGE LoadListener for " + loaded + " " + data); + if (addedElementMap.containsKey(data)) { // This element was just loaded, in // which case its hints need to @@ -2474,13 +2642,18 @@ public class GraphToDiagramSynchronizer extends AbstractDisposable implements ID return; } - // NOTICE: Layer information is loaded from the connection entity resource - // that is shared by all segments of the same connection. - ElementFactoryUtil.loadLayersForElement(graph, layerManager, diagram, edge, info.connection, - new AsyncProcedureAdapter() { + graph.syncRequest(new AsyncReadRequest() { @Override - public void exception(AsyncReadGraph graph, Throwable t) { - error("failed to load layers for connection segment", t); + public void run(AsyncReadGraph graph) { + // NOTICE: Layer information is loaded from the connection entity resource + // that is shared by all segments of the same connection. + ElementFactoryUtil.loadLayersForElement(graph, layerManager, diagram, edge, info.connection, + new AsyncProcedureAdapter() { + @Override + public void exception(AsyncReadGraph graph, Throwable t) { + error("failed to load layers for connection segment", t); + } + }); } }); @@ -2628,8 +2801,11 @@ public class GraphToDiagramSynchronizer extends AbstractDisposable implements ID diagramUpdateLock.lock(); try { - if (DebugPolicy.DEBUG_DIAGRAM_UPDATE) + if (DebugPolicy.DEBUG_DIAGRAM_UPDATE) { System.out.println("In diagramGraphUpdater:"); + System.out.println("-content = " + content); + System.out.println("-previousContent = " + previousContent); + } // Find out what has changed since the last query. Object task = Timing.BEGIN("diagramContentDifference"); @@ -2650,9 +2826,9 @@ public class GraphToDiagramSynchronizer extends AbstractDisposable implements ID GraphToDiagramUpdater updater = new GraphToDiagramUpdater(lastContent, content, changes); GraphToDiagramSynchronizer.this.currentUpdater = updater; try { - updater.process(graph); + updater.process(graph); } finally { - GraphToDiagramSynchronizer.this.currentUpdater = null; + GraphToDiagramSynchronizer.this.currentUpdater = null; } Timing.END(task); @@ -3413,7 +3589,7 @@ public class GraphToDiagramSynchronizer extends AbstractDisposable implements ID Resource resource = ElementUtils.adapt(ec, Resource.class); if (resource == null) { pass = false; - new Exception("Attempted to add an element to the diagram that is not adaptable to Resource: " + e + ", class: " + ec).printStackTrace(); + LOGGER.error("", new Exception("Attempted to add an element to the diagram that is not adaptable to Resource: " + e + ", class: " + ec)); } // Sanity check connection hints