/*********************************************************************
*	All Rights reserved,Copyright (c) K-Opticom
**********************************************************************
*＜プログラム内容＞
*	システム名		：eo顧客基幹システム
*	モジュール名	：JDKModelCommon
*	ソースファイル名：JDKModelCommon.java
*	作成者			：富士通
*	日付			：2011年11月17日
*＜機能概要＞
*	物流共通のチェックを行う
*＜修正履歴＞
*	バージョン	修正日		修正者		修正内容
*	v1.00.00	2011/11/17	富士通		新規作成
*   v5.00.00    2013/11/22  富士通      リターンコード0500対応(OM-2013-0004325)
*	v7.00.00	2013/11/07	富士通		ANK-1578-00-00(多機能ルータ対応)
*   v5.00.01    2014/01/08  富士通      パラメータ不正対応(OM-2014-0000087)
*   v7.00.00    2014/03/13  富士通      電話のサービス契約番号取得追加(OM-2014-0001074)
*   v8.00.00    2014/05/02  FJ)窪田     OM-2014-0001719
*   v9.00.00    2014/06/10  FJ)小島     ANK-2130-00-00
*   v61.00.00   2023/03/24  FJ)永江    【ANK-4315-00-00】【eo定期】 eoホームゲートウェイ導入対応
**********************************************************************/

package eo.ejb.common;

import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.fujitsu.futurity.model.base.CAANJDBCUtil;
import com.fujitsu.futurity.model.base.CAANMsg;
import com.fujitsu.futurity.model.base.CAANSchemaInfo;
import com.fujitsu.futurity.model.ejb.common.JSYejbLog;
import com.fujitsu.futurity.model.ejb.common.StatusCodes;
import com.fujitsu.futurity.model.ejb.common.fw.AgentDispatchContext;

import eo.common.constant.JDKStrConst;
import eo.common.util.JDKCommonUtil;
import eo.ejb.common.edit.JDKejbStringEdit;

/**
 * <p>
 * 物流共通チェック部品のアクセッサクラスです。
 * </p>
 * @author 富士通
 */
public class JDKModelCommon extends JCCModelCommon
{

    /**
     * エラーレベル
     */
    public static final String ERROR_LEVEL = "errorLevel";

    /**
     * リターンコード
     */
    public static final String RETURN_CD = "returnCode";

    /**
     * リターンメッセージ
     */
    public static final String RETURN_MESSAGE = "returnMessage";

    /**
     * エラーフィールド
     */
	private static final String ERROR_FIELD_MARK = "_err";
    
	/**
	 *オンライン運用日時(YYYYMMDDhhmm)を取得します。
	 */
	public static Object getOpeDateTime(CAANMsg inMsg, AgentDispatchContext context)
	{
		return JDKejbStringEdit.substring(inMsg, context, JPCModelCommon.getOpeDate(inMsg, context, null), "12");
	}
	
	
	/**
	 * 運用日時と比較します。
	 * 運用日と比較してkeyであらわされる日がoperatorの通りならtureを返す。それ以外はfalseを返す。
	 * operatorに指定できるのは以下
	 * lt  key &lt; opedate
	 * le  key &lt;= opedate
	 * eq  key == opedate
	 * ge  key &gt;= opedate
	 * gt  key &gt; opedate
	 */
	public static boolean compareToOpedate(CAANMsg inMsg, AgentDispatchContext context, Object key, Object operator)
	{
		String opedate = JDKModelCommon.getOpeDate(inMsg, null);
		
		String target = inMsg.getString(key.toString());
		
		if (target == null)
		{
			return false;
		}
		else if ("lt".equals(operator))
		{
			return target.compareTo(opedate) < 0;
		}
		else if ("le".equals(operator))
		{
			return target.compareTo(opedate) <= 0;
		}
		else if ("eq".equals(operator))
		{
			return target.compareTo(opedate) == 0;
		}
		else if ("ge".equals(operator))
		{
			return target.compareTo(opedate) >= 0;
		}
		else if ("gt".equals(operator))
		{
			return target.compareTo(opedate) > 0;
		}
		
		return false;
	}
	
	
	
	/**
	 * <p>
	 * 一意チェックを行います。
	 * </p>
	 * @param inMsg 処理対象のメッセージキャリア
	 * @param inContext Agentから渡されたAgentDispatchContext
	 * @param listKey リストのキー
	 * @param key 項目のキー
	 * @param errFlg エラーフラグ
	 * @param errTarget エラー項目
	 * @return 重複していない場合にtrue。以外の場合false。
	 */
	public static boolean isUnique(CAANMsg inMsg, AgentDispatchContext inContext, Object listKey, Object key, Object errFlg, Object errTarget)
	{

		boolean ret = true;
		CAANMsg[] datalist = inMsg.getCAANMsgList(listKey.toString());

		for (int i = 0; i < datalist.length; i++)
		{
			for (int j = i + 1; j < datalist.length; j++)
			{
				// 値がnullでなく重複した場合
				if ((!datalist[i].isNull(key.toString())) && 
						(datalist[i].getObject(key.toString()).equals(datalist[j].getObject(key.toString()))))
				{
					// エラー項目が存在する場合、エラー項目にエラーフラグを設定
					if (null != errTarget)
					{
						datalist[i].set(errTarget.toString(), errFlg.toString());
					}
					ret = false;
				}
			}
		}
		return ret;
	}

	/**
	 * 名称管理検索用のSQLを生成します
	 * @param cd 名称管理のコード値
	 * @param join 名称管理とjoinする項目
	 * @param alias エイリアス
	 * @return 名称管理検索SQL
	 */
	public static String cd(String cd, String join, String alias)
	{
		return cd(cd, join, COMMA.LEFT, alias);
	}

	
	/**
	 * 名称管理検索用のSQLを生成します
	 * @param cd 名称管理のコード値
	 * @param join 名称管理とjoinする項目
	 * @param connect カンマで接続するかどうか
	 * @param alias エイリアス
	 * @return 名称管理検索SQL
	 */
	public static String cd(String cd, String join, COMMA comma, String alias)
	{
		return cd(cd, join, comma, false, alias);
	}
	
	/**
	 * 名称管理検索用のSQLを生成します
	 * @param cd 名称管理のコード値
	 * @param join 名称管理とjoinする項目
	 * @param connect カンマで接続するかどうか
	 * @param alias エイリアス
	 * @return 名称管理検索SQL
	 */
	public static String cd(String cd, String join, COMMA comma, boolean between, String alias)
	{
		String sqlBase = new StringBufferWrapper()
							.append(" ( SELECT CD_DIV_NM ")
							.append("     FROM ZM_M_CD_NM_KANRI ")
							.append("    WHERE CD_SBT_CD = '%s' ")
							.append("      AND CD_DIV = %s ")
							.append("      AND CD_TSTAYMD <= ? %s ")
							.append("      AND MK_FLG = '0' ) %s ").toString();
		String sql = String.format(sqlBase, cd, join, between ? " AND CD_TENDYMD >= ? " : "", alias);
		
		if (comma == COMMA.LEFT)
		{
			return ", " + sql;
		}
		else if (comma == COMMA.RIGHT)
		{
			return sql + ", ";
		}
		
		return sql;
	}
	

	/**
	 * マスタから名称を参照します
	 * @param table 取得対象のマスタテーブル名
	 * @param col 取得対象のマスタカラム名
	 * @param alias 取得対象のマスタカラムのエイリアス
	 * @param join 結合条件
	 * @param comma コンマの位置
	 * @return 名称項目
	 */
	public static String cdNm(String table, String nmCol, String cdCol, String alias, String join, COMMA comma)
	{
		String sqlBase = new StringBufferWrapper()
								.append("(SELECT %s.%s")
								.append("   FROM %s ")
								.append("  WHERE %s.%s = %s")
								.append("    AND %s.MK_FLG = '0') AS %s").toString();
		
		String sql = String.format(sqlBase
								, table, nmCol
								, table
								, table, cdCol, join
								, table, alias);
		
		if (comma == COMMA.LEFT)
		{
			return ", " + sql;
		}
		else if (comma == COMMA.RIGHT)
		{
			return sql + ", ";
		}
		
		return sql;
	}
	
	
	/**
	 * マスタから名称を参照します
	 * @param table 取得対象のマスタテーブル名
	 * @param nmCol 取得対象のマスタカラム名
	 * @param join 結合条件のコード
	 * @param comma コンマの位置
	 * @return 名称項目
	 */
	public static String cdNm(String table, String nmCol, String join, COMMA comma)
	{
		String cdCol = join;
		if (join.indexOf(".") > 0)
		{
			cdCol = join.split("\\.")[1];
		}
		return cdNm(table, nmCol, cdCol, nmCol, join, comma);
	}
	
	/**
	 * コンマの位置を表す
	 */
	public enum COMMA
	{
		LEFT, RIGHT, NONE;
	}

	/**
	 * 名称管理検索用のSQLを生成します。運用日付での指定は行いません。
	 * @param cd 名称管理のコード値
	 * @param join 名称管理とjoinする項目
	 * @param comma カンマで接続するかどうか
	 * @param alias エイリアス
	 * @return 名称管理検索SQL
	 */
	public static String cdNoYmd(String cd, String join, COMMA comma, String alias)
	{
		String sqlBase = new StringBufferWrapper()
						.append("( SELECT CD_DIV_NM ")
						.append("    FROM ZM_M_CD_NM_KANRI ")
						.append("   WHERE CD_SBT_CD = '%s' ")
						.append("     AND CD_DIV = %s  ")
						.append("     AND MK_FLG = '0' ) %s  ").toString();
		String sql = String.format(sqlBase, cd, join, alias);
		
		if (comma == COMMA.LEFT)
		{
			return ", " + sql;
		}
		else if (comma == COMMA.RIGHT)
		{
			return sql + ", ";
		}
		
		return sql;
	}

	

