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.atomic.AtomicInteger;
16 import org.simantics.db.common.utils.Logger;
17 import org.simantics.db.exception.DatabaseException;
18 import org.simantics.db.impl.graph.ReadGraphImpl;
19 import org.simantics.db.impl.procedure.InternalProcedure;
21 import gnu.trove.procedure.TIntProcedure;
22 import gnu.trove.set.hash.TIntHashSet;
24 final public class SuperRelations extends UnaryQuery<InternalProcedure<IntSet>> {
26 SuperRelations(final int resource) {
30 final static SuperRelations entry(final QueryProcessor provider, final int r) {
31 return (SuperRelations)provider.cache.superRelationsMap.get(r);
35 final public void removeEntry(QueryProcessor provider) {
36 provider.cache.remove(this);
39 static int histoCounter = 0;
40 static int counter = 0;
44 private TIntHashSet set = null;
45 public int single = 0;
47 public boolean add(int val) {
48 if(single == val) return false;
53 if(set == null) set = new TIntHashSet(4);
59 if(single == 0) return 0;
60 if(set == null) return 1;
61 return set.size() + 1;
65 public void forEach(TIntProcedure proc) {
66 if(single > 0) proc.execute(single);
67 if(set != null) set.forEach(proc);
73 public Object compute(final ReadGraphImpl graph, final InternalProcedure<IntSet> procedure) throws DatabaseException {
75 QueryProcessor processor = graph.processor;
77 processor.querySupport.ensureLoaded(graph, id);
79 final InternalProcedure<IntSet> proc = (InternalProcedure<IntSet>)procedure;
81 final int subrelationOf = processor.getSubrelationOf();
83 final IntSet result = new IntSet(processor.querySupport);
85 final class DirectProcedure extends Koss implements IntProcedure, TIntProcedure, InternalProcedure<IntSet> {
87 final public boolean execute(int r) {
92 final public void execute(ReadGraphImpl graph, int r) {
100 final public void execute(ReadGraphImpl graph, IntSet set) throws DatabaseException {
102 addOrSet(graph, result, processor);
103 proc.execute(graph, result);
106 public void finished(ReadGraphImpl graph) {
109 public void exception(ReadGraphImpl graph, Throwable t) {
110 throw new Error("Errors are not supported.", t);
115 final DirectProcedure directProc = new DirectProcedure();
117 processor.querySupport.getObjects(graph, id, subrelationOf, directProc);
119 int size = directProc.size();
123 addOrSet(graph, IntSet.EMPTY, processor);
124 proc.execute(graph, IntSet.EMPTY);
126 } else if (size == 1) {
128 result.add(directProc.single);
129 QueryCache.runnerSuperRelations(graph, directProc.single, SuperRelations.this, null, directProc);
133 // if((counter++ % 500) == 0) System.out.println("SR " + counter);
135 final TIntProcedure addToResult = new TIntProcedure() {
137 public boolean execute(int r) {
138 synchronized(result) {
145 final AtomicInteger finishes = new AtomicInteger(0);
147 directProc.forEach(new TIntProcedure() {
150 public boolean execute(int arg0) {
152 return execute0(arg0);
153 } catch (DatabaseException e) {
154 Logger.defaultLogError(e);
159 public boolean execute0(int arg0) throws DatabaseException {
161 synchronized(result) {
165 QueryCache.runnerSuperRelations(graph, arg0, SuperRelations.this, null, new InternalProcedure<IntSet>() {
168 public void execute(ReadGraphImpl graph, IntSet set) throws DatabaseException {
169 set.forEach(addToResult);
170 int current = finishes.addAndGet(1);
171 if(current == directProc.size()) {
172 addOrSet(graph, result, processor);
173 proc.execute(graph, result);
179 public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
180 proc.exception(graph, t);
198 public String toString() {
199 return "SuperRelations[" + id + "]";
202 private void addOrSet(ReadGraphImpl graph, final IntSet value, QueryProcessor provider) {
217 public Object performFromCache(ReadGraphImpl graph, InternalProcedure<IntSet> procedure) throws DatabaseException {
221 if(handleException(graph, procedure)) return null;
223 IntSet result = getResult();
225 procedure.execute(graph, result);
232 public void recompute(ReadGraphImpl graph) throws DatabaseException {
234 compute(graph, new InternalProcedure<IntSet>() {
237 public void execute(ReadGraphImpl graph, IntSet result) {
241 public void exception(ReadGraphImpl graph, Throwable t) {
242 new Error("Error in recompute.", t).printStackTrace();
250 boolean isImmutable(ReadGraphImpl graph) {
251 return graph.processor.isImmutable(id);