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

import org.opengion.fukurou.util.ErrorMessage;
import org.opengion.fukurou.model.DataModel;				// 6.7.9.1 (2017/05/19)
import org.opengion.fukurou.system.OgRuntimeException ;		// 6.4.2.0 (2016/01/29)

/**
 * 配列型ﾃｰﾌﾞﾙﾓﾃﾞﾙをﾒｲﾝｶｰｿﾙとした業務ﾛｼﾞｯｸの構造を定義します｡
 *
 * 配列型ﾃｰﾌﾞﾙﾓﾃﾞﾙについては､setTable( ArrayTableModel )によりｾｯﾄします｡
 * 配列型ﾃｰﾌﾞﾙﾓﾃﾞﾙが定義されていない場合､ｴﾗｰとなります｡
 *
 * このｸﾗｽでは､以下に示すﾒｿｯﾄﾞが呼び出されるﾀｲﾐﾝｸﾞのみを定義しています｡
 * ﾒｿｯﾄﾞの中身については､ｻﾌﾞｸﾗｽでｵｰﾊﾞｰﾗｲﾄﾞし実装して下さい｡
 *
 * 処理が途中で中断される条件は､以下の3つです｡
 * ①各ﾒｿｯﾄﾞの戻り値がfalseの場合
 * ②ﾁｪｯｸﾒｿｯﾄﾞ(chk***())が全ての行で実行された後､ｴﾗｰﾒｯｾｰｼﾞに"ｴﾗｰ"が含まれている場合
 * ③実行時ｴﾗｰが発生した場合
 *
 *  fstchk()		  変更区分に関わらず   処理を始める前に呼び出し
 *    8.0.2.0 (2021/11/30) 行単位ﾛｼﾞｯｸﾁｪｯｸは廃止
 * <del>useLoop == true
 *        befchk( int row ) 変更区分に関わらず   各行について呼び出し(insert,modify,deleteの前に呼び出し)
 *        inschk( int row ) 変更区分が"A"の場合 各行について呼び出し
 *        modchk( int row ) 変更区分が"C"の場合 各行について呼び出し
 *        delchk( int row ) 変更区分が"D"の場合 各行について呼び出し
 *        allchk( int row ) 変更区分に関わらず   各行について呼び出し(insert,modify,deleteの後に呼び出し)
 * </del>
 *  first()			  変更区分に関わらず   最初の行でのみ呼び出し
 *    useLoop == true
 *      befall( int row ) 変更区分に関わらず   各行について呼び出し(insert,modify,deleteの前に呼び出し)
 *      insert( int row ) 変更区分が"A"の場合 各行について呼び出し
 *      modify( int row ) 変更区分が"C"の場合 各行について呼び出し
 *      delete( int row ) 変更区分が"D"の場合 各行について呼び出し
 *      allrow( int row ) 変更区分に関わらず   各行について呼び出し(insert,modify,deleteの後に呼び出し)
 *  last()            変更区分に関わらず   最後の行でのみ呼び出し
 *
 * ※ ｲﾝﾃﾞｯｸｽ(row)とは､このArrayTableModel に持つ vals 配列の行のｲﾝﾃﾞｯｸｽです｡
 * よって､ｵﾘｼﾞﾅﾙのDBTableModelの行番号ではありません｡
 *
 * 8.0.2.0 (2021/11/30) 行単位ﾛｼﾞｯｸﾁｪｯｸは廃止｡
 *  befchk,inschk,modchk,delchk,allchk
 *  必要であれば､fstchk() で､DataModel を取得して処理してください｡
 *
 * @og.rev 5.1.1.0 (2009/12/01) 新規作成
 * @og.group 業務ﾛｼﾞｯｸ
 *
 * @version 5.0
 * @author Hiroki Nakamura
 * @since JDK1.6,
 */
public class BizLogic_TABLE extends AbstractBizLogic {
	private boolean useLoop	= true;				// 6.8.5.0 (2018/01/09) ﾙｰﾌﾟを回すかどうかを引数で指定します｡

	/**
	 * ﾃﾞﾌｫﾙﾄｺﾝｽﾄﾗｸﾀｰ
	 *
	 * @og.rev 6.4.2.0 (2016/01/29) PMD refactoring. Each class should declare at least one constructor.
	 */
	public BizLogic_TABLE() { super(); }		// これも､自動的に呼ばれるが､空のﾒｿｯﾄﾞを作成すると警告されるので､明示的にしておきます｡

