X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;ds=sidebyside;f=bundles%2Forg.simantics.diagram%2Fsrc%2Forg%2Fsimantics%2Fdiagram%2Fflag%2FRouteGraphConnectionSplitter.java;h=3f1076b5df48e70047cd4dae8d9531bd494c9d0d;hb=ad5b573b5db77a3e00429fc24e2de855bce7f48a;hp=c23fe1d878b1945447642f2ee566e7ad663eb253;hpb=969bd23cab98a79ca9101af33334000879fb60c5;p=simantics%2Fplatform.git
diff --git a/bundles/org.simantics.diagram/src/org/simantics/diagram/flag/RouteGraphConnectionSplitter.java b/bundles/org.simantics.diagram/src/org/simantics/diagram/flag/RouteGraphConnectionSplitter.java
index c23fe1d87..3f1076b5d 100644
--- a/bundles/org.simantics.diagram/src/org/simantics/diagram/flag/RouteGraphConnectionSplitter.java
+++ b/bundles/org.simantics.diagram/src/org/simantics/diagram/flag/RouteGraphConnectionSplitter.java
@@ -1,430 +1,427 @@
-package org.simantics.diagram.flag;
-
-import gnu.trove.map.hash.TObjectIntHashMap;
-
-import java.awt.geom.AffineTransform;
-import java.awt.geom.Point2D;
-import java.util.ArrayList;
-import java.util.Collection;
-
-import javax.vecmath.Tuple2d;
-import javax.vecmath.Vector2d;
-
-import org.simantics.databoard.Bindings;
-import org.simantics.db.ReadGraph;
-import org.simantics.db.Resource;
-import org.simantics.db.Statement;
-import org.simantics.db.WriteGraph;
-import org.simantics.db.common.request.PossibleTypedParent;
-import org.simantics.db.common.utils.NameUtils;
-import org.simantics.db.common.utils.OrderedSetUtils;
-import org.simantics.db.exception.DatabaseException;
-import org.simantics.db.service.SerialisationSupport;
-import org.simantics.diagram.adapter.RouteGraphUtils;
-import org.simantics.diagram.connection.RouteGraph;
-import org.simantics.diagram.connection.RouteLine;
-import org.simantics.diagram.connection.RouteNode;
-import org.simantics.diagram.connection.RoutePoint;
-import org.simantics.diagram.connection.RouteTerminal;
-import org.simantics.diagram.connection.splitting.SplittedRouteGraph;
-import org.simantics.diagram.content.ConnectionUtil;
-import org.simantics.diagram.stubs.DiagramResource;
-import org.simantics.diagram.synchronization.graph.AddElement;
-import org.simantics.diagram.synchronization.graph.DiagramGraphUtil;
-import org.simantics.diagram.synchronization.graph.RouteGraphModification;
-import org.simantics.g2d.elementclass.FlagClass;
-import org.simantics.layer0.Layer0;
-import org.simantics.modeling.ModelingResources;
-import org.simantics.structural.stubs.StructuralResource2;
-
-/**
- * A class that handles splitting a route graph connection in two with diagram
- * local flags.
- *
- * The connection splitting process consists of the following steps:
- *
- * - Disconnect the end points of the selected connection edge segment (SEG).
- * An end point is either :DIA.BranchPoint or (terminal) DIA:Connector. This
- * operation will always split a valid connection into two separate parts.
- * - Calculate the contents of the two separated connection parts (branch
- * points and connectors) and decide which part to leave with the existing
- * connection (=P1) and which part to move into a new connection (=P2). The
- * current strategy is to move the parts that
- * do not contain output terminal connectors into a new connection.
- * This works well with diagram to composite mappings where output terminals
- * generate modules behind connections.
- * - Create new connection C' with the same type and STR.HasConnectionType as
- * the original connection C.
- * - Copy connection routing settings from C to C'.
- * - Move P2 into C'.
- * - Create two new flag elements into the same diagram, set their type and
- * interpolate a proper transformation for both along the existing connection
- * line.
- * - Connect the new flags to begin(SEG) and end(SEG) connectors.
- * - Join the flags together.
- *
- *
- * @author Tuukka Lehtonen
- * @author Hannu Niemistö
- */
-public class RouteGraphConnectionSplitter {
-
- private final static boolean DEBUG = false;
-
- Layer0 L0;
- DiagramResource DIA;
- StructuralResource2 STR;
- ModelingResources MOD;
- SerialisationSupport ss;
-
- public RouteGraphConnectionSplitter(ReadGraph graph) {
- this.L0 = Layer0.getInstance(graph);
- this.DIA = DiagramResource.getInstance(graph);
- this.STR = StructuralResource2.getInstance(graph);
- this.MOD = ModelingResources.getInstance(graph);
- this.ss = graph.getService(SerialisationSupport.class);
- }
-
- public void split(WriteGraph graph, Resource connection, RouteGraph rg, Point2D splitCanvasPos) throws DatabaseException {
- // Create modification writer
- RouteGraphModification modis = new RouteGraphModification(ss, rg);
- TObjectIntHashMap idMap = modis.getIdMap();
-
- // Find the edge to disconnect in the graph.
- // Bisect the nearest route line.
- RouteLine line = SplittedRouteGraph.findNearestLine(rg, splitCanvasPos);
- if (DEBUG)
- rg.print();
- if (line == null)
- return;
- if (DEBUG) {
- line.print(System.out);
- for (RoutePoint rp : line.getPoints())
- System.out.println("RP: " + rp.getX() + ", " + rp.getY());
- }
-
- // Get exact intersection point on the line
- double isectX = splitCanvasPos.getX();
- double isectY = splitCanvasPos.getY();
- SplittedRouteGraph srg;
- if (line.isHorizontal()) {
- isectY = line.getPosition();
- srg = rg.splitGraph(line, isectX);
- }
- else {
- isectX = line.getPosition();
- srg = rg.splitGraph(line, isectY);
- }
- if (DEBUG)
- System.out.println(srg);
-
- // Disconnect
- if(rg.isSimpleConnection()) {
- RouteNode na = srg.terminals1.iterator().next();
- RouteNode nb = srg.terminals2.iterator().next();
- Resource a = ss.getResource((Long)na.getData());
- Resource b = ss.getResource((Long)nb.getData());
- graph.deny(a, DIA.AreConnected, b);
- modis.addModi(new RouteGraphModification.RemoveLink(
- idMap.get(na), idMap.get(nb)
- ));
- }
- else if(srg.splitLine.isTransient()) {
- RouteTerminal terminal = srg.splitLine.getTerminal();
- Resource connector = ss.getResource((Long)terminal.getData());
- graph.deny(connector, DIA.AreConnected);
- modis.addModi(new RouteGraphModification.RemoveLink(
- idMap.get(terminal), idMap.get(terminal.getLine())
- ));
- }
- else {
- graph.deny(ss.getResource((Long)srg.splitLine.getData()));
- // TODO remove links
- modis.addModi(new RouteGraphModification.RemoveLine(
- idMap.get(srg.splitLine)
- ));
- }
-
- ArrayList interfaceNodes1Resources = new ArrayList(srg.interfaceNodes1.size());
- for(RouteNode n : srg.interfaceNodes1)
- interfaceNodes1Resources.add(ss.getResource((Long)n.getData()));
- ArrayList interfaceNodes2Resources = new ArrayList(srg.interfaceNodes2.size());
- for(RouteNode n : srg.interfaceNodes2)
- interfaceNodes2Resources.add(ss.getResource((Long)n.getData()));
-
- ArrayList lines2Resources = new ArrayList(srg.lines2.size());
- for(RouteLine n : srg.lines2)
- lines2Resources.add(ss.getResource((Long)n.getData()));
-
- ArrayList terminals1Resources = new ArrayList(srg.terminals1.size());
- for(RouteTerminal n : srg.terminals1)
- terminals1Resources.add(ss.getResource((Long)n.getData()));
- ArrayList terminals2Resources = new ArrayList(srg.terminals2.size());
- for(RouteTerminal n : srg.terminals2)
- terminals2Resources.add(ss.getResource((Long)n.getData()));
- doSplit(graph, connection,
- interfaceNodes1Resources,
- interfaceNodes2Resources,
- lines2Resources,
- terminals1Resources,
- terminals2Resources,
- line.isHorizontal(),
- isectX, isectY);
- modis.addModi(new RouteGraphModification.Split(
- modis.toIds(interfaceNodes1Resources),
- modis.toIds(interfaceNodes2Resources),
- modis.toIds(lines2Resources),
- modis.toIds(terminals1Resources),
- modis.toIds(terminals2Resources),
- line.isHorizontal(),
- isectX, isectY
- ));
-
- }
-
- public void doSplit(WriteGraph graph,
- Resource connection,
- ArrayList interfaceNodes1Resources,
- ArrayList interfaceNodes2Resources,
- ArrayList lines2Resources,
- ArrayList terminals1Resources,
- ArrayList terminals2Resources,
- boolean isHorizontal,
- double isectX, double isectY) throws DatabaseException {
-
- if (DEBUG) {
- System.out.println("doSplit:");
- System.out.println(NameUtils.getSafeName(graph, connection, true));
- for (Resource i : interfaceNodes1Resources)
- System.out.println("i1: " + NameUtils.getSafeName(graph, i, true));
- for (Resource i : interfaceNodes2Resources)
- System.out.println("i2: " + NameUtils.getSafeName(graph, i, true));
- for (Resource l : lines2Resources)
- System.out.println("l2r: " + NameUtils.getSafeName(graph, l, true));
- for (Resource t : terminals1Resources)
- System.out.println("t1: " + NameUtils.getSafeName(graph, t, true));
- for (Resource t : terminals2Resources)
- System.out.println("t2: " + NameUtils.getSafeName(graph, t, true));
- System.out.println("is horizontal: " + isHorizontal);
- System.out.println("@(x,y): " + isectX + ", " + isectY);
- }
-
- ConnectionUtil cu = new ConnectionUtil(graph);
- Resource diagram = OrderedSetUtils.getSingleOwnerList(graph, connection, DIA.Diagram);
-
- Resource connectionType = graph.getSingleType(connection, DIA.Connection);
- Resource hasConnectionType = graph.getPossibleObject(connection, STR.HasConnectionType);
- Resource newConnection = cu.newConnection(diagram, connectionType);
- if (hasConnectionType != null)
- graph.claim(newConnection, STR.HasConnectionType, null, hasConnectionType);
-
- // Give running name to connection increment the counter attached to the diagram.
- AddElement.claimFreshElementName(graph, diagram, newConnection);
-
- // WORKAROUND for mapping problems:
- // If any terminal of the split connection contains a flag, make sure their STR.Joins relations are all removed
- // to give mapping a chance to fix them properly.
- removeFlagJoins(graph, cu, connection, terminals1Resources);
- removeFlagJoins(graph, cu, connection, terminals2Resources);
-
- // Move route nodes to correct connections
- for(Resource rn : lines2Resources) {
- // TODO: use same predicate that was removed
- graph.denyStatement(connection, DIA.HasInteriorRouteNode, rn);
- graph.claim(newConnection, DIA.HasInteriorRouteNode, rn);
- }
- for(Resource rn : terminals2Resources) {
- Statement stat = graph.getSingleStatement(rn, DIA.IsConnectorOf);
- Resource predicate = stat.getPredicate();
- graph.deny(rn, predicate);
- graph.claim(rn, predicate, newConnection);
- }
-
- // 1 = output, 2 = input
- FlagClass.Type type1, type2;
-
- FlagLabelingScheme scheme = DiagramFlagPreferences.getActiveFlagLabelingScheme(graph);
- String commonLabel = scheme.generateLabel(graph, diagram);
-
- // Create flags and connect both disconnected ends to them.
- Vector2d pos1, pos2;
- double theta;
- double flagDist = 3.0;
- if(isHorizontal) {
- theta = 0.0;
- pos1 = new Vector2d(isectX-flagDist, isectY);
- pos2 = new Vector2d(isectX+flagDist, isectY);
- }
- else {
- theta = Math.PI*0.5;
- pos1 = new Vector2d(isectX, isectY-flagDist);
- pos2 = new Vector2d(isectX, isectY+flagDist);
- }
-
- // Chooses flag directions
- {
- @SuppressWarnings("unused")
- int inputs1 = 0, outputs1 = 0;
- for(Resource connector : terminals1Resources) {
- if(graph.hasStatement(connector, DIA.IsHeadConnectorOf))
- ++inputs1;
- else
- ++outputs1;
- }
- @SuppressWarnings("unused")
- int inputs2 = 0, outputs2 = 0;
- for(Resource connector : terminals2Resources) {
- if(graph.hasStatement(connector, DIA.IsHeadConnectorOf))
- ++inputs2;
- else
- ++outputs2;
- }
-
- if(outputs1 == 0) {
- type1 = FlagClass.Type.In;
- type2 = FlagClass.Type.Out;
- theta += Math.PI;
- }
- else {
- type1 = FlagClass.Type.Out;
- type2 = FlagClass.Type.In;
- }
- if (DEBUG) {
- System.out.println("inputs1: " + inputs1);
- System.out.println("outputs1: " + outputs1);
- System.out.println("=> type1: " + type1);
- System.out.println("inputs2: " + inputs2);
- System.out.println("outputs2: " + outputs2);
- System.out.println("=> type2: " + type2);
- }
- }
- Resource flag1 = createFlag(graph, diagram, getFlagTransform(pos1, theta), type1, commonLabel);
- Resource flag2 = createFlag(graph, diagram, getFlagTransform(pos2, theta), type2, commonLabel);
- if (DEBUG) {
- System.out.println("FLAG1: " + NameUtils.getSafeName(graph, flag1, true));
- System.out.println("FLAG2: " + NameUtils.getSafeName(graph, flag2, true));
- }
-
-// System.out.println("conn1: " + NameUtils.getSafeLabel(graph, type1 == FlagClass.Type.In ? DIA.HasPlainConnector : DIA.HasArrowConnector));
-// System.out.println("conn2: " + NameUtils.getSafeLabel(graph, type2 == FlagClass.Type.In ? DIA.HasPlainConnector : DIA.HasArrowConnector));
- Resource flagConnector1 = cu.newConnector(connection,
- type1 == FlagClass.Type.In ? DIA.HasPlainConnector : DIA.HasArrowConnector);
- Resource flagConnector2 = cu.newConnector(newConnection,
- type2 == FlagClass.Type.In ? DIA.HasPlainConnector : DIA.HasArrowConnector);
- graph.claim(flag1, DIA.Flag_ConnectionPoint, flagConnector1);
- graph.claim(flag2, DIA.Flag_ConnectionPoint, flagConnector2);
-
- double position = isHorizontal ? isectY : isectX;
- connectFlag(graph, isHorizontal, position, connection, flagConnector1,
- interfaceNodes1Resources);
- connectFlag(graph, isHorizontal, position, newConnection, flagConnector2,
- interfaceNodes2Resources);
-
- FlagUtil.join(graph, flag1, flag2);
-
- // Move mapping relations to new connection if necessary
- if(type1 == FlagClass.Type.In) {
- moveStatements(graph, connection, newConnection, MOD.ElementToComponent);
- moveStatements(graph, connection, newConnection, MOD.DiagramConnectionToConnection);
- moveStatements(graph, connection, newConnection, MOD.DiagramConnectionToConnectionSpecial);
- FlagUtil.fixBindsStatements(graph, graph.getPossibleObject(newConnection, MOD.DiagramConnectionToConnection));
- }
- else
- FlagUtil.fixBindsStatements(graph, graph.getPossibleObject(connection, MOD.DiagramConnectionToConnection));
- }
-
- /**
- * A workaround for problems with mapping not removing the necessary
- * STR.Joins relations from flags after a split.
- *
- * @param graph
- * @param cu
- * @param connection
- * @param connectors
- * @throws DatabaseException
- */
- private void removeFlagJoins(WriteGraph graph, ConnectionUtil cu, Resource connection, ArrayList connectors) throws DatabaseException {
- for (Resource connector : connectors) {
- Resource e = cu.getConnectedComponent(connection, connector);
- if (graph.isInstanceOf(e, DIA.Flag)) {
- Resource diagram = graph.syncRequest(new PossibleTypedParent(e, DIA.Diagram));
- if (diagram == null)
- continue;
- for (Resource join : graph.getObjects(e, DIA.FlagIsJoinedBy)) {
- Collection joinsComposites = graph.getObjects(join, STR.JoinsComposite);
- if (joinsComposites.size() == 1) {
- // Only remove joins that are internal to a diagram.
- graph.deny(join, STR.Joins);
- } else if (joinsComposites.size() == 2) {
- // Only remove the joins relations that refer to
- // connections that are part of the same diagram.
- for (Resource joins : graph.getObjects(join, STR.Joins)) {
- Resource diagramConnection = graph.getPossibleObject(joins, MOD.ConnectionToDiagramConnection);
- if (diagramConnection == null)
- continue;
- Resource partOfDiagram = graph.syncRequest(new PossibleTypedParent(diagramConnection, DIA.Diagram));
- if (diagram.equals(partOfDiagram)) {
- graph.deny(join, STR.Joins, joins);
- }
- }
- }
- }
- }
- }
- }
-
- private static void moveStatements(WriteGraph graph, Resource from, Resource to, Resource relation) throws DatabaseException {
- if(from.equals(to))
- return;
- for(Statement stat : graph.getStatements(from, relation))
- if(stat.getSubject().equals(from))
- graph.claim(to, stat.getPredicate(), stat.getObject());
- graph.deny(from, relation);
- }
-
- private void connectFlag(WriteGraph graph, boolean isHorizontal, double position, Resource connection, Resource flagConnector, Collection interfaceNodes)
- throws DatabaseException {
- if(interfaceNodes.size() > 1) {
- Resource routeLine = graph.newResource();
- graph.claim(routeLine, L0.InstanceOf, DIA.RouteLine);
- graph.claim(connection, DIA.HasInteriorRouteNode, routeLine);
- graph.claimLiteral(routeLine, DIA.IsHorizontal, isHorizontal);
- graph.claimLiteral(routeLine, DIA.HasPosition, position);
- graph.claim(routeLine, DIA.AreConnected, flagConnector);
- flagConnector = routeLine;
- }
- for(Resource rn : interfaceNodes) {
- graph.claim(flagConnector, DIA.AreConnected, rn);
- }
- }
-
- private AffineTransform getFlagTransform(Tuple2d pos, double theta) {
- AffineTransform at = AffineTransform.getTranslateInstance(pos.x, pos.y);
- at.rotate(theta);
- return at;
- }
-
- private Resource createFlag(WriteGraph graph, Resource diagram, AffineTransform tr, FlagClass.Type type, String label) throws DatabaseException {
- DiagramResource DIA = DiagramResource.getInstance(graph);
-
- Resource flag = graph.newResource();
- graph.claim(flag, L0.InstanceOf, null, DIA.Flag);
- AddElement.claimFreshElementName(graph, diagram, flag);
- graph.claim(flag, L0.PartOf, L0.ConsistsOf, diagram);
-
- DiagramGraphUtil.setTransform(graph, flag, tr);
- if (type != null)
- FlagUtil.setFlagType(graph, flag, type);
-
- if (label != null)
- graph.claimLiteral(flag, L0.HasLabel, DIA.FlagLabel, label, Bindings.STRING);
-
- OrderedSetUtils.add(graph, diagram, flag);
- return flag;
- }
-
- public static void splitConnection(WriteGraph graph, Resource connection, double x, double y) throws DatabaseException {
- RouteGraph rg = RouteGraphUtils.load(graph, null, connection);
- new RouteGraphConnectionSplitter(graph).split(graph, connection, rg, new Point2D.Double(x, y));
- }
+package org.simantics.diagram.flag;
+
+import gnu.trove.map.hash.TObjectIntHashMap;
+
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Point2D;
+import java.util.ArrayList;
+import java.util.Collection;
+
+import org.simantics.databoard.Bindings;
+import org.simantics.db.ReadGraph;
+import org.simantics.db.Resource;
+import org.simantics.db.Statement;
+import org.simantics.db.WriteGraph;
+import org.simantics.db.common.request.PossibleTypedParent;
+import org.simantics.db.common.utils.NameUtils;
+import org.simantics.db.common.utils.OrderedSetUtils;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.service.SerialisationSupport;
+import org.simantics.diagram.adapter.RouteGraphUtils;
+import org.simantics.diagram.connection.RouteGraph;
+import org.simantics.diagram.connection.RouteLine;
+import org.simantics.diagram.connection.RouteNode;
+import org.simantics.diagram.connection.RoutePoint;
+import org.simantics.diagram.connection.RouteTerminal;
+import org.simantics.diagram.connection.splitting.SplittedRouteGraph;
+import org.simantics.diagram.content.ConnectionUtil;
+import org.simantics.diagram.stubs.DiagramResource;
+import org.simantics.diagram.synchronization.graph.AddElement;
+import org.simantics.diagram.synchronization.graph.DiagramGraphUtil;
+import org.simantics.diagram.synchronization.graph.RouteGraphModification;
+import org.simantics.g2d.elementclass.FlagClass;
+import org.simantics.layer0.Layer0;
+import org.simantics.modeling.ModelingResources;
+import org.simantics.structural.stubs.StructuralResource2;
+
+/**
+ * A class that handles splitting a route graph connection in two with diagram
+ * local flags.
+ *
+ * The connection splitting process consists of the following steps:
+ *
+ * - Disconnect the end points of the selected connection edge segment (SEG).
+ * An end point is either :DIA.BranchPoint or (terminal) DIA:Connector. This
+ * operation will always split a valid connection into two separate parts.
+ * - Calculate the contents of the two separated connection parts (branch
+ * points and connectors) and decide which part to leave with the existing
+ * connection (=P1) and which part to move into a new connection (=P2). The
+ * current strategy is to move the parts that
+ * do not contain output terminal connectors into a new connection.
+ * This works well with diagram to composite mappings where output terminals
+ * generate modules behind connections.
+ * - Create new connection C' with the same type and STR.HasConnectionType as
+ * the original connection C.
+ * - Copy connection routing settings from C to C'.
+ * - Move P2 into C'.
+ * - Create two new flag elements into the same diagram, set their type and
+ * interpolate a proper transformation for both along the existing connection
+ * line.
+ * - Connect the new flags to begin(SEG) and end(SEG) connectors.
+ * - Join the flags together.
+ *
+ *
+ * @author Tuukka Lehtonen
+ * @author Hannu Niemistö
+ */
+public class RouteGraphConnectionSplitter {
+
+ private final static boolean DEBUG = false;
+
+ Layer0 L0;
+ DiagramResource DIA;
+ StructuralResource2 STR;
+ ModelingResources MOD;
+ SerialisationSupport ss;
+
+ public RouteGraphConnectionSplitter(ReadGraph graph) {
+ this.L0 = Layer0.getInstance(graph);
+ this.DIA = DiagramResource.getInstance(graph);
+ this.STR = StructuralResource2.getInstance(graph);
+ this.MOD = ModelingResources.getInstance(graph);
+ this.ss = graph.getService(SerialisationSupport.class);
+ }
+
+ public void split(WriteGraph graph, Resource connection, RouteGraph rg, Point2D splitCanvasPos) throws DatabaseException {
+ // Create modification writer
+ RouteGraphModification modis = new RouteGraphModification(ss, rg);
+ TObjectIntHashMap idMap = modis.getIdMap();
+
+ // Find the edge to disconnect in the graph.
+ // Bisect the nearest route line.
+ RouteLine line = SplittedRouteGraph.findNearestLine(rg, splitCanvasPos);
+ if (DEBUG)
+ rg.print();
+ if (line == null)
+ return;
+ if (DEBUG) {
+ line.print(System.out);
+ for (RoutePoint rp : line.getPoints())
+ System.out.println("RP: " + rp.getX() + ", " + rp.getY());
+ }
+
+ // Get exact intersection point on the line
+ double isectX = splitCanvasPos.getX();
+ double isectY = splitCanvasPos.getY();
+ SplittedRouteGraph srg;
+ if (line.isHorizontal()) {
+ isectY = line.getPosition();
+ srg = rg.splitGraph(line, isectX);
+ }
+ else {
+ isectX = line.getPosition();
+ srg = rg.splitGraph(line, isectY);
+ }
+ if (DEBUG)
+ System.out.println(srg);
+
+ // Disconnect
+ if(rg.isSimpleConnection()) {
+ RouteNode na = srg.terminals1.iterator().next();
+ RouteNode nb = srg.terminals2.iterator().next();
+ Resource a = ss.getResource((Long)na.getData());
+ Resource b = ss.getResource((Long)nb.getData());
+ graph.deny(a, DIA.AreConnected, b);
+ modis.addModi(new RouteGraphModification.RemoveLink(
+ idMap.get(na), idMap.get(nb)
+ ));
+ }
+ else if(srg.splitLine.isTransient()) {
+ RouteTerminal terminal = srg.splitLine.getTerminal();
+ Resource connector = ss.getResource((Long)terminal.getData());
+ graph.deny(connector, DIA.AreConnected);
+ modis.addModi(new RouteGraphModification.RemoveLink(
+ idMap.get(terminal), idMap.get(terminal.getLine())
+ ));
+ }
+ else {
+ graph.deny(ss.getResource((Long)srg.splitLine.getData()));
+ // TODO remove links
+ modis.addModi(new RouteGraphModification.RemoveLine(
+ idMap.get(srg.splitLine)
+ ));
+ }
+
+ ArrayList interfaceNodes1Resources = new ArrayList(srg.interfaceNodes1.size());
+ for(RouteNode n : srg.interfaceNodes1)
+ interfaceNodes1Resources.add(ss.getResource((Long)n.getData()));
+ ArrayList interfaceNodes2Resources = new ArrayList(srg.interfaceNodes2.size());
+ for(RouteNode n : srg.interfaceNodes2)
+ interfaceNodes2Resources.add(ss.getResource((Long)n.getData()));
+
+ ArrayList lines2Resources = new ArrayList(srg.lines2.size());
+ for(RouteLine n : srg.lines2)
+ lines2Resources.add(ss.getResource((Long)n.getData()));
+
+ ArrayList terminals1Resources = new ArrayList(srg.terminals1.size());
+ for(RouteTerminal n : srg.terminals1)
+ terminals1Resources.add(ss.getResource((Long)n.getData()));
+ ArrayList terminals2Resources = new ArrayList(srg.terminals2.size());
+ for(RouteTerminal n : srg.terminals2)
+ terminals2Resources.add(ss.getResource((Long)n.getData()));
+ doSplit(graph, connection,
+ interfaceNodes1Resources,
+ interfaceNodes2Resources,
+ lines2Resources,
+ terminals1Resources,
+ terminals2Resources,
+ line.isHorizontal(),
+ isectX, isectY);
+ modis.addModi(new RouteGraphModification.Split(
+ modis.toIds(interfaceNodes1Resources),
+ modis.toIds(interfaceNodes2Resources),
+ modis.toIds(lines2Resources),
+ modis.toIds(terminals1Resources),
+ modis.toIds(terminals2Resources),
+ line.isHorizontal(),
+ isectX, isectY
+ ));
+
+ }
+
+ public void doSplit(WriteGraph graph,
+ Resource connection,
+ ArrayList interfaceNodes1Resources,
+ ArrayList interfaceNodes2Resources,
+ ArrayList lines2Resources,
+ ArrayList terminals1Resources,
+ ArrayList terminals2Resources,
+ boolean isHorizontal,
+ double isectX, double isectY) throws DatabaseException {
+
+ if (DEBUG) {
+ System.out.println("doSplit:");
+ System.out.println(NameUtils.getSafeName(graph, connection, true));
+ for (Resource i : interfaceNodes1Resources)
+ System.out.println("i1: " + NameUtils.getSafeName(graph, i, true));
+ for (Resource i : interfaceNodes2Resources)
+ System.out.println("i2: " + NameUtils.getSafeName(graph, i, true));
+ for (Resource l : lines2Resources)
+ System.out.println("l2r: " + NameUtils.getSafeName(graph, l, true));
+ for (Resource t : terminals1Resources)
+ System.out.println("t1: " + NameUtils.getSafeName(graph, t, true));
+ for (Resource t : terminals2Resources)
+ System.out.println("t2: " + NameUtils.getSafeName(graph, t, true));
+ System.out.println("is horizontal: " + isHorizontal);
+ System.out.println("@(x,y): " + isectX + ", " + isectY);
+ }
+
+ ConnectionUtil cu = new ConnectionUtil(graph);
+ Resource diagram = OrderedSetUtils.getSingleOwnerList(graph, connection, DIA.Diagram);
+
+ Resource connectionType = graph.getSingleType(connection, DIA.Connection);
+ Resource hasConnectionType = graph.getPossibleObject(connection, STR.HasConnectionType);
+ Resource newConnection = cu.newConnection(diagram, connectionType);
+ if (hasConnectionType != null)
+ graph.claim(newConnection, STR.HasConnectionType, null, hasConnectionType);
+
+ // Give running name to connection increment the counter attached to the diagram.
+ AddElement.claimFreshElementName(graph, diagram, newConnection);
+
+ // WORKAROUND for mapping problems:
+ // If any terminal of the split connection contains a flag, make sure their STR.Joins relations are all removed
+ // to give mapping a chance to fix them properly.
+ removeFlagJoins(graph, cu, connection, terminals1Resources);
+ removeFlagJoins(graph, cu, connection, terminals2Resources);
+
+ // Move route nodes to correct connections
+ for(Resource rn : lines2Resources) {
+ // TODO: use same predicate that was removed
+ graph.denyStatement(connection, DIA.HasInteriorRouteNode, rn);
+ graph.claim(newConnection, DIA.HasInteriorRouteNode, rn);
+ }
+ for(Resource rn : terminals2Resources) {
+ Statement stat = graph.getSingleStatement(rn, DIA.IsConnectorOf);
+ Resource predicate = stat.getPredicate();
+ graph.deny(rn, predicate);
+ graph.claim(rn, predicate, newConnection);
+ }
+
+ // 1 = output, 2 = input
+ FlagClass.Type type1, type2;
+
+ FlagLabelingScheme scheme = DiagramFlagPreferences.getActiveFlagLabelingScheme(graph);
+ String commonLabel = scheme.generateLabel(graph, diagram);
+
+ // Create flags and connect both disconnected ends to them.
+ Point2D pos1, pos2;
+ double theta;
+ double flagDist = 3.0;
+ if(isHorizontal) {
+ theta = 0.0;
+ pos1 = new Point2D.Double(isectX-flagDist, isectY);
+ pos2 = new Point2D.Double(isectX+flagDist, isectY);
+ }
+ else {
+ theta = Math.PI*0.5;
+ pos1 = new Point2D.Double(isectX, isectY-flagDist);
+ pos2 = new Point2D.Double(isectX, isectY+flagDist);
+ }
+
+ // Chooses flag directions
+ {
+ @SuppressWarnings("unused")
+ int inputs1 = 0, outputs1 = 0;
+ for(Resource connector : terminals1Resources) {
+ if(graph.hasStatement(connector, DIA.IsHeadConnectorOf))
+ ++inputs1;
+ else
+ ++outputs1;
+ }
+ @SuppressWarnings("unused")
+ int inputs2 = 0, outputs2 = 0;
+ for(Resource connector : terminals2Resources) {
+ if(graph.hasStatement(connector, DIA.IsHeadConnectorOf))
+ ++inputs2;
+ else
+ ++outputs2;
+ }
+
+ if(outputs1 == 0) {
+ type1 = FlagClass.Type.In;
+ type2 = FlagClass.Type.Out;
+ theta += Math.PI;
+ }
+ else {
+ type1 = FlagClass.Type.Out;
+ type2 = FlagClass.Type.In;
+ }
+ if (DEBUG) {
+ System.out.println("inputs1: " + inputs1);
+ System.out.println("outputs1: " + outputs1);
+ System.out.println("=> type1: " + type1);
+ System.out.println("inputs2: " + inputs2);
+ System.out.println("outputs2: " + outputs2);
+ System.out.println("=> type2: " + type2);
+ }
+ }
+ Resource flag1 = createFlag(graph, diagram, getFlagTransform(pos1, theta), type1, commonLabel);
+ Resource flag2 = createFlag(graph, diagram, getFlagTransform(pos2, theta), type2, commonLabel);
+ if (DEBUG) {
+ System.out.println("FLAG1: " + NameUtils.getSafeName(graph, flag1, true));
+ System.out.println("FLAG2: " + NameUtils.getSafeName(graph, flag2, true));
+ }
+
+// System.out.println("conn1: " + NameUtils.getSafeLabel(graph, type1 == FlagClass.Type.In ? DIA.HasPlainConnector : DIA.HasArrowConnector));
+// System.out.println("conn2: " + NameUtils.getSafeLabel(graph, type2 == FlagClass.Type.In ? DIA.HasPlainConnector : DIA.HasArrowConnector));
+ Resource flagConnector1 = cu.newConnector(connection,
+ type1 == FlagClass.Type.In ? DIA.HasPlainConnector : DIA.HasArrowConnector);
+ Resource flagConnector2 = cu.newConnector(newConnection,
+ type2 == FlagClass.Type.In ? DIA.HasPlainConnector : DIA.HasArrowConnector);
+ graph.claim(flag1, DIA.Flag_ConnectionPoint, flagConnector1);
+ graph.claim(flag2, DIA.Flag_ConnectionPoint, flagConnector2);
+
+ double position = isHorizontal ? isectY : isectX;
+ connectFlag(graph, isHorizontal, position, connection, flagConnector1,
+ interfaceNodes1Resources);
+ connectFlag(graph, isHorizontal, position, newConnection, flagConnector2,
+ interfaceNodes2Resources);
+
+ FlagUtil.join(graph, flag1, flag2);
+
+ // Move mapping relations to new connection if necessary
+ if(type1 == FlagClass.Type.In) {
+ moveStatements(graph, connection, newConnection, MOD.ElementToComponent);
+ moveStatements(graph, connection, newConnection, MOD.DiagramConnectionToConnection);
+ moveStatements(graph, connection, newConnection, MOD.DiagramConnectionToConnectionSpecial);
+ FlagUtil.fixBindsStatements(graph, graph.getPossibleObject(newConnection, MOD.DiagramConnectionToConnection));
+ }
+ else
+ FlagUtil.fixBindsStatements(graph, graph.getPossibleObject(connection, MOD.DiagramConnectionToConnection));
+ }
+
+ /**
+ * A workaround for problems with mapping not removing the necessary
+ * STR.Joins relations from flags after a split.
+ *
+ * @param graph
+ * @param cu
+ * @param connection
+ * @param connectors
+ * @throws DatabaseException
+ */
+ private void removeFlagJoins(WriteGraph graph, ConnectionUtil cu, Resource connection, ArrayList connectors) throws DatabaseException {
+ for (Resource connector : connectors) {
+ Resource e = cu.getConnectedComponent(connection, connector);
+ if (graph.isInstanceOf(e, DIA.Flag)) {
+ Resource diagram = graph.syncRequest(new PossibleTypedParent(e, DIA.Diagram));
+ if (diagram == null)
+ continue;
+ for (Resource join : graph.getObjects(e, DIA.FlagIsJoinedBy)) {
+ Collection joinsComposites = graph.getObjects(join, STR.JoinsComposite);
+ if (joinsComposites.size() == 1) {
+ // Only remove joins that are internal to a diagram.
+ graph.deny(join, STR.Joins);
+ } else if (joinsComposites.size() == 2) {
+ // Only remove the joins relations that refer to
+ // connections that are part of the same diagram.
+ for (Resource joins : graph.getObjects(join, STR.Joins)) {
+ Resource diagramConnection = graph.getPossibleObject(joins, MOD.ConnectionToDiagramConnection);
+ if (diagramConnection == null)
+ continue;
+ Resource partOfDiagram = graph.syncRequest(new PossibleTypedParent(diagramConnection, DIA.Diagram));
+ if (diagram.equals(partOfDiagram)) {
+ graph.deny(join, STR.Joins, joins);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private static void moveStatements(WriteGraph graph, Resource from, Resource to, Resource relation) throws DatabaseException {
+ if(from.equals(to))
+ return;
+ for(Statement stat : graph.getStatements(from, relation))
+ if(stat.getSubject().equals(from))
+ graph.claim(to, stat.getPredicate(), stat.getObject());
+ graph.deny(from, relation);
+ }
+
+ private void connectFlag(WriteGraph graph, boolean isHorizontal, double position, Resource connection, Resource flagConnector, Collection interfaceNodes)
+ throws DatabaseException {
+ if(interfaceNodes.size() > 1) {
+ Resource routeLine = graph.newResource();
+ graph.claim(routeLine, L0.InstanceOf, DIA.RouteLine);
+ graph.claim(connection, DIA.HasInteriorRouteNode, routeLine);
+ graph.claimLiteral(routeLine, DIA.IsHorizontal, isHorizontal);
+ graph.claimLiteral(routeLine, DIA.HasPosition, position);
+ graph.claim(routeLine, DIA.AreConnected, flagConnector);
+ flagConnector = routeLine;
+ }
+ for(Resource rn : interfaceNodes) {
+ graph.claim(flagConnector, DIA.AreConnected, rn);
+ }
+ }
+
+ private AffineTransform getFlagTransform(Point2D pos, double theta) {
+ AffineTransform at = AffineTransform.getTranslateInstance(pos.getX(), pos.getY());
+ at.rotate(theta);
+ return at;
+ }
+
+ private Resource createFlag(WriteGraph graph, Resource diagram, AffineTransform tr, FlagClass.Type type, String label) throws DatabaseException {
+ DiagramResource DIA = DiagramResource.getInstance(graph);
+
+ Resource flag = graph.newResource();
+ graph.claim(flag, L0.InstanceOf, null, DIA.Flag);
+ AddElement.claimFreshElementName(graph, diagram, flag);
+ graph.claim(flag, L0.PartOf, L0.ConsistsOf, diagram);
+
+ DiagramGraphUtil.setTransform(graph, flag, tr);
+ if (type != null)
+ FlagUtil.setFlagType(graph, flag, type);
+
+ if (label != null)
+ graph.claimLiteral(flag, L0.HasLabel, DIA.FlagLabel, label, Bindings.STRING);
+
+ OrderedSetUtils.add(graph, diagram, flag);
+ return flag;
+ }
+
+ public static void splitConnection(WriteGraph graph, Resource connection, double x, double y) throws DatabaseException {
+ RouteGraph rg = RouteGraphUtils.load(graph, null, connection);
+ new RouteGraphConnectionSplitter(graph).split(graph, connection, rg, new Point2D.Double(x, y));
+ }
}
\ No newline at end of file