// <summary>ソースコード：演算結果DBアクセス出力制御クラス</summary>
// <author>CommonMP</author>

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

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

using CommonMP.HYMCO.Interface;
using CommonMP.HYMCO.Interface.Data;
using CommonMP.HYMCO.Interface.Model;
using CommonMP.HYMCO.CoreImpl;
using CommonMP.HYMCO.CoreImpl.Tool;
using CommonMP.HYMCO.CoreImpl.Data;
using CommonMP.HYMCO.CoreImpl.Data.FileIO;
using CommonMP.HYMCO.CoreImpl.Data.ProjectCtl;
using CommonMP.HYMCO.CoreImpl.Model;
using CommonMP.HYMCO.CoreImpl.Controller;
using CommonMP.HYMCO.CoreImpl.DBA;

namespace CommonMP.HYMCO.CoreImpl.Model
{
    /// <summary><para>class outline:</para>
    /// <para>演算結果DBアクセス出力制御クラス</para>
    /// </summary>
    /// <remarks><para>history:</para>
    /// <para>
    /// [CommonMP][ver 1.0.0][2009/06/10][新規作成]
    /// </para>
    /// </remarks>
    public class McCalResultDBAccessOut : McIOCtlModlBase, McOutModelCtlIF
    {
        //--------------------------------
        // 定数定義
        //--------------------------------
        /// <summary>演算結果DBアクセス出力要素プロパティ「格納データサイズ」　キー情報</summary>
        public static readonly string MODEL_DBACCESS_OUT_STOREDATA_SIZE_KEY = "StoreDataSize";
        /// <summary>演算結果DBアクセス出力要素プロパティ「格納データサイズ」　名称</summary>
        public static readonly string MODEL_DBACCESS_OUT_STOREDATA_SIZE_NAME = Properties.HymcoImplResources.MODEL_DBACCESS_OUT_STOREDATA_SIZE_NAME;
        /// <summary>演算結果DBアクセス出力要素プロパティ「DB格納データ間引き間隔」　キー情報</summary>
        public static readonly string MODEL_DBACCESS_OUT_THIN_OUT_SIZE_KEY = "ThinOutSize";
        /// <summary>演算結果DBアクセス出力要素プロパティ「DB格納データ間引き間隔」　名称</summary>
        public static readonly string MODEL_DBACCESS_OUT_THIN_OUT_SIZE_NAME = Properties.HymcoImplResources.MODEL_DBACCESS_OUT_THIN_OUT_SIZE_NAME;
        /// <summary>「格納データサイズ」デフォルト値</summary>
        public static readonly long DEFAULT_STOREDATA_SIZE = 100;
        /// <summary>「DB格納データ間引き間隔」デフォルト値</summary>
        public static readonly long DEFAULT_THIN_OUT_SIZE = 30;
        /// <summary>ログ出力用クラス名称</summary>
        private static readonly string CLASS_NAME = "McCalResultDBAccessOut";


        //---------------------------------------
        // 演算中データファイル出力 非対象メンバ
        //---------------------------------------
        /// <summary>DBアクセスコンポーネント</summary>
        protected HySCommonDBA m_csDBAccess = null;
        /// <summary>シミュレーションコンテナ</summary>
        protected HySSimulationDataContainer m_csDataContainer = null;
        /// <summary>演算結果データ格納サイズ最大値</summary>
        protected long m_lStoreDataMaxSize = 0;
        /// <summary>演算結果データ間引き間隔</summary>
        protected long m_lThinOutDataSize = 0;
        /// <summary>最終取得データバックアップ</summary>
        protected HySTimeRecordIF m_csLastDataBackUp = null;

        //---------------------------------------
        // 演算中データファイル出力 対象メンバ
        //---------------------------------------
        /// <summary>最終データ取得時刻</summary>
        protected HySTime m_csLastTime = HySTime.DEFAULT_TIME.Clone();
        /// <summary>演算結果格納先データ</summary>
        protected HySTimeSeriesBase m_csStoreData = null;
        /// <summary>演算結果格納先データ型</summary>
        protected HySObjectKind m_csStoreDataType = null;
        /// <summary>演算結果格納先データ次元数（0番目：1次元値　1番目：2次元値　2番目：3次元値</summary>
        protected HySLong[] m_csStoreDataDimentionList = null;
        /// <summary>1演算結果レコード連番</summary>
        protected long m_lCalResultRegistNo = 0;
        /// <summary>データ間引きカウント</summary>
        protected long m_lThinOutDataCount = 0;

        /// <summary><para>method outline:</para>
        /// <para>デフォルトコンストラクタ</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>McCalResultDBAccessOut csModel = McCalResultDBAccessOut()</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>McCalResultDBAccessOut　生成されたインスタンス</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public McCalResultDBAccessOut()
        {
            // DBアクセスコンポーネントの設定
            m_csDBAccess = new HySCalResultDataDBA();
        }

