// <summary>シミュレータ制御クラス</summary>
// <author>CommonMP</author>

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

using CommonMP.HYSSOP.Interface.HSData;
using CommonMP.HYSSOP.Interface.HSController;
using CommonMP.HYSSOP.Interface.HSSimulator;
using CommonMP.HYSSOP.CoreImpl.HSData;
using CommonMP.HYSSOP.CoreImpl.HSTools;

namespace CommonMP.HYSSOP.CoreImpl.HSController
{
    /// <summary><para>class outline:</para>
    /// <para>シミュレータ制御クラス</para>
    /// </summary>
    /// <remarks><para>history:</para>
    /// <para>[CommonMP][ver 1.0.0][2008/10/01][新規作成]</para>
    /// </remarks>
    public class HySSimulationController : HySControllerRoot
    {
        /// <summary>イベント管理</summary>
        protected HySEventManager m_csEventMng = null;

        /// <summary>ファクトリ管理</summary>
        protected HySFactoryMng m_csFactoryManager = null;

        /// <summary>シミュレーターファクトリ管理テーブル</summary>
        protected Hashtable m_csSimulatorFactoryTbl = new Hashtable();


        /// <summary>シミュレーター動作スレッドの数</summary>
        protected long m_lSimuThreadNumber = 0;
        /// <summary>シミュレーター動作スレッド管理用ハッシュテーブル</summary>
        protected Hashtable m_csSimuThreadTbl = new Hashtable();
        /// <summary>シミュレーター識別キー管理リスト</summary>
        protected IList m_csSimulatorKeyList = new ArrayList();

        /// <summary>現在実効中の演算スケジュール/// </summary>
        protected HySSimSchedule m_csActiveScedule=null;

        /// <summary>自身 </summary>
        public static HySSimulationController m_csInstance = null;

        /// <summary><para>method outline:</para>
        /// <para>デフォルトコンストラクタ</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySSimulationController csController = new HySSimulationController( ) </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public HySSimulationController()
        {
            HySSimulationController.m_csInstance = this;
        }

        /// <summary><para>method outline:</para>
        /// <para>ファクトリ管理クラス設定</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> SetFactoryManager( ) </para>
        /// </example>
        /// <param name="csFactoryManager">ファクトリ管理クラス</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public void SetFactoryManager(HySFactoryMng csFactoryManager)
        {
            m_csFactoryManager = csFactoryManager;
        }

        /// <summary><para>method outline:</para>
        /// <para>システム構成要素を設定する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> SetSysUnit( csUnit ) </para>
        /// </example>
        /// <param name="csUnit">システム構成要素</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual void SetSysUnit(HySSysUnit csUnit)
        {
            HySSimulatorRoot csSimu = ((HySSimThreadController)csUnit).GetSimulator();
            HySIdentifier csDataID = csSimu.GetID();
            HySKind csSimKind = csSimu.GetSimKind();
            HySString csPrcID = (HySString)csDataID.GetString();
            HySString csPrcKind = (HySString)csSimKind.GetString();
            HySString csPrcKey = csPrcKind + csPrcID;

            m_csSimuThreadTbl[csPrcKey] = csUnit;
            m_lSimuThreadNumber += 1;
            m_csSimulatorKeyList.Add(csPrcKey);
        }

        /// <summary><para>method outline:</para>
        /// <para>イベント管理クラスを設定する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> SetSysEventManager( csEventMng ) </para>
        /// </example>
        /// <param name="csEventMng">イベント管理クラス</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public void SetEventManager(HySEventMngRoot csEventMng)
        {
            m_csEventMng = (HySEventManager)csEventMng;
        }

