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