/*
 * DataFileCreator
 *
 * Utility class with static methods for manipulating Japanese text.
 *
 * Created: June 12, 2006
 * Author:  Alex Quinn
 */

class Japanese {
	static final int NOTHING=0, HIRAGANA=1, KATAKANA=2, KANJI=3, OTHER=4;
	static final String REPETITION_MARKER="\u3005";
	
	static int getCharType( char ch ) {
		if( charIsKatakana(ch) ) return KATAKANA;
		else if( charIsHiragana(ch) ) return HIRAGANA;
		else if( charIsKanji(ch) ) return KANJI;
		else return OTHER;
	}

	// These Unicode values were taken from the Unicode standard version 4.1
	// Source:  http://www.unicode.org/charts/
	static boolean charIsKatakana( char ch ) { return ch>=0x30A0 && ch<=0x30FF; } // real Unicode values
	static boolean charIsHiragana( char ch ) { return ch>=0x3040 && ch<=0x309F; } // real Unicode values
	//static boolean charIsKatakana( char ch ) { return ch>=0x30A1 && ch<=0x30F4; }   // excludes a few oddballs
	//static boolean charIsHiragana( char ch ) { return ch>=0x3041 && ch<=0x3094; }   // excludes a few oddballs

	static boolean charIsKana( char ch ) { return charIsKatakana(ch)||charIsHiragana(ch); }
	static boolean charIsAscii( char ch ) { return ch<0x0100; }
	static boolean charIsLetter( char ch ) { return ch>=0x0041&&ch<=0x005A || ch>=0x0061&&ch<=0x007A; }
	static boolean charIsNumber( char ch ) { return ch>=0x0030&&ch<=0x0039; }
	static boolean charIsKanji( char ch ) { return 
								ch>=0x4E00 && ch<=0x9FBF  /* "Unified CJK ideographs" */ ||
								ch>=0x3400 && ch<=0x4DBF  /* "Unified CJK ideographs extension A" */ ||
								ch>=0x20000&& ch<=0x2A6DF /* "Unified CJK ideographs extension B" */ ||
								ch>=0XF900 && ch<=0XFAFF  /* "CJK Compatibility Ideographs" */ ||
								ch>=0x2F800&& ch<=0x2FA1F /* "CJK Compatibility Ideographs Supplement" */ ||
								ch>=0x3190 && ch<=0X319F  /* "Kanbun" */   ; }

	// Convert a character to katakana, only if it's hiragana.
	// Return it unchanged if it's not hiragana.
	static char hiraganaToKatakana(char hiragana) {
		// These assertions define "hiragana" a little more narrowly then the
		// Unicode standard.  We define "hiragana" as only those characters which
		// have a direct translation into "katakana".
		//assert hiragana>=0x3041;
		//assert hiragana<=0x3094;
		if( hiragana>=0x3041 && hiragana<=0x3094 )
			return (char)((int)hiragana+96); // discovered this constant by experimentation
		else
			return hiragana;
	}

	// Convert a character to hiragana, only if it's katakana.
	// Return it unchanged if it's not katakana.
	static char katakanaToHiragana(char katakana) {
		// These assertions define "katakana" a little more narrowly then the
		// Unicode standard.  We define "katakana" as only those characters which
		// have a direct translation into "hiragana".
		//assert katakana>=0x30A1 : "(too small) katakana=="+Integer.toHexString((int)katakana);
		//assert katakana<=0x30F4 : "(too large) katakana=="+Integer.toHexString((int)katakana);
		if( katakana>=0x30A1 && katakana<=0x30F4 )
			return (char)((int)katakana-96); // discovered this constant by experimentation
		else
			return katakana;
	}
	