        /// <summary><para>method outline:</para>
        /// <para>イベントを受け取った時に動作するメソッド</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> Boolean bRtn = EventCallback( csEvent ) </para>
        /// </example>
        /// <param name="csEvent">送られたイベント</param>
        /// <returns>true:=正常, false:=異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>各実装クラスは受け取ったイベントをシステム構成要素にポストする</para>
        /// </remarks>
        public virtual Boolean EventCallback(HySSysEvent csEvent)
        {
            Boolean bRtn = false;
            try
            {
                HySKind csSimKind = (HySObjectKind)((HySEventObject)csEvent).GetToSimKind();
                HySID csID = ((HySEventObject)csEvent).GetSuppID();
                long lEventNo = ((HySEventObject)csEvent).GetEventNo();

                if (lEventNo == HySEventObject.CMND_SIMU_SCHEDULE_EVENT)
                {   // シミュレーション計算スケジュール関連のイベントならば
                    long lSubEventNo = ((HySEventObject)csEvent).GetSubEventNo();
                    if (m_csActiveScedule != null)
                    {
                        bRtn = m_csActiveScedule.EventCallback(csEvent);
                    }
                }
                else
                {   // 個別シミュレーションへのイベントならば
                    if (lEventNo == HySEventObject.CMND_NEW_SIMULATOR_CREATE)
                    {   // シミュレーター生成ならば
                        bRtn = this.CmndCreateNewSimulator(csEvent);
                    }
                    else if (lEventNo == HySEventObject.CMND_SIMULATOR_RESTORE)
                    {
                        // 演算中断復元処理ならば
                        bRtn = this.CmdStructureSimulation(csEvent);
                    }
                    else if (lEventNo == HySEventObject.CMND_SIMULATOR_SAVE)
                    {
                        // 演算中断保存処理ならば
                        bRtn = this.CmdSaveSimulation(csEvent);
                        if (bRtn == true)
                        {
                            // 成功時イベント送信
                            HySEventObject csEventObj = new HySEventObject(HySSysEvent.OBJID_BUSIPROCEDURE, HySEventObject.NOTICE_END_SIMULATOR_SAVE);
                            csEventObj.SetToSimKind(csSimKind);
                            csEventObj.SetSuppID(csID);
                            csEventObj.SetSubEventNo(((HySEventObject)csEvent).GetSubEventNo());
                            csEventObj.SetData(((HySEventObject)csEvent).GetData());
                            csEventObj.SetSubData(((HySEventObject)csEvent).GetSubData());
                            PutEvent(csEventObj);
                        }
                        else
                        {
                            // 失敗時イベント送信
                            HySEventObject csEventObj = new HySEventObject(HySSysEvent.OBJID_BUSIPROCEDURE, HySEventObject.NOTICE_END_SIMULATOR_SAVE_NG);
                            csEventObj.SetToSimKind(csSimKind);
                            csEventObj.SetSuppID(csID);
                            csEventObj.SetSubEventNo(((HySEventObject)csEvent).GetSubEventNo());
                            csEventObj.SetData(((HySEventObject)csEvent).GetData());
                            csEventObj.SetSubData(((HySEventObject)csEvent).GetSubData());
                            PutEvent(csEventObj);
                        }
                    }
                    else if (lEventNo == HySEventObject.CMND_SIMULATOR_DELETE)
                    {
                        // ★★★
                        //HySEventObject csEventObj = new HySEventObject(HySSysEvent.OBJID_BUSIPROCEDURE, HySEventObject.NOTICE_END_SIMULATOR_DELETE);
                        //csEventObj.SetSimKind(csSimKind);
                        //csEventObj.SetSuppID(csID);
                        //csEventObj.SetSubEventNo(((HySEventObject)csEvent).GetSubEventNo());
                        //PutEvent(csEventObj);

                        HySString csPrcID = (HySString)csID.GetString();
                        HySString csPrcKind = (HySString)csSimKind.GetString();
                        HySString csPrcKey = csPrcKind + csPrcID;
                        HySSimThreadController csThreadCtl = (HySSimThreadController)m_csSimuThreadTbl[csPrcKey];
                        if (csThreadCtl != null)
                        {

                            // ストップイベント発行 <== すると、業務側は、既にデリートされている為、業務側で死ぬ
                            csThreadCtl.EventCallback(new HySEventObject(HySSysEvent.OBJID_SIMULATOR, HySEventObject.CMND_PAUSE_SIMULATION));
                            System.Threading.Thread.Sleep(30); // 300mSec Sleep
                            csThreadCtl.EventCallback(new HySEventObject(HySSysEvent.OBJID_SIMULATOR, HySEventObject.CMND_STOP_SIMULATION));
                            // ExitOKを見て、それがOKとなるまでまつ。
                            for (long lWtLp = 0; lWtLp < 100; lWtLp++)
                            {
                                System.Threading.Thread.Sleep(30); // 300mSec Sleep
                                if (csThreadCtl.ExitOK() == true)
                                {
                                    break;
                                }
                            }
                            // 

                            csThreadCtl.DeleteSimulator();
                            m_csSimuThreadTbl.Remove(csPrcKey);
                            m_csSimulatorKeyList.Remove(csPrcKey);
                            m_lSimuThreadNumber -= 1;
                        }
                        else
                        {
                            // ver1.5 エラートレース日本語対応
                            HySLog.LogOut(HySLog.ONLINE, "HySSimulationController::EventCallback()", Properties.HysMsgResources.STATEMENT_NO_THREAD_CONTROLL + "[" + csPrcKey.ToString() + "]");
                          //HySLog.LogOut(HySLog.ONLINE, "HySSimulationController::EventCallback()", "No ThreadCtl[" + csPrcKey.ToString() + "]");
                        }
                        csEvent.SetTo(HySSysEvent.OBJID_BUSIPROCEDURE);
                        ((HySEventObject)csEvent).SetEventNo(HySEventObject.NOTICE_END_SIMULATOR_DELETE);
                        this.PutEvent(csEvent);
                        GC.Collect(); // 強制　ガベージコレクション
                    }
                    else
                    {   // シミュレーター生成以外のイベントならば

                        // 業務は複数あるため、どの業務なのかを判断する必要がある。
                        if (csSimKind != null)
                        {
                            HySString csPrcID = (HySString)csID.GetString();
                            HySString csPrcKind = (HySString)csSimKind.GetString();
                            HySString csPrcKey = csPrcKind + csPrcID;
                            HySSimThreadController csThreadCtl = (HySSimThreadController)m_csSimuThreadTbl[csPrcKey];
                            if (csThreadCtl != null)
                            {
                                bRtn = csThreadCtl.EventCallback(csEvent);
                            }
                            else
                            {
                                // ver1.5 エラートレース日本語対応
                                HySLog.LogOut(HySLog.ONLINE, "HySSimulationController::EventCallback()", Properties.HysMsgResources.STATEMENT_NO_THREAD_CONTROLL + "[" + csPrcKey.ToString() + "]");
                              //HySLog.LogOut(HySLog.ONLINE, "HySSimulationController::EventCallback()", "No ThreadCtl[" + csPrcKey.ToString() + "]");
                                csEvent.SetTo(HySSysEvent.OBJID_BUSIPROCEDURE);
                                ((HySEventObject)csEvent).SetSubEventNo(((HySEventObject)csEvent).GetEventNo());
                                ((HySEventObject)csEvent).SetEventNo(HySEventObject.NOTICE_SIMULATION_NG);
                                ((HySEventObject)csEvent).SetToSimKind(((HySEventObject)csEvent).GetFromSimKind());
                                ((HySEventObject)csEvent).SetSubData(new HySString("Abnomal Command to Simulator. --No ThreadCtl[" + csPrcKey.ToString() + "]"));
                                this.PutEvent(csEvent);
                            }
                        }
                        else
                        {
                            // ver1.5 エラートレース日本語対応 TODO:「シミュレーター種別識別子がありません。」？
                            HySLog.LogOut(HySLog.ONLINE, "HySSimulationController::EventCallback()", Properties.HysMsgResources.STATEMENT_NOTSET_SIMULATION);
                          //HySLog.LogOut(HySLog.ONLINE, "HySSimulationController::EventCallback()", "Simulation Kind is not set");
                        }
                    }
                } // end of else if(演算スケジュールイベント)
            }
            catch(Exception ex)
            {
                // ver1.5 エラートレース日本語対応
                HySLog.LogOut(HySLog.ONLINE, "HySSimulationController", "EventCallback", Properties.HysMsgResources.STATEMENT_CATCH_EXCEPTION + ex.Message);
              //HySLog.LogOut(HySLog.ONLINE, "HySSimulationController", "EventCallback", "Catch exception :" + ex.Message);
            }
            return bRtn;
        }

