head	1.1;
access;
symbols;
locks; strict;
comment	@# @;


1.1
date	2001.07.19.20.22.44;	author dlr;	state Exp;
branches;
next	;


desc
@@


1.1
log
@Ported Joist searching classes into Helm.
@
text
@/* ================================================================
 * Copyright (c) 2000 Collab.Net.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * 1. Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 *
 * 3. The end-user documentation included with the redistribution, if
 * any, must include the following acknowlegement: "This product includes
 * software developed by Collab.Net (http://www.Collab.Net/)."
 * Alternately, this acknowlegement may appear in the software itself, if
 * and wherever such third-party acknowlegements normally appear.
 *
 * 4. The hosted project names must not be used to endorse or promote
 * products derived from this software without prior written
 * permission. For written permission, please contact info@@collab.net.
 *
 * 5. Products derived from this software may not use the "Tigris" name
 * nor may "Tigris" appear in their names without prior written
 * permission of Collab.Net.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL COLLAB.NET OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of Collab.Net.
 */
 package org.tigris.helm.search;


/** Class to hold search result item
* <p>
* &laquo;Immutable -- Read-Only.&raquo;
*
* @@author <a href="mailto:stack@@collab.net">St.Ack</a>
* @@version $Id: SearchResultItem.java,v 1.10 2000/11/06 22:04:02 stack Exp $
*/
public class SearchResultItem
{
    /** Class version string
    */
    public static final String versionID
        = "$Id: SearchResultItem.java,v 1.10 2000/11/06 22:04:02 stack Exp $";


    /** Search engine ranking.
    */
    private int ranking = -1;


    /** File size
    */
    private int size = -1;


    /** File or URL pointing to file found.
    */
    private java.net.URL url = null;


    /** File title -- usually the HTML TITLE
    */
    private String title = null;


    /** The path to htdoc.
     * Used by the getFileRelativeToHtDoc( ) method.
     */
    private String htdocPath = null;
    
    
    /** Domain to use.
    * Needed to manufacture search result url 
    * according to receipe described at head of getSourceCastURL.
    * @@see #getSourceCaseURL
    */
    private String domain = null;
    
    
    /** Port to use.
    * Needed to manufacture search result url 
    * according to receipe described at head of getSourceCastURL.
    * @@see #getSourceCaseURL
    */    
    private String port = null;
    
    
    /** Protocol to use.
    * Needed to manufacture search result url 
    * according to receipe described at head of getSourceCastURL.
    * @@see #getSourceCaseURL
    */
    private String protocol = null;
    
    
    /** Protocol default.
    */
    private final static String PROTOCOL_DEFAULT = "http";
    
    
    /** Define for '/www/'.
    */
    private final static String SLASH_WWW_SLASH = "/www/";
    
    
    /** Default port 80 define.
    */
    public static final String DEFAULT_PORT_80
        = "80";


    /** Constructor
    *
    * @@param inRanking  Search ranking.  Meaning varies from search-engine
    *                   to search-engine. Enter -1 or 0 if not returned
    *                   by the search engine.
    * @@param inSize     Size of returned file.  Enter -1 or 0 if not
    *                   returned by the search engine.
    * @@param inURL      File or URL to search-engine result.
    * @@param inTitle    Title of the file.  May be null.
    * @@param inHtDocPath Path to htdocs.  Used by the
    *                    getFileRelativeToHtDoc method.
    *                    Cannot be null.  It's too important.
    * @@param inDomain   Pass me a domain.  I need this to make up a
    * search result url according to receipe described at head of 
    * getSourceCastURL.  Cannot be null.  Will throw exception if 
    * it is.
    * @@param inPort Port to use making up search result url 
    * according to receipe described at head of getSourceCastURL.
    * If null, we assume port 80.
    * @@param inProtocol Protocol to use making up search result url 
    * according to receipe described at head of getSourceCastURL.
    * If null we assume 'http'.
    *
    * @@exception NullPointerException If passed in inURL object is empty.
    */
    public SearchResultItem( int inRanking,
                                int inSize,
                                java.net.URL inURL,
                                String inTitle,
                                String inHtdocPath, 
                                String inDomain, 
                                String inPort, 
                                String inProtocol )
        throws NullPointerException
    {
        if( inURL == null )
            throw new NullPointerException( "inURL is null" );
        url = inURL;

        if( inHtdocPath == null )
            throw new NullPointerException( "inHtdocPath is null" );
        htdocPath = inHtdocPath.trim( );
        
        if( inDomain == null )
            throw new NullPointerException( "inDomain is null" );
        domain = inDomain.trim( );
        
        if( inPort != null )
            port = inPort.trim( );
        if( inProtocol != null )
            protocol = inProtocol.trim( );
        if( inTitle != null )
           title = inTitle.trim( );
           
        ranking = inRanking;
        size = inSize;
    }


