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
10 * Semantum Oy - initial API and implementation
\r
11 *******************************************************************************/
\r
12 package org.simantics.modeling;
\r
14 import gnu.trove.set.hash.THashSet;
\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
22 import org.simantics.databoard.Bindings;
\r
23 import org.simantics.db.ReadGraph;
\r
24 import org.simantics.db.Resource;
\r
25 import org.simantics.db.Statement;
\r
26 import org.simantics.db.WriteGraph;
\r
27 import org.simantics.db.common.NamedResource;
\r
28 import org.simantics.db.common.utils.NameUtils;
\r
29 import org.simantics.db.exception.DatabaseException;
\r
30 import org.simantics.db.layer0.util.Layer0Utils;
\r
31 import org.simantics.diagram.stubs.DiagramResource;
\r
32 import org.simantics.layer0.Layer0;
\r
33 import org.simantics.structural.stubs.StructuralResource2;
\r
34 import org.simantics.structural2.modelingRules.AllowedConnectionTypes;
\r
35 import org.simantics.utils.ObjectUtils;
\r
36 import org.simantics.utils.datastructures.Triple;
\r
39 * @author Antti Villberg
\r
41 public class MigrateModel {
\r
43 public static class MigrationOperation {
\r
45 public NamedResource instanceToMigrate;
\r
46 public NamedResource targetType;
\r
47 public NamedResource targetSymbol;
\r
49 public MigrationOperation(NamedResource nr, NamedResource targetType, NamedResource targetSymbol) {
\r
50 this.instanceToMigrate = nr;
\r
51 this.targetType = targetType;
\r
52 this.targetSymbol = targetSymbol;
\r
56 public String toString() {
\r
57 return instanceToMigrate.getName();
\r
60 public String getDescription(ReadGraph graph) throws DatabaseException {
\r
61 String sourceURI = graph.getPossibleURI(instanceToMigrate.getResource());
\r
62 if(sourceURI == null) sourceURI = NameUtils.getSafeName(graph, instanceToMigrate.getResource());
\r
63 sourceURI = sourceURI.replace("http://Projects/Development%20Project/", "");
\r
64 if(targetSymbol != null) {
\r
65 String targetURI = graph.getURI(targetSymbol.getResource());
\r
66 return sourceURI + " into " + targetURI;
\r
68 String targetURI = graph.getURI(targetType.getResource());
\r
69 return sourceURI + " into " + targetURI;
\r
73 private Resource getPossibleReplacement(ReadGraph graph, Resource type, Resource predicate) throws DatabaseException {
\r
74 Layer0 L0 = Layer0.getInstance(graph);
\r
75 String name = graph.getPossibleRelatedValue(predicate, L0.HasName, Bindings.STRING);
\r
76 if(name == null) return null;
\r
77 Resource child = Layer0Utils.getPossibleChild(graph, type, name);
\r
78 if(child != null) return child;
\r
79 for(Resource r : graph.getObjects(type, L0.DomainOf)) {
\r
80 String rName = graph.getPossibleRelatedValue(r, L0.HasName, Bindings.STRING);
\r
81 if(name.equals(rName)) return r;
\r
86 public String replace(WriteGraph graph, Resource instanceToMigrate, Resource type) throws DatabaseException {
\r
88 Layer0 L0 = Layer0.getInstance(graph);
\r
89 StructuralResource2 STR = StructuralResource2.getInstance(graph);
\r
91 Collection<Resource> currentTypes = graph.getPrincipalTypes(instanceToMigrate);
\r
92 if(currentTypes.size() == 1 && currentTypes.contains(type)) return null;
\r
94 StringBuilder problems = new StringBuilder();
\r
96 // Validate operation
\r
97 for(Statement stm : graph.getStatements(instanceToMigrate, L0.IsWeaklyRelatedTo)) {
\r
99 Resource predicate = stm.getPredicate();
\r
100 if(stm.isAsserted(instanceToMigrate)) continue;
\r
102 if(graph.isInstanceOf(predicate, STR.Property)) {
\r
103 Resource replacement = getPossibleReplacement(graph, type, predicate);
\r
104 // OK for a property to disappear
\r
105 if(replacement == null) continue;
\r
106 if(!graph.isInstanceOf(replacement, STR.Property)) {
\r
107 String name = graph.getRelatedValue(predicate, L0.HasName, Bindings.STRING);
\r
108 problems.append(" " + name + " was a property in the source type\n");
\r
111 String sourceValueType = graph.getPossibleRelatedValue(predicate, L0.RequiresValueType, Bindings.STRING);
\r
112 String replacementValueType = graph.getPossibleRelatedValue(replacement, L0.RequiresValueType, Bindings.STRING);
\r
113 if(!ObjectUtils.objectEquals(sourceValueType, replacementValueType)) {
\r
114 String name = graph.getRelatedValue(predicate, L0.HasName, Bindings.STRING);
\r
115 problems.append(" value types for property " + name + " differ (" + sourceValueType + " vs. " + replacementValueType + ")\n");
\r
120 if(graph.isInstanceOf(predicate, STR.ConnectionRelation)) {
\r
121 Resource replacement = getPossibleReplacement(graph, type, predicate);
\r
122 if(replacement == null) {
\r
123 String name = graph.getRelatedValue(predicate, L0.HasName, Bindings.STRING);
\r
124 problems.append(" used connection point " + name + " has been removed from target type\n");
\r
127 if(!graph.isInstanceOf(replacement, STR.ConnectionRelation)) {
\r
128 String name = graph.getRelatedValue(predicate, L0.HasName, Bindings.STRING);
\r
129 problems.append(" " + name + " was a connection point in the source type\n");
\r
133 Collection<Resource> sourceConnetionTypes = graph.syncRequest(new AllowedConnectionTypes(predicate));
\r
134 Collection<Resource> replacementConnectionTypes = graph.syncRequest(new AllowedConnectionTypes(replacement));
\r
136 Set<Resource> sourceSet = new THashSet<>(sourceConnetionTypes);
\r
137 Set<Resource> replacementSet = new THashSet<>(replacementConnectionTypes);
\r
139 if(!sourceSet.equals(replacementSet)) {
\r
140 String name = graph.getRelatedValue(predicate, L0.HasName, Bindings.STRING);
\r
141 problems.append(" allowed connection types for connection point " + name + " differ (" + NameUtils.getSafeName(graph, sourceSet) + " vs. " + NameUtils.getSafeName(graph, replacementSet) + ")\n");
\r
149 if(problems.length() > 0) {
\r
150 return problems.toString();
\r
153 // Perform operation
\r
154 for(Statement stm : graph.getStatements(instanceToMigrate, L0.IsWeaklyRelatedTo)) {
\r
156 Resource predicate = stm.getPredicate();
\r
157 if(stm.isAsserted(instanceToMigrate)) continue;
\r
159 if(L0.InstanceOf.equals(predicate)) {
\r
161 graph.claim(instanceToMigrate, L0.InstanceOf, type);
\r
164 if(graph.isInstanceOf(predicate, STR.Property) || graph.isInstanceOf(predicate, STR.ConnectionRelation)) {
\r
165 Resource replacement = getPossibleReplacement(graph, type, predicate);
\r
167 if(replacement == null) continue;
\r
168 graph.claim(stm.getSubject(), replacement, stm.getObject());
\r
177 public String perform(WriteGraph graph) throws DatabaseException {
\r
179 Resource instance = instanceToMigrate.getResource();
\r
180 Resource type = targetType.getResource();
\r
181 Resource symbol = targetSymbol != null ? targetSymbol.getResource() : null;
\r
183 String result = replace(graph, instance, type);
\r
184 if(result != null) return result;
\r
186 ModelingResources MOD = ModelingResources.getInstance(graph);
\r
187 Resource element = graph.getPossibleObject(instance, MOD.ComponentToElement);
\r
188 if(element == null) return null;
\r
190 Resource targetSymbol = symbol;
\r
191 if(targetSymbol == null) {
\r
192 Layer0 L0 = Layer0.getInstance(graph);
\r
193 DiagramResource DIA = DiagramResource.getInstance(graph);
\r
194 Resource currentSymbol = graph.getPossibleType(element, DIA.Element);
\r
195 if(currentSymbol != null) {
\r
196 String currentSymbolName = graph.getRelatedValue(currentSymbol, L0.HasName, Bindings.STRING);
\r
197 targetSymbol = Layer0Utils.getPossibleChild(graph, type, DIA.ElementClass, currentSymbolName);
\r
198 if(targetSymbol == null)
\r
199 return "Did not find symbol '" + currentSymbolName + "' from target type.\n";
\r
201 // No symbol - fine
\r
207 return replace(graph, element, targetSymbol);
\r
213 public int instanceCount = 0;
\r
214 public Set<Resource> activeModels = new THashSet<>();
\r
215 public List<Triple<String, NamedResource, Collection<MigrationOperation>>> instances = new ArrayList<>();
\r
216 public List<MigrationOperation> sortedShownInstances = Collections.emptyList();
\r