1 /*******************************************************************************
2 * Copyright (c) 2007, 2018 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 public final 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 if(nextIs.contains(candidateS)) {
168 // Candidate is a super type of next => next is the new candidate
172 candidateIs = nextIs;
176 // candidate and next are unrelated => error
177 ManyObjectsForFunctionalRelationException exception = new ManyObjectsForFunctionalRelationException("Functional relation has conflicting assertions " + r1 + ", " + r2 + " " + map , r1);
178 procedure.exception(graph, exception);
189 procedure.execute(graph, candidateO);
190 procedure.finished(graph);
196 final static InternalProcedure<IntSet> NOP = new InternalProcedure<IntSet>() {
199 public void execute(ReadGraphImpl graph, IntSet result) {
203 public void exception(ReadGraphImpl graph, Throwable throwable) {
208 final static TripleIntProcedure NOPT = new TripleIntProcedure() {
212 public void exception(ReadGraphImpl graph, Throwable throwable) {
216 public void execute(ReadGraphImpl graph, int s, int p, int o) {
220 public void finished(ReadGraphImpl graph) {
225 // Search for one statement
226 final public void computeFunctionalIndex(ReadGraphImpl graph, final QueryProcessor provider, final RelationInfo ri, final IntProcedure procedure) throws DatabaseException {
227 computeFunctionalIndex(graph, r1(), r2(), this, ri, procedure);
230 // Search for one statement
231 final static public void computeFunctionalIndex(ReadGraphImpl graph, final int r1, final int r2, final Objects parent, final RelationInfo ri, final IntProcedure procedure) throws DatabaseException {
235 int result = graph.processor.querySupport.getFunctionalObject(r1, r2);
239 // Check for assertions
240 forSingleAssertion(graph, r1, r2, parent, procedure);
242 } else if (result == -1) {
244 graph.processor.querySupport.getObjects(graph, r1, r2, new IntProcedure() {
247 public void execute(ReadGraphImpl graph, int i) throws DatabaseException {
248 procedure.execute(graph, i);
252 public void exception(ReadGraphImpl graph, Throwable t) {
253 if(DebugException.DEBUG) new DebugException(t).printStackTrace();
257 public void finished(ReadGraphImpl graph) {
262 // Check for assertions
263 forSingleAssertion(graph, r1, r2, parent, procedure);
267 // If functional relation was found there is no need to check assertions
268 procedure.execute(graph, result);
269 procedure.finished(graph);
275 // Note! The dependency is intentionally cut!
276 IntSet direct = QueryCache.resultDirectPredicates(graph, r1, null, null);
277 direct.forEach(graph, new SyncIntProcedure() {
287 public void run(ReadGraphImpl graph) throws DatabaseException {
291 procedure.finished(graph);
293 } else if(found == 0) {
295 // Check for assertions
296 forSingleAssertion(graph, r1, r2, parent, procedure);
303 public void execute(ReadGraphImpl graph, final int pred) throws DatabaseException {
310 // Note! The dependency is intentionally cut!
311 QueryCache.runnerDirectObjects(graph, r1, pred, null, null, new IntProcedure() {
314 public void execute(ReadGraphImpl graph, int i) throws DatabaseException {
318 procedure.execute(graph, i);
323 ManyObjectsForFunctionalRelationException exception = new ManyObjectsForFunctionalRelationException("Functional relation has more than one statement (r1=" + r1 + ", r2=" + r2 + ").", r1);
324 procedure.exception(graph, exception);
332 public void finished(ReadGraphImpl graph) {
336 public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
338 procedure.exception(graph, t);
347 QueryCache.runnerSuperRelations(graph, pred, parent, null, new InternalProcedure<IntSet>() {
350 public void execute(ReadGraphImpl graph, IntSet result) throws DatabaseException {
355 if(result.contains(r2)) {
357 // Note! The dependency is intentionally cut!
358 QueryCache.runnerDirectObjects(graph, r1, pred, null, null, new IntProcedure() {
361 public void execute(ReadGraphImpl graph, int i) throws DatabaseException {
365 procedure.execute(graph, i);
370 ManyObjectsForFunctionalRelationException exception = new ManyObjectsForFunctionalRelationException("Functional relation has more than one statement (r1=" + r1 + ", r2=" + r2 + ").", r1);
371 procedure.exception(graph, exception);
379 public void finished(ReadGraphImpl graph) {
383 public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
384 procedure.exception(graph, t);
395 public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
396 procedure.exception(graph, t);
407 public void finished(ReadGraphImpl graph) throws DatabaseException {
418 final static private void forAssertions(ReadGraphImpl graph, final int r1, final int r2, final Objects parent, final IntProcedure procedure) throws DatabaseException {
420 // Note! The dependency is intentionally cut!
421 QueryCache.runnerPrincipalTypes(graph, r1, null, null, new SyncIntProcedure() {
424 public void run(ReadGraphImpl graph) throws DatabaseException {
425 procedure.finished(graph);
428 TripleIntProcedure proc = new TripleIntProcedure() {
431 public void execute(ReadGraphImpl graph, int s, int p, int o) throws DatabaseException {
432 procedure.execute(graph, o);
436 public void finished(ReadGraphImpl graph) throws DatabaseException {
441 public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
442 if(DebugException.DEBUG) new DebugException(t).printStackTrace();
443 procedure.exception(graph, t);
450 public void execute(ReadGraphImpl graph, int type) throws DatabaseException {
453 QueryCache.runnerAssertedStatements(graph, type, r2, parent, null, proc);
458 public void finished(ReadGraphImpl graph) throws DatabaseException {
467 final public static void computeNotFunctionalFinalIndex(ReadGraphImpl graph, final int r1, final int r2, final QueryProcessor provider, RelationInfo ri, AsyncMultiProcedure<Resource> procedure) {
471 final public void computeNotFunctionalIndex(ReadGraphImpl graph, RelationInfo ri, final IntProcedure procedure) throws DatabaseException {
472 computeNotFunctionalIndex(graph, r1(), r2(), this, ri, procedure);
475 final static public void computeNotFunctionalIndex(ReadGraphImpl graph, final int r1, final int r2, final Objects parent, RelationInfo ri, final IntProcedure procedure) throws DatabaseException {
479 graph.processor.querySupport.getObjects(graph, r1, r2, new IntProcedure() {
482 public void execute(ReadGraphImpl graph, int i) throws DatabaseException {
483 procedure.execute(graph, i);
487 public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
488 if(DebugException.DEBUG) new DebugException(t).printStackTrace();
489 procedure.exception(graph, t);
493 public void finished(ReadGraphImpl graph) {
499 forAssertions(graph, r1, r2, parent, procedure);
501 procedure.finished(graph);
506 // Note! The dependency is intentionally cut!
507 IntSet direct = QueryCache.resultDirectPredicates(graph, r1, null, null);
508 direct.forEach(graph, new SyncIntProcedure() {
511 public void run(ReadGraphImpl graph) throws DatabaseException {
512 forAssertions(graph, r1, r2, parent, procedure);
516 public void execute(ReadGraphImpl graph, final int pred) throws DatabaseException {
520 // Note! The dependency is intentionally cut!
521 QueryCache.runnerDirectObjects(graph, r1, pred, null, null, new IntProcedure() {
524 public void execute(ReadGraphImpl graph, int i) throws DatabaseException {
525 procedure.execute(graph, i);
529 public void finished(ReadGraphImpl graph) throws DatabaseException {
533 public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
534 procedure.exception(graph, t);
543 IntSet result = QueryCache.resultSuperRelations(graph, pred, parent, null);
544 if(result.contains(r2)) {
548 // Note! The dependency is intentionally cut!
549 QueryCache.runnerDirectObjects(graph, r1, pred, null, null, new IntProcedure() {
552 public void execute(ReadGraphImpl graph, int i) throws DatabaseException {
553 procedure.execute(graph, i);
557 public void finished(ReadGraphImpl graph) throws DatabaseException {
562 public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
563 if(DebugException.DEBUG) new DebugException(t).printStackTrace();
564 procedure.exception(graph, t);
572 } catch (Throwable e) {
573 procedure.exception(graph, e);
581 public void finished(ReadGraphImpl graph) throws DatabaseException {
591 public Object compute(ReadGraphImpl graph, final IntProcedure procedure) throws DatabaseException {
592 computeForEach(graph, r1(), r2(), this, procedure);
596 public static void computeForEach(ReadGraphImpl graph, final int r1, final int r2, final Objects entry, final IntProcedure procedure_) throws DatabaseException {
598 IntProcedure procedure = entry != null ? entry : procedure_;
600 RelationInfo ri = QueryCache.resultRelationInfoQuery(graph, r2, entry, null);
601 graph.ensureLoaded(r1, r2);
602 if(ri.isFunctional) {
603 computeFunctionalIndex(graph, r1, r2, entry, ri, procedure);
605 computeNotFunctionalIndex(graph, r1, r2, entry, ri, procedure);
608 if(entry != null) entry.performFromCache(graph, procedure_);
613 public String toString() {
614 return "Objects[" + r1() + " - " + r2() + "]";
618 public Object performFromCache(ReadGraphImpl graph, final IntProcedure procedure) throws DatabaseException {
622 if(handleException(graph, procedure)) return getResult();
624 final IntArray value = (IntArray)getResult();
625 if(value.data == null) {
626 if(value.sizeOrData != IntArray.NO_DATA) procedure.execute(graph, value.sizeOrData);
628 for(int i = 0;i < value.sizeOrData ; i++) procedure.execute(graph, value.data[i]);
631 procedure.finished(graph);
638 public void recompute(ReadGraphImpl graph) throws DatabaseException {
640 compute(graph, new IntProcedureAdapter() {
643 public void finished(ReadGraphImpl graph) {
647 public void exception(ReadGraphImpl graph, Throwable t) {
648 new Error("Error in recompute.", t).printStackTrace();
657 return RequestFlags.IMMEDIATE_UPDATE;
661 boolean isImmutable(ReadGraphImpl graph) {
662 return graph.processor.isImmutable(r1());
666 public void execute(ReadGraphImpl graph, int i) throws DatabaseException {
667 IntArray value = (IntArray)getResult();
668 synchronized(value) {
674 public void finished(ReadGraphImpl graph) throws DatabaseException {
679 public void exception(ReadGraphImpl graph, Throwable throwable) throws DatabaseException {