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

import java.io.ByteArrayInputStream;
import java.io.StringWriter;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.logical_paradox.phalanx.binding.condition.Condition;
import org.logical_paradox.phalanx.binding.resultset.ResultSet;

/**
 * XMLドキュメントプロセッサ
 * XMLで指定された検索条件を処理して、適切な検索サービスに要求を発行する
 * @author satoshi akabane@logical-paradox.org
 * @version $Revision: 1.10 $
 */
public class DocumentProcessor {
	public static final String PHALANX_JAXB_PACKAGE_NAME = "org.logical_paradox.phalanx.binding";

	/** ロガー */
	private static Log log = LogFactory.getLog(DocumentProcessor.class);

	/** アンマーシャラーその他 */
	private JAXBContext conditionCtx;
	private JAXBContext resultSetCtx;
	private Unmarshaller conditionUnmarshaller;
	private Marshaller resultSetMarshaller;
	private String configDir;

	/**
	 * コンストラクタ
	 * @param dsruri DSRのURI
	 * @param xmlEncoding 検索結果XMLのエンコーディング
	 * @param configDir コンフィグファイルを格納したディレクトリ
	 * @throws RemoteException DSRのスタブが取得できなかった
	 */
	private DocumentProcessor(String dsruri, String xmlEncoding, String configDir) throws Exception {
		/*
		 * アンマーシャラーその他の作成
		 * XML検証機能つきアンマーシャラーを作成する
		 */
		conditionCtx = JAXBContext.newInstance(PHALANX_JAXB_PACKAGE_NAME + ".condition");
		resultSetCtx = JAXBContext.newInstance(PHALANX_JAXB_PACKAGE_NAME + ".resultset");
		conditionUnmarshaller = conditionCtx.createUnmarshaller();
		conditionUnmarshaller.setValidating(true);

		resultSetMarshaller = resultSetCtx.createMarshaller();
		resultSetMarshaller.setProperty(Marshaller.JAXB_ENCODING, xmlEncoding);
		resultSetMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.FALSE);

		this.configDir = configDir;
	}
	/**
	 * ドキュメントプロセッサを作成する
	 * ドキュメントプロセッサのインスタンスは，このメソッドを呼び出すたびに作成される．<br>
	 * ドキュメントプロセッサに関連づけされているルックアップサービスは，既存のものが再利用される．
	 * @param dsruri DSRのURI
	 * @param xmlEncoding 検索結果の出力エンコーディング
	 * @param configDir コンフィグファイルを格納したディレクトリ
	 * @return 生成されたドキュメントプロセッサ
	 * @throws Exception
	 */
	public static DocumentProcessor newInstance(String dsruri, String xmlEncoding, String configDir) throws Exception {
		return new DocumentProcessor(dsruri, xmlEncoding, configDir);
	}
	/**
	 * 検索を実行する
	 * @param query 問い合わせ電文(XML)
	 * @return 結果電文(XML)
	 * @throws JAXBException XMLドキュメントのアンマーシャルに失敗した
	 */
	public String search(String query) throws Exception {
		log.info("***** 問い合わせ電文を処理します: " + query);

		ByteArrayInputStream istream = new ByteArrayInputStream(query.getBytes("ISO-8859-1"));

		// XMLをアンマーシャリング
		Condition condition = (Condition)conditionUnmarshaller.unmarshal(istream);

		// 検索サーバーに問い合わせる
		SearchLogic logic = SearchLogicFactory.getSearchLogic(condition);
		log.info("***** 検索ロジック[" + logic.getLogicIdentifier() + "]が選択されました");

		// 検索
		ResultSet searchResult = logic.search(condition, configDir);

		// 検索結果をXMLに変換して返す
		StringWriter buffer = new StringWriter();
		resultSetMarshaller.marshal(searchResult, buffer);

		log.info("***** 検索結果を出力します: " + buffer.toString());

		return buffer.toString();
	}
}