	/**
	 * 機器提供サービス契約番号からサービス契約番号を引くSQLを返します。
	 * 置換すべきパラメータは運用日付＊7
	 * @param kk0341Alias 機器提供サービス契約テーブルのエイリアス
	 * @param alias 項目のエイリアス
	 * @param comma コンマの位置
	 * @return SQL
	 */
	public static String svcKeiNoFor(String kk0341Alias, String alias, String kaisenDateRange, COMMA comma)
	{
		return svcKeiNoFor(kk0341Alias, alias, kaisenDateRange, comma, "SUBSTR(?, 0, 8)");
	}
	/**
	 * 機器提供サービス契約番号からサービス契約番号を引くSQLを返します。
	 * @param kk0341Alias 機器提供サービス契約テーブルのエイリアス
	 * @param alias 項目のエイリアス
	 * @param comma コンマの位置
	 * @param dateCondition 日付条件
	 * @return SQL
	 */
	public static String svcKeiNoFor(String kk0341Alias, String alias, String kaisenDateRange, COMMA comma, String dateCondition)
	{
		StringBufferWrapper sb = new StringBufferWrapper();
		
		sb.append(" %s CASE %s.OYA_KEI_SKBT_CD ")
		.append("     WHEN '02' THEN ")
		.append("         CASE  ")
		.append("         WHEN %s.TAKNKIKI_SBT_CD IN ('D0', '60', '70', '90') THEN ")
		.append("           NVL(( ")
		.append("             SELECT KK0081.SVC_KEI_NO ")
		.append("               FROM KK_T_KAISEN_TG_SVKEI KK0241, KK_T_SVC_KEI KK0081  ")
		.append("              WHERE KK0241.SVC_KEI_KAISEN_UCWK_NO = %s.SVC_KEI_KAISEN_UCWK_NO  ")
		.append("                AND ((KK0241.KAISEN_UCWK_USE_STAYMD <> KK0241.KAISEN_UCWK_USE_ENDYMD  ")
		.append("                AND %s BETWEEN KK0241.KAISEN_UCWK_USE_STAYMD AND KK0241.KAISEN_UCWK_USE_ENDYMD) ")
		.append("                OR (KK0241.KAISEN_UCWK_USE_STAYMD = '20991231' AND KK0241.KAISEN_UCWK_USE_ENDYMD = '20991231'))  ")
		.append("                AND KK0241.MK_FLG = '0'  ")
		.append("                AND KK0081.SVC_KEI_NO = KK0241.SVC_KEI_NO  ")
		.append("                AND KK0081.SVC_KEI_STAT NOT IN ('910','920') ")
		.append("                AND KK0081.SVC_CD = '01' ")
		.append("                AND (KK0081.SVC_KEI_NO, KK0081.RSV_APLY_YMD || KK0081.GENE_ADD_DTM) =  ")
		.append("                  (SELECT KK0081_GENE.SVC_KEI_NO, MAX(KK0081_GENE.RSV_APLY_YMD || KK0081_GENE.GENE_ADD_DTM) AS KK0081_MAX  ")
		.append("                     FROM  KK_T_SVC_KEI KK0081_GENE  ")
		.append("                    WHERE KK0081_GENE.SVC_KEI_NO = KK0081.SVC_KEI_NO  ")
		.append("                      AND   KK0081_GENE.RSV_APLY_YMD <= %s ")
		.append("                      AND   KK0081_GENE.RSV_APLY_CD IN ('1','2') ")
		.append("                      AND   KK0081_GENE.MK_FLG = '0' ")
		.append("                    GROUP BY KK0081_GENE.SVC_KEI_NO ) ")
		.append("           ),( ")
		.append("             SELECT KK0081.SVC_KEI_NO ")
		.append("               FROM KK_T_KAISEN_TG_SVKEI KK0241, KK_T_SVC_KEI KK0081  ")
		.append("              WHERE KK0241.SVC_KEI_KAISEN_UCWK_NO = %s.SVC_KEI_KAISEN_UCWK_NO  ")
		.append("                AND ((KK0241.KAISEN_UCWK_USE_STAYMD <> KK0241.KAISEN_UCWK_USE_ENDYMD  ")
		.append("                AND %s BETWEEN KK0241.KAISEN_UCWK_USE_STAYMD AND KK0241.KAISEN_UCWK_USE_ENDYMD) ")
		.append("                OR (KK0241.KAISEN_UCWK_USE_STAYMD = '20991231' AND KK0241.KAISEN_UCWK_USE_ENDYMD = '20991231'))  ")
		.append("                AND KK0241.MK_FLG = '0'  ")
		.append("                AND KK0081.SVC_KEI_NO = KK0241.SVC_KEI_NO  ")
		.append("                AND KK0081.SVC_KEI_STAT NOT IN ('910','920') ")
		.append("                AND KK0081.SVC_CD = '02' ")
		.append("                AND (KK0081.SVC_KEI_NO, KK0081.RSV_APLY_YMD || KK0081.GENE_ADD_DTM) =  ")
		.append("                  (SELECT KK0081_GENE.SVC_KEI_NO, MAX(KK0081_GENE.RSV_APLY_YMD || KK0081_GENE.GENE_ADD_DTM) AS KK0081_MAX  ")
		.append("                     FROM  KK_T_SVC_KEI KK0081_GENE  ")
		.append("                    WHERE KK0081_GENE.SVC_KEI_NO = KK0081.SVC_KEI_NO  ")
		.append("                      AND   KK0081_GENE.RSV_APLY_YMD <= %s ")
		.append("                      AND   KK0081_GENE.RSV_APLY_CD IN ('1','2') ")
		.append("                      AND   KK0081_GENE.MK_FLG = '0' ")
		.append("                    GROUP BY KK0081_GENE.SVC_KEI_NO ) ")
		.append("           )) ")
// ANK-4315-00-00 MOD START
//		.append("         WHEN %s.TAKNKIKI_SBT_CD = 'R0' THEN ")
		.append("         WHEN %s.TAKNKIKI_SBT_CD IN ('R0','S0') THEN ")
// ANK-4315-00-00 MOD END
		.append("           NVL(( ")
		.append("             SELECT KK0081.SVC_KEI_NO ")
		.append("               FROM KK_T_KAISEN_TG_SVKEI KK0241, KK_T_SVC_KEI KK0081, KK_T_KKOP_SVC_KEI KK2811  ")
		.append("              WHERE KK0241.SVC_KEI_KAISEN_UCWK_NO = %s.SVC_KEI_KAISEN_UCWK_NO  ")
		.append("                AND ((KK0241.KAISEN_UCWK_USE_STAYMD <> KK0241.KAISEN_UCWK_USE_ENDYMD  ")
		.append("                AND %s BETWEEN KK0241.KAISEN_UCWK_USE_STAYMD AND KK0241.KAISEN_UCWK_USE_ENDYMD) ")
		.append("                OR (KK0241.KAISEN_UCWK_USE_STAYMD = '20991231' AND KK0241.KAISEN_UCWK_USE_ENDYMD = '20991231'))  ")
		.append("                AND KK0241.MK_FLG = '0'  ")
		.append("                AND KK0081.SVC_KEI_NO = KK0241.SVC_KEI_NO  ")
		.append("                AND KK0081.SVC_KEI_STAT NOT IN ('910','920') ")
		.append("                AND KK0081.SVC_CD = '01' ")
		.append("                AND (KK0081.SVC_KEI_NO, KK0081.RSV_APLY_YMD || KK0081.GENE_ADD_DTM) =  ")
		.append("                  (SELECT KK0081_GENE.SVC_KEI_NO, MAX(KK0081_GENE.RSV_APLY_YMD || KK0081_GENE.GENE_ADD_DTM) AS KK0081_MAX  ")
		.append("                     FROM  KK_T_SVC_KEI KK0081_GENE  ")
		.append("                    WHERE KK0081_GENE.SVC_KEI_NO = KK0241.SVC_KEI_NO  ")
		.append("                      AND   KK0081_GENE.RSV_APLY_YMD <= %s ")
		.append("                      AND   KK0081_GENE.RSV_APLY_CD IN ('1','2') ")
		.append("                      AND   KK0081_GENE.MK_FLG = '0' ")
		.append("                    GROUP BY KK0081_GENE.SVC_KEI_NO ) ")
		.append("                AND KK2811.KKTK_SVC_KEI_NO = %s.KKTK_SVC_KEI_NO  ")
		.append("                AND KK2811.KKOP_SVC_KEI_STAT NOT IN ('910','920') ")
		.append("                AND KK2811.KKOP_SVC_CD = 'G01' ")
		.append("                AND (KK2811.KKTK_SVC_KEI_NO, KK2811.RSV_APLY_YMD || KK2811.GENE_ADD_DTM) =   ")
		.append("                  (SELECT KK2811_GENE.KKTK_SVC_KEI_NO, MAX(KK2811_GENE.RSV_APLY_YMD || KK2811_GENE.GENE_ADD_DTM) AS KK2811_MAX  ")
		.append("                     FROM  KK_T_KKOP_SVC_KEI KK2811_GENE  ")
		.append("                    WHERE KK2811_GENE.KKTK_SVC_KEI_NO = KK2811.KKTK_SVC_KEI_NO  ")
		.append("                      AND   KK2811_GENE.KKOP_SVC_CD = 'G01'  ")
		.append("                      AND   KK2811_GENE.MK_FLG = '0'  ")
		.append("                    GROUP BY KK2811_GENE.KKTK_SVC_KEI_NO ) ")
		.append("           ),( ")
		.append("             SELECT KK0081.SVC_KEI_NO ")
		.append("               FROM KK_T_KAISEN_TG_SVKEI KK0241, KK_T_SVC_KEI KK0081, KK_T_KKOP_SVC_KEI KK2811  ")
		.append("              WHERE KK0241.SVC_KEI_KAISEN_UCWK_NO = %s.SVC_KEI_KAISEN_UCWK_NO  ")
		.append("                AND ((KK0241.KAISEN_UCWK_USE_STAYMD <> KK0241.KAISEN_UCWK_USE_ENDYMD  ")
		.append("                AND %s BETWEEN KK0241.KAISEN_UCWK_USE_STAYMD AND KK0241.KAISEN_UCWK_USE_ENDYMD) ")
		.append("                OR (KK0241.KAISEN_UCWK_USE_STAYMD = '20991231' AND KK0241.KAISEN_UCWK_USE_ENDYMD = '20991231'))  ")
		.append("                AND KK0241.MK_FLG = '0'  ")
		.append("                AND KK0081.SVC_KEI_NO = KK0241.SVC_KEI_NO  ")
		.append("                AND KK0081.SVC_KEI_STAT NOT IN ('910','920') ")
		.append("                AND KK0081.SVC_CD = '02' ")
		.append("                AND (KK0081.SVC_KEI_NO, KK0081.RSV_APLY_YMD || KK0081.GENE_ADD_DTM) =  ")
		.append("                  (SELECT KK0081_GENE.SVC_KEI_NO, MAX(KK0081_GENE.RSV_APLY_YMD || KK0081_GENE.GENE_ADD_DTM) AS KK0081_MAX  ")
		.append("                     FROM  KK_T_SVC_KEI KK0081_GENE  ")
		.append("                    WHERE KK0081_GENE.SVC_KEI_NO = KK0241.SVC_KEI_NO  ")
		.append("                      AND   KK0081_GENE.RSV_APLY_YMD <= %s ")
		.append("                      AND   KK0081_GENE.RSV_APLY_CD IN ('1','2') ")
		.append("                      AND   KK0081_GENE.MK_FLG = '0' ")
		.append("                    GROUP BY KK0081_GENE.SVC_KEI_NO ) ")
		.append("                AND KK2811.KKTK_SVC_KEI_NO = %s.KKTK_SVC_KEI_NO  ")
		.append("                AND KK2811.KKOP_SVC_KEI_STAT NOT IN ('910','920') ")
		.append("                AND KK2811.KKOP_SVC_CD = 'G02' ")
		.append("                AND (KK2811.KKTK_SVC_KEI_NO, KK2811.RSV_APLY_YMD || KK2811.GENE_ADD_DTM) =   ")
		.append("                  (SELECT KK2811_GENE.KKTK_SVC_KEI_NO, MAX(KK2811_GENE.RSV_APLY_YMD || KK2811_GENE.GENE_ADD_DTM) AS KK2811_MAX  ")
		.append("                     FROM  KK_T_KKOP_SVC_KEI KK2811_GENE  ")
		.append("                    WHERE KK2811_GENE.KKTK_SVC_KEI_NO = KK2811.KKTK_SVC_KEI_NO  ")
		.append("                      AND   KK2811_GENE.KKOP_SVC_CD = 'G02'  ")
		.append("                      AND   KK2811_GENE.MK_FLG = '0'  ")
		.append("                    GROUP BY KK2811_GENE.KKTK_SVC_KEI_NO ) ")
		.append("           )) ")
		.append("         WHEN %s.TAKNKIKI_SBT_CD = 'E0' THEN ")
		.append("           ( ")
		.append("             SELECT KK0081.SVC_KEI_NO ")
		.append("               FROM KK_T_KAISEN_TG_SVKEI KK0241, KK_T_SVC_KEI KK0081  ")
		.append("              WHERE KK0241.SVC_KEI_KAISEN_UCWK_NO = %s.SVC_KEI_KAISEN_UCWK_NO  ")
		.append("                AND ((KK0241.KAISEN_UCWK_USE_STAYMD <> KK0241.KAISEN_UCWK_USE_ENDYMD  ")
		.append("                AND %s BETWEEN KK0241.KAISEN_UCWK_USE_STAYMD AND KK0241.KAISEN_UCWK_USE_ENDYMD) ")
		.append("                OR (KK0241.KAISEN_UCWK_USE_STAYMD = '20991231' AND KK0241.KAISEN_UCWK_USE_ENDYMD = '20991231'))  ")
		.append("                AND KK0241.MK_FLG = '0'  ")
		.append("                AND KK0081.SVC_KEI_NO = KK0241.SVC_KEI_NO  ")
		.append("                AND KK0081.SVC_KEI_STAT NOT IN ('910','920') ")
		.append("                AND KK0081.SVC_CD = '03' ")
		.append("                AND (KK0081.SVC_KEI_NO, KK0081.RSV_APLY_YMD || KK0081.GENE_ADD_DTM) =   ")
		.append("                   (SELECT KK0081_GENE.SVC_KEI_NO, MAX(KK0081_GENE.RSV_APLY_YMD || KK0081_GENE.GENE_ADD_DTM) AS KK0341_MAX  ")
		.append("                      FROM  KK_T_SVC_KEI KK0081_GENE  ")
		.append("                     WHERE KK0081_GENE.SVC_KEI_NO = KK0081.SVC_KEI_NO  ")
		.append("                       AND   KK0081_GENE.RSV_APLY_YMD <= %s  ")
		.append("                       AND   KK0081_GENE.RSV_APLY_CD IN ('1','2') ")
		.append("                       AND   KK0081_GENE.MK_FLG = '0'  ")
		.append("                    GROUP BY KK0081_GENE.SVC_KEI_NO ) ")
		.append("           ) ")
		.append("         END ")
		.append("     ELSE ")
		.append("         %s.SVC_KEI_NO ")
		.append("     END AS %s %s ");
		
		return String.format(sb.toString()
				, (comma == COMMA.LEFT ? "," : ""), kk0341Alias
				, kk0341Alias		// 宅内機器種別 'D0', '60', '70', '90' の変数(ONU/VDSLモデム/スプリッター/インラインフィルター)

				, kk0341Alias
				, kaisenDateRange
				, dateCondition

				, kk0341Alias
				, kaisenDateRange
				, dateCondition

				, kk0341Alias		// 宅内機器種別 'R0'、'S0' の変数(多機能ルーター、ＨＧＷ)

				, kk0341Alias
				, kaisenDateRange
				, dateCondition
				, kk0341Alias

				, kk0341Alias
				, kaisenDateRange
				, dateCondition
				, kk0341Alias

				, kk0341Alias		// 宅内機器種別 'E0' の変数(V-ONU)

				, kk0341Alias
				, kaisenDateRange
				, dateCondition

				, kk0341Alias
				, alias, (comma == COMMA.RIGHT ? "," : ""));
	}

