/*
 * CB3Service.java
 * Copyright (C) 2008 Cyber Beans Corporation. All rights reserved.
 */
package jp.co.cybec.cb3.container.service;

import jp.co.cybec.cb3.accessor.DataAccessContext;
import jp.co.cybec.cb3.accessor.DataAccessContextLifeCycle;
import jp.co.cybec.cb3.exception.ServiceException;
import jp.co.cybec.cb3.exception.ServiceExecutionException;
import jp.co.cybec.cb3.session.RuntimeParameters;
import jp.co.cybec.cb3.session.ServiceParameters;
import jp.co.cybec.cb3.util.logging.ErrorCodeConstant;
import jp.co.cybec.cb3.util.logging.LogMessageConstant;
import jp.co.cybec.cb3.util.logging.LogMessageFactory;

/**
 * サービス基底クラス。<br>
 * サービスのテンプレートを提供します。
 * サービスクラス作成時は、このクラスを継承します。
 * @author Naoko Sugimoto
 */
public abstract class CB3Service implements Service {

	/** データアクセスコンテキスト */
	private DataAccessContext dataAccessContext = null;

	/** メッセージ */
	private static final LogMessageFactory MESSAGE = new LogMessageFactory(
			LogMessageConstant.CB3_MESSAGE_FILENAME);

	/**
	 * データアクセスコンテキストを設定します。
	 * @param dataAccessContext データアクセスコンテキスト
	 */
	public void setDataAccessContext(DataAccessContext dataAccessContext) {
		this.dataAccessContext = dataAccessContext;
	}

	/**
	 * データアクセスコンテキストを返します。
	 * @return データアクセスコンテキスト
	 */
	public DataAccessContext getDataAccessContext() {
		return dataAccessContext;
	}

	/**
	 * サービスを実行します。
	 * @param serviceParameters サービスパラメータ
	 * @param runtimeParameters 起動パラメータ
	 * @return 実行結果
	 */
	public int callService(
			ServiceParameters serviceParameters, RuntimeParameters runtimeParameters) {
		try {
			// 業務処理を実行する。
			return doService(serviceParameters, runtimeParameters);
		} catch (Exception e) {
			throw new ServiceExecutionException(MESSAGE.getErrorMessage(
					ErrorCodeConstant.CONTAINER_SERVICE_001,
					LogMessageConstant.CB3_CONTAINER_SERVICE_001), e);
		} finally {
			try {
				// データアクセスコンテキストの終了処理。
				if (dataAccessContext != null) {
					((DataAccessContextLifeCycle)getDataAccessContext()).release();
				}
			} catch (Exception e) {
				throw new ServiceExecutionException(MESSAGE.getErrorMessage(
						ErrorCodeConstant.CONTAINER_SERVICE_002,
						LogMessageConstant.CB3_CONTAINER_SERVICE_002), e);
			}
		}
	}

	/**
	 * 業務処理を記述するメソッドです。<br>
	 * サービスクラスでは、このメソッドをオーバーライドし、業務処理を記述します。<br>
	 * このメソッドには、{@link ServiceParameters}、{@link RuntimeParameters}が引数として渡されます。<br>
	 * <br>
	 * <strong>・ServiceParametersの使用方法</strong><br>
	 * ServiceParametersは、サービス間のパラメータ受け渡しに使用できます。<br>
	 * ServiceParametersはジョブ内で１つであり、あるサービス内でセットしたパラメータは、
	 * 他のサービスに引数として渡されたServiceParametersから取得できます。<br>
	 * {@link ServiceParameters#put(String, Serializable)}に指定するサービスパラメータキーは
	 * ジョブ内で一意である必要があります。<br>
	 * <br>
	 * 通常、{@link ServiceParameters#put(String, Serializable)}の引数に
	 * レコード単位のデータをセットすることは想定されていません。<br>
	 * <br>
	 * <table>
	 * <tr><td></td><td>想定されない使用例：</td></tr>
	 * <tr><td></td><td>サービスパラメータキー = ユーザID（"0001"など）</td></tr>
	 * <tr><td></td><td>サービスパラメータ = ユーザ名（"Naoko Sugimoto"など）</td></tr>
	 * </table>
	 * <br>
	 * ジョブ内で一意性を持てる単位でサービスパラメータキーを定義してください。<br>
	 * <br>
	 * <table>
	 * <tr><td></td><td>使用例：</td></tr>
	 * <tr><td></td><td>サービスパラメータキー = テーブル名</td></tr>
	 * <tr><td></td><td>サービスパラメータ = テーブルを表現するオブジェクト</td></tr>
	 * </table>
	 * <br>
	 * <strong>・RuntimeParametersの使用方法</strong><br>
	 * RuntimeParametersには、アプリケーション起動時に渡された引数が格納されています。<br>
	 * <br>
	 * <pre>
	 * 例：コンソール>java (略) xxx.ServiceProviderImpl -ServiceName sample -AppParams key1=value1 key2=value2 ...
	 * </pre>
	 * 起動時に上記のような引数が指定された場合、-AppParams以降がRuntimeParametersに格納され、
	 * {@link RuntimeParameters#get(String)}を使用して取得することができます。
	 * <pre>
	 * runtimeParameters.get("key1") → "value1"
	 * runtimeParameters.get("key2") → "value2"
	 *  …
	 * </pre>
	 *
	 * @param serviceParameters サービスパラメータ
	 * @param runtimeParameters 起動パラメータ
	 * @return 実行結果
	 * @throws ServiceException 業務処理で何らかの例外が発生した場合。
	 */
	protected abstract int doService(
			ServiceParameters serviceParameters, RuntimeParameters runtimeParameters) throws ServiceException;
}
