]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.db.procore/src/org/simantics/db/procore/cluster/CompleteTable.java
Fail safe import fixes made by Antti
[simantics/platform.git] / bundles / org.simantics.db.procore / src / org / simantics / db / procore / cluster / CompleteTable.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2010 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.procore.cluster;
13
14 import gnu.trove.map.hash.TIntIntHashMap;
15 import gnu.trove.procedure.TIntIntProcedure;
16 import gnu.trove.set.hash.TIntHashSet;
17
18 import org.simantics.db.exception.DatabaseException;
19 import org.simantics.db.exception.ValidationException;
20 import org.simantics.db.impl.ClusterBase;
21 import org.simantics.db.impl.ClusterI;
22 import org.simantics.db.impl.ClusterI.CompleteTypeEnum;
23 import org.simantics.db.impl.ClusterI.ObjectProcedure;
24 import org.simantics.db.impl.ClusterI.Procedure;
25 import org.simantics.db.impl.ClusterSupport;
26 import org.simantics.db.impl.ClusterTraitsBase;
27 import org.simantics.db.impl.Modifier;
28 import org.simantics.db.impl.Table;
29 import org.simantics.db.impl.TableFactory;
30 import org.simantics.db.impl.TableIntAllocatorAdapter;
31 import org.simantics.db.impl.TableSizeListener;
32 import org.simantics.db.procore.cluster.TableIntArraySet.Ints;
33
34 public class CompleteTable extends Table<int[]> {
35     public CompleteTable(TableSizeListener sizeListener, int[] header, int headerBase) {
36         super(TableFactory.getIntFactory(), sizeListener, header, headerBase);
37     }
38     public CompleteTable(TableSizeListener sizeListener, int[] header, int headerBase, int[] ints) {
39         super(TableFactory.getIntFactory(), sizeListener, header, headerBase, ints);
40     }
41     final int createCompleteArraySet(int o1, int o2)
42     throws DatabaseException {
43         if (0 == o1 || o1 == o2)
44             throw new DatabaseException("Illegal argument to createObejctArray");
45         int[] obs = new int[2];
46         obs[0] = o1;
47         obs[1] = o2;
48         int hashBase = TableIntArraySet.create(obs, new TableIntAllocatorAdapter(this));
49         return convertRealIndexToTableIndex(hashBase);
50     }
51     final void deleteCompleteSet(int index)
52     throws DatabaseException {
53       int hashBase = checkIndexAndGetRealIndex(index, 0);
54       if (TableIntArraySet.isArraySet(getTable(), hashBase)) {
55           int capacity = TableIntArraySet.getAllocatedSize(getTable(), hashBase);
56           int elementIndex = index - TableIntArraySet.HeaderSize;
57           deleteOldElement(elementIndex, capacity);
58       } else {
59           int capacity = TableIntSet.getAllocatedSize(getTable(), hashBase);
60           int elementIndex = index - TableIntSet.HeaderSize;
61           deleteOldElement(elementIndex, capacity);
62       }
63     }
64     final int getCompleteSetSize(int objectIndex) {
65         int hashBase = checkIndexAndGetRealIndex(objectIndex, 0);
66         if (TableIntArraySet.isArraySet(getTable(), hashBase))
67             return TableIntArraySet.getSize(getTable(), hashBase);
68         else
69             return TableIntSet.getSize(getTable(), hashBase);
70     }
71         /**
72         * @param setIndex
73         * @param oResourceIndex
74         * @return zero if complete already in the set else index of the set
75         */
76     final int addComplete(int setIndex, int oResourceIndex)
77     throws DatabaseException {
78         int hashBase = checkIndexAndGetRealIndex(setIndex, 0);
79         int newHashBase;
80         if (TableIntArraySet.isArraySet(getTable(), hashBase)) {
81             if (TableIntArraySet.getSize(getTable(), hashBase) < 5)
82                 newHashBase = TableIntArraySet.addInt(getTable(), hashBase, oResourceIndex, new TableIntAllocatorAdapter(this));
83             else {
84                 Ints ints = TableIntArraySet.getIntsIfValueNotFound(getTable(), hashBase, oResourceIndex);
85                 if (ints.found)
86                     return 0; // old object, not modified 
87                 this.deleteCompleteSet(setIndex);
88                 newHashBase = TableIntSet.create(ints.ints, new TableIntAllocatorAdapter(this));
89                 assert(0 != newHashBase);
90             }
91         } else
92             newHashBase = TableIntSet.addInt(getTable(), hashBase, oResourceIndex, new TableIntAllocatorAdapter(this));
93         if (0 == newHashBase)
94             return 0; // old object, not modified
95         int ni = convertRealIndexToTableIndex(newHashBase);
96         return ni;
97     }
98     final int removeLast(int setIndex)
99     throws DatabaseException {
100         int hashBase = checkIndexAndGetRealIndex(setIndex, 0);
101         int[] table = getTable();
102         int ref;
103         if (TableIntArraySet.isArraySet(table, hashBase))
104             ref = TableIntArraySet.removeIntLast(table, hashBase);
105         else {
106             ref = TableIntSet.removeIntLast(table, hashBase);
107         }
108         deleteCompleteSet(setIndex);
109         return ref;
110     }
111     /**
112      * @param setIndex
113      * @param oResourceIndex
114      * @return number of objects after removal.
115      */
116     final int removeComplete(int setIndex, int oResourceIndex)
117     throws DatabaseException {
118         int hashBase = checkIndexAndGetRealIndex(setIndex, 0);
119         int[] table = getTable();
120         if (TableIntArraySet.isArraySet(table, hashBase))
121             return TableIntArraySet.removeInt(table, hashBase, oResourceIndex);
122         else {
123             TableIntSet.removeInt(table, hashBase, oResourceIndex);
124             return TableIntSet.getSize(table, hashBase);
125         }
126     }
127     final public <Context> boolean foreachComplete(final int setIndex,
128         final ClusterI.ObjectProcedure<Context> procedure, final Context context, final ClusterSupport support,
129         final Modifier modifier) throws DatabaseException {
130         final int hashBase = checkIndexAndGetRealIndex(setIndex, 0);
131         boolean ret;
132         if (TableIntArraySet.isArraySet(getTable(), hashBase))
133             ret = TableIntArraySet.foreachInt(getTable(), hashBase, procedure, context, modifier);
134         else
135             ret = TableIntSet.foreachInt(getTable(), hashBase, procedure, context, modifier);
136         return ret;
137     }
138     public <Context> boolean foreachPredicate(int setIndex,
139             ClusterI.PredicateProcedure<Context> procedure,
140             Context context, ClusterSupport support, Modifier modifier)
141     throws DatabaseException {
142         ForeachPredicate<Context> t = new ForeachPredicate<Context>(procedure, support, modifier);
143         return foreachComplete(setIndex, t, context, null, null);
144     }
145     
146     public <Context> boolean foreachObject(int setIndex,
147             ClusterI.ObjectProcedure<Context> procedure,
148             Context context, ClusterSupport support, Modifier modifier,
149             ClusterI.CompleteTypeEnum completeType)
150     throws DatabaseException {
151         ForeachObject<Context> t = new ForeachObject<Context>
152         (procedure, support, modifier, completeType);
153         return foreachComplete(setIndex, t, context, null, null);
154     }
155     
156     private void checkEntry(ClusterBase cluster, int[] table, int index)
157     throws DatabaseException {
158         ClusterI.CompleteTypeEnum type = ClusterTraits.completeReferenceGetType(table[index]);
159         if (type == CompleteTypeEnum.NotComplete)
160             throw new ValidationException("Illegal CompleteTable entry type. Entry=" + table[index] + " index=" + index);
161         int fi = ClusterTraits.completeReferenceGetForeignIndex(table[index]);
162         int ri = ClusterTraits.completeReferenceGetResourceIndex(table[index]);
163         if (0 != fi) {
164             cluster.checkForeingIndex(fi);
165             if (ri < 1 || ri > ClusterTraits.getMaxNumberOfResources())
166                 throw new ValidationException("Illegal CompleteTable foreign entry. Entry=" + table[index] + " index=" + index);
167         } /*else if (ri < 1 || ri > cluster.getNumberOfResources(-1))
168                 throw new ValidationException("Illegal CompleteTable local entry. Entry=" + table[index] + " index=" + index);*/
169     }
170
171     private TIntHashSet checkIndexSet = null;
172     public final void check(ClusterBase cluster)
173     throws DatabaseException {
174         if (null == checkIndexSet)
175             checkIndexSet = new TIntHashSet();
176         else
177             checkIndexSet.clear();
178         int count = 0;
179         int[] table = getTable();
180         int ps = getHeader().getOffset() + ZERO_SHIFT;
181         int pe = ps + getTableSize();
182         for (int p = ps; p < pe;) {
183             int cap = p++;
184             if (table[cap] >= 0) {
185                 int use = p++;
186                 int fre = p++;
187                 int max = p++;
188                 assert(table[cap] >= table[use] + table[fre]);
189                 assert(table[max] == table[cap] >> 1);
190                 assert(table[max]+1 >= table[use]);
191                 checkIndexSet.add(p - ps);
192                 for (int e = p + table[cap]; p<e; p++) {
193                     if (IntHashTrait.isFull(table[p])) 
194                         checkEntry(cluster, table, p);
195                 }
196             } else {
197                 final int size = -table[cap];
198                 assert(size > 0);
199                 checkIndexSet.add(p - ps);
200                 boolean free = false;
201                 for (int e = p + size; p<e; p++) {
202                     if (free)
203                         assert(table[p] == 0);
204                     else if (table[p] == 0)
205                         free = true;
206                     else
207                         checkEntry(cluster, table, p);
208                 }
209             }
210             count++;
211         }
212         assert(getHeader().getCount() <= count);  // deleted objects are not recognized
213     }
214     public final void checkCompleteSetIndex(ClusterBase cluster, int i)
215     throws DatabaseException {
216         if (null == checkIndexSet)
217                 check(cluster); // builds checkIndexSet
218         if (!checkIndexSet.contains(i-ZERO_SHIFT))
219                 throw new ValidationException("Illegal object set index=" + i);
220     }
221     final void printDebugInfo() {
222       int count = 0;
223       int[] table = getTable();
224       int ps = getHeader().getOffset() + ZERO_SHIFT;
225       int pe = ps + getTableSize();
226       TIntIntHashMap stat = new TIntIntHashMap();
227       TIntIntHashMap stat2 = new TIntIntHashMap();
228       for (int p=ps; p<pe;) {
229           int cap = p++;
230           if (table[cap] >= 0) {
231               int use = p++;
232               int fre = p++;
233               int max = p++;
234               assert(table[cap] >= table[use] + table[fre]);
235               assert(table[max] == table[cap] >> 1);
236               p += table[cap];
237               int val = stat.get(table[use]) + 1;
238               stat.put(table[use], val);
239           } else {
240               final int size = -table[cap];
241               int val = stat2.get(size) + 1;
242               stat2.put(size, val);
243               p += size;
244           }
245           count++;
246       }
247       assert(getHeader().getCount() == count);
248       stat.forEachEntry(new TIntIntProcedure() {
249           @Override
250           public boolean execute(int a, int b) {
251               System.out.println("complete set capacity " + a + " instance count " + b);
252               return true;
253           }
254       });
255       stat2.forEachEntry(new TIntIntProcedure() {
256           @Override
257           public boolean execute(int a, int b) {
258               System.out.println("complete array set capacity " + a + " instance count " + b);
259               return true;
260           }
261       });
262     }
263     @Override
264     public <Context> boolean foreach(int setIndex, Procedure procedure, Context context, ClusterSupport support, Modifier modifier) throws DatabaseException {
265         return foreachComplete(setIndex, (ObjectProcedure<Context>)procedure, context, support, modifier);
266     }
267 }
268 class ForeachPredicate<Context>
269 implements ClusterI.ObjectProcedure<Context> {
270     private TIntHashSet completeTypes = new TIntHashSet();
271     private ClusterI.PredicateProcedure<Context> procedure; 
272     public ForeachPredicate(ClusterI.PredicateProcedure<Context>
273         procedure, ClusterSupport support, Modifier modifier) {
274         this.procedure = procedure;
275     }
276     @Override
277     public boolean execute(Context context, int completeRef) {
278         ClusterI.CompleteTypeEnum completeType = ClusterTraits.completeReferenceGetType(completeRef);
279         if (!completeTypes.contains(completeType.getValue())) {
280             completeTypes.add(completeType.getValue());
281             try {
282                 int pKey = ClusterTraitsBase.getCompleteTypeResourceKeyFromEnum(completeType);
283                 if (procedure.execute(context, pKey, 0))
284                     return true; // loop broken by procedure
285             } catch (DatabaseException e) {
286                 e.printStackTrace();
287                 return false;
288             }
289         }
290         return false;
291     }
292     
293 }
294 class ForeachObject<Context>
295 implements ClusterI.ObjectProcedure<Context> {
296     private ClusterI.ObjectProcedure<Context> procedure; 
297     private Modifier modifier;
298     private ClusterI.CompleteTypeEnum completeType;
299     public ForeachObject(ClusterI.ObjectProcedure<Context>
300         procedure, ClusterSupport support, Modifier modifier, ClusterI.CompleteTypeEnum completeType) {
301         this.procedure = procedure;
302         this.modifier = modifier;
303         this.completeType = completeType;
304     }
305     @Override
306     public boolean execute(Context context, int completeRef) throws DatabaseException {
307         ClusterI.CompleteTypeEnum completeType2 = ClusterTraits.completeReferenceGetType(completeRef);
308         if (completeType == completeType2) {
309             int clusterIndex = ClusterTraits.completeReferenceGetForeignIndex(completeRef);
310             int resourceIndex = ClusterTraits.completeReferenceGetResourceIndex(completeRef);
311             if (0 == clusterIndex) {
312                 int externalRef;
313                 if (null == modifier)
314                     externalRef = resourceIndex;
315                 else
316                     externalRef = modifier.execute(resourceIndex);
317                 return procedure.execute(context, externalRef);
318             } else {
319                 try {
320                     int externalRef = ClusterTraits.createForeignReference(clusterIndex, resourceIndex);
321                     if (null != modifier)
322                         externalRef = modifier.execute(externalRef);
323                     return procedure.execute(context, externalRef);
324                 } catch (DatabaseException e) {
325                     e.printStackTrace();
326                     return false; // continue looping
327                 }
328             }
329         }
330         return false; // continue looping
331     }
332     
333 }