        /// <summary><para>method outline:</para>
        /// <para>モデルを初期化する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn = Initialize(csInitialData)</para>
        /// </example>
        /// <param name="csInitialData">初期化設定情報</param>
        /// <returns>=true:正常、=false:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected override bool Initialize(ref McPropertyInfoRoot csInitialData)
        {
            // 演算結果格納先の初期化
            m_csStoreData = null;
            m_csStoreDataType = null;
            m_csStoreDataDimentionList = new HySLong[3];
            for (int i = 0; i < m_csStoreDataDimentionList.Length; i++)
            {
                m_csStoreDataDimentionList[i] = new HySLong(0);
            }

            m_lCalResultRegistNo = 0;

            m_lThinOutDataCount = m_lThinOutDataSize;

            // 最終データ取得時刻初期化
            m_csLastTime.SetTime(HySTime.DEFAULT_TIME);
            m_csLastDataBackUp = null;

            return true;
        }

        /// <summary><para>method outline:</para>
        /// <para>入力側の接続情報チェック</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn = ReceiveConnectionCheck(ref csErrorInf)</para>
        /// </example>
        /// <param name="csErrorInf">エラー出力</param>
        /// <returns>=true:正常、=false:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>受信するデータが自モデルが期待している情報か否かをチェックする</para>
        /// </remarks>
        protected override bool ReceiveConnectionCheck(ref McStructErrorInfo csErrorInf)
        {
            bool bRtn = true;

            // 受信接続可能伝送情報データ型リスト
            Type[] csReceiveTypeList = new Type[] {   typeof(McD1CellArrayTranInfo),
                                                      typeof(McD2CellArrayTranInfo),
                                                      typeof(McD3CellArrayTranInfo),
                                                      typeof(McTimeSeriesSingleCellTranInfo),
                                                      typeof(McTimeSeriesD1CellArrayTranInfo),
                                                      typeof(McTimeSeriesD2CellArrayTranInfo),
                                                      typeof(McTimeSeriesD3CellArrayTranInfo),
                                                      typeof(McGeoDim2MeshTranInfo),
                                                      typeof(McGeoDim3MeshTranInfo),
                                                      typeof(McTimeSeriesGeoD2MeshTranInfo),
                                                      typeof(McTimeSeriesGeoD3MeshTranInfo)
                                                  };

            // 接続数の確認
            if (m_lInputDataNum != 1)
            {
               // ver1.5 エラートレース日本語対応
                csErrorInf.AddCheckErrorData(this.m_csElement.GetID(), McModelLibraryDefine.HYM_MODEL_CALRESULT_DBA_OUT,
                                                Properties.HymcoImplResources.STATEMENT_NEED_ELEMENT_PORT );
               // csErrorInf.AddCheckErrorData(this.m_csElement.GetID(), McModelLibraryDefine.HYM_MODEL_CALRESULT_DBA_OUT,
               //                                 "Element need only one Recieve Port.");
                bRtn = false;
            }
            else
            {
                // 伝送情報データ型の確認
                bool bContain = false;
                Type csOutputDataType = m_csInputData[0].GetType();
                foreach (Type csType in csReceiveTypeList)
                {
                    if (csType.Equals(csOutputDataType))
                    {
                        bContain = true;
                        break;
                    }
                }

                // 接続可能伝送情報データ型に含まれていない場合はエラー
                if (!bContain)
                {
                   // ver1.5 エラートレース日本語対応
                    csErrorInf.AddCheckErrorData(this.m_csElement.GetID(), McModelLibraryDefine.HYM_MODEL_CALRESULT_DBA_OUT,
                                                    Properties.HymcoImplResources.STATEMENT_UNEXPECT_DATA_TYPE );
                   // csErrorInf.AddCheckErrorData(this.m_csElement.GetID(), McModelLibraryDefine.HYM_MODEL_CALRESULT_DBA_OUT,
                   //                                 "Unexpected send data type.");
                    bRtn = false;
                }
            }

            // ここまでのチェックがOKの場合のみチェック可能
            if (bRtn)
            {
                // セル内データ種別情報が設定されているかをチェック
                if (((McTranInfoIFCellType)m_csInputData[0]).GetCellDataCharacteristic() == null)
                {
                   // ver1.5 エラートレース日本語対応
                    csErrorInf.AddCheckErrorData(this.m_csElement.GetID(), McModelLibraryDefine.HYM_MODEL_CALRESULT_DBA_OUT,
                                                   Properties.HymcoImplResources.STATEMENT_NO_CELLDATA_CHARA );
                   // csErrorInf.AddCheckErrorData(this.m_csElement.GetID(), McModelLibraryDefine.HYM_MODEL_CALRESULT_DBA_OUT,
                   //                                 "Not set CellDataCharacteristic.");
                    bRtn = false;
                }
                else
                {
                    // セル内変数のデータ種別が重複していないかチェック
                    HySDataCharacteristicInCell csDataKindInCell = ((McTranInfoIFCellType)m_csInputData[0]).GetCellDataCharacteristic();
                    for (long lLp = 0; lLp < csDataKindInCell.GetDataNumber(); lLp++)
                    {
                        long lFlgNum = 0;
                        HySObjectKind csComparekind = null;
                        csComparekind = csDataKindInCell.GetDataKind(lLp);
                        for (long lLp2 = 0; lLp2 < csDataKindInCell.GetDataNumber(); lLp2++)
                        {
                            if (csDataKindInCell.GetDataKind(lLp2) == csComparekind)
                            {
                                lFlgNum += 1;
                                if (lFlgNum > 1)
                                {
                                    // 重複ありの場合、エラー出力
                                   // ver1.5 エラートレース日本語対応
                                    csErrorInf.AddCheckErrorData(this.m_csElement.GetID(), McModelLibraryDefine.HYM_MODEL_CALRESULT_DBA_OUT,
                                                            Properties.HymcoImplResources.STATEMENT_CLASSIFICAT_REPEAT );
                                   // csErrorInf.AddCheckErrorData(this.m_csElement.GetID(), McModelLibraryDefine.HYM_MODEL_CALRESULT_DBA_OUT,
                                   //                         "Receive data classification repeats.");
                                    bRtn = false;
                                }
                            }
                        }
                        if (bRtn == false)
                        {
                            // 重複データ種別が見つかればチェック終了
                            break;
                        }
                    }
                }
            }

            return bRtn;
        }

