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.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;
35 public class DirectQuerySupportImpl implements DirectQuerySupport {
37 final private SessionImplSocket session;
39 DirectQuerySupportImpl(SessionImplSocket session) {
40 this.session = session;
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);
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);
56 public void forEachDirectStatement(AsyncReadGraph graph, Resource subject, SyncProcedure<DirectStatements> procedure) {
57 forEachDirectStatement(graph, subject, new SyncToAsyncProcedure<DirectStatements>(procedure));
61 public void forEachDirectStatement(AsyncReadGraph graph, Resource subject, Procedure<DirectStatements> procedure) {
62 ReadGraphImpl impl = (ReadGraphImpl)graph;
63 impl.processor.forEachDirectStatement(impl, subject, procedure);
67 public void forRelationInfo(AsyncReadGraph graph, Resource subject, AsyncProcedure<RelationInfo> procedure) {
68 ReadGraphImpl impl = (ReadGraphImpl)graph;
69 impl.processor.forRelationInfo(impl, subject, procedure);
73 public void forRelationInfo(AsyncReadGraph graph, Resource subject, SyncProcedure<RelationInfo> procedure) {
74 forRelationInfo(graph, subject, new SyncToAsyncProcedure<RelationInfo>(procedure));
78 public void forRelationInfo(AsyncReadGraph graph, Resource subject, Procedure<RelationInfo> procedure) {
79 forRelationInfo(graph, subject, new NoneToAsyncProcedure<RelationInfo>(procedure));
83 public AsyncMultiProcedure<Resource> compileForEachObject(ReadGraph graph, final Resource relation, AsyncMultiProcedure<Resource> user) {
86 RelationInfo info = graph.syncRequest(new AsyncRead<RelationInfo>() {
89 public void perform(AsyncReadGraph graph, AsyncProcedure<RelationInfo> procedure) {
90 forRelationInfo(graph, relation, procedure);
94 public int threadHash() {
99 public int getFlags() {
104 final int predicateKey = ((ResourceImpl)relation).id;
105 return new ForEachObjectProcedure(predicateKey, info, session.queryProvider2, user);
106 } catch (DatabaseException e) {
113 public <C> AsyncContextMultiProcedure<C, Resource> compileForEachObject(ReadGraph graph, final Resource relation, AsyncContextMultiProcedure<C, Resource> user) {
116 RelationInfo info = graph.syncRequest(new AsyncRead<RelationInfo>() {
119 public void perform(AsyncReadGraph graph, AsyncProcedure<RelationInfo> procedure) {
120 forRelationInfo(graph, relation, procedure);
124 public int threadHash() {
129 public int getFlags() {
134 final int predicateKey = ((ResourceImpl)relation).id;
135 return new ForEachObjectContextProcedure<C>(predicateKey, info, session.queryProvider2, user);
136 } catch (DatabaseException e) {
143 public <T> AsyncProcedure<T> compilePossibleRelatedValue(ReadGraph graph, final Resource relation, AsyncProcedure<T> user) {
146 RelationInfo info = graph.syncRequest(new AsyncRead<RelationInfo>() {
149 public void perform(AsyncReadGraph graph, AsyncProcedure<RelationInfo> procedure) {
150 forRelationInfo(graph, relation, procedure);
154 public int threadHash() {
159 public int getFlags() {
164 final int predicateKey = ((ResourceImpl)relation).id;
165 return new ForPossibleRelatedValueProcedure<T>(predicateKey, info, user);
166 } catch (DatabaseException e) {
173 public <C, T> AsyncContextProcedure<C, T> compilePossibleRelatedValue(ReadGraph graph, final Resource relation, AsyncContextProcedure<C, T> user) {
176 RelationInfo info = graph.syncRequest(new AsyncRead<RelationInfo>() {
179 public void perform(AsyncReadGraph graph, AsyncProcedure<RelationInfo> procedure) {
180 forRelationInfo(graph, relation, procedure);
184 public int threadHash() {
189 public int getFlags() {
194 final int predicateKey = ((ResourceImpl)relation).id;
195 return new ForPossibleRelatedValueContextProcedure<C, T>(predicateKey, info, user);
196 } catch (DatabaseException e) {
203 public void forEachObjectCompiled(AsyncReadGraph graph, Resource subject, final AsyncMultiProcedure<Resource> procedure) {
205 assert(subject != null);
207 final ForEachObjectProcedure proc = (ForEachObjectProcedure)procedure;
208 // final RelationInfo info = proc.info;
210 final ReadGraphImpl impl = (ReadGraphImpl)graph;
211 final int subjectId = ((ResourceImpl)subject).id;
213 // int callerThread = impl.callerThread;
214 // int suggestSchedule = (subjectId>>16) & queryProvider2.THREAD_MASK;
218 // if(callerThread == suggestSchedule) {
220 // if(info.isFunctional) {
221 // querySupport.getObjects4(impl, subjectId, proc);
223 session.querySupport.getObjects4(impl, subjectId, proc);
228 // impl.state.barrier.inc();
229 // impl.state.barrier.dec(callerThread);
231 // queryProvider2.schedule(callerThread, new SessionTask(suggestSchedule) {
234 // public void run(int thread) {
236 // impl.state.barrier.inc(thread);
237 // impl.state.barrier.dec();
239 // if(info.isFunctional) {
240 // querySupport.getObjects4(impl.newAsync(thread), subjectId, proc);
242 // querySupport.getObjects4(impl.newAsync(thread), subjectId, proc);
248 // public String toString() {
259 public <C> void forEachObjectCompiled(AsyncReadGraph graph, Resource subject, C context, final AsyncContextMultiProcedure<C, Resource> procedure) {
261 assert(subject != null);
263 final ForEachObjectContextProcedure<C> proc = (ForEachObjectContextProcedure<C>)procedure;
264 final RelationInfo info = proc.info;
266 final ReadGraphImpl impl = (ReadGraphImpl)graph;
267 final int subjectId = ((ResourceImpl)subject).id;
269 // int callerThread = impl.callerThread;
270 // int suggestSchedule = (subjectId>>16) & queryProvider2.THREAD_MASK;
274 if(info.isFunctional) {
275 session.querySupport.getObjects4(impl, subjectId, context, proc);
277 session.querySupport.getObjects4(impl, subjectId, context, proc);
283 public <T> void forPossibleRelatedValueCompiled(AsyncReadGraph graph, Resource subject, final AsyncProcedure<T> procedure) {
285 assert(subject != null);
287 final ForPossibleRelatedValueProcedure<T> proc = (ForPossibleRelatedValueProcedure<T>)procedure;
288 final RelationInfo info = proc.info;
290 final ReadGraphImpl impl = (ReadGraphImpl)graph;
291 final int subjectId = ((ResourceImpl)subject).id;
293 // int callerThread = impl.callerThread;
294 // int suggestSchedule = (subjectId>>16) & session.queryProvider2.THREAD_MASK;
298 // if(callerThread == suggestSchedule) {
300 if(info.isFunctional) {
301 getRelatedValue4(impl, subjectId, proc);
303 getRelatedValue4(impl, subjectId, proc);
308 // impl.state.barrier.inc();
309 // impl.state.barrier.dec(callerThread);
311 // queryProvider2.schedule(callerThread, new SessionTask(suggestSchedule) {
314 // public void run(int thread) {
316 // impl.state.barrier.inc(thread);
317 // impl.state.barrier.dec();
319 // if(info.isFunctional) {
320 // getRelatedValue4(impl.newAsync(thread), subjectId, proc);
322 // getRelatedValue4(impl.newAsync(thread), subjectId, proc);
328 // public String toString() {
339 public <C, T> void forPossibleRelatedValueCompiled(AsyncReadGraph graph, Resource subject, C context, final AsyncContextProcedure<C, T> procedure) {
341 assert(subject != null);
343 final ForPossibleRelatedValueContextProcedure<C, T> proc = (ForPossibleRelatedValueContextProcedure<C, T>)procedure;
344 final RelationInfo info = proc.info;
346 final ReadGraphImpl impl = (ReadGraphImpl)graph;
347 final int subjectId = ((ResourceImpl)subject).id;
349 // int callerThread = impl.callerThread;
350 // int suggestSchedule = (subjectId>>16) & session.queryProvider2.THREAD_MASK;
354 if(info.isFunctional) {
355 getRelatedValue4(impl, subjectId, context, proc);
357 getRelatedValue4(impl, subjectId, context, proc);
363 public <T> void forPossibleType(final AsyncReadGraph graph, Resource subject, final AsyncProcedure<Resource> procedure) {
365 assert(subject != null);
367 final ReadGraphImpl impl = (ReadGraphImpl)graph;
368 final int subjectId = ((ResourceImpl)subject).id;
372 final ClusterI cluster = session.clusterTable.getClusterByResourceKey(subjectId);
373 if(!cluster.isLoaded()) {
375 // impl.state.inc(0);
377 session.queryProvider2.requestCluster(impl, cluster.getClusterId(), new Runnable() {
384 int result = cluster.getCompleteObjectKey(subjectId, session.clusterTranslator);
385 procedure.execute(graph, new ResourceImpl(session.resourceSupport, result));
387 // impl.state.dec(0);
389 } catch (DatabaseException e) {
399 int result = cluster.getCompleteObjectKey(subjectId, session.clusterTranslator);
400 procedure.execute(graph, new ResourceImpl(session.resourceSupport, result));
404 } catch (DatabaseException e) {
413 public <C> void forPossibleDirectType(final AsyncReadGraph graph, Resource subject, final C context, final AsyncContextProcedure<C, Resource> procedure) {
415 assert(subject != null);
417 final ReadGraphImpl impl = (ReadGraphImpl)graph;
418 final int subjectId = ((ResourceImpl)subject).id;
422 final ClusterI cluster = session.clusterTable.getClusterByResourceKey(subjectId);
423 if(!cluster.isLoaded()) {
425 // impl.state.inc(0);
427 session.queryProvider2.requestCluster(impl, cluster.getClusterId(), new Runnable() {
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));
439 procedure.execute(graph, context, null);
442 // impl.state.dec(0);
444 } catch (DatabaseException e) {
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));
459 procedure.execute(graph, context, null);
464 } catch (DatabaseException e) {
466 procedure.execute(graph, context, null);
468 } catch (Throwable t) {
471 procedure.execute(graph, context, null);
478 private <C, T> void getRelatedValue4(final ReadGraphImpl graph, final int subject, final C context, final ForPossibleRelatedValueContextProcedure<C, T> procedure) {
482 final int predicate = procedure.predicateKey;
486 if(!SessionImplSocket.areVirtualStatementsLoaded(session.virtualGraphServerSupport, subject, predicate)) {
487 SessionImplSocket.loadVirtualStatements(session.virtualGraphServerSupport, graph, subject, predicate, new Callback<ReadGraphImpl>() {
490 public void run(ReadGraphImpl graph) {
491 getRelatedValue4(graph, subject, context, procedure);
498 for(TransientGraph g : session.virtualGraphServerSupport.providers) {
499 for (int id : g.getObjects(subject, predicate)) {
501 procedure.exception(graph, new DatabaseException("Multiple objects"));
512 procedure.exception(graph, new DatabaseException("No objects for " + subject ));
518 getValue4(graph, null, result, context, procedure);
525 final org.simantics.db.procore.cluster.ClusterImpl cluster = session.clusterTable.getClusterByResourceKey(subject);
526 if(!cluster.isLoaded()) {
527 cluster.load(session.clusterTranslator, new Runnable() {
531 getRelatedValue4(graph, subject, context, procedure);
538 if(cluster.hasVirtual() && session.virtualGraphServerSupport.virtuals.contains(subject)) {
540 if(!SessionImplSocket.areVirtualStatementsLoaded(session.virtualGraphServerSupport, subject, predicate)) {
541 SessionImplSocket.loadVirtualStatements(session.virtualGraphServerSupport, graph, subject, predicate, new Callback<ReadGraphImpl>() {
544 public void run(ReadGraphImpl graph) {
545 getRelatedValue4(graph, subject, context, procedure);
552 for(TransientGraph g : session.virtualGraphServerSupport.providers) {
553 for (int id : g.getObjects(subject, predicate)) {
555 procedure.exception(graph, new DatabaseException("Multiple objects"));
564 getRelatedDirectValue4(graph, cluster, subject, result, context, procedure);
568 getRelatedDirectValue4(graph, cluster, subject, 0, context, procedure);
574 private <T> void getValue4(final ReadGraphImpl graph, final ClusterImpl containerCluster, final int subject, final ForPossibleRelatedValueProcedure<T> procedure) {
576 Object result = null;
580 if(!SessionImplSocket.areVirtualStatementsLoaded(session.virtualGraphServerSupport, subject)) {
581 SessionImplSocket.loadVirtualStatements(session.virtualGraphServerSupport, graph, subject, new Callback<ReadGraphImpl>() {
584 public void run(ReadGraphImpl graph) {
585 getValue4(graph, containerCluster, subject, procedure);
592 for(TransientGraph g : session.virtualGraphServerSupport.providers) {
593 Object value = g.getValue(subject);
596 procedure.exception(graph, new DatabaseException("Multiple values"));
605 procedure.execute(graph, (T)"name");
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() {
619 getValue4(graph, containerCluster, subject, procedure);
627 if(cluster.hasVirtual() && session.virtualGraphServerSupport.virtuals.contains(subject)) {
629 if(!SessionImplSocket.areVirtualStatementsLoaded(session.virtualGraphServerSupport, subject)) {
630 SessionImplSocket.loadVirtualStatements(session.virtualGraphServerSupport, graph, subject, new Callback<ReadGraphImpl>() {
633 public void run(ReadGraphImpl graph) {
634 getValue4(graph, containerCluster, subject, procedure);
641 for(TransientGraph g : session.virtualGraphServerSupport.providers) {
642 Object value = g.getValue(subject);
645 procedure.exception(graph, new DatabaseException("Multiple values"));
656 procedure.execute(graph, (T)result);
657 // graph.state.barrier.dec();
661 if(ClusterTypeEnum.SMALL == cluster.getType())
662 getDirectValue4(graph, (ClusterSmall)cluster, subject, procedure);
664 getDirectValue4(graph, (ClusterBig)cluster, subject, procedure);
669 if(ClusterTypeEnum.SMALL == cluster.getType())
670 getDirectValue4(graph, (ClusterSmall)cluster, subject, procedure);
672 getDirectValue4(graph, (ClusterBig)cluster, subject, procedure);
678 private <C, T> void getValue4(final ReadGraphImpl graph, final ClusterImpl containerCluster, final int subject, final C context, final ForPossibleRelatedValueContextProcedure<C, T> procedure) {
680 Object result = null;
684 if(!SessionImplSocket.areVirtualStatementsLoaded(session.virtualGraphServerSupport, subject)) {
685 SessionImplSocket.loadVirtualStatements(session.virtualGraphServerSupport, graph, subject, new Callback<ReadGraphImpl>() {
688 public void run(ReadGraphImpl graph) {
689 getValue4(graph, containerCluster, subject, context, procedure);
696 for(TransientGraph g : session.virtualGraphServerSupport.providers) {
697 Object value = g.getValue(subject);
700 procedure.exception(graph, new DatabaseException("Multiple values"));
709 procedure.execute(graph, context, (T)"name");
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() {
723 getValue4(graph, containerCluster, subject, context, procedure);
731 if(cluster.hasVirtual() && session.virtualGraphServerSupport.virtuals.contains(subject)) {
733 if(!SessionImplSocket.areVirtualStatementsLoaded(session.virtualGraphServerSupport, subject)) {
734 SessionImplSocket.loadVirtualStatements(session.virtualGraphServerSupport, graph, subject, new Callback<ReadGraphImpl>() {
737 public void run(ReadGraphImpl graph) {
738 getValue4(graph, containerCluster, subject, context, procedure);
745 for(TransientGraph g : session.virtualGraphServerSupport.providers) {
746 Object value = g.getValue(subject);
749 procedure.exception(graph, new DatabaseException("Multiple values"));
760 procedure.execute(graph, context, (T)result);
761 // graph.state.barrier.dec();
765 if(ClusterTypeEnum.SMALL == cluster.getType())
766 getDirectValue4(graph, (ClusterSmall)cluster, subject, context, procedure);
768 getDirectValue4(graph, (ClusterBig)cluster, subject, context, procedure);
773 if(ClusterTypeEnum.SMALL == cluster.getType())
774 getDirectValue4(graph, (ClusterSmall)cluster, subject, context, procedure);
776 getDirectValue4(graph, (ClusterBig)cluster, subject, context, procedure);
782 private <T> void getRelatedDirectValue4(final ReadGraphImpl graph, final ClusterImpl cluster, final int subject, final int result, final ForPossibleRelatedValueProcedure<T> procedure) {
786 int so = cluster.getSingleObject(subject, procedure, session.clusterTranslator);
789 procedure.exception(graph, new DatabaseException("No objects " + subject + " " + procedure.predicateKey));
792 getValue4(graph, cluster, result, procedure);
796 getValue4(graph, cluster, so, procedure);
798 procedure.exception(graph, new DatabaseException("Multiple objects"));
803 } catch (DatabaseException e) {
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) {
813 int so = cluster.getSingleObject(subject, procedure, session.clusterTranslator);
816 procedure.exception(graph, new DatabaseException("No objects " + subject + " " + procedure.predicateKey));
819 getValue4(graph, cluster, result, context, procedure);
823 getValue4(graph, cluster, so, context, procedure);
825 procedure.exception(graph, new DatabaseException("Multiple objects"));
830 } catch (DatabaseException e) {
836 public <T> void getRelatedValue4(final ReadGraphImpl graph, final int subject, final ForPossibleRelatedValueProcedure<T> procedure) {
840 final int predicate = procedure.predicateKey;
844 if(!SessionImplSocket.areVirtualStatementsLoaded(session.virtualGraphServerSupport, subject, predicate)) {
845 SessionImplSocket.loadVirtualStatements(session.virtualGraphServerSupport, graph, subject, predicate, new Callback<ReadGraphImpl>() {
848 public void run(ReadGraphImpl graph) {
849 getRelatedValue4(graph, subject, procedure);
856 for(TransientGraph g : session.virtualGraphServerSupport.providers) {
857 for (int id : g.getObjects(subject, predicate)) {
859 procedure.exception(graph, new DatabaseException("Multiple objects"));
870 procedure.exception(graph, new DatabaseException("No objects for " + subject ));
876 getValue4(graph, null, result, procedure);
883 final org.simantics.db.procore.cluster.ClusterImpl cluster = session.clusterTable.getClusterByResourceKey(subject);
884 if(!cluster.isLoaded()) {
885 cluster.load(session.clusterTranslator, new Runnable() {
889 getRelatedValue4(graph, subject, procedure);
896 if(cluster.hasVirtual() && session.virtualGraphServerSupport.virtuals.contains(subject)) {
898 if(!SessionImplSocket.areVirtualStatementsLoaded(session.virtualGraphServerSupport, subject, predicate)) {
899 SessionImplSocket.loadVirtualStatements(session.virtualGraphServerSupport, graph, subject, predicate, new Callback<ReadGraphImpl>() {
902 public void run(ReadGraphImpl graph) {
903 getRelatedValue4(graph, subject, procedure);
910 for(TransientGraph g : session.virtualGraphServerSupport.providers) {
911 for (int id : g.getObjects(subject, predicate)) {
913 procedure.exception(graph, new DatabaseException("Multiple objects"));
922 getRelatedDirectValue4(graph, cluster, subject, result, procedure);
926 getRelatedDirectValue4(graph, cluster, subject, 0, procedure);
932 private <C, T> void getDirectValue4(final ReadGraphImpl graph, final ClusterSmall cluster, final int subject, final C context, final ForPossibleRelatedValueContextProcedure<C, T> procedure) {
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);
946 private <T> void getDirectValue4(final ReadGraphImpl graph, final ClusterBig cluster, final int subject, final ForPossibleRelatedValueProcedure<T> procedure) {
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);
960 private <C, T> void getDirectValue4(final ReadGraphImpl graph, final ClusterBig cluster, final int subject, final C context, final ForPossibleRelatedValueContextProcedure<C, T> procedure) {
963 byte[] bytes = cluster.getValue(subject, session.clusterTranslator);
965 procedure.execute(graph, context, null);
967 T value = (T)utf(bytes);
968 procedure.execute(graph, context, value);
970 } catch (DatabaseException e) {
971 procedure.execute(graph, context, null);
978 private final char[] chars = new char[1024];
980 private <T> void getDirectValue4(final ReadGraphImpl graph, final ClusterSmall cluster, final int subject, final ForPossibleRelatedValueProcedure<T> procedure) {
982 ResourceTableSmall rt = cluster.resourceTable;
983 ValueTableSmall vt = cluster.valueTable;
985 byte[] bs = vt.table;
986 long[] ls = rt.table;
988 int index = ((subject&0xFFFF) << 1) - 1 + rt.offset;
990 int valueIndex = (int)(ls[index] >>> 24) & 0x3FFFFF + vt.offset;
992 int size = (int)bs[valueIndex++]-1;
994 for(int i=0;i<size;i++) {
995 chars[i] = (char)bs[valueIndex++];
998 T value = (T)new String(chars, 0, size);
1000 procedure.execute(graph, value);
1005 final private String utf(byte[] bytes) {
1007 if(bytes == null) return null;
1010 int length = bytes[index++]&0xff;
1011 if(length >= 0x80) {
1012 if(length >= 0xc0) {
1013 if(length >= 0xe0) {
1014 if(length >= 0xf0) {
1016 length += ((bytes[index++]&0xff)<<3);
1017 length += ((bytes[index++]&0xff)<<11);
1018 length += ((bytes[index++]&0xff)<<19);
1019 length += 0x10204080;
1023 length += ((bytes[index++]&0xff)<<4);
1024 length += ((bytes[index++]&0xff)<<12);
1025 length += ((bytes[index++]&0xff)<<20);
1031 length += ((bytes[index++]&0xff)<<5);
1032 length += ((bytes[index++]&0xff)<<13);
1038 length += ((bytes[index++]&0xff)<<6);
1044 int target = length+index;
1045 while(index < target) {
1046 int c = bytes[index++]&0xff;
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));
1054 int c2 = bytes[index++]&0xff;
1055 chars[i++] = (char)(((c&0x1f)<<6) + (c2&0x3f));
1059 // if (!((c >= 0x0001) && (c <= 0x007F))) {
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));
1070 // bytearr[byteIndex++] = (byte)(0xC0 | ((c >> 6) & 0x1F));
1071 // bytearr[byteIndex++] = (byte)(0x80 | ((c >> 0) & 0x3F));
1077 return new String(chars, 0, i);