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