package com.jware.util.bean;

/**
 * StringのUtilityクラス
 * Stringの変換、チェック、nvl,pad,replaceなどUtilityメソッド
 * を提供する
 */
public class StrUtil {

    public static final String LINE_SEPARATOR =
        System.getProperty("line.separator", "\n");

    private static final int MAXSPACES = 2560;

    private static final int MAXZEROS = 2560;

    private static final String INIT_SPACES =
        "                                        ";

    private static final int INIT_SPACESLEN = 40;

    private static final String INIT_ZEROS =
        "0000000000000000000000000000000000000000";

    private static final int INIT_ZEROSLEN = 40;

    private static String SPACES = "";

    private static int SPACESLEN = 0;

    private static String ZEROS = "";

    private static int ZEROSLEN = 0;

    private static Object lock = new Object();

    /**
     *   デフォルトコンストラクタ
     */
    private StrUtil() {
    }

    /**
     *   ブランク文字列の取得
     * 　指定する長さのブランク文字列を戻る
     * @param       len 長さ
     * @return      指定する長のブランク文字列
     * @exception   StringIndexOutOfBoundsException (長さは2560に超える場合).
     */
    public static String getSpaces(int len) {
        if (len > SPACESLEN && SPACESLEN < MAXSPACES) {
            //aquire lock only when neccessary
            synchronized (lock) {
                while (len > SPACESLEN && SPACESLEN < MAXSPACES) {
                    SPACES = SPACES + INIT_SPACES;
                    SPACESLEN = SPACESLEN + INIT_SPACESLEN;
                }
            }
        }
        return SPACES.substring(0, len);
    }

    /**
     * 　　　　　　指定長さの"0"文字列の取得
     * 　　　　指定する長さの0文字列を戻る(ASCII 48)
     *
     * @param       長さ
     * @return      文字列
     * @exception   StringIndexOutOfBoundsException (長さは2560に超える場合).
     */
    static public String getZeros(int len) {
        if (len > ZEROSLEN && ZEROSLEN < MAXZEROS) {
            synchronized (lock) {
                while (len > ZEROSLEN && ZEROSLEN < MAXZEROS) {
                    ZEROS = ZEROS + INIT_ZEROS;
                    ZEROSLEN = ZEROSLEN + INIT_ZEROSLEN;
                }
            }
        }
        return ZEROS.substring(0, len);
    }

    /**
     * 　文字列はNULLの場合,""を戻る。　
     * @param sIn
     * @return
     */
    public static String nvl(String sIn) {
        return (sIn == null) ? "" : sIn;
    }

    /**
     * 　change the input string to the specified string
     * if the input string is null　
     * @param sIn input string
     * @param sDef  replacement
     * @return 　change the input string to the specified string
     * if the input string is null
     */
    public static String nvl(String sIn, String sDef) {
        return (sIn == null) ? sDef : sIn;
    }

    /**
         *  Pads the String s to the given length by inserting blanks at the left
     * side. If s is longer than len, the String remains unchanged. 
     * @param       s String to pad
     * @param       len length of resulting String
     * @return      The padded String.
     */
    static public String padLeft(String s, int len) {
        return padLeft(s, len, false);
    }

    /**
     * 　Pads the String s to the given length by inserting blanks at the left
     * side. If s is longer than len and trim is set to true, the result is
     * truncated to the given length.　
     *
     * @param       s String to pad
     * @param       len length of resulting String
     * @param       trim truncates s if longer then len
     * @return      The padded String.
     */
    public static String padLeft(String s, int len, boolean trim) {
        s = StrUtil.nvl(s);
        int slen = s.getBytes().length;
        String ret = null;

        if (slen < len) {
            ret = getSpaces(len - slen) + s;
        } else if (slen > len && trim) {
            ret = "";
            int length = s.length();
            for (int n = 0; n < length; n++) {
                if ((ret + s.charAt(n)).getBytes().length > len) {
                    break;
                }
                ret = ret + s.charAt(n);
            }
        } else {
            ret = s;
        }
        return ret;
    }

    /**
     *　 Pads the String s to the given length by inserting blanks at the right
     * end. If s is longer than len, the String remains unchanged.
     *
     * @param       s String to pad
     * @param       len length of resulting String
     * @return      The padded String.
     */

    static public String padRight(String s, int len) {
        return padRight(s, len, false);
    }

    /**
     * 　Pads the String s to the given length by inserting blanks at the right
     * end. If s is longer than len and trim is true, the result is
     * truncated to the given length.
     *
     * @param       s String to pad
     * @param       len length of resulting String
     * @param       trim truncates s if longer then len
     * @return      The padded String.
     */

