1 /*******************************************************************************
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.db.layer0.request.combinations;
14 import java.util.HashMap;
17 import org.simantics.db.ReadGraph;
18 import org.simantics.db.Resource;
19 import org.simantics.db.common.request.ParametrizedRead;
20 import org.simantics.db.common.request.ResourceRead;
21 import org.simantics.db.exception.DatabaseException;
22 import org.simantics.db.procedure.Procedure;
23 import org.simantics.db.procedure.SyncMultiProcedure;
24 import org.simantics.db.request.MultiRead;
25 import org.simantics.db.request.Read;
26 import org.simantics.layer0.Layer0;
29 * Functions that create new read requests by combining simpler ones.
30 * @author Hannu Niemist�
32 public class Combinators {
34 // ------------------------------------------------------------------------
36 private static class Objects implements MultiRead<Resource> {
39 public Objects(Resource subject, Resource relation) {
40 this.subject = subject;
41 this.relation = relation;
44 public void perform(ReadGraph graph,
45 SyncMultiProcedure<Resource> callback)
46 throws DatabaseException {
47 for(Resource object : graph.getObjects(subject, relation)) {
48 callback.execute(graph, object);
52 public int hashCode() {
53 return subject.hashCode() + 31 * relation.hashCode();
56 public boolean equals(Object object) {
57 if (this == object) return true;
58 else if (object == null || getClass() != object.getClass()) return false;
59 Objects other = (Objects)object;
60 return subject.equals(other.subject) && relation.equals(other.relation);
65 * Returns a multi read request that reads the objects of given subject and relation.
67 public static MultiRead<Resource> objects(Resource subject, Resource relation) {
68 return new Objects(subject, relation);
71 // ------------------------------------------------------------------------
73 private static class Relation implements ParametrizedMultiRead<Resource, Resource> {
75 public Relation(Resource relation) {
76 this.relation = relation;
79 public MultiRead<Resource> get(Resource subject) {
80 return objects(subject, relation);
83 public int hashCode() {
84 return getClass().hashCode() + 31 * relation.hashCode();
87 public boolean equals(Object obj) {
88 if(obj == this) return true;
89 if(obj == null || obj.getClass() != getClass()) return false;
90 Relation other = (Relation)obj;
91 return relation.equals(other.relation);
96 * Returns a function <code>subject -> objects(subject, relation)</code>.
98 public static ParametrizedMultiRead<Resource,Resource> relation(Resource relation) {
99 return new Relation(relation);
102 // ------------------------------------------------------------------------
104 public static class SynchronizationProcedure<T> implements Procedure<T> {
106 DatabaseException exception;
107 boolean ready = false;
109 public synchronized void exception(Throwable t) {
111 t instanceof DatabaseException ? (DatabaseException)t : new DatabaseException(t);
116 public synchronized void execute(T result) {
117 this.result = result;
121 public synchronized T getResult() throws DatabaseException {
125 } catch (InterruptedException e) {
126 throw new DatabaseException(e);
129 if(exception != null)
135 private static class PossibleObject implements Read<Resource> {
138 public PossibleObject(Resource subject, Resource relation) {
139 this.subject = subject;
140 this.relation = relation;
143 public Resource perform(ReadGraph graph) throws DatabaseException {
144 return graph.getPossibleObject(subject, relation);
147 public int hashCode() {
148 return subject.hashCode() + 31 * relation.hashCode();
151 public boolean equals(Object object) {
152 if (this == object) return true;
153 else if (object == null || getClass() != object.getClass()) return false;
154 PossibleObject other = (PossibleObject)object;
155 return subject.equals(other.subject) && relation.equals(other.relation);
160 * Returns a read request that reads an object possibly connected to the subject by the relation.
162 public static Read<Resource> possibleObject(Resource subject, Resource relation) {
163 return new PossibleObject(subject, relation);
166 // ------------------------------------------------------------------------
168 private static class PartialFunction implements ParametrizedRead<Resource, Resource> {
170 public PartialFunction(Resource relation) {
171 this.relation = relation;
174 public Read<Resource> get(Resource subject) {
175 return possibleObject(subject, relation);
178 public int hashCode() {
179 return getClass().hashCode() + 31 * relation.hashCode();
182 public boolean equals(Object obj) {
183 if(obj == this) return true;
184 if(obj == null || obj.getClass() != getClass()) return false;
185 PartialFunction other = (PartialFunction)obj;
186 return relation.equals(other.relation);
191 * Returns a function <code>subject -> possibleObject(subject, relation)</code>.
193 public static ParametrizedRead<Resource,Resource> partialFunction(Resource relation) {
194 return new PartialFunction(relation);
197 // ------------------------------------------------------------------------
199 private static class SingleObject implements Read<Resource> {
202 public SingleObject(Resource subject, Resource relation) {
203 this.subject = subject;
204 this.relation = relation;
207 public Resource perform(ReadGraph graph) throws DatabaseException {
208 return graph.getSingleObject(subject, relation);
211 public int hashCode() {
212 return subject.hashCode() + 31 * relation.hashCode();
215 public boolean equals(Object object) {
216 if (this == object) return true;
217 else if (object == null || getClass() != object.getClass()) return false;
218 SingleObject other = (SingleObject)object;
219 return subject.equals(other.subject) && relation.equals(other.relation);
224 * Returns a read request that reads an object connected to the subject by the relation.
226 public static Read<Resource> singleObject(Resource subject, Resource relation) {
227 return new SingleObject(subject, relation);
230 // ------------------------------------------------------------------------
232 private static class CompleteFunction implements ParametrizedRead<Resource, Resource> {
234 public CompleteFunction(Resource relation) {
235 this.relation = relation;
238 public Read<Resource> get(Resource subject) {
239 return singleObject(subject, relation);
242 public int hashCode() {
243 return getClass().hashCode() + 31 * relation.hashCode();
246 public boolean equals(Object obj) {
247 if(obj == this) return true;
248 if(obj == null || obj.getClass() != getClass()) return false;
249 CompleteFunction other = (CompleteFunction)obj;
250 return relation.equals(other.relation);
255 * Returns a function <code>subject -> singleObject(subject, relation)</code>.
257 public static ParametrizedRead<Resource,Resource> completeFunction(Resource relation) {
258 return new CompleteFunction(relation);
261 // ------------------------------------------------------------------------
263 private static class Compose1<X, Y> implements Read<Y> {
264 final ParametrizedRead<X, Y> f;
266 public Compose1(ParametrizedRead<X, Y> f, Read<X> g) {
271 public Y perform(ReadGraph graph) throws DatabaseException {
272 return graph.syncRequest(f.get(graph.syncRequest(g)));
275 public int hashCode() {
276 return getClass().hashCode() + 31 * (f.hashCode() + 31 * g.hashCode());
279 public boolean equals(Object obj) {
280 if(obj == this) return true;
281 if(obj == null || obj.getClass() != getClass()) return false;
282 Compose1<?, ?> other = (Compose1<?, ?>)obj;
283 return f.equals(other.f) && g.equals(other.g);
287 public static <X, Y> Read<Y> compose(ParametrizedRead<X, Y> f, Read<X> g) {
288 return new Compose1<X, Y>(f, g);
291 // ------------------------------------------------------------------------
293 private static class Compose2<X, Y, Z> implements ParametrizedRead<X, Z> {
294 final ParametrizedRead<Y, Z> f;
295 final ParametrizedRead<X, Y> g;
296 public Compose2(ParametrizedRead<Y, Z> f, ParametrizedRead<X, Y> g) {
300 public Read<Z> get(X x) {
301 return compose(f, g.get(x));
304 public int hashCode() {
305 return getClass().hashCode() + 31 * (f.hashCode() + 31 * g.hashCode());
308 public boolean equals(Object obj) {
309 if(obj == this) return true;
310 if(obj == null || obj.getClass() != getClass()) return false;
311 Compose2<?, ?, ?> other = (Compose2<?, ?, ?>)obj;
312 return f.equals(other.f) && g.equals(other.g);
316 public static <X, Y, Z> ParametrizedRead<X, Z> compose(ParametrizedRead<Y, Z> f, ParametrizedRead<X, Y> g) {
317 return new Compose2<X, Y, Z>(f, g);
320 // ------------------------------------------------------------------------
322 private static class Compose3<X, Y> implements MultiRead<Y> {
323 final ParametrizedRead<X, Y> f;
324 final MultiRead<X> g;
325 public Compose3(ParametrizedRead<X, Y> f, MultiRead<X> g) {
329 public void perform(ReadGraph graph, final SyncMultiProcedure<Y> callback) throws DatabaseException {
331 for(X x : graph.syncRequest(g))
332 callback.execute(graph, graph.syncRequest(f.get(x)));
333 callback.finished(graph);
334 } catch(DatabaseException e) {
335 callback.exception(graph, e);
337 /*// Not sure if this is correct
338 graph.syncRequest(g, new SyncMultiProcedure<X>() {
340 public void exception(ReadGraph graph, Throwable throwable)
341 throws DatabaseException {
342 callback.exception(graph, throwable);
345 public void execute(ReadGraph graph, X x)
346 throws DatabaseException {
347 callback.execute(graph, graph.syncRequest(f.get(x)));
350 public void finished(ReadGraph graph)
351 throws DatabaseException {
354 callback.finished(graph);*/
357 public int hashCode() {
358 return getClass().hashCode() + 31 * (f.hashCode() + 31 * g.hashCode());
361 public boolean equals(Object obj) {
362 if(obj == this) return true;
363 if(obj == null || obj.getClass() != getClass()) return false;
364 Compose3<?, ?> other = (Compose3<?, ?>)obj;
365 return f.equals(other.f) && g.equals(other.g);
369 public static <X, Y> MultiRead<Y> compose(ParametrizedRead<X, Y> f, MultiRead<X> g) {
370 return new Compose3<X, Y>(f, g);
373 // ------------------------------------------------------------------------
375 private static class Compose4<X, Y, Z> implements ParametrizedMultiRead<X, Z> {
376 final ParametrizedRead<Y, Z> f;
377 final ParametrizedMultiRead<X, Y> g;
378 public Compose4(ParametrizedRead<Y, Z> f, ParametrizedMultiRead<X, Y> g) {
382 public MultiRead<Z> get(X x) {
383 return compose(f, g.get(x));
386 public int hashCode() {
387 return getClass().hashCode() + 31 * (f.hashCode() + 31 * g.hashCode());
390 public boolean equals(Object obj) {
391 if(obj == this) return true;
392 if(obj == null || obj.getClass() != getClass()) return false;
393 Compose4<?, ?, ?> other = (Compose4<?, ?, ?>)obj;
394 return f.equals(other.f) && g.equals(other.g);
398 public static <X, Y, Z> ParametrizedMultiRead<X, Z> compose(ParametrizedRead<Y, Z> f, ParametrizedMultiRead<X, Y> g) {
399 return new Compose4<X, Y, Z>(f, g);
402 // ------------------------------------------------------------------------
404 private static class Compose5<X, Y> implements MultiRead<Y> {
405 final ParametrizedMultiRead<X, Y> f;
407 public Compose5(ParametrizedMultiRead<X, Y> f, Read<X> g) {
412 public void perform(ReadGraph graph, SyncMultiProcedure<Y> callback)
413 throws DatabaseException {
414 graph.syncRequest(f.get(graph.syncRequest(g)), callback);
417 public int hashCode() {
418 return getClass().hashCode() + 31 * (f.hashCode() + 31 * g.hashCode());
421 public boolean equals(Object obj) {
422 if(obj == this) return true;
423 if(obj == null || obj.getClass() != getClass()) return false;
424 Compose5<?, ?> other = (Compose5<?, ?>)obj;
425 return f.equals(other.f) && g.equals(other.g);
429 public static <X, Y> MultiRead<Y> compose(ParametrizedMultiRead<X, Y> f, Read<X> g) {
430 return new Compose5<X, Y>(f, g);
433 // ------------------------------------------------------------------------
435 private static class Compose6<X, Y, Z> implements ParametrizedMultiRead<X, Z> {
436 final ParametrizedMultiRead<Y, Z> f;
437 final ParametrizedRead<X, Y> g;
438 public Compose6(ParametrizedMultiRead<Y, Z> f, ParametrizedRead<X, Y> g) {
442 public MultiRead<Z> get(X x) {
443 return compose(f, g.get(x));
446 public int hashCode() {
447 return getClass().hashCode() + 31 * (f.hashCode() + 31 * g.hashCode());
450 public boolean equals(Object obj) {
451 if(obj == this) return true;
452 if(obj == null || obj.getClass() != getClass()) return false;
453 Compose6<?, ?, ?> other = (Compose6<?, ?, ?>)obj;
454 return f.equals(other.f) && g.equals(other.g);
458 public static <X, Y, Z> ParametrizedMultiRead<X, Z> compose(ParametrizedMultiRead<Y, Z> f, ParametrizedRead<X, Y> g) {
459 return new Compose6<X, Y, Z>(f, g);
462 // ------------------------------------------------------------------------
464 private static class Compose7<X, Y> implements MultiRead<Y> {
465 final ParametrizedMultiRead<X, Y> f;
466 final MultiRead<X> g;
467 public Compose7(ParametrizedMultiRead<X, Y> f, MultiRead<X> g) {
471 public void perform(ReadGraph graph, final SyncMultiProcedure<Y> callback) throws DatabaseException {
473 for(X x : graph.syncRequest(g))
474 for(Y y : graph.syncRequest(f.get(x)))
475 callback.execute(graph, y);
476 callback.finished(graph);
477 } catch(DatabaseException e) {
478 callback.exception(graph, e);
480 /*// Not correct because inner syncRequest calls callback.finished
481 graph.syncRequest(g, new SyncMultiProcedure<X>() {
483 public void exception(ReadGraph graph, Throwable throwable)
484 throws DatabaseException {
485 callback.exception(graph, throwable);
488 public void execute(ReadGraph graph, X x) throws DatabaseException {
489 graph.syncRequest(f.get(x), callback);
492 public void finished(ReadGraph graph)
493 throws DatabaseException {
496 callback.finished(graph);
500 public int hashCode() {
501 return getClass().hashCode() + 31 * (f.hashCode() + 31 * g.hashCode());
504 public boolean equals(Object obj) {
505 if(obj == this) return true;
506 if(obj == null || obj.getClass() != getClass()) return false;
507 Compose7<?, ?> other = (Compose7<?, ?>)obj;
508 return f.equals(other.f) && g.equals(other.g);
512 public static <X, Y> MultiRead<Y> compose(ParametrizedMultiRead<X, Y> f, MultiRead<X> g) {
513 return new Compose7<X, Y>(f, g);
516 // ------------------------------------------------------------------------
518 private static class Compose8<X, Y, Z> implements ParametrizedMultiRead<X, Z> {
519 final ParametrizedMultiRead<Y, Z> f;
520 final ParametrizedMultiRead<X, Y> g;
521 public Compose8(ParametrizedMultiRead<Y, Z> f, ParametrizedMultiRead<X, Y> g) {
525 public MultiRead<Z> get(X x) {
526 return compose(f, g.get(x));
529 public int hashCode() {
530 return getClass().hashCode() + 31 * (f.hashCode() + 31 * g.hashCode());
533 public boolean equals(Object obj) {
534 if(obj == this) return true;
535 if(obj == null || obj.getClass() != getClass()) return false;
536 Compose8<?, ?, ?> other = (Compose8<?, ?, ?>)obj;
537 return f.equals(other.f) && g.equals(other.g);
541 public static <X, Y, Z> ParametrizedMultiRead<X, Z> compose(ParametrizedMultiRead<Y, Z> f, ParametrizedMultiRead<X, Y> g) {
542 return new Compose8<X, Y, Z>(f, g);
545 // ------------------------------------------------------------------------
547 private static class Index<K, V> implements Read<Map<K, V>> {
548 final MultiRead<V> values;
549 final ParametrizedRead<V, K> keyOfValue;
550 public Index(MultiRead<V> values, ParametrizedRead<V, K> keyOfValue) {
551 this.values = values;
552 this.keyOfValue = keyOfValue;
555 public Map<K, V> perform(ReadGraph graph) throws DatabaseException {
556 HashMap<K, V> result = new HashMap<K, V>();
557 for(V value : graph.syncRequest(values))
558 result.put(graph.syncRequest(keyOfValue.get(value)), value);
562 public int hashCode() {
563 return getClass().hashCode() + 31 * (values.hashCode() + 31 * keyOfValue.hashCode());
566 public boolean equals(Object obj) {
567 if(obj == this) return true;
568 if(obj == null || obj.getClass() != getClass()) return false;
569 Index<?, ?> other = (Index<?, ?>)obj;
570 return values.equals(other.values) && keyOfValue.equals(other.keyOfValue);
574 public static <K, V> Read<Map<K, V>> index(MultiRead<V> values, ParametrizedRead<V, K> keyOfValue) {
575 return new Index<K, V>(values, keyOfValue);
578 // ------------------------------------------------------------------------
580 private static class Constant<T> implements Read<T> {
582 public Constant(T value) {
586 public T perform(ReadGraph graph) throws DatabaseException {
590 public int hashCode() {
591 return value == null ? 0 : value.hashCode();
594 public boolean equals(Object obj) {
597 if (obj == null || getClass() != obj.getClass())
599 Constant<?> other = (Constant<?>) obj;
600 return value == null ? other.value == null : value.equals(other.value);
604 public static <T> Read<T> constant(T value) {
605 return new Constant<T>(value);
608 // ------------------------------------------------------------------------
610 private static class Singleton<T> implements MultiRead<T> {
612 public Singleton(T value) {
616 public void perform(ReadGraph graph, SyncMultiProcedure<T> callback)
617 throws DatabaseException {
618 callback.execute(graph, value);
619 callback.finished(graph);
622 public int hashCode() {
623 return value.hashCode();
626 public boolean equals(Object obj) {
629 if (obj == null || getClass() != obj.getClass())
631 Singleton<?> other = (Singleton<?>) obj;
632 return value.equals(other.value);
636 public static <T> MultiRead<T> singleton(T value) {
637 return new Singleton<T>(value);
640 // ------------------------------------------------------------------------
642 private static class Name extends ResourceRead<String> {
644 public Name(Resource resource) {
649 public String perform(ReadGraph graph) throws DatabaseException {
650 Layer0 L0 = Layer0.getInstance(graph);
651 return graph.getRelatedValue(resource, L0.HasName);
655 public static Read<String> name(Resource resource) {
656 return new Name(resource);
659 // ------------------------------------------------------------------------
661 public static final ParametrizedRead<Resource, String> NAME = new ParametrizedRead<Resource, String>() {
664 public Read<String> get(Resource resource) {
665 return name(resource);
670 // ------------------------------------------------------------------------