/*
 * MosP - Mind Open Source Project    http://www.mosp.jp/
 * Copyright (C) MIND Co., Ltd.       http://www.e-mind.co.jp/
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
package jp.mosp.common;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.List;

import javax.naming.NamingException;

import jp.mosp.common.common.BaseAction;
import jp.mosp.common.common.BaseDto;
import jp.mosp.common.common.InstanceFactory;
import jp.mosp.common.common.LogUtility;
import jp.mosp.common.common.MospConst;
import jp.mosp.common.common.MospException;
import jp.mosp.common.common.MospUtility;
import jp.mosp.common.dto.CmAspUserDto;
import jp.mosp.common.dto.CmUserDto;
import jp.mosp.common.dto.HumanBasisDtoInterface;
import jp.mosp.common.dto.MosPConfDto;
import jp.mosp.common.part.BasePart;
import jp.mosp.common.part.BaseStore;
import jp.mosp.common.part.PartInfo;
import jp.mosp.common.part.PartManager;
import jp.mosp.common.part.PartStore;
import jp.mosp.common.utils.CsvUtil;
import jp.mosp.common.utils.DataSourceUtil;
import jp.mosp.common.utils.DateUtil;
import jp.mosp.common.utils.StringUtil;
import jp.mosp.common.utils.VariousUtil;
import jp.mosp.common.vo.ExclusiveVo;

import org.apache.commons.csv.CSVParser;
import org.apache.commons.fileupload.FileItem;

/**
 * MosPのベースとなるActionクラス
 * @author yoshida
 *	@version	1.4
 */
public abstract class MosPAction extends BaseAction {
	
	// 排他関連フィールド
	private boolean						needExclusive;
	private List<ExclusiveVo>			listExclusive;
	
	// フィールド
	/**
	 * ログインユーザ人事基本情報
	 */
	protected HumanBasisDtoInterface	userBasis;
	
	/**
	 * BufferedReader
	 */
	protected BufferedReader			br;
	

	/**
	 * コンストラクタ
	 */
	public MosPAction() {
		super();
		setCheckAuth(false);
		setNeedExclusive(false);
	}
	
	/**
	 * 初期処理
	 * <p>
	 * ActionやVoで必要な初期処理を記述する。<br>
	 * {@link MosPAction}を拡張したクラスでオーバーライドして用いる。
	 * </p>
	 * @since	1.2
	 * @throws Exception 例外処理が発生した場合
	 */
	protected void init() throws Exception {
		// 処理無し
	}
	
	/**
	 * 表示処理（新規）
	 * <p>
	 * 主に画面の初期表示を行う。<br>
	 * {@link MosPAction}を拡張したクラスでオーバーライドして用いる。
	 * </p>
	 * @since	1.2
	 * @throws Exception 	例外処理が発生した場合
	 */
	protected void show() throws Exception {
		// 処理無し
	}
	
	/**
	 * 選択表示処理(キーで情報を検索)
	 * <p>
	 * 主に詳細画面の選択時表示を行う。<br>
	 * {@link MosPAction}を拡張したクラスでオーバーライドして用いる。
	 * </p>
	 * @since	1.2
	 * @throws Exception 例外処理が発生した場合
	 */
	protected void select() throws Exception {
		// 処理無し
	}
	
	/**
	 * 検索処理
	 * <p>
	 * 主に一覧画面の検索処理を行う。<br>
	 * {@link MosPAction}を拡張したクラスでオーバーライドして用いる。
	 * </p>
	 * @since	1.2
	 * @throws Exception 例外処理が発生した場合
	 */
	protected void search() throws Exception {
		// 処理無し
	}
	
	/**
	 * 再検索処理
	 * <p>
	 * 主に一覧画面の再検索処理を行う。<br>
	 * {@link MosPAction}を拡張したクラスでオーバーライドして用いる。
	 * </p>
	 * @since	1.2
	 * @throws Exception 例外処理が発生した場合
	 */
	protected void research() throws Exception {
		// 処理無し
	}
	
	/**
	 * 比較クラス取得
	 * <p>
	 * ソート時に利用する比較クラスを取得する。<br>
	 * {@link MosPAction}を拡張したクラスでオーバーライドして用いる。
	 * </p>
	 * @since	1.2
	 * @param  key ソートキー
	 * @return	比較クラス
	 * @throws MospException MosP例外処理が発生した場合
	 */
	protected Comparator<Object> getComparator(String key) throws MospException {
		return null;
	}
	
	/**
	 * データ挿入処理
	 * <p>
	 * 主に詳細画面の登録処理を行う。<br>
	 * {@link MosPAction}を拡張したクラスでオーバーライドして用いる。<br>
	 * </p>
	 * @since	1.2
	 * @throws Exception 例外処理が発生した場合
	 */
	protected void insert() throws Exception {
		// 処理無し
	}
	
