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

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

namespace CommonMP.HYSSOP.CoreImpl.HSDBA.FileBase
{
    /// <summary><para>class outline:</para>
    /// <para>演算ロット情報DBAクラス</para>
    /// </summary>
    /// <remarks><para>remarks:</para>
    /// <para>演算ロット情報DBへのアクセスを提供する。</para>
    /// <para>性能上の問題から、本DBは複数のサブフォルダで分割管理する</para>
    /// <para>本クラスではサブフォルダ分割に関わる部分の処理を担当し、サブフォルダ内の処理はHySCalLotInfoDBASubクラスに委譲する。</para>
    /// </remarks>
    /// <remarks><para>history:</para>
    /// <para>[CommonMP][ver 1.0.0][2009/06/22][新規作成]</para>
    /// </remarks>
    public class HySCalLotInfoDBA: HySCommonDBA
    {
        /// <summary>
        /// 自クラス名(ログ出力用)
        /// </summary>
        private const string m_csMyClassName = "HySCalLotInfoDBA";

        /// <summary><para>method outline:</para>
        /// <para>デフォルトコンストラクタ</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>HySCommonDBA csDBA = new HySCalLotInfoDBA();</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>HySCalLotInfoDBA 生成されたクラスのインスタンス</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public HySCalLotInfoDBA()
        {
        }

        /// <summary>
        /// DBフォルダパス名を環境設定から取得するためのキー
        /// </summary>
        public const string ENVKEY_DBPATH = "HSDBA_CALLOTINFO_PATH";

        /// <summary>
        /// デフォルトＤＢパス
        /// </summary>
        public const string DEFAULT_DBPATH = @"\SystemData\db\callotinfo";

        #region publicメソッドのオーバーライド

        /// <summary><para>method outline:</para>
        /// <para>1件新規登録</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn = RegisterNew(csStockData)</para>
        /// </example>
        /// <param name="csStockData">DB登録データ</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)";

            // 登録データからサブフォルダ名を取得する
            string csSubFolderPath;
            if (!GetSubFolderPathFromStockData(csStockData, out csSubFolderPath))
            {
                HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "GetSubFolderPathFromStockData() error");
                return false;
            }

            // サブフォルダDBに処理を委譲する
            HySCalLotInfoDBASub csDBASub = new HySCalLotInfoDBASub(Path.Combine(GetDBBasePath(), csSubFolderPath));
            if (!csDBASub.RegisterNew(csStockData))
            {
                HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "HySCalLotInfoDBASub.RegisterNew() error",
                    "SubFolderPath", csSubFolderPath);
                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">DB登録データ</param>
        /// <returns>true:成功, false:失敗</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>前処理として、HySStockDataの追加検索キー(KeyInfo)に演算ロット情報の一部を設定する</para>
        /// </remarks>
        public override bool RegisterNew(HySStockDataList csStockDataList)
        {
            const string csMyMethodName = "RegisterNew(HySStockDataList)";

            // 登録データをサブフォルダごとに振り分ける
            Dictionary<string, HySStockDataList> csDispatchedStockDataList;
            if (!DispatchHySStockDataList(csStockDataList, out csDispatchedStockDataList))
            {
                HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "csDispatchedStockDataList() error");
                return false;
            }

