1 package org.simantics.graph.query;
\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
8 import java.util.ArrayList;
\r
9 import java.util.Collection;
\r
10 import java.util.Collections;
\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
23 public class CompositeGraph implements IGraph {
\r
25 ArrayList<GraphStore> fragments = new ArrayList<GraphStore>();
\r
28 public CompositeGraph(Paths paths) {
\r
32 public void addFragment(GraphStore fragment) {
\r
33 fragments.add(fragment);
\r
36 public void undoAddFragment() {
\r
37 fragments.remove(fragments.size()-1);
\r
40 public void addFragments(Collection<GraphStore> fragments) {
\r
41 fragments.addAll(fragments);
\r
44 protected void rawGetObjects(GraphStore fragment, int subject, Res predicate, Collection<Res> result) {
\r
46 if(predicate instanceof Path) {
\r
47 predicateId = fragment.identities.pathToId((Path)predicate);
\r
52 IdRes idPredicate = (IdRes)predicate;
\r
53 if(idPredicate.fragment != fragment)
\r
55 predicateId = idPredicate.id;
\r
58 TIntArrayList objects = fragment.statements.getObjects(subject, predicateId);
\r
59 fragment.addIdsToResult(objects, result);
\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
68 rawGetObjects(fragment, id, predicate, result);
\r
72 IdRes idRes = (IdRes)subject;
\r
73 rawGetObjects(idRes.fragment, idRes.id, predicate, result);
\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
84 public Collection<Res> rawGetObjects(Res subject, Res predicate) {
\r
85 ArrayList<Res> result = new ArrayList<Res>();
\r
86 rawGetObjects(subject, predicate, result);
\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
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
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
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
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
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
146 private static boolean equals(Res r1, Res r2) {
\r
147 return r1.equals(r2);
\r
150 interface ResourceProcedure {
\r
151 public void execute(GraphStore fragment, int id);
\r
154 interface ResourceFunction<T> {
\r
155 public T execute(GraphStore fragment, int id);
\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
164 proc.execute(fragment, id);
\r
168 IdRes res = (IdRes)resource;
\r
169 proc.execute(res.fragment, res.id);
\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
179 T value = func.execute(fragment, id);
\r
187 IdRes res = (IdRes)resource;
\r
188 return func.execute(res.fragment, res.id);
\r
192 private static ResourceFunction<Datatype> getDatatype =
\r
193 new ResourceFunction<Datatype>() {
\r
195 public Datatype execute(GraphStore fragment, int id) {
\r
196 return fragment.values.getDatatypeValue(id);
\r
200 private static ResourceFunction<Variant> getValue =
\r
201 new ResourceFunction<Variant>() {
\r
203 public Variant execute(GraphStore fragment, int id) {
\r
204 return fragment.values.getByteValue(id);
\r
208 THashMap<Res, Datatype> datatypeCache = new THashMap<Res, Datatype>();
\r
211 public Datatype getDatatype(Res resource) {
\r
212 for(Res dt : getObjects(resource, paths.HasDatatype)) {
\r
213 Datatype type = datatypeCache.get(dt);
\r
215 type = apply(dt, getDatatype);
\r
216 datatypeCache.put(dt, type);
\r
224 public Datatype getAssertedDatatype(Res resource) {
\r
225 for(Res dt : getAssertedObjects(resource, paths.HasDatatype)) {
\r
226 Datatype type = datatypeCache.get(dt);
\r
228 type = apply(dt, getDatatype);
\r
229 datatypeCache.put(dt, type);
\r
237 public Variant getValue(Res resource) {
\r
238 return apply(resource, getValue);
\r
242 public Object getValue(Res resource, Binding binding) throws NoValueException {
\r
243 Variant value = getValue(resource);
\r
245 throw new NoValueException();
\r
247 return value.getValue(binding);
\r
248 } catch (AdaptException e) {
\r
249 throw new RuntimeAdaptException(e);
\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
258 public Object execute(GraphStore fragment, int id) {
\r
259 fragment.values.setValue(id, variant);
\r
266 * Tells in how many fragments the resource occurs.
\r
268 public int countOccurences(Res resource) {
\r
269 if(resource instanceof IdRes)
\r
271 else if(resource instanceof Path) {
\r
272 Path path = (Path)resource;
\r
274 for(GraphStore fragment : fragments)
\r
275 if(fragment.identities.contains(path))
\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
290 public Collection<Res> getInstances(Res supertype) {
\r
291 THashSet<Res> types = new THashSet<Res>();
\r
292 collectSubtypes(types, supertype);
\r
294 ArrayList<Res> result = new ArrayList<Res>();
\r
296 for(GraphStore fragment : fragments) {
\r
297 IdentityStore identities = fragment.identities;
\r
298 StatementStore statements = fragment.statements;
\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
308 IdRes idRes = (IdRes)type;
\r
309 if(idRes.fragment == fragment)
\r
316 int instanceOfId = identities.pathToId(paths.InstanceOf);
\r
317 if(instanceOfId < 0)
\r
320 int resourceCount = identities.getResourceCount();
\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
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
341 for(int child : ids.getChildren(id))
\r
342 result.add(store.idToRes(child));
\r
348 return Collections.<Res>emptyList();
\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
360 public Paths getPaths() {
\r