]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/PrincipalTypes.java
60fe074115e44aceb77d4b92a5a7b17a50724c4a
[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.impl.graph.ReadGraphImpl;
19 import org.simantics.db.impl.procedure.IntProcedureAdapter;
20 import org.simantics.db.impl.procedure.InternalProcedure;
21 import org.simantics.db.procedure.ListenerBase;
22
23 import gnu.trove.procedure.TIntProcedure;
24 import gnu.trove.set.hash.TIntHashSet;
25
26 final public class PrincipalTypes extends CollectionUnaryQuery<IntProcedure> {
27
28         private PrincipalTypes(final int resource) {
29                 super(resource);
30         }
31
32         final static PrincipalTypes entry(final QueryProcessor provider, final int r) {
33                 return (PrincipalTypes)provider.cache.principalTypesMap.get(r);
34         }
35
36         final static void runner(ReadGraphImpl graph, final int r, final CacheEntry parent, final ListenerBase listener, final IntProcedure procedure) {
37
38         QueryProcessor processor = graph.processor;
39                 
40                 PrincipalTypes entry = (PrincipalTypes)processor.cache.principalTypesMap.get(r); 
41                 if(entry == null) {
42
43                         entry = new PrincipalTypes(r);
44                 entry.setPending();
45                 entry.clearResult(processor.querySupport);
46                 entry.putEntry(processor);
47                         
48                 processor.performForEach(graph, entry, parent, listener, procedure);
49                         
50                 } else {
51                         
52             if(entry.isPending()) {
53                 synchronized(entry) {
54                     if(entry.isPending()) {
55                         throw new IllegalStateException();
56 //                                              if(entry.procs == null) entry.procs = new ArrayList<IntProcedure>(1);
57 //                                              entry.procs.add(procedure);
58 //                                              processor.registerDependencies(graph, entry, parent, listener, procedure, false);
59 //                                              return;
60                                         }
61                                 }
62                         }
63             processor.performForEach(graph, entry, parent, listener, procedure);
64                 }
65
66         }
67
68         final public static void queryEach(ReadGraphImpl graph, final int r, final QueryProcessor provider, final CacheEntry parent, final ListenerBase listener, final IntProcedure procedure) {
69
70                 assert(r != 0);
71
72         if(parent == null && listener == null) {
73                 PrincipalTypes.computeForEach(graph, r, null, graph.processor, procedure);
74         } else {
75                 runner(graph, r, parent, listener, procedure);
76         }
77
78         }
79
80         @Override
81         public UnaryQuery<IntProcedure> getEntry(QueryProcessor provider) {
82                 return provider.cache.principalTypesMap.get(id);
83         }
84
85         @Override
86         public void putEntry(QueryProcessor provider) {
87                 provider.cache.principalTypesMap.put(id, this);
88         }
89
90         @Override
91         final public void removeEntry(QueryProcessor provider) {
92                 provider.cache.principalTypesMap.remove(id);
93         }
94
95         static class Koss {
96
97                 private TIntHashSet set = null;
98                 public int single = 0;
99
100                 public boolean add(int val) {
101                         if(single == val) return false;
102                         if(single == 0) {
103                                 single = val;
104                                 return true;
105                         }
106                         if(set == null) set = new TIntHashSet(4);
107                         set.add(val);
108                         return true;
109                 }
110
111                 public int size() {
112
113                         if(single == 0) return 0;
114                         if(set == null) return 1;
115                         return set.size() + 1;
116
117                 }
118
119                 public int[] toArray() {
120
121                         int[] result = Arrays.copyOf(set.toArray(), set.size() + 1);
122                         result[set.size()] = single;
123                         return result;
124
125                 }
126
127                 public void forEach(TIntProcedure proc) {
128                         proc.execute(single);
129                         if(set != null) set.forEach(proc);
130                 }
131
132         }
133
134         @Override
135         public Object computeForEach(final ReadGraphImpl procedureGraph, final QueryProcessor provider, final IntProcedure proc, final boolean store) {
136
137                 return computeForEach(procedureGraph, id, this, provider, proc);
138                 
139         }
140         
141         public static Object computeForEach(final ReadGraphImpl graph, final int id, final PrincipalTypes entry, final QueryProcessor provider, final IntProcedure proc) {
142                 
143                 provider.querySupport.ensureLoaded(graph, id);
144                 assert(id != 0);
145
146                 int ret = provider.querySupport.getSingleInstance(id);
147                 if(ret > 0) {
148                         if(entry != null) {
149                                 entry.add(ret);
150                                 entry.finish(graph, provider);
151                         }
152                         proc.execute(graph, ret);
153                         proc.finished(graph);
154                         return ret;
155                 }
156
157                 final int instanceOf = provider.getInstanceOf();
158                 final int inherits = provider.getInherits();
159                 final int subrelationOf = provider.getSubrelationOf();
160
161                 final Koss indirect = new Koss();
162                 final Koss material = new Koss();
163
164                 IntProcedure directProc = new IntProcedure() {
165
166                         @Override
167                         public void execute(ReadGraphImpl graph, int i) {
168                                 material.add(i);
169                         }
170
171                         @Override
172                         public void exception(ReadGraphImpl graph, Throwable t) {
173                                 proc.exception(graph, t);
174                         }
175
176                         @Override
177                         public void finished(ReadGraphImpl graph) {
178                         }
179
180                 };
181
182                 IntProcedure indirectProc = new IntProcedure() {
183
184                         @Override
185                         public void execute(ReadGraphImpl graph, int i) {
186                                 indirect.add(i);
187                         }
188
189                         @Override
190                         public void exception(ReadGraphImpl graph, Throwable t) {
191                                 proc.exception(graph, t);
192                         }
193
194                         @Override
195                         public void finished(ReadGraphImpl graph) {
196                         }
197
198                 };
199
200                 provider.querySupport.getObjects(graph, id, instanceOf, directProc);
201                 provider.querySupport.getObjects(graph, id, inherits, indirectProc);
202                 provider.querySupport.getObjects(graph, id, subrelationOf, indirectProc);
203
204                 if(indirect.size() == 0) {
205                         int size = material.size(); 
206                         if(size == 0) {
207                                 if(entry != null) entry.finish(graph, provider);
208                                 proc.finished(graph);
209                                 return null;
210                         } else if(size == 1) {
211                                 int single = material.single; 
212                                 if(entry != null) {
213                                         entry.add(single);
214                                         entry.finish(graph, provider);
215                                 }
216                                 proc.execute(graph, single);
217                                 proc.finished(graph);
218                                 return single;
219                         } else {
220                                 addPrincipalType(graph, new TIntHashSet(4), material.toArray(), 0, provider, entry, proc);
221                                 return null;
222                         }
223                 }
224
225 //              final AtomicInteger finishes = new AtomicInteger(0);
226
227                 indirect.forEach(new TIntProcedure() {
228
229                         int finishes = 0;
230                         
231                         @Override
232                         public boolean execute(final int arg0) {
233
234                                 // No self-loops!
235                                 if(arg0 == id) {
236                                         int current = (++finishes);
237                                         if(current == indirect.size()) {
238                                                 int size = material.size(); 
239                                                 if(size == 0) {
240                                                         if(entry != null) entry.finish(graph, provider);
241                                                         proc.finished(graph);
242                                                         return true;
243                                                 } else if(size == 1) {
244                                                         int single = material.single; 
245                                                         if(entry != null) {
246                                                                 entry.add(single);
247                                                                 entry.finish(graph, provider);
248                                                         }
249                                                         proc.execute(graph, single);
250                                                         proc.finished(graph);
251                                                         return true;
252                                                 } else {
253                                                         addPrincipalType(graph, new TIntHashSet(4), material.toArray(), 0, provider, entry, proc);
254                                                         return true;
255                                                 }
256                                         }
257                                         return true;
258                                 }
259
260                                 PrincipalTypes.queryEach(graph, arg0, provider, entry, null, new IntProcedure() {
261
262                                         @Override
263                                         public void execute(ReadGraphImpl graph, int i) {
264                                                 synchronized(material) {
265                                                         material.add(i);
266                                                 }
267                                         }
268
269                                         @Override
270                                         public void finished(ReadGraphImpl graph) {
271
272                                                 int current = (++finishes);
273                                                 if(current == indirect.size()) {
274                                                         int size = material.size(); 
275                                                         if(size == 0) {
276                                                                 if(entry != null) entry.finish(graph, provider);
277                                                                 proc.finished(graph);
278                                                                 return;
279                                                         } else if(size == 1) {
280                                                                 int single = material.single; 
281                                                                 if(entry != null) {
282                                                                         entry.add(single);
283                                                                         entry.finish(graph, provider);
284                                                                 }
285                                                                 proc.execute(graph, single);
286                                                                 proc.finished(graph);
287                                                                 return;
288                                                         } else {
289                                                                 addPrincipalType(graph, new TIntHashSet(4), material.toArray(), 0, provider, entry, proc);
290                                                                 return;
291                                                         }
292                                                 }
293
294                                         }
295
296                                         @Override
297                                         public void exception(ReadGraphImpl graph, Throwable t) {
298                                                 proc.exception(graph, t);
299                                         }
300
301                                 });
302
303                                 return true;
304
305                         }
306
307                 });
308                 
309                 return null;
310
311         }
312
313         private static void finish(ReadGraphImpl graph, final TIntHashSet rejects, final int[] material, final PrincipalTypes entry, final QueryProcessor provider, final IntProcedure proc) {
314
315                 if(entry != null) {
316                         for(int i : material) {
317                                 if(!rejects.contains(i)) {
318                                         entry.add(i);
319                                 }
320                         }
321                         entry.finish(graph, provider);
322                 }
323
324                 for(int i : material) {
325                         if(!rejects.contains(i)) {
326                                 proc.execute(graph, i);
327                         }
328                 }
329
330                 proc.finished(graph);
331
332                 return;
333
334         }
335
336         private static void addPrincipalType(final ReadGraphImpl graph, final TIntHashSet rejects, final int[] material, int index, final QueryProcessor provider, final PrincipalTypes entry, final IntProcedure proc) {
337
338                 //        if((counter++ % 500) == 0) System.out.println("PT " + counter + " mat = " + material.length);
339
340                 if(index == material.length) { 
341                         finish(graph, rejects, material, entry, provider, proc);
342                         return;
343                 }
344
345                 int type = material[index++];
346                 while(rejects.contains(type)) {
347                         if(index == material.length) { 
348                                 finish(graph, rejects, material, entry, provider, proc);
349                                 return;
350                         }
351                         type = material[index++];
352                 }
353                 final int nextIndex = index;
354
355                 SuperTypes.queryEach(graph, type, provider, entry, null, new InternalProcedure<IntSet>() {
356
357                         @Override
358                         public void execute(ReadGraphImpl graph, IntSet supers) {
359
360                                 synchronized(rejects) {
361
362                                         supers.forEach(new TIntProcedure() {
363
364                                                 @Override
365                                                 public boolean execute(int arg0) {
366                                                         rejects.add(arg0);
367                                                         return true;
368                                                 }
369
370                                         });
371
372                                 }
373
374                                 addPrincipalType(graph, rejects, material, nextIndex, provider, entry, proc);
375
376                         }
377
378                         @Override
379                         public void exception(ReadGraphImpl graph, Throwable t) {
380                                 proc.exception(graph, t);
381                         }
382
383                 });
384
385         }
386
387         @Override
388         public String toString() {
389                 return "PrincipalTypes[" + id + "]";
390         }
391
392         final private void add(int val) {
393                 assert(isPending());
394                 IntArray v = (IntArray)getResult();
395                 v.add(val);
396         }
397
398         final private void finish(ReadGraphImpl graph, QueryProcessor provider) {
399
400                 assert(isPending());
401
402 //              ArrayList<IntProcedure> p = null;
403
404                 synchronized(this) {
405
406                         setReady();
407 //                      p = procs;
408 //                      procs = null;
409
410                 }
411
412 //              if(p != null) {
413 //
414 //                      IntArray v = (IntArray)getResult();
415 //                      if(v != null) {
416 //                              if(v.data == null) {
417 //                                      if(v.sizeOrData != IntArray.NO_DATA) {
418 //                                              for(IntProcedure proc : p) proc.execute(graph, v.sizeOrData);
419 //                                      }
420 //                              } else {
421 //                                      for(IntProcedure proc : p) {
422 //                                              for(int i = 0;i < v.sizeOrData ; i++) proc.execute(graph, v.data[i]);
423 //                                      }
424 //                              }
425 //                      }
426 //
427 //                      for(IntProcedure proc : p) proc.finished(graph);
428 //
429 //              }
430
431
432         }
433
434         @Override
435         public Object performFromCache(ReadGraphImpl graph, QueryProcessor provider, final IntProcedure procedure) {
436
437                 assert(isReady());
438
439         if(handleException(graph, procedure)) return EXCEPTED;
440                 
441                 final IntArray value = (IntArray)getResult();
442                 if(value.data == null) {
443                         if(value.sizeOrData != IntArray.NO_DATA) procedure.execute(graph, value.sizeOrData);
444                 } else {
445                         for(int i = 0;i < value.sizeOrData ; i++) procedure.execute(graph, value.data[i]);
446                 }
447
448                 procedure.finished(graph);
449                 
450                 return getResult();
451
452         }
453
454         @Override
455         public void recompute(ReadGraphImpl graph, QueryProcessor provider) {
456
457                 final Semaphore s = new Semaphore(0);
458
459                 computeForEach(graph, provider, new IntProcedureAdapter() {
460
461                         @Override
462                         public void finished(ReadGraphImpl graph) {
463                                 s.release();
464                         }
465
466                         @Override
467                         public void exception(ReadGraphImpl graph, Throwable t) {
468                                 s.release();
469                                 new Error("Error in recompute.", t).printStackTrace();
470                         }
471
472                 }, true);
473
474         while(!s.tryAcquire()) {
475                 provider.resume(graph);
476         }
477
478         }
479
480
481     @Override
482     boolean isImmutable(ReadGraphImpl graph) {
483         return graph.processor.isImmutable(id);
484     }
485     
486     @Override
487     protected void fillImpliedParents(QueryProcessor processor, ArrayList<CacheEntry> result) {
488 //              for(Objects o : Objects.entries(processor, id)) result.add(o);
489     }
490
491 }