        /// <summary><para>method outline:</para>
        /// <para>出力側の接続情報チェック</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn = SendConnectionCheck(ref csErrorInf)</para>
        /// </example>
        /// <param name="csErrorInf">エラー出力</param>
        /// <returns>=true:正常、=false:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>送信端子に設定されている伝送データが自モデルが期待している情報か否かをチェックする</para>
        /// </remarks>
        protected override bool SendConnectionCheck(ref McStructErrorInfo csErrorInf)
        {
            bool bRtn = true;

            // 出力要素が送信接続を持つ場合、エラー
            if (m_lOutputDataNum > 0)
            {
               // ver1.5 エラートレース日本語対応
                csErrorInf.AddCheckErrorData(this.m_csElement.GetID(), McModelLibraryDefine.HYM_MODEL_CALRESULT_DBA_OUT,
                                                Properties.HymcoImplResources.STATEMENT_NOT_ELEMENT_PORT );
               // csErrorInf.AddCheckErrorData(this.m_csElement.GetID(), McModelLibraryDefine.HYM_MODEL_CALRESULT_DBA_OUT,
               //                                 "Element must not have Send Ports.");
                bRtn = false;
            }

            return bRtn;
        }

        /// <summary><para>method outline:</para>
        /// <para>モデル演算結果を外部のエレメントに対して公開する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>long lRtn = DataFusion( )</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>=CALCULATION_NORMAL_RETURN:正常 それ以外:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected override long DataFusion()
        {
            return McDefine.CALCULATION_NORMAL_RETURN;
        }

        /// <summary><para>method outline:</para>
        /// <para>モデル演算</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>long lRtn = Calculate(ref csInputDataList)</para>
        /// </example>
        /// <param name="csInputDataList">演算に必要な入力情報リスト</param>
        /// <returns>CALCULATION_NORMAL_RETURN:正常, それ以外:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>受信伝送情報データから演算結果を取り出して内部に格納する</para>
        /// </remarks>
        public override long Calculate(ref HySDataLinkedList csInputDataList)
        {
            // 親の演算処理実行
            base.Calculate(ref csInputDataList);

            // 演算結果格納先が未作成の場合は作成する
            if (m_csStoreData == null)
            {
                m_csStoreData = CreateStoreData(m_csInputData[0], m_lStoreDataMaxSize);
            }

            // 伝送情報データの時刻を取得する
            HySTime csTranInfoTime = GetTranInfoLastTime(m_csInputData[0]);

            // データ更新のチェックを行う
            while (csTranInfoTime.After(m_csLastTime))
            {
                // 各受信伝送情報型に合わせて、1件のデータ受信する
                HySTimeRecordIF csRecord = GetReceiveData(m_csInputData[0]);

                // 現在のデータ間引き個数が設定値に到達している場合･･･データを格納
                if (m_lThinOutDataCount == m_lThinOutDataSize)
                {
                    AddStoreData(csRecord);
                    // データ間引きカウントのリセット
                    m_lThinOutDataCount = 0;
                }
                // 到達していない場合･･･データをバックアップ領域に格納し、間引きカウントを更新
                else
                {
                    m_csLastDataBackUp = csRecord;
                    m_lThinOutDataCount++;
                }

                // 格納データ数が格納サイズ最大値以上になった場合はデータ登録を行う
                if (m_csStoreData.GetCount() >= m_lStoreDataMaxSize)
                {
                    if (!RegisterData())
                    {
                        // 登録失敗時は強制終了
                        return McDefine.CALCULATION_FORCE_STOP_RETURN;
                    }
                }
            }

            return McDefine.CALCULATION_NORMAL_RETURN;
        }

