]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - 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
diff --git a/bundles/org.simantics.diagram/src/org/simantics/diagram/synchronization/graph/AddElement.java b/bundles/org.simantics.diagram/src/org/simantics/diagram/synchronization/graph/AddElement.java
new file mode 100644 (file)
index 0000000..05d2d1e
--- /dev/null
@@ -0,0 +1,170 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in 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.diagram.synchronization.graph;\r
+\r
+import java.awt.geom.AffineTransform;\r
+\r
+import org.simantics.databoard.Bindings;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.common.utils.CommonDBUtils;\r
+import org.simantics.db.common.utils.OrderedSetUtils;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.layer0.util.Layer0Utils;\r
+import org.simantics.diagram.stubs.DiagramResource;\r
+import org.simantics.diagram.synchronization.CopyAdvisor;\r
+import org.simantics.diagram.synchronization.IModifiableSynchronizationContext;\r
+import org.simantics.diagram.synchronization.ModificationAdapter;\r
+import org.simantics.diagram.synchronization.SynchronizationHints;\r
+import org.simantics.diagram.synchronization.graph.layer.GraphLayerManager;\r
+import org.simantics.diagram.ui.DiagramModelHints;\r
+import org.simantics.g2d.diagram.DiagramHints;\r
+import org.simantics.g2d.diagram.DiagramMutator;\r
+import org.simantics.g2d.diagram.IDiagram;\r
+import org.simantics.g2d.element.ElementHints;\r
+import org.simantics.g2d.element.ElementUtils;\r
+import org.simantics.g2d.element.IElement;\r
+import org.simantics.layer0.Layer0;\r
+\r
+/**\r
+ * @author Tuukka Lehtonen\r
+ */\r
+public class AddElement extends ModificationAdapter {\r
+\r
+    //private static final boolean       DEBUG_ELEMENT_COPY = false;\r
+\r
+    IModifiableSynchronizationContext context;\r
+    IDiagram                          diagram;\r
+    Resource                          diagramResource;\r
+    IElement                          element;\r
+    Resource                          copyOf;\r
+\r
+    public AddElement(IModifiableSynchronizationContext context, IDiagram d, IElement element) {\r
+        super(ADD_NODE_PRIORITY);\r
+\r
+        assert context != null;\r
+        assert d != null;\r
+        assert element != null;\r
+\r
+        this.context = context;\r
+        this.diagram = d;\r
+        this.diagramResource = d.getHint(DiagramModelHints.KEY_DIAGRAM_RESOURCE);\r
+        assert this.diagramResource != null;\r
+        this.element = element;\r
+        this.copyOf = element.getHint(ElementHints.KEY_COPY_OF_OBJECT);\r
+    }\r
+\r
+    @Override\r
+    public void perform(WriteGraph g) throws Exception {\r
+        BasicResources br = context.get(GraphSynchronizationHints.BASIC_RESOURCES);\r
+        DiagramMutator mutator = diagram.getHint(DiagramHints.KEY_MUTATOR);\r
+        \r
+        CommonDBUtils.selectClusterSet(g, diagramResource);\r
+\r
+        // 1. Resolve the element class to instantiate the new element from.\r
+        Resource elementClass = ElementUtils.checkedAdapt(element.getElementClass(), Resource.class);\r
+\r
+        // 2. Resolve custom element writer\r
+        ElementWriter writer = element.removeHint(DiagramModelHints.KEY_ELEMENT_WRITER);\r
+        if (writer == null)\r
+            writer = g.adapt(elementClass, ElementWriter.class);\r
+\r
+        Resource resource = null;\r
+\r
+        // 3. Try to copy the element from an existing element if requested.\r
+        if (copyOf instanceof Resource) {\r
+            CopyAdvisor ca = diagram.getHint(SynchronizationHints.COPY_ADVISOR);\r
+            if (ca != null) {\r
+                Resource sourceDiagram = g.getPossibleObject(copyOf, Layer0.getInstance(g).PartOf);\r
+                resource = CopyAdvisorUtil.copy(context, g, ca, copyOf, sourceDiagram, diagramResource);\r
+            }\r
+        }\r
+\r
+        if (resource == null) {\r
+            // Copying either was not issued or couldn't be performed.\r
+            // Create target resource for the new element.\r
+            resource = g.newResource();\r
+            g.claim(resource, br.L0.InstanceOf, null, elementClass);\r
+        }\r
+\r
+        // Add comment to change set.\r
+//        CommentMetadata cm = g.getMetadata(CommentMetadata.class);\r
+//        g.addMetadata(cm.add("Added element " + resource));\r
+\r
+        // 4. add the new element to the diagram composite\r
+        OrderedSetUtils.add(g, diagramResource, resource);\r
+\r
+        // 4.1. Give running name to element and increment the counter attached to the diagram.\r
+        String name = claimFreshElementName(g, diagramResource, resource);\r
+        \r
+        // Add comment to change set.\r
+        Layer0Utils.addCommentMetadata(g, "Added element " + name + " " + resource + " to composite " + diagramResource);\r
+        \r
+        // 4.2. Make the diagram consist of the new element\r
+        g.claim(diagramResource, br.L0.ConsistsOf, resource);\r
+\r
+        // 5. Synchronize the transformation of the element\r
+        AffineTransform at = element.getHint(ElementHints.KEY_TRANSFORM);\r
+        if (at != null)\r
+            DiagramGraphUtil.setTransform(g, resource, at);\r
+        \r
+        // 6. Perform custom per element type synchronization to graph\r
+        writer.addToGraph(g, element, resource);\r
+\r
+        // 7. Register the newly created element resource with mutator in case\r
+        // any other modification needs to reference it later on in the mutator\r
+        // commit process.\r
+        element.setHint(ElementHints.KEY_OBJECT, resource);\r
+        mutator.register(element, resource);\r
+\r
+        // 7. Put the element on all the currently active layers if possible.\r
+        GraphLayerManager glm = context.get(GraphSynchronizationHints.GRAPH_LAYER_MANAGER);\r
+        if (glm != null) {\r
+            glm.removeFromAllLayers(g, resource);\r
+            glm.putElementOnVisibleLayers(diagram, g, resource);\r
+        }\r
+    }\r
+\r
+//    String findFreshName(ReadGraph graph, Resource container) throws DatabaseException {\r
+//        Set<String> children = graph.syncRequest(new UnescapedChildMapOfResource(container)).keySet();\r
+//        String id;\r
+//        for (int i = 0; children.contains(id = String.valueOf(i)); ++i);\r
+//        return id;\r
+//    }\r
+\r
+    /**\r
+     * Names the specified element on the specified diagram based on a numeric\r
+     * ascending counter attached to the diagram. The purpose of the counter is\r
+     * to optimize name generation compared to always getting the names of each\r
+     * diagram element to make sure nothing collides. This method is much faster\r
+     * but obviously there is room for error.\r
+     * \r
+     * @param graph\r
+     * @param diagram\r
+     * @param element\r
+     * @return\r
+     * @throws DatabaseException\r
+     */\r
+    public static final String claimFreshElementName(WriteGraph graph, Resource diagram, Resource element) throws DatabaseException {\r
+        Layer0 L0 = Layer0.getInstance(graph);\r
+        DiagramResource DIA = DiagramResource.getInstance(graph);\r
+        // Give running name to element and increment the counter attached to the diagram.\r
+        Long l = graph.getPossibleRelatedValue(diagram, DIA.HasModCount, Bindings.LONG);\r
+        if (l == null)\r
+            l = Long.valueOf(0L);\r
+        String name = l.toString();\r
+        graph.claimLiteral(element, L0.HasName, name, Bindings.STRING);\r
+        graph.claimLiteral(diagram, DIA.HasModCount, ++l, Bindings.LONG);\r
+        return name;\r
+    }\r
+\r
+}
\ No newline at end of file