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