// AdminReader.java 
// $Id: AdminReader.java,v 1.10 1998/02/09 15:21:37 bmahe Exp $
// (c) COPYRIGHT MIT and INRIA, 1997.
// Please first read the full copyright statement in file COPYRIGHT.html


package org.w3c.jigsaw.admin;

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

import org.w3c.tools.resources.*;

class AdminReader implements AdminProtocol {
    /**
     * The RemoteResource factory to create remote resource instances.
     */
    RemoteResourceFactory factory = null;
    /**
     * The client side admin object we are attached to.
     */
    protected AdminContext admin = null;
    
    private RemoteResource readRawResource(URL parent
					  , String identifier
					  , DataInputStream in)
	throws IOException, AdminProtocolException
    {
	// Read the class hierarchy:
	Vector vector  = new Vector();
	int    clssz   = in.readInt();
	while (--clssz >= 0)
	    vector.addElement(in.readUTF());
	// And the identifier:
	String wireid = in.readUTF();
	wireid = (wireid.equals("")) ? null : wireid;
	String classes[] = new String[vector.size()];
	vector.copyInto(classes);
	if (identifier != null) {
	    // if ((wireid != null) && ! identifier.equals(wireid) )
	    // throw new RuntimeException("Implementation bug");
	    ;
	} else {
	    identifier = wireid;
	}
	// Create the RemoteResource with these infos:
	return factory.createRemoteResource(parent, identifier, classes);
    }
    
    private RemoteResource readRawResource(URL url
					   , DataInputStream in)
	throws IOException, AdminProtocolException
    {
	// Read the class hierarchy:
	Vector vector  = new Vector();
	int    clssz   = in.readInt();
	while (--clssz >= 0)
	    vector.addElement(in.readUTF());
	// And the resource identifier:
	String wireid = in.readUTF();
	String classes[] = new String[vector.size()];
	vector.copyInto(classes);
	// Create the RemoteResource with these infos:
	return factory.createRemoteResource(url, classes);
    }
    
    protected RemoteResource readFrame(URL frameUrl,
				       DataInputStream in)
      throws IOException, AdminProtocolException
    {
      int op = in.read();
      if (op != WIRED_FRAMED)
	throw new AdminProtocolException("Invalid frame");
      int            nfr      = in.readInt();
      RemoteResource frames[] = null;
      if (nfr > 0) {
	frames = new RemoteResource[nfr];
	for (int i=0 ; i < nfr ; i++) {
	  String frid = in.readUTF();
	  URL    url  = null;
	  try {
	    url = new URL(frameUrl.getProtocol(),
			  frameUrl.getHost(),
			  frameUrl.getPort(),
			  frameUrl.getFile()+"?" + frid);
	    //url = new URL(frameUrl, frameUrl.getFile()+"?" + frid);
	  } catch (MalformedURLException ex) {
	    ex.printStackTrace();
	  }
	  frames[i] = readFrame(url,in);
	  ((PlainRemoteResource) frames[i]).identifier = frid;
	}
      }
      PlainRemoteResource r = null;
      r = (PlainRemoteResource) readRawResource(frameUrl,in);
      r.setFrames(frames);
      return r;
    }

    protected RemoteResource readResource(URL parent
					  , String identifier
					  , DataInputStream in)
	throws IOException, AdminProtocolException
    {
      int op = in.read();
      switch(op) {
        case WIRED_PLAIN:
	  return readRawResource(parent, identifier, in);
        case WIRED_FRAMED:
	  int            nfr      = in.readInt();
	  RemoteResource frames[] = null;
	  if (nfr > 0) {
	    frames = new RemoteResource[nfr];
	    for (int i=0 ; i < nfr ; i++) {
	      String frid = in.readUTF();
	      URL    url  = null;
	      try {
		url = new URL(parent.toExternalForm()+identifier+"?"+frid);
	      } catch (MalformedURLException ex) {
		ex.printStackTrace();
	      }
	      frames[i] = readFrame(url, in);
	      //frames[i] = readRawResource(url, in);
	      ((PlainRemoteResource) frames[i]).identifier = frid;
	    }
	  }
	  PlainRemoteResource r = null;
	  r = (PlainRemoteResource) readRawResource(parent,identifier,in);
	  r.setFrames(frames);
	  return r;
      default:
	throw new RuntimeException("unknown opcode: "+op);
      }
    }

    protected Attribute[] readAttributes(DataInputStream in)
	throws IOException, AdminProtocolException
    {
	ObjectInputStream oin = new ObjectInputStream(in);
	try {
	    return (Attribute[]) oin.readObject();
	} catch (ClassNotFoundException ex) {
	    ex.printStackTrace();
	} catch (StreamCorruptedException ex) {
	    ex.printStackTrace();
	} catch (OptionalDataException ex) {
	    ex.printStackTrace();
	}
	throw new AdminProtocolException("Cannot restore attributes");
    }
    


    AdminReader(AdminContext admin) {
	this.admin   = admin;
	this.factory = new RemoteResourceFactory(admin);
    }
    
}


