/*
 * 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.hayabusa.taglib;

import org.opengion.hayabusa.common.HybsSystemException;

import static org.opengion.fukurou.util.StringUtil.nval ;
import org.opengion.fukurou.util.StringUtil;
import org.opengion.fukurou.process.HybsProcess;
import org.opengion.fukurou.process.Process_DBParam;

import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.io.IOException;

/**
 * MainProcess で実行される Processクラスを構築します。
 *
 * 親クラス(Process)は、org.opengion.fukurou.process パッケージの HybsProcess
 * インターフェースを実装したクラスの、Process_****.java の **** 部分を指定します。
 * 共通的な パラメータは、このTagクラスに実装しますが、それぞれ、個別に必要な
 * パラメータは、ParamTag を使用して指定します。
 * このタグは、MainProcess タグの内部にのみ、記述可能です。
 *
 * @og.formSample
 * ●形式：&lt;og:process processID="ZZZ" &gt;
 *             &lt;og:param key="AAA" value="111" /&gt;
 *         &lt;/og:process &gt;
 * ●body：あり(param)
 *
 * ●Tag定義：
 *   &lt;og:process
 *       processID        ○【TAG】リクエスト情報 に登録するキーをセットします。(必須)
 *       debug              【TAG】デバッグ情報を出力するかどうか[true/false]を指定します(初期値:false)
 *   &gt;   ... Body ...
 *   &lt;/og:process&gt;
 *
 * ●使用例
 *     一般的な変数の渡し方
 *   &lt;og:mainProcess &gt;
 *     &lt;og:process processID="DBReader" &gt;
 *        &lt;og:param key="dbid" value="FROM" /&gt;
 *        &lt;og:param key="sql"  value="select * from GE02" /&gt;
 *     &lt;/og:process &gt;
 *     &lt;og:process processID="DBWriter" &gt;
 *        &lt;og:param key="dbid"  value="TO" /&gt;
 *        &lt;og:param key="table" value="GE02" /&gt;
 *     &lt;/og:process &gt;
 *   &lt;/og:mainProcess &gt;
 *
 *     BODY 部に記述した変数の渡し方
 *     &lt;og:process processID="DBReader" &gt;
 *        &lt;og:param key="SQL" &gt;
 *              SELECT COUNT(*) FROM GEA03
 *              WHERE SYSTEM_ID=[SYSTEM_ID]
 *              AND   CLM=[CLM]
 *              AND   FGJ = '1'
 *        &lt;/og:param&gt;
 *     &lt;/og:process &gt;
 *
 * @og.group リアルバッチ系
 *
 * @version  4.0
 * @author	 Kazuhiko Hasegawa
 * @since    JDK5.0,
 */
public class ProcessTag extends CommonTagSupport {
	//* このプログラムのVERSION文字列を設定します。	{@value} */
	private static final String VERSION = "4.0.0 (2005/08/31)" ;

	private static final long serialVersionUID = 4000 ;	// 4.0.0 (2005/01/31)

	private static final String PRCS = "org.opengion.fukurou.process.Process_" ;

	private String		processID	= null;
	private transient HybsProcess	process		= null;

	/**
	 * Taglibの開始タグが見つかったときに処理する doStartTag() を オーバーライドします。
	 *
	 * @og.rev 4.3.1.1 (2008/09/04) DBParam 使用時は、専用の初期化メソッドを呼ぶ
	 *
	 * @return	後続処理の指示( EVAL_BODY_BUFFERED )
	 */
	@Override
	public int doStartTag() {
//		process = (HybsProcess)StringUtil.newInstance( PRCS + processID );
//		if( process == null ) {
//			String errMsg = "<b>指定の processID を持つ HybsProcess が見つかりません。</b>"
//								+ "processID=" + processID ;
//			throw new HybsSystemException( errMsg );
//		}

		MainProcessTag mainProcess = (MainProcessTag)findAncestorWithClass( this,MainProcessTag.class );
		if( mainProcess == null ) {
			String errMsg = "<b>このタグは、MainProcessTagの内側(要素)に記述してください。</b>"
								+ "processID=" + processID ;
			throw new HybsSystemException( errMsg );
		}

	 	// 4.3.1.1 (2008/09/04) DBParam 使用時は、専用の初期化メソッドを呼ぶ
		if( "DBParam".equals( processID ) ) {
			process = new Process_DBParam();
			((Process_DBParam)process).setAppInfo( getApplicationInfo() );
		}
		else {
			process = (HybsProcess)StringUtil.newInstance( PRCS + processID );
		}

		mainProcess.addProcess( process );

		return ( EVAL_BODY_BUFFERED );		// Body を評価する
	}

	/**
	 * タグリブオブジェクトをリリースします。
	 * キャッシュされて再利用されるので、フィールドの初期設定を行います。
	 *
	 */
	@Override
	protected void release2() {
		super.release2();
		processID	= null;
		process		= null;
	}

	/**
	 * 【TAG】リクエスト情報 に登録するキーをセットします。
	 *
	 * @og.tag
	 * processID は、org.opengion.fukurou.process.HybsProcess インターフェースを実装した
	 * Process_**** クラスの **** を与えます。
	 * これらは、HybsProcess インターフェースを継承したサブクラスである必要があります。
	 * 標準で、org.opengion.fukurou.process 以下の Process_**** クラスが、Process_**** 宣言 と
	 * して、定義されています。
	 * 属性クラス定義の {@link org.opengion.fukurou.process.HybsProcess HybsProcess} を参照願います。
	 *
	 * @param	pid リクエスト情報に登録するキー
	 * @see		org.opengion.fukurou.process.HybsProcess  HybsProcessのサブクラス
	 */
	public void setProcessID( final String pid ) {
		processID = nval( getRequestParameter( pid ),processID ) ;
	}

	/**
	 * 親クラスに登録するキーをセットします。
	 *
	 * @param	key		登録するキー
	 * @param	value	登録する値
	 */
	protected void addParam( final String key,final String value ) {
		process.putArgument( key,value );
	}

	/**
	 * シリアライズ用のカスタムシリアライズ書き込みメソッド
	 *
	 * @og.rev 4.0.0 (2006/09/31) 新規追加
	 * @serialData
	 *
	 * @param	strm	ObjectOutputStreamオブジェクト
	 */
	private void writeObject( final ObjectOutputStream strm ) throws IOException {
		strm.defaultWriteObject();
	}

	/**
	 * シリアライズ用のカスタムシリアライズ読み込みメソッド
	 *
	 * ここでは、transient 宣言された内部変数の内、初期化が必要なフィールドのみ設定します。
	 *
	 * @og.rev 4.0.0 (2006/09/31) 新規追加
	 * @serialData
	 *
	 * @param	strm	ObjectInputStreamオブジェクト
	 * @see #release2()
	 */
	private void readObject( final ObjectInputStream strm ) throws IOException , ClassNotFoundException {
		strm.defaultReadObject();
	}

	/**
	 * このオブジェクトの文字列表現を返します。
	 * 基本的にデバッグ目的に使用します。
	 *
	 * @return このクラスの文字列表現
	 */
	@Override
	public String toString() {
		return org.opengion.fukurou.util.ToString.title( this.getClass().getName() )
				.println( "VERSION"				,VERSION			)
				.println( "processID"			,processID			)
				.fixForm().toString() ;
	}
}
