1 /*******************************************************************************
\r
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
\r
3 * in Industry THTH ry.
\r
4 * All rights reserved. This program and the accompanying materials
\r
5 * are made available under the terms of the Eclipse Public License v1.0
\r
6 * which accompanies this distribution, and is available at
\r
7 * http://www.eclipse.org/legal/epl-v10.html
\r
10 * VTT Technical Research Centre of Finland - initial API and implementation
\r
11 *******************************************************************************/
\r
12 package org.simantics.db.services.adaption;
\r
14 import gnu.trove.map.hash.THashMap;
\r
15 import gnu.trove.procedure.TObjectObjectProcedure;
\r
16 import gnu.trove.set.hash.THashSet;
\r
18 import org.simantics.db.AsyncReadGraph;
\r
19 import org.simantics.db.ReadGraph;
\r
20 import org.simantics.db.Resource;
\r
21 import org.simantics.db.adaption.Adapter;
\r
22 import org.simantics.db.adaption.AdaptionService;
\r
23 import org.simantics.db.common.procedure.adapter.TransientCacheAsyncListener;
\r
24 import org.simantics.db.common.procedure.single.SyncReadProcedure;
\r
25 import org.simantics.db.common.request.BinaryRead;
\r
26 import org.simantics.db.common.request.ReadRequest;
\r
27 import org.simantics.db.common.request.TernaryRead;
\r
28 import org.simantics.db.common.uri.ResourceToURI;
\r
29 import org.simantics.db.common.utils.NameUtils;
\r
30 import org.simantics.db.exception.AdaptionException;
\r
31 import org.simantics.db.exception.DatabaseException;
\r
32 import org.simantics.db.exception.ServiceException;
\r
33 import org.simantics.db.exception.ValidationException;
\r
34 import org.simantics.db.procedure.AsyncProcedure;
\r
35 import org.simantics.db.request.AsyncRead;
\r
36 import org.simantics.db.request.Read;
\r
37 import org.simantics.layer0.Layer0;
\r
38 import org.simantics.utils.datastructures.Pair;
\r
40 public class AdaptionService2 implements AdaptionService {
\r
42 THashMap<Pair<Class<?>,Class<?>>, AdapterDeclaration<?>> adapters =
\r
43 new THashMap<Pair<Class<?>,Class<?>>, AdapterDeclaration<?>>();
\r
46 * Contains all adapter declarations and definitions for one class (clazz).
\r
48 static class AdapterDeclaration<T> {
\r
50 THashMap<Resource, Adapter<T,?>> typeAdapters =
\r
51 new THashMap<Resource, Adapter<T,?>>();
\r
52 THashMap<Resource, Adapter<T,?>> instanceAdapters =
\r
53 new THashMap<Resource, Adapter<T,?>>();
\r
54 THashSet<Resource> baseTypes = new THashSet<Resource>();
\r
56 String getDescription(final ReadGraph g) {
\r
57 final StringBuilder b = new StringBuilder();
\r
58 b.append("The following adapters have been defined for ");
\r
59 b.append(clazz.getCanonicalName());
\r
61 typeAdapters.forEachEntry(new TObjectObjectProcedure<Resource, Adapter<T,?>>() {
\r
64 public boolean execute(Resource arg0, Adapter<T,?> arg1) {
\r
67 b.append(g.syncRequest(new ResourceToURI(arg0)));
\r
68 } catch (DatabaseException e) {
\r
69 e.printStackTrace();
\r
79 synchronized (this) {
\r
80 instanceAdapters.forEachEntry(new TObjectObjectProcedure<Resource, Adapter<T,?>>() {
\r
83 public boolean execute(Resource arg0, Adapter<T,?> arg1) {
\r
84 b.append(" resource ");
\r
86 b.append(g.syncRequest(new ResourceToURI(arg0)));
\r
87 } catch (DatabaseException e) {
\r
88 e.printStackTrace();
\r
98 return b.toString();
\r
101 public AdapterDeclaration(Class<T> clazz) {
\r
102 this.clazz = clazz;
\r
105 static class AdapterResult<T,C> {
\r
106 Adapter<T,C> adapter;
\r
109 public AdapterResult(Adapter<T,C> adapter, Resource type) {
\r
110 this.adapter = adapter;
\r
116 * The query returns the adapter inherited by the parameter type.
\r
117 * The query is used only in the case, the type itself does not have
\r
118 * an adapter. The second component of the result contains the type
\r
119 * that originally contributed the adapter.
\r
121 static class GetInheritedAdapter<T,C> extends BinaryRead<Resource, AdapterDeclaration<T>, AdapterResult<T,C>> {
\r
123 public GetInheritedAdapter(Resource type, AdapterDeclaration<T> decl) {
\r
127 AdapterDeclaration<T> getDeclaration() {
\r
132 public String toString() {
\r
133 return "GetInheritedAdapter|" + parameter + "|" + parameter2;
\r
136 @SuppressWarnings("unchecked")
\r
138 public AdapterResult<T,C> perform(ReadGraph g) throws DatabaseException {
\r
139 Layer0 b = Layer0.getInstance(g);
\r
140 AdapterResult<T,C> result = null;
\r
141 for(Resource supertype : g.getObjects(parameter, b.Inherits)) {
\r
142 Adapter<T,C> adapter = (Adapter<T,C>)parameter2.typeAdapters.get(supertype);
\r
143 if(adapter != null) {
\r
145 result = new AdapterResult<T,C>(adapter, supertype);
\r
146 else if(!result.type.equals(supertype) &&
\r
147 !g.isInheritedFrom(result.type, supertype)) {
\r
148 if(g.isInheritedFrom(supertype, result.type))
\r
149 result = new AdapterResult<T,C>(adapter, supertype);
\r
150 else throw new AdaptionException("Type " +
\r
151 safeName(g, parameter) + " inherits conflicting adapters from "
\r
152 + safeName(g, supertype) + " and " + safeName(g, result.type));
\r
156 AdapterResult<T,C> temp =
\r
157 g.syncRequest(new GetInheritedAdapter<T, C>(supertype, parameter2), TransientCacheAsyncListener.<AdapterResult<T,C>>instance());
\r
161 else if(!result.type.equals(temp.type) &&
\r
162 !g.isInheritedFrom(result.type, temp.type)) {
\r
163 if(g.isInheritedFrom(temp.type, result.type))
\r
165 else throw new AdaptionException("Type " +
\r
166 safeName(g, parameter) + " inherits conflicting adapters from "
\r
167 + safeName(g, temp.type) + " and " + safeName(g, result.type));
\r
177 <C> void inheritedAdapter(AsyncReadGraph graph, Resource type, AsyncProcedure<AdapterResult<T,C>> procedure) {
\r
178 graph.asyncRequest(new GetInheritedAdapter<T, C>(type, this), procedure);
\r
181 Adapter<T,?> directAdapter(Resource r) {
\r
183 synchronized (this) {
\r
184 ret = instanceAdapters.get(r);
\r
189 static class FindAdapter<T,C> extends BinaryRead<Resource, AdapterDeclaration<T>, Adapter<T,C>> {
\r
191 public FindAdapter(Resource resource, AdapterDeclaration<T> decl) {
\r
192 super(resource, decl);
\r
195 @SuppressWarnings("unchecked")
\r
196 Adapter<T,C> findAdapter(Resource r, ReadGraph g) throws DatabaseException {
\r
199 Adapter<T,C> adapter;
\r
200 synchronized (this) {
\r
201 adapter = (Adapter<T,C>)parameter2.instanceAdapters.get(r);
\r
203 if(adapter != null)
\r
207 Layer0 b = Layer0.getInstance(g);
\r
210 * Try to find adapter from immediate types
\r
212 AdapterResult<T,C> adapterResult = null;
\r
213 for(Resource t : g.getObjects(r, b.InstanceOf)) {
\r
214 Adapter<T,C> adapter = (Adapter<T,C>)parameter2.typeAdapters.get(t);
\r
215 if(adapter != null) {
\r
216 if(adapterResult == null)
\r
217 adapterResult = new AdapterResult<T,C>(adapter, t);
\r
218 else if(!adapterResult.type.equals(t) &&
\r
219 !g.isInheritedFrom(adapterResult.type, t)) {
\r
220 if(g.isInheritedFrom(t, adapterResult.type))
\r
221 adapterResult = new AdapterResult<T,C>(adapter, t);
\r
222 else throw new AdaptionException("Resource " +
\r
223 safeName(g, r) + " has conflicting " + parameter2.clazz + "-adapters from "
\r
224 + safeName(g, t) + " and " + safeName(g, adapterResult.type)
\r
229 AdapterResult<T,C> temp =
\r
230 g.syncRequest(new GetInheritedAdapter<T, C>(t, parameter2), TransientCacheAsyncListener.<AdapterResult<T,C>>instance());
\r
232 if(adapterResult == null)
\r
233 adapterResult = temp;
\r
234 else if(!adapterResult.type.equals(temp.type) &&
\r
235 !g.isInheritedFrom(adapterResult.type, temp.type)) {
\r
236 if(g.isInheritedFrom(temp.type, adapterResult.type))
\r
237 adapterResult = temp;
\r
238 else throw new AdaptionException("Resource " +
\r
239 safeName(g, r) + " has conflicting " + parameter2.clazz + "-adapters from "
\r
240 + safeName(g, temp.type) + " and " + safeName(g, adapterResult.type)
\r
247 if(adapterResult != null)
\r
248 return adapterResult.adapter;
\r
250 for(Resource t : g.getObjects(r, b.Inherits)) {
\r
251 Adapter<T,C> adapter = findAdapter(t, g);
\r
252 if(adapter != null)
\r
256 for(Resource t : g.getObjects(r, b.SubrelationOf)) {
\r
257 Adapter<T,C> adapter = findAdapter(t, g);
\r
258 if(adapter != null)
\r
268 public Adapter<T,C> perform(ReadGraph g) throws DatabaseException {
\r
269 return (Adapter<T, C>)findAdapter(parameter, g);
\r
275 * The query returns either an adapter or adapted for the given
\r
276 * resource. It is assumed that the resource itself does not
\r
279 class Adapt<C> implements Read<T> {
\r
284 public Adapt(Resource resource, C context) {
\r
285 this.resource = resource;
\r
286 this.context = context;
\r
289 AdapterDeclaration<T> getDeclaration() {
\r
290 return AdapterDeclaration.this;
\r
293 @SuppressWarnings("unchecked")
\r
294 Adapter<T,C> findAdapter(Resource r, ReadGraph g) throws DatabaseException {
\r
297 Adapter<T,C> adapter;
\r
298 synchronized (this) {
\r
299 adapter = (Adapter<T,C>)instanceAdapters.get(r);
\r
301 if(adapter != null)
\r
305 Layer0 b = Layer0.getInstance(g);
\r
308 * Try to find adapter from immediate types
\r
310 AdapterResult<T,C> adapterResult = null;
\r
311 for(Resource t : g.getObjects(r, b.InstanceOf)) {
\r
312 Adapter<T,C> adapter = (Adapter<T,C>)typeAdapters.get(t);
\r
313 if(adapter != null) {
\r
314 if(adapterResult == null)
\r
315 adapterResult = new AdapterResult<T,C>(adapter, t);
\r
316 else if(!adapterResult.type.equals(t) &&
\r
317 !g.isInheritedFrom(adapterResult.type, t)) {
\r
318 if(g.isInheritedFrom(t, adapterResult.type))
\r
319 adapterResult = new AdapterResult<T,C>(adapter, t);
\r
320 else throw new AdaptionException("Resource " +
\r
321 safeName(g, r) + " has conflicting " + clazz + "-adapters from "
\r
322 + safeName(g, t) + " and " + safeName(g, adapterResult.type)
\r
327 AdapterResult<T,C> temp =
\r
328 g.syncRequest(new GetInheritedAdapter<T, C>(t, AdapterDeclaration.this));
\r
330 if(adapterResult == null)
\r
331 adapterResult = temp;
\r
332 else if(!adapterResult.type.equals(temp.type) &&
\r
333 !g.isInheritedFrom(adapterResult.type, temp.type)) {
\r
334 if(g.isInheritedFrom(temp.type, adapterResult.type))
\r
335 adapterResult = temp;
\r
336 else throw new AdaptionException("Resource " +
\r
337 safeName(g, r) + " has conflicting " + clazz + "-adapters from "
\r
338 + safeName(g, temp.type) + " and " + safeName(g, adapterResult.type)
\r
345 if(adapterResult != null)
\r
346 return adapterResult.adapter;
\r
348 for(Resource t : g.getObjects(r, b.Inherits)) {
\r
349 Adapter<T,C> adapter = findAdapter(t, g);
\r
350 if(adapter != null)
\r
354 for(Resource t : g.getObjects(r, b.SubrelationOf)) {
\r
355 Adapter<T,C> adapter = findAdapter(t, g);
\r
356 if(adapter != null)
\r
365 public T perform(ReadGraph g) throws DatabaseException {
\r
367 final Adapter<T,C> adapter = (Adapter<T, C>)findAdapter(resource, g);
\r
368 if(adapter == null) return null;
\r
369 else return g.syncRequest(new AsyncRead<T>() {
\r
372 public void perform(AsyncReadGraph graph, AsyncProcedure<T> procedure) {
\r
373 // System.out.println("adapter=" + adapter);
\r
374 adapter.adapt(graph, resource, context, procedure);
\r
378 public int threadHash() {
\r
383 public int getFlags() {
\r
391 @SuppressWarnings("rawtypes")
\r
393 public boolean equals(Object other) {
\r
397 else if (other == null)
\r
399 else if (other.getClass() != Adapt.class)
\r
402 return ((Adapt)other).resource.equals(resource)
\r
403 && ((Adapt)other).context.equals(context)
\r
404 && ((Adapt)other).getDeclaration()==getDeclaration();
\r
409 public int hashCode() {
\r
410 return resource.hashCode() + 31*((getClass().hashCode() + 41*(context.hashCode()) +
\r
411 71*getDeclaration().hashCode()));
\r
416 // void adapt2(AsyncReadGraph graph, Resource r, AsyncProcedure<T> procedure) {
\r
417 // graph.asyncRequest(new Adapt(r), procedure);
\r
420 <C> Adapter<T,C> findAdapter(ReadGraph g, Resource r, boolean possible) throws DatabaseException {
\r
422 Adapter<T,C> result = g.syncRequest(new FindAdapter<T,C>(r, AdapterDeclaration.this));
\r
423 if(result != null) return result;
\r
429 * We couldn't adapt the resource. We analyze the situation little for
\r
430 * better error message.
\r
432 for(Resource dt : baseTypes) {
\r
433 if(g.isInstanceOf(r, dt)) {
\r
434 throw new AdaptionException("Couldn't find a " + clazz + "-adapter for resource " +
\r
435 safeName(g, r) + " although it is instance of " +
\r
436 safeName(g, dt) + "\n" +
\r
437 getDescription(g));
\r
440 throw new AdaptionException("Couldn't find a " + clazz + "-adapter for resource " +
\r
442 ". This is because the resource is not instance of any type which the adapter is declared to.\n" +
\r
443 getDescription(g));
\r
447 <C> T adapt(ReadGraph g, Resource r, C context, boolean possible) throws DatabaseException {
\r
449 T result = g.syncRequest(new Adapt<C>(r,context));
\r
450 if(result != null) return result;
\r
456 * We couldn't adapt the resource. We analyze the situation little for
\r
457 * better error message.
\r
459 for(Resource dt : baseTypes) {
\r
460 if(g.isInstanceOf(r, dt)) {
\r
461 throw new AdaptionException("Couldn't find a " + clazz + "-adapter for resource " +
\r
462 safeName(g, r) + " although it is instance of " +
\r
463 safeName(g, dt) + "\n" +
\r
464 getDescription(g));
\r
467 throw new AdaptionException("Couldn't find a " + clazz + "-adapter for resource " +
\r
469 ". This is because the resource is not instance of any type which the adapter is declared to.\n" +
\r
470 getDescription(g));
\r
474 T adaptNew(ReadGraph g, final Resource r, boolean possible) throws DatabaseException {
\r
476 T result = new Adapt<Resource>(r,r).perform(g);
\r
477 if (result != null)
\r
483 for(Resource dt : baseTypes) {
\r
484 if(g.isInstanceOf(r, dt)) {
\r
485 throw new AdaptionException("Couldn't find a " + clazz + "-adapter for resource " +
\r
486 safeName(g, r) + " although it is instance of " +
\r
487 safeName(g, dt) + "\n" +
\r
488 getDescription(g));
\r
491 throw new AdaptionException("Couldn't find a " + clazz + "-adapter for resource " +
\r
493 ". This is because the resource is not instance of any type which the adapter is declared to.\n" +
\r
494 getDescription(g));
\r
500 private <T> AdapterDeclaration<T> getDeclaration(Class<T> targetClass, Class<?> contextClass) {
\r
501 Pair<Class<?>,Class<?>> key = new Pair<Class<?>,Class<?>>(targetClass, contextClass);
\r
502 @SuppressWarnings("unchecked")
\r
503 AdapterDeclaration<T> decl =
\r
504 (AdapterDeclaration<T>)adapters.get(key);
\r
506 decl = new AdapterDeclaration<T>(targetClass);
\r
507 adapters.put(key, decl);
\r
512 public <T,C> void getAdapter(AsyncReadGraph graph, final Resource r, final Class<C> contextClass, final Class<T> targetClass, final boolean possible, final AsyncProcedure<Adapter<T,C>> procedure) {
\r
514 final Pair<Class<T>, Class<?>> key = new Pair<Class<T>, Class<?>>(targetClass, contextClass);
\r
515 @SuppressWarnings("unchecked")
\r
516 final AdapterDeclaration<T> decl = (AdapterDeclaration<T>)adapters.get(key);
\r
520 procedure.execute(graph, null);
\r
522 procedure.exception(graph, new AdaptionException("There are no adapters declared or defined for class " + targetClass + "."));
\r
527 @SuppressWarnings("unchecked")
\r
528 final Adapter<T,C> adapter = (Adapter<T,C>)decl.directAdapter(r);
\r
529 if(adapter != null) {
\r
530 procedure.execute(graph, adapter);
\r
532 graph.forPossibleObject(r, graph.getService(Layer0.class).InstanceOf, new AsyncProcedure<Resource>() {
\r
535 public void exception(AsyncReadGraph graph, Throwable throwable) {
\r
536 procedure.exception(graph, new AdaptionException("Problems in reading types for resource. ", throwable));
\r
540 public void execute(AsyncReadGraph graph, final Resource singleType) {
\r
541 if(singleType != null) {
\r
542 getSingleTypeAdapter(graph, decl, key, r, singleType, possible, procedure);
\r
544 getSingleSuperTypeAdapter(graph, decl, key, r, r, possible, procedure);
\r
556 public <T,C> void adapt(AsyncReadGraph graph, final Resource r, final C context, Class<C> contextClass, Class<T> targetClass, final boolean possible, final AsyncProcedure<T> procedure) {
\r
558 getAdapter(graph, r, contextClass, targetClass, possible, new AsyncProcedure<Adapter<T,C>>() {
\r
561 public void execute(AsyncReadGraph graph, Adapter<T, C> result) {
\r
562 if(result == null) {
\r
564 procedure.execute(graph, null);
\r
566 procedure.exception(graph, new AdaptionException("Internal error. getAdapter returned null and possible was false."));
\r
569 result.adapt(graph, r, context, procedure);
\r
574 public void exception(AsyncReadGraph graph, Throwable throwable) {
\r
575 procedure.exception(graph, throwable);
\r
583 public <T, C> T adapt(ReadGraph g, Resource r, C context, Class<C> contextClass, Class<T> targetClass, boolean possible) throws DatabaseException {
\r
585 Adapter<T,C> adapter = getAdapter(g, r, context, contextClass, targetClass, possible);
\r
587 SyncReadProcedure<T> procedure = new SyncReadProcedure<T>();
\r
588 adapter.adapt(g, r, context, procedure);
\r
589 procedure.checkAndThrow();
\r
590 return procedure.result;
\r
594 private <T, C> Adapter<T,C> getAdapter(ReadGraph g, Resource r, C context, Class<C> contextClass, Class<T> targetClass, boolean possible) throws DatabaseException {
\r
596 final Pair<Class<T>, Class<?>> key = new Pair<Class<T>, Class<?>>(targetClass, contextClass);
\r
597 @SuppressWarnings("unchecked")
\r
598 final AdapterDeclaration<T> decl = (AdapterDeclaration<T>)adapters.get(key);
\r
601 if(possible) return null;
\r
602 else throw new AdaptionException("There are no adapters declared or defined for class " + targetClass + ".");
\r
606 @SuppressWarnings("unchecked")
\r
607 final Adapter<T,C> adapter = (Adapter<T,C>)decl.directAdapter(r);
\r
608 if(adapter != null) return adapter;
\r
610 Layer0 L0 = Layer0.getInstance(g);
\r
611 Resource singleType = g.getPossibleObject(r, L0.InstanceOf);
\r
612 if(singleType != null) {
\r
613 return getSingleTypeAdapter(g, decl, key, r, singleType, possible);
\r
615 return getSingleSuperTypeAdapter(g, decl, key, r, r, possible);
\r
622 private static class SingleTypeAdapter<T, C> extends TernaryRead<Pair<Class<T>, Class<?>>, Resource, Boolean, Adapter<T,C>> {
\r
624 final private AdapterDeclaration<T> decl;
\r
626 SingleTypeAdapter(AdapterDeclaration<T> decl, Pair<Class<T>, Class<?>> key, Resource instance, Boolean possible) {
\r
627 super(key, instance, possible);
\r
632 public Adapter<T,C> perform(ReadGraph graph) throws DatabaseException {
\r
633 return decl.findAdapter(graph, parameter2, parameter3);
\r
638 private <T,C> void getSingleTypeAdapter(AsyncReadGraph graph, final AdapterDeclaration<T> decl, final Pair<Class<T>, Class<?>> key, final Resource instance, final Resource type, final boolean possible, final AsyncProcedure<Adapter<T,C>> procedure) {
\r
640 @SuppressWarnings("unchecked")
\r
641 Adapter<T,C> adapter = (Adapter<T,C>)decl.typeAdapters.get(type);
\r
642 if(adapter != null) {
\r
643 procedure.execute(graph, adapter);
\r
645 graph.forPossibleObject(type, graph.getService(Layer0.class).Inherits, new AsyncProcedure<Resource>() {
\r
648 public void exception(AsyncReadGraph graph, Throwable throwable) {
\r
649 procedure.exception(graph, new AdaptionException("Problems in reading super types for resource. ", throwable));
\r
653 public void execute(AsyncReadGraph graph, Resource singleSuperType) {
\r
655 if(singleSuperType != null) {
\r
656 getSingleTypeAdapter(graph, decl, key, instance, singleSuperType, possible, procedure);
\r
658 graph.asyncRequest(new SingleTypeAdapter<T,C>(decl, key, instance, possible), procedure);
\r
670 private <T,C> Adapter<T,C> getSingleTypeAdapter(ReadGraph graph, final AdapterDeclaration<T> decl, final Pair<Class<T>, Class<?>> key, final Resource instance, final Resource type, final boolean possible) throws DatabaseException {
\r
672 @SuppressWarnings("unchecked")
\r
673 Adapter<T,C> adapter = (Adapter<T,C>)decl.typeAdapters.get(type);
\r
674 if(adapter != null) return adapter;
\r
676 Layer0 L0 = Layer0.getInstance(graph);
\r
677 Resource singleSuperType = graph.getPossibleObject(type, L0.Inherits);
\r
678 if(singleSuperType != null) {
\r
679 return getSingleTypeAdapter(graph, decl, key, instance, singleSuperType, possible);
\r
681 return graph.syncRequest(new SingleTypeAdapter<T,C>(decl, key, instance, possible), TransientCacheAsyncListener.<Adapter<T,C>>instance());
\r
686 // private <T,C> void adaptSingleType(AsyncReadGraph graph, final AdapterDeclaration<T> decl, final C context, final Resource instance, final Resource type, final boolean possible, final AsyncProcedure<T> procedure) {
\r
688 // @SuppressWarnings("unchecked")
\r
689 // Adapter<T,C> adapter = (Adapter<T,C>)decl.typeAdapters.get(type);
\r
690 // if(adapter != null) {
\r
692 // adapter.adapt(graph, instance, context, procedure);
\r
696 // graph.forPossibleObject(type, graph.getService(Layer0.class).Inherits, new AsyncProcedure<Resource>() {
\r
699 // public void exception(AsyncReadGraph graph, Throwable throwable) {
\r
701 // procedure.exception(graph, new AdaptionException("Problems in reading super types for resource. ", throwable));
\r
706 // public void execute(AsyncReadGraph graph, Resource singleSuperType) {
\r
708 // if(singleSuperType != null) {
\r
710 // adaptSingleType(graph, decl, context, instance, singleSuperType, possible, procedure);
\r
714 // graph.asyncRequest(new Read<T>() {
\r
717 // public T perform(ReadGraph graph)
\r
718 // throws DatabaseException {
\r
719 // return decl.adapt(graph, instance, context, possible);
\r
736 private static class SingleSuperTypeAdapter<T, C> extends TernaryRead<Pair<Class<T>, Class<?>>, Resource, Boolean, Adapter<T,C>> {
\r
738 final private AdapterDeclaration<T> decl;
\r
740 SingleSuperTypeAdapter(AdapterDeclaration<T> decl, Pair<Class<T>, Class<?>> key, Resource type, Boolean possible) {
\r
741 super(key, type, possible);
\r
746 public Adapter<T,C> perform(ReadGraph graph) throws DatabaseException {
\r
747 return decl.findAdapter(graph, parameter2, parameter3);
\r
752 private <T,C> void getSingleSuperTypeAdapter(AsyncReadGraph graph, final AdapterDeclaration<T> decl, final Pair<Class<T>, Class<?>> key, final Resource type, final Resource superType, final boolean possible, final AsyncProcedure<Adapter<T,C>> procedure) {
\r
754 @SuppressWarnings("unchecked")
\r
755 Adapter<T, C> adapter = (Adapter<T, C>)decl.instanceAdapters.get(superType);
\r
756 if(adapter != null) {
\r
757 procedure.execute(graph, adapter);
\r
760 graph.forPossibleObject(superType, graph.getService(Layer0.class).Inherits, new AsyncProcedure<Resource>() {
\r
763 public void exception(AsyncReadGraph graph, Throwable throwable) {
\r
764 procedure.exception(graph, new AdaptionException("Problems in reading super types for resource. ", throwable));
\r
768 public void execute(AsyncReadGraph graph, Resource singleSuperType) {
\r
770 if(singleSuperType != null) {
\r
772 getSingleSuperTypeAdapter(graph, decl, key, type, singleSuperType, possible, procedure);
\r
776 graph.asyncRequest(new SingleSuperTypeAdapter<T,C>(decl, key, type, possible), procedure);
\r
788 private <T,C> Adapter<T,C> getSingleSuperTypeAdapter(ReadGraph graph, final AdapterDeclaration<T> decl, final Pair<Class<T>, Class<?>> key, final Resource type, final Resource superType, final boolean possible) throws DatabaseException {
\r
790 @SuppressWarnings("unchecked")
\r
791 Adapter<T, C> adapter = (Adapter<T, C>)decl.instanceAdapters.get(superType);
\r
792 if(adapter != null) return adapter;
\r
794 Layer0 L0 = Layer0.getInstance(graph);
\r
795 Resource singleSuperType = graph.getPossibleObject(superType, L0.Inherits);
\r
796 if(singleSuperType != null) {
\r
797 return getSingleSuperTypeAdapter(graph, decl, key, type, singleSuperType, possible);
\r
799 return graph.syncRequest(new SingleSuperTypeAdapter<T,C>(decl, key, type, possible));
\r
804 // private <T,C> void adaptSingleSupertype(AsyncReadGraph graph, final AdapterDeclaration<T> decl, final C context, final Resource type, final Resource superType, final boolean possible, final AsyncProcedure<T> procedure) {
\r
806 // @SuppressWarnings("unchecked")
\r
807 // Adapter<T, C> adapter = (Adapter<T, C>)decl.instanceAdapters.get(superType);
\r
808 // if(adapter != null) {
\r
810 // adapter.adapt(graph, type, context, procedure);
\r
814 // graph.forPossibleObject(superType, graph.getService(Layer0.class).Inherits, new AsyncProcedure<Resource>() {
\r
817 // public void exception(AsyncReadGraph graph, Throwable throwable) {
\r
819 // procedure.exception(graph, new AdaptionException("Problems in reading super types for resource. ", throwable));
\r
824 // public void execute(AsyncReadGraph graph, Resource singleSuperType) {
\r
826 // if(singleSuperType != null) {
\r
828 // adaptSingleSupertype(graph, decl, context, type, singleSuperType, possible, procedure);
\r
832 // graph.asyncRequest(new Read<T>() {
\r
835 // public T perform(ReadGraph graph)
\r
836 // throws DatabaseException {
\r
837 // return decl.adapt(graph, type, context, possible);
\r
853 public <T> void adaptNew(AsyncReadGraph g, final Resource r, final Class<T> clazz, final boolean possible, final AsyncProcedure<T> procedure) {
\r
855 g.asyncRequest(new ReadRequest() {
\r
858 public void run(ReadGraph graph) throws DatabaseException {
\r
860 final Pair<Class<T>, Class<?>> key = new Pair<Class<T>, Class<?>>(clazz, Resource.class);
\r
862 @SuppressWarnings("unchecked")
\r
863 AdapterDeclaration<T> decl =
\r
864 (AdapterDeclaration<T>)adapters.get(key);
\r
868 procedure.execute(graph, null);
\r
870 procedure.exception(graph, new AdaptionException("There are no adapters declared or defined for class " + clazz + "."));
\r
874 procedure.execute(graph, decl.adaptNew(graph, r, possible));
\r
875 } catch (AdaptionException e) {
\r
877 procedure.execute(graph, null);
\r
879 procedure.exception(graph, e);
\r
881 } catch (ValidationException e) {
\r
882 procedure.exception(graph, e);
\r
883 } catch (DatabaseException e2) {
\r
884 procedure.exception(graph, new ServiceException(e2));
\r
895 public <T> void addInstanceAdapter(Resource resource, Class<T> targetClass, Adapter<T,?> adapter) {
\r
896 addInstanceAdapter(resource, targetClass, Resource.class, adapter);
\r
900 public <T> void addInstanceAdapter(Resource resource, Class<T> targetClass, Class<?> contextClass, Adapter<T,?> adapter) {
\r
901 synchronized (this) {
\r
902 getDeclaration(targetClass, contextClass).instanceAdapters.put(resource, adapter);
\r
907 public <T> Adapter<T,?> removeInstanceAdapter(Resource resource, Class<T> targetClass) {
\r
908 return removeInstanceAdapter(resource, targetClass, Resource.class);
\r
912 public <T> Adapter<T,?> removeInstanceAdapter(Resource resource, Class<T> targetClass, Class<?> contextClass) {
\r
913 synchronized (this) {
\r
914 return getDeclaration(targetClass, contextClass).instanceAdapters.remove(resource);
\r
919 public <T> void removeInstanceAdapter(Resource resource, Class<T> targetClass, Adapter<T,?> adapter) {
\r
920 removeInstanceAdapter(resource, targetClass, Resource.class, adapter);
\r
924 public <T> void removeInstanceAdapter(Resource resource, Class<T> targetClass, Class<?> contextClass, Adapter<T,?> adapter) {
\r
925 synchronized (this) {
\r
926 AdapterDeclaration<T> decl = getDeclaration(targetClass, contextClass);
\r
927 Adapter<T,?> existing = decl.instanceAdapters.get(resource);
\r
928 if (existing == adapter) {
\r
929 decl.instanceAdapters.remove(resource);
\r
935 public <T> void addAdapter(Resource type, Class<T> targetClass, Adapter<T,?> adapter) {
\r
936 addAdapter(type, targetClass, Resource.class, adapter);
\r
940 public <T> void addAdapter(Resource type, Class<T> targetClass, Class<?> contextClass, Adapter<T,?> adapter) {
\r
941 getDeclaration(targetClass, contextClass).typeAdapters.put(type, adapter);
\r
945 public <T> void declareAdapter(Resource type, Class<T> targetClass) {
\r
946 declareAdapter(type, targetClass, Resource.class);
\r
950 public <T> void declareAdapter(Resource type, Class<T> targetClass, Class<?> contextClass) {
\r
951 getDeclaration(targetClass, contextClass).baseTypes.add(type);
\r
954 public static String safeName(ReadGraph g, Resource r) throws DatabaseException {
\r
955 // Builtins b = g.getBuiltins();
\r
956 // for(Resource name : g.getObjects(r, b.HasName))
\r
957 // return g.getValue(name);
\r
958 // for(Resource t : g.getObjects(r, b.InstanceOf))
\r
959 // for(Resource name : g.getObjects(t, b.HasName))
\r
960 // return ": "+ g.getValue(name);
\r
961 // for(Resource t : g.getObjects(r, b.Inherits))
\r
962 // for(Resource name : g.getObjects(t, b.HasName))
\r
963 // return "<T "+ g.getValue(name);
\r
964 // for(Resource t : g.getObjects(r, b.SubrelationOf))
\r
965 // for(Resource name : g.getObjects(t, b.HasName))
\r
966 // return "<R "+ g.getValue(name);
\r
967 // if(g.hasValue(r))
\r
968 // return "\"" + g.getValue(r) + "\"";
\r
969 // return "" + r.getResourceId();
\r
970 return NameUtils.getSafeName(g, r, true);
\r