	// Convert all katakana in the string to hiragana.
	// Leave everything else as is.
	static String toHiragana(String katakana) {
		String hiragana="";
		for( char ch : katakana.toCharArray() ) {
			hiragana+=katakanaToHiragana(ch);
		}
		return hiragana;
	}
	// Convert all hiragana in the string to katakana.
	// Leave everything else as is.
	static String toKatakana(String hiragana) {
		String katakana="";
		for( char ch : hiragana.toCharArray() ) {
			katakana+=hiraganaToKatakana(ch);
		}
		return katakana;
	}
	static int countKanji(String s) {
		int kanjiCount = 0;
		for( char ch : s.toCharArray() ) {
			if( charIsKanji(ch) )
				kanjiCount++;
		}
		return kanjiCount;
	}

	// Named constants for all of the hiragana and katakana.
	public static final char HIRAGANA_XA = '\u3041';
	public static final char HIRAGANA_A = '\u3042';
	public static final char HIRAGANA_XI = '\u3043';
	public static final char HIRAGANA_I = '\u3044';
	public static final char HIRAGANA_XU = '\u3045';
	public static final char HIRAGANA_U = '\u3046';
	public static final char HIRAGANA_XE = '\u3047';
	public static final char HIRAGANA_E = '\u3048';
	public static final char HIRAGANA_XO = '\u3049';
	public static final char HIRAGANA_O = '\u304A';
	public static final char HIRAGANA_KA = '\u304B';
	public static final char HIRAGANA_GA = '\u304C';
	public static final char HIRAGANA_KI = '\u304D';
	public static final char HIRAGANA_GI = '\u304E';
	public static final char HIRAGANA_KU = '\u304F';
	public static final char HIRAGANA_GU = '\u3050';
	public static final char HIRAGANA_KE = '\u3051';
	public static final char HIRAGANA_GE = '\u3052';
	public static final char HIRAGANA_KO = '\u3053';
	public static final char HIRAGANA_GO = '\u3054';
	public static final char HIRAGANA_SA = '\u3055';
	public static final char HIRAGANA_ZA = '\u3056';
	public static final char HIRAGANA_SHI = '\u3057';
	public static final char HIRAGANA_JI = '\u3058';
	public static final char HIRAGANA_SU = '\u3059';
	public static final char HIRAGANA_ZU = '\u305A';
	public static final char HIRAGANA_SE = '\u305B';
	public static final char HIRAGANA_ZE = '\u305C';
	public static final char HIRAGANA_SO = '\u305D';
	public static final char HIRAGANA_ZO = '\u305E';
	public static final char HIRAGANA_TA = '\u305F';
	public static final char HIRAGANA_DA = '\u3060';
	public static final char HIRAGANA_CHI = '\u3061';
	public static final char HIRAGANA_DJI = '\u3062';
	public static final char HIRAGANA_XTSU = '\u3063';
	public static final char HIRAGANA_TSU = '\u3064';
	public static final char HIRAGANA_DU = '\u3065';
	public static final char HIRAGANA_TE = '\u3066';
	public static final char HIRAGANA_DE = '\u3067';
	public static final char HIRAGANA_TO = '\u3068';
	public static final char HIRAGANA_DO = '\u3069';
	public static final char HIRAGANA_NA = '\u306A';
	public static final char HIRAGANA_NI = '\u306B';
	public static final char HIRAGANA_NU = '\u306C';
	public static final char HIRAGANA_NE = '\u306D';
	public static final char HIRAGANA_NO = '\u306E';
	public static final char HIRAGANA_HA = '\u306F';
	public static final char HIRAGANA_BA = '\u3070';
	public static final char HIRAGANA_PA = '\u3071';
	public static final char HIRAGANA_HI = '\u3072';
	public static final char HIRAGANA_BI = '\u3073';
	public static final char HIRAGANA_PI = '\u3074';
	public static final char HIRAGANA_FU = '\u3075';
	public static final char HIRAGANA_BU = '\u3076';
	public static final char HIRAGANA_PU = '\u3077';
	public static final char HIRAGANA_HE = '\u3078';
	public static final char HIRAGANA_BE = '\u3079';
	public static final char HIRAGANA_PE = '\u307A';
	public static final char HIRAGANA_HO = '\u307B';
	public static final char HIRAGANA_BO = '\u307C';
	public static final char HIRAGANA_PO = '\u307D';
	public static final char HIRAGANA_MA = '\u307E';
	public static final char HIRAGANA_MI = '\u307F';
	public static final char HIRAGANA_MU = '\u3080';
	public static final char HIRAGANA_ME = '\u3081';
	public static final char HIRAGANA_MO = '\u3082';
	public static final char HIRAGANA_XYA = '\u3083';
	public static final char HIRAGANA_YA = '\u3084';
	public static final char HIRAGANA_XYU = '\u3085';
	public static final char HIRAGANA_YU = '\u3086';
	public static final char HIRAGANA_XYO = '\u3087';
	public static final char HIRAGANA_YO = '\u3088';
	public static final char HIRAGANA_RA = '\u3089';
	public static final char HIRAGANA_RI = '\u308A';
	public static final char HIRAGANA_RU = '\u308B';
	public static final char HIRAGANA_RE = '\u308C';
	public static final char HIRAGANA_RO = '\u308D';
	public static final char HIRAGANA_XWA = '\u308E';
	public static final char HIRAGANA_WA = '\u308F';
	public static final char HIRAGANA_WI = '\u3090';
	public static final char HIRAGANA_WE = '\u3091';
	public static final char HIRAGANA_WO = '\u3092';
	public static final char HIRAGANA_N = '\u3093';
	public static final char HIRAGANA_VU = '\u3094';
	public static final char KATAKANA_XA = '\u30A1';
	public static final char KATAKANA_A = '\u30A2';
	public static final char KATAKANA_XI = '\u30A3';
	public static final char KATAKANA_I = '\u30A4';
	public static final char KATAKANA_XU = '\u30A5';
	public static final char KATAKANA_U = '\u30A6';
	public static final char KATAKANA_XE = '\u30A7';
	public static final char KATAKANA_E = '\u30A8';
	public static final char KATAKANA_XO = '\u30A9';
	public static final char KATAKANA_O = '\u30AA';
	public static final char KATAKANA_KA = '\u30AB';
	public static final char KATAKANA_GA = '\u30AC';
	public static final char KATAKANA_KI = '\u30AD';
	public static final char KATAKANA_GI = '\u30AE';
	public static final char KATAKANA_KU = '\u30AF';
	public static final char KATAKANA_GU = '\u30B0';
	public static final char KATAKANA_KE = '\u30B1';
	public static final char KATAKANA_GE = '\u30B2';
	public static final char KATAKANA_KO = '\u30B3';
	public static final char KATAKANA_GO = '\u30B4';
	public static final char KATAKANA_SA = '\u30B5';
	public static final char KATAKANA_ZA = '\u30B6';
	public static final char KATAKANA_SHI = '\u30B7';
	public static final char KATAKANA_JI = '\u30B8';
	public static final char KATAKANA_SU = '\u30B9';
	public static final char KATAKANA_ZU = '\u30BA';
	public static final char KATAKANA_SE = '\u30BB';
	public static final char KATAKANA_ZE = '\u30BC';
	public static final char KATAKANA_SO = '\u30BD';
	public static final char KATAKANA_ZO = '\u30BE';
	public static final char KATAKANA_TA = '\u30BF';
	public static final char KATAKANA_DA = '\u30C0';
	public static final char KATAKANA_CHI = '\u30C1';
	public static final char KATAKANA_DJI = '\u30C2';
	public static final char KATAKANA_XTSU = '\u30C3';
	public static final char KATAKANA_TSU = '\u30C4';
	public static final char KATAKANA_DU = '\u30C5';
	public static final char KATAKANA_TE = '\u30C6';
	public static final char KATAKANA_DE = '\u30C7';
	public static final char KATAKANA_TO = '\u30C8';
	public static final char KATAKANA_DO = '\u30C9';
	public static final char KATAKANA_NA = '\u30CA';
	public static final char KATAKANA_NI = '\u30CB';
	public static final char KATAKANA_NU = '\u30CC';
	public static final char KATAKANA_NE = '\u30CD';
	public static final char KATAKANA_NO = '\u30CE';
	public static final char KATAKANA_HA = '\u30CF';
	public static final char KATAKANA_BA = '\u30D0';
	public static final char KATAKANA_PA = '\u30D1';
	public static final char KATAKANA_HI = '\u30D2';
	public static final char KATAKANA_BI = '\u30D3';
	public static final char KATAKANA_PI = '\u30D4';
	public static final char KATAKANA_FU = '\u30D5';
	public static final char KATAKANA_BU = '\u30D6';
	public static final char KATAKANA_PU = '\u30D7';
	public static final char KATAKANA_HE = '\u30D8';
	public static final char KATAKANA_BE = '\u30D9';
	public static final char KATAKANA_PE = '\u30DA';
	public static final char KATAKANA_HO = '\u30DB';
	public static final char KATAKANA_BO = '\u30DC';
	public static final char KATAKANA_PO = '\u30DD';
	public static final char KATAKANA_MA = '\u30DE';
	public static final char KATAKANA_MI = '\u30DF';
	public static final char KATAKANA_MU = '\u30E0';
	public static final char KATAKANA_ME = '\u30E1';
	public static final char KATAKANA_MO = '\u30E2';
	public static final char KATAKANA_XYA = '\u30E3';
	public static final char KATAKANA_YA = '\u30E4';
	public static final char KATAKANA_XYU = '\u30E5';
	public static final char KATAKANA_YU = '\u30E6';
	public static final char KATAKANA_XYO = '\u30E7';
	public static final char KATAKANA_YO = '\u30E8';
	public static final char KATAKANA_RA = '\u30E9';
	public static final char KATAKANA_RI = '\u30EA';
	public static final char KATAKANA_RU = '\u30EB';
	public static final char KATAKANA_RE = '\u30EC';
	public static final char KATAKANA_RO = '\u30ED';
	public static final char KATAKANA_XWA = '\u30EE';
	public static final char KATAKANA_WA = '\u30EF';
	public static final char KATAKANA_WI = '\u30F0';
	public static final char KATAKANA_WE = '\u30F1';
	public static final char KATAKANA_WO = '\u30F2';
	public static final char KATAKANA_N = '\u30F3';
	public static final char KATAKANA_VU = '\u30F4';
	public static final char KATAKANA_XKA = '\u30F5';
	public static final char KATAKANA_XKE = '\u30F6';
	public static final char KATAKANA_VA = '\u30F7';
	public static final char KATAKANA_VI = '\u30F8';
	public static final char KATAKANA_VE = '\u30F9';
	public static final char KATAKANA_VO = '\u30FA';

