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.impl.query;
14 import java.util.ArrayList;
15 import java.util.concurrent.Semaphore;
16 import java.util.concurrent.atomic.AtomicInteger;
18 import org.simantics.db.RelationInfo;
19 import org.simantics.db.exception.ManyObjectsForFunctionalRelationException;
20 import org.simantics.db.impl.graph.ReadGraphImpl;
21 import org.simantics.db.impl.procedure.InternalProcedure;
22 import org.simantics.db.impl.procedure.TripleIntProcedureAdapter;
23 import org.simantics.db.procedure.ListenerBase;
24 import org.simantics.db.request.RequestFlags;
27 final public class AssertedStatements extends CollectionBinaryQuery<TripleIntProcedure> {
29 public AssertedStatements(final int r1, final int r2) {
33 public static AssertedStatements newInstance(final int r1, final int r2) {
34 return new AssertedStatements(r1, r2);
37 final static AssertedStatements runner(ReadGraphImpl graph, final int r1, final int r2, final QueryProcessor provider, final AssertedStatements cached, final CacheEntry parent, final ListenerBase listener, final TripleIntProcedure procedure) {
39 AssertedStatements entry = cached != null ? cached : (AssertedStatements)provider.cache.assertedStatementsMap.get(id(r1,r2));
42 entry = new AssertedStatements(r1, r2);
44 entry.clearResult(provider.querySupport);
45 entry.putEntry(provider);
47 provider.performForEach(graph, entry, parent, listener, procedure);
53 if(entry.isPending()) {
55 if(entry.isPending()) {
56 throw new IllegalStateException();
57 // if(entry.procs == null) entry.procs = new ArrayList<TripleIntProcedure>();
58 // entry.procs.add(procedure);
59 // provider.registerDependencies(graph, entry, parent, listener, procedure, false);
64 provider.performForEach(graph, entry, parent, listener, procedure);
71 final public static AssertedStatements queryEach(ReadGraphImpl graph, final int r1, final int r2, final QueryProcessor provider, final CacheEntry parent, final ListenerBase listener, final TripleIntProcedure procedure) {
76 final AssertedStatements entry = (AssertedStatements)provider.cache.assertedStatementsMap.get(id(r1,r2));
78 if(parent == null && !(listener != null)) {
79 if(entry != null && entry.isReady()) {
80 entry.performFromCache(graph, provider, procedure);
85 return runner(graph, r1, r2, provider, entry, parent, listener, procedure);
90 public BinaryQuery<TripleIntProcedure> getEntry(QueryProcessor provider) {
91 return provider.cache.assertedStatementsMap.get(id);
95 public void putEntry(QueryProcessor provider) {
96 provider.cache.assertedStatementsMap.put(id, this);
100 final public void removeEntry(QueryProcessor provider) {
101 provider.cache.assertedStatementsMap.remove(id);
104 void computeInheritedAssertions(ReadGraphImpl graph, int type, final int predicate, final RelationInfo ri, final QueryProcessor queryProvider, final TripleIntProcedure proc) {
106 // final AtomicBoolean found = new AtomicBoolean(0);
108 DirectObjects.queryEach(graph, type, queryProvider.getInherits(), queryProvider, this, null, new SyncIntProcedure() {
111 public void run(ReadGraphImpl graph) {
113 // if(ri.isFunctional && found.get() == 1) {
115 // ManyObjectsForFunctionalRelationException exception = new ManyObjectsForFunctionalRelationException("Functional relation has assertions from multiple inherited types.");
116 // except(exception);
117 // proc.exception(graph, exception);
122 finish(graph, queryProvider);
123 proc.finished(graph);
128 public void execute(ReadGraphImpl graph, int inh) {
130 // if(ri.isFunctional && found.get() == 1) return;
134 AssertedStatements.queryEach(graph, inh, predicate, queryProvider, AssertedStatements.this, null, new TripleIntProcedureAdapter() {
137 public void execute(ReadGraphImpl graph, int s, int p, int o) {
139 // if(ri.isFunctional) {
141 //// if(found.get() == 1) return;
143 // if(found.compareAndSet(0, o)) {
145 proc.execute(graph, s, p, o);
147 // // If this was a duplicate, we can ignore this
148 // else if (found.compareAndSet(o, o)) {
149 // //System.err.println("duplicates!");
151 // // Otherwise we have error
158 // addOrSet(s, p, o);
159 // proc.execute(graph, s, p, o);
166 public void finished(ReadGraphImpl graph) {
171 public void exception(ReadGraphImpl graph, Throwable t) {
172 proc.exception(graph, t);
181 public void finished(ReadGraphImpl graph) {
189 void computeLocalAssertions(ReadGraphImpl graph, final int type, final int predicate, final RelationInfo ri, final QueryProcessor queryProvider, final TripleIntProcedure proc) {
191 final AtomicInteger found = new AtomicInteger(0);
193 DirectObjects.queryEach(graph, type, queryProvider.getAsserts(), queryProvider, this, null, new SyncIntProcedure() {
196 public void run(ReadGraphImpl graph) {
198 if(ri.isFunctional && found.get() > 1) {
200 ManyObjectsForFunctionalRelationException exception = new ManyObjectsForFunctionalRelationException("Functional relation has more than one asserted statement.");
202 proc.exception(graph, exception);
207 if(ri.isFunctional && found.get() == 1) {
209 finish(graph, queryProvider);
210 proc.finished(graph);
215 computeInheritedAssertions(graph, type, predicate, ri, queryProvider, proc);
220 public void execute(ReadGraphImpl graph, final int ass) {
222 if(ri.isFunctional && found.get() > 1) return;
226 DirectObjects.queryEach(graph, ass, queryProvider.getHasPredicate(), queryProvider, AssertedStatements.this, null, new IntProcedure() {
229 public void execute(ReadGraphImpl graph, final int pred) {
231 if(ri.isFunctional) {
233 if(found.get() > 1) return;
237 DirectObjects.queryEach(graph, ass, queryProvider.getHasObject(), queryProvider, AssertedStatements.this, null, new IntProcedure() {
240 public void execute(ReadGraphImpl graph, final int object) {
242 if(found.get() > 1) return;
244 if(pred == predicate) {
246 if(found.getAndIncrement() == 0) {
247 if(addOrSet(type, pred, object))
248 proc.execute(graph, type, pred, object);
259 SuperRelations.queryEach(graph, pred, queryProvider, AssertedStatements.this, null, new InternalProcedure<IntSet>() {
262 public void execute(ReadGraphImpl graph, IntSet result) {
264 if(found.get() > 1) {
269 if(result.contains(predicate)) {
271 if(found.getAndIncrement() == 0) {
272 if(addOrSet(type, pred, object))
273 proc.execute(graph, type, pred, object);
283 public void exception(ReadGraphImpl graph, Throwable t) {
285 proc.exception(graph, t);
297 public void finished(ReadGraphImpl graph) {
302 public void exception(ReadGraphImpl graph, Throwable t) {
303 proc.exception(graph, t);
313 DirectObjects.queryEach(graph, ass, queryProvider.getHasObject(), queryProvider, AssertedStatements.this, null, new IntProcedure() {
316 public void execute(ReadGraphImpl graph, final int object) {
318 if(pred == predicate) {
320 addOrSet(type, pred, object);
321 proc.execute(graph, type, pred, object);
330 SuperRelations.queryEach(graph, pred, queryProvider, AssertedStatements.this, null, new InternalProcedure<IntSet>() {
333 public void execute(ReadGraphImpl graph, IntSet result) {
335 if(result.contains(predicate)) {
337 addOrSet(type, pred, object);
338 proc.execute(graph, type, pred, object);
347 public void exception(ReadGraphImpl graph, Throwable t) {
348 proc.exception(graph, t);
359 public void finished(ReadGraphImpl graph) {
364 public void exception(ReadGraphImpl graph, Throwable t) {
365 proc.exception(graph, t);
376 public void finished(ReadGraphImpl graph) {
381 public void exception(ReadGraphImpl graph, Throwable t) {
382 proc.exception(graph, t);
391 public void finished(ReadGraphImpl graph) {
400 public void computeForEach(ReadGraphImpl graph, final QueryProcessor provider, final TripleIntProcedure procedure, boolean store) {
402 RelationInfoQuery.queryEach(graph, r2(), provider, this, null, new InternalProcedure<RelationInfo>() {
405 public void execute(ReadGraphImpl graph, RelationInfo ri) {
407 computeLocalAssertions(graph, r1(), r2(), ri, provider, procedure);
412 public void exception(ReadGraphImpl graph, Throwable t) {
413 procedure.exception(graph, t);
421 public String toString() {
422 return "AssertedStatements2[" + r1() + " - " + r2() + "]";
425 private boolean addOrSet(int s, int p, int o) {
429 IntArray value = (IntArray)getResult();
430 if(value.data != null) {
431 for(int i = 0;i < value.sizeOrData ; i+=3) {
432 int existingP = value.data[i+1];
434 int existingO = value.data[i+2];
435 if(existingO == o) return false;
451 final private void finish(ReadGraphImpl graph, QueryProcessor provider) {
455 // ArrayList<TripleIntProcedure> p = null;
466 // final IntArray value = (IntArray)getResult();
467 // for(TripleIntProcedure proc : p) {
468 // for(int i=0;i<value.size();i+=3) {
469 // proc.execute(graph, value.data[i], value.data[i+1], value.data[i+2]);
473 // for(TripleIntProcedure proc : p) proc.finished(graph);
479 public Object performFromCache(ReadGraphImpl graph, QueryProcessor provider, final TripleIntProcedure procedure) {
483 if(handleException(graph, procedure)) return getResult();
485 final IntArray value = (IntArray)getResult();
486 for(int i=0;i<value.size();i+=3) {
487 procedure.execute(graph, value.data[i], value.data[i+1], value.data[i+2]);
490 procedure.finished(graph);
497 public void recompute(ReadGraphImpl graph, QueryProcessor provider) {
499 final Semaphore s = new Semaphore(0);
501 computeForEach(graph, provider, new TripleIntProcedureAdapter() {
504 public void finished(ReadGraphImpl graph) {
509 public void exception(ReadGraphImpl graph, Throwable t) {
510 throw new Error("Error in recompute", t);
517 } catch (InterruptedException e) {
525 return RequestFlags.IMMEDIATE_UPDATE;
530 boolean isImmutable(ReadGraphImpl graph) {
531 return graph.processor.isImmutable(r1());