--- /dev/null
+/*******************************************************************************\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