-/*******************************************************************************\r
- * Copyright (c) 2011 Association for Decentralized Information Management in\r
- * Industry THTH ry.\r
- * All rights reserved. This program and the accompanying materials\r
- * are made available under the terms of the Eclipse Public License v1.0\r
- * which accompanies this distribution, and is available at\r
- * http://www.eclipse.org/legal/epl-v10.html\r
- *\r
- * Contributors:\r
- * VTT Technical Research Centre of Finland - initial API and implementation\r
- *******************************************************************************/\r
-package org.simantics.diagram.connection.delta;\r
-\r
-import gnu.trove.map.hash.THashMap;\r
-\r
-import java.io.Serializable;\r
-import java.util.ArrayList;\r
-import java.util.Collection;\r
-\r
-import org.simantics.diagram.connection.RouteGraph;\r
-import org.simantics.diagram.connection.RouteLine;\r
-import org.simantics.diagram.connection.RouteLink;\r
-import org.simantics.diagram.connection.RoutePoint;\r
-import org.simantics.diagram.connection.RouteTerminal;\r
-\r
-/**\r
- * Calculates the delta between two route graphs. Only\r
- * persistent lines are used in the computation. Lines,\r
- * links and terminals are matched by their data attribute.\r
- * If data is null, the node is not matched any node in\r
- * the other node. Two lines differ, if they have a \r
- * different orientation or position. Two terminals differ,\r
- * if they are linked to different route lines ({@link RouteTerminal#getLine()}). \r
- * @author Hannu Niemistö\r
- */\r
-public class RouteGraphDelta implements Serializable {\r
-\r
- private static final long serialVersionUID = 5011201407852172263L;\r
-\r
- ArrayList<RouteLine> linesOnlyInLeft = new ArrayList<RouteLine>();\r
- ArrayList<RouteLine> linesOnlyInRight = new ArrayList<RouteLine>();\r
- ArrayList<RouteLinePair> linesThatDiffer = new ArrayList<RouteLinePair>();\r
- ArrayList<RouteLink> linksOnlyInLeft = new ArrayList<RouteLink>();\r
- ArrayList<RouteLink> linksOnlyInRight = new ArrayList<RouteLink>();\r
- ArrayList<RouteTerminal> terminalsOnlyInLeft = new ArrayList<RouteTerminal>();\r
- ArrayList<RouteTerminal> terminalsOnlyInRight = new ArrayList<RouteTerminal>();\r
- ArrayList<RouteTerminalPair> terminalsThatDiffer = new ArrayList<RouteTerminalPair>();\r
- \r
- public static class RouteLinePair implements Serializable {\r
- private static final long serialVersionUID = 382349562756381086L;\r
-\r
- public final RouteLine left;\r
- public final RouteLine right;\r
-\r
- public RouteLinePair(RouteLine left, RouteLine right) {\r
- this.left = left;\r
- this.right = right;\r
- }\r
- }\r
- \r
- public static class RouteTerminalPair implements Serializable {\r
- private static final long serialVersionUID = 5286896101190626944L;\r
-\r
- public final RouteTerminal left;\r
- public final RouteTerminal right;\r
-\r
- public RouteTerminalPair(RouteTerminal left, RouteTerminal right) {\r
- this.left = left;\r
- this.right = right;\r
- }\r
- }\r
- \r
- public Collection<RouteLine> getLinesOnlyInLeft() {\r
- return linesOnlyInLeft;\r
- }\r
- \r
- public Collection<RouteLine> getLinesOnlyInRight() {\r
- return linesOnlyInRight;\r
- }\r
- \r
- public ArrayList<RouteLinePair> getLinesThatDiffer() {\r
- return linesThatDiffer;\r
- }\r
- \r
- public Collection<RouteLink> getLinksOnlyInLeft() {\r
- return linksOnlyInLeft;\r
- }\r
- \r
- public Collection<RouteLink> getLinksOnlyInRight() {\r
- return linksOnlyInRight;\r
- }\r
- \r
- public ArrayList<RouteTerminal> getTerminalsOnlyInLeft() {\r
- return terminalsOnlyInLeft;\r
- }\r
- \r
- public ArrayList<RouteTerminal> getTerminalsOnlyInRight() {\r
- return terminalsOnlyInRight;\r
- }\r
- \r
- public ArrayList<RouteTerminalPair> getTerminalsThatDiffer() {\r
- return terminalsThatDiffer;\r
- }\r
- \r
- private static class KeyPair {\r
- final Object a;\r
- final Object b;\r
- \r
- public KeyPair(Object a, Object b) {\r
- this.a = a;\r
- this.b = b;\r
- }\r
- \r
- @Override\r
- public int hashCode() {\r
- return 31*a.hashCode() + b.hashCode();\r
- }\r
- \r
- @Override\r
- public boolean equals(Object obj) {\r
- if(obj == this)\r
- return true;\r
- if(obj == null || obj.getClass() != KeyPair.class)\r
- return false;\r
- KeyPair other = (KeyPair)obj;\r
- return a.equals(other.a) && b.equals(other.b);\r
- }\r
- }\r
- \r
- public RouteGraphDelta(RouteGraph left, RouteGraph right) {\r
- {\r
- THashMap<Object, RouteLine> lineMap = \r
- new THashMap<Object, RouteLine>();\r
- for(RouteLine line : left.getLines()) {\r
- Object data = line.getData();\r
- if(data == null)\r
- linesOnlyInLeft.add(line);\r
- else\r
- lineMap.put(data, line);\r
- }\r
- for(RouteLine line : right.getLines()) {\r
- Object data = line.getData();\r
- if(data == null)\r
- linesOnlyInRight.add(line);\r
- else {\r
- RouteLine other =lineMap.remove(data);\r
- if(other == null)\r
- linesOnlyInRight.add(line);\r
- else if(line.getPosition() != other.getPosition() ||\r
- line.isHorizontal() != other.isHorizontal())\r
- linesThatDiffer.add(new RouteLinePair(other, line));\r
- }\r
- }\r
- linesOnlyInLeft.addAll(lineMap.values());\r
- }\r
- {\r
- THashMap<KeyPair, RouteLink> linkMap = \r
- new THashMap<KeyPair, RouteLink>();\r
- for(RouteLine a : left.getLines()) {\r
- for(RoutePoint point : a.getPoints()) {\r
- if(!(point instanceof RouteLink))\r
- continue;\r
- RouteLink link = (RouteLink)point;\r
- RouteLine b = link.getB();\r
- if(a == link.getA() && !b.isTransient()) {\r
- Object dataA = a.getData();\r
- Object dataB = b.getData();\r
- if(dataA == null || dataB == null)\r
- linksOnlyInLeft.add(link);\r
- else\r
- linkMap.put(new KeyPair(dataA, dataB), link);\r
- }\r
- }\r
- }\r
- for(RouteLine a : right.getLines()) {\r
- for(RoutePoint point : a.getPoints()) {\r
- if(!(point instanceof RouteLink))\r
- continue;\r
- RouteLink link = (RouteLink)point;\r
- RouteLine b = link.getB();\r
- if(a == link.getA() && !b.isTransient()) {\r
- Object dataA = a.getData();\r
- Object dataB = b.getData();\r
- if(dataA == null || dataB == null\r
- || (linkMap.remove(new KeyPair(dataA, dataB)) == null\r
- && linkMap.remove(new KeyPair(dataB, dataA)) == null))\r
- linksOnlyInRight.add(link);\r
- }\r
- }\r
- }\r
- linksOnlyInLeft.addAll(linkMap.values());\r
- } \r
- {\r
- THashMap<Object, RouteTerminal> terminalMap = \r
- new THashMap<Object, RouteTerminal>();\r
- for(RouteTerminal terminal : left.getTerminals()) {\r
- Object data = terminal.getData();\r
- if(data == null)\r
- terminalsOnlyInLeft.add(terminal);\r
- else\r
- terminalMap.put(data, terminal);\r
- }\r
- for(RouteTerminal terminal : right.getTerminals()) {\r
- Object data = terminal.getData();\r
- if(data == null)\r
- terminalsOnlyInRight.add(terminal);\r
- else {\r
- RouteTerminal other = terminalMap.remove(data);\r
- if(other == null)\r
- terminalsOnlyInRight.add(terminal);\r
- else if(!terminalsEqual(other, terminal))\r
- terminalsThatDiffer.add(new RouteTerminalPair(other, terminal));\r
- }\r
- }\r
- terminalsOnlyInLeft.addAll(terminalMap.values());\r
- }\r
- }\r
- \r
- private static boolean terminalsEqual(RouteTerminal left, RouteTerminal right) {\r
- if(left == null)\r
- return right == null;\r
- if(right == null)\r
- return false;\r
- RouteLine leftLine = left.getLine();\r
- RouteLine rightLine = right.getLine();\r
- if(leftLine == null)\r
- return rightLine == null;\r
- if(rightLine == null)\r
- return false;\r
- Object leftData = leftLine.getData();\r
- Object rightData = rightLine.getData();\r
- if(leftData == null || rightData == null) \r
- return false; // if both lines have null data, they are still not equal\r
- return leftData.equals(rightData);\r
- }\r
- \r
- public void print() {\r
- System.out.println("=== Delta ===");\r
- if(!linesOnlyInLeft.isEmpty() || !linksOnlyInLeft.isEmpty()\r
- || !terminalsOnlyInLeft.isEmpty()) {\r
- System.out.println("Only in the left route graph:");\r
- for(RouteLine line : linesOnlyInLeft)\r
- System.out.println(" line " + line.getData());\r
- for(RouteLink link : linksOnlyInLeft)\r
- System.out.println(" <" + link.getA().getData() + "," + link.getB().getData() + ">");\r
- for(RouteTerminal terminal : terminalsOnlyInLeft)\r
- System.out.println(" terminal " + terminal.getData());\r
- }\r
- if(!linesOnlyInRight.isEmpty() || !linksOnlyInRight.isEmpty()\r
- || !terminalsOnlyInRight.isEmpty()) {\r
- System.out.println("Only in the right route graph:");\r
- for(RouteLine line : linesOnlyInRight)\r
- System.out.println(" line " + line.getData());\r
- for(RouteLink link : linksOnlyInRight)\r
- System.out.println(" <" + link.getA().getData() + "," + link.getB().getData() + ">");\r
- for(RouteTerminal terminal : terminalsOnlyInRight)\r
- System.out.println(" terminal " + terminal.getData());\r
- }\r
- if(!linesThatDiffer.isEmpty() || !terminalsThatDiffer.isEmpty()) {\r
- System.out.println("Differing:");\r
- for(RouteLinePair pair : linesThatDiffer)\r
- System.out.println(" " + pair.left.getData() + " <> " + pair.right.getData());\r
- for(RouteTerminalPair pair : terminalsThatDiffer)\r
- System.out.println(" " + pair.left.getData() + " (" + pair.left.getX() + "," + pair.left.getY() + ") <> " + pair.right.getData() + " (" + pair.right.getX() + "," + pair.right.getY() + ")");\r
- }\r
- }\r
-\r
- public boolean isEmpty() {\r
- return\r
- linesOnlyInLeft.isEmpty() && linksOnlyInLeft.isEmpty() && terminalsOnlyInLeft.isEmpty() &&\r
- linesOnlyInRight.isEmpty() && linksOnlyInRight.isEmpty() && terminalsOnlyInRight.isEmpty() &&\r
- linesThatDiffer.isEmpty() && terminalsThatDiffer.isEmpty();\r
- }\r
-\r
-}\r
+/*******************************************************************************
+ * Copyright (c) 2011 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * VTT Technical Research Centre of Finland - initial API and implementation
+ *******************************************************************************/
+package org.simantics.diagram.connection.delta;
+
+import gnu.trove.map.hash.THashMap;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collection;
+
+import org.simantics.diagram.connection.RouteGraph;
+import org.simantics.diagram.connection.RouteLine;
+import org.simantics.diagram.connection.RouteLink;
+import org.simantics.diagram.connection.RoutePoint;
+import org.simantics.diagram.connection.RouteTerminal;
+
+/**
+ * Calculates the delta between two route graphs. Only
+ * persistent lines are used in the computation. Lines,
+ * links and terminals are matched by their data attribute.
+ * If data is null, the node is not matched any node in
+ * the other node. Two lines differ, if they have a
+ * different orientation or position. Two terminals differ,
+ * if they are linked to different route lines ({@link RouteTerminal#getLine()}).
+ * @author Hannu Niemistö
+ */
+public class RouteGraphDelta implements Serializable {
+
+ private static final long serialVersionUID = 5011201407852172263L;
+
+ ArrayList<RouteLine> linesOnlyInLeft = new ArrayList<RouteLine>();
+ ArrayList<RouteLine> linesOnlyInRight = new ArrayList<RouteLine>();
+ ArrayList<RouteLinePair> linesThatDiffer = new ArrayList<RouteLinePair>();
+ ArrayList<RouteLink> linksOnlyInLeft = new ArrayList<RouteLink>();
+ ArrayList<RouteLink> linksOnlyInRight = new ArrayList<RouteLink>();
+ ArrayList<RouteTerminal> terminalsOnlyInLeft = new ArrayList<RouteTerminal>();
+ ArrayList<RouteTerminal> terminalsOnlyInRight = new ArrayList<RouteTerminal>();
+ ArrayList<RouteTerminalPair> terminalsThatDiffer = new ArrayList<RouteTerminalPair>();
+
+ public static class RouteLinePair implements Serializable {
+ private static final long serialVersionUID = 382349562756381086L;
+
+ public final RouteLine left;
+ public final RouteLine right;
+
+ public RouteLinePair(RouteLine left, RouteLine right) {
+ this.left = left;
+ this.right = right;
+ }
+ }
+
+ public static class RouteTerminalPair implements Serializable {
+ private static final long serialVersionUID = 5286896101190626944L;
+
+ public final RouteTerminal left;
+ public final RouteTerminal right;
+
+ public RouteTerminalPair(RouteTerminal left, RouteTerminal right) {
+ this.left = left;
+ this.right = right;
+ }
+ }
+
+ public Collection<RouteLine> getLinesOnlyInLeft() {
+ return linesOnlyInLeft;
+ }
+
+ public Collection<RouteLine> getLinesOnlyInRight() {
+ return linesOnlyInRight;
+ }
+
+ public ArrayList<RouteLinePair> getLinesThatDiffer() {
+ return linesThatDiffer;
+ }
+
+ public Collection<RouteLink> getLinksOnlyInLeft() {
+ return linksOnlyInLeft;
+ }
+
+ public Collection<RouteLink> getLinksOnlyInRight() {
+ return linksOnlyInRight;
+ }
+
+ public ArrayList<RouteTerminal> getTerminalsOnlyInLeft() {
+ return terminalsOnlyInLeft;
+ }
+
+ public ArrayList<RouteTerminal> getTerminalsOnlyInRight() {
+ return terminalsOnlyInRight;
+ }
+
+ public ArrayList<RouteTerminalPair> getTerminalsThatDiffer() {
+ return terminalsThatDiffer;
+ }
+
+ private static class KeyPair {
+ final Object a;
+ final Object b;
+
+ public KeyPair(Object a, Object b) {
+ this.a = a;
+ this.b = b;
+ }
+
+ @Override
+ public int hashCode() {
+ return 31*a.hashCode() + b.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if(obj == this)
+ return true;
+ if(obj == null || obj.getClass() != KeyPair.class)
+ return false;
+ KeyPair other = (KeyPair)obj;
+ return a.equals(other.a) && b.equals(other.b);
+ }
+ }
+
+ public RouteGraphDelta(RouteGraph left, RouteGraph right) {
+ {
+ THashMap<Object, RouteLine> lineMap =
+ new THashMap<Object, RouteLine>();
+ for(RouteLine line : left.getLines()) {
+ Object data = line.getData();
+ if(data == null)
+ linesOnlyInLeft.add(line);
+ else
+ lineMap.put(data, line);
+ }
+ for(RouteLine line : right.getLines()) {
+ Object data = line.getData();
+ if(data == null)
+ linesOnlyInRight.add(line);
+ else {
+ RouteLine other =lineMap.remove(data);
+ if(other == null)
+ linesOnlyInRight.add(line);
+ else if(line.getPosition() != other.getPosition() ||
+ line.isHorizontal() != other.isHorizontal())
+ linesThatDiffer.add(new RouteLinePair(other, line));
+ }
+ }
+ linesOnlyInLeft.addAll(lineMap.values());
+ }
+ {
+ THashMap<KeyPair, RouteLink> linkMap =
+ new THashMap<KeyPair, RouteLink>();
+ for(RouteLine a : left.getLines()) {
+ for(RoutePoint point : a.getPoints()) {
+ if(!(point instanceof RouteLink))
+ continue;
+ RouteLink link = (RouteLink)point;
+ RouteLine b = link.getB();
+ if(a == link.getA() && !b.isTransient()) {
+ Object dataA = a.getData();
+ Object dataB = b.getData();
+ if(dataA == null || dataB == null)
+ linksOnlyInLeft.add(link);
+ else
+ linkMap.put(new KeyPair(dataA, dataB), link);
+ }
+ }
+ }
+ for(RouteLine a : right.getLines()) {
+ for(RoutePoint point : a.getPoints()) {
+ if(!(point instanceof RouteLink))
+ continue;
+ RouteLink link = (RouteLink)point;
+ RouteLine b = link.getB();
+ if(a == link.getA() && !b.isTransient()) {
+ Object dataA = a.getData();
+ Object dataB = b.getData();
+ if(dataA == null || dataB == null
+ || (linkMap.remove(new KeyPair(dataA, dataB)) == null
+ && linkMap.remove(new KeyPair(dataB, dataA)) == null))
+ linksOnlyInRight.add(link);
+ }
+ }
+ }
+ linksOnlyInLeft.addAll(linkMap.values());
+ }
+ {
+ THashMap<Object, RouteTerminal> terminalMap =
+ new THashMap<Object, RouteTerminal>();
+ for(RouteTerminal terminal : left.getTerminals()) {
+ Object data = terminal.getData();
+ if(data == null)
+ terminalsOnlyInLeft.add(terminal);
+ else
+ terminalMap.put(data, terminal);
+ }
+ for(RouteTerminal terminal : right.getTerminals()) {
+ Object data = terminal.getData();
+ if(data == null)
+ terminalsOnlyInRight.add(terminal);
+ else {
+ RouteTerminal other = terminalMap.remove(data);
+ if(other == null)
+ terminalsOnlyInRight.add(terminal);
+ else if(!terminalsEqual(other, terminal))
+ terminalsThatDiffer.add(new RouteTerminalPair(other, terminal));
+ }
+ }
+ terminalsOnlyInLeft.addAll(terminalMap.values());
+ }
+ }
+
+ private static boolean terminalsEqual(RouteTerminal left, RouteTerminal right) {
+ if(left == null)
+ return right == null;
+ if(right == null)
+ return false;
+ RouteLine leftLine = left.getLine();
+ RouteLine rightLine = right.getLine();
+ if(leftLine == null)
+ return rightLine == null;
+ if(rightLine == null)
+ return false;
+ Object leftData = leftLine.getData();
+ Object rightData = rightLine.getData();
+ if(leftData == null || rightData == null)
+ return false; // if both lines have null data, they are still not equal
+ return leftData.equals(rightData);
+ }
+
+ public void print() {
+ System.out.println("=== Delta ===");
+ if(!linesOnlyInLeft.isEmpty() || !linksOnlyInLeft.isEmpty()
+ || !terminalsOnlyInLeft.isEmpty()) {
+ System.out.println("Only in the left route graph:");
+ for(RouteLine line : linesOnlyInLeft)
+ System.out.println(" line " + line.getData());
+ for(RouteLink link : linksOnlyInLeft)
+ System.out.println(" <" + link.getA().getData() + "," + link.getB().getData() + ">");
+ for(RouteTerminal terminal : terminalsOnlyInLeft)
+ System.out.println(" terminal " + terminal.getData());
+ }
+ if(!linesOnlyInRight.isEmpty() || !linksOnlyInRight.isEmpty()
+ || !terminalsOnlyInRight.isEmpty()) {
+ System.out.println("Only in the right route graph:");
+ for(RouteLine line : linesOnlyInRight)
+ System.out.println(" line " + line.getData());
+ for(RouteLink link : linksOnlyInRight)
+ System.out.println(" <" + link.getA().getData() + "," + link.getB().getData() + ">");
+ for(RouteTerminal terminal : terminalsOnlyInRight)
+ System.out.println(" terminal " + terminal.getData());
+ }
+ if(!linesThatDiffer.isEmpty() || !terminalsThatDiffer.isEmpty()) {
+ System.out.println("Differing:");
+ for(RouteLinePair pair : linesThatDiffer)
+ System.out.println(" " + pair.left.getData() + " <> " + pair.right.getData());
+ for(RouteTerminalPair pair : terminalsThatDiffer)
+ System.out.println(" " + pair.left.getData() + " (" + pair.left.getX() + "," + pair.left.getY() + ") <> " + pair.right.getData() + " (" + pair.right.getX() + "," + pair.right.getY() + ")");
+ }
+ }
+
+ public boolean isEmpty() {
+ return
+ linesOnlyInLeft.isEmpty() && linksOnlyInLeft.isEmpty() && terminalsOnlyInLeft.isEmpty() &&
+ linesOnlyInRight.isEmpty() && linksOnlyInRight.isEmpty() && terminalsOnlyInRight.isEmpty() &&
+ linesThatDiffer.isEmpty() && terminalsThatDiffer.isEmpty();
+ }
+
+}