	/**
	 * 処理のﾒｲﾝﾛｼﾞｯｸの前処理を記述します｡
	 * (ここでは何もしません)
	 *
	 * このﾒｿｯﾄﾞ自体は､protected属性であるため､ｻﾌﾞｸﾗｽから直接参照することができます｡
	 * 但し､これは､各業務ﾛｼﾞｯｸで直接参照することを想定したものではなく､BizLogicの
	 * ﾒｲﾝ構造を拡張するｻﾌﾞｸﾗｽを定義する際に使用することを想定しています｡
	 * (この想定がなければ､本来は､package privateにすべきです)
	 * このため､業務ﾛｼﾞｯｸを各実装ｸﾗｽでは直接参照しないで下さい｡
	 */
	@Override
	protected void init() {
		// Document empty method ﾁｪｯｸ対策
	}

	/**
	 * 処理のﾒｲﾝﾛｼﾞｯｸを記述します｡
	 *
	 * このﾒｿｯﾄﾞ自体は､protected属性であるため､ｻﾌﾞｸﾗｽから直接参照することができます｡
	 * 但し､これは､各業務ﾛｼﾞｯｸで直接参照することを想定したものではなく､BizLogicの
	 * ﾒｲﾝ構造を拡張するｻﾌﾞｸﾗｽを定義する際に使用することを想定しています｡
	 * (この想定がなければ､本来は､package privateにすべきです)
	 * このため､業務ﾛｼﾞｯｸを各実装ｸﾗｽでは直接参照しないで下さい｡
	 *
	 * @og.rev 5.1.8.0 (2010/07/01) first,lastは行ﾙｰﾌﾟの中で呼び出し
	 * @og.rev 5.6.7.0 (2013/07/27) Exception を throw するとき､一旦､errMsg 変数にｾｯﾄします｡
	 * @og.rev 6.7.9.1 (2017/05/19) protected ArrayTableModel を､private DataModel に変更します｡
	 * @og.rev 6.8.5.0 (2018/01/09) first(),last() をﾙｰﾌﾟから出して､ﾙｰﾌﾟを回すかどうかを引数で指定します｡
	 * @og.rev 8.0.2.0 (2021/11/30) 行単位ﾛｼﾞｯｸﾁｪｯｸは廃止｡
	 *
	 * @return 処理が正常終了したか
	 */
	@Override
	protected boolean main() {
		final DataModel<String> table = getTable();		// 6.7.9.1 (2017/05/19)

		if( table == null ) {
			// 5.6.7.0 (2013/07/27) Exception を throw するとき､一旦､errMsg 変数にｾｯﾄします｡
			final String errMsg = "配列型ﾃｰﾌﾞﾙﾓﾃﾞﾙがｾｯﾄされていません｡" ;
			throw new OgRuntimeException( errMsg );
		}

		row = 0;
		if( !fstchk() ) { return false; }

//		final int rowLen = table.getRowCount();			// 6.8.5.0 (2018/01/09)

	//	8.0.2.0 (2021/11/30) 行単位ﾛｼﾞｯｸﾁｪｯｸは廃止｡
	//	if( useLoop ) {			// 6.8.5.0 (2018/01/09)
//	//		for( int i=0; i<table.getRowCount(); i++ ) {
		//	for( int i=0; i<rowLen; i++ ) {
		//		if( !befchk( row ) ) { return false; }

		//		final String modType = table.getModifyType( row );

		//		// 6.9.7.0 (2018/05/14) PMD These nested if statements could be combined
		//		if(    "A".equals( modType ) && !inschk( row )
		//			|| "C".equals( modType ) && !modchk( row )
		//			|| "D".equals( modType ) && !delchk( row )
		//			|| !allchk( row ) ) {
		//			return false;
		//		}

//				if( "A".equals( modType ) ) {
//					if( !inschk( row ) ) { return false; }
//				}
//				else if( "C".equals( modType ) ) {
//					if( !modchk( row ) ) { return false; }
//				}
//				else if( "D".equals( modType ) ) {
//					if( !delchk( row ) ) { return false; }
//				}
//
//				if( !allchk( row ) ) { return false; }

		//		row++;
		//	}
	//	}
		if( getKekka() >= ErrorMessage.NG ) { return false; }

	//	row = 0;
		final int rowLen = table.getRowCount();				// 6.8.5.0 (2018/01/09)
		if( rowLen > 0 && !first() ) { return false; }		// 6.8.5.0 (2018/01/09) ﾙｰﾌﾟの外に出します｡

		if( useLoop ) {			// 6.8.5.0 (2018/01/09)
//	//		for( int i=0; i<table.getRowCount(); i++ ) {
			for( int i=0; i<rowLen; i++ ) {
//	//			// 5.1.8.0 (2010/07/01) firstは行ﾙｰﾌﾟの中で呼び出し
//	//			if( row == 0 ) {
//	//				if( !first() ) { return false; }
//	//			}

				if( !befall( row ) ) { return false; }

				final String modType = table.getModifyType( row );

				// 6.9.7.0 (2018/05/14) PMD These nested if statements could be combined
				if(	   "A".equals( modType ) && !insert( row )
					|| "C".equals( modType ) && !modify( row )
					|| "D".equals( modType ) && !delete( row )
					|| !allrow( row ) ) {
					return false;
				}

//				if( !befall( row ) ) { return false; }
//
//				final String modType = table.getModifyType( row );
//				if( "A".equals( modType ) ) {
//					if( !insert( row ) ) { return false; }
//				}
//				else if( "C".equals( modType ) ) {
//					if( !modify( row ) ) { return false; }
//				}
//				else if( "D".equals( modType ) ) {
//					if( !delete( row ) ) { return false; }
//				}
//
//				if( !allrow( row ) ) { return false; }
//
//	//			// 5.1.8.0 (2010/07/01) lastは行ﾙｰﾌﾟの中で呼び出し
//	//			if( row == table.getRowCount() - 1 ) {
//	//				if( !last() ) { return false; }
//	//			}
				row++;
			}
		}

		if( rowLen > 0 ) {		// 6.8.5.0 (2018/01/09) ﾙｰﾌﾟの外に出します｡
			row = rowLen-1;
			if( !last() ) { return false; }
		}

		return true;
	}

