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 AssertedStatements(final int r1, final int r2) {
32 public static AssertedStatements newInstance(final int r1, final int r2) {
33 return new AssertedStatements(r1, r2);
36 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) {
38 AssertedStatements entry = cached != null ? cached : (AssertedStatements)provider.cache.assertedStatementsMap.get(id(r1,r2));
41 entry = new AssertedStatements(r1, r2);
43 entry.clearResult(provider.querySupport);
44 entry.putEntry(provider);
46 provider.performForEach(graph, entry, parent, listener, procedure);
52 if(entry.isPending()) {
54 if(entry.isPending()) {
55 throw new IllegalStateException();
56 // if(entry.procs == null) entry.procs = new ArrayList<TripleIntProcedure>();
57 // entry.procs.add(procedure);
58 // provider.registerDependencies(graph, entry, parent, listener, procedure, false);
63 provider.performForEach(graph, entry, parent, listener, procedure);
70 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) {
75 final AssertedStatements entry = (AssertedStatements)provider.cache.assertedStatementsMap.get(id(r1,r2));
77 if(parent == null && !(listener != null)) {
78 if(entry != null && entry.isReady()) {
79 entry.performFromCache(graph, provider, procedure);
84 return runner(graph, r1, r2, provider, entry, parent, listener, procedure);
89 public BinaryQuery<TripleIntProcedure> getEntry(QueryProcessor provider) {
90 return provider.cache.assertedStatementsMap.get(id);
94 public void putEntry(QueryProcessor provider) {
95 provider.cache.assertedStatementsMap.put(id, this);
99 final public void removeEntry(QueryProcessor provider) {
100 provider.cache.assertedStatementsMap.remove(id);
103 void computeInheritedAssertions(ReadGraphImpl graph, int type, final int predicate, final RelationInfo ri, final QueryProcessor queryProvider, final TripleIntProcedure proc) {
105 // final AtomicBoolean found = new AtomicBoolean(0);
107 DirectObjects.queryEach(graph, type, queryProvider.getInherits(), queryProvider, this, null, new SyncIntProcedure() {
110 public void run(ReadGraphImpl graph) {
112 // if(ri.isFunctional && found.get() == 1) {
114 // ManyObjectsForFunctionalRelationException exception = new ManyObjectsForFunctionalRelationException("Functional relation has assertions from multiple inherited types.");
115 // except(exception);
116 // proc.exception(graph, exception);
121 finish(graph, queryProvider);
122 proc.finished(graph);
127 public void execute(ReadGraphImpl graph, int inh) {
129 // if(ri.isFunctional && found.get() == 1) return;
133 AssertedStatements.queryEach(graph, inh, predicate, queryProvider, AssertedStatements.this, null, new TripleIntProcedureAdapter() {
136 public void execute(ReadGraphImpl graph, int s, int p, int o) {
138 // if(ri.isFunctional) {
140 //// if(found.get() == 1) return;
142 // if(found.compareAndSet(0, o)) {
144 proc.execute(graph, s, p, o);
146 // // If this was a duplicate, we can ignore this
147 // else if (found.compareAndSet(o, o)) {
148 // //System.err.println("duplicates!");
150 // // Otherwise we have error
157 // addOrSet(s, p, o);
158 // proc.execute(graph, s, p, o);
165 public void finished(ReadGraphImpl graph) {
170 public void exception(ReadGraphImpl graph, Throwable t) {
171 proc.exception(graph, t);
180 public void finished(ReadGraphImpl graph) {
188 void computeLocalAssertions(ReadGraphImpl graph, final int type, final int predicate, final RelationInfo ri, final QueryProcessor queryProvider, final TripleIntProcedure proc) {
190 final AtomicInteger found = new AtomicInteger(0);
192 DirectObjects.queryEach(graph, type, queryProvider.getAsserts(), queryProvider, this, null, new SyncIntProcedure() {
195 public void run(ReadGraphImpl graph) {
197 if(ri.isFunctional && found.get() > 1) {
199 ManyObjectsForFunctionalRelationException exception = new ManyObjectsForFunctionalRelationException("Functional relation has more than one asserted statement.");
201 proc.exception(graph, exception);
206 if(ri.isFunctional && found.get() == 1) {
208 finish(graph, queryProvider);
209 proc.finished(graph);
214 computeInheritedAssertions(graph, type, predicate, ri, queryProvider, proc);
219 public void execute(ReadGraphImpl graph, final int ass) {
221 if(ri.isFunctional && found.get() > 1) return;
225 DirectObjects.queryEach(graph, ass, queryProvider.getHasPredicate(), queryProvider, AssertedStatements.this, null, new IntProcedure() {
228 public void execute(ReadGraphImpl graph, final int pred) {
230 if(ri.isFunctional) {
232 if(found.get() > 1) return;
236 DirectObjects.queryEach(graph, ass, queryProvider.getHasObject(), queryProvider, AssertedStatements.this, null, new IntProcedure() {
239 public void execute(ReadGraphImpl graph, final int object) {
241 if(found.get() > 1) return;
243 if(pred == predicate) {
245 if(found.getAndIncrement() == 0) {
246 if(addOrSet(type, pred, object))
247 proc.execute(graph, type, pred, object);
258 SuperRelations.queryEach(graph, pred, queryProvider, AssertedStatements.this, null, new InternalProcedure<IntSet>() {
261 public void execute(ReadGraphImpl graph, IntSet result) {
263 if(found.get() > 1) {
268 if(result.contains(predicate)) {
270 if(found.getAndIncrement() == 0) {
271 if(addOrSet(type, pred, object))
272 proc.execute(graph, type, pred, object);
282 public void exception(ReadGraphImpl graph, Throwable t) {
284 proc.exception(graph, t);
296 public void finished(ReadGraphImpl graph) {
301 public void exception(ReadGraphImpl graph, Throwable t) {
302 proc.exception(graph, t);
312 DirectObjects.queryEach(graph, ass, queryProvider.getHasObject(), queryProvider, AssertedStatements.this, null, new IntProcedure() {
315 public void execute(ReadGraphImpl graph, final int object) {
317 if(pred == predicate) {
319 addOrSet(type, pred, object);
320 proc.execute(graph, type, pred, object);
329 SuperRelations.queryEach(graph, pred, queryProvider, AssertedStatements.this, null, new InternalProcedure<IntSet>() {
332 public void execute(ReadGraphImpl graph, IntSet result) {
334 if(result.contains(predicate)) {
336 addOrSet(type, pred, object);
337 proc.execute(graph, type, pred, object);
346 public void exception(ReadGraphImpl graph, Throwable t) {
347 proc.exception(graph, t);
358 public void finished(ReadGraphImpl graph) {
363 public void exception(ReadGraphImpl graph, Throwable t) {
364 proc.exception(graph, t);
375 public void finished(ReadGraphImpl graph) {
380 public void exception(ReadGraphImpl graph, Throwable t) {
381 proc.exception(graph, t);
390 public void finished(ReadGraphImpl graph) {
399 public void computeForEach(ReadGraphImpl graph, final QueryProcessor provider, final TripleIntProcedure procedure, boolean store) {
401 RelationInfoQuery.queryEach(graph, r2(), provider, this, null, new InternalProcedure<RelationInfo>() {
404 public void execute(ReadGraphImpl graph, RelationInfo ri) {
406 computeLocalAssertions(graph, r1(), r2(), ri, provider, procedure);
411 public void exception(ReadGraphImpl graph, Throwable t) {
412 procedure.exception(graph, t);
420 public String toString() {
421 return "AssertedStatements2[" + r1() + " - " + r2() + "]";
424 private boolean addOrSet(int s, int p, int o) {
428 IntArray value = (IntArray)getResult();
429 if(value.data != null) {
430 for(int i = 0;i < value.sizeOrData ; i+=3) {
431 int existingP = value.data[i+1];
433 int existingO = value.data[i+2];
434 if(existingO == o) return false;
450 final private void finish(ReadGraphImpl graph, QueryProcessor provider) {
454 // ArrayList<TripleIntProcedure> p = null;
465 // final IntArray value = (IntArray)getResult();
466 // for(TripleIntProcedure proc : p) {
467 // for(int i=0;i<value.size();i+=3) {
468 // proc.execute(graph, value.data[i], value.data[i+1], value.data[i+2]);
472 // for(TripleIntProcedure proc : p) proc.finished(graph);
478 public Object performFromCache(ReadGraphImpl graph, QueryProcessor provider, final TripleIntProcedure procedure) {
482 if(handleException(graph, procedure)) return getResult();
484 final IntArray value = (IntArray)getResult();
485 for(int i=0;i<value.size();i+=3) {
486 procedure.execute(graph, value.data[i], value.data[i+1], value.data[i+2]);
489 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());