/*
 * HDirectory.java
 * 
 * Author: http://www.hrtdotnet.jp/
 * 
 */
package jp.hrtdotnet.java.io;

import java.io.File;
import java.io.IOException;

/**
 * ディレクトリを操作するクラスです。
 * このクラスを利用してファイルを操作することは禁止されています。
 * 
 * @version 2.0
 * @author hrtdotnet.jp
 * <br>http://www.hrtdotnet.jp/
 * @since 2.0
 */
public class HDirectory extends File {

    private static final long serialVersionUID = -1822934435075769490L;

    /**
     * コンストラクタ。
     * 
     * @param directoryPath ディレクトリパス
     * @throws IOException
     *          directoryPathがファイルである、またはディレクトリとして不正なパスである場合
     * @since 2.0
     */
    public HDirectory(String directoryPath) throws IOException {
        super(directoryPath);
        if (exists() && isFile()) {
            throw new IOException("Directory is file.");
        }        
        if( checkDirectoryName(directoryPath) == false){
            throw new IOException("Directory-path is invalid.");
        }
    }

    /**
     * ディレクトリパスの正当性の判定をします。
     * ディレクトリパスが以下の条件にマッチする場合、不正であると判断されます。
     * <ol>
     * <li>null文字列</li>
     * <li>長さが0バイト（空文字）、256バイト以上</li>
     * <li>大小区別せずに頭文字が「CON.」「AUX.」「PRN.」「NUL.」から始まる</li>
     * <li>拡張子を除いた名前が「COM[0-9]」「LPT[0-9]」のもの（[0-9]は0〜9のどれか）</li>
     * <li>「\」「:」「*」「?」「&quot;」「&lt;」「&gt;」「|」を含む</li>
     * <li>末尾が「.」（ドット）</li>
     * </ol>
     * 
     * @param directory ディレクトリパス
     * @return 正当であればtrue、それ以外はfalse
     * @since 2.0
     */
    public static boolean checkDirectoryName(String directory) {

        if (directory == null || directory.length() < 1) {
            return false;
        }        
        directory = directory.replaceAll("\\\\", "/");
        String dirArray[] = directory.split("/");
        
        for (int i = 0; i < dirArray.length; i++) {
            if(dirArray[i] == null || dirArray.length < 1){
                continue;
            }

            // ファイル名が空文字はfalseを返す
            if (dirArray[i].length() > 255) {
                return false;
            }

            String upperStr = dirArray[i].toUpperCase();
            
            if (upperStr.startsWith("CON.")
                    || upperStr.startsWith("AUX.")
                    || upperStr.startsWith("PRN.")
                    || upperStr.startsWith("NUL.")) {
                return false;
            }

            if (upperStr.matches("COM[0-9]\\..*")
                    || upperStr.matches("LPT[0-9]\\..*")
                    || upperStr.matches("COM[0-9]")
                    || upperStr.matches("LPT[0-9]")) {
                return false;
            }

            if ((i == 0 && upperStr.matches("[a-zA-Z]:")) == false) {
                if (upperStr.indexOf(":") != -1) {
                    return false;
                }
            }
            
            if (upperStr.indexOf("*") != -1
                    || upperStr.indexOf("?") != -1 || upperStr.indexOf("\"") != -1
                    || upperStr.indexOf("<") != -1 || upperStr.indexOf(">") != -1
                    || upperStr.indexOf("|") != -1) {
                return false;
            }

            // ファイル名の最後が "." は不正
            if (dirArray[i].endsWith(".")) {
                return false;
            }
        }        
        return true;
    }

    /**
     * このメソッドは利用してはなりません。
     * 利用した場合、File#createNewFile()と同じ処理を行います。
     * 
     * @deprecated このメソッドは利用してはなりません。
     * @since 2.0
     */
    public boolean createNewFile() throws IOException {
        return super.createNewFile();
    }

}
