]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/request/combinations/Combinators.java
bd2409f5d9b2eecde6a5f369562a141365938adb
[simantics/platform.git] / bundles / org.simantics.db.layer0 / src / org / simantics / db / layer0 / request / combinations / Combinators.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management
3  * in Industry THTH ry.
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * which accompanies this distribution, and is available at
7  * http://www.eclipse.org/legal/epl-v10.html
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.db.layer0.request.combinations;
13
14 import java.util.HashMap;
15 import java.util.Map;
16
17 import org.simantics.db.ReadGraph;
18 import org.simantics.db.Resource;
19 import org.simantics.db.common.request.ParametrizedRead;
20 import org.simantics.db.exception.DatabaseException;
21 import org.simantics.db.procedure.AsyncMultiProcedure;
22 import org.simantics.db.procedure.Procedure;
23 import org.simantics.db.request.MultiRead;
24 import org.simantics.db.request.Read;
25 import org.simantics.layer0.Layer0;
26
27 /**
28  * Functions that create new read requests by combining simpler ones.
29  * @author Hannu Niemist�
30  */
31 public class Combinators {      
32                 
33         // ------------------------------------------------------------------------
34         
35         private static class Objects implements MultiRead<Resource> {
36                 Resource subject;               
37                 Resource relation;
38                 public Objects(Resource subject, Resource relation) {
39                         this.subject = subject;
40                         this.relation = relation;
41                 }
42                 @Override
43                 public void perform(ReadGraph graph,
44                                 AsyncMultiProcedure<Resource> callback)
45                                 throws DatabaseException {
46                         graph.forEachObject(subject, relation, callback);
47                 }               
48             @Override
49             public int hashCode() {
50                 return subject.hashCode() + 31 * relation.hashCode();
51             }
52             @Override
53             public boolean equals(Object object) {
54                 if (this == object) return true;
55                 else if (object == null || getClass() != object.getClass()) return false;
56                 Objects other = (Objects)object;
57                 return subject.equals(other.subject) && relation.equals(other.relation);
58             }
59         }
60         
61         /**
62          * Returns a multi read request that reads the objects of given subject and relation. 
63          */
64         public static MultiRead<Resource> objects(Resource subject, Resource relation) {
65                 return new Objects(subject, relation);
66         }
67         
68         // ------------------------------------------------------------------------
69         
70         private static class Relation implements ParametrizedMultiRead<Resource, Resource> {
71                 Resource relation;
72                 public Relation(Resource relation) {
73                         this.relation = relation;
74                 }
75                 @Override
76                 public MultiRead<Resource> get(Resource subject) {
77                         return objects(subject, relation);
78                 }
79             @Override
80             public int hashCode() {
81                 return getClass().hashCode() + 31 * relation.hashCode();
82             }
83                 @Override
84                 public boolean equals(Object obj) {
85                         if(obj == this) return true;
86                         if(obj == null || obj.getClass() != getClass()) return false;
87                         Relation other = (Relation)obj;
88                         return relation.equals(other.relation);
89                 }
90         }
91         
92         /**
93          * Returns a function <code>subject -> objects(subject, relation)</code>. 
94          */
95         public static ParametrizedMultiRead<Resource,Resource> relation(Resource relation) {
96                 return new Relation(relation);
97         }
98         
99         // ------------------------------------------------------------------------
100         
101         public static class SynchronizationProcedure<T> implements Procedure<T> {
102                 T result;
103                 DatabaseException exception;
104                 boolean ready = false;
105                 @Override
106                 public synchronized void exception(Throwable t) {
107                         this.exception = 
108                                 t instanceof DatabaseException ? (DatabaseException)t : new DatabaseException(t);
109                         ready = true;
110                         notify();
111                 }
112                 @Override
113                 public synchronized void execute(T result) {
114                         this.result = result;
115                         ready = true;           
116                         notify();
117                 }               
118                 public synchronized T getResult() throws DatabaseException {
119                         if(!ready) {
120                                 try {
121                                         wait();
122                                 } catch (InterruptedException e) {
123                                         throw new DatabaseException(e);
124                                 }       
125                         }
126                         if(exception != null)
127                                 throw exception;
128                         return result;
129                 }
130         }
131         
132         private static class PossibleObject implements Read<Resource> {
133                 Resource subject;               
134                 Resource relation;
135                 public PossibleObject(Resource subject, Resource relation) {
136                         this.subject = subject;
137                         this.relation = relation;
138                 }
139                 @Override
140                 public Resource perform(ReadGraph graph) throws DatabaseException {
141                         SynchronizationProcedure<Resource> procedure = new SynchronizationProcedure<Resource>();
142                         graph.forPossibleObject(subject, relation, procedure);
143                         return procedure.getResult();
144                 }       
145             @Override
146             public int hashCode() {
147                 return subject.hashCode() + 31 * relation.hashCode();
148             }
149             @Override
150             public boolean equals(Object object) {
151                 if (this == object) return true;
152                 else if (object == null || getClass() != object.getClass()) return false;
153                 PossibleObject other = (PossibleObject)object;
154                 return subject.equals(other.subject) && relation.equals(other.relation);
155             }
156         }
157         
158         /**
159          * Returns a read request that reads an object possibly connected to the subject by the relation.
160          */
161         public static Read<Resource> possibleObject(Resource subject, Resource relation) {
162                 return new PossibleObject(subject, relation);
163         }
164         
165         // ------------------------------------------------------------------------
166         
167         private static class PartialFunction implements ParametrizedRead<Resource, Resource> {
168                 Resource relation;
169                 public PartialFunction(Resource relation) {
170                         this.relation = relation;
171                 }
172                 @Override
173                 public Read<Resource> get(Resource subject) {
174                         return possibleObject(subject, relation);
175                 }
176             @Override
177             public int hashCode() {
178                 return getClass().hashCode() + 31 * relation.hashCode();
179             }
180                 @Override
181                 public boolean equals(Object obj) {
182                         if(obj == this) return true;
183                         if(obj == null || obj.getClass() != getClass()) return false;
184                         PartialFunction other = (PartialFunction)obj;
185                         return relation.equals(other.relation);
186                 }
187         }
188         
189         /**
190          * Returns a function <code>subject -> possibleObject(subject, relation)</code>. 
191          */
192         public static ParametrizedRead<Resource,Resource> partialFunction(Resource relation) {
193                 return new PartialFunction(relation);
194         }
195         
196         // ------------------------------------------------------------------------
197         
198         private static class SingleObject implements Read<Resource> {
199                 Resource subject;               
200                 Resource relation;
201                 public SingleObject(Resource subject, Resource relation) {
202                         this.subject = subject;
203                         this.relation = relation;
204                 }
205                 @Override
206                 public Resource perform(ReadGraph graph) throws DatabaseException {
207                         SynchronizationProcedure<Resource> procedure = new SynchronizationProcedure<Resource>();
208                         graph.forSingleObject(subject, relation, procedure);
209                         return procedure.getResult();
210                 }       
211             @Override
212             public int hashCode() {
213                 return subject.hashCode() + 31 * relation.hashCode();
214             }
215             @Override
216             public boolean equals(Object object) {
217                 if (this == object) return true;
218                 else if (object == null || getClass() != object.getClass()) return false;
219                 SingleObject other = (SingleObject)object;
220                 return subject.equals(other.subject) && relation.equals(other.relation);
221             }
222         }
223         
224         /**
225          * Returns a read request that reads an object connected to the subject by the relation.
226          */
227         public static Read<Resource> singleObject(Resource subject, Resource relation) {
228                 return new SingleObject(subject, relation);
229         }
230         
231         // ------------------------------------------------------------------------
232         
233         private static class CompleteFunction implements ParametrizedRead<Resource, Resource> {
234                 Resource relation;
235                 public CompleteFunction(Resource relation) {
236                         this.relation = relation;
237                 }
238                 @Override
239                 public Read<Resource> get(Resource subject) {
240                         return singleObject(subject, relation);
241                 }
242             @Override
243             public int hashCode() {
244                 return getClass().hashCode() + 31 * relation.hashCode();
245             }
246                 @Override
247                 public boolean equals(Object obj) {
248                         if(obj == this) return true;
249                         if(obj == null || obj.getClass() != getClass()) return false;
250                         CompleteFunction other = (CompleteFunction)obj;
251                         return relation.equals(other.relation);
252                 }
253         }
254         
255         /**
256          * Returns a function <code>subject -> singleObject(subject, relation)</code>. 
257          */
258         public static ParametrizedRead<Resource,Resource> completeFunction(Resource relation) {
259                 return new CompleteFunction(relation);
260         }
261         
262         // ------------------------------------------------------------------------
263         
264         private static class Compose1<X, Y> implements Read<Y> {
265                 final ParametrizedRead<X, Y> f;
266                 final Read<X> g;                
267                 public Compose1(ParametrizedRead<X, Y> f, Read<X> g) {
268                         this.f = f;
269                         this.g = g;
270                 }
271                 @Override
272                 public Y perform(ReadGraph graph) throws DatabaseException {
273                         return graph.syncRequest(f.get(graph.syncRequest(g)));
274                 }               
275                 @Override
276                 public int hashCode() {
277                         return getClass().hashCode() + 31 * (f.hashCode() + 31 * g.hashCode());
278                 }
279                 @Override
280                 public boolean equals(Object obj) {
281                         if(obj == this) return true;
282                         if(obj == null || obj.getClass() != getClass()) return false;
283                         Compose1<?, ?> other = (Compose1<?, ?>)obj;
284                         return f.equals(other.f) && g.equals(other.g);
285                 }
286         }
287         
288         public static <X, Y> Read<Y> compose(ParametrizedRead<X, Y> f, Read<X> g) {
289                 return new Compose1<X, Y>(f, g);
290         }
291
292         // ------------------------------------------------------------------------
293         
294         private static class Compose2<X, Y, Z> implements ParametrizedRead<X, Z> {
295                 final ParametrizedRead<Y, Z> f;
296                 final ParametrizedRead<X, Y> g;         
297                 public Compose2(ParametrizedRead<Y, Z> f, ParametrizedRead<X, Y> g) {
298                         this.f = f;
299                         this.g = g;
300                 }
301                 public Read<Z> get(X x) {
302                         return compose(f, g.get(x));
303                 }
304                 @Override
305                 public int hashCode() {
306                         return getClass().hashCode() + 31 * (f.hashCode() + 31 * g.hashCode());
307                 }
308                 @Override
309                 public boolean equals(Object obj) {
310                         if(obj == this) return true;
311                         if(obj == null || obj.getClass() != getClass()) return false;
312                         Compose2<?, ?, ?> other = (Compose2<?, ?, ?>)obj;
313                         return f.equals(other.f) && g.equals(other.g);
314                 }
315         }
316         
317         public static <X, Y, Z> ParametrizedRead<X, Z> compose(ParametrizedRead<Y, Z> f, ParametrizedRead<X, Y> g) {
318                 return new Compose2<X, Y, Z>(f, g);
319         }
320         
321         // ------------------------------------------------------------------------
322         
323         private static class Compose3<X, Y> implements MultiRead<Y> {
324                 final ParametrizedRead<X, Y> f;
325                 final MultiRead<X> g;           
326                 public Compose3(ParametrizedRead<X, Y> f, MultiRead<X> g) {
327                         this.f = f;
328                         this.g = g;
329                 }
330                 public void perform(ReadGraph graph, final AsyncMultiProcedure<Y> callback)     throws DatabaseException {
331                     try {
332                                 for(X x : graph.syncRequest(g))
333                                         callback.execute(graph, graph.syncRequest(f.get(x)));
334                                 callback.finished(graph);
335                         } catch(DatabaseException e) {
336                                 callback.exception(graph, e);
337                         }
338                         /*// Not sure if this is correct
339                    graph.syncRequest(g, new SyncMultiProcedure<X>() {
340                                 @Override
341                                 public void exception(ReadGraph graph, Throwable throwable)
342                                 throws DatabaseException {
343                                         callback.exception(graph, throwable);                                   
344                                 }
345                                 @Override
346                                 public void execute(ReadGraph graph, X x)
347                                 throws DatabaseException {
348                                         callback.execute(graph, graph.syncRequest(f.get(x)));
349                                 }
350                                 @Override
351                                 public void finished(ReadGraph graph)
352                                 throws DatabaseException {
353                                 }
354                         });
355                         callback.finished(graph);*/
356                 }                                       
357                 @Override
358                 public int hashCode() {
359                         return getClass().hashCode() + 31 * (f.hashCode() + 31 * g.hashCode());
360                 }
361                 @Override
362                 public boolean equals(Object obj) {
363                         if(obj == this) return true;
364                         if(obj == null || obj.getClass() != getClass()) return false;
365                         Compose3<?, ?> other = (Compose3<?, ?>)obj;
366                         return f.equals(other.f) && g.equals(other.g);
367                 }
368         }
369         
370         public static <X, Y> MultiRead<Y> compose(ParametrizedRead<X, Y> f, MultiRead<X> g) {
371                 return new Compose3<X, Y>(f, g);
372         }
373         
374         // ------------------------------------------------------------------------
375         
376         private static class Compose4<X, Y, Z> implements ParametrizedMultiRead<X, Z> {
377                 final ParametrizedRead<Y, Z> f;
378                 final ParametrizedMultiRead<X, Y> g;            
379                 public Compose4(ParametrizedRead<Y, Z> f, ParametrizedMultiRead<X, Y> g) {
380                         this.f = f;
381                         this.g = g;
382                 }
383                 public MultiRead<Z> get(X x) {
384                         return compose(f, g.get(x));
385                 }
386                 @Override
387                 public int hashCode() {
388                         return getClass().hashCode() + 31 * (f.hashCode() + 31 * g.hashCode());
389                 }
390                 @Override
391                 public boolean equals(Object obj) {
392                         if(obj == this) return true;
393                         if(obj == null || obj.getClass() != getClass()) return false;
394                         Compose4<?, ?, ?> other = (Compose4<?, ?, ?>)obj;
395                         return f.equals(other.f) && g.equals(other.g);
396                 }
397         }
398         
399         public static <X, Y, Z> ParametrizedMultiRead<X, Z> compose(ParametrizedRead<Y, Z> f, ParametrizedMultiRead<X, Y> g) {
400                 return new Compose4<X, Y, Z>(f, g);
401         }
402
403         // ------------------------------------------------------------------------
404         
405         private static class Compose5<X, Y> implements MultiRead<Y> {
406                 final ParametrizedMultiRead<X, Y> f;
407                 final Read<X> g;                
408                 public Compose5(ParametrizedMultiRead<X, Y> f, Read<X> g) {
409                         this.f = f;
410                         this.g = g;
411                 }
412                 @Override
413                 public void perform(ReadGraph graph, AsyncMultiProcedure<Y> callback)
414                                 throws DatabaseException {
415                         graph.syncRequest(f.get(graph.syncRequest(g)), callback);
416                 }
417                 @Override
418                 public int hashCode() {
419                         return getClass().hashCode() + 31 * (f.hashCode() + 31 * g.hashCode());
420                 }
421                 @Override
422                 public boolean equals(Object obj) {
423                         if(obj == this) return true;
424                         if(obj == null || obj.getClass() != getClass()) return false;
425                         Compose5<?, ?> other = (Compose5<?, ?>)obj;
426                         return f.equals(other.f) && g.equals(other.g);
427                 }
428         }
429         
430         public static <X, Y> MultiRead<Y> compose(ParametrizedMultiRead<X, Y> f, Read<X> g) {
431                 return new Compose5<X, Y>(f, g);
432         }
433
434         // ------------------------------------------------------------------------
435         
436         private static class Compose6<X, Y, Z> implements ParametrizedMultiRead<X, Z> {
437                 final ParametrizedMultiRead<Y, Z> f;
438                 final ParametrizedRead<X, Y> g;         
439                 public Compose6(ParametrizedMultiRead<Y, Z> f, ParametrizedRead<X, Y> g) {
440                         this.f = f;
441                         this.g = g;
442                 }
443                 public MultiRead<Z> get(X x) {
444                         return compose(f, g.get(x));
445                 }
446                 @Override
447                 public int hashCode() {
448                         return getClass().hashCode() + 31 * (f.hashCode() + 31 * g.hashCode());
449                 }
450                 @Override
451                 public boolean equals(Object obj) {
452                         if(obj == this) return true;
453                         if(obj == null || obj.getClass() != getClass()) return false;
454                         Compose6<?, ?, ?> other = (Compose6<?, ?, ?>)obj;
455                         return f.equals(other.f) && g.equals(other.g);
456                 }
457         }
458         
459         public static <X, Y, Z> ParametrizedMultiRead<X, Z> compose(ParametrizedMultiRead<Y, Z> f, ParametrizedRead<X, Y> g) {
460                 return new Compose6<X, Y, Z>(f, g);
461         }
462         
463         // ------------------------------------------------------------------------
464         
465         private static class Compose7<X, Y> implements MultiRead<Y> {
466                 final ParametrizedMultiRead<X, Y> f;
467                 final MultiRead<X> g;           
468                 public Compose7(ParametrizedMultiRead<X, Y> f, MultiRead<X> g) {
469                         this.f = f;
470                         this.g = g;
471                 }
472                 public void perform(ReadGraph graph, final AsyncMultiProcedure<Y> callback)     throws DatabaseException {
473                     try {
474                                 for(X x : graph.syncRequest(g))
475                                         for(Y y : graph.syncRequest(f.get(x)))
476                                                 callback.execute(graph, y);
477                                 callback.finished(graph);
478                         } catch(DatabaseException e) {
479                                 callback.exception(graph, e);
480                         }
481                         /*// Not correct because inner syncRequest calls callback.finished 
482                     graph.syncRequest(g, new SyncMultiProcedure<X>() {
483                                 @Override
484                                 public void exception(ReadGraph graph, Throwable throwable)
485                                 throws DatabaseException {
486                                         callback.exception(graph, throwable);                                   
487                                 }
488                                 @Override
489                                 public void execute(ReadGraph graph, X x) throws DatabaseException {
490                                         graph.syncRequest(f.get(x), callback);
491                                 }
492                                 @Override
493                                 public void finished(ReadGraph graph)
494                                 throws DatabaseException {
495                                 }
496                         });
497                         callback.finished(graph);
498                         */
499                 }                                       
500                 @Override
501                 public int hashCode() {
502                         return getClass().hashCode() + 31 * (f.hashCode() + 31 * g.hashCode());
503                 }
504                 @Override
505                 public boolean equals(Object obj) {
506                         if(obj == this) return true;
507                         if(obj == null || obj.getClass() != getClass()) return false;
508                         Compose7<?, ?> other = (Compose7<?, ?>)obj;
509                         return f.equals(other.f) && g.equals(other.g);
510                 }
511         }
512         
513         public static <X, Y> MultiRead<Y> compose(ParametrizedMultiRead<X, Y> f, MultiRead<X> g) {
514                 return new Compose7<X, Y>(f, g);
515         }
516         
517         // ------------------------------------------------------------------------
518         
519         private static class Compose8<X, Y, Z> implements ParametrizedMultiRead<X, Z> {
520                 final ParametrizedMultiRead<Y, Z> f;
521                 final ParametrizedMultiRead<X, Y> g;            
522                 public Compose8(ParametrizedMultiRead<Y, Z> f, ParametrizedMultiRead<X, Y> g) {
523                         this.f = f;
524                         this.g = g;
525                 }
526                 public MultiRead<Z> get(X x) {
527                         return compose(f, g.get(x));
528                 }
529                 @Override
530                 public int hashCode() {
531                         return getClass().hashCode() + 31 * (f.hashCode() + 31 * g.hashCode());
532                 }
533                 @Override
534                 public boolean equals(Object obj) {
535                         if(obj == this) return true;
536                         if(obj == null || obj.getClass() != getClass()) return false;
537                         Compose8<?, ?, ?> other = (Compose8<?, ?, ?>)obj;
538                         return f.equals(other.f) && g.equals(other.g);
539                 }
540         }
541         
542         public static <X, Y, Z> ParametrizedMultiRead<X, Z> compose(ParametrizedMultiRead<Y, Z> f, ParametrizedMultiRead<X, Y> g) {
543                 return new Compose8<X, Y, Z>(f, g);
544         }       
545         
546         // ------------------------------------------------------------------------
547
548         private static class Index<K, V> implements Read<Map<K, V>> {
549                 final MultiRead<V> values;
550                 final ParametrizedRead<V, K> keyOfValue;
551                 public Index(MultiRead<V> values, ParametrizedRead<V, K> keyOfValue) {
552                         this.values = values;
553                         this.keyOfValue = keyOfValue;
554                 }
555                 @Override
556                 public Map<K, V> perform(ReadGraph graph) throws DatabaseException {
557                         HashMap<K, V> result = new HashMap<K, V>();
558                         for(V value : graph.syncRequest(values))
559                                 result.put(graph.syncRequest(keyOfValue.get(value)), value);
560                         return result;
561                 }
562                 @Override
563                 public int hashCode() {
564                         return getClass().hashCode() + 31 * (values.hashCode() + 31 * keyOfValue.hashCode());
565                 }
566                 @Override
567                 public boolean equals(Object obj) {
568                         if(obj == this) return true;
569                         if(obj == null || obj.getClass() != getClass()) return false;
570                         Index<?, ?> other = (Index<?, ?>)obj;
571                         return values.equals(other.values) && keyOfValue.equals(other.keyOfValue);
572                 }       
573         }
574         
575         public static <K, V> Read<Map<K, V>> index(MultiRead<V> values, ParametrizedRead<V, K> keyOfValue) {
576                 return new Index<K, V>(values, keyOfValue);
577         }
578         
579         // ------------------------------------------------------------------------
580
581         private static class Constant<T> implements Read<T> {
582                 T value;
583                 public Constant(T value) {
584                         this.value = value;
585                 }
586                 @Override
587                 public T perform(ReadGraph graph) throws DatabaseException {
588                         return value;
589                 }
590                 @Override
591                 public int hashCode() {
592                         return value == null ? 0 : value.hashCode();
593                 }
594                 @Override
595                 public boolean equals(Object obj) {
596                         if (this == obj)
597                                 return true;
598                         if (obj == null || getClass() != obj.getClass())
599                                 return false;
600                         Constant<?> other = (Constant<?>) obj;
601                         return value == null ? other.value == null : value.equals(other.value);
602                 }               
603         }
604         
605         public static <T> Read<T> constant(T value) {
606                 return new Constant<T>(value);
607         }
608         
609         // ------------------------------------------------------------------------
610
611         private static class Singleton<T> implements MultiRead<T> {
612                 T value;
613                 public Singleton(T value) {
614                         this.value = value;
615                 }
616                 @Override
617                 public void perform(ReadGraph graph, AsyncMultiProcedure<T> callback)
618                                 throws DatabaseException {
619                         callback.execute(graph, value);
620                         callback.finished(graph);
621                 }
622                 @Override
623                 public int hashCode() {
624                         return value.hashCode();
625                 }
626                 @Override
627                 public boolean equals(Object obj) {
628                         if (this == obj)
629                                 return true;
630                         if (obj == null || getClass() != obj.getClass())
631                                 return false;
632                         Singleton<?> other = (Singleton<?>) obj;
633                         return value.equals(other.value);
634                 }       
635         }
636         
637         public static <T> MultiRead<T> singleton(T value) {
638                 return new Singleton<T>(value);
639         }
640         
641         // ------------------------------------------------------------------------
642         
643         private static class Name implements Read<String> {
644                 Resource resource;
645                 public Name(Resource resource) {
646                         this.resource = resource;
647                 }
648                 @Override
649                 public String perform(ReadGraph graph) throws DatabaseException {
650                 Layer0 L0 = Layer0.getInstance(graph);
651                         SynchronizationProcedure<String> procedure = new SynchronizationProcedure<String>();
652                         graph.forRelatedValue(resource, L0.HasName, procedure);
653                         return procedure.getResult();
654                 }
655             @Override
656             public int hashCode() {
657                 return getClass().hashCode() + 31 * resource.hashCode();
658             }
659                 @Override
660                 public boolean equals(Object obj) {
661                         if(obj == this) return true;
662                         if(obj == null || obj.getClass() != getClass()) return false;
663                         Name other = (Name)obj;
664                         return resource.equals(other.resource);
665                 }               
666         }       
667         public static Read<String> name(Resource resource) {
668                 return new Name(resource);
669         }
670         
671         // ------------------------------------------------------------------------
672         
673         public static final ParametrizedRead<Resource, String> NAME = new ParametrizedRead<Resource, String>() {
674
675                 @Override
676                 public Read<String> get(Resource resource) {
677                         return name(resource);
678                 }
679                 
680         };
681         
682         // ------------------------------------------------------------------------
683         
684 }