            // サブフォルダDBに処理を委譲する
            string csDBPath = GetDBBasePath();
            foreach (string csSubFolderPath in csDispatchedStockDataList.Keys)
            {
                HySCalLotInfoDBASub csDBASub = new HySCalLotInfoDBASub(Path.Combine(csDBPath, csSubFolderPath));
                if (!csDBASub.RegisterNew(csDispatchedStockDataList[csSubFolderPath]))
                {
                    HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "HySCalLotInfoDBASub.RegisterNew() error",
                        "SubFolderPath", csSubFolderPath);
                    return false;
                }
            }
            return true;
        }

        /// <summary><para>method outline:</para>
        /// <para>1件更新</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> bool bRtn = Update(csStockData) </para>
        /// </example>
        /// <param name="csStockData">DB登録データ</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";

            // 登録データからサブフォルダ名を取得する
            string csSubFolderPath;
            if (!GetSubFolderPathFromStockData(csStockData, out csSubFolderPath))
            {
                HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "GetSubFolderPathFromStockData() error");
                return false;
            }

            // サブフォルダDBに処理を委譲する
            HySCalLotInfoDBASub csDBASub = new HySCalLotInfoDBASub(Path.Combine(GetDBBasePath(), csSubFolderPath));
            if (!csDBASub.Update(csStockData))
            {
                HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "HySCalLotInfoDBASub.Update() error",
                    "SubFolderPath", csSubFolderPath);
                return false;
            }

            return true;
        }

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

            // 検索条件からサブフォルダパスを取得する
            string[] csSubFolderNames;
            if (!GetSubFolderListFromQuery(csQueryCtrlData, out csSubFolderNames))
            {
                HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "GetSubFolderListFromQuery() error");
                return false;
            }
            // 検索条件で指定されていない場合、全てのサブフォルダを対象とする
            if (csSubFolderNames.Length == 0)
            {
                csSubFolderNames = GetAllSubFolderPath();
            }

            // サブフォルダDBに処理を委譲する
            string csDBPath = GetDBBasePath();

            foreach (string csSubFolderPath in csSubFolderNames)
            {
                HySCalLotInfoDBASub csDBASub = new HySCalLotInfoDBASub(Path.Combine(csDBPath, csSubFolderPath));
                if (!csDBASub.Delete(csQueryCtrlData))
                {
                    HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "HySCalLotInfoDBASub.Delete() error",
                        "SubFolderPath", csSubFolderPath);
                    return false;
                }
            }

            return true;
        }

        /// <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)
        {
            const string csMyMethodName = "Delete(HySID[])";

            // 全てのサブフォルダを対象とする
            string[] csSubFolderNames = GetAllSubFolderPath();

            // サブフォルダDBに処理を委譲する
            string csDBPath = GetDBBasePath();

            foreach (string csSubFolderPath in csSubFolderNames)
            {
                HySCalLotInfoDBASub csDBASub = new HySCalLotInfoDBASub(Path.Combine(csDBPath, csSubFolderPath));
                if (!csDBASub.Delete(csIDs))
                {
                    HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "HySCalLotInfoDBASub.Delete(HySQueryCtlData) error",
                        "SubFolderPath", csSubFolderPath);
                    return false;
                }
            }

            return true;
        }

        /// <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)
        {
            const string csMyMethodName = "Delete(HySID)";

            // 全てのサブフォルダを対象とする
            string[] csSubFolderNames = GetAllSubFolderPath();

            // サブフォルダDBに処理を委譲する
            string csDBPath = GetDBBasePath();
            foreach (string csSubFolderPath in csSubFolderNames)
            {
                HySCalLotInfoDBASub csDBASub = new HySCalLotInfoDBASub(Path.Combine(csDBPath, csSubFolderPath));
                if (!csDBASub.Delete(csID))
                {
                    HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "HySCalLotInfoDBASub.Delete(HySID) error",
                        "SubFolderPath", csSubFolderPath);
                    return false;
                }
            }

            return true;   
        }

        /// <summary><para>method outline:</para>
        /// <para>1件データ取得(ID指定)</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> bool bRtn = GetData(csID, csStockData) </para>
        /// </example>
        /// <param name="csID">取得対象データID</param>
        /// <param name="csStockData">DB登録データ</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";
            csStockData = null;

            // ID-EQUALSの検索条件を組み立てる
            HySQueryCtlData csQuery = new HySQueryCtlData();
            csQuery.SetQueryEntryData(new HySQueryEntryData(HySQueryFieldNames.ID, typeof(HySID),
                HySQueryCompareMode.EQUALS, csID));

            // 全てのサブフォルダを対象とする
            string[] csSubFolderNames = GetAllSubFolderPath();

            // サブフォルダDBに処理を委譲する
            string csDBPath = GetDBBasePath();
            Dictionary<HySID, HySStockData> csStockDataDict = new Dictionary<HySID, HySStockData>();
            foreach (string csSubFolderPath in csSubFolderNames)
            {
                HySStockDataList csStockDataListBySubFolder;
                HySCalLotInfoDBASub csDBASub = new HySCalLotInfoDBASub(Path.Combine(csDBPath, csSubFolderPath));
                if (!csDBASub.SearchList(csQuery, out csStockDataListBySubFolder))
                {
                    HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "HySCalLotInfoDBASub.SearchList() error",
                        "SubFolderPath", csSubFolderPath);
                }

                // 見つかったら終了
                if (csStockDataListBySubFolder.GetCount() > 0)
                {
                    csStockData = (HySStockData)csStockDataListBySubFolder.GetFirstData();
                    return true;
                }
            }

            // 見つからなかった
            HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "data not found",
                "ID", csID);
            return false;
        }

        /// <summary><para>method outline:</para>
        /// <para>複数件データ取得(ID配列指定)</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> bool bRtn = GetDataList(csIDs, csStockDataList) </para>
        /// </example>
        /// <param name="csIDs">取得対象データID配列</param>
        /// <param name="csStockDataList">DB登録データ一覧</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 = "GetDataList";
            csStockDataList = null;

            // ID-INの検索条件を組み立てる
            HySQueryCtlData csQuery = new HySQueryCtlData();
            csQuery.SetQueryEntryData(new HySQueryEntryData(HySQueryFieldNames.ID, typeof(HySID),
                HySQueryCompareMode.IN, csIDs));

            // 全てのサブフォルダを対象とする
            string[] csSubFolderNames = GetAllSubFolderPath();
            
            // サブフォルダDBに処理を委譲する
            string csDBPath = GetDBBasePath();
            Dictionary<HySID, HySStockData> csStockDataDict = new Dictionary<HySID, HySStockData>();
            foreach (string csSubFolderPath in csSubFolderNames)
            {
                HySStockDataList csStockDataListBySubFolder;
                HySCalLotInfoDBASub csDBASub = new HySCalLotInfoDBASub(Path.Combine(csDBPath, csSubFolderPath));
                if (!csDBASub.SearchList(csQuery, out csStockDataListBySubFolder))
                {
                    HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "HySCalLotInfoDBASub.SearchList() error",
                        "SubFolderPath", csSubFolderPath);
                }

                // サブフォルダごとの結果を辞書(キー=ID)に登録する
                long lDataCount = csStockDataListBySubFolder.GetCount();
                csStockDataListBySubFolder.SetCursorFirst();
                for (long lIdx = 0; lIdx < lDataCount; ++lIdx)
                {
                    HySStockData csStockData = (HySStockData)csStockDataListBySubFolder.GetCursorData();
                    csStockDataListBySubFolder.MoveCursorNext();

                    csStockDataDict.Add(csStockData.GetID(), csStockData);
                }
                csStockDataListBySubFolder.Clear();
                csStockDataListBySubFolder = null;

                // 指定されたIDが全て収集されたら終了
                if (csStockDataDict.Count >= csIDs.Length)
                {
                    csStockDataList = new HySStockDataList();
                    foreach (HySID csID in csIDs)
                    {
                        csStockDataList.AddLast(csStockDataDict[csID]);
                    }
                    return true;
                }
            }
            // 見つからないものがあった
            HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "data not found",
                "IDs.Length", csIDs.Length,
                "Found.Count", csStockDataDict.Count);
            return false;
        }

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

            // 検索条件からサブフォルダパスを取得する
            string[] csSubFolderNames;
            if (!GetSubFolderListFromQuery(csQueryCtlData, out csSubFolderNames))
            {
                HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "GetSubFolderListFromQuery() error");
                return false;
            }
            // 検索条件で指定されていない場合、全てのサブフォルダを対象とする
            if (csSubFolderNames.Length == 0)
            {
                csSubFolderNames = GetAllSubFolderPath();
            }

            // サブフォルダDBに処理を委譲する
            string csDBPath = GetDBBasePath();
            string csDBPathFull = GetDBBasePath(true);
            HySStockDataList csOutStockDataList = new HySStockDataList();
            foreach (string csSubFolderPath in csSubFolderNames)
            {
                HySStockDataList csStockDataListBySubFolder;
                string csSubFolderFullPath = Path.Combine(csDBPathFull, csSubFolderPath);
                string csSubFolderRelPath = Path.Combine(csDBPath, csSubFolderPath);
                if (!Directory.Exists(csSubFolderFullPath))
                {
                    // サブフォルダ無し→スキップ
                    continue;
                }
                HySCalLotInfoDBASub csDBASub = new HySCalLotInfoDBASub(csSubFolderRelPath);
                if (!csDBASub.SearchList(csQueryCtlData, out csStockDataListBySubFolder))
                {
                    HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "HySCalLotInfoDBASub.SearchList() error",
                        "SubFolderPath", csSubFolderPath);
                    return false;
                }

                // サブフォルダごとの結果を収集する
                long lDataCount = csStockDataListBySubFolder.GetCount();
                csStockDataListBySubFolder.SetCursorFirst();
                for (long lIdx = 0; lIdx < lDataCount; ++lIdx)
                {
                    csOutStockDataList.AddLast(csStockDataListBySubFolder.GetCursorData());
                    csStockDataListBySubFolder.MoveCursorNext();
                }
                csStockDataListBySubFolder.Clear();
                csStockDataListBySubFolder = null;
            }

            csStockDataList = csOutStockDataList;
            return true;
        }

        /// <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>無し</para>
        /// </remarks>
        public override bool UpdatePartial(HySQueryCtlData csQueryCtlData, HySDataHashTable csModifyData)
        {
            const string csMyMethodName = "UpdatePartial";

            // 検索条件からサブフォルダパスを取得する
            string[] csSubFolderNames;
            if (!GetSubFolderListFromQuery(csQueryCtlData, out csSubFolderNames))
            {
                HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "GetSubFolderListFromQuery() error");
                return false;
            }
            // 検索条件で指定されていない場合、全てのサブフォルダを対象とする
            if (csSubFolderNames.Length == 0)
            {
                csSubFolderNames = GetAllSubFolderPath();
            }

            // サブフォルダDBに処理を委譲する
            string csDBPath = GetDBBasePath();
            HySStockDataList csOutStockDataList = new HySStockDataList();
            foreach (string csSubFolderPath in csSubFolderNames)
            {
                HySCalLotInfoDBASub csDBASub = new HySCalLotInfoDBASub(Path.Combine(csDBPath, csSubFolderPath));
                if (!csDBASub.UpdatePartial(csQueryCtlData, csModifyData))
                {
                    HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "HySCalLotInfoDBASub.UpdatePartial() error",
                        "SubFolderPath", csSubFolderPath);
                    return false;
                }
            }
            return true;
        }

        #endregion

        /// <summary><para>method outline:</para>
        /// <para>DB基準パスを取得する(フルパス/相対パス指定)</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> string csPath = GetDBBasePath(bIsFullPath) </para>
        /// </example>
        /// <param name="bIsFullPath">true:フルパス、false:相対パス</param>
        /// <returns>パス文字列</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        private string GetDBBasePath(bool bIsFullPath)
        {
            // 環境設定からDBフォルダを取得する
            string csDBPath = null;
            HySString csHySStringDBPath = HySEnvInf.GetEnvInf(ENVKEY_DBPATH);
            if (((object)csHySStringDBPath) != null)
            {
                csDBPath = csHySStringDBPath.ToString();
            }
            else
            {
                csDBPath = DEFAULT_DBPATH;  // fallback value
            }
            // 末尾にディレクトリ区切り文字を追加する
            if (csDBPath[csDBPath.Length - 1] != Path.DirectorySeparatorChar)
            {
                csDBPath += Path.DirectorySeparatorChar;
            }

            // フルパス指定の時、DBディレクトリと連結する
            if (bIsFullPath)
            {
                string csHomePath = HySEnvInf.GetDBDirectory().ToString();
                csDBPath = csHomePath + csDBPath;
            }

            return csDBPath;
        }

        /// <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>
        private string GetDBBasePath()
        {
            return GetDBBasePath(false);
        }

        /// <summary><para>method outline:</para>
        /// <para>DB保存データからサブフォルダ名を取得する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> bool bRtn = GetSubFolderPathFromStockData(csStockData, out csSubFolderPath) </para>
        /// </example>
        /// <param name="csStockData">DB保存データ</param>
        /// <param name="csSubFolderPath">csStockDataが格納されるべきサブフォルダの名称(相対パス)</param>
        /// <returns>true:成功, false:失敗(キーとなるデータが設定されていない)</returns>
        /// <remarks><para>remarks:</para>
        /// <para>実行時刻から年月を取得し、サブフォルダ文字列を構築する</para>
        /// </remarks>
        private bool GetSubFolderPathFromStockData(HySStockData csStockData, out string csSubFolderPath)
        {
            const string csMyMethodName = "GetSubFolderPathFromStockData";

            csSubFolderPath = null;

            HySCalcLotInfo csCalcLotInfo;
            //HySCalLotSuppInfo csCalLotSuppInfo;

            // 演算ロット情報を取得
            csCalcLotInfo = csStockData.GetData() as HySCalcLotInfo;
            if (csCalcLotInfo == null)
            {
                HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "StockData.GetData is null or not HySCalcLotInfo");
                return false;
            }

            // 実行時刻からサブフォルダパスを生成する
            if (!CreateSubFolderPathFromHySTime(csCalcLotInfo.GetCalcExecDate(), out csSubFolderPath))
            {
                HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "CreateSubFolderPathFromHySTime() error");
            }
            return true;
        }

        /// <summary><para>method outline:</para>
        /// <para>HySStockDataListに格納されたDB格納データをサブフォルダごとに振り分ける</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> bool bRtn = DispatchHySStockDataList(csStockDataList, out csStockDataListDict) </para>
        /// </example>
        /// <param name="csStockDataList">DB格納データリスト</param>
        /// <param name="csStockDataListDict">DB格納データリスト辞書。サブフォルダ名がキー</param>
        /// <returns>true:成功, false:失敗(不正なデータが混在している)</returns>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        private bool DispatchHySStockDataList(HySStockDataList csStockDataList, out Dictionary<string, HySStockDataList> csStockDataListDict)
        {
            const string csMyMethodName = "DispatchHySStockDataList";

            csStockDataListDict = new Dictionary<string, HySStockDataList>();
            long lDataCount = csStockDataList.GetCount();
            csStockDataList.SetCursorFirst();

            for (long lIdx = 0; lIdx < lDataCount; ++lIdx)
            {
                // DB保存データを取得し、カーソルを進める
                HySStockData csStockData = (HySStockData)csStockDataList.GetCursorData();
                csStockDataList.MoveCursorNext();

                // DB保存データからサブフォルダ名を取得する
                string csSubFolderName;
                if (!GetSubFolderPathFromStockData(csStockData, out csSubFolderName))
                {
                    HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "GetSubFolderPathFromStockData() error");
                    return false;
                }

                // 振り分けStockDataListを辞書から取得する
                HySStockDataList csDispatchedStockDataList;
                if (csStockDataListDict.ContainsKey(csSubFolderName))
                {
                    csDispatchedStockDataList = csStockDataListDict[csSubFolderName];
                }
                else
                {
                    // 未登録なら作って登録する
                    csDispatchedStockDataList = new HySStockDataList();
                    csStockDataListDict.Add(csSubFolderName, csDispatchedStockDataList);
                }

                // DB保存データを振り分ける
                csDispatchedStockDataList.AddLast(csStockData);
            }

            return true;
        }

        /// <summary><para>method outline:</para>
        /// <para>検索条件からサブフォルダパスを取得する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> bool bRtn = GetSubFolderListFromQuery(csQuery, out csSubFolderPaths) </para>
        /// </example>
        /// <param name="csQuery">検索条件</param>
        /// <param name="csSubFolderPaths">サブフォルダパス(相対パス)</param>
        /// <returns>true:成功, false:失敗(不正なデータ)</returns>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        private bool GetSubFolderListFromQuery(HySQueryCtlData csQuery, out string[] csSubFolderPaths)
        {
            const string csMyMethodName = "GetSubFolderListFromQuery";
            csSubFolderPaths = null;

            // 検索条件から実行時刻を取得する
            HySQueryEntryData csQEntry = csQuery.GetQueryEntryData(HySCalLotInfoQueryFieldNames.CALC_EXEC_DATE);
            if (csQEntry == null)
            {
                csSubFolderPaths = new string[0];   // 0件を返す
                return true;
            }

            // 検索条件から時刻データを取得する
            HySQueryCompareMode eCompareMode = csQEntry.GetCompareMode();
            List<HySTime> csHsTimeList = new List<HySTime>();

            if (eCompareMode == HySQueryCompareMode.EQUALS)
            {
                csHsTimeList.Add((HySTime)csQEntry.GetValueToCompare());
            }
            else if (eCompareMode == HySQueryCompareMode.IN)
            {
                csHsTimeList.AddRange((HySTime[])csQEntry.GetValueToCompare());
            }
            else if (eCompareMode == HySQueryCompareMode.BETWEEN)
            {
                // From-Toを1ヶ月間隔で展開する
                HySTime[] csHsTimeRange = (HySTime[])csQEntry.GetValueToCompare();
                double dFromTime = csHsTimeRange[0].GetTime();
                double dToTime = csHsTimeRange[1].GetTime();
                double dSecondsOfMonth = 60 * 60 * 24 * 31;   // 1ヶ月の秒数。31日で計算
                for (double dTime = dFromTime; dTime < dToTime; dTime += dSecondsOfMonth)
                {
                    csHsTimeList.Add(new HySTime(dTime));
                }
                csHsTimeList.Add(csHsTimeRange[1]);
            }
            else
            {
                HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "unsupported query",
                    "CompareMode", eCompareMode);
                return false;
            }

            // 時刻のリストをサブフォルダパスに展開する
            Dictionary<string, string> csSubFolderPathDict = new Dictionary<string, string>();
            foreach (HySTime csHsBaseTime in csHsTimeList)
            {
                string csSubFolderPath;
                if (!CreateSubFolderPathFromHySTime(csHsBaseTime, out csSubFolderPath))
                {
                    HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "CreateSubFolderPathFromHySTime() error",
                        "CompareMode", eCompareMode);
                    return false;
                }
                if (!csSubFolderPathDict.ContainsKey(csSubFolderPath))
                {
                    csSubFolderPathDict.Add(csSubFolderPath, null);
                }
            }

            // 出力パラメータ設定
            csSubFolderPaths = new string[csSubFolderPathDict.Count];
            int i = 0;
            foreach (string csSubFolderPath in csSubFolderPathDict.Keys)
            {
                csSubFolderPaths[i++] = csSubFolderPath;
            }

            return true;
        }

        /// <summary><para>method outline:</para>
        /// <para>全てのサブフォルダパスを取得する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> string[] csPathList = GetAllSubFolderPath() </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>全てのサブフォルダパス</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        private string[] GetAllSubFolderPath()
        {
            // DB基準パス(フルパス)を取得する
            string csDBPath = GetDBBasePath(true);

            // DB基準パス配下のディレクトリ一覧を収集する
            List<string> csSubFolderPathList = new List<string>();
            if (Directory.Exists(csDBPath))
            {
                foreach (string csSubFolderPath in Directory.GetDirectories(csDBPath))
                {
                    csSubFolderPathList.Add(csSubFolderPath.Replace(csDBPath, string.Empty));
                }
            }
            return csSubFolderPathList.ToArray();
        }

        /// <summary><para>method outline:</para>
        /// <para>実行時刻からサブフォルダパスを生成する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> bool bRtn = CreateSubFolderPathFromHySTime(csHsCalcExecData, out csSubFolderPath) </para>
        /// </example>
        /// <param name="csHsCalcExecDate">実行時刻</param>
        /// <param name="csSubFolderPath">サブフォルダパス(相対パス)</param>
        /// <returns>
        /// <para>true:成功, false:失敗(不正なデータ)</para>
        /// </returns>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        private bool CreateSubFolderPathFromHySTime(HySTime csHsCalcExecDate, out string csSubFolderPath)
        {
            const string csMyMethodName = "CreateSubFolderPathFromHySTime";
            csSubFolderPath = null;

            // 実行時刻のデータ型を変換する(HySTime→DateTime)
            string csBaseTimeString = HySCalendar.ToString(csHsCalcExecDate, HySCalendar.FORMAT.lSW_YEAR);
            DateTime csBaseTime;
            if (!DateTime.TryParse(csBaseTimeString, out csBaseTime))
            {
                HySDBALog.WriteOnline(m_csMyClassName, csMyMethodName, "BaseTime convert error",
                    "BaseTimeString", csBaseTimeString);
                return false;
            }

            // 実行時刻の年月からフォルダ名を作成する
            csSubFolderPath = csBaseTime.ToString("yyyyMM");

            return true;
        }

    }
}
