using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.IO;

using CommonMP.HYSSOP.Interface.HSData;
using CommonMP.HYSSOP.CoreImpl.HSData;
using CommonMP.HYSSOP.CoreImpl.HSDBA;
using CommonMP.HYSSOP.CoreImpl.HSTools;

namespace CommonMP.HYSSOP.CoreImpl.HSDBA.FileBase
{
    /// <summary><para>class outline:</para>
    /// <para>共通形式ファイルベースDBAクラス</para>
    /// </summary>
    /// <remarks><para>history:</para>
    /// <para>[CommonMP][ver 1.0.0][2009/06/30][新規作成]</para>
    /// </remarks>
    public abstract class HySCommonFileDBA : HySCommonDBA
    {
        #region フォルダ・ファイルパス情報

        /// <summary>MetaDataListFilePathプロパティの値</summary>
        private String m_csMetaDataListFilePath;
        /// <summary>TmpMetaDataListFilePathプロパティの値</summary>
        private String m_csTmpMetaDataListFilePath = null;

        /// <summary>メタデータリストファイル名（フルパス）</summary>
        private String MetaDataListFilePath
        {
            get
            {
                if (m_csMetaDataListFilePath == null)
                {
                    m_csMetaDataListFilePath = CreateMetaDataListFilePath(MetaDataListFileName);
                }
                return m_csMetaDataListFilePath;
            }
        }

        /// <summary>一時メタデータリストファイルパス（フルパス）</summary>
        private String TmpMetaDataListFilePath
        {
            get
            {
                if (m_csTmpMetaDataListFilePath == null)
                {
                    m_csTmpMetaDataListFilePath = CreateMetaDataListFilePath(TmpMetaDataListFileName);
                }
                return m_csTmpMetaDataListFilePath;
            }
        }

        #endregion

        # region サブクラスで変更可能なパラメータ

        /// <summary>DBBasePathプロパティの値</summary>
        private String m_csDBBasePath;
        /// <summary>DataFilePreffixプロパティの値</summary>
        private String m_csDataFilePreffix;
        /// <summary>DataFileExtensionプロパティの値</summary>
        private String m_csDataFileExtension;
        /// <summary>MetaDataListFileNameプロパティの値</summary>
        private String m_csMetaDataListFileName;
        /// <summary>TmpMetaDataListFileNameプロパティの値</summary>
        private String m_csTmpMetaDataListFileName;
        /// <summary>MetaDataListDumpFileNameプロパティの値</summary>
        private String m_csMetaDataListDumpFileName;


        /// <summary>ＤＢベースフォルダパス</summary>
        private String DBBasePath
        {
            get
            {
                if (m_csDBBasePath == null)
                {
                    m_csDBBasePath = GetDBBasePath();
                }
                return m_csDBBasePath;
            }
        }
        /// <summary>データファイルプレフィックス</summary>
        private String DataFilePreffix
        {
            get
            {
                if (m_csDataFilePreffix == null)
                {
                    m_csDataFilePreffix = GetDataFilePreffix();
                }
                return m_csDataFilePreffix;
            }
        }
        /// <summary>データファイル拡張子</summary>
        private String DataFileExtension
        {
            get
            {
                if (m_csDataFileExtension == null)
                {
                    m_csDataFileExtension = GetDataFileExtension();
                }
                return m_csDataFileExtension;
            }
        }
        /// <summary>メタデータリストファイル名</summary>
        private String MetaDataListFileName
        {
            get
            {
                if (m_csMetaDataListFileName == null)
                {
                    m_csMetaDataListFileName = GetMetaDataListFileName();
                }
                return m_csMetaDataListFileName;
            }
        }
        /// <summary>一時メタデータリストファイル名</summary>
        private String TmpMetaDataListFileName
        {
            get
            {
                if (m_csTmpMetaDataListFileName == null)
                {
                    m_csTmpMetaDataListFileName = GetTmpMetaDataListFileName();
                }
                return m_csTmpMetaDataListFileName;
            }
        }
        /// <summary>メタデータリストファイルダンプファイル名</summary>
        private String MetaDataListDumpFileName
        {
            get
            {
                if (m_csMetaDataListDumpFileName == null)
                {
                    m_csMetaDataListDumpFileName = GetMetaDataListDumpFileName();
                }
                return m_csMetaDataListDumpFileName;
            }
        }

        #endregion

        /// <summary>
        /// 自クラス名(ログ出力用)
        /// </summary>
        private string m_csMyClassName = "HySCommonFileDBA";

        #region publicメソッド

        /// <summary><para>method outline:</para>
        /// <para>デフォルトコンストラクタ</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>HySCommonFileDBA csManager = new HySCommonFileDBA()</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>HySCommonFileDBA 生成されたインスタンス</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public HySCommonFileDBA()
        {
            m_csMyClassName = string.Format("HySCommonFileDBA({0})", GetType().Name);
        }
        ///// <summary><para>method outline:</para>
        ///// <para>ファイル名初期化</para>
        ///// </summary>
        ///// <example><para>usage:</para>
        ///// <para> bool bRtn = HySCommonFileDBA.InitFileName( ) </para>
        ///// </example>
        ///// <param name="">無し</param>
        ///// <returns>true:正常、false:異常</returns>
        ///// <exception cref="">無し</exception>
        ///// <remarks><para>remarks:</para>
        ///// <para>無し</para>
        ///// </remarks>
        //private Boolean InitFileName()
        //{
        //    // ＤＢベースフォルダパスを取得
        //    DBBasePath = GetDBBasePath();

        //    // データファイルのプレフィックス、拡張子を取得
        //    DataFilePreffix = GetDataFilePreffix();
        //    DataFileExtension = GetDataFileExtension();

        //    // メタデータファイル名、一時保存ファイル名、ダンプファイル名を取得
        //    MetaDataListFileName = GetMetaDataListFileName();
        //    TmpMetaDataListFileName = GetTmpMetaDataListFileName();
        //    MetaDataListDumpFileName = GetMetaDataListDumpFileName();

        //    // メタデータリストファイルパス、一時保存ファイルパスを生成
        //    m_csMetaDataListFilePath = CreateMetaDataListFilePath(MetaDataListFileName);
        //    m_csTmpMetaDataListFilePath = CreateMetaDataListFilePath(TmpMetaDataListFileName);

        //    return true;
        //}

        /// <summary><para>method outline:</para>
        /// <para>個別登録データ検索</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn  = GetData(csID, out csStockData)</para>
        /// </example>
        /// <param name="csID">取得対象ユニークID</param>
        /// <param name="csStockData">データ本体</param>
        /// <returns>true:=正常, false:=異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public override bool GetData(HySIdentifier csID, out HySStockData csStockData)
        {
            const string csMyMethodName = "GetData";

            // 1個だけのID配列を作成し、共通処理で実行する
            HySID[] csIDs = new HySID[] { (HySID)csID };
            HySStockDataList csStockDataList;
            if (GetDataCommon(csIDs, out csStockDataList))
            {
                csStockData = (HySStockData)csStockDataList.GetFirstData();
                return true;
            }
            else
            {
                HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "GetDataCommon() error");
                csStockData = null;
                return false;
            }
        }
        /// <summary>
        /// <para>複数一括取得する(ID配列指定)</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn  = GetDataList(csIDs, out csStockDataList)</para>
        /// </example>
        /// <param name="csIDs">取得対象ユニークID配列</param>
        /// <param name="csStockDataList">登録データ本体リスト</param>
        /// <returns>true:成功, false:失敗</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public override bool GetDataList(HySIdentifier[] csIDs, out HySStockDataList csStockDataList)
        {
            const string csMyMethodName = "GetData";

            // 共通処理で実行する
            if (!GetDataCommon(csIDs, out csStockDataList))
            {
                HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "GetDataCommon() error");
                csStockDataList = null;
                return false;
            }

