1 package fi.vtt.simantics.procore.internal;
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.AssumptionException;
11 import org.simantics.db.exception.DatabaseException;
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;
36 * Note that the direct value retrieval in this implementation only supports
37 * String-type literals - nothing else!
39 * This implementation is mainly intended for optimizing database indexing
42 public class DirectQuerySupportImpl implements DirectQuerySupport {
44 final private SessionImplSocket session;
46 DirectQuerySupportImpl(SessionImplSocket session) {
47 this.session = session;
51 final public void forEachDirectPersistentStatement(AsyncReadGraph graph, final Resource subject, final AsyncProcedure<DirectStatements> procedure) {
52 ReadGraphImpl impl = (ReadGraphImpl)graph;
53 impl.processor.forEachDirectStatement(impl, subject, procedure, true);
57 final public void forEachDirectStatement(AsyncReadGraph graph, final Resource subject, final AsyncProcedure<DirectStatements> procedure) {
58 ReadGraphImpl impl = (ReadGraphImpl)graph;
59 impl.processor.forEachDirectStatement(impl, subject, procedure, false);
63 public void forEachDirectStatement(AsyncReadGraph graph, Resource subject, SyncProcedure<DirectStatements> procedure) {
64 forEachDirectStatement(graph, subject, new SyncToAsyncProcedure<DirectStatements>(procedure));
68 public void forEachDirectStatement(AsyncReadGraph graph, Resource subject, Procedure<DirectStatements> procedure) {
69 ReadGraphImpl impl = (ReadGraphImpl)graph;
70 impl.processor.forEachDirectStatement(impl, subject, procedure);
74 public void forRelationInfo(AsyncReadGraph graph, Resource subject, AsyncProcedure<RelationInfo> procedure) {
75 ReadGraphImpl impl = (ReadGraphImpl)graph;
76 impl.processor.forRelationInfo(impl, subject, procedure);
80 public void forRelationInfo(AsyncReadGraph graph, Resource subject, SyncProcedure<RelationInfo> procedure) {
81 forRelationInfo(graph, subject, new SyncToAsyncProcedure<RelationInfo>(procedure));
85 public void forRelationInfo(AsyncReadGraph graph, Resource subject, Procedure<RelationInfo> procedure) {
86 forRelationInfo(graph, subject, new NoneToAsyncProcedure<RelationInfo>(procedure));
90 public AsyncMultiProcedure<Resource> compileForEachObject(ReadGraph graph, final Resource relation, AsyncMultiProcedure<Resource> user) {
93 RelationInfo info = graph.syncRequest(new AsyncRead<RelationInfo>() {
96 public void perform(AsyncReadGraph graph, AsyncProcedure<RelationInfo> procedure) {
97 forRelationInfo(graph, relation, procedure);
101 public int threadHash() {
106 public int getFlags() {
111 final int predicateKey = ((ResourceImpl)relation).id;
112 return new ForEachObjectProcedure(predicateKey, info, session.queryProvider2, user);
113 } catch (DatabaseException e) {
120 public <C> AsyncContextMultiProcedure<C, Resource> compileForEachObject(ReadGraph graph, final Resource relation, AsyncContextMultiProcedure<C, Resource> user) {
123 RelationInfo info = graph.syncRequest(new AsyncRead<RelationInfo>() {
126 public void perform(AsyncReadGraph graph, AsyncProcedure<RelationInfo> procedure) {
127 forRelationInfo(graph, relation, procedure);
131 public int threadHash() {
136 public int getFlags() {
141 final int predicateKey = ((ResourceImpl)relation).id;
142 return new ForEachObjectContextProcedure<C>(predicateKey, info, session.queryProvider2, user);
143 } catch (DatabaseException e) {
150 public <T> AsyncProcedure<T> compilePossibleRelatedValue(ReadGraph graph, final Resource relation, AsyncProcedure<T> user) {
153 RelationInfo info = graph.syncRequest(new AsyncRead<RelationInfo>() {
156 public void perform(AsyncReadGraph graph, AsyncProcedure<RelationInfo> procedure) {
157 forRelationInfo(graph, relation, procedure);
161 public int threadHash() {
166 public int getFlags() {
171 final int predicateKey = ((ResourceImpl)relation).id;
172 return new ForPossibleRelatedValueProcedure<T>(predicateKey, info, user);
173 } catch (DatabaseException e) {
180 public <C, T> AsyncContextProcedure<C, T> compilePossibleRelatedValue(ReadGraph graph, final Resource relation, AsyncContextProcedure<C, T> user) {
183 RelationInfo info = graph.syncRequest(new AsyncRead<RelationInfo>() {
186 public void perform(AsyncReadGraph graph, AsyncProcedure<RelationInfo> procedure) {
187 forRelationInfo(graph, relation, procedure);
191 public int threadHash() {
196 public int getFlags() {
201 final int predicateKey = ((ResourceImpl)relation).id;
202 return new ForPossibleRelatedValueContextProcedure<C, T>(predicateKey, info, user);
203 } catch (DatabaseException e) {
210 public void forEachObjectCompiled(AsyncReadGraph graph, Resource subject, final AsyncMultiProcedure<Resource> procedure) {
212 assert(subject != null);
214 final ForEachObjectProcedure proc = (ForEachObjectProcedure)procedure;
215 // final RelationInfo info = proc.info;
217 final ReadGraphImpl impl = (ReadGraphImpl)graph;
218 final int subjectId = ((ResourceImpl)subject).id;
220 // int callerThread = impl.callerThread;
221 // int suggestSchedule = (subjectId>>16) & queryProvider2.THREAD_MASK;
225 // if(callerThread == suggestSchedule) {
227 // if(info.isFunctional) {
228 // querySupport.getObjects4(impl, subjectId, proc);
230 session.querySupport.getObjects4(impl, subjectId, proc);
235 // impl.state.barrier.inc();
236 // impl.state.barrier.dec(callerThread);
238 // queryProvider2.schedule(callerThread, new SessionTask(suggestSchedule) {
241 // public void run(int thread) {
243 // impl.state.barrier.inc(thread);
244 // impl.state.barrier.dec();
246 // if(info.isFunctional) {
247 // querySupport.getObjects4(impl.newAsync(thread), subjectId, proc);
249 // querySupport.getObjects4(impl.newAsync(thread), subjectId, proc);
255 // public String toString() {
266 public <C> void forEachObjectCompiled(AsyncReadGraph graph, Resource subject, C context, final AsyncContextMultiProcedure<C, Resource> procedure) {
268 assert(subject != null);
270 final ForEachObjectContextProcedure<C> proc = (ForEachObjectContextProcedure<C>)procedure;
271 final RelationInfo info = proc.info;
273 final ReadGraphImpl impl = (ReadGraphImpl)graph;
274 final int subjectId = ((ResourceImpl)subject).id;
276 // int callerThread = impl.callerThread;
277 // int suggestSchedule = (subjectId>>16) & queryProvider2.THREAD_MASK;
281 if(info.isFunctional) {
282 session.querySupport.getObjects4(impl, subjectId, context, proc);
284 session.querySupport.getObjects4(impl, subjectId, context, proc);
290 public <T> void forPossibleRelatedValueCompiled(AsyncReadGraph graph, Resource subject, final AsyncProcedure<T> procedure) {
292 assert(subject != null);
294 final ForPossibleRelatedValueProcedure<T> proc = (ForPossibleRelatedValueProcedure<T>)procedure;
295 final RelationInfo info = proc.info;
297 final ReadGraphImpl impl = (ReadGraphImpl)graph;
298 final int subjectId = ((ResourceImpl)subject).id;
300 // int callerThread = impl.callerThread;
301 // int suggestSchedule = (subjectId>>16) & session.queryProvider2.THREAD_MASK;
305 // if(callerThread == suggestSchedule) {
307 if(info.isFunctional) {
308 getRelatedValue4(impl, subjectId, proc);
310 getRelatedValue4(impl, subjectId, proc);
315 // impl.state.barrier.inc();
316 // impl.state.barrier.dec(callerThread);
318 // queryProvider2.schedule(callerThread, new SessionTask(suggestSchedule) {
321 // public void run(int thread) {
323 // impl.state.barrier.inc(thread);
324 // impl.state.barrier.dec();
326 // if(info.isFunctional) {
327 // getRelatedValue4(impl.newAsync(thread), subjectId, proc);
329 // getRelatedValue4(impl.newAsync(thread), subjectId, proc);
335 // public String toString() {
346 public <C, T> void forPossibleRelatedValueCompiled(AsyncReadGraph graph, Resource subject, C context, final AsyncContextProcedure<C, T> procedure) {
348 assert(subject != null);
350 final ForPossibleRelatedValueContextProcedure<C, T> proc = (ForPossibleRelatedValueContextProcedure<C, T>)procedure;
351 final RelationInfo info = proc.info;
353 final ReadGraphImpl impl = (ReadGraphImpl)graph;
354 final int subjectId = ((ResourceImpl)subject).id;
356 // int callerThread = impl.callerThread;
357 // int suggestSchedule = (subjectId>>16) & session.queryProvider2.THREAD_MASK;
361 if(info.isFunctional) {
362 getRelatedValue4(impl, subjectId, context, proc);
364 getRelatedValue4(impl, subjectId, context, proc);
370 public <T> void forPossibleType(final AsyncReadGraph graph, Resource subject, final AsyncProcedure<Resource> procedure) {
372 assert(subject != null);
374 final ReadGraphImpl impl = (ReadGraphImpl)graph;
375 final int subjectId = ((ResourceImpl)subject).id;
379 final ClusterI cluster = session.clusterTable.getClusterByResourceKey(subjectId);
380 if(!cluster.isLoaded()) {
382 // impl.state.inc(0);
384 session.queryProvider2.requestCluster(impl, cluster.getClusterId(), new Runnable() {
391 int result = cluster.getCompleteObjectKey(subjectId, session.clusterTranslator);
392 procedure.execute(graph, new ResourceImpl(session.resourceSupport, result));
394 // impl.state.dec(0);
396 } catch (DatabaseException e) {
406 int result = cluster.getCompleteObjectKey(subjectId, session.clusterTranslator);
407 procedure.execute(graph, new ResourceImpl(session.resourceSupport, result));
411 } catch (DatabaseException e) {
420 public <C> void forPossibleDirectType(final AsyncReadGraph graph, Resource subject, final C context, final AsyncContextProcedure<C, Resource> procedure) {
422 assert(subject != null);
424 final ReadGraphImpl impl = (ReadGraphImpl)graph;
425 final int subjectId = ((ResourceImpl)subject).id;
429 final ClusterI cluster = session.clusterTable.getClusterByResourceKey(subjectId);
430 if(!cluster.isLoaded()) {
432 // impl.state.inc(0);
434 session.queryProvider2.requestCluster(impl, cluster.getClusterId(), new Runnable() {
441 ClusterI.CompleteTypeEnum type = cluster.getCompleteType(subjectId, session.clusterTranslator);
442 if(ClusterI.CompleteTypeEnum.InstanceOf == type) {
443 int result = cluster.getCompleteObjectKey(subjectId, session.clusterTranslator);
444 procedure.execute(graph, context, new ResourceImpl(session.resourceSupport, result));
446 procedure.execute(graph, context, null);
449 // impl.state.dec(0);
451 } catch (DatabaseException e) {
461 ClusterI.CompleteTypeEnum type = cluster.getCompleteType(subjectId, session.clusterTranslator);
462 if(ClusterI.CompleteTypeEnum.InstanceOf == type) {
463 int result = cluster.getCompleteObjectKey(subjectId, session.clusterTranslator);
464 procedure.execute(graph, context, new ResourceImpl(session.resourceSupport, result));
466 procedure.execute(graph, context, null);
471 } catch (DatabaseException e) {
473 procedure.execute(graph, context, null);
475 } catch (Throwable t) {
478 procedure.execute(graph, context, null);
485 private <C, T> void getRelatedValue4(final ReadGraphImpl graph, final int subject, final C context, final ForPossibleRelatedValueContextProcedure<C, T> procedure) {
489 final int predicate = procedure.predicateKey;
493 if(!SessionImplSocket.areVirtualStatementsLoaded(session.virtualGraphServerSupport, subject, predicate)) {
494 SessionImplSocket.loadVirtualStatements(session.virtualGraphServerSupport, graph, subject, predicate,
495 g -> getRelatedValue4(g, subject, context, procedure)
500 for(TransientGraph g : session.virtualGraphServerSupport.providers) {
501 for (int id : g.getObjects(subject, predicate)) {
503 procedure.exception(graph, new DatabaseException("Multiple objects"));
514 procedure.exception(graph, new DatabaseException("No objects for " + subject ));
520 getValue4(graph, null, result, context, procedure);
527 final org.simantics.db.procore.cluster.ClusterImpl cluster = session.clusterTable.getClusterByResourceKey(subject);
528 if(!cluster.isLoaded()) {
529 cluster.load(session.clusterTranslator, () -> getRelatedValue4(graph, subject, context, procedure));
533 if(cluster.hasVirtual() && session.virtualGraphServerSupport.virtuals.contains(subject)) {
535 if(!SessionImplSocket.areVirtualStatementsLoaded(session.virtualGraphServerSupport, subject, predicate)) {
536 SessionImplSocket.loadVirtualStatements(session.virtualGraphServerSupport, graph, subject, predicate,
537 g -> getRelatedValue4(g, subject, context, procedure)
542 for(TransientGraph g : session.virtualGraphServerSupport.providers) {
543 for (int id : g.getObjects(subject, predicate)) {
545 procedure.exception(graph, new DatabaseException("Multiple objects"));
554 getRelatedDirectValue4(graph, cluster, subject, result, context, procedure);
558 getRelatedDirectValue4(graph, cluster, subject, 0, context, procedure);
564 @SuppressWarnings("unchecked")
565 private <T> void getValue4(final ReadGraphImpl graph, final ClusterImpl containerCluster, final int subject, final ForPossibleRelatedValueProcedure<T> procedure) {
567 Object result = null;
571 if(!SessionImplSocket.areVirtualStatementsLoaded(session.virtualGraphServerSupport, subject)) {
572 SessionImplSocket.loadVirtualStatements(session.virtualGraphServerSupport, graph, subject,
573 g -> getValue4(g, containerCluster, subject, procedure)
578 for(TransientGraph g : session.virtualGraphServerSupport.providers) {
579 Object value = g.getValue(subject);
582 procedure.exception(graph, new DatabaseException("Multiple values"));
591 procedure.execute(graph, (T)"name");
597 ClusterImpl cluster = containerCluster;
598 if(!containerCluster.contains(subject)) {
599 cluster = session.clusterTable.getClusterByResourceKey(subject);
600 if(!cluster.isLoaded()) {
601 cluster.load(session.clusterTranslator, new Runnable() {
605 getValue4(graph, containerCluster, subject, procedure);
613 if(cluster.hasVirtual() && session.virtualGraphServerSupport.virtuals.contains(subject)) {
615 if(!SessionImplSocket.areVirtualStatementsLoaded(session.virtualGraphServerSupport, subject)) {
616 SessionImplSocket.loadVirtualStatements(session.virtualGraphServerSupport, graph, subject,
617 g -> getValue4(g, containerCluster, subject, procedure)
622 for(TransientGraph g : session.virtualGraphServerSupport.providers) {
623 Object value = g.getValue(subject);
626 procedure.exception(graph, new DatabaseException("Multiple values"));
637 procedure.execute(graph, (T)result);
638 // graph.state.barrier.dec();
642 if(ClusterTypeEnum.SMALL == cluster.getType())
643 getDirectValue4(graph, (ClusterSmall)cluster, subject, procedure);
645 getDirectValue4(graph, (ClusterBig)cluster, subject, procedure);
650 if(ClusterTypeEnum.SMALL == cluster.getType())
651 getDirectValue4(graph, (ClusterSmall)cluster, subject, procedure);
653 getDirectValue4(graph, (ClusterBig)cluster, subject, procedure);
659 @SuppressWarnings("unchecked")
660 private <C, T> void getValue4(final ReadGraphImpl graph, final ClusterImpl containerCluster, final int subject, final C context, final ForPossibleRelatedValueContextProcedure<C, T> procedure) {
662 Object result = null;
666 if(!SessionImplSocket.areVirtualStatementsLoaded(session.virtualGraphServerSupport, subject)) {
667 SessionImplSocket.loadVirtualStatements(session.virtualGraphServerSupport, graph, subject,
668 g -> getValue4(g, containerCluster, subject, context, procedure)
673 for(TransientGraph g : session.virtualGraphServerSupport.providers) {
674 Object value = g.getValue(subject);
677 procedure.exception(graph, new DatabaseException("Multiple values"));
686 procedure.execute(graph, context, (T)"name");
692 ClusterImpl cluster = containerCluster;
693 if(!containerCluster.contains(subject)) {
694 cluster = session.clusterTable.getClusterByResourceKey(subject);
695 if(!cluster.isLoaded()) {
696 cluster.load(session.clusterTranslator, new Runnable() {
700 getValue4(graph, containerCluster, subject, context, procedure);
708 if(cluster.hasVirtual() && session.virtualGraphServerSupport.virtuals.contains(subject)) {
710 if(!SessionImplSocket.areVirtualStatementsLoaded(session.virtualGraphServerSupport, subject)) {
711 SessionImplSocket.loadVirtualStatements(session.virtualGraphServerSupport, graph, subject,
712 g -> getValue4(g, containerCluster, subject, context, procedure)
717 for(TransientGraph g : session.virtualGraphServerSupport.providers) {
718 Object value = g.getValue(subject);
721 procedure.exception(graph, new DatabaseException("Multiple values"));
732 procedure.execute(graph, context, (T)result);
733 // graph.state.barrier.dec();
737 if(ClusterTypeEnum.SMALL == cluster.getType())
738 getDirectValue4(graph, (ClusterSmall)cluster, subject, context, procedure);
740 getDirectValue4(graph, (ClusterBig)cluster, subject, context, procedure);
745 if(ClusterTypeEnum.SMALL == cluster.getType())
746 getDirectValue4(graph, (ClusterSmall)cluster, subject, context, procedure);
748 getDirectValue4(graph, (ClusterBig)cluster, subject, context, procedure);
754 private <T> void getRelatedDirectValue4(final ReadGraphImpl graph, final ClusterImpl cluster, final int subject, final int result, final ForPossibleRelatedValueProcedure<T> procedure) {
758 int so = cluster.getSingleObject(subject, procedure, session.clusterTranslator);
761 procedure.exception(graph, new DatabaseException("No objects " + subject + " " + procedure.predicateKey));
764 getValue4(graph, cluster, result, procedure);
768 getValue4(graph, cluster, so, procedure);
770 procedure.exception(graph, new DatabaseException("Multiple objects"));
775 } catch (DatabaseException e) {
781 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) {
785 int so = cluster.getSingleObject(subject, procedure, session.clusterTranslator);
788 procedure.exception(graph, new DatabaseException("No objects " + subject + " " + procedure.predicateKey));
791 getValue4(graph, cluster, result, context, procedure);
795 getValue4(graph, cluster, so, context, procedure);
797 procedure.exception(graph, new DatabaseException("Multiple objects"));
802 } catch (DatabaseException e) {
808 public <T> void getRelatedValue4(final ReadGraphImpl graph, final int subject, final ForPossibleRelatedValueProcedure<T> procedure) {
812 final int predicate = procedure.predicateKey;
816 if(!SessionImplSocket.areVirtualStatementsLoaded(session.virtualGraphServerSupport, subject, predicate)) {
817 SessionImplSocket.loadVirtualStatements(session.virtualGraphServerSupport, graph, subject, predicate,
818 g -> getRelatedValue4(g, subject, procedure)
823 for(TransientGraph g : session.virtualGraphServerSupport.providers) {
824 for (int id : g.getObjects(subject, predicate)) {
826 procedure.exception(graph, new DatabaseException("Multiple objects"));
837 procedure.exception(graph, new DatabaseException("No objects for " + subject ));
843 getValue4(graph, null, result, procedure);
850 final org.simantics.db.procore.cluster.ClusterImpl cluster = session.clusterTable.getClusterByResourceKey(subject);
851 if(!cluster.isLoaded()) {
852 cluster.load(session.clusterTranslator, new Runnable() {
856 getRelatedValue4(graph, subject, procedure);
863 if(cluster.hasVirtual() && session.virtualGraphServerSupport.virtuals.contains(subject)) {
865 if(!SessionImplSocket.areVirtualStatementsLoaded(session.virtualGraphServerSupport, subject, predicate)) {
866 SessionImplSocket.loadVirtualStatements(session.virtualGraphServerSupport, graph, subject, predicate,
867 g -> getRelatedValue4(graph, subject, procedure)
872 for(TransientGraph g : session.virtualGraphServerSupport.providers) {
873 for (int id : g.getObjects(subject, predicate)) {
875 procedure.exception(graph, new DatabaseException("Multiple objects"));
884 getRelatedDirectValue4(graph, cluster, subject, result, procedure);
888 getRelatedDirectValue4(graph, cluster, subject, 0, procedure);
894 private <C, T> void getDirectValue4(final ReadGraphImpl graph, final ClusterSmall cluster, final int subject, final C context, final ForPossibleRelatedValueContextProcedure<C, T> procedure) {
897 byte[] bytes = cluster.getValue(subject, session.clusterTranslator);
898 @SuppressWarnings("unchecked")
899 T value = (T)utf(bytes, 0);
900 procedure.execute(graph, context, value);
901 } catch (DatabaseException e) {
902 procedure.execute(graph, context, null);
909 private <T> void getDirectValue4(final ReadGraphImpl graph, final ClusterBig cluster, final int subject, final ForPossibleRelatedValueProcedure<T> procedure) {
912 byte[] bytes = cluster.getValue(subject, session.clusterTranslator);
913 @SuppressWarnings("unchecked")
914 T value = (T)utf(bytes, 0);
915 procedure.execute(graph, value);
916 } catch (DatabaseException e) {
917 procedure.execute(graph, null);
924 private <C, T> void getDirectValue4(final ReadGraphImpl graph, final ClusterBig cluster, final int subject, final C context, final ForPossibleRelatedValueContextProcedure<C, T> procedure) {
927 byte[] bytes = cluster.getValue(subject, session.clusterTranslator);
929 procedure.execute(graph, context, null);
931 @SuppressWarnings("unchecked")
932 T value = (T)utf(bytes, 0);
933 procedure.execute(graph, context, value);
935 } catch (DatabaseException e) {
936 procedure.execute(graph, context, null);
943 private <T> void getDirectValue4(final ReadGraphImpl graph, final ClusterSmall cluster, final int subject, final ForPossibleRelatedValueProcedure<T> procedure) {
945 // Note: this code avoids creating an intermediate byte[]
946 // to store the encoded string bytes and reads the UTF string
947 // from the value table byte[] directly into String instead.
949 ResourceTableSmall rt = cluster.resourceTable;
950 ValueTableSmall vt = cluster.valueTable;
952 byte[] bs = vt.table;
953 long[] ls = rt.table;
955 int index = ((subject&0xFFF) << 1) - 1 + rt.offset;
956 int valueIndex = ((int)(ls[index] >>> 24) & 0x3FFFFF) + vt.offset;
958 int size = bs[valueIndex++];
959 if (size < 0) // two byte size
960 size = (int)(((size & 0x7F) << 8) | (bs[valueIndex++] & 0xFF));
962 throw new DatabaseException("No value for " + subject);
964 @SuppressWarnings("unchecked")
965 T t = (T) utf(bs, valueIndex);
967 procedure.execute(graph, t);
968 } catch (DatabaseException e) {
969 procedure.exception(graph, e);
973 final private String utf(byte[] bytes, int offset) throws AssumptionException {
975 if(bytes == null) return null;
977 // Read databoard int32 using Length encoding
978 // https://dev.simantics.org/index.php/Databoard_Specification#Length
980 int length = bytes[index++]&0xff;
986 length += ((bytes[index++]&0xff)<<3);
987 length += ((bytes[index++]&0xff)<<11);
988 length += ((bytes[index++]&0xff)<<19);
989 length += 0x10204080;
993 length += ((bytes[index++]&0xff)<<4);
994 length += ((bytes[index++]&0xff)<<12);
995 length += ((bytes[index++]&0xff)<<20);
1001 length += ((bytes[index++]&0xff)<<5);
1002 length += ((bytes[index++]&0xff)<<13);
1008 length += ((bytes[index++]&0xff)<<6);
1013 // Copied from DataInputStream
1014 int utflen = length;
1015 char[] chararr = new char[utflen];
1017 int c, char2, char3;
1019 int target = index + length;
1020 int chararr_count=0;
1022 while (count < target) {
1023 c = (int) bytes[count] & 0xff;
1026 chararr[chararr_count++]=(char)c;
1029 while (count < target) {
1030 c = (int) bytes[count] & 0xff;
1032 case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
1035 chararr[chararr_count++]=(char)c;
1038 /* 110x xxxx 10xx xxxx*/
1041 throw new AssumptionException(
1042 "malformed input: partial character at end (" + (count-index) + " > " + utflen + ")");
1043 char2 = (int) bytes[count-1];
1044 if ((char2 & 0xC0) != 0x80)
1045 throw new AssumptionException(
1046 "malformed input around byte " + count);
1047 chararr[chararr_count++]=(char)(((c & 0x1F) << 6) |
1051 /* 1110 xxxx 10xx xxxx 10xx xxxx */
1054 throw new AssumptionException(
1055 "malformed input: partial character at end (" + (count-index) + " > " + utflen + ")");
1056 char2 = (int) bytes[count-2];
1057 char3 = (int) bytes[count-1];
1058 if (((char2 & 0xC0) != 0x80) || ((char3 & 0xC0) != 0x80))
1059 throw new AssumptionException(
1060 "malformed input around byte " + (count-1));
1061 chararr[chararr_count++]=(char)(((c & 0x0F) << 12) |
1062 ((char2 & 0x3F) << 6) |
1063 ((char3 & 0x3F) << 0));
1066 /* 10xx xxxx, 1111 xxxx */
1067 throw new AssumptionException(
1068 "malformed input around byte " + count);
1072 // The number of chars produced may be less than utflen
1073 return new String(chararr, 0, chararr_count);