]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.db.services/src/org/simantics/db/services/adaption/AdaptionService2.java
Still working for multiple readers
[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>(null, adapter);
590         
591 //              SyncReadProcedure<T> procedure = new SyncReadProcedure<T>();
592         adapter.adapt(g, r, context, ap);
593         return ap.get();
594 //              procedure.checkAndThrow();
595 //              return procedure.result;
596         
597     }
598     
599     private <T, C> Adapter<T,C> getAdapter(ReadGraph g, Resource r, C context, Class<C> contextClass, Class<T> targetClass, boolean possible) throws DatabaseException {
600         
601         final Pair<Class<T>, Class<?>> key = new Pair<Class<T>, Class<?>>(targetClass, contextClass); 
602         @SuppressWarnings("unchecked")
603         final AdapterDeclaration<T> decl = (AdapterDeclaration<T>)adapters.get(key);
604         if(decl == null) {
605
606             if(possible) return null;
607             else throw new AdaptionException("There are no adapters declared or defined for class " + targetClass + ".");
608
609         } else {
610
611             @SuppressWarnings("unchecked")
612             final Adapter<T,C> adapter = (Adapter<T,C>)decl.directAdapter(r);
613             if(adapter != null) return adapter;
614             
615             Layer0 L0 = Layer0.getInstance(g);
616             Resource singleType = g.getPossibleObject(r, L0.InstanceOf);
617             if(singleType != null) {
618                 return getSingleTypeAdapter(g, decl, key, r, singleType, possible);
619             } else {
620                 return getSingleSuperTypeAdapter(g, decl, key, r, r, possible);
621             }
622
623         }       
624         
625     }
626
627     private static class SingleTypeAdapter<T, C> extends TernaryRead<Pair<Class<T>, Class<?>>, Resource, Boolean, Adapter<T,C>> {
628
629         final private AdapterDeclaration<T> decl;
630         
631         SingleTypeAdapter(AdapterDeclaration<T> decl, Pair<Class<T>, Class<?>> key, Resource instance, Boolean possible) {
632                 super(key, instance, possible);
633                 this.decl = decl;
634         }
635         
636         @Override
637         public Adapter<T,C> perform(ReadGraph graph) throws DatabaseException {
638             return decl.findAdapter(graph, parameter2, parameter3);
639         }
640
641     }
642     
643     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) {
644
645         @SuppressWarnings("unchecked")
646         Adapter<T,C> adapter = (Adapter<T,C>)decl.typeAdapters.get(type);
647         if(adapter != null) {
648                 procedure.execute(graph, adapter);
649         } else {
650             graph.forPossibleObject(type, graph.getService(Layer0.class).Inherits, new AsyncProcedure<Resource>() {
651
652                 @Override
653                 public void exception(AsyncReadGraph graph, Throwable throwable) {
654                     procedure.exception(graph, new AdaptionException("Problems in reading super types for resource. ", throwable));
655                 }
656
657                 @Override
658                 public void execute(AsyncReadGraph graph, Resource singleSuperType) {
659
660                     if(singleSuperType != null) {
661                         getSingleTypeAdapter(graph, decl, key, instance, singleSuperType, possible, procedure);
662                     } else {
663                         graph.asyncRequest(new SingleTypeAdapter<T,C>(decl, key, instance, possible), procedure);
664                     }
665
666                 }
667
668             });
669
670
671         }
672
673     }
674     
675     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 {
676
677         @SuppressWarnings("unchecked")
678         Adapter<T,C> adapter = (Adapter<T,C>)decl.typeAdapters.get(type);
679         if(adapter != null) return adapter;
680         
681         Layer0 L0 = Layer0.getInstance(graph);
682         Resource singleSuperType = graph.getPossibleObject(type, L0.Inherits);
683         if(singleSuperType != null) {
684             return getSingleTypeAdapter(graph, decl, key, instance, singleSuperType, possible);
685         } else {
686             return graph.syncRequest(new SingleTypeAdapter<T,C>(decl, key, instance, possible), TransientCacheAsyncListener.<Adapter<T,C>>instance());
687         }
688
689     }    
690     
691 //    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) {
692 //
693 //        @SuppressWarnings("unchecked")
694 //        Adapter<T,C> adapter = (Adapter<T,C>)decl.typeAdapters.get(type);
695 //        if(adapter != null) {
696 //
697 //            adapter.adapt(graph, instance, context, procedure);
698 //
699 //        } else {
700 //
701 //            graph.forPossibleObject(type, graph.getService(Layer0.class).Inherits, new AsyncProcedure<Resource>() {
702 //
703 //                @Override
704 //                public void exception(AsyncReadGraph graph, Throwable throwable) {
705 //
706 //                    procedure.exception(graph, new AdaptionException("Problems in reading super types for resource. ", throwable));
707 //
708 //                }
709 //
710 //                @Override
711 //                public void execute(AsyncReadGraph graph, Resource singleSuperType) {
712 //
713 //                    if(singleSuperType != null) {
714 //
715 //                        adaptSingleType(graph, decl, context, instance, singleSuperType, possible, procedure);
716 //
717 //                    } else {
718 //
719 //                        graph.asyncRequest(new Read<T>() {
720 //
721 //                            @Override
722 //                            public T perform(ReadGraph graph)
723 //                            throws DatabaseException {
724 //                                return decl.adapt(graph, instance, context, possible);
725 //                            }
726 //
727 //                        }, procedure);
728 //
729 //                    }
730 //
731 //                }
732 //
733 //            });
734 //
735 //
736 //        }
737 //
738 //    }
739
740     
741     private static class SingleSuperTypeAdapter<T, C> extends TernaryRead<Pair<Class<T>, Class<?>>, Resource, Boolean, Adapter<T,C>> {
742
743         final private AdapterDeclaration<T> decl;
744         
745         SingleSuperTypeAdapter(AdapterDeclaration<T> decl, Pair<Class<T>, Class<?>> key, Resource type, Boolean possible) {
746                 super(key, type, possible);
747                 this.decl = decl;
748         }
749         
750         @Override
751         public Adapter<T,C> perform(ReadGraph graph) throws DatabaseException {
752             return decl.findAdapter(graph, parameter2, parameter3);
753         }
754
755     }
756     
757     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) {
758
759         @SuppressWarnings("unchecked")
760         Adapter<T, C> adapter = (Adapter<T, C>)decl.instanceAdapters.get(superType);
761         if(adapter != null) {
762                 procedure.execute(graph, adapter);
763         } else {
764
765             graph.forPossibleObject(superType, graph.getService(Layer0.class).Inherits, new AsyncProcedure<Resource>() {
766
767                 @Override
768                 public void exception(AsyncReadGraph graph, Throwable throwable) {
769                     procedure.exception(graph, new AdaptionException("Problems in reading super types for resource. ", throwable));
770                 }
771
772                 @Override
773                 public void execute(AsyncReadGraph graph, Resource singleSuperType) {
774
775                     if(singleSuperType != null) {
776
777                         getSingleSuperTypeAdapter(graph, decl, key, type, singleSuperType, possible, procedure);
778
779                     } else {
780
781                         graph.asyncRequest(new SingleSuperTypeAdapter<T,C>(decl, key, type, possible), procedure);
782
783                     }
784
785                 }
786
787             });
788
789         }
790
791     }
792
793     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 {
794
795         @SuppressWarnings("unchecked")
796         Adapter<T, C> adapter = (Adapter<T, C>)decl.instanceAdapters.get(superType);
797         if(adapter != null) return adapter;
798         
799         Layer0 L0 = Layer0.getInstance(graph);
800         Resource singleSuperType = graph.getPossibleObject(superType, L0.Inherits);
801         if(singleSuperType != null) {
802                 return getSingleSuperTypeAdapter(graph, decl, key, type, singleSuperType, possible);
803         } else {
804                 return graph.syncRequest(new SingleSuperTypeAdapter<T,C>(decl, key, type, possible));
805         }
806
807     }
808     
809 //    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) {
810 //
811 //        @SuppressWarnings("unchecked")
812 //        Adapter<T, C> adapter = (Adapter<T, C>)decl.instanceAdapters.get(superType);
813 //        if(adapter != null) {
814 //
815 //            adapter.adapt(graph, type, context, procedure);
816 //
817 //        } else {
818 //
819 //            graph.forPossibleObject(superType, graph.getService(Layer0.class).Inherits, new AsyncProcedure<Resource>() {
820 //
821 //                @Override
822 //                public void exception(AsyncReadGraph graph, Throwable throwable) {
823 //
824 //                    procedure.exception(graph, new AdaptionException("Problems in reading super types for resource. ", throwable));
825 //
826 //                }
827 //
828 //                @Override
829 //                public void execute(AsyncReadGraph graph, Resource singleSuperType) {
830 //
831 //                    if(singleSuperType != null) {
832 //
833 //                        adaptSingleSupertype(graph, decl, context, type, singleSuperType, possible, procedure);
834 //
835 //                    } else {
836 //
837 //                        graph.asyncRequest(new Read<T>() {
838 //
839 //                            @Override
840 //                            public T perform(ReadGraph graph)
841 //                            throws DatabaseException {
842 //                                return decl.adapt(graph, type, context, possible);
843 //                            }
844 //
845 //                        }, procedure);
846 //
847 //                    }
848 //
849 //                }
850 //
851 //            });
852 //
853 //        }
854 //
855 //    }
856
857     @Override
858     public <T> void adaptNew(AsyncReadGraph g, final Resource r, final Class<T> clazz, final boolean possible, final AsyncProcedure<T> procedure) {
859
860         g.asyncRequest(new ReadRequest() {
861
862             @Override
863             public void run(ReadGraph graph) throws DatabaseException {
864
865                 final Pair<Class<T>, Class<?>> key = new Pair<Class<T>, Class<?>>(clazz, Resource.class); 
866
867                 @SuppressWarnings("unchecked")
868                 AdapterDeclaration<T> decl =
869                     (AdapterDeclaration<T>)adapters.get(key);
870
871                 if(decl == null) {
872                     if(possible) {
873                         procedure.execute(graph, null);
874                     } else {
875                         procedure.exception(graph, new AdaptionException("There are no adapters declared or defined for class " + clazz + "."));
876                     }
877                 } else {
878                     try {
879                         procedure.execute(graph, decl.adaptNew(graph, r, possible));
880                     } catch (AdaptionException e) {
881                         if(possible) {
882                             procedure.execute(graph, null);
883                         } else {
884                             procedure.exception(graph, e);
885                         }
886                     } catch (ValidationException e) {
887                         procedure.exception(graph, e);
888                     } catch (DatabaseException e2) {
889                         procedure.exception(graph, new ServiceException(e2));
890                     }
891                 }
892
893             }
894
895         });
896
897     }
898
899     @Override
900     public <T> void addInstanceAdapter(Resource resource, Class<T> targetClass, Adapter<T,?> adapter) {
901         addInstanceAdapter(resource, targetClass, Resource.class, adapter);
902     }
903
904     @Override
905     public <T> void addInstanceAdapter(Resource resource, Class<T> targetClass, Class<?> contextClass, Adapter<T,?> adapter) {
906         synchronized (this) {
907             getDeclaration(targetClass, contextClass).instanceAdapters.put(resource, adapter);
908         }
909     }
910
911     @Override
912     public <T> Adapter<T,?> removeInstanceAdapter(Resource resource, Class<T> targetClass) {
913         return removeInstanceAdapter(resource, targetClass, Resource.class);
914     }
915     
916     @Override
917     public <T> Adapter<T,?> removeInstanceAdapter(Resource resource, Class<T> targetClass, Class<?> contextClass) {
918         synchronized (this) {
919             return getDeclaration(targetClass, contextClass).instanceAdapters.remove(resource);
920         }
921     }
922
923     @Override
924     public <T> void removeInstanceAdapter(Resource resource, Class<T> targetClass, Adapter<T,?> adapter) {
925         removeInstanceAdapter(resource, targetClass, Resource.class, adapter);
926     }
927
928     @Override
929     public <T> void removeInstanceAdapter(Resource resource, Class<T> targetClass, Class<?> contextClass, Adapter<T,?> adapter) {
930         synchronized (this) {
931             AdapterDeclaration<T> decl = getDeclaration(targetClass, contextClass);
932             Adapter<T,?> existing = decl.instanceAdapters.get(resource);
933             if (existing == adapter) {
934                 decl.instanceAdapters.remove(resource);
935             }
936         }
937     }
938
939     @Override
940     public <T> void addAdapter(Resource type, Class<T> targetClass, Adapter<T,?> adapter) {
941         addAdapter(type, targetClass, Resource.class, adapter);
942     }
943
944     @Override
945     public <T> void addAdapter(Resource type, Class<T> targetClass, Class<?> contextClass, Adapter<T,?> adapter) {
946         getDeclaration(targetClass, contextClass).typeAdapters.put(type, adapter);
947     }
948
949     @Override
950     public <T> void declareAdapter(Resource type, Class<T> targetClass) {
951         declareAdapter(type, targetClass, Resource.class);
952     }
953
954     @Override
955     public <T> void declareAdapter(Resource type, Class<T> targetClass, Class<?> contextClass) {
956         getDeclaration(targetClass, contextClass).baseTypes.add(type);
957     }
958
959     public static String safeName(ReadGraph g, Resource r) throws DatabaseException {
960 //        Builtins b = g.getBuiltins();
961 //        for(Resource name : g.getObjects(r, b.HasName))
962 //            return g.getValue(name);
963 //        for(Resource t : g.getObjects(r, b.InstanceOf))
964 //            for(Resource name : g.getObjects(t, b.HasName))
965 //                return ": "+ g.getValue(name);
966 //        for(Resource t : g.getObjects(r, b.Inherits))
967 //            for(Resource name : g.getObjects(t, b.HasName))
968 //                return "<T "+ g.getValue(name);
969 //        for(Resource t : g.getObjects(r, b.SubrelationOf))
970 //            for(Resource name : g.getObjects(t, b.HasName))
971 //                return "<R "+ g.getValue(name);
972 //        if(g.hasValue(r))
973 //            return "\"" + g.getValue(r) + "\"";
974 //        return "" + r.getResourceId();
975         return NameUtils.getSafeName(g, r, true);
976     }
977
978 }