Blame | Last modification | View Log | RSS feed
import java.nio.ByteBuffer;
// Assisting class for converting classes to a byte array and vice versa
public class NodeSerializer {
private MemManager memoryManager;
// Constructor
public NodeSerializer(MemManager mem) {
memoryManager = mem;
}
// Removes the handle and subhandles for leaf nodes (city name)
public void removeHandle(Handle handle) {
PRQuadTreeNode node = handleToNode(handle);
if (node instanceof PRQuadTreeNodeFlyweight) {
return;
} else if (node instanceof PRQuadTreeNodeLeaf) {
byte[] array = new byte[memoryManager.getDataBlockSize(handle)];
memoryManager.get(array, handle);
ByteBuffer buffer = ByteBuffer.wrap(array);
int records = (int)buffer.get();
records = (int)buffer.get();
for (int i = 0; i < records; i++) {
// Remove the CityRecord and the name of the city
int addr = buffer.getInt();
Handle cityhandle = new Handle(addr);
removeCityRecordHandle(cityhandle);
}
}
memoryManager.remove(handle);
}
public void removeCityRecordHandle(Handle handle) {
// Remove the handle to the city name
byte[] data = new byte[memoryManager.getDataBlockSize(handle)];
memoryManager.get(data, handle);
ByteBuffer cityrecord = ByteBuffer.wrap(data);
Handle name = new Handle(cityrecord.getInt(8));
memoryManager.remove(name);
memoryManager.remove(handle);
}
// Resets the empty block list in the memory manager to the size of the file
public void clearMemory() {
memoryManager.clear();
}
// Print debug info from the memory manager
public void printDebug() {
memoryManager.printBuffer();
memoryManager.dump();
}
// Allocates the node onto disk and returns a handle to the node
public Handle nodeToHandle(PRQuadTreeNode node) {
if (node instanceof PRQuadTreeNodeInternal) {
byte[] array = nodeInternalToByteArray((PRQuadTreeNodeInternal)node);
Handle ret = memoryManager.insert(array, array.length);
return ret;
} else if (node instanceof PRQuadTreeNodeLeaf) {
byte[] array = nodeLeafToByteArray((PRQuadTreeNodeLeaf)node);
Handle ret = memoryManager.insert(array, array.length);
return ret;
} else {
Handle ret = new Handle(-1);
return ret;
}
}
// Reads a handle off the disk and returns the corresponding
public PRQuadTreeNode handleToNode(Handle handle) {
if (handle.getAddress() == -1) {
PRQuadTreeNodeFlyweight ret = new PRQuadTreeNodeFlyweight();
return ret;
} else {
byte[] array = new byte[memoryManager.getDataBlockSize(handle)];
memoryManager.get(array, handle);
return byteArrayToNode(array);
}
}
private byte[] stringToByteArray(String str) {
// Use ByteBuffer to serialize to bytes
byte[] byteArray = new byte[str.length() + 1];
byte[] bstr = str.getBytes();
ByteBuffer buffer = ByteBuffer.wrap(byteArray);
// Set first byte as the length
buffer.put((byte)bstr.length);
// Set remaining bytes as the string
buffer.put(bstr);
return byteArray;
}
private byte[] nodeInternalToByteArray(PRQuadTreeNodeInternal node) {
byte[] byteArray = new byte[17];
ByteBuffer buffer = ByteBuffer.wrap(byteArray);
buffer.put((byte)1);
buffer.putInt((int)node.getNW().getAddress());
buffer.putInt((int)node.getNE().getAddress());
buffer.putInt((int)node.getSW().getAddress());
buffer.putInt((int)node.getSE().getAddress());
return byteArray;
}
private byte[] nodeLeafToByteArray(PRQuadTreeNodeLeaf node) {
byte[] byteArray = new byte[14];
ByteBuffer buffer = ByteBuffer.wrap(byteArray);
// Set first byte to indicate leaf node
buffer.put((byte)0);
// Set second byte to hold number of records
buffer.put((byte)node.getCount());
CityRecord record = (CityRecord) node.getFirst();
buffer.putInt((int)cityRecordToHandle(record).getAddress());
record = (CityRecord) node.getNext(record);
while (record != null) {
buffer.putInt((int)cityRecordToHandle(record).getAddress());
record = (CityRecord) node.getNext(record);
}
return byteArray;
}
private String byteArrayToString(byte[] byteArray) {
ByteBuffer buffer = ByteBuffer.wrap(byteArray);
byte[] bstr = new byte[(int)buffer.get()];
buffer.get(bstr);
String str = new String(bstr);
return str;
}
private PRQuadTreeNode byteArrayToNode(byte[] data) {
ByteBuffer buffer = ByteBuffer.wrap(data);
// Internal node
byte b = buffer.get();
if (b == (byte)1) {
PRQuadTreeNodeInternal newNode = new PRQuadTreeNodeInternal(new Handle(-1), this);
Handle NW = new Handle(buffer.getInt());
Handle NE = new Handle(buffer.getInt());
Handle SW = new Handle(buffer.getInt());
Handle SE = new Handle(buffer.getInt());
newNode.setNW(NW);
newNode.setNE(NE);
newNode.setSW(SW);
newNode.setSE(SE);
return newNode;
// Leaf node
} else if (b == (byte)0) {
PRQuadTreeNodeLeaf newNode = new PRQuadTreeNodeLeaf(3);
int records = (int)buffer.get();
for (int i = 0; i < records; i++) {
int address = buffer.getInt();
Handle handle = new Handle(address);
CityRecord record = handleToCityRecord(handle);
newNode.insert(record);
}
return newNode;
} else {
return null;
}
}
public Handle cityRecordToHandle(CityRecord record) {
byte[] data = new byte[12];
ByteBuffer buffer = ByteBuffer.wrap(data);
byte[] cityname = stringToByteArray(record.getName());
Handle handle = memoryManager.insert(cityname, cityname.length);
buffer.putInt(record.getX());
buffer.putInt(record.getY());
buffer.putInt((int)handle.getAddress());
Handle ret = memoryManager.insert(data, 12);
return ret;
}
public CityRecord handleToCityRecord(Handle handle) {
byte[] data = new byte[12];
memoryManager.get(data, handle);
ByteBuffer buffer = ByteBuffer.wrap(data);
int x = buffer.getInt();
int y = buffer.getInt();
int addr = buffer.getInt();
Handle cityhandle = new Handle(addr);
byte[] city = new byte[memoryManager.getDataBlockSize(cityhandle)];
memoryManager.get(city, cityhandle);
String cityname = byteArrayToString(city);
CityRecord record = new CityRecord(cityname, x, y);
return record;
}
}