	/**
	 * データ更新処理
	 * <p>
	 * 主に詳細画面の更新処理を行う。<br>
	 * {@link MosPAction}を拡張したクラスでオーバーライドして用いる。<br>
	 * </p>
	 * @since	1.2
	 * @throws Exception 例外処理が発生した場合
	 */
	protected void update() throws Exception {
		// 処理無し
	}
	
	/**
	 * ソート
	 * @param key ソートキー
	 * @throws Exception   例外処理が発生した場合
	 */
	protected void sortList(String key) throws Exception {
		MosPVo vo = (MosPVo)getVo();
		vo.sortList(key, getComparator(key));
		vo.setFields(vo.getList());
	}
	
	/**
	 * ソート(VO内のキー情報でソート)
	 * @throws Exception  例外処理が発生した場合
	 */
	protected void sortList() throws Exception {
		MosPVo vo = (MosPVo)getVo();
		vo.sortList(getComparator(vo.getFormerKey()));
		vo.setFields(vo.getList());
	}
	
	/**
	 * アクション後処理
	 * @throws SQLException  SQL例外が発生した場合
	 */
	@Override
	protected void afterAction() throws SQLException {
		// 消去
		partClear();
		// 後処理
		super.afterAction();
		if (!needExclusive) {
			if (VariousUtil.isNotNull(user)) {
				deleteExclusive(user.getUserId());
			}
		}
	}
	
	/**
	 * CmAspUserDtoの生成
	 */
	protected void createAspUser() {
		aspUser = new CmAspUserDto();
		aspUser.setAspUserId(cfg.getProperty(MospConst.PPT_ASP_ASPUSER));
		aspUser.setAspName(cfg.getProperty(MospConst.PPT_ASP_ASPNAME));
		aspUser.setDbDriver(cfg.getProperty(MospConst.PPT_ASP_DBDRIVER));
		aspUser.setDbUrl(cfg.getProperty(MospConst.PPT_ASP_DBURL));
		aspUser.setDbUser(cfg.getProperty(MospConst.PPT_ASP_DBUSER));
		aspUser.setDbPass(cfg.getProperty(MospConst.PPT_ASP_DBPASS));
	}
	
	/**
	 * ロゴファイル利用可否判断
	 */
	protected void setUseLogo() {
		boolean useLogoFlag = false;
		String useLogo = cfg.getProperty(CommonConst.PPT_USE_LOGO);
		StringBuffer filepath = new StringBuffer();
		filepath.append(cfg.getProperty(MospConst.PPT_APP_DOCBASE));
		filepath.append(System.getProperty("file.separator"));
		filepath.append("pub");
		filepath.append(System.getProperty("file.separator"));
		filepath.append(CommonConst.FILE_LOGO);
		if (StringUtil.isNotNull(useLogo) && Boolean.parseBoolean(useLogo) && new File(filepath.toString()).exists()) {
			useLogoFlag = true;
		}
		cfg.setProperty(CommonConst.PPT_USE_LOGO, String.valueOf(useLogoFlag));
	}
	

	/**
	 * PartClass初期化情報
	 * @since	1.0
	 */
	private PartInfo	partInfo;
	

	/**
	 * PartInfoインスタンスの生成
	 * <p>	一度生成した場合、使いまわす。	</p>
	 * @return	PartInfoインスタンス
	 * @throws SQLException  SQL例外が発生した場合
	 * @throws ClassNotFoundException 	 クラスが見つからなかった場合
	 * @since	1.0
	 */
	protected PartInfo partInfo() throws ClassNotFoundException, SQLException {
		if (VariousUtil.isNull(partInfo)) {
			// DBコネクション取得
			if (VariousUtil.isNull(conn)) {
				getConnection();
			}
			partInfo = PartManager.createPartInfo(cfg, cmd, aspUser, user, conn);
		}
		return partInfo;
	}
	
	/**
	 * 削除フラグリスト取得
	 * @return 削除フラグリスト
	 */
	protected String[][] getDeleteArray() {
		return VariousUtil.getDeleteArray();
	}
	
	/**
	 * 適用フラグリスト取得
	 * @return 削除フラグリスト
	 */
	protected String[][] getApplicableFlagArray() {
		return VariousUtil.getApplicableFlagArray();
	}
	
	/**
	 * 設定リスト取得(MOSP_CONF)
	 * @param confId 設定区分
	 * @return 設定リスト
	 * @throws Exception 例外処理が発生した場合
	 */
	protected String[][] getConfArray(String confId) throws Exception {
		return part().mospconf().getConfArray(confId);
	}
	
	/**
	 * 設定リスト取得(MOSP_CONF)
	 * @param confId 設定区分
	 * @return 設定リスト
	 * @throws Exception 例外処理が発生した場合
	 */
	protected List<MosPConfDto> getConfList(String confId) throws Exception {
		return part().mospconf().getConfList(confId);
	}
	
