/*
 * @(#)ZString.java
 *
 * Copyright 2000 by Intelligent Technology Inc. All rights reserved.
 */
package jp.co.iti.fagot.util;

import java.text.DateFormat;

import java.util.Date;
import java.util.Enumeration;
import java.util.Vector;
import java.util.StringTokenizer;
/**
 * FuStringクラスは文字列を分割します。
 * すべてstaticメソッドのユーティリティです
 *
 * @author  福島康治
 * @version 1.01 2000/12/01
 */
public class ZString {

	/**
	 * 唯一のコンストラクタです。
	 */
	public ZString() {
	}

	//## 区切り #######################################################
	/**
	 * 文字列を分割し配列に格納します。
	 *
	 * 区切り文字が続いた場合は、1つの区切り文字として認識します。
	 * 区切り文字が{先頭|最後}にある場合は、区切り文字を切り捨てます。
	 *
	 * パラメータの文字列により次のような値を返します。
	 * param       : return
	 * ------------ ---------------------------
	 * null        : length 0
	 * delm        : length 0
	 * delm + Str  : length 1 , Str
	 * Str + delm  : length 1 , Str
	 *
	 * @param szInput 分割元文字列
	 * @param szDelim 区切り文字
	 */
	static public String[] tokenize(String szInput,String szDelim ) {
	if ( szInput == null ) {
		return new String[0];
	}
	Vector v = new Vector();
	StringTokenizer tokn = new StringTokenizer(szInput,szDelim);
	String szCmd[];

	while (tokn.hasMoreTokens())
	    v.addElement(tokn.nextToken());
	szCmd = new String[v.size()];
	for (int i = 0; i < szCmd.length; i++)
	    szCmd[i] = (String) v.elementAt(i);

	return(szCmd);
	}

	/**
	 * 文字列を分割し配列に格納します。
	 * @param szInput 分割元文字列
	 */
	static public String[] tokenize(String szInput) {
	return(	tokenize(szInput, " \t\n\r\f") );
	}

	/**
	 * 文字列の最初の区切りのみ分割し配列に格納します。
	 * @param szInput 分割元文字列
	 * @param szDelim 区切り文字
	 */
	static public String[] tokenfirst(String szInput,String szDelim ) {
	String szValues[] = tokenize( szInput, szDelim );
	String szRet[] = new String[2];
	if ( szValues.length > 1 ) {
		szRet[0] = szValues[0];
		szRet[1] = szInput.substring(szRet[0].length()+1);
	} else {
		szRet[0] = szInput;
		szRet[1] = null;
	}
	return szRet;
	}

	/**
	 * 文字列の最初の区切りのみ分割し配列に格納します。
	 * @param szInput 分割元文字列
	 */
	static public String[] tokenfirst(String szInput) {
	return(	tokenfirst(szInput, " \t\n\r\f") );
	}

	//## trim #########################################################
	/**
	 * 文字列の左空白を削除します。
	 * @param szInput 元文字列
	 */
	static public String trimLeft( String szInput ) {
	int nIndex = 0;
	for ( nIndex=0; nIndex< szInput.length() ; nIndex++ ) {
		if ( !Character.isWhitespace( szInput.charAt(nIndex) ) ) {
			break;
		}
	}
	return ( szInput.substring( nIndex ) ) ;
	}

	/**
	 * 文字列の右空白を削除します。
	 * @param szInput 元文字列
	 */
	static public String trimRight( String szInput ) {
	int nIndex = 0;
	for ( nIndex=szInput.length()-1; nIndex >= 0 ; nIndex-- ) {
		if ( !Character.isWhitespace( szInput.charAt(nIndex) ) ) {
			break;
		}
	}
	return ( szInput.substring( 0, nIndex+1 ) ) ;
	}

	/**
	 * 文字列の左右空白を削除します。
	 * @param szInput 元文字列
	 */
	static public String trim( String szInput ) {
	String left  = trimLeft(szInput);
	String right = trimRight(left);
	return right ;
	}

	//## utility ######################################################
	/**
	 * 検索文字列のうち、いずれかの文字が含まれていれば、位置を返します
	 *
	 * @param szInput 元文字列
	 * @param szFind  検索文字列
	 */
	static public int findOneOf( String szInput, String szFind ) {
	int nRet = -1;
	int nIndex = 0;
	for ( nIndex=0; nIndex< szFind.length() ; nIndex++ ) {
		char find = szFind.charAt(nIndex);
		int nAt = szInput.indexOf( find );
		if ( nAt >= 0 ) {
			if ( nRet == -1 ) {
				nRet = nAt;
			} else {
				nRet = Math.min(nRet,nAt);
			}
		}
	}
	return nRet ;
	}

	/**
	 * 語句を抽出します。
	 * @param szInput 元文字列
	 */
	static public String getString( String szInput ) {
	int nIndex = 0;
	for ( nIndex=0; nIndex< szInput.length() ; nIndex++ ) {
		if ( Character.isLetterOrDigit( szInput.charAt(nIndex) ) ) {
			continue;
		} else if ( szInput.charAt(nIndex) == '.' ) {
			continue;
		}
		break;
	}
	return ( szInput.substring( 0,nIndex ) ) ;
	}

