]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.graph/src/org/simantics/graph/matching/IdentityMatchingStrategy.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.graph / src / org / simantics / graph / matching / IdentityMatchingStrategy.java
diff --git a/bundles/org.simantics.graph/src/org/simantics/graph/matching/IdentityMatchingStrategy.java b/bundles/org.simantics.graph/src/org/simantics/graph/matching/IdentityMatchingStrategy.java
new file mode 100644 (file)
index 0000000..9caee5c
--- /dev/null
@@ -0,0 +1,147 @@
+package org.simantics.graph.matching;\r
+\r
+import gnu.trove.map.hash.TIntIntHashMap;\r
+import gnu.trove.map.hash.TIntObjectHashMap;\r
+import gnu.trove.map.hash.TObjectIntHashMap;\r
+\r
+import java.util.ArrayList;\r
+\r
+import org.simantics.graph.representation.External;\r
+import org.simantics.graph.representation.Identity;\r
+import org.simantics.graph.representation.Internal;\r
+import org.simantics.graph.representation.Optional;\r
+import org.simantics.graph.representation.Root;\r
+\r
+/**\r
+ * A strategy matching resources with equal URIs.\r
+ * \r
+ * @author Hannu Niemistö\r
+ */\r
+public enum IdentityMatchingStrategy implements GraphMatchingStrategy {\r
+\r
+       INSTANCE;\r
+       \r
+       static class NamedResource {\r
+               String name;\r
+               int resource;\r
+               \r
+               public NamedResource(String name, int resource) {\r
+                       this.name = name;\r
+                       this.resource = resource;\r
+               }\r
+       }\r
+       \r
+       static class IdentityTree {\r
+               TIntObjectHashMap<ArrayList<NamedResource>> childMap = new TIntObjectHashMap<ArrayList<NamedResource>>();\r
+               ArrayList<NamedResource> roots = new ArrayList<NamedResource>(); \r
+               \r
+               public IdentityTree(Identity[] indentities) {\r
+                       for(Identity id : indentities) {\r
+                               if(id.definition instanceof External) {\r
+                                       External def = (External)id.definition;\r
+                                       addChild(id.resource, def.parent, def.name);\r
+                               }\r
+                               else if(id.definition instanceof Internal) {\r
+                                       Internal def = (Internal)id.definition;\r
+                                       addChild(id.resource, def.parent, def.name);\r
+                               }\r
+                               else if(id.definition instanceof Optional) {\r
+                                       Optional def = (Optional)id.definition;\r
+                                       addChild(id.resource, def.parent, def.name);\r
+                               }\r
+                               else if(id.definition instanceof Root) {\r
+                                       addRoot(id.resource, ((Root)id.definition).name);\r
+                               }\r
+                       }\r
+               }\r
+\r
+               private void addRoot(int root, String name) {\r
+                       roots.add(new NamedResource(name, root));\r
+               }\r
+               \r
+               private void addChild(int child, int parent, String name) {\r
+                       ArrayList<NamedResource> children = childMap.get(parent);\r
+                       if(children == null) {\r
+                               children = new ArrayList<NamedResource>();\r
+                               childMap.put(parent, children);\r
+                       }\r
+                       children.add(new NamedResource(name, child));\r
+               }\r
+       }\r
+       \r
+       static class MatchingProcess {\r
+               int[] aToB; \r
+               int[] bToA; \r
+               TIntIntHashMap aInv;\r
+               TIntIntHashMap bInv;\r
+               IdentityTree aTree; \r
+               IdentityTree bTree;\r
+               \r
+               public MatchingProcess(int[] aToB, int[] bToA,\r
+                               TIntIntHashMap aInv, TIntIntHashMap bInv,\r
+                               IdentityTree aTree, IdentityTree bTree) {\r
+                       this.aToB = aToB;\r
+                       this.bToA = bToA;\r
+                       this.aInv = aInv;\r
+                       this.bInv = bInv;\r
+                       this.aTree = aTree;\r
+                       this.bTree = bTree;\r
+               }\r
+\r
+               public void execute() {\r
+                       match(aTree.roots, bTree.roots);\r
+               }\r
+\r
+               private void match(ArrayList<NamedResource> as, ArrayList<NamedResource> bs) {\r
+                       TObjectIntHashMap<String> map = new TObjectIntHashMap<String>();\r
+                       for(NamedResource b : bs)\r
+                               map.put(b.name, b.resource);\r
+                       for(NamedResource a : as)\r
+                               if(map.contains(a.name))\r
+                                       match(a.resource, map.get(a.name));\r
+               }\r
+\r
+               private void match(int a, int b) {\r
+                       if(aToB[a] < 0 && bToA[b] < 0) {\r
+                               aToB[a] = b;\r
+                               bToA[b] = a;\r
+                               \r
+                               if(aInv.contains(a) && bInv.contains(b))\r
+                                       match(aInv.get(a), bInv.get(b));\r
+                               \r
+                               ArrayList<NamedResource> as = aTree.childMap.get(a);\r
+                               if(as == null)\r
+                                       return;\r
+                               ArrayList<NamedResource> bs = bTree.childMap.get(b);\r
+                               if(bs == null)\r
+                                       return;\r
+                               match(as, bs);\r
+                       }\r
+               }\r
+       }\r
+       \r
+       public void mapUnmapped(int[] map, TIntIntHashMap inverses, Identity[] identities, int rangeCount) {\r
+               for(Identity id : identities) {\r
+                       int r = id.resource;\r
+                       if(map[r] < 0) {\r
+                               map[r] = rangeCount++;\r
+                               if(inverses.containsKey(r))\r
+                                       map[inverses.get(r)] = rangeCount++;\r
+                       }\r
+               }\r
+       }\r
+       \r
+       @Override\r
+       public void applyTo(GraphMatching matching) {\r
+               new MatchingProcess(\r
+                               matching.aToB, matching.bToA, \r
+                               matching.aGraph.inverses, matching.bGraph.inverses,\r
+                               new IdentityTree(matching.aGraph.identities), new IdentityTree(matching.bGraph.identities)\r
+               ).execute();    \r
+               mapUnmapped(matching.aToB, matching.aGraph.inverses, \r
+                               matching.aGraph.identities, matching.bGraph.resourceCount);\r
+               mapUnmapped(matching.bToA, matching.bGraph.inverses, \r
+                               matching.bGraph.identities, matching.aGraph.resourceCount);\r
+               matching.recomputeSize();\r
+       }\r
+}\r