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