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