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