    /** Get search-engine ranking
    * @@return Returns an int.  It's meaning will differ across search-engines.
    * Will need some kind of impossible mapping function if we ever want to
    * compare.
    */
    public int getRanking( )
    {
        return ranking;
    }


    /** Get size of result as reported by the search-engine.
    * @@return File size.
    */
    public int getSize( )
    {
        return size;
    }


    /** Get search result file url.
    * Do a toExternalForm( ) or toString( )
    * on returned URL to just use it.  Use
    * getProtocol( ) to figure if it's a file
    * or http spec.   Use getFile( ) in this
    * class to get the 'file' only portion of
    * the url.
    * <p>
    * The way i'm going to make an URL is look at first
    * character. If it's not a '/' for an absolute path,
    * I'm going to throw a malformedURL exception until
    * I come back and fix this code to handle more than
    * just files but http protocol too...
    *
    * @@return File location as a java.net.URL.
    * @@see #getFile
    * @@see java.net.URL
    */
    public java.net.URL getUrl( )
    {
        return url;
    }


    /** Return the 'file' portion of the url.
    * Calls java.net.URL.getFile( ).
    * @@return 'File' portion of the url
    */
    public String getFile( )
    {
        return url.getFile( );
    }


    /** Return the 'file' portion of the url w/
    * the htdoc path stripped off the front.
    * Does nothing if htdoc is null.  
    * @@return 'File' portion of the url. 
    * Has a leading '/'.
    */
    public String getFileRelativeToHtDoc( )
    {
        int index = -1;
        String str2Return = getFile( );

        if( htdocPath != null )
        {
            if( str2Return.indexOf( htdocPath ) != -1 )
            {
                int len = htdocPath.length( );
                if( htdocPath.endsWith( "/" ) )
                    len -= 1;
                str2Return
                    = str2Return.substring( len );
            }
        }

        return str2Return;
    }


