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