/*
* Created on 01.12.2007
* Caleido AG, All Rights Reserved
* Author: Luzius Meisser
*/
package quickbase.internal.index;
import gnu.trove.TIntIntHashMap;
import gnu.trove.TIntIntProcedure;
import gnu.trove.TIntLongHashMap;
import gnu.trove.TIntLongProcedure;
import gnu.trove.TIntProcedure;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
public class AdaptingIntLongMap {
private static final byte USE_INTS = 1;
private static final byte USE_LONGS = 2;
private TIntIntHashMap index;
private TIntLongHashMap longIndex;
public AdaptingIntLongMap(int initialSize) {
this.index = new TIntIntHashMap(initialSize);
}
public AdaptingIntLongMap(DataInputStream dis) throws IOException {
byte type = dis.readByte();
int entries = dis.readInt();
if (type == USE_INTS) {
index = new TIntIntHashMap(entries);
for (int i = 0; i < entries; i++) {
int key = dis.readInt();
int value = dis.readInt();
if (value < 0){
throw new IOException("Negative value");
}
index.put(key, value);
}
} else if (type == USE_LONGS) {
longIndex = new TIntLongHashMap(entries);
for (int i = 0; i < entries; i++) {
int key = dis.readInt();
long value = dis.readLong();
if (value < 0){
throw new IOException("Negative value");
}
longIndex.put(key, value);
}
} else {
throw new IOException("Unexpected data: " + type);
}
}
public long get(int hash) {
if (index == null) {
if (longIndex.contains(hash)) {
return longIndex.get(hash);
} else {
return -1;
}
} else {
if (index.contains(hash)) {
return index.get(hash);
} else {
return -1;
}
}
}
public void put(int hash, long position) {
assert position >= 0;
if (index == null) {
longIndex.put(hash, position);
} else {
if (position > Integer.MAX_VALUE) {
convertMap();
longIndex.put(hash, position);
} else {
index.put(hash, (int) position);
}
}
}
private void convertMap() {
final TIntLongHashMap longIndex = new TIntLongHashMap(index.size());
index.forEachEntry(new TIntIntProcedure() {
public boolean execute(int a, int b) {
longIndex.put(a, b);
return true;
}
});
this.longIndex = longIndex;
this.index = null;
}
public void write(final DataOutputStream dos) throws IOException {
final IOException[] ex = new IOException[1];
if (index == null) {
dos.writeByte(USE_LONGS);
dos.writeInt(longIndex.size());
longIndex.forEachEntry(new TIntLongProcedure() {
public boolean execute(int a, long b) {
try {
dos.writeInt(a);
dos.writeLong(b);
return true;
} catch (IOException e) {
ex[0] = e;
return false;
}
}
});
} else {
dos.writeByte(USE_INTS);
dos.writeInt(index.size());
index.forEachEntry(new TIntIntProcedure() {
public boolean execute(int a, int b) {
try {
dos.writeInt(a);
dos.writeInt(b);
return true;
} catch (IOException e) {
ex[0] = e;
return false;
}
}
});
}
if (ex[0] != null) {
throw ex[0];
}
}
public void visitKeys(TIntProcedure visitor) {
if (index == null){
longIndex.forEachKey(visitor);
} else {
index.forEachKey(visitor);
}
}
}