	// Mapping from unvoiced to voiced kana.
	public static char[][] getReplaceWithVoicedArray() {
		return new char[][] {
		{Japanese.HIRAGANA_KA, Japanese.HIRAGANA_GA},
		{Japanese.HIRAGANA_KI, Japanese.HIRAGANA_GI},
		{Japanese.HIRAGANA_KU, Japanese.HIRAGANA_GU},
		{Japanese.HIRAGANA_KE, Japanese.HIRAGANA_GE},
		{Japanese.HIRAGANA_KO, Japanese.HIRAGANA_GO},
		{Japanese.HIRAGANA_SA, Japanese.HIRAGANA_ZA},
		{Japanese.HIRAGANA_SHI, Japanese.HIRAGANA_JI},
		{Japanese.HIRAGANA_SU, Japanese.HIRAGANA_ZU},
		{Japanese.HIRAGANA_SE, Japanese.HIRAGANA_ZE},
		{Japanese.HIRAGANA_SO, Japanese.HIRAGANA_ZO},
		{Japanese.HIRAGANA_TA, Japanese.HIRAGANA_DA},
		{Japanese.HIRAGANA_CHI, Japanese.HIRAGANA_DJI},
		{Japanese.HIRAGANA_TSU, Japanese.HIRAGANA_DU},
		{Japanese.HIRAGANA_TE, Japanese.HIRAGANA_DE},
		{Japanese.HIRAGANA_TO, Japanese.HIRAGANA_DO},
		{Japanese.HIRAGANA_HA, Japanese.HIRAGANA_BA},
		{Japanese.HIRAGANA_HI, Japanese.HIRAGANA_BI},
		{Japanese.HIRAGANA_FU, Japanese.HIRAGANA_BU},
		{Japanese.HIRAGANA_HE, Japanese.HIRAGANA_BE},
		{Japanese.HIRAGANA_HO, Japanese.HIRAGANA_BO},
		{Japanese.KATAKANA_KA, Japanese.KATAKANA_GA},
		{Japanese.KATAKANA_KI, Japanese.KATAKANA_GI},
		{Japanese.KATAKANA_KU, Japanese.KATAKANA_GU},
		{Japanese.KATAKANA_KE, Japanese.KATAKANA_GE},
		{Japanese.KATAKANA_KO, Japanese.KATAKANA_GO},
		{Japanese.KATAKANA_SA, Japanese.KATAKANA_ZA},
		{Japanese.KATAKANA_SHI, Japanese.KATAKANA_JI},
		{Japanese.KATAKANA_SU, Japanese.KATAKANA_ZU},
		{Japanese.KATAKANA_SE, Japanese.KATAKANA_ZE},
		{Japanese.KATAKANA_SO, Japanese.KATAKANA_ZO},
		{Japanese.KATAKANA_TA, Japanese.KATAKANA_DA},
		{Japanese.KATAKANA_CHI, Japanese.KATAKANA_DJI},
		{Japanese.KATAKANA_TSU, Japanese.KATAKANA_DU},
		{Japanese.KATAKANA_TE, Japanese.KATAKANA_DE},
		{Japanese.KATAKANA_TO, Japanese.KATAKANA_DO},
		{Japanese.KATAKANA_HA, Japanese.KATAKANA_BA},
		{Japanese.KATAKANA_HI, Japanese.KATAKANA_BI},
		{Japanese.KATAKANA_FU, Japanese.KATAKANA_BU},
		{Japanese.KATAKANA_HE, Japanese.KATAKANA_BE},
		{Japanese.KATAKANA_HO, Japanese.KATAKANA_BO}  };
	}
	
