/*
 * $Id: Parser.java,v 1.7 2006/02/15 16:23:59 rampil Exp $
 * Copyright (c) 2004 LOGICAL-PARADOX.ORG
 */
package org.logical_paradox.koike.core.parser;

import java.util.ArrayList;
import java.util.HashMap;

/**
 * N-gramパーザー
 * 
 * @author satoshi akabane@logical-paradox.org
 * @version $Revision: 1.7 $
 */
public class Parser {
	private int ngramLength;

	/**
	 * コンストラクタ
	 * @param ngram N-gram長
	 */
	public Parser(int ngram) {
		ngramLength = ngram;
	}
	/**
	 * 指定された文字列をN-gram分割する
	 * @param doc 元の文字列
	 * @return n-gram分割された索引語
	 * @throws ParserException 分割処理に失敗した
	 */
	public Term[] parse(String doc) throws ParserException {
		HashMap<String, Term> map = new HashMap<String, Term>();

		int loopCnt = doc.length() - (ngramLength-1);
		if(loopCnt <= 0) {
			throw new ParserException( "与えられた文字列の長さに対してN-gram分割数が大きすぎます" );
		}

		// 指定された文字数で分割する
		for(int cnt = 0; cnt < loopCnt; cnt++) {
			int tokenLength = ngramLength - ((cnt-loopCnt) <= 0 ? 0 : cnt-loopCnt);
			String token = doc.substring(cnt, cnt + tokenLength);

			Term key = (Term)map.get(token);
			if(key == null) {
				key = new Term(token);
			}
			// 索引語を追加する
			key.add(cnt);
			map.put(token, key);

			Thread.yield();
		}

		// ハッシュマップの内容を配列に変換して返す
		ArrayList<Term> list = new ArrayList<Term>();
		for(Term term : map.values()) {
			list.add(term);
		}

		return list.toArray(new Term[0]);
	}
	/**
	 * 文字列をn-gramで分割する
	 * @param doc 元の文字列
	 * @return 指定文字数で分割された断片
	 * @throws ParserException 分割処理に失敗した
	 */
	public String[] split(String doc) throws ParserException {
		int loopCnt = doc.length() - (ngramLength-1);
		if(loopCnt <= 0) {
			throw new ParserException( "与えられた文字列の長さに対してN-gram分割数が大きすぎます" );
		}

		String[] tokens = new String[loopCnt];

		// 指定された文字数で分割する
		for(int cnt = 0; cnt < loopCnt; cnt++) {
			int tokenLength = ngramLength - ((cnt-loopCnt) <= 0 ? 0 : cnt-loopCnt);
			tokens[cnt] = doc.substring(cnt, cnt + tokenLength);
		}

		return tokens;
	}
}
