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