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

package w3c.jigsaw.upgrade.from1to2;

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

public class FilteredResourceUpgrader extends RawResourceUpgrader {

    protected void skipShadowAttributes(Class cls
					, DataInputStream in
					, Vector ret)
	throws IOException
    {
	// First stage: skip the AttributeHolder bytes:
	w3c.tools.store.Attribute attrs[] = null;
	attrs = w3c.tools.store.AttributeRegistry.getClassAttributes(cls);
	for (int i = 0 ; i < attrs.length ; i++) {
	    if ( attrs[i].getName().equals("store-entry") )
		continue;
	    if ( in.readBoolean() ) {
		System.out.println("got "+attrs[i].getName());
		ret.addElement(new UpgradeAttribute(attrs[i]
						    , attrs[i].unpickle(in)));
	    } 
	}
	return;
    }

    protected Vector skipShadowAttributes(Class cls, DataInputStream in) 
	throws IOException 
    {
	Vector ret = new Vector(8);
	skipShadowAttributes(cls, in, ret);
	return ret;
    }

    protected int skipFilters(Class cls, DataInputStream in
			      , Vector filters, Vector fattrs)
	throws IOException
    {
	// Fix the resource filters:
	int nfilters = in.readInt();
	for (int i = 0 ; i < nfilters; i++) {
	    filters.addElement(skipAttributeHolder(in));
	    fattrs.addElement(skipShadowAttributes(cls, in));
	}
	return nfilters;
    }

    protected void dumpFilters(DataOutputStream out
			       , int nfilters
			       , Vector filters
			       , Vector fattrs)
	throws IOException
    {
	out.writeInt(nfilters);
	for (int i = 0 ; i < nfilters ; i++) {
	    Vector resource = (Vector) filters.elementAt(i);
	    Vector shadow   = (Vector) fattrs.elementAt(i);
	    // Dump the filters' resource:
	    out.writeUTF(((Class) resource.elementAt(0)).getName());
	    out.writeBoolean(false);
	    resource.removeElementAt(0);
	    pickleAttributes(resource, out);
	    // Dump the filters' shadow attributes:
	    pickleAttributes(shadow, out);
	}
    }

    public byte[] upgrade(byte oldbits[], int off, int len) {
	Vector filters  = new Vector(8);
	Vector fattrs   = new Vector(8);
	Class  cls      = null;
	int    nfilters = 0;
	Vector rattrs   = null;

	// Read in the old format:
	try {
	    DataInputStream in     = (new DataInputStream
				      (new ByteArrayInputStream(oldbits
								, off
								, len)));
	    int                  oldlen = oldbits.length;
	    // Get the resource class and attributes
	    if ((rattrs = skipAttributeHolder(in)) == null)
		return null;
	    cls    = (Class) rattrs.elementAt(0);
	    rattrs.removeElementAt(0);
	    // Fix the resource filters:
	    nfilters = skipFilters(cls, in, filters, fattrs);
	} catch (Exception ex) {
	    ex.printStackTrace();
	    return null;
	}
	// Convert into the new format:
	try {
	    ByteArrayOutputStream bout = new ByteArrayOutputStream(512);
	    DataOutputStream      out  = new DataOutputStream(bout);
	    // Dump the class (slow pickle) and std resource attrs:
	    dump(out, cls, rattrs);
	    // Dump the filters:
	    dumpFilters(out, nfilters, filters, fattrs);
	    out.close();
	    return bout.toByteArray();
	} catch (Exception ex) {
	    ex.printStackTrace();
	    return null;
	}
    }

    public byte[] upgrade(Class cls, DataInputStream in) {
	try {
	    ByteArrayOutputStream bout = new ByteArrayOutputStream(512);
	    DataOutputStream      out  = new DataOutputStream(bout);
	    if ( in.readBoolean() )
		return null;
	    // Read in resource attributes:
	    Vector attrs = new Vector(8);
	    skipAttributes(cls, in, attrs);
	    // Read in filters:
	    Vector filters  = new Vector();
	    Vector fattrs   = new Vector();
	    int    nfilters = skipFilters(cls, in, filters, fattrs);
	    // Dump main resource:
	    dump(out, cls, attrs);
	    // Dump filters:
	    dumpFilters(out, nfilters, filters, fattrs);
	    out.close();
	    return bout.toByteArray();
	} catch (Exception ex) {
	    ex.printStackTrace();
	}
	return null;
    }

}

