-/*******************************************************************************\r
- * Copyright (c) 2012 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.modeling.flags;\r
-\r
-import gnu.trove.map.hash.THashMap;\r
-import gnu.trove.set.hash.THashSet;\r
-\r
-import java.util.ArrayList;\r
-import java.util.Iterator;\r
-import java.util.List;\r
-\r
-import org.simantics.db.ReadGraph;\r
-import org.simantics.db.Resource;\r
-import org.simantics.db.Statement;\r
-import org.simantics.db.WriteGraph;\r
-import org.simantics.db.common.request.IndexRoot;\r
-import org.simantics.db.common.utils.NameUtils;\r
-import org.simantics.db.common.utils.OrderedSetUtils;\r
-import org.simantics.db.exception.DatabaseException;\r
-import org.simantics.diagram.content.ConnectionUtil;\r
-import org.simantics.diagram.stubs.DiagramResource;\r
-import org.simantics.layer0.Layer0;\r
-import org.simantics.modeling.ModelingResources;\r
-import org.simantics.scl.commands.Commands;\r
-import org.simantics.scl.runtime.tuple.Tuple2;\r
-import org.simantics.structural.stubs.StructuralResource2;\r
-\r
-public class MergeFlags {\r
-\r
- private static class CP {\r
- public final Resource component;\r
- public final Resource connectionPoint;\r
- \r
- public CP(Resource component, Resource connectionPoint) {\r
- super();\r
- this.component = component;\r
- this.connectionPoint = connectionPoint;\r
- }\r
-\r
- @Override\r
- public int hashCode() {\r
- return component.hashCode() + 31 * connectionPoint.hashCode();\r
- }\r
-\r
- @Override\r
- public boolean equals(Object obj) {\r
- if (this == obj)\r
- return true;\r
- if (obj == null)\r
- return false;\r
- if (getClass() != obj.getClass())\r
- return false;\r
- CP other = (CP) obj;\r
- return component.equals(other.component) \r
- && connectionPoint.equals(other.connectionPoint);\r
- }\r
- }\r
- \r
- public static String validateForMerge(ReadGraph g,\r
- List<Resource> flags) throws DatabaseException {\r
- if(flags.size() <= 1)\r
- return "At least two flags must be chosen.";\r
- \r
- DiagramResource DIA = DiagramResource.getInstance(g);\r
- StructuralResource2 STR = StructuralResource2.getInstance(g);\r
- \r
- for(Resource flag : flags)\r
- if(!g.hasStatement(flag, DIA.FlagIsJoinedBy))\r
- return "All flags are not joined to other flags.";\r
-\r
- List<Resource> connectors = getPossibleRelated(g, flags, DIA.Flag_ConnectionPoint);\r
- for(Resource connector : connectors) {\r
- if(connector == null)\r
- return "All flags are not connected";\r
- }\r
- \r
- List<Resource> connections = getConnection(g, flags, connectors);\r
- for(Resource connection : connections) {\r
- if(connection == null)\r
- return "Invalid flag. Didn't find configuration connection.";\r
- }\r
- \r
- THashSet<Resource> uniqueConnections = new THashSet<Resource>(connections.size());\r
- for(Resource connection : connections) {\r
- uniqueConnections.add(connection);\r
- }\r
- \r
- if(uniqueConnections.size() == 1)\r
- return null;\r
- \r
- Iterator<Resource> it = uniqueConnections.iterator();\r
- THashSet<CP> cps = getConnectionPoints(g, STR, it.next());\r
- while(it.hasNext()) {\r
- cps.retainAll(getConnectionPoints(g, STR, it.next()));\r
- if(cps.isEmpty())\r
- return "Flags are not connected to a common terminal.";\r
- }\r
- \r
- return null;\r
- }\r
- \r
- private static THashSet<CP> getConnectionPoints(ReadGraph g, StructuralResource2 STR, Resource connection) throws DatabaseException {\r
- THashSet<CP> result = new THashSet<CP>(); \r
- for(Statement stat : g.getStatements(connection, STR.Connects))\r
- result.add(new CP(stat.getObject(), g.getInverse(stat.getPredicate())));\r
- return result;\r
- }\r
- \r
- /**\r
- * Merges all flags in the given list to one or two flags.\r
- * @param g\r
- * @param flags to join\r
- * @return Error message or empty string if the operation succeeded.\r
- */\r
- public static String merge(WriteGraph g, List<Resource> flags) throws DatabaseException {\r
- return (String)Commands.get(g, "Simantics/Flag/mergeFlags").execute(g, g.syncRequest(new IndexRoot(flags.get(0))), flags);\r
- }\r
- \r
- public static String mergeWithoutMetadata(WriteGraph g, List<Resource> flags) throws DatabaseException {\r
- THashMap<Tuple2, ArrayList<Resource>> groups = \r
- new THashMap<Tuple2, ArrayList<Resource>>();\r
- \r
- DiagramResource DIA = DiagramResource.getInstance(g);\r
- StructuralResource2 STR = StructuralResource2.getInstance(g);\r
- for(Resource flag : flags) {\r
- Resource connector = g.getSingleObject(flag, DIA.Flag_ConnectionPoint);\r
- Resource connection = null;\r
- for(Resource temp : g.getObjects(connector, STR.Connects))\r
- if(!temp.equals(flag)) {\r
- connection = temp;\r
- break;\r
- }\r
- if(connection == null)\r
- continue;\r
- \r
- Resource flagType = g.getSingleObject(flag, DIA.HasFlagType);\r
- Resource connectionType = g.getPossibleObject(connection, STR.HasConnectionType);\r
- \r
- Tuple2 tuple = new Tuple2(flagType, connectionType);\r
- ArrayList<Resource> group = groups.get(tuple);\r
- if(group == null) {\r
- group = new ArrayList<Resource>();\r
- groups.put(tuple, group);\r
- }\r
- group.add(flag);\r
- }\r
- \r
- String errorMessage = "";\r
- for(ArrayList<Resource> group : groups.values()) {\r
- if(group.size() > 1) {\r
- String temp = mergeAux(g, group);\r
- if(temp != null)\r
- errorMessage = temp;\r
- }\r
- }\r
- return errorMessage;\r
- }\r
- \r
- /**\r
- * Merges all flags in the given list to the first flag of the list.\r
- * @param g\r
- * @param flags to join\r
- * @return Error message or null if the operation succeeded.\r
- */\r
- private static String mergeAux(WriteGraph g, List<Resource> flags) throws DatabaseException {\r
- if(flags.size() <= 1)\r
- return null; // Nothing to do\r
- \r
- DiagramResource DIA = DiagramResource.getInstance(g);\r
- StructuralResource2 STR = StructuralResource2.getInstance(g);\r
- \r
- // Find connectors\r
- List<Resource> connectors = getPossibleRelated(g, flags, DIA.Flag_ConnectionPoint);\r
- for(Resource connector : connectors) {\r
- if(connector == null)\r
- return "All flags are not connected";\r
- } \r
- \r
- // Find configuration connections\r
- List<Resource> connections = getConnection(g, flags, connectors);\r
- for(Resource connection : connections) {\r
- if(connection == null)\r
- return "Invalid flag. Didn't find configuration connection.";\r
- }\r
- \r
- // Choose canonical flag and connection where other flags are merged to\r
- Resource canonicalFlag = flags.get(0);\r
- Resource canonicalConnection = connections.get(0);\r
- \r
- // Do the merging\r
- for(int i=1;i<flags.size();++i) {\r
- Resource flag = flags.get(i);\r
- Resource connection = connections.get(i);\r
- \r
- // Replace references in joins to the canonical flag and connection\r
- for(Resource join : g.getObjects(flag, DIA.FlagIsJoinedBy)) {\r
- g.denyStatement(flag, DIA.FlagIsJoinedBy, join);\r
- g.claim(canonicalFlag, DIA.FlagIsJoinedBy, join);\r
- g.denyStatement(join, STR.Joins, connection);\r
- g.claim(join, STR.Joins, canonicalConnection);\r
- }\r
- \r
- // Remove flag and its connector\r
- removeElement(g, flag);\r
- g.deny(connectors.get(i));\r
- }\r
- \r
- // Clean up connections (remove extra route lines and complete connections)\r
- THashSet<Resource> uniqueConnections = new THashSet<Resource>(connections.size());\r
- for(int i=1;i<connections.size();++i)\r
- uniqueConnections.add(connections.get(i));\r
- \r
- for(Resource connection : uniqueConnections)\r
- cleanUpConnection(g, connection);\r
- \r
- return null;\r
- }\r
-\r
- private static void cleanUpConnection(WriteGraph g, Resource connection) throws DatabaseException {\r
- DiagramResource DIA = DiagramResource.getInstance(g);\r
- StructuralResource2 STR = StructuralResource2.getInstance(g);\r
- ModelingResources MOD = ModelingResources.getInstance(g);\r
- \r
- Resource diagramConnection = g.getSingleObject(connection, MOD.ConnectionToDiagramConnection);\r
- \r
- // If connection is degenerated, remove it\r
- if(g.getObjects(connection, STR.IsJoinedBy).size() == 0 && \r
- g.getObjects(connection, STR.Connects).size() <= 1) {\r
- g.deny(connection);\r
- // Garbage collection removes interior route nodes etc. stuff\r
- //removeElement(g, diagramConnection);\r
- // platform #4473: Remove connection completely to not leave behind stray connectors.\r
- new ConnectionUtil(g).removeConnection(diagramConnection);\r
- }\r
- // Otherwise just remove degenerated route nodes\r
- else {\r
- boolean modifiedSomething = true;\r
- while(modifiedSomething) { // loop until no modification are made (O(n^2) algorithm)\r
- modifiedSomething = false;\r
- for(Resource routeNode : g.getObjects(diagramConnection, DIA.HasInteriorRouteNode))\r
- if(g.getObjects(routeNode, DIA.AreConnected).size() <= 1) {\r
- g.deny(routeNode);\r
- modifiedSomething = true;\r
- }\r
- }\r
- }\r
- }\r
- \r
- private static void removeElement(WriteGraph g, Resource element) throws DatabaseException {\r
- OrderedSetUtils.remove(g, OrderedSetUtils.getSingleOwnerList(g, element), element);\r
- g.deny(element);\r
- }\r
-\r
- private static List<Resource> getConnection(ReadGraph g, List<Resource> flags, List<Resource> connectors) throws DatabaseException {\r
- ArrayList<Resource> result = new ArrayList<Resource>(flags.size());\r
- for(int i=0;i<flags.size();++i)\r
- result.add(getConnection(g, flags.get(i), connectors.get(i)));\r
- return result;\r
- }\r
- \r
- private static Resource getConnection(ReadGraph g, Resource flag, Resource connector) throws DatabaseException {\r
- StructuralResource2 STR = StructuralResource2.getInstance(g);\r
- ModelingResources MOD = ModelingResources.getInstance(g);\r
- for(Resource diagramConnection : g.getObjects(connector, STR.Connects)) {\r
- if(!flag.equals(diagramConnection)) {\r
- return g.getPossibleObject(diagramConnection, MOD.DiagramConnectionToConnection);\r
- }\r
- }\r
- return null;\r
- }\r
- \r
- private static List<Resource> getPossibleRelated(ReadGraph g, List<Resource> subjects, Resource relation) throws DatabaseException {\r
- ArrayList<Resource> result = new ArrayList<Resource>(subjects.size());\r
- for(int i=0;i<subjects.size();++i)\r
- result.add(g.getPossibleObject(subjects.get(i), relation));\r
- return result;\r
- }\r
-\r
- public static void expandFlagSet(ReadGraph graph, List<Resource> flags) throws DatabaseException {\r
- DiagramResource DIA = DiagramResource.getInstance(graph);\r
- StructuralResource2 STR = StructuralResource2.getInstance(graph);\r
- \r
- THashSet<Resource> connectionSet = new THashSet<Resource>();\r
- \r
- for(Resource flag : flags) {\r
- for(Resource connector : graph.getObjects(flag, STR.IsConnectedTo))\r
- for(Resource connection : graph.getObjects(connector, STR.Connects))\r
- if(!connection.equals(flag))\r
- connectionSet.add(connection);\r
- }\r
- \r
- for(Resource connection : connectionSet.toArray(new Resource[connectionSet.size()])) {\r
- for(Resource connector : graph.getObjects(connection, STR.IsConnectedTo))\r
- for(Statement stat : graph.getStatements(connector, STR.Connects))\r
- if(!stat.getObject().equals(connection))\r
- for(Resource connector2 : graph.getObjects(stat.getObject(), graph.getInverse(stat.getPredicate())))\r
- if(!connector2.equals(connector))\r
- for(Resource connection2 : graph.getObjects(connector2, STR.Connects))\r
- if(graph.isInstanceOf(connection2, DIA.Connection))\r
- connectionSet.add(connection2);\r
- }\r
- \r
- THashSet<Resource> visited = new THashSet<Resource>(flags);\r
- \r
- for(Resource connection : connectionSet) {\r
- visited.add(connection);\r
- for(Resource connector : graph.getObjects(connection, STR.IsConnectedTo))\r
- for(Resource flag : graph.getObjects(connector, STR.Connects))\r
- if(visited.add(flag) && graph.isInstanceOf(flag, DIA.Flag)\r
- && graph.hasStatement(flag, DIA.FlagIsJoinedBy))\r
- flags.add(flag);\r
- } \r
- } \r
- \r
- public static void collectFlagGroupsInComposite(ReadGraph g, Resource composite, ArrayList<ArrayList<Resource>> groups) throws DatabaseException {\r
- DiagramResource DIA = DiagramResource.getInstance(g);\r
- ModelingResources MOD = ModelingResources.getInstance(g);\r
- Layer0 L0 = Layer0.getInstance(g);\r
- \r
- Resource diagram = g.getPossibleObject(composite, MOD.CompositeToDiagram);\r
- if(diagram == null)\r
- return;\r
- \r
- THashSet<Resource> flags = new THashSet<Resource>();\r
- for(Resource element : g.getObjects(diagram, L0.ConsistsOf))\r
- if(g.isInstanceOf(element, DIA.Flag) && g.hasStatement(element, DIA.FlagIsJoinedBy))\r
- flags.add(element);\r
- \r
- for(Resource flag : flags.toArray(new Resource[flags.size()])) \r
- if(flags.contains(flag)) {\r
- ArrayList<Resource> group = new ArrayList<Resource>();\r
- group.add(flag);\r
- expandFlagSet(g, group);\r
- flags.removeAll(group);\r
- if(group.size() > 1)\r
- groups.add(group);\r
- }\r
- }\r
- \r
- public static void expandCompositeSet(ReadGraph g, THashSet<Resource> composites) throws DatabaseException {\r
- for(Resource composite : composites.toArray(new Resource[composites.size()]))\r
- expandCompositeSet(g, composite, composites);\r
- }\r
-\r
- private static void expandCompositeSet(ReadGraph g, Resource composite,\r
- THashSet<Resource> composites) throws DatabaseException {\r
- Layer0 L0 = Layer0.getInstance(g);\r
- StructuralResource2 STR = StructuralResource2.getInstance(g);\r
- for(Resource child : g.getObjects(composite, L0.ConsistsOf))\r
- if(g.isInstanceOf(child, STR.Composite))\r
- if(composites.add(child))\r
- expandCompositeSet(g, child, composites);\r
- }\r
- \r
- public static String mergeFlags (WriteGraph graph, Resource diagram ) throws DatabaseException {\r
- \r
- ArrayList<ArrayList<Resource>> groups = new ArrayList<ArrayList<Resource>>();\r
- MergeFlags.collectFlagGroupsInComposite(graph, diagram, groups);\r
- for(ArrayList<Resource> group : groups) {\r
- MergeFlags.merge(graph, group);\r
- }\r
-\r
- return "Merged flags in diagram resource: " + diagram.toString() + " and name: " + NameUtils.getSafeName(graph, diagram);\r
- }\r
- \r
- public static void expandFlags(WriteGraph graph, Resource diagram) throws DatabaseException {\r
- ArrayList<Resource> groups = new ArrayList<Resource>();\r
- ExpandFlags.collectGroupedFlags(graph, diagram, groups);\r
- for(Resource group : groups) {\r
- ExpandFlags.expandFlag(graph, group);\r
- }\r
- } \r
-}\r
+/*******************************************************************************
+ * Copyright (c) 2012 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.modeling.flags;
+
+import gnu.trove.map.hash.THashMap;
+import gnu.trove.set.hash.THashSet;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+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.IndexRoot;
+import org.simantics.db.common.utils.NameUtils;
+import org.simantics.db.common.utils.OrderedSetUtils;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.diagram.content.ConnectionUtil;
+import org.simantics.diagram.stubs.DiagramResource;
+import org.simantics.layer0.Layer0;
+import org.simantics.modeling.ModelingResources;
+import org.simantics.scl.commands.Commands;
+import org.simantics.scl.runtime.tuple.Tuple2;
+import org.simantics.structural.stubs.StructuralResource2;
+
+public class MergeFlags {
+
+ private static class CP {
+ public final Resource component;
+ public final Resource connectionPoint;
+
+ public CP(Resource component, Resource connectionPoint) {
+ super();
+ this.component = component;
+ this.connectionPoint = connectionPoint;
+ }
+
+ @Override
+ public int hashCode() {
+ return component.hashCode() + 31 * connectionPoint.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ CP other = (CP) obj;
+ return component.equals(other.component)
+ && connectionPoint.equals(other.connectionPoint);
+ }
+ }
+
+ public static String validateForMerge(ReadGraph g,
+ List<Resource> flags) throws DatabaseException {
+ if(flags.size() <= 1)
+ return "At least two flags must be chosen.";
+
+ DiagramResource DIA = DiagramResource.getInstance(g);
+ StructuralResource2 STR = StructuralResource2.getInstance(g);
+
+ for(Resource flag : flags)
+ if(!g.hasStatement(flag, DIA.FlagIsJoinedBy))
+ return "All flags are not joined to other flags.";
+
+ List<Resource> connectors = getPossibleRelated(g, flags, DIA.Flag_ConnectionPoint);
+ for(Resource connector : connectors) {
+ if(connector == null)
+ return "All flags are not connected";
+ }
+
+ List<Resource> connections = getConnection(g, flags, connectors);
+ for(Resource connection : connections) {
+ if(connection == null)
+ return "Invalid flag. Didn't find configuration connection.";
+ }
+
+ THashSet<Resource> uniqueConnections = new THashSet<Resource>(connections.size());
+ for(Resource connection : connections) {
+ uniqueConnections.add(connection);
+ }
+
+ if(uniqueConnections.size() == 1)
+ return null;
+
+ Iterator<Resource> it = uniqueConnections.iterator();
+ THashSet<CP> cps = getConnectionPoints(g, STR, it.next());
+ while(it.hasNext()) {
+ cps.retainAll(getConnectionPoints(g, STR, it.next()));
+ if(cps.isEmpty())
+ return "Flags are not connected to a common terminal.";
+ }
+
+ return null;
+ }
+
+ private static THashSet<CP> getConnectionPoints(ReadGraph g, StructuralResource2 STR, Resource connection) throws DatabaseException {
+ THashSet<CP> result = new THashSet<CP>();
+ for(Statement stat : g.getStatements(connection, STR.Connects))
+ result.add(new CP(stat.getObject(), g.getInverse(stat.getPredicate())));
+ return result;
+ }
+
+ /**
+ * Merges all flags in the given list to one or two flags.
+ * @param g
+ * @param flags to join
+ * @return Error message or empty string if the operation succeeded.
+ */
+ public static String merge(WriteGraph g, List<Resource> flags) throws DatabaseException {
+ return (String)Commands.get(g, "Simantics/Flag/mergeFlags").execute(g, g.syncRequest(new IndexRoot(flags.get(0))), flags);
+ }
+
+ public static String mergeWithoutMetadata(WriteGraph g, List<Resource> flags) throws DatabaseException {
+ THashMap<Tuple2, ArrayList<Resource>> groups =
+ new THashMap<Tuple2, ArrayList<Resource>>();
+
+ DiagramResource DIA = DiagramResource.getInstance(g);
+ StructuralResource2 STR = StructuralResource2.getInstance(g);
+ for(Resource flag : flags) {
+ Resource connector = g.getSingleObject(flag, DIA.Flag_ConnectionPoint);
+ Resource connection = null;
+ for(Resource temp : g.getObjects(connector, STR.Connects))
+ if(!temp.equals(flag)) {
+ connection = temp;
+ break;
+ }
+ if(connection == null)
+ continue;
+
+ Resource flagType = g.getSingleObject(flag, DIA.HasFlagType);
+ Resource connectionType = g.getPossibleObject(connection, STR.HasConnectionType);
+
+ Tuple2 tuple = new Tuple2(flagType, connectionType);
+ ArrayList<Resource> group = groups.get(tuple);
+ if(group == null) {
+ group = new ArrayList<Resource>();
+ groups.put(tuple, group);
+ }
+ group.add(flag);
+ }
+
+ String errorMessage = "";
+ for(ArrayList<Resource> group : groups.values()) {
+ if(group.size() > 1) {
+ String temp = mergeAux(g, group);
+ if(temp != null)
+ errorMessage = temp;
+ }
+ }
+ return errorMessage;
+ }
+
+ /**
+ * Merges all flags in the given list to the first flag of the list.
+ * @param g
+ * @param flags to join
+ * @return Error message or null if the operation succeeded.
+ */
+ private static String mergeAux(WriteGraph g, List<Resource> flags) throws DatabaseException {
+ if(flags.size() <= 1)
+ return null; // Nothing to do
+
+ DiagramResource DIA = DiagramResource.getInstance(g);
+ StructuralResource2 STR = StructuralResource2.getInstance(g);
+
+ // Find connectors
+ List<Resource> connectors = getPossibleRelated(g, flags, DIA.Flag_ConnectionPoint);
+ for(Resource connector : connectors) {
+ if(connector == null)
+ return "All flags are not connected";
+ }
+
+ // Find configuration connections
+ List<Resource> connections = getConnection(g, flags, connectors);
+ for(Resource connection : connections) {
+ if(connection == null)
+ return "Invalid flag. Didn't find configuration connection.";
+ }
+
+ // Choose canonical flag and connection where other flags are merged to
+ Resource canonicalFlag = flags.get(0);
+ Resource canonicalConnection = connections.get(0);
+
+ // Do the merging
+ for(int i=1;i<flags.size();++i) {
+ Resource flag = flags.get(i);
+ Resource connection = connections.get(i);
+
+ // Replace references in joins to the canonical flag and connection
+ for(Resource join : g.getObjects(flag, DIA.FlagIsJoinedBy)) {
+ g.denyStatement(flag, DIA.FlagIsJoinedBy, join);
+ g.claim(canonicalFlag, DIA.FlagIsJoinedBy, join);
+ g.denyStatement(join, STR.Joins, connection);
+ g.claim(join, STR.Joins, canonicalConnection);
+ }
+
+ // Remove flag and its connector
+ removeElement(g, flag);
+ g.deny(connectors.get(i));
+ }
+
+ // Clean up connections (remove extra route lines and complete connections)
+ THashSet<Resource> uniqueConnections = new THashSet<Resource>(connections.size());
+ for(int i=1;i<connections.size();++i)
+ uniqueConnections.add(connections.get(i));
+
+ for(Resource connection : uniqueConnections)
+ cleanUpConnection(g, connection);
+
+ return null;
+ }
+
+ private static void cleanUpConnection(WriteGraph g, Resource connection) throws DatabaseException {
+ DiagramResource DIA = DiagramResource.getInstance(g);
+ StructuralResource2 STR = StructuralResource2.getInstance(g);
+ ModelingResources MOD = ModelingResources.getInstance(g);
+
+ Resource diagramConnection = g.getSingleObject(connection, MOD.ConnectionToDiagramConnection);
+
+ // If connection is degenerated, remove it
+ if(g.getObjects(connection, STR.IsJoinedBy).size() == 0 &&
+ g.getObjects(connection, STR.Connects).size() <= 1) {
+ g.deny(connection);
+ // Garbage collection removes interior route nodes etc. stuff
+ //removeElement(g, diagramConnection);
+ // platform #4473: Remove connection completely to not leave behind stray connectors.
+ new ConnectionUtil(g).removeConnection(diagramConnection);
+ }
+ // Otherwise just remove degenerated route nodes
+ else {
+ boolean modifiedSomething = true;
+ while(modifiedSomething) { // loop until no modification are made (O(n^2) algorithm)
+ modifiedSomething = false;
+ for(Resource routeNode : g.getObjects(diagramConnection, DIA.HasInteriorRouteNode))
+ if(g.getObjects(routeNode, DIA.AreConnected).size() <= 1) {
+ g.deny(routeNode);
+ modifiedSomething = true;
+ }
+ }
+ }
+ }
+
+ private static void removeElement(WriteGraph g, Resource element) throws DatabaseException {
+ OrderedSetUtils.remove(g, OrderedSetUtils.getSingleOwnerList(g, element), element);
+ g.deny(element);
+ }
+
+ private static List<Resource> getConnection(ReadGraph g, List<Resource> flags, List<Resource> connectors) throws DatabaseException {
+ ArrayList<Resource> result = new ArrayList<Resource>(flags.size());
+ for(int i=0;i<flags.size();++i)
+ result.add(getConnection(g, flags.get(i), connectors.get(i)));
+ return result;
+ }
+
+ private static Resource getConnection(ReadGraph g, Resource flag, Resource connector) throws DatabaseException {
+ StructuralResource2 STR = StructuralResource2.getInstance(g);
+ ModelingResources MOD = ModelingResources.getInstance(g);
+ for(Resource diagramConnection : g.getObjects(connector, STR.Connects)) {
+ if(!flag.equals(diagramConnection)) {
+ return g.getPossibleObject(diagramConnection, MOD.DiagramConnectionToConnection);
+ }
+ }
+ return null;
+ }
+
+ private static List<Resource> getPossibleRelated(ReadGraph g, List<Resource> subjects, Resource relation) throws DatabaseException {
+ ArrayList<Resource> result = new ArrayList<Resource>(subjects.size());
+ for(int i=0;i<subjects.size();++i)
+ result.add(g.getPossibleObject(subjects.get(i), relation));
+ return result;
+ }
+
+ public static void expandFlagSet(ReadGraph graph, List<Resource> flags) throws DatabaseException {
+ DiagramResource DIA = DiagramResource.getInstance(graph);
+ StructuralResource2 STR = StructuralResource2.getInstance(graph);
+
+ THashSet<Resource> connectionSet = new THashSet<Resource>();
+
+ for(Resource flag : flags) {
+ for(Resource connector : graph.getObjects(flag, STR.IsConnectedTo))
+ for(Resource connection : graph.getObjects(connector, STR.Connects))
+ if(!connection.equals(flag))
+ connectionSet.add(connection);
+ }
+
+ for(Resource connection : connectionSet.toArray(new Resource[connectionSet.size()])) {
+ for(Resource connector : graph.getObjects(connection, STR.IsConnectedTo))
+ for(Statement stat : graph.getStatements(connector, STR.Connects))
+ if(!stat.getObject().equals(connection))
+ for(Resource connector2 : graph.getObjects(stat.getObject(), graph.getInverse(stat.getPredicate())))
+ if(!connector2.equals(connector))
+ for(Resource connection2 : graph.getObjects(connector2, STR.Connects))
+ if(graph.isInstanceOf(connection2, DIA.Connection))
+ connectionSet.add(connection2);
+ }
+
+ THashSet<Resource> visited = new THashSet<Resource>(flags);
+
+ for(Resource connection : connectionSet) {
+ visited.add(connection);
+ for(Resource connector : graph.getObjects(connection, STR.IsConnectedTo))
+ for(Resource flag : graph.getObjects(connector, STR.Connects))
+ if(visited.add(flag) && graph.isInstanceOf(flag, DIA.Flag)
+ && graph.hasStatement(flag, DIA.FlagIsJoinedBy))
+ flags.add(flag);
+ }
+ }
+
+ public static void collectFlagGroupsInComposite(ReadGraph g, Resource composite, ArrayList<ArrayList<Resource>> groups) throws DatabaseException {
+ DiagramResource DIA = DiagramResource.getInstance(g);
+ ModelingResources MOD = ModelingResources.getInstance(g);
+ Layer0 L0 = Layer0.getInstance(g);
+
+ Resource diagram = g.getPossibleObject(composite, MOD.CompositeToDiagram);
+ if(diagram == null)
+ return;
+
+ THashSet<Resource> flags = new THashSet<Resource>();
+ for(Resource element : g.getObjects(diagram, L0.ConsistsOf))
+ if(g.isInstanceOf(element, DIA.Flag) && g.hasStatement(element, DIA.FlagIsJoinedBy))
+ flags.add(element);
+
+ for(Resource flag : flags.toArray(new Resource[flags.size()]))
+ if(flags.contains(flag)) {
+ ArrayList<Resource> group = new ArrayList<Resource>();
+ group.add(flag);
+ expandFlagSet(g, group);
+ flags.removeAll(group);
+ if(group.size() > 1)
+ groups.add(group);
+ }
+ }
+
+ public static void expandCompositeSet(ReadGraph g, THashSet<Resource> composites) throws DatabaseException {
+ for(Resource composite : composites.toArray(new Resource[composites.size()]))
+ expandCompositeSet(g, composite, composites);
+ }
+
+ private static void expandCompositeSet(ReadGraph g, Resource composite,
+ THashSet<Resource> composites) throws DatabaseException {
+ Layer0 L0 = Layer0.getInstance(g);
+ StructuralResource2 STR = StructuralResource2.getInstance(g);
+ for(Resource child : g.getObjects(composite, L0.ConsistsOf))
+ if(g.isInstanceOf(child, STR.Composite))
+ if(composites.add(child))
+ expandCompositeSet(g, child, composites);
+ }
+
+ public static String mergeFlags (WriteGraph graph, Resource diagram ) throws DatabaseException {
+
+ ArrayList<ArrayList<Resource>> groups = new ArrayList<ArrayList<Resource>>();
+ MergeFlags.collectFlagGroupsInComposite(graph, diagram, groups);
+ for(ArrayList<Resource> group : groups) {
+ MergeFlags.merge(graph, group);
+ }
+
+ return "Merged flags in diagram resource: " + diagram.toString() + " and name: " + NameUtils.getSafeName(graph, diagram);
+ }
+
+ public static void expandFlags(WriteGraph graph, Resource diagram) throws DatabaseException {
+ ArrayList<Resource> groups = new ArrayList<Resource>();
+ ExpandFlags.collectGroupedFlags(graph, diagram, groups);
+ for(Resource group : groups) {
+ ExpandFlags.expandFlag(graph, group);
+ }
+ }
+}