/*********************************************************************
* All Rights reserved,Copyright (c) K-Opticom
**********************************************************************
*＜プログラム内容＞
*   システム名      ：eo顧客基幹システム
*   ソースファイル名：JCCcomFileSearchUtil.java
*   作成者          ：富士通
*   日付            ：2009/05/10
*＜機能概要＞
*   指定ディレクトリからファイルを検索する
*＜修正履歴＞
*   バージョン  修正日      修正者      修正内容
*   v1.0版      2009/05/10  富士通      新規作成
*
**********************************************************************/
package eo.common.util;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TreeSet;

/**
 * 
 */
public class JCCcomFileSearchUtil {

    public static final int FILE_OR_DIR = 1;
    public static final int FILE = 2;
    public static final int DIR = 3;

    /** アルファベット順に並べるためTreeSetを使用 */
    private TreeSet set = new TreeSet();

    /**
     * 指定したディレクトリ[directory]から、正規表現として指定された
     * 検索対象のファイル[fileName]を再帰的に検索し、
     * 該当するファイルオブジェクトのリストを返します。
     * 
     * また、ファイルの更新日付が指定日数経過しているかどうかを検索条件に
     * 指定する事ができます。
     * 
     * 呼び出し例) 
     *     public File[] getlistFiles(String directory, String fileName) {
     *         // ワイルドカード文字として*を正規表現に変換
     *         if (fileName != null) {
     *             fileName = fileName.replace(".", "\\.");
     *             fileName = fileName.replace("*", ".*");
     *         }
     *         listFiles("C:/filelist/", "*.java",TYPE_FILE, true, 7);
     *     }
     * 上記の例では、ディレクトリfilelistを再帰的に検索し、7日前以降に更新
     * された拡張子javaのファイルリストを取得します。
     * 
     * @param directory 検索対象のディレクトリを表すパス
     * @param fileName 検索対象のファイル名[正規表現]
     * @param objType 該当するファイルオブジェクトは[type]により、
     *                以下の指定が可能
     *                FILE_OR_DIR・・・ファイル及びディレクトリ 
     *                FILE・・・ファイル
     *                DIR・・・ディレクトリ
     * @param isRecursive 再帰的に検索する場合はtrue
     * @param checkDate 検索対象として、ファイルの更新日付が指定日数経過
     *                しているかどうかを設定可能
     *                0の場合は対象外
     *                1以上の場合、指定日数以降のファイルを検索対象とする
     *                -1以下の場合、指定日数以前のファイルを検索対象とする
     * @return 検索にマッチしたファイルオブジェクト
     */
    public File[] listFiles(String directory, 
            String fileName, int objType, 
            boolean isRecursive, int checkDate) throws Exception{
        
        File dir = new File(directory);
        if (!dir.isDirectory()) {
            throw new Exception
            ("引数で指定されたパスはディレクトリではありません。:[" + dir.getAbsolutePath() + "]");
        }
        File[] files = dir.listFiles();
        // その出力
        for (int i = 0; i < files.length; i++) {
            File file = files[i];
            fileMatcher(objType, fileName, set, file, checkDate);
            // 再帰的に検索＆ディレクトリならば再帰的にリストに追加
            if (isRecursive && file.isDirectory()) {
                listFiles(file.getAbsolutePath(), fileName, 
                            objType, isRecursive, checkDate);
            }
        }
        return (File[]) set.toArray(new File[set.size()]);
    }

    private void fileMatcher(int objType, String fileName, TreeSet set,
            File file,int checkDate) {
        switch (objType) {
        case FILE:
            if (!file.isFile()) {
                return;
            }
            break;
        case DIR:
            if (!file.isDirectory()) {
                return;
            }
            break;
        }
        if (fileName != null && !file.getName().matches(fileName)) {
            return;
        }
        // 指定日数経過しているかどうかの指定がある場合
        if (checkDate != 0) {
            // ファイル更新日付
            Date lastModifiedDate = new Date(file.lastModified());
            String lastModifiedDateStr = new SimpleDateFormat("yyyyMMdd")
                    .format(lastModifiedDate);

            // 指定の日付（１日をミリ秒で計算）
            long oneDayTime = 24L * 60L * 60L * 1000L; 
            long periodTime = oneDayTime * Math.abs(checkDate);
            Date designatedDate = 
                new Date(System.currentTimeMillis() - periodTime);
            String designatedDateStr = new SimpleDateFormat("yyyyMMdd")
                    .format(designatedDate);
            if (checkDate > 0) {
                if (lastModifiedDateStr.compareTo(designatedDateStr) < 0) {
                    return;
                }
            } else {
                if (lastModifiedDateStr.compareTo(designatedDateStr) > 0) {
                    return;
                }
            }
        }
        // 全ての条件に該当する場合リストに格納
        set.add(file);

    }

    /**
     * インスタンスを生成後、続けて使用する場合は、このメソッドを
     * 呼び出しクリアする必要がある。
     * 例)
     *  FileSearch search = new FileSearch();
     *  File[] f1 = search.listFiles(C:/filelist/", "*.java");
     *  search.clear();
     *  File[] f2 = search.listFiles("C:/filelist/", "*.jsp"); 
     */
    public void clear(){
    	set.clear();
    }
}