	/**
	 * 機器提供サービス契約番号からサービス契約番号を引くSQLを返します。
	 * @param kk0341Alias 機器提供サービス契約テーブルのエイリアス
	 * @param alias 項目のエイリアス
	 * @param comma コンマの位置
	 * @param dateCondition 日付条件
	 * @return SQL
	 */
	public static String svcKeiNoFor2(String kk0341Alias, String alias, String kaisenDateRange, COMMA comma, String dateCondition)
	{
		StringBuffer sb = new StringBuffer();
		
		sb.append(" %s CASE %s.OYA_KEI_SKBT_CD ")
		.append("     WHEN '02' THEN ")
		.append("         CASE  ")
		.append("         WHEN %s.TAKNKIKI_SBT_CD IN ('D0', '60', '70', '90') THEN ")
		.append("           NVL(( ")
		.append("             SELECT SUBSTR(MAX(KK0241.KAISEN_UCWK_USE_STAYMD || KK0081.SVC_KEI_NO),9,10) AS SVC_KEI_NO ")
		.append("               FROM KK_T_KAISEN_TG_SVKEI KK0241, KK_T_SVC_KEI KK0081  ")
		.append("              WHERE KK0241.SVC_KEI_KAISEN_UCWK_NO = %s.SVC_KEI_KAISEN_UCWK_NO  ")
		.append("                AND ((KK0241.KAISEN_UCWK_USE_STAYMD <> KK0241.KAISEN_UCWK_USE_ENDYMD  ")
		.append("                AND %s BETWEEN KK0241.KAISEN_UCWK_USE_STAYMD AND KK0241.KAISEN_UCWK_USE_ENDYMD) ")
		.append("                OR (KK0241.KAISEN_UCWK_USE_STAYMD = '20991231' AND KK0241.KAISEN_UCWK_USE_ENDYMD = '20991231'))  ")
		.append("                AND KK0241.MK_FLG = '0'  ")
		.append("                AND KK0081.SVC_KEI_NO = KK0241.SVC_KEI_NO  ")
		.append("                AND KK0081.SVC_CD = '01' ")
		.append("                AND (KK0081.SVC_KEI_NO, KK0081.RSV_APLY_YMD || KK0081.GENE_ADD_DTM) =   ")
		.append("                  (SELECT KK0081_GENE.SVC_KEI_NO, MAX(KK0081_GENE.RSV_APLY_YMD || KK0081_GENE.GENE_ADD_DTM) AS KK0341_MAX  ")
		.append("                     FROM  KK_T_SVC_KEI KK0081_GENE  ")
		.append("                    WHERE KK0081_GENE.SVC_KEI_NO = KK0081.SVC_KEI_NO  ")
		.append("                      AND   KK0081_GENE.RSV_APLY_YMD <= %s ")
		.append("                      AND   KK0081_GENE.MK_FLG = '0'  ")
		.append("                      GROUP BY KK0081_GENE.SVC_KEI_NO ) ")
		.append("           ),( ")
		.append("             SELECT SUBSTR(MAX(KK0241.KAISEN_UCWK_USE_STAYMD || KK0081.SVC_KEI_NO),9,10) AS SVC_KEI_NO ")
		.append("               FROM KK_T_KAISEN_TG_SVKEI KK0241, KK_T_SVC_KEI KK0081  ")
		.append("              WHERE KK0241.SVC_KEI_KAISEN_UCWK_NO = %s.SVC_KEI_KAISEN_UCWK_NO  ")
		.append("                AND ((KK0241.KAISEN_UCWK_USE_STAYMD <> KK0241.KAISEN_UCWK_USE_ENDYMD  ")
		.append("                AND %s BETWEEN KK0241.KAISEN_UCWK_USE_STAYMD AND KK0241.KAISEN_UCWK_USE_ENDYMD) ")
		.append("                OR (KK0241.KAISEN_UCWK_USE_STAYMD = '20991231' AND KK0241.KAISEN_UCWK_USE_ENDYMD = '20991231'))  ")
		.append("                AND KK0241.MK_FLG = '0'  ")
		.append("                AND KK0081.SVC_KEI_NO = KK0241.SVC_KEI_NO  ")
		.append("                AND KK0081.SVC_CD = '02' ")
		.append("                AND (KK0081.SVC_KEI_NO, KK0081.RSV_APLY_YMD || KK0081.GENE_ADD_DTM) =   ")
		.append("                  (SELECT KK0081_GENE.SVC_KEI_NO, MAX(KK0081_GENE.RSV_APLY_YMD || KK0081_GENE.GENE_ADD_DTM) AS KK0341_MAX  ")
		.append("                     FROM  KK_T_SVC_KEI KK0081_GENE  ")
		.append("                    WHERE KK0081_GENE.SVC_KEI_NO = KK0081.SVC_KEI_NO  ")
		.append("                      AND   KK0081_GENE.RSV_APLY_YMD <= %s ")
		.append("                      AND   KK0081_GENE.MK_FLG = '0'  ")
		.append("                      GROUP BY KK0081_GENE.SVC_KEI_NO ) ")
		.append("           )) ")
// ANK-4315-00-00 MOD START
//		.append("         WHEN %s.TAKNKIKI_SBT_CD = 'R0' THEN ")
		.append("         WHEN %s.TAKNKIKI_SBT_CD IN ('R0','S0') THEN ")
// ANK-4315-00-00 MOD END
		.append("           NVL(( ")
		.append("             SELECT SUBSTR(MAX(KK0241.KAISEN_UCWK_USE_STAYMD || KK0081.SVC_KEI_NO),9,10) AS SVC_KEI_NO ")
		.append("               FROM KK_T_KAISEN_TG_SVKEI KK0241, KK_T_SVC_KEI KK0081, KK_T_KKOP_SVC_KEI KK2811  ")
		.append("              WHERE KK0241.SVC_KEI_KAISEN_UCWK_NO = %s.SVC_KEI_KAISEN_UCWK_NO  ")
		.append("                AND ((KK0241.KAISEN_UCWK_USE_STAYMD <> KK0241.KAISEN_UCWK_USE_ENDYMD  ")
		.append("                AND %s BETWEEN KK0241.KAISEN_UCWK_USE_STAYMD AND KK0241.KAISEN_UCWK_USE_ENDYMD) ")
		.append("                OR (KK0241.KAISEN_UCWK_USE_STAYMD = '20991231' AND KK0241.KAISEN_UCWK_USE_ENDYMD = '20991231'))  ")
		.append("                AND KK0241.MK_FLG = '0'  ")
		.append("                AND KK0081.SVC_KEI_NO = KK0241.SVC_KEI_NO  ")
		.append("                AND KK0081.SVC_CD = '01' ")
		.append("                AND (KK0081.SVC_KEI_NO, KK0081.RSV_APLY_YMD || KK0081.GENE_ADD_DTM) =  ")
		.append("                  (SELECT KK0081_GENE.SVC_KEI_NO, MAX(KK0081_GENE.RSV_APLY_YMD || KK0081_GENE.GENE_ADD_DTM) AS KK0081_MAX  ")
		.append("                     FROM  KK_T_SVC_KEI KK0081_GENE  ")
		.append("                    WHERE KK0081_GENE.SVC_KEI_NO = KK0241.SVC_KEI_NO  ")
		.append("                      AND   KK0081_GENE.RSV_APLY_YMD <= %s ")
		.append("                      AND   KK0081_GENE.MK_FLG = '0' ")
		.append("                    GROUP BY KK0081_GENE.SVC_KEI_NO ) ")
		.append("                AND KK2811.KKTK_SVC_KEI_NO = %s.KKTK_SVC_KEI_NO  ")
		.append("                AND KK2811.KKOP_SVC_CD = 'G01' ")
		.append("                AND (KK2811.KKTK_SVC_KEI_NO, KK2811.RSV_APLY_YMD || KK2811.GENE_ADD_DTM) =   ")
		.append("                  (SELECT KK2811_GENE.KKTK_SVC_KEI_NO, MAX(KK2811_GENE.RSV_APLY_YMD || KK2811_GENE.GENE_ADD_DTM) AS KK2811_MAX  ")
		.append("                     FROM  KK_T_KKOP_SVC_KEI KK2811_GENE  ")
		.append("                    WHERE KK2811_GENE.KKTK_SVC_KEI_NO = KK2811.KKTK_SVC_KEI_NO  ")
		.append("                      AND   KK2811_GENE.KKOP_SVC_CD = 'G01'  ")
		.append("                      AND   KK2811_GENE.MK_FLG = '0'  ")
		.append("                    GROUP BY KK2811_GENE.KKTK_SVC_KEI_NO ) ")
		.append("           ),( ")
		.append("             SELECT SUBSTR(MAX(KK0241.KAISEN_UCWK_USE_STAYMD || KK0081.SVC_KEI_NO),9,10) AS SVC_KEI_NO ")
		.append("               FROM KK_T_KAISEN_TG_SVKEI KK0241, KK_T_SVC_KEI KK0081, KK_T_KKOP_SVC_KEI KK2811  ")
		.append("              WHERE KK0241.SVC_KEI_KAISEN_UCWK_NO = %s.SVC_KEI_KAISEN_UCWK_NO  ")
		.append("                AND ((KK0241.KAISEN_UCWK_USE_STAYMD <> KK0241.KAISEN_UCWK_USE_ENDYMD  ")
		.append("                AND %s BETWEEN KK0241.KAISEN_UCWK_USE_STAYMD AND KK0241.KAISEN_UCWK_USE_ENDYMD) ")
		.append("                OR (KK0241.KAISEN_UCWK_USE_STAYMD = '20991231' AND KK0241.KAISEN_UCWK_USE_ENDYMD = '20991231'))  ")
		.append("                AND KK0241.MK_FLG = '0'  ")
		.append("                AND KK0081.SVC_KEI_NO = KK0241.SVC_KEI_NO  ")
		.append("                AND KK0081.SVC_CD = '02' ")
		.append("                AND (KK0081.SVC_KEI_NO, KK0081.RSV_APLY_YMD || KK0081.GENE_ADD_DTM) =  ")
		.append("                  (SELECT KK0081_GENE.SVC_KEI_NO, MAX(KK0081_GENE.RSV_APLY_YMD || KK0081_GENE.GENE_ADD_DTM) AS KK0081_MAX  ")
		.append("                     FROM  KK_T_SVC_KEI KK0081_GENE  ")
		.append("                    WHERE KK0081_GENE.SVC_KEI_NO = KK0241.SVC_KEI_NO  ")
		.append("                      AND   KK0081_GENE.RSV_APLY_YMD <= %s ")
		.append("                      AND   KK0081_GENE.MK_FLG = '0' ")
		.append("                    GROUP BY KK0081_GENE.SVC_KEI_NO ) ")
		.append("                AND KK2811.KKTK_SVC_KEI_NO = %s.KKTK_SVC_KEI_NO  ")
		.append("                AND KK2811.KKOP_SVC_CD = 'G02' ")
		.append("                AND (KK2811.KKTK_SVC_KEI_NO, KK2811.RSV_APLY_YMD || KK2811.GENE_ADD_DTM) =   ")
		.append("                  (SELECT KK2811_GENE.KKTK_SVC_KEI_NO, MAX(KK2811_GENE.RSV_APLY_YMD || KK2811_GENE.GENE_ADD_DTM) AS KK2811_MAX  ")
		.append("                     FROM  KK_T_KKOP_SVC_KEI KK2811_GENE  ")
		.append("                    WHERE KK2811_GENE.KKTK_SVC_KEI_NO = KK2811.KKTK_SVC_KEI_NO  ")
		.append("                      AND   KK2811_GENE.KKOP_SVC_CD = 'G02'  ")
		.append("                      AND   KK2811_GENE.MK_FLG = '0'  ")
		.append("                    GROUP BY KK2811_GENE.KKTK_SVC_KEI_NO ) ")
		.append("           )) ")
		.append("         WHEN %s.TAKNKIKI_SBT_CD = 'E0' THEN ")
		.append("           ( ")
		.append("             SELECT SUBSTR(MAX(KK0241.KAISEN_UCWK_USE_STAYMD || KK0081.SVC_KEI_NO),9,10) AS SVC_KEI_NO ")
		.append("               FROM KK_T_KAISEN_TG_SVKEI KK0241, KK_T_SVC_KEI KK0081  ")
		.append("              WHERE KK0241.SVC_KEI_KAISEN_UCWK_NO = %s.SVC_KEI_KAISEN_UCWK_NO  ")
		.append("                AND ((KK0241.KAISEN_UCWK_USE_STAYMD <> KK0241.KAISEN_UCWK_USE_ENDYMD  ")
		.append("                AND %s BETWEEN KK0241.KAISEN_UCWK_USE_STAYMD AND KK0241.KAISEN_UCWK_USE_ENDYMD) ")
		.append("                OR (KK0241.KAISEN_UCWK_USE_STAYMD = '20991231' AND KK0241.KAISEN_UCWK_USE_ENDYMD = '20991231'))  ")
		.append("                AND KK0241.MK_FLG = '0'  ")
		.append("                AND KK0081.SVC_KEI_NO = KK0241.SVC_KEI_NO  ")
		.append("                AND KK0081.SVC_CD = '03' ")
		.append("                AND (KK0081.SVC_KEI_NO, KK0081.RSV_APLY_YMD || KK0081.GENE_ADD_DTM) =   ")
		.append("                  (SELECT KK0081_GENE.SVC_KEI_NO, MAX(KK0081_GENE.RSV_APLY_YMD || KK0081_GENE.GENE_ADD_DTM) AS KK0341_MAX  ")
		.append("                     FROM  KK_T_SVC_KEI KK0081_GENE  ")
		.append("                    WHERE KK0081_GENE.SVC_KEI_NO = KK0081.SVC_KEI_NO  ")
		.append("                      AND   KK0081_GENE.RSV_APLY_YMD <= %s ")
		.append("                      AND   KK0081_GENE.MK_FLG = '0'  ")
		.append("                      GROUP BY KK0081_GENE.SVC_KEI_NO ) ")
		.append("           ) ")
		.append("         END ")
		.append("     ELSE ")
		.append("         %s.SVC_KEI_NO ")
		.append("     END AS %s %s ");
		
		return String.format(sb.toString()
				, (comma == COMMA.LEFT ? "," : ""), kk0341Alias

				, kk0341Alias		// 宅内機器種別 'D0', '60', '70', '90' の変数(ONU/VDSLモデム/スプリッター/インラインフィルター)

				, kk0341Alias
				, kaisenDateRange
				, dateCondition

				, kk0341Alias
				, kaisenDateRange
				, dateCondition

				, kk0341Alias		// 宅内機器種別 'R0'、'S0' の変数(多機能ルーター、ＨＧＷ)

				, kk0341Alias
				, kaisenDateRange
				, dateCondition
				, kk0341Alias

				, kk0341Alias
				, kaisenDateRange
				, dateCondition
				, kk0341Alias

				, kk0341Alias		// 宅内機器種別 'E0' の変数(V-ONU)

				, kk0341Alias
				, kaisenDateRange
				, dateCondition

				, kk0341Alias
				, alias, (comma == COMMA.RIGHT ? "," : ""));
	}
	
