]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.db.services/src/org/simantics/db/services/adaption/AdaptionService2.java
Merge branch 'private/db-threads' into private/threads-testing
[simantics/platform.git] / bundles / org.simantics.db.services / src / org / simantics / db / services / adaption / AdaptionService2.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.services.adaption;
13
14 import gnu.trove.map.hash.THashMap;
15 import gnu.trove.procedure.TObjectObjectProcedure;
16 import gnu.trove.set.hash.THashSet;
17
18 import org.simantics.db.AsyncReadGraph;
19 import org.simantics.db.ReadGraph;
20 import org.simantics.db.Resource;
21 import org.simantics.db.adaption.Adapter;
22 import org.simantics.db.adaption.AdaptionService;
23 import org.simantics.db.common.procedure.BlockingAsyncProcedure;
24 import org.simantics.db.common.procedure.adapter.TransientCacheAsyncListener;
25 import org.simantics.db.common.procedure.single.SyncReadProcedure;
26 import org.simantics.db.common.request.BinaryRead;
27 import org.simantics.db.common.request.ReadRequest;
28 import org.simantics.db.common.request.TernaryRead;
29 import org.simantics.db.common.uri.ResourceToURI;
30 import org.simantics.db.common.utils.NameUtils;
31 import org.simantics.db.exception.AdaptionException;
32 import org.simantics.db.exception.DatabaseException;
33 import org.simantics.db.exception.ServiceException;
34 import org.simantics.db.exception.ValidationException;
35 import org.simantics.db.procedure.AsyncProcedure;
36 import org.simantics.db.request.AsyncRead;
37 import org.simantics.db.request.Read;
38 import org.simantics.layer0.Layer0;
39 import org.simantics.utils.datastructures.Pair;
40
41 public class AdaptionService2 implements AdaptionService {
42
43     THashMap<Pair<Class<?>,Class<?>>, AdapterDeclaration<?>> adapters =
44         new THashMap<Pair<Class<?>,Class<?>>, AdapterDeclaration<?>>();
45
46     /**
47      * Contains all adapter declarations and definitions for one class (clazz).
48      */
49     static class AdapterDeclaration<T> {
50         Class<T> clazz;
51         THashMap<Resource, Adapter<T,?>> typeAdapters =
52             new THashMap<Resource, Adapter<T,?>>();
53         THashMap<Resource, Adapter<T,?>> instanceAdapters =
54             new THashMap<Resource, Adapter<T,?>>();
55         THashSet<Resource> baseTypes = new THashSet<Resource>();
56
57         String getDescription(final ReadGraph g) {
58             final StringBuilder b = new StringBuilder();
59             b.append("The following adapters have been defined for ");
60             b.append(clazz.getCanonicalName());
61             b.append("\n");
62             typeAdapters.forEachEntry(new TObjectObjectProcedure<Resource, Adapter<T,?>>() {
63
64                 @Override
65                 public boolean execute(Resource arg0, Adapter<T,?> arg1) {
66                     b.append("    type ");
67                     try {
68                         b.append(g.syncRequest(new ResourceToURI(arg0)));
69                     } catch (DatabaseException e) {
70                         e.printStackTrace();
71                     }
72                     b.append(" : ");
73                     b.append(arg1);
74                     b.append('\n');
75                     return true;
76                 }
77
78             });
79
80             synchronized (this) {
81                 instanceAdapters.forEachEntry(new TObjectObjectProcedure<Resource, Adapter<T,?>>() {
82
83                     @Override
84                     public boolean execute(Resource arg0, Adapter<T,?> arg1) {
85                         b.append("    resource ");
86                         try {
87                             b.append(g.syncRequest(new ResourceToURI(arg0)));
88                         } catch (DatabaseException e) {
89                             e.printStackTrace();
90                         }
91                         b.append(" : ");
92                         b.append(arg1);
93                         b.append('\n');
94                         return true;
95                     }
96
97                 });
98             }
99             return b.toString();
100         }
101
102         public AdapterDeclaration(Class<T> clazz) {
103             this.clazz = clazz;
104         }
105
106         static class AdapterResult<T,C> {
107             Adapter<T,C> adapter;
108             Resource type;
109
110             public AdapterResult(Adapter<T,C> adapter, Resource type) {
111                 this.adapter = adapter;
112                 this.type = type;
113             }
114         }
115
116         /**
117          * The query returns the adapter inherited by the parameter type.
118          * The query is used only in the case, the type itself does not have
119          * an adapter. The second component of the result contains the type
120          * that originally contributed the adapter.
121          */
122         static class GetInheritedAdapter<T,C> extends BinaryRead<Resource, AdapterDeclaration<T>, AdapterResult<T,C>>  {
123
124             public GetInheritedAdapter(Resource type, AdapterDeclaration<T> decl) {
125                 super(type, decl);
126             }
127
128             AdapterDeclaration<T> getDeclaration() {
129                 return parameter2;
130             }
131
132             @Override
133             public String toString() {
134                 return "GetInheritedAdapter|" + parameter + "|" + parameter2;
135             }
136
137             @SuppressWarnings("unchecked")
138             @Override
139             public AdapterResult<T,C> perform(ReadGraph g) throws DatabaseException {
140                 Layer0 b = Layer0.getInstance(g);
141                 AdapterResult<T,C> result = null;
142                 for(Resource supertype : g.getObjects(parameter, b.Inherits)) {
143                     Adapter<T,C> adapter = (Adapter<T,C>)parameter2.typeAdapters.get(supertype);
144                     if(adapter != null) {
145                         if(result == null)
146                             result = new AdapterResult<T,C>(adapter, supertype);
147                         else if(!result.type.equals(supertype) &&
148                                 !g.isInheritedFrom(result.type, supertype)) {
149                             if(g.isInheritedFrom(supertype, result.type))
150                                 result = new AdapterResult<T,C>(adapter, supertype);
151                             else throw new AdaptionException("Type " +
152                                     safeName(g, parameter) + " inherits conflicting adapters from "
153                                     + safeName(g, supertype) + " and " + safeName(g, result.type));
154                         }
155                     }
156                     else {
157                         AdapterResult<T,C> temp =
158                             g.syncRequest(new GetInheritedAdapter<T, C>(supertype, parameter2), TransientCacheAsyncListener.<AdapterResult<T,C>>instance());
159                         if(temp != null) {
160                             if(result == null)
161                                 result = temp;
162                             else if(!result.type.equals(temp.type) &&
163                                     !g.isInheritedFrom(result.type, temp.type)) {
164                                 if(g.isInheritedFrom(temp.type, result.type))
165                                     result = temp;
166                                 else throw new AdaptionException("Type " +
167                                         safeName(g, parameter) + " inherits conflicting adapters from "
168                                         + safeName(g, temp.type) + " and " + safeName(g, result.type));
169                             }
170                         }
171                     }
172                 }
173                 return result;
174             }
175
176         }
177
178         <C> void inheritedAdapter(AsyncReadGraph graph, Resource type, AsyncProcedure<AdapterResult<T,C>> procedure) {
179             graph.asyncRequest(new GetInheritedAdapter<T, C>(type, this), procedure);
180         }
181
182         Adapter<T,?> directAdapter(Resource r) {
183             Adapter<T,?> ret;
184             synchronized (this) {
185                 ret = instanceAdapters.get(r);
186             }
187             return ret;
188         }
189
190         static class FindAdapter<T,C> extends BinaryRead<Resource, AdapterDeclaration<T>, Adapter<T,C>> {
191
192             public FindAdapter(Resource resource, AdapterDeclaration<T> decl) {
193                 super(resource, decl);
194             }
195             
196             @SuppressWarnings("unchecked")
197             Adapter<T,C> findAdapter(Resource r, ReadGraph g) throws DatabaseException {
198
199                 {
200                     Adapter<T,C> adapter;
201                     synchronized (this) {
202                         adapter = (Adapter<T,C>)parameter2.instanceAdapters.get(r);
203                     }
204                     if(adapter != null)
205                         return adapter;
206                 }
207
208                 Layer0 b = Layer0.getInstance(g);
209
210                 /*
211                  * Try to find adapter from immediate types
212                  */
213                 AdapterResult<T,C> adapterResult = null;
214                 for(Resource t : g.getObjects(r, b.InstanceOf)) {
215                     Adapter<T,C> adapter = (Adapter<T,C>)parameter2.typeAdapters.get(t);
216                     if(adapter != null) {
217                         if(adapterResult == null)
218                             adapterResult = new AdapterResult<T,C>(adapter, t);
219                         else if(!adapterResult.type.equals(t) &&
220                                 !g.isInheritedFrom(adapterResult.type, t)) {
221                             if(g.isInheritedFrom(t, adapterResult.type))
222                                 adapterResult = new AdapterResult<T,C>(adapter, t);
223                             else throw new AdaptionException("Resource " +
224                                     safeName(g, r) + " has conflicting " + parameter2.clazz + "-adapters from "
225                                     + safeName(g, t) + " and " + safeName(g, adapterResult.type)
226                             );
227                         }
228                     }
229                     else {
230                         AdapterResult<T,C> temp =
231                             g.syncRequest(new GetInheritedAdapter<T, C>(t, parameter2), TransientCacheAsyncListener.<AdapterResult<T,C>>instance());
232                         if(temp != null) {
233                             if(adapterResult == null)
234                                 adapterResult = temp;
235                             else if(!adapterResult.type.equals(temp.type) &&
236                                     !g.isInheritedFrom(adapterResult.type, temp.type)) {
237                                 if(g.isInheritedFrom(temp.type, adapterResult.type))
238                                     adapterResult = temp;
239                                 else throw new AdaptionException("Resource " +
240                                         safeName(g, r) + " has conflicting " + parameter2.clazz + "-adapters from "
241                                         + safeName(g, temp.type) + " and " + safeName(g, adapterResult.type)
242                                 );
243                             }
244                         }
245                     }
246                 }
247
248                 if(adapterResult != null)
249                     return adapterResult.adapter;
250
251                 for(Resource t : g.getObjects(r, b.Inherits)) {
252                     Adapter<T,C> adapter = findAdapter(t, g);
253                     if(adapter != null)
254                         return adapter;
255                 }
256
257                 for(Resource t : g.getObjects(r, b.SubrelationOf)) {
258                     Adapter<T,C> adapter = findAdapter(t, g);
259                     if(adapter != null)
260                         return adapter;
261                 }
262
263                 return null;
264
265             }
266
267                         
268             @Override
269             public Adapter<T,C> perform(ReadGraph g) throws DatabaseException {
270                 return (Adapter<T, C>)findAdapter(parameter, g);
271             }
272                 
273         }
274         
275         /**
276          * The query returns either an adapter or adapted for the given
277          * resource. It is assumed that the resource itself does not
278          * have adapted.
279          */
280         class Adapt<C> implements Read<T> {
281
282             Resource resource;
283             C context;
284
285             public Adapt(Resource resource, C context) {
286                 this.resource = resource;
287                 this.context = context;
288             }
289
290             AdapterDeclaration<T> getDeclaration() {
291                 return AdapterDeclaration.this;
292             }
293
294             @SuppressWarnings("unchecked")
295             Adapter<T,C> findAdapter(Resource r, ReadGraph g) throws DatabaseException {
296
297                 {
298                     Adapter<T,C> adapter;
299                     synchronized (this) {
300                         adapter = (Adapter<T,C>)instanceAdapters.get(r);
301                     }
302                     if(adapter != null)
303                         return adapter;
304                 }
305
306                 Layer0 b = Layer0.getInstance(g);
307
308                 /*
309                  * Try to find adapter from immediate types
310                  */
311                 AdapterResult<T,C> adapterResult = null;
312                 for(Resource t : g.getObjects(r, b.InstanceOf)) {
313                     Adapter<T,C> adapter = (Adapter<T,C>)typeAdapters.get(t);
314                     if(adapter != null) {
315                         if(adapterResult == null)
316                             adapterResult = new AdapterResult<T,C>(adapter, t);
317                         else if(!adapterResult.type.equals(t) &&
318                                 !g.isInheritedFrom(adapterResult.type, t)) {
319                             if(g.isInheritedFrom(t, adapterResult.type))
320                                 adapterResult = new AdapterResult<T,C>(adapter, t);
321                             else throw new AdaptionException("Resource " +
322                                     safeName(g, r) + " has conflicting " + clazz + "-adapters from "
323                                     + safeName(g, t) + " and " + safeName(g, adapterResult.type)
324                             );
325                         }
326                     }
327                     else {
328                         AdapterResult<T,C> temp =
329                             g.syncRequest(new GetInheritedAdapter<T, C>(t, AdapterDeclaration.this));
330                         if(temp != null) {
331                             if(adapterResult == null)
332                                 adapterResult = temp;
333                             else if(!adapterResult.type.equals(temp.type) &&
334                                     !g.isInheritedFrom(adapterResult.type, temp.type)) {
335                                 if(g.isInheritedFrom(temp.type, adapterResult.type))
336                                     adapterResult = temp;
337                                 else throw new AdaptionException("Resource " +
338                                         safeName(g, r) + " has conflicting " + clazz + "-adapters from "
339                                         + safeName(g, temp.type) + " and " + safeName(g, adapterResult.type)
340                                 );
341                             }
342                         }
343                     }
344                 }
345
346                 if(adapterResult != null)
347                     return adapterResult.adapter;
348
349                 for(Resource t : g.getObjects(r, b.Inherits)) {
350                     Adapter<T,C> adapter = findAdapter(t, g);
351                     if(adapter != null)
352                         return adapter;
353                 }
354
355                 for(Resource t : g.getObjects(r, b.SubrelationOf)) {
356                     Adapter<T,C> adapter = findAdapter(t, g);
357                     if(adapter != null)
358                         return adapter;
359                 }
360
361                 return null;
362
363             }
364
365             @Override
366             public T perform(ReadGraph g) throws DatabaseException {
367
368                 final Adapter<T,C> adapter = (Adapter<T, C>)findAdapter(resource, g);
369                 if(adapter == null) return null;
370                 else return g.syncRequest(new AsyncRead<T>() {
371
372                     @Override
373                     public void perform(AsyncReadGraph graph, AsyncProcedure<T> procedure) {
374 //                      System.out.println("adapter=" + adapter);
375                         adapter.adapt(graph, resource, context, procedure);
376                     }
377
378                     @Override
379                             public int threadHash() {
380                                 return hashCode();
381                             }
382
383                     @Override
384                     public int getFlags() {
385                         return 0;
386                     }
387
388                 });
389
390             }
391
392             @SuppressWarnings("rawtypes")
393             @Override
394             public boolean equals(Object other) {
395
396                 if (this == other)
397                     return true;
398                 else if (other == null)
399                     return false;
400                 else if (other.getClass() != Adapt.class)
401                     return false;
402
403                 return ((Adapt)other).resource.equals(resource)
404                 && ((Adapt)other).context.equals(context)
405                 && ((Adapt)other).getDeclaration()==getDeclaration();
406
407             }
408
409             @Override
410             public int hashCode() {
411                 return resource.hashCode() + 31*((getClass().hashCode() + 41*(context.hashCode()) + 
412                         71*getDeclaration().hashCode()));
413             }
414
415         }
416
417 //        void adapt2(AsyncReadGraph graph, Resource r, AsyncProcedure<T> procedure) {
418 //            graph.asyncRequest(new Adapt(r), procedure);
419 //        }
420
421         <C> Adapter<T,C> findAdapter(ReadGraph g, Resource r, boolean possible) throws DatabaseException {
422
423             Adapter<T,C> result = g.syncRequest(new FindAdapter<T,C>(r, AdapterDeclaration.this));
424             if(result != null) return result;
425
426             if (possible)
427                 return null;
428
429             /*
430              * We couldn't adapt the resource. We analyze the situation little for
431              * better error message.
432              */
433             for(Resource dt : baseTypes) {
434                 if(g.isInstanceOf(r, dt)) {
435                     throw new AdaptionException("Couldn't find a " + clazz + "-adapter for resource " +
436                             safeName(g, r) + " although it is instance of " +
437                             safeName(g, dt) + "\n" +
438                             getDescription(g));
439                 }
440             }
441             throw new AdaptionException("Couldn't find a " + clazz + "-adapter for resource " +
442                     safeName(g, r) +
443                     ". This is because the resource is not instance of any type which the adapter is declared to.\n" +
444                     getDescription(g));
445
446         }
447         
448         <C> T adapt(ReadGraph g, Resource r, C context, boolean possible) throws DatabaseException {
449
450             T result = g.syncRequest(new Adapt<C>(r,context));
451             if(result != null) return result;
452
453             if (possible)
454                 return null;
455
456             /*
457              * We couldn't adapt the resource. We analyze the situation little for
458              * better error message.
459              */
460             for(Resource dt : baseTypes) {
461                 if(g.isInstanceOf(r, dt)) {
462                     throw new AdaptionException("Couldn't find a " + clazz + "-adapter for resource " +
463                             safeName(g, r) + " although it is instance of " +
464                             safeName(g, dt) + "\n" +
465                             getDescription(g));
466                 }
467             }
468             throw new AdaptionException("Couldn't find a " + clazz + "-adapter for resource " +
469                     safeName(g, r) +
470                     ". This is because the resource is not instance of any type which the adapter is declared to.\n" +
471                     getDescription(g));
472
473         }
474
475         T adaptNew(ReadGraph g, final Resource r, boolean possible) throws DatabaseException {
476
477             T result = new Adapt<Resource>(r,r).perform(g);
478             if (result != null)
479                 return result;
480
481             if (possible)
482                 return null;
483
484             for(Resource dt : baseTypes) {
485                 if(g.isInstanceOf(r, dt)) {
486                     throw new AdaptionException("Couldn't find a " + clazz + "-adapter for resource " +
487                             safeName(g, r) + " although it is instance of " +
488                             safeName(g, dt) + "\n" +
489                             getDescription(g));
490                 }
491             }
492             throw new AdaptionException("Couldn't find a " + clazz + "-adapter for resource " +
493                     safeName(g, r) +
494                     ". This is because the resource is not instance of any type which the adapter is declared to.\n" +
495                     getDescription(g));
496
497         }
498
499     }
500
501     private <T> AdapterDeclaration<T> getDeclaration(Class<T> targetClass, Class<?> contextClass) {
502         Pair<Class<?>,Class<?>> key = new Pair<Class<?>,Class<?>>(targetClass, contextClass);
503         @SuppressWarnings("unchecked")
504         AdapterDeclaration<T> decl =
505             (AdapterDeclaration<T>)adapters.get(key);
506         if(decl == null) {
507             decl = new AdapterDeclaration<T>(targetClass);
508             adapters.put(key, decl);
509         }
510         return decl;
511     }
512
513     public <T,C> void getAdapter(AsyncReadGraph graph, final Resource r, final Class<C> contextClass, final Class<T> targetClass, final boolean possible, final AsyncProcedure<Adapter<T,C>> procedure) {
514         
515         final Pair<Class<T>, Class<?>> key = new Pair<Class<T>, Class<?>>(targetClass, contextClass); 
516         @SuppressWarnings("unchecked")
517         final AdapterDeclaration<T> decl = (AdapterDeclaration<T>)adapters.get(key);
518         if(decl == null) {
519
520             if(possible) {
521                 procedure.execute(graph, null);
522             } else {
523                 procedure.exception(graph, new AdaptionException("There are no adapters declared or defined for class " + targetClass + "."));
524             }
525
526         } else {
527
528             @SuppressWarnings("unchecked")
529             final Adapter<T,C> adapter = (Adapter<T,C>)decl.directAdapter(r);
530             if(adapter != null) {
531                 procedure.execute(graph, adapter);
532             } else {
533                 graph.forPossibleObject(r, graph.getService(Layer0.class).InstanceOf, new AsyncProcedure<Resource>() {
534
535                     @Override
536                     public void exception(AsyncReadGraph graph, Throwable throwable) {
537                         procedure.exception(graph, new AdaptionException("Problems in reading types for resource. ", throwable));
538                     }
539
540                     @Override
541                     public void execute(AsyncReadGraph graph, final Resource singleType) {
542                         if(singleType != null) {
543                             getSingleTypeAdapter(graph, decl, key, r, singleType, possible, procedure);
544                         } else {
545                             getSingleSuperTypeAdapter(graph, decl, key, r, r, possible, procedure);
546                         }
547                     }
548
549                 });
550             }
551
552         }
553         
554     }
555     
556     @Override
557     public <T,C> void adapt(AsyncReadGraph graph, final Resource r, final C context, Class<C> contextClass, Class<T> targetClass, final boolean possible, final AsyncProcedure<T> procedure) {
558
559         getAdapter(graph, r, contextClass, targetClass, possible, new AsyncProcedure<Adapter<T,C>>() {
560
561                         @Override
562                         public void execute(AsyncReadGraph graph, Adapter<T, C> result) {
563                                 if(result == null) {
564                                         if(possible) {
565                                                 procedure.execute(graph, null);
566                                         } else {
567                                                 procedure.exception(graph, new AdaptionException("Internal error. getAdapter returned null and possible was false."));
568                                         }
569                                 } else {
570                                         result.adapt(graph, r, context, procedure);
571                                 }
572                         }
573
574                         @Override
575                         public void exception(AsyncReadGraph graph, Throwable throwable) {
576                                 procedure.exception(graph, throwable);
577                         }
578                 
579         });
580
581     }
582     
583     @Override
584     public <T, C> T adapt(ReadGraph g, Resource r, C context, Class<C> contextClass, Class<T> targetClass, boolean possible) throws DatabaseException {
585
586         Adapter<T,C> adapter = getAdapter(g, r, context, contextClass, targetClass, possible);
587         if(adapter == null) return null;
588         
589         BlockingAsyncProcedure<T> ap = new BlockingAsyncProcedure<T>(g, null, adapter);
590         adapter.adapt(g, r, context, ap);
591         return ap.get();
592         
593     }
594     
595     private <T, C> Adapter<T,C> getAdapter(ReadGraph g, Resource r, C context, Class<C> contextClass, Class<T> targetClass, boolean possible) throws DatabaseException {
596         
597         final Pair<Class<T>, Class<?>> key = new Pair<Class<T>, Class<?>>(targetClass, contextClass); 
598         @SuppressWarnings("unchecked")
599         final AdapterDeclaration<T> decl = (AdapterDeclaration<T>)adapters.get(key);
600         if(decl == null) {
601
602             if(possible) return null;
603             else throw new AdaptionException("There are no adapters declared or defined for class " + targetClass + ".");
604
605         } else {
606
607             @SuppressWarnings("unchecked")
608             final Adapter<T,C> adapter = (Adapter<T,C>)decl.directAdapter(r);
609             if(adapter != null) return adapter;
610             
611             Layer0 L0 = Layer0.getInstance(g);
612             Resource singleType = g.getPossibleObject(r, L0.InstanceOf);
613             if(singleType != null) {
614                 return getSingleTypeAdapter(g, decl, key, r, singleType, possible);
615             } else {
616                 return getSingleSuperTypeAdapter(g, decl, key, r, r, possible);
617             }
618
619         }       
620         
621     }
622
623     private static class SingleTypeAdapter<T, C> extends TernaryRead<Pair<Class<T>, Class<?>>, Resource, Boolean, Adapter<T,C>> {
624
625         final private AdapterDeclaration<T> decl;
626         
627         SingleTypeAdapter(AdapterDeclaration<T> decl, Pair<Class<T>, Class<?>> key, Resource instance, Boolean possible) {
628                 super(key, instance, possible);
629                 this.decl = decl;
630         }
631         
632         @Override
633         public Adapter<T,C> perform(ReadGraph graph) throws DatabaseException {
634             return decl.findAdapter(graph, parameter2, parameter3);
635         }
636
637     }
638     
639     private <T,C> void getSingleTypeAdapter(AsyncReadGraph graph, final AdapterDeclaration<T> decl, final Pair<Class<T>, Class<?>> key, final Resource instance, final Resource type, final boolean possible, final AsyncProcedure<Adapter<T,C>> procedure) {
640
641         @SuppressWarnings("unchecked")
642         Adapter<T,C> adapter = (Adapter<T,C>)decl.typeAdapters.get(type);
643         if(adapter != null) {
644                 procedure.execute(graph, adapter);
645         } else {
646             graph.forPossibleObject(type, graph.getService(Layer0.class).Inherits, new AsyncProcedure<Resource>() {
647
648                 @Override
649                 public void exception(AsyncReadGraph graph, Throwable throwable) {
650                     procedure.exception(graph, new AdaptionException("Problems in reading super types for resource. ", throwable));
651                 }
652
653                 @Override
654                 public void execute(AsyncReadGraph graph, Resource singleSuperType) {
655
656                     if(singleSuperType != null) {
657                         getSingleTypeAdapter(graph, decl, key, instance, singleSuperType, possible, procedure);
658                     } else {
659                         graph.asyncRequest(new SingleTypeAdapter<T,C>(decl, key, instance, possible), procedure);
660                     }
661
662                 }
663
664             });
665
666
667         }
668
669     }
670     
671     private <T,C> Adapter<T,C> getSingleTypeAdapter(ReadGraph graph, final AdapterDeclaration<T> decl, final Pair<Class<T>, Class<?>> key, final Resource instance, final Resource type, final boolean possible) throws DatabaseException {
672
673         @SuppressWarnings("unchecked")
674         Adapter<T,C> adapter = (Adapter<T,C>)decl.typeAdapters.get(type);
675         if(adapter != null) return adapter;
676         
677         Layer0 L0 = Layer0.getInstance(graph);
678         Resource singleSuperType = graph.getPossibleObject(type, L0.Inherits);
679         if(singleSuperType != null) {
680             return getSingleTypeAdapter(graph, decl, key, instance, singleSuperType, possible);
681         } else {
682             return graph.syncRequest(new SingleTypeAdapter<T,C>(decl, key, instance, possible), TransientCacheAsyncListener.<Adapter<T,C>>instance());
683         }
684
685     }    
686     
687 //    private <T,C> void adaptSingleType(AsyncReadGraph graph, final AdapterDeclaration<T> decl, final C context, final Resource instance, final Resource type, final boolean possible, final AsyncProcedure<T> procedure) {
688 //
689 //        @SuppressWarnings("unchecked")
690 //        Adapter<T,C> adapter = (Adapter<T,C>)decl.typeAdapters.get(type);
691 //        if(adapter != null) {
692 //
693 //            adapter.adapt(graph, instance, context, procedure);
694 //
695 //        } else {
696 //
697 //            graph.forPossibleObject(type, graph.getService(Layer0.class).Inherits, new AsyncProcedure<Resource>() {
698 //
699 //                @Override
700 //                public void exception(AsyncReadGraph graph, Throwable throwable) {
701 //
702 //                    procedure.exception(graph, new AdaptionException("Problems in reading super types for resource. ", throwable));
703 //
704 //                }
705 //
706 //                @Override
707 //                public void execute(AsyncReadGraph graph, Resource singleSuperType) {
708 //
709 //                    if(singleSuperType != null) {
710 //
711 //                        adaptSingleType(graph, decl, context, instance, singleSuperType, possible, procedure);
712 //
713 //                    } else {
714 //
715 //                        graph.asyncRequest(new Read<T>() {
716 //
717 //                            @Override
718 //                            public T perform(ReadGraph graph)
719 //                            throws DatabaseException {
720 //                                return decl.adapt(graph, instance, context, possible);
721 //                            }
722 //
723 //                        }, procedure);
724 //
725 //                    }
726 //
727 //                }
728 //
729 //            });
730 //
731 //
732 //        }
733 //
734 //    }
735
736     
737     private static class SingleSuperTypeAdapter<T, C> extends TernaryRead<Pair<Class<T>, Class<?>>, Resource, Boolean, Adapter<T,C>> {
738
739         final private AdapterDeclaration<T> decl;
740         
741         SingleSuperTypeAdapter(AdapterDeclaration<T> decl, Pair<Class<T>, Class<?>> key, Resource type, Boolean possible) {
742                 super(key, type, possible);
743                 this.decl = decl;
744         }
745         
746         @Override
747         public Adapter<T,C> perform(ReadGraph graph) throws DatabaseException {
748             return decl.findAdapter(graph, parameter2, parameter3);
749         }
750
751     }
752     
753     private <T,C> void getSingleSuperTypeAdapter(AsyncReadGraph graph, final AdapterDeclaration<T> decl, final Pair<Class<T>, Class<?>> key, final Resource type, final Resource superType, final boolean possible, final AsyncProcedure<Adapter<T,C>> procedure) {
754
755         @SuppressWarnings("unchecked")
756         Adapter<T, C> adapter = (Adapter<T, C>)decl.instanceAdapters.get(superType);
757         if(adapter != null) {
758                 procedure.execute(graph, adapter);
759         } else {
760
761             graph.forPossibleObject(superType, graph.getService(Layer0.class).Inherits, new AsyncProcedure<Resource>() {
762
763                 @Override
764                 public void exception(AsyncReadGraph graph, Throwable throwable) {
765                     procedure.exception(graph, new AdaptionException("Problems in reading super types for resource. ", throwable));
766                 }
767
768                 @Override
769                 public void execute(AsyncReadGraph graph, Resource singleSuperType) {
770
771                     if(singleSuperType != null) {
772
773                         getSingleSuperTypeAdapter(graph, decl, key, type, singleSuperType, possible, procedure);
774
775                     } else {
776
777                         graph.asyncRequest(new SingleSuperTypeAdapter<T,C>(decl, key, type, possible), procedure);
778
779                     }
780
781                 }
782
783             });
784
785         }
786
787     }
788
789     private <T,C> Adapter<T,C> getSingleSuperTypeAdapter(ReadGraph graph, final AdapterDeclaration<T> decl, final Pair<Class<T>, Class<?>> key, final Resource type, final Resource superType, final boolean possible) throws DatabaseException {
790
791         @SuppressWarnings("unchecked")
792         Adapter<T, C> adapter = (Adapter<T, C>)decl.instanceAdapters.get(superType);
793         if(adapter != null) return adapter;
794         
795         Layer0 L0 = Layer0.getInstance(graph);
796         Resource singleSuperType = graph.getPossibleObject(superType, L0.Inherits);
797         if(singleSuperType != null) {
798                 return getSingleSuperTypeAdapter(graph, decl, key, type, singleSuperType, possible);
799         } else {
800                 return graph.syncRequest(new SingleSuperTypeAdapter<T,C>(decl, key, type, possible));
801         }
802
803     }
804     
805 //    private <T,C> void adaptSingleSupertype(AsyncReadGraph graph, final AdapterDeclaration<T> decl, final C context, final Resource type, final Resource superType, final boolean possible, final AsyncProcedure<T> procedure) {
806 //
807 //        @SuppressWarnings("unchecked")
808 //        Adapter<T, C> adapter = (Adapter<T, C>)decl.instanceAdapters.get(superType);
809 //        if(adapter != null) {
810 //
811 //            adapter.adapt(graph, type, context, procedure);
812 //
813 //        } else {
814 //
815 //            graph.forPossibleObject(superType, graph.getService(Layer0.class).Inherits, new AsyncProcedure<Resource>() {
816 //
817 //                @Override
818 //                public void exception(AsyncReadGraph graph, Throwable throwable) {
819 //
820 //                    procedure.exception(graph, new AdaptionException("Problems in reading super types for resource. ", throwable));
821 //
822 //                }
823 //
824 //                @Override
825 //                public void execute(AsyncReadGraph graph, Resource singleSuperType) {
826 //
827 //                    if(singleSuperType != null) {
828 //
829 //                        adaptSingleSupertype(graph, decl, context, type, singleSuperType, possible, procedure);
830 //
831 //                    } else {
832 //
833 //                        graph.asyncRequest(new Read<T>() {
834 //
835 //                            @Override
836 //                            public T perform(ReadGraph graph)
837 //                            throws DatabaseException {
838 //                                return decl.adapt(graph, type, context, possible);
839 //                            }
840 //
841 //                        }, procedure);
842 //
843 //                    }
844 //
845 //                }
846 //
847 //            });
848 //
849 //        }
850 //
851 //    }
852
853     @Override
854     public <T> void adaptNew(AsyncReadGraph g, final Resource r, final Class<T> clazz, final boolean possible, final AsyncProcedure<T> procedure) {
855
856         g.asyncRequest(new ReadRequest() {
857
858             @Override
859             public void run(ReadGraph graph) throws DatabaseException {
860
861                 final Pair<Class<T>, Class<?>> key = new Pair<Class<T>, Class<?>>(clazz, Resource.class); 
862
863                 @SuppressWarnings("unchecked")
864                 AdapterDeclaration<T> decl =
865                     (AdapterDeclaration<T>)adapters.get(key);
866
867                 if(decl == null) {
868                     if(possible) {
869                         procedure.execute(graph, null);
870                     } else {
871                         procedure.exception(graph, new AdaptionException("There are no adapters declared or defined for class " + clazz + "."));
872                     }
873                 } else {
874                     try {
875                         procedure.execute(graph, decl.adaptNew(graph, r, possible));
876                     } catch (AdaptionException e) {
877                         if(possible) {
878                             procedure.execute(graph, null);
879                         } else {
880                             procedure.exception(graph, e);
881                         }
882                     } catch (ValidationException e) {
883                         procedure.exception(graph, e);
884                     } catch (DatabaseException e2) {
885                         procedure.exception(graph, new ServiceException(e2));
886                     }
887                 }
888
889             }
890
891         });
892
893     }
894
895     @Override
896     public <T> void addInstanceAdapter(Resource resource, Class<T> targetClass, Adapter<T,?> adapter) {
897         addInstanceAdapter(resource, targetClass, Resource.class, adapter);
898     }
899
900     @Override
901     public <T> void addInstanceAdapter(Resource resource, Class<T> targetClass, Class<?> contextClass, Adapter<T,?> adapter) {
902         synchronized (this) {
903             getDeclaration(targetClass, contextClass).instanceAdapters.put(resource, adapter);
904         }
905     }
906
907     @Override
908     public <T> Adapter<T,?> removeInstanceAdapter(Resource resource, Class<T> targetClass) {
909         return removeInstanceAdapter(resource, targetClass, Resource.class);
910     }
911     
912     @Override
913     public <T> Adapter<T,?> removeInstanceAdapter(Resource resource, Class<T> targetClass, Class<?> contextClass) {
914         synchronized (this) {
915             return getDeclaration(targetClass, contextClass).instanceAdapters.remove(resource);
916         }
917     }
918
919     @Override
920     public <T> void removeInstanceAdapter(Resource resource, Class<T> targetClass, Adapter<T,?> adapter) {
921         removeInstanceAdapter(resource, targetClass, Resource.class, adapter);
922     }
923
924     @Override
925     public <T> void removeInstanceAdapter(Resource resource, Class<T> targetClass, Class<?> contextClass, Adapter<T,?> adapter) {
926         synchronized (this) {
927             AdapterDeclaration<T> decl = getDeclaration(targetClass, contextClass);
928             Adapter<T,?> existing = decl.instanceAdapters.get(resource);
929             if (existing == adapter) {
930                 decl.instanceAdapters.remove(resource);
931             }
932         }
933     }
934
935     @Override
936     public <T> void addAdapter(Resource type, Class<T> targetClass, Adapter<T,?> adapter) {
937         addAdapter(type, targetClass, Resource.class, adapter);
938     }
939
940     @Override
941     public <T> void addAdapter(Resource type, Class<T> targetClass, Class<?> contextClass, Adapter<T,?> adapter) {
942         getDeclaration(targetClass, contextClass).typeAdapters.put(type, adapter);
943     }
944
945     @Override
946     public <T> void declareAdapter(Resource type, Class<T> targetClass) {
947         declareAdapter(type, targetClass, Resource.class);
948     }
949
950     @Override
951     public <T> void declareAdapter(Resource type, Class<T> targetClass, Class<?> contextClass) {
952         getDeclaration(targetClass, contextClass).baseTypes.add(type);
953     }
954
955     public static String safeName(ReadGraph g, Resource r) throws DatabaseException {
956 //        Builtins b = g.getBuiltins();
957 //        for(Resource name : g.getObjects(r, b.HasName))
958 //            return g.getValue(name);
959 //        for(Resource t : g.getObjects(r, b.InstanceOf))
960 //            for(Resource name : g.getObjects(t, b.HasName))
961 //                return ": "+ g.getValue(name);
962 //        for(Resource t : g.getObjects(r, b.Inherits))
963 //            for(Resource name : g.getObjects(t, b.HasName))
964 //                return "<T "+ g.getValue(name);
965 //        for(Resource t : g.getObjects(r, b.SubrelationOf))
966 //            for(Resource name : g.getObjects(t, b.HasName))
967 //                return "<R "+ g.getValue(name);
968 //        if(g.hasValue(r))
969 //            return "\"" + g.getValue(r) + "\"";
970 //        return "" + r.getResourceId();
971         return NameUtils.getSafeName(g, r, true);
972     }
973
974 }