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.concurrent.Semaphore;
15 import java.util.concurrent.atomic.AtomicInteger;
17 import org.simantics.db.RelationInfo;
18 import org.simantics.db.exception.ManyObjectsForFunctionalRelationException;
19 import org.simantics.db.impl.graph.ReadGraphImpl;
20 import org.simantics.db.impl.procedure.InternalProcedure;
21 import org.simantics.db.impl.procedure.TripleIntProcedureAdapter;
22 import org.simantics.db.procedure.ListenerBase;
23 import org.simantics.db.request.RequestFlags;
26 final public class AssertedStatements extends CollectionBinaryQuery<TripleIntProcedure> {
28 // public ArrayList<TripleIntProcedure> procs;
30 public AssertedStatements(final int r1, final int r2) {
34 public static AssertedStatements newInstance(final int r1, final int r2) {
35 return new AssertedStatements(r1, r2);
38 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) {
40 AssertedStatements entry = cached != null ? cached : (AssertedStatements)provider.assertedStatementsMap.get(id(r1,r2));
43 entry = new AssertedStatements(r1, r2);
45 entry.clearResult(provider.querySupport);
46 entry.putEntry(provider);
48 provider.performForEach(graph, entry, parent, listener, procedure);
54 if(entry.isPending()) {
56 if(entry.isPending()) {
57 throw new IllegalStateException();
58 // if(entry.procs == null) entry.procs = new ArrayList<TripleIntProcedure>();
59 // entry.procs.add(procedure);
60 // provider.registerDependencies(graph, entry, parent, listener, procedure, false);
65 provider.performForEach(graph, entry, parent, listener, procedure);
72 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) {
77 final AssertedStatements entry = (AssertedStatements)provider.assertedStatementsMap.get(id(r1,r2));
79 if(parent == null && !(listener != null)) {
80 if(entry != null && entry.isReady()) {
81 entry.performFromCache(graph, provider, procedure);
86 return runner(graph, r1, r2, provider, entry, parent, listener, procedure);
91 public BinaryQuery<TripleIntProcedure> getEntry(QueryProcessor provider) {
92 return provider.assertedStatementsMap.get(id);
96 public void putEntry(QueryProcessor provider) {
97 provider.assertedStatementsMap.put(id, this);
101 final public void removeEntry(QueryProcessor provider) {
102 provider.assertedStatementsMap.remove(id);
105 void computeInheritedAssertions(ReadGraphImpl graph, int type, final int predicate, final RelationInfo ri, final QueryProcessor queryProvider, final TripleIntProcedure proc) {
107 // final AtomicBoolean found = new AtomicBoolean(0);
109 DirectObjects.queryEach(graph, type, queryProvider.getInherits(), queryProvider, this, null, new SyncIntProcedure() {
112 public void run(ReadGraphImpl graph) {
114 // if(ri.isFunctional && found.get() == 1) {
116 // ManyObjectsForFunctionalRelationException exception = new ManyObjectsForFunctionalRelationException("Functional relation has assertions from multiple inherited types.");
117 // except(exception);
118 // proc.exception(graph, exception);
123 finish(graph, queryProvider);
124 proc.finished(graph);
129 public void execute(ReadGraphImpl graph, int inh) {
131 // if(ri.isFunctional && found.get() == 1) return;
135 AssertedStatements.queryEach(graph, inh, predicate, queryProvider, AssertedStatements.this, null, new TripleIntProcedureAdapter() {
138 public void execute(ReadGraphImpl graph, int s, int p, int o) {
140 // if(ri.isFunctional) {
142 //// if(found.get() == 1) return;
144 // if(found.compareAndSet(0, o)) {
146 proc.execute(graph, s, p, o);
148 // // If this was a duplicate, we can ignore this
149 // else if (found.compareAndSet(o, o)) {
150 // //System.err.println("duplicates!");
152 // // Otherwise we have error
159 // addOrSet(s, p, o);
160 // proc.execute(graph, s, p, o);
167 public void finished(ReadGraphImpl graph) {
172 public void exception(ReadGraphImpl graph, Throwable t) {
173 proc.exception(graph, t);
182 public void finished(ReadGraphImpl graph) {
190 void computeLocalAssertions(ReadGraphImpl graph, final int type, final int predicate, final RelationInfo ri, final QueryProcessor queryProvider, final TripleIntProcedure proc) {
192 final AtomicInteger found = new AtomicInteger(0);
194 DirectObjects.queryEach(graph, type, queryProvider.getAsserts(), queryProvider, this, null, new SyncIntProcedure() {
197 public void run(ReadGraphImpl graph) {
199 if(ri.isFunctional && found.get() > 1) {
201 ManyObjectsForFunctionalRelationException exception = new ManyObjectsForFunctionalRelationException("Functional relation has more than one asserted statement.");
203 proc.exception(graph, exception);
208 if(ri.isFunctional && found.get() == 1) {
210 finish(graph, queryProvider);
211 proc.finished(graph);
216 computeInheritedAssertions(graph, type, predicate, ri, queryProvider, proc);
221 public void execute(ReadGraphImpl graph, final int ass) {
223 if(ri.isFunctional && found.get() > 1) return;
227 DirectObjects.queryEach(graph, ass, queryProvider.getHasPredicate(), queryProvider, AssertedStatements.this, null, new IntProcedure() {
230 public void execute(ReadGraphImpl graph, final int pred) {
232 if(ri.isFunctional) {
234 if(found.get() > 1) return;
238 DirectObjects.queryEach(graph, ass, queryProvider.getHasObject(), queryProvider, AssertedStatements.this, null, new IntProcedure() {
241 public void execute(ReadGraphImpl graph, final int object) {
243 if(found.get() > 1) return;
245 if(pred == predicate) {
247 if(found.getAndIncrement() == 0) {
248 if(addOrSet(type, pred, object))
249 proc.execute(graph, type, pred, object);
260 SuperRelations.queryEach(graph, pred, queryProvider, AssertedStatements.this, null, new InternalProcedure<IntSet>() {
263 public void execute(ReadGraphImpl graph, IntSet result) {
265 if(found.get() > 1) {
270 if(result.contains(predicate)) {
272 if(found.getAndIncrement() == 0) {
273 if(addOrSet(type, pred, object))
274 proc.execute(graph, type, pred, object);
284 public void exception(ReadGraphImpl graph, Throwable t) {
286 proc.exception(graph, t);
298 public void finished(ReadGraphImpl graph) {
303 public void exception(ReadGraphImpl graph, Throwable t) {
304 proc.exception(graph, t);
314 DirectObjects.queryEach(graph, ass, queryProvider.getHasObject(), queryProvider, AssertedStatements.this, null, new IntProcedure() {
317 public void execute(ReadGraphImpl graph, final int object) {
319 if(pred == predicate) {
321 addOrSet(type, pred, object);
322 proc.execute(graph, type, pred, object);
331 SuperRelations.queryEach(graph, pred, queryProvider, AssertedStatements.this, null, new InternalProcedure<IntSet>() {
334 public void execute(ReadGraphImpl graph, IntSet result) {
336 if(result.contains(predicate)) {
338 addOrSet(type, pred, object);
339 proc.execute(graph, type, pred, object);
348 public void exception(ReadGraphImpl graph, Throwable t) {
349 proc.exception(graph, t);
360 public void finished(ReadGraphImpl graph) {
365 public void exception(ReadGraphImpl graph, Throwable t) {
366 proc.exception(graph, t);
377 public void finished(ReadGraphImpl graph) {
382 public void exception(ReadGraphImpl graph, Throwable t) {
383 proc.exception(graph, t);
392 public void finished(ReadGraphImpl graph) {
401 public void computeForEach(ReadGraphImpl graph, final QueryProcessor provider, final TripleIntProcedure procedure, boolean store) {
403 RelationInfoQuery.queryEach(graph, r2(), provider, this, null, new InternalProcedure<RelationInfo>() {
406 public void execute(ReadGraphImpl graph, RelationInfo ri) {
408 computeLocalAssertions(graph, r1(), r2(), ri, provider, procedure);
413 public void exception(ReadGraphImpl graph, Throwable t) {
414 procedure.exception(graph, t);
422 public String toString() {
423 return "AssertedStatements2[" + r1() + " - " + r2() + "]";
426 private boolean addOrSet(int s, int p, int o) {
430 IntArray value = (IntArray)getResult();
431 if(value.data != null) {
432 for(int i = 0;i < value.sizeOrData ; i+=3) {
433 int existingP = value.data[i+1];
435 int existingO = value.data[i+2];
436 if(existingO == o) return false;
452 final private void finish(ReadGraphImpl graph, QueryProcessor provider) {
456 // ArrayList<TripleIntProcedure> p = null;
467 // final IntArray value = (IntArray)getResult();
468 // for(TripleIntProcedure proc : p) {
469 // for(int i=0;i<value.size();i+=3) {
470 // proc.execute(graph, value.data[i], value.data[i+1], value.data[i+2]);
474 // for(TripleIntProcedure proc : p) proc.finished(graph);
480 public void performFromCache(ReadGraphImpl graph, QueryProcessor provider, final TripleIntProcedure procedure) {
484 if(handleException(graph, procedure)) return;
486 final IntArray value = (IntArray)getResult();
487 for(int i=0;i<value.size();i+=3) {
488 procedure.execute(graph, value.data[i], value.data[i+1], value.data[i+2]);
491 procedure.finished(graph);
496 public void recompute(ReadGraphImpl graph, QueryProcessor provider) {
498 final Semaphore s = new Semaphore(0);
500 computeForEach(graph, provider, new TripleIntProcedureAdapter() {
503 public void finished(ReadGraphImpl graph) {
508 public void exception(ReadGraphImpl graph, Throwable t) {
509 throw new Error("Error in recompute", t);
516 } catch (InterruptedException e) {
524 return RequestFlags.IMMEDIATE_UPDATE;
529 boolean isImmutable(ReadGraphImpl graph) {
530 return graph.processor.isImmutable(r1());