	/**
	 * コードリスト取得(CM_CODE)
	 * @param tId コード区分
	 * @return コードリスト
	 * @throws Exception 例外処理が発生した場合
	 */
	@Override
	protected String[][] getCodeArray(String tId) throws Exception {
		return part().cmcode().getCodeArray(tId);
	}
	
	/**
	 * コード区分取得(CM_CODE)
	 * @return コード区分リスト
	 * @throws Exception 例外処理が発生した場合
	 */
	protected String[][] getCodeArray() throws Exception {
		return part().cmcode().getCodeArray();
	}
	
	/**
	 * コード区分名称取得(CM_CODE)
	 * @param	tId コード区分
	 * @return	tId コード区分名称
	 * @throws Exception 例外処理が発生した場合
	 */
	protected String getCodeTypeName(String tId) throws Exception {
		return part().cmcode().getCodeTypeName(tId);
	}
	
	/**
	 * 権限コードリスト取得(CM_AUTHORITY)
	 * @return コードリスト
	 * @throws Exception 例外処理が発生した場合
	 */
	protected String[][] getArrangeAuthArray() throws Exception {
		return part().authority().getArrangeAuthArray();
	}
	
	/**
	 * 全権限コードリスト取得(CM_AUTHORITY)
	 * @return コードリスト
	 * @throws Exception 例外処理が発生した場合
	 */
	protected String[][] getArrangeAuthArrayAll() throws Exception {
		return part().authority().getArrangeAuthArrayAll();
	}
	
	/**
	 * コード区分取得(M_CODE)
	 * @return コード区分リスト
	 * @throws Exception 例外処理が発生した場合
	 */
	protected String[][] getMosPCodeArray() throws Exception {
		return part().mospcode().getMosPCodeArray();
	}
	
	/**
	 * コード区分取得(M_CODE)
	 * @return コード配列[][]<br>
	 * 			[0]tcode<br>
	 * 			[1]tname<br>
	 * @param tid コードID
	 * @throws Exception 例外処理が発生した場合
	 */
	protected String[][] getMosPCodeArray(String tid) throws Exception {
		return part().mospcode().getMosPCodeArray(tid);
	}
	
	/**
	 * コード区分取得(M_CODE)
	 * @return コード配列[][]<br>
	 * 			[0]tcode<br>
	 * 			[1]tname<br>
	 * 			[2]tchange
	 * @param tid コードID
	 * @param tcode コード
	 * @throws Exception 例外処理が発生した場合
	 */
	protected String[][] getMosPCodeArray(String tid, String tcode) throws Exception {
		return part().mospcode().getMosPCodeArray(tid, tcode);
	}
	
	/**
	 * コード区分取得(M_CODE)
	 * @return コード配列[][]<br>
	 * 			[0]tcode<br>
	 * 			[1]tname<br>
	 * 			[2]tchange
	 * @param tid コードID
	 * @param tcode コード
	 * @throws Exception 例外処理が発生した場合
	 */
	protected String[] getMosPCode(String tid, String tcode) throws Exception {
		return part().mospcode().getMosPCode(tid, tcode);
	}
	
	/**
	 * 理由区分取得(M_CODE)
	 * @param tid コードID
	 * @return コード配列[][]<br>
	 * 			[0]tcode<br>
	 * 			[1]tname<br>
	 * @throws Exception 例外処理が発生した場合
	 */
	protected String[][] getReasonCodeArray(String tid) throws Exception {
		return part().mospcode().getReasonCodeArray(tid);
	}
	
	/**
	 * コード区分取得(M_CODE)
	 * @return コード配列[][]<br>
	 * 			[0]tcode<br>
	 * 			[1]tname<br>
	 * 			[2]tchange
	 * @param tid コードID
	 * @throws Exception 例外処理が発生した場合
	 */
	protected String[] getMosPCode(String tid) throws Exception {
		return part().mospcode().getMosPCode(tid);
	}
	
	/**
	 * ユーザー情報取得(CM_USER)
	 * @param userId 情報取得対象ユーザーID
	 * @return ユーザー情報(CmUserDto)
	 * @throws Exception 例外処理が発生した場合
	 */
	protected CmUserDto getUserInfo(String userId) throws Exception {
		return part().mospuser().getUserInfo(userId);
	}
	
	/**
	 * ユーザー情報取得(MOSP_USER)
	 * @param kcode		情報取得対象社員コード
	 * @return ユーザー情報(CmUserDto)
	 * @throws Exception 例外処理が発生した場合
	 */
	protected CmUserDto getUserInfoForKCode(String kcode) throws Exception {
		return part().mospuser().getUserInfoForKCode(kcode);
	}
	
