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