/*
 * $Id: StringUtil.java 223 2007-10-14 08:07:40Z sugimotokenichi $
 * Copyright (C) 2005 SUGIMOTO Ken-ichi
 * 作成日: 2005/04/17
 */
package feat2;


import java.io.UnsupportedEncodingException;
import java.util.Locale;
import java.util.Map;

import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.WordUtils;


/**
 * 文字列操作のユーティリティメソッドを集めたクラス。
 * @author SUGIMOTO Ken-ichi
 */
public class StringUtil {

    /**
     * 文字列をホワイトスペースを境界として分割する。
     * 文字列の先頭と末尾のスペースは無視される。
     * @param str
     * @return
     */
    public static String[] split(String str) {
        return StringUtils.split(str);
    }


    public static String[] split(String str, String delimitor) {
        return StringUtils.split(str, delimitor);
    }


    public static String[] split(String str, char delim) {
        return StringUtils.split(str, delim);
    }


    public static String join(String[] array, String str) {
        return StringUtils.join(array, str);
    }


    public static String[] stripAll(String[] str) {
        return StringUtils.stripAll(str);
    }


    public static String substringBefore(String str, String separator) {
        return StringUtils.substringBefore(str, separator);
    }


    /**
     * 空白で区切られた単語の先頭の文字を大文字にする。
     * @param str
     * @return
     */
    public static String capitalize(String str) {
        return WordUtils.capitalize(str);
    }


    /**
     * asciiとしてJava文字列に変換されてしまったテキストを指定のエンコーディングでJava文字列に変換しなおす。
     * @param str
     * @param encoding
     * @return
     * @throws UnsupportedEncodingException
     */
    public static String convertEncoding(String str, String encoding) throws UnsupportedEncodingException {
        return new String( str.getBytes("ISO-8859-1"), encoding );
    }


    public static String[] convertEncoding(String[] str, String encoding) throws UnsupportedEncodingException {
        String[] ret = new String[str.length];
        for (int i = 0; i < str.length; i++) {
            ret[i] = convertEncoding(str[i], encoding);
        }
        return ret;
    }


    public static String escapeHTMLText(String str) {
        str = StringUtils.replace(str, "&", "&amp;");
        str = StringUtils.replace(str, "<", "&lt;");
        str = StringUtils.replace(str, ">", "&gt;");
        str = StringUtils.replace(str, "\"", "&quot;");
        return str;
    }


    public static String unescapeHTMLText(String escaped) {
        escaped = StringUtils.replace(escaped, "&lt;", "<");
        escaped = StringUtils.replace(escaped, "&gt;", ">");
        escaped = StringUtils.replace(escaped, "&quot;", "\"");
        escaped = StringUtils.replace(escaped, "&amp;", "&");
        return escaped;
    }


    public static String escapeXMLText(String str) {
        str = StringUtils.replace(str, "&", "&amp;");
        str = StringUtils.replace(str, "<", "&lt;");
        str = StringUtils.replace(str, ">", "&gt;");
        str = StringUtils.replace(str, "\"", "&quot;");
        str = StringUtils.replace(str, "'", "&apos;");
        return str;
    }


    public static String unescapeXMLText(String escaped) {
        return StringEscapeUtils.unescapeXml(escaped);
    }


    /**
     * JavaScriptの文字列のためのエスケープ
     * @param val
     * @return
     */
    public static String escapeJavaScriptString(String val) {
        return StringEscapeUtils.escapeJavaScript(val);
    }


    public static String replace(String str, String o, String n) {
        return StringUtils.replace(str, o, n);
    }


    private static final String SJIS_CHARS =  "\u301C\u2212\u2016\u00A2\u00A3\u00AC";
    private static final String MS932_CHARS = "\uFF5E\uFF0D\u2225\uFFE0\uFFE1\uFFE2";
    public static String toSJISString(String str) {

        return StringUtils.replaceChars(str, MS932_CHARS, SJIS_CHARS);

    }


    public static String toMS932String(String str) {

        return StringUtils.replaceChars(str, SJIS_CHARS, MS932_CHARS);

    }


    public static String correctJapaneseChars(String str, String enc) {

        if ( enc != null && str != null ) {

            if ( enc.equalsIgnoreCase("windows-31j") || enc.equalsIgnoreCase("ms932") )
                return toMS932String(str);

            else if ( enc.equalsIgnoreCase("shift_jis") || enc.equalsIgnoreCase("sjis") )
                return toSJISString(str);

        }

        return str;

    }


    public static String replaceParameters(String str, String[] values) {
        String[] names = new String[values.length];
        for(int i=0; i<names.length; i++) {
            names[i] = Integer.toString(i+1);
        }
        return replaceParameters(str, names, values);
    }


    public static String replaceParameters(String str, Map keywords) {

        if ( keywords.size() == 0 )
            return str;

        String[] names = (String[])keywords.keySet().toArray(new String[0]);
        String[] values = new String[names.length];

        for (int i = 0; i < names.length; i++) {
            values[i] = (String)keywords.get(names[i]);
        }

        return replaceParameters(str, names, values);

    }


    public static String replaceParameters(String str, String[] names, String[] values) {

        if ( names.length == 0 )
            return str;

        char[] c = str.toCharArray();
        StringBuffer buf = new StringBuffer(c.length * 6 / 5);
        StringBuffer name = new StringBuffer();
        int mode = 0;
        for(int idx=0; idx<c.length; idx++) {
            switch(mode) {
                // '$'を探す
                case 0:
                    if ( c[idx] == '$' )
                        mode = 1;
                    else
                        buf.append(c[idx]);
                    break;
                // '$'の次の文字
                case 1:
                    if ( c[idx] == '$' ) {
                        buf.append('$');
                        mode = 0;
                    }
                    else if ( c[idx] == '{' ) {
                        mode = 2;
                        name.setLength(0);
                    }
                    break;
                // パラメータ名
                case 2:
                    if ( c[idx] == '}' ) {
                        mode = 0;
                        String n = name.toString();
                        for(int i=0; i<names.length; i++) {
                            if ( names[i].equals(n) ) {
                                buf.append(values[i]);
                            }
                        }
                    }
                    else {
                        name.append(c[idx]);
                    }
                    break;
            }
        }
        return buf.toString();
    }


    /**
     * ロケール名を含んだファイル名を作る。
     * 元のファイル名の拡張子の前に指定のロケール名を挿入する。
     * 拡張子とみなされるのはファイル名の最後の'.'の後ろ。
     * 拡張子が２つ以上重なっている".tar.gz"のようなファイル名は".tar.ja.gz"となってしまうので注意。
     * @param baseName 元になるファイル名
     * @param locale ロケール
     * @return
     */
    public static String makeLocaleFilename(String baseName, Locale locale) {
        if ( locale != null && !locale.equals(Util.NULL_LOCALE) ) {
            int dotIdx = baseName.lastIndexOf('.');
            String ret = baseName.substring(0, dotIdx) + "." + locale.toString() + baseName.substring(dotIdx);
            return ret;
        }
        else
            return baseName;
    }

}