	/**
	 * MANAGER権限確認
	 * @return TRAINER権限有無(true：権限有、false：権限無)
	 * @throws Exception 例外処理が発生した場合
	 */
	protected boolean hasManagerAuth() throws Exception {
		return part().authority().hasManagerAuth();
	}
	
	/**
	 * MANAGER権限確認
	 * @throws Exception 例外処理が発生した場合
	 */
	protected void confirmManagerAuth() throws Exception {
		if (!hasManagerAuth()) {
			throw new MospException(MospConst.EX_AUTHORITY);
		}
	}
	
	/**
	 * PAYROLL権限確認
	 * @return PAYROLL権限有無(true：権限有、false：権限無)
	 * @throws Exception 例外処理が発生した場合
	 */
	protected boolean hasPayrollAuth() throws Exception {
		return part().authority().hasPayrollAuth();
	}
	
	/**
	 * PAYROLL権限確認
	 * @throws Exception 例外処理が発生した場合
	 */
	protected void confirmPayrollAuth() throws Exception {
		if (!hasPayrollAuth()) {
			throw new MospException(MospConst.EX_AUTHORITY);
		}
	}
	
	/**
	 * HUMAN権限確認
	 * @return PAYROLL権限有無(true：権限有、false：権限無)
	 * @throws Exception 例外処理が発生した場合
	 */
	protected boolean hasHumanAuth() throws Exception {
		return part().authority().hasHumanAuth();
	}
	
	/**
	 * HUMAN権限確認
	 * @throws Exception 例外処理が発生した場合
	 */
	protected void confirmHumanAuth() throws Exception {
		if (!hasHumanAuth()) {
			throw new MospException(MospConst.EX_AUTHORITY);
		}
	}
	
	/**
	 * CALCULATE権限確認
	 * @return CALCULATE権限有無(true：権限有、false：権限無)
	 * @throws Exception 例外処理が発生した場合
	 */
	protected boolean hasCalculateAuth() throws Exception {
		return part().authority().hasCalculateAuth();
	}
	
	/**
	 * CALCULATE権限確認
	 * @throws Exception 例外処理が発生した場合
	 */
	protected void confirmCalculateAuth() throws Exception {
		if (!hasCalculateAuth()) {
			throw new MospException(MospConst.EX_AUTHORITY);
		}
	}
	
	/**
	 * SYSTEM権限確認
	 * @return SYSTEM権限有無(true：権限有、false：権限無)
	 * @throws Exception 例外処理が発生した場合
	 */
	protected boolean hasSystemAuth() throws Exception {
		return part().authority().hasSystemAuth();
	}
	
	/**
	 * SYSTEM権限確認
	 * @throws Exception 例外処理が発生した場合
	 */
	protected void confirmSystemAuth() throws Exception {
		if (!hasSystemAuth()) {
			throw new MospException(MospConst.EX_AUTHORITY);
		}
	}
	
	/**
	 * キー値取得(複合キー)
	 * @param keyIndex キーインデックス
	 * @return キー値
	 */
	protected String getKeyValue(int keyIndex) {
		return VariousUtil.getKeyValue(key2, keyIndex);
	}
	
	/**
	 * 排他情報取得
	 * @param exclusiveType 排他区分
	 * @param userId        対象ユーザーID
	 * @return 編集者コード(編集者がいない、または自分の場合はnull)
	 * ServletContextを利用するため、複数JVMでの動作は保障しない。
	 */
	@SuppressWarnings("unchecked")
	protected String getExclusive(int exclusiveType, String userId) {
		listExclusive = (List<ExclusiveVo>)ctx.getAttribute(CommonConst.ATT_EXCLUSIVE);
		ExclusiveVo exclusiveVo;
		if (listExclusive == null) {
			return null;
		}
		for (int i = listExclusive.size() - 1; i >= 0; i--) {
			exclusiveVo = listExclusive.get(i);
			if (exclusiveVo.getExclusiveType() == exclusiveType) {
				if (exclusiveVo.getUserId().equals(userId)) {
					// 自分の排他データを削除
					listExclusive.remove(i);
					continue;
				}
				return exclusiveVo.getUserId();
			}
		}
		return null;
	}
	
	/**
	 * 排他情報設定
	 * @param exclusiveType 排他区分
	 * @param userId        対象ユーザーID
	 * @param target        編集対象
	 * @return 編集者コード(編集者がいない、または自分の場合はnull)
	 * ServletContextを利用するため、複数JVMでの動作は保障しない。
	 */
	@SuppressWarnings("unchecked")
	protected String setExclusive(int exclusiveType, String userId, String target) {
		listExclusive = (List<ExclusiveVo>)ctx.getAttribute(CommonConst.ATT_EXCLUSIVE);
		ExclusiveVo exclusiveVo;
		String editor = null;
		if (listExclusive == null) {
			listExclusive = new ArrayList<ExclusiveVo>();
			ctx.setAttribute(CommonConst.ATT_EXCLUSIVE, listExclusive);
		}
		deleteExclusive(userId);
		for (int i = listExclusive.size() - 1; i >= 0; i--) {
			exclusiveVo = listExclusive.get(i);
			if (exclusiveVo.getExclusiveType() == exclusiveType && exclusiveVo.getTarget().equals(target)) {
				editor = exclusiveVo.getUserId();
			}
		}
		addList(listExclusive, new ExclusiveVo(exclusiveType, userId, target));
		return editor;
	}
	
