1 /*******************************************************************************
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
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
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.modeling.adapters;
14 import java.util.ArrayList;
15 import java.util.Collection;
16 import java.util.HashSet;
17 import java.util.List;
20 import org.simantics.db.ReadGraph;
21 import org.simantics.db.Resource;
22 import org.simantics.db.common.request.ObjectsWithType;
23 import org.simantics.db.common.request.PossibleIndexRoot;
24 import org.simantics.db.exception.DatabaseException;
25 import org.simantics.db.function.DbConsumer;
26 import org.simantics.db.layer0.adapter.SubgraphExtent.ExtentStatus;
27 import org.simantics.db.layer0.adapter.impl.DefaultCopyHandler;
28 import org.simantics.db.layer0.util.TransferableGraphConfiguration2;
29 import org.simantics.db.layer0.util.TransferableGraphConfiguration2.RootSpec;
30 import org.simantics.diagram.stubs.DiagramResource;
31 import org.simantics.layer0.Layer0;
32 import org.simantics.modeling.ModelingResources;
33 import org.simantics.modeling.ModelingUtils.CompositeInfo;
34 import org.simantics.modeling.ModelingUtils.DiagramComponentInfo;
35 import org.simantics.structural.stubs.StructuralResource2;
38 * @author Tuukka Lehtonen
40 public class CompositeCopyHandler extends DefaultCopyHandler {
42 public CompositeCopyHandler(Resource composite) {
46 public CompositeCopyHandler(Collection<Resource> composites) {
51 protected TransferableGraphConfiguration2 createConfiguration(ReadGraph graph, boolean cut) throws DatabaseException {
53 Layer0 L0 = Layer0.getInstance(graph);
54 StructuralResource2 SR = StructuralResource2.getInstance(graph);
55 DiagramResource DIA = DiagramResource.getInstance(graph);
56 ModelingResources MOD = ModelingResources.getInstance(graph);
58 Set<Resource> resourceSet = (resources instanceof Set)
59 ? (Set<Resource>) resources : new HashSet<>(resources);
60 Set<Resource> exclusions = new HashSet<>();
61 Set<Resource> externals = new HashSet<>();
62 List<RootSpec> roots = new ArrayList<>();
64 Resource indexRoot = graph.syncRequest(new PossibleIndexRoot(resources.iterator().next()));
65 if(indexRoot == null) throw new DatabaseException("Composite is not part of any index root");
66 String indexRootUri = graph.getURI(indexRoot);
68 DbConsumer<Resource> identifierExcluder = r -> {
70 exclusions.addAll(graph.getObjects(r, L0.identifier));
73 for(Resource resource : resources) {
74 // Process all connection joins.
75 // This is the only way to access all of them.
76 for (Resource diagram : graph.getObjects(resource, MOD.CompositeToDiagram)) {
77 identifierExcluder.accept(diagram);
79 for (Resource element : graph.getObjects(diagram, L0.ConsistsOf)) {
80 identifierExcluder.accept(element);
82 Set<Resource> types = graph.getTypes(element);
84 // Check all diagram flag elements for necessary exclusions.
85 if (types.contains(DIA.Flag)) {
86 for (Resource join : graph.getObjects(element, DIA.FlagIsJoinedBy)) {
87 // Joins with external references are omitted
88 for (Resource comp : graph.getObjects(join, SR.JoinsComposite)) {
89 if (!resourceSet.contains(comp))
92 // This code excludes joins with flags to external
93 // diagrams that are not connected (have no
94 // configuration for the flag)
95 for (Resource flag2 : graph.getObjects(join, DIA.JoinsFlag)) {
96 Resource diagram2 = graph.getPossibleObject(flag2, L0.PartOf);
97 if (diagram2 != null) {
98 Resource comp = graph.getPossibleObject(diagram2, MOD.DiagramToComposite);
99 if (!resourceSet.contains(comp))
100 exclusions.add(join);
106 // Check all diagram monitor elements.
107 // Any components referenced that are external to the exported diagrams must be excluded from the export.
108 // This will leave the monitors without a monitored component but export and import will work anyway.
109 if (types.contains(DIA.Monitor)) {
110 for (Resource monitoredComponent : graph.getObjects(element, DIA.HasMonitorComponent)) {
111 Resource monitoredComponentComposite = graph.getPossibleObject(monitoredComponent, L0.PartOf);
112 if (monitoredComponentComposite != null && !resourceSet.contains(monitoredComponentComposite)) {
113 exclusions.add(monitoredComponent);
118 // Check all diagram reference elements for necessary exclusions.
119 if (types.contains(MOD.ReferenceElement)) {
120 for (Resource rel : graph.getObjects(element, L0.ConsistsOf)) {
121 identifierExcluder.accept(rel);
122 for (Resource invRel : graph.getObjects(rel, L0.ConsistsOf)) {
123 identifierExcluder.accept(invRel);
130 // Leave any diagram monitors out of the export that are contained
131 // by diagrams that are not part of this export, when the monitored
132 // components happen to be a part of the exported composites.
133 for (Resource ref : graph.syncRequest(new ObjectsWithType(resource, L0.ConsistsOf, SR.Component))) {
134 for (Resource monitor : graph.getObjects(ref, DIA.HasMonitorComponent_Inverse)) {
135 Resource monitorDiagram = graph.getPossibleObject(monitor, L0.PartOf);
136 if (monitorDiagram != null) {
137 Resource monitorComposite = graph.getPossibleObject(monitorDiagram, MOD.DiagramToComposite);
138 if (monitorComposite != null && !resourceSet.contains(monitorComposite))
139 exclusions.add(monitor);
144 // Include resource as root
145 CompositeInfo info = CompositeInfo.fromResource(graph, resource);
146 roots.add(new RootSpec(resource, info.getTGName(), true, typeId(graph, L0, indexRootUri, resource)));
147 identifierExcluder.accept(resource);
148 // Include components as roots
149 for (Resource child : graph.sync(new ObjectsWithType(resource, L0.ConsistsOf, SR.Component))) {
150 DiagramComponentInfo cinfo = DiagramComponentInfo.fromResource(graph, info, child);
151 identifierExcluder.accept(child);
152 roots.add(new RootSpec(child, cinfo.getTGName(info), true, typeId(graph, L0, indexRootUri, child)));
156 roots.add(new RootSpec(indexRoot, "%model", false));
158 TransferableGraphConfiguration2 config = TransferableGraphConfiguration2.createWithNames2(graph, roots, exclusions, true, false);
159 for (Resource external : externals)
160 config.preStatus.put(external, ExtentStatus.EXTERNAL);
164 private static String typeId(ReadGraph graph, Layer0 L0, String indexRootUri, Resource r) throws DatabaseException {
165 Resource type = graph.getPossibleType(r, L0.Entity);
167 return Layer0.URIs.Entity;
168 String typeUri = graph.getPossibleURI(type);
169 if (typeUri == null || !typeUri.startsWith(indexRootUri))
171 return "%model" + typeUri.substring(indexRootUri.length());