        /// <summary><para>method outline:</para>
        /// <para>演算結果格納先データ生成</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>HySTimeSeriesBase csStoreData = CreateStoreData(csTranInfo, lStoreDataMaxSize)</para>
        /// </example>
        /// <param name="csTranInfo">受信する伝送情報データクラス</param>
        /// <param name="lStoreDataMaxSize">レコード格納最大値</param>
        /// <returns>HySTimeSeriesBase 受信する伝送情報データクラスに対応するデータ格納クラス</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>受信する伝送情報データ型に合わせて、演算結果を格納するためのデータクラスを生成する</para>
        /// </remarks>
        protected virtual HySTimeSeriesBase CreateStoreData(McTranInfo csTranInfo, long lStoreDataMaxSize)
        {
            HySTimeSeriesBase csRtnData = null;

            //-------------------------------------------- 
            // 各伝送情報型に対応する演算結果格納データクラスを生成する
            //--------------------------------------------

            // 1次元セル
            if (csTranInfo is McD1CellArrayTranInfo)
            {
                csRtnData = new HySTimeSeriesD1CellArrayData((HySD1CellArrayData)csTranInfo);
                m_csStoreDataType = HySDataKindDefine.D1_CELL_SERIAL;
            }
            // 2次元セル
            else if (csTranInfo is McD2CellArrayTranInfo)
            {
                csRtnData = new HySTimeSeriesD2CellArrayData((HySD2CellArrayData)csTranInfo);
                m_csStoreDataType = HySDataKindDefine.D2_CELL_SERIAL;
            }
            // 3次元セル
            else if (csTranInfo is McD3CellArrayTranInfo)
            {
                csRtnData = new HySTimeSeriesD3CellArrayData((HySD3CellArrayData)csTranInfo);
                m_csStoreDataType = HySDataKindDefine.D3_CELL_SERIAL;
            }
            // 時系列 単独セル
            else if (csTranInfo is McTimeSeriesSingleCellTranInfo)
            {
                csRtnData = new HySTimeSeriesD1CellArrayData((HySTimeSeriesD1CellArrayData)csTranInfo);
                m_csStoreDataType = HySDataKindDefine.D1_CELL_SERIAL;
            }
            // 時系列 1次元セル
            else if (csTranInfo is McTimeSeriesD1CellArrayTranInfo)
            {
                csRtnData = new HySTimeSeriesD1CellArrayData((HySTimeSeriesD1CellArrayData)csTranInfo);
                m_csStoreDataType = HySDataKindDefine.D1_CELL_SERIAL;
            }
            // 時系列 2次元セル
            else if (csTranInfo is McTimeSeriesD2CellArrayTranInfo)
            {
                csRtnData = new HySTimeSeriesD2CellArrayData((HySTimeSeriesD2CellArrayData)csTranInfo);
                m_csStoreDataType = HySDataKindDefine.D2_CELL_SERIAL;
            }
            // 時系列 3次元セル
            else if (csTranInfo is McTimeSeriesD3CellArrayTranInfo)
            {
                csRtnData = new HySTimeSeriesD3CellArrayData((HySTimeSeriesD3CellArrayData)csTranInfo);
                m_csStoreDataType = HySDataKindDefine.D3_CELL_SERIAL;
            }
            // 2次元地理メッシュ
            else if (csTranInfo is McGeoDim2MeshTranInfo)
            {
                csRtnData = new HySGeoDim2MeshSerialData((HySGeoDim2MeshData)csTranInfo);
                m_csStoreDataType = HySDataKindDefine.D2_GIS_MESH_SERIAL;
            }
            // 3次元地理メッシュ
            else if (csTranInfo is McGeoDim3MeshTranInfo)
            {
                csRtnData = new HySGeoDim3MeshSerialData((HySGeoDim3MeshData)csTranInfo);
                m_csStoreDataType = HySDataKindDefine.D3_GIS_MESH_SERIAL;
            }
            // 時系列 2次元地理メッシュ
            else if (csTranInfo is McTimeSeriesGeoD2MeshTranInfo)
            {
                csRtnData = new HySGeoDim2MeshSerialData((HySGeoDim2MeshSerialData)csTranInfo);
                m_csStoreDataType = HySDataKindDefine.D2_GIS_MESH_SERIAL;
            }
            // 時系列 3次元地理メッシュ
            else if (csTranInfo is McTimeSeriesGeoD3MeshTranInfo)
            {
                csRtnData = new HySGeoDim3MeshSerialData((HySGeoDim3MeshSerialData)csTranInfo);
                m_csStoreDataType = HySDataKindDefine.D3_GIS_MESH_SERIAL;
            }

            // 次元数の取得
            McTranInfoIFCellType csCellTypeTranInfo = (McTranInfoIFCellType)csTranInfo;
            csCellTypeTranInfo.GetDimension(ref m_csStoreDataDimentionList[0].m_lValue,
                                            ref m_csStoreDataDimentionList[1].m_lValue,
                                            ref m_csStoreDataDimentionList[2].m_lValue);

            // 初期化
            csRtnData.Clear();
            // レコード格納サイズ設定
            csRtnData.SetMaxHoldDataNum(lStoreDataMaxSize);

            return csRtnData;
        }