	/**
	 * このｸﾗｽは､ﾃｰﾌﾞﾙﾓﾃﾞﾙが外部から指定されている必要があります｡
	 *
	 * このﾒｿｯﾄﾞ自体は､protected属性であるため､ｻﾌﾞｸﾗｽから直接参照することができます｡
	 * 但し､これは､各業務ﾛｼﾞｯｸで直接参照することを想定したものではなく､BizLogicの
	 * ﾒｲﾝ構造を拡張するｻﾌﾞｸﾗｽを定義する際に使用することを想定しています｡
	 * (この想定がなければ､本来は､package privateにすべきです)
	 * このため､業務ﾛｼﾞｯｸを各実装ｸﾗｽでは直接参照しないで下さい｡
	 *
	 * @og.rev 8.0.2.0 (2021/11/30) protected → default 変更(ｻﾌﾞｸﾗｽからのｱｸｾｽはない)
	 *
	 * @return ﾃｰﾌﾞﾙﾓﾃﾞﾙが外部から指定されている必要があるかどうか(常にtrue)
	 * @see AbstractBizLogic#isRequireTable()
	 */
	@Override
//	protected boolean isRequireTable() {
	/* default */ boolean isRequireTable() {
		return true;
	}

	/**
	 * ﾒｲﾝｶｰｿﾙの一番初めで呼ばれるﾁｪｯｸﾛｼﾞｯｸを定義します｡
	 * ここでは何も実装されていません｡
	 *
	 * @return 処理が正常終了したか
	 */
	protected boolean fstchk() {
		return true;
	}

//	/**
//	 * ﾒｲﾝｶｰｿﾙの各行(変更区分の各処理の前)で呼ばれるﾁｪｯｸﾛｼﾞｯｸを定義します｡
//	 * ここでは何も実装されていません｡
//	 *
//	 * @og.rev 8.0.2.0 (2021/11/30) 行単位ﾛｼﾞｯｸﾁｪｯｸは廃止｡
//	 *
//	 * @param row 行番号(ｲﾝﾃﾞｯｸｽ)
//	 *
//	 * @return 処理が正常終了したか
//	 */
//	protected boolean befchk( final int row ) {
//		return true;
//	}

//	/**
//	 * ﾒｲﾝｶｰｿﾙの各行(変更区分の各処理の後)で呼ばれるﾁｪｯｸﾛｼﾞｯｸを定義します｡
//	 * ここでは何も実装されていません｡
//	 *
//	 * @og.rev 8.0.2.0 (2021/11/30) 行単位ﾛｼﾞｯｸﾁｪｯｸは廃止｡
//	 *
//	 * @param row 行番号(ｲﾝﾃﾞｯｸｽ)
//	 *
//	 * @return 処理が正常終了したか
//	 */
//	protected boolean allchk( final int row ) {
//		return true;
//	}

//	/**
//	 * ﾒｲﾝｶｰｿﾙの各行(変更区分="A")で呼ばれるﾁｪｯｸﾛｼﾞｯｸを定義します｡
//	 * ここでは何も実装されていません｡
//	 *
//	 * @og.rev 8.0.2.0 (2021/11/30) 行単位ﾛｼﾞｯｸﾁｪｯｸは廃止｡
//	 *
//	 * @param row 行番号(ｲﾝﾃﾞｯｸｽ)
//	 *
//	 * @return 処理が正常終了したか
//	 */
//	protected boolean inschk( final int row ) {
//		return true;
//	}

//	/**
//	 * ﾒｲﾝｶｰｿﾙの各行(変更区分="C")で呼ばれるﾁｪｯｸﾛｼﾞｯｸを定義します｡
//	 * ここでは何も実装されていません｡
//	 *
//	 * @og.rev 8.0.2.0 (2021/11/30) 行単位ﾛｼﾞｯｸﾁｪｯｸは廃止｡
//	 *
//	 * @param row 行番号(ｲﾝﾃﾞｯｸｽ)
//	 *
//	 * @return 処理が正常終了したか
//	 */
//	protected boolean modchk( final int row ) {
//		return true;
//	}

//	/**
//	 * ﾒｲﾝｶｰｿﾙの各行(変更区分="D")で呼ばれるﾁｪｯｸﾛｼﾞｯｸを定義します｡
//	 * ここでは何も実装されていません｡
//	 *
//	 * @og.rev 8.0.2.0 (2021/11/30) 行単位ﾛｼﾞｯｸﾁｪｯｸは廃止｡
//	 *
//	 * @param row 行番号(ｲﾝﾃﾞｯｸｽ)
//	 *
//	 * @return 処理が正常終了したか
//	 */
//	protected boolean delchk( final int row ) {
//		return true;
//	}

