New splash.bmp with version 1.36.0
[simantics/platform.git] / bundles / org.simantics.db.impl / src / org / simantics / db / impl / graph / ReadGraphImpl.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management
3  * in Industry THTH ry.
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * which accompanies this distribution, and is available at
7  * http://www.eclipse.org/legal/epl-v10.html
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.db.impl.graph;
13
14 import java.io.BufferedOutputStream;
15 import java.io.File;
16 import java.io.FileOutputStream;
17 import java.io.IOException;
18 import java.io.PrintStream;
19 import java.lang.reflect.Array;
20 import java.lang.reflect.InvocationTargetException;
21 import java.nio.BufferUnderflowException;
22 import java.util.ArrayList;
23 import java.util.Collection;
24 import java.util.Collections;
25 import java.util.IdentityHashMap;
26 import java.util.Iterator;
27 import java.util.List;
28 import java.util.ListIterator;
29 import java.util.Set;
30 import java.util.function.Consumer;
31
32 import org.eclipse.core.runtime.Platform;
33 import org.simantics.databoard.Accessors;
34 import org.simantics.databoard.Bindings;
35 import org.simantics.databoard.accessor.Accessor;
36 import org.simantics.databoard.accessor.error.AccessorConstructionException;
37 import org.simantics.databoard.adapter.AdaptException;
38 import org.simantics.databoard.binding.Binding;
39 import org.simantics.databoard.binding.error.RuntimeBindingConstructionException;
40 import org.simantics.databoard.binding.impl.ObjectVariantBinding;
41 import org.simantics.databoard.binding.mutable.Variant;
42 import org.simantics.databoard.serialization.Serializer;
43 import org.simantics.databoard.type.Datatype;
44 import org.simantics.databoard.util.binary.BinaryFile;
45 import org.simantics.databoard.util.binary.RandomAccessBinary;
46 import org.simantics.db.AsyncReadGraph;
47 import org.simantics.db.DevelopmentKeys;
48 import org.simantics.db.ExternalValueSupport;
49 import org.simantics.db.ReadGraph;
50 import org.simantics.db.RelationContext;
51 import org.simantics.db.Resource;
52 import org.simantics.db.Session;
53 import org.simantics.db.Statement;
54 import org.simantics.db.adaption.AdaptionService;
55 import org.simantics.db.common.primitiverequest.Adapter;
56 import org.simantics.db.common.primitiverequest.Builtin;
57 import org.simantics.db.common.primitiverequest.DatatypeBinding;
58 import org.simantics.db.common.primitiverequest.ForEachAssertedObject;
59 import org.simantics.db.common.primitiverequest.ForEachAssertedStatement;
60 import org.simantics.db.common.primitiverequest.HasStatement;
61 import org.simantics.db.common.primitiverequest.HasStatementSubject;
62 import org.simantics.db.common.primitiverequest.HasStatementSubjectObject;
63 import org.simantics.db.common.primitiverequest.HasValue;
64 import org.simantics.db.common.primitiverequest.Inverse;
65 import org.simantics.db.common.primitiverequest.IsInheritedFrom;
66 import org.simantics.db.common.primitiverequest.IsInstanceOf;
67 import org.simantics.db.common.primitiverequest.IsSubrelationOf;
68 import org.simantics.db.common.primitiverequest.OrderedSet;
69 import org.simantics.db.common.primitiverequest.PossibleAdapter;
70 import org.simantics.db.common.primitiverequest.PossibleInverse;
71 import org.simantics.db.common.primitiverequest.PossibleObject;
72 import org.simantics.db.common.primitiverequest.PossibleRelatedValue;
73 import org.simantics.db.common.primitiverequest.PossibleRelatedValueImplied;
74 import org.simantics.db.common.primitiverequest.PossibleStatement;
75 import org.simantics.db.common.primitiverequest.PossibleType;
76 import org.simantics.db.common.primitiverequest.PossibleUniqueAdapter;
77 import org.simantics.db.common.primitiverequest.PossibleValue;
78 import org.simantics.db.common.primitiverequest.PossibleValueImplied;
79 import org.simantics.db.common.primitiverequest.RelatedValue;
80 import org.simantics.db.common.primitiverequest.RelatedValueImplied;
81 import org.simantics.db.common.primitiverequest.SingleObject;
82 import org.simantics.db.common.primitiverequest.SingleStatement;
83 import org.simantics.db.common.primitiverequest.SingleType;
84 import org.simantics.db.common.primitiverequest.SingleTypeAny;
85 import org.simantics.db.common.primitiverequest.Types;
86 import org.simantics.db.common.primitiverequest.UniqueAdapter;
87 import org.simantics.db.common.primitiverequest.Value;
88 import org.simantics.db.common.primitiverequest.ValueImplied;
89 import org.simantics.db.common.primitiverequest.VariantValueImplied;
90 import org.simantics.db.common.procedure.adapter.AsyncMultiProcedureAdapter;
91 import org.simantics.db.common.procedure.adapter.ProcedureAdapter;
92 import org.simantics.db.common.procedure.adapter.TransientCacheAsyncListener;
93 import org.simantics.db.common.procedure.adapter.TransientCacheListener;
94 import org.simantics.db.common.procedure.single.SyncReadProcedure;
95 import org.simantics.db.common.procedure.single.wrapper.DeepSingleOrErrorProcedure;
96 import org.simantics.db.common.procedure.single.wrapper.DeepSingleOrNullProcedure;
97 import org.simantics.db.common.procedure.single.wrapper.ExceptionToNullProcedure;
98 import org.simantics.db.common.procedure.single.wrapper.NullSingleOrNullProcedure;
99 import org.simantics.db.common.procedure.single.wrapper.SingleFunctionalOrNullProcedure;
100 import org.simantics.db.common.procedure.single.wrapper.SingleOrErrorProcedure;
101 import org.simantics.db.common.procedure.single.wrapper.SingleOrNullProcedure;
102 import org.simantics.db.common.procedure.wrapper.NoneToAsyncListener;
103 import org.simantics.db.common.procedure.wrapper.NoneToAsyncMultiListener;
104 import org.simantics.db.common.procedure.wrapper.NoneToAsyncMultiProcedure;
105 import org.simantics.db.common.procedure.wrapper.NoneToAsyncProcedure;
106 import org.simantics.db.common.procedure.wrapper.NoneToAsyncSetProcedure;
107 import org.simantics.db.common.procedure.wrapper.SyncToAsyncListener;
108 import org.simantics.db.common.procedure.wrapper.SyncToAsyncMultiListener;
109 import org.simantics.db.common.procedure.wrapper.SyncToAsyncMultiProcedure;
110 import org.simantics.db.common.procedure.wrapper.SyncToAsyncProcedure;
111 import org.simantics.db.common.procedure.wrapper.SyncToAsyncSetProcedure;
112 import org.simantics.db.common.request.AdaptValue;
113 import org.simantics.db.common.request.ResourceRead;
114 import org.simantics.db.common.utils.Logger;
115 import org.simantics.db.common.utils.NameUtils;
116 import org.simantics.db.common.validation.L0Validations;
117 import org.simantics.db.exception.AdaptionException;
118 import org.simantics.db.exception.ArgumentException;
119 import org.simantics.db.exception.AssumptionException;
120 import org.simantics.db.exception.BindingException;
121 import org.simantics.db.exception.DatabaseException;
122 import org.simantics.db.exception.DoesNotContainValueException;
123 import org.simantics.db.exception.EmptyResourceException;
124 import org.simantics.db.exception.InternalException;
125 import org.simantics.db.exception.InvalidLiteralException;
126 import org.simantics.db.exception.ManyObjectsForFunctionalRelationException;
127 import org.simantics.db.exception.NoInverseException;
128 import org.simantics.db.exception.NoSingleResultException;
129 import org.simantics.db.exception.ResourceNotFoundException;
130 import org.simantics.db.exception.ServiceException;
131 import org.simantics.db.exception.ValidationException;
132 import org.simantics.db.impl.RelationContextImpl;
133 import org.simantics.db.impl.ResourceImpl;
134 import org.simantics.db.impl.internal.RandomAccessValueSupport;
135 import org.simantics.db.impl.internal.ResourceData;
136 import org.simantics.db.impl.procedure.CallWrappedSingleQueryProcedure4;
137 import org.simantics.db.impl.procedure.ResultCallWrappedQueryProcedure4;
138 import org.simantics.db.impl.procedure.ResultCallWrappedSingleQueryProcedure4;
139 import org.simantics.db.impl.query.CacheEntry;
140 import org.simantics.db.impl.query.QueryProcessor;
141 import org.simantics.db.impl.query.QuerySupport;
142 import org.simantics.db.impl.query.TripleIntProcedure;
143 import org.simantics.db.impl.support.ResourceSupport;
144 import org.simantics.db.procedure.AsyncListener;
145 import org.simantics.db.procedure.AsyncMultiListener;
146 import org.simantics.db.procedure.AsyncMultiProcedure;
147 import org.simantics.db.procedure.AsyncProcedure;
148 import org.simantics.db.procedure.AsyncSetListener;
149 import org.simantics.db.procedure.Listener;
150 import org.simantics.db.procedure.ListenerBase;
151 import org.simantics.db.procedure.MultiListener;
152 import org.simantics.db.procedure.MultiProcedure;
153 import org.simantics.db.procedure.Procedure;
154 import org.simantics.db.procedure.SetListener;
155 import org.simantics.db.procedure.StatementProcedure;
156 import org.simantics.db.procedure.SyncListener;
157 import org.simantics.db.procedure.SyncMultiListener;
158 import org.simantics.db.procedure.SyncMultiProcedure;
159 import org.simantics.db.procedure.SyncProcedure;
160 import org.simantics.db.procedure.SyncSetListener;
161 import org.simantics.db.request.AsyncMultiRead;
162 import org.simantics.db.request.AsyncRead;
163 import org.simantics.db.request.DelayedWrite;
164 import org.simantics.db.request.DelayedWriteResult;
165 import org.simantics.db.request.ExternalRead;
166 import org.simantics.db.request.MultiRead;
167 import org.simantics.db.request.Read;
168 import org.simantics.db.request.ReadInterface;
169 import org.simantics.db.request.RequestFlags;
170 import org.simantics.db.request.Write;
171 import org.simantics.db.request.WriteInterface;
172 import org.simantics.db.request.WriteOnly;
173 import org.simantics.db.request.WriteOnlyResult;
174 import org.simantics.db.request.WriteResult;
175 import org.simantics.layer0.Layer0;
176 import org.simantics.scl.compiler.types.Type;
177 import org.simantics.scl.compiler.types.exceptions.SCLTypeParseException;
178 import org.simantics.scl.reflection.ReflectionUtils;
179 import org.simantics.scl.reflection.ValueNotFoundException;
180 import org.simantics.scl.runtime.function.Function3;
181 import org.simantics.utils.DataContainer;
182 import org.simantics.utils.Development;
183 import org.simantics.utils.datastructures.Pair;
184 import org.simantics.utils.datastructures.collections.CollectionUtils;
185
186 import gnu.trove.map.hash.TObjectIntHashMap;
187
188 public class ReadGraphImpl implements ReadGraph {
189
190     final static boolean EMPTY_RESOURCE_CHECK = false;
191     
192         final public CacheEntry parent;
193         final public QueryProcessor processor;
194         
195         final static Binding DATA_TYPE_BINDING_INTERNAL = Bindings.getBindingUnchecked(Datatype.class);
196         final static Serializer DATA_TYPE_SERIALIZER = Bindings.getSerializerUnchecked(DATA_TYPE_BINDING_INTERNAL);
197
198         final public static TObjectIntHashMap<String> counters = new TObjectIntHashMap<String>(); 
199         
200         public static void resetCounters() {
201                 counters.clear();
202         }
203         
204         public static String listCounters(File file) throws IOException {
205                 
206                 PrintStream b = new PrintStream(new BufferedOutputStream(new FileOutputStream(file)));
207
208                 for(Pair<String,Integer> p : CollectionUtils.valueSortedEntries(counters)) {
209                         b.print(-p.second + " " + p.first + "\n");
210                 }
211
212                 b.close();
213
214                 return "Dumped " + counters.size() + " queries.";
215                 
216         }
217         
218         /*
219          * Implementation of the interface ReadGraph
220          */
221         final public String getURI(final Resource resource)     throws AssumptionException, ValidationException, ServiceException {
222                 
223                 assert (resource != null);
224
225                 try {
226
227                         return syncRequest(new org.simantics.db.common.uri.ResourceToURI(resource));
228
229                 } catch (AssumptionException e) {
230
231                         throw new AssumptionException(e);
232
233                 } catch (ValidationException e) {
234
235                         throw new ValidationException(e);
236
237                 } catch (ServiceException e) {
238
239                         throw new ServiceException(e);
240
241                 } catch (DatabaseException e) {
242
243                         throw new ServiceException(INTERNAL_ERROR_STRING, e);
244
245                 }
246
247         }
248         
249         final public String getPossibleURI(final Resource resource)     throws ValidationException,     ServiceException {
250
251                 assert (resource != null);
252
253                 try {
254
255                         return syncRequest(new org.simantics.db.common.uri.ResourceToPossibleURI(resource));
256
257                 } catch (ValidationException e) {
258
259                         throw new ValidationException(e);
260
261                 } catch (ServiceException e) {
262
263                         throw new ServiceException(e);
264
265                 } catch (DatabaseException e) {
266
267                         throw new ServiceException(INTERNAL_ERROR_STRING, e);
268
269                 }
270
271         }
272
273         final public Resource getResource(final String id)
274                         throws ResourceNotFoundException, ValidationException,
275                         ServiceException {
276
277                 assert (id != null);
278
279                 try {
280
281                         return syncRequest(new org.simantics.db.common.primitiverequest.Resource(
282                                         id));
283
284                 } catch (ResourceNotFoundException e) {
285
286                         throw new ResourceNotFoundException(id, e);
287
288                 } catch (ValidationException e) {
289
290                         throw new ValidationException(e);
291
292                 } catch (ServiceException e) {
293
294                         throw new ServiceException(e);
295
296                 } catch (DatabaseException e) {
297
298                         throw new ServiceException(INTERNAL_ERROR_STRING, e);
299
300                 }
301
302         }
303
304         final public Resource getPossibleResource(final String id)
305         throws ResourceNotFoundException, ValidationException,
306         ServiceException {
307
308                 assert (id != null);
309
310                 try {
311
312                         return syncRequest(new org.simantics.db.common.primitiverequest.Resource(
313                                         id));
314
315                 } catch (ResourceNotFoundException e) {
316                         
317                         return null;
318
319                 } catch (ValidationException e) {
320
321                         throw new ValidationException(e);
322
323                 } catch (ServiceException e) {
324
325                         throw new ServiceException(e);
326
327                 } catch (DatabaseException e) {
328
329                         throw new ServiceException(INTERNAL_ERROR_STRING, e);
330
331                 }
332
333         }
334
335         final public Resource getRootLibrary() {
336                 return processor.getRootLibraryResource();
337         }
338         
339         final public Resource getBuiltin(final String id)
340                         throws ResourceNotFoundException, ServiceException {
341
342                 assert (id != null);
343
344                 try {
345
346                         return syncRequest(new Builtin(id));
347
348                 } catch (ResourceNotFoundException e) {
349
350                         throw new ResourceNotFoundException(id, e);
351
352                 } catch (ServiceException e) {
353
354                         throw new ServiceException(e);
355
356                 } catch (DatabaseException e) {
357
358                         throw new ServiceException(INTERNAL_ERROR_STRING, e);
359
360                 }
361
362         }
363
364         static class StatementReadProcedure extends TIntArrayListInternal implements StatementProcedure {
365
366                 private static Throwable DONE = new Throwable();
367                 
368                 Throwable exception = null;
369                 
370                 final ResourceSupport support;
371                 
372                 public StatementReadProcedure(ResourceSupport support) {
373                         this.support = support;
374                 }
375                 
376                 @Override
377                 public synchronized void execute(AsyncReadGraph graph, int s, int p, int o) {
378                         add(s);
379                         add(p);
380                         add(o);
381                 }
382                 
383                 @Override
384                 public void finished(AsyncReadGraph graph) {
385                         exception = DONE;
386                 }
387
388                 @Override
389                 public void exception(AsyncReadGraph graph, Throwable t) {
390                         exception = t;
391                 }
392                 
393                 public void checkAndThrow() throws DatabaseException {
394                         if(exception != DONE) {
395                                 if (exception instanceof DatabaseException)
396                                         throw (DatabaseException) exception;
397                                 else
398                                         throw new DatabaseException(
399                                                         "Unexpected exception in ReadGraph.syncRequest(AsyncMultiRead)",
400                                                         exception);
401                         }
402                 }
403                 
404                 public boolean done() {
405                         return exception != null;
406                 }
407
408                 @Override
409                 public boolean contains(Object obj) {
410                     if(!(obj instanceof InternalStatement))
411                         return false;
412                     InternalStatement statement = (InternalStatement)obj;
413                     int s = statement.s;
414                     int p = statement.p;
415                     int o = statement.o;
416                     for(int i=0;i<sizeInternal();i+=3)
417                 if(s==getQuick(i) && p==getQuick(i+1) && o==getQuick(i+2))
418                     return true;
419                     return false;
420                 }
421
422                 @SuppressWarnings("unchecked")
423         @Override
424                 public <T> T[] toArray(T[] a) {
425                     int length = sizeInternal() / 3;
426                     if(length > a.length) {
427                         Class<?> arrayType = a.getClass();
428                         a = (arrayType == Object[].class) 
429                                 ? (T[]) new Object[length]
430                                 : (T[]) Array.newInstance(arrayType.getComponentType(), length);
431                     }
432                     else {
433                         for(int i=length;i<a.length;++i)
434                             a[i] = null;
435                     }
436             for(int i=0,j=0;i<sizeInternal();i+=3,++j)
437                 a[j] = (T)new InternalStatement(support, getQuick(i), getQuick(i+1), getQuick(i+2));
438             return a;
439                 }
440
441                 @Override
442                 public boolean add(Statement e) {
443                         throw new UnsupportedOperationException();
444                 }
445
446                 @Override
447                 public boolean remove(Object o) {
448                         throw new UnsupportedOperationException();
449                 }
450
451                 @Override
452                 public boolean addAll(Collection<? extends Statement> c) {
453                         throw new UnsupportedOperationException();
454                 }
455
456                 class IteratorImpl implements ListIterator<Statement> {
457             
458             int index;
459             
460             public IteratorImpl(int index) {
461                 this.index = index;
462             }
463
464             @Override
465             public boolean hasNext() {
466                 return index < sizeInternal(); 
467             }
468
469             @Override
470             public Statement next() {
471                 Statement result = new InternalStatement(support, getQuick(index), getQuick(index+1), getQuick(index+2)); 
472                 index += 3;
473                 return result;
474             }
475
476             @Override
477             public void remove() {
478                 throw new Error("Not supported");
479             }
480
481             @Override
482             public boolean hasPrevious() {
483                 return index > 0;
484             }
485
486             @Override
487             public Statement previous() {
488                 index -= 3;
489                 Statement result = new InternalStatement(support, getQuick(index), getQuick(index+1), getQuick(index+2)); 
490                 return result;
491             }
492
493             @Override
494             public int nextIndex() {
495                 return index/3;
496             }
497
498             @Override
499             public int previousIndex() {
500                 return index/3-1;
501             }
502
503             @Override
504             public void set(Statement e) {
505                 throw new UnsupportedOperationException();
506             }
507
508             @Override
509             public void add(Statement e) {
510                 throw new UnsupportedOperationException();
511             }
512             
513         };
514         
515                 @Override
516                 public Iterator<Statement> iterator() {
517                         return new IteratorImpl(0);
518                 }
519                 
520                 @Override
521                 public int size() {
522                         return sizeInternal() / 3;
523                 }
524
525                 @Override
526                 public Object[] toArray() {
527                     Object[] result = new Object[sizeInternal() / 3];
528                     for(int i=0,j=0;j<sizeInternal();i++,j+=3)
529                         result[i] = new InternalStatement(support, getQuick(j), getQuick(j+1), getQuick(j+2));
530                         return result;
531                 }
532
533         @Override
534         public boolean addAll(int index, Collection<? extends Statement> c) {
535             throw new UnsupportedOperationException();
536         }
537
538         @Override
539         public Statement get(int index) {
540             index += 3;
541             if(index < 0 || index >= sizeInternal())
542                 throw new IndexOutOfBoundsException();
543             return new InternalStatement(support, getQuick(index), getQuick(index+1), getQuick(index+2));
544         }
545
546         @Override
547         public Statement set(int index, Statement element) {
548             throw new UnsupportedOperationException();
549         }
550
551         @Override
552         public void add(int index, Statement element) {
553             throw new UnsupportedOperationException();
554         }
555
556         @Override
557         public Statement remove(int index) {
558             throw new UnsupportedOperationException();
559         }
560
561         @Override
562         public int indexOf(Object obj) {
563             if(!(obj instanceof InternalStatement))
564                 return -1;
565             InternalStatement statement = (InternalStatement)obj;
566             int s = statement.s;
567             int p = statement.p;
568             int o = statement.o;
569             for(int i=0;i<sizeInternal();i+=3)
570                 if(s==getQuick(i) && p==getQuick(i+1) && o==getQuick(i+2))
571                     return i/3;
572             return -1;
573         }
574
575         @Override
576         public int lastIndexOf(Object obj) {
577             if(!(obj instanceof InternalStatement))
578                 return -1;
579             InternalStatement statement = (InternalStatement)obj;
580             int s = statement.s;
581             int p = statement.p;
582             int o = statement.o;
583             for(int i=sizeInternal()-3;i>=0;i-=3)
584                 if(s==getQuick(i) && p==getQuick(i+1) && o==getQuick(i+2))
585                     return i/3;
586             return -1;
587         }
588
589         @Override
590         public ListIterator<Statement> listIterator() {
591             return new IteratorImpl(0);
592         }
593
594         @Override
595         public ListIterator<Statement> listIterator(int index) {
596             return new IteratorImpl(index*3);
597         }
598
599         @Override
600         public List<Statement> subList(int fromIndex, int toIndex) {
601             if(fromIndex < 0 || toIndex*3 >= sizeInternal() || fromIndex > toIndex)
602                 throw new IndexOutOfBoundsException();
603             return new RandomAccessSubList<Statement>(this, fromIndex, toIndex-fromIndex);
604         }
605         }
606         
607         @Override
608         final public Collection<Statement> getStatements(final Resource subject,
609                         final Resource relation)
610                         throws ManyObjectsForFunctionalRelationException, ServiceException {
611
612                 assert (subject != null);
613                 assert (relation != null);
614
615                 try {
616
617                         StatementReadProcedure procedure = new StatementReadProcedure(getResourceSupport());
618                         processor.forEachStatement(this, subject, relation, procedure);
619                         procedure.checkAndThrow();
620                         return procedure;
621                         
622                 } catch (DatabaseException e) {
623
624                         System.err.println(INTERNAL_ERROR_STRING + " getStatements " + subject + " " + relation);
625
626                         StatementReadProcedure procedure = new StatementReadProcedure(getResourceSupport());
627                         processor.forEachStatement(this, subject, relation, procedure);
628                         
629                         return Collections.emptyList();
630                 
631 //                      throw new ServiceException(INTERNAL_ERROR_STRING + " getStatements " + subject + " " + relation, e);
632
633                 }
634
635         }
636
637         @Override
638         final public Collection<Statement> getAssertedStatements(final Resource subject, final Resource relation)
639                         throws ManyObjectsForFunctionalRelationException, ServiceException {
640
641                 assert (subject != null);
642                 assert (relation != null);
643
644                 try {
645
646                         return syncRequest(new ForEachAssertedStatement(subject, relation));
647
648                 } catch (ManyObjectsForFunctionalRelationException e) {
649
650                         throw new ManyObjectsForFunctionalRelationException(e);
651
652                 } catch (ServiceException e) {
653
654                         throw new ServiceException(e);
655
656                 } catch (DatabaseException e) {
657
658                         throw new ServiceException(INTERNAL_ERROR_STRING, e);
659
660                 }
661
662         }
663
664         @Override
665         final public Collection<Resource> getPredicates(final Resource subject) throws ServiceException {
666
667                 assert (subject != null);
668
669                 try {
670
671                         return processor.getPredicates(this, subject);
672
673 //                      AsyncMultiReadProcedure<Resource> procedure = new AsyncMultiReadProcedure<Resource>();
674 //                      processor.forEachPredicate(this, subject, procedure);
675 //                      procedure.checkAndThrow();
676 //                      return procedure;
677
678                 } catch (ServiceException e) {
679
680                         throw new ServiceException(e);
681
682                 } catch (DatabaseException e) {
683
684                         throw new ServiceException(INTERNAL_ERROR_STRING, e);
685
686                 }  catch (Throwable e) {
687
688             throw new ServiceException(e);
689
690                 }
691
692         }
693
694         @Override
695         final public Collection<Resource> getPrincipalTypes(final Resource subject)
696                         throws ServiceException {
697
698                 assert (subject != null);
699
700                 try {
701
702                         AsyncMultiReadProcedure<Resource> procedure = new AsyncMultiReadProcedure<Resource>();
703                         processor.forEachPrincipalType(this, subject, procedure);
704                         procedure.checkAndThrow();
705                         return procedure;
706                         
707                 } catch (ServiceException e) {
708
709                         throw new ServiceException(e);
710
711                 } catch (DatabaseException e) {
712
713                         throw new ServiceException(INTERNAL_ERROR_STRING, e);
714
715                 }
716
717         }
718
719         @Override
720         final public Set<Resource> getTypes(final Resource subject) throws ServiceException {
721
722                 assert (subject != null);
723
724                 try {
725                         
726                         return processor.getTypes(this, subject);
727                         
728                 } catch (ServiceException e) {
729
730                         throw new ServiceException(e);
731                         
732                 } catch (DatabaseException e) {
733
734                         throw new ServiceException(INTERNAL_ERROR_STRING, e);
735
736         } catch (Throwable e) {
737
738             throw new ServiceException(e);
739
740                 }
741
742         }
743
744         @Override
745         final public Set<Resource> getSupertypes(final Resource subject)
746                         throws ServiceException {
747
748                 assert (subject != null);
749
750                 try {
751
752                         SyncReadProcedure<Set<Resource>> procedure = new SyncReadProcedure<Set<Resource>>();
753                         processor.forSupertypes(this, subject, procedure);
754                         procedure.checkAndThrow();
755                         return procedure.result;
756
757                 } catch (ServiceException e) {
758
759                         throw new ServiceException(e);
760
761                 } catch (DatabaseException e) {
762
763                         throw new ServiceException(INTERNAL_ERROR_STRING, e);
764
765                 }
766
767         }
768
769         @Override
770         final public Set<Resource> getSuperrelations(final Resource subject)
771                         throws ServiceException {
772
773                 assert (subject != null);
774
775                 try {
776
777                         SyncReadProcedure<Set<Resource>> procedure = new SyncReadProcedure<Set<Resource>>();
778                         processor.forSuperrelations(this, subject, procedure);
779                         procedure.checkAndThrow();
780                         return procedure.result;
781
782                 } catch (ServiceException e) {
783
784                         throw new ServiceException(e);
785
786                 } catch (DatabaseException e) {
787
788                         throw new ServiceException(INTERNAL_ERROR_STRING, e);
789
790                 }
791
792         }
793         
794         @Override
795         public Resource getPossibleSuperrelation(Resource subject) throws ServiceException {
796                 
797                 try {
798
799                         SyncReadProcedure<Resource> procedure = new SyncReadProcedure<Resource>();
800                         processor.forPossibleSuperrelation(this, subject, procedure);
801                         procedure.checkAndThrow();
802                         return procedure.result;
803
804                 } catch (ServiceException e) {
805
806                         throw new ServiceException(e);
807
808                 } catch (DatabaseException e) {
809
810                         throw new ServiceException(INTERNAL_ERROR_STRING, e);
811
812                 }
813
814         }
815
816         @Override
817         final public Collection<Resource> getObjects(final Resource subject, final Resource relation)
818                         throws ServiceException {
819
820                 assert (subject != null);
821                 assert (relation != null);
822
823                 if(Development.DEVELOPMENT) {
824             if(Development.isTrue(DevelopmentKeys.READGRAPH_COUNT)) {
825                 counters.adjustOrPutValue("objects $" + subject.getResourceId() + " $" + relation.getResourceId(), 1, 1);
826             }
827             //if(subject.getResourceId()==xx && relation.getResourceId()==xx) new Exception().printStackTrace();
828                 }
829                 
830                 try {
831
832                         AsyncMultiReadProcedure<Resource> procedure = new AsyncMultiReadProcedure<Resource>();
833                         processor.forEachObject(this, subject, relation, procedure);
834                         procedure.checkAndThrow();
835                         return procedure;
836                         
837                 } catch (DatabaseException e) {
838
839                         throw new ServiceException(INTERNAL_ERROR_STRING, e);
840
841                 }
842
843         }
844
845         @Override
846         final public Collection<Resource> getAssertedObjects(
847                         final Resource subject, final Resource relation)
848                         throws ManyObjectsForFunctionalRelationException, ServiceException {
849
850         if (subject == null)
851             throw new ArgumentException("Subject must not be null.");
852         if (relation == null)
853             throw new ArgumentException("Relation must not be null. Subject=" + subject);
854
855                 try {
856
857                         return syncRequest(new ForEachAssertedObject(subject, relation));
858
859                 } catch (ManyObjectsForFunctionalRelationException e) {
860
861                         throw new ManyObjectsForFunctionalRelationException(e);
862
863                 } catch (ServiceException e) {
864
865                         throw new ServiceException(e);
866
867                 } catch (DatabaseException e) {
868
869                         throw new ServiceException(INTERNAL_ERROR_STRING, e);
870
871                 }
872
873         }
874
875         @Override
876         final public Resource getInverse(final Resource relation) throws NoInverseException, ServiceException {
877
878                 assert (relation != null);
879
880                 try {
881
882                         return getSingleObject(relation, processor.querySupport.getResource(processor.getInverseOf()));
883
884                 } catch (NoSingleResultException e) {
885
886                         throw new NoInverseException(e);
887
888                 } catch (ServiceException e) {
889
890                         throw new ServiceException(e);
891
892                 }
893
894         }
895
896         @Override
897         final public Resource getSingleObject(final Resource subject, final Resource relation) throws NoSingleResultException, ServiceException {
898
899                 if( subject == null) throw new IllegalArgumentException("subject can not be null");
900                 if( relation == null) throw new IllegalArgumentException("relation can not be null");
901
902                 try {
903                         int single = processor.getSingleObject(this, subject, relation);
904                         if (single == 0) {
905                                 if (EMPTY_RESOURCE_CHECK) {
906                                         if (!hasStatement(subject)) {
907                                                 throw new EmptyResourceException("Resource " + debugString(subject));
908                                         }
909                                 }
910                                 throw new NoSingleResultException("No single object for subject " + debugString(subject)
911                                                 + " and relation " + debugString(relation), single);
912                         }
913                         return processor.querySupport.getResource(single);
914                 } catch (NoSingleResultException e) {
915                         throw e;
916                 } catch (DatabaseException e) {
917                         throw new ServiceException(e);
918                 } 
919         }
920
921         @Override
922         final public Statement getSingleStatement(final Resource subject, final Resource relation) throws NoSingleResultException, ManyObjectsForFunctionalRelationException, ServiceException {
923                 assert (subject != null);
924                 assert (relation != null);
925                 try {
926                         Collection<Statement> statements = getStatements(subject, relation);
927                         if (statements.size() == 1) {
928                                 return statements.iterator().next();
929                         } else {
930                                 if (EMPTY_RESOURCE_CHECK)
931                                         if (!hasStatement(subject))
932                                                 throw new EmptyResourceException("Resource " + debugString(subject));
933                                 throw new NoSingleResultException("No single statement for subject " + debugString(subject)
934                                                 + " and relation " + debugString(relation), statements.size());
935                         }
936                 } catch (ServiceException e) {
937                         throw new ServiceException(e);
938                 } 
939         }
940
941         @Override
942         final public Resource getSingleType(final Resource subject) throws NoSingleResultException, ServiceException {
943                 assert (subject != null);
944                 try {
945                         ArrayList<Resource> principalTypes = (ArrayList<Resource>)getPrincipalTypes(subject);
946                         if (principalTypes.size() == 1) {
947                             return principalTypes.get(0);
948                         } else {
949                             throw new NoSingleResultException("No single type for subject " + debugString(subject), principalTypes.size());
950                         }
951                 } catch (ServiceException e) {
952                         throw new ServiceException(e);
953                 } 
954         }
955
956         @Override
957         final public Resource getSingleType(final Resource subject,
958                         final Resource baseType) throws NoSingleResultException,
959                         ServiceException {
960
961                 assert (subject != null);
962                 assert (baseType != null);
963
964                 try {
965                         return syncRequest(new SingleType(subject, baseType));
966                 } catch (DatabaseException e) {
967                     throw new NoSingleResultException("subject=" + subject + ", baseType=" + baseType, 0, e);
968                 }
969         }
970
971         @Override
972         final public <T> T getValue(final Resource subject) throws DoesNotContainValueException, ServiceException {
973
974                 assert (subject != null);
975
976                 try {
977
978                         Layer0 L0 = processor.getL0(this);
979             int object = processor.getSingleObject(this, subject, L0.HasDataType);
980             if(object == 0) throw new DoesNotContainValueException("No data type for " + subject);
981             
982             if(processor.isImmutable(object)) {
983                 Binding binding = syncRequest(new DatatypeBinding(processor.querySupport.getResource(object)), TransientCacheListener.<Binding>instance()); 
984                         return getValue(subject, binding);
985             } else {
986                     byte[] dt = processor.getValue(this, object);
987                     if(dt == null) throw new ServiceException("No data type for " + subject);
988                     Datatype datatype = (Datatype)DATA_TYPE_SERIALIZER.deserialize(dt);
989                     Binding binding = Bindings.getBinding(datatype);
990                     return getValue(subject, binding);
991             }
992                         
993         } catch (IOException e) {
994
995             throw new ServiceException(e);
996
997                 } catch (DoesNotContainValueException e) {
998
999                         throw new DoesNotContainValueException(e, subject);
1000
1001                 } catch (ServiceException e) {
1002
1003                         throw new ServiceException(e);
1004
1005                 } catch (DatabaseException e) {
1006
1007                         throw new ServiceException(INTERNAL_ERROR_STRING, e);
1008
1009         }
1010
1011         }
1012
1013     @Override
1014     final public Variant getVariantValue(final Resource subject) throws DoesNotContainValueException, ServiceException {
1015
1016         assert (subject != null);
1017
1018         try {
1019
1020             Layer0 L0 = processor.getL0(this);
1021             int object = processor.getSingleObject(this, subject, L0.HasDataType);
1022             if(object == 0) throw new DoesNotContainValueException("No data type for " + subject);
1023             
1024             if(processor.isImmutable(object)) {
1025                 Binding binding = syncRequest(new DatatypeBinding(processor.querySupport.getResource(object)), TransientCacheListener.<Binding>instance()); 
1026                 return new Variant(binding, getValue(subject, binding));
1027             } else {
1028                 byte[] dt = processor.getValue(this, object);
1029                 if(dt == null) throw new ServiceException("No data type for " + subject);
1030                 Datatype datatype = (Datatype)DATA_TYPE_SERIALIZER.deserialize(dt);
1031                 Binding binding = Bindings.getBinding(datatype);
1032                 return new Variant(binding, getValue(subject, binding));
1033             }
1034             
1035         } catch (IOException e) {
1036
1037             throw new ServiceException(e);
1038
1039         } catch (DoesNotContainValueException e) {
1040
1041             throw new DoesNotContainValueException(e, subject);
1042
1043         } catch (ServiceException e) {
1044
1045             throw new ServiceException(e);
1046
1047         } catch (DatabaseException e) {
1048
1049             throw new ServiceException(INTERNAL_ERROR_STRING, e);
1050
1051         }               
1052         }
1053
1054         static final IdentityHashMap<Binding,Serializer> serializers = new IdentityHashMap<Binding,Serializer>();
1055         
1056         static {
1057                 serializers.put(Bindings.STRING, Bindings.STRING.serializer());
1058         }
1059         
1060         final protected Serializer getSerializer(Binding binding) {
1061             return binding.serializer();
1062         }
1063         
1064         @Override
1065         final public <T> T getValue(final Resource subject, final Binding binding) throws DoesNotContainValueException, BindingException,
1066                         ServiceException {
1067
1068                 assert (subject != null);
1069
1070                 try {
1071                         
1072                         byte[] bytes = processor.getValue(this, subject);
1073                         if (bytes == null) throw new DoesNotContainValueException("No value for resource " + subject);
1074
1075                         Serializer serializer = getSerializer(binding);
1076                         return (T)serializer.deserialize(bytes);
1077
1078                 } catch (DoesNotContainValueException e) {
1079
1080                         throw new DoesNotContainValueException(e);
1081
1082                 } catch (IOException e) {
1083
1084                         throw new ServiceException(e);
1085
1086                 } catch (DatabaseException e) {
1087                     
1088             throw new ServiceException(e);
1089             
1090         } catch (BufferUnderflowException e) {
1091             // This is sometimes thrown when deserialize fails because wrong format.
1092             // For callers of this method this is just an service exception.
1093             throw new ServiceException(e);
1094         }
1095
1096         }
1097
1098         @Override
1099         final public <T> T getRelatedValue(final Resource subject, final Resource relation) throws NoSingleResultException,
1100                         DoesNotContainValueException, ServiceException {
1101
1102                 assert (subject != null);
1103                 assert (relation != null);
1104
1105                 try {
1106                         Resource object = getSingleObject(subject, relation);
1107                         return getValue(object);
1108                 } catch (NoSingleResultException e) {
1109                         throw new NoSingleResultException("No single value found for subject " + debugString(subject) + " and relation " + debugString(relation), e.getResultCount(), e);
1110                 } catch (DoesNotContainValueException e) {
1111                         try {
1112                                 Layer0 L0 = processor.getL0(this);
1113                                 Resource object = getPossibleObject(subject, relation);
1114                                 if(isInstanceOf(object, L0.Value)) {
1115                                         if(isInstanceOf(object, L0.Literal)) {
1116                                                 throw new DoesNotContainValueException(e);
1117                                         } else {
1118                                                 throw new InvalidLiteralException("The object " + object + " is not an instance of L0.Literal (use getRelatedValue2 instead)", e);
1119                                         }
1120                                 } else {
1121                                         throw new DoesNotContainValueException("The object " + object + " is not an instance of L0.Value", e);
1122                                 }
1123                         } catch (DoesNotContainValueException e2) {
1124                                 throw e2;
1125                         } catch (DatabaseException e2) {
1126                                 throw new InternalException("The client failed to analyse the cause of the following exception", e);
1127                         }
1128                 } catch (ServiceException e) {
1129                         throw new ServiceException(e);
1130                 }
1131         }
1132
1133     @Override
1134     final public Variant getRelatedVariantValue(final Resource subject, final Resource relation) throws NoSingleResultException,
1135             DoesNotContainValueException, ServiceException {
1136
1137         assert (subject != null);
1138         assert (relation != null);
1139
1140         try {
1141             Resource object = getSingleObject(subject, relation);
1142             return getVariantValue(object);
1143         } catch (NoSingleResultException e) {
1144             throw new NoSingleResultException("No single object for subject " + debugString(subject) + " and relation " + debugString(relation), e.getResultCount(), e);
1145         } catch (DoesNotContainValueException e) {
1146             try {
1147                 Layer0 L0 = processor.getL0(this);
1148                 Resource object = getPossibleObject(subject, relation);
1149                 if(isInstanceOf(object, L0.Value)) {
1150                     if(isInstanceOf(object, L0.Literal)) {
1151                         throw new DoesNotContainValueException(e);
1152                     } else {
1153                         throw new InvalidLiteralException("The object " + object + " is not an instance of L0.Literal (use getRelatedValue2 instead)", e);
1154                     }
1155                 } else {
1156                     throw new DoesNotContainValueException("The object " + object + " is not an instance of L0.Value", e);
1157                 }
1158             } catch (DoesNotContainValueException e2) {
1159                 throw e2;
1160             } catch (DatabaseException e2) {
1161                 throw new InternalException("The client failed to analyse the cause of the following exception", e);
1162             }
1163         } catch (ServiceException e) {
1164             throw new ServiceException(e);
1165         } 
1166     }
1167     
1168         @Override
1169         final public <T> T getRelatedValue(final Resource subject, final Resource relation, final Binding binding)
1170                         throws NoSingleResultException, DoesNotContainValueException, BindingException, ServiceException {
1171
1172                 assert (subject != null);
1173                 assert (relation != null);
1174
1175                 try {
1176                         Resource object = getSingleObject(subject, relation);
1177                         return getValue(object, binding);
1178                 } catch (NoSingleResultException e) {
1179                     String message = "";
1180                     try {
1181                     String subjectName = NameUtils.getSafeName(this, subject, true);
1182                     String relationName = NameUtils.getSafeName(this, relation, true);
1183                     message = "Subject: " + subjectName + ", Relation: " + relationName;
1184                     } catch (DatabaseException e2) {
1185                         
1186                     }
1187             throw new NoSingleResultException(message, e.getResultCount(), e);
1188                 } catch (DoesNotContainValueException e) {
1189                         throw new DoesNotContainValueException(e);
1190                 } catch (ServiceException e) {
1191                         throw new ServiceException(e);
1192                 }
1193         }
1194
1195         @Override
1196         final public <T> T adapt(final Resource resource, final Class<T> clazz)
1197                         throws AdaptionException, ValidationException, ServiceException {
1198
1199                 assert (resource != null);
1200                 assert (clazz != null);
1201
1202                 try {
1203
1204                         return syncRequest(new Adapter<T>(resource, clazz));
1205
1206                 } catch (AdaptionException e) {
1207
1208                         throw new AdaptionException(e);
1209
1210                 } catch (ValidationException e) {
1211
1212                         throw new ValidationException(e);
1213
1214                 } catch (ServiceException e) {
1215
1216                         throw new ServiceException(e);
1217
1218                 } catch (DatabaseException e) {
1219
1220                         throw new ServiceException(INTERNAL_ERROR_STRING, e);
1221
1222                 }
1223
1224         }
1225
1226         @Override
1227         final public <T,C> T adaptContextual(final Resource resource, final C context, final Class<C> contextClass, final Class<T> clazz)
1228                         throws AdaptionException, ValidationException, ServiceException {
1229
1230                 assert (resource != null);
1231                 assert (context != null);
1232
1233                 class ContextualAdapter implements AsyncRead<T> {
1234
1235                         final private Resource resource;
1236                         final private C context;
1237                     final private Class<T> clazz;
1238                     
1239                     @Override
1240                     public int hashCode() {
1241                         return resource.hashCode() + 31 * (clazz.hashCode() + 41 * context.hashCode());
1242                     }
1243                     
1244                     @Override
1245                     final public int threadHash() {
1246                         return resource.getThreadHash();
1247                     }
1248                     
1249                     @Override
1250                     public boolean equals(Object object) {
1251                         if (this == object)
1252                             return true;
1253                         else if (object == null)
1254                             return false;
1255                         else if (getClass() != object.getClass())
1256                             return false;
1257                         ContextualAdapter r = (ContextualAdapter)object;
1258                         return resource.equals(r.resource) && context.equals(r.context) && clazz.equals(r.clazz);
1259                     }
1260
1261                     @Override
1262                     public int getFlags() {
1263                         return 0;
1264                     }
1265                     
1266                     public ContextualAdapter(Resource resource, C context, Class<T> clazz) {
1267                         this.resource = resource;
1268                         this.context = context;
1269                         this.clazz = clazz;
1270                     }
1271
1272                     @Override
1273                     public void perform(AsyncReadGraph graph, AsyncProcedure<T> procedure) {
1274                         
1275                                 final AdaptionService service = getSession().peekService(AdaptionService.class);
1276                                 if (service == null)
1277                                         procedure.exception(graph, new ServiceException("No AdaptionService available")); 
1278                                 else
1279                                         service.adapt(graph, resource, context, contextClass, clazz, false, procedure); 
1280                         
1281                     }
1282
1283                     @Override
1284                     public String toString() {
1285                         return "Adapter for (" + resource + "," + context + ") as " + clazz.getName();
1286                     }
1287                     
1288                 }
1289                 
1290                 try {
1291
1292                         return syncRequest(new ContextualAdapter(resource, context, clazz));
1293
1294                 } catch (AdaptionException e) {
1295
1296                         throw new AdaptionException(e);
1297
1298                 } catch (ValidationException e) {
1299
1300                         throw new ValidationException(e);
1301
1302                 } catch (ServiceException e) {
1303
1304                         throw new ServiceException(e);
1305
1306                 } catch (DatabaseException e) {
1307
1308                         throw new ServiceException(INTERNAL_ERROR_STRING, e);
1309
1310                 }
1311
1312         }
1313         
1314         @Override
1315         final public <T> T adaptRelated(final Resource resource, final Resource relation, final Class<T> clazz)
1316                         throws AdaptionException, NoSingleResultException, ValidationException, ServiceException {
1317
1318                 assert (resource != null);
1319                 assert (clazz != null);
1320
1321                 Statement stm = getSingleStatement(resource, relation);
1322                 
1323                 return adaptContextual(stm.getObject(), new RelationContextImpl(resource, stm), RelationContext.class, clazz);
1324                 
1325         }
1326
1327         @Override
1328         final public <T> T getPossibleRelatedAdapter(final Resource resource, final Resource relation, final Class<T> clazz)
1329                         throws ValidationException, ServiceException {
1330
1331                 try {
1332                         return adaptRelated(resource, relation, clazz);
1333                 } catch (DatabaseException e) {
1334                         return null;
1335                 }
1336                 
1337         }
1338
1339         @Override
1340         final public <T,C> T getPossibleContextualAdapter(final Resource resource, final C context, final Class<C> contextClass, final Class<T> clazz)
1341                         throws ValidationException, ServiceException {
1342
1343                 assert (resource != null);
1344                 assert (context != null);
1345
1346                 class PossibleContextualAdapter implements AsyncRead<T> {
1347
1348                         final private Resource resource;
1349                         final private C context;
1350                     final private Class<T> clazz;
1351                     
1352                     @Override
1353                     public int hashCode() {
1354                         return resource.hashCode() + 31 * (clazz.hashCode() + 41 * context.hashCode());
1355                     }
1356                     
1357                     @Override
1358                     final public int threadHash() {
1359                         return resource.getThreadHash();
1360                     }
1361                     
1362                     @Override
1363                     public boolean equals(Object object) {
1364                         if (this == object)
1365                             return true;
1366                         else if (object == null)
1367                             return false;
1368                         else if (getClass() != object.getClass())
1369                             return false;
1370                         PossibleContextualAdapter r = (PossibleContextualAdapter)object;
1371                         return resource.equals(r.resource) && context.equals(r.context) && clazz.equals(r.clazz);
1372                     }
1373
1374                     @Override
1375                     public int getFlags() {
1376                         return 0;
1377                     }
1378                     
1379                     public PossibleContextualAdapter(Resource resource, C context, Class<T> clazz) {
1380                         this.resource = resource;
1381                         this.context = context;
1382                         this.clazz = clazz;
1383                     }
1384
1385                     @Override
1386                     public void perform(AsyncReadGraph graph, AsyncProcedure<T> procedure) {
1387                         
1388                                 final AdaptionService service = getSession().peekService(AdaptionService.class);
1389                                 if (service == null)
1390                                         procedure.exception(graph, new ServiceException("No AdaptionService available")); 
1391                                 else
1392                                         service.adapt(graph, resource, context, contextClass, clazz, true, procedure); 
1393                         
1394                     }
1395
1396                     @Override
1397                     public String toString() {
1398                         return "Possible adapter for (" + resource + "," + context + ") as " + clazz.getName();
1399                     }
1400                     
1401                 }
1402                 
1403                 try {
1404
1405                         return syncRequest(new PossibleContextualAdapter(resource, context, clazz));
1406
1407                 } catch (ValidationException e) {
1408
1409                         throw new ValidationException(e);
1410
1411                 } catch (ServiceException e) {
1412
1413                         throw new ServiceException(e);
1414
1415                 } catch (DatabaseException e) {
1416
1417                         throw new ServiceException(INTERNAL_ERROR_STRING, e);
1418
1419                 }
1420                 
1421         }
1422
1423         @Override
1424         final public <T> T adaptUnique(final Resource resource, final Class<T> clazz)
1425                         throws AdaptionException, ValidationException, ServiceException {
1426
1427                 assert (resource != null);
1428                 assert (clazz != null);
1429
1430                 try {
1431
1432                         return syncRequest(new UniqueAdapter<T>(resource, clazz));
1433
1434                 } catch (AdaptionException e) {
1435
1436                         throw new AdaptionException(e);
1437
1438                 } catch (ValidationException e) {
1439
1440                         throw new ValidationException(e);
1441
1442                 } catch (ServiceException e) {
1443
1444                         throw new ServiceException(e);
1445
1446                 } catch (DatabaseException e) {
1447
1448                         throw new ServiceException(INTERNAL_ERROR_STRING, e);
1449
1450                 }
1451
1452         }
1453
1454         @Override
1455         final public Resource getPossibleInverse(final Resource relation)
1456                         throws ServiceException {
1457
1458                 assert (relation != null);
1459
1460                 try {
1461
1462                         return getPossibleObject(relation, processor.querySupport.getResource(processor.getInverseOf()));
1463
1464                 } catch (ServiceException e) {
1465
1466                         throw new ServiceException(e);
1467
1468                 } catch (DatabaseException e) {
1469
1470                         throw new ServiceException(INTERNAL_ERROR_STRING, e);
1471
1472                 }
1473
1474         }
1475
1476         @Override
1477         public Resource getPossibleObject(final Resource subject, final Resource relation)
1478                         throws ManyObjectsForFunctionalRelationException, ServiceException {
1479
1480                 assert (subject != null);
1481                 assert (relation != null);
1482
1483                 try {
1484
1485                     int result = processor.getSingleObject(this, subject, relation);
1486                     if(result == 0) return null;
1487                     
1488                     return processor.querySupport.getResource(result);
1489
1490              } catch (ManyObjectsForFunctionalRelationException e) {
1491
1492                  throw new ManyObjectsForFunctionalRelationException("subject=" + subject + ", relation=" + relation, e);
1493                  
1494                 } catch (DatabaseException e) {
1495
1496                         throw new ServiceException(e);
1497
1498                 }
1499                 
1500         }
1501
1502         @Override
1503         final public Statement getPossibleStatement(final Resource subject, final Resource relation)
1504                         throws ManyObjectsForFunctionalRelationException, ServiceException {
1505
1506                 assert (subject != null);
1507                 assert (relation != null);
1508
1509                 try {
1510
1511                         Collection<Statement> statements = getStatements(subject, relation);
1512                         if(statements.size() == 1) return statements.iterator().next();
1513                         else return null;
1514
1515                 } catch (ManyObjectsForFunctionalRelationException e) {
1516
1517                         throw new ManyObjectsForFunctionalRelationException("Many objects in " + subject + " for functional relation " + relation);
1518
1519                 } catch (ServiceException e) {
1520
1521                         throw new ServiceException(e);
1522
1523                 } 
1524
1525         }
1526
1527         @Override
1528         final public Resource getPossibleType(final Resource subject, final Resource baseType) throws ServiceException {
1529
1530                 assert (subject != null);
1531                 assert (baseType != null);
1532
1533                 try {
1534
1535                         AsyncReadProcedure<Resource> procedure = new AsyncReadProcedure<Resource>();
1536                         forPossibleType(subject, baseType, procedure);
1537                         procedure.checkAndThrow();
1538                         return procedure.result;                        
1539
1540                 } catch (ServiceException e) {
1541
1542                         throw new ServiceException(e);
1543
1544                 } catch (DatabaseException e) {
1545
1546                         throw new ServiceException(INTERNAL_ERROR_STRING, e);
1547
1548                 }
1549
1550         }
1551
1552         @Override
1553         final public <T> T getPossibleValue(final Resource subject) throws ServiceException {
1554
1555                 assert (subject != null);
1556
1557                 try {
1558                     
1559                     int object = processor.getSingleObject(this, subject, processor.getL0(this).HasDataType);
1560                     if(object == 0) return null;
1561                     
1562             if(processor.isImmutable(object)) {
1563                 Binding binding = syncRequest(new DatatypeBinding(processor.querySupport.getResource(object)), TransientCacheListener.<Binding>instance()); 
1564                         return getPossibleValue(subject, binding);
1565             } else {
1566                     byte[] dt = processor.getValue(this, object);
1567                     if(dt == null) return null;
1568                     Datatype datatype = (Datatype)DATA_TYPE_SERIALIZER.deserialize(dt);
1569                     Binding binding = Bindings.getBinding(datatype);
1570                     return getPossibleValue(subject, binding);
1571             }
1572                     
1573         } catch (IOException e) {
1574             
1575             throw new ServiceException(e);
1576             
1577                 } catch (ServiceException e) {
1578
1579                         throw new ServiceException(e);
1580
1581                 } catch (DatabaseException e) {
1582
1583                         throw new ServiceException(INTERNAL_ERROR_STRING, e);
1584
1585         }
1586
1587         }
1588
1589         @Override
1590         final public <T> T getPossibleValue(final Resource subject, final Binding binding) throws BindingException, ServiceException {
1591
1592                 assert (subject != null);
1593                 assert (binding != null);
1594
1595                 try {
1596
1597             byte[] dt = processor.getValue(this, subject);
1598             if(dt == null) return null;
1599                         Serializer serializer = getSerializer(binding);
1600             return (T)serializer.deserialize(dt);
1601
1602         } catch (IOException e) {
1603
1604             throw new ServiceException(e);
1605             
1606                 } catch (BindingException e) {
1607
1608                         throw new BindingException(e);
1609
1610                 } catch (ServiceException e) {
1611
1612                         throw new ServiceException(e);
1613
1614                 } catch (DatabaseException e) {
1615                         e.printStackTrace();
1616                         throw new ServiceException(INTERNAL_ERROR_STRING, e);
1617         }
1618
1619         }
1620
1621         @Override
1622         public <T> T getPossibleRelatedValue(final Resource subject, final Resource relation)
1623                         throws ManyObjectsForFunctionalRelationException, ServiceException {
1624
1625                 assert (subject != null);
1626                 assert (relation != null);
1627
1628                 try {
1629
1630                         Resource object = getPossibleObject(subject, relation);
1631                         if(object == null) return null;
1632                         else return getPossibleValue(object);
1633
1634                 } catch (ManyObjectsForFunctionalRelationException e) {
1635
1636                         throw new ManyObjectsForFunctionalRelationException(e);
1637
1638                 } catch (ServiceException e) {
1639
1640                         throw new ServiceException(e);
1641
1642                 } 
1643
1644         }
1645
1646         @Override
1647         public <T> T getPossibleRelatedValue(final Resource subject, final Resource relation, final Binding binding)
1648                         throws ManyObjectsForFunctionalRelationException, BindingException, ServiceException {
1649
1650                 assert (subject != null);
1651                 assert (relation != null);
1652                 assert (binding != null);
1653
1654                 try {
1655
1656                         Resource object = getPossibleObject(subject, relation);
1657                         if(object == null) return null;
1658                         else return getPossibleValue(object, binding);
1659
1660                 } catch (ManyObjectsForFunctionalRelationException e) {
1661
1662                         throw new ManyObjectsForFunctionalRelationException(e);
1663
1664                 } catch (BindingException e) {
1665
1666                         throw new BindingException(e);
1667
1668                 } catch (ServiceException e) {
1669
1670                         throw new ServiceException(e);
1671
1672                 }
1673
1674         }
1675
1676         @Override
1677         public <T> T getPossibleAdapter(Resource resource, Class<T> clazz) throws ValidationException, ServiceException {
1678
1679                 assert (resource != null);
1680                 assert (clazz != null);
1681
1682                 try {
1683
1684                         return syncRequest(new PossibleAdapter<T>(resource, clazz));
1685
1686                 } catch (ValidationException e) {
1687
1688                         throw new ValidationException(e);
1689
1690                 } catch (AdaptionException e) {
1691
1692                         return null;
1693
1694                 } catch (DatabaseException e) {
1695
1696                         throw new ServiceException(INTERNAL_ERROR_STRING, e);
1697
1698                 }
1699         }
1700
1701         @Override
1702         public <T> T getPossibleUniqueAdapter(Resource resource, Class<T> clazz) throws ValidationException, ServiceException {
1703
1704                 assert (resource != null);
1705                 assert (clazz != null);
1706
1707                 try {
1708
1709                         return syncRequest(new PossibleUniqueAdapter<T>(resource, clazz));
1710
1711                 } catch (AdaptionException e) {
1712
1713                         return null;
1714
1715                 } catch (ValidationException e) {
1716
1717                         throw new ValidationException(e);
1718
1719                 } catch (DatabaseException e) {
1720
1721                         throw new ServiceException(INTERNAL_ERROR_STRING, e);
1722
1723                 }
1724
1725         }
1726
1727     @Override
1728     final public boolean isInstanceOf(final Resource resource, final Resource type) throws ServiceException {
1729
1730         assert (resource != null);
1731         assert (type != null);
1732
1733         Set<Resource> resources = getTypes(resource);
1734         // This check was necessary because some of the callers of this method got stuck when the NPE was thrown from here.
1735         if (null == resources)
1736             return false;
1737         
1738         if(EMPTY_RESOURCE_CHECK) {
1739             if (resources.isEmpty()) {
1740                 if(!hasStatement(resource)) throw new EmptyResourceException("Resource " + debugString(resource));
1741             }
1742         }
1743         
1744         return resources.contains(type);
1745
1746     }
1747
1748         @Override
1749         final public boolean isInheritedFrom(final Resource resource, final Resource type) throws ServiceException {
1750
1751                 assert (resource != null);
1752                 assert (type != null);
1753
1754                 try {
1755
1756                         if(resource.equals(type)) return true;
1757                         
1758                         return getSupertypes(resource).contains(type);
1759
1760                 } catch (ServiceException e) {
1761
1762                         throw new ServiceException(e);
1763
1764                 } 
1765                 
1766         }
1767
1768         @Override
1769         final public boolean isSubrelationOf(final Resource resource, final Resource type) throws ServiceException {
1770
1771                 assert (resource != null);
1772                 assert (type != null);
1773
1774                 try {
1775
1776                         if(resource.equals(type)) return true;
1777                         
1778                         return getSuperrelations(resource).contains(type);
1779
1780                 } catch (ServiceException e) {
1781
1782                         throw new ServiceException(e);
1783
1784                 } 
1785
1786         }
1787
1788         @Override
1789         final public boolean hasStatement(final Resource subject) throws ServiceException {
1790
1791                 assert (subject != null);
1792
1793                 try {
1794
1795                         SyncReadProcedure<Boolean> procedure = new SyncReadProcedure<Boolean>();
1796                         processor.forHasStatement(this, subject, procedure);
1797                         procedure.checkAndThrow();
1798                         return procedure.result;
1799
1800                 } catch (ServiceException e) {
1801
1802                         throw new ServiceException(e);
1803
1804                 } catch (DatabaseException e) {
1805
1806                         throw new ServiceException(INTERNAL_ERROR_STRING, e);
1807
1808                 }
1809
1810         }
1811
1812         @Override
1813         final public boolean hasStatement(final Resource subject, final Resource relation) throws ServiceException {
1814
1815                 assert (subject != null);
1816                 assert (relation != null);
1817
1818                 try {
1819
1820                         Collection<Resource> objects = getObjects(subject, relation);
1821                         return !objects.isEmpty();
1822
1823                 } catch (ServiceException e) {
1824
1825                         throw new ServiceException(e);
1826
1827                 } 
1828                 
1829         }
1830
1831         @Override
1832         final public boolean hasStatement(final Resource subject, final Resource relation, final Resource object) throws ServiceException {
1833
1834                 assert (subject != null);
1835                 assert (relation != null);
1836                 assert (object != null);
1837
1838                 try {
1839
1840                         for(Resource o : getObjects(subject, relation)) {
1841                                 if(object.equals(o)) return true;
1842                         }
1843                         
1844                         return false;
1845
1846                 } catch (ServiceException e) {
1847
1848                         throw new ServiceException(e);
1849
1850                 }
1851
1852         }
1853
1854         @Override
1855         final public boolean hasValue(final Resource subject) throws ServiceException {
1856
1857                 assert (subject != null);
1858
1859                 try {
1860
1861                         SyncReadProcedure<Boolean> procedure = new SyncReadProcedure<Boolean>();
1862                         processor.forHasValue(this, subject, procedure);
1863                         procedure.checkAndThrow();
1864                         return procedure.result;
1865
1866                 } catch (ServiceException e) {
1867
1868                         throw new ServiceException(e);
1869
1870                 } catch (DatabaseException e) {
1871
1872                         throw new ServiceException(INTERNAL_ERROR_STRING, e);
1873
1874                 }
1875
1876         }
1877
1878         final AsyncProcedure<?> NONE = new AsyncProcedure<Object>() {
1879
1880                 @Override
1881                 public void execute(AsyncReadGraph graph, Object result) {
1882                 }
1883
1884                 @Override
1885                 public void exception(AsyncReadGraph graph, Throwable throwable) {
1886                 }
1887                 
1888         };
1889         
1890         /*
1891          * Implementation of the interface RequestProcessor
1892          */
1893
1894         @Override
1895         public <T> T syncRequest(final Read<T> request) throws DatabaseException {
1896
1897                 assert (request != null);
1898
1899                 if (parent != null) {
1900
1901                         try {
1902                                 return processor.queryRead(this, request, parent, null, null);
1903                         } catch (Throwable e) {
1904                                 if(e instanceof DatabaseException) throw (DatabaseException)e;
1905                                 else throw new DatabaseException(e);
1906                         }
1907
1908                 } else {
1909
1910                         try {
1911
1912                                 return processor.tryQuery(this, request);
1913
1914                         } catch (Throwable throwable) {
1915
1916                                 //Logger.defaultLogError("Internal read request failure", throwable);
1917
1918                                 if (throwable instanceof DatabaseException)
1919                                         throw (DatabaseException) throwable;
1920                                 else
1921                                         throw new DatabaseException(
1922                                                         "Unexpected exception in ReadGraph.syncRequest(Read,Procedure)",
1923                                                         throwable);
1924
1925                         }
1926
1927                 }
1928                 
1929         }
1930
1931         @Override
1932         public <T> T syncRequest(Read<T> request, SyncListener<T> procedure)
1933                         throws DatabaseException {
1934                 return syncRequest(request, new SyncToAsyncListener<T>(procedure));
1935         }
1936
1937         @Override
1938         public <T> T syncRequest(Read<T> request, final Listener<T> procedure)
1939                         throws DatabaseException {
1940                 return syncRequest(request, new NoneToAsyncListener<T>(procedure));
1941         }
1942
1943         @Override
1944         public <T> T syncRequest(final Read<T> request, final AsyncProcedure<T> procedure) throws DatabaseException {
1945
1946                 assert (request != null);
1947
1948                 ListenerBase listener = procedure != null ? getListenerBase(procedure) : null;
1949
1950                 if (parent != null || listener != null) {
1951                         
1952                         try {
1953                 return processor.queryRead(this, request, parent, procedure, listener);
1954             } catch (Throwable e) {
1955                 if(e instanceof DatabaseException) throw (DatabaseException)e;
1956                 else throw new DatabaseException(e);
1957             }
1958
1959                 } else {
1960
1961                         try {
1962
1963                                 T t = processor.tryQuery(this, request);
1964                                 if(procedure != null)
1965                                         procedure.execute(this, t);
1966
1967                                 return t;
1968
1969                         } catch (Throwable throwable) {
1970
1971                                 Logger.defaultLogError("Internal read request failure", throwable);
1972
1973                                 if(procedure != null)
1974                                         procedure.exception(this, throwable);
1975                                 
1976                                 if (throwable instanceof DatabaseException)
1977                                         throw (DatabaseException) throwable;
1978                                 else
1979                                         throw new DatabaseException(
1980                                                         "Unexpected exception in ReadGraph.syncRequest(Read,Procedure)",
1981                                                         throwable);
1982
1983                         }
1984
1985                 }
1986
1987         }
1988
1989         @Override
1990         public <T> T syncRequest(final Read<T> request,
1991                         final SyncProcedure<T> procedure) throws DatabaseException {
1992                 return syncRequest(request, new SyncToAsyncProcedure<T>(procedure));
1993         }
1994
1995         @Override
1996         public <T> T syncRequest(Read<T> request, Procedure<T> procedure)
1997                         throws DatabaseException {
1998                 return syncRequest(request, new NoneToAsyncProcedure<T>(procedure));
1999         }
2000
2001         static class AsyncReadProcedure<T> implements AsyncProcedure<T> {
2002
2003                 private static Throwable DONE = new Throwable();
2004                 
2005                 T result = null;
2006                 Throwable exception = null;
2007                 
2008                 @Override
2009                 public void execute(AsyncReadGraph graph, T t) {
2010                         result = t;
2011                         exception = DONE;
2012                 }
2013
2014                 @Override
2015                 public void exception(AsyncReadGraph graph, Throwable t) {
2016                         exception = t;
2017                 }
2018                 
2019                 public void checkAndThrow() throws DatabaseException {
2020                         if(exception != DONE) {
2021                                 if (exception instanceof DatabaseException)
2022                                         throw (DatabaseException) exception;
2023                                 else
2024                                         throw new DatabaseException(
2025                                                         "Unexpected exception in ReadGraph.syncRequest(AsyncMultiRead)",
2026                                                         exception);
2027                         }
2028                 }
2029                 
2030                 public boolean done() {
2031                         return exception != null;
2032                 }
2033                 
2034         }
2035         
2036         @Override
2037         public <T> T syncRequest(final AsyncRead<T> request)
2038                         throws DatabaseException {
2039
2040                 assert (request != null);
2041                 AsyncReadProcedure<T> procedure = new AsyncReadProcedure<T>();
2042                 syncRequest(request, procedure);
2043                 procedure.checkAndThrow();
2044                 return procedure.result;
2045                 
2046 //              return syncRequest(request, new AsyncProcedureAdapter<T>());
2047
2048         }
2049
2050         @Override
2051         public <T> T syncRequest(AsyncRead<T> request, AsyncListener<T> procedure)
2052                         throws DatabaseException {
2053                 return syncRequest(request, (AsyncProcedure<T>) procedure);
2054         }
2055
2056         @Override
2057         public <T> T syncRequest(AsyncRead<T> request, SyncListener<T> procedure)
2058                         throws DatabaseException {
2059                 return syncRequest(request, new SyncToAsyncListener<T>(procedure));
2060         }
2061
2062         @Override
2063         public <T> T syncRequest(AsyncRead<T> request, Listener<T> procedure)
2064                         throws DatabaseException {
2065                 return syncRequest(request, new NoneToAsyncListener<T>(procedure));
2066         }
2067
2068         @Override
2069         final public <T> T syncRequest(final AsyncRead<T> request,
2070                         final AsyncProcedure<T> procedure) throws DatabaseException {
2071
2072                 assert (request != null);
2073
2074                 // System.out.println("syncRequest " + request + " syncParent=" +
2075                 // syncParent);
2076
2077                 ListenerBase listener = getListenerBase(procedure);
2078
2079                 if (parent != null || listener != null || ((request.getFlags() & RequestFlags.SCHEDULE) > 0)) {
2080
2081 //                      Object syncParent = request;
2082
2083 //                      final ReadGraphImpl newGraph = newSync();
2084
2085                         final ResultCallWrappedSingleQueryProcedure4<T> wrapper = new ResultCallWrappedSingleQueryProcedure4<T>(
2086                                         procedure, request);
2087                         
2088                         processor.query(this, request, parent, wrapper, listener);
2089
2090 //                      newGraph.waitAsync(syncParent);
2091                         
2092                         Throwable e = wrapper.getException();
2093                         if (e != null) {
2094                                 // The request was async - produce meaningful stack trace by
2095                                 // wrapping
2096                                 if (e instanceof DatabaseException)
2097                                         throw (DatabaseException) e;
2098                                 else
2099                                         throw new DatabaseException(e);
2100                         }
2101                         
2102                         return wrapper.getResult();
2103
2104                 } else {
2105
2106                         // System.out.println("direct call " + request );
2107
2108                         // Do not set the sync state.parent for external threads
2109 //                      Object syncParent = request;
2110
2111 //                      final ReadGraphImpl newGraph = newSync();
2112
2113                         final ResultCallWrappedSingleQueryProcedure4<T> wrapper = new ResultCallWrappedSingleQueryProcedure4<T>(
2114                                         procedure, request);
2115
2116                         try {
2117
2118                                 processor.tryQuery(this, request, wrapper);
2119
2120                         } catch (Throwable t) {
2121
2122                                 wrapper.exception(this, t);
2123
2124                         }
2125
2126                         Throwable e = wrapper.getException();
2127                         if (e != null) {
2128                                 // The request was async - produce meaningful stack trace by
2129                                 // wrapping
2130                                 if (e instanceof DatabaseException)
2131                                         throw (DatabaseException) e;
2132                                 else
2133                                         throw new DatabaseException(e);
2134                         }
2135                         
2136                         return wrapper.getResult();
2137
2138                 }
2139
2140         }
2141
2142         final private <T> void syncRequest(final AsyncRead<T> request, final AsyncReadProcedure<T> procedure) throws DatabaseException {
2143
2144                 assert (request != null);
2145
2146                 // System.out.println("syncRequest " + request + " syncParent=" +
2147                 // syncParent);
2148
2149                 ListenerBase listener = getListenerBase(procedure);
2150
2151                 if (parent != null || listener != null || ((request.getFlags() & RequestFlags.SCHEDULE) > 0)) {
2152
2153 //                      final ReadGraphImpl newGraph = newSync();
2154
2155                         final ResultCallWrappedSingleQueryProcedure4<T> wrapper = new ResultCallWrappedSingleQueryProcedure4<T>(
2156                                         procedure, request);
2157
2158                         processor.query(this, request, parent, wrapper, listener);
2159
2160                 } else {
2161
2162                         try {
2163
2164 //                              final ReadGraphImpl newGraph = newSync();
2165                                 processor.tryQuery(this, request, procedure);
2166 //                              newGraph.waitAsync(null);
2167                                 waitAsyncProcedure(procedure);
2168
2169                         } catch (Throwable t) {
2170                                 if(Development.DEVELOPMENT) {
2171                                         if(Development.<Boolean>getProperty(DevelopmentKeys.WRITEGRAPH_EXCEPTION_STACKTRACES, Bindings.BOOLEAN)) {
2172                                         t.printStackTrace();
2173                                         }
2174                                 }
2175                                 procedure.exception(this, t);
2176                                 waitAsyncProcedure(procedure);
2177                         }
2178
2179                 }
2180
2181         }
2182
2183         @Override
2184         public <T> T syncRequest(AsyncRead<T> request,
2185                         final SyncProcedure<T> procedure) throws DatabaseException {
2186                 return syncRequest(request, new SyncToAsyncProcedure<T>(procedure));
2187         }
2188
2189         @Override
2190         final public <T> T syncRequest(final AsyncRead<T> request,
2191                         final Procedure<T> procedure) throws DatabaseException {
2192                 return syncRequest(request, new NoneToAsyncProcedure<T>(procedure));
2193         }
2194
2195         @Override
2196         public <T> Collection<T> syncRequest(final MultiRead<T> request)
2197                         throws DatabaseException {
2198
2199                 assert (request != null);
2200
2201                 final ArrayList<T> result = new ArrayList<T>();
2202                 final DataContainer<Throwable> exception = new DataContainer<Throwable>();
2203
2204                 syncRequest(request, new AsyncMultiProcedure<T>() {
2205
2206                         @Override
2207                         public void execute(AsyncReadGraph graph, T t) {
2208                                 synchronized (result) {
2209                                         result.add(t);
2210                                 }
2211                         }
2212
2213                         @Override
2214                         public void finished(AsyncReadGraph graph) {
2215                         }
2216
2217                         @Override
2218                         public void exception(AsyncReadGraph graph, Throwable t) {
2219                                 exception.set(t);
2220                         }
2221
2222                         @Override
2223                         public String toString() {
2224                                 return "syncRequest(MultiRead) -> " + request;
2225                         }
2226
2227                 });
2228
2229                 Throwable t = exception.get();
2230                 if (t != null) {
2231                         if (t instanceof DatabaseException)
2232                                 throw (DatabaseException) t;
2233                         else
2234                                 throw new DatabaseException(
2235                                                 "Unexpected exception in ReadGraph.syncRequest(Read)",
2236                                                 t);
2237                 }
2238
2239                 return result;
2240
2241         }
2242
2243         @Override
2244         public <T> Collection<T> syncRequest(MultiRead<T> request,
2245                         AsyncMultiListener<T> procedure) {
2246                 return syncRequest(request, (AsyncMultiProcedure<T>) procedure);
2247         }
2248
2249         @Override
2250         public <T> Collection<T> syncRequest(MultiRead<T> request,
2251                         SyncMultiListener<T> procedure) {
2252                 return syncRequest(request, new SyncToAsyncMultiListener<T>(procedure));
2253         }
2254
2255         @Override
2256         public <T> Collection<T> syncRequest(MultiRead<T> request,
2257                         MultiListener<T> procedure) {
2258                 return syncRequest(request, new NoneToAsyncMultiListener<T>(procedure));
2259         }
2260
2261         @Override
2262         public <T> Collection<T> syncRequest(MultiRead<T> request,
2263                         AsyncMultiProcedure<T> procedure) {
2264
2265                 assert (request != null);
2266
2267                 ListenerBase listener = getListenerBase(procedure);
2268
2269                 if (parent != null || listener != null) {
2270
2271 //                      Object syncParent = request;
2272
2273 //                      final ReadGraphImpl newGraph = newSync();
2274
2275                         processor.query(this, request, parent, procedure, listener);
2276
2277 //                      newGraph.waitAsync(syncParent);
2278
2279                 } else {
2280
2281 //                      Object syncParent = request;
2282
2283 //                      final ReadGraphImpl newGraph = newSync();
2284
2285                         final ResultCallWrappedQueryProcedure4<T> wrapper = new ResultCallWrappedQueryProcedure4<T>(procedure);
2286
2287                         try {
2288
2289                                 request.perform(this, wrapper);
2290
2291                         } catch (Throwable t) {
2292
2293                                 wrapper.exception(this, t);
2294 //                              newGraph.waitAsync(syncParent);
2295
2296                         }
2297
2298                 }
2299
2300                 // TODO
2301                 return null;
2302
2303         }
2304
2305         @Override
2306         public <T> Collection<T> syncRequest(MultiRead<T> request,
2307                         SyncMultiProcedure<T> procedure) {
2308                 return syncRequest(request, new SyncToAsyncMultiProcedure<T>(procedure));
2309         }
2310
2311         @Override
2312         public <T> Collection<T> syncRequest(MultiRead<T> request,
2313                         MultiProcedure<T> procedure) {
2314                 return syncRequest(request, new NoneToAsyncMultiProcedure<T>(procedure));
2315         }
2316
2317         static class AsyncMultiReadProcedure<T> extends ArrayList<T> implements AsyncMultiProcedure<T> {
2318
2319                 private static Throwable DONE = new Throwable();
2320                 
2321                 private static final long serialVersionUID = -6494230465108115812L;
2322                 
2323                 Throwable exception = null;
2324                 
2325                 @Override
2326                 public synchronized void execute(AsyncReadGraph graph, T t) {
2327                         add(t);
2328                 }
2329
2330                 @Override
2331                 public void finished(AsyncReadGraph graph) {
2332                         exception = DONE;
2333                 }
2334
2335                 @Override
2336                 public void exception(AsyncReadGraph graph, Throwable t) {
2337                         exception = t;
2338                 }
2339                 
2340                 public void checkAndThrow() throws DatabaseException {
2341                         if(exception != DONE) {
2342                                 if (exception instanceof DatabaseException)
2343                                         throw (DatabaseException) exception;
2344                                 else
2345                                         throw new DatabaseException(
2346                                                         "Unexpected exception in ReadGraph.syncRequest(AsyncMultiRead)",
2347                                                         exception);
2348                         }
2349                 }
2350                 
2351                 public boolean done() {
2352                         return exception != null;
2353                 }
2354                 
2355         }
2356
2357         @Override
2358         final public <T> Collection<T> syncRequest(AsyncMultiRead<T> request)
2359                         throws DatabaseException {
2360
2361                 assert (request != null);
2362
2363                 final AsyncMultiReadProcedure<T> procedure = new AsyncMultiReadProcedure<T>();
2364                 
2365                 syncRequest(request, procedure);
2366                 
2367                 procedure.checkAndThrow();
2368                 return procedure;
2369
2370         }
2371
2372         @Override
2373         public <T> Collection<T> syncRequest(AsyncMultiRead<T> request,
2374                         AsyncMultiListener<T> procedure) {
2375                 return syncRequest(request, (AsyncMultiProcedure<T>) procedure);
2376         }
2377
2378         @Override
2379         public <T> Collection<T> syncRequest(AsyncMultiRead<T> request,
2380                         SyncMultiListener<T> procedure) {
2381                 return syncRequest(request, new SyncToAsyncMultiListener<T>(procedure));
2382         }
2383
2384         @Override
2385         public <T> Collection<T> syncRequest(AsyncMultiRead<T> request,
2386                         MultiListener<T> procedure) {
2387                 return syncRequest(request, new NoneToAsyncMultiListener<T>(procedure));
2388         }
2389
2390         final private <T> void syncRequest(final AsyncMultiRead<T> request,
2391                         final AsyncMultiReadProcedure<T> procedure) {
2392
2393                 assert (request != null);
2394                 assert (procedure != null);
2395
2396                 ListenerBase listener = getListenerBase(procedure);
2397
2398                 if (parent != null || listener != null) {
2399
2400 //                      Object syncParent = request;
2401
2402 //                      final ReadGraphImpl newGraph = newSync();
2403
2404                         processor.query(this, request, parent, procedure, listener);
2405
2406 //                      newGraph.waitAsync(syncParent);
2407                         waitAsyncProcedure(procedure);
2408
2409                 } else {
2410
2411 //                      Object syncParent = callerThread == Integer.MIN_VALUE ? null
2412 //                                      : request;
2413 //
2414 //                      final ReadGraphImpl newGraph = newSyncAsync(syncParent);
2415
2416                         try {
2417
2418 //                              inc();
2419 //                              ReadGraphImpl sync = newSync();
2420                                 request.perform(this, procedure);
2421 //                              sync.waitAsync(null);
2422                                 waitAsyncProcedure(procedure);
2423 //                              dec();
2424
2425                         } catch (Throwable t) {
2426
2427                                 waitAsyncProcedure(procedure);
2428 //                              dec();
2429
2430                         }
2431
2432                 }
2433
2434         }
2435         
2436         
2437         @Override
2438         final public <T> Collection<T> syncRequest(final AsyncMultiRead<T> request,
2439                         final AsyncMultiProcedure<T> procedure) {
2440
2441                 assert (request != null);
2442                 assert (procedure != null);
2443
2444                 ListenerBase listener = getListenerBase(procedure);
2445
2446                 if (parent != null || listener != null) {
2447
2448 //                      Object syncParent = request;
2449
2450 //                      final ReadGraphImpl newGraph = newSync();
2451
2452                         processor.query(this, request, parent, procedure, listener);
2453
2454 //                      newGraph.waitAsync(syncParent);
2455
2456                 } else {
2457
2458 //                      Object syncParent = request;
2459
2460 //                      final ReadGraphImpl newGraph = newSync();
2461
2462                         try {
2463
2464                                 request.perform(this, new AsyncMultiProcedure<T>() {
2465
2466                                         @Override
2467                                         public void execute(AsyncReadGraph graph, T result) {
2468                                                 procedure.execute(graph, result);
2469                                         }
2470
2471                                         @Override
2472                                         public void finished(AsyncReadGraph graph) {
2473                                                 procedure.finished(graph);
2474                                         }
2475
2476                                         @Override
2477                                         public void exception(AsyncReadGraph graph, Throwable t) {
2478                                                 procedure.exception(graph, t);
2479                                         }
2480
2481                                         @Override
2482                                         public String toString() {
2483                                                 return "syncRequest(AsyncMultiRead) -> " + procedure;
2484                                         }
2485
2486                                 });
2487
2488                         } catch (Throwable t) {
2489
2490                         }
2491
2492                 }
2493
2494                 // TODO!!
2495                 return null;
2496
2497         }
2498
2499         @Override
2500         public <T> Collection<T> syncRequest(AsyncMultiRead<T> request,
2501                         final SyncMultiProcedure<T> procedure) {
2502                 return syncRequest(request, new SyncToAsyncMultiProcedure<T>(procedure));
2503         }
2504
2505         @Override
2506         final public <T> Collection<T> syncRequest(final AsyncMultiRead<T> request,
2507                         final MultiProcedure<T> procedure) {
2508                 return syncRequest(request, new NoneToAsyncMultiProcedure<T>(procedure));
2509         }
2510
2511         @Override
2512         public <T> T syncRequest(final ExternalRead<T> request)
2513                         throws DatabaseException {
2514
2515                 assert (request != null);
2516
2517                 return syncRequest(request, new Procedure<T>() {
2518
2519                         @Override
2520                         public void execute(T t) {
2521                         }
2522
2523                         @Override
2524                         public void exception(Throwable t) {
2525                         }
2526
2527                         @Override
2528                         public String toString() {
2529                                 return "syncRequest(AsyncRead) -> " + request;
2530                         }
2531
2532                 });
2533
2534         }
2535
2536         @Override
2537         public <T> T syncRequest(ExternalRead<T> request, Listener<T> procedure) throws DatabaseException {
2538                 return syncRequest(request, (Procedure<T>) procedure);
2539         }
2540
2541         @Override
2542         final public <T> T syncRequest(final ExternalRead<T> request,
2543                         final Procedure<T> procedure) throws DatabaseException {
2544
2545                 assert (request != null);
2546
2547                 ListenerBase listener = getListenerBase(procedure);
2548
2549                 final DataContainer<Throwable> exception = new DataContainer<Throwable>();
2550                 final DataContainer<T> result = new DataContainer<T>();
2551
2552                 if (parent != null || listener != null) {
2553
2554 //                      final ReadGraphImpl newGraph = newSync();
2555                         
2556                         processor.query(this, request, parent, new Procedure<T>() {
2557
2558                                 @Override
2559                                 public void exception(Throwable throwable) {
2560                                         exception.set(throwable);
2561                                         procedure.exception(throwable);
2562                                 }
2563
2564                                 @Override
2565                                 public void execute(T t) {
2566                                         result.set(t);
2567                                         procedure.execute(t);
2568                                 }
2569
2570                         }, listener);
2571
2572 //                      newGraph.waitAsync(request);
2573
2574                 } else {
2575
2576                         try {
2577
2578                                 T t = processor.tryQuery(this, request);
2579                                 result.set(t);
2580                                 procedure.execute(t);
2581
2582                         } catch (Throwable t) {
2583
2584                             if (t instanceof DatabaseException) {
2585                                 exception.set((DatabaseException)t);
2586                                 procedure.exception(exception.get());
2587                             } else {
2588                                 exception.set(new DatabaseException(
2589                                         "Unexpected exception in ReadGraph.syncRequest(Read)",
2590                                         t));
2591                                 procedure.exception(exception.get());
2592                             }
2593
2594                         }
2595
2596                 }
2597
2598                 Throwable t = exception.get();
2599                 if (t != null) {
2600                         if (t instanceof DatabaseException)
2601                                 throw (DatabaseException) t;
2602                         else
2603                                 throw new DatabaseException(
2604                                                 "Unexpected exception in ReadGraph.syncRequest(Read)",
2605                                                 t);
2606                 }
2607
2608                 return result.get();            
2609
2610         }
2611
2612         @Override
2613         public void syncRequest(final Write request) throws DatabaseException {
2614
2615                 assert (request != null);
2616
2617                 throw new DatabaseException(
2618                                 "Write operations are not supported during read transactions!");
2619
2620         }
2621
2622         @Override
2623         public <T> T syncRequest(final WriteResult<T> request) throws DatabaseException {
2624
2625                 assert (request != null);
2626
2627                 throw new DatabaseException(
2628                                 "Write operations are not supported during read transactions!");
2629
2630         }
2631
2632         @Override
2633         public void syncRequest(final DelayedWrite request)
2634                         throws DatabaseException {
2635
2636                 assert (request != null);
2637
2638                 throw new DatabaseException(
2639                                 "Write operations are not supported during read transactions!");
2640
2641         }
2642
2643         @Override
2644         public <T> T syncRequest(final DelayedWriteResult<T> request) throws DatabaseException {