        /// <summary><para>method outline:</para>
        /// <para>伝送情報データ最新時刻取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>HySTime csTime = GetTranInfoLastTime(csTranInfo)</para>
        /// </example>
        /// <param name="csTranInfo">受信伝送情報データ</param>
        /// <returns>HySTime 伝送情報データに設定されている時刻</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>伝送情報データに設定されている最新時刻を取得する</para>
        /// </remarks>
        protected virtual HySTime GetTranInfoLastTime(McTranInfo csTranInfo)
        {
            HySTime csRtnTime = null;
            // 時系列データ
            if (csTranInfo is HySTimeSeriesBase)
            {
                csRtnTime = ((HySTimeSeriesBase)csTranInfo).GetLastTime();
            }
            // 非時系列データ（時系列の1レコード)
            else
            {
                csRtnTime = ((HySTimeRecordIF)csTranInfo).GetLastTime();
            }

            return csRtnTime;
        }

        /// <summary><para>method outline:</para>
        /// <para>受信データ1件取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>HySTimeRecordIF csData = GetReceiveData(csTranInfo)</para>
        /// </example>
        /// <param name="csTranInfo">受信伝送情報データ</param>
        /// <returns>HySTimeRecordIF 1件分の受信データレコード</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>伝送情報型の種別に合わせてデータを1件取得する</para>
        /// </remarks>
        protected virtual HySTimeRecordIF GetReceiveData(McTranInfo csTranInfo)
        {
            HySTimeRecordIF csRecord = null;

            // 伝送情報型の種別に合わせて演算結果を取得する

            // 時系列
            if (csTranInfo is HySTimeSeriesBase)
            {
                HySTimeSeriesBase csTimeSeries = (HySTimeSeriesBase)csTranInfo;
                // カーソルをデータ取得時刻の直後に設定
                csTimeSeries.SetCursorPlus(m_csLastTime);

                csRecord = csTimeSeries.GetCursorData();
            }
            // 非時系列（時系列の1レコード）
            else
            {
                csRecord = (HySTimeRecordIF)csTranInfo;
            }

            // データ取得時刻の更新
            m_csLastTime.SetTime(csRecord.GetLastTime());

            return csRecord;
        }

        /// <summary><para>method outline:</para>
        /// <para>格納データ1件追加</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>AddStoreData(csRecord)</para>
        /// </example>
        /// <param name="csRecord">1件分の受信データレコード</param>
        /// <returns>無し </returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>データ格納先の種別に合わせてデータを1件追加する</para>
        /// </remarks>
        protected virtual void AddStoreData( HySTimeRecordIF csRecord )
        {
            // 演算結果格納先のデータ型に合わせて格納

            // セル時系列形式
            if (!IsGeoMeshSerial(m_csStoreData))
            {
                HySCellArray csCellRecord = (HySCellArray)m_csStoreData.CreateNewRecord();
                csCellRecord.CopyData((HySCellArray)csRecord);
                m_csStoreData.AddData(csCellRecord);
            }
            // 地理メッシュ時系列形式
            else
            {
                HySGeoMesh csMeshRecord = (HySGeoMesh)m_csStoreData.CreateNewRecord();
                csMeshRecord.CopyData((HySGeoMesh)csRecord);
                m_csStoreData.AddData(csMeshRecord);
            }

            // バックアップデータの削除
            m_csLastDataBackUp = null;
        }

        /// <summary><para>method outline:</para>
        /// <para>計算中断時に動作する処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn = SuspendCalculation( )</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>true :正常 , false:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>出力結果をDBに登録する</para>
        /// </remarks>
        public override bool SuspendCalculation()
        {
            return ForceRegistration();
        }

        /// <summary><para>method outline:</para>
        /// <para>計算終了時に動作する処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn = CompleteCalculation( )</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>true :正常 , false:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>出力結果をDBに登録する</para>
        /// </remarks>
        public override bool CompleteCalculation()
        {
            return ForceRegistration();
        }

        /// <summary><para>method outline:</para>
        /// <para>強制登録</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn = ForceRegistration( )</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>true :正常 , false:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>現在格納中の演算結果が0件でない限り登録を実行する</para>
        /// </remarks>
        protected virtual bool ForceRegistration()
        {
            // 最終取得データバックアップ有の場合は演算結果に追加する
            if (m_csLastDataBackUp != null)
            {
                AddStoreData(m_csLastDataBackUp);
            }

            // 受信データ数が0件でないorバックアップデータ有の場合、登録を実行
            bool bRtn = true;
            if ((m_csStoreData.GetCount() > 0))
            {
                bRtn = RegisterData();
            }

            return bRtn;
        }

