// FilteredResourceUpgrader.java
// $Id: FilteredResourceUpgrader.java,v 1.2 1997/07/30 14:02:21 ylafon Exp $  
// (c) COPYRIGHT MIT and INRIA, 1997.
// Please first read the full copyright statement in file COPYRIGHT.html

package w3c.jigsaw.upgrade.from2to3;

import java.io.*;
import java.util.Vector;

class AttributeInfo {
    String name = null;
    short len = -1;
    byte value[] = null;
}

class FilterInfo {
    String className = null;
    Vector attrs = null;
}

public class FilteredResourceUpgrader extends ResourceUpgrader {
    String className = null;

    public Vector skipAttributes(DataInputStream in, boolean checkSlow) 
	throws IOException, ResourceUpgraderException
    {
	// Fast pickle: we loose...
	if ( checkSlow ) {
	    if ( in.readBoolean() ) 
		throw new ResourceUpgraderException("Can't upgrade fast "+
						    "pickled resources...");
	}
	// Slow pickle...cool:
	Vector attrs = new Vector();
	String name  = null;
	while ( ! (name = in.readUTF()).equals("") ) {
	    AttributeInfo info = new AttributeInfo();
	    info.name  = name;
	    info.len   = in.readShort();
	    info.value = new byte[(int) info.len];
	    in.read(info.value, 0, (int) info.len);
	    attrs.addElement(info);
	}
	return attrs;
    }

    public Vector skipAttributes(DataInputStream in) 
	throws IOException, ResourceUpgraderException
    {
	return skipAttributes(in, true);
    }

    public void pickleAttributes(DataOutputStream out
				 , String className
				 , Vector attrs)
	throws IOException
    {
	out.writeUTF(className);
	out.writeBoolean(false);
	for (int i = 0 ; i < attrs.size() ; i++) {
	    AttributeInfo info = (AttributeInfo) attrs.elementAt(i);
	    out.writeUTF(info.name);
	    out.writeShort(info.len);
	    out.write(info.value, 0, (int) info.len);
	}
    }

    public byte[] pickleFilters(Vector filters) 
	throws IOException
    {
	ByteArrayOutputStream bout = new ByteArrayOutputStream(512);
	DataOutputStream      out  = new DataOutputStream(bout);
	out.writeInt(filters.size());
	for (int i = 0 ; i < filters.size() ; i++) {
	    FilterInfo info = (FilterInfo) filters.elementAt(i);
	    pickleAttributes(out, info.className, info.attrs);
	    out.writeUTF("");
	}
	out.close();
	return bout.toByteArray();
    }

    public Vector skipFilters(DataInputStream in) 
	throws IOException, ResourceUpgraderException
    {
	int count = -1;
	try {
	    count = in.readInt();
	} catch (IOException ex) {
	    // That's to cope with a unknown bug (probably VOR - Very Old Res)
	    count = 0;
	}
	// No filters, that's easy
	if ( count == 0 )
	    return null;
	// Hard case, hack:
	Vector filters = new Vector();
	for (int i = 0 ; i < count ; i++) {
	    FilterInfo info = new FilterInfo();
	    info.className = in.readUTF();
	    info.attrs     = skipAttributes(in);
	    // Get rid of shadow attributes:
	    skipAttributes(in, false);
	    filters.addElement(info);
	}
	return filters;
    }

    public byte[] upgrade(byte oldbits[], int off, int len) {
	Vector attrs   = null;
	Vector filters = null;
	// Read in the old format:
	try {
	    DataInputStream in = (new DataInputStream
				  (new ByteArrayInputStream(oldbits
							    , off
							    , len)));
	    int oldlen = oldbits.length;
	    // Get the class name:
	    className = in.readUTF();
	    // Get the resource class and attributes
	    attrs = skipAttributes(in);
	    // Get the filters:
	    filters = skipFilters(in);
	    if ( filters == null )
		return oldbits;
	    in.close();
	} catch (Exception ex) {
	    // ex.printStackTrace();
	    return null;
	}
	// Write out the new format:
	try {
	    ByteArrayOutputStream bout = new ByteArrayOutputStream(512);
	    DataOutputStream      out  = new DataOutputStream(bout);
	    // Upgrade filters...
	    pickleAttributes(out, className, attrs);
	    // Dump the filters into a byte array and emit them as an attribute
	    byte frameBytes[] = pickleFilters(filters);
	    out.writeUTF("frames");
	    out.writeShort((short) frameBytes.length);
	    out.write(frameBytes, 0, frameBytes.length);
	    out.writeUTF("");
	    out.close();
	    return bout.toByteArray();
	} catch (Exception ex) {
	    // ex.printStackTrace();
	    return null;
	}
    }
    
    public byte[] upgrade(Class cls, DataInputStream in) {
	return null;
    }

    public FilteredResourceUpgrader() {
    }
}
