// Main.java
// $Id: Main.java,v 1.6 1997/07/30 14:10:11 ylafon Exp $  
// (c) COPYRIGHT MIT and INRIA, 1997.
// Please first read the full copyright statement in file COPYRIGHT.html

package w3c.tools.resources.tests;

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

import w3c.tools.resources.*;
import w3c.tools.resources.event.*;
import w3c.tools.resources.simple.*;
import w3c.tools.resources.ascii.*;
import w3c.tools.resources.property.*;
import w3c.tools.resources.impl.ResourceContextImpl;

class AttributeMonitor implements AttributeChangedListener {

    public void attributeChanged(AttributeChangedEvent evt) {
	Resource source   = (Resource) evt.getSource();
	String   name     = evt.getPropertyName();
	Object   oldvalue = evt.getOldValue();
	Object   newvalue = evt.getNewValue();
	System.out.println(source.getName()+"."+name
			   + " " + oldvalue + " -> "+ newvalue);
    }
}

class StructureMonitor implements StructureChangedListener {

    public void resourceUnloaded(StructureChangedEvent evt) {
	System.out.println("-> unloaded: "+evt.getResource().getName());
    }
    public void resourceInited(StructureChangedEvent evt) {
	System.out.println("-> inited: "+evt.getResource().getName());
    }
    public void resourceCreated(StructureChangedEvent evt) {
	System.out.println("-> created: "+evt.getResource().getName());
    }
    public void resourceDeleted(StructureChangedEvent evt) {
	System.out.println("-> deleted: "+evt.getResource().getName());
    }

}

public class Main {

    public static void lookupBench(ResourceSpace space, LookupState state) {
	long start = System.currentTimeMillis();
	for (int i = 0 ; i < 10000 ; i++) {
	    LookupState s = (LookupState) state.clone();
	    space.resolve(s);
	}
	long end   = System.currentTimeMillis();
	System.out.println("10000 lookup in "+(end-start)+" ms.");
    }

    public static void initialize(File storedir) {
	File store = new File(storedir, "root.st");
	try {
	    Resource r = new SimpleResourceContainer();
	    r.setName("root");
	    ObjectOutputStream oo = (new ObjectOutputStream
				     (new BufferedOutputStream
				      (new FileOutputStream(store))));
	    oo.writeInt(1);
	    oo.writeObject(r);
	    oo.close();
	} catch (Exception ex) {
	    ex.printStackTrace();
	}
	System.out.println(store+": created.");
	System.exit(0);
    }

    public static Object convertValue(String s, String str) {
	try {
	    switch(s.charAt(3)) {
	      case 'i':
		  return new Integer(Integer.parseInt(str));
	      case 'l':
		  return new Long(Long.parseLong(str));
	      case 's':
		  return str;
	      case 'f':
		  return new File(str);
	      case 'b':
		  return (str.equalsIgnoreCase("true")
			  ? Boolean.TRUE
			  : Boolean.FALSE);
	      case 't':
		  return new w3c.www.mime.MimeType(str);
	    }
	} catch (Exception ex) {
	}
	throw new RuntimeException("unknown set: "+s);
    }

