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