package jp.agentec.sinaburocast.common.util;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.net.UnknownHostException;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.swing.JTextArea;

import jp.agentec.sinaburocast.common.SinaburoConstant;
import jp.agentec.sinaburocast.common.SinaburoConstant.Dir;
import jp.agentec.sinaburocast.common.SinaburoConstant.Formats;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.net.util.SubnetUtils;
import org.apache.commons.validator.GenericValidator;
import org.apache.log4j.Logger;
import org.apache.velocity.tools.generic.DateTool;
import org.seasar.framework.util.StringUtil;

/**
 * Utilクラス<br>
 * 主に数値・文字列操作を扱うメソッドを集約<br>
 *
 * ※メソッド追加の際はApache Commons, Seaserのユーティリティクラスに該当の機能が存在しないことをまず確認すること。
 *
 * @author tsukada
 *
 */
public class SinaburoUtil {
	private static final Logger LOGGER = Logger.getLogger(SinaburoUtil.class);

	/**
	 * 配列が空ではないか返す。
	 *
	 * @param objectArray
	 * @return
	 */
	public static boolean isNotEmpty(Object[] objectArray) {
		return !ArrayUtils.isEmpty(objectArray);
	}

	/**
	 * 文字列がブランクかもしくはスペース(全角含む)のみで構成されているか返す。
	 *
	 * @param s
	 * @return
	 *
	 * use {@link StringUtils#isBlank(String)} instead.
	 */
	public static boolean isBlankOrSpace(String s) {
		if (s == null || s.trim().length() == 0) {
			return true;
		}
		else {
			s = StringUtil.replace(s, " ", "");
			s = s.trim();
			return s.length() == 0;
		}
	}

	/**
	 * 文字列がブランクもしくはスペースのみ以外であるか返す。
	 *
	 * @param s
	 * @return
	 *
	 * use {@link StringUtils#isNotBlank(String)} instead.
	 */
	public static boolean isNotBlankOrSpace(String s) {
		return !isBlankOrSpace(s);
	}

	/**
	 * 第一引数がnullもしくはブランクの場合に、第二引数の文字列を返す。
	 *
	 * @param org
	 * @param rep
	 * @return
	 *
	 * LATER If org is an instance of String, use {@link StringUtils#defaultIfEmpty(String, String)} instead.
	 */
	public static String nvl(Object org, String rep) {
		if (org == null || org.toString().length() == 0) {
			return rep;
		}
		else {
			return org.toString();
		}
	}

	/**
	 * nullの場合に、空文字を返す。
	 *
	 * @param org
	 * @return
	 *
	 * LATER If org is an instance of String, use {@link StringUtils#defaultIfEmpty(String, "")} instead.
	 */
	public static String nvl(Object org) {
		return nvl(org, "");
	}

	/**
	 * 空文字の場合、nullを返す。
	 *
	 * @param s
	 * @return
	 */
	public static String toNull(String s) {
		if (StringUtils.isEmpty(s)) {
			return null;
		}
		return s;
	}

	/**
	 * 0の場合に、デフォルト値を返す。
	 *
	 * @param org
	 * @return
	 */
	public static int zvl(int org, int def) {
		if (org == 0) {
			return def;
		}
		return org;
	}

	/**
	 * Integerをintに変換する。<br>
	 * nullの場合0を返す
	 *
	 * @param integer
	 * @return
	 */
	public static int parseInt(Integer integer) {
		if (integer == null) {
			return 0;
		}
		return integer;
	}

	/**
	 * 文字列をshortに変換する。<br>
	 * shortに変換できない場合0を返す。
	 *
	 * @param s
	 * @return
	 *
	 * LATER Apache commonsを2.5以降にバージョンアップすれば廃止できる
	 */
	public static short toShort(String str) {
		short s = 0;
		try {
			s = Short.parseShort(str);
		} catch (Exception e) {}
		return s;
	}

	/**
	 * 文字列を、指定の長さで、指定セパレータで折り返して返却する。<br>
	 * 単語の途中では区切らない。
	 *
	 * @param message 元の文字列
	 * @param maxwidth 一行の長さ
	 * @param separator 行のセパレータ
	 * @return 折り返した文字列
	 */
	public static String wrapLine(String message, int maxwidth, String separator) {
		if (maxwidth < 1) return message;
		if (StringUtils.isEmpty(message)) return "";
		if (separator == null) {
			separator = "";
		}

		// LATER \S, \sの定義はロケールによって変化するが本当でこれでよいのか?
    	Pattern regx = Pattern.compile("(\\S\\S{" + maxwidth + ",}|.{1," + maxwidth + "})(\\s+|$)");
		List<String> list = new LinkedList<String>();
		Matcher m = regx.matcher(message);
		while (m.find()) list.add(m.group());
		return StringUtils.chomp(StringUtils.join(list, separator));
	}

