// ContainerResourceEditor.java
// $Id: ContainerResourceEditor.java,v 1.10 1997/03/07 12:44:20 abaird Exp $
// (c) COPYRIGHT MIT and INRIA, 1996.
// Please first read the full copyright statement in file COPYRIGHT.html


package w3c.jigsaw.formedit;

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

import w3c.tools.store.*;
import w3c.tools.sorter.*;
import w3c.jigsaw.http.*;
import w3c.jigsaw.resources.*;
import w3c.jigsaw.forms.*;

class DirectoryAddHandler extends FormCardHandler {
    ContainerResource target = null ;

    public String notifyEndProcessing(FormCardResource card, Request request)
	throws FormProcessingException
    {
	String name = (String) card.lookupField("name").getValue() ;
	Class  cls  = (Class) card.lookupField("class").getValue() ;
	if ((name == null) || (cls == null)) {
	    String msg = "Fill in the name of the extension, and the class " 
                + " that files having this extension should be exported " 
                + " with." ; 
            throw new FormProcessingException (msg) ; 
	} 
	// Create and register the new resource:
	try {
	    Hashtable    defs     = new Hashtable(11);
	    HTTPResource resource = (HTTPResource) cls.newInstance() ;
	    target.registerResource(name, resource, defs);
	} catch (Exception ex) {
	    ex.printStackTrace();
	    throw new FormProcessingException ("Unable to create "
					       + name
					       + ": "
					       + ex.getMessage());
	}
	return null;
    }

    DirectoryAddHandler(ContainerResource target) {
	this.target = target ;
    }

}

class DirectoryListHandler extends FormCardHandler {
    protected static String commands[] = { "Update", "Remove", "Reindex" } ;

    protected ContainerResource  target     = null ;
    protected long               card_stamp = -1 ;
    protected FormFieldInterface command    = null ;
    protected FormFieldInterface commandAll = null ;
    protected String             edurl      = null;
    protected boolean            all        = false;

    /**
     * The list of marked resources to act on.
     */
    Vector marked = null ;
    /**
     * The command to run on the marked resources.
     */
    protected String runcmd = null ;

    protected Vector listAll() {
	Enumeration e = target.enumerateResourceIdentifiers();
	Vector      a = new Vector();
	while ( e.hasMoreElements() )
	    a.addElement(e.nextElement());
	return a;
    }

    /**
     * Update the directory list card if needed.
     * @param card The card to be updated.
     */

    public FormCardResource updateFormCard(FormCardResource card) {
	// Check if the card is still valid ?
	if ( card_stamp >= target.getLastModified() ) 
	    return card ;
	card.reset() ;
	String targetloc = target.getURLPath();
	// Generate the whole list of existing resources:
	FormFieldInterface field     = null ;
	Enumeration        enum      = target.enumerateResourceIdentifiers() ;
	Vector             resources = Sorter.sortStringEnumeration(enum) ;
	for (int i = 0 ; i < resources.size() ; i++) {
	    String name = (String) resources.elementAt(i) ;
	    field = new CheckBoxField(name
				      , name
				      , edurl + targetloc + name
				      , false) ;
	    card.addField(field) ;
	}
	// Generate the command radio box:
	command = new RadioBoxField("Command", "Command", null, commands, 0);
	card.addField(command) ;
	commandAll = new RadioBoxField("CommandAll", "Command (All)"
				       , null
				       , commands, 0);
	card.addField(commandAll);
	card_stamp = target.getLastModified() ;
	return card ;
    }


    /**
     * Notify that some field value has changed.
     * We jut maintain here the list of resources to act on. Remember that
     * by default, the <code>notify...</code> method calls are atomic
     * (they can't overlap).
     * @param field The field that changed.
     * @param value Its new value.
     */

    public void notifyChange(FormFieldInterface field, Object value) {
	// Is it the command ?
	if ( field == command ) {
	    this.runcmd = (String) value ;
	    this.all    = false;
	} else if ( field == commandAll ) {
	    this.runcmd = (String) value;
	    this.all    = true;
	} else {
	    // One of our resources, mark it:
	    if ( marked == null )
		marked = new Vector() ;
	    marked.addElement(field.getName()) ;
	}
    }
     
