/******************************************************************************* * Copyright (c) 2007, 2018 Association for Decentralized Information Management * in Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ package org.simantics.db.services.adaption; import org.simantics.db.AsyncReadGraph; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; import org.simantics.db.adaption.Adapter; import org.simantics.db.adaption.AdaptionService; import org.simantics.db.common.procedure.adapter.TransientCacheAsyncListener; import org.simantics.db.common.request.BinaryRead; import org.simantics.db.common.request.ReadRequest; import org.simantics.db.common.request.TernaryRead; import org.simantics.db.common.uri.ResourceToURI; import org.simantics.db.common.utils.NameUtils; import org.simantics.db.exception.AdaptionException; import org.simantics.db.exception.DatabaseException; import org.simantics.db.exception.ServiceException; import org.simantics.db.exception.ValidationException; import org.simantics.db.procedure.AsyncProcedure; import org.simantics.db.request.AsyncRead; import org.simantics.db.request.Read; import org.simantics.layer0.Layer0; import org.simantics.utils.datastructures.Pair; import gnu.trove.map.hash.THashMap; import gnu.trove.procedure.TObjectObjectProcedure; import gnu.trove.set.hash.THashSet; public class AdaptionService2 implements AdaptionService { THashMap,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((AsyncRead)(graph, procedure) -> { //System.out.println("adapter=" + adapter); adapter.adapt(graph, resource, context, procedure); }); } @SuppressWarnings("rawtypes") @Override public boolean equals(Object other) { if (this == other) return true; else if (other == null) return false; else if (other.getClass() != Adapt.class) return false; return ((Adapt)other).resource.equals(resource) && ((Adapt)other).context.equals(context) && ((Adapt)other).getDeclaration()==getDeclaration(); } @Override public int hashCode() { return resource.hashCode() + 31*((getClass().hashCode() + 41*(context.hashCode()) + 71*getDeclaration().hashCode())); } } // void adapt2(AsyncReadGraph graph, Resource r, AsyncProcedure 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); if(adapter == null) return null; return g.syncRequest((AsyncRead)(graph, procedure) -> adapter.adapt(graph, r, context, procedure)); } 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(g, null); } else { procedure.exception(g, new AdaptionException("There are no adapters declared or defined for class " + clazz + ".")); } } else { try { procedure.execute(g, decl.adaptNew(graph, r, possible)); } catch (AdaptionException e) { if(possible) { procedure.execute(g, null); } else { procedure.exception(g, e); } } catch (ValidationException e) { procedure.exception(g, e); } catch (DatabaseException e2) { procedure.exception(g, new ServiceException(e2)); } } } }); } @Override public 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 "