	/**
	 * 排他情報削除
	 * @param userId 対象ユーザーID
	 * ServletContextを利用するため、複数JVMでの動作は保障しない。
	 */
	@SuppressWarnings("unchecked")
	protected void deleteExclusive(String userId) {
		listExclusive = (List<ExclusiveVo>)ctx.getAttribute(CommonConst.ATT_EXCLUSIVE);
		ExclusiveVo exclusiveVo;
		if (listExclusive == null) {
			return;
		}
		for (int i = listExclusive.size() - 1; i >= 0; i--) {
			exclusiveVo = listExclusive.get(i);
			if (VariousUtil.getTimeRemainder(new Date(), exclusiveVo.getDate()) * 60 > Integer.parseInt(cfg
				.getProperty(MospConst.PPT_APP_INTERVAL))) {
				// セッション保持時間以上経っている排他データを削除
				listExclusive.remove(i);
			} else if (exclusiveVo.getUserId().equals(userId)) {
				// 自分の排他データを削除
				listExclusive.remove(i);
			}
		}
	}
	
	/**
	 * ファイル作成
	 * @param upfile アップロードファイル
	 * @return file
	 * @throws Exception	Exception
	 */
	protected File getUploadFile(FileItem upfile) throws Exception {
		// 選択ファイル名取得
		File file = new File(upfile.getFieldName());
		// ファイルへの書き出し
		upfile.write(file);
		return file;
	}
	
	/**
	 * ファイル作成(CSV)
	 * @param csvFile アップロードCSVファイル
	 * @return CSVファイル内容
	 * @throws Exception 例外処理が発生した場合
	 */
	protected File getCSVFileData(FileItem csvFile) throws Exception {
		return getUploadFile(csvFile);
	}
	
	/**
	 * CSVデータパース
	 * @param csvFile	CSVファイル
	 * @return CSVファイル内容
	 * @throws Exception 例外処理が発生した場合
	 */
	protected CSVParser parseCSVData(File csvFile) throws Exception {
		br = CsvUtil.getCsvFileReader(csvFile);
		return new CSVParser(br);
	}
	
	/**
	 * CSVヘッダー作成
	 * @param parser	CSVParser
	 * @return ヘッダ配列
	 * @throws MospException MosP例外処理が発生した場合
	 */
	protected String[] getCSVHeadData(CSVParser parser) throws MospException {
		String[] line;
		try {
			line = parser.getLine();
		} catch (IOException e) {
			// 形式エラー
			addErrMessage(getMessage(CommonConst.MSG_INVALID_HEAD_TYPE, ""));
			throw new MospException(MospConst.EX_PARAMS_INVALID);
		}
		return line;
	}
	
	/**
	 * CSVデータ作成
	 * @param parser	CSVParser
	 * @param idx		インデックス
	 * @return　データ配列
	 * @throws MospException MosP例外処理が発生した場合
	 */
	protected String[] getCSVData(CSVParser parser, int idx) throws MospException {
		String[] line;
		try {
			line = parser.getAllValues()[idx];
		} catch (IOException e) {
			// 形式エラー
			addErrMessage(getMessage(CommonConst.MSG_INVALID_DATA_TYPE, String.valueOf(idx + 1)));
			throw new MospException(MospConst.EX_PARAMS_INVALID);
		}
		return line;
	}
	
	/**
	 * データ存在確認
	 * @param dto 確認対象DTO
	 * @return boolean	対象DTO存在有無
	 */
	protected boolean chkExistDto(BaseDto dto) {
		return VariousUtil.chkExistDto(dto);
	}
	
	/**
	 * データ存在確認
	 * @param obj 確認対象Object
	 * @return boolean	対象Object存在有無
	 */
	protected boolean chkExistObject(Object obj) {
		return VariousUtil.chkExistObject(obj);
	}
	
	/**
	 * 曜日設定
	 * @param dayOfWeek 曜日
	 * @return 曜日名
	 */
	protected String getDayOfWeek(int dayOfWeek) {
		return VariousUtil.getDayOfWeek(dayOfWeek);
	}
	
	/**
	 * 時間フォーマット
	 * @param hour 時間
	 * @return 時間(文字列)
	 */
	protected String getHourString(double hour) {
		return VariousUtil.getHourString(hour);
	}
	