        /// <summary><para>method outline:</para>
        /// <para>データ登録処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn = RegisterData()</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>true :正常 , false:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>出力結果をDBに登録する</para>
        /// </remarks>
        protected virtual bool RegisterData()
        {
            string strMethodName = System.Reflection.MethodBase.GetCurrentMethod().Name;

            HySStockDataList csRegistDataList = new HySStockDataList();

            // 共通項目を設定したレコードの生成
            HySStockData csBaseStockData = CreateBaseStockData();


            // データ種別数分のレコードを生成
            HySDataCharacteristicInCell csCharaIncell = ((McTranInfoIFCellType)m_csInputData[0]).GetCellDataCharacteristic();
            for(long i = 0; i < csCharaIncell.GetDataNumber(); i++)
            {
                // 登録共通項目のコピーを生成
                HySStockData csWkStockData = (HySStockData)csBaseStockData.Clone();

                // データ種別
                HySObjectKind csDataKind = GetSingleDataKind(csCharaIncell, i);
                if (csDataKind == null)
                {
                    // エラーログ出力
                   // ver1.5 エラートレース日本語対応
                    McLog.DebugOut(m_csSimTime, m_csElement.GetID(), CLASS_NAME, strMethodName,
                        Properties.HymcoImplResources.STATEMENT_DATA_TYPE_INDENT );
                   // McLog.DebugOut(m_csSimTime, m_csElement.GetID(), CLASS_NAME, strMethodName, "非対応のデータ種別識別子です。");
                    return false;
                }
                csWkStockData.SetDataKind(csDataKind);
                // 演算結果データ
                csWkStockData.SetData(CreateSingleKindData(i));

                csRegistDataList.AddLast(csWkStockData);
            }

            // 登録処理の実行
            if (!m_csDBAccess.RegisterNew(csRegistDataList))
            {
                // エラーログ出力
               // ver1.5 エラートレース日本語対応
                McLog.DebugOut(m_csSimTime, m_csElement.GetID(), CLASS_NAME, strMethodName,
                    Properties.HymcoImplResources.STATEMENT_CALC_RESULT_DB_REGIST_NG );
               // McLog.DebugOut(m_csSimTime, m_csElement.GetID(), CLASS_NAME, strMethodName, "演算結果のDB登録処理が失敗しました。");
                return false;
            }

            m_csStoreData.Clear();
            m_lCalResultRegistNo++;

            return true;
        }

        /// <summary><para>method outline:</para>
        /// <para>共通レコード作成</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>HySStockData csStockData = CreateBaseStockData()</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>HySStockData 共通項目を設定したレコード</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>データ種別数分登録するレコードの項目のうちの共通項目を設定したインスタンスを生成する</para>
        /// </remarks>
        protected virtual HySStockData CreateBaseStockData()
        {
            // 以下の共通項目を設定する
            // シミュレータ種別、要素ID、プロジェクト情報（8種)、ロット情報(2種)、登録レコード連番、保存期限区分
            HySID csElementID = (HySID)((McCmnElement)m_csElement).GetID();
            HySString csElementName = ((McCmnElement)m_csElement).GetElementName();
            McProjectInfData csPrjInf = (McProjectInfData)m_csDataContainer.GetData(McDefine.HYM_DATA_PROJECT_INFO);
            HySCalcLotInfo csLotInf = (HySCalcLotInfo)m_csDataContainer.GetData(HySCalcLotInfo.DATA_KEY_CALC_LOT);

            HySStockData csRtnStockData = new HySStockData(McDefine.SIMULATOR_KIND, csPrjInf.GetProjectID());

            // 任意検索キーを設定
            HySDataHashTable csKeyInfo = new HySDataHashTable();
            
            csKeyInfo.AddObject(HySCalResultDataQueryFieldNames.PROJECT_NAME, csPrjInf.GetProjectName());
            csKeyInfo.AddObject(HySCalResultDataQueryFieldNames.MANAGER_NAME, csPrjInf.GetAdminName());
            csKeyInfo.AddObject(HySCalResultDataQueryFieldNames.MODEL_CALC_TYPE, csPrjInf.GetModelCalcType());
            csKeyInfo.AddObject(HySCalResultDataQueryFieldNames.MODEL_SITUATION, csPrjInf.GetModelSituation());
            csKeyInfo.AddObject(HySCalResultDataQueryFieldNames.MODEL_SUBJECT, csPrjInf.GetModelSubject());
            csKeyInfo.AddObject(HySCalResultDataQueryFieldNames.MODEL_TARGET, csPrjInf.GetModelTarget());
            csKeyInfo.AddObject(HySCalResultDataQueryFieldNames.MODEL_TYPE, csPrjInf.GetModelType());

            csKeyInfo.AddObject(HySCalResultDataQueryFieldNames.ELEMENT_ID, csElementID);
            csKeyInfo.AddObject(HySCalResultDataQueryFieldNames.ELEMENT_NAME, csElementName);

            csKeyInfo.AddObject(HySCalResultDataQueryFieldNames.DATA_TYPE, m_csStoreDataType);

            csKeyInfo.AddObject(HySCalResultDataQueryFieldNames.DATA_DIM1, m_csStoreDataDimentionList[0]);
            csKeyInfo.AddObject(HySCalResultDataQueryFieldNames.DATA_DIM2, m_csStoreDataDimentionList[1]);
            csKeyInfo.AddObject(HySCalResultDataQueryFieldNames.DATA_DIM3, m_csStoreDataDimentionList[2]);

            csKeyInfo.AddObject(HySCalResultDataQueryFieldNames.LOT_ID, csLotInf.GetCalcLotID());
            csKeyInfo.AddObject(HySCalResultDataQueryFieldNames.CALC_EXEC_DATE, csLotInf.GetCalcExecDate());

            csKeyInfo.AddObject(HySCalResultDataQueryFieldNames.CALC_RESULT_SEQNO, new HySLong(m_lCalResultRegistNo));

            csRtnStockData.SetKeyInfo(csKeyInfo);

            csRtnStockData.SetPeservedPeriod(HySStockData.PeservedPeriod.Temporary);

            return csRtnStockData;

        }