    static public String padRight(String s, int len, boolean trim) {
        s = StrUtil.nvl(s);
        //int slen = s.length();
        int slen = s.getBytes().length;
        String ret = null;

        if (slen < len) {
            ret = s + getSpaces(len - slen);
        } else if (slen > len && trim) {
            ret = "";
            int length = s.length();
            for (int n = 0; n < length; n++) {
                if ((ret + s.charAt(n)).getBytes().length > len) {
                    break;
                }
                ret = ret + s.charAt(n);
            }
        } else {
            ret = s;
        }
        return ret;
    }

    /**
     * 　Left-pads the String with zeros to the given length.
     *
     * @param       s String to pad
     * @param       len length of resulting String
     * @return      The padded value as a String.
     */
    static public String padZero(String s, int len) {
        s = StrUtil.nvl(s);
        //int slen = s.length();
        int slen = s.getBytes().length;

        String ret = null;
        if (slen < len) {
            ret = getZeros(len - slen) + s;
        } else {
            ret = s;
        }

        return ret;
    }

    /**
         *　 Converts the integer value into a String which is left-padded with
     * zeros to the given length.
     *
     * @param       value integer value to pad
     * @param       len length of resulting String
     * @return      The padded value as a String.
     */
    static public String padZero(int value, int len) {
        String s = "" + value;
        int slen = s.length();
        String ret = null;

        if (slen < len) {
            ret = getZeros(len - slen) + s;
        } else {
            ret = s;
        }
        return ret;
    }

    /**
     * 　文字列を変換する。
     *
     * @param src　
     * @param sFnd
     * @param sRep
     * @return 変換された文字列
     */
    public static String replaceStr(String src, String sFnd, String sRep) {
        String sTemp = "";
        int endIndex = 0;
        int beginIndex = 0;

        do {
            endIndex = src.indexOf(sFnd, beginIndex);
            if (endIndex >= 0) { //mean found it.
                sTemp = sTemp + src.substring(beginIndex, endIndex) + sRep;
                beginIndex = endIndex + sFnd.length();
            } else if (beginIndex >= 0) {
                sTemp = sTemp + src.substring(beginIndex);
                break;
            }
        } while (endIndex >= 0);

        return sTemp;
    }

    /**
     *  remove char from the input string 
     * @param   str    input string
     * @param   rc     removed char
     * @return  string
     */
    public static String removeChar(String str, String rc) {
        if (str == null) {
            return null;
        }

        int i = str.indexOf(rc);
        while (i >= 0) {
            str = str.substring(0, i) + str.substring(i + 1, str.length());
            i = str.indexOf(rc);
        }

        return str;
    }

    /**
     *  文字は空白かどうかをチェックする。
     *
     * @param c 文字
     * @return true 文字列は空白である。
     *          false 文字列は空白ではない。
     */
    public static boolean isSpace(char c) {
        return (c == ' ' || c == '\t' || c == ' ');
    }

    /**
     *   文字列は空白かどうかをチェックする。
     *
     * @param s 文字列
     * @return true 文字列は空白である。
     *          false 文字列は空白ではない。
     */
    public static boolean isSpace(String s) {
        if (s == null) {
            return false;
        }
        int length = s.length();
        for (int i = 0; i < length; i++) {
            if (!isSpace(s.charAt(i))) {
                return false;
            }
        }

        return true;
    }

    /**
     *  文字はNULLまたは\0かどうかをチェックする。
     *
     * @param c 文字
     * @return true 文字列はＮＵＬＬまたは\0
     */
    public static boolean isNullString(String str) {
        return (str == null || "".equals(str.trim()));
    }

    /**
     *  文字列の前後空白を除く。
     *
     * @param s 文字列
     * @return  変更された文字列。
     */
    public static String trim(String s) {

        if (s == null) {
            return null;
        }

        int begin = 0;
        int end = 0;
        int length = s.length();
        for (begin = 0; (begin < length); begin++) {
            if (!isSpace(s.charAt(begin))) {
                break;
            }
        }

        for (end = length - 1; end >= 0; end--) {
            if (!isSpace(s.charAt(end))) {
                break;
            }
        }

        if (end < begin) {
            return "";

        }
        return s.substring(begin, end + 1);
    }

    /**
     *   数字の判断　
     *
     * @param s 文字列
     * @return　文字列のcharは数字であれば、trueを戻る
     */
    public static boolean isDigit(String s) {
        s = trim(s);
        final int n = s.length();
        for (int i = 0; i < n; i++) {
            char c = s.charAt(i);
            if (!Character.isDigit(c)) {
                return false;
            }
        }
        return true;
    }
}
