]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.modeling/src/org/simantics/modeling/adapters/CompositeCopyHandler.java
Clean up and support internal seed resources in tg export
[simantics/platform.git] / bundles / org.simantics.modeling / src / org / simantics / modeling / adapters / CompositeCopyHandler.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management
3  * in Industry THTH ry.
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
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.modeling.adapters;
13
14 import java.util.ArrayList;
15 import java.util.Collection;
16 import java.util.HashSet;
17 import java.util.List;
18 import java.util.Set;
19
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.SeedSpec;
30 import org.simantics.db.layer0.util.TransferableGraphConfiguration2.SeedSpec.SeedSpecType;
31 import org.simantics.diagram.stubs.DiagramResource;
32 import org.simantics.layer0.Layer0;
33 import org.simantics.modeling.ModelingResources;
34 import org.simantics.modeling.ModelingUtils.CompositeInfo;
35 import org.simantics.modeling.ModelingUtils.DiagramComponentInfo;
36 import org.simantics.structural.stubs.StructuralResource2;
37
38 /**
39  * @author Tuukka Lehtonen
40  */
41 public class CompositeCopyHandler extends DefaultCopyHandler {
42
43     public CompositeCopyHandler(Resource composite) {
44         super(composite);
45     }
46
47     public CompositeCopyHandler(Collection<Resource> composites) {
48         super(composites);
49     }
50
51     @Override
52     protected TransferableGraphConfiguration2 createConfiguration(ReadGraph graph, boolean cut) throws DatabaseException {
53
54         Layer0 L0 = Layer0.getInstance(graph);
55         StructuralResource2 SR = StructuralResource2.getInstance(graph);
56         DiagramResource DIA = DiagramResource.getInstance(graph);
57         ModelingResources MOD = ModelingResources.getInstance(graph);
58
59         Set<Resource> resourceSet = (resources instanceof Set)
60                 ? (Set<Resource>) resources : new HashSet<>(resources);
61         Set<Resource> exclusions = new HashSet<>();
62         Set<Resource> externals = new HashSet<>();
63         List<SeedSpec> roots = new ArrayList<>();
64
65         Resource indexRoot = graph.syncRequest(new PossibleIndexRoot(resources.iterator().next()));
66         if(indexRoot == null) throw new DatabaseException("Composite is not part of any index root");
67         String indexRootUri = graph.getURI(indexRoot);
68
69         DbConsumer<Resource> identifierExcluder = r -> {
70             if (r != null)
71                 exclusions.addAll(graph.getObjects(r, L0.identifier));
72         };
73
74         for(Resource resource : resources) {
75             // Process all connection joins.
76             // This is the only way to access all of them.
77             for (Resource diagram : graph.getObjects(resource, MOD.CompositeToDiagram)) {
78                 identifierExcluder.accept(diagram);
79
80                 for (Resource element : graph.getObjects(diagram, L0.ConsistsOf)) {
81                     identifierExcluder.accept(element);
82
83                     Set<Resource> types = graph.getTypes(element);
84
85                     // Check all diagram flag elements for necessary exclusions.
86                     if (types.contains(DIA.Flag)) {
87                         for (Resource join : graph.getObjects(element, DIA.FlagIsJoinedBy)) {
88                             // Joins with external references are omitted
89                             for (Resource comp : graph.getObjects(join, SR.JoinsComposite)) {
90                                 if (!resourceSet.contains(comp))
91                                     exclusions.add(join);
92                             }
93                             // This code excludes joins with flags to external
94                             // diagrams that are not connected (have no
95                             // configuration for the flag)
96                             for (Resource flag2 : graph.getObjects(join, DIA.JoinsFlag)) {
97                                 Resource diagram2 = graph.getPossibleObject(flag2, L0.PartOf);
98                                 if (diagram2 != null) {
99                                     Resource comp = graph.getPossibleObject(diagram2, MOD.DiagramToComposite);
100                                     if (!resourceSet.contains(comp))
101                                         exclusions.add(join); 
102                                 }
103                             }
104                         }
105                     }
106
107                     // Check all diagram monitor elements.
108                     // Any components referenced that are external to the exported diagrams must be excluded from the export.
109                     // This will leave the monitors without a monitored component but export and import will work anyway.
110                     if (types.contains(DIA.Monitor)) {
111                         for (Resource monitoredComponent : graph.getObjects(element, DIA.HasMonitorComponent)) {
112                             Resource monitoredComponentComposite = graph.getPossibleObject(monitoredComponent, L0.PartOf);
113                             if (monitoredComponentComposite != null && !resourceSet.contains(monitoredComponentComposite)) {
114                                 exclusions.add(monitoredComponent);
115                             }
116                         }
117                     }
118
119                     // Check all diagram reference elements for necessary exclusions.
120                     if (types.contains(MOD.ReferenceElement)) {
121                         for (Resource rel : graph.getObjects(element, L0.ConsistsOf)) {
122                             identifierExcluder.accept(rel);
123                             for (Resource invRel : graph.getObjects(rel, L0.ConsistsOf)) {
124                                 identifierExcluder.accept(invRel);
125                             }
126                         }
127                     }
128                 }
129             }
130
131             // Leave any diagram monitors out of the export that are contained
132             // by diagrams that are not part of this export, when the monitored
133             // components happen to be a part of the exported composites.
134             for (Resource ref : graph.syncRequest(new ObjectsWithType(resource, L0.ConsistsOf, SR.Component))) {
135                 for (Resource monitor : graph.getObjects(ref, DIA.HasMonitorComponent_Inverse)) {
136                     Resource monitorDiagram = graph.getPossibleObject(monitor, L0.PartOf);
137                     if (monitorDiagram != null) {
138                         Resource monitorComposite = graph.getPossibleObject(monitorDiagram, MOD.DiagramToComposite);
139                         if (monitorComposite != null && !resourceSet.contains(monitorComposite))
140                             exclusions.add(monitor);
141                     }
142                 }
143             }
144
145             // Include resource as root
146             CompositeInfo info = CompositeInfo.fromResource(graph, resource);
147             roots.add(new SeedSpec(resource, info.getTGName(), SeedSpecType.ROOT, typeId(graph, L0, indexRootUri, resource)));
148             identifierExcluder.accept(resource);
149             // Include components as roots
150             for (Resource child : graph.sync(new ObjectsWithType(resource, L0.ConsistsOf, SR.Component))) {
151                 DiagramComponentInfo cinfo = DiagramComponentInfo.fromResource(graph, info, child);
152                 identifierExcluder.accept(child);
153                 roots.add(new SeedSpec(child, cinfo.getTGName(info), SeedSpecType.ROOT, typeId(graph, L0, indexRootUri, child)));
154             }
155         }
156
157         roots.add(new SeedSpec(indexRoot, "%model", SeedSpecType.SPECIAL_ROOT));
158
159         TransferableGraphConfiguration2 config = TransferableGraphConfiguration2.createWithNames2(graph, roots, exclusions, true, false);
160         for (Resource external : externals)
161             config.preStatus.put(external, ExtentStatus.EXTERNAL);
162         return config;
163     }
164
165     private static String typeId(ReadGraph graph, Layer0 L0, String indexRootUri, Resource r) throws DatabaseException {
166         Resource type = graph.getPossibleType(r, L0.Entity);
167         if (type == null)
168             return Layer0.URIs.Entity;
169         String typeUri = graph.getPossibleURI(type);
170         if (typeUri == null || !typeUri.startsWith(indexRootUri))
171             return typeUri;
172         return "%model" + typeUri.substring(indexRootUri.length());
173     }
174
175 }