	/**
	 * 機器提供サービス契約番号からサービス契約番号を引くSQLを返します。
	 * 置換すべきパラメータは運用日付＊7
	 * @param kk0341Alias 機器提供サービス契約テーブルのエイリアス
	 * @param alias 項目のエイリアス
	 * @param comma コンマの位置
	 * @return SQL
	 */
	public static String svcKeiNoForTel(String kk0341Alias, String alias, String kaisenDateRange, COMMA comma)
	{
		return svcKeiNoForTel(kk0341Alias, alias, kaisenDateRange, comma, "SUBSTR(?, 0, 8)");
	}
	
	/**
	 * 機器提供サービス契約番号から電話のサービス契約番号を引くSQLを返します。
	 * @param kk0341Alias 機器提供サービス契約テーブルのエイリアス
	 * @param alias 項目のエイリアス
	 * @param comma コンマの位置
	 * @param dateCondition 日付条件
	 * @return SQL
	 */
	public static String svcKeiNoForTel(String kk0341Alias, String alias, String kaisenDateRange, COMMA comma, String dateCondition)
	{
		StringBufferWrapper sb = new StringBufferWrapper();
		
		sb.append(" %s CASE ")
// ANK-4315-00-00 MOD START
//		.append("      WHEN %s.TAKNKIKI_SBT_CD = 'R0' THEN ")
		.append("      WHEN %s.TAKNKIKI_SBT_CD IN ('R0','S0') THEN ")
// ANK-4315-00-00 MOD END
		.append("           ( ")
		.append("             SELECT KK0081.SVC_KEI_NO ")
		.append("               FROM KK_T_KAISEN_TG_SVKEI KK0241, KK_T_SVC_KEI KK0081, KK_T_KKOP_SVC_KEI KK2811  ")
		.append("              WHERE KK0241.SVC_KEI_KAISEN_UCWK_NO = %s.SVC_KEI_KAISEN_UCWK_NO  ")
		.append("                AND ((KK0241.KAISEN_UCWK_USE_STAYMD <> KK0241.KAISEN_UCWK_USE_ENDYMD  ")
		.append("                AND %s BETWEEN KK0241.KAISEN_UCWK_USE_STAYMD AND KK0241.KAISEN_UCWK_USE_ENDYMD) ")
		.append("                OR (KK0241.KAISEN_UCWK_USE_STAYMD = '20991231' AND KK0241.KAISEN_UCWK_USE_ENDYMD = '20991231'))  ")
		.append("                AND KK0241.MK_FLG = '0'  ")
		.append("                AND KK0081.SVC_KEI_NO = KK0241.SVC_KEI_NO  ")
		.append("                AND KK0081.SVC_CD = '02' ")
		.append("                AND (KK0081.SVC_KEI_NO, KK0081.RSV_APLY_YMD || KK0081.GENE_ADD_DTM) =  ")
		.append("                  (SELECT KK0081_GENE.SVC_KEI_NO, MAX(KK0081_GENE.RSV_APLY_YMD || KK0081_GENE.GENE_ADD_DTM) AS KK0081_MAX  ")
		.append("                     FROM  KK_T_SVC_KEI KK0081_GENE  ")
		.append("                    WHERE KK0081_GENE.SVC_KEI_NO = KK0241.SVC_KEI_NO  ")
		.append("                      AND   KK0081_GENE.RSV_APLY_YMD <= %s ")
		.append("                      AND   KK0081_GENE.RSV_APLY_CD IN ('1','2') ")
		.append("                      AND   KK0081_GENE.MK_FLG = '0' ")
		.append("                    GROUP BY KK0081_GENE.SVC_KEI_NO ) ")
		.append("                AND KK2811.KKTK_SVC_KEI_NO = KK0341.KKTK_SVC_KEI_NO  ")
		.append("                AND KK2811.KKOP_SVC_KEI_STAT NOT IN ('910','920') ")
		.append("                AND KK2811.KKOP_SVC_CD = 'G02' ")
		.append("                AND (KK2811.KKTK_SVC_KEI_NO, KK2811.RSV_APLY_YMD || KK2811.GENE_ADD_DTM) =   ")
		.append("                  (SELECT KK2811_GENE.KKTK_SVC_KEI_NO, MAX(KK2811_GENE.RSV_APLY_YMD || KK2811_GENE.GENE_ADD_DTM) AS KK2811_MAX  ")
		.append("                     FROM  KK_T_KKOP_SVC_KEI KK2811_GENE  ")
		.append("                    WHERE KK2811_GENE.KKTK_SVC_KEI_NO = KK2811.KKTK_SVC_KEI_NO  ")
		.append("                      AND   KK2811_GENE.KKOP_SVC_CD = 'G02'  ")
		.append("                      AND   KK2811_GENE.MK_FLG = '0'  ")
		.append("                    GROUP BY KK2811_GENE.KKTK_SVC_KEI_NO ) ")
		.append("           ) ")
		.append("      WHEN %s.TAKNKIKI_SBT_CD = '50' THEN ")
		.append("         %s.SVC_KEI_NO ")
		.append("      ELSE NULL ")
		.append("      END AS %s %s ");
		
		return String.format(sb.toString()
				, (comma == COMMA.LEFT ? "," : "")
				, kk0341Alias
				, kk0341Alias
				, kaisenDateRange
				, dateCondition
				, kk0341Alias
				, kk0341Alias
				, alias
				, (comma == COMMA.RIGHT ? "," : ""));
	}

