]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.modeling/src/org/simantics/modeling/adapters/ElementRemover.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.modeling / src / org / simantics / modeling / adapters / ElementRemover.java
1 /*******************************************************************************\r
2  * Copyright (c) 2012 Association for Decentralized Information Management in\r
3  * Industry THTH ry.\r
4  * All rights reserved. This program and the accompanying materials\r
5  * are made available under the terms of the Eclipse Public License v1.0\r
6  * which accompanies this distribution, and is available at\r
7  * http://www.eclipse.org/legal/epl-v10.html\r
8  *\r
9  * Contributors:\r
10  *     VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.simantics.modeling.adapters;\r
13 \r
14 import gnu.trove.set.hash.THashSet;\r
15 \r
16 import java.util.ArrayList;\r
17 import java.util.Collection;\r
18 import java.util.Set;\r
19 \r
20 import org.simantics.db.Resource;\r
21 import org.simantics.db.WriteGraph;\r
22 import org.simantics.db.common.utils.OrderedSetUtils;\r
23 import org.simantics.db.exception.DatabaseException;\r
24 import org.simantics.db.layer0.adapter.Remover;\r
25 import org.simantics.db.layer0.adapter.impl.AbstractRemover;\r
26 import org.simantics.db.layer0.adapter.impl.EntityRemover;\r
27 import org.simantics.db.layer0.util.RemoverUtil;\r
28 import org.simantics.diagram.content.ConnectionUtil;\r
29 import org.simantics.diagram.stubs.DiagramResource;\r
30 import org.simantics.layer0.utils.binaryPredicates.OrderedSetElementsPredicate;\r
31 import org.simantics.modeling.ModelingResources;\r
32 import org.simantics.structural.stubs.StructuralResource2;\r
33 \r
34 /**\r
35  * A {@link Remover} implementation for removing DIA.Element instances.\r
36  * \r
37  * The implementation has separate paths for STR.Connection instances and other\r
38  * DIA.Element instances. For DIA.Element this remover will:\r
39  * <ol>\r
40  * <li>List connections/monitors the element is attached to</li>\r
41  * <li>Disconnect the element from its owner diagram(s)</li>\r
42  * <li>Remove the element itself with EntityRemover default logic</li>\r
43  * <li>Recursively remove all related degenerate connections, i.e. connections\r
44  * that only have one connector after remove the one connected to this removed\r
45  * element.</li>\r
46  * <li>Recursively remove monitors attached to the removed element</li>\r
47  * </ol>\r
48  * \r
49  * <p>\r
50  * For STR.Connections this remover will:\r
51  * <ol>\r
52  * <li>List all related data (monitors, mapped data)</li> \r
53  * <li>Remove the connection itself</li>\r
54  * <li>Remove the related data</li>\r
55  * </ol>\r
56  * \r
57  * @author Tuukka Lehtonen\r
58  */\r
59 public class ElementRemover extends AbstractRemover {\r
60 \r
61     private static final boolean DEBUG = false;\r
62 \r
63     public ElementRemover(Resource element) {\r
64         super(element);\r
65     }\r
66 \r
67     @Override\r
68     public void remove(WriteGraph graph) throws DatabaseException {\r
69         // 0. Find all connections to the removed element\r
70         StructuralResource2 STR = StructuralResource2.getInstance(graph);\r
71 \r
72         if (graph.isInstanceOf(resource, STR.Connection)) {\r
73             removeConnection(graph);\r
74         } else {\r
75             removeElement(graph);\r
76         }\r
77     }\r
78 \r
79     public void removeElement(WriteGraph graph) throws DatabaseException {\r
80         if (DEBUG)\r
81             System.out.println(this + " removing element");\r
82 \r
83         Set<Resource> connectors = null;\r
84 \r
85         StructuralResource2 STR = StructuralResource2.getInstance(graph);\r
86         DiagramResource DIA = DiagramResource.getInstance(graph);\r
87 \r
88         Collection<Resource> connectedTo = graph.getObjects(resource, STR.IsConnectedTo);\r
89         for (Resource connector : connectedTo) {\r
90             if (connectors == null)\r
91                 connectors = new THashSet<Resource>(connectedTo.size());\r
92             connectors.add(connector);\r
93         }\r
94         Collection<Resource> monitors = graph.getObjects(resource, DIA.HasMonitorComponent_Inverse);\r
95 \r
96         if (DEBUG) {\r
97             if (connectors != null)\r
98                 System.out.println(this + " found " + connectors.size() + " connectors connected to element");\r
99             if (!monitors.isEmpty())\r
100                 System.out.println(this + " found " + monitors.size() + " monitors attached to element");\r
101         }\r
102 \r
103         // 1. Disconnect element from diagrams\r
104         for (Resource diagram : OrderedSetElementsPredicate.INSTANCE.getSubjects(graph, resource)) {\r
105             OrderedSetUtils.remove(graph, diagram, resource);\r
106         }\r
107 \r
108         // 2. Delete element itself\r
109         EntityRemover.remove(graph, resource);\r
110 \r
111         // 3. Recursively remove all related degenerate connections\r
112         // i.e. connections that only have one connector after remove the\r
113         // one connected to this removed element.\r
114         ConnectionUtil cu = null;\r
115         Set<Resource> connectionsToRemove = null;\r
116         if (connectors != null) {\r
117             cu = new ConnectionUtil(graph);\r
118             Set<Resource> touchedConnections = new THashSet<Resource>(connectors.size());\r
119             for (Resource connector : connectors) {\r
120                 Resource connection = ConnectionUtil.tryGetConnection(graph, connector);\r
121                 if (connection != null)\r
122                     touchedConnections.add(connection);\r
123                 cu.removeConnectionPart(connector);\r
124             }\r
125             for (Resource connection : touchedConnections) {\r
126                 int removedConnectors = cu.removeUnusedConnectors(connection);\r
127                 if (DEBUG)\r
128                     System.out.println(this + " PRUNED " + removedConnectors + " UNUSED CONNECTORS FROM TOUCHED CONNECTION " + connection);\r
129                 while (true) {\r
130                     int removedInteriorRouteNodes = cu.removeExtraInteriorRouteNodes(connection);\r
131                     if (DEBUG)\r
132                         System.out.println(this + " PRUNED " + removedInteriorRouteNodes + " INTERIOR ROUTE NODES FROM TOUCHED CONNECTION " + connection);\r
133                     if (removedInteriorRouteNodes == 0)\r
134                         break;\r
135                 }\r
136                 int connectorCount = cu.getConnectedConnectors(connection, null).size();\r
137                 if (DEBUG)\r
138                     System.out.println(this + " \t" + connectorCount + " CONNECTORS LEFT");\r
139                 if (connectorCount < 2) {\r
140                     if (connectionsToRemove == null)\r
141                         connectionsToRemove = new THashSet<Resource>(touchedConnections.size());\r
142                     connectionsToRemove.add(connection);\r
143                 }\r
144             }\r
145         }\r
146         if (connectionsToRemove != null) {\r
147             for (Resource connection : connectionsToRemove) {\r
148                 if (DEBUG)\r
149                     System.out.println(this + " REMOVING connection " + connection);\r
150                 RemoverUtil.remove(graph, connection);\r
151             }\r
152         }\r
153 \r
154         // 4. Recursively remove monitors attached to element\r
155         if (!monitors.isEmpty())\r
156             for (Resource monitor : monitors)\r
157                 RemoverUtil.remove(graph, monitor);\r
158 \r
159     }\r
160 \r
161     public void removeConnection(WriteGraph graph) throws DatabaseException {\r
162         if (DEBUG)\r
163             System.out.println(this + " removing connection element");\r
164 \r
165         DiagramResource DIA = DiagramResource.getInstance(graph);\r
166         ModelingResources MOD = ModelingResources.getInstance(graph);\r
167 \r
168         // 0. Get set of related data\r
169         Collection<Resource> objects = new ArrayList<Resource>();\r
170         for (Resource relation : new Resource[] {\r
171                 DIA.HasMonitorComponent_Inverse,\r
172                 MOD.ElementToComponent,\r
173                 MOD.DiagramConnectionToConnection,\r
174                 MOD.DiagramConnectionToConnectionSpecial\r
175         }) {\r
176             for (Resource object : graph.getObjects(resource, relation)) {\r
177                 if (!object.equals(resource))\r
178                     objects.add(object);\r
179             }\r
180         }\r
181 \r
182         // 1. Remove connection itself\r
183         new ConnectionUtil(graph).removeConnection(resource);\r
184 \r
185         // 2. Recursively remove related data\r
186         if (!objects.isEmpty())\r
187             for (Resource object : objects)\r
188                 RemoverUtil.remove(graph, object);\r
189     }\r
190 \r
191     @Override\r
192     public String toString() {\r
193         return getClass().getSimpleName() + resource;\r
194     }\r
195 \r
196 }\r