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