            return true;
        }

        /// <summary><para>method outline:</para>
        /// <para>登録データ一覧検索</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn  = SearchList(csQueryCtlData, out csStockDataList)</para>
        /// </example>
        /// <param name="csQueryCtlData">検索条件</param>
        /// <param name="csStockDataList">検索結果リスト</param>
        /// <returns>true:=正常, false:=異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public override bool SearchList(HySQueryCtlData csQueryCtlData, out HySStockDataList csStockDataList)
        {
            const string csMyMethodName = "SearchList";

            // 出力パラメータ初期化
            csStockDataList = null;
            HySDBALockFile csLockFile = new HySDBALockFile();
            if (!csLockFile.Lock(MetaDataListFilePath, HySDBALockFile.LockMode.FOR_READONLY))
            {
                HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "HySDBALockFile.Lock() error");
                return false;
            }
            try
            {
                // メタデータリストファイル読み込み
                HySStockMetaDataList csMetaDataList = ReadMetaDataListFile();
                if (csMetaDataList == null)
                {
                    HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "ReadMetaDataListFile() return null");
                    return false;
                }

                if (csMetaDataList.GetCount() == 0)
                {
                    // 登録データがない場合は、検索結果0件で返す
                    csStockDataList = new HySStockDataList();
                    return true;
                }

                // 登録データ本体検索
                if (!SearchData(csMetaDataList, csQueryCtlData, out csStockDataList))
                {
                    HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "SearchData() error");
                    return false;
                }

                return true;
            }
            finally
            {
                csLockFile.UnLock();
            }
        }

        /// <summary><para>method outline:</para>
        /// <para>新規登録</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn = RegisterNew(csStockData)</para>
        /// </example>
        /// <param name="csStockData">登録対象データ</param>
        /// <returns>true:成功, false:失敗</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public override bool RegisterNew(HySStockData csStockData)
        {
            const string csMyMethodName = "RegisterNew(HySStockData)";

            // 1件だけのリストを作成し、共通処理で登録処理を実行する
            HySStockDataList csStockDataList = new HySStockDataList();
            csStockDataList.AddFirst(csStockData);
            if (!RegisterNewList(csStockDataList))
            {
                HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "RegisterNewList() error");
                return false;
            }
            return true;
        }

        /// <summary><para>method outline:</para>
        /// <para>複数一括で新規登録する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn = RegisterNew(csStockDataList)</para>
        /// </example>
        /// <param name="csStockDataList">登録対象データ</param>
        /// <returns>true:成功, false:失敗</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public override bool RegisterNew(HySStockDataList csStockDataList)
        {
            const string csMyMethodName = "RegisterNew(HySStockDataList)";

            // 共通処理で登録処理を実行する
            if (!RegisterNewList(csStockDataList))
            {
                HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "RegisterNewList() error");
                return false;
            }
            return true;
        }

        /// <summary><para>method outline:</para>
        /// <para>更新</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn = Update(csStockData)</para>
        /// </example>
        /// <param name="csStockData">更新対象データ</param>
        /// <returns>true:成功, false:失敗</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public override bool Update(HySStockData csStockData)
        {
            const string csMyMethodName = "Update";

            HySDBALockFile csLockFile1 = new HySDBALockFile();
            if (!csLockFile1.Lock(MetaDataListFilePath, HySDBALockFile.LockMode.FOR_MODIFY))
            {
                HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "HySDBALockFile.Lock() error");
                return false;
            }
            try
            {
                // メタデータリストファイル読み込み
                HySStockMetaDataList csMetaDataList = ReadMetaDataListFile();
                if (csMetaDataList == null)
                {
                    HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "ReadMetaDataListFile() return null");
                    return false;
                }

                // 未登録の場合、処理失敗とする
                HySID csID = csStockData.GetID();
                Boolean bExists = csMetaDataList.Contains(csID);
                if (!bExists)
                {
                    HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "data not exists",
                        "ID", csID);
                    return false;
                }

                // 登録データ本体ファイル削除のために古いレコード取得
                HySStockMetaData csOldRecord = csMetaDataList.GetData(csID);

                // 振り分け先サブフォルダを取得
                string csSubFolderPath = GetSubFolderPath(csStockData);

                // 登録データ本体をファイルに保存
                String csDataFilePath;
                if (!CreateDataFilePath(csSubFolderPath, out csDataFilePath))
                {
                    HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "CreateDataFilePath() error");
                    return false;
                }
                if (!SaveFile(csDataFilePath, csStockData))
                {
                    HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "SaveFile(Data File) error",
                        "DataFilePath", csDataFilePath);
                    return false;
                }

                // メタデータリスト更新
                //HySString csDataFileName = new HySString(Path.GetFileName(csDataFilePath.ToString()));
                HySString csDataFileName = new HySString(Path.Combine(csSubFolderPath, Path.GetFileName(csDataFilePath)));
                HySStockMetaData csRecord = new HySStockMetaData(csStockData, csDataFileName);
                csMetaDataList[csID] = csRecord;

                // メタデータリストファイル一時保存
                if (!SaveFile(TmpMetaDataListFilePath, csMetaDataList))
                {
                    HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "SaveFile(Meta File) error",
                        "TmpMetaDataListFilePath", TmpMetaDataListFilePath);
                    return false;
                }

                // ここまで、
                //   * 登録データ本体ファイル
                //   * 一時メタデータリストファイル
                // が作成されている。
                if (!UpdateMetaDataListFile())
                {
                    HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "UpdateMetaDataListFile() error");

                    // 管理ファイルの更新に失敗した場合、一時メタデータリストファイルを削除
                    DeleteFile(TmpMetaDataListFilePath);

                    // 更新用の登録データ本体ファイルを削除
                    DeleteFile(csDataFilePath);
                    return false;
                }

                // 古い登録データ本体ファイルを削除
                String csPath = Path.Combine(GetDBPath(), csOldRecord.GetPhysicalName().ToString());
                DeleteFile(csPath);

                // 不要ファイル削除処理を呼び出し、メタデータリストファイルのテキストダンプを行う
                CleanUp(csMetaDataList);
                DumpMetaDataListFile(csMetaDataList);

                return true;
            }
            finally
            {
                csLockFile1.UnLock();
            }
        }

        /// <summary><para>method outline:</para>
        /// <para>複数一括削除する(検索条件指定)</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn = Delete(csQueryCtlData)</para>
        /// </example>
        /// <param name="csQueryCtlData">削除対象データ検索条件</param>
        /// <returns>true:成功, false:失敗</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public override bool Delete(HySQueryCtlData csQueryCtlData)
        {
            const string csMyMethodName = "Delete(HySQueryCtlData)";

            // パラメータチェック：検索条件に何も指定されていない場合はエラーにする(全件削除を避けるため)
            if (csQueryCtlData.GetCount() == 0)
            {
                HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "QueryCtlData has no entry");
                return false;
            }
            HySDBALockFile csLockFile = new HySDBALockFile();
            if (!csLockFile.Lock(MetaDataListFilePath, HySDBALockFile.LockMode.FOR_MODIFY))
            {
                HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "HySDBALockFile.Lock() error");
                return false;
            }
            try
            {
                // メタデータリストファイル読み込み
                HySStockMetaDataList csMetaDataList = ReadMetaDataListFile();
                if (csMetaDataList == null)
                {
                    HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "ReadMetaDataListFile() return null");
                    return false;
                }

                if (csMetaDataList.GetCount() == 0)
                {
                    // 登録データがない場合は、処理成功とする
                    HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "DB is empty");
                    return true;
                }


                // 削除対象データ検索
                // 削除の場合はメタデータのみでよいので、検索条件オブジェクトのメタデータのみ
                // 取得フラグを設定する。
                HySStockDataList csStockDataList = new HySStockDataList();
                HySQueryCtlData csQuery = new HySQueryCtlData(csQueryCtlData);
                csQuery.SetIsMetaDataOnly(true);
                if (!SearchData(csMetaDataList, csQuery, out csStockDataList))
                {
                    HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "SearchData() error");
                    return false;
                }
                // 削除データがない場合は、処理成功とする
                long lDataCount = csStockDataList.GetCount();
                if (lDataCount == 0)
                {
                    HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "no data deleted");
                    return true;
                }

                // メタデータリストからID指定で削除する
                csStockDataList.SetCursorFirst();
                for (long lCnt = 0; lCnt < lDataCount; ++lCnt)
                {
                    HySStockData csStockData = (HySStockData)csStockDataList.GetCursorData();
                    if (!csMetaDataList.RemoveData(csStockData.GetID()))
                    {
                        HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "HySStockMetaData.RemoveData() error",
                            "ID", csStockData.GetID());
                        return false;
                    }
                    csStockDataList.MoveCursorNext();
                }

                // メタデータリスト一時保存
                if (!SaveFile(TmpMetaDataListFilePath, csMetaDataList))
                {
                    HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "SaveFile(Tmp Meta) error",
                        "TmpMetaDataListFilePath", TmpMetaDataListFilePath);
                    return false;
                }
                
                // メタデータリストの更新
                if (!UpdateMetaDataListFile())
                {
                    HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "UpdateMetaDataListFile() error");
                    // 管理ファイルの更新に失敗した場合、一時メタデータリストファイルを削除
                    DeleteFile(TmpMetaDataListFilePath);
                    return false;
                }

                // 不要ファイル削除処理を呼び出し、メタデータリストファイルのテキストダンプを行う
                CleanUp(csMetaDataList);
                DumpMetaDataListFile(csMetaDataList);

                return true;
            }
            finally
            {
                csLockFile.UnLock();
            }
        }

        /// <summary><para>method outline:</para>
        /// <para>複数一括削除する(ID配列指定)</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn = Delete(csIDs)</para>
        /// </example>
        /// <param name="csIDs">削除対象ユニークID配列</param>
        /// <returns>true:成功, false:失敗</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public override bool Delete(HySIdentifier[] csIDs)
        {
            // 共通処理で実行
            return DeleteCommon(csIDs);
        }

        /// <summary><para>method outline:</para>
        /// <para>1件削除</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn = Delete(csID)</para>
        /// </example>
        /// <param name="csID">削除対象ユニークID</param>
        /// <returns>true:成功, false:失敗</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public override bool Delete(HySIdentifier csID)
        {
            // 共通処理で実行
            HySIdentifier[] csIDs = new HySIdentifier[] { (HySID)csID };
            return DeleteCommon(csIDs);
        }

        /// <summary><para>method outline:</para>
        /// <para>部分更新</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn = UpdatePartial(csQueryCtlData, csModifyData)</para>
        /// </example>
        /// <param name="csQueryCtlData">更新対象データの検索条件</param>
        /// <param name="csModifyData">更新データ。更新対象フィールド名は検索条件フィールド名と同じ。</param>
        /// <returns>true:成功, false:失敗</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>デフォルト実装は非サポートで常にエラーを返す。
        /// 部分更新機能が必要なサブクラスで<see cref="CheckUpdatePartialParameter"/>
        /// および<see cref="ApplyUpdatePartialParameter"/>をオーバーライドすること。</para>
        /// </remarks>
        public override bool UpdatePartial(HySQueryCtlData csQueryCtlData, HySDataHashTable csModifyData)
        {
            const string csMyMethodName = "UpdatePartial";

            // パラメータの事前チェックを行う
            if (!CheckUpdatePartialParameter(csModifyData))
            {
                HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "CheckUpdatePartialParameter() error");
                return false;
            }

            // メタデータリストファイルをロックする
            HySDBALockFile csLockFile = new HySDBALockFile();
            if (!csLockFile.Lock(MetaDataListFilePath, HySDBALockFile.LockMode.FOR_MODIFY))
            {
                HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "HySDBALockFile.Lock() error");
                return false;
            }
            try
            {
                // メタデータリストファイル読み込み
                HySStockMetaDataList csMetaDataList = ReadMetaDataListFile();
                if (csMetaDataList == null)
                {
                    HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "ReadMetaDataListFile() return null");
                    return false;
                }

                if (csMetaDataList.GetCount() == 0)
                {
                    // 登録データがない場合は処理終了する
                    return true;
                }

                // 登録データ本体検索
                HySStockDataList csStockDataList;
                if (!SearchData(csMetaDataList, csQueryCtlData, out csStockDataList))
                {
                    HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "SearchData() error");
                    return false;
                }

                // 見つかったレコードを更新する
                List<HySStockMetaData> csOldMetaDataList = new List<HySStockMetaData>();    // 成功時、古いファイルを削除するためのリスト
                List<string> csDataFilePathList = new List<string>();   // 失敗時、新規作成したファイルを削除するためのリスト
                long lDataCount = csStockDataList.GetCount();
                csStockDataList.SetCursorFirst();
                for (long lIdx = 0; lIdx < lDataCount; ++lIdx)
                {
                    // レコード本体とIDを取得
                    HySStockData csStockData = (HySStockData)csStockDataList.GetCursorData();
                    csStockDataList.MoveCursorNext();
                    HySID csID = csStockData.GetID();

                    // 登録データ本体ファイル削除のために古いレコード取得
                    HySStockMetaData csOldRecord = csMetaDataList.GetData(csID);
                    csOldMetaDataList.Add(csOldRecord);

                    // 部分更新を適用
                    ApplyUpdatePartialParameter(csStockData, csModifyData);

                    // 振り分け先サブフォルダを取得
                    string csSubFolderPath = GetSubFolderPath(csStockData);

                    // 登録データ本体をファイルに保存
                    String csDataFilePath;
                    if (!CreateDataFilePath(csSubFolderPath, out csDataFilePath))
                    {
                        HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "CreateDataFilePath() error");
                        return false;
                    }
                    if (!SaveFile(csDataFilePath, csStockData))
                    {
                        HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "SaveFile(Data File) error",
                            "DataFilePath", csDataFilePath);
                        return false;
                    }
                    csDataFilePathList.Add(csDataFilePath);

                    // メタデータリスト更新
                    HySString csDataFileName = new HySString(Path.Combine(csSubFolderPath, Path.GetFileName(csDataFilePath)));
                    HySStockMetaData csRecord = new HySStockMetaData(csStockData, csDataFileName);
                    csMetaDataList[csID] = csRecord;

                }
                // メタデータリストファイル一時保存
                if (!SaveFile(TmpMetaDataListFilePath, csMetaDataList))
                {
                    HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "SaveFile(Meta File) error",
                        "TmpMetaDataListFilePath", TmpMetaDataListFilePath);
                    return false;
                }

                // ここまで、
                //   * 登録データ本体ファイル
                //   * 一時メタデータリストファイル
                // が作成されている。
                if (!UpdateMetaDataListFile())
                {
                    HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "UpdateMetaDataListFile() error");

                    // 管理ファイルの更新に失敗した場合、一時メタデータリストファイルを削除
                    DeleteFile(TmpMetaDataListFilePath);

                    // 更新用の登録データ本体ファイルを削除
                    foreach (string csDataFilePath in csDataFilePathList)
                    {
                        DeleteFile(csDataFilePath);
                    }
                    return false;
                }

                // 古い登録データ本体ファイルを削除
                foreach (HySStockMetaData csOldRecord in csOldMetaDataList)
                {
                    String csPath = Path.Combine(GetDBPath(), csOldRecord.GetPhysicalName().ToString());
                    DeleteFile(csPath);
                }

                // 不要ファイル削除処理を呼び出し、メタデータリストファイルのテキストダンプを行う
                CleanUp(csMetaDataList);
                DumpMetaDataListFile(csMetaDataList);
                return true;
            }
            finally
            {
                csLockFile.UnLock();
            }
        }

