X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;ds=sidebyside;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=b7cc76a09c97ffb712ed5a0a99ea2855411e91b5;hb=969bd23cab98a79ca9101af33334000879fb60c5;hp=0000000000000000000000000000000000000000;hpb=866dba5cd5a3929bbeae85991796acb212338a08;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 new file mode 100644 index 000000000..b7cc76a09 --- /dev/null +++ b/bundles/org.simantics.db.services/src/org/simantics/db/services/adaption/AdaptionService2.java @@ -0,0 +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 "