-package org.simantics.graph.store;\r
-\r
-import java.util.ArrayList;\r
-\r
-import gnu.trove.list.array.TIntArrayList;\r
-import gnu.trove.map.hash.TIntIntHashMap;\r
-import gnu.trove.map.hash.TIntObjectHashMap;\r
-import gnu.trove.procedure.TIntObjectProcedure;\r
-import gnu.trove.procedure.TIntProcedure;\r
-import gnu.trove.procedure.TObjectProcedure;\r
-import gnu.trove.set.hash.TIntHashSet;\r
-\r
-/**\r
- * Statement store indexes a set of statements. \r
- * @author Hannu Niemist�\r
- */\r
-public class StatementStore implements IStore {\r
- \r
- static private final TIntArrayList EMPTY_INT_LIST = new TIntArrayList(0); \r
- \r
- TIntObjectHashMap<TIntObjectHashMap<TIntArrayList>> statements =\r
- new TIntObjectHashMap<TIntObjectHashMap<TIntArrayList>>();\r
- \r
- /**\r
- * Adds a statement to the store.\r
- * @param subject\r
- * @param predicate\r
- * @param object\r
- */\r
- public void add(int subject, int predicate, int object) {\r
- assert(subject >= 0);\r
- assert(predicate >= 0);\r
- assert(object >= 0);\r
- TIntObjectHashMap<TIntArrayList> localStatements = \r
- statements.get(subject);\r
- if(localStatements == null) {\r
- localStatements = new TIntObjectHashMap<TIntArrayList>(3);\r
- statements.put(subject, localStatements);\r
- }\r
- TIntArrayList objects = localStatements.get(predicate);\r
- if(objects == null) {\r
- objects = new TIntArrayList(2);\r
- localStatements.put(predicate, objects);\r
- }\r
- objects.add(object);\r
- }\r
- \r
- public void map(final TIntIntHashMap map) {\r
- final TIntObjectHashMap<TIntObjectHashMap<TIntArrayList>> newStatements = \r
- new TIntObjectHashMap<TIntObjectHashMap<TIntArrayList>>(statements.size()*2+1);\r
- statements.forEachEntry(new TIntObjectProcedure<TIntObjectHashMap<TIntArrayList>>() {\r
- \r
- TIntObjectHashMap<TIntArrayList> newLocalStatements;\r
- TIntArrayList newObjects;\r
- \r
- TIntProcedure objectProcedure = new TIntProcedure() { \r
- @Override\r
- public boolean execute(int o) {\r
- if(map.contains(o))\r
- o = map.get(o);\r
- newObjects.add(o);\r
- return true;\r
- }\r
- };\r
- \r
- TIntObjectProcedure<TIntArrayList> predicateProcedure = new TIntObjectProcedure<TIntArrayList>() {\r
- @Override\r
- public boolean execute(int p, TIntArrayList objects) {\r
- if(map.contains(p))\r
- p = map.get(p);\r
- TIntArrayList exObjects = newLocalStatements.get(p);\r
- if(exObjects == null) {\r
- IndexMappingUtils.map(map, objects);\r
- newLocalStatements.put(p, objects);\r
- }\r
- else {\r
- newObjects = exObjects;\r
- objects.forEach(objectProcedure);\r
- }\r
- return true;\r
- }\r
- };\r
- \r
- @Override\r
- public boolean execute(int s, TIntObjectHashMap<TIntArrayList> localStatements) {\r
- if(map.contains(s))\r
- s = map.get(s);\r
- TIntObjectHashMap<TIntArrayList> exLocalStatements = newStatements.get(s); \r
- if(exLocalStatements == null) {\r
- exLocalStatements = new TIntObjectHashMap<TIntArrayList>(localStatements.size()*2 + 1);\r
- newStatements.put(s, exLocalStatements);\r
- }\r
- newLocalStatements = exLocalStatements;\r
- localStatements.forEachEntry(predicateProcedure);\r
- return true;\r
- }\r
- });\r
- statements = newStatements;\r
- }\r
- \r
- public void forStatements(final IStatementProcedure proc) {\r
- statements.forEachEntry(new TIntObjectProcedure<TIntObjectHashMap<TIntArrayList>>() {\r
- @Override\r
- public boolean execute(final int s, TIntObjectHashMap<TIntArrayList> localStatements) {\r
- localStatements.forEachEntry(new TIntObjectProcedure<TIntArrayList>() {\r
- @Override\r
- public boolean execute(final int p, TIntArrayList objects) {\r
- objects.forEach(new TIntProcedure() { \r
- @Override\r
- public boolean execute(int o) {\r
- proc.execute(s, p, o);\r
- return true;\r
- }\r
- });\r
- return true;\r
- }\r
- });\r
- return true;\r
- }\r
- });\r
- }\r
- \r
- private static class ForStatementsWithSubjectProc implements TIntObjectProcedure<TIntArrayList>, TIntProcedure {\r
- int s;\r
- int p;\r
- IStatementProcedure proc;\r
- \r
- public ForStatementsWithSubjectProc(int s, IStatementProcedure proc) {\r
- this.s = s;\r
- this.proc = proc;\r
- }\r
-\r
- @Override\r
- public boolean execute(int o) {\r
- proc.execute(s, p, o);\r
- return true;\r
- }\r
-\r
- @Override\r
- public boolean execute(int p, TIntArrayList b) {\r
- this.p = p;\r
- b.forEach(this);\r
- return true;\r
- } \r
- }\r
- \r
- public void forStatementsWithSubject(int s, IStatementProcedure proc) {\r
- TIntObjectHashMap<TIntArrayList> localStatements = statements.get(s);\r
- if(localStatements == null)\r
- return;\r
- localStatements.forEachEntry(new ForStatementsWithSubjectProc(s, proc));\r
- }\r
- \r
- public void forStatements(final int predicate, final IStatementProcedure proc) {\r
- statements.forEachEntry(new TIntObjectProcedure<TIntObjectHashMap<TIntArrayList>>() {\r
- @Override\r
- public boolean execute(final int s, TIntObjectHashMap<TIntArrayList> localStatements) {\r
- TIntArrayList objects = localStatements.get(predicate);\r
- if(objects != null)\r
- objects.forEach(new TIntProcedure() { \r
- @Override\r
- public boolean execute(int o) {\r
- proc.execute(s, predicate, o);\r
- return true;\r
- }\r
- }); \r
- return true;\r
- }\r
- });\r
- }\r
- \r
- public TIntArrayList getRelation(int predicate) {\r
- final TIntArrayList result = new TIntArrayList();\r
- forStatements(predicate, new IStatementProcedure() { \r
- @Override\r
- public void execute(int s, int p, int o) {\r
- result.add(s);\r
- result.add(o);\r
- }\r
- });\r
- return result;\r
- }\r
- \r
- public TIntHashSet getRelationDomain(final int predicate) {\r
- final TIntHashSet result = new TIntHashSet();\r
- statements.forEachEntry(new TIntObjectProcedure<TIntObjectHashMap<TIntArrayList>>() {\r
- @Override\r
- public boolean execute(int s, TIntObjectHashMap<TIntArrayList> localStatements) {\r
- if(localStatements.containsKey(predicate))\r
- result.add(s);\r
- return true;\r
- }\r
- });\r
- return result;\r
- }\r
- \r
- public TIntArrayList extractRelation(final int predicate) {\r
- final TIntArrayList result = new TIntArrayList();\r
- final TIntArrayList removals = new TIntArrayList();\r
- statements.forEachEntry(new TIntObjectProcedure<TIntObjectHashMap<TIntArrayList>>() {\r
- @Override\r
- public boolean execute(int s, TIntObjectHashMap<TIntArrayList> localStatements) {\r
- TIntArrayList objects = localStatements.remove(predicate);\r
- if(objects != null) {\r
- for(int o : objects.toArray()) {\r
- result.add(s);\r
- result.add(o);\r
- }\r
- }\r
- if(localStatements.isEmpty())\r
- removals.add(s);\r
- return true;\r
- }\r
- });\r
- for(int s : removals.toArray())\r
- statements.remove(s);\r
- return result;\r
- }\r
- \r
- public TIntArrayList getObjects(int subject, int predicate) {\r
- TIntObjectHashMap<TIntArrayList> localStatements = statements.get(subject);\r
- if(localStatements == null)\r
- return EMPTY_INT_LIST;\r
- TIntArrayList objects = localStatements.get(predicate);\r
- if(objects == null)\r
- return EMPTY_INT_LIST;\r
- return objects;\r
- }\r
-\r
- public int[] toArray(final TIntIntHashMap inverseMap) {\r
- final TIntArrayList statements = new TIntArrayList();\r
- forStatements(new IStatementProcedure() { \r
- @Override\r
- public void execute(int s, int p, int o) {\r
- statements.add(s);\r
- statements.add(p);\r
- int inverse = -1;\r
- if(inverseMap.contains(p)) {\r
- inverse = inverseMap.get(p);\r
- if(p==inverse && s == o)\r
- inverse = -1;\r
- }\r
- statements.add(inverse);\r
- statements.add(o); \r
- }\r
- });\r
- return statements.toArray();\r
- }\r
- \r
- public void collectReferences(final boolean[] set) {\r
- forStatements(new IStatementProcedure() { \r
- @Override\r
- public void execute(int s, int p, int o) {\r
- set[s] = true;\r
- set[p] = true;\r
- set[o] = true; \r
- }\r
- });\r
- }\r
-\r
- public TIntHashSet getPredicates() {\r
- final TIntHashSet result = new TIntHashSet();\r
- statements.forEachValue(new TObjectProcedure<TIntObjectHashMap<TIntArrayList>>() { \r
- TIntProcedure proc = new TIntProcedure() { \r
- @Override\r
- public boolean execute(int value) {\r
- result.add(value);\r
- return true;\r
- }\r
- }; \r
- @Override\r
- public boolean execute(TIntObjectHashMap<TIntArrayList> localStatements) {\r
- localStatements.forEachKey(proc);\r
- return true;\r
- }\r
- });\r
- return result;\r
- }\r
-\r
- public int[] toArray() {\r
- final TIntArrayList statements = new TIntArrayList();\r
- forStatements(new IStatementProcedure() { \r
- @Override\r
- public void execute(int s, int p, int o) {\r
- statements.add(s);\r
- statements.add(p);\r
- statements.add(-1);\r
- statements.add(o); \r
- }\r
- });\r
- return statements.toArray();\r
- }\r
-\r
- private static class CollisionSubjectProcedure implements TIntObjectProcedure<TIntObjectHashMap<TIntArrayList>> {\r
- CollisionPredicateProcedure predicateProcedure;\r
-\r
- public CollisionSubjectProcedure(CollisionPredicateProcedure predicateProcedure) {\r
- this.predicateProcedure = predicateProcedure;\r
- }\r
-\r
- @Override\r
- public boolean execute(int subject, TIntObjectHashMap<TIntArrayList> predicateObjectMap) {\r
- predicateProcedure.subject = subject;\r
- predicateObjectMap.forEachEntry(predicateProcedure);\r
- return true;\r
- }\r
-\r
- }\r
-\r
- private static class CollisionPredicateProcedure implements TIntObjectProcedure<TIntArrayList> {\r
- ArrayList<StatementCollision> collisions;\r
- int subject;\r
- \r
- public CollisionPredicateProcedure(ArrayList<StatementCollision> collisions) {\r
- this.collisions = collisions;\r
- }\r
- \r
- @Override\r
- public boolean execute(int predicate, TIntArrayList objects) {\r
- if(objects.size() > 1) {\r
- objects.sort();\r
- int oldObject = objects.get(0);\r
- int collisionCount = 1;\r
- for(int i=1;i<objects.size();++i) {\r
- int curObject = objects.get(i);\r
- if(curObject == oldObject) {\r
- ++collisionCount;\r
- }\r
- else {\r
- if(collisionCount > 1) {\r
- collisions.add(new StatementCollision(subject, predicate, oldObject, collisionCount));\r
- collisionCount = 1;\r
- }\r
- oldObject = curObject;\r
- }\r
- }\r
- if(collisionCount > 1)\r
- collisions.add(new StatementCollision(subject, predicate, oldObject, collisionCount));\r
- }\r
- return true;\r
- }\r
-\r
- }\r
-\r
- public ArrayList<StatementCollision> getCollisions() {\r
- ArrayList<StatementCollision> collisions = new ArrayList<StatementCollision>();\r
- CollisionPredicateProcedure predicateProcedure = new CollisionPredicateProcedure(collisions);\r
- CollisionSubjectProcedure subjectProcedure = new CollisionSubjectProcedure(predicateProcedure);\r
- statements.forEachEntry(subjectProcedure);\r
- return collisions;\r
- } \r
-}\r
+package org.simantics.graph.store;
+
+import java.util.ArrayList;
+
+import gnu.trove.list.array.TIntArrayList;
+import gnu.trove.map.hash.TIntIntHashMap;
+import gnu.trove.map.hash.TIntObjectHashMap;
+import gnu.trove.procedure.TIntObjectProcedure;
+import gnu.trove.procedure.TIntProcedure;
+import gnu.trove.procedure.TObjectProcedure;
+import gnu.trove.set.hash.TIntHashSet;
+
+/**
+ * Statement store indexes a set of statements.
+ * @author Hannu Niemist�
+ */
+public class StatementStore implements IStore {
+
+ static private final TIntArrayList EMPTY_INT_LIST = new TIntArrayList(0);
+
+ TIntObjectHashMap<TIntObjectHashMap<TIntArrayList>> statements =
+ new TIntObjectHashMap<TIntObjectHashMap<TIntArrayList>>();
+
+ /**
+ * Adds a statement to the store.
+ * @param subject
+ * @param predicate
+ * @param object
+ */
+ public void add(int subject, int predicate, int object) {
+ assert(subject >= 0);
+ assert(predicate >= 0);
+ assert(object >= 0);
+ TIntObjectHashMap<TIntArrayList> localStatements =
+ statements.get(subject);
+ if(localStatements == null) {
+ localStatements = new TIntObjectHashMap<TIntArrayList>(3);
+ statements.put(subject, localStatements);
+ }
+ TIntArrayList objects = localStatements.get(predicate);
+ if(objects == null) {
+ objects = new TIntArrayList(2);
+ localStatements.put(predicate, objects);
+ }
+ objects.add(object);
+ }
+
+ public void map(final TIntIntHashMap map) {
+ final TIntObjectHashMap<TIntObjectHashMap<TIntArrayList>> newStatements =
+ new TIntObjectHashMap<TIntObjectHashMap<TIntArrayList>>(statements.size()*2+1);
+ statements.forEachEntry(new TIntObjectProcedure<TIntObjectHashMap<TIntArrayList>>() {
+
+ TIntObjectHashMap<TIntArrayList> newLocalStatements;
+ TIntArrayList newObjects;
+
+ TIntProcedure objectProcedure = new TIntProcedure() {
+ @Override
+ public boolean execute(int o) {
+ if(map.contains(o))
+ o = map.get(o);
+ newObjects.add(o);
+ return true;
+ }
+ };
+
+ TIntObjectProcedure<TIntArrayList> predicateProcedure = new TIntObjectProcedure<TIntArrayList>() {
+ @Override
+ public boolean execute(int p, TIntArrayList objects) {
+ if(map.contains(p))
+ p = map.get(p);
+ TIntArrayList exObjects = newLocalStatements.get(p);
+ if(exObjects == null) {
+ IndexMappingUtils.map(map, objects);
+ newLocalStatements.put(p, objects);
+ }
+ else {
+ newObjects = exObjects;
+ objects.forEach(objectProcedure);
+ }
+ return true;
+ }
+ };
+
+ @Override
+ public boolean execute(int s, TIntObjectHashMap<TIntArrayList> localStatements) {
+ if(map.contains(s))
+ s = map.get(s);
+ TIntObjectHashMap<TIntArrayList> exLocalStatements = newStatements.get(s);
+ if(exLocalStatements == null) {
+ exLocalStatements = new TIntObjectHashMap<TIntArrayList>(localStatements.size()*2 + 1);
+ newStatements.put(s, exLocalStatements);
+ }
+ newLocalStatements = exLocalStatements;
+ localStatements.forEachEntry(predicateProcedure);
+ return true;
+ }
+ });
+ statements = newStatements;
+ }
+
+ public void forStatements(final IStatementProcedure proc) {
+ statements.forEachEntry(new TIntObjectProcedure<TIntObjectHashMap<TIntArrayList>>() {
+ @Override
+ public boolean execute(final int s, TIntObjectHashMap<TIntArrayList> localStatements) {
+ localStatements.forEachEntry(new TIntObjectProcedure<TIntArrayList>() {
+ @Override
+ public boolean execute(final int p, TIntArrayList objects) {
+ objects.forEach(new TIntProcedure() {
+ @Override
+ public boolean execute(int o) {
+ proc.execute(s, p, o);
+ return true;
+ }
+ });
+ return true;
+ }
+ });
+ return true;
+ }
+ });
+ }
+
+ private static class ForStatementsWithSubjectProc implements TIntObjectProcedure<TIntArrayList>, TIntProcedure {
+ int s;
+ int p;
+ IStatementProcedure proc;
+
+ public ForStatementsWithSubjectProc(int s, IStatementProcedure proc) {
+ this.s = s;
+ this.proc = proc;
+ }
+
+ @Override
+ public boolean execute(int o) {
+ proc.execute(s, p, o);
+ return true;
+ }
+
+ @Override
+ public boolean execute(int p, TIntArrayList b) {
+ this.p = p;
+ b.forEach(this);
+ return true;
+ }
+ }
+
+ public void forStatementsWithSubject(int s, IStatementProcedure proc) {
+ TIntObjectHashMap<TIntArrayList> localStatements = statements.get(s);
+ if(localStatements == null)
+ return;
+ localStatements.forEachEntry(new ForStatementsWithSubjectProc(s, proc));
+ }
+
+ public void forStatements(final int predicate, final IStatementProcedure proc) {
+ statements.forEachEntry(new TIntObjectProcedure<TIntObjectHashMap<TIntArrayList>>() {
+ @Override
+ public boolean execute(final int s, TIntObjectHashMap<TIntArrayList> localStatements) {
+ TIntArrayList objects = localStatements.get(predicate);
+ if(objects != null)
+ objects.forEach(new TIntProcedure() {
+ @Override
+ public boolean execute(int o) {
+ proc.execute(s, predicate, o);
+ return true;
+ }
+ });
+ return true;
+ }
+ });
+ }
+
+ public TIntArrayList getRelation(int predicate) {
+ final TIntArrayList result = new TIntArrayList();
+ forStatements(predicate, new IStatementProcedure() {
+ @Override
+ public void execute(int s, int p, int o) {
+ result.add(s);
+ result.add(o);
+ }
+ });
+ return result;
+ }
+
+ public TIntHashSet getRelationDomain(final int predicate) {
+ final TIntHashSet result = new TIntHashSet();
+ statements.forEachEntry(new TIntObjectProcedure<TIntObjectHashMap<TIntArrayList>>() {
+ @Override
+ public boolean execute(int s, TIntObjectHashMap<TIntArrayList> localStatements) {
+ if(localStatements.containsKey(predicate))
+ result.add(s);
+ return true;
+ }
+ });
+ return result;
+ }
+
+ public TIntArrayList extractRelation(final int predicate) {
+ final TIntArrayList result = new TIntArrayList();
+ final TIntArrayList removals = new TIntArrayList();
+ statements.forEachEntry(new TIntObjectProcedure<TIntObjectHashMap<TIntArrayList>>() {
+ @Override
+ public boolean execute(int s, TIntObjectHashMap<TIntArrayList> localStatements) {
+ TIntArrayList objects = localStatements.remove(predicate);
+ if(objects != null) {
+ for(int o : objects.toArray()) {
+ result.add(s);
+ result.add(o);
+ }
+ }
+ if(localStatements.isEmpty())
+ removals.add(s);
+ return true;
+ }
+ });
+ for(int s : removals.toArray())
+ statements.remove(s);
+ return result;
+ }
+
+ public TIntArrayList getObjects(int subject, int predicate) {
+ TIntObjectHashMap<TIntArrayList> localStatements = statements.get(subject);
+ if(localStatements == null)
+ return EMPTY_INT_LIST;
+ TIntArrayList objects = localStatements.get(predicate);
+ if(objects == null)
+ return EMPTY_INT_LIST;
+ return objects;
+ }
+
+ public int[] toArray(final TIntIntHashMap inverseMap) {
+ final TIntArrayList statements = new TIntArrayList();
+ forStatements(new IStatementProcedure() {
+ @Override
+ public void execute(int s, int p, int o) {
+ statements.add(s);
+ statements.add(p);
+ int inverse = -1;
+ if(inverseMap.contains(p)) {
+ inverse = inverseMap.get(p);
+ if(p==inverse && s == o)
+ inverse = -1;
+ }
+ statements.add(inverse);
+ statements.add(o);
+ }
+ });
+ return statements.toArray();
+ }
+
+ public void collectReferences(final boolean[] set) {
+ forStatements(new IStatementProcedure() {
+ @Override
+ public void execute(int s, int p, int o) {
+ set[s] = true;
+ set[p] = true;
+ set[o] = true;
+ }
+ });
+ }
+
+ public TIntHashSet getPredicates() {
+ final TIntHashSet result = new TIntHashSet();
+ statements.forEachValue(new TObjectProcedure<TIntObjectHashMap<TIntArrayList>>() {
+ TIntProcedure proc = new TIntProcedure() {
+ @Override
+ public boolean execute(int value) {
+ result.add(value);
+ return true;
+ }
+ };
+ @Override
+ public boolean execute(TIntObjectHashMap<TIntArrayList> localStatements) {
+ localStatements.forEachKey(proc);
+ return true;
+ }
+ });
+ return result;
+ }
+
+ public int[] toArray() {
+ final TIntArrayList statements = new TIntArrayList();
+ forStatements(new IStatementProcedure() {
+ @Override
+ public void execute(int s, int p, int o) {
+ statements.add(s);
+ statements.add(p);
+ statements.add(-1);
+ statements.add(o);
+ }
+ });
+ return statements.toArray();
+ }
+
+ private static class CollisionSubjectProcedure implements TIntObjectProcedure<TIntObjectHashMap<TIntArrayList>> {
+ CollisionPredicateProcedure predicateProcedure;
+
+ public CollisionSubjectProcedure(CollisionPredicateProcedure predicateProcedure) {
+ this.predicateProcedure = predicateProcedure;
+ }
+
+ @Override
+ public boolean execute(int subject, TIntObjectHashMap<TIntArrayList> predicateObjectMap) {
+ predicateProcedure.subject = subject;
+ predicateObjectMap.forEachEntry(predicateProcedure);
+ return true;
+ }
+
+ }
+
+ private static class CollisionPredicateProcedure implements TIntObjectProcedure<TIntArrayList> {
+ ArrayList<StatementCollision> collisions;
+ int subject;
+
+ public CollisionPredicateProcedure(ArrayList<StatementCollision> collisions) {
+ this.collisions = collisions;
+ }
+
+ @Override
+ public boolean execute(int predicate, TIntArrayList objects) {
+ if(objects.size() > 1) {
+ objects.sort();
+ int oldObject = objects.get(0);
+ int collisionCount = 1;
+ for(int i=1;i<objects.size();++i) {
+ int curObject = objects.get(i);
+ if(curObject == oldObject) {
+ ++collisionCount;
+ }
+ else {
+ if(collisionCount > 1) {
+ collisions.add(new StatementCollision(subject, predicate, oldObject, collisionCount));
+ collisionCount = 1;
+ }
+ oldObject = curObject;
+ }
+ }
+ if(collisionCount > 1)
+ collisions.add(new StatementCollision(subject, predicate, oldObject, collisionCount));
+ }
+ return true;
+ }
+
+ }
+
+ public ArrayList<StatementCollision> getCollisions() {
+ ArrayList<StatementCollision> collisions = new ArrayList<StatementCollision>();
+ CollisionPredicateProcedure predicateProcedure = new CollisionPredicateProcedure(collisions);
+ CollisionSubjectProcedure subjectProcedure = new CollisionSubjectProcedure(predicateProcedure);
+ statements.forEachEntry(subjectProcedure);
+ return collisions;
+ }
+}