	/**
	 * 文字列を置換します。
	 * 検索文字列が見つかっても何度でも繰り返して置換します。
	 * @param szInput 元文字列
	 * @param szSrc   検索文字列
	 * @param szDst   置換文字列
	 */
	static public String replace( String szInput,String szSrc, String szDst ) {
	int nIndex = 0;
	String szRet = new String();
	while ( (nIndex=szInput.indexOf(szSrc)) >=0 ) {
		if ( nIndex > 0 ) {
			szRet = szRet + szInput.substring(0,nIndex) ;
		}
		szRet = szRet + szDst ;
		if ( szInput.length() == (nIndex+szSrc.length()) ) {
			szInput = null;
			break ;
		}
		szInput = szInput.substring( nIndex+szSrc.length() );
	}
	if ( szInput != null ) {
		szRet = szRet + szInput ;
	}
	return ( szRet ) ;
	}

	/**
	 * 共通文字列を抽出します
	 * @param strs 文字列群
	 */
	static public String getCommonStrings( Vector strs ) {
	Vector cmn = null;
	Enumeration elm = strs.elements();
//	ZDebug.trace();
	while ( elm.hasMoreElements() ) {
		String tmp = (String)elm.nextElement();
//		ZDebug.trace("    add:"+tmp);
		String[] str = tokenize(tmp);
		if ( cmn == null ) {
			// 最初のエレメントは全て登録
			cmn = new Vector();
			for ( int nIndex=0; nIndex<str.length ; nIndex++ ) {
				cmn.add(str[nIndex]);
			}
		} else {
			Vector newcmn = new Vector();
			// 共通の文字が、今度の文字に含まれているか？
			Enumeration cmnelm = cmn.elements();
			while( cmnelm.hasMoreElements() ) {
				String szcmn = (String)cmnelm.nextElement();
				for ( int nIndex=0; nIndex<str.length ; nIndex++ ) {
					if ( szcmn.equals(str[nIndex]) ) {
						newcmn.add( szcmn ) ;
						break;
					}
				}
			}
			cmn = newcmn;
		}
	}
	String szRet = "";
	if ( cmn != null ) {
		Enumeration cmnelm = cmn.elements();
		while( cmnelm.hasMoreElements() ) {
			szRet += (String)cmnelm.nextElement() + " ";
		}
	}
	szRet = trimRight(szRet);
//	ZDebug.trace("    cmn:"+szRet);
	return szRet;
	}

	//## 時間 #########################################################
	/**
	 * 現在時刻を返します。
	 */
	static public String getTime() {
	Date date = new Date();
	DateFormat fmt = DateFormat.getTimeInstance();
	return fmt.format(date);
	}

	/**
	 * 現在日付を返します。
	 */
	static public String getDate() {
	Date date = new Date();
	DateFormat fmt = DateFormat.getDateInstance();
	return fmt.format(date);
	}

	/**
	 * 現在時刻を返します。
	 */
	static public String getDateTime() {
	Date date = new Date();
	DateFormat fmt = DateFormat.getDateTimeInstance();
	return fmt.format(date);
	}

	//## 変換 #########################################################
	/**
	 * 数値を取得します
	 * @param szStr 数値文字列
	 * @param nErr  エラーの場合に返す値
	 */
	static public byte parseByte(String szStr, byte nErr) {
	if ( szStr == null ) {
		return nErr;
	}
	try {
		byte nIndex = Byte.parseByte(szStr);
		return nIndex;
	} catch(NumberFormatException nf) {
//		ZDebug.trace("Parse Error:"+szStr);
	}
	return nErr;
	}

	/**
	 * 数値を取得します
	 * @param szStr 数値文字列
	 * @param nErr  エラーの場合に返す値
	 */
	static public double parseDouble(String szStr, double nErr) {
	if ( szStr == null ) {
		return nErr;
	}

	// SVG Spec
	// @see http://www.w3.org/TR/SVG/coords.html#UnitIdentifiers
	double dUnit = 1.0;
	if ( szStr.endsWith("px") ) {
		szStr = szStr.substring(0,szStr.length()-2);
	} else if ( szStr.endsWith("pt") ) {
		szStr = szStr.substring(0,szStr.length()-2); dUnit = 1.25 ;
	} else if ( szStr.endsWith("pc") ) {
		szStr = szStr.substring(0,szStr.length()-2); dUnit = 15 ;
	} else if ( szStr.endsWith("mm") ) {
		szStr = szStr.substring(0,szStr.length()-2); dUnit = 3.543307 ;
	} else if ( szStr.endsWith("cm") ) {
		szStr = szStr.substring(0,szStr.length()-2); dUnit = 35.43307 ;
	} else if ( szStr.endsWith("in") ) {
		szStr = szStr.substring(0,szStr.length()-2); dUnit = 90 ;
	}

	try {
		double nIndex = Double.parseDouble(szStr);
		return nIndex * dUnit;
	} catch(NumberFormatException nf) {
//		ZDebug.trace("Parse Error:"+szStr);
	}
	return nErr;
	}


	/**
	 * 数値を取得します
	 * @param szStr 数値文字列
	 * @param nErr  エラーの場合に返す値
	 */
	static public int parseInt(String szStr, int nErr) {
	if ( szStr == null ) {
		return nErr;
	}
	try {
		int nIndex = Integer.parseInt(szStr);
		return nIndex;
	} catch(NumberFormatException nf) {
//		ZDebug.trace("Parse Error:"+szStr);
	}
	return nErr;
	}

	/**
	 * 数値を取得します
	 * エラーの場合、-1を返します
	 * @param szStr 数値文字列
	 */
	static public int parseInt(String szStr) {
	return parseInt(szStr,-1);
	}
}