	/**
	 * 有給繰越情報
	 * @return	String[]	有給繰越情報
	 * <p>
	 * [0]...繰越月、
	 * [1]...繰越日数、
	 * [2]...繰越区分
	 * </p>
	 * @throws Exception 例外処理が発生した場合
	 */
	protected String[] getPaidHolidayInfo() throws Exception {
		return part().mospcode().getPaidHolidayInfo();
	}
	
	/**
	 * 有給休暇支給日数
	 * @return [0]…勤続年数、[1]…支給日数
	 * @throws Exception 例外処理が発生した場合
	 */
	protected String[][] getPaidHolidayArray() throws Exception {
		return part().mospcode().getPaidHolidayArray();
	}
	
	/**
	 * 出力範囲プルダウンリスト
	 * @return	String[][]	出力範囲配列
	 */
	protected String[][] getOutputScopeArray() {
		return VariousUtil.getOutputScopeArray();
	}
	
	/**
	 * 勤怠承認機能状況取得(M_CODE)
	 * @return	boolean 	勤怠承認機能の有効無効
	 * @throws Exception 例外処理が発生した場合
	 */
	protected boolean isAttendanceApprovalFunction() throws Exception {
		return part().mospcode().isAttendanceApprovalFunction();
	}
	
	/**
	 * パスワード有効期限日数
	 * @return	int		パスワード有効期限日数
	 * @throws Exception 例外処理が発生した場合
	 */
	protected int getPasswordTerm() throws Exception {
		return part().mospcode().getPasswordTerm();
	}
	
	/**
	 * フィールド名称内のデータ分解取得
	 *  0 : ファイルID
	 *  1 : 管理番号
	 *  2 : フィールドID
	 *  3 : フィールド名称
	 * @param csvString カンマ区切りの文字列
	 * @param i 対象インデックス
	 * @return 文字列
	 */
	protected String getEFnameItem(String csvString, int i) {
		return VariousUtil.getCsvSplitInfo(csvString, i);
	}
	
	/**
	 * 該当フラグ配列
	 * @return 該当フラグ配列
	 */
	protected String[][] getCorrespondFlagArray() {
		return VariousUtil.getCorrespondFlagArray();
	}
	
	/**
	 * 和暦元号配列
	 * @return	和暦元号配列
	 * @throws Exception 例外処理が発生した場合
	 */
	protected String[][] getJPCalendarGengo() throws Exception {
		return part().cmcode().getJPCalendarGengo();
	}
	
	/**
	 * DTO同一性チェック
	 * @param formerDto		元対象DTO
	 * @param currentDto	現対象DTO
	 * @return
	 * <p>
	 * 更新日時が同一の場合true、そうでない場合false
	 * </p>
	 * @throws MospException MosP例外処理が発生した場合
	 */
	protected boolean chkIdentityDto(BaseDto formerDto, BaseDto currentDto) throws MospException {
		return VariousUtil.chkIdentityDto(formerDto, currentDto);
	}
	
	/**
	 * 対象年から対象年度を取得
	 * @param year		対象年
	 * @param month		対象月
	 * @param startmonth	年度開始月
	 * @return	対象年度
	 * @throws Exception 例外処理が発生した場合
	 */
	protected int getTargetFiscalYear(int year, int month, int startmonth) throws Exception {
		return VariousUtil.getTargetFiscalYear(year, month, startmonth);
	}
	
	/**
	 * 対象年度から対象年を取得
	 * @param fiscalyear		対象年度
	 * @param month				対象月
	 * @param startmonth		年度開始月
	 * @return	対象年
	 */
	protected int getTargetYear(int fiscalyear, int month, int startmonth) {
		return VariousUtil.getTargetYear(fiscalyear, month, startmonth);
	}
	
	/**
	 * 対象年度開始日取得
	 * @param fiscalyear 対象年度
	 * @param startMonth 年度開始月
	 * @return 対象年度開始日
	 * @throws Exception 例外処理が発生した場合
	 */
	protected Date getFiscalStartDate(int fiscalyear, int startMonth) throws Exception {
		return DateUtil.getFiscalStartDate(fiscalyear, startMonth);
	}
	
	/**
	 * 対象年度終了日取得
	 * @param fiscalyear 対象年度
	 * @param startMonth 年度開始月
	 * @return 対象年度終了日
	 * @throws Exception 例外処理が発生した場合
	 */
	protected Date getFiscalEndDate(int fiscalyear, int startMonth) throws Exception {
		return DateUtil.getFiscalEndDate(fiscalyear, startMonth);
	}
	
	/**
	 * 和暦表示設定
	 * @param targetDate	対象年月日
	 * @return	和暦表示
	 * @throws Exception 例外処理が発生した場合
	 */
	protected String getJapaneseDate(Date targetDate) throws Exception {
		return part().jpdate().getJapaneseDate(targetDate);
	}
	
