0,0 → 1,216 |
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; |
} |
} |