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 ArrayList<TripleIntProcedure> procs;
31 public AssertedStatements(final int r1, final int r2) {
35 public static AssertedStatements newInstance(final int r1, final int r2) {
36 return new AssertedStatements(r1, r2);
39 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) {
41 AssertedStatements entry = cached != null ? cached : (AssertedStatements)provider.assertedStatementsMap.get(id(r1,r2));
44 entry = new AssertedStatements(r1, r2);
46 entry.clearResult(provider.querySupport);
47 entry.putEntry(provider);
49 provider.performForEach(graph, entry, parent, listener, procedure);
55 if(entry.isPending()) {
57 if(entry.isPending()) {
58 throw new IllegalStateException();
59 // if(entry.procs == null) entry.procs = new ArrayList<TripleIntProcedure>();
60 // entry.procs.add(procedure);
61 // provider.registerDependencies(graph, entry, parent, listener, procedure, false);
66 provider.performForEach(graph, entry, parent, listener, procedure);
73 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) {
78 final AssertedStatements entry = (AssertedStatements)provider.assertedStatementsMap.get(id(r1,r2));
80 if(parent == null && !(listener != null)) {
81 if(entry != null && entry.isReady()) {
82 entry.performFromCache(graph, provider, procedure);
87 return runner(graph, r1, r2, provider, entry, parent, listener, procedure);
92 public BinaryQuery<TripleIntProcedure> getEntry(QueryProcessor provider) {
93 return provider.assertedStatementsMap.get(id);
97 public void putEntry(QueryProcessor provider) {
98 provider.assertedStatementsMap.put(id, this);
102 final public void removeEntry(QueryProcessor provider) {
103 provider.assertedStatementsMap.remove(id);
106 void computeInheritedAssertions(ReadGraphImpl graph, int type, final int predicate, final RelationInfo ri, final QueryProcessor queryProvider, final TripleIntProcedure proc) {
108 // final AtomicBoolean found = new AtomicBoolean(0);
110 DirectObjects.queryEach(graph, type, queryProvider.getInherits(), queryProvider, this, null, new SyncIntProcedure() {
113 public void run(ReadGraphImpl graph) {
115 // if(ri.isFunctional && found.get() == 1) {
117 // ManyObjectsForFunctionalRelationException exception = new ManyObjectsForFunctionalRelationException("Functional relation has assertions from multiple inherited types.");
118 // except(exception);
119 // proc.exception(graph, exception);
124 finish(graph, queryProvider);
125 proc.finished(graph);
130 public void execute(ReadGraphImpl graph, int inh) {
132 // if(ri.isFunctional && found.get() == 1) return;
136 AssertedStatements.queryEach(graph, inh, predicate, queryProvider, AssertedStatements.this, null, new TripleIntProcedureAdapter() {
139 public void execute(ReadGraphImpl graph, int s, int p, int o) {
141 // if(ri.isFunctional) {
143 //// if(found.get() == 1) return;
145 // if(found.compareAndSet(0, o)) {
147 proc.execute(graph, s, p, o);
149 // // If this was a duplicate, we can ignore this
150 // else if (found.compareAndSet(o, o)) {
151 // //System.err.println("duplicates!");
153 // // Otherwise we have error
160 // addOrSet(s, p, o);
161 // proc.execute(graph, s, p, o);
168 public void finished(ReadGraphImpl graph) {
173 public void exception(ReadGraphImpl graph, Throwable t) {
174 proc.exception(graph, t);
183 public void finished(ReadGraphImpl graph) {
191 void computeLocalAssertions(ReadGraphImpl graph, final int type, final int predicate, final RelationInfo ri, final QueryProcessor queryProvider, final TripleIntProcedure proc) {
193 final AtomicInteger found = new AtomicInteger(0);
195 DirectObjects.queryEach(graph, type, queryProvider.getAsserts(), queryProvider, this, null, new SyncIntProcedure() {
198 public void run(ReadGraphImpl graph) {
200 if(ri.isFunctional && found.get() > 1) {
202 ManyObjectsForFunctionalRelationException exception = new ManyObjectsForFunctionalRelationException("Functional relation has more than one asserted statement.");
204 proc.exception(graph, exception);
209 if(ri.isFunctional && found.get() == 1) {
211 finish(graph, queryProvider);
212 proc.finished(graph);
217 computeInheritedAssertions(graph, type, predicate, ri, queryProvider, proc);
222 public void execute(ReadGraphImpl graph, final int ass) {
224 if(ri.isFunctional && found.get() > 1) return;
228 DirectObjects.queryEach(graph, ass, queryProvider.getHasPredicate(), queryProvider, AssertedStatements.this, null, new IntProcedure() {
231 public void execute(ReadGraphImpl graph, final int pred) {
233 if(ri.isFunctional) {
235 if(found.get() > 1) return;
239 DirectObjects.queryEach(graph, ass, queryProvider.getHasObject(), queryProvider, AssertedStatements.this, null, new IntProcedure() {
242 public void execute(ReadGraphImpl graph, final int object) {
244 if(found.get() > 1) return;
246 if(pred == predicate) {
248 if(found.getAndIncrement() == 0) {
249 if(addOrSet(type, pred, object))
250 proc.execute(graph, type, pred, object);
261 SuperRelations.queryEach(graph, pred, queryProvider, AssertedStatements.this, null, new InternalProcedure<IntSet>() {
264 public void execute(ReadGraphImpl graph, IntSet result) {
266 if(found.get() > 1) {
271 if(result.contains(predicate)) {
273 if(found.getAndIncrement() == 0) {
274 if(addOrSet(type, pred, object))
275 proc.execute(graph, type, pred, object);
285 public void exception(ReadGraphImpl graph, Throwable t) {
287 proc.exception(graph, t);
299 public void finished(ReadGraphImpl graph) {
304 public void exception(ReadGraphImpl graph, Throwable t) {
305 proc.exception(graph, t);
315 DirectObjects.queryEach(graph, ass, queryProvider.getHasObject(), queryProvider, AssertedStatements.this, null, new IntProcedure() {
318 public void execute(ReadGraphImpl graph, final int object) {
320 if(pred == predicate) {
322 addOrSet(type, pred, object);
323 proc.execute(graph, type, pred, object);
332 SuperRelations.queryEach(graph, pred, queryProvider, AssertedStatements.this, null, new InternalProcedure<IntSet>() {
335 public void execute(ReadGraphImpl graph, IntSet result) {
337 if(result.contains(predicate)) {
339 addOrSet(type, pred, object);
340 proc.execute(graph, type, pred, object);
349 public void exception(ReadGraphImpl graph, Throwable t) {
350 proc.exception(graph, t);
361 public void finished(ReadGraphImpl graph) {
366 public void exception(ReadGraphImpl graph, Throwable t) {
367 proc.exception(graph, t);
378 public void finished(ReadGraphImpl graph) {
383 public void exception(ReadGraphImpl graph, Throwable t) {
384 proc.exception(graph, t);
393 public void finished(ReadGraphImpl graph) {
402 public void computeForEach(ReadGraphImpl graph, final QueryProcessor provider, final TripleIntProcedure procedure, boolean store) {
404 RelationInfoQuery.queryEach(graph, r2(), provider, this, null, new InternalProcedure<RelationInfo>() {
407 public void execute(ReadGraphImpl graph, RelationInfo ri) {
409 computeLocalAssertions(graph, r1(), r2(), ri, provider, procedure);
414 public void exception(ReadGraphImpl graph, Throwable t) {
415 procedure.exception(graph, t);
423 public String toString() {
424 return "AssertedStatements2[" + r1() + " - " + r2() + "]";
427 private boolean addOrSet(int s, int p, int o) {
431 IntArray value = (IntArray)getResult();
432 if(value.data != null) {
433 for(int i = 0;i < value.sizeOrData ; i+=3) {
434 int existingP = value.data[i+1];
436 int existingO = value.data[i+2];
437 if(existingO == o) return false;
453 final private void finish(ReadGraphImpl graph, QueryProcessor provider) {
457 // ArrayList<TripleIntProcedure> p = null;
468 // final IntArray value = (IntArray)getResult();
469 // for(TripleIntProcedure proc : p) {
470 // for(int i=0;i<value.size();i+=3) {
471 // proc.execute(graph, value.data[i], value.data[i+1], value.data[i+2]);
475 // for(TripleIntProcedure proc : p) proc.finished(graph);
481 public void performFromCache(ReadGraphImpl graph, QueryProcessor provider, final TripleIntProcedure procedure) {
485 if(handleException(graph, procedure)) return;
487 final IntArray value = (IntArray)getResult();
488 for(int i=0;i<value.size();i+=3) {
489 procedure.execute(graph, value.data[i], value.data[i+1], value.data[i+2]);
492 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());