// test class
package org.w3c.tools.resources;

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

import org.w3c.tools.resources.store.*;

public class Main {

  public static ResourceStoreManager manager = null;
  public static String root_name = null;
  public static File space_dir = null;

  public static void initialize(String dir,
				String root_class,
				String root_name)
  {
    if (dir == null) {
      System.out.println("storedir is mandatory!");
      usage();
      System.exit(-1);
    }
    File storedir = new File(dir);
    if (! storedir.exists() || ! storedir.isDirectory()) {
      System.out.println(storedir.getAbsolutePath()+" is not a directory.");
      System.exit(-1);
    }
    ResourceContext context = 
      new ResourceContext((ServerInterface) null) ;
    Hashtable defs = new Hashtable(5);
    defs.put("url", "/");
    defs.put("directory", space_dir) ;
    defs.put("context", context);
    manager = new ResourceStoreManager(storedir, root_class, root_name, 
				       defs);
    context.setSpace(manager);
    Main.root_name = root_name;
  }

  public static void initialize(String dir) {
    initialize(dir, null, null);
  }


  public static void create(int nb) {
    ResourceReference root_ref = getRootReference();
    try {
      ContainerResource root = (ContainerResource) root_ref.lock();
      System.out.println("root loaded : ["+root.getIdentifier()+"]");
      root.print(System.out);
      ContainerResource cont1 = root;
      ContainerResource cont2 = null;
      for (int i = 0 ; i < nb ; i++) {
	cont2 =  new ContainerResource(); 
	System.out.println("registering cont"+i+".");
	cont1.registerResource("cont"+i,
			       cont2,
			       null);
	cont1 = cont2;
      }
      manager.checkpoint();
    } catch (InvalidResourceException ex) {
      System.out.println(ex.getMessage());
      ex.printStackTrace();
    } finally {
      root_ref.unlock();
    }
  }

  public static void lookupAll(int nb) {
    ResourceReference root_ref = getRootReference();
    try {
      ContainerResource root = (ContainerResource) root_ref.lock();
      ContainerResource cont1 = root;
      for (int i = 0 ; i < nb ; i++) {
	ResourceReference rr2 = cont1.lookup("cont"+i);
	try {
	  ContainerResource cont0 = (ContainerResource) rr2.lock();
	  System.out.println("**** cont"+i+" found ****");
	  cont0.print(System.out);
	  System.out.println("*************************\n");
	  cont1 = cont0;
	} catch (InvalidResourceException ex) {
	  ex.printStackTrace();
	} finally {
	  rr2.unlock();
	}
      }
    } catch (InvalidResourceException ex) {
      System.out.println(ex.getMessage());
      ex.printStackTrace();
    } finally {
      root_ref.unlock();
    }
  }

  public static ResourceReference lookup(String uri, boolean display) {
    ResourceReference root_ref = getRootReference();
    System.out.println("\nLoooking up : "+uri);
    LookupState ls = null;
    try {
      ls  = new LookupState(uri);
    } catch (ProtocolException ex) {
      System.out.println(ex.getMessage());
      ex.printStackTrace();
    }
    LookupResult lr = new LookupResult(root_ref);
    try {
      ContainerResource resource = (ContainerResource) root_ref.lock();
      try {
	if (resource.lookup(ls,lr)) {
	  ResourceReference result = lr.getTarget();
	  if (result == null) {
	    System.out.println("LOOKUP RESULT NULL!");
	    return null;
	  }
	  else {
	    try {
	      Resource res = result.lock();
	      if (display)
		res.print(System.out);
	      return result;
	    } catch (InvalidResourceException ex) {
	      System.out.println(ex.getMessage());
	      ex.printStackTrace();
	      return null;
	    } finally {
	      result.unlock();
	    }
	  }
	} else {
	  System.out.println("NOT FOUND!");
	  return null;
	}
      } catch (ProtocolException ex) {
	System.out.println(ex.getMessage());
	ex.printStackTrace();
	return null;
      }
    } catch (InvalidResourceException ex) {
      System.out.println(ex.getMessage());
      ex.printStackTrace();
      return null;
    } finally {
      root_ref.unlock();
    }
  }

  public static ResourceReference getRootReference() {
    ResourceContext context = new ResourceContext(manager, null);
    Hashtable defs = new Hashtable();
    defs.put("context", context);
    defs.put("url","/");
    defs.put("directory", space_dir);
    ResourceReference root_ref = null;
    root_ref = manager.loadRootResource("root", defs);
    context.setResourceReference(root_ref);
    return root_ref;
  }

  public static void exit() {
    System.out.println("\n\n**** SHUTDOWN ****");
    manager.shutdown();
    System.out.println("done.");
    System.exit(0);
  }

