--- /dev/null
+package org.simantics.modeling.mapping;\r
+\r
+import java.util.HashMap;\r
+import java.util.Map;\r
+\r
+import org.simantics.databoard.Bindings;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.WriteOnlyGraph;\r
+import org.simantics.db.common.request.FreshEscapedName;\r
+import org.simantics.db.common.utils.OrderedSetUtils;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.layer0.request.PossibleModel;\r
+import org.simantics.diagram.stubs.DiagramResource;\r
+import org.simantics.diagram.stubs.G2DResource;\r
+import org.simantics.graph.db.IImportAdvisor;\r
+import org.simantics.graph.representation.Root;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.modeling.ModelingResources;\r
+\r
+/**\r
+ * ImportAdvisor for handling Component and Element copies.\r
+ * \r
+ * The advisor can be configured to copy just component or element.\r
+ * \r
+ * When copying a component, handling the element many vary:\r
+ * 1. If copied data does not contain element, but the target composite is attached to a diagram, the advisor creates the element.\r
+ * 2. If copied data contains element, but target composite is not attached to a diagram, the advisor deletes the element. \r
+ * \r
+ * \r
+ * @author Marko Luukkainen <marko.luukkainen@vtt.fi>\r
+ *\r
+ */\r
+public class ComponentAndElementPasteImportAdvisor implements IImportAdvisor {\r
+ \r
+ private static boolean DEBUG = false;\r
+ \r
+ protected Resource element;\r
+ protected Resource component;\r
+ \r
+ protected Root elementRoot;\r
+ protected Root componentRoot;\r
+ \r
+ protected Resource composite;\r
+ protected Resource diagram;\r
+ protected Resource model;\r
+ \r
+ protected Map<String, String> nameMappings = new HashMap<String, String>();\r
+ \r
+ protected boolean includeComponent = true;\r
+ protected boolean includeElement = true;\r
+ \r
+ public ComponentAndElementPasteImportAdvisor(ReadGraph graph, Resource composite) throws DatabaseException{\r
+ this.composite = composite;\r
+ this.diagram = graph.getPossibleObject(composite, ModelingResources.getInstance(graph).CompositeToDiagram);\r
+ this.includeElement = diagram != null;\r
+ this.model = graph.sync(new PossibleModel(composite));\r
+ }\r
+ \r
+ public ComponentAndElementPasteImportAdvisor(ReadGraph graph, Resource resource, boolean includeComponent, boolean includeElement) throws DatabaseException{\r
+ if (!includeComponent && !includeElement)\r
+ throw new IllegalArgumentException();\r
+ \r
+ this.includeComponent = includeComponent;\r
+ this.includeElement = includeElement;\r
+ if (includeComponent) {\r
+ this.composite = resource;\r
+ this.diagram = graph.getPossibleObject(composite, ModelingResources.getInstance(graph).CompositeToDiagram);\r
+ if (this.diagram == null)\r
+ this.includeElement = false;\r
+ } else {\r
+ this.diagram = resource;\r
+ this.composite = graph.getPossibleObject(diagram, ModelingResources.getInstance(graph).DiagramToComposite);\r
+ }\r
+ \r
+ }\r
+ \r
+ @Override\r
+ public Resource analyzeRoot(ReadGraph graph, Root root) throws DatabaseException {\r
+\r
+ if("%model".equals(root.name)) return model;\r
+ \r
+ DiagramResource DIA = DiagramResource.getInstance(graph);\r
+ String type = root.type;\r
+ \r
+ Resource typeRes = graph.getResource(type);\r
+ if (graph.isInheritedFrom(typeRes, DIA.Element)) {\r
+ elementRoot = root;\r
+ String newName = root.name;\r
+ if (diagram != null)\r
+ newName = newName(graph, diagram, root.name);\r
+ nameMappings.put(root.name, newName);\r
+ } else {\r
+ componentRoot = root;\r
+ String newName = newName(graph, composite, root.name);\r
+ nameMappings.put(root.name, newName);\r
+ }\r
+ \r
+ return null;\r
+ \r
+ }\r
+ \r
+ public String newName(ReadGraph graph, Resource library, String name) throws DatabaseException {\r
+ return graph.syncRequest(new FreshEscapedName(library, Layer0.getInstance(graph).ConsistsOf, name));\r
+ }\r
+ \r
+ public Resource getComponent() {\r
+ return component;\r
+ }\r
+ \r
+ public Resource getElement() {\r
+ return element;\r
+ }\r
+ \r
+ @Override\r
+ public Resource createRoot(WriteOnlyGraph graph, Root root)\r
+ throws DatabaseException {\r
+ Layer0 l0 = graph.getService(Layer0.class);\r
+ if (root == elementRoot) {\r
+ element = graph.newResource();\r
+ String name = root.name;\r
+ String newName = nameMappings.get(name);\r
+ graph.addLiteral(element, l0.HasName, l0.NameOf, l0.String, newName, Bindings.STRING);\r
+ if (DEBUG) System.out.println("CaECopyAdvisor created element " + element + " " + newName);\r
+ return element;\r
+ } else if (root == componentRoot) {\r
+ component = graph.newResource();\r
+ String name = root.name;\r
+ String newName = nameMappings.get(name);\r
+ graph.addLiteral(component, l0.HasName, l0.NameOf, l0.String, newName, Bindings.STRING);\r
+ if (DEBUG) System.out.println("CaECopyAdvisor created component " + component + " " + newName);\r
+ return component;\r
+ }\r
+ throw new DatabaseException("Unknown root " + root);\r
+ }\r
+ \r
+ /**\r
+ * Attaches pasted component / element to composite / diagram\r
+ * @param graph\r
+ * @throws DatabaseException\r
+ */\r
+ public void attach(WriteGraph graph) throws DatabaseException{\r
+ Layer0 l0 = Layer0.getInstance(graph);\r
+ if (includeComponent) {\r
+ if (component != null)\r
+ graph.claim(composite, l0.ConsistsOf, l0.PartOf, component);\r
+ } else {\r
+ if (component != null)\r
+ graph.deny(component);\r
+ }\r
+ if (!includeElement) {\r
+ // paste target does not need the element.\r
+ if (element != null) {\r
+ graph.deny(element);\r
+ }\r
+ } else {\r
+ // paste target needs the element.\r
+ boolean created = false;\r
+ if (element == null) {\r
+ // element was not in the copied data, we must create a new one.\r
+ \r
+ ModelingResources MR = ModelingResources.getInstance(graph);\r
+ DiagramResource DIA = DiagramResource.getInstance(graph);\r
+ G2DResource G2D = G2DResource.getInstance(graph);\r
+ \r
+ Resource componentType = graph.getSingleType(component);\r
+ Resource elementType = graph.getSingleObject(componentType, MR.ComponentTypeToSymbol);\r
+ \r
+ element = graph.newResource();\r
+ \r
+ String newName = newName(graph, diagram, "element");\r
+ graph.claimLiteral(element, l0.HasName, newName);\r
+ \r
+ graph.claim(element, l0.InstanceOf, elementType);\r
+ graph.claim(component, MR.ComponentToElement, element);\r
+ \r
+ graph.claimLiteral(element, DIA.HasTransform, G2D.Transform, new double[]{1,0,0,1,0,0});\r
+ \r
+ if (DEBUG) System.out.println("CaECopyAdvisor created deferred element " + element + " " + newName);\r
+ \r
+ created = true;\r
+ }\r
+ graph.claim(diagram, l0.ConsistsOf, l0.PartOf, element);\r
+ OrderedSetUtils.add(graph, diagram, element);\r
+ if (created) {\r
+ createElement(graph, element);\r
+ }\r
+ }\r
+\r
+ }\r
+ \r
+ /**\r
+ * Callback called, if copied data did not contain element, and the advisor had to create the element by itself.\r
+ * \r
+ * Note: default implementation does nothing.\r
+ * \r
+ * @param graph\r
+ * @param element\r
+ * @throws DatabaseException\r
+ */\r
+ public void createElement(WriteGraph graph, Resource element) throws DatabaseException{\r
+ \r
+ }\r
+ \r
+\r
+}\r