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);
276 // Note! The dependency is intentionally cut!
277 IntSet direct = QueryCache.resultDirectPredicates(graph, r1, null, null);
278 direct.forEach(graph, new SyncIntProcedure() {
280 boolean found = false;
283 public void run(ReadGraphImpl graph) throws DatabaseException {
286 procedure.finished(graph);
289 // Check for assertions
290 forSingleAssertion(graph, r1, r2, parent, procedure);
297 public void execute(ReadGraphImpl graph, final int pred) throws DatabaseException {
303 // Note! The dependency is intentionally cut!
304 QueryCache.runnerDirectObjects(graph, r1, pred, null, null, new IntProcedure() {
307 public void execute(ReadGraphImpl graph, int i) throws DatabaseException {
311 procedure.execute(graph, i);
316 ManyObjectsForFunctionalRelationException exception = new ManyObjectsForFunctionalRelationException("Functional relation has more than one statement (r1=" + r1 + ", r2=" + r2 + ").", r1);
317 procedure.exception(graph, exception);
324 public void finished(ReadGraphImpl graph) {
328 public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
329 procedure.exception(graph, t);
336 QueryCache.runnerSuperRelations(graph, pred, parent, null, new InternalProcedure<IntSet>() {
339 public void execute(ReadGraphImpl graph, IntSet result) throws DatabaseException {
343 if(result.contains(r2)) {
345 // Note! The dependency is intentionally cut!
346 QueryCache.runnerDirectObjects(graph, r1, pred, null, null, new IntProcedure() {
349 public void execute(ReadGraphImpl graph, int i) throws DatabaseException {
353 procedure.execute(graph, i);
358 ManyObjectsForFunctionalRelationException exception = new ManyObjectsForFunctionalRelationException("Functional relation has more than one statement (r1=" + r1 + ", r2=" + r2 + ").", r1);
359 procedure.exception(graph, exception);
366 public void finished(ReadGraphImpl graph) {
370 public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
371 procedure.exception(graph, t);
381 public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
382 procedure.exception(graph, t);
392 public void finished(ReadGraphImpl graph) throws DatabaseException {
405 final static private void forAssertions(ReadGraphImpl graph, final int r1, final int r2, final Objects parent, final IntProcedure procedure) throws DatabaseException {
407 // Note! The dependency is intentionally cut!
408 QueryCache.runnerPrincipalTypes(graph, r1, null, null, new SyncIntProcedure() {
411 public void run(ReadGraphImpl graph) throws DatabaseException {
412 procedure.finished(graph);
415 TripleIntProcedure proc = new TripleIntProcedure() {
418 public void execute(ReadGraphImpl graph, int s, int p, int o) throws DatabaseException {
419 procedure.execute(graph, o);
423 public void finished(ReadGraphImpl graph) throws DatabaseException {
428 public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
429 if(DebugException.DEBUG) new DebugException(t).printStackTrace();
430 procedure.exception(graph, t);
437 public void execute(ReadGraphImpl graph, int type) throws DatabaseException {
440 QueryCache.runnerAssertedStatements(graph, type, r2, parent, null, proc);
445 public void finished(ReadGraphImpl graph) throws DatabaseException {
454 final public static void computeNotFunctionalFinalIndex(ReadGraphImpl graph, final int r1, final int r2, final QueryProcessor provider, RelationInfo ri, AsyncMultiProcedure<Resource> procedure) {
458 final public void computeNotFunctionalIndex(ReadGraphImpl graph, RelationInfo ri, final IntProcedure procedure) throws DatabaseException {
459 computeNotFunctionalIndex(graph, r1(), r2(), this, ri, procedure);
462 final static public void computeNotFunctionalIndex(ReadGraphImpl graph, final int r1, final int r2, final Objects parent, RelationInfo ri, final IntProcedure procedure) throws DatabaseException {
466 graph.processor.querySupport.getObjects(graph, r1, r2, new IntProcedure() {
469 public void execute(ReadGraphImpl graph, int i) throws DatabaseException {
470 procedure.execute(graph, i);
474 public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
475 if(DebugException.DEBUG) new DebugException(t).printStackTrace();
476 procedure.exception(graph, t);
480 public void finished(ReadGraphImpl graph) {
486 forAssertions(graph, r1, r2, parent, procedure);
488 procedure.finished(graph);
493 // Note! The dependency is intentionally cut!
494 IntSet direct = QueryCache.resultDirectPredicates(graph, r1, null, null);
495 direct.forEach(graph, new SyncIntProcedure() {
498 public void run(ReadGraphImpl graph) throws DatabaseException {
499 forAssertions(graph, r1, r2, parent, procedure);
503 public void execute(ReadGraphImpl graph, final int pred) throws DatabaseException {
509 // Note! The dependency is intentionally cut!
510 QueryCache.runnerDirectObjects(graph, r1, pred, null, null, new IntProcedure() {
513 public void execute(ReadGraphImpl graph, int i) throws DatabaseException {
514 procedure.execute(graph, i);
518 public void finished(ReadGraphImpl graph) throws DatabaseException {
523 public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
524 procedure.exception(graph, t);
534 QueryCache.runnerSuperRelations(graph, pred, parent, null, new InternalProcedure<IntSet>() {
537 public void execute(ReadGraphImpl graph, IntSet result) throws DatabaseException {
539 if(result.contains(r2)) {
543 // Note! The dependency is intentionally cut!
544 QueryCache.runnerDirectObjects(graph, r1, pred, null, null, new IntProcedure() {
547 public void execute(ReadGraphImpl graph, int i) throws DatabaseException {
548 procedure.execute(graph, i);
552 public void finished(ReadGraphImpl graph) throws DatabaseException {
557 public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
558 if(DebugException.DEBUG) new DebugException(t).printStackTrace();
559 procedure.exception(graph, t);
572 public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
573 procedure.exception(graph, t);
584 public void finished(ReadGraphImpl graph) throws DatabaseException {
594 public Object compute(ReadGraphImpl graph, final IntProcedure procedure) throws DatabaseException {
595 computeForEach(graph, r1(), r2(), this, procedure);
599 public static void computeForEach(ReadGraphImpl graph, final int r1, final int r2, final Objects entry, final IntProcedure procedure_) throws DatabaseException {
601 IntProcedure procedure = entry != null ? entry : procedure_;
603 RelationInfo ri = QueryCache.resultRelationInfoQuery(graph, r2, entry, null);
604 graph.ensureLoaded(r1, r2);
605 if(ri.isFunctional) {
606 computeFunctionalIndex(graph, r1, r2, entry, ri, procedure);
608 computeNotFunctionalIndex(graph, r1, r2, entry, ri, procedure);
611 if(entry != null) entry.performFromCache(graph, procedure_);
616 public String toString() {
617 return "Objects[" + r1() + " - " + r2() + "]";
621 public Object performFromCache(ReadGraphImpl graph, final IntProcedure procedure) throws DatabaseException {
625 if(handleException(graph, procedure)) return getResult();
627 final IntArray value = (IntArray)getResult();
628 if(value.data == null) {
629 if(value.sizeOrData != IntArray.NO_DATA) procedure.execute(graph, value.sizeOrData);
631 for(int i = 0;i < value.sizeOrData ; i++) procedure.execute(graph, value.data[i]);
634 procedure.finished(graph);
641 public void recompute(ReadGraphImpl graph) throws DatabaseException {
643 compute(graph, new IntProcedureAdapter() {
646 public void finished(ReadGraphImpl graph) {
650 public void exception(ReadGraphImpl graph, Throwable t) {
651 new Error("Error in recompute.", t).printStackTrace();
660 return RequestFlags.IMMEDIATE_UPDATE;
664 boolean isImmutable(ReadGraphImpl graph) {
665 return graph.processor.isImmutable(r1());
669 public void execute(ReadGraphImpl graph, int i) throws DatabaseException {
670 IntArray value = (IntArray)getResult();
671 synchronized(value) {
677 public void finished(ReadGraphImpl graph) throws DatabaseException {
682 public void exception(ReadGraphImpl graph, Throwable throwable) throws DatabaseException {