// <summary>ソースコード：セル識別子とセルの配列管理データ</summary>
// <author>CommonMP</author>

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Serialization;

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


namespace CommonMP.HYSSOP.CoreImpl.HSData
{
    /// <summary><para>class outline:</para>
    /// <para>セル識別子とセルの配列管理データ</para>
    /// </summary>
    /// <remarks><para>remarks:</para>
    /// <para>
    /// セルを個別に区別する場合に、識別子をつけたセルの配列位置を保持する
    /// 　セルＩＤ→セルの配列位置取得(補足情報として HySObjectKindも使用可)
    /// 　セル配列位置→セルＩＤ取得
    /// </para>
    /// </remarks>
    /// <remarks><para>history:</para>
    /// <para>[CommonMP][ver 1.0.0][2009/08/01][新規作成]</para>
    /// </remarks>
    [Serializable]
    public class HySCellIDManageData : HySDataRoot, HySVersionManagement
    {
        /// <summary><para>class outline:</para>
        /// <para>配列位置管理データ</para>
        /// </summary>
        /// <remarks><para>remarks:</para>
        /// <para>本クラスの派生クラスは全て[Serializable]であること</para>
        /// </remarks>
        /// <remarks><para>history:</para>
        /// <para>[CommonMP][ver 1.0.0][2008/10/01][新規作成]</para>
        /// </remarks>
        [Serializable]
        public class HySDimIdx : HySDataRoot, HySVersionManagement
        {
            /// <summary>データ内：配列１次元 </summary>
            public long m_lDim1 = -1;
            /// <summary>データ内：配列２次元 </summary>
            public long m_lDim2 = -1;
            /// <summary>データ内：配列３次元 </summary>
            public long m_lDim3 = -1;

            /// <summary>種別 </summary>
            public HySObjectKind m_csObjectKind = null;

            /// <summary><para>method outline:</para>
            /// <para>コンストラクタ</para>
            /// </summary>
            /// <example><para>usage:</para>
            /// <para> HySDimIdx csObj = new HySDimIdx(lDim1,lDim2,lDim3) </para>
            /// </example>
            /// <param name="lDim1">配列１次元位置（０相対）</param>
            /// <param name="lDim2">配列２次元位置（０相対）</param>
            /// <param name="lDim3">配列３次元位置（０相対）</param>
            /// <param name="csKind">セルの種別</param>
            /// <returns>HySDimIdx  生成したインスタンス</returns>
            /// <exception cref="">無し</exception>
            /// <remarks><para>remarks:</para>
            /// <para>無し</para>
            /// </remarks>
            public HySDimIdx(long lDim1, long lDim2, long lDim3, HySObjectKind csKind)
            {
                m_lDim1 = lDim1;
                m_lDim2 = lDim2;
                m_lDim3 = lDim3;
                m_csObjectKind = csKind;
                //バージョン情報設定
                SetNowVersion();
            }
            /// <summary><para>method outline:</para>
            /// <para>文字列化</para>
            /// </summary>
            /// <example><para>usage:</para>
            /// <para> HySString csKeyStr = GetString( ) </para>
            /// </example>
            /// <param name="">無し</param>
            /// <returns>HySString 文字列</returns>
            /// <exception cref="">無し</exception>
            /// <remarks><para>remarks:</para>
            /// <para>無し</para>
            /// </remarks>
            virtual public HySString GetString()
            {
                return new HySString( m_lDim1.ToString() + "," + m_lDim2.ToString() + "," + m_lDim3.ToString() );
            }

