]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.graph/src/org/simantics/graph/representation/TransferableGraphQueries.java
Fixed multiple issues causing dangling references to discarded queries
[simantics/platform.git] / bundles / org.simantics.graph / src / org / simantics / graph / representation / TransferableGraphQueries.java
1 package org.simantics.graph.representation;
2
3 import java.util.Comparator;
4 import java.util.Set;
5 import java.util.TreeMap;
6 import java.util.TreeSet;
7
8 import org.simantics.databoard.util.URIStringUtils;
9
10 import gnu.trove.impl.Constants;
11 import gnu.trove.list.array.TIntArrayList;
12 import gnu.trove.map.hash.TIntObjectHashMap;
13 import gnu.trove.map.hash.TObjectIntHashMap;
14 import gnu.trove.procedure.TObjectProcedure;
15
16 public class TransferableGraphQueries {
17
18     private static final int NOT_FOUND = TransferableGraphUtils.NOT_FOUND;
19
20     private final TransferableGraph1 tg;
21
22     private final TIntObjectHashMap<Identity> internalIdentities = new TIntObjectHashMap<>(Constants.DEFAULT_CAPACITY, Constants.DEFAULT_LOAD_FACTOR, NOT_FOUND);
23     private final TIntObjectHashMap<Identity> externalIdentities = new TIntObjectHashMap<>(Constants.DEFAULT_CAPACITY, Constants.DEFAULT_LOAD_FACTOR, NOT_FOUND);
24     private final TIntObjectHashMap<Identity> rootIdentities = new TIntObjectHashMap<>(Constants.DEFAULT_CAPACITY, Constants.DEFAULT_LOAD_FACTOR, NOT_FOUND);
25
26     private final TObjectIntHashMap<String> internalIdentitiesByURI = new TObjectIntHashMap<>();
27     private final TObjectIntHashMap<String> externalIdentitiesByURI = new TObjectIntHashMap<>();
28     private final TObjectIntHashMap<String> rootIdentitiesByURI = new TObjectIntHashMap<>();
29
30     private final TIntObjectHashMap<TIntArrayList> statementsCache = new TIntObjectHashMap<>(Constants.DEFAULT_CAPACITY, Constants.DEFAULT_LOAD_FACTOR, NOT_FOUND);
31     
32     public TransferableGraphQueries(TransferableGraph1 graph) {
33         this.tg = graph;
34         
35         // Calculate internals
36         initializeIdentities();
37     }
38
39     private void initializeIdentities() {
40         for (Identity identity : tg.identities) {
41             IdentityDefinition definition = identity.definition;
42             if (definition instanceof Internal) {
43                 Internal internal = (Internal) definition;
44                 internalIdentities.put(identity.resource, identity);
45                 internalIdentitiesByURI.put(getURI(identity), identity.resource);
46             } else if (definition instanceof External) {
47                 External external = (External) definition;
48                 externalIdentities.put(identity.resource, identity);
49                 externalIdentitiesByURI.put(getURI(identity), identity.resource);
50             } else if (definition instanceof Root) {
51                 Root root = (Root) definition;
52                 rootIdentities.put(identity.resource, identity);
53                 rootIdentitiesByURI.put(getURI(identity), identity.resource);
54             }
55         }
56     }
57
58     public String getURI(Identity identity) {
59         IdentityDefinition definition = identity.definition;
60         if(definition instanceof External) {
61             External def = (External)definition;
62             if(def.parent == -1) return "http:/";
63             else return getURI(def.parent) + "/" + URIStringUtils.escape(def.name);
64         } else if(definition instanceof Root) {
65             Root def = (Root)definition;
66             if(def.name.isEmpty()) return "http:/";
67             return def.name;
68         } else if (definition instanceof Internal) {
69             Internal def = (Internal)definition;
70             return getURI(def.parent) + "/" + URIStringUtils.escape(def.name);
71         } else {
72             return "";
73         }
74     }
75
76     public String getURI(int id) {
77         Identity identity = getIdentity(id);
78         if (identity == null)
79             return "<internal reference " + id + ">:";
80         return getURI(identity);
81     }
82
83     private static final Comparator<Identity> IDENTITY_NAME_COMPARATOR = new Comparator<Identity>() {
84         
85         @Override
86         public int compare(Identity o1, Identity o2) {
87             if (o1.definition instanceof Internal && o2.definition instanceof Internal) {
88                 Internal i1 = (Internal) o1.definition; 
89                 Internal i2 = (Internal) o2.definition;
90                 return i1.name.compareTo(i2.name);
91             } else if (o1.definition instanceof External && o2.definition instanceof External) {
92                 External e1 = (External) o1.definition;
93                 External e2 = (External) o2.definition;
94                 return e1.name.compareTo(e2.name);
95             } else {
96                 throw new IllegalArgumentException(o1 + " " + o2);
97             }
98         }
99     };
100
101     public Set<Identity> getChildren(Identity parent) {
102         TreeSet<Identity> children = new TreeSet<>(IDENTITY_NAME_COMPARATOR);
103         internalIdentities.forEachEntry((resource, identity) -> {
104             Internal internal = (Internal) identity.definition;
105             if (internal.parent == parent.resource)
106                 children.add(identity);
107             return true;
108         });
109         
110         return children;
111     }
112     
113     public Identity findInternalByName(String name) {
114         int internal = internalIdentitiesByURI.get(name);
115         if (internal == NOT_FOUND)
116             return null;
117         return internalIdentities.get(internal);
118     }
119
120     private Identity findExternalByName(String name) {
121         int external = externalIdentitiesByURI.get(name);
122         if (external == NOT_FOUND)
123             return null;
124         return externalIdentities.get(external);
125     }
126
127     private Identity findExternalByNameAndParent(String name, int parent) {
128         Identity external = findExternalByName(name);
129         if (external.resource == parent)
130             return external;
131         return null;
132     }
133
134     public Identity findExternalByURI(String uri) {
135         int v = externalIdentitiesByURI.get(uri);
136         if (v == NOT_FOUND)
137             return null;
138         return externalIdentities.get(v);
139     }
140
141     public Identity findRootByName(String name) {
142         int root = rootIdentitiesByURI.get(name);
143         if (root == NOT_FOUND)
144             return null;
145         return rootIdentities.get(root);
146     }
147     
148     public String getName(Identity identity) {
149         return TransferableGraphUtils.getName(identity);
150     }
151
152     public void forIdentities(TObjectProcedure<Identity> procedure) {
153         for (Identity identity : tg.identities) {
154             if (!procedure.execute(identity)) {
155                 break;
156             }
157         }
158     }
159
160     public Identity getIdentity(int resource) {
161         Identity result = rootIdentities.get(resource);
162         if (result == null)
163             result = externalIdentities.get(resource);
164         if (result == null)
165             result = internalIdentities.get(resource);
166         return result;
167     }
168
169     public Value findValue(int object) {
170         return TransferableGraphUtils.findValue(tg, object);
171     }
172
173     public TreeMap<String, TreeSet<Integer>> sortByPredicateUniqueStatements(int resource) {
174         TreeMap<String, TreeSet<Integer>> results = new TreeMap<>();
175         TIntArrayList statements = getStatements(resource);
176         for (int i = 0; i < statements.size(); i += 2) {
177             int predicate = statements.get(i);
178             String predicateURI = getURI(predicate);
179             TreeSet<Integer> objects = results.get(predicateURI);
180             if (objects == null) {
181                 objects = new TreeSet<>();
182             }
183             objects.add(statements.get(i + 1));
184             results.put(predicateURI, objects);
185         }
186         return results;
187     }
188
189     public TIntArrayList getStatements(int resource) {
190 //        System.out.println("getting statements with " + resource);
191         TIntArrayList statements = statementsCache.get(resource);
192         if (statements == null) {
193             statements = TransferableGraphUtils.getStatements(tg, resource);
194             statementsCache.put(resource, statements);
195         }
196         return statements;
197     }
198
199     public int getPossibleObject(int subject, Identity predicate) {
200         return TransferableGraphUtils.getPossibleObject2(tg, subject, predicate);
201     }
202
203     public TransferableGraph1 getGraph() {
204         return tg;
205     }
206     
207 }