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

import org.opengion.hayabusa.db.AbstractTableFilter;
import org.opengion.hayabusa.db.DBTableModel;

import org.opengion.fukurou.util.ErrorMessage;
import org.opengion.fukurou.util.StringUtil;

/**
 * TableFilter_KBCLM は、TableFilter インターフェースを継承した、DBTableModel 処理用の
 * 実装クラスです。
 *
 * ここでは、キーは、GE18(DB定義書管理テーブル)のカラムを元に、ｶﾗﾑ区分(KBCLM)を設定します。
 * SELECTするテーブルもカラムも固定です。設定するカラムは、KBCLM 固定です。
 * 最低限必要なのは、CLM,UK,LUK,IXA,IXB,IXC,IXD,IXE,IXF,IXG,IXH,IXI,IXJ,IXK,NOT_NULL と KBCLM です。
 * 唯一の引数は、共通カラムとして指定するCSV形式のカラム名です。keys="COM_CLMS" に、設定します。
 *
 * 具体的には、KBCLM に設定する値は、下記のとおりです。
 *
 * KBCLM
 * 0:初期(未)  区分未設定の初期状態です
 * 1:UK  (◎)  物理ユニークカラムです
 * 2:LUK (〇)  論理ユニークカラムです
 * 3:IDX (+)   インデックスカラムです
 * 4:NN  (*)   Not Nullカラムです
 * 5:一般(_)   ＤＢ関連図では省略可能です
 * 6:除外(-)   リソース反映除外カラムです
 * 7:共通(C)   全テーブル共通属性です
 * 8:有閑(Y)   存在しますが未使用カラムです
 * 9:削除(X)   実態は削除済みです
 * 
 * 設定する値の優先順位は、7:共通,1:UK,2:LUK,3:IDX,4:NN になります。
 *
 * パラメータは、tableFilterタグの keys, vals にそれぞれ記述するか、BODY 部にCSS形式で記述します。
 * 【パラメータ】
 *  {
 *       COM_CLMS   : {&#064;COM_CLMS}  ; 共通カラムとして指定するCSV形式のカラム名
 *  }
 *
 * @og.formSample
 * ●形式：
 *      ① &lt;og:tableFilter classId="KBCLM" keys="COM_CLMS" vals="{&#064;COM_CLMS}" /&gt;
 *
 *      ② &lt;og:tableFilter classId="KBCLM" &gt;
 *               {
 *                   COM_CLMS   : {&#064;COM_CLMS}   ;
 *               }
 *         &lt;/og:tableFilter&gt;
 *
 * @og.rev 5.7.6.2 (2014/05/16) 新規追加
 *
 * @version  6.0  2014/05/02
 * @author   Kazuhiko Hasegawa
 * @since    JDK1.7,
 */
public class TableFilter_KBCLM extends AbstractTableFilter {
	/** このプログラムのVERSION文字列を設定します。	{@value} */
	private static final String VERSION = "6.5.0.1 (2016/10/21)" ;

	/**
	 * デフォルトコンストラクター
	 *
	 * @og.rev 6.4.1.1 (2016/01/16) keysMap を、サブクラスから設定させるように変更。
	 */
	public TableFilter_KBCLM() {
		super();
		initSet( "COM_CLMS"		, "共通カラムとして指定するCSV形式のカラム名"	);
	}