	// Mapping from H kana (ha/hi/fu/he/ho) to P kana (pa/pi/pu/pe/po).
	public static char[][] getReplaceHWithPArray() {
		return new char[][] {
		{Japanese.HIRAGANA_HA, Japanese.HIRAGANA_PA},
		{Japanese.HIRAGANA_HI, Japanese.HIRAGANA_PI},
		{Japanese.HIRAGANA_FU, Japanese.HIRAGANA_PU},
		{Japanese.HIRAGANA_HE, Japanese.HIRAGANA_PE},
		{Japanese.HIRAGANA_HO, Japanese.HIRAGANA_PO},
		{Japanese.KATAKANA_HA, Japanese.KATAKANA_PA},
		{Japanese.KATAKANA_HI, Japanese.KATAKANA_PI},
		{Japanese.KATAKANA_FU, Japanese.KATAKANA_PU},
		{Japanese.KATAKANA_HE, Japanese.KATAKANA_PE},
		{Japanese.KATAKANA_HO, Japanese.KATAKANA_PO} };
	}
	
	// Mapping from KU/TSU to small TSU.  This is used for matching
	// kanji readings to their inflected uses in the readings of
	// example compounds.
	public static char[][] getReplaceKuTsuWithXtsuArray() {
		return new char[][] {
		{Japanese.HIRAGANA_KU, Japanese.HIRAGANA_XTSU},
		{Japanese.HIRAGANA_TSU, Japanese.HIRAGANA_XTSU},
		{Japanese.KATAKANA_KU, Japanese.KATAKANA_XTSU},
		{Japanese.KATAKANA_TSU, Japanese.KATAKANA_XTSU} };
	}
}
