package org.wikiwebserver.distribute.util;

import java.io.*;
import java.util.*;

import org.wikiwebserver.distribute.interfaces.Persistable;

@SuppressWarnings({ "unchecked", "rawtypes" })
public class PersistableVector extends Vector implements Persistable {

    private static final long serialVersionUID = 1L;
    
    private static final int NULL = 0;
    private static final int INTEGER = 1;
    private static final int LONG = 2;
    private static final int STRING = 3;
    private static final int PERSISTABLE = 4;

    public void persist(DataOutputStream dout) throws IOException {

        int n = size();
        dout.writeInt(n);

        for(int i = 0; i < n; ++i){
        	Object obj = elementAt(i);
            
        	if (obj instanceof String){
                dout.writeByte(STRING);
                dout.writeUTF((String) obj);
            } 
        	else if (obj instanceof Integer){
                dout.writeByte(INTEGER);
                dout.writeInt(((Integer) obj).intValue());
            } 
        	else if (obj instanceof Long){
                dout.writeByte(LONG);
                dout.writeLong(((Long) obj).longValue());
            }         	
        	else if(obj instanceof Persistable){
                dout.writeByte(PERSISTABLE);
                dout.writeUTF(obj.getClass().getName());
                ((Persistable) obj).persist(dout);
            } 
        	else if(obj == null){
                dout.writeByte(NULL);
            } 
        	else {
                throw new IOException("Cannot persist object of type " +
                   obj.getClass().getName() );
            }
        }
    }

    public void resurrect(DataInputStream din) throws IOException {

        int n = din.readInt();

        for(int i = 0; i < n; ++i){
            
        	int type = din.readByte();
            if (type == NULL){
                addElement(null);
            }
            else if (type == INTEGER){
                addElement(new Integer(din.readInt()));
            } 
            else if (type == LONG){
                addElement(new Long(din.readLong()));
            }             
            else if(type == STRING){
                addElement(din.readUTF());
            } 
            else if(type == PERSISTABLE){
                String className = din.readUTF();
               
                try {
                    Class cl = Class.forName(className);
                    Object o = cl.newInstance();
                    ((Persistable) o).resurrect(din);
                    addElement(o);
                }
                catch (IOException e){
                    throw e;
                }
                catch (Exception e){
                    throw new IOException("Exception " +e.toString() );
                }
                
            } else {
               throw new IOException("Unknown type " + type );
            }
        }
    }
}