        /// <summary><para>method outline:</para>
        /// <para>イベントをイベント管理クラスにポストする</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> Boolean bRtn = PutEvent( csEvent ) </para>
        /// </example>
        /// <param name="csEvent">送るイベント</param>
        /// <returns>true:=正常, false:=異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>送信元識別子を自分で付与する</para>
        /// </remarks>
        public virtual Boolean PutEvent(HySSysEvent csEvent)
        {
            csEvent.SetFrom(HySSysEvent.OBJID_SIMULATOR);
            return m_csEventMng.PutEvent(csEvent);
        }


        /// <summary><para>method outline:</para>
        /// <para>初期化処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> Initialize( ) </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>true : 正常、false : 異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual Boolean Initialize()
        {
            HySSimulatorFactory csSimulatorFactory = null;
            HySObjectKind csSimKind = null;
            HySString csSimKey = null;
            // 複数の　業務生成ファクトリに対してそれぞれ業務を作成させる
            long lFctNo = m_csFactoryManager.GetFactoryNum();
            for (long lLp = 0; lLp < lFctNo; lLp++)
            {
                csSimulatorFactory = m_csFactoryManager.GetFactory(lLp) as HySSimulatorFactory;
                if (csSimulatorFactory != null)
                {
                    csSimKind = (HySObjectKind)csSimulatorFactory.GetSimKind();
                    csSimKey = (HySString)csSimKind.GetString();
                    m_csSimulatorFactoryTbl.Add(csSimKey.ToString(), csSimulatorFactory);  // シミュレーション管理テーブルへ積み込み
                }
            }
            return true;
        }

