-/*******************************************************************************\r
- * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
- * in Industry THTH ry.\r
- * All rights reserved. This program and the accompanying materials\r
- * are made available under the terms of the Eclipse Public License v1.0\r
- * which accompanies this distribution, and is available at\r
- * http://www.eclipse.org/legal/epl-v10.html\r
- *\r
- * Contributors:\r
- * VTT Technical Research Centre of Finland - initial API and implementation\r
- *******************************************************************************/\r
-package org.simantics.db.procore.cluster;\r
-\r
-import gnu.trove.map.hash.TIntIntHashMap;\r
-import gnu.trove.procedure.TIntIntProcedure;\r
-import gnu.trove.set.hash.TIntHashSet;\r
-\r
-import org.simantics.db.exception.DatabaseException;\r
-import org.simantics.db.exception.ValidationException;\r
-import org.simantics.db.impl.ClusterBase;\r
-import org.simantics.db.impl.ClusterI;\r
-import org.simantics.db.impl.ClusterI.CompleteTypeEnum;\r
-import org.simantics.db.impl.ClusterI.ObjectProcedure;\r
-import org.simantics.db.impl.ClusterI.Procedure;\r
-import org.simantics.db.impl.ClusterSupport;\r
-import org.simantics.db.impl.ClusterTraitsBase;\r
-import org.simantics.db.impl.Modifier;\r
-import org.simantics.db.impl.Table;\r
-import org.simantics.db.impl.TableFactory;\r
-import org.simantics.db.impl.TableIntAllocatorAdapter;\r
-import org.simantics.db.impl.TableSizeListener;\r
-import org.simantics.db.procore.cluster.TableIntArraySet.Ints;\r
-\r
-public class CompleteTable extends Table<int[]> {\r
- public CompleteTable(TableSizeListener sizeListener, int[] header, int headerBase) {\r
- super(TableFactory.getIntFactory(), sizeListener, header, headerBase);\r
- }\r
- public CompleteTable(TableSizeListener sizeListener, int[] header, int headerBase, int[] ints) {\r
- super(TableFactory.getIntFactory(), sizeListener, header, headerBase, ints);\r
- }\r
- final int createCompleteArraySet(int o1, int o2)\r
- throws DatabaseException {\r
- if (0 == o1 || o1 == o2)\r
- throw new DatabaseException("Illegal argument to createObejctArray");\r
- int[] obs = new int[2];\r
- obs[0] = o1;\r
- obs[1] = o2;\r
- int hashBase = TableIntArraySet.create(obs, new TableIntAllocatorAdapter(this));\r
- return convertRealIndexToTableIndex(hashBase);\r
- }\r
- final void deleteCompleteSet(int index)\r
- throws DatabaseException {\r
- int hashBase = checkIndexAndGetRealIndex(index, 0);\r
- if (TableIntArraySet.isArraySet(getTable(), hashBase)) {\r
- int capacity = TableIntArraySet.getAllocatedSize(getTable(), hashBase);\r
- int elementIndex = index - TableIntArraySet.HeaderSize;\r
- deleteOldElement(elementIndex, capacity);\r
- } else {\r
- int capacity = TableIntSet.getAllocatedSize(getTable(), hashBase);\r
- int elementIndex = index - TableIntSet.HeaderSize;\r
- deleteOldElement(elementIndex, capacity);\r
- }\r
- }\r
- final int getCompleteSetSize(int objectIndex) {\r
- int hashBase = checkIndexAndGetRealIndex(objectIndex, 0);\r
- if (TableIntArraySet.isArraySet(getTable(), hashBase))\r
- return TableIntArraySet.getSize(getTable(), hashBase);\r
- else\r
- return TableIntSet.getSize(getTable(), hashBase);\r
- }\r
- /**\r
- * @param setIndex\r
- * @param oResourceIndex\r
- * @return zero if complete already in the set else index of the set\r
- */\r
- final int addComplete(int setIndex, int oResourceIndex)\r
- throws DatabaseException {\r
- int hashBase = checkIndexAndGetRealIndex(setIndex, 0);\r
- int newHashBase;\r
- if (TableIntArraySet.isArraySet(getTable(), hashBase)) {\r
- if (TableIntArraySet.getSize(getTable(), hashBase) < 5)\r
- newHashBase = TableIntArraySet.addInt(getTable(), hashBase, oResourceIndex, new TableIntAllocatorAdapter(this));\r
- else {\r
- Ints ints = TableIntArraySet.getIntsIfValueNotFound(getTable(), hashBase, oResourceIndex);\r
- if (ints.found)\r
- return 0; // old object, not modified \r
- this.deleteCompleteSet(setIndex);\r
- newHashBase = TableIntSet.create(ints.ints, new TableIntAllocatorAdapter(this));\r
- assert(0 != newHashBase);\r
- }\r
- } else\r
- newHashBase = TableIntSet.addInt(getTable(), hashBase, oResourceIndex, new TableIntAllocatorAdapter(this));\r
- if (0 == newHashBase)\r
- return 0; // old object, not modified\r
- int ni = convertRealIndexToTableIndex(newHashBase);\r
- return ni;\r
- }\r
- final int removeLast(int setIndex)\r
- throws DatabaseException {\r
- int hashBase = checkIndexAndGetRealIndex(setIndex, 0);\r
- int[] table = getTable();\r
- int ref;\r
- if (TableIntArraySet.isArraySet(table, hashBase))\r
- ref = TableIntArraySet.removeIntLast(table, hashBase);\r
- else {\r
- ref = TableIntSet.removeIntLast(table, hashBase);\r
- }\r
- deleteCompleteSet(setIndex);\r
- return ref;\r
- }\r
- /**\r
- * @param setIndex\r
- * @param oResourceIndex\r
- * @return number of objects after removal.\r
- */\r
- final int removeComplete(int setIndex, int oResourceIndex)\r
- throws DatabaseException {\r
- int hashBase = checkIndexAndGetRealIndex(setIndex, 0);\r
- int[] table = getTable();\r
- if (TableIntArraySet.isArraySet(table, hashBase))\r
- return TableIntArraySet.removeInt(table, hashBase, oResourceIndex);\r
- else {\r
- TableIntSet.removeInt(table, hashBase, oResourceIndex);\r
- return TableIntSet.getSize(table, hashBase);\r
- }\r
- }\r
- final public <Context> boolean foreachComplete(final int setIndex,\r
- final ClusterI.ObjectProcedure<Context> procedure, final Context context, final ClusterSupport support,\r
- final Modifier modifier) throws DatabaseException {\r
- final int hashBase = checkIndexAndGetRealIndex(setIndex, 0);\r
- boolean ret;\r
- if (TableIntArraySet.isArraySet(getTable(), hashBase))\r
- ret = TableIntArraySet.foreachInt(getTable(), hashBase, procedure, context, modifier);\r
- else\r
- ret = TableIntSet.foreachInt(getTable(), hashBase, procedure, context, modifier);\r
- return ret;\r
- }\r
- public <Context> boolean foreachPredicate(int setIndex,\r
- ClusterI.PredicateProcedure<Context> procedure,\r
- Context context, ClusterSupport support, Modifier modifier)\r
- throws DatabaseException {\r
- ForeachPredicate<Context> t = new ForeachPredicate<Context>(procedure, support, modifier);\r
- return foreachComplete(setIndex, t, context, null, null);\r
- }\r
- \r
- public <Context> boolean foreachObject(int setIndex,\r
- ClusterI.ObjectProcedure<Context> procedure,\r
- Context context, ClusterSupport support, Modifier modifier,\r
- ClusterI.CompleteTypeEnum completeType)\r
- throws DatabaseException {\r
- ForeachObject<Context> t = new ForeachObject<Context>\r
- (procedure, support, modifier, completeType);\r
- return foreachComplete(setIndex, t, context, null, null);\r
- }\r
- \r
- private void checkEntry(ClusterBase cluster, int[] table, int index)\r
- throws DatabaseException {\r
- ClusterI.CompleteTypeEnum type = ClusterTraits.completeReferenceGetType(table[index]);\r
- if (type == CompleteTypeEnum.NotComplete)\r
- throw new ValidationException("Illegal CompleteTable entry type. Entry=" + table[index] + " index=" + index);\r
- int fi = ClusterTraits.completeReferenceGetForeignIndex(table[index]);\r
- int ri = ClusterTraits.completeReferenceGetResourceIndex(table[index]);\r
- if (0 != fi) {\r
- cluster.checkForeingIndex(fi);\r
- if (ri < 1 || ri > ClusterTraits.getMaxNumberOfResources())\r
- throw new ValidationException("Illegal CompleteTable foreign entry. Entry=" + table[index] + " index=" + index);\r
- } /*else if (ri < 1 || ri > cluster.getNumberOfResources(-1))\r
- throw new ValidationException("Illegal CompleteTable local entry. Entry=" + table[index] + " index=" + index);*/\r
- }\r
-\r
- private TIntHashSet checkIndexSet = null;\r
- public final void check(ClusterBase cluster)\r
- throws DatabaseException {\r
- if (null == checkIndexSet)\r
- checkIndexSet = new TIntHashSet();\r
- else\r
- checkIndexSet.clear();\r
- int count = 0;\r
- int[] table = getTable();\r
- int ps = getHeader().getOffset() + ZERO_SHIFT;\r
- int pe = ps + getTableSize();\r
- for (int p = ps; p < pe;) {\r
- int cap = p++;\r
- if (table[cap] >= 0) {\r
- int use = p++;\r
- int fre = p++;\r
- int max = p++;\r
- assert(table[cap] >= table[use] + table[fre]);\r
- assert(table[max] == table[cap] >> 1);\r
- assert(table[max]+1 >= table[use]);\r
- checkIndexSet.add(p - ps);\r
- for (int e = p + table[cap]; p<e; p++) {\r
- if (IntHashTrait.isFull(table[p])) \r
- checkEntry(cluster, table, p);\r
- }\r
- } else {\r
- final int size = -table[cap];\r
- assert(size > 0);\r
- checkIndexSet.add(p - ps);\r
- boolean free = false;\r
- for (int e = p + size; p<e; p++) {\r
- if (free)\r
- assert(table[p] == 0);\r
- else if (table[p] == 0)\r
- free = true;\r
- else\r
- checkEntry(cluster, table, p);\r
- }\r
- }\r
- count++;\r
- }\r
- assert(getHeader().getCount() <= count); // deleted objects are not recognized\r
- }\r
- public final void checkCompleteSetIndex(ClusterBase cluster, int i)\r
- throws DatabaseException {\r
- if (null == checkIndexSet)\r
- check(cluster); // builds checkIndexSet\r
- if (!checkIndexSet.contains(i-ZERO_SHIFT))\r
- throw new ValidationException("Illegal object set index=" + i);\r
- }\r
- final void printDebugInfo() {\r
- int count = 0;\r
- int[] table = getTable();\r
- int ps = getHeader().getOffset() + ZERO_SHIFT;\r
- int pe = ps + getTableSize();\r
- TIntIntHashMap stat = new TIntIntHashMap();\r
- TIntIntHashMap stat2 = new TIntIntHashMap();\r
- for (int p=ps; p<pe;) {\r
- int cap = p++;\r
- if (table[cap] >= 0) {\r
- int use = p++;\r
- int fre = p++;\r
- int max = p++;\r
- assert(table[cap] >= table[use] + table[fre]);\r
- assert(table[max] == table[cap] >> 1);\r
- p += table[cap];\r
- int val = stat.get(table[use]) + 1;\r
- stat.put(table[use], val);\r
- } else {\r
- final int size = -table[cap];\r
- int val = stat2.get(size) + 1;\r
- stat2.put(size, val);\r
- p += size;\r
- }\r
- count++;\r
- }\r
- assert(getHeader().getCount() == count);\r
- stat.forEachEntry(new TIntIntProcedure() {\r
- @Override\r
- public boolean execute(int a, int b) {\r
- System.out.println("complete set capacity " + a + " instance count " + b);\r
- return true;\r
- }\r
- });\r
- stat2.forEachEntry(new TIntIntProcedure() {\r
- @Override\r
- public boolean execute(int a, int b) {\r
- System.out.println("complete array set capacity " + a + " instance count " + b);\r
- return true;\r
- }\r
- });\r
- }\r
- @Override\r
- public <Context> boolean foreach(int setIndex, Procedure procedure, Context context, ClusterSupport support, Modifier modifier) throws DatabaseException {\r
- return foreachComplete(setIndex, (ObjectProcedure<Context>)procedure, context, support, modifier);\r
- }\r
-}\r
-class ForeachPredicate<Context>\r
-implements ClusterI.ObjectProcedure<Context> {\r
- private TIntHashSet completeTypes = new TIntHashSet();\r
- private ClusterI.PredicateProcedure<Context> procedure; \r
- public ForeachPredicate(ClusterI.PredicateProcedure<Context>\r
- procedure, ClusterSupport support, Modifier modifier) {\r
- this.procedure = procedure;\r
- }\r
- @Override\r
- public boolean execute(Context context, int completeRef) {\r
- ClusterI.CompleteTypeEnum completeType = ClusterTraits.completeReferenceGetType(completeRef);\r
- if (!completeTypes.contains(completeType.getValue())) {\r
- completeTypes.add(completeType.getValue());\r
- try {\r
- int pKey = ClusterTraitsBase.getCompleteTypeResourceKeyFromEnum(completeType);\r
- if (procedure.execute(context, pKey, 0))\r
- return true; // loop broken by procedure\r
- } catch (DatabaseException e) {\r
- e.printStackTrace();\r
- return false;\r
- }\r
- }\r
- return false;\r
- }\r
- \r
-}\r
-class ForeachObject<Context>\r
-implements ClusterI.ObjectProcedure<Context> {\r
- private ClusterI.ObjectProcedure<Context> procedure; \r
- private Modifier modifier;\r
- private ClusterI.CompleteTypeEnum completeType;\r
- public ForeachObject(ClusterI.ObjectProcedure<Context>\r
- procedure, ClusterSupport support, Modifier modifier, ClusterI.CompleteTypeEnum completeType) {\r
- this.procedure = procedure;\r
- this.modifier = modifier;\r
- this.completeType = completeType;\r
- }\r
- @Override\r
- public boolean execute(Context context, int completeRef) throws DatabaseException {\r
- ClusterI.CompleteTypeEnum completeType2 = ClusterTraits.completeReferenceGetType(completeRef);\r
- if (completeType == completeType2) {\r
- int clusterIndex = ClusterTraits.completeReferenceGetForeignIndex(completeRef);\r
- int resourceIndex = ClusterTraits.completeReferenceGetResourceIndex(completeRef);\r
- if (0 == clusterIndex) {\r
- int externalRef;\r
- if (null == modifier)\r
- externalRef = resourceIndex;\r
- else\r
- externalRef = modifier.execute(resourceIndex);\r
- return procedure.execute(context, externalRef);\r
- } else {\r
- try {\r
- int externalRef = ClusterTraits.createForeignReference(clusterIndex, resourceIndex);\r
- if (null != modifier)\r
- externalRef = modifier.execute(externalRef);\r
- return procedure.execute(context, externalRef);\r
- } catch (DatabaseException e) {\r
- e.printStackTrace();\r
- return false; // continue looping\r
- }\r
- }\r
- }\r
- return false; // continue looping\r
- }\r
- \r
+/*******************************************************************************
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management
+ * in Industry THTH ry.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * VTT Technical Research Centre of Finland - initial API and implementation
+ *******************************************************************************/
+package org.simantics.db.procore.cluster;
+
+import gnu.trove.map.hash.TIntIntHashMap;
+import gnu.trove.procedure.TIntIntProcedure;
+import gnu.trove.set.hash.TIntHashSet;
+
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.exception.ValidationException;
+import org.simantics.db.impl.ClusterBase;
+import org.simantics.db.impl.ClusterI;
+import org.simantics.db.impl.ClusterI.CompleteTypeEnum;
+import org.simantics.db.impl.ClusterI.ObjectProcedure;
+import org.simantics.db.impl.ClusterI.Procedure;
+import org.simantics.db.impl.ClusterSupport;
+import org.simantics.db.impl.ClusterTraitsBase;
+import org.simantics.db.impl.Modifier;
+import org.simantics.db.impl.Table;
+import org.simantics.db.impl.TableFactory;
+import org.simantics.db.impl.TableIntAllocatorAdapter;
+import org.simantics.db.impl.TableSizeListener;
+import org.simantics.db.procore.cluster.TableIntArraySet.Ints;
+
+public class CompleteTable extends Table<int[]> {
+ public CompleteTable(TableSizeListener sizeListener, int[] header, int headerBase) {
+ super(TableFactory.getIntFactory(), sizeListener, header, headerBase);
+ }
+ public CompleteTable(TableSizeListener sizeListener, int[] header, int headerBase, int[] ints) {
+ super(TableFactory.getIntFactory(), sizeListener, header, headerBase, ints);
+ }
+ final int createCompleteArraySet(int o1, int o2)
+ throws DatabaseException {
+ if (0 == o1 || o1 == o2)
+ throw new DatabaseException("Illegal argument to createObejctArray");
+ int[] obs = new int[2];
+ obs[0] = o1;
+ obs[1] = o2;
+ int hashBase = TableIntArraySet.create(obs, new TableIntAllocatorAdapter(this));
+ return convertRealIndexToTableIndex(hashBase);
+ }
+ final void deleteCompleteSet(int index)
+ throws DatabaseException {
+ int hashBase = checkIndexAndGetRealIndex(index, 0);
+ if (TableIntArraySet.isArraySet(getTable(), hashBase)) {
+ int capacity = TableIntArraySet.getAllocatedSize(getTable(), hashBase);
+ int elementIndex = index - TableIntArraySet.HeaderSize;
+ deleteOldElement(elementIndex, capacity);
+ } else {
+ int capacity = TableIntSet.getAllocatedSize(getTable(), hashBase);
+ int elementIndex = index - TableIntSet.HeaderSize;
+ deleteOldElement(elementIndex, capacity);
+ }
+ }
+ final int getCompleteSetSize(int objectIndex) {
+ int hashBase = checkIndexAndGetRealIndex(objectIndex, 0);
+ if (TableIntArraySet.isArraySet(getTable(), hashBase))
+ return TableIntArraySet.getSize(getTable(), hashBase);
+ else
+ return TableIntSet.getSize(getTable(), hashBase);
+ }
+ /**
+ * @param setIndex
+ * @param oResourceIndex
+ * @return zero if complete already in the set else index of the set
+ */
+ final int addComplete(int setIndex, int oResourceIndex)
+ throws DatabaseException {
+ int hashBase = checkIndexAndGetRealIndex(setIndex, 0);
+ int newHashBase;
+ if (TableIntArraySet.isArraySet(getTable(), hashBase)) {
+ if (TableIntArraySet.getSize(getTable(), hashBase) < 5)
+ newHashBase = TableIntArraySet.addInt(getTable(), hashBase, oResourceIndex, new TableIntAllocatorAdapter(this));
+ else {
+ Ints ints = TableIntArraySet.getIntsIfValueNotFound(getTable(), hashBase, oResourceIndex);
+ if (ints.found)
+ return 0; // old object, not modified
+ this.deleteCompleteSet(setIndex);
+ newHashBase = TableIntSet.create(ints.ints, new TableIntAllocatorAdapter(this));
+ assert(0 != newHashBase);
+ }
+ } else
+ newHashBase = TableIntSet.addInt(getTable(), hashBase, oResourceIndex, new TableIntAllocatorAdapter(this));
+ if (0 == newHashBase)
+ return 0; // old object, not modified
+ int ni = convertRealIndexToTableIndex(newHashBase);
+ return ni;
+ }
+ final int removeLast(int setIndex)
+ throws DatabaseException {
+ int hashBase = checkIndexAndGetRealIndex(setIndex, 0);
+ int[] table = getTable();
+ int ref;
+ if (TableIntArraySet.isArraySet(table, hashBase))
+ ref = TableIntArraySet.removeIntLast(table, hashBase);
+ else {
+ ref = TableIntSet.removeIntLast(table, hashBase);
+ }
+ deleteCompleteSet(setIndex);
+ return ref;
+ }
+ /**
+ * @param setIndex
+ * @param oResourceIndex
+ * @return number of objects after removal.
+ */
+ final int removeComplete(int setIndex, int oResourceIndex)
+ throws DatabaseException {
+ int hashBase = checkIndexAndGetRealIndex(setIndex, 0);
+ int[] table = getTable();
+ if (TableIntArraySet.isArraySet(table, hashBase))
+ return TableIntArraySet.removeInt(table, hashBase, oResourceIndex);
+ else {
+ TableIntSet.removeInt(table, hashBase, oResourceIndex);
+ return TableIntSet.getSize(table, hashBase);
+ }
+ }
+ final public <Context> boolean foreachComplete(final int setIndex,
+ final ClusterI.ObjectProcedure<Context> procedure, final Context context, final ClusterSupport support,
+ final Modifier modifier) throws DatabaseException {
+ final int hashBase = checkIndexAndGetRealIndex(setIndex, 0);
+ boolean ret;
+ if (TableIntArraySet.isArraySet(getTable(), hashBase))
+ ret = TableIntArraySet.foreachInt(getTable(), hashBase, procedure, context, modifier);
+ else
+ ret = TableIntSet.foreachInt(getTable(), hashBase, procedure, context, modifier);
+ return ret;
+ }
+ public <Context> boolean foreachPredicate(int setIndex,
+ ClusterI.PredicateProcedure<Context> procedure,
+ Context context, ClusterSupport support, Modifier modifier)
+ throws DatabaseException {
+ ForeachPredicate<Context> t = new ForeachPredicate<Context>(procedure, support, modifier);
+ return foreachComplete(setIndex, t, context, null, null);
+ }
+
+ public <Context> boolean foreachObject(int setIndex,
+ ClusterI.ObjectProcedure<Context> procedure,
+ Context context, ClusterSupport support, Modifier modifier,
+ ClusterI.CompleteTypeEnum completeType)
+ throws DatabaseException {
+ ForeachObject<Context> t = new ForeachObject<Context>
+ (procedure, support, modifier, completeType);
+ return foreachComplete(setIndex, t, context, null, null);
+ }
+
+ private void checkEntry(ClusterBase cluster, int[] table, int index)
+ throws DatabaseException {
+ ClusterI.CompleteTypeEnum type = ClusterTraits.completeReferenceGetType(table[index]);
+ if (type == CompleteTypeEnum.NotComplete)
+ throw new ValidationException("Illegal CompleteTable entry type. Entry=" + table[index] + " index=" + index);
+ int fi = ClusterTraits.completeReferenceGetForeignIndex(table[index]);
+ int ri = ClusterTraits.completeReferenceGetResourceIndex(table[index]);
+ if (0 != fi) {
+ cluster.checkForeingIndex(fi);
+ if (ri < 1 || ri > ClusterTraits.getMaxNumberOfResources())
+ throw new ValidationException("Illegal CompleteTable foreign entry. Entry=" + table[index] + " index=" + index);
+ } /*else if (ri < 1 || ri > cluster.getNumberOfResources(-1))
+ throw new ValidationException("Illegal CompleteTable local entry. Entry=" + table[index] + " index=" + index);*/
+ }
+
+ private TIntHashSet checkIndexSet = null;
+ public final void check(ClusterBase cluster)
+ throws DatabaseException {
+ if (null == checkIndexSet)
+ checkIndexSet = new TIntHashSet();
+ else
+ checkIndexSet.clear();
+ int count = 0;
+ int[] table = getTable();
+ int ps = getHeader().getOffset() + ZERO_SHIFT;
+ int pe = ps + getTableSize();
+ for (int p = ps; p < pe;) {
+ int cap = p++;
+ if (table[cap] >= 0) {
+ int use = p++;
+ int fre = p++;
+ int max = p++;
+ assert(table[cap] >= table[use] + table[fre]);
+ assert(table[max] == table[cap] >> 1);
+ assert(table[max]+1 >= table[use]);
+ checkIndexSet.add(p - ps);
+ for (int e = p + table[cap]; p<e; p++) {
+ if (IntHashTrait.isFull(table[p]))
+ checkEntry(cluster, table, p);
+ }
+ } else {
+ final int size = -table[cap];
+ assert(size > 0);
+ checkIndexSet.add(p - ps);
+ boolean free = false;
+ for (int e = p + size; p<e; p++) {
+ if (free)
+ assert(table[p] == 0);
+ else if (table[p] == 0)
+ free = true;
+ else
+ checkEntry(cluster, table, p);
+ }
+ }
+ count++;
+ }
+ assert(getHeader().getCount() <= count); // deleted objects are not recognized
+ }
+ public final void checkCompleteSetIndex(ClusterBase cluster, int i)
+ throws DatabaseException {
+ if (null == checkIndexSet)
+ check(cluster); // builds checkIndexSet
+ if (!checkIndexSet.contains(i-ZERO_SHIFT))
+ throw new ValidationException("Illegal object set index=" + i);
+ }
+ final void printDebugInfo() {
+ int count = 0;
+ int[] table = getTable();
+ int ps = getHeader().getOffset() + ZERO_SHIFT;
+ int pe = ps + getTableSize();
+ TIntIntHashMap stat = new TIntIntHashMap();
+ TIntIntHashMap stat2 = new TIntIntHashMap();
+ for (int p=ps; p<pe;) {
+ int cap = p++;
+ if (table[cap] >= 0) {
+ int use = p++;
+ int fre = p++;
+ int max = p++;
+ assert(table[cap] >= table[use] + table[fre]);
+ assert(table[max] == table[cap] >> 1);
+ p += table[cap];
+ int val = stat.get(table[use]) + 1;
+ stat.put(table[use], val);
+ } else {
+ final int size = -table[cap];
+ int val = stat2.get(size) + 1;
+ stat2.put(size, val);
+ p += size;
+ }
+ count++;
+ }
+ assert(getHeader().getCount() == count);
+ stat.forEachEntry(new TIntIntProcedure() {
+ @Override
+ public boolean execute(int a, int b) {
+ System.out.println("complete set capacity " + a + " instance count " + b);
+ return true;
+ }
+ });
+ stat2.forEachEntry(new TIntIntProcedure() {
+ @Override
+ public boolean execute(int a, int b) {
+ System.out.println("complete array set capacity " + a + " instance count " + b);
+ return true;
+ }
+ });
+ }
+ @Override
+ public <Context> boolean foreach(int setIndex, Procedure procedure, Context context, ClusterSupport support, Modifier modifier) throws DatabaseException {
+ return foreachComplete(setIndex, (ObjectProcedure<Context>)procedure, context, support, modifier);
+ }
+}
+class ForeachPredicate<Context>
+implements ClusterI.ObjectProcedure<Context> {
+ private TIntHashSet completeTypes = new TIntHashSet();
+ private ClusterI.PredicateProcedure<Context> procedure;
+ public ForeachPredicate(ClusterI.PredicateProcedure<Context>
+ procedure, ClusterSupport support, Modifier modifier) {
+ this.procedure = procedure;
+ }
+ @Override
+ public boolean execute(Context context, int completeRef) {
+ ClusterI.CompleteTypeEnum completeType = ClusterTraits.completeReferenceGetType(completeRef);
+ if (!completeTypes.contains(completeType.getValue())) {
+ completeTypes.add(completeType.getValue());
+ try {
+ int pKey = ClusterTraitsBase.getCompleteTypeResourceKeyFromEnum(completeType);
+ if (procedure.execute(context, pKey, 0))
+ return true; // loop broken by procedure
+ } catch (DatabaseException e) {
+ e.printStackTrace();
+ return false;
+ }
+ }
+ return false;
+ }
+
+}
+class ForeachObject<Context>
+implements ClusterI.ObjectProcedure<Context> {
+ private ClusterI.ObjectProcedure<Context> procedure;
+ private Modifier modifier;
+ private ClusterI.CompleteTypeEnum completeType;
+ public ForeachObject(ClusterI.ObjectProcedure<Context>
+ procedure, ClusterSupport support, Modifier modifier, ClusterI.CompleteTypeEnum completeType) {
+ this.procedure = procedure;
+ this.modifier = modifier;
+ this.completeType = completeType;
+ }
+ @Override
+ public boolean execute(Context context, int completeRef) throws DatabaseException {
+ ClusterI.CompleteTypeEnum completeType2 = ClusterTraits.completeReferenceGetType(completeRef);
+ if (completeType == completeType2) {
+ int clusterIndex = ClusterTraits.completeReferenceGetForeignIndex(completeRef);
+ int resourceIndex = ClusterTraits.completeReferenceGetResourceIndex(completeRef);
+ if (0 == clusterIndex) {
+ int externalRef;
+ if (null == modifier)
+ externalRef = resourceIndex;
+ else
+ externalRef = modifier.execute(resourceIndex);
+ return procedure.execute(context, externalRef);
+ } else {
+ try {
+ int externalRef = ClusterTraits.createForeignReference(clusterIndex, resourceIndex);
+ if (null != modifier)
+ externalRef = modifier.execute(externalRef);
+ return procedure.execute(context, externalRef);
+ } catch (DatabaseException e) {
+ e.printStackTrace();
+ return false; // continue looping
+ }
+ }
+ }
+ return false; // continue looping
+ }
+
}
\ No newline at end of file