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