        /// <summary><para>method outline:</para>
        /// <para>立ち上がり処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> Boolean bRtn = WakeUp( ) </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>true : 正常、false : 異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual Boolean WakeUp()
        {
            return true;
        }

        /// <summary><para>method outline:</para>
        /// <para>終了処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> Boolean bRtn = Initialize( ) </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>true : 正常、false : 異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual Boolean ShutDown()
        {
            bool bRtn = true;
            HySEventObject csEvent = new HySEventObject(HySSysEvent.OBJID_SIMULATOR, HySEventObject.CMND_STOP_SIMULATION);
            if (m_csActiveScedule != null)
            {
                csEvent.SetSubEventNo(HySEventObject.CMND_STOP_SIMULATION);
                bRtn = m_csActiveScedule.EventCallback(csEvent);
            }


            for (long lLp = 1; lLp <= m_lSimuThreadNumber; lLp++)
            {
                HySString csPrcKey = (HySString)m_csSimulatorKeyList[(int)(lLp - 1)];
                HySSimThreadController csUnit = (HySSimThreadController)m_csSimuThreadTbl[csPrcKey];
                csUnit.EventCallback(csEvent);
            }
            return bRtn;
        }

        /// <summary><para>method outline:</para>
        /// <para>システム終了準備完了判別</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> Boolean bRtn = ExitOK( ) </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>true : システムExit準備OK　、false : システムExit準備NG</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual Boolean ExitOK()
        {
            Boolean bRtn = true;
            Boolean bLocalRtn = false;

            if (m_csActiveScedule != null)
            {
                bLocalRtn = m_csActiveScedule.ExitOK();
                if (bLocalRtn != true)
                {
                    bRtn = false;
                }
            }
            for (long lLp = 1; lLp <= m_lSimuThreadNumber; lLp++)
            {
                HySString csPrcKey = (HySString)m_csSimulatorKeyList[(int)(lLp - 1)];
                HySSimThreadController csUnit = (HySSimThreadController)m_csSimuThreadTbl[csPrcKey];
                if (csUnit != null)
                {
                    bLocalRtn = csUnit.ExitOK();
                    if (bLocalRtn != true)
                    {
                        bRtn = false;
                        break;
                    }
                }
            }

            return bRtn;
        }

        /// <summary><para>method outline:</para>
        /// <para>宛先識別番号を取得する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> long lAdressIDNo = AdressIDNo() </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>宛先識別番号:(HySSysEvent.OBJID_GISCONTROLLER)</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public long AdressIDNo()
        {
            return HySSysEvent.OBJID_SIMULATOR;
        }

