--- /dev/null
+package org.simantics.debug.graphical;\r
+\r
+import gnu.trove.list.array.TDoubleArrayList;\r
+import gnu.trove.map.hash.THashMap;\r
+import gnu.trove.map.hash.TObjectIntHashMap;\r
+\r
+import java.awt.Color;\r
+import java.awt.GradientPaint;\r
+import java.awt.Graphics;\r
+import java.awt.Graphics2D;\r
+import java.awt.RenderingHints;\r
+import java.awt.datatransfer.Transferable;\r
+import java.awt.datatransfer.UnsupportedFlavorException;\r
+import java.awt.dnd.DnDConstants;\r
+import java.awt.dnd.DropTarget;\r
+import java.awt.dnd.DropTargetAdapter;\r
+import java.awt.dnd.DropTargetDropEvent;\r
+import java.awt.event.KeyAdapter;\r
+import java.awt.event.KeyEvent;\r
+import java.awt.event.MouseAdapter;\r
+import java.awt.event.MouseEvent;\r
+import java.awt.event.MouseMotionAdapter;\r
+import java.awt.event.MouseWheelEvent;\r
+import java.awt.event.MouseWheelListener;\r
+import java.awt.geom.AffineTransform;\r
+import java.awt.geom.Point2D;\r
+import java.awt.geom.Rectangle2D;\r
+import java.io.IOException;\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.Random;\r
+\r
+import javax.swing.JPanel;\r
+import javax.swing.SwingUtilities;\r
+\r
+import org.eclipse.core.runtime.IAdaptable;\r
+import org.eclipse.jface.viewers.IStructuredSelection;\r
+import org.simantics.Simantics;\r
+import org.simantics.db.ChangeSet;\r
+import org.simantics.db.ChangeSetIdentifier;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.Session;\r
+import org.simantics.db.Statement;\r
+import org.simantics.db.common.request.ReadRequest;\r
+import org.simantics.db.common.utils.NameUtils;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.service.ManagementSupport;\r
+import org.simantics.debug.graphical.layout.ExtensionLayoutAlgorithm;\r
+import org.simantics.debug.graphical.layout.LayoutGraph;\r
+import org.simantics.debug.graphical.model.Edge;\r
+import org.simantics.debug.graphical.model.LabelContent;\r
+import org.simantics.debug.graphical.model.Node;\r
+import org.simantics.debug.graphical.model.NodeData;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.ui.dnd.LocalObjectTransfer;\r
+import org.simantics.ui.dnd.LocalObjectTransferable;\r
+import org.simantics.ui.selection.AnyResource;\r
+import org.simantics.ui.selection.WorkbenchSelectionElement;\r
+\r
+public class DebuggerCanvas extends JPanel {\r
+\r
+ private static final long serialVersionUID = -718678297301786379L;\r
+ \r
+ ArrayList<Node> nodes = new ArrayList<Node>();\r
+ THashMap<Resource, Node> nodeMap = new THashMap<Resource, Node>(); \r
+ ArrayList<Edge> edges = new ArrayList<Edge>();\r
+ ArrayList<Node> extensionNodes = new ArrayList<Node>();\r
+ ArrayList<Edge> extensionEdges = new ArrayList<Edge>();\r
+ ArrayList<Edge> addedEdges = new ArrayList<Edge>();\r
+ ArrayList<Edge> removedEdges = new ArrayList<Edge>();\r
+ double canvasPosX = 0.0;\r
+ double canvasPosY = 0.0;\r
+ double canvasZoom = 1.0;\r
+ boolean extensionMode = false;\r
+ Random random = new Random();\r
+\r
+ LabelingPreferences labelingPreferences = \r
+ new LabelingPreferences();\r
+ \r
+ @Override\r
+ public void paint(Graphics _g) {\r
+ Graphics2D g = (Graphics2D)_g;\r
+ \r
+ g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, \r
+ RenderingHints.VALUE_ANTIALIAS_ON);\r
+ g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, \r
+ RenderingHints.VALUE_FRACTIONALMETRICS_ON);\r
+ g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, \r
+ RenderingHints.VALUE_TEXT_ANTIALIAS_ON);\r
+ \r
+ g.setPaint(new GradientPaint(0.0f, 0.0f, new Color(200, 200, 200), getWidth(), getHeight(), Color.WHITE));\r
+ g.fill(new Rectangle2D.Double(0, 0, getWidth(), getHeight()));\r
+ g.setColor(Color.BLACK);\r
+ g.setTransform(new AffineTransform(\r
+ canvasZoom, 0.0, \r
+ 0.0, canvasZoom, \r
+ -canvasPosX*canvasZoom, -canvasPosY*canvasZoom));\r
+ for(Node node : nodes)\r
+ node.render(g);\r
+ for(Edge edge : edges)\r
+ edge.render(g);\r
+ if(extensionMode) {\r
+ for(Node node : extensionNodes)\r
+ node.render(g);\r
+ for(Edge edge : extensionEdges)\r
+ edge.render(g);\r
+ }\r
+ g.setColor(Color.GREEN);\r
+ for(Edge edge : addedEdges)\r
+ edge.render(g);\r
+ g.setColor(Color.RED);\r
+ for(Edge edge : removedEdges)\r
+ edge.render(g);\r
+ }\r
+ \r
+ public Node pick(double x, double y) {\r
+ for(Node node : nodes)\r
+ if(node.pick(x, y))\r
+ return node;\r
+ return null;\r
+ }\r
+ \r
+ public Node pickExtension(double x, double y) {\r
+ for(Node node : extensionNodes)\r
+ if(node.pick(x, y))\r
+ return node;\r
+ return null;\r
+ }\r
+ \r
+ {\r
+ addMouseListener(new MouseAdapter() {\r
+ @Override\r
+ public void mousePressed(MouseEvent e) { \r
+ double x = canvasPosX+e.getX()/canvasZoom;\r
+ double y = canvasPosY+e.getY()/canvasZoom;\r
+ if(e.getButton() == MouseEvent.BUTTON1)\r
+ handleMouseLeftPressed(x, y);\r
+ else if(e.getButton() == MouseEvent.BUTTON2)\r
+ handleMouseMiddlePressed(x, y);\r
+ }\r
+ @Override\r
+ public void mouseMoved(MouseEvent e) {\r
+ handleMouseMoved(canvasPosX+e.getX()/canvasZoom, \r
+ canvasPosY+e.getY()/canvasZoom);\r
+ }\r
+ @Override\r
+ public void mouseReleased(MouseEvent e) {\r
+ handleMouseReleased(canvasPosX+e.getX()/canvasZoom, \r
+ canvasPosY+e.getY()/canvasZoom);\r
+ }\r
+ @Override\r
+ public void mouseWheelMoved(MouseWheelEvent e) {\r
+ double x = canvasPosX+e.getX()/canvasZoom;\r
+ double y = canvasPosY+e.getY()/canvasZoom;\r
+ handleMouseWheelMoved(x, y, e.getWheelRotation());\r
+ }\r
+ });\r
+ addMouseMotionListener(new MouseMotionAdapter() {\r
+ @Override\r
+ public void mouseDragged(MouseEvent e) {\r
+ handleMouseMoved(canvasPosX+e.getX()/canvasZoom, \r
+ canvasPosY+e.getY()/canvasZoom);\r
+ } \r
+ });\r
+ addMouseWheelListener(new MouseWheelListener() { \r
+ @Override\r
+ public void mouseWheelMoved(MouseWheelEvent e) {\r
+ double x = canvasPosX+e.getX()/canvasZoom;\r
+ double y = canvasPosY+e.getY()/canvasZoom;\r
+ handleMouseWheelMoved(x, y, e.getWheelRotation());\r
+ }\r
+ });\r
+ addKeyListener(new UsefulKeyAdapter(new KeyAdapter() {\r
+ @Override\r
+ public void keyPressed(KeyEvent e) {\r
+ DebuggerCanvas.this.keyPressed(e);\r
+ }\r
+ @Override\r
+ public void keyReleased(KeyEvent e) {\r
+ DebuggerCanvas.this.keyReleased(e);\r
+ }\r
+ }));\r
+ DropTarget dropTarget = new DropTarget(this, new DropTargetAdapter() {\r
+ @Override\r
+ public void drop(DropTargetDropEvent dtde) {\r
+ try {\r
+ Transferable transferable = dtde.getTransferable();\r
+ \r
+ if( transferable.isDataFlavorSupported( \r
+ LocalObjectTransferable.FLAVOR ) ) {\r
+ dtde.acceptDrop( DnDConstants.ACTION_MOVE );\r
+ \r
+ transferable.getTransferData(LocalObjectTransferable.FLAVOR );\r
+ Object obj = LocalObjectTransfer.getTransfer().getObject();\r
+ double x = canvasPosX+dtde.getLocation().getX()/canvasZoom;\r
+ double y = canvasPosY+dtde.getLocation().getY()/canvasZoom;\r
+ handleDrop(x, y, obj);\r
+ \r
+ dtde.getDropTargetContext().dropComplete( true );\r
+ }\r
+ else {\r
+ dtde.rejectDrop();\r
+ }\r
+ } catch( IOException exception ) {\r
+ exception.printStackTrace();\r
+ dtde.rejectDrop();\r
+ } catch( UnsupportedFlavorException ufException ) {\r
+ ufException.printStackTrace();\r
+ dtde.rejectDrop();\r
+ }\r
+ } \r
+ });\r
+ } \r
+ \r
+ public void keyPressed(KeyEvent e) {\r
+ switch(e.getKeyCode()) {\r
+ case KeyEvent.VK_1:\r
+ zoomToFit();\r
+ break;\r
+ case KeyEvent.VK_L:\r
+ layoutGraph();\r
+ break;\r
+ case KeyEvent.VK_CONTROL:\r
+ if(!extensionMode) {\r
+ initializeExtension();\r
+ extensionMode = true;\r
+ repaint();\r
+ }\r
+ break;\r
+ case KeyEvent.VK_C:\r
+ findPreviousChangeset();\r
+ break;\r
+ case KeyEvent.VK_DELETE:\r
+ if (!extensionMode && dragging != null) {\r
+ nodes.remove(dragging);\r
+ scheduleUpdate();\r
+ repaint();\r
+ }\r
+ break;\r
+ }\r
+ }\r
+ \r
+ public void keyReleased(KeyEvent e) {\r
+ if(e.getKeyCode() == KeyEvent.VK_CONTROL) {\r
+ extensionMode = false;\r
+ scheduleUpdate();\r
+ repaint();\r
+ }\r
+ }\r
+\r
+ private static Resource extractResource(Object obj) {\r
+ System.out.println("- " + obj.getClass().getName());\r
+ if(obj instanceof WorkbenchSelectionElement) {\r
+ Resource resource = ((WorkbenchSelectionElement)obj).getContent(new AnyResource(Simantics.getSession()));\r
+ if(resource != null)\r
+ return resource;\r
+ }\r
+ if(obj instanceof IAdaptable) {\r
+ Resource resource = (Resource)((IAdaptable)obj).getAdapter(Resource.class);\r
+ if(resource != null)\r
+ return resource;\r
+ }\r
+ return null;\r
+ }\r
+ \r
+ private void handleDrop(double x, double y, Object obj) {\r
+ //System.out.println(obj.getClass().getName());\r
+ if(obj instanceof IStructuredSelection) {\r
+ for(Object element : ((IStructuredSelection)obj).toArray()) {\r
+ Resource resource = extractResource(element);\r
+ if(resource != null && !nodeMap.containsKey(resource)) {\r
+ addResource(x, y, resource); \r
+ repaint();\r
+ }\r
+ }\r
+ }\r
+ } \r
+ \r
+ private Node addResource(double x, double y, Resource resource) {\r
+ Node a = new Node(new NodeData(resource));\r
+ a.setPos(x, y);\r
+ scheduleUpdate();\r
+ nodes.add(a);\r
+ return a;\r
+ }\r
+\r
+ private void scheduleUpdate() {\r
+ Simantics.getSession().asyncRequest(new ReadRequest() { \r
+ @Override\r
+ public void run(ReadGraph graph) throws DatabaseException { \r
+ updateNodes(graph);\r
+ updateEdges(graph);\r
+ SwingUtilities.invokeLater(new Runnable() {\r
+ @Override\r
+ public void run() {\r
+ repaint();\r
+ }\r
+ \r
+ });\r
+ } \r
+ }); \r
+ }\r
+ \r
+ public void layoutGraph() {\r
+ ArrayList<Edge> allEdges = new ArrayList<Edge>(\r
+ edges.size() + addedEdges.size() + removedEdges.size()\r
+ );\r
+ allEdges.addAll(edges);\r
+ allEdges.addAll(addedEdges);\r
+ allEdges.addAll(removedEdges);\r
+ LayoutGraph.layout(\r
+ nodes.toArray(new Node[nodes.size()]), \r
+ allEdges.toArray(new Edge[edges.size()]));\r
+ repaint(); \r
+ }\r
+ \r
+ private void updateNodes(ReadGraph graph) throws DatabaseException {\r
+ for(Node node : nodes) {\r
+ node.getData().updateData(graph, labelingPreferences);\r
+ node.setContent(new LabelContent(node.getData().getLabels()));\r
+ }\r
+ nodeMap.clear();\r
+ for(Node node : nodes) {\r
+ NodeData data = node.getData();\r
+ nodeMap.put(data.getResource(), node);\r
+ }\r
+ }\r
+ \r
+ private void updateEdges(ReadGraph graph) throws DatabaseException {\r
+ ArrayList<Edge> edges = new ArrayList<Edge>();\r
+ for(Node node : nodes) {\r
+ NodeData data = node.getData();\r
+ Resource subject = data.getResource();\r
+ ArrayList<Statement> filteredStatements = new ArrayList<Statement>(data.getStatements().size());\r
+ for(Statement stat : data.getStatements()) {\r
+ Resource object = stat.getObject();\r
+ Node node2 = nodeMap.get(object);\r
+ if(node2 != null) {\r
+ if(object.getResourceId() > subject.getResourceId() ||\r
+ graph.getPossibleInverse(stat.getPredicate()) == null) {\r
+ edges.add(createEdge(graph, stat, node, node2));\r
+ }\r
+ }\r
+ else\r
+ filteredStatements.add(stat);\r
+ }\r
+ data.setStatements(filteredStatements);\r
+ }\r
+ this.edges = edges;\r
+ this.addedEdges = filterEdgesWithoutNodes( this.addedEdges );\r
+ this.removedEdges = filterEdgesWithoutNodes( this.removedEdges );\r
+ }\r
+\r
+ private ArrayList<Edge> filterEdgesWithoutNodes(Collection<Edge> edges) {\r
+ ArrayList<Edge> result = new ArrayList<Edge>(edges.size());\r
+ for (Edge e : edges) {\r
+ if (!nodeMap.containsValue(e.getA()) || !nodeMap.containsValue(e.getB()))\r
+ continue;\r
+ result.add(e);\r
+ }\r
+ return result;\r
+ }\r
+\r
+ private Edge createEdge(ReadGraph graph, Statement stat, Node n1, Node n2) throws DatabaseException {\r
+ Resource predicate = stat.getPredicate();\r
+ Resource inverse = graph.getPossibleInverse(predicate); \r
+ if(inverse != null) {\r
+ Layer0 L0 = Layer0.getInstance(graph);\r
+ if(graph.hasStatement(predicate, L0.PartOf, inverse)\r
+ || predicate.equals(L0.PartOf)\r
+ || predicate.equals(L0.SuperrelationOf)\r
+ || predicate.equals(L0.SupertypeOf)) {\r
+ predicate = inverse;\r
+ Node temp = n1;\r
+ n1 = n2;\r
+ n2 = temp;\r
+ }\r
+ }\r
+ Edge edge = new Edge(n1, n2);\r
+ edge.setContent(new LabelContent(new String[] {\r
+ NameUtils.getSafeName(graph, predicate)}));\r
+ return edge;\r
+ }\r
+ \r
+ Node dragging = null;\r
+ double dragDX, dragDY;\r
+ private void handleMouseLeftPressed(double x, double y) {\r
+ Node node;\r
+ if(extensionMode) {\r
+ node = pickExtension(x, y);\r
+ if(node != null) {\r
+ nodes.add(node);\r
+ extensionNodes.remove(node);\r
+ }\r
+ }\r
+ else\r
+ node = pick(x, y);\r
+ if(node != null) {\r
+ dragDX = x - node.getX();\r
+ dragDY = y - node.getY();\r
+ dragging = node;\r
+ }\r
+ }\r
+ \r
+ Point2D panningStartMouse;\r
+ private void handleMouseMiddlePressed(double x, double y) {\r
+ panningStartMouse = new Point2D.Double(x, y);\r
+ }\r
+ \r
+ private void handleMouseMoved(double x, double y) {\r
+ if(dragging != null) {\r
+ dragging.setPos(x-dragDX, y-dragDY);\r
+ repaint();\r
+ }\r
+ if(panningStartMouse != null) {\r
+ canvasPosX -= x - panningStartMouse.getX();\r
+ canvasPosY -= y - panningStartMouse.getY();\r
+ repaint();\r
+ }\r
+ }\r
+ \r
+ private void handleMouseWheelMoved(double x, double y, double amount) {\r
+ double s = Math.exp(-0.2*amount);\r
+ canvasZoom *= s;\r
+ canvasPosX = x - (x-canvasPosX)/s;\r
+ canvasPosY = y - (y-canvasPosY)/s;\r
+ repaint();\r
+ }\r
+\r
+ private void handleMouseReleased(double x, double y) {\r
+ dragging = null;\r
+ panningStartMouse = null;\r
+ }\r
+ \r
+ public void zoomToFit() {\r
+ if(!nodes.isEmpty()) {\r
+ double minX = Double.POSITIVE_INFINITY;\r
+ double minY = Double.POSITIVE_INFINITY;\r
+ double maxX = Double.NEGATIVE_INFINITY;\r
+ double maxY = Double.NEGATIVE_INFINITY;\r
+ System.out.println("(" + minX + "," + minY + ") - (" + maxX + "," + maxY + ")");\r
+ for(Node node : nodes) {\r
+ minX = Math.min(minX, node.getMinX());\r
+ minY = Math.min(minY, node.getMinY());\r
+ maxX = Math.max(maxX, node.getMaxX());\r
+ maxY = Math.max(maxY, node.getMaxY());\r
+ } \r
+ canvasZoom = Math.min(getWidth()/(maxX-minX), getHeight()/(maxY-minY));\r
+ canvasZoom *= 0.9;\r
+ canvasPosX = minX - 0.5 * (getWidth()/canvasZoom - maxX+minX);\r
+ canvasPosY = minY - 0.5 * (getHeight()/canvasZoom - maxY+minY);\r
+ repaint();\r
+ }\r
+ }\r
+\r
+ THashMap<Resource, Node> extensionNodeMap = new THashMap<Resource, Node>();\r
+ public void initializeExtension() {\r
+ extensionNodes.clear();\r
+ extensionEdges.clear();\r
+ try {\r
+ Simantics.getSession().syncRequest(new ReadRequest() {\r
+ @Override\r
+ public void run(ReadGraph graph) throws DatabaseException {\r
+ THashMap<Resource, Node> oldExtensionNodeMap = DebuggerCanvas.this.extensionNodeMap;\r
+ THashMap<Resource, Node> extensionNodeMap = new THashMap<Resource, Node>();\r
+ for(Node node : nodes) {\r
+ for(Statement stat : node.getData().getStatements()) {\r
+ Resource object = stat.getObject();\r
+ Node node2 = extensionNodeMap.get(object);\r
+ if(node2 == null) {\r
+ node2 = oldExtensionNodeMap.get(object);\r
+ if(node2 == null) {\r
+ node2 = new Node(new NodeData(object));\r
+ double angle = random.nextDouble() * Math.PI * 2.0;\r
+ double dx = Math.cos(angle);\r
+ double dy = Math.sin(angle);\r
+ double len = 150.0;\r
+ node2.setPos(node.getX() + dx*len, node.getY() + dy*len);\r
+ }\r
+ node2.getData().updateData(graph, labelingPreferences); \r
+ node2.setContent(new LabelContent(node2.getData().getLabels()));\r
+ extensionNodeMap.put(object, node2);\r
+ extensionNodes.add(node2);\r
+ }\r
+ extensionEdges.add(createEdge(graph, stat, node, node2));\r
+ }\r
+ }\r
+ DebuggerCanvas.this.extensionNodeMap = extensionNodeMap;\r
+ layoutExtension();\r
+ } \r
+ });\r
+ } catch (DatabaseException e) {\r
+ e.printStackTrace();\r
+ }\r
+ }\r
+\r
+ private void layoutExtension() { \r
+ TObjectIntHashMap<Node> extensionNodeIds = new TObjectIntHashMap<Node>();\r
+ for(int i=0;i<extensionNodes.size();++i)\r
+ extensionNodeIds.put(extensionNodes.get(i), i);\r
+ \r
+ double[][] neighbors = new double[extensionNodes.size()][];\r
+ {\r
+ TDoubleArrayList[] neighborLists = new TDoubleArrayList[neighbors.length]; \r
+ for(int i=0;i<neighborLists.length;++i)\r
+ neighborLists[i] = new TDoubleArrayList();\r
+ for(Edge edge : extensionEdges) {\r
+ int id;\r
+ Node node;\r
+ if(extensionNodeIds.containsKey(edge.getA())) {\r
+ id = extensionNodeIds.get(edge.getA());\r
+ node = edge.getB();\r
+ }\r
+ else {\r
+ id = extensionNodeIds.get(edge.getB());\r
+ node = edge.getA();\r
+ }\r
+ TDoubleArrayList list = neighborLists[id];\r
+ list.add(node.getX());\r
+ list.add(node.getY());\r
+ } \r
+ for(int i=0;i<neighborLists.length;++i) {\r
+ neighbors[i] = neighborLists[i].toArray();\r
+ }\r
+ }\r
+ \r
+ double[] fixedRepulsiveX = new double[nodes.size()];\r
+ double[] fixedRepulsiveY = new double[nodes.size()];\r
+ for(int i=0;i<nodes.size();++i) {\r
+ Node node = nodes.get(i);\r
+ fixedRepulsiveX[i] = node.getX();\r
+ fixedRepulsiveY[i] = node.getY();\r
+ }\r
+ ExtensionLayoutAlgorithm algo = \r
+ new ExtensionLayoutAlgorithm(neighbors, fixedRepulsiveX, fixedRepulsiveY);\r
+ double[] posX = algo.getPosX();\r
+ double[] posY = algo.getPosY();\r
+ for(int i=0;i<extensionNodes.size();++i) {\r
+ posX[i] = extensionNodes.get(i).getX();\r
+ posY[i] = extensionNodes.get(i).getY();\r
+ } \r
+ algo.optimize();\r
+ for(int i=0;i<extensionNodes.size();++i) {\r
+ extensionNodes.get(i).setPos(posX[i], posY[i]);\r
+ } \r
+ } \r
+ \r
+ private Node getNode(Resource resource) {\r
+ Node node = nodeMap.get(resource);\r
+ if(node == null) {\r
+ node = addResource(random.nextDouble()*200.0-100.0, \r
+ random.nextDouble()*200.0-100.0, \r
+ resource);\r
+ nodeMap.put(resource, node);\r
+ }\r
+ return node;\r
+ }\r
+ \r
+ public void findPreviousChangeset() {\r
+ try {\r
+ Session session = Simantics.getSession();\r
+ final ManagementSupport ms = session.getService(ManagementSupport.class);\r
+ final long lastId = ms.getHeadRevisionId();\r
+ final long firstId = getOpId(ms, lastId);\r
+ //System.out.println(firstId + "-" + lastId);\r
+ addedEdges.clear();\r
+ removedEdges.clear(); \r
+ session.asyncRequest(new ReadRequest() {\r
+ @Override\r
+ public void run(ReadGraph graph) throws DatabaseException {\r
+ final Collection<ChangeSet> css = \r
+ ms.fetchChangeSets(graph, firstId, lastId);\r
+ Layer0 L0 = Layer0.getInstance(graph);\r
+ for(ChangeSet cs : css) {\r
+ for(ChangeSet.StatementChange stat : cs.changedStatements()) {\r
+ Resource predicate = stat.getPredicate();\r
+ if(predicate.equals(L0.InstanceOf) ||\r
+ predicate.equals(L0.HasName) ||\r
+ predicate.equals(L0.NameOf))\r
+ continue;\r
+ Edge edge = createEdge(graph, stat, \r
+ getNode(stat.getSubject()),\r
+ getNode(stat.getObject()));\r
+ if(stat.isClaim())\r
+ addedEdges.add(edge);\r
+ else\r
+ removedEdges.add(edge);\r
+ }\r
+ } \r
+ scheduleUpdate();\r
+ } \r
+ }); \r
+ } catch(DatabaseException e) {\r
+ e.printStackTrace();\r
+ }\r
+ } \r
+ \r
+ private static long getOpId(ManagementSupport ms, long revisionId) throws DatabaseException {\r
+ Collection<ChangeSetIdentifier> ids = ms.getChangeSetIdentifiers(revisionId, revisionId);\r
+ ChangeSetIdentifier curId = ids.iterator().next();\r
+ byte[] opIdData = curId.getMetadata().get("opid");\r
+ System.out.println(new String(opIdData));\r
+ long opId = Long.parseLong(new String(opIdData));\r
+ if(opId == 0)\r
+ opId = revisionId;\r
+ return opId;\r
+ }\r
+\r
+}\r