]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/PrincipalTypes.java
Generate parts of db client query code
[simantics/platform.git] / bundles / org.simantics.db.impl / src / org / simantics / db / impl / query / PrincipalTypes.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management
3  * in Industry THTH ry.
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * which accompanies this distribution, and is available at
7  * http://www.eclipse.org/legal/epl-v10.html
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.db.impl.query;
13
14 import java.util.ArrayList;
15 import java.util.Arrays;
16 import java.util.concurrent.Semaphore;
17
18 import org.simantics.db.common.utils.Logger;
19 import org.simantics.db.exception.DatabaseException;
20 import org.simantics.db.impl.graph.ReadGraphImpl;
21 import org.simantics.db.impl.procedure.IntProcedureAdapter;
22 import org.simantics.db.impl.procedure.InternalProcedure;
23 import org.simantics.db.procedure.ListenerBase;
24
25 import gnu.trove.procedure.TIntProcedure;
26 import gnu.trove.set.hash.TIntHashSet;
27
28 final public class PrincipalTypes extends CollectionUnaryQuery<IntProcedure> {
29
30         PrincipalTypes(final int resource) {
31                 super(resource);
32         }
33
34         @Override
35         final public void removeEntry(QueryProcessor provider) {
36                 provider.cache.remove(this);
37         }
38
39         static class Koss {
40
41                 private TIntHashSet set = null;
42                 public int single = 0;
43
44                 public boolean add(int val) {
45                         if(single == val) return false;
46                         if(single == 0) {
47                                 single = val;
48                                 return true;
49                         }
50                         if(set == null) set = new TIntHashSet(4);
51                         set.add(val);
52                         return true;
53                 }
54
55                 public int size() {
56
57                         if(single == 0) return 0;
58                         if(set == null) return 1;
59                         return set.size() + 1;
60
61                 }
62
63                 public int[] toArray() {
64
65                         int[] result = Arrays.copyOf(set.toArray(), set.size() + 1);
66                         result[set.size()] = single;
67                         return result;
68
69                 }
70
71                 public void forEach(TIntProcedure proc) {
72                         proc.execute(single);
73                         if(set != null) set.forEach(proc);
74                 }
75
76         }
77
78         @Override
79         public Object compute(final ReadGraphImpl graph, final IntProcedure proc) throws DatabaseException {
80                 return computeForEach(graph, id, this, proc);
81         }
82         
83         public static Object computeForEach(final ReadGraphImpl graph, final int id, final PrincipalTypes entry, final IntProcedure proc) throws DatabaseException {
84
85                 QueryProcessor provider = graph.processor;
86                 
87                 provider.querySupport.ensureLoaded(graph, id);
88                 assert(id != 0);
89
90                 int ret = provider.querySupport.getSingleInstance(id);
91                 if(ret > 0) {
92                         if(entry != null) {
93                                 entry.add(ret);
94                                 entry.finish(graph, provider);
95                         }
96                         proc.execute(graph, ret);
97                         proc.finished(graph);
98                         return ret;
99                 }
100
101                 final int instanceOf = provider.getInstanceOf();
102                 final int inherits = provider.getInherits();
103                 final int subrelationOf = provider.getSubrelationOf();
104
105                 final Koss indirect = new Koss();
106                 final Koss material = new Koss();
107
108                 IntProcedure directProc = new IntProcedure() {
109
110                         @Override
111                         public void execute(ReadGraphImpl graph, int i) {
112                                 material.add(i);
113                         }
114
115                         @Override
116                         public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
117                                 proc.exception(graph, t);
118                         }
119
120                         @Override
121                         public void finished(ReadGraphImpl graph) {
122                         }
123
124                 };
125
126                 IntProcedure indirectProc = new IntProcedure() {
127
128                         @Override
129                         public void execute(ReadGraphImpl graph, int i) {
130                                 indirect.add(i);
131                         }
132
133                         @Override
134                         public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
135                                 proc.exception(graph, t);
136                         }
137
138                         @Override
139                         public void finished(ReadGraphImpl graph) {
140                         }
141
142                 };
143
144                 provider.querySupport.getObjects(graph, id, instanceOf, directProc);
145                 provider.querySupport.getObjects(graph, id, inherits, indirectProc);
146                 provider.querySupport.getObjects(graph, id, subrelationOf, indirectProc);
147
148                 if(indirect.size() == 0) {
149                         int size = material.size(); 
150                         if(size == 0) {
151                                 if(entry != null) entry.finish(graph, provider);
152                                 proc.finished(graph);
153                                 return null;
154                         } else if(size == 1) {
155                                 int single = material.single; 
156                                 if(entry != null) {
157                                         entry.add(single);
158                                         entry.finish(graph, provider);
159                                 }
160                                 proc.execute(graph, single);
161                                 proc.finished(graph);
162                                 return single;
163                         } else {
164                                 addPrincipalType(graph, new TIntHashSet(4), material.toArray(), 0, provider, entry, proc);
165                                 return null;
166                         }
167                 }
168
169 //              final AtomicInteger finishes = new AtomicInteger(0);
170
171                 indirect.forEach(new TIntProcedure() {
172
173                         int finishes = 0;
174                         
175                         @Override
176                         public boolean execute(final int arg0) {
177                                 try {
178                                         return execute0(arg0);
179                                 } catch (DatabaseException e) {
180                                         Logger.defaultLogError(e);
181                                 }
182                                 return false;
183                         }
184                         
185                         public boolean execute0(final int arg0) throws DatabaseException {
186
187                                 // No self-loops!
188                                 if(arg0 == id) {
189                                         int current = (++finishes);
190                                         if(current == indirect.size()) {
191                                                 int size = material.size(); 
192                                                 if(size == 0) {
193                                                         if(entry != null) entry.finish(graph, provider);
194                                                         proc.finished(graph);
195                                                         return true;
196                                                 } else if(size == 1) {
197                                                         int single = material.single; 
198                                                         if(entry != null) {
199                                                                 entry.add(single);
200                                                                 entry.finish(graph, provider);
201                                                         }
202                                                         proc.execute(graph, single);
203                                                         proc.finished(graph);
204                                                         return true;
205                                                 } else {
206                                                         addPrincipalType(graph, new TIntHashSet(4), material.toArray(), 0, provider, entry, proc);
207                                                         return true;
208                                                 }
209                                         }
210                                         return true;
211                                 }
212
213                                 QueryCache.runnerPrincipalTypes(graph, arg0, entry, null, new IntProcedure() {
214
215                                         @Override
216                                         public void execute(ReadGraphImpl graph, int i) {
217                                                 synchronized(material) {
218                                                         material.add(i);
219                                                 }
220                                         }
221
222                                         @Override
223                                         public void finished(ReadGraphImpl graph) throws DatabaseException {
224
225                                                 int current = (++finishes);
226                                                 if(current == indirect.size()) {
227                                                         int size = material.size(); 
228                                                         if(size == 0) {
229                                                                 if(entry != null) entry.finish(graph, provider);
230                                                                 proc.finished(graph);
231                                                                 return;
232                                                         } else if(size == 1) {
233                                                                 int single = material.single; 
234                                                                 if(entry != null) {
235                                                                         entry.add(single);
236                                                                         entry.finish(graph, provider);
237                                                                 }
238                                                                 proc.execute(graph, single);
239                                                                 proc.finished(graph);
240                                                                 return;
241                                                         } else {
242                                                                 addPrincipalType(graph, new TIntHashSet(4), material.toArray(), 0, provider, entry, proc);
243                                                                 return;
244                                                         }
245                                                 }
246
247                                         }
248
249                                         @Override
250                                         public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
251                                                 proc.exception(graph, t);
252                                         }
253
254                                 });
255
256                                 return true;
257
258                         }
259
260                 });
261                 
262                 return null;
263
264         }
265
266         private static void finish(ReadGraphImpl graph, final TIntHashSet rejects, final int[] material, final PrincipalTypes entry, final QueryProcessor provider, final IntProcedure proc) throws DatabaseException {
267
268                 if(entry != null) {
269                         for(int i : material) {
270                                 if(!rejects.contains(i)) {
271                                         entry.add(i);
272                                 }
273                         }
274                         entry.finish(graph, provider);
275                 }
276
277                 for(int i : material) {
278                         if(!rejects.contains(i)) {
279                                 proc.execute(graph, i);
280                         }
281                 }
282
283                 proc.finished(graph);
284
285                 return;
286
287         }
288
289         private static void addPrincipalType(final ReadGraphImpl graph, final TIntHashSet rejects, final int[] material, int index, final QueryProcessor provider, final PrincipalTypes entry, final IntProcedure proc) throws DatabaseException {
290
291                 //        if((counter++ % 500) == 0) System.out.println("PT " + counter + " mat = " + material.length);
292
293                 if(index == material.length) { 
294                         finish(graph, rejects, material, entry, provider, proc);
295                         return;
296                 }
297
298                 int type = material[index++];
299                 while(rejects.contains(type)) {
300                         if(index == material.length) { 
301                                 finish(graph, rejects, material, entry, provider, proc);
302                                 return;
303                         }
304                         type = material[index++];
305                 }
306                 final int nextIndex = index;
307
308                 QueryCache.runnerSuperTypes(graph, type, entry, null, new InternalProcedure<IntSet>() {
309
310                         @Override
311                         public void execute(ReadGraphImpl graph, IntSet supers) throws DatabaseException {
312
313                                 synchronized(rejects) {
314
315                                         supers.forEach(new TIntProcedure() {
316
317                                                 @Override
318                                                 public boolean execute(int arg0) {
319                                                         rejects.add(arg0);
320                                                         return true;
321                                                 }
322
323                                         });
324
325                                 }
326
327                                 addPrincipalType(graph, rejects, material, nextIndex, provider, entry, proc);
328
329                         }
330
331                         @Override
332                         public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
333                                 proc.exception(graph, t);
334                         }
335
336                 });
337
338         }
339
340         @Override
341         public String toString() {
342                 return "PrincipalTypes[" + id + "]";
343         }
344
345         final private void add(int val) {
346                 assert(isPending());
347                 IntArray v = (IntArray)getResult();
348                 v.add(val);
349         }
350
351         final private void finish(ReadGraphImpl graph, QueryProcessor provider) {
352
353                 assert(isPending());
354                 synchronized(this) {
355                         setReady();
356                 }
357
358         }
359
360         @Override
361         public Object performFromCache(ReadGraphImpl graph, final IntProcedure procedure) throws DatabaseException {
362
363                 assert(isReady());
364
365         if(handleException(graph, procedure)) return EXCEPTED;
366                 
367                 final IntArray value = (IntArray)getResult();
368                 if(value.data == null) {
369                         if(value.sizeOrData != IntArray.NO_DATA) procedure.execute(graph, value.sizeOrData);
370                 } else {
371                         for(int i = 0;i < value.sizeOrData ; i++) procedure.execute(graph, value.data[i]);
372                 }
373
374                 procedure.finished(graph);
375                 
376                 return getResult();
377
378         }
379
380         @Override
381         public void recompute(ReadGraphImpl graph) throws DatabaseException {
382
383                 compute(graph, new IntProcedureAdapter() {
384
385                         @Override
386                         public void finished(ReadGraphImpl graph) {
387                         }
388
389                         @Override
390                         public void exception(ReadGraphImpl graph, Throwable t) {
391                                 new Error("Error in recompute.", t).printStackTrace();
392                         }
393
394                 });
395
396         }
397
398
399     @Override
400     boolean isImmutable(ReadGraphImpl graph) {
401         return graph.processor.isImmutable(id);
402     }
403     
404     @Override
405     protected void fillImpliedParents(QueryProcessor processor, ArrayList<CacheEntry<?>> result) {
406     }
407
408 }