]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - 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
diff --git a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/request/combinations/Combinators.java b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/request/combinations/Combinators.java
new file mode 100644 (file)
index 0000000..2fc619e
--- /dev/null
@@ -0,0 +1,684 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.db.layer0.request.combinations;\r
+\r
+import java.util.HashMap;\r
+import java.util.Map;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.common.request.ParametrizedRead;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.procedure.AsyncMultiProcedure;\r
+import org.simantics.db.procedure.Procedure;\r
+import org.simantics.db.request.MultiRead;\r
+import org.simantics.db.request.Read;\r
+import org.simantics.layer0.Layer0;\r
+\r
+/**\r
+ * Functions that create new read requests by combining simpler ones.\r
+ * @author Hannu Niemist�\r
+ */\r
+public class Combinators {     \r
+               \r
+       // ------------------------------------------------------------------------\r
+       \r
+       private static class Objects implements MultiRead<Resource> {\r
+               Resource subject;               \r
+               Resource relation;\r
+               public Objects(Resource subject, Resource relation) {\r
+                       this.subject = subject;\r
+                       this.relation = relation;\r
+               }\r
+               @Override\r
+               public void perform(ReadGraph graph,\r
+                               AsyncMultiProcedure<Resource> callback)\r
+                               throws DatabaseException {\r
+                       graph.forEachObject(subject, relation, callback);\r
+               }               \r
+           @Override\r
+           public int hashCode() {\r
+               return subject.hashCode() + 31 * relation.hashCode();\r
+           }\r
+           @Override\r
+           public boolean equals(Object object) {\r
+               if (this == object) return true;\r
+               else if (object == null || getClass() != object.getClass()) return false;\r
+               Objects other = (Objects)object;\r
+               return subject.equals(other.subject) && relation.equals(other.relation);\r
+           }\r
+       }\r
+       \r
+       /**\r
+        * Returns a multi read request that reads the objects of given subject and relation. \r
+        */\r
+       public static MultiRead<Resource> objects(Resource subject, Resource relation) {\r
+               return new Objects(subject, relation);\r
+       }\r
+       \r
+       // ------------------------------------------------------------------------\r
+       \r
+       private static class Relation implements ParametrizedMultiRead<Resource, Resource> {\r
+               Resource relation;\r
+               public Relation(Resource relation) {\r
+                       this.relation = relation;\r
+               }\r
+               @Override\r
+               public MultiRead<Resource> get(Resource subject) {\r
+                       return objects(subject, relation);\r
+               }\r
+           @Override\r
+           public int hashCode() {\r
+               return getClass().hashCode() + 31 * relation.hashCode();\r
+           }\r
+               @Override\r
+               public boolean equals(Object obj) {\r
+                       if(obj == this) return true;\r
+                       if(obj == null || obj.getClass() != getClass()) return false;\r
+                       Relation other = (Relation)obj;\r
+                       return relation.equals(other.relation);\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Returns a function <code>subject -> objects(subject, relation)</code>. \r
+        */\r
+       public static ParametrizedMultiRead<Resource,Resource> relation(Resource relation) {\r
+               return new Relation(relation);\r
+       }\r
+       \r
+       // ------------------------------------------------------------------------\r
+       \r
+       public static class SynchronizationProcedure<T> implements Procedure<T> {\r
+               T result;\r
+               DatabaseException exception;\r
+               boolean ready = false;\r
+               @Override\r
+               public synchronized void exception(Throwable t) {\r
+                       this.exception = \r
+                               t instanceof DatabaseException ? (DatabaseException)t : new DatabaseException(t);\r
+                       ready = true;\r
+                       notify();\r
+               }\r
+               @Override\r
+               public synchronized void execute(T result) {\r
+                       this.result = result;\r
+                       ready = true;           \r
+                       notify();\r
+               }               \r
+               public synchronized T getResult() throws DatabaseException {\r
+                       if(!ready) {\r
+                               try {\r
+                                       wait();\r
+                               } catch (InterruptedException e) {\r
+                                       throw new DatabaseException(e);\r
+                               }       \r
+                       }\r
+                       if(exception != null)\r
+                               throw exception;\r
+                       return result;\r
+               }\r
+       }\r
+       \r
+       private static class PossibleObject implements Read<Resource> {\r
+               Resource subject;               \r
+               Resource relation;\r
+               public PossibleObject(Resource subject, Resource relation) {\r
+                       this.subject = subject;\r
+                       this.relation = relation;\r
+               }\r
+               @Override\r
+               public Resource perform(ReadGraph graph) throws DatabaseException {\r
+                       SynchronizationProcedure<Resource> procedure = new SynchronizationProcedure<Resource>();\r
+                       graph.forPossibleObject(subject, relation, procedure);\r
+                       return procedure.getResult();\r
+               }       \r
+           @Override\r
+           public int hashCode() {\r
+               return subject.hashCode() + 31 * relation.hashCode();\r
+           }\r
+           @Override\r
+           public boolean equals(Object object) {\r
+               if (this == object) return true;\r
+               else if (object == null || getClass() != object.getClass()) return false;\r
+               PossibleObject other = (PossibleObject)object;\r
+               return subject.equals(other.subject) && relation.equals(other.relation);\r
+           }\r
+       }\r
+       \r
+       /**\r
+        * Returns a read request that reads an object possibly connected to the subject by the relation.\r
+        */\r
+       public static Read<Resource> possibleObject(Resource subject, Resource relation) {\r
+               return new PossibleObject(subject, relation);\r
+       }\r
+       \r
+       // ------------------------------------------------------------------------\r
+       \r
+       private static class PartialFunction implements ParametrizedRead<Resource, Resource> {\r
+               Resource relation;\r
+               public PartialFunction(Resource relation) {\r
+                       this.relation = relation;\r
+               }\r
+               @Override\r
+               public Read<Resource> get(Resource subject) {\r
+                       return possibleObject(subject, relation);\r
+               }\r
+           @Override\r
+           public int hashCode() {\r
+               return getClass().hashCode() + 31 * relation.hashCode();\r
+           }\r
+               @Override\r
+               public boolean equals(Object obj) {\r
+                       if(obj == this) return true;\r
+                       if(obj == null || obj.getClass() != getClass()) return false;\r
+                       PartialFunction other = (PartialFunction)obj;\r
+                       return relation.equals(other.relation);\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Returns a function <code>subject -> possibleObject(subject, relation)</code>. \r
+        */\r
+       public static ParametrizedRead<Resource,Resource> partialFunction(Resource relation) {\r
+               return new PartialFunction(relation);\r
+       }\r
+       \r
+       // ------------------------------------------------------------------------\r
+       \r
+       private static class SingleObject implements Read<Resource> {\r
+               Resource subject;               \r
+               Resource relation;\r
+               public SingleObject(Resource subject, Resource relation) {\r
+                       this.subject = subject;\r
+                       this.relation = relation;\r
+               }\r
+               @Override\r
+               public Resource perform(ReadGraph graph) throws DatabaseException {\r
+                       SynchronizationProcedure<Resource> procedure = new SynchronizationProcedure<Resource>();\r
+                       graph.forSingleObject(subject, relation, procedure);\r
+                       return procedure.getResult();\r
+               }       \r
+           @Override\r
+           public int hashCode() {\r
+               return subject.hashCode() + 31 * relation.hashCode();\r
+           }\r
+           @Override\r
+           public boolean equals(Object object) {\r
+               if (this == object) return true;\r
+               else if (object == null || getClass() != object.getClass()) return false;\r
+               SingleObject other = (SingleObject)object;\r
+               return subject.equals(other.subject) && relation.equals(other.relation);\r
+           }\r
+       }\r
+       \r
+       /**\r
+        * Returns a read request that reads an object connected to the subject by the relation.\r
+        */\r
+       public static Read<Resource> singleObject(Resource subject, Resource relation) {\r
+               return new SingleObject(subject, relation);\r
+       }\r
+       \r
+       // ------------------------------------------------------------------------\r
+       \r
+       private static class CompleteFunction implements ParametrizedRead<Resource, Resource> {\r
+               Resource relation;\r
+               public CompleteFunction(Resource relation) {\r
+                       this.relation = relation;\r
+               }\r
+               @Override\r
+               public Read<Resource> get(Resource subject) {\r
+                       return singleObject(subject, relation);\r
+               }\r
+           @Override\r
+           public int hashCode() {\r
+               return getClass().hashCode() + 31 * relation.hashCode();\r
+           }\r
+               @Override\r
+               public boolean equals(Object obj) {\r
+                       if(obj == this) return true;\r
+                       if(obj == null || obj.getClass() != getClass()) return false;\r
+                       CompleteFunction other = (CompleteFunction)obj;\r
+                       return relation.equals(other.relation);\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Returns a function <code>subject -> singleObject(subject, relation)</code>. \r
+        */\r
+       public static ParametrizedRead<Resource,Resource> completeFunction(Resource relation) {\r
+               return new CompleteFunction(relation);\r
+       }\r
+       \r
+       // ------------------------------------------------------------------------\r
+       \r
+       private static class Compose1<X, Y> implements Read<Y> {\r
+               final ParametrizedRead<X, Y> f;\r
+               final Read<X> g;                \r
+               public Compose1(ParametrizedRead<X, Y> f, Read<X> g) {\r
+                       this.f = f;\r
+                       this.g = g;\r
+               }\r
+               @Override\r
+               public Y perform(ReadGraph graph) throws DatabaseException {\r
+                       return graph.syncRequest(f.get(graph.syncRequest(g)));\r
+               }               \r
+               @Override\r
+               public int hashCode() {\r
+                       return getClass().hashCode() + 31 * (f.hashCode() + 31 * g.hashCode());\r
+               }\r
+               @Override\r
+               public boolean equals(Object obj) {\r
+                       if(obj == this) return true;\r
+                       if(obj == null || obj.getClass() != getClass()) return false;\r
+                       Compose1<?, ?> other = (Compose1<?, ?>)obj;\r
+                       return f.equals(other.f) && g.equals(other.g);\r
+               }\r
+       }\r
+       \r
+       public static <X, Y> Read<Y> compose(ParametrizedRead<X, Y> f, Read<X> g) {\r
+               return new Compose1<X, Y>(f, g);\r
+       }\r
+\r
+       // ------------------------------------------------------------------------\r
+       \r
+       private static class Compose2<X, Y, Z> implements ParametrizedRead<X, Z> {\r
+               final ParametrizedRead<Y, Z> f;\r
+               final ParametrizedRead<X, Y> g;         \r
+               public Compose2(ParametrizedRead<Y, Z> f, ParametrizedRead<X, Y> g) {\r
+                       this.f = f;\r
+                       this.g = g;\r
+               }\r
+               public Read<Z> get(X x) {\r
+                       return compose(f, g.get(x));\r
+               }\r
+               @Override\r
+               public int hashCode() {\r
+                       return getClass().hashCode() + 31 * (f.hashCode() + 31 * g.hashCode());\r
+               }\r
+               @Override\r
+               public boolean equals(Object obj) {\r
+                       if(obj == this) return true;\r
+                       if(obj == null || obj.getClass() != getClass()) return false;\r
+                       Compose2<?, ?, ?> other = (Compose2<?, ?, ?>)obj;\r
+                       return f.equals(other.f) && g.equals(other.g);\r
+               }\r
+       }\r
+       \r
+       public static <X, Y, Z> ParametrizedRead<X, Z> compose(ParametrizedRead<Y, Z> f, ParametrizedRead<X, Y> g) {\r
+               return new Compose2<X, Y, Z>(f, g);\r
+       }\r
+       \r
+       // ------------------------------------------------------------------------\r
+       \r
+       private static class Compose3<X, Y> implements MultiRead<Y> {\r
+               final ParametrizedRead<X, Y> f;\r
+               final MultiRead<X> g;           \r
+               public Compose3(ParametrizedRead<X, Y> f, MultiRead<X> g) {\r
+                       this.f = f;\r
+                       this.g = g;\r
+               }\r
+               public void perform(ReadGraph graph, final AsyncMultiProcedure<Y> callback)     throws DatabaseException {\r
+                   try {\r
+                               for(X x : graph.syncRequest(g))\r
+                                       callback.execute(graph, graph.syncRequest(f.get(x)));\r
+                               callback.finished(graph);\r
+                       } catch(DatabaseException e) {\r
+                               callback.exception(graph, e);\r
+                       }\r
+                       /*// Not sure if this is correct\r
+                  graph.syncRequest(g, new SyncMultiProcedure<X>() {\r
+                               @Override\r
+                               public void exception(ReadGraph graph, Throwable throwable)\r
+                               throws DatabaseException {\r
+                                       callback.exception(graph, throwable);                                   \r
+                               }\r
+                               @Override\r
+                               public void execute(ReadGraph graph, X x)\r
+                               throws DatabaseException {\r
+                                       callback.execute(graph, graph.syncRequest(f.get(x)));\r
+                               }\r
+                               @Override\r
+                               public void finished(ReadGraph graph)\r
+                               throws DatabaseException {\r
+                               }\r
+                       });\r
+                       callback.finished(graph);*/\r
+               }                                       \r
+               @Override\r
+               public int hashCode() {\r
+                       return getClass().hashCode() + 31 * (f.hashCode() + 31 * g.hashCode());\r
+               }\r
+               @Override\r
+               public boolean equals(Object obj) {\r
+                       if(obj == this) return true;\r
+                       if(obj == null || obj.getClass() != getClass()) return false;\r
+                       Compose3<?, ?> other = (Compose3<?, ?>)obj;\r
+                       return f.equals(other.f) && g.equals(other.g);\r
+               }\r
+       }\r
+       \r
+       public static <X, Y> MultiRead<Y> compose(ParametrizedRead<X, Y> f, MultiRead<X> g) {\r
+               return new Compose3<X, Y>(f, g);\r
+       }\r
+       \r
+       // ------------------------------------------------------------------------\r
+       \r
+       private static class Compose4<X, Y, Z> implements ParametrizedMultiRead<X, Z> {\r
+               final ParametrizedRead<Y, Z> f;\r
+               final ParametrizedMultiRead<X, Y> g;            \r
+               public Compose4(ParametrizedRead<Y, Z> f, ParametrizedMultiRead<X, Y> g) {\r
+                       this.f = f;\r
+                       this.g = g;\r
+               }\r
+               public MultiRead<Z> get(X x) {\r
+                       return compose(f, g.get(x));\r
+               }\r
+               @Override\r
+               public int hashCode() {\r
+                       return getClass().hashCode() + 31 * (f.hashCode() + 31 * g.hashCode());\r
+               }\r
+               @Override\r
+               public boolean equals(Object obj) {\r
+                       if(obj == this) return true;\r
+                       if(obj == null || obj.getClass() != getClass()) return false;\r
+                       Compose4<?, ?, ?> other = (Compose4<?, ?, ?>)obj;\r
+                       return f.equals(other.f) && g.equals(other.g);\r
+               }\r
+       }\r
+       \r
+       public static <X, Y, Z> ParametrizedMultiRead<X, Z> compose(ParametrizedRead<Y, Z> f, ParametrizedMultiRead<X, Y> g) {\r
+               return new Compose4<X, Y, Z>(f, g);\r
+       }\r
+\r
+       // ------------------------------------------------------------------------\r
+       \r
+       private static class Compose5<X, Y> implements MultiRead<Y> {\r
+               final ParametrizedMultiRead<X, Y> f;\r
+               final Read<X> g;                \r
+               public Compose5(ParametrizedMultiRead<X, Y> f, Read<X> g) {\r
+                       this.f = f;\r
+                       this.g = g;\r
+               }\r
+               @Override\r
+               public void perform(ReadGraph graph, AsyncMultiProcedure<Y> callback)\r
+                               throws DatabaseException {\r
+                       graph.syncRequest(f.get(graph.syncRequest(g)), callback);\r
+               }\r
+               @Override\r
+               public int hashCode() {\r
+                       return getClass().hashCode() + 31 * (f.hashCode() + 31 * g.hashCode());\r
+               }\r
+               @Override\r
+               public boolean equals(Object obj) {\r
+                       if(obj == this) return true;\r
+                       if(obj == null || obj.getClass() != getClass()) return false;\r
+                       Compose5<?, ?> other = (Compose5<?, ?>)obj;\r
+                       return f.equals(other.f) && g.equals(other.g);\r
+               }\r
+       }\r
+       \r
+       public static <X, Y> MultiRead<Y> compose(ParametrizedMultiRead<X, Y> f, Read<X> g) {\r
+               return new Compose5<X, Y>(f, g);\r
+       }\r
+\r
+       // ------------------------------------------------------------------------\r
+       \r
+       private static class Compose6<X, Y, Z> implements ParametrizedMultiRead<X, Z> {\r
+               final ParametrizedMultiRead<Y, Z> f;\r
+               final ParametrizedRead<X, Y> g;         \r
+               public Compose6(ParametrizedMultiRead<Y, Z> f, ParametrizedRead<X, Y> g) {\r
+                       this.f = f;\r
+                       this.g = g;\r
+               }\r
+               public MultiRead<Z> get(X x) {\r
+                       return compose(f, g.get(x));\r
+               }\r
+               @Override\r
+               public int hashCode() {\r
+                       return getClass().hashCode() + 31 * (f.hashCode() + 31 * g.hashCode());\r
+               }\r
+               @Override\r
+               public boolean equals(Object obj) {\r
+                       if(obj == this) return true;\r
+                       if(obj == null || obj.getClass() != getClass()) return false;\r
+                       Compose6<?, ?, ?> other = (Compose6<?, ?, ?>)obj;\r
+                       return f.equals(other.f) && g.equals(other.g);\r
+               }\r
+       }\r
+       \r
+       public static <X, Y, Z> ParametrizedMultiRead<X, Z> compose(ParametrizedMultiRead<Y, Z> f, ParametrizedRead<X, Y> g) {\r
+               return new Compose6<X, Y, Z>(f, g);\r
+       }\r
+       \r
+       // ------------------------------------------------------------------------\r
+       \r
+       private static class Compose7<X, Y> implements MultiRead<Y> {\r
+               final ParametrizedMultiRead<X, Y> f;\r
+               final MultiRead<X> g;           \r
+               public Compose7(ParametrizedMultiRead<X, Y> f, MultiRead<X> g) {\r
+                       this.f = f;\r
+                       this.g = g;\r
+               }\r
+               public void perform(ReadGraph graph, final AsyncMultiProcedure<Y> callback)     throws DatabaseException {\r
+                   try {\r
+                               for(X x : graph.syncRequest(g))\r
+                                       for(Y y : graph.syncRequest(f.get(x)))\r
+                                               callback.execute(graph, y);\r
+                               callback.finished(graph);\r
+                       } catch(DatabaseException e) {\r
+                               callback.exception(graph, e);\r
+                       }\r
+                       /*// Not correct because inner syncRequest calls callback.finished \r
+                   graph.syncRequest(g, new SyncMultiProcedure<X>() {\r
+                               @Override\r
+                               public void exception(ReadGraph graph, Throwable throwable)\r
+                               throws DatabaseException {\r
+                                       callback.exception(graph, throwable);                                   \r
+                               }\r
+                               @Override\r
+                               public void execute(ReadGraph graph, X x) throws DatabaseException {\r
+                                       graph.syncRequest(f.get(x), callback);\r
+                               }\r
+                               @Override\r
+                               public void finished(ReadGraph graph)\r
+                               throws DatabaseException {\r
+                               }\r
+                       });\r
+                       callback.finished(graph);\r
+                       */\r
+               }                                       \r
+               @Override\r
+               public int hashCode() {\r
+                       return getClass().hashCode() + 31 * (f.hashCode() + 31 * g.hashCode());\r
+               }\r
+               @Override\r
+               public boolean equals(Object obj) {\r
+                       if(obj == this) return true;\r
+                       if(obj == null || obj.getClass() != getClass()) return false;\r
+                       Compose7<?, ?> other = (Compose7<?, ?>)obj;\r
+                       return f.equals(other.f) && g.equals(other.g);\r
+               }\r
+       }\r
+       \r
+       public static <X, Y> MultiRead<Y> compose(ParametrizedMultiRead<X, Y> f, MultiRead<X> g) {\r
+               return new Compose7<X, Y>(f, g);\r
+       }\r
+       \r
+       // ------------------------------------------------------------------------\r
+       \r
+       private static class Compose8<X, Y, Z> implements ParametrizedMultiRead<X, Z> {\r
+               final ParametrizedMultiRead<Y, Z> f;\r
+               final ParametrizedMultiRead<X, Y> g;            \r
+               public Compose8(ParametrizedMultiRead<Y, Z> f, ParametrizedMultiRead<X, Y> g) {\r
+                       this.f = f;\r
+                       this.g = g;\r
+               }\r
+               public MultiRead<Z> get(X x) {\r
+                       return compose(f, g.get(x));\r
+               }\r
+               @Override\r
+               public int hashCode() {\r
+                       return getClass().hashCode() + 31 * (f.hashCode() + 31 * g.hashCode());\r
+               }\r
+               @Override\r
+               public boolean equals(Object obj) {\r
+                       if(obj == this) return true;\r
+                       if(obj == null || obj.getClass() != getClass()) return false;\r
+                       Compose8<?, ?, ?> other = (Compose8<?, ?, ?>)obj;\r
+                       return f.equals(other.f) && g.equals(other.g);\r
+               }\r
+       }\r
+       \r
+       public static <X, Y, Z> ParametrizedMultiRead<X, Z> compose(ParametrizedMultiRead<Y, Z> f, ParametrizedMultiRead<X, Y> g) {\r
+               return new Compose8<X, Y, Z>(f, g);\r
+       }       \r
+       \r
+       // ------------------------------------------------------------------------\r
+\r
+       private static class Index<K, V> implements Read<Map<K, V>> {\r
+               final MultiRead<V> values;\r
+               final ParametrizedRead<V, K> keyOfValue;\r
+               public Index(MultiRead<V> values, ParametrizedRead<V, K> keyOfValue) {\r
+                       this.values = values;\r
+                       this.keyOfValue = keyOfValue;\r
+               }\r
+               @Override\r
+               public Map<K, V> perform(ReadGraph graph) throws DatabaseException {\r
+                       HashMap<K, V> result = new HashMap<K, V>();\r
+                       for(V value : graph.syncRequest(values))\r
+                               result.put(graph.syncRequest(keyOfValue.get(value)), value);\r
+                       return result;\r
+               }\r
+               @Override\r
+               public int hashCode() {\r
+                       return getClass().hashCode() + 31 * (values.hashCode() + 31 * keyOfValue.hashCode());\r
+               }\r
+               @Override\r
+               public boolean equals(Object obj) {\r
+                       if(obj == this) return true;\r
+                       if(obj == null || obj.getClass() != getClass()) return false;\r
+                       Index<?, ?> other = (Index<?, ?>)obj;\r
+                       return values.equals(other.values) && keyOfValue.equals(other.keyOfValue);\r
+               }       \r
+       }\r
+       \r
+       public static <K, V> Read<Map<K, V>> index(MultiRead<V> values, ParametrizedRead<V, K> keyOfValue) {\r
+               return new Index<K, V>(values, keyOfValue);\r
+       }\r
+       \r
+       // ------------------------------------------------------------------------\r
+\r
+       private static class Constant<T> implements Read<T> {\r
+               T value;\r
+               public Constant(T value) {\r
+                       this.value = value;\r
+               }\r
+               @Override\r
+               public T perform(ReadGraph graph) throws DatabaseException {\r
+                       return value;\r
+               }\r
+               @Override\r
+               public int hashCode() {\r
+                       return value == null ? 0 : value.hashCode();\r
+               }\r
+               @Override\r
+               public boolean equals(Object obj) {\r
+                       if (this == obj)\r
+                               return true;\r
+                       if (obj == null || getClass() != obj.getClass())\r
+                               return false;\r
+                       Constant<?> other = (Constant<?>) obj;\r
+                       return value == null ? other.value == null : value.equals(other.value);\r
+               }               \r
+       }\r
+       \r
+       public static <T> Read<T> constant(T value) {\r
+               return new Constant<T>(value);\r
+       }\r
+       \r
+       // ------------------------------------------------------------------------\r
+\r
+       private static class Singleton<T> implements MultiRead<T> {\r
+               T value;\r
+               public Singleton(T value) {\r
+                       this.value = value;\r
+               }\r
+               @Override\r
+               public void perform(ReadGraph graph, AsyncMultiProcedure<T> callback)\r
+                               throws DatabaseException {\r
+                       callback.execute(graph, value);\r
+                       callback.finished(graph);\r
+               }\r
+               @Override\r
+               public int hashCode() {\r
+                       return value.hashCode();\r
+               }\r
+               @Override\r
+               public boolean equals(Object obj) {\r
+                       if (this == obj)\r
+                               return true;\r
+                       if (obj == null || getClass() != obj.getClass())\r
+                               return false;\r
+                       Singleton<?> other = (Singleton<?>) obj;\r
+                       return value.equals(other.value);\r
+               }       \r
+       }\r
+       \r
+       public static <T> MultiRead<T> singleton(T value) {\r
+               return new Singleton<T>(value);\r
+       }\r
+       \r
+       // ------------------------------------------------------------------------\r
+       \r
+       private static class Name implements Read<String> {\r
+               Resource resource;\r
+               public Name(Resource resource) {\r
+                       this.resource = resource;\r
+               }\r
+               @Override\r
+               public String perform(ReadGraph graph) throws DatabaseException {\r
+               Layer0 L0 = Layer0.getInstance(graph);\r
+                       SynchronizationProcedure<String> procedure = new SynchronizationProcedure<String>();\r
+                       graph.forRelatedValue(resource, L0.HasName, procedure);\r
+                       return procedure.getResult();\r
+               }\r
+           @Override\r
+           public int hashCode() {\r
+               return getClass().hashCode() + 31 * resource.hashCode();\r
+           }\r
+               @Override\r
+               public boolean equals(Object obj) {\r
+                       if(obj == this) return true;\r
+                       if(obj == null || obj.getClass() != getClass()) return false;\r
+                       Name other = (Name)obj;\r
+                       return resource.equals(other.resource);\r
+               }               \r
+       }       \r
+       public static Read<String> name(Resource resource) {\r
+               return new Name(resource);\r
+       }\r
+       \r
+       // ------------------------------------------------------------------------\r
+       \r
+       public static final ParametrizedRead<Resource, String> NAME = new ParametrizedRead<Resource, String>() {\r
+\r
+               @Override\r
+               public Read<String> get(Resource resource) {\r
+                       return name(resource);\r
+               }\r
+               \r
+       };\r
+       \r
+       // ------------------------------------------------------------------------\r
+       \r
+}\r