]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.diagram/src/org/simantics/diagram/synchronization/graph/AddElement.java
Fixed multiple issues causing dangling references to discarded queries
[simantics/platform.git] / bundles / org.simantics.diagram / src / org / simantics / diagram / synchronization / graph / AddElement.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management
3  * in 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.diagram.synchronization.graph;
13
14 import java.awt.geom.AffineTransform;
15
16 import org.simantics.databoard.Bindings;
17 import org.simantics.db.Resource;
18 import org.simantics.db.WriteGraph;
19 import org.simantics.db.common.utils.CommonDBUtils;
20 import org.simantics.db.common.utils.OrderedSetUtils;
21 import org.simantics.db.exception.DatabaseException;
22 import org.simantics.db.layer0.util.Layer0Utils;
23 import org.simantics.diagram.stubs.DiagramResource;
24 import org.simantics.diagram.synchronization.CopyAdvisor;
25 import org.simantics.diagram.synchronization.IModifiableSynchronizationContext;
26 import org.simantics.diagram.synchronization.ModificationAdapter;
27 import org.simantics.diagram.synchronization.SynchronizationHints;
28 import org.simantics.diagram.synchronization.graph.layer.GraphLayerManager;
29 import org.simantics.diagram.ui.DiagramModelHints;
30 import org.simantics.g2d.diagram.DiagramHints;
31 import org.simantics.g2d.diagram.DiagramMutator;
32 import org.simantics.g2d.diagram.IDiagram;
33 import org.simantics.g2d.element.ElementHints;
34 import org.simantics.g2d.element.ElementUtils;
35 import org.simantics.g2d.element.IElement;
36 import org.simantics.layer0.Layer0;
37
38 /**
39  * @author Tuukka Lehtonen
40  */
41 public class AddElement extends ModificationAdapter {
42
43     //private static final boolean       DEBUG_ELEMENT_COPY = false;
44
45     IModifiableSynchronizationContext context;
46     IDiagram                          diagram;
47     Resource                          diagramResource;
48     IElement                          element;
49     Resource                          copyOf;
50
51     public AddElement(IModifiableSynchronizationContext context, IDiagram d, IElement element) {
52         super(ADD_NODE_PRIORITY);
53
54         assert context != null;
55         assert d != null;
56         assert element != null;
57
58         this.context = context;
59         this.diagram = d;
60         this.diagramResource = d.getHint(DiagramModelHints.KEY_DIAGRAM_RESOURCE);
61         assert this.diagramResource != null;
62         this.element = element;
63         this.copyOf = element.getHint(ElementHints.KEY_COPY_OF_OBJECT);
64     }
65
66     @Override
67     public void perform(WriteGraph g) throws Exception {
68         BasicResources br = context.get(GraphSynchronizationHints.BASIC_RESOURCES);
69         DiagramMutator mutator = diagram.getHint(DiagramHints.KEY_MUTATOR);
70         
71         CommonDBUtils.selectClusterSet(g, diagramResource);
72
73         // 1. Resolve the element class to instantiate the new element from.
74         Resource elementClass = ElementUtils.checkedAdapt(element.getElementClass(), Resource.class);
75
76         // 2. Resolve custom element writer
77         ElementWriter writer = element.removeHint(DiagramModelHints.KEY_ELEMENT_WRITER);
78         if (writer == null)
79             writer = g.adapt(elementClass, ElementWriter.class);
80
81         Resource resource = null;
82
83         // 3. Try to copy the element from an existing element if requested.
84         if (copyOf instanceof Resource) {
85             CopyAdvisor ca = diagram.getHint(SynchronizationHints.COPY_ADVISOR);
86             if (ca != null) {
87                 Resource sourceDiagram = g.getPossibleObject(copyOf, Layer0.getInstance(g).PartOf);
88                 resource = CopyAdvisorUtil.copy(context, g, ca, copyOf, sourceDiagram, diagramResource);
89             }
90         }
91
92         if (resource == null) {
93             // Copying either was not issued or couldn't be performed.
94             // Create target resource for the new element.
95             resource = g.newResource();
96             g.claim(resource, br.L0.InstanceOf, null, elementClass);
97         }
98
99         // Add comment to change set.
100 //        CommentMetadata cm = g.getMetadata(CommentMetadata.class);
101 //        g.addMetadata(cm.add("Added element " + resource));
102
103         // 4. add the new element to the diagram composite
104         OrderedSetUtils.add(g, diagramResource, resource);
105
106         // 4.1. Give running name to element and increment the counter attached to the diagram.
107         String name = claimFreshElementName(g, diagramResource, resource);
108         
109         // Add comment to change set.
110         Layer0Utils.addCommentMetadata(g, "Added element " + name + " " + resource + " to composite " + diagramResource);
111         
112         // 4.2. Make the diagram consist of the new element
113         g.claim(diagramResource, br.L0.ConsistsOf, resource);
114
115         // 5. Synchronize the transformation of the element
116         AffineTransform at = element.getHint(ElementHints.KEY_TRANSFORM);
117         if (at != null)
118             DiagramGraphUtil.setTransform(g, resource, at);
119         
120         // 6. Perform custom per element type synchronization to graph
121         writer.addToGraph(g, element, resource);
122
123         // 7. Register the newly created element resource with mutator in case
124         // any other modification needs to reference it later on in the mutator
125         // commit process.
126         element.setHint(ElementHints.KEY_OBJECT, resource);
127         mutator.register(element, resource);
128
129         // 7. Put the element on all the currently active layers if possible.
130         GraphLayerManager glm = context.get(GraphSynchronizationHints.GRAPH_LAYER_MANAGER);
131         if (glm != null) {
132             glm.removeFromAllLayers(g, resource);
133             glm.putElementOnVisibleLayers(diagram, g, resource);
134         }
135     }
136
137 //    String findFreshName(ReadGraph graph, Resource container) throws DatabaseException {
138 //        Set<String> children = graph.syncRequest(new UnescapedChildMapOfResource(container)).keySet();
139 //        String id;
140 //        for (int i = 0; children.contains(id = String.valueOf(i)); ++i);
141 //        return id;
142 //    }
143
144     /**
145      * Names the specified element on the specified diagram based on a numeric
146      * ascending counter attached to the diagram. The purpose of the counter is
147      * to optimize name generation compared to always getting the names of each
148      * diagram element to make sure nothing collides. This method is much faster
149      * but obviously there is room for error.
150      * 
151      * @param graph
152      * @param diagram
153      * @param element
154      * @return
155      * @throws DatabaseException
156      */
157     public static final String claimFreshElementName(WriteGraph graph, Resource diagram, Resource element) throws DatabaseException {
158         Layer0 L0 = Layer0.getInstance(graph);
159         DiagramResource DIA = DiagramResource.getInstance(graph);
160         // Give running name to element and increment the counter attached to the diagram.
161         Long l = graph.getPossibleRelatedValue(diagram, DIA.HasModCount, Bindings.LONG);
162         if (l == null)
163             l = Long.valueOf(0L);
164         String name = l.toString();
165         graph.claimLiteral(element, L0.HasName, name, Bindings.STRING);
166         graph.claimLiteral(diagram, DIA.HasModCount, ++l, Bindings.LONG);
167         return name;
168     }
169
170 }