// ExtensionsEditor.java
// $Id: ExtensionsEditor.java,v 1.9 1997/01/24 12:00:53 abaird Exp $
// (c) COPYRIGHT MIT and INRIA, 1996.
// Please first read the full copyright statement in file COPYRIGHT.html

package w3c.jigsaw.indexer ;

import java.util.* ;

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

class ExtensionsAddHandler extends FormCardHandler {
    ResourceIndexer indexer = null ;
    String          url     = null ;

    public void notifyButtonClick(String label) {
	indexer.save() ;
    }

    /**
     * We just handle the notification of end of processing.
     */

    public String notifyEndProcessing(FormCardResource card, Request request)
	throws FormProcessingException
    {
	// Get and check the input values:
	String name = (String) card.lookupField("name").getValue() ;
	Class  cls  = (Class) card.lookupField("class").getValue();
	if (name == null) {
	    String msg = "Fill in the name of the extension. If the class is "
		+ " left blank, than this extension will be associated to "
		+ " a set of HTTPResource attributes, but file having only "
		+ " this extension won't be exported.";
	    throw new FormProcessingException (msg) ;
	}
	// Default the class to HTTPResource:
	if ( cls == null ) {
	    try {
		cls = Class.forName("w3c.jigsaw.resources.HTTPResource");
	    } catch (Exception ex) {
		ex.printStackTrace();
		System.exit(1);
	    }
	}
	// Create and register the new extension:
	try {
	    HTTPResource ext = (HTTPResource) cls.newInstance();
	    ext.setValue("identifier", name);
	    indexer.registerExtension(ext) ;
	} catch (Exception ex) {
	    String msg = ("Internal server error while creating extension "
			  + name + " of class " + cls.getName()
			  + ": " + ex.getMessage());
	    throw new FormProcessingException(msg);
	}
	// Relocate to the extension editor:
	return url+"/"+name;
    }

    ExtensionsAddHandler(String url, ResourceIndexer indexer) {
	this.url     = url ;
	this.indexer = indexer ;
    }

}

class ExtensionsListHandler extends FormCardHandler {
    ResourceIndexer indexer = null ;
    Vector          marked  = null ;
    String          url     = null ;

    /**
     * Update the form card.
     * We are really not clever here, this will be improved soon.
     */

    public FormCardResource updateFormCard(FormCardResource card) {
	// Reset the card of all its known fields:
	card.reset() ;
	// Rebuild the fields that are valid now:
	Enumeration enum = indexer.enumerateExtensionNames() ;
	Vector      exts = Sorter.sortStringEnumeration(enum) ;
	for (int i = 0 ; i < exts.size() ; i ++) {
	    String    name  = (String) exts.elementAt(i) ;
	    FormField field = new CheckBoxField(name
						, name
						, url + "/" + name
						, false);
	    card.addField(field);
	}
	return card ;
    }

    /**
     * On notifyChange, mark extension to be removed.
     */
    
    public void notifyChange(FormFieldInterface field, Object value)
	throws FormFieldException
    {
	if ( marked == null )
	    marked = new Vector() ;
	marked.addElement(field.getName()) ;
    }

    /**
     * On notifyEndProcessing, remove marked extensions.
     */

    public String notifyEndProcessing(FormCardResource card, Request request)
	throws FormProcessingException
    {
	// No extensions marked ?
	if ( marked == null )
	    return null;
	// Remove all the marked ones
	int vsize = marked.size() ;
	for (int i = 0 ; i < vsize ; i++) {
	    String id = (String) marked.elementAt(i) ;
	    indexer.unregisterExtension(id) ;
	    card.removeField(id) ;
	}
	marked.setSize(0) ;
	return null ;
    }

    ExtensionsListHandler(String url, ResourceIndexer indexer) {
	this.url     = url ;
	this.indexer = indexer ;
    }
}

public class ExtensionsEditor extends FormResource implements ResourceLocker {
    Hashtable       loaded  = null ;
    ResourceIndexer indexer = null ;

    /**
     * Define the form cards.
     * The extensions editor provides one form card for editing the list
     * of known extensions, and another one for adding new extensions.
     */

    protected void defineFormCards() {
	FormFieldInterface field = null ;
	String             url   = getURLPath() ;

	// The card to remove extensions:
	FormCardHandler list_handler = new ExtensionsListHandler(url,indexer);
	FormCardResource c = defineCard(list_handler
					, "Extensions"
					, "Defined extensions") ;
	c.setOkLabel("Delete");
	list_handler.updateFormCard(c) ;
	// The card to define new extensions:
	FormCardHandler add_handler = new ExtensionsAddHandler(url,indexer);
	c = defineCard(add_handler, "Add extension", "Add a new extension.");
	// The input field for the name of the extension:
	field = new TextField("name", "name", null, null) ;
	c.addField(field) ;
	// The input field for the class name:
	field = new ClassnameField("class", "class", null, null) ;
	c.addField(field) ;
	// A Save button:
	c.addButton("Save");
    }
	
    /**
     * Resource locker implementation - Our lock is being breaked.
     * @param resource The resource going down.
     */

    public synchronized void notifyResourceLockBreak(Resource resource) {
	loaded.remove(resource.getIdentifier()) ;
    }

    /** 
     * Lookup in the extensions editor for a defined extension.
     * @param state The current lookup state object.
     * @return A Resource to edit the extension or <strong>null</strong>.
     */
					    
    public synchronized boolean lookup (LookupState ls, LookupResult lr)
	throws HTTPException
    {
	if ( ! ls.hasMoreComponents() )
	    return super.lookup(ls, lr);
	// Look for an already existing editor, fallback to super otherwise
	String       name   = ls.peekNextComponent() ;
	HTTPResource editor = (HTTPResource) loaded.get(name) ;
	if ( editor != null ) {
	    ls.getNextComponent() ;
	    lr.setTarget(editor);
	    return editor.lookup(ls, lr);
	}
	// Get the target resource to edit:
	HTTPResource target = (HTTPResource) indexer.loadExtension(name);
	if ( target == null ) {
	    // No target, our super-class may know how to deal with the comp:
	    return super.lookup(ls, lr);
	}
	ls.getNextComponent();
	// Create a default editor for it:
	Hashtable defs = new Hashtable(11);
	defs.put("identifier", name) ;
	defs.put("parent", this) ;
	defs.put("url", getURLPath() +"/" + name) ;
	defs.put("target", target) ;
	defs.put("server", getServer());
	editor = FormEditorFactory.getEditor(target);
	editor.initialize(defs);
	target.lock(this);
	// Install it in our loaded set:
	loaded.put(name, editor) ;
	lr.setTarget(editor);
	return editor.lookup(ls, lr);
    }

    /**
     * Initialize the extension editor.
     */

    public void initialize(Object values[]) {
	super.initialize(values) ;
	this.indexer = getServer().getIndexer() ;
	this.loaded  = new Hashtable(35) ;
	defineFormCards() ;
    }

}
