--- /dev/null
+package org.simantics.graph.refactoring;\r
+\r
+import java.util.ArrayList;\r
+\r
+import org.simantics.graph.query.Path;\r
+import org.simantics.graph.query.PathChild;\r
+import org.simantics.graph.query.TransferableGraphConversion;\r
+import org.simantics.graph.query.UriUtils;\r
+import org.simantics.graph.refactoring.MappingSpecification.MappingRule;\r
+import org.simantics.graph.representation.External;\r
+import org.simantics.graph.representation.Identity;\r
+import org.simantics.graph.representation.IdentityDefinition;\r
+import org.simantics.graph.representation.Internal;\r
+import org.simantics.graph.representation.Optional;\r
+import org.simantics.graph.representation.Root;\r
+import org.simantics.graph.representation.TransferableGraph1;\r
+import org.simantics.graph.representation.TransferableGraphUtils;\r
+import org.simantics.graph.representation.old.OldTransferableGraph1;\r
+import org.simantics.graph.representation.old.OldValue1;\r
+import org.simantics.graph.store.IdentityStore;\r
+\r
+import gnu.trove.list.array.TIntArrayList;\r
+import gnu.trove.set.hash.TIntHashSet;\r
+\r
+public class GraphRefactoringUtils {\r
+\r
+ /**\r
+ * Moves an external resource. Returns true if did something.\r
+ * @param parentsAffected \r
+ */\r
+ public static boolean moveExternal(TransferableGraph1 tg, IdentityStore ids, Path from, PathChild to, TIntHashSet parentsAffected) throws GraphRefactoringException {\r
+ // Find from id\r
+ int fromId = ids.pathToId(from);\r
+ if(fromId < 0)\r
+ return false;\r
+ if(ids.isNewResource(fromId))\r
+ throw new GraphRefactoringException("Cannot move internal resource " + from + ".");\r
+\r
+ // Remove old identity\r
+ int parentId = ids.removeIdentity(fromId);\r
+ if(parentId >= 0)\r
+ parentsAffected.add(parentId);\r
+\r
+ // Find parent id\r
+ int toParentId = ids.createPathToId(to.parent);\r
+ if(ids.hasChild(toParentId, to.name)) {\r
+ System.err.println("refactor statements from " + from + " to " + to);\r
+ //throw new GraphRefactoringException("External reference to " + to + " already exists.");\r
+ int toId = ids.pathToId(to);\r
+ int[] statements = tg.statements;\r
+ for(int i=0;i<tg.statements.length;++i) {\r
+ if(statements[i] == fromId) statements[i] = toId;\r
+ }\r
+ return true;\r
+ }\r
+ \r
+ // Set new identity\r
+ ids.setIdentity(fromId, toParentId, to.name);\r
+ return true;\r
+ }\r
+ \r
+ public static void refactor(TransferableGraph1 tg, IdentityStore ids, MappingSpecification spec, TIntHashSet parentsAffected) throws GraphRefactoringException {\r
+ for(MappingRule rule : spec.getRules()) {\r
+ if(!(rule.to instanceof PathChild))\r
+ throw new GraphRefactoringException("Invalid target URI " + rule.to);\r
+ if(!moveExternal(tg, ids, rule.from, (PathChild)rule.to, parentsAffected))\r
+ System.err.println("Didn't find " + rule.from);\r
+ }\r
+ }\r
+\r
+ public static boolean fixIncorrectRoot(Identity[] ids) {\r
+ for(int i=0;i<ids.length;++i) {\r
+ Identity id = ids[i];\r
+ if(id.definition instanceof External) {\r
+ External ext = (External)id.definition;\r
+ if(ext.parent == -1 && (ext.name.equals("http:/") || ext.name.equals(""))) {\r
+ id.definition = new Root("", "");\r
+ return true;\r
+ }\r
+ }\r
+ }\r
+ return false;\r
+ }\r
+\r
+ public static void fixOntologyExport(TransferableGraph1 tg) {\r
+ \r
+ fixIncorrectRoot(tg.identities);\r
+ fixOntologyRoot(tg, true);\r
+ \r
+ }\r
+ \r
+ public static void fixOntologyRoot(TransferableGraph1 tg, boolean tryToFix) {\r
+\r
+ Identity[] ids = tg.identities;\r
+ for(int i=0;i<ids.length;++i) {\r
+ Identity id = ids[i];\r
+ if(id.definition instanceof Root) {\r
+ Root ext = (Root)id.definition;\r
+ if(ext.name.startsWith("http://")) {\r
+ String rootName = ext.name.substring(ext.name.lastIndexOf("/")+1);\r
+ String path = ext.name.substring(0, ext.name.lastIndexOf("/"));\r
+ Identity pathId = TransferableGraphUtils.findExternal(tg, path);\r
+ System.err.println("GraphRefactoringUtils.rootName=" + rootName);\r
+ System.err.println("GraphRefactoringUtils.path2=" + path);\r
+ if(pathId == null) {\r
+ if(!tryToFix) return;\r
+ IdentityStore idStore = TransferableGraphConversion.extractIdentities(tg);\r
+ idStore.createPathToId(UriUtils.uriToPath(path));\r
+ tg.resourceCount = idStore.getResourceCount();\r
+ tg.identities = idStore.toArray();\r
+ fixOntologyRoot(tg, false);\r
+ return;\r
+ } else {\r
+ id.definition = new Internal(pathId.resource, rootName);\r
+ TIntArrayList stms = new TIntArrayList(tg.statements);\r
+ Identity consistsOf = TransferableGraphUtils.findExternal(tg, "http://www.simantics.org/Layer0-1.1/ConsistsOf");\r
+ Identity partOf = TransferableGraphUtils.findExternal(tg, "http://www.simantics.org/Layer0-1.1/PartOf");\r
+ stms.add(id.resource);\r
+ stms.add(partOf.resource);\r
+ stms.add(consistsOf.resource);\r
+ stms.add(pathId.resource);\r
+ tg.statements = stms.toArray();\r
+ return;\r
+ }\r
+ \r
+ }\r
+ }\r
+ }\r
+ \r
+ }\r
+\r
+ public static void unfixIncorrectRoot(Identity[] ids) {\r
+ for(int i=0;i<ids.length;++i) {\r
+ Identity id = ids[i];\r
+ if(id.definition instanceof Root) {\r
+ Root root = (Root)id.definition;\r
+ if(root.name.equals("") && root.type.equals("")) {\r
+ id.definition = new External(-1, "http:/");\r
+ return;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ public static void compactify(OldTransferableGraph1 tg,\r
+ TIntHashSet removed) {\r
+ // Filter removed set\r
+ for(Identity id : tg.identities) {\r
+ IdentityDefinition def = id.definition;\r
+ if(def instanceof Root)\r
+ removed.remove(id.resource);\r
+ else if(def instanceof External)\r
+ removed.remove(((External)def).parent);\r
+ else if(def instanceof Internal)\r
+ removed.remove(((Internal)def).parent);\r
+ else if(def instanceof Optional)\r
+ removed.remove(((Optional)def).parent);\r
+ }\r
+ for(int r : tg.statements)\r
+ removed.remove(r);\r
+ for(OldValue1 value : tg.values)\r
+ removed.remove(value.resource);\r
+ \r
+ // Compactify\r
+ if(!removed.isEmpty()) {\r
+ // create map\r
+ int resourceCount = tg.resourceCount;\r
+ int[] map = new int[resourceCount];\r
+ for(int i=0;i<resourceCount;++i)\r
+ map[i] = i;\r
+ for(int r : removed.toArray()) {\r
+ map[--resourceCount] = map[r];\r
+ }\r
+ \r
+ // map\r
+ ArrayList<Identity> newIdentities = new ArrayList<Identity>(tg.identities.length);\r
+ for(Identity id : tg.identities) {\r
+ if(removed.contains(id.resource))\r
+ continue;\r
+ else\r
+ newIdentities.add(id); \r
+ id.resource = map[id.resource];\r
+ IdentityDefinition def = id.definition;\r
+ if(def instanceof External) {\r
+ External d = (External)def;\r
+ d.parent = map[d.parent];\r
+ }\r
+ else if(def instanceof Internal) {\r
+ External d = (External)def;\r
+ d.parent = map[d.parent];\r
+ }\r
+ else if(def instanceof Optional) {\r
+ External d = (External)def;\r
+ d.parent = map[d.parent];\r
+ }\r
+ }\r
+ tg.identities = newIdentities.toArray(new Identity[newIdentities.size()]);\r
+ int[] statements = tg.statements;\r
+ for(int i=0;i<statements.length;++i) {\r
+ int r = statements[i]; \r
+ if(r >= 0)\r
+ statements[i] = map[r];\r
+ }\r
+ for(OldValue1 value : tg.values)\r
+ value.resource = map[value.resource];\r
+ tg.resourceCount = resourceCount;\r
+ }\r
+ }\r
+\r
+}\r