]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.graph/src/org/simantics/graph/store/IdentityStore.java
Fixed all line endings of the repository
[simantics/platform.git] / bundles / org.simantics.graph / src / org / simantics / graph / store / IdentityStore.java
index c84358cb077b37fff57c57a572c85298b4ef421a..5ed32c0786bde4778a2125eb358be6a461020232 100644 (file)
-package org.simantics.graph.store;\r
-\r
-import gnu.trove.list.array.TIntArrayList;\r
-import gnu.trove.map.hash.THashMap;\r
-import gnu.trove.map.hash.TIntIntHashMap;\r
-import gnu.trove.map.hash.TIntObjectHashMap;\r
-import gnu.trove.map.hash.TObjectIntHashMap;\r
-import gnu.trove.procedure.TIntProcedure;\r
-import gnu.trove.procedure.TObjectIntProcedure;\r
-import gnu.trove.procedure.TObjectObjectProcedure;\r
-import gnu.trove.procedure.TObjectProcedure;\r
-import gnu.trove.set.hash.THashSet;\r
-import gnu.trove.set.hash.TIntHashSet;\r
-\r
-import java.util.ArrayList;\r
-import java.util.regex.Pattern;\r
-\r
-import org.simantics.graph.query.Path;\r
-import org.simantics.graph.query.PathChild;\r
-import org.simantics.graph.query.PathRoot;\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.Root;\r
-\r
-public class IdentityStore implements IStore {\r
-       \r
-       private static int[] EMPTY_INT_ARRAY = new int[0];\r
-       \r
-       public static class ConsistsOf {\r
-               public int parent;\r
-               public String name;\r
-               public int child;\r
-               \r
-               public ConsistsOf(int parent, String name, int child) {\r
-                       //System.out.println(parent + "." + name + " = " + child);\r
-                       this.parent = parent;\r
-                       this.name = name;\r
-                       this.child = child;\r
-               }\r
-       }\r
-       \r
-       TObjectIntHashMap<String> roots = new TObjectIntHashMap<String>();\r
-       TIntObjectHashMap<String> invRoots = new TIntObjectHashMap<String>();\r
-       TIntObjectHashMap<THashMap<String, ConsistsOf>> parentMap =\r
-               new TIntObjectHashMap<THashMap<String, ConsistsOf>>();\r
-       TIntObjectHashMap<ConsistsOf> childMap = new TIntObjectHashMap<ConsistsOf>();\r
-       TIntHashSet newResources = new TIntHashSet();\r
-       int resourceCount = 0;\r
-       TIntIntHashMap unifications = new TIntIntHashMap();\r
-       TIntHashSet collisions = new TIntHashSet();\r
-       \r
-       public int newResource() {\r
-               return resourceCount++;\r
-       }\r
-\r
-       public boolean markNew(int resource) {\r
-               return newResources.add(resource);\r
-       }\r
-       \r
-       public int[] getNewResources() {\r
-               return newResources.toArray();\r
-       }\r
-       \r
-       public int getResourceCount() {\r
-               return resourceCount;\r
-       }\r
-       \r
-       public void setResourceCount(int newCount) {\r
-               resourceCount = newCount;\r
-       }\r
-               \r
-       public void defineRoot(String name, int root) {\r
-               if(roots.contains(name))\r
-                       unify(root, roots.get(name));\r
-               roots.put(name, root);\r
-               invRoots.put(root, name);\r
-       }\r
-       \r
-       public void defineChild(int parent, String name, int child) {\r
-               THashMap<String, ConsistsOf> map = parentMap.get(parent);\r
-               if(map == null) {\r
-                       map = new THashMap<String, ConsistsOf>();\r
-                       parentMap.put(parent, map);                     \r
-               }\r
-               ConsistsOf consistsOf = new ConsistsOf(parent, name, child);\r
-               ConsistsOf oldC = map.put(name, consistsOf);\r
-               if(oldC != null)\r
-                       unify(child, oldC.child);\r
-               childMap.put(child, consistsOf);\r
-       }\r
-       \r
-       public boolean hasChild(int parent, String name) {\r
-           THashMap<String, ConsistsOf> map = parentMap.get(parent);\r
-        if(map == null)\r
-            return false;\r
-        else\r
-            return map.contains(name);\r
-       }\r
-       \r
-       public int getChild(int parent, String name) {\r
-               THashMap<String, ConsistsOf> map = parentMap.get(parent);\r
-               if(map == null) {\r
-                       map = new THashMap<String, ConsistsOf>();\r
-                       parentMap.put(parent, map);                     \r
-               }\r
-               else if(map.contains(name))\r
-                       return map.get(name).child;\r
-               int child = newResource();\r
-               ConsistsOf consistsOf = new ConsistsOf(parent, name, child);\r
-               map.put(name, consistsOf);\r
-               childMap.put(child, consistsOf);\r
-               return child;\r
-       }\r
-       \r
-       public int getChildIfExists(int parent, String name) {\r
-               THashMap<String, ConsistsOf> map = parentMap.get(parent);\r
-               if(map != null && map.contains(name))\r
-                       return map.get(name).child;\r
-               return -1;\r
-       }\r
-\r
-       public int getRoot(String uri) {\r
-               if(roots.contains(uri))\r
-                       return roots.get(uri);\r
-               else {\r
-                       int root = newResource();\r
-                       roots.put(uri, root);\r
-                       invRoots.put(root, uri);\r
-                       return root;\r
-               }\r
-       }\r
-       \r
-       public int getRootIfExists(String uri) {\r
-               if(roots.contains(uri))\r
-                       return roots.get(uri);\r
-               return -1;\r
-       }\r
-       \r
-       public int[] getChildren(int id) {\r
-               THashMap<String,ConsistsOf> map = parentMap.get(id);\r
-               if(map == null)\r
-                       return EMPTY_INT_ARRAY;\r
-               final int[] result = new int[map.size()];\r
-               map.forEachValue(new TObjectProcedure<ConsistsOf>() {\r
-                       int i=0;\r
-                       @Override\r
-                       public boolean execute(ConsistsOf object) {\r
-                               result[i++] = object.child;\r
-                               return true;\r
-                       }\r
-               });\r
-               return result;\r
-       }\r
-       \r
-       public THashMap<String, ConsistsOf> getChildMap(int parent) {\r
-        return parentMap.get(parent);      \r
-       }\r
-       \r
-       private void collectIdentities(final int parent, final ArrayList<Identity> identities) {\r
-               THashMap<String, ConsistsOf> map = parentMap.get(parent);\r
-               if(map != null) {\r
-                       map.forEachEntry(new TObjectObjectProcedure<String, ConsistsOf>() {\r
-                               \r
-                               @Override\r
-                               public boolean execute(String a, ConsistsOf b) {\r
-                                       if(newResources.contains(b.child))\r
-                                               identities.add(new Identity(b.child, new Internal(parent, a)));\r
-                                       else\r
-                                               identities.add(new Identity(b.child, new External(parent, a)));\r
-                                       collectIdentities(b.child, identities);\r
-                                       return true;\r
-                               }\r
-                       });\r
-               }\r
-       }\r
-       \r
-       private void collectIdentities(final ArrayList<Identity> identities) {\r
-               roots.forEachEntry(new TObjectIntProcedure<String>() {                  \r
-                       @Override\r
-                       public boolean execute(String a, int b) {\r
-                               identities.add(new Identity(b, new Root(a, "")));\r
-                               collectIdentities(b, identities);\r
-                               return true;\r
-                       }                       \r
-               });\r
-       }\r
-       \r
-       @Override\r
-       public void map(final TIntIntHashMap map) {\r
-               collisions = IndexMappingUtils.map(map, collisions);\r
-               newResources = IndexMappingUtils.map(map, newResources);                \r
-               IndexMappingUtils.map(map, roots);\r
-               invRoots = IndexMappingUtils.map(map, invRoots, collisions);\r
-               \r
-               final ArrayList<ConsistsOf> consistsOfs = new ArrayList<ConsistsOf>(childMap.size());\r
-               childMap.forEachValue(new TObjectProcedure<IdentityStore.ConsistsOf>() {                        \r
-                       @Override\r
-                       public boolean execute(ConsistsOf c) {\r
-                               if(map.contains(c.parent))\r
-                                       c.parent = map.get(c.parent);\r
-                               if(map.contains(c.child))\r
-                                       c.child = map.get(c.child);\r
-                               consistsOfs.add(c);\r
-                               return true;\r
-                       }\r
-               });\r
-               \r
-               childMap.clear();\r
-               parentMap.clear();\r
-               assert(unifications.isEmpty());\r
-               \r
-               for(ConsistsOf c : consistsOfs) {\r
-                       THashMap<String, ConsistsOf> m = parentMap.get(c.parent);\r
-                       if(m == null) {\r
-                               m = new THashMap<String, ConsistsOf>();\r
-                               parentMap.put(c.parent, m);                     \r
-                       }\r
-                       ConsistsOf oldC = m.put(c.name, c);\r
-                       ConsistsOf childC = childMap.put(c.child, c);\r
-                       if(childC != null && (childC.parent != c.parent || !childC.name.equals(c.name)))\r
-                               collisions.add(c.child);\r
-                       \r
-                       if(oldC != null) \r
-                               unify(oldC.child, c.child);\r
-               }\r
-       }\r
-       \r
-       public int pathToId(Path path) {\r
-               if(path instanceof PathChild) {\r
-                       PathChild child = (PathChild)path;\r
-                       int parent = pathToId(child.parent);\r
-                       if(parent < 0)\r
-                               return -1;\r
-                       return getChildIfExists(parent, child.name);\r
-               }\r
-               else if(path instanceof PathRoot)\r
-                       return getRootIfExists(((PathRoot)path).name);\r
-               else\r
-                       throw new IllegalArgumentException();\r
-       }\r
-       \r
-       public int createPathToId(Path path) {\r
-               if(path instanceof PathChild) {\r
-                       PathChild child = (PathChild)path;\r
-                       return getChild(createPathToId(child.parent), child.name);\r
-               }\r
-               else if(path instanceof PathRoot)\r
-                       return getRoot(((PathRoot)path).name);\r
-               else\r
-                       throw new IllegalArgumentException();\r
-       }\r
-       \r
-       public Path idToPath(int id) {\r
-               ConsistsOf consistsOf = childMap.get(id);\r
-               if(consistsOf == null) {\r
-                       String root = invRoots.get(id);\r
-                       if(root == null)\r
-                               return null;\r
-                       else\r
-                               return new PathRoot(root);\r
-               }\r
-               /*System.out.println("ConsistsOf(" + \r
-                               consistsOf.parent + "." + consistsOf.name + \r
-                               " = " + consistsOf.child + ")");\r
-                               */\r
-               //if(consistsOf.parent == consistsOf.child)\r
-               //    return null; \r
-               Path parentPath = idToPath(consistsOf.parent);\r
-               if(parentPath == null)\r
-                       return null;\r
-               return new PathChild(consistsOf.name, parentPath);\r
-       }\r
-       \r
-       public boolean contains(Path path) {\r
-               return pathToId(path) >= 0;\r
-       }\r
-\r
-       public boolean isNewResource(int id) {\r
-               return newResources.contains(id);\r
-       }\r
-\r
-       public Identity[] toArray() {\r
-               final ArrayList<Identity> identities = new ArrayList<Identity>();\r
-               collectIdentities(identities);\r
-               return identities.toArray(new Identity[identities.size()]);\r
-       }\r
-       \r
-       public void collectReferences(final boolean[] set) {\r
-               TIntProcedure proc = new TIntProcedure() {                      \r
-                       @Override\r
-                       public boolean execute(int value) {\r
-                               set[value] = true;\r
-                               return true;\r
-                       }\r
-               };\r
-               \r
-               roots.forEachValue(proc);\r
-               childMap.forEach(proc);\r
-               parentMap.forEach(proc);\r
-       }\r
-\r
-       public int removeIdentity(int id) {\r
-               ConsistsOf c = childMap.remove(id);\r
-               if(c != null) {             \r
-                   parentMap.get(c.parent).remove(c.name);\r
-                   return c.parent;\r
-               }\r
-               return -1;\r
-       }\r
-\r
-       public boolean hasIdentity(int id) {\r
-               return childMap.containsKey(id);\r
-       }\r
-\r
-       public void definePath(Path path, int resource) {\r
-               if(path instanceof PathChild) {\r
-                       PathChild child = (PathChild)path;\r
-                       int parent = createPathToId(child.parent);\r
-                       defineChild(parent, child.name, resource);\r
-               }\r
-               else if(path instanceof PathRoot) {\r
-                       defineRoot(((PathRoot)path).name, resource);\r
-               }\r
-               else\r
-                       throw new IllegalArgumentException();           \r
-       }\r
-       \r
-       public void printChildMap() {\r
-               System.out.println("ChildMap:");\r
-               childMap.forEachValue(new TObjectProcedure<ConsistsOf>() {\r
-\r
-                       @Override\r
-                       public boolean execute(ConsistsOf c) {\r
-                               System.out.println("    " + \r
-                                               c.child + " = " + c.parent + "." + c.name);\r
-                               return true;\r
-                       }\r
-                       \r
-               });\r
-       }\r
-       \r
-       private int canonical(int a) {\r
-               if(unifications.contains(a)) {\r
-                       int b = unifications.get(a);\r
-                       if(unifications.contains(b)) {\r
-                               int c = canonical(b);\r
-                               unifications.put(a, c);\r
-                               unifications.put(b, c);\r
-                               return c;\r
-                       }\r
-                       else \r
-                               return b;\r
-               }\r
-               else\r
-                       return a;\r
-       }\r
-       \r
-       public TIntIntHashMap extractUnifications() {\r
-               // This normalizes the map\r
-               for(int a : unifications.keys())\r
-                       canonical(a);\r
-               \r
-               TIntIntHashMap result = unifications;\r
-               unifications = new TIntIntHashMap();\r
-               \r
-               return result;\r
-       }\r
-       \r
-       public void unify(int a, int b) {\r
-               if(a != b) {\r
-                       a = canonical(a);\r
-                       b = canonical(b);\r
-                       if(a != b)\r
-                               unifications.put(a, b);\r
-               }\r
-       }\r
-       \r
-       public TIntHashSet getCollisions() {\r
-               return collisions;\r
-       }\r
-\r
-       public String[] getRoots() {\r
-               return roots.keys(new String[roots.size()]);\r
-       }\r
-\r
-       void findChildren(int id, final Path path, final String suffix,\r
-                       final Pattern pattern, final THashSet<Path> result) {\r
-               if(pattern.matcher(suffix).matches())\r
-                       result.add(path);\r
-               THashMap<String,ConsistsOf> map = parentMap.get(id);\r
-               if(map != null)\r
-                       map.forEachValue(new TObjectProcedure<ConsistsOf>() {\r
-                               @Override\r
-                               public boolean execute(ConsistsOf consistsOf) {\r
-                                       findChildren(consistsOf.child, new PathChild(consistsOf.name, path), \r
-                                                       suffix + "/" + consistsOf.name, pattern, result);\r
-                                       return true;\r
-                               }\r
-                       });\r
-       }\r
-\r
-    public int[] getUnfoundedIdentities() {\r
-        TIntArrayList result = new TIntArrayList();\r
-        for(int resource : parentMap.keys()) {\r
-            if(!childMap.containsKey(resource) && !invRoots.containsKey(resource)) {\r
-                result.add(resource);\r
-            }\r
-        }\r
-        return result.toArray();\r
-    }\r
-    \r
-    public void forEachChild(TObjectProcedure<ConsistsOf> proc) {\r
-        childMap.forEachValue(proc);\r
-    }\r
-\r
-    public void setIdentity(int child, int parent, String name) {\r
-        THashMap<String, ConsistsOf> map = parentMap.get(parent);\r
-        if(map == null) {\r
-            map = new THashMap<String, ConsistsOf>();\r
-            parentMap.put(parent, map);         \r
-        }\r
-        else if(map.contains(name))\r
-            throw new IllegalStateException();        \r
-        ConsistsOf consistsOf = new ConsistsOf(parent, name, child);\r
-        map.put(name, consistsOf);\r
-        childMap.put(child, consistsOf);\r
-    }\r
-       \r
-}\r
+package org.simantics.graph.store;
+
+import gnu.trove.list.array.TIntArrayList;
+import gnu.trove.map.hash.THashMap;
+import gnu.trove.map.hash.TIntIntHashMap;
+import gnu.trove.map.hash.TIntObjectHashMap;
+import gnu.trove.map.hash.TObjectIntHashMap;
+import gnu.trove.procedure.TIntProcedure;
+import gnu.trove.procedure.TObjectIntProcedure;
+import gnu.trove.procedure.TObjectObjectProcedure;
+import gnu.trove.procedure.TObjectProcedure;
+import gnu.trove.set.hash.THashSet;
+import gnu.trove.set.hash.TIntHashSet;
+
+import java.util.ArrayList;
+import java.util.regex.Pattern;
+
+import org.simantics.graph.query.Path;
+import org.simantics.graph.query.PathChild;
+import org.simantics.graph.query.PathRoot;
+import org.simantics.graph.representation.External;
+import org.simantics.graph.representation.Identity;
+import org.simantics.graph.representation.Internal;
+import org.simantics.graph.representation.Root;
+
+public class IdentityStore implements IStore {
+       
+       private static int[] EMPTY_INT_ARRAY = new int[0];
+       
+       public static class ConsistsOf {
+               public int parent;
+               public String name;
+               public int child;
+               
+               public ConsistsOf(int parent, String name, int child) {
+                       //System.out.println(parent + "." + name + " = " + child);
+                       this.parent = parent;
+                       this.name = name;
+                       this.child = child;
+               }
+       }
+       
+       TObjectIntHashMap<String> roots = new TObjectIntHashMap<String>();
+       TIntObjectHashMap<String> invRoots = new TIntObjectHashMap<String>();
+       TIntObjectHashMap<THashMap<String, ConsistsOf>> parentMap =
+               new TIntObjectHashMap<THashMap<String, ConsistsOf>>();
+       TIntObjectHashMap<ConsistsOf> childMap = new TIntObjectHashMap<ConsistsOf>();
+       TIntHashSet newResources = new TIntHashSet();
+       int resourceCount = 0;
+       TIntIntHashMap unifications = new TIntIntHashMap();
+       TIntHashSet collisions = new TIntHashSet();
+       
+       public int newResource() {
+               return resourceCount++;
+       }
+
+       public boolean markNew(int resource) {
+               return newResources.add(resource);
+       }
+       
+       public int[] getNewResources() {
+               return newResources.toArray();
+       }
+       
+       public int getResourceCount() {
+               return resourceCount;
+       }
+       
+       public void setResourceCount(int newCount) {
+               resourceCount = newCount;
+       }
+               
+       public void defineRoot(String name, int root) {
+               if(roots.contains(name))
+                       unify(root, roots.get(name));
+               roots.put(name, root);
+               invRoots.put(root, name);
+       }
+       
+       public void defineChild(int parent, String name, int child) {
+               THashMap<String, ConsistsOf> map = parentMap.get(parent);
+               if(map == null) {
+                       map = new THashMap<String, ConsistsOf>();
+                       parentMap.put(parent, map);                     
+               }
+               ConsistsOf consistsOf = new ConsistsOf(parent, name, child);
+               ConsistsOf oldC = map.put(name, consistsOf);
+               if(oldC != null)
+                       unify(child, oldC.child);
+               childMap.put(child, consistsOf);
+       }
+       
+       public boolean hasChild(int parent, String name) {
+           THashMap<String, ConsistsOf> map = parentMap.get(parent);
+        if(map == null)
+            return false;
+        else
+            return map.contains(name);
+       }
+       
+       public int getChild(int parent, String name) {
+               THashMap<String, ConsistsOf> map = parentMap.get(parent);
+               if(map == null) {
+                       map = new THashMap<String, ConsistsOf>();
+                       parentMap.put(parent, map);                     
+               }
+               else if(map.contains(name))
+                       return map.get(name).child;
+               int child = newResource();
+               ConsistsOf consistsOf = new ConsistsOf(parent, name, child);
+               map.put(name, consistsOf);
+               childMap.put(child, consistsOf);
+               return child;
+       }
+       
+       public int getChildIfExists(int parent, String name) {
+               THashMap<String, ConsistsOf> map = parentMap.get(parent);
+               if(map != null && map.contains(name))
+                       return map.get(name).child;
+               return -1;
+       }
+
+       public int getRoot(String uri) {
+               if(roots.contains(uri))
+                       return roots.get(uri);
+               else {
+                       int root = newResource();
+                       roots.put(uri, root);
+                       invRoots.put(root, uri);
+                       return root;
+               }
+       }
+       
+       public int getRootIfExists(String uri) {
+               if(roots.contains(uri))
+                       return roots.get(uri);
+               return -1;
+       }
+       
+       public int[] getChildren(int id) {
+               THashMap<String,ConsistsOf> map = parentMap.get(id);
+               if(map == null)
+                       return EMPTY_INT_ARRAY;
+               final int[] result = new int[map.size()];
+               map.forEachValue(new TObjectProcedure<ConsistsOf>() {
+                       int i=0;
+                       @Override
+                       public boolean execute(ConsistsOf object) {
+                               result[i++] = object.child;
+                               return true;
+                       }
+               });
+               return result;
+       }
+       
+       public THashMap<String, ConsistsOf> getChildMap(int parent) {
+        return parentMap.get(parent);      
+       }
+       
+       private void collectIdentities(final int parent, final ArrayList<Identity> identities) {
+               THashMap<String, ConsistsOf> map = parentMap.get(parent);
+               if(map != null) {
+                       map.forEachEntry(new TObjectObjectProcedure<String, ConsistsOf>() {
+                               
+                               @Override
+                               public boolean execute(String a, ConsistsOf b) {
+                                       if(newResources.contains(b.child))
+                                               identities.add(new Identity(b.child, new Internal(parent, a)));
+                                       else
+                                               identities.add(new Identity(b.child, new External(parent, a)));
+                                       collectIdentities(b.child, identities);
+                                       return true;
+                               }
+                       });
+               }
+       }
+       
+       private void collectIdentities(final ArrayList<Identity> identities) {
+               roots.forEachEntry(new TObjectIntProcedure<String>() {                  
+                       @Override
+                       public boolean execute(String a, int b) {
+                               identities.add(new Identity(b, new Root(a, "")));
+                               collectIdentities(b, identities);
+                               return true;
+                       }                       
+               });
+       }
+       
+       @Override
+       public void map(final TIntIntHashMap map) {
+               collisions = IndexMappingUtils.map(map, collisions);
+               newResources = IndexMappingUtils.map(map, newResources);                
+               IndexMappingUtils.map(map, roots);
+               invRoots = IndexMappingUtils.map(map, invRoots, collisions);
+               
+               final ArrayList<ConsistsOf> consistsOfs = new ArrayList<ConsistsOf>(childMap.size());
+               childMap.forEachValue(new TObjectProcedure<IdentityStore.ConsistsOf>() {                        
+                       @Override
+                       public boolean execute(ConsistsOf c) {
+                               if(map.contains(c.parent))
+                                       c.parent = map.get(c.parent);
+                               if(map.contains(c.child))
+                                       c.child = map.get(c.child);
+                               consistsOfs.add(c);
+                               return true;
+                       }
+               });
+               
+               childMap.clear();
+               parentMap.clear();
+               assert(unifications.isEmpty());
+               
+               for(ConsistsOf c : consistsOfs) {
+                       THashMap<String, ConsistsOf> m = parentMap.get(c.parent);
+                       if(m == null) {
+                               m = new THashMap<String, ConsistsOf>();
+                               parentMap.put(c.parent, m);                     
+                       }
+                       ConsistsOf oldC = m.put(c.name, c);
+                       ConsistsOf childC = childMap.put(c.child, c);
+                       if(childC != null && (childC.parent != c.parent || !childC.name.equals(c.name)))
+                               collisions.add(c.child);
+                       
+                       if(oldC != null) 
+                               unify(oldC.child, c.child);
+               }
+       }
+       
+       public int pathToId(Path path) {
+               if(path instanceof PathChild) {
+                       PathChild child = (PathChild)path;
+                       int parent = pathToId(child.parent);
+                       if(parent < 0)
+                               return -1;
+                       return getChildIfExists(parent, child.name);
+               }
+               else if(path instanceof PathRoot)
+                       return getRootIfExists(((PathRoot)path).name);
+               else
+                       throw new IllegalArgumentException();
+       }
+       
+       public int createPathToId(Path path) {
+               if(path instanceof PathChild) {
+                       PathChild child = (PathChild)path;
+                       return getChild(createPathToId(child.parent), child.name);
+               }
+               else if(path instanceof PathRoot)
+                       return getRoot(((PathRoot)path).name);
+               else
+                       throw new IllegalArgumentException();
+       }
+       
+       public Path idToPath(int id) {
+               ConsistsOf consistsOf = childMap.get(id);
+               if(consistsOf == null) {
+                       String root = invRoots.get(id);
+                       if(root == null)
+                               return null;
+                       else
+                               return new PathRoot(root);
+               }
+               /*System.out.println("ConsistsOf(" + 
+                               consistsOf.parent + "." + consistsOf.name + 
+                               " = " + consistsOf.child + ")");
+                               */
+               //if(consistsOf.parent == consistsOf.child)
+               //    return null; 
+               Path parentPath = idToPath(consistsOf.parent);
+               if(parentPath == null)
+                       return null;
+               return new PathChild(consistsOf.name, parentPath);
+       }
+       
+       public boolean contains(Path path) {
+               return pathToId(path) >= 0;
+       }
+
+       public boolean isNewResource(int id) {
+               return newResources.contains(id);
+       }
+
+       public Identity[] toArray() {
+               final ArrayList<Identity> identities = new ArrayList<Identity>();
+               collectIdentities(identities);
+               return identities.toArray(new Identity[identities.size()]);
+       }
+       
+       public void collectReferences(final boolean[] set) {
+               TIntProcedure proc = new TIntProcedure() {                      
+                       @Override
+                       public boolean execute(int value) {
+                               set[value] = true;
+                               return true;
+                       }
+               };
+               
+               roots.forEachValue(proc);
+               childMap.forEach(proc);
+               parentMap.forEach(proc);
+       }
+
+       public int removeIdentity(int id) {
+               ConsistsOf c = childMap.remove(id);
+               if(c != null) {             
+                   parentMap.get(c.parent).remove(c.name);
+                   return c.parent;
+               }
+               return -1;
+       }
+
+       public boolean hasIdentity(int id) {
+               return childMap.containsKey(id);
+       }
+
+       public void definePath(Path path, int resource) {
+               if(path instanceof PathChild) {
+                       PathChild child = (PathChild)path;
+                       int parent = createPathToId(child.parent);
+                       defineChild(parent, child.name, resource);
+               }
+               else if(path instanceof PathRoot) {
+                       defineRoot(((PathRoot)path).name, resource);
+               }
+               else
+                       throw new IllegalArgumentException();           
+       }
+       
+       public void printChildMap() {
+               System.out.println("ChildMap:");
+               childMap.forEachValue(new TObjectProcedure<ConsistsOf>() {
+
+                       @Override
+                       public boolean execute(ConsistsOf c) {
+                               System.out.println("    " + 
+                                               c.child + " = " + c.parent + "." + c.name);
+                               return true;
+                       }
+                       
+               });
+       }
+       
+       private int canonical(int a) {
+               if(unifications.contains(a)) {
+                       int b = unifications.get(a);
+                       if(unifications.contains(b)) {
+                               int c = canonical(b);
+                               unifications.put(a, c);
+                               unifications.put(b, c);
+                               return c;
+                       }
+                       else 
+                               return b;
+               }
+               else
+                       return a;
+       }
+       
+       public TIntIntHashMap extractUnifications() {
+               // This normalizes the map
+               for(int a : unifications.keys())
+                       canonical(a);
+               
+               TIntIntHashMap result = unifications;
+               unifications = new TIntIntHashMap();
+               
+               return result;
+       }
+       
+       public void unify(int a, int b) {
+               if(a != b) {
+                       a = canonical(a);
+                       b = canonical(b);
+                       if(a != b)
+                               unifications.put(a, b);
+               }
+       }
+       
+       public TIntHashSet getCollisions() {
+               return collisions;
+       }
+
+       public String[] getRoots() {
+               return roots.keys(new String[roots.size()]);
+       }
+
+       void findChildren(int id, final Path path, final String suffix,
+                       final Pattern pattern, final THashSet<Path> result) {
+               if(pattern.matcher(suffix).matches())
+                       result.add(path);
+               THashMap<String,ConsistsOf> map = parentMap.get(id);
+               if(map != null)
+                       map.forEachValue(new TObjectProcedure<ConsistsOf>() {
+                               @Override
+                               public boolean execute(ConsistsOf consistsOf) {
+                                       findChildren(consistsOf.child, new PathChild(consistsOf.name, path), 
+                                                       suffix + "/" + consistsOf.name, pattern, result);
+                                       return true;
+                               }
+                       });
+       }
+
+    public int[] getUnfoundedIdentities() {
+        TIntArrayList result = new TIntArrayList();
+        for(int resource : parentMap.keys()) {
+            if(!childMap.containsKey(resource) && !invRoots.containsKey(resource)) {
+                result.add(resource);
+            }
+        }
+        return result.toArray();
+    }
+    
+    public void forEachChild(TObjectProcedure<ConsistsOf> proc) {
+        childMap.forEachValue(proc);
+    }
+
+    public void setIdentity(int child, int parent, String name) {
+        THashMap<String, ConsistsOf> map = parentMap.get(parent);
+        if(map == null) {
+            map = new THashMap<String, ConsistsOf>();
+            parentMap.put(parent, map);         
+        }
+        else if(map.contains(name))
+            throw new IllegalStateException();        
+        ConsistsOf consistsOf = new ConsistsOf(parent, name, child);
+        map.put(name, consistsOf);
+        childMap.put(child, consistsOf);
+    }
+       
+}