	/**
	 * DBTableModel処理を実行します。
	 *
	 * @og.rev 6.5.0.1 (2016/10/21) ErrorMessage をまとめるのと、直接 Throwable を渡します。
	 *
	 * @return 処理結果のDBTableModel
	 */
	public DBTableModel execute() {
		final DBTableModel table = getDBTableModel();		// 5.5.2.6 (2012/05/25) インターフェースにgetterメソッド追加

		final String comClms = StringUtil.nval( getValue( "COM_CLMS" ) ,null );

		final int clmNo  = table.getColumnNo( "CLM",false );		// 存在しない場合は、-1 を返す。
		final int ukNo   = table.getColumnNo( "UK" ,false );
		final int lukNo  = table.getColumnNo( "LUK",false );
		final int ixaNo  = table.getColumnNo( "IXA",false );
		final int ixbNo  = table.getColumnNo( "IXB",false );
		final int ixcNo  = table.getColumnNo( "IXC",false );
		final int ixdNo  = table.getColumnNo( "IXD",false );
		final int ixeNo  = table.getColumnNo( "IXE",false );
		final int ixfNo  = table.getColumnNo( "IXF",false );
		final int ixgNo  = table.getColumnNo( "IXG",false );
		final int ixhNo  = table.getColumnNo( "IXH",false );
		final int ixiNo  = table.getColumnNo( "IXI",false );
		final int ixjNo  = table.getColumnNo( "IXJ",false );
		final int ixkNo  = table.getColumnNo( "IXK",false );
		final int nnNo   = table.getColumnNo( "NOT_NULL",false );

		final int kbclmNo = table.getColumnNo( "KBCLM",false );	// 計算結果の値を書き出すカラム

		if( kbclmNo >= 0 ) {
			String[] data  = null;
			final int rowCnt = table.getRowCount();
			// 6.3.9.1 (2015/11/27) Found 'DD'-anomaly for variable(PMD)
			// KBCLMに変更がなければ、レコードを削除します。よって、逆順にチェックします。
			for( int row=rowCnt-1; row>=0; row-- ) {
				try {
					data   = table.getValues( row );
					// 6.3.9.1 (2015/11/27) Found 'DD'-anomaly for variable(PMD)
					final boolean isUK   = ukNo  >= 0 && data[ukNo]  != null && data[ukNo].trim().length()  > 0 ;
					final boolean isLUK  = lukNo >= 0 && data[lukNo] != null && data[lukNo].trim().length() > 0 ;
					final boolean isNN   = nnNo  >= 0 && data[nnNo]  != null && data[nnNo].trim().length()  > 0 ;
					final boolean isCOM  = clmNo >= 0 && data[clmNo] != null && comClms != null
								&& comClms.indexOf( "'" + data[clmNo].trim() + "'" ) >= 0 ;
					final boolean isIDX  = ixaNo >= 0 && data[ixaNo] != null && data[ixaNo].trim().length() > 0
										|| ixbNo >= 0 && data[ixbNo] != null && data[ixbNo].trim().length() > 0
										|| ixcNo >= 0 && data[ixcNo] != null && data[ixcNo].trim().length() > 0
										|| ixdNo >= 0 && data[ixdNo] != null && data[ixdNo].trim().length() > 0
										|| ixeNo >= 0 && data[ixeNo] != null && data[ixeNo].trim().length() > 0
										|| ixfNo >= 0 && data[ixfNo] != null && data[ixfNo].trim().length() > 0
										|| ixgNo >= 0 && data[ixgNo] != null && data[ixgNo].trim().length() > 0
										|| ixhNo >= 0 && data[ixhNo] != null && data[ixhNo].trim().length() > 0
										|| ixiNo >= 0 && data[ixiNo] != null && data[ixiNo].trim().length() > 0
										|| ixjNo >= 0 && data[ixjNo] != null && data[ixjNo].trim().length() > 0
										|| ixkNo >= 0 && data[ixkNo] != null && data[ixkNo].trim().length() > 0 ;

					// KBCLM の値をチェックします。
					final String kbclm =makeKBCLM( isUK , isLUK , isIDX , isNN , isCOM , data[kbclmNo] ) ;
					// 6.4.1.1 (2016/01/16) PMD refactoring. Avoid if (x != y) ..; else ..;
					if( kbclm == null ) {
						table.removeValue( row );		// kbclm に変更がなければ、null なので、レコード削除
					}
					else {
						data[kbclmNo] = kbclm ;			// 値の書き戻し
					}
				}
				catch( final RuntimeException ex ) {
					// 6.5.0.1 (2016/10/21) ErrorMessage をまとめるのと、直接 Throwable を渡します。
					makeErrorMessage( "TableFilter_KBCLM Error",ErrorMessage.NG )
						.addMessage( row+1,ErrorMessage.NG,"KBCLM"
							, "comClms=[" + comClms + "]"
							, StringUtil.array2csv( data )
						)
						.addMessage( ex );
				}
			}
		}
		return table;
	}

	/**
	 * UK,LUK,ｲﾝﾃﾞｯｸｽ,NotNull,共通カラム から、ｶﾗﾑ区分(KBCLM) を作成します。
	 * KBCLM に変更がなければ、null を返します。
	 *
	 * 0:初期(未)  区分未設定の初期状態です			(ここでは設定されません。)
	 * 1:UK  (◎)  物理ユニークカラムです			isUK=true の場合の第2優先
	 * 2:LUK (〇)  論理ユニークカラムです			isLUK=true の場合の第3優先
	 * 3:IDX (+)   インデックスカラムです			isIDX=true の場合の第4優先
	 * 4:NN  (*)   Not Nullカラムです				isNN=true の場合の第5優先
	 * 5:一般(_)   ＤＢ関連図では省略可能です		既存が 0,1,2,3,4,7 で該当しない場合、5:一般 に設定します。
	 * 6:除外(-)   リソース反映除外カラムです		(ここでは設定されません。)
	 * 7:共通(C)   全テーブル共通属性です			isCOM=true の場合の第1優先
	 * 8:有閑(Y)   存在しますが未使用カラムです		(ここでは設定されません。)
	 * 9:削除(X)   実態は削除済みです				(ここでは設定されません。)
	 *
	 * @og.rev 5.7.6.2 (2014/05/16) 新規追加
	 *
	 * @param  isUK 物理ユニークキーかどうか(true/false)
	 * @param  isLUK 論理ユニークキーかどうか(true/false)
	 * @param  isIDX インデックスカラムかどうか(true/false)
	 * @param  isNN  NOT NULL制約が設定されているかどうか(true/false)
	 * @param  isCOM 共通カラム名と一致しているかどうか(true/false)
	 * @param  kbclm 現在のｶﾗﾑ区分(KBCLM)の値
	 * @return 対応する ｶﾗﾑ区分(KBCLM)の値(変更がなければ、nullを返す)
	 */
	private String makeKBCLM( final boolean isUK , final boolean isLUK , final boolean isIDX
							 , final boolean isNN , final boolean isCOM , final String kbclm ) {

		// 6.3.9.1 (2015/11/27) Found 'DD'-anomaly for variable(PMD)
		final String rtn;

		if(     isCOM )		{ rtn = "7"; }
		else if( isUK )		{ rtn = "1"; }
		else if( isLUK )	{ rtn = "2"; }
		else if( isIDX )	{ rtn = "3"; }
		else if( isNN  )	{ rtn = "4"; }
		else if( "0,1,2,3,4,7".contains( kbclm ) ) { rtn = "5"; }	// 5:一般 に設定
		else				{ rtn = null; }

		return rtn != null && rtn.equals( kbclm ) ? null : rtn ;	// 同じ値の場合は、null に戻す。
	}
}
