]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.modeling/src/org/simantics/modeling/MigrateModel.java
eb0b80709b70094fcdfff1f5900a70f35d0dee2e
[simantics/platform.git] / bundles / org.simantics.modeling / src / org / simantics / modeling / MigrateModel.java
1 /*******************************************************************************
2  * Copyright (c) 2014, 2015 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  *     Semantum Oy - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.modeling;
13
14 import gnu.trove.set.hash.THashSet;
15
16 import java.util.ArrayList;
17 import java.util.Collection;
18 import java.util.Collections;
19 import java.util.List;
20 import java.util.Set;
21
22 import org.simantics.databoard.Bindings;
23 import org.simantics.databoard.util.URIStringUtils;
24 import org.simantics.db.ReadGraph;
25 import org.simantics.db.Resource;
26 import org.simantics.db.Statement;
27 import org.simantics.db.WriteGraph;
28 import org.simantics.db.common.NamedResource;
29 import org.simantics.db.common.utils.NameUtils;
30 import org.simantics.db.exception.DatabaseException;
31 import org.simantics.db.layer0.adapter.Instances;
32 import org.simantics.db.layer0.util.Layer0Utils;
33 import org.simantics.diagram.stubs.DiagramResource;
34 import org.simantics.layer0.Layer0;
35 import org.simantics.structural.stubs.StructuralResource2;
36 import org.simantics.structural2.modelingRules.AllowedConnectionTypes;
37 import org.simantics.utils.ObjectUtils;
38 import org.simantics.utils.datastructures.Triple;
39
40 /**
41  * @author Antti Villberg
42  */
43 public class MigrateModel {
44
45         public static class MigrationOperation {
46                 
47                 public NamedResource instanceToMigrate;
48                 public NamedResource targetType;
49                 public NamedResource targetSymbol;
50                 
51                 public MigrationOperation(NamedResource nr, NamedResource targetType, NamedResource targetSymbol) {
52                         this.instanceToMigrate = nr;
53                         this.targetType = targetType;
54                         this.targetSymbol = targetSymbol;
55                 }
56                 
57                 @Override
58                 public String toString() {
59                         return instanceToMigrate.getName();
60                 }
61                 
62                 public String getDescription(ReadGraph graph) throws DatabaseException {
63                         String sourceURI = graph.getPossibleURI(instanceToMigrate.getResource());
64                         if(sourceURI == null) sourceURI = NameUtils.getSafeName(graph, instanceToMigrate.getResource());
65                         sourceURI = sourceURI.replace("http://Projects/Development%20Project/", "");
66                         if(targetSymbol != null) {
67                                 String targetURI = graph.getURI(targetSymbol.getResource());
68                                 return URIStringUtils.unescape(sourceURI) + " into " + URIStringUtils.unescape(targetURI);
69                         } else {
70                                 String targetURI = graph.getURI(targetType.getResource());
71                                 return URIStringUtils.unescape(sourceURI) + " into " + URIStringUtils.unescape(targetURI);
72                         }
73                 }
74                 
75                 private Resource getPossibleReplacement(ReadGraph graph, Resource type, Resource predicate) throws DatabaseException {
76                         Layer0 L0 = Layer0.getInstance(graph);
77                         String name = graph.getPossibleRelatedValue(predicate, L0.HasName, Bindings.STRING);
78                         if(name == null) return null;
79                         Resource child = Layer0Utils.getPossibleChild(graph, type, name);
80                         if(child != null) return child;
81                         for(Resource r : graph.getObjects(type, L0.DomainOf)) {
82                                 String rName = graph.getPossibleRelatedValue(r, L0.HasName, Bindings.STRING);
83                                 if(name.equals(rName)) return r;
84                         }
85                         return null; 
86                 }
87                 
88                 public String replace(WriteGraph graph, Resource instanceToMigrate, Resource type) throws DatabaseException {
89
90                         Layer0 L0 = Layer0.getInstance(graph);
91                         StructuralResource2 STR = StructuralResource2.getInstance(graph);
92
93                         Collection<Resource> currentTypes = graph.getPrincipalTypes(instanceToMigrate);
94                         if(currentTypes.size() == 1 && currentTypes.contains(type)) return null;
95                         
96                         StringBuilder problems = new StringBuilder();
97                         
98                         // Validate operation
99                         for(Statement stm : graph.getStatements(instanceToMigrate, L0.IsWeaklyRelatedTo)) {
100
101                                 Resource predicate = stm.getPredicate();
102                                 if(stm.isAsserted(instanceToMigrate)) continue;
103                                 
104                                 if(graph.isInstanceOf(predicate, STR.Property)) {
105                                         Resource replacement = getPossibleReplacement(graph, type, predicate);
106                                         // OK for a property to disappear
107                                         if(replacement == null) continue;
108                                         if(!graph.isInstanceOf(replacement, STR.Property)) {
109                                                 String name = graph.getRelatedValue(predicate, L0.HasName, Bindings.STRING);
110                                                 problems.append(" " + name + " was a property in the source type\n");
111                                                 continue;
112                                         }
113                                         String sourceValueType = graph.getPossibleRelatedValue(predicate, L0.RequiresValueType, Bindings.STRING);
114                                         String replacementValueType = graph.getPossibleRelatedValue(replacement, L0.RequiresValueType, Bindings.STRING);
115                                         if(!ObjectUtils.objectEquals(sourceValueType, replacementValueType)) {
116                                                 String name = graph.getRelatedValue(predicate, L0.HasName, Bindings.STRING);
117                                                 problems.append(" value types for property " + name + " differ (" + sourceValueType + " vs. " + replacementValueType + ")\n");
118                                                 continue;
119                                         }
120                                 }
121
122                                 if(graph.isInstanceOf(predicate, STR.ConnectionRelation)) {
123                                         Resource replacement = getPossibleReplacement(graph, type, predicate);
124                                         if(replacement == null) {
125                                                 String name = graph.getRelatedValue(predicate, L0.HasName, Bindings.STRING);
126                                                 problems.append(" used connection point " + name + " has been removed from target type\n");
127                                                 continue;
128                                         }
129                                         if(!graph.isInstanceOf(replacement, STR.ConnectionRelation)) {
130                                                 String name = graph.getRelatedValue(predicate, L0.HasName, Bindings.STRING);
131                                                 problems.append(" " + name + " was a connection point in the source type\n");
132                                                 continue;
133                                         }
134
135                                         Collection<Resource> sourceConnetionTypes = graph.syncRequest(new AllowedConnectionTypes(predicate));
136                                         Collection<Resource> replacementConnectionTypes = graph.syncRequest(new AllowedConnectionTypes(replacement));
137                                         
138                                         Set<Resource> sourceSet = new THashSet<>(sourceConnetionTypes);
139                                         Set<Resource> replacementSet = new THashSet<>(replacementConnectionTypes);
140                                         
141                                         if(!sourceSet.equals(replacementSet)) {
142                                                 String name = graph.getRelatedValue(predicate, L0.HasName, Bindings.STRING);
143                                                 problems.append(" allowed connection types for connection point " + name + " differ (" + NameUtils.getSafeName(graph, sourceSet) + " vs. " + NameUtils.getSafeName(graph, replacementSet) + ")\n");
144                                                 continue;
145                                         }
146
147                                 }
148                                 
149                         }
150                         
151                         if(problems.length() > 0) {
152                                 return problems.toString();
153                         }
154
155                         // Perform operation
156                         for(Statement stm : graph.getStatements(instanceToMigrate, L0.IsWeaklyRelatedTo)) {
157
158                                 Resource predicate = stm.getPredicate();
159                                 if(stm.isAsserted(instanceToMigrate)) continue;
160                                                 
161                                 if(L0.InstanceOf.equals(predicate)) {
162                                         graph.deny(stm);
163                                         graph.claim(instanceToMigrate, L0.InstanceOf, type);
164                                 }
165                                 
166                                 if(graph.isInstanceOf(predicate, STR.Property) || graph.isInstanceOf(predicate, STR.ConnectionRelation)) {
167                                         Resource replacement = getPossibleReplacement(graph, type, predicate);
168                                         graph.deny(stm);
169                                         if(replacement == null) continue;
170                                         graph.claim(stm.getSubject(), replacement, stm.getObject());
171                                 }
172                                 
173                         }
174                         
175                         return null;
176
177                 }
178                 
179                 public String perform(WriteGraph graph) throws DatabaseException {
180                         
181                         Resource instance = instanceToMigrate.getResource();
182                         Resource type = targetType.getResource();
183                         Resource symbol = targetSymbol != null ? targetSymbol.getResource() : null;
184                         
185                         String result = replace(graph, instance, type);
186                         if(result != null) return result;
187                         
188                         ModelingResources MOD = ModelingResources.getInstance(graph);
189                         Resource element = graph.getPossibleObject(instance, MOD.ComponentToElement);
190                         if(element == null) return null;
191                         
192                         Resource targetSymbol = symbol;
193                         if(targetSymbol == null) {
194                                 Layer0 L0 = Layer0.getInstance(graph);
195                                 DiagramResource DIA = DiagramResource.getInstance(graph);
196                                 Resource currentSymbol = graph.getPossibleType(element, DIA.Element);
197                                 if(currentSymbol != null) {
198                                         String currentSymbolName = graph.getRelatedValue(currentSymbol, L0.HasName, Bindings.STRING);
199                                         targetSymbol = Layer0Utils.getPossibleChild(graph, type, DIA.ElementClass, currentSymbolName);
200                                         if(targetSymbol == null)
201                                                 return "Did not find symbol '" + currentSymbolName + "' from target type.\n";
202                                 } else {
203                                         // No symbol - fine 
204                                         return null;
205                                 }
206
207                         }
208                         
209                         return replace(graph, element, targetSymbol);
210                         
211                 }
212                 
213         }
214
215         public int instanceCount = 0;
216         public Set<Resource> activeModels = new THashSet<>();
217         public List<Triple<String, NamedResource, Collection<MigrationOperation>>> instances = new ArrayList<>();
218         public List<MigrationOperation> sortedShownInstances = Collections.emptyList();
219
220         public static void changeComponentType(WriteGraph graph, Resource instance, Resource newComponentType) throws DatabaseException {
221             ModelingResources MOD = ModelingResources.getInstance(graph);
222             Resource newSymbol = graph.getSingleObject(newComponentType, MOD.ComponentTypeToSymbol);
223             new MigrationOperation(new NamedResource("", instance), new NamedResource("", newComponentType), new NamedResource("", newSymbol))
224             .perform(graph);
225         }
226
227         public static void changeAllComponentTypes(WriteGraph graph, Resource model, Resource oldComponentType, Resource newComponentType) throws DatabaseException {
228             ModelingResources MOD = ModelingResources.getInstance(graph);
229             NamedResource newComponentTypeN = new NamedResource("", newComponentType);
230         Resource newSymbol = graph.getSingleObject(newComponentType, MOD.ComponentTypeToSymbol);
231         NamedResource newSymbolN = new NamedResource("", newSymbol);
232         
233             Collection<Resource> instances = graph.adapt(oldComponentType, Instances.class).find(graph, model);
234             
235             for(Resource instance : instances) {
236                 new MigrationOperation(
237                         new NamedResource("", instance),
238                         newComponentTypeN,
239                         newSymbolN)
240                 .perform(graph);
241             }
242         }
243
244 }