        /// <summary><para>method outline:</para>
        /// <para>シミュレーターを新規に作成する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> Boolean bRtn = CmndCreateNewSimulator(csEvent) </para>
        /// </example>
        /// <param name="csEvent">イベント</param>
        /// <returns>true : 正常、false : 異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected virtual Boolean CmndCreateNewSimulator(HySSysEvent csEvent)
        {
            Boolean bRtn = false;
            long lEventNo = ((HySEventObject)csEvent).GetEventNo();
            HySSimulationDataContainer csContainer = null;

            // イベント内の　シミュレーター識別子から　関連ファクトリを探す
            HySObjectKind csSimKind = (HySObjectKind)((HySEventObject)csEvent).GetToSimKind();
            HySString csKey = (HySString)csSimKind.GetString();
            HySSimulatorFactory csSimulatorFactory = (HySSimulatorFactory)m_csSimulatorFactoryTbl[csKey.ToString()];

            if (csSimulatorFactory != null)
            {   // 対象ファクトリ有り

                HySID csID = ((HySEventObject)csEvent).GetSuppID();  // シミュレーター固有ID

                // シミュレーター本体を作成させる
                HySSimulatorRoot csSimulator = csSimulatorFactory.CreateSimulator(csSimKind, csID); // シミュレーター設定
                if (csSimulator != null)
                {   // シミュレーター作成成功ならば
                    bRtn = true;

                    if (lEventNo == HySEventObject.CMND_SIMULATOR_RESTORE)
                    {
                        // ファイルからプロジェクトを開く場合
                        HySEventObject csHySEvent = (HySEventObject)csEvent;
                        HySFileOutData csFileOutData = (HySFileOutData)csHySEvent.GetData();
                        // シミュレータに対して、データクラスを提供するのみ。データの復元はシミュレータ自身が行う。
                        bRtn = csSimulator.StructureAllInfo(csFileOutData);
                    }
                    else
                    {
                        // にコンテナ等を設定
                        csContainer = (HySSimulationDataContainer)((HySEventObject)csEvent).GetData(); // コンテナ取得
                        if (csContainer == null)
                        {
                            csContainer = (HySSimulationDataContainer)csSimulatorFactory.CreateDataContainer(csSimKind, csID); // コンテナ生成
                        }
                        else
                        {
                            csContainer.SetID(csID);
                        }
                        csSimulator.SetContainer(csContainer); // データコンテナ設定
                    }

                    // シミュレーター動作用のスレッド制御を生成する
                    HySSimThreadController csThreadCtl = new HySSimThreadController(csSimulator);
                    csThreadCtl.SetController(this);

                    // ハッシュ管理テーブルに追加
                    this.SetSysUnit(csThreadCtl);

                    // シミュレーターに対して、自らに関連するファクトリクラスを設定する
                    csSimulator.SetSimulatorFactory(csSimulatorFactory);

                    // シミュレーターの立ち上がり初期化
                    csSimulator.Initialize();

                    if (lEventNo != HySEventObject.CMND_SIMULATOR_RESTORE)
                    {
                        // シミュレータ生成完了報告
                        HySEventObject csEventObj = new HySEventObject(HySSysEvent.OBJID_BUSIPROCEDURE, HySEventObject.NOTICE_SIMULATOR_CREATE_SUCCESS);
                        csEventObj.SetToSimKind(csSimKind);
                        csEventObj.SetSuppID(csID);
                        csEventObj.SetData(csContainer); // データコンテナを付加
                        csEventObj.SetSubEventNo(((HySEventObject)csEvent).GetSubEventNo());

                        //★サーバー／クライアント化で追加
                        csEventObj.SetResponseInfo(((HySEventObject)csEvent).GetResponseInfo());
                        //★サーバー／クライアント化で追加

                        this.PutEvent(csEventObj);
                    }
                }
                else
                {
                    // ver1.5 エラートレース日本語対応
                    HySLog.LogOut(HySLog.TRIAL_RUN, "HySSimulationController::CmndCreateNewSimulator", Properties.HysMsgResources.STATEMENT_FAILED_CREATE_SIM + " (" + csKey.ToString() + ")");
                  //HySLog.LogOut(HySLog.TRIAL_RUN, "HySSimulationController::CmndCreateNewSimulator", "Cannot Create Simulator(" + csKey.ToString() + ")");

                    // シミュレータ生成失敗報告
                    HySEventObject csEventObj = new HySEventObject(HySSysEvent.OBJID_BUSIPROCEDURE, HySEventObject.NOTICE_SIMULATOR_CREATE_FAIL);
                    csEventObj.SetToSimKind(csSimKind);
                    csEventObj.SetSuppID(csID);

                    //★サーバー／クライアント化で追加
                    csEventObj.SetResponseInfo(((HySEventObject)csEvent).GetResponseInfo());
                    //★サーバー／クライアント化で追加

                    this.PutEvent(csEventObj);
                }
            }
            else
            {
                // ver1.5 エラートレース日本語対応
                HySLog.LogOut(HySLog.TRIAL_RUN, "HySSimulationController::CmndCreateNewSimulator", Properties.HysMsgResources.STATEMENT_NOTFOUND_SIMFACTORY + " (" + csKey.ToString() + ")");
              //HySLog.LogOut(HySLog.TRIAL_RUN, "HySSimulationController::CmndCreateNewSimulator", "Cannot be find SimulatorFactory(" + csKey.ToString() + ")");
                // シミュレータ生成失敗報告
                HySEventObject csEventObj = new HySEventObject(HySSysEvent.OBJID_BUSIPROCEDURE, HySEventObject.NOTICE_SIMULATOR_CREATE_FAIL);
                csEventObj.SetToSimKind(csSimKind);
                
                //★サーバー／クライアント化で追加
                csEventObj.SetResponseInfo(((HySEventObject)csEvent).GetResponseInfo());
                //★サーバー／クライアント化で追加

                this.PutEvent(csEventObj);
            }   // end of if(csSimulatorFactory)
            return bRtn;
        }