	/**
	 * ﾒｲﾝｶｰｿﾙの一番初めで呼ばれるﾛｼﾞｯｸを定義します｡
	 * ここでは何も実装されていません｡
	 *
	 * @return 処理が正常終了したか
	 */
	protected boolean first() {
		return true;
	}

	/**
	 * ﾒｲﾝｶｰｿﾙの一番最後で呼ばれるﾛｼﾞｯｸを定義します｡
	 * ここでは何も実装されていません｡
	 *
	 * @return 処理が正常終了したか
	 */
	protected boolean last() {
		return true;
	}

	/**
	 * ﾒｲﾝｶｰｿﾙの各行(変更区分の各処理の前)で呼ばれるﾛｼﾞｯｸを定義します｡
	 * ここでは何も実装されていません｡
	 *
	 * @param row 行番号(ｲﾝﾃﾞｯｸｽ)
	 *
	 * @return 処理が正常終了したか
	 */
	protected boolean befall( final int row ) {
		return true;
	}

	/**
	 * ﾒｲﾝｶｰｿﾙの各行(変更区分の各処理の後)で呼ばれるﾛｼﾞｯｸを定義します｡
	 * ここでは何も実装されていません｡
	 *
	 * @param row 行番号(ｲﾝﾃﾞｯｸｽ)
	 *
	 * @return 処理が正常終了したか
	 */
	protected boolean allrow( final int row ) {
		return true;
	}

	/**
	 * ﾒｲﾝｶｰｿﾙの各行(変更区分="A")で呼ばれるﾛｼﾞｯｸを定義します｡
	 * ここでは何も実装されていません｡
	 *
	 * @param row 行番号(ｲﾝﾃﾞｯｸｽ)
	 *
	 * @return 処理が正常終了したか
	 */
	protected boolean insert( final int row ) {
		return true;
	}

	/**
	 * ﾒｲﾝｶｰｿﾙの各行(変更区分="C")で呼ばれるﾛｼﾞｯｸを定義します｡
	 * ここでは何も実装されていません｡
	 *
	 * @param row 行番号(ｲﾝﾃﾞｯｸｽ)
	 *
	 * @return 処理が正常終了したか
	 */
	protected boolean modify( final int row ) {
		return true;
	}

	/**
	 * ﾒｲﾝｶｰｿﾙの各行(変更区分="D")で呼ばれるﾛｼﾞｯｸを定義します｡
	 * ここでは何も実装されていません｡
	 *
	 * @param row 行番号(ｲﾝﾃﾞｯｸｽ)
	 *
	 * @return 処理が正常終了したか
	 */
	protected boolean delete( final int row ) {
		return true;
	}

	/**
	 * ﾙｰﾌﾟを回すかどうかを指定します｡
	 *
	 * ﾙｰﾌﾟ処理を使用しない場合の処理速度向上のためのﾌﾗｸﾞです｡
	 *
	 * ﾙｰﾌﾟ処理とは､引数に row番号を指定する関数です｡
	 * 初期値は､true(ﾙｰﾌﾟを回す) です｡
	 * false を指定すると､それらのﾒｿｯﾄﾞは使用されず､fstchk()､first()､last() のみ呼び出されます｡
	 *
	 * init() と main() は､AbstractBizLogic#exec() から呼ばれるため､通常通り呼び出されます｡
	 *
	 * @og.rev 6.8.5.0 (2018/01/09) ﾙｰﾌﾟを回すかどうかを引数で指定します｡
	 *
	 * @param useLoop ﾙｰﾌﾟを回すかどうか
	 */
	protected final void setUseLoop( final boolean useLoop ) {
		this.useLoop = useLoop;
	}
}
