// ContentTypeIndexer.java
// $Id: ContentTypeIndexer.java,v 1.5 1998/06/11 14:07:42 bmahe Exp $
// (c) COPYRIGHT MIT and INRIA, 1998.
// Please first read the full copyright statement in file COPYRIGHT.html
 
package org.w3c.jigsaw.indexer;

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

import org.w3c.tools.resources.indexer.*;
import org.w3c.tools.resources.*;
import org.w3c.www.mime.*;
import org.w3c.jigsaw.http.*;
import org.w3c.jigsaw.frames.*;

/**
 * @version $Revision: 1.5 $
 * @author  Benoît Mahé (bmahe@w3.org)
 */

class ContentTypesIndexerEnumeration implements Enumeration {
    private static final String list[] = {
	"directories",
	"extensions",
	"content-types"
    };

    int idx = 0;
    
    public boolean hasMoreElements() {
	return idx < list.length;
    }

    public Object nextElement() {
	if ( idx >= list.length )
	    throw new NoSuchElementException("ContentTypesIndexer enum");
	return list[idx++];
    }

    ContentTypesIndexerEnumeration() {
	this.idx = 0;
    }

}

public class ContentTypeIndexer extends SampleResourceIndexer {
    
    protected ResourceReference contentTypes  = null;

    public Enumeration enumerateResourceIdentifiers(boolean all) {
	return new ContentTypesIndexerEnumeration();
    }
    
    protected synchronized ResourceReference getContentTypes() {
	if ( contentTypes == null ) {
	    String typesidxid = getIdentifier()+"-c";
	    contentTypes = new DummyResourceReference(
			      new TemplateContainer(
				    new ResourceContext(getContext()),
				    typesidxid+".db"));
	}
	return contentTypes;
    }

    public ResourceReference lookup(String name) {
	if ( name.equals("directories") ) {
	    return getDirectories();
	} else if ( name.equals("extensions") ) {
	    return getExtensions();
	} else if ( name.equals("content-types") ) {
	    return getContentTypes();
	}  
	return null;
    }

    public synchronized void delete() 
	throws MultipleLockException
    {
	DummyResourceReference rr = 
	    (DummyResourceReference) getContentTypes();
	try {
	    Resource r = rr.lock();
	    r.delete();
	} catch (InvalidResourceException ex) {
	} finally {
	    rr.invalidate();
	    rr.unlock();
	}
	super.delete();
    }

    /*
     * Load an content-type descriptor.
     * @param type The name of the content-type.
     * @return An instance of Extension, or <strong>null</strong>.
     */

    public synchronized ResourceReference loadContentType (String type) {
	String key = (extCaseSensitive ? 
		      type : 
		      type.toLowerCase()).replace('/',':');
	ResourceReference rr = getContentTypes();
	try {
	    TemplateContainer types = (TemplateContainer) rr.lock();
	    return types.lookup(key);
	} catch (InvalidResourceException ex) {
	    String msg = ("[resource indexer]: content-types \""+
			  type+
			  "\" couldn't be restored ("+ex.getMessage()+")");
	    getContext().getServer().errlog(msg);
	    return null;
	} finally {
	    rr.unlock();
	}
    }

    /**
     * Create a default file resource for this file (that exists).
     * @param directory The directory of the file.
     * @param name The name of the file.
     * @param defs A set of default attribute values.
     * @return An instance of Resource, or <strong>null</strong> if
     *    we were unable to create it.
     */
    
    protected Resource createFileResource(File directory,
					  RequestInterface req,
					  String name,
					  Hashtable defs) 
    {
	File         file     = new File(directory, name) ;
	ResourceReference rr = null;
	FramedResource template = null;
	
	//try with content type in request.
	if (req instanceof Request) {
	    Request request = (Request) req;
	    MimeType type = request.getContentType();
	    if (type != null)
		rr = loadContentType(type.toString());
	    if (rr != null) {
		if ( defs == null )
		    defs = new Hashtable(5) ;
		if ( defs.get("directory") == null )
		    defs.put("directory", directory) ;
		if ( defs.get("identifier") == null )
		    defs.put("identifier", name) ;
		if ( defs.get("context") == null )
		    defs.put("context", getContext());
		//read attribute from request
		try {
		    template = (FramedResource) rr.lock();
		    // Create, initialize and return the new resouce
		    try {
			FramedResource resource = null;
			resource = (FramedResource) template.getClone(defs);
			// Now update HTTPFrame from request
			String contentLanguage[] = 
			    request.getContentLanguage();
			String contentEncoding[] = 
			    request.getContentEncoding();
			//get the HTTPFrame.
			Class httpFrameClass = 
			    Class.forName("org.w3c.jigsaw.frames.HTTPFrame");
			HTTPFrame hframe = (HTTPFrame)
			    resource.getFrame(httpFrameClass);
			if (hframe != null) {
			    if ((contentLanguage != null) && 
				(contentLanguage.length > 0))
				hframe.setValue("content-language",
						contentLanguage[0]);
			    if ((contentEncoding != null) &&
				(contentEncoding.length > 0))
				hframe.setValue("content-encoding",
						contentEncoding[0]);
			}
			return resource;
		    } catch (Exception ex) {
			ex.printStackTrace() ;
		    }
		} catch (InvalidResourceException ex) {
		    ex.printStackTrace();
		} finally {
		    rr.unlock();
		}
	    }
	}
	// now try with extensions...
	String exts[] = null;
	if (rr == null) {
	    // Check that at least one class is defined for all 
	    // the extensions:
	    exts = getFileExtensions(name) ;
	    if ( exts == null )
		return null ;
	    for (int i = exts.length-1 ; i >= 0 ; i--) {
		rr = getTemplateFor(exts[i]) ;
		if ( rr != null )
		    break ;
	    }
	    if ( rr == null ) {
		// Look for a default template:
		if ((rr = loadExtension(defname)) == null)
		    return null ;
	    }
	}
	// Create the runtime-time default values for attributes.
	if ( defs == null )
	    defs = new Hashtable(5) ;
	if ( defs.get("directory") == null )
	    defs.put("directory", directory) ;
	if ( defs.get("identifier") == null )
	    defs.put("identifier", name) ;
	if ( defs.get("context") == null )
	    defs.put("context", getContext());
	try {
	    template = (FramedResource) rr.lock();
	    if (exts != null) {
		// Merge with values defined by the extension:
		for (int i = exts.length ; --i >= 0 ; ) 
		    mergeDefaultAttributes(template, exts[i], defs) ;
	    }
	    // Create, initialize and return the new resouce
	    try {
		return (FramedResource) template.getClone(defs);
	    } catch (Exception ex) {
		ex.printStackTrace() ;
		return null ;
	    }
	} catch (InvalidResourceException ex) {
	    ex.printStackTrace();
	    return null;
	} finally {
	    rr.unlock();
	}
    }
    
}
