]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.graph/src/org/simantics/graph/store/StatementStore.java
cc82975c8191fe2cd980c9eaf3963fa47e49939c
[simantics/platform.git] / bundles / org.simantics.graph / src / org / simantics / graph / store / StatementStore.java
1 package org.simantics.graph.store;\r
2 \r
3 import java.util.ArrayList;\r
4 \r
5 import gnu.trove.list.array.TIntArrayList;\r
6 import gnu.trove.map.hash.TIntIntHashMap;\r
7 import gnu.trove.map.hash.TIntObjectHashMap;\r
8 import gnu.trove.procedure.TIntObjectProcedure;\r
9 import gnu.trove.procedure.TIntProcedure;\r
10 import gnu.trove.procedure.TObjectProcedure;\r
11 import gnu.trove.set.hash.TIntHashSet;\r
12 \r
13 /**\r
14  * Statement store indexes a set of statements. \r
15  * @author Hannu Niemist�\r
16  */\r
17 public class StatementStore implements IStore {\r
18         \r
19         static private final TIntArrayList EMPTY_INT_LIST = new TIntArrayList(0);       \r
20         \r
21         TIntObjectHashMap<TIntObjectHashMap<TIntArrayList>> statements =\r
22                 new TIntObjectHashMap<TIntObjectHashMap<TIntArrayList>>();\r
23         \r
24         /**\r
25          * Adds a statement to the store.\r
26          * @param subject\r
27          * @param predicate\r
28          * @param object\r
29          */\r
30         public void add(int subject, int predicate, int object) {\r
31                 assert(subject >= 0);\r
32                 assert(predicate >= 0);\r
33                 assert(object >= 0);\r
34                 TIntObjectHashMap<TIntArrayList> localStatements = \r
35                         statements.get(subject);\r
36                 if(localStatements == null) {\r
37                         localStatements = new TIntObjectHashMap<TIntArrayList>(3);\r
38                         statements.put(subject, localStatements);\r
39                 }\r
40                 TIntArrayList objects = localStatements.get(predicate);\r
41                 if(objects == null) {\r
42                         objects = new TIntArrayList(2);\r
43                         localStatements.put(predicate, objects);\r
44                 }\r
45                 objects.add(object);\r
46         }\r
47         \r
48         public void map(final TIntIntHashMap map) {\r
49                 final TIntObjectHashMap<TIntObjectHashMap<TIntArrayList>> newStatements = \r
50                         new TIntObjectHashMap<TIntObjectHashMap<TIntArrayList>>(statements.size()*2+1);\r
51                 statements.forEachEntry(new TIntObjectProcedure<TIntObjectHashMap<TIntArrayList>>() {\r
52                         \r
53                         TIntObjectHashMap<TIntArrayList> newLocalStatements;\r
54                         TIntArrayList newObjects;\r
55                         \r
56                         TIntProcedure objectProcedure = new TIntProcedure() {                                                           \r
57                                 @Override\r
58                                 public boolean execute(int o) {\r
59                                         if(map.contains(o))\r
60                                                 o = map.get(o);\r
61                                         newObjects.add(o);\r
62                                         return true;\r
63                                 }\r
64                         };\r
65                         \r
66                         TIntObjectProcedure<TIntArrayList> predicateProcedure = new TIntObjectProcedure<TIntArrayList>() {\r
67                                 @Override\r
68                                 public boolean execute(int p, TIntArrayList objects) {\r
69                                         if(map.contains(p))\r
70                                                 p = map.get(p);\r
71                                         TIntArrayList exObjects = newLocalStatements.get(p);\r
72                                         if(exObjects == null) {\r
73                                                 IndexMappingUtils.map(map, objects);\r
74                                                 newLocalStatements.put(p, objects);\r
75                                         }\r
76                                         else {\r
77                                                 newObjects = exObjects;\r
78                                                 objects.forEach(objectProcedure);\r
79                                         }\r
80                                         return true;\r
81                                 }\r
82                         };\r
83                         \r
84                         @Override\r
85                         public boolean execute(int s, TIntObjectHashMap<TIntArrayList> localStatements) {\r
86                                 if(map.contains(s))\r
87                                         s = map.get(s);\r
88                                 TIntObjectHashMap<TIntArrayList> exLocalStatements = newStatements.get(s);                              \r
89                                 if(exLocalStatements == null) {\r
90                                         exLocalStatements = new TIntObjectHashMap<TIntArrayList>(localStatements.size()*2 + 1);\r
91                                         newStatements.put(s, exLocalStatements);\r
92                                 }\r
93                                 newLocalStatements = exLocalStatements;\r
94                                 localStatements.forEachEntry(predicateProcedure);\r
95                                 return true;\r
96                         }\r
97                 });\r
98                 statements = newStatements;\r
99         }\r
100         \r
101         public void forStatements(final IStatementProcedure proc) {\r
102                 statements.forEachEntry(new TIntObjectProcedure<TIntObjectHashMap<TIntArrayList>>() {\r
103                         @Override\r
104                         public boolean execute(final int s, TIntObjectHashMap<TIntArrayList> localStatements) {\r
105                                 localStatements.forEachEntry(new TIntObjectProcedure<TIntArrayList>() {\r
106                                         @Override\r
107                                         public boolean execute(final int p, TIntArrayList objects) {\r
108                                                 objects.forEach(new TIntProcedure() {                                                   \r
109                                                         @Override\r
110                                                         public boolean execute(int o) {\r
111                                                                 proc.execute(s, p, o);\r
112                                                                 return true;\r
113                                                         }\r
114                                                 });\r
115                                                 return true;\r
116                                         }\r
117                                 });\r
118                                 return true;\r
119                         }\r
120                 });\r
121         }\r
122         \r
123         private static class ForStatementsWithSubjectProc implements TIntObjectProcedure<TIntArrayList>, TIntProcedure {\r
124                 int s;\r
125                 int p;\r
126                 IStatementProcedure proc;\r
127                 \r
128                 public ForStatementsWithSubjectProc(int s, IStatementProcedure proc) {\r
129                         this.s = s;\r
130                         this.proc = proc;\r
131                 }\r
132 \r
133                 @Override\r
134                 public boolean execute(int o) {\r
135                         proc.execute(s, p, o);\r
136                         return true;\r
137                 }\r
138 \r
139                 @Override\r
140                 public boolean execute(int p, TIntArrayList b) {\r
141                         this.p = p;\r
142                         b.forEach(this);\r
143                         return true;\r
144                 }               \r
145         }\r
146         \r
147         public void forStatementsWithSubject(int s, IStatementProcedure proc) {\r
148                 TIntObjectHashMap<TIntArrayList> localStatements = statements.get(s);\r
149                 if(localStatements == null)\r
150                         return;\r
151                 localStatements.forEachEntry(new ForStatementsWithSubjectProc(s, proc));\r
152         }\r
153         \r
154         public void forStatements(final int predicate, final IStatementProcedure proc) {\r
155                 statements.forEachEntry(new TIntObjectProcedure<TIntObjectHashMap<TIntArrayList>>() {\r
156                         @Override\r
157                         public boolean execute(final int s, TIntObjectHashMap<TIntArrayList> localStatements) {\r
158                                 TIntArrayList objects = localStatements.get(predicate);\r
159                                 if(objects != null)\r
160                                         objects.forEach(new TIntProcedure() {                                                   \r
161                                                         @Override\r
162                                                         public boolean execute(int o) {\r
163                                                                 proc.execute(s, predicate, o);\r
164                                                                 return true;\r
165                                                         }\r
166                                                 });                                             \r
167                                 return true;\r
168                         }\r
169                 });\r
170         }\r
171         \r
172         public TIntArrayList getRelation(int predicate) {\r
173                 final TIntArrayList result = new TIntArrayList();\r
174                 forStatements(predicate, new IStatementProcedure() {                    \r
175                         @Override\r
176                         public void execute(int s, int p, int o) {\r
177                                 result.add(s);\r
178                                 result.add(o);\r
179                         }\r
180                 });\r
181                 return result;\r
182         }\r
183         \r
184         public TIntHashSet getRelationDomain(final int predicate) {\r
185                 final TIntHashSet result = new TIntHashSet();\r
186                 statements.forEachEntry(new TIntObjectProcedure<TIntObjectHashMap<TIntArrayList>>() {\r
187                         @Override\r
188                         public boolean execute(int s, TIntObjectHashMap<TIntArrayList> localStatements) {\r
189                                 if(localStatements.containsKey(predicate))\r
190                                         result.add(s);\r
191                                 return true;\r
192                         }\r
193                 });\r
194                 return result;\r
195         }\r
196         \r
197         public TIntArrayList extractRelation(final int predicate) {\r
198                 final TIntArrayList result = new TIntArrayList();\r
199                 final TIntArrayList removals = new TIntArrayList();\r
200                 statements.forEachEntry(new TIntObjectProcedure<TIntObjectHashMap<TIntArrayList>>() {\r
201                         @Override\r
202                         public boolean execute(int s, TIntObjectHashMap<TIntArrayList> localStatements) {\r
203                                 TIntArrayList objects = localStatements.remove(predicate);\r
204                                 if(objects != null) {\r
205                                         for(int o : objects.toArray()) {\r
206                                                 result.add(s);\r
207                                                 result.add(o);\r
208                                         }\r
209                                 }\r
210                                 if(localStatements.isEmpty())\r
211                                         removals.add(s);\r
212                                 return true;\r
213                         }\r
214                 });\r
215                 for(int s : removals.toArray())\r
216                         statements.remove(s);\r
217                 return result;\r
218         }\r
219         \r
220         public TIntArrayList getObjects(int subject, int predicate) {\r
221                 TIntObjectHashMap<TIntArrayList> localStatements = statements.get(subject);\r
222                 if(localStatements == null)\r
223                         return EMPTY_INT_LIST;\r
224                 TIntArrayList objects = localStatements.get(predicate);\r
225                 if(objects == null)\r
226                         return EMPTY_INT_LIST;\r
227                 return objects;\r
228         }\r
229 \r
230         public int[] toArray(final TIntIntHashMap inverseMap) {\r
231                 final TIntArrayList statements = new TIntArrayList();\r
232                 forStatements(new IStatementProcedure() {                       \r
233                         @Override\r
234                         public void execute(int s, int p, int o) {\r
235                                 statements.add(s);\r
236                                 statements.add(p);\r
237                                 int inverse = -1;\r
238                                 if(inverseMap.contains(p)) {\r
239                                         inverse = inverseMap.get(p);\r
240                                         if(p==inverse && s == o)\r
241                                                 inverse = -1;\r
242                                 }\r
243                                 statements.add(inverse);\r
244                                 statements.add(o);                              \r
245                         }\r
246                 });\r
247                 return statements.toArray();\r
248         }\r
249         \r
250         public void collectReferences(final boolean[] set) {\r
251                 forStatements(new IStatementProcedure() {                       \r
252                         @Override\r
253                         public void execute(int s, int p, int o) {\r
254                                 set[s] = true;\r
255                                 set[p] = true;\r
256                                 set[o] = true;          \r
257                         }\r
258                 });\r
259         }\r
260 \r
261         public TIntHashSet getPredicates() {\r
262                 final TIntHashSet result = new TIntHashSet();\r
263                 statements.forEachValue(new TObjectProcedure<TIntObjectHashMap<TIntArrayList>>() {                      \r
264                         TIntProcedure proc = new TIntProcedure() {                              \r
265                                 @Override\r
266                                 public boolean execute(int value) {\r
267                                         result.add(value);\r
268                                         return true;\r
269                                 }\r
270                         };                      \r
271                         @Override\r
272                         public boolean execute(TIntObjectHashMap<TIntArrayList> localStatements) {\r
273                                 localStatements.forEachKey(proc);\r
274                                 return true;\r
275                         }\r
276                 });\r
277                 return result;\r
278         }\r
279 \r
280         public int[] toArray() {\r
281                 final TIntArrayList statements = new TIntArrayList();\r
282                 forStatements(new IStatementProcedure() {                       \r
283                         @Override\r
284                         public void execute(int s, int p, int o) {\r
285                                 statements.add(s);\r
286                                 statements.add(p);\r
287                                 statements.add(-1);\r
288                                 statements.add(o);                              \r
289                         }\r
290                 });\r
291                 return statements.toArray();\r
292         }\r
293 \r
294         private static class CollisionSubjectProcedure implements TIntObjectProcedure<TIntObjectHashMap<TIntArrayList>> {\r
295             CollisionPredicateProcedure predicateProcedure;\r
296 \r
297             public CollisionSubjectProcedure(CollisionPredicateProcedure predicateProcedure) {\r
298                 this.predicateProcedure = predicateProcedure;\r
299             }\r
300 \r
301             @Override\r
302             public boolean execute(int subject, TIntObjectHashMap<TIntArrayList> predicateObjectMap) {\r
303                 predicateProcedure.subject = subject;\r
304                 predicateObjectMap.forEachEntry(predicateProcedure);\r
305                 return true;\r
306             }\r
307 \r
308         }\r
309 \r
310         private static class CollisionPredicateProcedure implements TIntObjectProcedure<TIntArrayList> {\r
311         ArrayList<StatementCollision> collisions;\r
312             int subject;\r
313             \r
314             public CollisionPredicateProcedure(ArrayList<StatementCollision> collisions) {\r
315             this.collisions = collisions;\r
316         }\r
317             \r
318         @Override\r
319             public boolean execute(int predicate, TIntArrayList objects) {\r
320                 if(objects.size() > 1) {\r
321                     objects.sort();\r
322                     int oldObject = objects.get(0); \r
323                     for(int i=1;i<objects.size();++i) {\r
324                         int curObject = objects.get(i);\r
325                         if(curObject == oldObject)\r
326                             collisions.add(new StatementCollision(subject, predicate, curObject));\r
327                         oldObject = curObject;\r
328                     }\r
329                 }\r
330                 return true;\r
331             }\r
332 \r
333         }\r
334 \r
335         public ArrayList<StatementCollision> getCollisions() {\r
336             ArrayList<StatementCollision> collisions = new ArrayList<StatementCollision>();\r
337             CollisionPredicateProcedure predicateProcedure = new CollisionPredicateProcedure(collisions);\r
338             CollisionSubjectProcedure subjectProcedure = new CollisionSubjectProcedure(predicateProcedure);\r
339             statements.forEachEntry(subjectProcedure);\r
340             return collisions;\r
341         }       \r
342 }\r