]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/DirectQuerySupportImpl.java
Use java.util.Consumer instead of os.utils.datastructures.Callback
[simantics/platform.git] / bundles / org.simantics.db.procore / src / fi / vtt / simantics / procore / internal / DirectQuerySupportImpl.java
1 package fi.vtt.simantics.procore.internal;
2
3 import org.simantics.db.AsyncReadGraph;
4 import org.simantics.db.DirectStatements;
5 import org.simantics.db.ReadGraph;
6 import org.simantics.db.RelationInfo;
7 import org.simantics.db.Resource;
8 import org.simantics.db.common.procedure.wrapper.NoneToAsyncProcedure;
9 import org.simantics.db.common.procedure.wrapper.SyncToAsyncProcedure;
10 import org.simantics.db.exception.DatabaseException;
11 import org.simantics.db.impl.ClusterI;
12 import org.simantics.db.impl.ClusterI.ClusterTypeEnum;
13 import org.simantics.db.impl.ForEachObjectContextProcedure;
14 import org.simantics.db.impl.ForEachObjectProcedure;
15 import org.simantics.db.impl.ForPossibleRelatedValueContextProcedure;
16 import org.simantics.db.impl.ForPossibleRelatedValueProcedure;
17 import org.simantics.db.impl.ResourceImpl;
18 import org.simantics.db.impl.TransientGraph;
19 import org.simantics.db.impl.graph.ReadGraphImpl;
20 import org.simantics.db.procedure.AsyncContextMultiProcedure;
21 import org.simantics.db.procedure.AsyncContextProcedure;
22 import org.simantics.db.procedure.AsyncMultiProcedure;
23 import org.simantics.db.procedure.AsyncProcedure;
24 import org.simantics.db.procedure.Procedure;
25 import org.simantics.db.procedure.SyncProcedure;
26 import org.simantics.db.procore.cluster.ClusterBig;
27 import org.simantics.db.procore.cluster.ClusterImpl;
28 import org.simantics.db.procore.cluster.ClusterSmall;
29 import org.simantics.db.procore.cluster.ResourceTableSmall;
30 import org.simantics.db.procore.cluster.ValueTableSmall;
31 import org.simantics.db.request.AsyncRead;
32 import org.simantics.db.service.DirectQuerySupport;
33
34 public class DirectQuerySupportImpl implements DirectQuerySupport {
35
36         final private SessionImplSocket session;
37         
38         DirectQuerySupportImpl(SessionImplSocket session) {
39                 this.session = session;
40         }
41
42         @Override
43         final public void forEachDirectPersistentStatement(AsyncReadGraph graph, final Resource subject, final AsyncProcedure<DirectStatements> procedure) {
44                 ReadGraphImpl impl = (ReadGraphImpl)graph;
45                 impl.processor.forEachDirectStatement(impl, subject, procedure, true);
46         }
47
48         @Override
49         final public void forEachDirectStatement(AsyncReadGraph graph, final Resource subject, final AsyncProcedure<DirectStatements> procedure) {
50                 ReadGraphImpl impl = (ReadGraphImpl)graph;
51                 impl.processor.forEachDirectStatement(impl, subject, procedure, false);
52         }
53
54         @Override
55         public void forEachDirectStatement(AsyncReadGraph graph, Resource subject, SyncProcedure<DirectStatements> procedure) {
56                 forEachDirectStatement(graph, subject, new SyncToAsyncProcedure<DirectStatements>(procedure));
57         }
58
59         @Override
60         public void forEachDirectStatement(AsyncReadGraph graph, Resource subject, Procedure<DirectStatements> procedure) {
61                 ReadGraphImpl impl = (ReadGraphImpl)graph;
62                 impl.processor.forEachDirectStatement(impl, subject, procedure);
63         }
64
65         @Override
66         public void forRelationInfo(AsyncReadGraph graph, Resource subject, AsyncProcedure<RelationInfo> procedure) {
67                 ReadGraphImpl impl = (ReadGraphImpl)graph;
68                 impl.processor.forRelationInfo(impl, subject, procedure);
69         }
70
71         @Override
72         public void forRelationInfo(AsyncReadGraph graph, Resource subject, SyncProcedure<RelationInfo> procedure) {
73                 forRelationInfo(graph, subject, new SyncToAsyncProcedure<RelationInfo>(procedure));
74         }
75
76         @Override
77         public void forRelationInfo(AsyncReadGraph graph, Resource subject, Procedure<RelationInfo> procedure) {
78                 forRelationInfo(graph, subject, new NoneToAsyncProcedure<RelationInfo>(procedure));
79         }
80
81         @Override
82         public AsyncMultiProcedure<Resource> compileForEachObject(ReadGraph graph, final Resource relation, AsyncMultiProcedure<Resource> user) {
83                 
84                 try {
85                         RelationInfo info = graph.syncRequest(new AsyncRead<RelationInfo>() {
86
87                                 @Override
88                                 public void perform(AsyncReadGraph graph, AsyncProcedure<RelationInfo> procedure) {
89                                         forRelationInfo(graph, relation, procedure);
90                                 }
91
92                 @Override
93                     public int threadHash() {
94                         return hashCode();
95                     }
96
97                                 @Override
98                                 public int getFlags() {
99                                         return 0;
100                                 }
101
102                         });
103                 final int predicateKey = ((ResourceImpl)relation).id;
104                         return new ForEachObjectProcedure(predicateKey, info, session.queryProvider2, user);
105                 } catch (DatabaseException e) {
106                         return null;
107                 }               
108         
109         }
110
111         @Override
112         public <C> AsyncContextMultiProcedure<C, Resource> compileForEachObject(ReadGraph graph, final Resource relation, AsyncContextMultiProcedure<C, Resource> user) {
113                 
114                 try {
115                         RelationInfo info = graph.syncRequest(new AsyncRead<RelationInfo>() {
116
117                                 @Override
118                                 public void perform(AsyncReadGraph graph, AsyncProcedure<RelationInfo> procedure) {
119                                         forRelationInfo(graph, relation, procedure);
120                                 }
121
122                 @Override
123                     public int threadHash() {
124                         return hashCode();
125                     }
126
127                                 @Override
128                                 public int getFlags() {
129                                         return 0;
130                                 }
131
132                         });
133                 final int predicateKey = ((ResourceImpl)relation).id;
134                         return new ForEachObjectContextProcedure<C>(predicateKey, info, session.queryProvider2, user);
135                 } catch (DatabaseException e) {
136                         return null;
137                 }               
138         
139         }
140         
141         @Override
142         public <T> AsyncProcedure<T> compilePossibleRelatedValue(ReadGraph graph, final Resource relation, AsyncProcedure<T> user) {
143                 
144                 try {
145                         RelationInfo info = graph.syncRequest(new AsyncRead<RelationInfo>() {
146
147                                 @Override
148                                 public void perform(AsyncReadGraph graph, AsyncProcedure<RelationInfo> procedure) {
149                                         forRelationInfo(graph, relation, procedure);
150                                 }
151
152                 @Override
153                     public int threadHash() {
154                         return hashCode();
155                     }
156
157                                 @Override
158                                 public int getFlags() {
159                                         return 0;
160                                 }
161
162                         });
163                 final int predicateKey = ((ResourceImpl)relation).id;
164                         return new ForPossibleRelatedValueProcedure<T>(predicateKey, info, user);
165                 } catch (DatabaseException e) {
166                         return null;
167                 }               
168         
169         }
170
171         @Override
172         public <C, T> AsyncContextProcedure<C, T> compilePossibleRelatedValue(ReadGraph graph, final Resource relation, AsyncContextProcedure<C, T> user) {
173                 
174                 try {
175                         RelationInfo info = graph.syncRequest(new AsyncRead<RelationInfo>() {
176
177                                 @Override
178                                 public void perform(AsyncReadGraph graph, AsyncProcedure<RelationInfo> procedure) {
179                                         forRelationInfo(graph, relation, procedure);
180                                 }
181
182                 @Override
183                     public int threadHash() {
184                         return hashCode();
185                     }
186
187                                 @Override
188                                 public int getFlags() {
189                                         return 0;
190                                 }
191
192                         });
193                 final int predicateKey = ((ResourceImpl)relation).id;
194                         return new ForPossibleRelatedValueContextProcedure<C, T>(predicateKey, info, user);
195                 } catch (DatabaseException e) {
196                         return null;
197                 }               
198         
199         }
200         
201         @Override
202         public void forEachObjectCompiled(AsyncReadGraph graph, Resource subject, final AsyncMultiProcedure<Resource> procedure) {
203                 
204         assert(subject != null);
205         
206         final ForEachObjectProcedure proc = (ForEachObjectProcedure)procedure;
207 //        final RelationInfo info = proc.info;
208
209         final ReadGraphImpl impl = (ReadGraphImpl)graph;
210         final int subjectId = ((ResourceImpl)subject).id;
211
212 //        int callerThread = impl.callerThread;
213 //        int suggestSchedule = (subjectId>>16) & queryProvider2.THREAD_MASK;
214         
215 //        impl.inc();
216         
217 //        if(callerThread == suggestSchedule) {
218                 
219 //              if(info.isFunctional) {
220 //                      querySupport.getObjects4(impl, subjectId, proc);
221 //              } else {
222                 session.querySupport.getObjects4(impl, subjectId, proc);
223 //              }
224                 
225 //        } else {
226 //              
227 //              impl.state.barrier.inc();
228 //            impl.state.barrier.dec(callerThread);
229 //              
230 //              queryProvider2.schedule(callerThread, new SessionTask(suggestSchedule) {
231 //      
232 //                      @Override
233 //                      public void run(int thread) {
234 //                              
235 //                      impl.state.barrier.inc(thread);
236 //                              impl.state.barrier.dec();
237 //
238 //                      if(info.isFunctional) {
239 //                              querySupport.getObjects4(impl.newAsync(thread), subjectId, proc);
240 //                      } else {
241 //                              querySupport.getObjects4(impl.newAsync(thread), subjectId, proc);
242 //                      }
243 //                              
244 //                      }
245 //                      
246 //                      @Override
247 //                      public String toString() {
248 //                              return "gaff8";
249 //                      }
250 //      
251 //              });
252 //              
253 //        }
254                 
255         }
256
257         @Override
258         public <C> void forEachObjectCompiled(AsyncReadGraph graph, Resource subject, C context, final AsyncContextMultiProcedure<C, Resource> procedure) {
259                 
260                 assert(subject != null);
261
262                 final ForEachObjectContextProcedure<C> proc = (ForEachObjectContextProcedure<C>)procedure;
263                 final RelationInfo info = proc.info;
264
265                 final ReadGraphImpl impl = (ReadGraphImpl)graph;
266                 final int subjectId = ((ResourceImpl)subject).id;
267
268 //              int callerThread = impl.callerThread;
269 //              int suggestSchedule = (subjectId>>16) & queryProvider2.THREAD_MASK;
270
271 //              impl.inc();
272
273                 if(info.isFunctional) {
274                         session.querySupport.getObjects4(impl, subjectId, context, proc);
275                 } else {
276                         session.querySupport.getObjects4(impl, subjectId, context, proc);
277                 }
278                 
279         }
280         
281         @Override
282         public <T> void forPossibleRelatedValueCompiled(AsyncReadGraph graph, Resource subject, final AsyncProcedure<T> procedure) {
283                 
284                 assert(subject != null);
285
286         final ForPossibleRelatedValueProcedure<T> proc = (ForPossibleRelatedValueProcedure<T>)procedure;
287         final RelationInfo info = proc.info;
288         
289         final ReadGraphImpl impl = (ReadGraphImpl)graph;
290         final int subjectId = ((ResourceImpl)subject).id;
291         
292 //        int callerThread = impl.callerThread;
293 //        int suggestSchedule = (subjectId>>16) & session.queryProvider2.THREAD_MASK;
294         
295 //        impl.inc();
296         
297 //        if(callerThread == suggestSchedule) {
298                 
299                 if(info.isFunctional) {
300                         getRelatedValue4(impl, subjectId, proc);
301                 } else {
302                         getRelatedValue4(impl, subjectId, proc);
303                 }
304                 
305 //        } else {
306 //              
307 //              impl.state.barrier.inc();
308 //            impl.state.barrier.dec(callerThread);
309 //              
310 //              queryProvider2.schedule(callerThread, new SessionTask(suggestSchedule) {
311 //      
312 //                      @Override
313 //                      public void run(int thread) {
314 //
315 //                      impl.state.barrier.inc(thread);
316 //                      impl.state.barrier.dec();
317 //                              
318 //                      if(info.isFunctional) {
319 //                              getRelatedValue4(impl.newAsync(thread), subjectId, proc);
320 //                      } else {
321 //                              getRelatedValue4(impl.newAsync(thread), subjectId, proc);
322 //                      }
323 //                              
324 //                      }
325 //                      
326 //                      @Override
327 //                      public String toString() {
328 //                              return "gaff11";
329 //                      }
330 //      
331 //              });
332 //              
333 //        }
334                 
335         }
336
337         @Override
338         public <C, T> void forPossibleRelatedValueCompiled(AsyncReadGraph graph, Resource subject, C context, final AsyncContextProcedure<C, T> procedure) {
339                 
340                 assert(subject != null);
341
342         final ForPossibleRelatedValueContextProcedure<C, T> proc = (ForPossibleRelatedValueContextProcedure<C, T>)procedure;
343         final RelationInfo info = proc.info;
344         
345         final ReadGraphImpl impl = (ReadGraphImpl)graph;
346         final int subjectId = ((ResourceImpl)subject).id;
347         
348 //        int callerThread = impl.callerThread;
349 //        int suggestSchedule = (subjectId>>16) & session.queryProvider2.THREAD_MASK;
350         
351 //        impl.inc();
352                 
353         if(info.isFunctional) {
354                 getRelatedValue4(impl, subjectId, context, proc);
355         } else {
356                 getRelatedValue4(impl, subjectId, context, proc);
357         }
358                 
359         }
360         
361         @Override
362         public <T> void forPossibleType(final AsyncReadGraph graph, Resource subject, final AsyncProcedure<Resource> procedure) {
363                 
364         assert(subject != null);
365
366         final ReadGraphImpl impl = (ReadGraphImpl)graph;
367         final int subjectId = ((ResourceImpl)subject).id;
368
369         try {
370                 
371                 final ClusterI cluster = session.clusterTable.getClusterByResourceKey(subjectId);
372                 if(!cluster.isLoaded()) {
373
374 //                      impl.state.inc(0);
375                         
376                         session.queryProvider2.requestCluster(impl, cluster.getClusterId(), new Runnable() {
377                 
378                                         @Override
379                                         public void run() {
380
381                                         try {
382
383                                                         int result = cluster.getCompleteObjectKey(subjectId, session.clusterTranslator);
384                                                 procedure.execute(graph, new ResourceImpl(session.resourceSupport, result));
385
386 //                                              impl.state.dec(0);                                              
387                                                 
388                                         } catch (DatabaseException e) {
389                                                 e.printStackTrace();
390                                         }
391                 
392                                         }
393                 
394                                 });
395                                 
396                 } else {
397
398                         int result = cluster.getCompleteObjectKey(subjectId, session.clusterTranslator);
399                         procedure.execute(graph, new ResourceImpl(session.resourceSupport, result));
400                         
401                 }
402                 
403         } catch (DatabaseException e) {
404                 e.printStackTrace();
405         }
406         
407         
408                 
409         }
410
411         @Override
412         public <C> void forPossibleDirectType(final AsyncReadGraph graph, Resource subject, final C context, final AsyncContextProcedure<C, Resource> procedure) {
413                 
414         assert(subject != null);
415
416         final ReadGraphImpl impl = (ReadGraphImpl)graph;
417         final int subjectId = ((ResourceImpl)subject).id;
418         
419         try {
420                 
421                 final ClusterI cluster = session.clusterTable.getClusterByResourceKey(subjectId);
422                 if(!cluster.isLoaded()) {
423
424 //                      impl.state.inc(0);
425                         
426                         session.queryProvider2.requestCluster(impl, cluster.getClusterId(), new Runnable() {
427                 
428                                         @Override
429                                         public void run() {
430
431                                         try {
432
433                                                 ClusterI.CompleteTypeEnum type = cluster.getCompleteType(subjectId, session.clusterTranslator);
434                                                 if(ClusterI.CompleteTypeEnum.InstanceOf == type) {
435                                                         int result = cluster.getCompleteObjectKey(subjectId, session.clusterTranslator);
436                                                         procedure.execute(graph, context, new ResourceImpl(session.resourceSupport, result));
437                                                 } else {
438                                                 procedure.execute(graph, context, null);
439                                                 }
440
441 //                                              impl.state.dec(0);
442                                                 
443                                         } catch (DatabaseException e) {
444                                                 e.printStackTrace();
445                                         }
446                 
447                                         }
448                 
449                                 });
450                                 
451                 } else {
452
453                         ClusterI.CompleteTypeEnum type = cluster.getCompleteType(subjectId, session.clusterTranslator);
454                         if(ClusterI.CompleteTypeEnum.InstanceOf == type) {
455                                 int result = cluster.getCompleteObjectKey(subjectId, session.clusterTranslator);
456                                 procedure.execute(graph, context, new ResourceImpl(session.resourceSupport, result));
457                         } else {
458                         procedure.execute(graph, context, null);
459                         }
460                         
461                 }
462                 
463         } catch (DatabaseException e) {
464                 
465                 procedure.execute(graph, context, null);
466                 
467         } catch (Throwable t) {
468
469                 t.printStackTrace();
470                 procedure.execute(graph, context, null);
471                 
472         }
473                 
474         }
475         
476         
477         private <C, T> void getRelatedValue4(final ReadGraphImpl graph, final int subject, final C context, final ForPossibleRelatedValueContextProcedure<C, T> procedure) {
478                 
479                 int result = 0;
480                 
481                 final int predicate = procedure.predicateKey;
482
483                 if(subject < 0) {
484
485                         if(!SessionImplSocket.areVirtualStatementsLoaded(session.virtualGraphServerSupport, subject, predicate)) {
486                             SessionImplSocket.loadVirtualStatements(session.virtualGraphServerSupport, graph, subject, predicate,
487                                     g -> getRelatedValue4(g, subject, context, procedure)
488                                 );
489                                 return;
490                         }
491                         
492                         for(TransientGraph g : session.virtualGraphServerSupport.providers) {
493                 for (int id : g.getObjects(subject, predicate)) {
494                         if(result != 0) {
495                                 procedure.exception(graph, new DatabaseException("Multiple objects"));
496 //                              graph.dec();
497                                 return;
498                         } else {
499                                 result = id;
500                         }
501                 }
502                         }
503                         
504                         if(result == 0) {
505                                 
506                         procedure.exception(graph, new DatabaseException("No objects for " + subject ));
507 //                      graph.dec();
508                         return;
509                         
510                         } else {
511                                 
512                                 getValue4(graph, null, result, context, procedure);
513                                 return;
514                                 
515                         }
516                         
517                 } 
518                 
519         final org.simantics.db.procore.cluster.ClusterImpl cluster = session.clusterTable.getClusterByResourceKey(subject);
520         if(!cluster.isLoaded()) {
521                 cluster.load(session.clusterTranslator, () -> getRelatedValue4(graph, subject, context, procedure));
522                 return;
523         }
524         
525         if(cluster.hasVirtual() && session.virtualGraphServerSupport.virtuals.contains(subject)) {
526                         
527                         if(!SessionImplSocket.areVirtualStatementsLoaded(session.virtualGraphServerSupport, subject, predicate)) {
528                             SessionImplSocket.loadVirtualStatements(session.virtualGraphServerSupport, graph, subject, predicate,
529                                     g -> getRelatedValue4(g, subject, context, procedure)
530                                 );
531                                 return;
532                         }
533                 
534                         for(TransientGraph g : session.virtualGraphServerSupport.providers) {
535                 for (int id : g.getObjects(subject, predicate)) {
536                         if(result != 0) {
537                                 procedure.exception(graph, new DatabaseException("Multiple objects"));
538 //                              graph.dec();
539                                 return;
540                         } else {
541                                 result = id;
542                         }
543                 }
544                         }
545                         
546                         getRelatedDirectValue4(graph, cluster, subject, result, context, procedure);
547                         
548                 } else {
549                         
550                         getRelatedDirectValue4(graph, cluster, subject, 0, context, procedure);
551                         
552                 }
553                 
554         }
555         
556         private <T> void getValue4(final ReadGraphImpl graph, final ClusterImpl containerCluster, final int subject, final ForPossibleRelatedValueProcedure<T> procedure) {
557                 
558                 Object result = null;
559         
560                 if(subject < 0) {
561
562                         if(!SessionImplSocket.areVirtualStatementsLoaded(session.virtualGraphServerSupport, subject)) {
563                             SessionImplSocket.loadVirtualStatements(session.virtualGraphServerSupport, graph, subject, 
564                                     g -> getValue4(g, containerCluster, subject, procedure)
565                             );
566                                 return;
567                         }
568                         
569                         for(TransientGraph g : session.virtualGraphServerSupport.providers) {
570                                 Object value = g.getValue(subject);
571                                 if(value != null) {
572                                         if(result != null) {
573                                                 procedure.exception(graph, new DatabaseException("Multiple values"));
574 //                                              graph.dec();
575                                                 return;
576                                         } else {
577                                                 result = value;
578                                         }
579                                 }
580                         }
581
582                         procedure.execute(graph, (T)"name");
583 //                      graph.dec();
584                         return;
585
586                 }
587                 
588                 ClusterImpl cluster = containerCluster;
589                 if(!containerCluster.contains(subject)) {
590                         cluster = session.clusterTable.getClusterByResourceKey(subject);
591                         if(!cluster.isLoaded()) {
592                                 cluster.load(session.clusterTranslator, new Runnable() {
593
594                                         @Override
595                                         public void run() {
596                                                 getValue4(graph, containerCluster, subject, procedure);
597                                         }
598
599                                 });
600                                 return;
601                         }
602                 }
603                 
604         if(cluster.hasVirtual() && session.virtualGraphServerSupport.virtuals.contains(subject)) {
605
606                         if(!SessionImplSocket.areVirtualStatementsLoaded(session.virtualGraphServerSupport, subject)) {
607                             SessionImplSocket.loadVirtualStatements(session.virtualGraphServerSupport, graph, subject,
608                             g -> getValue4(g, containerCluster, subject, procedure)
609                             );
610                                 return;
611                         }
612                 
613                         for(TransientGraph g : session.virtualGraphServerSupport.providers) {
614                                 Object value = g.getValue(subject);
615                                 if(value != null) {
616                                         if(result != null) {
617                                                 procedure.exception(graph, new DatabaseException("Multiple values"));
618 //                                              graph.dec();
619                                                 return;
620                                         } else {
621                                                 result = value;
622                                         }
623                                 }
624                         }
625                         
626                         if(result != null) {
627                                 
628                                 procedure.execute(graph, (T)result);
629 //                              graph.state.barrier.dec();
630                                 
631                         } else {
632                                 
633                                 if(ClusterTypeEnum.SMALL == cluster.getType())
634                                         getDirectValue4(graph, (ClusterSmall)cluster, subject, procedure);
635                                 else 
636                                         getDirectValue4(graph, (ClusterBig)cluster, subject, procedure);
637                         }
638
639                 } else {
640
641                         if(ClusterTypeEnum.SMALL == cluster.getType())
642                                 getDirectValue4(graph, (ClusterSmall)cluster, subject, procedure);
643                         else 
644                                 getDirectValue4(graph, (ClusterBig)cluster, subject, procedure);
645
646                 }
647         
648         }
649         
650         private <C, T> void getValue4(final ReadGraphImpl graph, final ClusterImpl containerCluster, final int subject, final C context, final ForPossibleRelatedValueContextProcedure<C, T> procedure) {
651                 
652                 Object result = null;
653         
654                 if(subject < 0) {
655
656                         if(!SessionImplSocket.areVirtualStatementsLoaded(session.virtualGraphServerSupport, subject)) {
657                             SessionImplSocket.loadVirtualStatements(session.virtualGraphServerSupport, graph, subject,
658                                     g -> getValue4(g, containerCluster, subject, context, procedure)
659                             );
660                                 return;
661                         }
662                         
663                         for(TransientGraph g : session.virtualGraphServerSupport.providers) {
664                                 Object value = g.getValue(subject);
665                                 if(value != null) {
666                                         if(result != null) {
667                                                 procedure.exception(graph, new DatabaseException("Multiple values"));
668 //                                              graph.dec();
669                                                 return;
670                                         } else {
671                                                 result = value;
672                                         }
673                                 }
674                         }
675
676                         procedure.execute(graph, context, (T)"name");
677 //                      graph.dec();
678                         return;
679
680                 }
681                 
682                 ClusterImpl cluster = containerCluster;
683                 if(!containerCluster.contains(subject)) {
684                         cluster = session.clusterTable.getClusterByResourceKey(subject);
685                         if(!cluster.isLoaded()) {
686                                 cluster.load(session.clusterTranslator, new Runnable() {
687
688                                         @Override
689                                         public void run() {
690                                                 getValue4(graph, containerCluster, subject, context, procedure);
691                                         }
692
693                                 });
694                                 return;
695                         }
696                 }
697                 
698         if(cluster.hasVirtual() && session.virtualGraphServerSupport.virtuals.contains(subject)) {
699
700                         if(!SessionImplSocket.areVirtualStatementsLoaded(session.virtualGraphServerSupport, subject)) {
701                             SessionImplSocket.loadVirtualStatements(session.virtualGraphServerSupport, graph, subject,
702                                      g -> getValue4(g, containerCluster, subject, context, procedure)
703                             );
704                                 return;
705                         }
706                 
707                         for(TransientGraph g : session.virtualGraphServerSupport.providers) {
708                                 Object value = g.getValue(subject);
709                                 if(value != null) {
710                                         if(result != null) {
711                                                 procedure.exception(graph, new DatabaseException("Multiple values"));
712 //                                              graph.dec();
713                                                 return;
714                                         } else {
715                                                 result = value;
716                                         }
717                                 }
718                         }
719                         
720                         if(result != null) {
721                                 
722                                 procedure.execute(graph, context, (T)result);
723 //                              graph.state.barrier.dec();
724                                 
725                         } else {
726                                 
727                                 if(ClusterTypeEnum.SMALL == cluster.getType())
728                                         getDirectValue4(graph, (ClusterSmall)cluster, subject, context, procedure);
729                                 else 
730                                         getDirectValue4(graph, (ClusterBig)cluster, subject, context, procedure);
731                         }
732
733                 } else {
734
735                         if(ClusterTypeEnum.SMALL == cluster.getType())
736                                 getDirectValue4(graph, (ClusterSmall)cluster, subject, context, procedure);
737                         else 
738                                 getDirectValue4(graph, (ClusterBig)cluster, subject, context, procedure);
739
740                 }
741         
742         }
743
744         private <T> void getRelatedDirectValue4(final ReadGraphImpl graph, final ClusterImpl cluster, final int subject, final int result, final ForPossibleRelatedValueProcedure<T> procedure) {
745
746                 try {
747
748                         int so = cluster.getSingleObject(subject, procedure, session.clusterTranslator);
749                         if(so == 0) {
750                                 if(result == 0) {
751                                         procedure.exception(graph, new DatabaseException("No objects " + subject + " " + procedure.predicateKey));
752 //                                      graph.dec();
753                                 } else {
754                                         getValue4(graph, cluster, result, procedure);
755                                 }
756                         } else {
757                                 if(result == 0) {
758                                         getValue4(graph, cluster, so, procedure);
759                                 } else {
760                                         procedure.exception(graph, new DatabaseException("Multiple objects"));
761 //                                      graph.dec();
762                                 }
763                         }
764
765                 } catch (DatabaseException e) {
766                         e.printStackTrace();
767                 }
768                 
769         }
770
771         private <C, T> void getRelatedDirectValue4(final ReadGraphImpl graph, final ClusterImpl cluster, final int subject, final int result, final C context, final ForPossibleRelatedValueContextProcedure<C, T> procedure) {
772
773                 try {
774
775                         int so = cluster.getSingleObject(subject, procedure, session.clusterTranslator);
776                         if(so == 0) {
777                                 if(result == 0) {
778                                         procedure.exception(graph, new DatabaseException("No objects " + subject + " " + procedure.predicateKey));
779 //                                      graph.dec();
780                                 } else {
781                                         getValue4(graph, cluster, result, context, procedure);
782                                 }
783                         } else {
784                                 if(result == 0) {
785                                         getValue4(graph, cluster, so, context, procedure);
786                                 } else {
787                                         procedure.exception(graph, new DatabaseException("Multiple objects"));
788 //                                      graph.dec();
789                                 }
790                         }
791
792                 } catch (DatabaseException e) {
793                         e.printStackTrace();
794                 }
795                 
796         }
797         
798         public <T> void getRelatedValue4(final ReadGraphImpl graph, final int subject, final ForPossibleRelatedValueProcedure<T> procedure) {
799                 
800                 int result = 0;
801                 
802                 final int predicate = procedure.predicateKey;
803
804                 if(subject < 0) {
805
806                         if(!SessionImplSocket.areVirtualStatementsLoaded(session.virtualGraphServerSupport, subject, predicate)) {
807                             SessionImplSocket.loadVirtualStatements(session.virtualGraphServerSupport, graph, subject, predicate,
808                                     g -> getRelatedValue4(g, subject, procedure)
809                             );
810                                 return;
811                         }
812                         
813                         for(TransientGraph g : session.virtualGraphServerSupport.providers) {
814                 for (int id : g.getObjects(subject, predicate)) {
815                         if(result != 0) {
816                                 procedure.exception(graph, new DatabaseException("Multiple objects"));
817 //                              graph.dec();
818                                 return;
819                         } else {
820                                 result = id;
821                         }
822                 }
823                         }
824                         
825                         if(result == 0) {
826                                 
827                         procedure.exception(graph, new DatabaseException("No objects for " + subject ));
828 //                      graph.dec();
829                         return;
830                         
831                         } else {
832                                 
833                                 getValue4(graph, null, result, procedure);
834                                 return;
835                                 
836                         }
837                         
838                 } 
839                 
840         final org.simantics.db.procore.cluster.ClusterImpl cluster = session.clusterTable.getClusterByResourceKey(subject);
841         if(!cluster.isLoaded()) {
842                 cluster.load(session.clusterTranslator, new Runnable() {
843
844                                 @Override
845                                 public void run() {
846                                         getRelatedValue4(graph, subject, procedure);
847                                 }
848                         
849                 });
850                 return;
851         }
852         
853         if(cluster.hasVirtual() && session.virtualGraphServerSupport.virtuals.contains(subject)) {
854                         
855                         if(!SessionImplSocket.areVirtualStatementsLoaded(session.virtualGraphServerSupport, subject, predicate)) {
856                             SessionImplSocket.loadVirtualStatements(session.virtualGraphServerSupport, graph, subject, predicate,
857                                     g -> getRelatedValue4(graph, subject, procedure)
858                             );
859                                 return;
860                         }
861                 
862                         for(TransientGraph g : session.virtualGraphServerSupport.providers) {
863                 for (int id : g.getObjects(subject, predicate)) {
864                         if(result != 0) {
865                                 procedure.exception(graph, new DatabaseException("Multiple objects"));
866 //                              graph.dec();
867                                 return;
868                         } else {
869                                 result = id;
870                         }
871                 }
872                         }
873                         
874                         getRelatedDirectValue4(graph, cluster, subject, result, procedure);
875                         
876                 } else {
877                         
878                         getRelatedDirectValue4(graph, cluster, subject, 0, procedure);
879                         
880                 }
881                 
882         }
883         
884         private <C, T> void getDirectValue4(final ReadGraphImpl graph, final ClusterSmall cluster, final int subject, final C context, final ForPossibleRelatedValueContextProcedure<C, T> procedure) {
885                 
886                 try {
887                         byte[] bytes = cluster.getValue(subject, session.clusterTranslator);
888                         T value = (T)utf(bytes);
889                         procedure.execute(graph, context, value);
890                 } catch (DatabaseException e) {
891                         procedure.execute(graph, context, null);
892                 }
893
894 //              graph.dec();
895                 
896         }
897
898         private <T> void getDirectValue4(final ReadGraphImpl graph, final ClusterBig cluster, final int subject, final ForPossibleRelatedValueProcedure<T> procedure) {
899                 
900                 try {
901                         byte[] bytes = cluster.getValue(subject, session.clusterTranslator);
902                         T value = (T)utf(bytes);
903                         procedure.execute(graph, value);
904                 } catch (DatabaseException e) {
905                         procedure.execute(graph, null);
906                 }
907
908 //              graph.dec();
909                 
910         }
911
912         private <C, T> void getDirectValue4(final ReadGraphImpl graph, final ClusterBig cluster, final int subject, final C context, final ForPossibleRelatedValueContextProcedure<C, T> procedure) {
913                 
914                 try {
915                         byte[] bytes = cluster.getValue(subject, session.clusterTranslator);
916                         if(bytes == null) {
917                                 procedure.execute(graph, context, null);
918                         } else {
919                                 T value = (T)utf(bytes);
920                                 procedure.execute(graph, context, value);
921                         }
922                 } catch (DatabaseException e) {
923                         procedure.execute(graph, context, null);
924                 }
925
926 //              graph.dec();
927                 
928         }
929         
930         private final char[] chars = new char[1024];
931         
932         private <T> void getDirectValue4(final ReadGraphImpl graph, final ClusterSmall cluster, final int subject, final ForPossibleRelatedValueProcedure<T> procedure) {
933
934                 ResourceTableSmall rt = cluster.resourceTable;
935                 ValueTableSmall vt = cluster.valueTable;
936
937                 byte[] bs = vt.table;
938                 long[] ls = rt.table;
939
940                 int index = ((subject&0xFFFF) << 1) - 1 + rt.offset;
941
942                 int valueIndex = (int)(ls[index] >>> 24) & 0x3FFFFF + vt.offset;
943
944                 int size = (int)bs[valueIndex++]-1;
945                 valueIndex++;
946                 for(int i=0;i<size;i++) {
947                         chars[i] = (char)bs[valueIndex++];
948                 }
949
950                 T value = (T)new String(chars, 0, size);
951
952                 procedure.execute(graph, value);
953 //              graph.dec();
954                 
955         }
956
957         final private String utf(byte[] bytes) {
958                 
959                 if(bytes == null) return null;
960                 
961                 int index = 0;
962                 int length = bytes[index++]&0xff; 
963                 if(length >= 0x80) {
964                         if(length >= 0xc0) {
965                                 if(length >= 0xe0) {
966                                         if(length >= 0xf0) {
967                                                 length &= 0x0f;
968                                                 length += ((bytes[index++]&0xff)<<3);
969                                                 length += ((bytes[index++]&0xff)<<11);
970                                                 length += ((bytes[index++]&0xff)<<19);
971                                                 length += 0x10204080;
972                                         }
973                                         else {
974                                                 length &= 0x1f;
975                                                 length += ((bytes[index++]&0xff)<<4);
976                                                 length += ((bytes[index++]&0xff)<<12);
977                                                 length += ((bytes[index++]&0xff)<<20);
978                                                 length += 0x204080;
979                                         }
980                                 }
981                                 else {
982                                         length &= 0x3f;
983                                         length += ((bytes[index++]&0xff)<<5);
984                                         length += ((bytes[index++]&0xff)<<13);
985                                         length += 0x4080;
986                                 }
987                         }
988                         else {
989                                 length &= 0x7f;
990                                 length += ((bytes[index++]&0xff)<<6);
991                                 length += 0x80;
992                         }
993                 }
994                 
995                 int i = 0;
996                 int target = length+index;
997                 while(index < target) {
998                         int c = bytes[index++]&0xff;
999                         if(c <= 0x7F) {
1000                                 chars[i++] = (char)(c&0x7F);
1001                         } else if (c > 0x07FF) {
1002                                 int c2 = bytes[index++]&0xff;
1003                                 int c3 = bytes[index++]&0xff;
1004                                 chars[i++] = (char)(((c&0xf)<<12) + ((c2&0x3f)<<6) + (c3&0x3f)); 
1005                         } else {
1006                                 int c2 = bytes[index++]&0xff;
1007                                 chars[i++] = (char)(((c&0x1f)<<6) + (c2&0x3f)); 
1008                         }
1009                         
1010                         
1011 //                      if (!((c >= 0x0001) && (c <= 0x007F))) {
1012 //                      } else {
1013 //                      }
1014 //                      
1015 //                              if ((c >= 0x0001) && (c <= 0x007F)) {
1016 //                                      bytearr[byteIndex++] = (byte)( c );
1017 //                              } else if (c > 0x07FF) {
1018 //                                      bytearr[byteIndex++] = (byte)(0xE0 | ((c >> 12) & 0x0F));
1019 //                                      bytearr[byteIndex++] = (byte)(0x80 | ((c >>  6) & 0x3F));
1020 //                                      bytearr[byteIndex++] = (byte)(0x80 | ((c >>  0) & 0x3F));
1021 //                              } else {
1022 //                                      bytearr[byteIndex++] = (byte)(0xC0 | ((c >>  6) & 0x1F));
1023 //                                      bytearr[byteIndex++] = (byte)(0x80 | ((c >>  0) & 0x3F));
1024 //                              }
1025 //                      }
1026                         
1027                         
1028                 }
1029                 return new String(chars, 0, i);
1030         }
1031         
1032 }