]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - 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
diff --git a/bundles/org.simantics.db.services/src/org/simantics/db/services/adaption/AdaptionService2.java b/bundles/org.simantics.db.services/src/org/simantics/db/services/adaption/AdaptionService2.java
new file mode 100644 (file)
index 0000000..b7cc76a
--- /dev/null
@@ -0,0 +1,973 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.db.services.adaption;\r
+\r
+import gnu.trove.map.hash.THashMap;\r
+import gnu.trove.procedure.TObjectObjectProcedure;\r
+import gnu.trove.set.hash.THashSet;\r
+\r
+import org.simantics.db.AsyncReadGraph;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.adaption.Adapter;\r
+import org.simantics.db.adaption.AdaptionService;\r
+import org.simantics.db.common.procedure.adapter.TransientCacheAsyncListener;\r
+import org.simantics.db.common.procedure.single.SyncReadProcedure;\r
+import org.simantics.db.common.request.BinaryRead;\r
+import org.simantics.db.common.request.ReadRequest;\r
+import org.simantics.db.common.request.TernaryRead;\r
+import org.simantics.db.common.uri.ResourceToURI;\r
+import org.simantics.db.common.utils.NameUtils;\r
+import org.simantics.db.exception.AdaptionException;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.exception.ServiceException;\r
+import org.simantics.db.exception.ValidationException;\r
+import org.simantics.db.procedure.AsyncProcedure;\r
+import org.simantics.db.request.AsyncRead;\r
+import org.simantics.db.request.Read;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.utils.datastructures.Pair;\r
+\r
+public class AdaptionService2 implements AdaptionService {\r
+\r
+    THashMap<Pair<Class<?>,Class<?>>, AdapterDeclaration<?>> adapters =\r
+        new THashMap<Pair<Class<?>,Class<?>>, AdapterDeclaration<?>>();\r
+\r
+    /**\r
+     * Contains all adapter declarations and definitions for one class (clazz).\r
+     */\r
+    static class AdapterDeclaration<T> {\r
+        Class<T> clazz;\r
+        THashMap<Resource, Adapter<T,?>> typeAdapters =\r
+            new THashMap<Resource, Adapter<T,?>>();\r
+        THashMap<Resource, Adapter<T,?>> instanceAdapters =\r
+            new THashMap<Resource, Adapter<T,?>>();\r
+        THashSet<Resource> baseTypes = new THashSet<Resource>();\r
+\r
+        String getDescription(final ReadGraph g) {\r
+            final StringBuilder b = new StringBuilder();\r
+            b.append("The following adapters have been defined for ");\r
+            b.append(clazz.getCanonicalName());\r
+            b.append("\n");\r
+            typeAdapters.forEachEntry(new TObjectObjectProcedure<Resource, Adapter<T,?>>() {\r
+\r
+                @Override\r
+                public boolean execute(Resource arg0, Adapter<T,?> arg1) {\r
+                    b.append("    type ");\r
+                    try {\r
+                        b.append(g.syncRequest(new ResourceToURI(arg0)));\r
+                    } catch (DatabaseException e) {\r
+                        e.printStackTrace();\r
+                    }\r
+                    b.append(" : ");\r
+                    b.append(arg1);\r
+                    b.append('\n');\r
+                    return true;\r
+                }\r
+\r
+            });\r
+\r
+            synchronized (this) {\r
+                instanceAdapters.forEachEntry(new TObjectObjectProcedure<Resource, Adapter<T,?>>() {\r
+\r
+                    @Override\r
+                    public boolean execute(Resource arg0, Adapter<T,?> arg1) {\r
+                        b.append("    resource ");\r
+                        try {\r
+                            b.append(g.syncRequest(new ResourceToURI(arg0)));\r
+                        } catch (DatabaseException e) {\r
+                            e.printStackTrace();\r
+                        }\r
+                        b.append(" : ");\r
+                        b.append(arg1);\r
+                        b.append('\n');\r
+                        return true;\r
+                    }\r
+\r
+                });\r
+            }\r
+            return b.toString();\r
+        }\r
+\r
+        public AdapterDeclaration(Class<T> clazz) {\r
+            this.clazz = clazz;\r
+        }\r
+\r
+        static class AdapterResult<T,C> {\r
+            Adapter<T,C> adapter;\r
+            Resource type;\r
+\r
+            public AdapterResult(Adapter<T,C> adapter, Resource type) {\r
+                this.adapter = adapter;\r
+                this.type = type;\r
+            }\r
+        }\r
+\r
+        /**\r
+         * The query returns the adapter inherited by the parameter type.\r
+         * The query is used only in the case, the type itself does not have\r
+         * an adapter. The second component of the result contains the type\r
+         * that originally contributed the adapter.\r
+         */\r
+        static class GetInheritedAdapter<T,C> extends BinaryRead<Resource, AdapterDeclaration<T>, AdapterResult<T,C>>  {\r
+\r
+            public GetInheritedAdapter(Resource type, AdapterDeclaration<T> decl) {\r
+                super(type, decl);\r
+            }\r
+\r
+            AdapterDeclaration<T> getDeclaration() {\r
+               return parameter2;\r
+            }\r
+\r
+            @Override\r
+            public String toString() {\r
+                return "GetInheritedAdapter|" + parameter + "|" + parameter2;\r
+            }\r
+\r
+            @SuppressWarnings("unchecked")\r
+            @Override\r
+            public AdapterResult<T,C> perform(ReadGraph g) throws DatabaseException {\r
+               Layer0 b = Layer0.getInstance(g);\r
+                AdapterResult<T,C> result = null;\r
+                for(Resource supertype : g.getObjects(parameter, b.Inherits)) {\r
+                    Adapter<T,C> adapter = (Adapter<T,C>)parameter2.typeAdapters.get(supertype);\r
+                    if(adapter != null) {\r
+                        if(result == null)\r
+                            result = new AdapterResult<T,C>(adapter, supertype);\r
+                        else if(!result.type.equals(supertype) &&\r
+                                !g.isInheritedFrom(result.type, supertype)) {\r
+                            if(g.isInheritedFrom(supertype, result.type))\r
+                                result = new AdapterResult<T,C>(adapter, supertype);\r
+                            else throw new AdaptionException("Type " +\r
+                                    safeName(g, parameter) + " inherits conflicting adapters from "\r
+                                    + safeName(g, supertype) + " and " + safeName(g, result.type));\r
+                        }\r
+                    }\r
+                    else {\r
+                        AdapterResult<T,C> temp =\r
+                            g.syncRequest(new GetInheritedAdapter<T, C>(supertype, parameter2), TransientCacheAsyncListener.<AdapterResult<T,C>>instance());\r
+                        if(temp != null) {\r
+                            if(result == null)\r
+                                result = temp;\r
+                            else if(!result.type.equals(temp.type) &&\r
+                                    !g.isInheritedFrom(result.type, temp.type)) {\r
+                                if(g.isInheritedFrom(temp.type, result.type))\r
+                                    result = temp;\r
+                                else throw new AdaptionException("Type " +\r
+                                        safeName(g, parameter) + " inherits conflicting adapters from "\r
+                                        + safeName(g, temp.type) + " and " + safeName(g, result.type));\r
+                            }\r
+                        }\r
+                    }\r
+                }\r
+                return result;\r
+            }\r
+\r
+        }\r
+\r
+        <C> void inheritedAdapter(AsyncReadGraph graph, Resource type, AsyncProcedure<AdapterResult<T,C>> procedure) {\r
+            graph.asyncRequest(new GetInheritedAdapter<T, C>(type, this), procedure);\r
+        }\r
+\r
+        Adapter<T,?> directAdapter(Resource r) {\r
+            Adapter<T,?> ret;\r
+            synchronized (this) {\r
+                ret = instanceAdapters.get(r);\r
+            }\r
+            return ret;\r
+        }\r
+\r
+        static class FindAdapter<T,C> extends BinaryRead<Resource, AdapterDeclaration<T>, Adapter<T,C>> {\r
+\r
+            public FindAdapter(Resource resource, AdapterDeclaration<T> decl) {\r
+               super(resource, decl);\r
+            }\r
+            \r
+            @SuppressWarnings("unchecked")\r
+            Adapter<T,C> findAdapter(Resource r, ReadGraph g) throws DatabaseException {\r
+\r
+                {\r
+                    Adapter<T,C> adapter;\r
+                    synchronized (this) {\r
+                        adapter = (Adapter<T,C>)parameter2.instanceAdapters.get(r);\r
+                    }\r
+                    if(adapter != null)\r
+                        return adapter;\r
+                }\r
+\r
+                Layer0 b = Layer0.getInstance(g);\r
+\r
+                /*\r
+                 * Try to find adapter from immediate types\r
+                 */\r
+                AdapterResult<T,C> adapterResult = null;\r
+                for(Resource t : g.getObjects(r, b.InstanceOf)) {\r
+                    Adapter<T,C> adapter = (Adapter<T,C>)parameter2.typeAdapters.get(t);\r
+                    if(adapter != null) {\r
+                        if(adapterResult == null)\r
+                            adapterResult = new AdapterResult<T,C>(adapter, t);\r
+                        else if(!adapterResult.type.equals(t) &&\r
+                                !g.isInheritedFrom(adapterResult.type, t)) {\r
+                            if(g.isInheritedFrom(t, adapterResult.type))\r
+                                adapterResult = new AdapterResult<T,C>(adapter, t);\r
+                            else throw new AdaptionException("Resource " +\r
+                                    safeName(g, r) + " has conflicting " + parameter2.clazz + "-adapters from "\r
+                                    + safeName(g, t) + " and " + safeName(g, adapterResult.type)\r
+                            );\r
+                        }\r
+                    }\r
+                    else {\r
+                        AdapterResult<T,C> temp =\r
+                            g.syncRequest(new GetInheritedAdapter<T, C>(t, parameter2), TransientCacheAsyncListener.<AdapterResult<T,C>>instance());\r
+                        if(temp != null) {\r
+                            if(adapterResult == null)\r
+                                adapterResult = temp;\r
+                            else if(!adapterResult.type.equals(temp.type) &&\r
+                                    !g.isInheritedFrom(adapterResult.type, temp.type)) {\r
+                                if(g.isInheritedFrom(temp.type, adapterResult.type))\r
+                                    adapterResult = temp;\r
+                                else throw new AdaptionException("Resource " +\r
+                                        safeName(g, r) + " has conflicting " + parameter2.clazz + "-adapters from "\r
+                                        + safeName(g, temp.type) + " and " + safeName(g, adapterResult.type)\r
+                                );\r
+                            }\r
+                        }\r
+                    }\r
+                }\r
+\r
+                if(adapterResult != null)\r
+                    return adapterResult.adapter;\r
+\r
+                for(Resource t : g.getObjects(r, b.Inherits)) {\r
+                    Adapter<T,C> adapter = findAdapter(t, g);\r
+                    if(adapter != null)\r
+                        return adapter;\r
+                }\r
+\r
+                for(Resource t : g.getObjects(r, b.SubrelationOf)) {\r
+                    Adapter<T,C> adapter = findAdapter(t, g);\r
+                    if(adapter != null)\r
+                        return adapter;\r
+                }\r
+\r
+                return null;\r
+\r
+            }\r
+\r
+                       \r
+            @Override\r
+            public Adapter<T,C> perform(ReadGraph g) throws DatabaseException {\r
+                return (Adapter<T, C>)findAdapter(parameter, g);\r
+            }\r
+               \r
+        }\r
+        \r
+        /**\r
+         * The query returns either an adapter or adapted for the given\r
+         * resource. It is assumed that the resource itself does not\r
+         * have adapted.\r
+         */\r
+        class Adapt<C> implements Read<T> {\r
+\r
+            Resource resource;\r
+            C context;\r
+\r
+            public Adapt(Resource resource, C context) {\r
+                this.resource = resource;\r
+                this.context = context;\r
+            }\r
+\r
+            AdapterDeclaration<T> getDeclaration() {\r
+                return AdapterDeclaration.this;\r
+            }\r
+\r
+            @SuppressWarnings("unchecked")\r
+            Adapter<T,C> findAdapter(Resource r, ReadGraph g) throws DatabaseException {\r
+\r
+                {\r
+                    Adapter<T,C> adapter;\r
+                    synchronized (this) {\r
+                        adapter = (Adapter<T,C>)instanceAdapters.get(r);\r
+                    }\r
+                    if(adapter != null)\r
+                        return adapter;\r
+                }\r
+\r
+                Layer0 b = Layer0.getInstance(g);\r
+\r
+                /*\r
+                 * Try to find adapter from immediate types\r
+                 */\r
+                AdapterResult<T,C> adapterResult = null;\r
+                for(Resource t : g.getObjects(r, b.InstanceOf)) {\r
+                    Adapter<T,C> adapter = (Adapter<T,C>)typeAdapters.get(t);\r
+                    if(adapter != null) {\r
+                        if(adapterResult == null)\r
+                            adapterResult = new AdapterResult<T,C>(adapter, t);\r
+                        else if(!adapterResult.type.equals(t) &&\r
+                                !g.isInheritedFrom(adapterResult.type, t)) {\r
+                            if(g.isInheritedFrom(t, adapterResult.type))\r
+                                adapterResult = new AdapterResult<T,C>(adapter, t);\r
+                            else throw new AdaptionException("Resource " +\r
+                                    safeName(g, r) + " has conflicting " + clazz + "-adapters from "\r
+                                    + safeName(g, t) + " and " + safeName(g, adapterResult.type)\r
+                            );\r
+                        }\r
+                    }\r
+                    else {\r
+                        AdapterResult<T,C> temp =\r
+                            g.syncRequest(new GetInheritedAdapter<T, C>(t, AdapterDeclaration.this));\r
+                        if(temp != null) {\r
+                            if(adapterResult == null)\r
+                                adapterResult = temp;\r
+                            else if(!adapterResult.type.equals(temp.type) &&\r
+                                    !g.isInheritedFrom(adapterResult.type, temp.type)) {\r
+                                if(g.isInheritedFrom(temp.type, adapterResult.type))\r
+                                    adapterResult = temp;\r
+                                else throw new AdaptionException("Resource " +\r
+                                        safeName(g, r) + " has conflicting " + clazz + "-adapters from "\r
+                                        + safeName(g, temp.type) + " and " + safeName(g, adapterResult.type)\r
+                                );\r
+                            }\r
+                        }\r
+                    }\r
+                }\r
+\r
+                if(adapterResult != null)\r
+                    return adapterResult.adapter;\r
+\r
+                for(Resource t : g.getObjects(r, b.Inherits)) {\r
+                    Adapter<T,C> adapter = findAdapter(t, g);\r
+                    if(adapter != null)\r
+                        return adapter;\r
+                }\r
+\r
+                for(Resource t : g.getObjects(r, b.SubrelationOf)) {\r
+                    Adapter<T,C> adapter = findAdapter(t, g);\r
+                    if(adapter != null)\r
+                        return adapter;\r
+                }\r
+\r
+                return null;\r
+\r
+            }\r
+\r
+            @Override\r
+            public T perform(ReadGraph g) throws DatabaseException {\r
+\r
+                final Adapter<T,C> adapter = (Adapter<T, C>)findAdapter(resource, g);\r
+                if(adapter == null) return null;\r
+                else return g.syncRequest(new AsyncRead<T>() {\r
+\r
+                    @Override\r
+                    public void perform(AsyncReadGraph graph, AsyncProcedure<T> procedure) {\r
+//                      System.out.println("adapter=" + adapter);\r
+                        adapter.adapt(graph, resource, context, procedure);\r
+                    }\r
+\r
+                    @Override\r
+                           public int threadHash() {\r
+                               return hashCode();\r
+                           }\r
+\r
+                    @Override\r
+                    public int getFlags() {\r
+                        return 0;\r
+                    }\r
+\r
+                });\r
+\r
+            }\r
+\r
+            @SuppressWarnings("rawtypes")\r
+            @Override\r
+            public boolean equals(Object other) {\r
+\r
+                if (this == other)\r
+                    return true;\r
+                else if (other == null)\r
+                    return false;\r
+                else if (other.getClass() != Adapt.class)\r
+                    return false;\r
+\r
+                return ((Adapt)other).resource.equals(resource)\r
+                && ((Adapt)other).context.equals(context)\r
+                && ((Adapt)other).getDeclaration()==getDeclaration();\r
+\r
+            }\r
+\r
+            @Override\r
+            public int hashCode() {\r
+                return resource.hashCode() + 31*((getClass().hashCode() + 41*(context.hashCode()) + \r
+                        71*getDeclaration().hashCode()));\r
+            }\r
+\r
+        }\r
+\r
+//        void adapt2(AsyncReadGraph graph, Resource r, AsyncProcedure<T> procedure) {\r
+//            graph.asyncRequest(new Adapt(r), procedure);\r
+//        }\r
+\r
+        <C> Adapter<T,C> findAdapter(ReadGraph g, Resource r, boolean possible) throws DatabaseException {\r
+\r
+            Adapter<T,C> result = g.syncRequest(new FindAdapter<T,C>(r, AdapterDeclaration.this));\r
+            if(result != null) return result;\r
+\r
+            if (possible)\r
+                return null;\r
+\r
+            /*\r
+             * We couldn't adapt the resource. We analyze the situation little for\r
+             * better error message.\r
+             */\r
+            for(Resource dt : baseTypes) {\r
+                if(g.isInstanceOf(r, dt)) {\r
+                    throw new AdaptionException("Couldn't find a " + clazz + "-adapter for resource " +\r
+                            safeName(g, r) + " although it is instance of " +\r
+                            safeName(g, dt) + "\n" +\r
+                            getDescription(g));\r
+                }\r
+            }\r
+            throw new AdaptionException("Couldn't find a " + clazz + "-adapter for resource " +\r
+                    safeName(g, r) +\r
+                    ". This is because the resource is not instance of any type which the adapter is declared to.\n" +\r
+                    getDescription(g));\r
+\r
+        }\r
+        \r
+        <C> T adapt(ReadGraph g, Resource r, C context, boolean possible) throws DatabaseException {\r
+\r
+            T result = g.syncRequest(new Adapt<C>(r,context));\r
+            if(result != null) return result;\r
+\r
+            if (possible)\r
+                return null;\r
+\r
+            /*\r
+             * We couldn't adapt the resource. We analyze the situation little for\r
+             * better error message.\r
+             */\r
+            for(Resource dt : baseTypes) {\r
+                if(g.isInstanceOf(r, dt)) {\r
+                    throw new AdaptionException("Couldn't find a " + clazz + "-adapter for resource " +\r
+                            safeName(g, r) + " although it is instance of " +\r
+                            safeName(g, dt) + "\n" +\r
+                            getDescription(g));\r
+                }\r
+            }\r
+            throw new AdaptionException("Couldn't find a " + clazz + "-adapter for resource " +\r
+                    safeName(g, r) +\r
+                    ". This is because the resource is not instance of any type which the adapter is declared to.\n" +\r
+                    getDescription(g));\r
+\r
+        }\r
+\r
+        T adaptNew(ReadGraph g, final Resource r, boolean possible) throws DatabaseException {\r
+\r
+            T result = new Adapt<Resource>(r,r).perform(g);\r
+            if (result != null)\r
+                return result;\r
+\r
+            if (possible)\r
+                return null;\r
+\r
+            for(Resource dt : baseTypes) {\r
+                if(g.isInstanceOf(r, dt)) {\r
+                    throw new AdaptionException("Couldn't find a " + clazz + "-adapter for resource " +\r
+                            safeName(g, r) + " although it is instance of " +\r
+                            safeName(g, dt) + "\n" +\r
+                            getDescription(g));\r
+                }\r
+            }\r
+            throw new AdaptionException("Couldn't find a " + clazz + "-adapter for resource " +\r
+                    safeName(g, r) +\r
+                    ". This is because the resource is not instance of any type which the adapter is declared to.\n" +\r
+                    getDescription(g));\r
+\r
+        }\r
+\r
+    }\r
+\r
+    private <T> AdapterDeclaration<T> getDeclaration(Class<T> targetClass, Class<?> contextClass) {\r
+       Pair<Class<?>,Class<?>> key = new Pair<Class<?>,Class<?>>(targetClass, contextClass);\r
+        @SuppressWarnings("unchecked")\r
+        AdapterDeclaration<T> decl =\r
+            (AdapterDeclaration<T>)adapters.get(key);\r
+        if(decl == null) {\r
+            decl = new AdapterDeclaration<T>(targetClass);\r
+            adapters.put(key, decl);\r
+        }\r
+        return decl;\r
+    }\r
+\r
+    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
+       \r
+       final Pair<Class<T>, Class<?>> key = new Pair<Class<T>, Class<?>>(targetClass, contextClass); \r
+        @SuppressWarnings("unchecked")\r
+        final AdapterDeclaration<T> decl = (AdapterDeclaration<T>)adapters.get(key);\r
+        if(decl == null) {\r
+\r
+            if(possible) {\r
+                procedure.execute(graph, null);\r
+            } else {\r
+                procedure.exception(graph, new AdaptionException("There are no adapters declared or defined for class " + targetClass + "."));\r
+            }\r
+\r
+        } else {\r
+\r
+            @SuppressWarnings("unchecked")\r
+            final Adapter<T,C> adapter = (Adapter<T,C>)decl.directAdapter(r);\r
+            if(adapter != null) {\r
+               procedure.execute(graph, adapter);\r
+            } else {\r
+                graph.forPossibleObject(r, graph.getService(Layer0.class).InstanceOf, new AsyncProcedure<Resource>() {\r
+\r
+                    @Override\r
+                    public void exception(AsyncReadGraph graph, Throwable throwable) {\r
+                        procedure.exception(graph, new AdaptionException("Problems in reading types for resource. ", throwable));\r
+                    }\r
+\r
+                    @Override\r
+                    public void execute(AsyncReadGraph graph, final Resource singleType) {\r
+                        if(singleType != null) {\r
+                            getSingleTypeAdapter(graph, decl, key, r, singleType, possible, procedure);\r
+                        } else {\r
+                            getSingleSuperTypeAdapter(graph, decl, key, r, r, possible, procedure);\r
+                        }\r
+                    }\r
+\r
+                });\r
+            }\r
+\r
+        }\r
+       \r
+    }\r
+    \r
+    @Override\r
+    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
+\r
+       getAdapter(graph, r, contextClass, targetClass, possible, new AsyncProcedure<Adapter<T,C>>() {\r
+\r
+                       @Override\r
+                       public void execute(AsyncReadGraph graph, Adapter<T, C> result) {\r
+                               if(result == null) {\r
+                                       if(possible) {\r
+                                               procedure.execute(graph, null);\r
+                                       } else {\r
+                                               procedure.exception(graph, new AdaptionException("Internal error. getAdapter returned null and possible was false."));\r
+                                       }\r
+                               } else {\r
+                                       result.adapt(graph, r, context, procedure);\r
+                               }\r
+                       }\r
+\r
+                       @Override\r
+                       public void exception(AsyncReadGraph graph, Throwable throwable) {\r
+                               procedure.exception(graph, throwable);\r
+                       }\r
+               \r
+       });\r
+\r
+    }\r
+    \r
+    @Override\r
+    public <T, C> T adapt(ReadGraph g, Resource r, C context, Class<C> contextClass, Class<T> targetClass, boolean possible) throws DatabaseException {\r
+\r
+       Adapter<T,C> adapter = getAdapter(g, r, context, contextClass, targetClass, possible);\r
+       \r
+               SyncReadProcedure<T> procedure = new SyncReadProcedure<T>();\r
+       adapter.adapt(g, r, context, procedure);\r
+               procedure.checkAndThrow();\r
+               return procedure.result;\r
+       \r
+    }\r
+    \r
+    private <T, C> Adapter<T,C> getAdapter(ReadGraph g, Resource r, C context, Class<C> contextClass, Class<T> targetClass, boolean possible) throws DatabaseException {\r
+       \r
+       final Pair<Class<T>, Class<?>> key = new Pair<Class<T>, Class<?>>(targetClass, contextClass); \r
+        @SuppressWarnings("unchecked")\r
+        final AdapterDeclaration<T> decl = (AdapterDeclaration<T>)adapters.get(key);\r
+        if(decl == null) {\r
+\r
+            if(possible) return null;\r
+            else throw new AdaptionException("There are no adapters declared or defined for class " + targetClass + ".");\r
+\r
+        } else {\r
+\r
+            @SuppressWarnings("unchecked")\r
+            final Adapter<T,C> adapter = (Adapter<T,C>)decl.directAdapter(r);\r
+            if(adapter != null) return adapter;\r
+            \r
+            Layer0 L0 = Layer0.getInstance(g);\r
+            Resource singleType = g.getPossibleObject(r, L0.InstanceOf);\r
+            if(singleType != null) {\r
+                return getSingleTypeAdapter(g, decl, key, r, singleType, possible);\r
+            } else {\r
+                return getSingleSuperTypeAdapter(g, decl, key, r, r, possible);\r
+            }\r
+\r
+        }      \r
+       \r
+    }\r
+\r
+    private static class SingleTypeAdapter<T, C> extends TernaryRead<Pair<Class<T>, Class<?>>, Resource, Boolean, Adapter<T,C>> {\r
+\r
+       final private AdapterDeclaration<T> decl;\r
+       \r
+       SingleTypeAdapter(AdapterDeclaration<T> decl, Pair<Class<T>, Class<?>> key, Resource instance, Boolean possible) {\r
+               super(key, instance, possible);\r
+               this.decl = decl;\r
+       }\r
+       \r
+        @Override\r
+        public Adapter<T,C> perform(ReadGraph graph) throws DatabaseException {\r
+            return decl.findAdapter(graph, parameter2, parameter3);\r
+        }\r
+\r
+    }\r
+    \r
+    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
+\r
+        @SuppressWarnings("unchecked")\r
+        Adapter<T,C> adapter = (Adapter<T,C>)decl.typeAdapters.get(type);\r
+        if(adapter != null) {\r
+               procedure.execute(graph, adapter);\r
+        } else {\r
+            graph.forPossibleObject(type, graph.getService(Layer0.class).Inherits, new AsyncProcedure<Resource>() {\r
+\r
+                @Override\r
+                public void exception(AsyncReadGraph graph, Throwable throwable) {\r
+                    procedure.exception(graph, new AdaptionException("Problems in reading super types for resource. ", throwable));\r
+                }\r
+\r
+                @Override\r
+                public void execute(AsyncReadGraph graph, Resource singleSuperType) {\r
+\r
+                    if(singleSuperType != null) {\r
+                        getSingleTypeAdapter(graph, decl, key, instance, singleSuperType, possible, procedure);\r
+                    } else {\r
+                        graph.asyncRequest(new SingleTypeAdapter<T,C>(decl, key, instance, possible), procedure);\r
+                    }\r
+\r
+                }\r
+\r
+            });\r
+\r
+\r
+        }\r
+\r
+    }\r
+    \r
+    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
+\r
+        @SuppressWarnings("unchecked")\r
+        Adapter<T,C> adapter = (Adapter<T,C>)decl.typeAdapters.get(type);\r
+        if(adapter != null) return adapter;\r
+        \r
+        Layer0 L0 = Layer0.getInstance(graph);\r
+        Resource singleSuperType = graph.getPossibleObject(type, L0.Inherits);\r
+        if(singleSuperType != null) {\r
+            return getSingleTypeAdapter(graph, decl, key, instance, singleSuperType, possible);\r
+        } else {\r
+            return graph.syncRequest(new SingleTypeAdapter<T,C>(decl, key, instance, possible), TransientCacheAsyncListener.<Adapter<T,C>>instance());\r
+        }\r
+\r
+    }    \r
+    \r
+//    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
+//\r
+//        @SuppressWarnings("unchecked")\r
+//        Adapter<T,C> adapter = (Adapter<T,C>)decl.typeAdapters.get(type);\r
+//        if(adapter != null) {\r
+//\r
+//            adapter.adapt(graph, instance, context, procedure);\r
+//\r
+//        } else {\r
+//\r
+//            graph.forPossibleObject(type, graph.getService(Layer0.class).Inherits, new AsyncProcedure<Resource>() {\r
+//\r
+//                @Override\r
+//                public void exception(AsyncReadGraph graph, Throwable throwable) {\r
+//\r
+//                    procedure.exception(graph, new AdaptionException("Problems in reading super types for resource. ", throwable));\r
+//\r
+//                }\r
+//\r
+//                @Override\r
+//                public void execute(AsyncReadGraph graph, Resource singleSuperType) {\r
+//\r
+//                    if(singleSuperType != null) {\r
+//\r
+//                        adaptSingleType(graph, decl, context, instance, singleSuperType, possible, procedure);\r
+//\r
+//                    } else {\r
+//\r
+//                        graph.asyncRequest(new Read<T>() {\r
+//\r
+//                            @Override\r
+//                            public T perform(ReadGraph graph)\r
+//                            throws DatabaseException {\r
+//                                return decl.adapt(graph, instance, context, possible);\r
+//                            }\r
+//\r
+//                        }, procedure);\r
+//\r
+//                    }\r
+//\r
+//                }\r
+//\r
+//            });\r
+//\r
+//\r
+//        }\r
+//\r
+//    }\r
+\r
+    \r
+    private static class SingleSuperTypeAdapter<T, C> extends TernaryRead<Pair<Class<T>, Class<?>>, Resource, Boolean, Adapter<T,C>> {\r
+\r
+       final private AdapterDeclaration<T> decl;\r
+       \r
+       SingleSuperTypeAdapter(AdapterDeclaration<T> decl, Pair<Class<T>, Class<?>> key, Resource type, Boolean possible) {\r
+               super(key, type, possible);\r
+               this.decl = decl;\r
+       }\r
+       \r
+        @Override\r
+        public Adapter<T,C> perform(ReadGraph graph) throws DatabaseException {\r
+            return decl.findAdapter(graph, parameter2, parameter3);\r
+        }\r
+\r
+    }\r
+    \r
+    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
+\r
+        @SuppressWarnings("unchecked")\r
+        Adapter<T, C> adapter = (Adapter<T, C>)decl.instanceAdapters.get(superType);\r
+        if(adapter != null) {\r
+               procedure.execute(graph, adapter);\r
+        } else {\r
+\r
+            graph.forPossibleObject(superType, graph.getService(Layer0.class).Inherits, new AsyncProcedure<Resource>() {\r
+\r
+                @Override\r
+                public void exception(AsyncReadGraph graph, Throwable throwable) {\r
+                    procedure.exception(graph, new AdaptionException("Problems in reading super types for resource. ", throwable));\r
+                }\r
+\r
+                @Override\r
+                public void execute(AsyncReadGraph graph, Resource singleSuperType) {\r
+\r
+                    if(singleSuperType != null) {\r
+\r
+                        getSingleSuperTypeAdapter(graph, decl, key, type, singleSuperType, possible, procedure);\r
+\r
+                    } else {\r
+\r
+                        graph.asyncRequest(new SingleSuperTypeAdapter<T,C>(decl, key, type, possible), procedure);\r
+\r
+                    }\r
+\r
+                }\r
+\r
+            });\r
+\r
+        }\r
+\r
+    }\r
+\r
+    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
+\r
+        @SuppressWarnings("unchecked")\r
+        Adapter<T, C> adapter = (Adapter<T, C>)decl.instanceAdapters.get(superType);\r
+        if(adapter != null) return adapter;\r
+        \r
+        Layer0 L0 = Layer0.getInstance(graph);\r
+        Resource singleSuperType = graph.getPossibleObject(superType, L0.Inherits);\r
+        if(singleSuperType != null) {\r
+               return getSingleSuperTypeAdapter(graph, decl, key, type, singleSuperType, possible);\r
+        } else {\r
+               return graph.syncRequest(new SingleSuperTypeAdapter<T,C>(decl, key, type, possible));\r
+        }\r
+\r
+    }\r
+    \r
+//    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
+//\r
+//        @SuppressWarnings("unchecked")\r
+//        Adapter<T, C> adapter = (Adapter<T, C>)decl.instanceAdapters.get(superType);\r
+//        if(adapter != null) {\r
+//\r
+//            adapter.adapt(graph, type, context, procedure);\r
+//\r
+//        } else {\r
+//\r
+//            graph.forPossibleObject(superType, graph.getService(Layer0.class).Inherits, new AsyncProcedure<Resource>() {\r
+//\r
+//                @Override\r
+//                public void exception(AsyncReadGraph graph, Throwable throwable) {\r
+//\r
+//                    procedure.exception(graph, new AdaptionException("Problems in reading super types for resource. ", throwable));\r
+//\r
+//                }\r
+//\r
+//                @Override\r
+//                public void execute(AsyncReadGraph graph, Resource singleSuperType) {\r
+//\r
+//                    if(singleSuperType != null) {\r
+//\r
+//                        adaptSingleSupertype(graph, decl, context, type, singleSuperType, possible, procedure);\r
+//\r
+//                    } else {\r
+//\r
+//                        graph.asyncRequest(new Read<T>() {\r
+//\r
+//                            @Override\r
+//                            public T perform(ReadGraph graph)\r
+//                            throws DatabaseException {\r
+//                                return decl.adapt(graph, type, context, possible);\r
+//                            }\r
+//\r
+//                        }, procedure);\r
+//\r
+//                    }\r
+//\r
+//                }\r
+//\r
+//            });\r
+//\r
+//        }\r
+//\r
+//    }\r
+\r
+    @Override\r
+    public <T> void adaptNew(AsyncReadGraph g, final Resource r, final Class<T> clazz, final boolean possible, final AsyncProcedure<T> procedure) {\r
+\r
+        g.asyncRequest(new ReadRequest() {\r
+\r
+            @Override\r
+            public void run(ReadGraph graph) throws DatabaseException {\r
+\r
+               final Pair<Class<T>, Class<?>> key = new Pair<Class<T>, Class<?>>(clazz, Resource.class); \r
+\r
+                @SuppressWarnings("unchecked")\r
+                AdapterDeclaration<T> decl =\r
+                    (AdapterDeclaration<T>)adapters.get(key);\r
+\r
+                if(decl == null) {\r
+                    if(possible) {\r
+                        procedure.execute(graph, null);\r
+                    } else {\r
+                        procedure.exception(graph, new AdaptionException("There are no adapters declared or defined for class " + clazz + "."));\r
+                    }\r
+                } else {\r
+                    try {\r
+                        procedure.execute(graph, decl.adaptNew(graph, r, possible));\r
+                    } catch (AdaptionException e) {\r
+                        if(possible) {\r
+                            procedure.execute(graph, null);\r
+                        } else {\r
+                            procedure.exception(graph, e);\r
+                        }\r
+                    } catch (ValidationException e) {\r
+                        procedure.exception(graph, e);\r
+                    } catch (DatabaseException e2) {\r
+                        procedure.exception(graph, new ServiceException(e2));\r
+                    }\r
+                }\r
+\r
+            }\r
+\r
+        });\r
+\r
+    }\r
+\r
+    @Override\r
+    public <T> void addInstanceAdapter(Resource resource, Class<T> targetClass, Adapter<T,?> adapter) {\r
+       addInstanceAdapter(resource, targetClass, Resource.class, adapter);\r
+    }\r
+\r
+    @Override\r
+    public <T> void addInstanceAdapter(Resource resource, Class<T> targetClass, Class<?> contextClass, Adapter<T,?> adapter) {\r
+        synchronized (this) {\r
+            getDeclaration(targetClass, contextClass).instanceAdapters.put(resource, adapter);\r
+        }\r
+    }\r
+\r
+    @Override\r
+    public <T> Adapter<T,?> removeInstanceAdapter(Resource resource, Class<T> targetClass) {\r
+       return removeInstanceAdapter(resource, targetClass, Resource.class);\r
+    }\r
+    \r
+    @Override\r
+    public <T> Adapter<T,?> removeInstanceAdapter(Resource resource, Class<T> targetClass, Class<?> contextClass) {\r
+        synchronized (this) {\r
+            return getDeclaration(targetClass, contextClass).instanceAdapters.remove(resource);\r
+        }\r
+    }\r
+\r
+    @Override\r
+    public <T> void removeInstanceAdapter(Resource resource, Class<T> targetClass, Adapter<T,?> adapter) {\r
+       removeInstanceAdapter(resource, targetClass, Resource.class, adapter);\r
+    }\r
+\r
+    @Override\r
+    public <T> void removeInstanceAdapter(Resource resource, Class<T> targetClass, Class<?> contextClass, Adapter<T,?> adapter) {\r
+        synchronized (this) {\r
+            AdapterDeclaration<T> decl = getDeclaration(targetClass, contextClass);\r
+            Adapter<T,?> existing = decl.instanceAdapters.get(resource);\r
+            if (existing == adapter) {\r
+                decl.instanceAdapters.remove(resource);\r
+            }\r
+        }\r
+    }\r
+\r
+    @Override\r
+    public <T> void addAdapter(Resource type, Class<T> targetClass, Adapter<T,?> adapter) {\r
+        addAdapter(type, targetClass, Resource.class, adapter);\r
+    }\r
+\r
+    @Override\r
+    public <T> void addAdapter(Resource type, Class<T> targetClass, Class<?> contextClass, Adapter<T,?> adapter) {\r
+        getDeclaration(targetClass, contextClass).typeAdapters.put(type, adapter);\r
+    }\r
+\r
+    @Override\r
+    public <T> void declareAdapter(Resource type, Class<T> targetClass) {\r
+       declareAdapter(type, targetClass, Resource.class);\r
+    }\r
+\r
+    @Override\r
+    public <T> void declareAdapter(Resource type, Class<T> targetClass, Class<?> contextClass) {\r
+        getDeclaration(targetClass, contextClass).baseTypes.add(type);\r
+    }\r
+\r
+    public static String safeName(ReadGraph g, Resource r) throws DatabaseException {\r
+//        Builtins b = g.getBuiltins();\r
+//        for(Resource name : g.getObjects(r, b.HasName))\r
+//            return g.getValue(name);\r
+//        for(Resource t : g.getObjects(r, b.InstanceOf))\r
+//            for(Resource name : g.getObjects(t, b.HasName))\r
+//                return ": "+ g.getValue(name);\r
+//        for(Resource t : g.getObjects(r, b.Inherits))\r
+//            for(Resource name : g.getObjects(t, b.HasName))\r
+//                return "<T "+ g.getValue(name);\r
+//        for(Resource t : g.getObjects(r, b.SubrelationOf))\r
+//            for(Resource name : g.getObjects(t, b.HasName))\r
+//                return "<R "+ g.getValue(name);\r
+//        if(g.hasValue(r))\r
+//            return "\"" + g.getValue(r) + "\"";\r
+//        return "" + r.getResourceId();\r
+        return NameUtils.getSafeName(g, r, true);\r
+    }\r
+\r
+}
\ No newline at end of file