        /// <summary><para>method outline:</para>
        /// <para>GISメッシュ情報チェック</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>HySObjectKind csDataKind = CreateSingleDataKind(csCharaIncell,lDataIndex)</para>
        /// </example>
        /// <param name="csTimeSeriesData">時系列データ</param>
        /// <returns>true:GISメッシュ情報である false:GISメッシュ情報でない</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>指定された時系列データがGISメッシュ情報形式かをチェックする。</para>
        /// </remarks>
        protected bool IsGeoMeshSerial(HySTimeSeriesBase csTimeSeriesData)
        {
            return csTimeSeriesData is HySGeoMeshSerial;
        }

        /// <summary><para>method outline:</para>
        /// <para>単独データ種別識別子取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>HySObjectKind csDataKind = GetSingleDataKind(csCharaIncell,lDataIndex)</para>
        /// </example>
        /// <param name="csCharaIncell">セル内部データ種別情報</param>
        /// <param name="lDataIndex">内部データ種別Index</param>
        /// <returns>HySObjectKind データ種別識別子</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>
        /// セル内部データ種別情報から指定したデータ種別Indexのデータ種別識別子を取得する。
        /// 格納データがGIS形式の場合はGIS版データ種別識別子に変換される。
        /// </para>
        /// </remarks>
        protected virtual HySObjectKind GetSingleDataKind(HySDataCharacteristicInCell csCharaIncell, long lDataIndex)
        {
            HySObjectKind csRtnData = null;
            // セル時系列形式･･･そのままのデータ種別識別子を設定
            if (!IsGeoMeshSerial(m_csStoreData))
            {
                csRtnData = csCharaIncell.m_csDataKind[lDataIndex].Clone();
            }
            // 地理メッシュ時系列形式･･･GISデータ種別識別子に変換して設定
            else
            {
                csRtnData = HySDataKindDefine.GetGISDataKind(csCharaIncell.m_csDataKind[lDataIndex]);
            }

            return csRtnData;
        }

        /// <summary><para>method outline:</para>
        /// <para>単独種別データ生成</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>HySTimeSeriesBase csRtnData = CreateSingleKindData(lDataIndex)</para>
        /// </example>
        /// <param name="lDataIndex">内部データ種別Index</param>
        /// <returns>HySTimeSeriesBase 1種別分の登録データ</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>演算結果格納先から指定したデータ種別Indexのみの結果を持つ時系列データを生成する</para>
        /// </remarks>
        protected virtual HySTimeSeriesBase CreateSingleKindData(long lDataIndex)
        {
            HySTimeSeriesBase csRtnData = null;
            // セル時系列形式
            if (!IsGeoMeshSerial(m_csStoreData))
            {
                csRtnData = ((HySTimeSeriesCellArray)m_csStoreData).CreateSingleDataCellArray(lDataIndex);
            }
            // 地理メッシュ時系列形式
            else
            {
                csRtnData = ((HySGeoMeshSerial)m_csStoreData).CreateSingleDataMeshSerial(lDataIndex);
            }

            return csRtnData;
        }

