/******************************************************************************* * 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 subject; Resource relation; public Objects(Resource subject, Resource relation) { this.subject = subject; this.relation = relation; } @Override public void perform(ReadGraph graph, SyncMultiProcedure 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 objects(Resource subject, Resource relation) { return new Objects(subject, relation); } // ------------------------------------------------------------------------ private static class Relation implements ParametrizedMultiRead { Resource relation; public Relation(Resource relation) { this.relation = relation; } @Override public MultiRead 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 subject -> objects(subject, relation). */ public static ParametrizedMultiRead relation(Resource relation) { return new Relation(relation); } // ------------------------------------------------------------------------ public static class SynchronizationProcedure implements Procedure { 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 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 possibleObject(Resource subject, Resource relation) { return new PossibleObject(subject, relation); } // ------------------------------------------------------------------------ private static class PartialFunction implements ParametrizedRead { Resource relation; public PartialFunction(Resource relation) { this.relation = relation; } @Override public Read 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 subject -> possibleObject(subject, relation). */ public static ParametrizedRead partialFunction(Resource relation) { return new PartialFunction(relation); } // ------------------------------------------------------------------------ private static class SingleObject implements Read { 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 singleObject(Resource subject, Resource relation) { return new SingleObject(subject, relation); } // ------------------------------------------------------------------------ private static class CompleteFunction implements ParametrizedRead { Resource relation; public CompleteFunction(Resource relation) { this.relation = relation; } @Override public Read 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 subject -> singleObject(subject, relation). */ public static ParametrizedRead completeFunction(Resource relation) { return new CompleteFunction(relation); } // ------------------------------------------------------------------------ private static class Compose1 implements Read { final ParametrizedRead f; final Read g; public Compose1(ParametrizedRead f, Read 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 Read compose(ParametrizedRead f, Read g) { return new Compose1(f, g); } // ------------------------------------------------------------------------ private static class Compose2 implements ParametrizedRead { final ParametrizedRead f; final ParametrizedRead g; public Compose2(ParametrizedRead f, ParametrizedRead g) { this.f = f; this.g = g; } public Read 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 ParametrizedRead compose(ParametrizedRead f, ParametrizedRead g) { return new Compose2(f, g); } // ------------------------------------------------------------------------ private static class Compose3 implements MultiRead { final ParametrizedRead f; final MultiRead g; public Compose3(ParametrizedRead f, MultiRead g) { this.f = f; this.g = g; } public void perform(ReadGraph graph, final SyncMultiProcedure 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() { @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 MultiRead compose(ParametrizedRead f, MultiRead g) { return new Compose3(f, g); } // ------------------------------------------------------------------------ private static class Compose4 implements ParametrizedMultiRead { final ParametrizedRead f; final ParametrizedMultiRead g; public Compose4(ParametrizedRead f, ParametrizedMultiRead g) { this.f = f; this.g = g; } public MultiRead 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 ParametrizedMultiRead compose(ParametrizedRead f, ParametrizedMultiRead g) { return new Compose4(f, g); } // ------------------------------------------------------------------------ private static class Compose5 implements MultiRead { final ParametrizedMultiRead f; final Read g; public Compose5(ParametrizedMultiRead f, Read g) { this.f = f; this.g = g; } @Override public void perform(ReadGraph graph, SyncMultiProcedure 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 MultiRead compose(ParametrizedMultiRead f, Read g) { return new Compose5(f, g); } // ------------------------------------------------------------------------ private static class Compose6 implements ParametrizedMultiRead { final ParametrizedMultiRead f; final ParametrizedRead g; public Compose6(ParametrizedMultiRead f, ParametrizedRead g) { this.f = f; this.g = g; } public MultiRead 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 ParametrizedMultiRead compose(ParametrizedMultiRead f, ParametrizedRead g) { return new Compose6(f, g); } // ------------------------------------------------------------------------ private static class Compose7 implements MultiRead { final ParametrizedMultiRead f; final MultiRead g; public Compose7(ParametrizedMultiRead f, MultiRead g) { this.f = f; this.g = g; } public void perform(ReadGraph graph, final SyncMultiProcedure 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() { @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 MultiRead compose(ParametrizedMultiRead f, MultiRead g) { return new Compose7(f, g); } // ------------------------------------------------------------------------ private static class Compose8 implements ParametrizedMultiRead { final ParametrizedMultiRead f; final ParametrizedMultiRead g; public Compose8(ParametrizedMultiRead f, ParametrizedMultiRead g) { this.f = f; this.g = g; } public MultiRead 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 ParametrizedMultiRead compose(ParametrizedMultiRead f, ParametrizedMultiRead g) { return new Compose8(f, g); } // ------------------------------------------------------------------------ private static class Index implements Read> { final MultiRead values; final ParametrizedRead keyOfValue; public Index(MultiRead values, ParametrizedRead keyOfValue) { this.values = values; this.keyOfValue = keyOfValue; } @Override public Map perform(ReadGraph graph) throws DatabaseException { HashMap result = new HashMap(); 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 Read> index(MultiRead values, ParametrizedRead keyOfValue) { return new Index(values, keyOfValue); } // ------------------------------------------------------------------------ private static class Constant implements Read { 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 Read constant(T value) { return new Constant(value); } // ------------------------------------------------------------------------ private static class Singleton implements MultiRead { T value; public Singleton(T value) { this.value = value; } @Override public void perform(ReadGraph graph, SyncMultiProcedure 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 MultiRead singleton(T value) { return new Singleton(value); } // ------------------------------------------------------------------------ private static class Name extends ResourceRead { 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 name(Resource resource) { return new Name(resource); } // ------------------------------------------------------------------------ public static final ParametrizedRead NAME = new ParametrizedRead() { @Override public Read get(Resource resource) { return name(resource); } }; // ------------------------------------------------------------------------ }