--- /dev/null
+/*******************************************************************************\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