        /// <summary><para>method outline:</para>
        /// <para>プロパティ情報を設定する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn = SetProperty(csPropertyInfo)</para>
        /// </example>
        /// <param name="csPropertyInfo">プロパティ情報</param>
        /// <returns>=true:正常、=false:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public override bool SetProperty(McModelPropertyIF csPropertyInfo)
        {
            bool bRtn = true;
            McModelPropertyInfo csModelPrptyInfo = (McModelPropertyInfo)csPropertyInfo;
            // 格納データサイズの取得
            csModelPrptyInfo.GetInfo(MODEL_DBACCESS_OUT_STOREDATA_SIZE_KEY, ref m_lStoreDataMaxSize);
            
            // 演算結果格納先生成済の場合は保持サイズを設定しなおす
            if( m_csStoreData != null)
            {
                m_csStoreData.SetMaxHoldDataNum(m_lStoreDataMaxSize);
            }

            // DB格納データ間引き間隔の取得
            csModelPrptyInfo.GetInfo(MODEL_DBACCESS_OUT_THIN_OUT_SIZE_KEY, ref m_lThinOutDataSize);
            
            return bRtn;
        }

        /// <summary><para>method outline:</para>
        /// <para>計算状態復元のためのデータクラスを生成する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>McCmnElementOutData csElementOutData = CreateOutData()</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>データクラス</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public override McCmnElementOutData CreateOutData()
        {
            return new McCalResultDBAOutData();
        }

        /// <summary><para>method outline:</para>
        /// <para>ファイルにモデル内情報を全て書き出す</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn = FileOUT(csData)</para>
        /// </example>
        /// <param name="csData">演算要素データ</param>
        /// <returns>=true:正常、=false:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public override bool FileOUT(HySDataRoot csData)
        {
            // ファイル出力データクラスに演算中に変更のあるパラメタを設定する
            McCalResultDBAOutData csOutData = (McCalResultDBAOutData)csData;

            csOutData.SetStoreData(m_csStoreData);
            csOutData.SetCalResultRegistNo(m_lCalResultRegistNo);
            csOutData.SetLastTime(m_csLastTime);
            csOutData.SetStoreDataType(m_csStoreDataType);
            csOutData.SetStoreDataDimentionList(m_csStoreDataDimentionList);
            csOutData.SetThinOutDataCount(m_lThinOutDataCount);

            return true;
        }

        /// <summary><para>method outline:</para>
        /// <para>ファイルからモデル情報を全て読み出す</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn = FileIN(csData)</para>
        /// </example>
        /// <param name="csData">演算要素データ</param>
        /// <returns>=true:正常、=false:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public override bool FileIN(HySDataRoot csData)
        {
            // ファイル出力データクラスから演算中に変更のあるパラメタを読み込む
            McCalResultDBAOutData csOutData = (McCalResultDBAOutData)csData;

            m_csStoreData = csOutData.GetStoreData();
            m_lCalResultRegistNo = csOutData.GetCalResultRegistNo();
            m_csLastTime = csOutData.GetLastTime();
            m_csStoreDataType = csOutData.GetStoreDataType();
            m_csStoreDataDimentionList = csOutData.GetStoreDataDimentionList();
            m_lThinOutDataCount = csOutData.GetThinOutDataCount();

            return true;
        }

        /// <summary><para>method outline:</para>
        /// <para>シミュレーションデータコンテナの内容を設定する処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>SetSimDataContainer( csDataContainer )</para>
        /// </example>
        /// <param name="csDataContainer">シミュレーションデータコンテナ</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public override void SetSimDataContainer(HySSimulationDataContainer csDataContainer)
        {
            // シミュレーションコンテナインスタンスを内部に保持しておく
            m_csDataContainer = csDataContainer;
        }

        /// <summary><para>method outline:</para>
        /// <para>演算実行中断中のプロパティ等情報設定</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn = SetOnlineProperty(csPropertyInfo)</para>
        /// </example>
        /// <param name="csPropertyInfo">プロパティ情報</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>演算中断中にプロパティ、初期値等を変更して動作させ場合等に使用する</para>
        /// </remarks>
        public override bool SetOnlineProperty(McPropertyInfoRoot csPropertyInfo)
        {
            // 通常のプロパティ設定をコール
            McModelPropertyIF csCellModelInfo = csPropertyInfo as McModelPropertyIF;
            return this.SetProperty(csCellModelInfo);

        }

        /// <summary><para>method outline:</para>
        /// <para>演算実行中断中のモデルを初期化</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn = OnlineInitialize(ref csInitialData, ref csInputDataList, ref csOutputDataList)</para>
        /// </example>
        /// <param name="csInitialData">初期化設定情報</param>
        /// <param name="csInputDataList">前段接続要素からの伝送情報リスト</param>
        /// <param name="csOutputDataList">前段接続要素への伝送情報リスト</param>
        /// <returns>=true:正常、=false:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>演算中断中にプロパティ、初期値等を変更して動作させ場合等に使用する</para>
        /// </remarks>
        public override bool OnlineInitialize(ref McPropertyInfoRoot csInitialData, ref HySDataLinkedList csInputDataList, ref HySDataLinkedList csOutputDataList)
        {
            // 処理無し
            return true;
        }
    }
}