	/**
	 * 機器提供サービス契約番号からサービス契約番号を引くSQLを返します。
	 * 置換すべきパラメータは運用日付＊7
	 * @param kk0341Alias 機器提供サービス契約テーブルのエイリアス
	 * @param alias 項目のエイリアス
	 * @param comma コンマの位置
	 * @return SQL
	 */
	public static String svcKeiNoForTel2(String kk0341Alias, String alias, String kaisenDateRange, COMMA comma)
	{
		return svcKeiNoForTel2(kk0341Alias, alias, kaisenDateRange, comma, "SUBSTR(?, 0, 8)");
	}
	
	/**
	 * 機器提供サービス契約番号から電話のサービス契約番号を引くSQLを返します。
	 * @param kk0341Alias 機器提供サービス契約テーブルのエイリアス
	 * @param alias 項目のエイリアス
	 * @param comma コンマの位置
	 * @param dateCondition 日付条件
	 * @return SQL
	 */
	public static String svcKeiNoForTel2(String kk0341Alias, String alias, String kaisenDateRange, COMMA comma, String dateCondition)
	{
		StringBufferWrapper sb = new StringBufferWrapper();
		
		sb.append(" %s CASE ")
// ANK-4315-00-00 MOD START
//		.append("      WHEN %s.TAKNKIKI_SBT_CD = 'R0' THEN ")
		.append("      WHEN %s.TAKNKIKI_SBT_CD IN ('R0','S0') THEN ")
// ANK-4315-00-00 MOD END
		.append("           ( ")
		.append("             SELECT SUBSTR(MAX(KK0241.KAISEN_UCWK_USE_STAYMD || KK0081.SVC_KEI_NO),9,10) AS SVC_KEI_NO ")
		.append("               FROM KK_T_KAISEN_TG_SVKEI KK0241, KK_T_SVC_KEI KK0081, KK_T_KKOP_SVC_KEI KK2811  ")
		.append("              WHERE KK0241.SVC_KEI_KAISEN_UCWK_NO = %s.SVC_KEI_KAISEN_UCWK_NO  ")
		.append("                AND ((KK0241.KAISEN_UCWK_USE_STAYMD <> KK0241.KAISEN_UCWK_USE_ENDYMD  ")
		.append("                AND %s BETWEEN KK0241.KAISEN_UCWK_USE_STAYMD AND KK0241.KAISEN_UCWK_USE_ENDYMD) ")
		.append("                OR (KK0241.KAISEN_UCWK_USE_STAYMD = '20991231' AND KK0241.KAISEN_UCWK_USE_ENDYMD = '20991231'))  ")
		.append("                AND KK0241.MK_FLG = '0'  ")
		.append("                AND KK0081.SVC_KEI_NO = KK0241.SVC_KEI_NO  ")
		.append("                AND KK0081.SVC_CD = '02' ")
		.append("                AND (KK0081.SVC_KEI_NO, KK0081.RSV_APLY_YMD || KK0081.GENE_ADD_DTM) =  ")
		.append("                  (SELECT KK0081_GENE.SVC_KEI_NO, MAX(KK0081_GENE.RSV_APLY_YMD || KK0081_GENE.GENE_ADD_DTM) AS KK0081_MAX  ")
		.append("                     FROM  KK_T_SVC_KEI KK0081_GENE  ")
		.append("                    WHERE KK0081_GENE.SVC_KEI_NO = KK0241.SVC_KEI_NO  ")
		.append("                      AND   KK0081_GENE.RSV_APLY_YMD <= %s ")
		.append("                      AND   KK0081_GENE.RSV_APLY_CD IN ('1','2') ")
		.append("                      AND   KK0081_GENE.MK_FLG = '0' ")
		.append("                    GROUP BY KK0081_GENE.SVC_KEI_NO ) ")
		.append("                AND KK2811.KKTK_SVC_KEI_NO = KK0341.KKTK_SVC_KEI_NO  ")
		.append("                AND KK2811.KKOP_SVC_KEI_STAT NOT IN ('910','920') ")
		.append("                AND KK2811.KKOP_SVC_CD = 'G02' ")
		.append("                AND (KK2811.KKTK_SVC_KEI_NO, KK2811.RSV_APLY_YMD || KK2811.GENE_ADD_DTM) =   ")
		.append("                  (SELECT KK2811_GENE.KKTK_SVC_KEI_NO, MAX(KK2811_GENE.RSV_APLY_YMD || KK2811_GENE.GENE_ADD_DTM) AS KK2811_MAX  ")
		.append("                     FROM  KK_T_KKOP_SVC_KEI KK2811_GENE  ")
		.append("                    WHERE KK2811_GENE.KKTK_SVC_KEI_NO = KK2811.KKTK_SVC_KEI_NO  ")
		.append("                      AND   KK2811_GENE.KKOP_SVC_CD = 'G02'  ")
		.append("                      AND   KK2811_GENE.MK_FLG = '0'  ")
		.append("                    GROUP BY KK2811_GENE.KKTK_SVC_KEI_NO ) ")
		.append("           ) ")
		.append("      WHEN %s.TAKNKIKI_SBT_CD = '50' THEN ")
		.append("         %s.SVC_KEI_NO ")
		.append("      ELSE NULL ")
		.append("      END AS %s %s ");
		
		return String.format(sb.toString()
				, (comma == COMMA.LEFT ? "," : "")
				, kk0341Alias
				, kk0341Alias
				, kaisenDateRange
				, dateCondition
				, kk0341Alias
				, kk0341Alias
				, alias
				, (comma == COMMA.RIGHT ? "," : ""));
	}

	/**
	 * 世代管理テーブルをjoinします
	 * @param table 結合対象テーブル名
	 * @param tableAlias  tableのエイリアス
	 * @param joinFrom join元のテーブル(参照可能なエイリアス)
	 * @param joinColumn 結合するカラム
	 * @return sql
	 */
	public static String outerJoinToGen(String table, String tableAlias, String joinFrom, String joinColumn)
	{
		return joinToGenTable(table, tableAlias, joinFrom, joinColumn, "LEFT OUTER", "?");
	}

	/**
	 * 世代管理テーブルをjoinします
	 * @param table 結合対象テーブル名
	 * @param tableAlias  tableのエイリアス
	 * @param joinFrom join元のテーブル(参照可能なエイリアス)
	 * @param joinColumn 結合するカラム
	 * @return sql
	 */
	public static String innerJoinToGen(String table, String tableAlias, String joinFrom, String joinColumn)
	{
		return joinToGenTable(table, tableAlias, joinFrom, joinColumn, "INNER", "?");
	}


