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