            // ================================================
            //   バージョンアップ時の下位互換性を保つ為の処理
            // ================================================
            /// <summary>保存バージョン情報</summary>
            private string m_sDecodedVersion;
            /// <summary><para>method outline:</para>
            /// <para>バージョン情報取得</para>
            /// </summary>
            /// <example><para>usage:</para>
            /// <para> string sDecodedVersion = GetDecodedVersion()</para>
            /// </example>
            /// <param name="">無し</param>
            /// <returns>string 保存バージョン情報</returns>
            /// <exception cref="">無し</exception>
            /// <remarks><para>remarks:</para>
            /// <para>メンバー変数に設定されているバージョン情報を返す</para>
            /// </remarks>
            public  string GetDecodedVersion()
            {
                return m_sDecodedVersion;
            }
            /// <summary><para>method outline:</para>
            /// <para>バージョン情報取得</para>
            /// </summary>
            /// <example><para>usage:</para>
            /// <para> string sVersion = GetNowVersion()</para>
            /// </example>
            /// <param name="">無し</param>
            /// <returns>string 現在のバージョン情報</returns>
            /// <exception cref="">無し</exception>
            /// <remarks><para>remarks:</para>
            /// <para>無し</para>
            /// </remarks>
            public  string GetNowVersion()
            {
                return "1.00";
            }
            /// <summary><para>method outline:</para>
            /// <para>バージョン情報設定</para>
            /// </summary>
            /// <example><para>usage:</para>
            /// <para> SetNowVersion()</para>
            /// </example>
            /// <param name="">無し</param>
            /// <returns>無し</returns>
            /// <exception cref="">無し</exception>
            /// <remarks><para>remarks:</para>
            /// <para>現在のバージョン情報をメンバー変数に設定する</para>
            /// </remarks>
            public  void SetNowVersion()
            {
                m_sDecodedVersion = GetNowVersion();
            }
            /// <summary><para>method outline:</para>
            /// <para>復元後の整合性確保処理</para>
            /// </summary>
            /// <example><para>usage:</para>
            /// <para> PostDeserialize( ) </para>
            /// </example>
            /// <param name="">無し</param>
            /// <returns>無し</returns>
            /// <exception cref="">無し</exception>
            /// <remarks><para>remarks:</para>
            /// <para>シリアライズされた旧バージョン情報を復元する際、過去の整合性をとる時に使用する
            /// バージョンによって変数等追加がない場合には、実装の必要がない
            /// </para>
            /// </remarks>
            public virtual void PostDeserialize()
            {
                if (GetDecodedVersion() != GetNowVersion())
                {
                    if (GetDecodedVersion() == null)
                    {
                        // 旧バージョンからの移行処理を入れる
                    }
                    else
                    {
                        //旧バージョンから順にバージョンを上げて行く
                        switch (GetDecodedVersion())
                        {
                            case "1.00":
                                {
                                    // 旧バージョンからの移行処理を入れる
                                    break;
                                }
                            //case "2.00": << 以後バージョンアップに伴って処理追加
                            //{
                            //    break;
                            //}
                        }
                    }
                    SetNowVersion();
                }
            }
            /// <summary><para>method outline:</para>
            /// <para>逆シリアル化時追加処理</para>
            /// </summary>
            /// <example><para>usage:</para>
            /// <para> IDeserializationCallback.OnDeserialization(csObj)</para>
            /// </example>
            /// <param name="csObj">ダミー</param>
            /// <returns>無し</returns>
            /// <exception cref="">無し</exception>
            /// <remarks><para>remarks:</para>
            /// <para>予約処理</para>
            /// </remarks>
            void IDeserializationCallback.OnDeserialization(Object csObj)
            {
                PostDeserialize();
            }
        }

        /// <summary> セル識別子格納テーブル </summary>
        protected HySDataHashTable m_csKeyTbl = new HySDataHashTable();
        /// <summary>　セルインデックス位置格納テーブル </summary>
        protected HySDataHashTable m_csIndexTbl = new HySDataHashTable();
        /// <summary> キー情報一覧 </summary>
        protected HySDataLinkedList m_csIDList = new HySDataLinkedList();

        /// <summary>ワーク変数</summary>
        protected HySDimIdx m_csWorkIdx = new HySDimIdx(-1,-1,-1, null);

        /// <summary><para>method outline:</para>
        /// <para>デフォルトコンストラクタ</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySCellIDManageData csData = new HySCellIDManageData() </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns> HySCellIDManageData 生成されたクラスのインスタンス</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>使用禁止</para>
        /// </remarks>
        public HySCellIDManageData()
        {
            //バージョン情報設定
            SetNowVersion();
        }

