/*
 * @(#)ExtensionListFilter.java
 *
 * Summary: Select a file based on it matches one of list of extensions.
 *
 * Copyright: (c) 2005-2010 Roedy Green, Canadian Mind Products, http://mindprod.com
 *
 * Licence: This software may be copied and used freely for any purpose but military.
 *          http://mindprod.com/contact/nonmil.html
 *
 * Requires: JDK 1.5+
 *
 * Created with: IntelliJ IDEA IDE.
 *
 * Version History:
 *  2.5 2009-02-28 - CommandLine split off in its own package.
 */
package com.mindprod.filter;

import java.io.File;
import java.io.FilenameFilter;
import java.util.HashSet;

/**
 * Select a file based on it matches one of list of extensions.
 * <p/>
 * Does not work with directories, see DirListFilter. see also
 * FileListFilter and ClamFilter. Rejects all directories.
 *
 * @author Roedy Green, Canadian Mind Products
 * @version 2.5 2009-02-28 - CommandLine split off in its own package.
 * @since 2005-06-30
 */
public final class ExtensionListFilter implements FilenameFilter// note Sun's
        // spelling, not
        // FileNameFilter

    {
    // ------------------------------ CONSTANTS ------------------------------

    /**
     * true if debugging. Enables debugging harness.
     */
    public static final boolean DEBUGGING = false;

    // ------------------------------ FIELDS ------------------------------

    /**
     * Collection of extension names describing directories you do want, in lower case, without the leading dot.
     */
    private HashSet<String> want;
    // -------------------------- PUBLIC INSTANCE  METHODS --------------------------

    /**
     * constructor
     *
     * @param want Array of simple file extensios names, case insensitive, e.g. new String["html", "txt", "bat" ];
     */
    public ExtensionListFilter( String... want )
        {
        // we need them in lower case. We don't want to disturb the caller's
        // array.
        // we don't lower case the caller's array.

        this.want = new HashSet<String>( Math.max( ( int ) ( want.length / .75f ) + 1, 16 ) );
        if ( want == null )
            {
            return;
            }
        for ( int i = 0; i < want.length; i++ )
            {
            if ( want[ i ].startsWith( "." ) )
                {
                throw new IllegalArgumentException(
                        "ExtensionListFilter extensions should not include the leading dot"
                        + want[ i ] );
                }
            this.want.add( want[ i ].toLowerCase() );
            }
        }

    /**
     * Select only Files with an extension in our want list
     *
     * @param dir  the directory in which the file was found.
     * @param name the name of the file
     *
     * @return true if and only if the name should be included in the file list; false otherwise.
     */
    public boolean accept( File dir, String name )
        {
        File f = new File( dir, name );
        if ( f.isDirectory() )
            {
            return false;
            }
        // strip out the extension.
        int place = name.lastIndexOf( '.' );
        if ( place < 0 )
            {
            return false;
            }
        // get just stuff past the dot to the end
        String ext = name.substring( place + 1 );
        return want.contains( ext.toLowerCase() );
        }

    // --------------------------- main() method ---------------------------

    /**
     * TEST harness
     *
     * @param args not used
     */
    public static void main( String[] args )
        {
        if ( DEBUGGING )
            {
            // find all just the files listed, case insensitive.
            FilenameFilter f = new ExtensionListFilter( "java", "class" );

            String[] filenames = new File( "C:\\com\\mindprod\\filter" )
                    .list( f );

            for ( int i = 0; i < filenames.length; i++ )
                {
                System.out.println( filenames[ i ] );
                }
            }
        }
    }// end ExtensionListFilter
