]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/SuperRelations.java
1f540062e9440d2db81164ee820c05566f4a55c0
[simantics/platform.git] / bundles / org.simantics.db.impl / src / org / simantics / db / impl / query / SuperRelations.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2018 Association for Decentralized Information Management
3  * in Industry THTH ry.
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
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.db.impl.query;
13
14 import java.util.concurrent.atomic.AtomicInteger;
15
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;
20
21 import gnu.trove.procedure.TIntProcedure;
22 import gnu.trove.set.hash.TIntHashSet;
23
24 public final class SuperRelations extends UnaryQueryP<IntSet> {
25
26     SuperRelations(final int resource) {
27         super(resource);
28     }
29
30     static final SuperRelations entry(final QueryProcessor provider, final int r) {
31         return (SuperRelations)provider.cache.superRelationsMap.get(r);
32     }
33
34         @Override
35         public final void removeEntry(QueryProcessor provider) {
36                 provider.cache.remove(this);
37         }
38         
39     static class Ints {
40         
41         private TIntHashSet set = null;
42         public int single = 0;
43         
44         public boolean add(int val) {
45             if(single == val) return false;
46             if(single == 0) {
47                 single = val;
48                 return true;
49             }
50             if(set == null) set = new TIntHashSet(4);
51             return set.add(val);
52         }
53         
54         public int size() {
55             
56             if(single == 0) return 0;
57             if(set == null) return 1;
58             return set.size() + 1;
59             
60         }
61
62         public void forEach(TIntProcedure proc) {
63             if(single > 0) proc.execute(single);
64             if(set != null) set.forEach(proc);
65         }
66         
67     }
68
69         public void compute(final ReadGraphImpl graph, final InternalProcedure<IntSet> procedure) throws DatabaseException {
70             computeForEach(graph, id, this, procedure);
71         }
72
73     static class DirectProcedure extends Ints implements IntProcedure, TIntProcedure, InternalProcedure<IntSet> {
74         
75         IntSet result;
76         InternalProcedure<IntSet> proc;
77         
78         public DirectProcedure(IntSet result, InternalProcedure<IntSet> proc) {
79             this.result = result;
80             this.proc = proc;
81         }
82         
83         @Override
84         final public boolean execute(int r) {
85             result.add(r);
86             return true;
87         }
88         @Override
89         final public void execute(ReadGraphImpl graph, int r) {
90             if(single == 0) {
91                 single = r;
92                 return;
93             }
94             add(r);
95         }
96         @Override
97         public final void execute(ReadGraphImpl graph, IntSet set) throws DatabaseException {
98             set.forEach(this);
99             proc.execute(graph, result);
100         }
101         @Override
102         public void finished(ReadGraphImpl graph) {
103         }
104         @Override
105         public void exception(ReadGraphImpl graph, Throwable t) {
106             throw new Error("Errors are not supported.", t);
107         }
108
109     }
110
111         public static Object computeForEach(final ReadGraphImpl graph, int id, SuperRelations entry, final InternalProcedure<IntSet> procedure_) throws DatabaseException {
112             
113             InternalProcedure<IntSet> procedure = entry != null ? entry : procedure_;
114
115             QueryProcessor processor = graph.processor;
116                 
117                 processor.querySupport.ensureLoaded(graph, id);
118                 
119             final InternalProcedure<IntSet> proc = (InternalProcedure<IntSet>)procedure;
120
121             final int subrelationOf = processor.getSubrelationOf();
122
123             final IntSet result = new IntSet(processor.querySupport);
124
125             final DirectProcedure directProc = new DirectProcedure(result, proc);
126
127            processor.querySupport.getObjects(graph, id, subrelationOf, directProc);
128
129             int size = directProc.size();
130
131             if(size == 0) {
132                 proc.execute(graph, IntSet.EMPTY);
133             } else if (size == 1) {
134                 result.add(directProc.single);
135                 QueryCache.runnerSuperRelations(graph, directProc.single, entry, null, directProc);
136             } else {
137
138                 final TIntProcedure addToResult = new TIntProcedure() {
139                         @Override
140                         public boolean execute(int r) {
141                                 synchronized(result) {
142                                         result.add(r);
143                                 }
144                                 return true;
145                         }
146                 };
147
148                 final AtomicInteger finishes = new AtomicInteger(0);
149
150                 directProc.forEach(new TIntProcedure() {
151
152                         @Override
153                         public boolean execute(int arg0) {
154                                 try {
155                                                 return execute0(arg0);
156                                         } catch (DatabaseException e) {
157                                                 Logger.defaultLogError(e);
158                                         }
159                                 return false;
160                         }
161
162                         public boolean execute0(int arg0) throws DatabaseException {
163
164                                 synchronized(result) {
165                                         result.add(arg0);
166                                 }
167
168                                 QueryCache.runnerSuperRelations(graph, arg0, entry, null, new InternalProcedure<IntSet>() {
169
170                                         @Override
171                                         public void execute(ReadGraphImpl graph, IntSet set) throws DatabaseException {
172                                                 set.forEach(addToResult);
173                                                 int current = finishes.addAndGet(1);
174                                                 if(current == directProc.size()) {
175                                                         proc.execute(graph, result);
176                                                         return; 
177                                                 }
178                                         }
179
180                                         @Override
181                                         public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
182                                                 proc.exception(graph, t);
183                                         }
184
185                                 });
186
187                                 return true;
188
189                         }
190
191                 });
192
193             }
194             
195             if(entry != null) entry.performFromCache(graph, procedure_);
196              
197             return result;
198         
199     }
200     
201     @Override
202     public String toString() {
203         return "SuperRelations[" + id + "]";
204     }
205     
206 }