-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
+package org.simantics.graph.matching;
+
+import gnu.trove.map.hash.TIntIntHashMap;
+import gnu.trove.map.hash.TIntObjectHashMap;
+import gnu.trove.map.hash.TObjectIntHashMap;
+
+import java.util.ArrayList;
+
+import org.simantics.graph.representation.External;
+import org.simantics.graph.representation.Identity;
+import org.simantics.graph.representation.Internal;
+import org.simantics.graph.representation.Optional;
+import org.simantics.graph.representation.Root;
+
+/**
+ * A strategy matching resources with equal URIs.
+ *
+ * @author Hannu Niemistö
+ */
+public enum IdentityMatchingStrategy implements GraphMatchingStrategy {
+
+ INSTANCE;
+
+ static class NamedResource {
+ String name;
+ int resource;
+
+ public NamedResource(String name, int resource) {
+ this.name = name;
+ this.resource = resource;
+ }
+ }
+
+ static class IdentityTree {
+ TIntObjectHashMap<ArrayList<NamedResource>> childMap = new TIntObjectHashMap<ArrayList<NamedResource>>();
+ ArrayList<NamedResource> roots = new ArrayList<NamedResource>();
+
+ public IdentityTree(Identity[] indentities) {
+ for(Identity id : indentities) {
+ if(id.definition instanceof External) {
+ External def = (External)id.definition;
+ addChild(id.resource, def.parent, def.name);
+ }
+ else if(id.definition instanceof Internal) {
+ Internal def = (Internal)id.definition;
+ addChild(id.resource, def.parent, def.name);
+ }
+ else if(id.definition instanceof Optional) {
+ Optional def = (Optional)id.definition;
+ addChild(id.resource, def.parent, def.name);
+ }
+ else if(id.definition instanceof Root) {
+ addRoot(id.resource, ((Root)id.definition).name);
+ }
+ }
+ }
+
+ private void addRoot(int root, String name) {
+ roots.add(new NamedResource(name, root));
+ }
+
+ private void addChild(int child, int parent, String name) {
+ ArrayList<NamedResource> children = childMap.get(parent);
+ if(children == null) {
+ children = new ArrayList<NamedResource>();
+ childMap.put(parent, children);
+ }
+ children.add(new NamedResource(name, child));
+ }
+ }
+
+ static class MatchingProcess {
+ int[] aToB;
+ int[] bToA;
+ TIntIntHashMap aInv;
+ TIntIntHashMap bInv;
+ IdentityTree aTree;
+ IdentityTree bTree;
+
+ public MatchingProcess(int[] aToB, int[] bToA,
+ TIntIntHashMap aInv, TIntIntHashMap bInv,
+ IdentityTree aTree, IdentityTree bTree) {
+ this.aToB = aToB;
+ this.bToA = bToA;
+ this.aInv = aInv;
+ this.bInv = bInv;
+ this.aTree = aTree;
+ this.bTree = bTree;
+ }
+
+ public void execute() {
+ match(aTree.roots, bTree.roots);
+ }
+
+ private void match(ArrayList<NamedResource> as, ArrayList<NamedResource> bs) {
+ TObjectIntHashMap<String> map = new TObjectIntHashMap<String>();
+ for(NamedResource b : bs)
+ map.put(b.name, b.resource);
+ for(NamedResource a : as)
+ if(map.contains(a.name))
+ match(a.resource, map.get(a.name));
+ }
+
+ private void match(int a, int b) {
+ if(aToB[a] < 0 && bToA[b] < 0) {
+ aToB[a] = b;
+ bToA[b] = a;
+
+ if(aInv.contains(a) && bInv.contains(b))
+ match(aInv.get(a), bInv.get(b));
+
+ ArrayList<NamedResource> as = aTree.childMap.get(a);
+ if(as == null)
+ return;
+ ArrayList<NamedResource> bs = bTree.childMap.get(b);
+ if(bs == null)
+ return;
+ match(as, bs);
+ }
+ }
+ }
+
+ public void mapUnmapped(int[] map, TIntIntHashMap inverses, Identity[] identities, int rangeCount) {
+ for(Identity id : identities) {
+ int r = id.resource;
+ if(map[r] < 0) {
+ map[r] = rangeCount++;
+ if(inverses.containsKey(r))
+ map[inverses.get(r)] = rangeCount++;
+ }
+ }
+ }
+
+ @Override
+ public void applyTo(GraphMatching matching) {
+ new MatchingProcess(
+ matching.aToB, matching.bToA,
+ matching.aGraph.inverses, matching.bGraph.inverses,
+ new IdentityTree(matching.aGraph.identities), new IdentityTree(matching.bGraph.identities)
+ ).execute();
+ mapUnmapped(matching.aToB, matching.aGraph.inverses,
+ matching.aGraph.identities, matching.bGraph.resourceCount);
+ mapUnmapped(matching.bToA, matching.bGraph.inverses,
+ matching.bGraph.identities, matching.aGraph.resourceCount);
+ matching.recomputeSize();
+ }
+}