    /**
     * Process the card.
     * @param card The card to be processed.
     * @param request The request that triggered the request.
     * @exception FormProcessingException If the processing failed.
     */

    public String notifyEndProcessing(FormCardResource card, Request request)
	throws FormProcessingException
    {
	// Check that we did get a command to run:
	if ( runcmd == null ) {
	    throw new FormProcessingException("You haven't selected a command"
					      +" from the appropriate command"
					      +" field.");
	}
	// Run the command:
	try {
	    if ( runcmd.equals("Remove") ) {
		if ( all ) 
		    marked = listAll();
		// Remove all marked resources:
		for (int i = 0 ; i < marked.size() ; i++) {
		    String   name = (String) marked.elementAt(i);
		    Resource r    = null;
		    try {
			if ((r = target.lookup(name)) != null) {
			    r.delete();
			}
		    } catch (InvalidResourceException ex) {
			// We really want to remove that resource:
			target.getResourceStore().removeResource(name);
		    }
		}
	    } else if ( runcmd.equals("Update") ) {
		if ( all )
		    marked = listAll();
		// Update all children resources...
		for (int i = 0 ; i < marked.size() ; i++) {
		    String       name = (String) marked.elementAt(i) ;
		    try {
			Resource res = target.lookup(name) ;
			if ((res != null) && (res instanceof HTTPResource))
			    ((HTTPResource) res).updateAttributes() ;
		    } catch (InvalidResourceException ex) {
		    }
		}
	    } else if ( runcmd.equals("Reindex") ) {
		if ( all ) 
		    marked = listAll();
		// Reindex marked resources:
		for (int i = 0 ; i < marked.size() ; i++) {
		    String name = (String) marked.elementAt(i) ;
		    try {
			Resource r = target.lookup(name);
			if (r != null) {
			    r.delete();
			    target.createDefaultResource(name);
			}
		    } catch (InvalidResourceException ex) {
		    }
		}
	    } else {
		// Unknwon command !
		System.out.println("Unknown command: "+runcmd) ;
	    }
	} finally {
	    marked.setSize(0) ;
	    runcmd = null ;
	}
	return null ;
    }

    /**
     * Create a directory list handler object.
     */
    
    DirectoryListHandler(String edurl, ContainerResource target) {
	this.edurl  = edurl ;
	this.target = target ;
    }

}


public class ContainerResourceEditor extends FilteredResourceEditor {
    ContainerResource target = null ;

    public ContainerResource getTargetDirectory() {
	return (ContainerResource) super.getTarget() ;
    }

    /**
     * Defines the card to add brand new resources.
     * This card allows to add new resources to a directory. If the directory
     * isn't extensible, than this is the only way to add new resources.
     * Otherwise, you can also use the laziness of the direrctory resource
     * to create file resource on demand.
     */

    protected void defineDirectoryAddCard() {
	ContainerResource   target  = getTargetDirectory() ;
	DirectoryAddHandler handler = new DirectoryAddHandler(target) ;
	FormCardResource    card    = defineCard(handler
						 , "Add resource"
						 , "Adding resources in "
						 + target.getIdentifier()) ;
	card.setOkLabel("Create");
	FormFieldInterface field = null ;
	// The name of the resource:
	field = new TextField("name", "name", null, null);
	card.addField(field);
	// THe class for the new resource:
	field = new ClassnameField("class", "class", null, null) ;
	card.addField(field);
    }

    /**
     * Current list of resources for the directorty.
     * This card will list the available children resources, and provide
     * commands to update or delete them.
     */

    protected void defineDirectoryListCard() {
	String editor = getParent().getURLPath();
	ContainerResource    target  = getTargetDirectory() ;
	DirectoryListHandler handler = new DirectoryListHandler(editor
								, target) ;
	FormCardResource     card    = defineCard(handler
						  , "Existing resources"
						  , "Existing resources of "
						  + target.getIdentifier());
	handler.updateFormCard(card) ;
    }
	    
    // Note the order in which the cards are created. 
    // The directory listing appears first, to ease navigation.

    protected void defineCards() {
	// Define the card to list directory content:
	defineDirectoryListCard() ;
	// Define the generic cards:
	super.defineCards() ;
	// define the card to define new resources
	defineDirectoryAddCard() ;
    }
	
}
