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

import java.util.Map;
import java.util.List;

import org.opengion.fukurou.system.HybsConst ;		// 6.1.0.0 (2014/12/26)
import org.opengion.fukurou.util.FileInfo;			// 6.2.0.0 (2015/02/27)
import org.opengion.fukurou.system.ThrowUtil;							// 6.4.2.0 (2016/01/29)
import org.opengion.fukurou.xml.JspParserFilter;
import org.opengion.fukurou.xml.OGDocument;
import org.opengion.fukurou.xml.OGElement;
import org.opengion.fukurou.xml.OGNode;

/**
 * コンストラクタに引数で与えられたマスタデータ情報を元に、特定のJSPタグ情報を生成する基底クラス。
 * マスタデータ情報はGF92のNMSYORIカラムの種別毎にJspConvertEntityオブジェクトに事前に準備する必要がある。
 *
 * 例)
 * JspConvertEntity e = new JspConvertEntity("RESULT");
 * e.setTableName("GF92");
 * e.setColumnName("NMSYORI");
 *
 *
 * 継承先のクラスのexecuteメソッドでは、引数のマスタデータ情報からJSPタグの文字列を生成する処理を実装します。
 *
 * @author Takeshi.Takada
 *
 */
public abstract class AbstractJspCreate implements JspParserFilter {
	/** タブを定数化しておきます。 */
	public static final String T1 = "\t" ;				// 5.6.4.4 (2013/05/31) タブを定数化しておきます。
	public static final String T2 = "\t\t" ;			// 5.6.4.4 (2013/05/31) タブを定数化しておきます。
	public static final String T3 = "\t\t\t" ;			// 5.6.4.4 (2013/05/31) タブを定数化しておきます。

	/** システムの改行コードを設定します。*/
	protected static final String CR		 = HybsConst.CR;			// 6.1.0.0 (2014/12/26) refactoring
	/** StringBilderなどの初期値を設定します。	{@value} */
	protected static final int BUFFER_MIDDLE = HybsConst.BUFFER_MIDDLE;	// 6.1.0.0 (2014/12/26) refactoring

	// 5.6.1.2 (2013/02/22) 初期値を設定。NAME は、複数のファイル名をCSV形式で与えられるように想定を変更。
	private final String KEY	;				// 6.3.9.1 (2015/11/27)
	private final String NAMES	;				// 6.3.9.1 (2015/11/27)

	/**
	 * タグ名とファイル名を指定するコンストラクター
	 *
	 * タグ名は、og:XXXX , :XXX , XXX いづれの形式でも可能です。部分一致で判断するので、
	 * og固定にしないのであれば、:XXX 形式で指定するのが良いと思います。
	 * ファイル名(names)は、拡張子なしのファイル名(index,query,result,・・・)などになります。
	 * 先に指定しているファイル名と部分一致(大文字小文字は区別)するかどうかで判定します。
	 *
	 * @og.rev 6.3.9.1 (2015/11/27) コンストラクタを用意して、KEY,NAME をセットするように変更します。
	 *
	 * @param	key		タグ名の指定(og:XXXX , :XXX , XXX いづれの形式でも可)
	 * @param	names	処理対象のファイル名(複数のファイル名をCSV形式で指定可能)
	 */
	protected AbstractJspCreate( final String key , final String names ) {
		KEY   = key;
		NAMES = names;
	}

	/**
	 * ファイル名から、処理対象かどうかを判断します。
	 * ファイル名は、拡張子なしのファイル名(index,query,result,・・・)などになります。
	 * 先に指定しているファイル名と部分一致するかどうかで判定します。
	 *
	 * @og.rev 5.6.1.2 (2013/02/22) NAME は、複数のファイル名をCSV形式で与えられるように変更。
	 *
	 * @param	name	処理対象のファイル名
	 *
	 * @return	処理対象なら true/ そうでなければ、false
	 */
	protected boolean isExecute( final String name ) {
		return NAMES.contains( FileInfo.getNAME( name ) );
	}

	/**
	 * 初期化メソッド
	 *
	 * 内部で使用する JspConvertEntity の List のマップを受け取り、初期化を行います。
	 *
	 * @param	master	JspConvertEntityのリストのマップ
	 */
	protected abstract void init( final Map<String,List<JspConvertEntity>> master );

	/**
	 * JSPに出力するタグの内容を作成します。
	 * 引数より作成前のタグの属性内容を確認するする事が出来ます。
	 *
	 * @og.rev 5.2.1.0 (2010/10/01) メソッドの引数を、OGAttributes から OGElement に変更します。
	 *
	 * @param	ele	エレメントオブジェクト
	 * @param	nameSpace	このドキュメントのnameSpace( og とか mis とか )
	 *
	 * @return	変換された文字列
	 * @throws Throwable 変換時のエラー
	 */
	protected abstract String execute( final OGElement ele , final String nameSpace )  throws Throwable ;

	/**
	 * ドキュメントオブジェクト を変換します。
	 *
	 * 引数に null が設定された場合も、正常に処理を行います。(return null とする)
	 * 後続処理を行いたくない場合にも、null を返します。
	 *
	 * @og.rev 5.2.1.0 (2010/10/01) メソッドの引数を、OGAttributes から OGElement に変更します。
	 * @og.rev 6.4.2.0 (2016/01/29) ex.printStackTrace() を、ThrowUtil#ogStackTrace(Throwable) に置き換え。
	 *
	 * @param	doc	処理を行う ドキュメントオブジェクト
	 *
	 * @return	処理した結果の ドキュメントオブジェクト
	 * @see org.opengion.fukurou.xml.JspParserFilter#filter( OGDocument )
	 */
	@Override
	public OGDocument filter( final OGDocument doc ) {
		if( doc == null ) { return doc; }
		final OGDocument rtndoc = doc;

		final String name = doc.getFilename();
		if( isExecute( name ) && KEY != null ) {
			try {
				final String nameSpace = doc.getNameSpace();
				final String key = (KEY.indexOf( ':' ) == 0 ) ? nameSpace + KEY : KEY ;

				final List<OGElement> list = doc.getElementList( key );
				for( final OGElement ele : list ) {
					final OGNode newNode = new OGNode( execute( ele,nameSpace ) );		// 5.2.1.0 (2010/10/01)
					rtndoc.changeNode( ele,newNode );
				}
			} catch( final Throwable th ) {
				System.err.println( ThrowUtil.ogStackTrace( th ) );				// 6.4.2.0 (2016/01/29)
			}
		}
		return rtndoc;
	}

	/**
	 * 引数のリストを連結文字列で連結した文字列を作成して返します。
	 *
	 * @param	list	処理を行うドキュメントリスト
	 * @param	sep		連結する区切り文字
	 *
	 * @return	連結された文字列
	 * @og.rtnNotNull
	 */
	protected String chainChar( final List<String> list , final String sep ){
		final StringBuilder buf = new StringBuilder( BUFFER_MIDDLE );

		for( final String st : list ) {
			if( buf.length() > 0 ) {
				buf.append( sep ) ;
			}
			buf.append( st ) ;
		}
		return buf.toString();
	}

	/**
	 * 指定のListオブジェクトが null でなく、かつ、空でないか、判定する。
	 *
	 * @og.rev 5.2.1.0 (2010/10/01) 新規追加
	 *
	 * @param	list	、判定するListオブジェクト
	 *
	 * @return	nullでなく、かつ、空でない場合、true
	 */
	protected boolean isNotEmpty( final List<JspConvertEntity> list ) {
		return list != null && !list.isEmpty() ;
	}
}