#endregion

        #region テンプレートメソッド。サブクラスでオーバーライドすること

        /// <summary><para>method outline:</para>
        /// <para>（抽象メソッド）DBパスを取得する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> string csPath = GetDBBasePath() </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>DBパス名</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected abstract String GetDBBasePath();
        //{
        //    return DEFAULT_DB_PATH;
        //}

        /// <summary><para>method outline:</para>
        /// <para>（抽象メソッド）データファイルのプレフィックスを取得する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> string csPreffix = GetDataFilePreffix() </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>データファイルのプレフィックス</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected abstract String GetDataFilePreffix();
        //{
        //    return DEFAULT_DATAFILE_PREFFIX;
        //}

        /// <summary><para>method outline:</para>
        /// <para>（抽象メソッド）データファイルの拡張子を取得する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> string csExt = GetDataFileExtension() </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>データファイルの拡張子</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected abstract String GetDataFileExtension();
        //{
        //    return DEFAULT_DATAFILE_EXTENSION;
        //}

        /// <summary><para>method outline:</para>
        /// <para>（抽象メソッド）メタデータリストファイル名を取得する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> string csFileName = GetMetaDataListFileName() </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>メタデータリストファイル名</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected abstract String GetMetaDataListFileName();
        //{
        //    return DEFAULT_METADATALIST_FILENAME;
        //}

        /// <summary><para>method outline:</para>
        /// <para>（抽象メソッド）メタデータリスト一時ファイル名を取得する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> string csFileName = GetTmpMetaDataListFileName() </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>メタデータリスト一時ファイル名</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected abstract String GetTmpMetaDataListFileName();
        //{
        //    return DEFAULT_TEMP_METADATALIST_FILENAME;
        //}

        /// <summary><para>method outline:</para>
        /// <para>（抽象メソッド）メタデータリストダンプファイル名を取得する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> string csFileName = GetMetaDataListDumpFileName() </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>メタデータリストダンプファイル名</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected abstract String GetMetaDataListDumpFileName();
        //{
        //    return DEFAULT_METADATALIST_DUMP_FILENAME;
        //}

        /// <summary><para>method outline:</para>
        /// <para>（仮想メソッド）検索処理の準備を行う</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>PrepareQuery(csQueryCtlData, csComparerList)</para>
        /// </example>
        /// <param name="csQueryCtlData">検索条件</param>
        /// <param name="csComparerList">比較リスト</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>必要に応じてサブクラスで追加検索条件を設定すること</para>
        /// </remarks>
        protected virtual void PrepareQuery(HySQueryCtlData csQueryCtlData, ref List<HySDBAFieldComparer> csComparerList)
        {
            // 検索条件がある場合、該当するフィールドを比較するためのデリゲート情報を設定する

            HySQueryEntryData csQueryEntryData;
            // ID
            if ((csQueryEntryData = csQueryCtlData.GetQueryEntryData(HySQueryFieldNames.ID)) != null)
            {
                csComparerList.Add(new HySDBAFieldComparer(csQueryEntryData, delegate(HySStockData csStockData)
                {
                    return csStockData.GetID();
                }));
            }
            // データ種別
            if ((csQueryEntryData = csQueryCtlData.GetQueryEntryData(HySQueryFieldNames.DATA_KIND)) != null)
            {
                csComparerList.Add(new HySDBAFieldComparer(csQueryEntryData, delegate(HySStockData csStockData)
                {
                    return csStockData.GetDataKind();
                }));
            }
            // シミュレータ種別
            if ((csQueryEntryData = csQueryCtlData.GetQueryEntryData(HySQueryFieldNames.SIM_KIND)) != null)
            {
                csComparerList.Add(new HySDBAFieldComparer(csQueryEntryData, delegate(HySStockData csStockData)
                {
                    return csStockData.GetSimKind();
                }));
            }
            // シミュレータID(プロジェクトID)
            if ((csQueryEntryData = csQueryCtlData.GetQueryEntryData(HySQueryFieldNames.SIM_ID)) != null)
            {
                csComparerList.Add(new HySDBAFieldComparer(csQueryEntryData, delegate(HySStockData csStockData)
                {
                    return csStockData.GetSimID();
                }));
            }
            // 地点ID
            if ((csQueryEntryData = csQueryCtlData.GetQueryEntryData(HySQueryFieldNames.POINT_ID)) != null)
            {
                csComparerList.Add(new HySDBAFieldComparer(csQueryEntryData, delegate(HySStockData csStockData)
                {
                    return csStockData.GetPointID();
                }));
            }
            // 登録名
            if ((csQueryEntryData = csQueryCtlData.GetQueryEntryData(HySQueryFieldNames.SAVE_NAME)) != null)
            {
                csComparerList.Add(new HySDBAFieldComparer(csQueryEntryData, delegate(HySStockData csStockData)
                {
                    return csStockData.GetSaveName();
                }));
            }
            // 保存期限区分
            if ((csQueryEntryData = csQueryCtlData.GetQueryEntryData(HySQueryFieldNames.PRESERVED_PERIOD)) != null)
            {
                csComparerList.Add(new HySDBAFieldComparer(csQueryEntryData, delegate(HySStockData csStockData)
                {
                    return csStockData.GetPeservedPeriod();
                }));
            }
            // ロットID
            if ((csQueryEntryData = csQueryCtlData.GetQueryEntryData(HySQueryFieldNames.LOT_ID)) != null)
            {
                csComparerList.Add(new HySDBAFieldComparer(csQueryEntryData, delegate(HySStockData csStockData)
                {
                    // 「その他検索条件」からデータを取得する
                    long lKeyNumber = 0;
                    HySDataHashTable csKeyInfo = csStockData.GetKeyInfo(ref lKeyNumber);
                    if (lKeyNumber > 0)
                    {
                        HySID csLotID = csKeyInfo.GetObject(HySQueryFieldNames.LOT_ID) as HySID;
                        if (csLotID != null)
                        {
                            return csLotID;
                        }
                    }
                    return null;    // ロットIDは含まれていなかった
                }));
            }
            // 保存期限区分変更日
            if ((csQueryEntryData = csQueryCtlData.GetQueryEntryData(HySQueryFieldNames.PRESERVED_PERIOD_MODIFY_TIME)) != null)
            {
                csComparerList.Add(new HySDBAFieldComparer(csQueryEntryData, delegate(HySStockData csStockData)
                {
                    return csStockData.GetPreservedPeriodModifyTime();
                }));
            }

        }
        /// <summary><para>method outline:</para>
        /// <para>（仮想メソッド）登録データを振り分けるサブフォルダ名を取得する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>string csSubFolderPath = GetSubFolderPath(csStockData)</para>
        /// </example>
        /// <param name="csStockData">登録データ</param>
        /// <returns>サブフォルダパス名(相対パス)</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>デフォルトは空文字列を返す(振り分け無し＝カレントディレクトリ)</para>
        /// </remarks>
        protected virtual string GetSubFolderPath(HySStockData csStockData)
        {
            return string.Empty;
        }

        /// <summary><para>method outline:</para>
        /// <para>（仮想メソッド）登録時の追加重複チェック</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn = AdditionalDuplicateCheck(csMetaDataList, csStockData)</para>
        /// </example>
        /// <param name="csMetaDataList">メタデータリスト</param>
        /// <param name="csStockData">登録対象のDB保存データ</param>
        /// <returns>true:登録可能(重複なし)、false:登録不可(重複あり)</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>デフォルト実装は成功を返す(ID以外の重複はチェックしない)</para>
        /// </remarks>
        protected virtual bool AdditionalDuplicateCheck(HySStockMetaDataList csMetaDataList, HySStockData csStockData)
        {
            return true;
        }

        /// <summary><para>method outline:</para>
        /// <para>（仮想メソッド）部分更新データのチェック</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn = CheckUpdatePartialParameter(csModifyData)</para>
        /// </example>
        /// <param name="csModifyData">部分更新データ</param>
        /// <returns>true:更新可能、false:更新不可(非サポートフィールド名等)</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>デフォルト実装はエラーを返す(UpdatePartialメソッド自体が非サポート)</para>
        /// </remarks>
        protected virtual bool CheckUpdatePartialParameter(HySDataHashTable csModifyData)
        {
            const string csMyMethodName = "CheckUpdatePartialParameter";
            HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "UpdatePartial() not supported");
            return false;
        }

        /// <summary><para>method outline:</para>
        /// <para>（仮想メソッド）部分更新データの適用</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>ApplyUpdatePartialParameter(csStockData, csModifyData)</para>
        /// </example>
        /// <param name="csStockData">適用対象DB保存データ</param>
        /// <param name="csModifyData">部分更新データ</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>デフォルト実装は何もしない</para>
        /// </remarks>
        protected virtual void ApplyUpdatePartialParameter(HySStockData csStockData, HySDataHashTable csModifyData)
        {
            return;
        }

        #endregion


        //-------------------------------------------------------------------------------------
        // 登録処理ユーティリティメソッド
        //-------------------------------------------------------------------------------------
        /// <summary><para>method outline:</para>
        /// <para>現在日取得メソッド</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>HySTime csTime = GetToday()</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>現在日</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected HySTime GetToday()
        {
            //データ作成
            DateTime csDTBase = DateTime.Parse("1/1/1970 0:0:0");   // 基準時刻
            TimeSpan csTS = DateTime.Today - csDTBase;
            HySTime csToday = new HySTime((long)csTS.TotalSeconds);
            return csToday;
        }

        #region privateメソッド

        //-------------------------------------------------------------------------------------
        // 管理データ検索処理メソッド
        //-------------------------------------------------------------------------------------

        /// <summary><para>method outline:</para>
        /// <para>登録データ本体検索</para>
        /// </summary>
        /// <param name="csMetaDataList">管理ファイル情報</param>
        /// <param name="csQueryCtlData">検索条件</param>
        /// <param name="csStockDataList">登録データリスト</param>
        /// <returns>true:成功、false:失敗</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        private bool SearchData(HySStockMetaDataList csMetaDataList, HySQueryCtlData csQueryCtlData, out HySStockDataList csStockDataList)
        {
            csStockDataList = new HySStockDataList();

            // 検索準備
            List<HySDBAFieldComparer> csComparerList = new List<HySDBAFieldComparer>();
            PrepareQuery(csQueryCtlData, ref csComparerList);

            // リスト走査
            foreach (HySStockMetaData csStockMetaData in csMetaDataList)
            {
                HySStockData csStockData = csStockMetaData.GetStockData();
                bool bIsMatch = true;
                foreach (HySDBAFieldComparer csComparer in csComparerList)
                {
                    if (!csComparer.Evaluate(csStockData))
                    {
                        bIsMatch = false;
                        break;
                    }
                }
                if (bIsMatch)   // 検索条件に合致(または検索条件が指定されていない)
                {
                    if (!csQueryCtlData.GetIsMetaDataOnly()) // 実データ必要
                    {
                        // 実データファイルを読み込む
                        string csDataFilePath = Path.Combine(GetDBPath().ToString(), csStockMetaData.GetPhysicalName().ToString());
                        HySDBALockFile csLockFile2 = new HySDBALockFile();
                        if (!csLockFile2.Lock(csDataFilePath, HySDBALockFile.LockMode.FOR_READONLY))
                        {
                            return false;
                        }
                        try
                        {
                            csStockData = ReadStockDataFile(new HySString(csDataFilePath));
                        }
                        finally
                        {
                            csLockFile2.UnLock();
                        }
                    }
                    csStockDataList.AddLast(csStockData);
                }
            }
            return true;
        }

        //-------------------------------------------------------------------------------------
        // ファイル操作処理メソッド
        //-------------------------------------------------------------------------------------

        /// <summary><para>method outline:</para>
        /// <para>メタデータリストファイル読み込み</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>ReadMetaDataListFile()</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>メタデータリストファイルデータ</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>エラー発生した場合はnullを返す。メタデータリストファイルが存在しない場合は、HySStockMetaDataListクラスのインスタンス(登録データが1件もない)を返す。</para>
        /// </remarks>
        private HySStockMetaDataList ReadMetaDataListFile()
        {
            const String csMyMethodName = "ReadMetaDataListFile";

            // メタデータリストファイル存在チェック
            if (!File.Exists(MetaDataListFilePath))
            {
                // メタデータリストファイルが存在しない場合は、DB未登録の状態なので、
                // 空(登録データが1件もない)のインスタンスを返す
                return new HySStockMetaDataList();
            }

            // メタデータリストファイル読み込み
            HySFile csFileIn = new HySFile(MetaDataListFilePath);
            if (csFileIn.Open(HySFile.OPEN_MODE.OPEN, HySFile.READ_WRITE_MODE.READ, HySFile.DIRECTORY_MODE.NOT_MK_DIR) != 0)
            {
                HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "ファイルオープン失敗: " + MetaDataListFilePath);
                return null;
            }
            HySStockMetaDataList csMetaDataList = (HySStockMetaDataList)csFileIn.DataRead();
            csFileIn.Close();

            return csMetaDataList;
        }

        /// <summary><para>method outline:</para>
        /// <para>登録データ本体ファイル読み込み</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>ReadStockDataFile(csFilePath)</para>
        /// </example>
        /// <param name="csFilePath">ファイルパス</param>
        /// <returns>登録データ本体</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        private HySStockData ReadStockDataFile(HySString csFilePath)
        {
            const String csMyMethodName = "ReadStockDataFile";

            // 登録データ本体ファイル読み込み
            HySFile csFileIn = new HySFile(csFilePath);
            if (csFileIn.Open(HySFile.OPEN_MODE.OPEN, HySFile.READ_WRITE_MODE.READ, HySFile.DIRECTORY_MODE.NOT_MK_DIR) != 0)
            {
                HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "ファイルオープン失敗: " + csFilePath.ToString());
                return null;
            }
            HySStockData csStockData = (HySStockData)csFileIn.DataRead();
            csFileIn.Close();

            return csStockData;
        }

        /// <summary><para>method outline:</para>
        /// <para>マスターファイルパス(フルパス)作成</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> CreateMetaDataListFilePath(csFilename)</para>
        /// </example>
        /// <param name="csFilename">ファイル名</param>
        /// <returns>マスターファイルパス(フルパス)</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        private String CreateMetaDataListFilePath(String csFilename)
        {
            return Path.Combine(GetDBPath(), csFilename);
        }

        /// <summary><para>method outline:</para>
        /// <para>登録データ本体ファイルパス作成</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> CreateDataFilePath()</para>
        /// </example>
        /// <param name="csSubFolderPath">サブフォルダパス</param>
        /// <param name="csFilePath">登録データ本体ファイルパス</param>
        /// <returns>true:成功、false:失敗</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>登録データ本体ファイルパスを作成する。ファイル名はランダムに生成され、同じファイル名が存在する場合は、再びランダムにファイル名を生成する。ファイル名生成は10回まで試み、それでも同一ファイル名が存在する場合はエラー(null)返す。</para>
        /// </remarks>
        private bool CreateDataFilePath(string csSubFolderPath, out String csFilePath)
        {
            const String csMyMethodName = "CreateDataFilePath";

            csFilePath = null;

            String csDBBasePath = GetDBPath();
            String csDataFileDirPath = Path.Combine(csDBBasePath, csSubFolderPath);
            bool bSuccess = false;
            for (int iNumRetry = 10; iNumRetry > 0; iNumRetry--)
            {
                String csDataFileName = string.Format("{0}{1}{2}", DataFilePreffix, Path.GetRandomFileName(), DataFileExtension);
                String csDataFilePath = Path.Combine(csDataFileDirPath, csDataFileName);
                if (!Directory.Exists(csDataFileDirPath) || !File.Exists(csDataFilePath))
                {
                    bSuccess = true;
                    csFilePath = csDataFilePath;
                    break;
                }
            }
            if (!bSuccess)
            {
                HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "登録データ本体ファイルパス作成失敗");
            }
            return bSuccess;
        }

        /// <summary><para>method outline:</para>
        /// <para>DBパス取得(フルパス)</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>GetDBPath()</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>DBへのパス(フルパス)</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        private String GetDBPath()
        {
            String csDBPath;
            HySString csCurrentPath = HySEnvInf.GetDBDirectory();
            csDBPath = csCurrentPath.ToString() + DBBasePath;
            return csDBPath;
        }

        /// <summary><para>method outline:</para>
        /// <para>ファイル保存</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>SaveFile(csFilePath, csData)</para>
        /// </example>
        /// <param name="csFilePath">保存ファイルパス</param>
        /// <param name="csData">保存データ</param>
        /// <returns>true:=正常, false:=異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        private Boolean SaveFile(String csFilePath, HySDataRoot csData)
        {
            const String csMyMethodName = "SaveFile";

            HySFile csFileOut = new HySFile(csFilePath);
            if (csFileOut.Open(HySFile.OPEN_MODE.CREATE_NEW, HySFile.READ_WRITE_MODE.WRITE, HySFile.DIRECTORY_MODE.MK_DIR) != 0)
            {
                HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "HySFile.Open() error",
                    "FilePath", csFilePath);
                return false;
            }
            try
            {
                if (!csFileOut.DataWrite(csData))
                {
                    HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "HySFile.DataWrite() error",
                        "FilePath", csFilePath);
                    return false;
                }
            }
            catch (Exception ex)
            {
                HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "HySFile.DataWrite() exception",
                    "FilePath", csFilePath,
                    "exception", ex);
                return false;
            }
            finally
            {
                csFileOut.Close();
            }
            return true;
        }

        /// <summary><para>method outline:</para>
        /// <para>ファイル削除</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> DeleteFile(csFilename)</para>
        /// </example>
        /// <param name="csFilename">ファイル名</param>
        /// <returns>true:=正常, false:=異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        private Boolean DeleteFile(String csFilename)
        {
            const String csMyMethodName = "DeleteFile";
            try
            {
                HySDBAFileIOWrapper.FileDelete(csFilename.ToString());
            }
            catch (Exception ex)
            {
                HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "HySDBAFileIOWrapper.FileDelete() exception",
                    "Filename", csFilename,
                    "exception", ex);
                return false;
            }
            return true;
        }

        /// <summary><para>method outline:</para>
        /// <para>メタデータリストファイル更新</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> UpdateMetaDataListFile()</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>true:=正常, false:=異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        private Boolean UpdateMetaDataListFile()
        {
            const String csMyMethodName = "UpdateMetaDataListFile";
            try
            {
                if (File.Exists(MetaDataListFilePath))
                {
                    HySDBAFileIOWrapper.FileReplace(TmpMetaDataListFilePath, MetaDataListFilePath, null);
                }
                else
                {
                    HySDBAFileIOWrapper.FileMove(TmpMetaDataListFilePath, MetaDataListFilePath);
                }
            }
            catch (Exception ex)
            {
                HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "HySDBAFileIOWrapper.FileReplace()/FileMove() exception",
                    "path-from", TmpMetaDataListFilePath,
                    "path-to", MetaDataListFilePath,
                    "exception", ex);
                return false;
            }
            return true;
        }

        /// <summary><para>method outline:</para>
        /// <para>メタデータリストファイルテキストダンプ</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> DumpMetaDataListFile(csMetaDataList)</para>
        /// </example>
        /// <param name="csMetaDataList">メタデータリスト</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>ユニークIDと登録データ本体ファイルとの対応を人が見て分かるようにテキストダンプする。</para>
        /// <para>エラーが発生しても処理には影響ないため、異常としない。</para>
        /// </remarks>
        private void DumpMetaDataListFile(HySStockMetaDataList csMetaDataList)
        {
            const String csMyMethodName = "DumpMetaDataListFile";
            String csDumpFilePath = Path.Combine(GetDBPath(), MetaDataListDumpFileName);

            try
            {
                if (csMetaDataList.GetCount() == 0)
                {
                    // 0件の場合ファイル削除
                    if (File.Exists(csDumpFilePath))
                    {
                        DeleteFile(csDumpFilePath);
                    }
                }
                else
                {
                    using (StreamWriter csWriter = new StreamWriter(csDumpFilePath, false, Encoding.GetEncoding(932)))
                    {
                        csWriter.WriteLine("ユニークID, 登録データ本体ファイル名, その他付加情報");

                        foreach (HySStockMetaData csRecord in csMetaDataList)
                        {
                            csWriter.WriteLine(CreateDumpLine(csRecord).ToString());
                        }
                        csWriter.Close();
                    }
                }
            }
            catch (Exception ex)
            {
                HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "warning: exception occured",
                    "DumpFilePath", csDumpFilePath,
                    "exception", ex);
            }
        }

        /// <summary><para>method outline:</para>
        /// <para>メタデータリストファイルダンプ1行作成</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>CreateDumpLine</para>
        /// </example>
        /// <param name="csRecord">メタデータ1件</param>
        /// <returns>ダンプファイル1行分のデータ</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        private HySString CreateDumpLine(HySStockMetaData csRecord)
        {
            HySStockData csStockData = csRecord.GetStockData();
            StringBuilder csSb = new StringBuilder();
            csSb.Append(csStockData.GetID().ToString());
            csSb.Append(", ");
            csSb.Append(csRecord.GetPhysicalName().ToString());
            csSb.Append(", {");
            long lKeyNumber = 0;

            // キーをソートする
            HySDataHashTable csKeyInfo = csStockData.GetKeyInfo(ref lKeyNumber);
            SortedList<string, HySString> csSortedKeyList = new SortedList<string, HySString>();
            if (lKeyNumber > 0)
            {
                HySDataLinkedList csKeyList = csKeyInfo.GetKeyList();
                csKeyList.SetCursorFirst();
                for (long lIdx = 0; lIdx < lKeyNumber; ++lIdx)
                {
                    HySString csKey = (HySString)csKeyList.GetCursorData();
                    csKeyList.MoveCursorNext();

                    csSortedKeyList.Add(csKey.ToString(), csKey);
                }
            }
            // キーと値のペアを作る
            List<string> csKeyInfoStringList = new List<string>();
            foreach (string csKeyString in csSortedKeyList.Keys)
            {
                HySString csKey = csSortedKeyList[csKeyString];
                HySDataRoot csValue = csKeyInfo.GetObject(csKey);
                string csValueString = null;
                if (csValue is HySString)
                {
                    csValueString = ((HySString)csValue).ToString();
                }
                else if (csValue is HySID)
                {
                    csValueString = ((HySID)csValue).ToString();
                }
                else if (csValue is HySObjectKind)
                {
                    csValueString = ((HySObjectKind)csValue).ToString();
                }
                else if (csValue is HySTime)
                {
                    csValueString = HySCalendar.ToString((HySTime)csValue, HySCalendar.FORMAT.lSW_YEAR);
                }
                else if (csValue is HySLong)
                {
                    csValueString = ((HySLong)csValue).m_lValue.ToString();
                }
                else if (csValue != null)
                {
                    csValueString = csValue.ToString();
                }
                if (csValueString != null)
                {
                    csKeyInfoStringList.Add(string.Format("{0}={1}", ((HySString)csKey).ToString(), csValueString));
                }
            }
            // カンマで連結する
            csSb.Append(string.Join(",", csKeyInfoStringList.ToArray()));
            csSb.Append("}");
            return new HySString(csSb.ToString());
        }

        /// <summary><para>method outline:</para>
        /// <para>不要ファイル削除</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>CleanUp(csMetaDataList)</para>
        /// </example>
        /// <param name="csMetaDataList">メタデータリスト</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>不要ファイル削除に失敗しても処理には影響ないため、異常とはしない。</para>
        /// </remarks>
        private void CleanUp(HySStockMetaDataList csMetaDataList)
        {
            const String csMyMethodName = "CleanUp";
            try
            {
                if (csMetaDataList.GetCount() == 0)
                {
                    // 登録件数0件の場合管理ファイルも不要なので削除する
                    if (File.Exists(MetaDataListFilePath))
                    {
                        DeleteFile(MetaDataListFilePath);
                    }
                }
                // ハッシュテーブルを利用して、管理ファイルに格納されたメタデータリストファイルと
                // DBディレクトリに存在する登録データ本体ファイルの比較を行う
                string csDBBasePath = GetDBPath();
                Hashtable csFileNames = new Hashtable();
                foreach (HySStockMetaData csRecord in csMetaDataList)
                {
                    csFileNames[csRecord.GetPhysicalName().ToString()] = null;
                }

                // DBディレクトリから登録データ本体ファイル(特定のプレフィックスと拡張子を持つもの)を取得する
                string csFilePattern = string.Format("{0}*{1}", DataFilePreffix, DataFileExtension);
                String[] csFiles = Directory.GetFiles(GetDBPath(), csFilePattern, SearchOption.AllDirectories);
                foreach (String csPath in csFiles)
                {
                    string csRelPath = csPath.Replace(csDBBasePath, "");
                    if (csRelPath.StartsWith(Path.DirectorySeparatorChar.ToString()))
                    {
                        csRelPath = csRelPath.Remove(0, 1);
                    }
                    if (!csFileNames.Contains(csRelPath))
                    {
                        // メタデータリストファイルに存在しないファイルは削除
                        DeleteFile(csPath);
                    }
                }
            }
            catch (Exception ex)
            {
                HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "warning: exception occured",
                    "exception", ex);
            }
        }

        /// <summary><para>method outline:</para>
        /// <para>複数データ一括登録(共通処理)</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn = RegisterNewList(csStockDataList)</para>
        /// </example>
        /// <param name="csStockDataList">登録対象データリスト</param>
        /// <returns>true:成功、false:失敗</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        private bool RegisterNewList(HySStockDataList csStockDataList)
        {
            const string csMyMethodName = "RegisterNewList";

            HySDBALockFile csLockFile1 = new HySDBALockFile();
            if (!csLockFile1.Lock(MetaDataListFilePath, HySDBALockFile.LockMode.FOR_MODIFY))
            {
                HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "HySDBALockFile.Lock() error");
                return false;
            }
            try
            {
                // メタデータリストファイル読み込み
                HySStockMetaDataList csMetaDataList = ReadMetaDataListFile();
                if (csMetaDataList == null)
                {
                    HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "ReadMetaDataListFile() error");
                    return false;
                }

                // 登録済みをチェックする
                csStockDataList.SetCursorFirst();   // カーソルを先頭にセットする
                long lCount = csStockDataList.GetCount();
                for (long lIdx = 0; lIdx < lCount; ++lIdx)
                {
                    HySStockData csStockData = (HySStockData)csStockDataList.GetCursorData();
                    // 既に登録済みの場合、処理失敗とする
                    HySID csID = csStockData.GetID();
                    if (csMetaDataList.Contains(csID))
                    {
                        HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "data already exists",
                            "ID", csID);
                        return false;
                    }
                    // 追加重複チェックを行う
                    if (!AdditionalDuplicateCheck(csMetaDataList, csStockData))
                    {
                        HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "AdditionalDuplicateCheck() error");
                        return false;
                    }
                    csStockDataList.MoveCursorNext();   // 次のデータへ
                }
                csStockDataList.SetCursorFirst();   // カーソルを先頭に戻す

                // 登録処理実行
                HySTime csRegisterdTime = GetToday();
                for (long lIdx = 0; lIdx < lCount; ++lIdx)
                {
                    HySStockData csStockData = (HySStockData)csStockDataList.GetCursorData();
                    
                    // 振り分け先サブフォルダを取得
                    string csSubFolderPath = GetSubFolderPath(csStockData);

                    // 登録日時と保存期限区分変更日を設定
                    csStockData.SetRegisertTime(csRegisterdTime);
                    csStockData.SetPreservedPeriodModifyTime(csRegisterdTime);

                    // 登録データ本体をファイルに保存
                    String csDataFilePath;
                    if (!CreateDataFilePath(csSubFolderPath, out csDataFilePath))
                    {
                        HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "CreateDataFilePath() error");
                        return false;
                    }
                    if (!SaveFile(csDataFilePath, csStockData))
                    {
                        HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "SaveFile() error",
                            "DataFilePath", csDataFilePath);
                        return false;
                    }

                    // メタデータリストに追加する
                    HySID csID = csStockData.GetID();
                    //HySString csDataFileName = new HySString(Path.GetFileName(csDataFilePath.ToString()));
                    HySString csDataFileName = new HySString(Path.Combine(csSubFolderPath, Path.GetFileName(csDataFilePath)));
                    HySStockMetaData csRecord = new HySStockMetaData(csStockData, csDataFileName);
                    csMetaDataList.AddData(csID, csRecord);

                    csStockDataList.MoveCursorNext();   // 次のデータへ
                }
                // メタデータリスト一時保存
                if (!SaveFile(TmpMetaDataListFilePath, csMetaDataList))
                {
                    HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "SaveFile() error",
                        "TmpMetaDataListFilePath", TmpMetaDataListFilePath);
                    return false;
                }

                // ここまで、
                //   * 登録データ本体ファイル
                //   * 一時メタデータリストファイル
                // が作成されている。
                if (!UpdateMetaDataListFile())
                {
                    HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "UpdateMetaDataListFile() error");
                    // 管理ファイルの更新に失敗した場合、一時メタデータリストファイルを削除
                    DeleteFile(TmpMetaDataListFilePath);
                    return false;
                }

                // 不要ファイル削除処理を呼び出し、メタデータリストファイルのテキストダンプを行う
                CleanUp(csMetaDataList);
                DumpMetaDataListFile(csMetaDataList);

                return true;
            }
            finally
            {
                csLockFile1.UnLock();
            }
        }

        /// <summary><para>method outline:</para>
        /// <para>複数データ取得処理(共通処理)</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn = GetDataCommon(csIDs, csStockDataList)</para>
        /// </example>
        /// <param name="csIDs">ID配列</param>
        /// <param name="csStockDataList">登録データリスト</param>
        /// <returns>true:成功、false:失敗</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        private bool GetDataCommon(HySIdentifier[] csIDs, out HySStockDataList csStockDataList)
        {
            const string csMyMethodName = "GetDataCommon";

            // 出力パラメータ初期化
            csStockDataList = new HySStockDataList();

            HySDBALockFile csLockFile = new HySDBALockFile();
            if (!csLockFile.Lock(MetaDataListFilePath.ToString(), HySDBALockFile.LockMode.FOR_READONLY))
            {
                HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "HySDBALockFile.Lock() error");
                return false;
            }
            try
            {
                // メタデータリストファイル読み込み
                HySStockMetaDataList csMetaDataList = ReadMetaDataListFile();
                if (csMetaDataList == null)
                {
                    HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "ReadMetaDataListFile() error");
                    return false;
                }

                foreach (HySID csID in csIDs)
                {
                    // 指定されたユニークIDがメタデータリストファイルに含まれているか?
                    if (!csMetaDataList.Contains(csID))
                    {
                        HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "data not exists",
                            "ID", csID);
                        return false;
                    }

                    // メタデータリストファイルデータから登録データ本体ファイル名を取り出し、登録データ本体を
                    // 読み込む
                    HySStockMetaData csRecord = csMetaDataList.GetData(csID);
                    string csPath = Path.Combine(GetDBPath().ToString(), csRecord.GetPhysicalName().ToString());
                    HySDBALockFile csLockFile2 = new HySDBALockFile();
                    if (!csLockFile2.Lock(csPath, HySDBALockFile.LockMode.FOR_READONLY))
                    {
                        return false;
                    }
                    try
                    {
                        HySStockData csStockData = ReadStockDataFile(new HySString(csPath));
                        if (csStockData == null)
                        {
                            return false;
                        }
                        csStockDataList.AddLast(csStockData);
                    }
                    finally
                    {
                        csLockFile2.UnLock();
                    }
                }
                // 正常終了
                return true;
            }
            finally
            {
                csLockFile.UnLock();
            }
        }

        /// <summary><para>method outline:</para>
        /// <para>複数データ削除(共通処理)</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn = DeleteCommon(csIDs)</para>
        /// </example>
        /// <param name="csIDs">削除対象データID配列</param>
        /// <returns>true:成功、false:失敗</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        private bool DeleteCommon(HySIdentifier[] csIDs)
        {
            const string csMyMethodName = "DeleteCommon";

            HySDBALockFile csLockFile1 = new HySDBALockFile();
            if (!csLockFile1.Lock(MetaDataListFilePath.ToString(), HySDBALockFile.LockMode.FOR_MODIFY))
            {
                return false;
            }
            try
            {
                // メタデータリストファイル読み込み
                HySStockMetaDataList csMetaDataList = ReadMetaDataListFile();
                if (csMetaDataList == null)
                {
                    HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "ReadMetaDataListFile() error");
                    return false;
                }

                // メタデータリストからIDを削除する
                foreach (HySID csID in csIDs)
                {
                    if (!csMetaDataList.RemoveData(csID))
                    {
                        HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "HySStockMetaDataList.RemoveData() error",
                            "ID", csID);
                        return false;
                    }
                }

                // メタデータリスト一時保存
                if (!SaveFile(TmpMetaDataListFilePath, csMetaDataList))
                {
                    HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "SaveFile() error",
                        "TmpMetaDataListFilePath", TmpMetaDataListFilePath);
                    return false;
                }
                
                // メタデータリストファイル更新
                if (!UpdateMetaDataListFile())
                {
                    HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "UpdateMetaDataListFile() error");
                    // 管理ファイルの更新に失敗した場合、一時メタデータリストファイルを削除
                    DeleteFile(TmpMetaDataListFilePath);
                    return false;
                }

                // 不要ファイル削除処理を呼び出し、メタデータリストファイルのテキストダンプを行う
                CleanUp(csMetaDataList);
                DumpMetaDataListFile(csMetaDataList);

                return true;
            }
            finally
            {
                csLockFile1.UnLock();
            }
        }
        #endregion
    }
}
