Subversion Repositories Code-Repo

Rev

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;
        }
}