  public static void usage() {
    System.out.println("Usage : "+
		       "\n\t-st storedir"+
		       "\n\t-rc root_class"+
		       "\n\t-rn root_name"+
		       "\n\t-sp spacedir"+
		       "\n\t-create nb"+
		       "\n\t-lookup nb"+
		       "\n\t-lookupuri uri"+
		       "\n\t-add uri class name"+
		       "\n\t-del uri name"+
		       "\n\t-attr name value"+
		       "\n\t-enum uri");
    System.exit(-1);
  }

  public static void main(String args[]) {
    String action     = null;
    String storedir   = null;
    String root_class = null;
    String root_name  = null;
    String uri        = null;
    String addclass   = null;
    String addname    = null;
    String delname    = null;
    Hashtable defs    = null;
    int createnb = 0;
    int lookupnb = 0;
    // Parse the command line:
    for (int i = 0 ; i < args.length ; i++) {
      if ( args[i].equals("-st") ) {
	storedir = args[++i];
      } else if ( args[i].equals("-rc") ) {
	root_class = args[++i];
      } else if ( args[i].equals("-sp") ) {
	space_dir = new File(args[++i]);
      } else if ( args[i].equals("-rn") ) {
	root_name = args[++i];
      } else if ( args[i].equals("-attr") ) {
	if (defs == null)
	  defs = new Hashtable(5);
	String key = args[++i];
	defs.put( key, args[++i]);
      } else if ( args[i].equals("-create") ) {
	action = "create";
	try {
	  createnb = Integer.parseInt(args[++i]);
	} catch (NumberFormatException ex) {
	  createnb = 10;
	}
      } else if ( args[i].equals("-lookup") ) {
	action = "lookup";
	try {
	  lookupnb = Integer.parseInt(args[++i]);
	} catch (NumberFormatException ex) {
	  lookupnb = 10;
	}
      } else if (args[i].equals("-lookupuri")) {
	action = "lookupuri";
	uri = args[++i];
      } else if (args[i].equals("-add")) {
	action   = "add";
	uri      = args[++i];
	addclass = args[++i];
	addname  = args[++i];
      } else if (args[i].equals("-del")) {
	action  = "del";
	uri     = args[++i];
	delname = args[++i];
      } else if (args[i].equals("-enum")) {
	action = "enum";
	uri = args[++i];
      } else {
	usage();
      }
    }
    if (storedir == null) {
      storedir = System.getProperty("user.dir");
      System.out.println("no storedir argument, taking current dir :"+
			 storedir);
    }
    initialize (storedir, root_class, root_name);

    if (action == null) 
      exit();

    //perform the action
    if (action.equals("create")) {
      create(createnb);
    } else if (action.equals("lookup")) {
      lookupAll(lookupnb);
    } else if (action.equals("lookupuri")) {
      lookup(uri, true);
    } else if (action.equals("add")) {
      ResourceReference rcont = lookup(uri, false);
      if (rcont != null) {
	try {
	  ContainerResource cont = (ContainerResource) rcont.lock();
	  Resource resource = null;
	  try {
	    Class c = Class.forName(addclass);
	    resource = (Resource) c.newInstance();
	    cont.registerResource(addname, resource, defs);
	  } catch (Exception ex) {
	    System.out.println(ex.getMessage());
	    ex.printStackTrace();
	  }
	} catch (InvalidResourceException ex) {
	  System.out.println(ex.getMessage());
	  ex.printStackTrace();
	} finally {
	  rcont.unlock();
	}
      }
    } else if (action.equals("del")) {
      ResourceReference rcont = lookup(uri, false);
      if (rcont != null) {
	try {
	  ContainerResource cont = (ContainerResource) rcont.lock();
	  cont.delete(delname);
	} catch (InvalidResourceException ex) {
	  System.out.println(ex.getMessage());
	  ex.printStackTrace();
	} finally {
	  rcont.unlock();
	}
      }
    } else if (action.equals("enum")) {
      ResourceReference rcont = lookup(uri, false);
      if (rcont != null) {
	try {
	  ContainerResource cont = (ContainerResource) rcont.lock();
	  Enumeration enum = cont.enumerateResourceIdentifiers();
	  System.out.println("\nChildren of "+cont.getIdentifier());
	  while (enum.hasMoreElements()) {
	    System.out.println(" - "+(String)enum.nextElement());
	  }
	} catch (InvalidResourceException ex) {
	  System.out.println(ex.getMessage());
	  ex.printStackTrace();
	} finally {
	  rcont.unlock();
	}
      }
    }

    exit();
  }

}