	/**
	 * 世代管理テーブルをjoinします
	 * @param table 結合対象テーブル名
	 * @param tableAlias  tableのエイリアス
	 * @param joinFrom join元のテーブル(参照可能なエイリアス)
	 * @param joinColumn 結合するカラム
	 * @param joinMode 外部結合なのか内部結合なのか
	 * @param additionalConditions 追加の結合条件
	 * @return sql
	 */
	public static String joinToGenTable(String table, String tableAlias, String joinFrom, String joinColumn, 
										String joinMode, String dateConnection, String...additionalConditions)
	{
		return joinToGenTable(table, tableAlias, joinFrom, joinColumn, joinMode, dateConnection, true, additionalConditions);
	}
	
	
	/**
	 * 世代管理テーブルをjoinします
	 * @param table 結合対象テーブル名
	 * @param tableAlias  tableのエイリアス
	 * @param joinFrom join元のテーブル(参照可能なエイリアス)
	 * @param joinColumn 結合するカラム
	 * @param joinMode 外部結合なのか内部結合なのか
	 * @param additionalConditions 追加の結合条件
	 * @return sql
	 */
	public static String joinToGenTable(String table, String tableAlias, String joinFrom, String joinColumn, 
										String joinMode, String dateConnection, boolean needRsvCd, String...additionalConditions)
	{
		int joinHash = (table + joinFrom + joinColumn).hashCode() % 1000;
		if (joinHash < 0)
		{
			joinHash *= -1;
		}
		
		String generationTableAlias = String.format("%s_%d", table, joinHash);
		
		StringBuffer additionalWhere = new StringBuffer();
		if (additionalConditions != null && additionalConditions.length > 0)
		{
			for (String additionalCondition : additionalConditions)
			{
				additionalWhere.append(String.format(" AND %s.%s = %s.%s ", generationTableAlias, additionalCondition, joinFrom, additionalCondition));
			}
		}
		
		String joinOnRsvCd = "";
		if (needRsvCd) {
			joinOnRsvCd = String.format(" AND %s.RSV_APLY_CD = '2' ", generationTableAlias);
		}
		
		StringBufferWrapper sb = new StringBufferWrapper
		       (" %s JOIN %s %s ")
		.append("      ON %s.%s = %s.%s ")
		.append("     AND %s.RSV_APLY_YMD || %s.GENE_ADD_DTM =  ")
		.append("     (SELECT MAX(%s.RSV_APLY_YMD || %s.GENE_ADD_DTM) ")
		.append("        FROM %s %s ")
		.append("       WHERE %s.%s = %s.%s ")
		.append(          joinOnRsvCd)
		.append("         AND %s.RSV_APLY_YMD <= %s ")
		.append("         %s ")
		.append("         AND %s.MK_FLG = '0') ");
		
		return String.format(sb.toString()
				, joinMode, table, tableAlias
				, tableAlias, joinColumn, joinFrom, joinColumn
				, tableAlias, tableAlias
				, generationTableAlias, generationTableAlias
				, table, generationTableAlias
				, generationTableAlias, joinColumn, tableAlias, joinColumn
				, generationTableAlias, dateConnection
				, additionalWhere.toString()
				, generationTableAlias);
	}
	

	/**
	 * 機器提供サービス契約をjoinします
	 * @param tableAlias  KK_T_KKTK_SVC_KEIのエイリアス
	 * @param joinFrom join元のテーブル(参照可能なエイリアス)
	 * @param joinColumn 結合するカラム
	 * @param kikiChgNo のカラム名
	 * @param joinMode 外部結合なのか内部結合なのか
	 * @return sql
	 */
	public static String joinKKTKSvc(String tableAlias, String joinFrom, String joinColumn, String kikiChgNo, String joinMode)
	{
		int joinHash = (joinFrom + joinColumn).hashCode() % 1000;
		if (joinHash < 0)
		{
			joinHash *= -1;
		}
		
		String generationTableAlias = String.format("%s_%d", "KK0341", joinHash);
		
		StringBufferWrapper sb = new StringBufferWrapper
		       (" %s JOIN KK_T_KKTK_SVC_KEI %s ")
		.append("      ON %s.%s = %s.%s ")
		.append("     AND %s.GENE_ADD_DTM =  ")
		.append("     (SELECT MAX(%s.GENE_ADD_DTM) ")
		.append("        FROM KK_T_KKTK_SVC_KEI %s ")
		.append("       WHERE %s.%s = %s.%s ")
		.append("         AND %s.KIKI_CHG_NO = %s.KIKI_CHG_NO ")
		.append("         AND %s.RSV_APLY_CD IN ('1', '2') ")
		.append("         AND %s.MK_FLG = '0') ")
		.append("     AND %s.KIKI_CHG_NO = %s.%s ");
		
		String ret = String.format(sb.toString()
				, joinMode, tableAlias
				, tableAlias, joinColumn, joinFrom, joinColumn
				, tableAlias
				, generationTableAlias
				, generationTableAlias
				, generationTableAlias, joinColumn, tableAlias, joinColumn
				, generationTableAlias, joinFrom
				, generationTableAlias
				, generationTableAlias
				, tableAlias, joinFrom, kikiChgNo);
		
		return ret;
	}

	
	/**
	 * 機器提供サービス契約をjoinします
	 * @param tableAlias  KK_T_KKTK_SVC_KEIのエイリアス
	 * @param joinFrom join元のテーブル(参照可能なエイリアス)
	 * @param joinColumn 結合するカラム
	 * @param kikiChgNo のカラム名
	 * @param joinMode 外部結合なのか内部結合なのか
	 * @return sql
	 */
	public static String joinKKTKSvc2(String tableAlias, String joinFrom, String joinColumn, String kikiChgNo, String joinMode)
	{
		int joinHash = (joinFrom + joinColumn).hashCode() % 1000;
		if (joinHash < 0)
		{
			joinHash *= -1;
		}
		
		String generationTableAlias = String.format("%s_%d", "KK0341", joinHash);
		
		StringBufferWrapper sb = new StringBufferWrapper
		       (" %s JOIN KK_T_KKTK_SVC_KEI %s ")
		.append("      ON %s.%s = %s.%s ")
		.append("     AND %s.GENE_ADD_DTM =  ")
		.append("     (SELECT MAX(%s.GENE_ADD_DTM) ")
		.append("        FROM KK_T_KKTK_SVC_KEI %s ")
		.append("       WHERE %s.%s = %s.%s ")
		.append("         AND %s.KIKI_CHG_NO = %s.KIKI_CHG_NO ")
		.append("         AND %s.MK_FLG = '0') ")
		.append("     AND %s.KIKI_CHG_NO = %s.%s ");
		
		String ret = String.format(sb.toString()
				, joinMode, tableAlias
				, tableAlias, joinColumn, joinFrom, joinColumn
				, tableAlias
				, generationTableAlias
				, generationTableAlias
				, generationTableAlias, joinColumn, tableAlias, joinColumn
				, generationTableAlias, joinFrom
				, generationTableAlias
				, tableAlias, joinFrom, kikiChgNo);
		
		return ret;
	}

	
	/**
	 * 指定回数パラメータを設定します。
	 * @param param パラメータ名
	 * @param times 回数
	 * @param index 現インデックス
	 * @param inMsg メッセージ
	 * @param pstmt ステートメント
	 * @return 新インデックス
	 * @throws SQLException
	 */
	public static int setParamTimes(String param, int times, int index, CAANMsg inMsg, PreparedStatement pstmt) throws SQLException
	{
		for (int i=0; i<times; i++)
		{
			CAANJDBCUtil.setParam(pstmt, index++, inMsg.getObject(param));
		}
		return index;
	}
	

	/**
	 * リソースを解放します。
	 * @param statement 解放対象のステートメント
	 * @param statement 解放対象のステートメント
	 * @return 例外発生時
	 */
	public static SQLException close (Statement statement, ResultSet resultset)
	{
		return close (new Statement [] {statement}, new ResultSet [] {resultset});
	}
	/**
	 * リソースを解放します。
	 * @param statement1 解放対象のステートメント
	 * @param statement2 解放対象のステートメント
	 * @param resultSet1 解放対象のリザルトセット
	 * @param resultSet2 解放対象のリザルトセット
	 * @return 例外発生時
	 */
	public static SQLException close (Statement statement1, Statement statement2, ResultSet resultset1, ResultSet resultset2)
	{
		return close (new Statement [] {statement1, statement2}, new ResultSet [] {resultset1, resultset2});
	}
	/**
	 * リソースを解放します。
	 * @param statements 解放対象のステートメント
	 * @param resultSets 解放対象のリザルトセット
	 * @return 例外発生時
	 */
	public static SQLException close (Statement [] statements, ResultSet [] resultsets)
	{
		SQLException exceptionOnCloseResultSet = close(resultsets);
		SQLException exceptionOnCloseStatement = close(statements);

		if (exceptionOnCloseResultSet != null)
		{
			return exceptionOnCloseResultSet;
		}
		if (exceptionOnCloseStatement != null)
		{
			return exceptionOnCloseStatement;
		}
		return null;
	}

	/**
	 * リソースを解放します。
	 * @param statements 解放対象のステートメント
	 * @return エラー情報
	 */
	private static SQLException close (Statement ... statements)
	{
		SQLException exception = null;
		
		for (Statement statement : statements)
		{
			if (statement == null)
			{
				continue;
			}
			
			try 
			{
				statement.close();
			}
			catch (SQLException e)
			{
				exception = e;
			}
		}
		
		return exception;
	}
	/**
	 * リソースを解放します。
	 * @param resultSets 解放対象のリザルトセット
	 * @return エラー情報
	 */
	private static SQLException close (ResultSet ... resultSets)
	{
		SQLException exception = null;
		
		for (ResultSet resultSet : resultSets)
		{
			if (resultSet == null)
			{
				continue;
			}
			
			try 
			{
				resultSet.close();
			}
			catch (SQLException e)
			{
				exception = e;
			}
		}
		
		return exception;
	}
	

	
	/**
	 * ResultSetからデータを引き上げます
	 * @param rs ResultSet
	 * @return 取得データ
	 * @throws SQLException エラー時
	 */
	public static List<Map<String, Object>> resultSetToListOfMap(ResultSet rs) throws SQLException
	{
		List<String> cols = new ArrayList<String>();
		ResultSetMetaData rsm = rs.getMetaData();
		int colCount = rsm.getColumnCount();
		for (int i = 1;i <= colCount; i++)
		{
			cols.add(rsm.getColumnName(i));
		}
		
		return resultSetToListOfMap(rs, cols.toArray(new String [colCount]));
	}
	
