/*
 * EntityResolver.java
 *
 * Created on 10 June 2002, 16:18
 */

package org.bodington.xml;

import java.io.File;
import java.io.IOException;
import org.xml.sax.*;

/**
 *
 * @author  bmb6jrm
 * @version
 */
public class EntityResolver implements org.xml.sax.EntityResolver

{
    private File entity_folder;
    
    /** Creates new EntityResolver */
    public EntityResolver( String property_name )
    {
	this( property_name, null );
    }
    
    public EntityResolver( String property_name, String sub_folder )
    {
	if ( property_name == null )
	    throw new NullPointerException( "EntityResolver constructor needs non-null parameter." );
	
	String folder_name = System.getProperty( property_name );
	
	if ( folder_name == null )
	    throw new NullPointerException( "EntityResolver needs System parameter to be set." );
	
	File base_folder = new File( folder_name );
	if ( sub_folder != null )
	    entity_folder = new File( base_folder, sub_folder );
	else
	    entity_folder = base_folder;
	
	if ( !entity_folder.exists() )
	    throw new NullPointerException( "EntityResolver needs valid entity folder." );
	
	if ( !entity_folder.isDirectory() )
	    throw new NullPointerException( "EntityResolver needs valid entity folder." );
    }
    
    /**
     * Allow the application to resolve external entities.
     *
     * <p>The Parser will call this method before opening any external
     * entity except the top-level document entity (including the
     * external DTD subset, external entities referenced within the
     * DTD, and external entities referenced within the document
     * element): the application may request that the parser resolve
     * the entity itself, that it use an alternative URI, or that it
     * use an entirely different input source.</p>
     *
     * <p>Application writers can use this method to redirect external
     * system identifiers to secure and/or local URIs, to look up
     * public identifiers in a catalogue, or to read an entity from a
     * database or other input source (including, for example, a dialog
     * box).</p>
     *
     * <p>If the system identifier is a URL, the SAX parser must
     * resolve it fully before reporting it to the application.</p>
     *
     * @param publicId The public identifier of the external entity
     *       being referenced, or null if none was supplied.
     * @param systemId The system identifier of the external entity
     *       being referenced.
     * @return An InputSource object describing the new input source,
     *        or null to request that the parser open a regular
     *        URI connection to the system identifier.
     * @exception org.xml.sax.SAXException Any SAX exception, possibly
     *           wrapping another exception.
     * @exception java.io.IOException A Java-specific IO exception,
     *           possibly the result of creating a new InputStream
     *           or Reader for the InputSource.
     * @see org.xml.sax.InputSource
     */
    public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException
    {
	InputSource source = null;
	
	if ( publicId != null )
	{
	    source = resolveToFile( publicId );
	    if ( source != null )
		return source;
	    // give up on publicId if there isn't an obvious file and try systemId
	}
	
	// if the systemID is just a file name try treating it the same
	// as the publicId
	if ( systemId!=null && systemId.indexOf( ':' ) < 0 )
	{
	    source = resolveToFile( systemId );
	    if ( source != null )
		return source;
	}

	// the systemID has a protocol if it has a colon in it
	// so just pass it through...
	return null;
	
    }
    
    private InputSource resolveToFile( String Id )
    {
	File entity_file = new File( entity_folder, Id );
	if ( entity_file.exists() && entity_file.isFile() )
	{
	    return new InputSource( "file:" + entity_file.getAbsolutePath() );
	}
	
	return null;
    }
}