        /// <summary><para>method outline:</para>
        /// <para>演算中断保存処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> Boolean bRtn = CmdSaveSimulation(csEvent) </para>
        /// </example>
        /// <param name="csEvent">イベント</param>
        /// <returns>true : 正常、false : 異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected virtual Boolean CmdSaveSimulation(HySSysEvent csEvent)
        {
            Boolean bRtn = false;

            HySKind csSimKind = (HySObjectKind)((HySEventObject)csEvent).GetToSimKind();
            HySID csID = ((HySEventObject)csEvent).GetSuppID();
            long lEventNo = ((HySEventObject)csEvent).GetEventNo();
            HySSimulatorRoot csSimulator;
            HySString csPrcID = (HySString)csID.GetString();
            HySString csPrcKind = (HySString)csSimKind.GetString();
            HySString csPrcKey = csPrcKind + csPrcID;
            HySEventObject csHySEvent = (HySEventObject)csEvent;
            HySString csFilePath = (HySString)csHySEvent.GetData();
            HySFile csFile = new HySFile(csFilePath);
            HySSimThreadController csThreadCtl = (HySSimThreadController)m_csSimuThreadTbl[csPrcKey];

            try
            {
                if (csThreadCtl != null)
                {
                    // シミュレータの取得
                    csSimulator = csThreadCtl.GetSimulator();
                    // ファイル出力用データクラスの作成
                    HySFileOutData csFileOutData = new HySFileOutData();
                    // シミュレータに対して、データクラスを提供するのみ。データの出力はシミュレータ自身が行う。
                    bRtn = csSimulator.SerializeAllInfo(csFileOutData);
                    if (bRtn == true)
                    {
                        // 演算情報出力処理が正常終了した場合
                        if (csFile.Open(HySFile.OPEN_MODE.CREATE_NEW, HySFile.READ_WRITE_MODE.WRITE, HySFile.DIRECTORY_MODE.NOT_MK_DIR) == 0)
                        {
                            // ファイルへ書き込み
                            csFile.DataWrite(csFileOutData);
                            csFile.Close();
                        }
                        else
                        {
                            // ファイルオープン処理が失敗した場合(他プロセスにより開かれている等)
                            bRtn = false;
                        }
                    }
                    // 演算情報出力処理が異常終了した場合
                    csFile = null;
                    return bRtn;
                }
                else
                {
                    csFile = null;
                    return false;
                }
            }
            catch (Exception ex)
            {
                try
                {
                    // ファイルの存在を確認してファイルの削除
                    // ファイル書き込み中ではファイルがすでに生成されているため
                    if (csFile.Exist() == true)
                    {
                        csFile.Delete();
                    }
                    // ver1.5 エラートレース日本語対応
                    HySLog.LogOut(HySLog.ONLINE, "HySSimulationController::CmdSaveSimulation", Properties.HysMsgResources.STATEMENT_CATCH_EXCEPTION + ex.ToString());
                  //HySLog.LogOut(HySLog.ONLINE, "HySSimulationController::CmdSaveSimulation", "catch Exception" + ":" + ex.ToString());
                    csFile = null;
                    return false;
                }
                catch (Exception ex2)
                {
                    // 削除処理が失敗した場合
                    // ver1.5 エラートレース日本語対応
                    HySLog.LogOut(HySLog.ONLINE, "HySSimulationController::CmdSaveSimulation", Properties.HysMsgResources.STATEMENT_CATCH_CATCH_EXCEPTION + ex2.ToString());
                  //HySLog.LogOut(HySLog.ONLINE, "HySSimulationController::CmdSaveSimulation", "catch Exception - catch" + ":" + ex2.ToString());
                    return false;
                }
            }
        }

