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