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 org.simantics.db.RelationInfo;
15 import org.simantics.db.Resource;
16 import org.simantics.db.common.exception.DebugException;
17 import org.simantics.db.exception.DatabaseException;
18 import org.simantics.db.exception.ManyObjectsForFunctionalRelationException;
19 import org.simantics.db.impl.graph.ReadGraphImpl;
20 import org.simantics.db.impl.procedure.IntProcedureAdapter;
21 import org.simantics.db.impl.procedure.InternalProcedure;
22 import org.simantics.db.procedure.AsyncMultiProcedure;
23 import org.simantics.db.request.RequestFlags;
29 * statusOrException 4 byte
31 * p2OrParents = 4 byte
38 final public class Objects extends CollectionBinaryQuery<IntProcedure> implements IntProcedure {
40 public Objects(final int r1, final int r2) {
45 final public void removeEntry(QueryProcessor provider) {
46 provider.cache.remove(this);
49 final static private IntArray getAssertionMap(ReadGraphImpl graph, final int r1, final int r2, final Objects entry) throws DatabaseException {
51 class AssertionMapProc implements IntProcedure {
55 private IntArray result;
57 public void addStatement(int s, int p, int o) {
59 if(result.size() == 0) {
64 for(int i = 0;i < result.sizeOrData ; i+=3) {
65 int existingP = result.data[i+1];
67 int existingO = result.data[i+2];
68 if(existingO == o) return;
79 public void execute(ReadGraphImpl graph, int type) throws DatabaseException {
81 result = QueryCacheBase.resultAssertedStatements(graph, type, r2, entry, null);
85 result = new IntArray();
87 for(int i = 0;i < ia.sizeOrData ; i+=3) addStatement(ia.data[i],ia.data[i+1],ia.data[i+2]);
91 IntArray ia = QueryCacheBase.resultAssertedStatements(graph, type, r2, entry, null);
93 for(int i = 0;i < ia.sizeOrData ; i+=3) addStatement(ia.data[i],ia.data[i+1],ia.data[i+2]);
99 public void finished(ReadGraphImpl graph) {
103 public void exception(ReadGraphImpl graph, Throwable throwable) {
108 AssertionMapProc amp = new AssertionMapProc();
110 // This dependency could be cut
111 QueryCache.runnerPrincipalTypes(graph, r1, entry, null, amp);
117 final static private void forSingleAssertion(ReadGraphImpl graph, final int r1, final int r2, final Objects parent, final IntProcedure procedure) throws DatabaseException {
119 IntArray map = getAssertionMap(graph, r1, r2, parent);
121 procedure.finished(graph);
125 int size = map.size();
127 int value = map.data[2];
128 procedure.execute(graph, value);
129 procedure.finished(graph);
130 } else if(size == 0) {
131 procedure.finished(graph);
134 int candidateS = map.data[0];
135 int candidateO = map.data[2];
137 IntSet candidateIs = null;
139 candidateIs = QueryCache.resultSuperTypes(graph, candidateS, parent, null);
140 } catch (DatabaseException e) {
141 procedure.exception(graph, e);
145 for(int i=3;i<map.size();i+=3) {
147 int nextS = map.data[i];
148 int nextO = map.data[i+2];
150 if(nextS != candidateS) {
152 if(candidateIs.contains(nextS)) {
154 // Next is a super type of candidate => ignore next
158 IntSet nextIs = null;
160 nextIs = QueryCache.resultSuperTypes(graph, nextS, parent, null);
161 } catch (DatabaseException e) {
162 procedure.exception(graph, e);
166 // SuperTypes next = SuperTypes.queryEach(graph, nextS, graph.processor, entry, null, NOP);
167 // if(next.isExcepted()) {
168 // if(entry != null) entry.except((Throwable)next.getResult());
169 // procedure.exception(graph, (Throwable)next.getResult());
172 // IntSet nextIs = next.getResult();
174 if(nextIs.contains(candidateS)) {
176 // Candidate is a super type of next => next is the new candidate
180 candidateIs = nextIs;
184 // candidate and next are unrelated => error
185 ManyObjectsForFunctionalRelationException exception = new ManyObjectsForFunctionalRelationException("Functional relation has conflicting assertions " + r1 + ", " + r2 + " " + map , r1);
186 procedure.exception(graph, exception);
197 procedure.execute(graph, candidateO);
198 procedure.finished(graph);
204 final static InternalProcedure<IntSet> NOP = new InternalProcedure<IntSet>() {
207 public void execute(ReadGraphImpl graph, IntSet result) {
211 public void exception(ReadGraphImpl graph, Throwable throwable) {
216 final static TripleIntProcedure NOPT = new TripleIntProcedure() {
220 public void exception(ReadGraphImpl graph, Throwable throwable) {
224 public void execute(ReadGraphImpl graph, int s, int p, int o) {
228 public void finished(ReadGraphImpl graph) {
233 // Search for one statement
234 final public void computeFunctionalIndex(ReadGraphImpl graph, final QueryProcessor provider, final RelationInfo ri, final IntProcedure procedure) throws DatabaseException {
235 computeFunctionalIndex(graph, r1(), r2(), this, ri, procedure);
238 // Search for one statement
239 final static public void computeFunctionalIndex(ReadGraphImpl graph, final int r1, final int r2, final Objects parent, final RelationInfo ri, final IntProcedure procedure) throws DatabaseException {
243 int result = graph.processor.querySupport.getFunctionalObject(r1, r2);
247 // Check for assertions
248 forSingleAssertion(graph, r1, r2, parent, procedure);
250 } else if (result == -1) {
252 graph.processor.querySupport.getObjects(graph, r1, r2, new IntProcedure() {
255 public void execute(ReadGraphImpl graph, int i) throws DatabaseException {
256 procedure.execute(graph, i);
260 public void exception(ReadGraphImpl graph, Throwable t) {
261 if(DebugException.DEBUG) new DebugException(t).printStackTrace();
265 public void finished(ReadGraphImpl graph) {
270 // Check for assertions
271 forSingleAssertion(graph, r1, r2, parent, procedure);
275 // If functional relation was found there is no need to check assertions
276 procedure.execute(graph, result);
277 procedure.finished(graph);
284 // Note! The dependency is intentionally cut!
285 IntSet direct = QueryCache.resultDirectPredicates(graph, r1, null, null);
286 direct.forEach(graph, new SyncIntProcedure() {
288 boolean found = false;
291 public void run(ReadGraphImpl graph) throws DatabaseException {
294 procedure.finished(graph);
297 // Check for assertions
298 forSingleAssertion(graph, r1, r2, parent, procedure);
305 public void execute(ReadGraphImpl graph, final int pred) throws DatabaseException {
311 // Note! The dependency is intentionally cut!
312 QueryCache.runnerDirectObjects(graph, r1, pred, null, null, new IntProcedure() {
315 public void execute(ReadGraphImpl graph, int i) throws DatabaseException {
319 procedure.execute(graph, i);
324 ManyObjectsForFunctionalRelationException exception = new ManyObjectsForFunctionalRelationException("Functional relation has more than one statement (r1=" + r1 + ", r2=" + r2 + ").", r1);
325 procedure.exception(graph, exception);
332 public void finished(ReadGraphImpl graph) {
336 public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
337 procedure.exception(graph, t);
344 QueryCache.runnerSuperRelations(graph, pred, parent, null, new InternalProcedure<IntSet>() {
347 public void execute(ReadGraphImpl graph, IntSet result) throws DatabaseException {
351 if(result.contains(r2)) {
353 // Note! The dependency is intentionally cut!
354 QueryCache.runnerDirectObjects(graph, r1, pred, null, null, new IntProcedure() {
357 public void execute(ReadGraphImpl graph, int i) throws DatabaseException {
361 procedure.execute(graph, i);
366 ManyObjectsForFunctionalRelationException exception = new ManyObjectsForFunctionalRelationException("Functional relation has more than one statement (r1=" + r1 + ", r2=" + r2 + ").", r1);
367 procedure.exception(graph, exception);
374 public void finished(ReadGraphImpl graph) {
378 public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
379 procedure.exception(graph, t);
389 public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
390 procedure.exception(graph, t);
400 public void finished(ReadGraphImpl graph) throws DatabaseException {
413 final static private void forAssertions(ReadGraphImpl graph, final int r1, final int r2, final Objects parent, final IntProcedure procedure) throws DatabaseException {
415 // Note! The dependency is intentionally cut!
416 QueryCache.runnerPrincipalTypes(graph, r1, null, null, new SyncIntProcedure() {
419 public void run(ReadGraphImpl graph) throws DatabaseException {
420 procedure.finished(graph);
423 TripleIntProcedure proc = new TripleIntProcedure() {
426 public void execute(ReadGraphImpl graph, int s, int p, int o) throws DatabaseException {
427 procedure.execute(graph, o);
431 public void finished(ReadGraphImpl graph) throws DatabaseException {
436 public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
437 if(DebugException.DEBUG) new DebugException(t).printStackTrace();
438 procedure.exception(graph, t);
445 public void execute(ReadGraphImpl graph, int type) throws DatabaseException {
448 QueryCache.runnerAssertedStatements(graph, type, r2, parent, null, proc);
453 public void finished(ReadGraphImpl graph) throws DatabaseException {
462 final public static void computeNotFunctionalFinalIndex(ReadGraphImpl graph, final int r1, final int r2, final QueryProcessor provider, RelationInfo ri, AsyncMultiProcedure<Resource> procedure) {
466 final public void computeNotFunctionalIndex(ReadGraphImpl graph, RelationInfo ri, final IntProcedure procedure) throws DatabaseException {
467 computeNotFunctionalIndex(graph, r1(), r2(), this, ri, procedure);
470 final static public void computeNotFunctionalIndex(ReadGraphImpl graph, final int r1, final int r2, final Objects parent, RelationInfo ri, final IntProcedure procedure) throws DatabaseException {
474 graph.processor.querySupport.getObjects(graph, r1, r2, new IntProcedure() {
477 public void execute(ReadGraphImpl graph, int i) throws DatabaseException {
478 procedure.execute(graph, i);
482 public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
483 if(DebugException.DEBUG) new DebugException(t).printStackTrace();
484 procedure.exception(graph, t);
488 public void finished(ReadGraphImpl graph) {
494 forAssertions(graph, r1, r2, parent, procedure);
496 procedure.finished(graph);
501 // Note! The dependency is intentionally cut!
502 IntSet direct = QueryCache.resultDirectPredicates(graph, r1, null, null);
503 direct.forEach(graph, new SyncIntProcedure() {
506 public void run(ReadGraphImpl graph) throws DatabaseException {
507 forAssertions(graph, r1, r2, parent, procedure);
511 public void execute(ReadGraphImpl graph, final int pred) throws DatabaseException {
517 // Note! The dependency is intentionally cut!
518 QueryCache.runnerDirectObjects(graph, r1, pred, null, null, new IntProcedure() {
521 public void execute(ReadGraphImpl graph, int i) throws DatabaseException {
522 procedure.execute(graph, i);
526 public void finished(ReadGraphImpl graph) throws DatabaseException {
531 public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
532 procedure.exception(graph, t);
542 QueryCache.runnerSuperRelations(graph, pred, parent, null, new InternalProcedure<IntSet>() {
545 public void execute(ReadGraphImpl graph, IntSet result) throws DatabaseException {
547 if(result.contains(r2)) {
551 // Note! The dependency is intentionally cut!
552 QueryCache.runnerDirectObjects(graph, r1, pred, null, null, new IntProcedure() {
555 public void execute(ReadGraphImpl graph, int i) throws DatabaseException {
556 procedure.execute(graph, i);
560 public void finished(ReadGraphImpl graph) throws DatabaseException {
565 public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
566 if(DebugException.DEBUG) new DebugException(t).printStackTrace();
567 procedure.exception(graph, t);
580 public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
581 procedure.exception(graph, t);
592 public void finished(ReadGraphImpl graph) throws DatabaseException {
603 public Object compute(ReadGraphImpl graph, final IntProcedure procedure) throws DatabaseException {
604 computeForEach(graph, r1(), r2(), this, procedure);
608 public static void computeForEach(ReadGraphImpl graph, final int r1, final int r2, final Objects entry, final IntProcedure procedure_) throws DatabaseException {
610 IntProcedure procedure = entry != null ? entry : procedure_;
612 RelationInfo ri = QueryCache.resultRelationInfoQuery(graph, r2, entry, null);
613 graph.ensureLoaded(r1, r2);
614 if(ri.isFunctional) {
615 computeFunctionalIndex(graph, r1, r2, entry, ri, procedure);
617 computeNotFunctionalIndex(graph, r1, r2, entry, ri, procedure);
620 if(entry != null) entry.performFromCache(graph, procedure_);
625 public String toString() {
626 return "Objects[" + r1() + " - " + r2() + "]";
629 // final private void finish(ReadGraphImpl graph, IntProcedure procedure) throws DatabaseException {
631 // assert(assertPending());
633 // synchronized(this) {
637 // IntArray v = (IntArray)getResult();
639 // if(v.data == null) {
640 // if(v.sizeOrData != IntArray.NO_DATA) {
641 // procedure.execute(graph, v.sizeOrData);
644 // for(int i = 0;i < v.sizeOrData ; i++) {
645 // procedure.execute(graph, v.data[i]);
649 // procedure.finished(graph);
653 // final public void addOrSet(int add) {
655 // assert(assertPending());
657 // IntArray value = (IntArray)getResult();
658 // synchronized(value) {
664 // final public void addOrSetFunctional(int add) {
666 // assert(isPending());
668 // IntArray value = (IntArray)getResult();
674 public Object performFromCache(ReadGraphImpl graph, final IntProcedure procedure) throws DatabaseException {
678 if(handleException(graph, procedure)) return getResult();
680 final IntArray value = (IntArray)getResult();
681 if(value.data == null) {
682 if(value.sizeOrData != IntArray.NO_DATA) procedure.execute(graph, value.sizeOrData);
684 for(int i = 0;i < value.sizeOrData ; i++) procedure.execute(graph, value.data[i]);
687 procedure.finished(graph);
694 public void recompute(ReadGraphImpl graph) throws DatabaseException {
696 compute(graph, new IntProcedureAdapter() {
699 public void finished(ReadGraphImpl graph) {
703 public void exception(ReadGraphImpl graph, Throwable t) {
704 new Error("Error in recompute.", t).printStackTrace();
713 return RequestFlags.IMMEDIATE_UPDATE;
717 boolean isImmutable(ReadGraphImpl graph) {
718 return graph.processor.isImmutable(r1());
722 public void execute(ReadGraphImpl graph, int i) throws DatabaseException {
723 IntArray value = (IntArray)getResult();
724 synchronized(value) {
730 public void finished(ReadGraphImpl graph) throws DatabaseException {
735 public void exception(ReadGraphImpl graph, Throwable throwable) throws DatabaseException {