A utility class for recursive search in cyclic graph
[simantics/platform.git] / bundles / org.simantics.db.common / src / org / simantics / db / common / recursive / FindParentsWithType.java
1 package org.simantics.db.common.recursive;
2
3 import java.util.ArrayList;
4 import java.util.Collection;
5 import java.util.Collections;
6 import java.util.List;
7 import java.util.Set;
8
9 import org.simantics.db.ReadGraph;
10 import org.simantics.db.Resource;
11 import org.simantics.db.Statement;
12 import org.simantics.db.exception.DatabaseException;
13 import org.simantics.layer0.Layer0;
14
15 public class FindParentsWithType extends FindRoots {
16     private final ReadGraph graph;
17     private final Resource rootType;
18     private final Layer0 L0;
19     
20     public FindParentsWithType(ReadGraph graph, Resource rootType) {
21         this.graph = graph;
22         this.rootType = rootType;
23         this.L0 = Layer0.getInstance(graph);
24     }
25
26     @Override
27     protected boolean isRoot(Resource resource) throws DatabaseException {
28         return graph.isInstanceOf(resource, rootType);
29     }
30
31     @Override
32     protected Collection<Resource> children(Resource resource) throws DatabaseException {
33         Resource parent = graph.getPossibleObject(resource, L0.PartOf);
34         if(parent != null)
35             return Collections.singletonList(parent);
36         
37         ArrayList<Resource> result = new ArrayList<Resource>(4); 
38         for(Statement s : graph.getStatements(resource, L0.IsWeaklyRelatedTo)) {
39             if(!s.getSubject().equals(resource))
40                 continue;
41             Resource inverse = graph.getPossibleInverse(s.getPredicate());
42             if(inverse != null && graph.isSubrelationOf(inverse, L0.IsRelatedTo))
43                 result.add(s.getObject());
44         }
45         return result;
46     }
47
48     /**
49      * Makes a query for just one resource. If you want to make multiple queries with the same type, 
50      * instantiate this class and call the {@code get} method.
51      */
52     public static List<Resource> findParentsWithType(ReadGraph graph, Resource r, Resource type) throws DatabaseException {
53         Set<Resource> set = new FindParentsWithType(graph, type).get(r);
54         if(set == null)
55             return Collections.emptyList();
56         else
57             return new ArrayList<Resource>(set);
58     }
59 }