	/**
	 * 文字列を、指定の長さで、指定セパレータで折り返して返却する。<br>
	 * 単語の途中でも折り返す。
	 *
	 * @param message 元の文字列
	 * @param maxwidth 一行の長さ
	 * @param separator 行のセパレータ
	 * @return 折り返した文字列
	 */
	public static String wrapLineNoWord(String message, int maxwidth, String separator) {
		if (StringUtils.isEmpty(message)) return "";
		if (maxwidth < 1) return message;
		if (separator == null) {
			separator = "";
		}

		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < message.length(); i++) {
			sb.append(message.charAt(i));
			if (i != 0 && i % maxwidth == 0) {
				sb.append(separator);
			}

		}
		return StringUtils.chomp(sb.toString());
	}

	/**
	 * バイト表示フォーマットに変換する。<br>
	 * B, K, M, G単位で丸める。<br>
	 *
	 * @param size
	 * @return
	 */
	public static String formatByte(long size){
		if(size/1024 < 1){
			return size + "B";
		}
		else if(size/(1024*1024) < 1){
				return size/1024 + "K";
		}
		else if(size/(1024*1024*1024) < 1){
			return size/(1024*1024) + "M";
		}
		else{
			return size/(1024*1024*1024) + "G";
		}
	}
	/**
	 * 現在値に対して対象bitの値をonまたはoffにする。
	 * (チェックボックス用)
	 *
	 * @param currentVal 現在値
	 * @param targetFlgVal 対象bitの値
	 * @param on オンかどうか
	 * @return
	 */
	public static int mergeBitValue(int currentVal, int targetFlgVal, boolean on) {
		int clearTargetFlg = (currentVal & targetFlgVal) > 0? currentVal - targetFlgVal: currentVal;
		return clearTargetFlg | (on? targetFlgVal:0);
	}


	/**
	 * 引数のStringの中で最初に空でないものを返す。
	 * @param args
	 * @return
	 */
	public static String getFirstNoBlank(String... args) {
		if (args != null) {
			for (String str: args) {
				if (StringUtils.isNotEmpty(str)) {
					return str;
				}
			}
		}
		return "";
	}


	/**
	 * 引数の中で、空ではない個数を返す。
	 *
	 * @param args
	 * @return
	 */
	public static int getNoBlankCount(String... args) {
		int count = 0;
		if (args != null) {
			for (String str: args) {
				if (StringUtils.isNotEmpty(str)) {
					count++;
				}
			}
		}
		return count;
	}

	/**
	 * 第二引数以降の文字列を、第一引数のセパレータで連結して返す。
	 *
	 * @param separator
	 * @param args
	 * @return
	 */
	public static String joinAllNoBlank(String separator, Object... args) {
		if (args == null) return "";
		if (separator == null) separator = "";

		StringBuilder sb = new StringBuilder();
		boolean first = true;
		for (Object obj: args) {
			if (obj == null) {
				obj = "";
			}
			if (StringUtils.isNotEmpty(obj.toString())) {
				if (first) {
					sb.append(obj);
					first = !first;
				}
				else {
					sb.append(separator).append(obj);
				}
			}
		}
		return sb.toString();
	}

	/**
	 * オブジェクトから指定フィールドの値を取り出す。<br>
	 * (リフレクションを用いる)
	 *
	 * @param object
	 * @param fieldName
	 * @return
	 */
	public static Object getFieldValue(Object object, String fieldName) {
		Field field;
		try {
			field = getField(object, fieldName);
			field.setAccessible(true);
			return field.get(object);
		} catch (SecurityException e) {
			LOGGER.error("unable to get field", e);
		} catch (IllegalArgumentException e) {
			LOGGER.error("unable to get field", e);
		} catch (IllegalAccessException e) {
			LOGGER.error("unable to get field", e);
		}
		return null;
	}

	/**
	 * オブジェクトから指定フィールドを取り出す。<br>
	 * (リフレクションを用いる)
	 *
	 * @param object
	 * @param fieldName
	 * @return
	 */
	public static Field getField(Object object, String fieldName) {
		Field field;
		try {
			field = object.getClass().getDeclaredField(fieldName);
			field.setAccessible(true);
			return field;
		} catch (SecurityException e) {
			LOGGER.fatal("unable to get field", e);
		} catch (NoSuchFieldException e) {
			if (LOGGER.isDebugEnabled()) {
				LOGGER.debug("unable to get field: " + fieldName + " of " + object);
			}
		} catch (IllegalArgumentException e) {
			LOGGER.fatal("unable to get field", e);
		}
		return null;
	}

	/**
	 * オブジェクトの指定フィールドに値をセットする。<br>
	 * (リフレクションを用いる)
	 *
	 * @param object
	 * @param fieldName
	 * @return
	 */
	public static void setField(Object object, String fieldName, Object val) {
		Field field;
		try {
			field = object.getClass().getDeclaredField(fieldName);
			field.setAccessible(true);
			field.set(object, val);
		} catch (SecurityException e) {
			LOGGER.fatal("unable to get field", e);
		} catch (NoSuchFieldException e) {
			if (LOGGER.isDebugEnabled()) {
				LOGGER.debug("unable to get field: " + fieldName + " of " + object);
			}
		} catch (IllegalArgumentException e) {
			LOGGER.fatal("unable to get field", e);
		} catch (IllegalAccessException e) {
			LOGGER.fatal("unable to set field", e);
		}
	}

	/**
	 * オブジェクトから指定フィールドの値を取り出す。<br>
	 * (リフレクションを用いる)
	 *
	 * @param object
	 * @param field
	 * @return
	 */
	public static Object getFieldValue(Object object, Field field) {
		try {
			return field.get(object);
		} catch (IllegalArgumentException e) {
			LOGGER.fatal("field get value", e);
		} catch (IllegalAccessException e) {
			LOGGER.fatal("field get value", e);
		}
		return new Object();
	}

	/**
	 * ファイル名から拡張子を取り出す。<br>
	 * 拡張子がない場合空文字を返す。
	 *
	 * @param filename
	 * @return
	 */
	public static String getExtension(String filename) {
		if (StringUtils.isEmpty(filename)) return "";

		int lastIndex = filename.lastIndexOf(".");
		if (lastIndex != -1) {
			return filename.substring(lastIndex + 1);
		}
		else {
			return "";
		}
	}

	/**
	 * 拡張子を除いたファイル名を取り出す。<br>
	 * 拡張子がない場合はそのまま返す。
	 *
	 * @param filename
	 * @return
	 */
	public static String getFilenameWithoutExt(String filename) {
		if (StringUtils.isEmpty(filename)) return "";

		int lastIndex = filename.lastIndexOf(".");
		if (lastIndex != -1) {
			return filename.substring(0, lastIndex);
		}
		else {
		    return filename;
		}
	}

	/**
	 * 呼び出しメソッドを返す。
	 *
	 * @return
	 */
	public static String getCaller() {
		return getCaller(3);
	}

	/**
	 * 呼び出し階層のindex番目のメソッドを返す。<br>
	 * 1番は、このメソッド自体、2番がこのメソッドを呼び出すメソッドとなる。
	 *
	 * @param index
	 * @return
	 */
	public static String getCaller(int index) {
		return new Throwable().getStackTrace()[index].getClassName();
	}

	/**
	 * 正規表現に従ってマッチするかどうかを返す
	 *
	 * @param src
	 * @param regex
	 * @return
	 */
	public static boolean match(String src, String regex) {
		Pattern regx = Pattern.compile(regex);
		Matcher m = regx.matcher(src);
		return m.find();
	}

	/**
	 * 正規表現にしたがって文字列を抽出する
	 *
	 * @param src 対象文字列
	 * @param regex 正規表現
	 * @param index 正規表現中の抽出対象となる()の番号
	 * @return ヒットした最初の文字列
	 */
	public static String extractRegexString(String src, String regex, int index) {
		Pattern regx = Pattern.compile(regex);
		Matcher m = regx.matcher(src);
		if (m.find()) {
			return m.group(index);
		}
		return null;
	}


	/**
	 * 正規表現にしたがって文字列(複数)を抽出する
	 *
	 * @param src 対象文字列
	 * @param regex 正規表現
	 * @param index 正規表現中の抽出対象となる()の番号(配列)
	 * @return ヒットしたすべての文字列リスト
	 */
	@SuppressWarnings("unchecked")
	public static List<List> extractRegexString(String src, String regex, int[] index) {
		Pattern regx = Pattern.compile(regex);
		List<List> list = new LinkedList<List>();
		Matcher m = regx.matcher(src);
		while (m.find()) {
			List<String> matchList = new LinkedList<String>();
			for (int element : index) {
				matchList.add(m.group(element));
			}
			list.add(matchList);
		}
		return list;
	}

	/**
	 * 親のパスを返す(/もしくは\区切り)
	 *
	 * @param name
	 * @return
	 */
	public static String getParentPath(String name) {
		if (StringUtils.isEmpty(name)) return name;

		int index = name.lastIndexOf('/');
		if (index == -1) {
			index = name.lastIndexOf('\\');
		}

		if (index > 0) {
			return name.substring(0, index);
		}
		else {
			return null;
		}
	}

	/**
	 * パスからファイル名を取り出して返す(/もしくは\区切り)
	 *
	 * @param name
	 * @return
	 */
	public static String getFileName(String name) {
		if (StringUtils.isEmpty(name)) return name;

		int index = name.lastIndexOf('/');
		if (index == -1) {
			index = name.lastIndexOf('\\');
		}

		if (index != -1) {
			return name.substring(index + 1);
		}
		else {
			return name;
		}
	}

	/**
	 * 文字列にダブルバイトを含むかどうかを返す。<br>
	 * \を含むものもダブルバイトとみなす。
	 *
	 * @param s
	 * @return
	 */
	public static boolean hasDoubleByte(String s) {
		if (StringUtils.isEmpty(s)) return false;

		if (s.contains("\\")) {
			return true;
		}

		return s.getBytes().length != s.length();
	}

	/**
	 * cygwinのパスからWindowsのパスへ変換する。
	 *
	 * @param path
	 * @param drive ドライブレターを含めるか否か
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static String cygwinToWin(String path, boolean drive) {
		try {
			if (path.contains("\\")) {
				path = StringUtils.replace(path, "\\", "/");
			}

			if (path.startsWith("/cygdrive/")) {
				List list = extractRegexString(path, "/cygdrive/(.)/(.*)", new int[]{1,2});
				List matchList = (List)list.get(0);
				return drive? matchList.get(0) + ":/" + matchList.get(1): "/" + matchList.get(1);
			}
		} catch (Exception e) {
			LOGGER.error("cygwinToWin failed: " + path);
		}
		return path;
	}

	/**
	 * Windowsのパスをcygwinのパスに変換する
	 *
	 * @param path
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static String winToCygwin(String path) {
		try {
			List list = extractRegexString(path, "(.):/(.*)", new int[]{1,2});
			if (list.size() == 0) {
				list = extractRegexString(path, "(.):\\\\(.*)", new int[]{1,2});
			}
			if (list.size() == 0) {
				if (!path.startsWith("/cygdrive/") && path.startsWith("/")){
					return "/cygdrive/c" + path;
				}
				else {
					return path;
				}
			}
			List matchList = (List)list.get(0);
			return "/cygdrive/"+ matchList.get(0) + "/" + StringUtils.replace((String) matchList.get(1), "\\", "/");
		} catch (Exception e) {
			LOGGER.error("cygwinToWin failed: " + path, e);
		}
		return path;
	}

	/**
	 * カレントディレクトリを返す。
	 *
	 * @return
	 */
	public static String getCurrentDirectory() {
		return new File(".").getAbsoluteFile().getParent();
	}

	/**
	 * Linuxパス形式に変換する
	 *
	 * @param path
	 * @return
	 */
	public static String toLinuxPath(String path) {
		String linuxPath = StringUtils.replace(path, Dir.WINDOWS_SEP, Dir.LINUX_SEP);
		int driveIndex = linuxPath.indexOf(":");
		if (driveIndex != -1) {
			linuxPath = linuxPath.substring(driveIndex+ 1);
		}
		return linuxPath;
	}

	/**
	 * Windowsパス形式に変換する
	 *
	 * @param path
	 * @return
	 */
	public static String toWinPath(String path) {
		return StringUtils.replace(path, Dir.LINUX_SEP, Dir.WINDOWS_SEP);
	}

	/**
	 * 文字列をMD5Hash化する
	 *
	 * @param str
	 * @return
	 */
	public static String toMd5Hash(String str) {
		return DigestUtils.md5Hex(str);
	}

	/**
	 * 第一引数の文字列を第二引数の文字列で分解し、空白以外のものを<br>
	 * リストにして返す。
	 *
	 * @param inputStr
	 * @param splitStr
	 * @return
	 */
	public static List<String> stringToListWithoutBlank(String inputStr, String splitStr) {
		List<String> retList = new ArrayList<String>();
		if (StringUtils.isNotEmpty(inputStr)) {
			String[] strArray = inputStr.split(splitStr);
			for (String string : strArray) {
				if (StringUtils.isNotEmpty(string.trim())) {
					retList.add(string.trim());
				}
			}
		}
		return retList;
	}

    /**
     * @param str
     * @param splitStr
     * @return
     */
    public static List<Integer> stringToList(String str, String splitStr){
    	List<Integer> list = new ArrayList<Integer>();
    	if(StringUtils.isNotBlank(str)){
    		String[] strs = str.split(splitStr);
        	for(String id : strs){
        		list.add(new Integer(id));
        	}
    	}
    	return list;
    }

	/**
	 * 空白が含まれるかどうかを返す。
	 *
	 * @param path
	 * @return
	 */
	public static boolean hasSpace(String path) {
		if (StringUtils.isEmpty(path)) return false;
		return path.contains(" ");
	}

	/**
	 * スラッシュが含まれるかどうかを返す。
	 *
	 * @param val
	 * @return
	 */
	public static boolean hasSlash(String val) {
		if (StringUtils.isEmpty(val)) return false;
		return val.contains("/");
	}

	/**
	 * Leftパディング<br>
	 * numをpadStrでパディングした文字列を返します。<br>
	 * num > sizeの場合はnumを文字列変換した値を返却します。
	 * @param num
	 * @param size
	 * @param padStr
	 * @return
	 */
	public static String leftPad(long num, int size, String padStr){
		String str = Long.toString(num);
		if (str.length() > size) {
			return Long.toString(num);
		}
		return StringUtils.leftPad(Long.toString(num), size, padStr);
	}

	/**
	 * 現在日時を返却します
	 * @return 現在日時
	 */
	public static Timestamp getTimestamp(){
		return new Timestamp(System.currentTimeMillis());
	}

	/**
	 * String文字列をTimestamp型に変換します。<br>
	 * 変換時例外が発生した場合はnullを返却します。
	 * @param time 文字列
	 * @param format ハイフン区切りフォーマット
	 * @return Timestamp
	 */
	public static Timestamp convertStringToTimestamp(String time, String format){

		time = time.replaceAll("/", "-");

		try {
			return new Timestamp(new SimpleDateFormat(format).parse(time).getTime());
		} catch (ParseException e) {
			return null;
		}

	}

	/**
	 * String配列をInteger配列に変換して返却します。
	 * 変換時エラーはnullを返却します。
	 * @param strList String配列
	 * @return Integer配列
	 */
	public static Integer[] changeStringToInteger(String[] strList){
		Integer[] intList = new Integer[strList.length];
		try {
			for (int i=0; i<strList.length; i++) {
				intList[i] = Integer.parseInt(strList[i]);
			}
		} catch (NumberFormatException e) {
			return null;
		}
		return intList;
	}

	/**
	 * 指定日付のDateを返す。
	 *
	 * @param year
	 * @param month
	 * @param day
	 * @return
	 */
	public static Date getDate(int year, int month, int day) {
		return getDate(year, month, day, 0, 0, 0);
	}

	/**
	 * 指定日付のDateを返す。
	 *
	 * @param year
	 * @param month
	 * @param day
	 * @return
	 */
	public static Date getDate(String year, String month, String day) {

		return getDate(Integer.parseInt(year), Integer.parseInt(month), Integer.parseInt(day), 0, 0, 0);
	}
	/**
	 * 指定日時のDateを返す。
	 *
	 * @param year
	 * @param month
	 * @param day
	 * @param hour
	 * @param minute
	 * @param second
	 * @return
	 */
	public static Date getDate(int year, int month, int day, int hour, int minute, int second) {
		Calendar c = Calendar.getInstance();
		c.set(year, month - 1, day, hour, minute, second);
		return c.getTime();
	}

	public static Timestamp getAddSecond(Date date, int hour) {
		return getAddDate(date, hour, Calendar.SECOND);
	}

	/**
	 * 指定日から時間を加減する。
	 * @param date
	 * @param hour
	 * @return
	 */
	public static Timestamp getAddHour(Date date, int hour) {
		return getAddDate(date, hour, Calendar.HOUR);
	}

	/**
	 * 指定日から日数を加減する。
	 * @param date
	 * @param day
	 * @return
	 */
	public static Timestamp getAddDate(Date date, int day) {
		return getAddDate(date, day, Calendar.DATE);
	}

	public static Timestamp getAddDate(Date date, int value, int calendarType) {
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		c.add(calendarType, value);
		return new Timestamp(c.getTimeInMillis());
	}

	//public static Date getAddDate()


	/**
	 * TimestampからYYYY/MM/DD文字列に変換します
	 * @param insertDate
	 * @return
	 */
	public static String dateDispFormat(Timestamp insertDate){
		if (null == insertDate) {
			return null;
		}
		return new SimpleDateFormat(Formats.DATATYPE_DATE_FORMAT).format(insertDate.getTime());
	}

	/**
	 * 今日のYYYYMMDD文字列に変換します
	 * @return   ex) 20120829
	 */
	public static String getToDayString(){

		return new SimpleDateFormat(Formats.DATATYPE_DATE_FORMAT_NON_SLASH).format(new Timestamp(System.currentTimeMillis()).getTime());
	}

	/**
	 * 引数searchに一致するclazzクラスのメンバ名を全て返却します。<br>
	 * Pattern・Matcherを使用しているため、引数searchは正規表現可となります。
	 * @param search
	 * @return
	 */
	public static List<String> getFieldNames(Class<?> clazz, String search){
		String[] allNames = getFieldNames(clazz);
		List<String> resultList = new ArrayList<String>();
		Pattern p = Pattern.compile(search);
		for (String allName : allNames) {
			Matcher m = p.matcher(allName);
			if (m.matches()) {
				resultList.add(allName);
			}
		}
		return resultList;
	}

	/**
	 * 引数 clazzクラスのメンバ名を全て返却します。
	 * @param clazz
	 * @return
	 */
	public static String[] getFieldNames(Class<?> clazz){
		Field[] fields = clazz.getFields();
		String[] names = new String[fields.length];
		for (int i=0; i<fields.length;i++) {
			names[i] = fields[i].getName();
		}
		return names;
	}

	/**
	* 半角カナチェック<br>
	* 引数の文字列に半角カナが含まれている場合にはtrueを返します。
	* @param String str 検索文字列
	* @return boolean true:半角カナ, false:半角カナ以外もあり
	*/
	public static boolean isHankakuKana(String str) {

		if (StringUtils.isNotEmpty(str)) {
			char[] chars = str.toCharArray();

			for (char target : chars) {
				if (0xff61 <= target && target <= 0xff9f) {
					return true;
				}
			}
		}
		return false;
	}

	/**
	* 全角→半角変換<br>
	* 引数の文字列に全角英数字が含まれている場合には半角に変換して返します。
	* @param String 検索文字列
	* @return String
	*/
	public static String getZenkakuToHankaku(String value, int flg) {
	    StringBuilder sb = new StringBuilder(value);
	    for (int i = 0; i < sb.length(); i++) {
	        int c = (int) sb.charAt(i);
	        if ((c >= 0xFF10 && c <= 0xFF19) || (c >= 0xFF21 && c <= 0xFF3A) || (c >= 0xFF41 && c <= 0xFF5A)) {
	            sb.setCharAt(i, (char) (c - 0xFEE0));
	        }

	        //"、", " "全角→半角
	        if( flg == 1 ){
	        	if (sb.charAt(i) == ' ') {
		            sb.setCharAt(i, ' ');
		        }else if( sb.charAt(i) == '、') {
		        	sb.setCharAt(i, ',');
		        }
	        }
	    }
	    value = sb.toString();
	    return value;
	}

	/**
	* 半角カナ→全角カナ変換<br>
	* @param String 検索文字列
	* @return String
	*/
	public static String getHankanaToZenKana(String s) {

        HashMap<String,String> hmCharTbl = new HashMap<String,String>();

        hmCharTbl.put("ア", "ア");
        hmCharTbl.put("イ", "イ");
        hmCharTbl.put("ウ", "ウ");
        hmCharTbl.put("エ", "エ");
        hmCharTbl.put("オ", "オ");
        hmCharTbl.put("カ", "カ");
        hmCharTbl.put("キ", "キ");
        hmCharTbl.put("ク", "ク");
        hmCharTbl.put("ケ", "ケ");
        hmCharTbl.put("コ", "コ");
        hmCharTbl.put("サ", "サ");
        hmCharTbl.put("シ", "シ");
        hmCharTbl.put("ス", "ス");
        hmCharTbl.put("セ", "セ");
        hmCharTbl.put("ソ", "ソ");
        hmCharTbl.put("タ", "タ");
        hmCharTbl.put("チ", "チ");
        hmCharTbl.put("ツ", "ツ");
        hmCharTbl.put("テ", "テ");
        hmCharTbl.put("ト", "ト");
        hmCharTbl.put("ナ", "ナ");
        hmCharTbl.put("ニ", "ニ");
        hmCharTbl.put("ヌ", "ヌ");
        hmCharTbl.put("ネ", "ネ");
        hmCharTbl.put("ノ", "ノ");
        hmCharTbl.put("ハ", "ハ");
        hmCharTbl.put("ヒ", "ヒ");
        hmCharTbl.put("フ", "フ");
        hmCharTbl.put("ヘ", "ヘ");
        hmCharTbl.put("ホ", "ホ");
        hmCharTbl.put("マ", "マ");
        hmCharTbl.put("ミ", "ミ");
        hmCharTbl.put("ム", "ム");
        hmCharTbl.put("メ", "メ");
        hmCharTbl.put("モ", "モ");
        hmCharTbl.put("ヤ", "ヤ");
        hmCharTbl.put("ユ", "ユ");
        hmCharTbl.put("ヨ", "ヨ");
        hmCharTbl.put("ラ", "ラ");
        hmCharTbl.put("リ", "リ");
        hmCharTbl.put("ル", "ル");
        hmCharTbl.put("レ", "レ");
        hmCharTbl.put("ロ", "ロ");
        hmCharTbl.put("ワ", "ワ");
        hmCharTbl.put("ヲ", "ヲ");
        hmCharTbl.put("ン", "ン");
        hmCharTbl.put("ァ", "ァ");
        hmCharTbl.put("ィ", "ィ");
        hmCharTbl.put("ゥ", "ゥ");
        hmCharTbl.put("ェ", "ェ");
        hmCharTbl.put("ォ", "ォ");
        hmCharTbl.put("ッ", "ッ");
        hmCharTbl.put("ャ", "ャ");
        hmCharTbl.put("ュ", "ュ");
        hmCharTbl.put("ョ", "ョ");
        hmCharTbl.put("ー", "ー");
        hmCharTbl.put("。", "。");
        hmCharTbl.put("、", "、");
        hmCharTbl.put("・", "・");
        hmCharTbl.put("「", "「");
        hmCharTbl.put("」", "」");
        hmCharTbl.put("゙", "゛");
        hmCharTbl.put("゚", "゜");
        hmCharTbl.put("ヴ", "ヴ");
        hmCharTbl.put("ガ", "ガ");
        hmCharTbl.put("ギ", "ギ");
        hmCharTbl.put("グ", "グ");
        hmCharTbl.put("ゲ", "ゲ");
        hmCharTbl.put("ゴ", "ゴ");
        hmCharTbl.put("ザ", "ザ");
        hmCharTbl.put("ジ", "ジ");
        hmCharTbl.put("ズ", "ズ");
        hmCharTbl.put("ゼ", "ゼ");
        hmCharTbl.put("ゾ", "ゾ");
        hmCharTbl.put("ダ", "ダ");
        hmCharTbl.put("ヂ", "ヂ");
        hmCharTbl.put("ヅ", "ヅ");
        hmCharTbl.put("デ", "デ");
        hmCharTbl.put("ド", "ド");
        hmCharTbl.put("バ", "バ");
        hmCharTbl.put("ビ", "ビ");
        hmCharTbl.put("ブ", "ブ");
        hmCharTbl.put("ベ", "ベ");
        hmCharTbl.put("ボ", "ボ");
        hmCharTbl.put("パ", "パ");
        hmCharTbl.put("ピ", "ピ");
        hmCharTbl.put("プ", "プ");
        hmCharTbl.put("ペ", "ペ");
        hmCharTbl.put("ポ", "ポ");

        StringBuffer sbBuf = new StringBuffer();
        String  strKey = "";  // HashMapのKEY
        String  strChar1 = "";          // 1文字目
        char    c1 = ' ';               // 1文字目
        char    c2 = ' ';               // 2文字目
        int     i;
        for (i=0; i<s.length(); i++) {

            c1 = ' ';
            c2 = ' ';
            c1 = s.charAt(i);
            if ((i+1) < s.length()) {
                c2 = s.charAt(i+1);
            }

            strChar1 = "";
            if (c2 == '゙' || c2 == '゚') {
                strKey = String.valueOf(c1) + String.valueOf(c2);
                strChar1 = (String)hmCharTbl.get(strKey);
                if (strChar1 == null) {
                    strKey = String.valueOf(c1);
                    strChar1 = (String)hmCharTbl.get(strKey);
                    if (strChar1 == null) {
                        sbBuf.append(c1);
                    } else {
                        sbBuf.append(strChar1);
                    }
                } else {
                    sbBuf.append(strChar1);
                    i++;
                }
            } else {
                strKey = String.valueOf(c1);
                strChar1 = (String)hmCharTbl.get(strKey);
                if (strChar1 == null) {
                    sbBuf.append(c1);
                } else {
                    sbBuf.append(strChar1);
                }
            }
        }
        return sbBuf.toString();
    }


	/**
	 * String文字列をDate型に変換して返却します。<br>
	 * 変換できなかった場合はParseExceptionをthrowします。
	 * ex) "2010/06/15" → 変換OK
	 *     "2010-06-15" → 変換NG
	 *     "20100615"   → 変換NG
	 * @param dateStr
	 * @return
	 * @throws ParseException
	 */
	public static Date stringToDateSlash(String dateStr){

		Date  date = null;
		try{
			date = DateFormat.getDateInstance().parse(dateStr);
		}catch (Exception e) {
			LOGGER.error(e,e);
			return null;
		}
		return date;
	}

	/**
	 * Timestamp型を文字列に変換します。<br>
	 * 変換時例外が発生した場合はnullを返却します。
	 * @param time Timestamp
	 * @param format 文字列
	 * @return Timestamp
	 */
	public static String convertTimestampToString(Timestamp time, String dateformat){
		return new SimpleDateFormat(dateformat).format(time);
	}

	/**
	 * Date型を文字列に変換します。<br>
	 * 変換時例外が発生した場合はnullを返却します。
	 * @param time Date
	 * @param format フォーマット
	 * @return String
	 */
	public static String convertTimestampToString(Date time, String dateformat){
		return new SimpleDateFormat(dateformat).format(time);
	}

	/**
	 * 現在日時を指定フォーマットで返します。
	 *
	 * @param dateformat
	 * @return
	 */
	public static String getTimeStringAs(String dateformat){
		return new SimpleDateFormat(dateformat).format(getTimestamp());
	}


	/**
	 * 第一引数に、第二引数以降のいずれかが一致した場合trueを返す
	 *
	 * @param s
	 * @param targets
	 * @return
	 */
	public static boolean equalsAny(String s, String... targets) {
		for (String target : targets) {
			if (s.equals(target)) {
				return true;
			}
		}
		return false;
	}

	/**
	 * SQLのlike検索用に「keywordを含む任意の文字列」にマッチするパターンを作成する.
	 *
	 * キーワード自体にワイルドカードが含まれていた場合はエスケープする。
	 *
	 * <em>PostgreSQL用。別のRDBMSにはおそらく別のメソッドが必要。</em>
	 * PostgreSQLのワイルドカードは _, %の2種。
	 * エスケープ文字は設定で変更可能だがデフォルトでは \
	 */
	private static String makeLikePattern_PostgreSQL(String keyword) {
		final int length = keyword.length();
		StringBuilder sb = new StringBuilder(length + 2);
		sb.append('%');
		for (int i = 0 ; i < length ; i++ ) {
			switch (keyword.charAt(i)) {
			case '%':
			case '_':
			case '\\':
				sb.append('\\');
				/* don't break */
			default:
				sb.append(keyword.charAt(i));
			}
		}
		sb.append('%');

		return	sb.toString();
	}

	/**
	 * SQLのlike検索用に「keywordを含む任意の文字列」にマッチするパターンを作成する.
	 *
	 * キーワード自体にワイルドカードが含まれていた場合はエスケープする。
	 *
	 * LATER:arima: 今のところPostgreSQL用しか実装していない
	 */
	public static String makeLikePattern(String keyword) {
		if (keyword == null)	return	null;
		if (keyword.isEmpty())	return	"";

		return	makeLikePattern_PostgreSQL(keyword);
	}

	/**
	 * 日数を加減する。
	 *
	 * @param days
	 * @return Timestampのタイプ
	 */
	public static Timestamp addDate(int days) {
		Calendar cal = Calendar.getInstance();
		cal.add(Calendar.DATE, days);

		return new Timestamp(cal.getTime().getTime());
	}

	/**
	 * 分を加減する。
	 *
	 * @param mins
	 * @return Timestampのタイプ
	 */
	public static Timestamp addMin(int mins) {
		Calendar cal = Calendar.getInstance();
		cal.add(Calendar.MINUTE, mins);

		return new Timestamp(cal.getTime().getTime());
	}

	/**
	 * 月数を加減する。
	 *
	 * @param months
	 * @return Timestampのタイプ
	 */
	public static Timestamp addMonth(int months) {
		Calendar cal = Calendar.getInstance();
		cal.add(Calendar.MONTH, months);

		return new Timestamp(cal.getTime().getTime());
	}

	/**
	 * disk容量を表示単位で計算(MB,GB,TB)
	 * @param diskvolume disk容量
	 * @return disk容量
	 */
	public static String calculateDiskVolume(Long diskVolume) {
		if (diskVolume == null) {
			return "0Byte";
		}
		//KB
		BigDecimal kb = new BigDecimal(1024L);
		//MB
		BigDecimal mb = new BigDecimal(1048576L);
		//GB
		BigDecimal gb = new BigDecimal(1073741824L);
		//TB
		BigDecimal tb = new BigDecimal(1099511627776L);

		//Byte
		if (diskVolume < 1000L) {
			return diskVolume + "Byte";
		}

		//KB
		if (diskVolume < 1000000L) {
			BigDecimal diskvDecimal = new BigDecimal(diskVolume);
			return diskvDecimal.divide(kb, 2, BigDecimal.ROUND_HALF_UP).doubleValue() + "KB";
		}

		//MB
		if (diskVolume < 1000000000L) {
			BigDecimal diskvDecimal = new BigDecimal(diskVolume);
			return diskvDecimal.divide(mb, 2, BigDecimal.ROUND_HALF_UP).doubleValue() + "MB";
		}

		//GB
		if (diskVolume < 1000000000000L) {
			BigDecimal diskvDecimal = new BigDecimal(diskVolume);
			return diskvDecimal.divide(gb, 2, BigDecimal.ROUND_HALF_UP).doubleValue() + "GB";
		}
		//TB
		BigDecimal diskvDecimal = new BigDecimal(diskVolume);
		return diskvDecimal.divide(tb, 2, BigDecimal.ROUND_HALF_UP).doubleValue() + "TB";
	}

	/**
	 * リストの各要素を型チェックしてキャスト
	 * @param <E>
	 * @param list
	 * @return 各要素がEであることが型保証されたリスト
	 */
	@SuppressWarnings("unchecked")
	public static <E> List<E> castList(List<?> list, Class<E> type) {
		for (Object obj : list) {
			if (type.isInstance(obj) || obj == null) continue;

			throw new ClassCastException("object[" + obj + "][" + obj.getClass() + "] is not element type[" + type + "]");
		}

		return (List<E>)list;
	}

	private static String ELLIPSIS = "...";
	private static String NBSP = "&nbsp;";

	/**
	 * 文字列長が指定したmaxlengthを越えないように適宜省略する
	 * @param str 表示される文字列
	 * @param maxlength 許容される最大長
	 * @return
	 */
	public static String getBrief(String str, final int maxlength) {
		/* パラメータ補正 */
		if (str == null)	str = "";
		if (maxlength < ELLIPSIS.length()) {
			/* ワーストケースでは ... となるため最低3文字必要 */
			throw new IllegalArgumentException("maxlength is too small");
		}

		final int len = str.length();
		if (len <= maxlength) {
			return	str;
		} else if (len > ELLIPSIS.length()) {
			return	str.substring(0, maxlength - ELLIPSIS.length()) + ELLIPSIS;
		} else {
			return	ELLIPSIS;
		}
	}

	/**
	 * 2つの文字列を一行に並べて表示する。その際、合計の文字列長が指定したmaxlengthを越えないように適宜省略する
	 * @param str1 左側に表示される文字列
	 * @param str2 右側に表示される文字列
	 * @param maxlength 許容される最大長
	 * @return
	 */
	public static String getBrief2(String str1, String str2, final int maxlength) {
		/* パラメータ補正 */
		if (str1 == null)	str1 = "";
		if (str2 == null)	str2 = "";
		if (maxlength < ELLIPSIS.length() * 2) {
			/* ワーストケースでは ... ... となるため最低6文字必要 */
			throw new IllegalArgumentException("maxlength is too small");
		}

		final int len1 = str1.length();
		final int len2 = str2.length();
		if (len1 + len2 > maxlength) {
			final int len_overflow = len1 + len2 - maxlength + ELLIPSIS.length();
			if (len1 >= len_overflow) {
				/* str1のみ短縮すればよい */
				str1 = str1.substring(0, len1 - len_overflow) + ELLIPSIS;
			} else if (len2 >= len_overflow) {
				/* str2のみ短縮すればよい */
				str2 = str2.substring(0, len2 - len_overflow) + ELLIPSIS;
			} else {
				/* 双方とも短縮が必要 */
				final int targetlength = maxlength / 2 - ELLIPSIS.length();
				str1 = len1 > targetlength
					? str1.substring(0, targetlength) + ELLIPSIS
					: ELLIPSIS;
				str2 = len2 > targetlength
					? str2.substring(0, targetlength) + ELLIPSIS
					: ELLIPSIS;
			}
		}

		return	str1 + NBSP + str2;
	}

	public static boolean containsLast(List<String> list, String target) {
		if (CollectionUtils.isEmpty(list) || StringUtil.isEmpty(target)) {
			return false;
		}

		for (String str : list) {
			if (!str.isEmpty() && target.endsWith(str)) {
				return true;
			}
		}
		return false;
	}


	/**
	 * ビット演算でvalがtarget値を含む場合true
	 *
	 * @param val
	 * @param target
	 * @return
	 */
	public static boolean include(Integer val, Integer target) {
		if (val == null || target == null) return false;
		return (val & target) == target;
	}

	// isHexメソッド用
	private static Pattern regxHexStr = Pattern.compile("^[0-9a-fA-F]+$");
	/**
	 * 引数が16進数かどうか返す。
	 * Long.parseLong(str, 16)は使わない
	 *
	 * @param str
	 * @return
	 */
	public static boolean isHex(String str) {
		try {
			Matcher m = regxHexStr.matcher(str);
			return m.find();
		} catch (Exception e) {
			return false;
		}
	}

	/**
	 * 第一引数strが空でなければ、str + sep、空であれば空文字を返す。
	 *
	 * @param str
	 * @param sep
	 * @return
	 */
	public static String prepend(String str, String sep) {
		return StringUtils.isNotEmpty(str)? str + sep: "";
	}

	/**
	 * 配列から""を削除
	 * @param strs
	 * @return
	 */
	public static String[] deleteNullStringForArray(String[] strs) {
		List<String> list = new ArrayList<String>();
		for (String  str : strs) {
			if (StringUtils.isNotBlank(str)) {
				list.add(str);
			}
		}
		return list.toArray(new String[list.size()]);
	}

	/**
	 * 分の最後を0にする。ex)49分→40分
	 * @param mm
	 * @return
	 */
	public static String convertMinute(String mm) {
		return StringUtils.left(mm, 1) + "0";
	}

	/**
	 * strにnum文字同じ文字が連続して含まれるか
	 *
	 * @return
	 */
	public static boolean hasSeqChar(String str, int num) {
		int count = 0;
		char prev = 0;

		for (int i = 0; i < str.length(); i++) {
			char c = str.charAt(i);
			if (i > 0 && prev == c) {
				count++;
				if (count == num - 1) {
					return true;
				}
			}
			else {
				count = 0;
			}
			prev = c;
		}

		return false;
	}

	/**
	 * str1に、str2と同じ連続したnum文字が含まれるか
	 *
	 * @param str2
	 * @return
	 */
	public static boolean containSameSeqChar(String str1, String str2, int num) {
		if (str2.length() < num || str1.length() < num) {
			return false;
		}

		for (int i = 0; i <= str2.length() - num; i++) {
			String target = str2.substring(i, i + num);
			if (str1.contains(target)) {
				return true;
			}
		}

		return false;
	}

	/**
	 * アルファベットと数字両方を含むか
	 *
	 * @param str
	 * @return
	 */
	public static boolean hasBothAlphaDigit(String str) {
		return SinaburoUtil.match(str, "[0-9]") && SinaburoUtil.match(str, "[a-zA-Z]");
	}

	/**
	 * classesディレクトリの絶対パスを返す
	 *
	 * @return
	 */
	public static String getClassesPath() {
		return StringUtils.substringBefore(SinaburoUtil.class.getResource("SinaburoUtil.class").getFile(), "/jp/");
	}

	/**
	 * 文字列実体参照を置換する
	 * @param value
	 * @return
	 */
	public static String charEntityReferenceReplacement(String value) {
		if (value == null) {
			return value;
		}

		StringBuffer buff = new StringBuffer();
		for (int i = 0; i < value.length(); i++) {
			switch (value.charAt(i)) {
			case '<' :
				buff.append("&lt;");
			    break;
			case '>' :
				buff.append("&gt;");
			    break;
			case '&' :
				if (i + 1 <= value.length() - 1 && value.charAt(i + 1) == '#') {
					buff.append('&');
				} else {
					buff.append("&amp;");
				}
				break;
//			case '"' :
//				buff.append("&quot;");
//			    break;
//			case '\'' :
//				buff.append("&#39;");
//			    break;
			default :
			    buff.append(value.charAt(i));
			    break;
			}
		}

		return buff.toString();
	}

	public static boolean isIp4Address(String remoteAddr) {
		if (remoteAddr == null) {
			return false;
		}
		return match(remoteAddr, "\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}");
	}

	/**
	 * 携帯メールアドレスチェック
	 *
	 * @param str
	 * @return true:携帯メール、false:PCメール
	 */
	public static boolean mobileAddressCheck(String mailAddress) {
		if(StringUtil.isBlank(mailAddress)) {
			return true;
		}

		// TODO: 	PropertyUtil.getPropertiesStartWith("MOBILE.")で書き換え
		if (mailAddress.matches(PropertyUtil.getProperty("MOBILE.AU"))
				|| mailAddress.matches(PropertyUtil.getProperty("MOBILE.AU.COM"))
				|| mailAddress.matches(PropertyUtil.getProperty("MOBILE.DOCOMO"))
				|| mailAddress.matches(PropertyUtil.getProperty("MOBILE.VODAFONE"))
				|| mailAddress.matches(PropertyUtil.getProperty("MOBILE.SOFTBANK"))
				|| mailAddress.matches(PropertyUtil.getProperty("MOBILE.PDX"))
				|| mailAddress.matches(PropertyUtil.getProperty("MOBILE.PDX2"))
				|| mailAddress.matches(PropertyUtil.getProperty("MOBILE.PDX3"))
				|| mailAddress.matches(PropertyUtil.getProperty("MOBILE.PDX4"))
				|| mailAddress.matches(PropertyUtil.getProperty("MOBILE.PDX5"))
				|| mailAddress.matches(PropertyUtil.getProperty("MOBILE.DOCOMO.CAMERA"))
				|| mailAddress.matches(PropertyUtil.getProperty("MOBILE.MOPERA"))
				|| mailAddress.matches(PropertyUtil.getProperty("MOBILE.DWMAIL"))
				|| mailAddress.matches(PropertyUtil.getProperty("MOBILE.IDO"))
				|| mailAddress.matches(PropertyUtil.getProperty("MOBILE.DESNEY"))
				|| mailAddress.matches(PropertyUtil.getProperty("MOBILE.I.SOFTBANK"))
				|| mailAddress.matches(PropertyUtil.getProperty("MOBILE.WILLCOM"))
				|| mailAddress.matches(PropertyUtil.getProperty("MOBILE.EMNET"))
				|| mailAddress.matches(PropertyUtil.getProperty("MOBILE.VERTUCLUB"))) {
			return true;
		}
		return false;
	}

	/**
	 * Date型を文字列に変換します。<br>
	 * 変換時例外が発生した場合はnullを返却します。
	 * @param String DATE
	 * @param format 文字列
	 * @return Timestamp
	 * @throws ParseException
	 */
	public static String convertStringDateToFormat(String date, String dateformat) {
		if (date == null) {
			return null;
		}
		date = date.substring(0, 4)+dateformat+date.substring(4, 6)+dateformat+date.substring(6, 8);

		return date;
	}

	public static String convertStringTimeToFormat(String date, String dateformat) {
		if (date == null) {
			return null;
		}
		date = date.substring(0, 4)+dateformat+date.substring(4, 6)+dateformat+date.substring(6, 8)+" "
				+ date.substring(8, 10)+":"+date.substring(10, 12)+":"+date.substring(12, 14);

		return date;
	}


    public static String addhyphenDate(String arg){
    	if(arg == null){
    		return arg;
    	}
    	String val = arg;

    	if (arg.length() == 8) {
    		val =  convertStringDateToFormat(arg, "-");
    	}
    	if (arg.length() == 6) {
    		val =  convertStringDateToFormat2(arg, "-");
    	}
    	return val;
    }

	/**
	 * Date型を文字列に変換します。<br>
	 * 変換時例外が発生した場合はnullを返却します。
	 * @param String DATE
	 * @param format 文字列
	 * @return Timestamp
	 * @throws ParseException
	 */
	public static String convertStringDateToFormat2(String date, String dateformat) {
		if (date == null) {
			return null;
		}
		date = date.substring(0, 4)+dateformat+date.substring(4, 6);

		return date;
	}
	/**
	 * "0"をつめる<br>
	 * @param String str
	 * @param int length
	 * @return str
	 */
	public static String  LeftPadZero (String str, int value) {
		if (str.length() == value || str.length() == 0) {
			return str;
		} else {
			for (int i = 1; i < value; i++) {
				str = "0"+str;
			}
		}
		return str;
	}

	/**
	 * argsの中にsrcが存在していたらtrue
	 * @param src
	 * @param args
	 * @return argsの存在していたらtrue
	 */
	public static boolean contain(Object src ,Object... args ){

		for(int i=0;i < args.length;i++){
			if(src.toString().equals(args[i].toString())){
				return true;
			}
		}
		return false;
	}

	/**
	 * 入力されたurlのhtml文字列を戻す。
	 * @param url
	 * @return
	 */
	public static String getHtml(URL url){

		String charset = "UTF-8";
		JTextArea htmlArea = htmlArea = new JTextArea();
        // Webページを読み込む
        try {
            // 接続
            URLConnection uc = url.openConnection();
            // HTMLを読み込む
            BufferedInputStream bis = new BufferedInputStream(uc.getInputStream());
            BufferedReader br = new BufferedReader(new InputStreamReader(bis, charset));
            htmlArea.setText("");//初期化
            String line;
            while ((line = br.readLine()) != null) {
                htmlArea.append(line + SinaburoConstant.newLine.N);
            }
        } catch (MalformedURLException ex) {
            htmlArea.setText("URLが不正です。");
            ex.printStackTrace();
        } catch (UnknownHostException ex) {
            htmlArea.setText("サイトが見つかりません。");
        } catch (IOException ex) {
            ex.printStackTrace();
        }

        return htmlArea.getText();
    }


	public static void writeFile(String filePath,String content,String chaString)throws Exception{
		  String charset = "UTF-8";
		  if(chaString == null  )chaString = charset;

		  FileOutputStream fos = new FileOutputStream(filePath);
		  OutputStreamWriter osW = new OutputStreamWriter(fos, chaString);

		  BufferedWriter bw = new BufferedWriter(osW);

	       //ファイルに書き込み
	      bw.write(content);
	      bw.close();
	}

	/**
	 * 2つの日付の差を求めます。
	 * 日付文字列 strDate1 - strDate2 が何日かを返します。
	 *
	 * @param strDate1    日付文字列 yyyy/MM/dd
	 * @param strDate2    日付文字列 yyyy/MM/dd
	 * @return    2つの日付の差
	 * @throws ParseException 日付フォーマットが不正な場合
	 */
	public static int differenceDays(String strDate1,String strDate2)
	    throws ParseException {
		String [] date1 = strDate1.split("/");
		String [] date2 = strDate2.split("/");

	    Date date3 = getDate(date1[0],date1[1],date1[2]);//DateFormat.getDateInstance().parse(strDate1);
	    Date date4 = getDate(date2[0],date2[1],date2[2]);//DateFormat.getDateInstance().parse(strDate2);
	    return differenceDays(date3,date4);
	}

	/**
	 * 2つの日付の差を求めます。
	 * java.util.Date 型の日付 date1 - date2 が何日かを返します。
	 *
	 * 計算方法は以下となります。
	 * 1.最初に2つの日付を long 値に変換します。
	 *  ※この long 値は 1970 年 1 月 1 日 00:00:00 GMT からの
	 *  経過ミリ秒数となります。
	 * 2.次にその差を求めます。
	 * 3.上記の計算で出た数量を 1 日の時間で割ることで
	 *  日付の差を求めることができます。
	 *  ※1 日 ( 24 時間) は、86,400,000 ミリ秒です。
	 *
	 * @param date1    日付 java.util.Date
	 * @param date2    日付 java.util.Date
	 * @return    2つの日付の差
	 */
	public static int differenceDays(Date date1,Date date2) {
	    long datetime1 = date1.getTime();
	    long datetime2 = date2.getTime();
	    long one_date_time = 1000 * 60 * 60 * 24;
	    long diffDays = (datetime1 - datetime2) / one_date_time;
	    return (int)diffDays;
	}


	public static String dateToString (Date date) {
		DateFormat sdFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
		String tempDate = sdFormat.format(date);
		return tempDate;
	}

	public static String dateToString2 (Date date) {
		DateFormat sdFormat = new SimpleDateFormat("yyyy/MM/dd");
		String tempDate = sdFormat.format(date);
		return tempDate;
	}


	/**
	 * メール形式をチェックする。※「@」が含むかだけチェックする。
	 * ※null,""の場合はtrue。文字列がある場合のみチェックを行う。
	 * @param value
	 * @return
	 */
	public static boolean emailCheck(String value){
		if(!GenericValidator.isBlankOrNull(value) && !value.matches("^[!-~]+@[!-~]+$")){
			return false;
		}
		return true;
	}
	/**
	 * 現在時間と比較結果を戻す。
	 *	1未来
	 *	0現在
	 *	-1過去
	 * @param strDate
	 * @param format
	 * @return
	 */
	public static int strDateCompare(String strDate,String format){
		DateTool dateTool = new DateTool();
		String nowStr = dateTool.format(format,dateTool.getSystemDate());
		return strDate.compareTo(nowStr) > 0 ? 1 : ((strDate.compareTo(nowStr) == 0)? 0 :-1);
	}

	/**
	 * ダブルクォーテーション追加[タブ区切り版]、CSV、TSVに"を追加する。
	 * @param argStr
	 * @return
	 */
	public static String addDoubleStr(String argStr){
		String convert =("\""+argStr.replaceAll("\t\r\n", "\r\n")/*タブの直後改行はタグ削除*/).replace("\r\n","\r\n\""/*先頭に"*/).replace("\r\n","\"\r\n"/*最後に"*/).replace("\t", "\"\t\"");
		return convert.substring(0,convert.length()-1);
	}


	/**
	 * 半角数字チェック
	 * @param arg
	 * @return
	 */
	public static boolean isHanaku09(String arg){
		return arg != null && arg.matches(SinaburoConstant.Regex.HANKAKU_09);
	}

	/**
	 * 半角英数字チェック
	 * @param arg
	 * @return
	 */
	public static boolean isHanakuE09(String arg){
		return arg != null && arg.matches(SinaburoConstant.Regex.HANKAKU_E09);
	}

	/**
	 * 全角カナ
	 * @param arg
	 * @return
	 */
	public static boolean isZenkakuKana(String arg){
		return arg != null && arg.matches(SinaburoConstant.Regex.ZENKAKU_KANA);
	}

	/**
	 * 全角
	 * @param arg
	 * @return
	 */
	public static boolean isZenkaku(String arg){
		return arg != null && arg.matches(SinaburoConstant.Regex.ZENKAKU);
	}

	/**
	 * 電話番号
	 * @param arg
	 * @return
	 */
	public static boolean isPhoneNo(String arg){
		return arg != null && arg.replace("-", "").replace("ー", "").matches(SinaburoConstant.Regex.HANKAKU_09);
	}

	/**
	 * 郵便番号
	 * @param arg
	 * @return
	 */
	public static boolean isPostNo(String arg){
		return arg != null && arg.replace("-", "").replace("ー", "").matches(SinaburoConstant.Regex.POSTNO);
	}

	/**
	 * yyyy/MM/dd形式の次の日付を求める。
	 * @param to
	 * @return
	 */
	public static String getNextDay(String to){
		String [] yyyymmdd = to.split("/");

		return
		new DateTool().format("yyyy/MM/dd",SinaburoUtil.getAddDate(SinaburoUtil.getDate(Integer.parseInt(yyyymmdd[0]),
			Integer.parseInt(yyyymmdd[1]),Integer.parseInt(yyyymmdd[2]),0,0,0), 1) );


	}

	/**
	 * 日付の妥当性チェックを行います。
	 * 指定した日付文字列(yyyy/M/d or yyyy-M-d)が
	 * カレンダーに存在するかどうかを返します。
	 * 年は4桁である必要があり。
	 * 
	 * @param strDate チェック対象の文字列
	 * @return 存在する日付の場合true
	 */
	public static boolean checkDate(String strDate) {
	    if (strDate == null) {
	        return false;
	    }
	    try {
	    	strDate = strDate.replace('-', '/');
	    	String[] ymd = strDate.split("/");
	    	if (ymd.length != 3 || ymd[0].length() != 4) {
	    		return false;
	    	}
	    	strDate = ymd[0] + "/" + StringUtils.leftPad(ymd[1], 2, "0") + "/" + StringUtils.leftPad(ymd[2], 2, "0") ;
		    SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd");
		    format.setLenient(false);
	        format.parse(strDate);
	        return true;
	    } catch (Exception e) {
	        return false;
	    }
	}



	/**
	 * 日付の妥当性チェック
	 * @param from 開始日 nullまたは空で判定対象外
	 * @param to   終了日 nullまたは空で判定対象外
	 * @param value 比較日
	 * @return
	 */
	public static boolean dateFromToCheck(String from, String to, String value) {
		boolean result = false;
		try {
			value = dateStrToYYMMDD(value);
			from = dateStrToYYMMDD(from);
			to = dateStrToYYMMDD(to);

			if (StringUtil.isNotBlank(from) && StringUtil.isNotBlank(to)) {
				result = value.compareTo(from) >= 0 && to.compareTo(value) >= 0;
			} else if (StringUtil.isBlank(from) && StringUtil.isNotBlank(to)) {
				result = to.compareTo(value) >= 0;
			} else if (StringUtil.isNotBlank(from) && StringUtil.isBlank(to)) {
				result = value.compareTo(from) >= 0;
			}
		} catch (Exception e) {
			return false;
		}
		return result;
	}

	
	/**
	 * YYYY/M/Dなどの日付をYYYY/MM/DDに変更する。空文字の場合そのまま返す。
	 * 
	 * @param value 日付
	 * @return YYYY/MM/DD形式の文字列
	 * @throws Exception
	 */
	public static String dateStrToYYMMDD(String value) throws Exception {
		if (StringUtil.isBlank(value)) {
			return value;
		}

		value = value.replace('-', '/');
		String[] ymd = value.split("/");
		if (ymd.length != 3 || ymd[0].length() != 4) {
			throw new Exception();
		}

		value = ymd[0] + "/" + StringUtils.leftPad(ymd[1], 2, "0") + "/" + StringUtils.leftPad(ymd[2], 2, "0");
		SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd");
		format.setLenient(false);
		format.parse(value);

		return value;
	}	
	
	/**
	 * 生年月日から年齢を取得する。
	 * @param strbirthDay
	 * @return
	 * @throws ParseException
	 */
	public static int getAge(String strbirthDay) throws ParseException{
		
		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
		Calendar birthDay = Calendar.getInstance();
		birthDay.setTime(sdf.parse(strbirthDay));
		Calendar today = Calendar.getInstance();
		today.setTime(sdf.parse(new SimpleDateFormat(Formats.DATATYPE_DATE_FORMAT_NON_SLASH).format(new Timestamp(System.currentTimeMillis()).getTime())));
		int age = today.get(Calendar.YEAR) - birthDay.get(Calendar.YEAR);
		birthDay.clear(Calendar.YEAR);
		today.clear(Calendar.YEAR);
		if (birthDay.after(today)) {
			age -= 1;
		}
		return age;
	}

	/**
     * 引数の文字列(UTF-8)を、Shift_JISにエンコードする。
     * 
     * @param value 変換対象の文字列
     * @return エンコードされた文字列
     */
    public static String utf8ToSjis(String value) throws UnsupportedEncodingException {
        byte[] srcStream = value.getBytes("UTF-8");
        //value = convert(new String(srcStream, "UTF-8"), "UTF-8", "SJIS");
        value = convert(new String(srcStream, "UTF-8"), "UTF-8", "Windows-31J");
        byte[] destStream = value.getBytes("Windows-31J");
        value = new String(destStream, "Windows-31J");
        return value;
    }

    /**
     * 引数の文字列を、エンコードする。
     * 
     * @param value 変換対象の文字列
     * @param src 変換前の文字コード
     * @param dest 変換後の文字コード
     * @return エンコードされた文字列
     */
    private static String convert(String value, String src, String dest) throws UnsupportedEncodingException {
        Map<String, String> conversion = createConversionMap(src, dest);
        char oldChar;
        char newChar;
        String key;
        for (Iterator<String> itr = conversion.keySet().iterator() ; itr.hasNext() ;) {
            key = itr.next();
            oldChar = toChar(key);
            newChar = toChar(conversion.get(key));
            value = value.replace(oldChar, newChar);
        }
        return value;
    }
    
    /**
     * エンコード情報を作成する
     * 
     * @param src 変換前の文字コード
     * @param dest 変換後の文字コード
     * @return エンコードされた文字列
     */
    private static Map<String, String> createConversionMap(String src, String dest) throws UnsupportedEncodingException {
        Map<String, String> conversion = new HashMap<String, String>();
        if ((src.equals("UTF-8")) && (dest.equals("SJIS"))) {
            // -(全角マイナス)
            conversion.put("U+FF0D", "U+2212");
            // ~(全角チルダ)
            conversion.put("U+FF5E", "U+301C");
            // ¢(セント)
            conversion.put("U+FFE0", "U+00A2");
            // £(ポンド)
            conversion.put("U+FFE1", "U+00A3");
            // ¬(ノット)
            conversion.put("U+FFE2", "U+00AC");
            // ―(全角マイナスより少し幅のある文字)
            conversion.put("U+2015", "U+2014");
            // ∥(半角パイプが2つ並んだような文字)
            conversion.put("U+2225", "U+2016");

        } else if ((src.equals("SJIS")) && (dest.equals("UTF-8"))) {
            // -(全角マイナス)
            conversion.put("U+2212", "U+FF0D");
            // ~(全角チルダ)
            conversion.put("U+301C", "U+FF5E");
            // ¢(セント)
            conversion.put("U+00A2", "U+FFE0");
            // £(ポンド)
            conversion.put("U+00A3", "U+FFE1");
            // ¬(ノット)
            conversion.put("U+00AC", "U+FFE2");
            // ―(全角マイナスより少し幅のある文字)
            conversion.put("U+2014", "U+2015");
            // ∥(半角パイプが2つ並んだような文字)
            conversion.put("U+2016", "U+2225");

        } else {
            throw new UnsupportedEncodingException("この文字コードはサポートしていません。\n・src=" + src + ",dest=" + dest);
        }
        return conversion;
    }

    /**
     * 16進表記の文字を取得する。
     * 
     * @param value 変換対象の文字列
     * @return 16進表記の文字
     */
    private static char toChar(String value) {
        return (char)Integer.parseInt(value.trim().substring("U+".length()), 16);
    }

	public static boolean isAllowedSrc(String ipAddress, List<String> allowedList) {
		if (!allowedList.isEmpty()) {
			for (String address : allowedList) {
				if (address.endsWith("*") && ipAddress.startsWith(address.substring(0, address.length() - 1))) {
					return true;
				} else if (address.contains("/")) {
					try {
						SubnetUtils subnetUtils = new SubnetUtils(address);
						subnetUtils.setInclusiveHostCount(true);
						if (subnetUtils.getInfo().isInRange(ipAddress)) {
							return true;
						}
					} catch (Exception e) {
						LOGGER.fatal("invalid address " + address + " : " + e.toString());
					}
				} else if (address.equals(ipAddress)) {
					return true;
				}
			}
		} else {
			// 未設定の場合は、IP制限なし
			return true;
		}
		return false;
	}
	
	
	/**
	 * UTF8からSJISに変換時文字化ける文字を置換
	 * 
	 * @param s
	 * @return
	 */
	public static String toSJIS(String s) {
		
		if(s == null){
			return "";
		}
		
		StringBuffer sb = new StringBuffer();
		char c;

		for (int i = 0; i < s.length(); i++) {
			c  = s.charAt(i);
			switch (c) {
				case 0x301c:
					c = 0xff5e;
					break;
				case 0x2016:
					c = 0x2225;
					break;
				case 0x2212:
					c = 0xff0d;
					break;
				case 0x00a2:
					c = 0xffe0;
					break;
				case 0x00a3:
					c = 0xffe1;
					break;
				case 0x00ac:
					c = 0xffe2;
					break;
				case 0x2014:
					c = 0x2015;
					break;
				default:
					break;
			}

			sb.append(c);
		}
		return new String(sb);
	}
	
}