        /// <summary><para>method outline:</para>
        /// <para>演算中断復元処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> Boolean bRtn = CmdStructureSimulation(csEvent) </para>
        /// </example>
        /// <param name="csEvent">イベント</param>
        /// <returns>true : 正常、false : 異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected virtual Boolean CmdStructureSimulation(HySSysEvent csEvent)
        {
            Boolean bRtn = false;

            HySKind csSimKind = (HySObjectKind)((HySEventObject)csEvent).GetToSimKind();
            HySID csID = ((HySEventObject)csEvent).GetSuppID();
            HySEventObject csHySEvent = (HySEventObject)csEvent;
            HySString csFilePath = (HySString)csHySEvent.GetData();
            HySFile csFile = new HySFile(csFilePath);
            HySFileOutData csFileOutData = null;
            HySString csPrcKey = null;

            try
            {
                if (csFile.Open(HySFile.OPEN_MODE.OPEN, HySFile.READ_WRITE_MODE.READ, HySFile.DIRECTORY_MODE.NOT_MK_DIR) == 0)
                {
                    // ファイルからデータクラスを読み込み
                    csFileOutData = (HySFileOutData)csFile.DataRead();
                    csFile.Close();
                }
                else
                {
                    // ファイルオープン処理が失敗した場合(他プロセスにより開かれている等)

                    // 失敗イベント送信
                    HySEventObject csEventObj = new HySEventObject(HySSysEvent.OBJID_BUSIPROCEDURE, HySEventObject.NOTICE_END_SIMULATOR_RESTORE_NG);
                    csEventObj.SetToSimKind(csSimKind);
                    PutEvent(csEventObj);
                    csFile = null;
                    return false;
                }
                // コンテナ取得
                HySSimulationDataContainer csContainer = (HySSimulationDataContainer)csFileOutData.GetContainer();
                // シミュレータ種別・ＩＤよりキー生成
                csSimKind = csContainer.GetSimKind();
                csID = (HySID)csContainer.GetID();
                HySString csKey = (HySString)csSimKind.GetString();
                HySString csPrcID = (HySString)csID.GetString();
                csPrcKey = csKey + csPrcID;
                // 開く対象のシミュレータがすでに存在するか確認
                HySSimThreadController csSimThreadCtl = (HySSimThreadController)m_csSimuThreadTbl[csPrcKey];
                if (csSimThreadCtl == null)
                {
                    // シミュレータの新規作成と復元開始
                    csHySEvent.SetData(csFileOutData);
                    bRtn = this.CmndCreateNewSimulator(csHySEvent);

                    if (bRtn == true)
                    {
                        // 成功時イベント送信
                        HySEventObject csEventObj = new HySEventObject(HySSysEvent.OBJID_BUSIPROCEDURE, HySEventObject.NOTICE_END_SIMULATOR_RESTORE);
                        csEventObj.SetToSimKind(csSimKind);
                        csEventObj.SetData(csContainer);
                        csEventObj.SetSubData(csFilePath);
                        PutEvent(csEventObj);
                    }
                    else
                    {
                        // 失敗時にはシミュレータを破棄する
                        if (m_lSimuThreadNumber != 0)
                        {
                            // シミュレータ生成に成功し、計算情報復元処理にて失敗した場合
                            HySSimThreadController csThreadCtl = (HySSimThreadController)m_csSimuThreadTbl[csPrcKey];
                            if (csThreadCtl != null)
                            {
                                csThreadCtl.DeleteSimulator();
                                m_csSimuThreadTbl.Remove(csPrcKey);
                                m_csSimulatorKeyList.Remove(csPrcKey);
                                m_lSimuThreadNumber -= 1;
                                GC.Collect();
                            }
                        }

                        // 失敗イベント送信
                        HySEventObject csEventObj = new HySEventObject(HySSysEvent.OBJID_BUSIPROCEDURE, HySEventObject.NOTICE_END_SIMULATOR_RESTORE_NG);
                        csEventObj.SetToSimKind(csSimKind);
                        PutEvent(csEventObj);
                    }
                }
                else
                {
                    // 対象のシミュレータがすでに存在する
                    // 既に開かれているプロジェクトのデータコンテナを取得し報告
                    HySSimulatorRoot csSimulator = csSimThreadCtl.GetSimulator();
                    HySSimulationDataContainer csDataCont = (HySSimulationDataContainer)csSimulator.GetContainer();
                    HySEventObject csEventObj = new HySEventObject(HySSysEvent.OBJID_BUSIPROCEDURE, HySEventObject.NOTICE_END_SIMULATOR_RESTORE_NG);
                    csEventObj.SetToSimKind(csSimKind);
                    csEventObj.SetData(csDataCont);
                    PutEvent(csEventObj);
                }
                csFile = null;
            }
            catch (Exception ex)
            {
                // ver1.5 エラートレース日本語対応
                HySLog.LogOut(HySLog.ONLINE, "HySSimulationController::CmdStructureSimulation", Properties.HysMsgResources.STATEMENT_CATCH_EXCEPTION + ex.Message + ex.StackTrace);
              //HySLog.LogOut(HySLog.ONLINE, "HySSimulationController::CmdStructureSimulation", "catch Exception" + ":" + ex.Message + ex.StackTrace);
                // 失敗時にはシミュレータを破棄する
                if (m_lSimuThreadNumber != 0)
                {
                    if ((object)csPrcKey != null)
                    {
                        HySSimThreadController csThreadCtl = (HySSimThreadController)m_csSimuThreadTbl[csPrcKey];
                        if (csThreadCtl != null)
                        {
                            csThreadCtl.DeleteSimulator();
                            m_csSimuThreadTbl.Remove(csPrcKey);
                            m_csSimulatorKeyList.Remove(csPrcKey);
                            m_lSimuThreadNumber -= 1;
                            GC.Collect();
                        }
                    }
                }
                // 失敗イベント送信
                HySEventObject csEventObj = new HySEventObject(HySSysEvent.OBJID_BUSIPROCEDURE, HySEventObject.NOTICE_END_SIMULATOR_RESTORE_NG);
                csEventObj.SetToSimKind(csSimKind);
                PutEvent(csEventObj);
                csFile = null;
                return false;
            }
            return bRtn;
        }

        /// <summary><para>method outline:</para>
        /// <para>シミュレーター取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySSimulator csSim = GetSimulator(csKind,csID) </para>
        /// </example>
        /// <param name="csKind">シミュレーター種別</param>
        /// <param name="csID">シミュレーター識別子</param>
        /// <returns>インスタンス</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual HySSimulatorRoot GetSimulator(HySObjectKind csKind, HySID csID)
        {
            HySSimulatorRoot csRtn = null;
            HySString csPrcKey = ((HySString)csKind.GetString()) + ((HySString)csID.GetString());
            HySSimThreadController csThreadCtl = (HySSimThreadController)m_csSimuThreadTbl[csPrcKey];
            if (csThreadCtl != null)
            {
                csRtn = csThreadCtl.GetSimulator();
            }
            return csRtn;
        }
    }
}