    public static void main(String args[]) {
	String      rname  = null;
	String      rclass = null;
	String      action = null;
	String      path   = null;
	ResourceReference targetref = null;
	Resource    target = null;
	String      pname  = null;
	String      pvalue = null;
	StructureMonitor structMonitor = null;
	AttributeMonitor attrMonitor   = null;
	int count = 1;
	boolean server = false;
	String spaceName = null;
	String delPath = null;

	try {
	    // Parse the command line:
	    for (int i = 0 ; i < args.length ; i++) {
		if ( args[i].equals("-delegatee") ) {
		    delPath = args[++i];
		} else if ( args[i].equals("-space") ) {
		    spaceName = args[++i];
		} else if ( args[i].equals("-count")) {
		    count = Integer.parseInt(args[++i]);
		} else if ( args[i].equals("-struct") ) {
		    structMonitor = new StructureMonitor();
		} else if ( args[i].equals("-attr") ) {
		    attrMonitor = new AttributeMonitor();
		} else if ( args[i].equals("-init") ) {
		    File storedir = new File(args[++i]);
		    initialize(storedir);
		} else if ( args[i].equals("-p") ) {
		    path = args[++i];
		} else if ( args[i].equals("-a") ) {
		    rname  = args[++i];
		    rclass = args[++i];
		    action = "add";
		} else if ( args[i].equals("-d") ) {
		    rname  = args[++i];
		    action = "delete";
		} else if ( args[i].equals("-l") ) {
		    action = "list";
		} else if ( args[i].equals("-print") ) {
		    action = "print";
		} else if ( args[i].startsWith("-set") ) {
		    action = args[i].substring(1);
		    pname  = args[++i];
		    pvalue = args[++i];
		} else if ( args[i].equals("-get") ) {
		    action = "get";
		    pname  = args[++i];
		} else if ( args[i].equals("-server") ) {
		    server = true;
		} else {
		    System.out.println("usage: -p target-path "
				       + " -a(dd) name class "
				       + " -d(elete) name");
		    System.exit(1);
		}
	    }
	    // Create a the ResourceSpace:
	    ResourceSpaceManager spaceManager = null;
	    spaceManager = ResourceSpaceManager.getResourceSpaceManager();
	    ResourceSpace space = spaceManager.getResourceSpace(spaceName);
	    if ( structMonitor != null ) {
		System.out.println("*** Monitoring structure changes");
		space.addStructureChangedListener(structMonitor); 
	    }
	    // If server, do it:
	    if ( server ) {
		w3c.tools.resources.rmi.RemoteResourceSpaceImpl.exportResourceSpace("space", space);
		System.out.println("space exported as \"space\"");
	    }
	    // Resolve the path, or use root:
	    if ( path == null )
		targetref = space.resolve(new LookupState(space, "/"));
	    else
		targetref = space.resolve(new LookupState(space, path));
	    if ( targetref == null )
		throw new RuntimeException(path+": not found !");
	    target = targetref.lock();
	    if ( attrMonitor != null )
		target.addAttributeChangedListener(attrMonitor);
	    if ( delPath != null ) {
		LookupState state = new LookupState(space, delPath);
		ResourceReference delResource = space.resolve(state);
		target.addDelegatee(delResource);
		try {
		    Resource r = delResource.lock();
		    System.out.println("delgation to \""
                                       + r.getName()
				       + "\" set.");
		} finally {
		    delResource.unlock();
		}
	    }
	    System.out.println("*** target="+target.getValue("name"));
	    // Perform the action:
	    if ( action == null ) {
		;
	    } else if ( action.equals("add") ) {
		// Target must be a ResourceContainer:
		if ( ! ( target instanceof ResourceContainer ) )
		    throw new RuntimeException("target not a container");
		Resource            r  = null;
		ResourceContextImpl cc = null;
		while ( --count >= 0 ) {
		    try {
System.out.println("rclass="+rclass);
			r = (Resource)Class.forName(rclass).newInstance();
			cc = new ResourceContextImpl(space, targetref);
			cc.addProperty("name"
				       , (count==0) ? rname:(rname+count));
			r.create(cc);
			((ResourceContainer) target).registerChild(r, cc);
		    } catch (Exception ex) {
			ex.printStackTrace();
		    }
		}
	    } else if ( action.equals("delete") ) { 
		target.destroy();
	    } else if ( action.equals("list")) {
		if ( ! ( target instanceof ResourceContainer ) )
		    throw new RuntimeException("target not a container");
		Enumeration e = ((ResourceContainer) target).listChildNames();
		while ( e.hasMoreElements() )
		    System.out.println("\t"+e.nextElement());
	    } else if ( action.equals("print") ) {
		System.out.println(target);
	    } else if ( action.startsWith("set") ) {
		Object value = convertValue(action, pvalue);
		target.setValue(pname, value);
	    } else if ( action.equals("get") ) {
		System.out.println(target.getName()
				   + "["+pname+"]="
				   + target.getValue(pname));
	    } else {
		System.out.println("unknown action: "+action);
	    } 
	    space.checkpoint();
	    System.out.println("space saved.");
	} catch (Exception ex) {
	    ex.printStackTrace();
	} finally {
	    if ( target != null )
		targetref.unlock();
	}
    }

}
