/*
 * Copyright (c) 2009 The openGion Project.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
 * either express or implied. See the License for the specific language
 * governing permissions and limitations under the License.
 */
package org.opengion.fukurou.util;

/**
 * KanaFilter.java は、半角カタカナを全角カタカナに変換するフィルターツールです。
 *
 * 大元の出典は、『CJKV日中韓越情報処理』のフィルターアルゴリズムです。
 * 濁点や半濁点の正しい処理も含まれています。
 *
 * @version  4.0
 * @author   Kazuhiko Hasegawa
 * @since    JDK5.0,
 */
public final class KanaFilter {

	// uFF61 から uFF9Fまでの半角カナに対応(u3002 ～ u309C)
	private static final char ZEN_KANA[] = {
		'。','「','」','、','・',
		'ヲ','ァ','ィ','ゥ','ェ','ォ',
		'ャ','ュ','ョ','ッ','ー',
		'ア','イ','ウ','エ','オ',
		'カ','キ','ク','ケ','コ',
		'サ','シ','ス','セ','ソ',
		'タ','チ','ツ','テ','ト',
		'ナ','ニ','ヌ','ネ','ノ',
		'ハ','ヒ','フ','ヘ','ホ',
		'マ','ミ','ム','メ','モ',
		'ヤ','ユ','ヨ',
		'ラ','リ','ル','レ','ロ',
		'ワ','ン','゛','゜'
	};

	/**
	 * すべてが staticメソッドなので、コンストラクタを呼び出さなくしておきます。
	 *
	 */
	private KanaFilter() {}

	/**
	 * 半角カタカナを全角カタカナに
	 *
	 * 半角カタカナの定義は、\uFF61 から \uFF9F までです。
	 *
	 * @param   in 半角カタカナ文字列
	 *
	 * @return  全角文字列
	 */
	public static String han2zen( final String in ) {
		int ixIn  = 0;
		int ixOut = 0;
		int len = in.length();
		char[] input = in.toCharArray();
		char[] output = new char[len + 1];

		while( ixIn < len ) {
			// 半角カタカナの範囲
			if( input[ixIn] >= '\uFF61' && input[ixIn] <= '\uFF9F' ) {
				if( ixIn + 1 >= len ) {
					output[ixOut++] = ZEN_KANA[input[ixIn++] - '\uFF61'];
				}
				else {
					// 濁点(ヴ)
					if( input[ixIn+1] == 'ﾞ' ||
							input[ixIn+1] == '\u3099' ||
							input[ixIn+1] == '゛' ) {
						if( input[ixIn] == 'ｳ' ) {
							output[ixOut++] = 'ヴ' ;
							ixIn +=2 ;
						}
						else {
							// 濁点(ガ～ド、バ～ボ)
							if( input[ixIn] >= 'ｶ' &&
									input[ixIn] <= 'ﾄ' ||
									input[ixIn] >= 'ﾊ' &&
									input[ixIn] <= 'ﾎ' ) {
								output[ixOut] = ZEN_KANA[input[ixIn] - '\uFF61'];
								output[ixOut++]++;
								ixIn +=2 ;
							}
							else {
								output[ixOut++] = ZEN_KANA[input[ixIn++] - '\uFF61'];
							}
						}
					}
					else {
						// 半濁点(パ～ポ)
						if( input[ixIn+1] == 'ﾟ' ||
								input[ixIn+1] == '\u309A' ||
								input[ixIn+1] == '゜' ) {
							if( input[ixIn] >= 'ﾊ' &&
									input[ixIn] <= 'ﾎ' ) {
								output[ixOut] = ZEN_KANA[input[ixIn] - '\uFF61'];
								output[ixOut++]+=2;
								ixIn +=2 ;
							}
							else {
								output[ixOut++] = ZEN_KANA[input[ixIn++] - '\uFF61'];
							}
						}
						else {
							output[ixOut++] = ZEN_KANA[input[ixIn++] - '\uFF61'];
						}
					}
				}
			}
			else {
				output[ixOut++] = input[ixIn++];
			}
		}
		String output_string = new String( output );
		return output_string.substring(0,ixOut);
	}

	/**
	 * テスト用 mainメソッド
	 *
	 * @param	args	変換元文字列
	 */
	public static void main( final String[] args ) {
		System.out.println( KanaFilter.han2zen( args[0] ) );
	}

}
