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

/**
 * 条件にあうファイルのリストを作成・保持する抽象クラス。
 */
public abstract class FileFinder {
    /**
     * 結果のファイルのリスト
     */
    private ArrayList<File> result;

    /**
     * 見つけたファイルを列挙結果に含めるか判定する抽象メソッド。
     * @return	列挙するときtrue
     */
    abstract boolean filter(File f);

    /**
     * ディレクトリの探索を打ち切るか決めるメソッド。
     * filter()の結果とは独立に動作する。
     */
    abstract boolean prune(File f);

    //----------------------------------------------------------------------

    /**
     * コンストラクタ
     */
    public FileFinder() {
	result = new ArrayList<File>();
    }

    /**
     * トラバースを実施する。
     */
    protected void traverse(File f) {
	if(filter(f))
	    result.add(f);

	if(f.isDirectory()) {
	    if(prune(f))
		return; // 探索打ち切り
	    File[] arr = f.listFiles();
	    if(arr == null)
		return; // ディレクトリの中身が取得できない
	    for(int i = 0; i < arr.length; i++)
		traverse(arr[i]);
	}
    }

    /**
     * トラバースを実施して結果を保存し、自分自身を返す
     */
    public FileFinder find(File f) {
	traverse(f);
	return this;
    }

    /**
     * 結果をList<File>として取り出す
     */
    public List<File> getList() {
	return result;
    }

    /**
     * 結果をFile[]として取り出す
     */
    public File[] getArray() {
	return result.toArray(new File[0]);
    }

    //----------------------------------------------------------------------

    /**
     * テスト。レギュラーファイルをリストアップする
     */
    public static void main(String argv[]) {
	FileFinder ff = new FileFinder() {
		boolean filter(File f) {
		    return f.canRead();
		}
		boolean prune(File f) {
		    return false;
		}
	    };
	Iterator<File> i = ff.find(new File(argv[0])).getList().iterator();
	while(i.hasNext()) {
	    File f = i.next();
	    System.out.println(f.getPath());
	}
    }
}