        /// <summary><para>method outline:</para>
        /// <para>セルの配列位置（０相対）設定</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> SetID( csCellID, lDim1 ) </para>
        /// </example>
        /// <param name="csCellID">識別子</param> 
        /// <param name="lDim1">配列１次元位置（０相対）</param>
        /// <param name="csKind">セルの種別</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        virtual public void SetID(HySID csCellID, long lDim1, HySObjectKind csKind)
        {
            this.SetID(csCellID, lDim1, -1, -1,csKind);
        }
        /// <summary><para>method outline:</para>
        /// <para>セルの配列位置（０相対）設定</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> SetID( csCellID, lDim1, lDim2) </para>
        /// </example>
        /// <param name="csCellID">識別子</param> 
        /// <param name="lDim1">配列１次元位置（０相対）</param>
        /// <param name="lDim2">配列２次元位置（０相対）</param>
        /// <param name="csKind">セルの種別</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        virtual public void SetID(HySID csCellID, long lDim1, long lDim2, HySObjectKind csKind)
        {
            this.SetID(csCellID,lDim1, lDim2, -1 ,csKind);
        }
        /// <summary><para>method outline:</para>
        /// <para>セルの配列位置（０相対）設定</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> SetID( csCellID, lDim1, lDim2, lDim3) </para>
        /// </example>
        /// <param name="csCellID">識別子</param> 
        /// <param name="lDim1">配列１次元位置（０相対）</param>
        /// <param name="lDim2">配列２次元位置（０相対）</param>
        /// <param name="lDim3">配列３次元位置（０相対）</param>
        /// <param name="csKind">セルの種別</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        virtual public void SetID(HySID csCellID, long lDim1, long lDim2, long lDim3, HySObjectKind csKind)
        {
            HySDimIdx csIdx = new HySDimIdx(lDim1, lDim2, lDim3, csKind);
            m_csKeyTbl.AddObject( csIdx.GetString(), csCellID);
            m_csIndexTbl.AddObject((HySString)csCellID.GetString(), csIdx);
            m_csIDList.AddLast(csCellID);
        }
        /// <summary><para>method outline:</para>
        /// <para>セルの識別子取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySID csID = GetID( lDim1 ) </para>
        /// </example>
        /// <param name="lDim1">配列１次元位置（０相対）</param>
        /// <returns>識別子</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        virtual public HySID GetID(long lDim1)
        {
            return GetID(lDim1, -1, -1);
        }
        /// <summary><para>method outline:</para>
        /// <para>セルの識別子取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySID csID = GetID( lDim1, lDim2 ) </para>
        /// </example>
        /// <param name="lDim1">配列１次元位置（０相対）</param>
        /// <param name="lDim2">配列２次元位置（０相対）</param>
        /// <returns>識別子</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        virtual public HySID GetID(long lDim1, long lDim2)
        {
            return GetID(lDim1, lDim2, -1);
        }
        /// <summary><para>method outline:</para>
        /// <para>セルの識別子取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySID csID = GetID( lDim1, lDim2, lDim3) </para>
        /// </example>
        /// <param name="lDim1">配列１次元位置（０相対）</param>
        /// <param name="lDim2">配列２次元位置（０相対）</param>
        /// <param name="lDim3">配列３次元位置（０相対）</param>
        /// <returns>識別子</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        virtual public HySID GetID(long lDim1, long lDim2, long lDim3)
        {
            HySID csRtn = null;
            m_csWorkIdx.m_lDim1 = lDim1;
            m_csWorkIdx.m_lDim2 = lDim2;
            m_csWorkIdx.m_lDim3 = lDim3;
            csRtn = m_csKeyTbl.GetObject(m_csWorkIdx.GetString()) as HySID;
            return csRtn;
        }
        /// <summary><para>method outline:</para>
        /// <para>セルの配列位置（０相対）取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> GetCellIdx(csID, ref lDim1, ref lDim2, ref lDim3) </para>
        /// </example>
        /// <param name="csCellID">識別子</param>
        /// <param name="lDim1">配列１次元位置（０相対）</param>
        /// <param name="lDim2">配列２次元位置（０相対）</param>
        /// <param name="lDim3">配列３次元位置（０相対）</param>
        /// <param name="csKind">セルの種別</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        virtual public void GetCellIdx(HySID csCellID, ref long lDim1, ref long lDim2, ref long lDim3, ref HySObjectKind csKind)
        {

            HySDimIdx csRtn = null;
            if (csCellID != null)
            {
                csRtn = m_csIndexTbl.GetObject((HySString)csCellID.GetString()) as HySDimIdx;
            }
            if (csRtn != null)
            {
                lDim1 = csRtn.m_lDim1;
                lDim2 = csRtn.m_lDim2;
                lDim3 = csRtn.m_lDim3;
                csKind = csRtn.m_csObjectKind.Clone();
            }
            else
            {
                lDim1 = -1;
                lDim2 = -1;
                lDim3 = -1;
                csKind = new HySObjectKind("");
            }
        }
        /// <summary><para>method outline:</para>
        /// <para>セルの配列位置（０相対）一覧取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> GetCellIdx(ref lIdxNumber) </para>
        /// </example>
        /// <param name="lIdxNumber">個数</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        virtual public HySDimIdx[] GetCellIdx(ref long lIdxNumber)
        {
            HySDimIdx[] csRtn = null;
            HySID csID = null;
            lIdxNumber = m_csIDList.GetCount();
            csRtn = new HySDimIdx[lIdxNumber];
            m_csIDList.SetCursorFirst();
            for (long lLp = 0; lLp < lIdxNumber; lLp++)
            {
                csID = m_csIDList.GetCursorData() as HySID;

                csRtn[lLp] = m_csIndexTbl.GetObject((HySString)csID.GetString()) as HySDimIdx;

                m_csIDList.MoveCursorNext();
            }
            return csRtn;
        }

