1 /*******************************************************************************
\r
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
\r
3 * in Industry THTH ry.
\r
4 * All rights reserved. This program and the accompanying materials
\r
5 * are made available under the terms of the Eclipse Public License v1.0
\r
6 * which accompanies this distribution, and is available at
\r
7 * http://www.eclipse.org/legal/epl-v10.html
\r
10 * VTT Technical Research Centre of Finland - initial API and implementation
\r
11 *******************************************************************************/
\r
12 package org.simantics.db.procore.cluster;
\r
14 import java.util.Arrays;
\r
15 import java.util.Map;
\r
16 import java.util.TreeMap;
\r
18 import org.simantics.db.exception.DatabaseException;
\r
19 import org.simantics.db.exception.ValidationException;
\r
20 import org.simantics.db.impl.ClusterI.ObjectProcedure;
\r
21 import org.simantics.db.impl.ClusterI.Procedure;
\r
22 import org.simantics.db.impl.ClusterSupport;
\r
23 import org.simantics.db.impl.Modifier;
\r
24 import org.simantics.db.impl.Table;
\r
25 import org.simantics.db.impl.TableFactory;
\r
26 import org.simantics.db.impl.TableSizeListener;
\r
28 public final class ValueTableSmall extends Table<byte[]> {
\r
29 private static final boolean DEBUG = ClusterImpl.DEBUG;
\r
30 public ValueTableSmall(TableSizeListener sizeListener, int[] header, int headerBase) {
\r
31 super(TableFactory.getByteFactory(), sizeListener, header, headerBase);
\r
33 public ValueTableSmall(TableSizeListener sizeListener, int[] header, int headerBase, byte[] bytes) {
\r
34 super(TableFactory.getByteFactory(), sizeListener, header, headerBase, bytes);
\r
36 private static final class IndexAndSize {
\r
37 int index; // Real index (zero based) to start of value data.
\r
38 short size; // Size of value data.
\r
40 private IndexAndSize checkIndexAndGetRealIndex(int index) {
\r
41 if (index < ZERO_SHIFT) // Index starts with ZERO_SHIFT.
\r
42 throw new IllegalArgumentException("Underflow, index=" + index);
\r
43 int tableSize = getTableSize();
\r
44 if (index >= tableSize) // Element size is at least two (one byte length and one byte data).
\r
45 throw new IllegalArgumentException("Overflow, index=" + index);
\r
46 int i = index + offset;
\r
47 byte[] table = getTable();
\r
48 IndexAndSize is = new IndexAndSize();
\r
49 is.size = table[i++];
\r
51 throw new IllegalArgumentException("Removed, index=" + index);
\r
52 if (is.size < 0) // two byte size
\r
53 is.size = (short)(((is.size & 0x7F) << 8) | (table[i++] & 0xFF));
\r
55 if (is.index + is.size > tableSize) // Element size too big.
\r
56 throw new IllegalArgumentException("Illegal size, index=" + is.index + " size=" + is.size);
\r
59 public byte[] getValue(int valueIndex) {
\r
60 IndexAndSize is = checkIndexAndGetRealIndex(valueIndex);
\r
61 byte[] value = new byte[is.size];
\r
62 System.arraycopy(table, is.index, value, 0, is.size);
\r
64 System.out.println("ValueTableSmall.getValue " + valueIndex + " " + Arrays.toString(value));
\r
67 char[] getString(int valueIndex) {
\r
68 IndexAndSize is = checkIndexAndGetRealIndex(valueIndex);
\r
69 final int size = is.size-1;
\r
70 char[] t = new char[size];
\r
71 int start = is.index;
\r
72 for(int i=0; i<size; i++, ++start)
\r
73 t[i] = (char)table[start];
\r
76 int setValue(int valueIndex, byte[] value, int offset, int length) {
\r
77 if (valueIndex != 0) // Modify old value.
\r
78 removeValue(valueIndex);
\r
79 return createValue(value, offset, length);
\r
81 int createValue(byte[] value, int voffset, int vsize) {
\r
82 if (vsize < 1 || vsize > (1<<15)-1)
\r
83 throw new IllegalArgumentException("Illegal internal value size=" + vsize + ".");
\r
89 int valueIndex = createNewElement(size);
\r
90 int i = checkIndexAndGetRealIndex(valueIndex, 1);
\r
92 table[i++] = (byte)((vsize >>> 8) | 1<<7); // msb
\r
93 table[i++] = (byte)(vsize & 0xFF); // lsb
\r
95 table[i++] = (byte)vsize;
\r
96 System.arraycopy(value, voffset, table, i, vsize);
\r
99 void removeValue(int valueIndex) {
\r
100 IndexAndSize is = checkIndexAndGetRealIndex(valueIndex);
\r
101 int length = is.size;
\r
102 int index = is.index;
\r
103 if (is.size > 0x7F) {
\r
106 table[index+1] = 0;
\r
112 deleteOldElement(valueIndex, length);
\r
114 // boolean isEqual(int valueIndex, byte[] value, int voffset, int vsize) {
\r
115 // return isEqual(valueIndex, value, 0, value.length);
\r
117 private TreeMap<Integer, Integer> valueMap =
\r
118 new TreeMap<Integer, Integer>();
\r
120 private int VALUE_SIZE = 0;
\r
121 private int VALUE_OFFSET = 0;
\r
122 public void checkValueInit()
\r
123 throws DatabaseException {
\r
125 final int s = getTableSize();
\r
126 final int c = getTableCapacity();
\r
127 if (s < 0 || s > c)
\r
128 throw new ValidationException("Illegal value table size=" + s + " cap=" + c);
\r
130 VALUE_OFFSET = getTableBase() - ValueTableSmall.ZERO_SHIFT;
\r
132 public void checkValue(int capacity, int index)
\r
133 throws DatabaseException {
\r
134 if (0 == capacity && 0 == index)
\r
137 throw new ValidationException("Illegal resource value capacity=" + capacity);
\r
139 throw new ValidationException("Illegal resource value index=" + index);
\r
140 if (VALUE_SIZE < capacity + index + VALUE_OFFSET)
\r
141 throw new ValidationException("Illegal resource value c=" + capacity +
\r
142 " i=" + index + " ts=" + VALUE_SIZE + " off=" + VALUE_OFFSET);
\r
143 // Duplicate index is allowed because new index is created only if new size is greater than old.
\r
144 Integer valueCap = valueMap.get(index);
\r
145 if (null == valueCap)
\r
146 valueMap.put(index, capacity);
\r
147 else if (capacity > valueCap)
\r
148 valueMap.put(index, capacity);
\r
150 valueMap.put(index, valueCap);
\r
152 public void checkValueFini()
\r
153 throws DatabaseException {
\r
155 for (Map.Entry<Integer, Integer> e : valueMap.entrySet()) {
\r
156 int i = e.getKey();
\r
157 int c = e.getValue();
\r
158 int cur = VALUE_OFFSET + i;
\r
160 throw new ValidationException("Index error with resource value c=" + c +
\r
161 " i=" + i + " ts=" + VALUE_SIZE + " off=" + VALUE_OFFSET);
\r
166 public <Context> boolean foreach(int setIndex, Procedure procedure, Context context, ClusterSupport support, Modifier modifier) throws DatabaseException {
\r
167 throw new UnsupportedOperationException();
\r