1 package org.simantics.graph.refactoring;
3 import java.util.ArrayList;
4 import java.util.Arrays;
6 import org.simantics.databoard.util.URIStringUtils;
7 import org.simantics.graph.query.Path;
8 import org.simantics.graph.query.PathChild;
9 import org.simantics.graph.query.TransferableGraphConversion;
10 import org.simantics.graph.query.UriUtils;
11 import org.simantics.graph.refactoring.MappingSpecification.MappingRule;
12 import org.simantics.graph.representation.External;
13 import org.simantics.graph.representation.Identity;
14 import org.simantics.graph.representation.IdentityDefinition;
15 import org.simantics.graph.representation.Internal;
16 import org.simantics.graph.representation.Optional;
17 import org.simantics.graph.representation.Root;
18 import org.simantics.graph.representation.TransferableGraph1;
19 import org.simantics.graph.representation.TransferableGraphUtils;
20 import org.simantics.graph.representation.old.OldTransferableGraph1;
21 import org.simantics.graph.representation.old.OldValue1;
22 import org.simantics.graph.store.GraphStore;
23 import org.simantics.graph.store.IdentityStore;
25 import gnu.trove.list.array.TIntArrayList;
26 import gnu.trove.map.hash.TIntIntHashMap;
27 import gnu.trove.set.hash.TIntHashSet;
29 public class GraphRefactoringUtils {
32 * Moves an external resource. Returns true if did something.
33 * @param parentsAffected
35 public static boolean moveExternal(TransferableGraph1 tg, IdentityStore ids, Path from, PathChild to, TIntHashSet parentsAffected) throws GraphRefactoringException {
37 int fromId = ids.pathToId(from);
40 if(ids.isNewResource(fromId))
41 throw new GraphRefactoringException("Cannot move internal resource " + from + ".");
43 // Remove old identity
44 int parentId = ids.removeIdentity(fromId);
46 parentsAffected.add(parentId);
49 int toParentId = ids.createPathToId(to.parent);
50 if(ids.hasChild(toParentId, to.name)) {
51 System.err.println("refactor statements from " + from + " to " + to);
52 //throw new GraphRefactoringException("External reference to " + to + " already exists.");
53 int toId = ids.pathToId(to);
54 int[] statements = tg.statements;
55 for(int i=0;i<tg.statements.length;++i) {
56 if(statements[i] == fromId) statements[i] = toId;
62 ids.setIdentity(fromId, toParentId, to.name);
66 public static void refactor(TransferableGraph1 tg, IdentityStore ids, MappingSpecification spec, TIntHashSet parentsAffected) throws GraphRefactoringException {
67 for(MappingRule rule : spec.getRules()) {
68 if(!(rule.to instanceof PathChild))
69 throw new GraphRefactoringException("Invalid target URI " + rule.to);
70 if(!moveExternal(tg, ids, rule.from, (PathChild)rule.to, parentsAffected))
71 System.err.println("Didn't find " + rule.from);
75 public static boolean fixIncorrectRoot(Identity[] ids) {
76 for(int i=0;i<ids.length;++i) {
78 if(id.definition instanceof External) {
79 External ext = (External)id.definition;
80 if(ext.parent == -1 && (ext.name.equals("http:/") || ext.name.equals(""))) {
81 id.definition = new Root("", "");
89 public static void fixOntologyExport(TransferableGraph1 tg) {
91 fixIncorrectRoot(tg.identities);
92 fixOntologyRoot(tg, true);
96 private static Identity recursePath(TransferableGraph1 tg, String path) {
98 Identity extId = TransferableGraphUtils.findExternal(tg, path);
99 if(extId != null) return extId;
100 if("http://".equals(path)) return TransferableGraphUtils.findRootWithName(tg, "");
101 String[] parts = URIStringUtils.splitURI(path);
102 Identity parentId = recursePath(tg, parts[0]);
103 tg.identities = Arrays.copyOf(tg.identities, tg.identities.length+1);
104 Identity childIdentity = new Identity(tg.resourceCount++, new External(parentId.resource, parts[1]));
105 tg.identities[tg.identities.length-1] = childIdentity;
106 return childIdentity;
110 public static void fixOntologyRoot(TransferableGraph1 tg, boolean tryToFix) {
112 Identity[] ids = tg.identities;
113 for(int i=0;i<ids.length;++i) {
114 Identity id = ids[i];
115 if(id.definition instanceof Root) {
116 Root ext = (Root)id.definition;
117 if(ext.name.startsWith("http://")) {
119 String[] parts = URIStringUtils.splitURI(ext.name);
120 Identity path = recursePath(tg, parts[0]);
121 id.definition = new Internal(path.resource, parts[1]);
123 GraphStore store = TransferableGraphConversion.convert(tg);
124 int rootId = store.identities.createPathToId(UriUtils.uriToPath(ext.name));
125 propagateNewMarks(store.identities, rootId);
127 TransferableGraph1 tgNew = TransferableGraphConversion.convert(store);
129 tg.resourceCount = tgNew.resourceCount;
130 tg.identities = tgNew.identities;
131 tg.values = tgNew.values;
132 tg.statements = tgNew.statements;
142 private static void propagateNewMarks(IdentityStore identities, int resource) {
143 if(identities.markNew(resource)) {
144 for(int child : identities.getChildren(resource))
145 propagateNewMarks(identities, child);
149 public static void unfixIncorrectRoot(Identity[] ids) {
150 for(int i=0;i<ids.length;++i) {
151 Identity id = ids[i];
152 if(id.definition instanceof Root) {
153 Root root = (Root)id.definition;
154 if(root.name.equals("") && root.type.equals("")) {
155 id.definition = new External(-1, "http:/");
162 public static void compactify(OldTransferableGraph1 tg,
163 TIntHashSet removed) {
164 // Filter removed set
165 for(Identity id : tg.identities) {
166 IdentityDefinition def = id.definition;
167 if(def instanceof Root)
168 removed.remove(id.resource);
169 else if(def instanceof External)
170 removed.remove(((External)def).parent);
171 else if(def instanceof Internal)
172 removed.remove(((Internal)def).parent);
173 else if(def instanceof Optional)
174 removed.remove(((Optional)def).parent);
176 for(int r : tg.statements)
178 for(OldValue1 value : tg.values)
179 removed.remove(value.resource);
182 if(!removed.isEmpty()) {
184 int resourceCount = tg.resourceCount;
185 int[] map = new int[resourceCount];
186 for(int i=0;i<resourceCount;++i)
188 for(int r : removed.toArray()) {
189 map[--resourceCount] = map[r];
193 ArrayList<Identity> newIdentities = new ArrayList<Identity>(tg.identities.length);
194 for(Identity id : tg.identities) {
195 if(removed.contains(id.resource))
198 newIdentities.add(id);
199 id.resource = map[id.resource];
200 IdentityDefinition def = id.definition;
201 if(def instanceof External) {
202 External d = (External)def;
203 d.parent = map[d.parent];
205 else if(def instanceof Internal) {
206 External d = (External)def;
207 d.parent = map[d.parent];
209 else if(def instanceof Optional) {
210 External d = (External)def;
211 d.parent = map[d.parent];
214 tg.identities = newIdentities.toArray(new Identity[newIdentities.size()]);
215 int[] statements = tg.statements;
216 for(int i=0;i<statements.length;++i) {
217 int r = statements[i];
219 statements[i] = map[r];
221 for(OldValue1 value : tg.values)
222 value.resource = map[value.resource];
223 tg.resourceCount = resourceCount;