/**
 * LOGICAL-PARADOX.ORG
 * Copyright (C)2004 satoshi akabane(akabane@logical-paradox.org)
 *
 */
package org.logical_paradox.kinako.logic;

import java.io.InputStream;
import java.io.StringWriter;
import java.math.BigInteger;
import java.util.Properties;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.logical_paradox.common.net.HttpRequestSender;
import org.logical_paradox.kinako.constant.ApConstant;
import org.logical_paradox.kinako.logic.parser.SearchConditionParser;
import org.logical_paradox.kinako.object.FailureTransitionException;
import org.logical_paradox.kinako.object.SearchCondition;
import org.logical_paradox.phalanx.binding.condition.Condition;

/**
 * 検索ロジック
 * 画面から入力された検索キーワードを，検索サーバーに送信し，結果を受信する．<br>
 * 検索サーバーはweb serviceで公開されており，データの送受信処理はSOAPにて行われる．
 * 
 * @author satoshi akabane@logical-paradox.org
 * @version $Revision: 1.11 $
 */
public class KinakoSearchLogic {
	/** ロガー */
	private static final Log log = LogFactory.getLog(KinakoSearchLogic.class);

	private final Marshaller marshaller;
	private final String xmlEncoding;

	/**
	 * コンストラクタ
	 * @param encoding XMLのエンコーディング
	 */
	public KinakoSearchLogic(String encoding) throws JAXBException {
		JAXBContext conditionCtx = JAXBContext.newInstance(ApConstant.PHALANX_JAXB_PACKAGE_NAME + ".condition");
		xmlEncoding = encoding;
		marshaller = conditionCtx.createMarshaller();
		marshaller.setProperty(Marshaller.JAXB_ENCODING, xmlEncoding);
		marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.FALSE);
	}
	/**
	 * 検索処理を実行する
	 * @param phalanxのURL
	 * @param keyword キーワード(スペース区切り)
	 * @param encoding キーワード文字列のエンコーディング
	 * @return 検索結果のXML
	 */
	public InputStream search(String url, SearchCondition searchCondition, String encoding) throws Exception {
		log.info("***** 検索処理を開始します");
		// 入力された検索条件をオブジェクトのツリー構造に変換する
		// 検索キーワードを変換しておく
		Condition condition = SearchConditionParser.getParser().parse(searchCondition.getKeyword());
		if(condition == null) {
			log.fatal("***** 生成された検索条件(condition)がnullです");
			throw new FailureTransitionException();
		}
		condition.setMethod("ngramFtsSearchLogic");
		condition.setStartindex(BigInteger.valueOf(searchCondition.getStartIndex()));
		condition.setEndindex(BigInteger.valueOf(searchCondition.getEndIndex()));

		StringWriter buffer = new StringWriter();
		marshaller.marshal(condition, buffer);

		// XMLを所定の形式でエンコードする
		String xml = buffer.toString();

		log.info("***** 検索条件をXMLに変換しました: " + xml);

		// 全文検索システムに問い合わせる
		Properties postdata = new Properties();
		postdata.setProperty("req", xml);
		InputStream response = HttpRequestSender.post(url, HttpRequestSender.urlEncodeAll(postdata, encoding));

		return response;
	}
}
