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

import java.text.Normalizer;

/**
 * TableFilter_BIKOSET は、TableFilter インターフェースを継承した、DBTableModel 処理用の
 * 実装クラスです。
 *
 * ここでは、NAME_JA と、BIKO をそれぞれ最適な値に再設定します。
 * 具体的には、NAME_JA は、最初のスペースか、括弧"(" より前方のみを切り出します。
 * BIKO は、スペース、括弧"(",")" 、カンマ で分割して、コロン(全角なら半角に変換)の
 * ある文字列のみを、スペース区切りに区切りなおします。
 * これらの変換を行うことで、BIKO2CODE を使用して、コードリソースの自動作成が可能になります。
 *
 * パラメータは、tableFilterタグの keys, vals にそれぞれ記述するか、BODY 部にCSS形式で記述します。
 * 【パラメータ】
 *  {
 *       NAME_JA        : NAME_JA ;   カラムリソースのラベルとなる値が設定されているカラム名を指定します。
 *       BIKO           : BIKO    ;   コードリソース作成に使用する備考欄が設定されているカラム名を指定します。
 *  }
 *
 * @og.formSample
 * ●形式：
 *      ① &lt;og:tableFilter classId="BIKOSET" keys="NAME_JA,BIKO"
 *                                              vals="CLM_NAME,COMMENTS" /&gt;
 *
 *      ② &lt;og:tableFilter classId="BIKOSET" &gt;
 *               {
 *                       NAME_JA   : CLM_NAME ;
 *                       BIKO      : COMMENTS ;
 *               }
 *         &lt;/og:tableFilter&gt;
 *
 * @og.rev 6.4.3.3 (2016/03/04) コードリソース作成時の効率化アップのため。
 *
 * @version  0.9.0  2000/10/17
 * @author   Kazuhiko Hasegawa
 * @since    JDK1.8,
 */
public class TableFilter_BIKOSET extends AbstractTableFilter {
	/** このプログラムのVERSION文字列を設定します。	{@value} */
	private static final String VERSION = "6.5.0.1 (2016/10/21)" ;

	/**
	 * デフォルトコンストラクター
	 *
	 * @og.rev 6.4.3.3 (2016/03/04) 新規追加。
	 */
	public TableFilter_BIKOSET() {
		super();
		initSet( "NAME_JA"	, "カラムリソースのラベルとなる値が設定されているカラム名を指定します。"		);
		initSet( "BIKO" 	, "コードリソース作成に使用する備考欄が設定されているカラム名を指定します。"	);
	}

	/**
	 * DBTableModel処理を実行します。
	 *
	 * @og.rev 6.4.3.3 (2016/03/04) 新規追加。
	 * @og.rev 6.5.0.1 (2016/10/21) ErrorMessage をまとめるのと、直接 Throwable を渡します。
	 *
	 * @return 処理結果のDBTableModel
	 */
	public DBTableModel execute() {
		final DBTableModel table = getDBTableModel();
		if( table == null ) { return table; }

		final int nameNo = table.getColumnNo( StringUtil.nval( getValue( "NAME_JA" ), "NAME_JA" ), false );		// 存在しない場合は、-1 を返す。
		final int bikoNo = table.getColumnNo( StringUtil.nval( getValue( "BIKO"    ), "BIKO"    ), false );

		if( nameNo >= 0 && bikoNo >= 0 ) {
			String[] data  = null;
			final int rowCnt = table.getRowCount();
			for( int row=0; row<rowCnt; row++ ) {
				String bkName = null ;
				try {
					data = table.getValues( row );

					bkName = data[nameNo];					// Exception 発生に表示する値

					// 副作用を及ぼします。
					data[nameNo]	= makeName( bkName );
					data[bikoNo]	= makeBiko( data[bikoNo],data[nameNo] );
				}
				catch( final RuntimeException ex ) {
					// 6.5.0.1 (2016/10/21) ErrorMessage をまとめるのと、直接 Throwable を渡します。
					makeErrorMessage( "TableFilter_BIKOSET Error",ErrorMessage.NG )
						.addMessage( row+1,ErrorMessage.NG,"BIKOSET"
							, "NAME_JA=[" + bkName + "]"
							, StringUtil.array2csv( data )
						)
						.addMessage( ex );
				}
			}
		}

		return table;
	}

	/**
	 * ラベルとなる文字列をピックアップして、返します。
	 * 最初のスペースか、括弧"(" より前方のみを切り出します。
	 *
	 * @param	name	カラム名称となる元の値
	 *
	 * @return	切り出したカラム名称
	 */
	private String makeName( final String name ) {
		return name == null ? "" : Normalizer.normalize( name, Normalizer.Form.NFKC ).split( "[\\( ]" )[0];
	}

	/**
	 * 備考となる文字列をピックアップして、返します。
	 * スペース、括弧"(",")" 、カンマ で分割して、コロン(全角なら半角に変換)の
	 * ある文字列のみを、スペース区切りに区切りなおします。
	 *
	 * 備考欄は、カラム名称と同じ場合は、""(ゼロ文字列)を返します。
	 * 先頭が、カラム名称と同じ場合は、先頭部分（同じ文字列部分）は削除します。
	 *
	 * @param	biko	カラム名称となる元の値
	 * @param	name	カラム名称となる元の値
	 *
	 * @return	切り出したカラム名称
	 */
	private String makeBiko( final String biko,final String name ) {
		// 全角の"（" , "）","　","：","，" は、半角に変換されます。
		String rtn = biko == null ? "" : Normalizer.normalize( biko, Normalizer.Form.NFKC );	// 半角英数記号に変換する。

		// 先頭文字列が、name と一致する場合は、一致部分(重複部分)を削除します。
		if( rtn.startsWith( name ) ) {
			rtn = rtn.substring( name.length() );
		}

		// コロンを含む場合は、コードリソースとして分解対象になる。
		if( rtn.contains( ":" ) ) {
			rtn = String.join( " " , rtn.split( "[\\(\\),、 ]" ) );
		}

		return rtn.trim();
	}
}