	/**
	 * ResultSetからデータを引き上げます
	 * @param rs ResultSet
	 * @return 取得データ
	 * @param cols 取得対象カラム名
	 * @throws SQLException エラー時
	 */
	public static List<Map<String, Object>> resultSetToListOfMap(ResultSet rs, String ... cols) throws SQLException
	{
		List<Map<String, Object>> list = new ArrayList<Map<String,Object>>();
		
		while (rs.next())
		{
			
			Map<String,Object> data = mapInstance();

			for (String col : cols)
			{
				Object val = rs.getObject(col.toUpperCase());
				data.put(col.toLowerCase(), val);

				JSYejbLog.outlog(null, JSYejbLog.DEBUG, JDKModelCommon.class, String.format ("set \"%s\" to \"%s\".", val, col));
			}
			
			list.add(data);
		}
		JSYejbLog.outlog(null, JSYejbLog.DEBUG, JDKModelCommon.class, String.format("Fetch %d lines.", list.size()));
		
		return list;
	}


	/**
	 * キー配列を使用して、CAANMsgから入力データをMapに引き上げます
	 * @param map データ格納先のマップ
	 * @param msg 入力データ
	 * @param keyAndTypes 項目定義
	 * @return マップ
	 */
	private static Map<String, Object> inMsgToMap(Map<String, Object> map, CAANMsg msg, Object[][] keyAndTypes)
	{
		if (JDKCommonUtil.isNull(keyAndTypes))
		{
			return map;
		}
		
		if (msg == null) {
			return map;
		}
		
		for (Object[] keyAndType : keyAndTypes)
		{
			String key = keyAndType[0].toString();
			String type = keyAndType[1].toString();
			
			String val = "";
			if ("int".equals(type))
			{
				val = Integer.toString(msg.getInt(key));
				map.put(key, val);
			}
			else if ("String".equals(type))
			{
				val = msg.getString(key);
				map.put(key, val);
			}
			else if (type.endsWith("[]"))
			{
				String listType = type.substring(0, type.length() - 2);

				List<Map<String, Object>> list = new ArrayList<Map<String,Object>>();
				@SuppressWarnings("unchecked")
				Class subListClass = null;
				try 
				{
					subListClass = Class.forName(listType);
				}
				catch (ClassNotFoundException e)
				{
//					System.out.println (e);
					continue;
				}
				
				map.put(key, list);
				
				CAANMsg[] subMsgs = msg.getCAANMsgList(key);
				if (null == subMsgs)
				{
					continue;
				}

				for (CAANMsg subMessage : subMsgs)
				{
					list.add(msgToMap(subMessage, subListClass));
				}
			}
			
			else
			{
				// error?
			}
		}
		
		return map;
	}
	
	/**
	 * CAANMsgをMapの階層構造に変換します。
	 * @param msg SerivceI/Fの入力
	 * @param clazz 入力の項目名が定義されているクラス
	 * @return マップ
	 */
	public static Map<String, Object> msgToMap(CAANMsg msg, Class<?> clazz)
	{
		Field contentsField = null;
		try
		{
			contentsField = clazz.getDeclaredField("CONTENTS");
		}
		catch (NoSuchFieldException e)
		{
//			System.out.println(e.getMessage());
			return null;
		}
		
		contentsField.setAccessible(true);
		
		Object[][] contents = null;
		try
		{
			contents = (Object[][])contentsField.get(contentsField);
		}
		catch (IllegalAccessException e)
		{
			return null;
		}
		
		return inMsgToMap(mapInstance(), msg, contents);
	}
	
	
	
	private static final Map<String, String> TK_COLUMN_TRANSLATIONS = new HashMap<String, String>();
	static
	{
		TK_COLUMN_TRANSLATIONS.put("key_kihon_upd_dttm",    "MOD_DTTM");
		TK_COLUMN_TRANSLATIONS.put("soko_syukka_ymd",       "SOKO_SHKA_YMD");
		TK_COLUMN_TRANSLATIONS.put("yobih_flg",             "YOBI_GDS_FLG");
		TK_COLUMN_TRANSLATIONS.put("ybkiki_shka_fin_num",   "YOBI_KKSHKA_FIN_NUM");
		TK_COLUMN_TRANSLATIONS.put("shelf_mv_shka_fin_num", "SLF_MV_SHKA_FIN_NUM");
		TK_COLUMN_TRANSLATIONS.put("shelf_mv_nyka_fin_num", "SLF_MV_NYUKA_FIN_NUM");
		TK_COLUMN_TRANSLATIONS.put("ybkiki_haiso_chu_num",  "YBKKHAI_CHU_NUM");
		TK_COLUMN_TRANSLATIONS.put("shelf_mv_sji_num",      "SLF_MV_SJI_NUM");
		TK_COLUMN_TRANSLATIONS.put("ybkiki_haiso_sji_num",  "YBKKHAI_SJI_NUM");
		TK_COLUMN_TRANSLATIONS.put("key_knri_plc_skbt_cd",  "KNRI_PLC_SKBT_CD");
		TK_COLUMN_TRANSLATIONS.put("key_knri_plc_cd",       "KNRI_PLC_CD");
		TK_COLUMN_TRANSLATIONS.put("key_knri_plc_slf_cd",   "KNRI_PLC_SLF_CD");
		TK_COLUMN_TRANSLATIONS.put("key_tk_mdl_cd_btry_zik","TK_MDL_CD");
		TK_COLUMN_TRANSLATIONS.put("key_gds_stat_cd",       "GDS_STAT_CD");
	}

	/**
	 * 更新用のステートメントを生成します。
	 * @param connection コネクション
	 * @param table 更新対象テーブル
	 * @param values 更新内容が格納されたマップ
	 * @param keies valuesのうち、キー項目として使用される項目
	 * @return ステートメント
	 * @throws SQLException
	 */
	public static int update(String table, Set<String> sets, Set<String> keies, String lockBy
							, Connection connection, Map<String, Object> values, Map<String, String> translation) throws SQLException
	{
		return update(table, sets, keies, lockBy, connection, values, null, translation);
	}
	/**
	 * 更新用のステートメントを生成します。
	 * @param connection コネクション
	 * @param table 更新対象テーブル
	 * @param values 更新内容が格納されたマップ
	 * @param keies valuesのうち、キー項目として使用される項目
	 * @return ステートメント
	 * @throws SQLException
	 */
	public static int update(String table, Set<String> sets, Set<String> keies, String lockBy
							, Connection connection, Map<String, Object> values, String epiFix, Map<String, String> translation) throws SQLException
	{
		List<Object> setParams = new ArrayList<Object>();
		List<Object> whereParams = new ArrayList<Object>();
		
		
		List<String> setStatements = new ArrayList<String>();
		for (String col : sets)
		{
			String realColName = col;
			if (TK_COLUMN_TRANSLATIONS.containsKey(col))
			{
				realColName = TK_COLUMN_TRANSLATIONS.get(col);
			}
			
			Object val = values.get(col);
			if (val == null)
			{
				continue;
			}
			if ("".equals(val.toString()))
			{
				continue;
			}
			
			if (epiFix != null && col.endsWith(epiFix))
			{
				realColName = col.substring(0, col.length() - epiFix.length());
			}
			if (translation != null && translation.containsKey(col))
			{
				realColName = translation.get(col);
			}
			
			if (realColName.endsWith("dttm") || realColName.endsWith("DTTM"))
			{
				setStatements.add(String.format("%s = to_timestamp(?, 'YYYYMMDDHHMISSFF')", realColName));
				setParams.add(values.get(realColName));
				continue;
			}
			
			if (col.endsWith("num"))
			{
				setStatements.add(String.format("%s = %s + ?", realColName, realColName));
			}
			else
			{
				setStatements.add(String.format("%s = ?", realColName));
			}
			setParams.add(values.get(col));
		}
		String setSqlFragment = JDKCommonUtil.join(",", setStatements);
		
		List<String> whereStatements = new ArrayList<String>();
		for (String whereKey : keies)
		{
			String realKey = whereKey;
			if (realKey.startsWith("key_"))
			{
				realKey = realKey.substring(4, realKey.length());
			}
			if (epiFix != null && realKey.endsWith(epiFix))
			{
				realKey = realKey.substring(0, realKey.length() - epiFix.length());
			}
			if (translation != null && translation.containsKey(whereKey))
			{
				realKey = translation.get(whereKey);
			}
			whereStatements.add(String.format("%s = ?", realKey));
			whereParams.add(values.get(whereKey));
		}
		String whereSqlFragment = JDKCommonUtil.join(" AND ", whereStatements);

		int index = 1;
		int updated = 0;
		PreparedStatement statement = null;
		PreparedStatement updateStatement = null;
		ResultSet rslt = null;
		
		try
		{
			if (!JDKCommonUtil.isNull(lockBy))
			{
				String lockSql = String.format("SELECT %s FROM %s WHERE %s FOR UPDATE", lockBy, table, whereSqlFragment);

				statement = connection.prepareStatement(lockSql.toString());
				index = 1;
				for (Object param : whereParams)
				{
					statement.setObject(index++, param);
				}
				rslt = statement.executeQuery();
			}

			StringBuffer updateSql = new StringBuffer(String.format("UPDATE %s SET ", table));
			updateSql.append(setSqlFragment);
			updateSql.append(" WHERE ");
			updateSql.append(whereSqlFragment);

			JSYejbLog.outlog(null, JSYejbLog.DEBUG, JDKModelCommon.class, updateSql);
			
			updateStatement = connection.prepareStatement(updateSql.toString());
			index = 1;
			for (Object param : setParams)
			{
				JSYejbLog.outlog(null, JSYejbLog.DEBUG, JDKModelCommon.class, String.format("sets %d : %s", index, param));
				updateStatement.setObject(index++, param);
			}
			for (Object param : whereParams)
			{
				JSYejbLog.outlog(null, JSYejbLog.DEBUG, JDKModelCommon.class, String.format("where %d : %s", index, param));
				updateStatement.setObject(index++, param);
			}
			
			updated = updateStatement.executeUpdate();
		} 
		catch ( SQLException e) 
		{
			throw e;
		}
		finally
		{
			SQLException e = close(statement, updateStatement);
			SQLException e1 = close(rslt);
			if (e != null || e1 != null)
			{
				throw (e == null ? e1 : e);
			}
		}
		
		return updated;
	}
	
	
	/**
	 * nullチェック付きのHashMapインスタンスを生成します。
	 * @return マップ
	 */
	private static Map<String, Object> mapInstance()
	{
		return new HashMap<String, Object>() {
			private static final long serialVersionUID = 1L;
			@Override
			public Object put(String key, Object val) {
//				System.out.println ("-- k : " + key + " v : " + val);
				return super.put(key, val == null ? "" : val);
			}
		};
	}
	
	
	/**
	 * 配列をセットに変換します。
	 * @param <E> 型情報
	 * @param es 変換元
	 * @return esのset
	 */
	public static <E> Set<E> setOf(E...es)
	{
		Set<E> set = new LinkedHashSet<E>();
		if (es == null)
		{
			return set;
		}
		for (E e : es)
		{
			set.add(e);
		}
		return set;
	}
	
