1 /*******************************************************************************
\r
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
\r
3 * in Industry THTH ry.
\r
4 * All rights reserved. This program and the accompanying materials
\r
5 * are made available under the terms of the Eclipse Public License v1.0
\r
6 * which accompanies this distribution, and is available at
\r
7 * http://www.eclipse.org/legal/epl-v10.html
\r
10 * VTT Technical Research Centre of Finland - initial API and implementation
\r
11 *******************************************************************************/
\r
12 package org.simantics.db.impl.query;
\r
14 import java.util.ArrayList;
\r
15 import java.util.concurrent.Semaphore;
\r
16 import java.util.concurrent.atomic.AtomicInteger;
\r
18 import org.simantics.db.RelationInfo;
\r
19 import org.simantics.db.exception.ManyObjectsForFunctionalRelationException;
\r
20 import org.simantics.db.impl.graph.ReadGraphImpl;
\r
21 import org.simantics.db.impl.procedure.InternalProcedure;
\r
22 import org.simantics.db.impl.procedure.TripleIntProcedureAdapter;
\r
23 import org.simantics.db.procedure.ListenerBase;
\r
24 import org.simantics.db.request.RequestFlags;
\r
27 final public class AssertedStatements extends CollectionBinaryQuery<TripleIntProcedure> {
\r
29 // public ArrayList<TripleIntProcedure> procs;
\r
31 public AssertedStatements(final int r1, final int r2) {
\r
35 public static AssertedStatements newInstance(final int r1, final int r2) {
\r
36 return new AssertedStatements(r1, r2);
\r
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) {
\r
41 AssertedStatements entry = cached != null ? cached : (AssertedStatements)provider.assertedStatementsMap.get(id(r1,r2));
\r
44 entry = new AssertedStatements(r1, r2);
\r
46 entry.clearResult(provider.querySupport);
\r
47 entry.putEntry(provider);
\r
49 provider.performForEach(graph, entry, parent, listener, procedure);
\r
55 if(entry.isPending()) {
\r
56 synchronized(entry) {
\r
57 if(entry.isPending()) {
\r
58 throw new IllegalStateException();
\r
59 // if(entry.procs == null) entry.procs = new ArrayList<TripleIntProcedure>();
\r
60 // entry.procs.add(procedure);
\r
61 // provider.registerDependencies(graph, entry, parent, listener, procedure, false);
\r
66 provider.performForEach(graph, entry, parent, listener, procedure);
\r
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) {
\r
78 final AssertedStatements entry = (AssertedStatements)provider.assertedStatementsMap.get(id(r1,r2));
\r
80 if(parent == null && !(listener != null)) {
\r
81 if(entry != null && entry.isReady()) {
\r
82 entry.performFromCache(graph, provider, procedure);
\r
87 return runner(graph, r1, r2, provider, entry, parent, listener, procedure);
\r
92 public BinaryQuery<TripleIntProcedure> getEntry(QueryProcessor provider) {
\r
93 return provider.assertedStatementsMap.get(id);
\r
97 public void putEntry(QueryProcessor provider) {
\r
98 provider.assertedStatementsMap.put(id, this);
\r
102 final public void removeEntry(QueryProcessor provider) {
\r
103 provider.assertedStatementsMap.remove(id);
\r
106 void computeInheritedAssertions(ReadGraphImpl graph, int type, final int predicate, final RelationInfo ri, final QueryProcessor queryProvider, final TripleIntProcedure proc) {
\r
108 // final AtomicBoolean found = new AtomicBoolean(0);
\r
110 DirectObjects.queryEach(graph, type, queryProvider.getInherits(), queryProvider, this, null, new SyncIntProcedure() {
\r
113 public void run(ReadGraphImpl graph) {
\r
115 // if(ri.isFunctional && found.get() == 1) {
\r
117 // ManyObjectsForFunctionalRelationException exception = new ManyObjectsForFunctionalRelationException("Functional relation has assertions from multiple inherited types.");
\r
118 // except(exception);
\r
119 // proc.exception(graph, exception);
\r
124 finish(graph, queryProvider);
\r
125 proc.finished(graph);
\r
130 public void execute(ReadGraphImpl graph, int inh) {
\r
132 // if(ri.isFunctional && found.get() == 1) return;
\r
136 AssertedStatements.queryEach(graph, inh, predicate, queryProvider, AssertedStatements.this, null, new TripleIntProcedureAdapter() {
\r
139 public void execute(ReadGraphImpl graph, int s, int p, int o) {
\r
141 // if(ri.isFunctional) {
\r
143 //// if(found.get() == 1) return;
\r
145 // if(found.compareAndSet(0, o)) {
\r
146 if(addOrSet(s,p,o))
\r
147 proc.execute(graph, s, p, o);
\r
149 // // If this was a duplicate, we can ignore this
\r
150 // else if (found.compareAndSet(o, o)) {
\r
151 // //System.err.println("duplicates!");
\r
153 // // Otherwise we have error
\r
160 // addOrSet(s, p, o);
\r
161 // proc.execute(graph, s, p, o);
\r
168 public void finished(ReadGraphImpl graph) {
\r
173 public void exception(ReadGraphImpl graph, Throwable t) {
\r
174 proc.exception(graph, t);
\r
183 public void finished(ReadGraphImpl graph) {
\r
191 void computeLocalAssertions(ReadGraphImpl graph, final int type, final int predicate, final RelationInfo ri, final QueryProcessor queryProvider, final TripleIntProcedure proc) {
\r
193 final AtomicInteger found = new AtomicInteger(0);
\r
195 DirectObjects.queryEach(graph, type, queryProvider.getAsserts(), queryProvider, this, null, new SyncIntProcedure() {
\r
198 public void run(ReadGraphImpl graph) {
\r
200 if(ri.isFunctional && found.get() > 1) {
\r
202 ManyObjectsForFunctionalRelationException exception = new ManyObjectsForFunctionalRelationException("Functional relation has more than one asserted statement.");
\r
204 proc.exception(graph, exception);
\r
209 if(ri.isFunctional && found.get() == 1) {
\r
211 finish(graph, queryProvider);
\r
212 proc.finished(graph);
\r
217 computeInheritedAssertions(graph, type, predicate, ri, queryProvider, proc);
\r
222 public void execute(ReadGraphImpl graph, final int ass) {
\r
224 if(ri.isFunctional && found.get() > 1) return;
\r
228 DirectObjects.queryEach(graph, ass, queryProvider.getHasPredicate(), queryProvider, AssertedStatements.this, null, new IntProcedure() {
\r
231 public void execute(ReadGraphImpl graph, final int pred) {
\r
233 if(ri.isFunctional) {
\r
235 if(found.get() > 1) return;
\r
239 DirectObjects.queryEach(graph, ass, queryProvider.getHasObject(), queryProvider, AssertedStatements.this, null, new IntProcedure() {
\r
242 public void execute(ReadGraphImpl graph, final int object) {
\r
244 if(found.get() > 1) return;
\r
246 if(pred == predicate) {
\r
248 if(found.getAndIncrement() == 0) {
\r
249 if(addOrSet(type, pred, object))
\r
250 proc.execute(graph, type, pred, object);
\r
257 if ( !ri.isFinal ) {
\r
261 SuperRelations.queryEach(graph, pred, queryProvider, AssertedStatements.this, null, new InternalProcedure<IntSet>() {
\r
264 public void execute(ReadGraphImpl graph, IntSet result) {
\r
266 if(found.get() > 1) {
\r
271 if(result.contains(predicate)) {
\r
273 if(found.getAndIncrement() == 0) {
\r
274 if(addOrSet(type, pred, object))
\r
275 proc.execute(graph, type, pred, object);
\r
285 public void exception(ReadGraphImpl graph, Throwable t) {
\r
287 proc.exception(graph, t);
\r
299 public void finished(ReadGraphImpl graph) {
\r
304 public void exception(ReadGraphImpl graph, Throwable t) {
\r
305 proc.exception(graph, t);
\r
315 DirectObjects.queryEach(graph, ass, queryProvider.getHasObject(), queryProvider, AssertedStatements.this, null, new IntProcedure() {
\r
318 public void execute(ReadGraphImpl graph, final int object) {
\r
320 if(pred == predicate) {
\r
322 addOrSet(type, pred, object);
\r
323 proc.execute(graph, type, pred, object);
\r
328 if ( !ri.isFinal ) {
\r
332 SuperRelations.queryEach(graph, pred, queryProvider, AssertedStatements.this, null, new InternalProcedure<IntSet>() {
\r
335 public void execute(ReadGraphImpl graph, IntSet result) {
\r
337 if(result.contains(predicate)) {
\r
339 addOrSet(type, pred, object);
\r
340 proc.execute(graph, type, pred, object);
\r
349 public void exception(ReadGraphImpl graph, Throwable t) {
\r
350 proc.exception(graph, t);
\r
361 public void finished(ReadGraphImpl graph) {
\r
366 public void exception(ReadGraphImpl graph, Throwable t) {
\r
367 proc.exception(graph, t);
\r
378 public void finished(ReadGraphImpl graph) {
\r
383 public void exception(ReadGraphImpl graph, Throwable t) {
\r
384 proc.exception(graph, t);
\r
393 public void finished(ReadGraphImpl graph) {
\r
402 public void computeForEach(ReadGraphImpl graph, final QueryProcessor provider, final TripleIntProcedure procedure, boolean store) {
\r
404 RelationInfoQuery.queryEach(graph, r2(), provider, this, null, new InternalProcedure<RelationInfo>() {
\r
407 public void execute(ReadGraphImpl graph, RelationInfo ri) {
\r
409 computeLocalAssertions(graph, r1(), r2(), ri, provider, procedure);
\r
414 public void exception(ReadGraphImpl graph, Throwable t) {
\r
415 procedure.exception(graph, t);
\r
423 public String toString() {
\r
424 return "AssertedStatements2[" + r1() + " - " + r2() + "]";
\r
427 private boolean addOrSet(int s, int p, int o) {
\r
429 assert(isPending());
\r
431 IntArray value = (IntArray)getResult();
\r
432 if(value.data != null) {
\r
433 for(int i = 0;i < value.sizeOrData ; i+=3) {
\r
434 int existingP = value.data[i+1];
\r
435 if(p == existingP) {
\r
436 int existingO = value.data[i+2];
\r
437 if(existingO == o) return false;
\r
453 final private void finish(ReadGraphImpl graph, QueryProcessor provider) {
\r
455 assert(isPending());
\r
457 // ArrayList<TripleIntProcedure> p = null;
\r
459 synchronized(this) {
\r
468 // final IntArray value = (IntArray)getResult();
\r
469 // for(TripleIntProcedure proc : p) {
\r
470 // for(int i=0;i<value.size();i+=3) {
\r
471 // proc.execute(graph, value.data[i], value.data[i+1], value.data[i+2]);
\r
475 // for(TripleIntProcedure proc : p) proc.finished(graph);
\r
481 public void performFromCache(ReadGraphImpl graph, QueryProcessor provider, final TripleIntProcedure procedure) {
\r
485 if(handleException(graph, procedure)) return;
\r
487 final IntArray value = (IntArray)getResult();
\r
488 for(int i=0;i<value.size();i+=3) {
\r
489 procedure.execute(graph, value.data[i], value.data[i+1], value.data[i+2]);
\r
492 procedure.finished(graph);
\r
497 public void recompute(ReadGraphImpl graph, QueryProcessor provider) {
\r
499 final Semaphore s = new Semaphore(0);
\r
501 computeForEach(graph, provider, new TripleIntProcedureAdapter() {
\r
504 public void finished(ReadGraphImpl graph) {
\r
509 public void exception(ReadGraphImpl graph, Throwable t) {
\r
510 throw new Error("Error in recompute", t);
\r
517 } catch (InterruptedException e) {
\r
518 throw new Error(e);
\r
524 public int type() {
\r
525 return RequestFlags.IMMEDIATE_UPDATE;
\r
530 boolean isImmutable(ReadGraphImpl graph) {
\r
531 return graph.processor.isImmutable(r1());
\r