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