	/**
	 * setOfのシンタックスシュガー
	 */
	public static <E> Set<E> whereOf(E...es)
	{
		return setOf(es);
	}
	
	/**
	 * リストの項目存在確認を行う
	 * @param listName リスト名
	 * @return true:存在する false:存在しない
	 */
	public static boolean existList(CAANMsg inMsg, AgentDispatchContext context, Object listName)
	{
		if (!inMsg.containsKeyOfMsgData(listName.toString())) 
		{
			return false;
		}
		
		CAANMsg[] list = inMsg.getCAANMsgList(listName.toString());
		if (list == null) 
		{
			return false;
		}
		
		return list.length != 0;
	}
	/**
	 * key項目の値を srcからdestに移送する
	 * @param key キー値
	 * @param msg 移送先
	 * @param takunaiMap 移送元
	 */
	@SuppressWarnings("unchecked")
	public static void transportData(String key, CAANMsg msg, Map takunaiMap) 
	{
		transportData(key, key, msg, takunaiMap);
	}

	/**
	 * keys項目の値を srcからdestに移送する
	 * @param keys キーリスト
	 * @param dest 移送先
	 * @param src 移送元
	 */
	@SuppressWarnings("unchecked")
	public static void transportAllData(List<String> keys, CAANMsg dest, Map src)
	{
		for (String key : keys)
		{
			if (!key.toLowerCase().endsWith(ERROR_FIELD_MARK)) 
			{	
				transportData(key, dest, src);
			}
		}

	}
	
	/**
	 * srcKey項目の値を destKey項目に srcから destへ移送する
	 * @param destKey destキー項目
	 * @param srcKey srcキー項目
	 * @param msg 移送先
	 * @param takunaiMap 移送元
	 */
	@SuppressWarnings("unchecked")
	private static void transportData(String destKey, String srcKey, CAANMsg msg, Map takunaiMap) 
	{
		if (!msg.containsKeyOfSchema(destKey)) 
		{
			return;
		}

		for (String key : new String [] {srcKey.toUpperCase(), srcKey.toLowerCase()})
		{
			if (takunaiMap.containsKey(key))
			{
				msg.set(destKey, takunaiMap.get(key).toString());
				return;
			}
		}

		msg.setNull(destKey);
	}
	
	/**
	 * エラー内容及びステータスを destに移送する
	 * @param msg 移送先
	 * @param takunaiMap 移送元
	 * @param destListKey 移送先リスト名
	 * @param srcListKey 移送元リスト名
	 */
	public static int transportStatus(CAANMsg msg, Map<String, Object> takunaiMap)
	{
		JSYejbLog.println(JSYejbLog.Message_Dump, JDKModelCommon.class, "CMD_RESULT_CD : " + takunaiMap.get(JDKStrConst.CMD_RESULT_CD));

		if(takunaiMap.get(JDKStrConst.CMD_RESULT_CD) != null && takunaiMap.get(JDKStrConst.CMD_RESULT_CD).equals("1"))
		{
			// StatusCodes.EXTERNAL_IF_ERR1は"6000"であり、『APLConst.properties』で「RETURN_MESSAGE_6000」は定義されていない為、
			// エラーとして扱われない為、エラーとして取り扱われる値に修正する。
			//msg.set("status", StatusCodes.EXTERNAL_IF_ERR1);
			msg.set("status", 9000);
			msg.set("error_level", "999");
			return StatusCodes.EXTERNAL_IF_ERR1;
		}
		
		JSYejbLog.println(JSYejbLog.Message_Dump, JDKModelCommon.class, 
				String.format("error_level=%s return_Cd=%s return_Message=%s"
							, takunaiMap.get(ERROR_LEVEL), takunaiMap.get(RETURN_CD), takunaiMap.get(RETURN_MESSAGE)));

		msg.set("error_level", takunaiMap.get(ERROR_LEVEL));
		msg.set("return_Cd", takunaiMap.get(RETURN_CD));
		msg.set("return_Message", takunaiMap.get(RETURN_MESSAGE));

		try
		{
			Integer status = Integer.parseInt((String)takunaiMap.get(RETURN_CD));
			// リターンコード0500の場合、既存のエラーハンドリングで処理されない事への対応を追加。
			// （マッパー及びCCで『APLConst.properties』で「RETURN_MESSAGE_XXXX」として登録されていない場合、エラーとして扱われない
			//   今後リターンコードが1000未満かつ0以外のコードが連携されて来た場合にもシステムエラーとして取り扱われるように修正する。）
			//if (status > 1100)
			if (status > 1100 || (status != 0 && status < 1000))
			{
				JSYejbLog.println(JSYejbLog.Message_Dump, JDKModelCommon.class, String.format("returnCd%dを受信しましたが1100として扱います : ", status));
				status = 1100;
			}
			msg.set("status", status);
		}
		catch (NumberFormatException e)
		{
			JSYejbLog.println(JSYejbLog.Message_Dump, JDKModelCommon.class, "不正なreturnCodeを受信 : " + takunaiMap.get(RETURN_CD));
			
			// StatusCodes.EXTERNAL_IF_ERR1は"6000"であり、『APLConst.properties』で「RETURN_MESSAGE_6000」は定義されていない為、
			// エラーとして扱われない為、エラーとして取り扱われる値に修正する。
			//msg.set("status", StatusCodes.EXTERNAL_IF_ERR1);
			msg.set("status", 9000);
			msg.set("error_level", "999");
		}

		return msg.getInt("status");
	}
	
	/**
	 * エラー内容及びステータスを destに移送する
	 * (移送先がリストで無い場合に使用する)
	 * @param dest 移送先
	 * @param src 移送元
	 * @param srcListKey 移送元リスト名
	 */
	@SuppressWarnings("unchecked")
	public static void transportErrorRecord(CAANMsg dest, Map<String, Object> src, 
			String srcListKey)
	{
		List<Map<String, Object>> list = (List<Map<String, Object>>)src.get(srcListKey);
		if (list == null || list.size() < 0)
		{
			return;
		}
		
		for (Map<String, Object> map : list)
		{
			transportErrorData(dest, map);
		}
	}

	/**
	 * エラー内容及びステータスを destに移送する
	 * @param dest 移送先
	 * @param src 移送元
	 * @param destListKey 移送先リスト名
	 * @param srcListKey 移送元リスト名
	 */
	@SuppressWarnings("unchecked")
	public static void transportErrorRecord(CAANMsg dest, Map<String, Object> src, 
			String destListKey, String srcListKey)
	{
		CAANMsg[] conditions = dest.getCAANMsgList(destListKey);
		List<Map<String, Object>> list = (List<Map<String, Object>>)src.get(srcListKey);
		if ((list == null || list.size() == 0) || (conditions == null || conditions.length == 0))
		{
			return;
		}
		
		int index = list.size() / conditions.length;
		for (int i=0; i<conditions.length; i++)
		{
			for (int j=0; j<index; j++) {
				transportErrorData(conditions[i], list.get((i*index)+j));
			}
		}
	}

	/**
	 * エラー内容及びステータスを destに移送する
	 * (ConditionとUpdateを持っている場合に使用する)
	 * @param dest 移送先
	 * @param takunaiMap 移送元
	 * @param conditionKey 移送先リスト名1
	 * @param updateKey 移送先リスト名2
	 * @param srcListKey 移送元リスト名
	 */
	@SuppressWarnings("unchecked")
	public static void transportErrorCondition(CAANMsg dest, Map<String, Object> takunaiMap, 
			String conditionKey, String updateKey, String srcListKey)
	{
		CAANMsg[] msg1 = dest.getCAANMsgList(conditionKey);
		CAANMsg[] msg2 = dest.getCAANMsgList(updateKey);
		List<Map<String, Object>> takunaiReturns = (List<Map<String, Object>>)takunaiMap.get(srcListKey);
		if (takunaiReturns == null || takunaiReturns.size() == 0)
		{
			return;
		}
		
		int size1 = msg1 == null ? 0 : msg1.length;
		for (int i=0; i<size1; i++)
		{
			if (msg1 != null && i < msg1.length)
			{
				transportErrorData(msg1[i], takunaiReturns.get(i*2));
				transportErrorData(msg1[i], takunaiReturns.get((i*2)+1));	
			}
		}

		int size2 = msg2 == null ? 0 : msg2.length;
		for (int i = 0; i < size2;i++)
		{
			if (msg2 != null && i < msg2.length)
			{
				int takunaiIndex = (i+size1);
				transportErrorData(msg2[i], takunaiReturns.get(takunaiIndex*2));
				transportErrorData(msg2[i], takunaiReturns.get((takunaiIndex*2)+1));
			}
		}
	}

	/**
	 * エラーデータを srcからdestに移送する
	 * @param msg 移送先
	 * @param takujnaiMap 移送元
	 */
	private static void transportErrorData(CAANMsg msg, Map<String, Object> takujnaiMap)
	{
		for (String key : takujnaiMap.keySet())
		{
			if (key.toLowerCase().endsWith(ERROR_FIELD_MARK))
			{
				transportData(key, msg, takujnaiMap);
			}
		}
	}
	
	/**
	 * CAANMsgのフィールド一覧を取得する
	 * @param <T> CAANMsgのスパークラス
	 * @param clazz 対象クラス
	 * @return フィールド一覧
	 */
	public static <T extends CAANSchemaInfo>List<String> getMsgFields(Class<T> clazz)
	{
		List<String> list = new ArrayList<String>();
		CAANSchemaInfo info;
		try 
		{
			info = clazz.newInstance();
		}
		catch (Exception e) 
		{
			return list;
		}

		Enumeration<String> keys = info.getKeys();
		while(keys.hasMoreElements())
		{
			list.add(keys.nextElement());
		}

		return list;
	}

	/**
	 * 入力の桁数になるように文字列の後にゼロ埋めを行う
	 * @param value
	 * @param len
	 * @return String
	 */
	public static Object setZeroAfter(CAANMsg inMsg, AgentDispatchContext context, Object value, Object len)
	{
		if(value == null)
		{
			return value;
		}
		StringBuilder sb = new StringBuilder();
		sb.append(value);
		
		int length = Integer.parseInt((String)len);
		
		while(sb.length() < length)
		{
			sb.append("0");
		}
		
		return sb.toString();
	}

}

final class StringBufferWrapper
{
	private String linePrefix = "\n";
	private StringBuffer sb = new StringBuffer();
	public StringBufferWrapper ()
	{
	}
	public StringBufferWrapper (String s)
	{
		sb.append(s);
	}
	public StringBufferWrapper append(String str)
	{
		sb.append(linePrefix);
		sb.append(str);
		return this;
	}
	
	public String toString()
	{
		return sb.toString();
	}
}
