1 /*******************************************************************************
2 * Copyright (c) 2014, 2015 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 * Semantum Oy - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.modeling;
14 import gnu.trove.set.hash.THashSet;
16 import java.util.ArrayList;
17 import java.util.Collection;
18 import java.util.Collections;
19 import java.util.List;
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;
41 * @author Antti Villberg
43 public class MigrateModel {
45 public static class MigrationOperation {
47 public NamedResource instanceToMigrate;
48 public NamedResource targetType;
49 public NamedResource targetSymbol;
51 public MigrationOperation(NamedResource nr, NamedResource targetType, NamedResource targetSymbol) {
52 this.instanceToMigrate = nr;
53 this.targetType = targetType;
54 this.targetSymbol = targetSymbol;
58 public String toString() {
59 return instanceToMigrate.getName();
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);
70 String targetURI = graph.getURI(targetType.getResource());
71 return URIStringUtils.unescape(sourceURI) + " into " + URIStringUtils.unescape(targetURI);
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;
88 public String replace(WriteGraph graph, Resource instanceToMigrate, Resource type) throws DatabaseException {
90 Layer0 L0 = Layer0.getInstance(graph);
91 StructuralResource2 STR = StructuralResource2.getInstance(graph);
93 Collection<Resource> currentTypes = graph.getPrincipalTypes(instanceToMigrate);
94 if(currentTypes.size() == 1 && currentTypes.contains(type)) return null;
96 StringBuilder problems = new StringBuilder();
99 for(Statement stm : graph.getStatements(instanceToMigrate, L0.IsWeaklyRelatedTo)) {
101 Resource predicate = stm.getPredicate();
102 if(stm.isAsserted(instanceToMigrate)) continue;
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");
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");
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");
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");
135 Collection<Resource> sourceConnetionTypes = graph.syncRequest(new AllowedConnectionTypes(predicate));
136 Collection<Resource> replacementConnectionTypes = graph.syncRequest(new AllowedConnectionTypes(replacement));
138 Set<Resource> sourceSet = new THashSet<>(sourceConnetionTypes);
139 Set<Resource> replacementSet = new THashSet<>(replacementConnectionTypes);
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");
151 if(problems.length() > 0) {
152 return problems.toString();
156 for(Statement stm : graph.getStatements(instanceToMigrate, L0.IsWeaklyRelatedTo)) {
158 Resource predicate = stm.getPredicate();
159 if(stm.isAsserted(instanceToMigrate)) continue;
161 if(L0.InstanceOf.equals(predicate)) {
163 graph.claim(instanceToMigrate, L0.InstanceOf, type);
166 if(graph.isInstanceOf(predicate, STR.Property) || graph.isInstanceOf(predicate, STR.ConnectionRelation)) {
167 Resource replacement = getPossibleReplacement(graph, type, predicate);
169 if(replacement == null) continue;
170 graph.claim(stm.getSubject(), replacement, stm.getObject());
179 public String perform(WriteGraph graph) throws DatabaseException {
181 Resource instance = instanceToMigrate.getResource();
182 Resource type = targetType.getResource();
183 Resource symbol = targetSymbol != null ? targetSymbol.getResource() : null;
185 String result = replace(graph, instance, type);
186 if(result != null) return result;
188 ModelingResources MOD = ModelingResources.getInstance(graph);
189 Resource element = graph.getPossibleObject(instance, MOD.ComponentToElement);
190 if(element == null) return null;
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";
209 return replace(graph, element, targetSymbol);
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();
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))
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);
233 Collection<Resource> instances = graph.adapt(oldComponentType, Instances.class).find(graph, model);
235 for(Resource instance : instances) {
236 new MigrationOperation(
237 new NamedResource("", instance),