    /** Return the file title.
    * Usually the HTML file TITLE
    * @@return File title.  Can be null.
    */
    public String getTitle( )
    {
        return title;
    }
    
    
    /** Run a special sourcecast transformation on the search engine result.
    *
    * Talking to Jason Robbins today, 11/01/2000, he explained the following
    * transform for the results returned by swish-e.  The transform is to be
    * used as the URL that a user clicks on in the search page when they want
    * to go to a found item.
    * <p>
    * Here is the receipe. If swish-e returns 
    * /home/stack/cvsroot/sandbox/data/helm/htdocs/bsdchess/www/index.html,
    * we should manufacture a result URL of http://bsdchess.wireopen.org/index.html.
    * More formally, using the PROTOCOL, PORT, DOMAIN and HTDOC passed to this
    * constructor, rearrange the swish-e result file path extracting the project
    * name and parring back the file path to what's left stripping to after the
    * 'www' -- the PATH_REMAINDER -- as: PROTOCOL://PROJECT.DOMAIN:PORT/PATH_REMAINDER
    * <p>
    * I expect the rules to change.
    *
    * @@return String of the form 'PROTOCOL://PROJECT.DOMAIN:PORT/PATH_REMAINDER
    * Returns null for fields for which we can't determine a value.
    *
    * @@exception NullPointerException If passed in inURL object is empty.
    * @@exception IndexOutOfBoundsException If what we find doesn't fit 
    * expected pattern
    */
    public String getSourceCastURL( )
        throws NullPointerException,
                IndexOutOfBoundsException
    {
        StringBuffer strBuffer = new StringBuffer( ); // StrBuffer to build url in.        
        PathParseResult parse = parsePath( ); // Parse up path of found file
        
        // Now start making up the url
        //
        strBuffer.append( ( protocol == null )
            ? PROTOCOL_DEFAULT
            : protocol );
        strBuffer.append( "://" );
        strBuffer.append( parse.getProjectName( ) );
        strBuffer.append( "." );
        strBuffer.append( domain );
        if( port != null
            && !port.equals( DEFAULT_PORT_80 ) )
        {
            strBuffer.append( ":" );
            strBuffer.append( port );
        }
        strBuffer.append( "/" );
        strBuffer.append( parse.getPathRemainder( ) );
        
        return strBuffer.toString( );
    }
    
    
    /** Parse up the file path pulling out project name and project relative
    * path remainder.
    *
    * Call to getFileRelativeToHtDoc( ) in the below code strips
    * the htdoc path from head of full-path to found file. 
    * The return looks like /PROJECT_NAME/www/some_file, etc.
    * Cut it up into projectName and PATH_REMAINDER, 
    * a project relative path. In the case of our example it 
    * will be 'some_file'.
    *
    * @@return An instance of our private class defined below.
    *
    * @@exception NullPointerException If passed in inURL object is empty.
    * @@exception IndexOutOfBoundsException If what we find doesn't fit 
    * expected pattern
    *
    * @@see #getSourceCastURL for specification.
    */
    private PathParseResult parsePath( )
        throws NullPointerException,
                IndexOutOfBoundsException
    {
        String projectName = null; // Name of project.
        String resource = null; // Part of file-path that follows '...htdocs/project/www/'
        
        String relativeURL = getFileRelativeToHtDoc( );
        if( relativeURL == null )
            throw new NullPointerException( "getFileRelativeToHtDoc( ) returned null" );
        if( relativeURL.startsWith( java.io.File.separator ) )
            relativeURL = relativeURL.substring( 1 ); // Strip leading '/'
        int index = relativeURL.indexOf( SLASH_WWW_SLASH );
        if( index < 0 )
        {
            throw new IndexOutOfBoundsException( "getFileRelativeToHtDoc( )"
                + " does not have expected 'project'/www/'resource' pattern: "
                + relativeURL );
        }
        projectName = relativeURL.substring( 0, index );
        if( projectName.length( ) <= 0 )
            throw new NullPointerException( "projectName is zero length" );   
        resource = relativeURL.substring( index + SLASH_WWW_SLASH.length( ) );
        if( resource.length( ) <= 0 )
            throw new NullPointerException( "resource is zero length" );
            
        return new PathParseResult( projectName, resource );

    }
    
    
    /** Structure to hold two values.  
    * Defined as an inner class.  Immutable.
    * Private.
    */
    private class PathParseResult
    {
        /** The project name found.
        */
        private String projectName = null;
        
        
        /** The remainder after stripping
        * project name, www, etc.
        */
        private String pathRemainder = null;
        
        
        /** Constructor
        */
        private PathParseResult( String inProjectName,
                                    String inPathRemainder )
            throws NullPointerException
        {
            if( inProjectName == null )
                throw new NullPointerException( "inProjectName null" );
            projectName = inProjectName;
            if( inPathRemainder == null )
                throw new NullPointerException( "inPathRemainder null" );
            pathRemainder = inPathRemainder;
        }
        
        
        /** Accessor for pathRemainder
        * @@return String of the pathRemainder
        */
        private String getPathRemainder( )
        {
            return pathRemainder;
        }
        
        
         /** Accessor for projectName
        * @@return String of the pathRemainder
        */
        private String getProjectName( )
        {
            return projectName;
        }       
    }
}
@
