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