        /// <summary><para>method outline:</para>
        /// <para>識別子数取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> long lCount = GetIDCount() </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>long　レコード数</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        virtual public long GetIDCount()
        {
            return m_csIDList.GetCount();
        }
        /// <summary><para>method outline:</para>
        /// <para>識別子一覧取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySDataLinkedList csIDList = GetIDList() </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>HySDataLinkedList　一覧リスト</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        virtual public HySDataLinkedList GetIDList()
        {
            return m_csIDList;
        }
        /// <summary><para>method outline:</para>
        /// <para>内部情報クリア</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> Clear() </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        virtual public void Clear()
        {
            m_csKeyTbl.ClearAllObject();
            m_csIndexTbl.ClearAllObject();
            m_csIDList.Clear();
        }

        /// <summary><para>method outline:</para>
        /// <para>引数で与えられたデータを自分にコピーする</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> bool bRtn = CopyData(csOrgData) </para>
        /// </example>
        /// <param name="csOrgData">コピー元情報</param>
        /// <returns> 無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual void CopyData(HySCellIDManageData csOrgData)
        {
            if (csOrgData == null) { return; }
            m_csIndexTbl.ClearAllObject();
            m_csIndexTbl.Copy(csOrgData.m_csIndexTbl);

            m_csKeyTbl.ClearAllObject();
            m_csKeyTbl.Copy(csOrgData.m_csKeyTbl);

            m_csIDList.Clear();
            long lNDtNo = csOrgData.m_csIDList.GetCount();
            csOrgData.m_csIDList.SetCursorFirst();
            for (int i = 0; i < lNDtNo; i++)
            {
                m_csIDList.AddLast(csOrgData.m_csIDList.GetCursorData());
                csOrgData.m_csIDList.MoveCursorNext();
            }
        }

        // ================================================
        //   バージョンアップ時の下位互換性を保つ為の処理
        // ================================================
        /// <summary>保存バージョン情報</summary>
        private string m_sDecodedVersion;
        /// <summary><para>method outline:</para>
        /// <para>バージョン情報取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> string sDecodedVersion = GetDecodedVersion()</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>string 保存バージョン情報</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>メンバー変数に設定されているバージョン情報を返す</para>
        /// </remarks>
        public string GetDecodedVersion()
        {
            return m_sDecodedVersion;
        }
        /// <summary><para>method outline:</para>
        /// <para>バージョン情報取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> string sVersion = GetNowVersion()</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>string 現在のバージョン情報</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public string GetNowVersion()
        {
            return "1.00";
        }
        /// <summary><para>method outline:</para>
        /// <para>バージョン情報設定</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> SetNowVersion()</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>現在のバージョン情報をメンバー変数に設定する</para>
        /// </remarks>
        public void SetNowVersion()
        {
            m_sDecodedVersion = GetNowVersion();
        }
        /// <summary><para>method outline:</para>
        /// <para>復元後の整合性確保処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> PostDeserialize( ) </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>シリアライズされた旧バージョン情報を復元する際、過去の整合性をとる時に使用する
        /// バージョンによって変数等追加がない場合には、実装の必要がない
        /// </para>
        /// </remarks>
        public virtual void PostDeserialize()
        {
            if (GetDecodedVersion() != GetNowVersion())
            {
                //旧バージョンから順にバージョンを上げて行く
                switch (GetDecodedVersion())
                {
                    case "1.00":
                        break;
                }
                SetNowVersion();
            }
        }
        /// <summary><para>method outline:</para>
        /// <para>逆シリアル化時追加処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> IDeserializationCallback.OnDeserialization(csObj)</para>
        /// </example>
        /// <param name="csObj">ダミー</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>予約処理</para>
        /// </remarks>
        void IDeserializationCallback.OnDeserialization(Object csObj)
        {
            PostDeserialize();
        }
    }
}
