X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics.db.services%2Fsrc%2Forg%2Fsimantics%2Fdb%2Fservices%2Fadaption%2FAdaptionService2.java;fp=bundles%2Forg.simantics.db.services%2Fsrc%2Forg%2Fsimantics%2Fdb%2Fservices%2Fadaption%2FAdaptionService2.java;h=47a14ddbcbccc7424bec9fe1ea059c588dffc24d;hb=0ae2b770234dfc3cbb18bd38f324125cf0faca07;hp=b7cc76a09c97ffb712ed5a0a99ea2855411e91b5;hpb=24e2b34260f219f0d1644ca7a138894980e25b14;p=simantics%2Fplatform.git diff --git a/bundles/org.simantics.db.services/src/org/simantics/db/services/adaption/AdaptionService2.java b/bundles/org.simantics.db.services/src/org/simantics/db/services/adaption/AdaptionService2.java index b7cc76a09..47a14ddbc 100644 --- a/bundles/org.simantics.db.services/src/org/simantics/db/services/adaption/AdaptionService2.java +++ b/bundles/org.simantics.db.services/src/org/simantics/db/services/adaption/AdaptionService2.java @@ -1,973 +1,973 @@ -/******************************************************************************* - * Copyright (c) 2007, 2010 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 gnu.trove.map.hash.THashMap; -import gnu.trove.procedure.TObjectObjectProcedure; -import gnu.trove.set.hash.THashSet; - -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.procedure.single.SyncReadProcedure; -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; - -public class AdaptionService2 implements AdaptionService { - - THashMap,Class>, AdapterDeclaration> adapters = - new THashMap,Class>, AdapterDeclaration>(); - - /** - * Contains all adapter declarations and definitions for one class (clazz). - */ - static class AdapterDeclaration { - Class clazz; - THashMap> typeAdapters = - new THashMap>(); - THashMap> instanceAdapters = - new THashMap>(); - THashSet baseTypes = new THashSet(); - - 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>() { - - @Override - public boolean execute(Resource arg0, Adapter 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>() { - - @Override - public boolean execute(Resource arg0, Adapter 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 clazz) { - this.clazz = clazz; - } - - static class AdapterResult { - Adapter adapter; - Resource type; - - public AdapterResult(Adapter 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 extends BinaryRead, AdapterResult> { - - public GetInheritedAdapter(Resource type, AdapterDeclaration decl) { - super(type, decl); - } - - AdapterDeclaration getDeclaration() { - return parameter2; - } - - @Override - public String toString() { - return "GetInheritedAdapter|" + parameter + "|" + parameter2; - } - - @SuppressWarnings("unchecked") - @Override - public AdapterResult perform(ReadGraph g) throws DatabaseException { - Layer0 b = Layer0.getInstance(g); - AdapterResult result = null; - for(Resource supertype : g.getObjects(parameter, b.Inherits)) { - Adapter adapter = (Adapter)parameter2.typeAdapters.get(supertype); - if(adapter != null) { - if(result == null) - result = new AdapterResult(adapter, supertype); - else if(!result.type.equals(supertype) && - !g.isInheritedFrom(result.type, supertype)) { - if(g.isInheritedFrom(supertype, result.type)) - result = new AdapterResult(adapter, supertype); - else throw new AdaptionException("Type " + - safeName(g, parameter) + " inherits conflicting adapters from " - + safeName(g, supertype) + " and " + safeName(g, result.type)); - } - } - else { - AdapterResult temp = - g.syncRequest(new GetInheritedAdapter(supertype, parameter2), TransientCacheAsyncListener.>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; - } - - } - - void inheritedAdapter(AsyncReadGraph graph, Resource type, AsyncProcedure> procedure) { - graph.asyncRequest(new GetInheritedAdapter(type, this), procedure); - } - - Adapter directAdapter(Resource r) { - Adapter ret; - synchronized (this) { - ret = instanceAdapters.get(r); - } - return ret; - } - - static class FindAdapter extends BinaryRead, Adapter> { - - public FindAdapter(Resource resource, AdapterDeclaration decl) { - super(resource, decl); - } - - @SuppressWarnings("unchecked") - Adapter findAdapter(Resource r, ReadGraph g) throws DatabaseException { - - { - Adapter adapter; - synchronized (this) { - adapter = (Adapter)parameter2.instanceAdapters.get(r); - } - if(adapter != null) - return adapter; - } - - Layer0 b = Layer0.getInstance(g); - - /* - * Try to find adapter from immediate types - */ - AdapterResult adapterResult = null; - for(Resource t : g.getObjects(r, b.InstanceOf)) { - Adapter adapter = (Adapter)parameter2.typeAdapters.get(t); - if(adapter != null) { - if(adapterResult == null) - adapterResult = new AdapterResult(adapter, t); - else if(!adapterResult.type.equals(t) && - !g.isInheritedFrom(adapterResult.type, t)) { - if(g.isInheritedFrom(t, adapterResult.type)) - adapterResult = new AdapterResult(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 temp = - g.syncRequest(new GetInheritedAdapter(t, parameter2), TransientCacheAsyncListener.>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 adapter = findAdapter(t, g); - if(adapter != null) - return adapter; - } - - for(Resource t : g.getObjects(r, b.SubrelationOf)) { - Adapter adapter = findAdapter(t, g); - if(adapter != null) - return adapter; - } - - return null; - - } - - - @Override - public Adapter perform(ReadGraph g) throws DatabaseException { - return (Adapter)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 implements Read { - - Resource resource; - C context; - - public Adapt(Resource resource, C context) { - this.resource = resource; - this.context = context; - } - - AdapterDeclaration getDeclaration() { - return AdapterDeclaration.this; - } - - @SuppressWarnings("unchecked") - Adapter findAdapter(Resource r, ReadGraph g) throws DatabaseException { - - { - Adapter adapter; - synchronized (this) { - adapter = (Adapter)instanceAdapters.get(r); - } - if(adapter != null) - return adapter; - } - - Layer0 b = Layer0.getInstance(g); - - /* - * Try to find adapter from immediate types - */ - AdapterResult adapterResult = null; - for(Resource t : g.getObjects(r, b.InstanceOf)) { - Adapter adapter = (Adapter)typeAdapters.get(t); - if(adapter != null) { - if(adapterResult == null) - adapterResult = new AdapterResult(adapter, t); - else if(!adapterResult.type.equals(t) && - !g.isInheritedFrom(adapterResult.type, t)) { - if(g.isInheritedFrom(t, adapterResult.type)) - adapterResult = new AdapterResult(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 temp = - g.syncRequest(new GetInheritedAdapter(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 adapter = findAdapter(t, g); - if(adapter != null) - return adapter; - } - - for(Resource t : g.getObjects(r, b.SubrelationOf)) { - Adapter adapter = findAdapter(t, g); - if(adapter != null) - return adapter; - } - - return null; - - } - - @Override - public T perform(ReadGraph g) throws DatabaseException { - - final Adapter adapter = (Adapter)findAdapter(resource, g); - if(adapter == null) return null; - else return g.syncRequest(new AsyncRead() { - - @Override - public void perform(AsyncReadGraph graph, AsyncProcedure procedure) { -// System.out.println("adapter=" + adapter); - adapter.adapt(graph, resource, context, procedure); - } - - @Override - public int threadHash() { - return hashCode(); - } - - @Override - public int getFlags() { - return 0; - } - - }); - - } - - @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 procedure) { -// graph.asyncRequest(new Adapt(r), procedure); -// } - - Adapter findAdapter(ReadGraph g, Resource r, boolean possible) throws DatabaseException { - - Adapter result = g.syncRequest(new FindAdapter(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)); - - } - - T adapt(ReadGraph g, Resource r, C context, boolean possible) throws DatabaseException { - - T result = g.syncRequest(new Adapt(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(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 AdapterDeclaration getDeclaration(Class targetClass, Class contextClass) { - Pair,Class> key = new Pair,Class>(targetClass, contextClass); - @SuppressWarnings("unchecked") - AdapterDeclaration decl = - (AdapterDeclaration)adapters.get(key); - if(decl == null) { - decl = new AdapterDeclaration(targetClass); - adapters.put(key, decl); - } - return decl; - } - - public void getAdapter(AsyncReadGraph graph, final Resource r, final Class contextClass, final Class targetClass, final boolean possible, final AsyncProcedure> procedure) { - - final Pair, Class> key = new Pair, Class>(targetClass, contextClass); - @SuppressWarnings("unchecked") - final AdapterDeclaration decl = (AdapterDeclaration)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 adapter = (Adapter)decl.directAdapter(r); - if(adapter != null) { - procedure.execute(graph, adapter); - } else { - graph.forPossibleObject(r, graph.getService(Layer0.class).InstanceOf, new AsyncProcedure() { - - @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 void adapt(AsyncReadGraph graph, final Resource r, final C context, Class contextClass, Class targetClass, final boolean possible, final AsyncProcedure procedure) { - - getAdapter(graph, r, contextClass, targetClass, possible, new AsyncProcedure>() { - - @Override - public void execute(AsyncReadGraph graph, Adapter 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 adapt(ReadGraph g, Resource r, C context, Class contextClass, Class targetClass, boolean possible) throws DatabaseException { - - Adapter adapter = getAdapter(g, r, context, contextClass, targetClass, possible); - - SyncReadProcedure procedure = new SyncReadProcedure(); - adapter.adapt(g, r, context, procedure); - procedure.checkAndThrow(); - return procedure.result; - - } - - private Adapter getAdapter(ReadGraph g, Resource r, C context, Class contextClass, Class targetClass, boolean possible) throws DatabaseException { - - final Pair, Class> key = new Pair, Class>(targetClass, contextClass); - @SuppressWarnings("unchecked") - final AdapterDeclaration decl = (AdapterDeclaration)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 adapter = (Adapter)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 extends TernaryRead, Class>, Resource, Boolean, Adapter> { - - final private AdapterDeclaration decl; - - SingleTypeAdapter(AdapterDeclaration decl, Pair, Class> key, Resource instance, Boolean possible) { - super(key, instance, possible); - this.decl = decl; - } - - @Override - public Adapter perform(ReadGraph graph) throws DatabaseException { - return decl.findAdapter(graph, parameter2, parameter3); - } - - } - - private void getSingleTypeAdapter(AsyncReadGraph graph, final AdapterDeclaration decl, final Pair, Class> key, final Resource instance, final Resource type, final boolean possible, final AsyncProcedure> procedure) { - - @SuppressWarnings("unchecked") - Adapter adapter = (Adapter)decl.typeAdapters.get(type); - if(adapter != null) { - procedure.execute(graph, adapter); - } else { - graph.forPossibleObject(type, graph.getService(Layer0.class).Inherits, new AsyncProcedure() { - - @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(decl, key, instance, possible), procedure); - } - - } - - }); - - - } - - } - - private Adapter getSingleTypeAdapter(ReadGraph graph, final AdapterDeclaration decl, final Pair, Class> key, final Resource instance, final Resource type, final boolean possible) throws DatabaseException { - - @SuppressWarnings("unchecked") - Adapter adapter = (Adapter)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(decl, key, instance, possible), TransientCacheAsyncListener.>instance()); - } - - } - -// private void adaptSingleType(AsyncReadGraph graph, final AdapterDeclaration decl, final C context, final Resource instance, final Resource type, final boolean possible, final AsyncProcedure procedure) { -// -// @SuppressWarnings("unchecked") -// Adapter adapter = (Adapter)decl.typeAdapters.get(type); -// if(adapter != null) { -// -// adapter.adapt(graph, instance, context, procedure); -// -// } else { -// -// graph.forPossibleObject(type, graph.getService(Layer0.class).Inherits, new AsyncProcedure() { -// -// @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() { -// -// @Override -// public T perform(ReadGraph graph) -// throws DatabaseException { -// return decl.adapt(graph, instance, context, possible); -// } -// -// }, procedure); -// -// } -// -// } -// -// }); -// -// -// } -// -// } - - - private static class SingleSuperTypeAdapter extends TernaryRead, Class>, Resource, Boolean, Adapter> { - - final private AdapterDeclaration decl; - - SingleSuperTypeAdapter(AdapterDeclaration decl, Pair, Class> key, Resource type, Boolean possible) { - super(key, type, possible); - this.decl = decl; - } - - @Override - public Adapter perform(ReadGraph graph) throws DatabaseException { - return decl.findAdapter(graph, parameter2, parameter3); - } - - } - - private void getSingleSuperTypeAdapter(AsyncReadGraph graph, final AdapterDeclaration decl, final Pair, Class> key, final Resource type, final Resource superType, final boolean possible, final AsyncProcedure> procedure) { - - @SuppressWarnings("unchecked") - Adapter adapter = (Adapter)decl.instanceAdapters.get(superType); - if(adapter != null) { - procedure.execute(graph, adapter); - } else { - - graph.forPossibleObject(superType, graph.getService(Layer0.class).Inherits, new AsyncProcedure() { - - @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(decl, key, type, possible), procedure); - - } - - } - - }); - - } - - } - - private Adapter getSingleSuperTypeAdapter(ReadGraph graph, final AdapterDeclaration decl, final Pair, Class> key, final Resource type, final Resource superType, final boolean possible) throws DatabaseException { - - @SuppressWarnings("unchecked") - Adapter adapter = (Adapter)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(decl, key, type, possible)); - } - - } - -// private void adaptSingleSupertype(AsyncReadGraph graph, final AdapterDeclaration decl, final C context, final Resource type, final Resource superType, final boolean possible, final AsyncProcedure procedure) { -// -// @SuppressWarnings("unchecked") -// Adapter adapter = (Adapter)decl.instanceAdapters.get(superType); -// if(adapter != null) { -// -// adapter.adapt(graph, type, context, procedure); -// -// } else { -// -// graph.forPossibleObject(superType, graph.getService(Layer0.class).Inherits, new AsyncProcedure() { -// -// @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() { -// -// @Override -// public T perform(ReadGraph graph) -// throws DatabaseException { -// return decl.adapt(graph, type, context, possible); -// } -// -// }, procedure); -// -// } -// -// } -// -// }); -// -// } -// -// } - - @Override - public void adaptNew(AsyncReadGraph g, final Resource r, final Class clazz, final boolean possible, final AsyncProcedure procedure) { - - g.asyncRequest(new ReadRequest() { - - @Override - public void run(ReadGraph graph) throws DatabaseException { - - final Pair, Class> key = new Pair, Class>(clazz, Resource.class); - - @SuppressWarnings("unchecked") - AdapterDeclaration decl = - (AdapterDeclaration)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 " + clazz + ".")); - } - } else { - try { - procedure.execute(graph, decl.adaptNew(graph, r, possible)); - } catch (AdaptionException e) { - if(possible) { - procedure.execute(graph, null); - } else { - procedure.exception(graph, e); - } - } catch (ValidationException e) { - procedure.exception(graph, e); - } catch (DatabaseException e2) { - procedure.exception(graph, new ServiceException(e2)); - } - } - - } - - }); - - } - - @Override - public void addInstanceAdapter(Resource resource, Class targetClass, Adapter adapter) { - addInstanceAdapter(resource, targetClass, Resource.class, adapter); - } - - @Override - public void addInstanceAdapter(Resource resource, Class targetClass, Class contextClass, Adapter adapter) { - synchronized (this) { - getDeclaration(targetClass, contextClass).instanceAdapters.put(resource, adapter); - } - } - - @Override - public Adapter removeInstanceAdapter(Resource resource, Class targetClass) { - return removeInstanceAdapter(resource, targetClass, Resource.class); - } - - @Override - public Adapter removeInstanceAdapter(Resource resource, Class targetClass, Class contextClass) { - synchronized (this) { - return getDeclaration(targetClass, contextClass).instanceAdapters.remove(resource); - } - } - - @Override - public void removeInstanceAdapter(Resource resource, Class targetClass, Adapter adapter) { - removeInstanceAdapter(resource, targetClass, Resource.class, adapter); - } - - @Override - public void removeInstanceAdapter(Resource resource, Class targetClass, Class contextClass, Adapter adapter) { - synchronized (this) { - AdapterDeclaration decl = getDeclaration(targetClass, contextClass); - Adapter existing = decl.instanceAdapters.get(resource); - if (existing == adapter) { - decl.instanceAdapters.remove(resource); - } - } - } - - @Override - public void addAdapter(Resource type, Class targetClass, Adapter adapter) { - addAdapter(type, targetClass, Resource.class, adapter); - } - - @Override - public void addAdapter(Resource type, Class targetClass, Class contextClass, Adapter adapter) { - getDeclaration(targetClass, contextClass).typeAdapters.put(type, adapter); - } - - @Override - public void declareAdapter(Resource type, Class targetClass) { - declareAdapter(type, targetClass, Resource.class); - } - - @Override - public void declareAdapter(Resource type, Class 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 ",Class>, AdapterDeclaration> adapters = + new THashMap,Class>, AdapterDeclaration>(); + + /** + * Contains all adapter declarations and definitions for one class (clazz). + */ + static class AdapterDeclaration { + Class clazz; + THashMap> typeAdapters = + new THashMap>(); + THashMap> instanceAdapters = + new THashMap>(); + THashSet baseTypes = new THashSet(); + + 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>() { + + @Override + public boolean execute(Resource arg0, Adapter 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>() { + + @Override + public boolean execute(Resource arg0, Adapter 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 clazz) { + this.clazz = clazz; + } + + static class AdapterResult { + Adapter adapter; + Resource type; + + public AdapterResult(Adapter 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 extends BinaryRead, AdapterResult> { + + public GetInheritedAdapter(Resource type, AdapterDeclaration decl) { + super(type, decl); + } + + AdapterDeclaration getDeclaration() { + return parameter2; + } + + @Override + public String toString() { + return "GetInheritedAdapter|" + parameter + "|" + parameter2; + } + + @SuppressWarnings("unchecked") + @Override + public AdapterResult perform(ReadGraph g) throws DatabaseException { + Layer0 b = Layer0.getInstance(g); + AdapterResult result = null; + for(Resource supertype : g.getObjects(parameter, b.Inherits)) { + Adapter adapter = (Adapter)parameter2.typeAdapters.get(supertype); + if(adapter != null) { + if(result == null) + result = new AdapterResult(adapter, supertype); + else if(!result.type.equals(supertype) && + !g.isInheritedFrom(result.type, supertype)) { + if(g.isInheritedFrom(supertype, result.type)) + result = new AdapterResult(adapter, supertype); + else throw new AdaptionException("Type " + + safeName(g, parameter) + " inherits conflicting adapters from " + + safeName(g, supertype) + " and " + safeName(g, result.type)); + } + } + else { + AdapterResult temp = + g.syncRequest(new GetInheritedAdapter(supertype, parameter2), TransientCacheAsyncListener.>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; + } + + } + + void inheritedAdapter(AsyncReadGraph graph, Resource type, AsyncProcedure> procedure) { + graph.asyncRequest(new GetInheritedAdapter(type, this), procedure); + } + + Adapter directAdapter(Resource r) { + Adapter ret; + synchronized (this) { + ret = instanceAdapters.get(r); + } + return ret; + } + + static class FindAdapter extends BinaryRead, Adapter> { + + public FindAdapter(Resource resource, AdapterDeclaration decl) { + super(resource, decl); + } + + @SuppressWarnings("unchecked") + Adapter findAdapter(Resource r, ReadGraph g) throws DatabaseException { + + { + Adapter adapter; + synchronized (this) { + adapter = (Adapter)parameter2.instanceAdapters.get(r); + } + if(adapter != null) + return adapter; + } + + Layer0 b = Layer0.getInstance(g); + + /* + * Try to find adapter from immediate types + */ + AdapterResult adapterResult = null; + for(Resource t : g.getObjects(r, b.InstanceOf)) { + Adapter adapter = (Adapter)parameter2.typeAdapters.get(t); + if(adapter != null) { + if(adapterResult == null) + adapterResult = new AdapterResult(adapter, t); + else if(!adapterResult.type.equals(t) && + !g.isInheritedFrom(adapterResult.type, t)) { + if(g.isInheritedFrom(t, adapterResult.type)) + adapterResult = new AdapterResult(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 temp = + g.syncRequest(new GetInheritedAdapter(t, parameter2), TransientCacheAsyncListener.>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 adapter = findAdapter(t, g); + if(adapter != null) + return adapter; + } + + for(Resource t : g.getObjects(r, b.SubrelationOf)) { + Adapter adapter = findAdapter(t, g); + if(adapter != null) + return adapter; + } + + return null; + + } + + + @Override + public Adapter perform(ReadGraph g) throws DatabaseException { + return (Adapter)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 implements Read { + + Resource resource; + C context; + + public Adapt(Resource resource, C context) { + this.resource = resource; + this.context = context; + } + + AdapterDeclaration getDeclaration() { + return AdapterDeclaration.this; + } + + @SuppressWarnings("unchecked") + Adapter findAdapter(Resource r, ReadGraph g) throws DatabaseException { + + { + Adapter adapter; + synchronized (this) { + adapter = (Adapter)instanceAdapters.get(r); + } + if(adapter != null) + return adapter; + } + + Layer0 b = Layer0.getInstance(g); + + /* + * Try to find adapter from immediate types + */ + AdapterResult adapterResult = null; + for(Resource t : g.getObjects(r, b.InstanceOf)) { + Adapter adapter = (Adapter)typeAdapters.get(t); + if(adapter != null) { + if(adapterResult == null) + adapterResult = new AdapterResult(adapter, t); + else if(!adapterResult.type.equals(t) && + !g.isInheritedFrom(adapterResult.type, t)) { + if(g.isInheritedFrom(t, adapterResult.type)) + adapterResult = new AdapterResult(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 temp = + g.syncRequest(new GetInheritedAdapter(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 adapter = findAdapter(t, g); + if(adapter != null) + return adapter; + } + + for(Resource t : g.getObjects(r, b.SubrelationOf)) { + Adapter adapter = findAdapter(t, g); + if(adapter != null) + return adapter; + } + + return null; + + } + + @Override + public T perform(ReadGraph g) throws DatabaseException { + + final Adapter adapter = (Adapter)findAdapter(resource, g); + if(adapter == null) return null; + else return g.syncRequest(new AsyncRead() { + + @Override + public void perform(AsyncReadGraph graph, AsyncProcedure procedure) { +// System.out.println("adapter=" + adapter); + adapter.adapt(graph, resource, context, procedure); + } + + @Override + public int threadHash() { + return hashCode(); + } + + @Override + public int getFlags() { + return 0; + } + + }); + + } + + @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 procedure) { +// graph.asyncRequest(new Adapt(r), procedure); +// } + + Adapter findAdapter(ReadGraph g, Resource r, boolean possible) throws DatabaseException { + + Adapter result = g.syncRequest(new FindAdapter(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)); + + } + + T adapt(ReadGraph g, Resource r, C context, boolean possible) throws DatabaseException { + + T result = g.syncRequest(new Adapt(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(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 AdapterDeclaration getDeclaration(Class targetClass, Class contextClass) { + Pair,Class> key = new Pair,Class>(targetClass, contextClass); + @SuppressWarnings("unchecked") + AdapterDeclaration decl = + (AdapterDeclaration)adapters.get(key); + if(decl == null) { + decl = new AdapterDeclaration(targetClass); + adapters.put(key, decl); + } + return decl; + } + + public void getAdapter(AsyncReadGraph graph, final Resource r, final Class contextClass, final Class targetClass, final boolean possible, final AsyncProcedure> procedure) { + + final Pair, Class> key = new Pair, Class>(targetClass, contextClass); + @SuppressWarnings("unchecked") + final AdapterDeclaration decl = (AdapterDeclaration)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 adapter = (Adapter)decl.directAdapter(r); + if(adapter != null) { + procedure.execute(graph, adapter); + } else { + graph.forPossibleObject(r, graph.getService(Layer0.class).InstanceOf, new AsyncProcedure() { + + @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 void adapt(AsyncReadGraph graph, final Resource r, final C context, Class contextClass, Class targetClass, final boolean possible, final AsyncProcedure procedure) { + + getAdapter(graph, r, contextClass, targetClass, possible, new AsyncProcedure>() { + + @Override + public void execute(AsyncReadGraph graph, Adapter 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 adapt(ReadGraph g, Resource r, C context, Class contextClass, Class targetClass, boolean possible) throws DatabaseException { + + Adapter adapter = getAdapter(g, r, context, contextClass, targetClass, possible); + + SyncReadProcedure procedure = new SyncReadProcedure(); + adapter.adapt(g, r, context, procedure); + procedure.checkAndThrow(); + return procedure.result; + + } + + private Adapter getAdapter(ReadGraph g, Resource r, C context, Class contextClass, Class targetClass, boolean possible) throws DatabaseException { + + final Pair, Class> key = new Pair, Class>(targetClass, contextClass); + @SuppressWarnings("unchecked") + final AdapterDeclaration decl = (AdapterDeclaration)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 adapter = (Adapter)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 extends TernaryRead, Class>, Resource, Boolean, Adapter> { + + final private AdapterDeclaration decl; + + SingleTypeAdapter(AdapterDeclaration decl, Pair, Class> key, Resource instance, Boolean possible) { + super(key, instance, possible); + this.decl = decl; + } + + @Override + public Adapter perform(ReadGraph graph) throws DatabaseException { + return decl.findAdapter(graph, parameter2, parameter3); + } + + } + + private void getSingleTypeAdapter(AsyncReadGraph graph, final AdapterDeclaration decl, final Pair, Class> key, final Resource instance, final Resource type, final boolean possible, final AsyncProcedure> procedure) { + + @SuppressWarnings("unchecked") + Adapter adapter = (Adapter)decl.typeAdapters.get(type); + if(adapter != null) { + procedure.execute(graph, adapter); + } else { + graph.forPossibleObject(type, graph.getService(Layer0.class).Inherits, new AsyncProcedure() { + + @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(decl, key, instance, possible), procedure); + } + + } + + }); + + + } + + } + + private Adapter getSingleTypeAdapter(ReadGraph graph, final AdapterDeclaration decl, final Pair, Class> key, final Resource instance, final Resource type, final boolean possible) throws DatabaseException { + + @SuppressWarnings("unchecked") + Adapter adapter = (Adapter)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(decl, key, instance, possible), TransientCacheAsyncListener.>instance()); + } + + } + +// private void adaptSingleType(AsyncReadGraph graph, final AdapterDeclaration decl, final C context, final Resource instance, final Resource type, final boolean possible, final AsyncProcedure procedure) { +// +// @SuppressWarnings("unchecked") +// Adapter adapter = (Adapter)decl.typeAdapters.get(type); +// if(adapter != null) { +// +// adapter.adapt(graph, instance, context, procedure); +// +// } else { +// +// graph.forPossibleObject(type, graph.getService(Layer0.class).Inherits, new AsyncProcedure() { +// +// @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() { +// +// @Override +// public T perform(ReadGraph graph) +// throws DatabaseException { +// return decl.adapt(graph, instance, context, possible); +// } +// +// }, procedure); +// +// } +// +// } +// +// }); +// +// +// } +// +// } + + + private static class SingleSuperTypeAdapter extends TernaryRead, Class>, Resource, Boolean, Adapter> { + + final private AdapterDeclaration decl; + + SingleSuperTypeAdapter(AdapterDeclaration decl, Pair, Class> key, Resource type, Boolean possible) { + super(key, type, possible); + this.decl = decl; + } + + @Override + public Adapter perform(ReadGraph graph) throws DatabaseException { + return decl.findAdapter(graph, parameter2, parameter3); + } + + } + + private void getSingleSuperTypeAdapter(AsyncReadGraph graph, final AdapterDeclaration decl, final Pair, Class> key, final Resource type, final Resource superType, final boolean possible, final AsyncProcedure> procedure) { + + @SuppressWarnings("unchecked") + Adapter adapter = (Adapter)decl.instanceAdapters.get(superType); + if(adapter != null) { + procedure.execute(graph, adapter); + } else { + + graph.forPossibleObject(superType, graph.getService(Layer0.class).Inherits, new AsyncProcedure() { + + @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(decl, key, type, possible), procedure); + + } + + } + + }); + + } + + } + + private Adapter getSingleSuperTypeAdapter(ReadGraph graph, final AdapterDeclaration decl, final Pair, Class> key, final Resource type, final Resource superType, final boolean possible) throws DatabaseException { + + @SuppressWarnings("unchecked") + Adapter adapter = (Adapter)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(decl, key, type, possible)); + } + + } + +// private void adaptSingleSupertype(AsyncReadGraph graph, final AdapterDeclaration decl, final C context, final Resource type, final Resource superType, final boolean possible, final AsyncProcedure procedure) { +// +// @SuppressWarnings("unchecked") +// Adapter adapter = (Adapter)decl.instanceAdapters.get(superType); +// if(adapter != null) { +// +// adapter.adapt(graph, type, context, procedure); +// +// } else { +// +// graph.forPossibleObject(superType, graph.getService(Layer0.class).Inherits, new AsyncProcedure() { +// +// @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() { +// +// @Override +// public T perform(ReadGraph graph) +// throws DatabaseException { +// return decl.adapt(graph, type, context, possible); +// } +// +// }, procedure); +// +// } +// +// } +// +// }); +// +// } +// +// } + + @Override + public void adaptNew(AsyncReadGraph g, final Resource r, final Class clazz, final boolean possible, final AsyncProcedure procedure) { + + g.asyncRequest(new ReadRequest() { + + @Override + public void run(ReadGraph graph) throws DatabaseException { + + final Pair, Class> key = new Pair, Class>(clazz, Resource.class); + + @SuppressWarnings("unchecked") + AdapterDeclaration decl = + (AdapterDeclaration)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 " + clazz + ".")); + } + } else { + try { + procedure.execute(graph, decl.adaptNew(graph, r, possible)); + } catch (AdaptionException e) { + if(possible) { + procedure.execute(graph, null); + } else { + procedure.exception(graph, e); + } + } catch (ValidationException e) { + procedure.exception(graph, e); + } catch (DatabaseException e2) { + procedure.exception(graph, new ServiceException(e2)); + } + } + + } + + }); + + } + + @Override + public void addInstanceAdapter(Resource resource, Class targetClass, Adapter adapter) { + addInstanceAdapter(resource, targetClass, Resource.class, adapter); + } + + @Override + public void addInstanceAdapter(Resource resource, Class targetClass, Class contextClass, Adapter adapter) { + synchronized (this) { + getDeclaration(targetClass, contextClass).instanceAdapters.put(resource, adapter); + } + } + + @Override + public Adapter removeInstanceAdapter(Resource resource, Class targetClass) { + return removeInstanceAdapter(resource, targetClass, Resource.class); + } + + @Override + public Adapter removeInstanceAdapter(Resource resource, Class targetClass, Class contextClass) { + synchronized (this) { + return getDeclaration(targetClass, contextClass).instanceAdapters.remove(resource); + } + } + + @Override + public void removeInstanceAdapter(Resource resource, Class targetClass, Adapter adapter) { + removeInstanceAdapter(resource, targetClass, Resource.class, adapter); + } + + @Override + public void removeInstanceAdapter(Resource resource, Class targetClass, Class contextClass, Adapter adapter) { + synchronized (this) { + AdapterDeclaration decl = getDeclaration(targetClass, contextClass); + Adapter existing = decl.instanceAdapters.get(resource); + if (existing == adapter) { + decl.instanceAdapters.remove(resource); + } + } + } + + @Override + public void addAdapter(Resource type, Class targetClass, Adapter adapter) { + addAdapter(type, targetClass, Resource.class, adapter); + } + + @Override + public void addAdapter(Resource type, Class targetClass, Class contextClass, Adapter adapter) { + getDeclaration(targetClass, contextClass).typeAdapters.put(type, adapter); + } + + @Override + public void declareAdapter(Resource type, Class targetClass) { + declareAdapter(type, targetClass, Resource.class); + } + + @Override + public void declareAdapter(Resource type, Class 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 "