]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.graph/src/org/simantics/graph/query/CompositeGraph.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.graph / src / org / simantics / graph / query / CompositeGraph.java
1 package org.simantics.graph.query;\r
2 \r
3 import gnu.trove.list.array.TIntArrayList;\r
4 import gnu.trove.map.hash.THashMap;\r
5 import gnu.trove.set.hash.THashSet;\r
6 import gnu.trove.set.hash.TIntHashSet;\r
7 \r
8 import java.util.ArrayList;\r
9 import java.util.Collection;\r
10 import java.util.Collections;\r
11 \r
12 import org.simantics.databoard.adapter.AdaptException;\r
13 import org.simantics.databoard.adapter.RuntimeAdaptException;\r
14 import org.simantics.databoard.binding.Binding;\r
15 import org.simantics.databoard.binding.mutable.Variant;\r
16 import org.simantics.databoard.type.Datatype;\r
17 import org.simantics.graph.store.GraphStore;\r
18 import org.simantics.graph.store.IdRes;\r
19 import org.simantics.graph.store.IdentityStore;\r
20 import org.simantics.graph.store.PathPattern;\r
21 import org.simantics.graph.store.StatementStore;\r
22 \r
23 public class CompositeGraph implements IGraph {\r
24 \r
25         ArrayList<GraphStore> fragments = new ArrayList<GraphStore>();\r
26         Paths paths;\r
27         \r
28         public CompositeGraph(Paths paths) {\r
29         this.paths = paths;\r
30     }\r
31 \r
32     public void addFragment(GraphStore fragment) {\r
33                 fragments.add(fragment);\r
34         }\r
35         \r
36         public void undoAddFragment() {\r
37                 fragments.remove(fragments.size()-1);\r
38         }\r
39         \r
40         public void addFragments(Collection<GraphStore> fragments) {\r
41                 fragments.addAll(fragments);\r
42         }\r
43         \r
44         protected void rawGetObjects(GraphStore fragment, int subject, Res predicate, Collection<Res> result) {\r
45                 int predicateId;\r
46                 if(predicate instanceof Path) {\r
47                         predicateId = fragment.identities.pathToId((Path)predicate);\r
48                         if(predicateId < 0)\r
49                                 return;\r
50                 } \r
51                 else {\r
52                         IdRes idPredicate = (IdRes)predicate;\r
53                         if(idPredicate.fragment != fragment)\r
54                                 return;\r
55                         predicateId = idPredicate.id;\r
56                 }\r
57                 \r
58                 TIntArrayList objects = fragment.statements.getObjects(subject, predicateId);\r
59                 fragment.addIdsToResult(objects, result);\r
60         }\r
61                         \r
62         private void rawGetObjects(Res subject, Res predicate, Collection<Res> result) {\r
63                 if(subject instanceof Path) {\r
64                         Path path = (Path)subject;\r
65                         for(GraphStore fragment : fragments) {\r
66                                 int id = fragment.identities.pathToId(path);\r
67                                 if(id >= 0)\r
68                                         rawGetObjects(fragment, id, predicate, result);\r
69                         }\r
70                 }\r
71                 else {\r
72                         IdRes idRes = (IdRes)subject;                                           \r
73                         rawGetObjects(idRes.fragment, idRes.id, predicate, result);\r
74                 }\r
75         }\r
76         \r
77         public boolean hasRawObjects(Res subject, Path predicate) {\r
78                 ArrayList<Res> result = new ArrayList<Res>();\r
79                 rawGetObjects(subject, predicate, result);\r
80                 return !result.isEmpty();\r
81         }\r
82         \r
83         @Override\r
84         public Collection<Res> rawGetObjects(Res subject, Res predicate) {\r
85                 ArrayList<Res> result = new ArrayList<Res>();\r
86                 rawGetObjects(subject, predicate, result);\r
87                 return result;\r
88         }\r
89         \r
90         @Override\r
91         public Res singleRawObject(Res subject, Res predicate) throws NoUniqueObjectException {\r
92                 ArrayList<Res> result = new ArrayList<Res>(1);\r
93                 rawGetObjects(subject, predicate, result);\r
94                 if(result.size() != 1)\r
95                         throw new NoUniqueObjectException("No unique objects (" + result.size()+ ") for " +\r
96                                         subject + " -> " + predicate);          \r
97                 return result.get(0);\r
98         }\r
99         \r
100         @Override\r
101         public Collection<Res> getTypes(Res subject) {\r
102                 THashSet<Res> result = new THashSet<Res>(); \r
103                 rawGetObjects(subject, paths.InstanceOf, result);\r
104                 for(Res type : result.toArray(new Res[result.size()]))\r
105                         collectSupertypes(type, result);\r
106                 return result;\r
107         }\r
108         \r
109         public Collection<Res> getSupertypes(Res subject) {\r
110                 THashSet<Res> result = new THashSet<Res>(); \r
111                 result.add(subject);            \r
112                 collectSupertypes(subject, result);\r
113                 return result;\r
114         }\r
115         \r
116         private void collectSupertypes(Res type, THashSet<Res> result) {\r
117                 for(Res supertype : rawGetObjects(type, paths.Inherits))\r
118                         if(result.add(supertype))\r
119                                 collectSupertypes(supertype, result);           \r
120         }\r
121 \r
122         @Override\r
123         public Collection<Res> getObjects(Res subject, Res predicate) {\r
124                 ArrayList<Res> result = new ArrayList<Res>();\r
125                 rawGetObjects(subject, predicate, result);\r
126                 for(Res type : getTypes(subject)) \r
127                         for(Res assertion : rawGetObjects(type, paths.Asserts)) {\r
128                                 Res pred = singleRawObject(assertion, paths.HasPredicate);\r
129                                 if(equals(pred, predicate))\r
130                                         result.add(singleRawObject(assertion, paths.HasObject));\r
131                         }\r
132                 return result;\r
133         }\r
134         \r
135         public Collection<Res> getAssertedObjects(Res subject, Path predicate) {\r
136                 ArrayList<Res> result = new ArrayList<Res>();\r
137                 for(Res type : getSupertypes(subject)) \r
138                         for(Res assertion : rawGetObjects(type, paths.Asserts)) {\r
139                                 Res pred = singleRawObject(assertion, paths.HasPredicate);\r
140                                 if(equals(pred, predicate))\r
141                                         result.add(singleRawObject(assertion, paths.HasObject));\r
142                         }\r
143                 return result;\r
144         }\r
145         \r
146         private static boolean equals(Res r1, Res r2) {\r
147                 return r1.equals(r2);\r
148         }\r
149         \r
150         interface ResourceProcedure {\r
151                 public void execute(GraphStore fragment, int id);\r
152         }\r
153         \r
154         interface ResourceFunction<T> {\r
155                 public T execute(GraphStore fragment, int id);\r
156         }\r
157         \r
158         public void forEachFragmentContaining(Res resource, ResourceProcedure proc) {\r
159                 if(resource instanceof Path) {\r
160                         Path path = (Path)resource;\r
161                         for(GraphStore fragment : fragments) {\r
162                                 int id = fragment.identities.pathToId(path);\r
163                                 if(id >= 0)\r
164                                         proc.execute(fragment, id);\r
165                         }\r
166                 }\r
167                 else {\r
168                         IdRes res = (IdRes)resource;\r
169                         proc.execute(res.fragment, res.id);\r
170                 }\r
171         }\r
172         \r
173         public <T> T apply(Res resource, ResourceFunction <T> func) {\r
174                 if(resource instanceof Path) {\r
175                         Path path = (Path)resource;\r
176                         for(GraphStore fragment : fragments) {\r
177                                 int id = fragment.identities.pathToId(path);\r
178                                 if(id >= 0) {\r
179                                         T value = func.execute(fragment, id);\r
180                                         if(value != null)\r
181                                                 return value;\r
182                                 }\r
183                         }\r
184                         return null;\r
185                 }\r
186                 else {\r
187                         IdRes res = (IdRes)resource;\r
188                         return func.execute(res.fragment, res.id);\r
189                 }\r
190         }\r
191         \r
192         private static ResourceFunction<Datatype> getDatatype = \r
193                 new ResourceFunction<Datatype>() {\r
194                         @Override\r
195                         public Datatype execute(GraphStore fragment, int id) {\r
196                                 return fragment.values.getDatatypeValue(id);\r
197                         }               \r
198         };\r
199         \r
200         private static ResourceFunction<Variant> getValue = \r
201                 new ResourceFunction<Variant>() {\r
202                         @Override\r
203                         public Variant execute(GraphStore fragment, int id) {\r
204                                 return fragment.values.getByteValue(id);\r
205                         }               \r
206         };\r
207                 \r
208         THashMap<Res, Datatype> datatypeCache = new THashMap<Res, Datatype>();\r
209         \r
210         @Override\r
211         public Datatype getDatatype(Res resource) {\r
212                 for(Res dt : getObjects(resource, paths.HasDatatype)) {\r
213                         Datatype type = datatypeCache.get(dt);\r
214                         if(type == null) {\r
215                                 type = apply(dt, getDatatype);\r
216                                 datatypeCache.put(dt, type);\r
217                         }\r
218                         return type;\r
219                 }\r
220                 return null;\r
221         }\r
222         \r
223         @Override\r
224         public Datatype getAssertedDatatype(Res resource) {\r
225                 for(Res dt : getAssertedObjects(resource, paths.HasDatatype)) {\r
226                         Datatype type = datatypeCache.get(dt);\r
227                         if(type == null) {\r
228                                 type = apply(dt, getDatatype);\r
229                                 datatypeCache.put(dt, type);\r
230                         }\r
231                         return type;\r
232                 }\r
233                 return null;\r
234         }\r
235         \r
236         @Override\r
237         public Variant getValue(Res resource) {\r
238                 return apply(resource, getValue);\r
239         }\r
240         \r
241         @Override\r
242         public Object getValue(Res resource, Binding binding) throws NoValueException {\r
243             Variant value = getValue(resource);\r
244                 if(value == null)\r
245                         throw new NoValueException();\r
246                 try {\r
247             return value.getValue(binding);\r
248         } catch (AdaptException e) {\r
249             throw new RuntimeAdaptException(e);\r
250         }\r
251         }\r
252         \r
253         @Override\r
254         public void setValue(Res resource, Object value, Binding binding) {\r
255             final Variant variant = new Variant(binding, value);\r
256             apply(resource, new ResourceFunction<Object>() {\r
257             @Override\r
258             public Object execute(GraphStore fragment, int id) {\r
259                 fragment.values.setValue(id, variant);\r
260                 return null;\r
261             }           \r
262             });\r
263         }\r
264         \r
265         /**\r
266          * Tells in how many fragments the resource occurs.\r
267          */\r
268         public int countOccurences(Res resource) {\r
269                 if(resource instanceof IdRes)\r
270                         return 1;\r
271                 else if(resource instanceof Path) {\r
272                         Path path = (Path)resource;\r
273                         int count = 0;\r
274                         for(GraphStore fragment : fragments)\r
275                                 if(fragment.identities.contains(path))\r
276                                         ++count;\r
277                         return count;\r
278                 }\r
279                 else\r
280                         return 0;\r
281         }\r
282         \r
283         private void collectSubtypes(THashSet<Res> types, Res type) {\r
284                 if(types.add(type)) \r
285                         for(Res subtype : rawGetObjects(type, paths.SupertypeOf))\r
286                                 collectSubtypes(types, subtype);\r
287         }\r
288         \r
289         @Override\r
290         public Collection<Res> getInstances(Res supertype) {\r
291                 THashSet<Res> types = new THashSet<Res>(); \r
292                 collectSubtypes(types, supertype);\r
293                 \r
294                 ArrayList<Res> result = new ArrayList<Res>();\r
295                 fragmentLoop:\r
296                 for(GraphStore fragment : fragments) {\r
297                         IdentityStore identities = fragment.identities;\r
298                         StatementStore statements = fragment.statements;\r
299                         \r
300                         TIntHashSet ids = new TIntHashSet(types.size());\r
301                         for(Res type : types) {\r
302                                 if(type instanceof Path) {\r
303                                         int id = identities.pathToId((Path)type);\r
304                                         if(id >= 0)\r
305                                                 ids.add(id);\r
306                                 }\r
307                                 else {\r
308                                         IdRes idRes = (IdRes)type;\r
309                                         if(idRes.fragment == fragment)\r
310                                                 ids.add(idRes.id);\r
311                                 }\r
312                         }\r
313                         if(ids.isEmpty())\r
314                                 continue;\r
315                         \r
316                         int instanceOfId = identities.pathToId(paths.InstanceOf);\r
317                         if(instanceOfId < 0)\r
318                                 continue;\r
319                         \r
320                         int resourceCount = identities.getResourceCount();\r
321                         nextResource:\r
322                         for(int i=0;i<resourceCount;++i)\r
323                                 for(int typeId : statements.getObjects(i, instanceOfId).toArray())\r
324                                         if(ids.contains(typeId)) {\r
325                                                 result.add(fragment.idToRes(i));\r
326                                                 continue nextResource;\r
327                                         }\r
328                 }\r
329                 \r
330                 return result;\r
331         }\r
332 \r
333         @Override\r
334         public Collection<Res> getChildren(Res res) {\r
335                 if(res instanceof Path) {\r
336                         THashSet<Res> result = new THashSet<Res>();\r
337                         for(GraphStore store : fragments) {\r
338                                 IdentityStore ids = store.identities;\r
339                                 int id = ids.pathToId((Path)res);\r
340                                 if(id >= 0) {\r
341                                         for(int child : ids.getChildren(id))\r
342                                                 result.add(store.idToRes(child));\r
343                                 }\r
344                         }\r
345                         return result;\r
346                 }\r
347                 else\r
348                         return Collections.<Res>emptyList();\r
349         }\r
350         \r
351         public Collection<Path> searchByPattern(String pattern) {\r
352                 THashSet<Path> result = new THashSet<Path>();\r
353                 PathPattern pathPattern = PathPattern.compile(pattern);\r
354                 for(GraphStore store : fragments)\r
355                         pathPattern.search(store.identities, result);\r
356                 return result;\r
357         }\r
358         \r
359         @Override\r
360         public Paths getPaths() {\r
361             return paths;\r
362         }\r
363 }\r