	/**
	 * 和暦表示設定
	 * @param targetDate	対象年月日(yyyy-MM-dd)
	 * @return	和暦表示
	 * @throws Exception 例外処理が発生した場合
	 */
	protected String getJapaneseDate(String targetDate) throws Exception {
		return part().jpdate().getJapaneseDate(targetDate);
	}
	
	/**
	 * 承認ステータスコードリスト取得
	 * @return 承認ステータスコードリスト配列
	 */
	protected String[] getApprovalStatusCodeArray() {
		return VariousUtil.getApprovalStatusCodeArray();
	}
	
	/**
	 * 更新日時による排他確認。<br>
	 * @since	1.3
	 * currentDtoに対して{@link #chkExist(BaseDto)}を実行した後、
	 * formerDtoとcurrentDtoの更新日時を比較する。<br>
	 * 更新日時が同じでない場合、{@link MospException}を発行する。<br>
	 * @param formerDto 更新対象DTO(編集前)
	 * @param currentDto 更新対象DTO(最新)
	 * @throws MospException MosP例外処理が発生した場合
	 */
	protected void chkExclusive(BaseDto formerDto, BaseDto currentDto) throws MospException {
		super.chkExclusive(formerDto, currentDto, getVo());
	}
	
	/**
	 * データ重複確認。<br>
	 * @since	1.3
	 * dtoがnullでない場合、{@link MospException}を発行する。<br>
	 * @param dto 確認対象DTO
	 * @throws MospException MosP例外処理が発生した場合
	 */
	protected void chkDuplicate(BaseDto dto) throws MospException {
		super.chkDuplicate(dto, getVo());
	}
	
	/**
	 * メッセージ取得
	 * @param msgCode 	メッセージコード
	 * @param rep		置換文字列(複数ある場合はカンマ区切り)
	 * @return	メッセージ文字列
	 * @throws MospException MosP例外処理が発生した場合
	 */
	protected String getMessage(String msgCode, String rep) throws MospException {
		return MospUtility.getMessage(msg, msgCode, rep);
	}
	
	/**
	 * セッションに保持されているDTOの取得。<br>
	 * 属性は{@link MospConst#ATT_DTO}
	 * @return セッションに保持されているDTO
	 */
	protected BaseDto getSessionDto() {
		Object obj = session.getAttribute(MospConst.ATT_DTO);
		return obj instanceof BaseDto ? (BaseDto)obj : null;
	}
	
	/**
	 * セッションにDTOをセット。<br>
	 * 属性は{@link MospConst#ATT_DTO}
	 * @param dto セッションに保持させるDTO
	 */
	protected void setSessionDto(BaseDto dto) {
		session.setAttribute(MospConst.ATT_DTO, dto);
	}
	
	/**
	 * セッションに保持されているDTOを消去する。
	 */
	protected void removeSessionDto() {
		session.removeAttribute(MospConst.ATT_DTO);
	}
	
	@Override
	protected void getConnection() throws ClassNotFoundException, SQLException {
		boolean isDefault = true;
		// DataSourceが利用できるか判断
		if (canUseDataSource()) {
			try {
				getConnection(cfg.getProperty(MospConst.PPT_ASP_DSOURCE));
			} catch (NamingException e) {
				// エラーをログに出力する。
				LogUtility.log(cfg, "", "", cmd, 5, MospConst.LOG_MOSPERR, MospConst.LOG_MSG_5003);
				e.printStackTrace();
			} catch (SQLException e) {
				// エラーをログに出力する。
				LogUtility.log(cfg, "", "", cmd, 5, MospConst.LOG_MOSPERR, MospConst.LOG_MSG_5003);
				e.printStackTrace();
			} finally {
				if (VariousUtil.isNotNull(conn)) {
					isDefault = false;
				} else {
					// 設定がエラーの場合、デフォルトの接続を利用する。
					cfg.setProperty(CommonConst.PPT_USE_DATA_SOURCE, String.valueOf(false));
				}
			}
		}
		if (isDefault) {
			super.getConnection();
		}
	}
	
	/**
	 * DataSource利用可否判断
	 * @return
	 * <p>
	 * DataSourceが利用できる場合true、そうでない場合false<br>
	 * 一度判断したら、cfgにセットし次回からそちらを利用する。
	 * </p>
	 */
	protected boolean canUseDataSource() {
		// 設定ファイルのプロパティから取得
		String pptDataSource = cfg.getProperty(CommonConst.PPT_USE_DATA_SOURCE);
		if (pptDataSource == null) {
			// プロパティに無い場合、設定する。
			boolean dsourceFlag = false;
			if (DataSourceUtil.canUseDataSource(cfg.getProperty(MospConst.PPT_ASP_DSOURCE))) {
				dsourceFlag = true;
				LogUtility.log(cfg, "", "", "", 4, MospConst.LOG_MOSPINF, DataSourceUtil.USE_DATA_SOURCE_MESSAGE);
			}
			cfg.setProperty(CommonConst.PPT_USE_DATA_SOURCE, String.valueOf(dsourceFlag));
			pptDataSource = String.valueOf(dsourceFlag);
		}
		return Boolean.valueOf(pptDataSource);
	}
	
	/**
	 * 初期コマンド取得。<br>
	 * @param invalidProcSeq 処理シーケンス不正時フラグ
	 * @return 初期コマンド
	 */
	@Override
	protected String getIndexCommand(boolean invalidProcSeq) {
		try {
			// ASPユーザー取得(設定ファイルのASP設定で判断)
			switch (MospUtility.getAspFlag(cfg)) {
				case 0:
				case 1:
					// 0：ASP(xユーザー:1アプリ)
					// 1：ASP(1ユーザー:1アプリ)
					return "C3011";
				case 2:
					// 2：非ASP
					//return MospConst.CMD_INDEX;
				default:
					return MospConst.CMD_INDEX;
			}
		} catch (MospException e) {
			return MospConst.CMD_INDEX;
		}
	}
	
	/*
	 * 以下、オプション関連のメソッド
	 */

	/**
	 * OptionConst取得
	 * @return	OptionConstのクラスオブジェクト
	 * @throws ClassNotFoundException 	 クラスが見つからなかった場合
	 */
	protected Class<?> getOptionConstClass() throws ClassNotFoundException {
		return Class.forName(CommonConst.OPTION_CONST_FULLNAME);
	}
	
	/**
	 * オプション機能有効判定
	 * <p>2008/12/10	m.yoshida	追加</p>
	 * @return useOption
	 * <p>
	 * オプション機能を利用することができる場合true、<br>
	 * そうでない場合false
	 * </p>
	 */
	protected boolean canUseOptionPackage() {
		// 設定ファイルのプロパティから取得
		try {
			if (cfg.getProperty(CommonConst.PPT_USE_OPTION) == null) {
				// OptionConstクラスが存在するか確認
				Class<?> cls = getOptionConstClass();
				// プロパティに無い場合、設定する。
				if (cls != null) {
					cfg.setProperty(CommonConst.PPT_USE_OPTION, String.valueOf(true));
				}
			}
		} catch (ClassNotFoundException e) {
			cfg.setProperty(CommonConst.PPT_USE_OPTION, String.valueOf(false));
		}
		return Boolean.valueOf(cfg.getProperty(CommonConst.PPT_USE_OPTION));
	}
	
	// アクセサメソッド
	/**
	 * @param needExclusive		排他制御フラグ
	 */
	protected void setNeedExclusive(boolean needExclusive) {
		this.needExclusive = needExclusive;
	}
	
	/* Part関連 */

	/**
	 * 初期化済みPartクラスインスタンス取得
	 * @param partClassName		対象Partクラス
	 * @return	対象初期化済みPartクラスインスタンス
	 * @throws Exception 例外処理が発生した場合
	 */
	protected BasePart getPart(String partClassName) throws Exception {
		return part().get(partClassName);
	}
	
	/**
	 * 初期化済みPartクラスインスタンス取得
	 * @param cls 対象Partクラス
	 * @return	対象初期化済みPartクラスインスタンス
	 * @throws Exception 例外処理が発生した場合
	 */
	protected BasePart getPart(Class<?> cls) throws Exception {
		return part().get(cls);
	}
	

	private BaseStore	baseStore;
	

	/**
	 * PartStoreインスタンス取得
	 * @return	PartStoreインスタンス
	 * @throws MospException  MosP例外処理が発生した場合
	 * @throws SQLException   SQL例外が発生した場合
	 * @throws ClassNotFoundException  クラスが見つからなかった場合
	 */
	protected PartStore part() throws MospException, ClassNotFoundException, SQLException {
		return (PartStore)getBaseStore(PartStore.class);
	}
	
	/**
	 * BaseStoreインスタンス取得
	 * @since 0.1.4
	 * @param cls BaseStoreを継承したクラス
	 * @return BaseStoreインスタンス
	 * @throws SQLException   SQL例外が発生した場合
	 * @throws ClassNotFoundException  クラスが見つからなかった場合
	 * @throws MospException  MosP例外処理が発生した場合
	 */
	protected BaseStore getBaseStore(Class<?> cls) throws MospException, ClassNotFoundException, SQLException {
		if (VariousUtil.isNull(baseStore)) {
			baseStore = (BaseStore)InstanceFactory.loadInstance(cls.getCanonicalName());
			baseStore.setPartInfo(partInfo());
		}
		return baseStore;
	}
	
	/**
	 * 保持していたPartクラスを消去。
	 */
	private void partClear() {
		if (VariousUtil.isNotNull(baseStore)) {
			baseStore.clear();
			baseStore = null;
		}
	}
	
}
