using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Xml;

namespace CommonMP.HYMCO.OptionImpl.McStructureXmlFileEditorForDevelop
{
    /// <summary><para>class outline:</para>
    /// <para>構造定義ファイルコントロールクラス</para>
    /// </summary>
    /// <remarks><para>history:</para>
    /// <para>[CommonMP][ver 1.0.0][2010/11/01][新規作成]</para>
    /// </remarks>
    public class StructFileController
    {
        //============================================================
        // 構造定義ファイルXML：タグ定数
        //============================================================
        /// <summary> 構造定義ファイルXMLタグ：Components </summary>
        public static readonly string XML_TAG_COMPONENTS = "Components";    //MainSystem/Components
        /// <summary> 構造定義ファイルXMLタグ：CalElement </summary>
        public static readonly string XML_TAG_CALELEMENT = "CalElement";    // ./Components/CalElement
        /// <summary> 構造定義ファイルXMLタグ：Property </summary>
        public static readonly string XML_TAG_PROPERTY = "Property";        // ./CalElement/Property
        /// <summary> 構造定義ファイルXMLタグ：InitialSet </summary>
        public static readonly string XML_TAG_INITIAL = "InitialSet";       // ./CalElement/InitialSet
        /// <summary> 構造定義ファイルXMLタグ：Variable </summary>
        public static readonly string XML_TAG_VARIABLE = "Variable";        // ./Property/Variable, /InitialSet/Variable
        /// <summary> 構造定義ファイルXMLタグ：独自パラメータ用Original </summary>
        public static readonly string XML_TAG_ORIGINAL = "Original";        // ./Property/Original, /InitialSet/Original

        /// <summary> 構造定義ファイルXMLタグ：独自パラメータ用Table </summary>
        public static readonly string XML_TAG_TABLE = "Table";              // ./Property/Table, /InitialSet/Table


        /// <summary> 構造定義ファイルXMLタグ：Ports </summary>
        public static readonly string XML_TAG_PORTS = "Ports";              // ./CalElement/Ports
        /// <summary> 構造定義ファイルXMLタグ：ReceivePort </summary>
        public static readonly string XML_TAG_RECEIVEPORT = "ReceivePort";  // ./Ports/ReceivePort
        /// <summary> 構造定義ファイルXMLタグ：SendPort </summary>
        public static readonly string XML_TAG_SENDPORT = "SendPort";        // ./Ports/SendPort


        /// <summary> 構造定義ファイルXMLタグ：Wiring </summary>
        public static readonly string XML_TAG_WIRING = "Wiring";            //MainSystem/Wiring
        /// <summary> 構造定義ファイルXMLタグ：Connection </summary>
        public static readonly string XML_TAG_CONNECTION = "Connection";    // ./Wiring/Connection
        /// <summary> 構造定義ファイルXMLタグ：SendElementOutPattern </summary>
        public static readonly string XML_TAG_SEND_OUT_PATTERN = "SendElementOutPattern";   // ./Property/SendElementOutPattern
        /// <summary> 構造定義ファイルXMLタグ：ReceiveElementInPattern </summary>
        public static readonly string XML_TAG_RECEIVE_IN_PATTERN = "ReceiveElementInPattern"; // ./Property/ReceiveElementInPattern
        /// <summary> 構造定義ファイルXMLタグ：InterpolateType </summary>
        public static readonly string XML_TAG_INTERPOLATE_TYPE = "InterpolateType"; // ./Property/InterpolateType
        /// <summary> 構造定義ファイルXMLタグ：CellDataGetter </summary>
        public static readonly string XML_TAG_CELLDATAGETTER = "CellDataGetter"; // ./Property/CellDataGetter

        /// <summary> 構造定義ファイルXML CalElement属性リスト </summary>
        public static readonly string[] XML_ATTR_CALELEMENT = { "ID", "Model", "FactoryID", "ShapeKind", "X", "Y", "Rotation", "Width", "Height", "ElementName" };    //CalElementのAttribute名
        /// <summary> 構造定義ファイルXML Connection属性リスト </summary>
        public static readonly string[] XML_ATTR_CONNECTION = { "ID", "From", "To", "TranInfo", "FactoryID", "Name" };
        /// <summary> 構造定義ファイルXML ReceivePort/SendPort属性リスト </summary>
        public static readonly string[] XML_ATTR_PORT = { "ID", "Direction", "X", "Y" };
        /// <summary> 構造定義ファイルXML ReceivePort/SendPort属性リスト </summary>
        public static readonly string[] XML_ATTR_VARIABLE = { "Key", "Name", "DataType", "Value" };


        /// <summary> 構造定義ファイルXMLﾃﾝﾌﾟﾚｰﾄ </summary>
        public static readonly string XML_TEMPLATE = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
                                                    + "<MainSystem ID=\"FigureUnity31821-2-1059098951\">\n"
                                                    + "  <Property DataFusionTiming=\"ASYNCHRONOUS\" TimeStep=\"60\" />\n"
                                                    + "  <Components />\n"
                                                    + "  <Wiring />\n"
                                                    + "</MainSystem>\n";

        /// <summary> モデル判別キー形式[モデル種別|モデルファクトリ識別子] </summary>
        public static readonly string MODEL_KEY_FORMAT = "{0}|{1}";


        /// <summary> チェックエラーリスト </summary>
        public List<ErrorItem> m_csErrorList = new List<ErrorItem>();

        /// <summary> 構造定義ファイル名パス </summary>
        public string m_sXmlFileNamePath;
        /// <summary> 構造定義ファイルXmlドキュメント </summary>
        public XmlDocument m_xmlDoc = new XmlDocument();
        /// <summary> CalElementリスト </summary>
        public XmlNodeList m_ndlCalElement = null;
        /// <summary> Connectionリスト </summary>
        public XmlNodeList m_ndlConnection = null;

        /// <summary> モデル種別ごとにしたCalElement情報(※GroupingCalElement()にて作成される) </summary>
        public Dictionary<string, CalElementModelGroup> m_lstCalElementGroups = null;

        /// <summary> CalElement情報(※PositioningCalElement()にて作成される) </summary>
        public DataTable m_dtCalElement = null;

        /// <summary> 要素IDの番号最大値[E{0}-{1}-{2:ddMMyyyy}] </summary>
        protected Dictionary<string, int> m_lstIDSeq = new Dictionary<string, int>();

        /// <summary> X座標最小値 </summary>
        protected int m_iCalElementMinX = 0;
        /// <summary> Y座標最小値 </summary>
        protected int m_iCalElementMinY = 0;


        /// <summary><para>method outline:</para>
        /// <para>コンストラクタ</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>StructFileController csStruct = new StructFileController();</para>
        /// </example>
        /// <returns>StructFileController 生成されたインスタンス</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public StructFileController()
        {
        }

        /// <summary><para>method outline:</para>
        /// <para>モデル接続作成用Excel出力</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>OutputExcel(sXmlFileNamePath, sExcelFileNamePath);</para>
        /// </example>
        /// <param name="sXmlFileNamePath">読込む構造定義ファイル名パス（未指定の場合、新規作成用）</param>
        /// <param name="sExcelFileNamePath">出力Excelファイル名パス</param>
        /// <returns>無し</returns>
        /// <exception cref="System.Exception">Excelファイル作成に失敗</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual void OutputExcel(string sXmlFileNamePath, string sExcelFileNamePath)
        {   //継承先で実装
        }

        /// <summary><para>method outline:</para>
        /// <para>構造定義ファイル出力</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bChk = OutputStructXml(sXmlFileNamePath, sExcelFileNamePath, sOutputXmlFileNamePath);</para>
        /// </example>
        /// <param name="sXmlFileNamePath">読込む構造定義ファイル名パス（未指定の場合、新規作成用）</param>
        /// <param name="sExcelFileNamePath">読込むExcelファイル名パス</param>
        /// <param name="sOutputXmlFileNamePath">出力構造定義ファイル名パス</param>
        /// <returns>true=正常/false=チェックエラーあり</returns>
        /// <exception cref="System.Exception">構造定義ファイル作成に失敗</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual bool OutputStructXml(string sXmlFileNamePath, string sExcelFileNamePath, string sOutputXmlFileNamePath)
        {   //継承先で実装
            return true;
        }


        /// <summary><para>method outline:</para>
        /// <para>エラー情報追加</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>AddError(sSheetName, iRow, iCol, sItemName, sMessage);</para>
        /// </example>
        /// <param name="sSheetName">シート名</param>
        /// <param name="iRow">行</param>
        /// <param name="iCol">列</param>
        /// <param name="sItemName">項目</param>
        /// <param name="sMessage">エラー内容</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected void AddError(string sSheetName, int iRow, int iCol, string sItemName, string sMessage)
        {
            ErrorItem err = new ErrorItem(sSheetName, iRow, iCol, sItemName, sMessage);
            AddError(err);
        }
        /// <summary><para>method outline:</para>
        /// <para>エラー情報追加</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>AddError(err);</para>
        /// </example>
        /// <param name="err">ErrorItem</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected void AddError(ErrorItem err)
        {
            m_csErrorList.Add(err);
        }

        /// <summary><para>method outline:</para>
        /// <para>ID採番</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>NewID(sIDKind);</para>
        /// </example>
        /// <param name="sIDKind">IDに付けるヘッダ</param>
        /// <returns>ID</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected string NewID(string sIDKind)
        {
            int iIDSeq = 1;
            if (m_lstIDSeq.ContainsKey(sIDKind))
                iIDSeq = m_lstIDSeq[sIDKind] + 1;

            string sID = string.Format("{0}{1}-{2:Hms}-{2:ddMMyyyy}", sIDKind, iIDSeq, DateTime.Now);

            if (m_lstIDSeq.ContainsKey(sIDKind))
                m_lstIDSeq[sIDKind] = iIDSeq;
            else
                m_lstIDSeq.Add(sIDKind, iIDSeq);

            return sID;
        }

        /// <summary><para>method outline:</para>
        /// <para>構造定義ファイル読込み</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>LoadXml(sXmlFileNamePath);</para>
        /// </example>
        /// <param name="sXmlFileNamePath">構造定義ファイル名パス（未指定の場合、新規作成）</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected void LoadXml(string sXmlFileNamePath)
        {
            m_sXmlFileNamePath = sXmlFileNamePath;
            if (!string.IsNullOrEmpty(m_sXmlFileNamePath))
            {   //構造定義ファイル読込み
                m_xmlDoc.Load(m_sXmlFileNamePath);
            }
            else
            {
                m_xmlDoc.LoadXml(XML_TEMPLATE);
            }

            //[Components/CalElement]を検索
            m_ndlCalElement = m_xmlDoc.DocumentElement.SelectNodes(string.Format("{0}/{1}", XML_TAG_COMPONENTS, XML_TAG_CALELEMENT));
            //[Wiring/Connection]を検索
            m_ndlConnection = m_xmlDoc.DocumentElement.SelectNodes(string.Format("{0}/{1}", XML_TAG_WIRING, XML_TAG_CONNECTION));
        }

        /// <summary><para>method outline:</para>
        /// <para>構造定義ファイル保存</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>SaveXml(sXmlFileNamePath);</para>
        /// </example>
        /// <param name="sXmlFileNamePath">構造定義ファイル名パス</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected void SaveXml(string sXmlFileNamePath)
        {
            m_xmlDoc.Save(sXmlFileNamePath);
        }


        /// <summary><para>method outline:</para>
        /// <para>属性値設定</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>SetAttributeValue(elmCalElement, sTagPath, sKey, sValue);</para>
        /// </example>
        /// <param name="elmCalElement">対象のノード</param>
        /// <param name="sTagPath">ノードのパス</param>
        /// <param name="sKey">検索する属性値[Key]</param>
        /// <param name="sValue">設定する値[Value]</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected void SetAttributeValue(XmlElement elmCalElement, string sTagPath, string sKey, string sValue)
        {
            SetAttributeValue(elmCalElement, sTagPath, "Key", "Value", sKey, sValue);
        }
        /// <summary><para>method outline:</para>
        /// <para>属性値設定</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>SetAttributeValue(elmCalElement, sTagPath, sAttrKey, sAttrValue, sKey, sValue);</para>
        /// </example>
        /// <param name="elmCalElement">対象のノード</param>
        /// <param name="sTagPath">ノードのパス</param>
        /// <param name="sAttrKey">検索する属性名</param>
        /// <param name="sAttrValue">設定する属性名</param>
        /// <param name="sKey">検索する属性値</param>
        /// <param name="sValue">設定する値</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected void SetAttributeValue(XmlElement elmCalElement, string sTagPath, string sAttrKey, string sAttrValue, string sKey, string sValue)
        {
            XmlNode elmNode = elmCalElement.SelectSingleNode(string.Format("{0}[@{1}='{2}']", sTagPath, sAttrKey, sKey));
            if (elmNode != null)
                elmNode.Attributes[sAttrValue].Value = sValue;
        }

        /// <summary><para>method outline:</para>
        /// <para>属性値取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>string sValue = GetAttribute(elmNode, sAttributeName);</para>
        /// </example>
        /// <param name="elmNode">対象のノード</param>
        /// <param name="sAttributeName">属性名</param>
        /// <returns>値</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected string GetAttribute(XmlElement elmNode, string sAttributeName)
        {
            string sValue = "";
            if (elmNode.HasAttribute(sAttributeName))
                sValue = elmNode.Attributes[sAttributeName].Value;
            return sValue;
        }

        /// <summary><para>method outline:</para>
        /// <para>属性値取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bValue = GetBoolAttribute(elmNode, sAttributeName, bDefault);</para>
        /// </example>
        /// <param name="elmNode">対象のノード</param>
        /// <param name="sAttributeName">属性名</param>
        /// <param name="bDefault">属性がない場合の値</param>
        /// <returns>値</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected bool GetBoolAttribute(XmlElement elmNode, string sAttributeName, bool bDefault)
        {
            bool bValue = bDefault;
            if (elmNode.HasAttribute(sAttributeName))
            {
                string sValue = elmNode.Attributes[sAttributeName].Value.ToUpper();
                bValue = (sValue == "TRUE" ? true : false);
            }
            return bValue;
        }

        /// <summary><para>method outline:</para>
        /// <para>属性値取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>int iValue = GetIntAttribute(elmNode, sAttributeName, iDefault);</para>
        /// </example>
        /// <param name="elmNode">対象のノード</param>
        /// <param name="sAttributeName">属性名</param>
        /// <param name="iDefault">属性がない場合の値</param>
        /// <returns>値</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected int GetIntAttribute(XmlElement elmNode, string sAttributeName, int iDefault)
        {
            int iValue = iDefault;
            if (elmNode.HasAttribute(sAttributeName))
            {
                string sValue = elmNode.Attributes[sAttributeName].Value;
                if(!int.TryParse(sValue, out iValue))
                    iValue = iDefault;
            }
            return iValue;
        }

        /// <summary><para>method outline:</para>
        /// <para>ポート(端子)のIDよりCalElementを検索</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>DataRow csDr = SearchPortInCalElement(sSearchTag, sID);</para>
        /// </example>
        /// <param name="sSearchTag">検索するタグ（[ReceivePort]/[SendPort]）</param>
        /// <param name="sID">ポートID</param>
        /// <returns>CalElementのDataRow</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected DataRow SearchPortInCalElement(string sSearchTag, string sID)
        {
            DataRow dr = null;
            //[Components/CalElement/Ports/ReceivePort or SendPort]ノード検索
            XmlNode elmNode = m_xmlDoc.DocumentElement.SelectSingleNode(string.Format("{0}/{1}/{2}/{3}[@ID='{4}']", XML_TAG_COMPONENTS, XML_TAG_CALELEMENT, XML_TAG_PORTS, sSearchTag, sID));
            if (elmNode != null)
            {   //CalElementタグのID取得
                string sElementID = GetAttribute((XmlElement)elmNode.ParentNode.ParentNode, "ID");
                dr = SearchCalElement(sElementID);
            }

            return dr;
        }

        /// <summary><para>method outline:</para>
        /// <para>ElementIDよりCalElementを検索</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>DataRow csDr = SearchCalElement(sElementID);</para>
        /// </example>
        /// <param name="sElementID">要素ID</param>
        /// <returns>CalElementのDataRow</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected DataRow SearchCalElement(string sElementID)
        {
            DataRow dr = null;
            DataRow[] drs = m_dtCalElement.Select(string.Format("ID='{0}'", sElementID));
            if (drs.Length > 0)
                dr = drs[0];
            return dr;
        }

        /// <summary><para>method outline:</para>
        /// <para>パターンID取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>string sPatternID = GetPatternID(elmConnection, sSearchTag);</para>
        /// </example>
        /// <param name="elmConnection">Connectionノード</param>
        /// <param name="sSearchTag">検索するタグ（[SendElementOutPattern]/[ReceiveElementInPattern]）</param>
        /// <returns>パターンID</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected string GetPatternID(XmlElement elmConnection, string sSearchTag)
        {
            string sPatternID = "";
            //[Property/SendElementOutPattern or ReceiveElementInPattern]ノード検索
            XmlNode elmNode = elmConnection.SelectSingleNode(string.Format("{0}/{1}", XML_TAG_PROPERTY, sSearchTag));
            if (elmNode != null)
            {   //PatternID取得
                sPatternID = elmNode.Attributes["PatternID"].Value;
            }
            return sPatternID;
        }

        /// <summary><para>method outline:</para>
        /// <para>接続IDに一致するPort位置情報取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn = GetPortPosition(sID, iFromX, iFromY, portSend, iToX, iToY, portReceive);</para>
        /// </example>
        /// <param name="sID">接続ID</param>
        /// <param name="iFromX">上流モデル(From)のX</param>
        /// <param name="iFromY">上流モデル(From)のY</param>
        /// <param name="portSend">上流モデル(From)のPort情報</param>
        /// <param name="iToX">下流モデル(To)のX</param>
        /// <param name="iToY">下流モデル(To)のY</param>
        /// <param name="portReceive">下流モデル(To)のPort情報</param>
        /// <returns>true=一致するConnectionノードあり/false=なし</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected bool GetPortPosition(string sID, ref int iFromX, ref int iFromY, PortItem portSend, ref int iToX, ref int iToY, PortItem portReceive) 
        {
            if (string.IsNullOrEmpty(sID))
                return false;

            //IDが一致するConnectionノード検索
            XmlElement elmConn = (XmlElement)m_xmlDoc.DocumentElement.SelectSingleNode(string.Format("{0}/{1}[@ID='{2}']", XML_TAG_WIRING, XML_TAG_CONNECTION, sID));
            if (elmConn != null)
            {
                ConnectionItem citem = new ConnectionItem();
                GetConnectionAttribute(elmConn, citem);

                //上流モデル(From)PortのIDから[Components/CalElement/Ports/SendPort]ノードを検索
                XmlNode elmSend = m_xmlDoc.DocumentElement.SelectSingleNode(string.Format("{0}/{1}/{2}/{3}[@ID='{4}']",
                                                            XML_TAG_COMPONENTS, XML_TAG_CALELEMENT, XML_TAG_PORTS, XML_TAG_SENDPORT, citem.From));
                if (elmSend != null)
                {
                    portSend.ID = citem.From;
                    portSend.Direction = GetIntAttribute((XmlElement)elmSend, "Direction", 0);
                    portSend.X = GetIntAttribute((XmlElement)elmSend, "X", 0);
                    portSend.Y = GetIntAttribute((XmlElement)elmSend, "Y", 0);
                    iFromX = GetIntAttribute((XmlElement)elmSend.ParentNode.ParentNode, "X", 0);
                    iFromY = GetIntAttribute((XmlElement)elmSend.ParentNode.ParentNode, "Y", 0);
                }

                //下流モデル(To)PortのIDから[Components/CalElement/Ports/ReceivePort]ノードを検索
                XmlNode elmTo = m_xmlDoc.DocumentElement.SelectSingleNode(string.Format("{0}/{1}/{2}/{3}[@ID='{4}']",
                                                            XML_TAG_COMPONENTS, XML_TAG_CALELEMENT, XML_TAG_PORTS, XML_TAG_RECEIVEPORT, citem.To));
                if (elmTo != null)
                {
                    portReceive.ID = citem.To;
                    portReceive.Direction = GetIntAttribute((XmlElement)elmTo, "Direction", 0);
                    portReceive.X = GetIntAttribute((XmlElement)elmTo, "X", 0);
                    portReceive.Y = GetIntAttribute((XmlElement)elmTo, "Y", 0);
                    iToX = GetIntAttribute((XmlElement)elmTo.ParentNode.ParentNode, "X", 0);
                    iToY = GetIntAttribute((XmlElement)elmTo.ParentNode.ParentNode, "Y", 0);
                }

                return true;
            }

            //一致するConnectionノードなし
            return false;
        }

        /// <summary><para>method outline:</para>
        /// <para>Connectionノードの属性取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>GetConnectionAttribute(elmConnection, citem);</para>
        /// </example>
        /// <param name="elmConnection">Connectionノード</param>
        /// <param name="citem">格納するConnectionItem</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected void GetConnectionAttribute(XmlElement elmConnection, ConnectionItem citem)
        {
            citem.ID = elmConnection.Attributes["ID"].Value;
            citem.From = elmConnection.Attributes["From"].Value;
            citem.To = elmConnection.Attributes["To"].Value;
            citem.TranInfo = elmConnection.Attributes["TranInfo"].Value;
            citem.FactoryID = elmConnection.Attributes["FactoryID"].Value;
            citem.Name = elmConnection.Attributes["Name"].Value;
            citem.ConnectionName = citem.TranInfo;
        }

        /// <summary><para>method outline:</para>
        /// <para>ConnectionノードのVariable変数値取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>string sValue = GetConnectionVariable(elmConnection, sKey);</para>
        /// </example>
        /// <param name="elmConnection">Connectionノード</param>
        /// <param name="sKey">変数名</param>
        /// <returns>値</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected string GetConnectionVariable(XmlElement elmConnection, string sKey)
        {
            string sValue = "";
            //[Property/Variable]ノード検索
            XmlNode elmNode = elmConnection.SelectSingleNode(string.Format("{0}/{1}[@Key='{2}']", XML_TAG_PROPERTY, XML_TAG_VARIABLE, sKey));
            if (elmNode != null)
            {
                sValue = elmNode.Attributes["Value"].Value;
            }
            return sValue;
        }


        /// <summary><para>method outline:</para>
        /// <para>モデル種別ごとにグルーピング</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>GroupingCalElement();</para>
        /// </example>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected void GroupingCalElement()
        {
            m_lstCalElementGroups = new Dictionary<string, CalElementModelGroup>();
            
            int iIdx = 0;
            foreach (XmlNode elmNode in m_ndlCalElement)
            {
                CalElementItem item = new CalElementItem();
                item.Index = iIdx;
                item.ID = elmNode.Attributes["ID"].Value;
                item.Model = elmNode.Attributes["Model"].Value;
                item.FactoryID = elmNode.Attributes["FactoryID"].Value;
                item.ElementName = elmNode.Attributes["ElementName"].Value;

                //キー[Model|FactoryID]
                string sKey = string.Format(StructFileController.MODEL_KEY_FORMAT, item.Model, item.FactoryID);
                CalElementModelGroup gp = null;
                if (!m_lstCalElementGroups.ContainsKey(sKey))
                {   //初めて出現するモデル種別ならばモデル種別追加
                    gp = new CalElementModelGroup();
                    gp.Model = item.Model;
                    gp.FactoryID = item.FactoryID;
                    gp.ModelName = item.Model;
                    gp.Items.Add(item.ID, item);
                    m_lstCalElementGroups.Add(sKey, gp);
                }
                else
                {   //同じモデル種別のリストに追加
                    gp = m_lstCalElementGroups[sKey];
                    gp.Items.Add(item.ID, item);
                }


                XmlElement ndCalElement = (XmlElement)elmNode;
                foreach (XmlElement elmNode0 in ndCalElement.ChildNodes)
                {
                    if ( (!elmNode0.Name.Equals(StructFileController.XML_TAG_PROPERTY)) && 
                         (!elmNode0.Name.Equals(StructFileController.XML_TAG_INITIAL)) )
                        continue;
                    foreach (XmlElement elmNode1 in elmNode0.ChildNodes)
                    {
                        if (elmNode1.Name.Equals(StructFileController.XML_TAG_VARIABLE) || elmNode1.Name.Equals(StructFileController.XML_TAG_ORIGINAL))
                        {   //[Variable][Original]
                            CalElementVariable data = new CalElementVariable();
                            data.Key = elmNode1.Attributes["Key"].Value;
                            data.Name = elmNode1.Attributes["Name"].Value;
                            data.DataType = elmNode1.Attributes["DataType"].Value.ToUpper();
                            data.Value = elmNode1.Attributes["Value"].Value;
                            data.TagPath = string.Format("{0}/{1}", elmNode0.Name, elmNode1.Name);
                            string sPKey = string.Format("{0}[@Key='{1}']", data.TagPath, data.Key);

                            //プロパティ情報[Property] or 初期状態情報[InitialSet]
                            item.Propertys.Add(sPKey, data);

                            //同じモデルなら項目数も同じはずだが、バージョンなどによって違う場合もあるので全項目のリストを作成
                            if (!gp.PropertyKeys.Contains(sPKey))
                                gp.PropertyKeys.Add(sPKey);
                        }
                        else if (elmNode1.Name.Equals(StructFileController.XML_TAG_TABLE))
                        {   //[Table]
                            CalElementOriginal data = new CalElementOriginal();
                            data.Key = elmNode1.Attributes["Key"].Value;
                            data.Name = elmNode1.Attributes["Name"].Value;
                            data.AddCols = GetBoolAttribute(elmNode1, "AddCols", false);
                            data.AddRows = GetBoolAttribute(elmNode1, "AddRows", false);
                            data.RowNumHeader = GetBoolAttribute(elmNode1, "RowNumHeader", false);
                            data.TagPath = string.Format("{0}/{1}", elmNode0.Name, elmNode1.Name);
                            string sPKey = string.Format("{0}[@Key='{1}']", data.TagPath, data.Key);

                            //スキーマ情報
                            XmlNodeList ndlSchema = elmNode1.SelectNodes("Schema/Element");
                            foreach (XmlElement elmSchema in ndlSchema)
                            {
                                CalElementOriginalSchema scm = new CalElementOriginalSchema();
                                scm.Key = elmSchema.Attributes["Key"].Value;
                                scm.Name = elmSchema.Attributes["Name"].Value;
                                scm.DataType = elmSchema.Attributes["DataType"].Value.ToUpper();
                                scm.Occurs = GetBoolAttribute(elmSchema, "Occurs", false);

                                data.Schemas.Add(scm.Key, scm);
                            }

                            XmlNodeList ndlRows = elmNode1.SelectNodes("Row");
                            foreach (XmlNode ndRow in ndlRows)
                            {   //行データ
                                Dictionary<string, CalElementOriginalColumn> cols = new Dictionary<string, CalElementOriginalColumn>();
                                XmlNodeList ndlCols = ndRow.SelectNodes("Col");
                                foreach (XmlElement elmCol in ndlCols)
                                {   //列データ
                                    CalElementOriginalColumn col = new CalElementOriginalColumn();
                                    col.Key = elmCol.Attributes["Key"].Value;
                                    col.Value = elmCol.Attributes["Value"].Value;
                                    col.No = GetIntAttribute(elmCol, "No", 0);

                                    //対応するスキーマ取得
                                    if (data.Schemas.ContainsKey(col.Key))
                                    {
                                        CalElementOriginalSchema scm = data.Schemas[col.Key];
                                        if (scm.Occurs)
                                        {   //繰り返し項目の場合、Noの最小値・最大値をセット
                                            scm.MinNo = (scm.MinNo == 0 ? col.No : Math.Min(scm.MinNo, col.No));
                                            scm.MaxNo = (scm.MaxNo == 0 ? col.No : Math.Max(scm.MaxNo, col.No));

                                            data.MinNo = (data.MinNo == 0 ? col.No : Math.Min(data.MinNo, col.No));
                                            data.MaxNo = (data.MaxNo == 0 ? col.No : Math.Max(data.MaxNo, col.No));
                                        }

                                        string sColKey = string.Format("{0}|{1:#}", col.Key, (scm.Occurs ? col.No : 0));
                                        cols.Add(sColKey, col);
                                    }
                                }
                                data.Rows.Add(cols);
                            }

                            //列数をカウント
                            foreach (KeyValuePair<string, CalElementOriginalSchema> csSchema in data.Schemas)
                            {
                                CalElementOriginalSchema scm = csSchema.Value;
                                data.ColCount += (scm.MaxNo - scm.MinNo + 1);
                            }

                            //独自プロパティ情報・初期状態情報
                            item.OriginalPropertys.Add(sPKey, data);
                        }
                    }
                }

                iIdx++;
            }

        }
        /// <summary><para>method outline:</para>
        /// <para>行ノード作成</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>XmlElement csNew = CreateOriginalRow(xmlNewDoc, csSchemas, csCols, iMinNo, iMaxNo);</para>
        /// </example>
        /// <param name="xmlNewDoc">XmlDocument</param>
        /// <param name="csSchemas">スキーマ</param>
        /// <param name="csCols">列データ</param>
        /// <param name="iMinNo">No最小値</param>
        /// <param name="iMaxNo">No最大値</param>
        /// <returns>XmlElement</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected XmlElement CreateOriginalRow(XmlDocument xmlNewDoc, Dictionary<string, CalElementOriginalSchema> csSchemas,
                    Dictionary<string, CalElementOriginalColumn> csCols, int iMinNo, int iMaxNo)
        {
            XmlElement elmRow = xmlNewDoc.CreateElement("Row");
            List<CalElementOriginalSchema> lstOccurs = new List<CalElementOriginalSchema>();
            foreach (KeyValuePair<string, CalElementOriginalSchema> csSchema in csSchemas)
            {
                CalElementOriginalSchema scm = csSchema.Value;
                if (scm.Occurs)
                {   //繰り返し項目の場合、まとめてNoごとに出力
                    lstOccurs.Add(scm);
                }
                else
                {
                    if (lstOccurs.Count > 0)
                    {   //繰り返し項目
                        for (int iNo = iMinNo; iNo <= iMaxNo; iNo++)
                        {
                            for (int i = 0; i < lstOccurs.Count; i++)
                            {
                                XmlElement elmCol = CreateOriginalCol(xmlNewDoc, lstOccurs[i].Key, iNo, csCols);
                                if (elmCol != null)
                                    elmRow.AppendChild(elmCol);
                            }
                        }
                        lstOccurs.Clear();
                    }

                    //繰り返さない項目
                    XmlElement elmC = CreateOriginalCol(xmlNewDoc, scm.Key, 0, csCols);
                    elmRow.AppendChild(elmC);
                }
            }
            if (lstOccurs.Count > 0)
            {   //繰り返し項目
                for (int iNo = iMinNo; iNo <= iMaxNo; iNo++)
                {
                    for (int i = 0; i < lstOccurs.Count; i++)
                    {
                        XmlElement elmCol = CreateOriginalCol(xmlNewDoc, lstOccurs[i].Key, iNo, csCols);
                        if (elmCol != null)
                            elmRow.AppendChild(elmCol);
                    }
                }
            }
            return elmRow;
        }
        /// <summary><para>method outline:</para>
        /// <para>列ノード作成</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>XmlElement csNew = CreateOriginalCol(xmlNewDoc, sKey, iNo, csCols);</para>
        /// </example>
        /// <param name="xmlNewDoc">XmlDocument</param>
        /// <param name="sKey">変数名</param>
        /// <param name="iNo">No</param>
        /// <param name="csCols">列データ</param>
        /// <returns>XmlElement</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        private XmlElement CreateOriginalCol(XmlDocument xmlNewDoc, string sKey, int iNo, Dictionary<string, CalElementOriginalColumn> csCols)
        {
            XmlElement elmCol = null;
            string sColKey = string.Format("{0}|{1:#}", sKey, iNo);
            if (csCols.ContainsKey(sColKey))
            {
                if (iNo > 0)
                {
                    elmCol = CreateNewElement(xmlNewDoc, "Col", new string[] { "Key", "No", "Value" });
                    elmCol.Attributes["No"].Value = iNo.ToString();
                }
                else
                {
                    elmCol = CreateNewElement(xmlNewDoc, "Col", new string[] { "Key", "Value" });
                }
                elmCol.Attributes["Key"].Value = sKey;
                elmCol.Attributes["Value"].Value = csCols[sColKey].Value;
            }
            return elmCol;
        }

        /// <summary><para>method outline:</para>
        /// <para>要素モデルのテーブルを作成し、モデル配置決定</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>PositioningCalElement(dCelWidth, dCelHeight);</para>
        /// </example>
        /// <param name="dCelWidth">1セルの幅</param>
        /// <param name="dCelHeight">1セルの高さ</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected void PositioningCalElement(double dCelWidth, double dCelHeight)
        {
            string[] sIntCols = { "No", "CellX", "CellY", "X", "Y", "Rotation", "Width", "Height" };
            
            //--------------------------------------------------
            // テーブル初期化
            //--------------------------------------------------
            m_dtCalElement = new DataTable("CalElement");
            DataTable dt = m_dtCalElement;
            dt.Columns.Add("No", Type.GetType("System.Int32"));
            dt.Columns.Add("CellX", Type.GetType("System.Int32"));
            dt.Columns.Add("CellY", Type.GetType("System.Int32"));
            for (int i = 0; i < XML_ATTR_CALELEMENT.Length; i++)
            {
                string sType = (Array.IndexOf(sIntCols, XML_ATTR_CALELEMENT[i]) >= 0 ? "System.Int32" : "System.String");
                dt.Columns.Add(XML_ATTR_CALELEMENT[i], Type.GetType(sType));
            }
            //Noをﾌﾟﾗｲﾏﾘｷｰに設定
            DataColumn[] keys = { dt.Columns["No"] };
            dt.PrimaryKey = keys;
            
            //--------------------------------------------------
            int iIDSeq = 0;
            int iNo = 0;
            foreach (XmlElement elmNode in m_ndlCalElement)
            {
                iNo++;
                DataRow dr = dt.NewRow();
                for (int i = 0; i < XML_ATTR_CALELEMENT.Length; i++)
                {
                    string sAttr = XML_ATTR_CALELEMENT[i];
                    if (Array.IndexOf(sIntCols, sAttr) >= 0)
                        dr[sAttr] = Convert.ToInt32(elmNode.Attributes[sAttr].Value);
                    else
                        dr[sAttr] = elmNode.Attributes[sAttr].Value;
                }
                dr["No"] = iNo;

                dt.Rows.Add(dr);

                //IDの番号部分を取得
                int iSeq = 0;
                string[] sID = dr["ID"].ToString().Split('-');
                if (sID.Length > 0 && sID[0].StartsWith("E") && int.TryParse(sID[0].Substring(1), out iSeq))
                {
                    iIDSeq = Math.Max(iIDSeq, iSeq);
                }
            }

            if (m_lstIDSeq.ContainsKey("E"))
                m_lstIDSeq["E"] = iIDSeq;
            else
                m_lstIDSeq.Add("E", iIDSeq);

            if (dt.Rows.Count > 0)
            {   //座標XYの最小値取得
                m_iCalElementMinX = Convert.ToInt32(dt.Compute("MIN(X)", ""));
                m_iCalElementMinY = Convert.ToInt32(dt.Compute("MIN(Y)", ""));
            }

            foreach (DataRow dr in dt.Rows)
            {
                //最小値を左上(0,0)とした座標にする
                int iX = (int)dr["X"] - m_iCalElementMinX;
                int iY = (int)dr["Y"] - m_iCalElementMinY;
                //座標XYをセル位置に変換する
                dr["CellX"] = Convert.ToInt32(Math.Round(iX / dCelWidth, MidpointRounding.AwayFromZero));   //四捨五入
                dr["CellY"] = Convert.ToInt32(Math.Round(iY / dCelHeight, MidpointRounding.AwayFromZero));  //四捨五入
            }

            //セル位置でソートする
            DataView dv = new DataView(dt.Copy(), "", "CellY,CellX,X", DataViewRowState.CurrentRows);
            for (int i = 1; i < dv.Count; i++)
            {   //セル位置の重複を直す
                DataRow dr0 = dt.Rows.Find(dv[i - 1]["No"]);
                DataRow dr1 = dt.Rows.Find(dv[i]["No"]);
                if ((int)dr0["CellY"] == (int)dr1["CellY"] && (int)dr0["CellX"] >= (int)dr1["CellX"])
                {   //同じY位置で、Xが同じ場合は右にずらす
                    dr1["CellX"] = (int)dr0["CellX"] + 1;
                }
            }

        }

        /// <summary><para>method outline:</para>
        /// <para>位置ｻｲｽﾞ設定（同じIDのCalElementがある場合、位置とｻｲｽﾞはもとの値を引き継ぐ）</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>SetCalElementPosition(eitem);</para>
        /// </example>
        /// <param name="eitem">CalElementItem</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected void SetCalElementPosition(CalElementItem eitem)
        {
            eitem.IsChangePosition = true;

            //同じIDのCalElementがある場合、位置とｻｲｽﾞはもとの値を引き継ぐ
            DataRow dr = SearchCalElement(eitem.ID);
            if (dr != null)
            {   //更新
                int iCellX = (int)dr["CellX"];
                int iCellY = (int)dr["CellY"];
                if (iCellX == eitem.CellX && iCellY == eitem.CellY)
                {   //配置セル位置が変更されていない場合はX,Y,Rotation,Width,Heightはそのまま
                    eitem.X = (int)dr["X"];
                    eitem.Y = (int)dr["Y"];
                    eitem.Rotation = (int)dr["Rotation"];
                    eitem.Width = (int)dr["Width"];
                    eitem.Height = (int)dr["Height"];
                    //位置変更なしにセット
                    eitem.IsChangePosition = false;
                }
            }
        }

        /// <summary><para>method outline:</para>
        /// <para>CalElementノード作成</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>XmlElement csNew = CreateCalElement(xmlNewDoc, eitem);</para>
        /// </example>
        /// <param name="xmlNewDoc">XmlDocument</param>
        /// <param name="eitem">CalElementItem</param>
        /// <returns>CalElementノード</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected XmlElement CreateCalElement(XmlDocument xmlNewDoc, CalElementItem eitem)
        {
            XmlElement elmCalElement = null;
            XmlNode elmNode = xmlNewDoc.DocumentElement.SelectSingleNode(string.Format("{0}/{1}[@ID='{2}']", XML_TAG_COMPONENTS, XML_TAG_CALELEMENT, eitem.ID));
            if (elmNode == null)
            {   //IDが一致するCalElementがなかった場合、新規作成
                elmCalElement = CreateNewElement(xmlNewDoc, XML_TAG_CALELEMENT, XML_ATTR_CALELEMENT, XML_TAG_PORTS);
                elmCalElement.Attributes["ID"].Value = eitem.ID;
            }
            else
            {   //一致あり
                elmCalElement = (XmlElement)elmNode.Clone();
            }

            if (!elmCalElement.Attributes["Model"].Value.Equals(eitem.Model) ||
                !elmCalElement.Attributes["FactoryID"].Value.Equals(eitem.FactoryID))
            {   //新規か要素モデルが変更されている場合
                XmlNode ndProperty = elmCalElement.SelectSingleNode(string.Format("{0}", XML_TAG_PROPERTY));
                if (ndProperty != null)
                    elmCalElement.RemoveChild(ndProperty);
                XmlNode ndInitial = elmCalElement.SelectSingleNode(string.Format("{0}", XML_TAG_INITIAL));
                if (ndInitial != null)
                    elmCalElement.RemoveChild(ndInitial);
                
                elmCalElement.Attributes["Model"].Value = eitem.Model;
                elmCalElement.Attributes["FactoryID"].Value = eitem.FactoryID;
                elmCalElement.Attributes["ShapeKind"].Value = eitem.ShapeKind;
                elmCalElement.Attributes["Rotation"].Value = eitem.Rotation.ToString();
                elmCalElement.Attributes["Width"].Value = eitem.Width.ToString();
                elmCalElement.Attributes["Height"].Value = eitem.Height.ToString();
            }
            elmCalElement.Attributes["ElementName"].Value = eitem.ElementName;
            elmCalElement.Attributes["X"].Value = eitem.X.ToString();
            elmCalElement.Attributes["Y"].Value = eitem.Y.ToString();

            //ポート
            XmlNode ndPorts = elmCalElement.SelectSingleNode(string.Format("{0}", XML_TAG_PORTS));
            if (ndPorts == null)
            {   //[Ports]ノード自体がない場合、新規作成
                XmlElement elmPorts = xmlNewDoc.CreateElement(XML_TAG_PORTS);
                elmCalElement.AppendChild(elmPorts);
                ndPorts = (XmlElement)elmPorts;
            }
            else
            {
                ndPorts.RemoveAll();
            }
            //受信端子ノード追加
            CreatePorts(xmlNewDoc, ndPorts, XML_TAG_RECEIVEPORT, XML_ATTR_PORT, eitem.ReceivePorts);
            //送信端子ノード追加
            CreatePorts(xmlNewDoc, ndPorts, XML_TAG_SENDPORT, XML_ATTR_PORT, eitem.SendPorts);
            

            return elmCalElement;
        }

        /// <summary><para>method outline:</para>
        /// <para>ReceivePort/SendPortノード作成</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>CreatePorts(xmlNewDoc, ndPorts, sTag, sAttrKey, lstPorts);</para>
        /// </example>
        /// <param name="xmlNewDoc">XmlDocument</param>
        /// <param name="ndPorts">Portsノード</param>
        /// <param name="sTag">作成するノード名（ReceivePort/SendPort）</param>
        /// <param name="sAttrKey">属性リスト</param>
        /// <param name="lstPorts">追加するノード</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        private void CreatePorts(XmlDocument xmlNewDoc, XmlNode ndPorts, string sTag ,string[] sAttrKey, Dictionary<int, PortItem> lstPorts)
        {
            foreach (KeyValuePair<int, PortItem> pt in lstPorts)
            {
                PortItem pitem = pt.Value;
                XmlElement elmPort = xmlNewDoc.CreateElement(sTag);
                //属性追加
                for (int i = 0; i < sAttrKey.Length; i++)
                {
                    XmlAttribute atr = xmlNewDoc.CreateAttribute(sAttrKey[i]);
                    if (sAttrKey[i].Equals("ID"))
                        atr.Value = pitem.ID;
                    if (sAttrKey[i].Equals("Direction"))
                        atr.Value = pitem.Direction.ToString();
                    if (sAttrKey[i].Equals("X"))
                        atr.Value = pitem.X.ToString();
                    if (sAttrKey[i].Equals("Y"))
                        atr.Value = pitem.Y.ToString();

                    elmPort.Attributes.Append(atr);
                }

                ndPorts.AppendChild(elmPort);
            }
        }

        /// <summary><para>method outline:</para>
        /// <para>Connectionノード作成</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>XmlElement csNew = CreateConnection(xmlNewDoc, citem);</para>
        /// </example>
        /// <param name="xmlNewDoc">XmlDocument</param>
        /// <param name="citem">ConnectionItem</param>
        /// <returns>Connectionノード</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected XmlElement CreateConnection(XmlDocument xmlNewDoc, ConnectionItem citem)
        {
            XmlElement elmConnection = null;
            XmlNode elmNode = xmlNewDoc.DocumentElement.SelectSingleNode(string.Format("{0}/{1}[@ID='{2}']", XML_TAG_WIRING, XML_TAG_CONNECTION, citem.ID));
            if (elmNode == null)
            {   //IDが一致するConnectionがなかった場合、新規作成
                elmConnection = CreateNewElement(xmlNewDoc, XML_TAG_CONNECTION, XML_ATTR_CONNECTION, XML_TAG_PROPERTY);
                elmConnection.Attributes["ID"].Value = citem.ID;
            }
            else
            {   //一致あり
                elmConnection = (XmlElement)elmNode.Clone();
            }

            elmConnection.Attributes["From"].Value = citem.From;
            elmConnection.Attributes["To"].Value = citem.To;
            elmConnection.Attributes["Name"].Value = citem.Name;

            //[Property]ノード取得
            XmlElement ndProperty = (XmlElement)elmConnection.SelectSingleNode(string.Format("{0}", XML_TAG_PROPERTY));
            if (ndProperty == null)
            {   //[Property]ノード自体がない場合、新規作成
                ndProperty = xmlNewDoc.CreateElement(XML_TAG_PROPERTY);
                elmConnection.AppendChild(ndProperty);
            }
            XmlElement ndPropertyBak = (XmlElement)ndProperty.Clone();
            ndProperty.RemoveAll();

            if (!elmConnection.Attributes["TranInfo"].Value.Equals(citem.TranInfo) ||
                !elmConnection.Attributes["FactoryID"].Value.Equals(citem.FactoryID))
            {   //新規か要素接続が変更されている場合
                elmConnection.Attributes["TranInfo"].Value = citem.TranInfo;
                elmConnection.Attributes["FactoryID"].Value = citem.FactoryID;
                ndPropertyBak = null;
            }

            //[Variable]子ノード作成
            foreach (CalElementVariable vari in citem.Variables)
            {
                if (string.IsNullOrEmpty(vari.Key))
                    continue;
                XmlElement child = CreateNewElement(xmlNewDoc, XML_TAG_VARIABLE, XML_ATTR_VARIABLE);
                child.Attributes["Key"].Value = vari.Key;
                child.Attributes["Name"].Value = vari.Name;
                child.Attributes["DataType"].Value = vari.DataType;
                child.Attributes["Value"].Value = vari.Value;
                ndProperty.AppendChild(child);
            }
            //[SendElementOutPattern]子ノード作成
            XmlElement childS = CreateNewElement(xmlNewDoc, XML_TAG_SEND_OUT_PATTERN, new string[] { "PatternID" });
            childS.Attributes["PatternID"].Value = citem.FromPatternID;
            ndProperty.AppendChild(childS);

            //[ReceiveElementInPattern]子ノード作成
            XmlElement childR = CreateNewElement(xmlNewDoc, XML_TAG_RECEIVE_IN_PATTERN, new string[] { "PatternID" });
            childR.Attributes["PatternID"].Value = citem.ToPatternID;
            ndProperty.AppendChild(childR);

            //[InterpolateType]子ノード作成
            XmlElement childI = CreateNewElement(xmlNewDoc, XML_TAG_INTERPOLATE_TYPE, new string[] { "Kind" });
            childI.Attributes["Kind"].Value = citem.InterpolateType;
            ndProperty.AppendChild(childI);

            //上記以外の子ノードコピー
            if (ndPropertyBak != null)
            {
                foreach (XmlElement elmChild1 in ndPropertyBak.ChildNodes)
                {
                    XmlNodeList ndList = ndProperty.SelectNodes(string.Format("{0}", elmChild1.Name));
                    if (ndList.Count == 0)
                    {   //追加済みノード以外
                        ndProperty.AppendChild(elmChild1.Clone());
                    }
                }
            }

            return elmConnection;
        }

        /// <summary><para>method outline:</para>
        /// <para>新しいノード作成</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>XmlElement csNew = CreateNewElement(xmlNewDoc, sTag, sAttrKey, sChildNodes);</para>
        /// </example>
        /// <param name="xmlNewDoc">XmlDocument</param>
        /// <param name="sTag">ノード名</param>
        /// <param name="sAttrKey">属性リスト</param>
        /// <param name="sChildNodes">子ノード名</param>
        /// <returns>新しいノード</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        private XmlElement CreateNewElement(XmlDocument xmlNewDoc, string sTag, string[] sAttrKey, params string[] sChildNodes)
        {
            XmlElement elmNewElement = xmlNewDoc.CreateElement(sTag);
            //属性追加
            for (int i = 0; i < sAttrKey.Length; i++)
            {
                XmlAttribute atr = xmlNewDoc.CreateAttribute(sAttrKey[i]);
                elmNewElement.Attributes.Append(atr);
            }
            //子ノード作成
            for (int i = 0; i < sChildNodes.Length; i++)
            {
                XmlElement child = xmlNewDoc.CreateElement(sChildNodes[i]);
                elmNewElement.AppendChild(child);
            }
            return elmNewElement;
        }

        /// <summary><para>method outline:</para>
        /// <para>子ノードを全削除して追加</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>AppendChildNodes(xmlDoc, lstNodes, sParentTag);</para>
        /// </example>
        /// <param name="xmlDoc">XmlDocument</param>
        /// <param name="lstNodes">追加する子ノード</param>
        /// <param name="sParentTag">親ノード名</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected void AppendChildNodes(XmlDocument xmlDoc, List<XmlElement> lstNodes, string sParentTag)
        {
            XmlNode ndParent = xmlDoc.DocumentElement.SelectSingleNode(string.Format("{0}", sParentTag));
            ndParent.RemoveAll();
            foreach (XmlElement elmNode in lstNodes)
            {
                ndParent.AppendChild(elmNode);
            }
        }
        /// <summary><para>method outline:</para>
        /// <para>指定された子ノードを全削除して追加</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>AppendChildNodes(elmParent, lstNodes, sDeleteChildTag);</para>
        /// </example>
        /// <param name="elmParent">XmlElement</param>
        /// <param name="lstNodes">追加する子ノード</param>
        /// <param name="sDeleteChildTag">削除する子ノード名</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected void AppendChildNodes(XmlElement elmParent, List<XmlElement> lstNodes, string sDeleteChildTag)
        {
            XmlNodeList ndlChilds = elmParent.SelectNodes(string.Format("{0}", sDeleteChildTag));
            foreach (XmlElement elmNode in ndlChilds)
            {
                elmParent.RemoveChild(elmNode);
            }
            foreach (XmlElement elmNode in lstNodes)
            {
                elmParent.AppendChild(elmNode);
            }
        }

    }


    //===========================================================================================
    /// <summary><para>class outline:</para>
    /// <para>要素モデルグループデータクラス</para>
    /// </summary>
    /// <remarks><para>history:</para>
    /// <para>[CommonMP][ver 1.0.0][2010/11/01][新規作成]</para>
    /// </remarks>
    public class CalElementModelGroup
    {
        /// <summary> モデル種別 </summary>
        public string Model;
        /// <summary> モデルファクトリ識別子 </summary>
        public string FactoryID;
        /// <summary> モデル名称 </summary>
        public string ModelName;
        /// <summary> 要素[Key=ID] </summary>
        public Dictionary<string, CalElementItem> Items = new Dictionary<string, CalElementItem>();

        /// <summary> プロパティ情報・初期状態情報 [TagPath[\@Key='変数名']] </summary>
        public List<string> PropertyKeys = new List<string>();
    }

    /// <summary><para>class outline:</para>
    /// <para>要素モデルデータクラス</para>
    /// </summary>
    /// <remarks><para>history:</para>
    /// <para>[CommonMP][ver 1.0.0][2010/11/01][新規作成]</para>
    /// </remarks>
    public class CalElementItem
    {
        /// <summary> ノードのインデックス </summary>
        public int Index;
        /// <summary> モデル名称 </summary>
        public string ModelName;
        /// <summary> セル位置X </summary>
        public int CellX;
        /// <summary> セル位置Y </summary>
        public int CellY;
        /// <summary> 位置変更フラグ(true=位置変更あり) </summary>
        public bool IsChangePosition = true;

        /// <summary> ID </summary>
        public string ID;
        /// <summary> モデル種別 </summary>
        public string Model;
        /// <summary> モデルファクトリ識別子 </summary>
        public string FactoryID;
        /// <summary> 要素名称 </summary>
        public string ElementName;

        /// <summary> ShapeKind </summary>
        public string ShapeKind;
        /// <summary> X </summary>
        public int X;
        /// <summary> Y </summary>
        public int Y;
        /// <summary> Rotation </summary>
        public int Rotation;
        /// <summary> Width </summary>
        public int Width;
        /// <summary> Height </summary>
        public int Height;

        /// <summary> プロパティ情報・初期状態情報 [Key=TagPath[\@Key='変数名']] </summary>
        public Dictionary<string, CalElementVariable> Propertys = new Dictionary<string, CalElementVariable>();

        /// <summary> 独自プロパティ情報・独自初期状態情報 [Key=TagPath[\@Key='変数名']] </summary>
        public Dictionary<string, CalElementOriginal> OriginalPropertys = new Dictionary<string, CalElementOriginal>();


        /// <summary> 送信用ポート [Key=接続リストへのインデックス] </summary>
        public Dictionary<int, PortItem> SendPorts = new Dictionary<int, PortItem>();
        /// <summary> 受信用ポート [Key=接続リストへのインデックス] </summary>
        public Dictionary<int, PortItem> ReceivePorts = new Dictionary<int, PortItem>();
    }

    /// <summary><para>class outline:</para>
    /// <para>ポートデータクラス</para>
    /// </summary>
    /// <remarks><para>history:</para>
    /// <para>[CommonMP][ver 1.0.0][2010/11/01][新規作成]</para>
    /// </remarks>
    public class PortItem
    {
        /// <summary> ID </summary>
        public string ID;
        /// <summary> Direction </summary>
        public int Direction;
        /// <summary> X </summary>
        public int X;
        /// <summary> Y </summary>
        public int Y;
    }

    /// <summary><para>class outline:</para>
    /// <para>接続データクラス</para>
    /// </summary>
    /// <remarks><para>history:</para>
    /// <para>[CommonMP][ver 1.0.0][2010/11/01][新規作成]</para>
    /// </remarks>
    public class ConnectionItem
    {
        /// <summary> ID </summary>
        public string ID;
        /// <summary> From </summary>
        public string From;
        /// <summary> To </summary>
        public string To;
        /// <summary> 接続種別 </summary>
        public string TranInfo;
        /// <summary> 接続ファクトリ識別子 </summary>
        public string FactoryID;
        /// <summary> 接続名称 </summary>
        public string Name;

        /// <summary> 要素接続名称 </summary>
        public string ConnectionName;

        /// <summary> From側の要素No </summary>
        public int FromNo;
        /// <summary> From側のPatternID </summary>
        public string FromPatternID;
        /// <summary> From側のPattern名 </summary>
        public string FromPattern;

        /// <summary> To側の要素No </summary>
        public int ToNo;
        /// <summary> To側のPatternID </summary>
        public string ToPatternID;
        /// <summary> To側のPattern名 </summary>
        public string ToPattern;

        /// <summary> InterpolateType </summary>
        public string InterpolateType;

        /// <summary> プロパティ変数[Key=変数名] </summary>
        public List<CalElementVariable> Variables = new List<CalElementVariable>();

    }

    /// <summary><para>class outline:</para>
    /// <para>パラメータデータクラス</para>
    /// </summary>
    /// <remarks><para>history:</para>
    /// <para>[CommonMP][ver 1.0.0][2010/11/01][新規作成]</para>
    /// </remarks>
    public class CalElementVariable
    {
        /// <summary> タグパス </summary>
        public string TagPath;

        /// <summary> 変数名 </summary>
        public string Key;
        /// <summary> 項目 </summary>
        public string Name;
        /// <summary> 型 </summary>
        public string DataType;
        /// <summary> 値 </summary>
        public string Value;
    }

    /// <summary><para>class outline:</para>
    /// <para>表形式パラメータデータクラス</para>
    /// </summary>
    /// <remarks><para>history:</para>
    /// <para>[CommonMP][ver 1.0.0][2010/11/01][新規作成]</para>
    /// </remarks>
    public class CalElementOriginal
    {
        /// <summary> タグパス </summary>
        public string TagPath;

        /// <summary> 変数名 </summary>
        public string Key;
        /// <summary> 項目 </summary>
        public string Name;
        /// <summary> 列追加可能か [true=列追加可能/false=列数固定] </summary>
        public bool AddCols;
        /// <summary> 行追加可能か [true=行追加可能/false=行数固定] </summary>
        public bool AddRows;
        /// <summary> 行No見出し表示するか [true=表示する/false=表示なし（※省略時=false）] </summary>
        public bool RowNumHeader = false;

        /// <summary> スキーマ情報 [Key=変数名] </summary>
        public Dictionary<string, CalElementOriginalSchema> Schemas = new Dictionary<string, CalElementOriginalSchema>();

        /// <summary> 行データ[Key=変数名|No] </summary>
        public List<Dictionary<string, CalElementOriginalColumn>> Rows = new List<Dictionary<string, CalElementOriginalColumn>>();

        
        /// <summary> 列数 </summary>
        public int ColCount;
        /// <summary> No最小値（列追加可能の場合のみ） </summary>
        public int MinNo;
        /// <summary> No最大値（列追加可能の場合のみ） </summary>
        public int MaxNo;
    }
    /// <summary><para>class outline:</para>
    /// <para>表形式パラメータのスキーマ情報データクラス</para>
    /// </summary>
    /// <remarks><para>history:</para>
    /// <para>[CommonMP][ver 1.0.0][2010/11/01][新規作成]</para>
    /// </remarks>
    public class CalElementOriginalSchema
    {
        /// <summary> 変数名 </summary>
        public string Key;
        /// <summary> 項目 </summary>
        public string Name;
        /// <summary> 型 </summary>
        public string DataType;
        /// <summary> 繰り返し項目か [true=有/false=無（※省略時=false）] </summary>
        public bool Occurs = false;

        /// <summary> No最小値（繰り返し項目の場合のみ） </summary>
        public int MinNo;
        /// <summary> No最大値（繰り返し項目の場合のみ） </summary>
        public int MaxNo;
    }
    /// <summary><para>class outline:</para>
    /// <para>列データデータクラス</para>
    /// </summary>
    /// <remarks><para>history:</para>
    /// <para>[CommonMP][ver 1.0.0][2010/11/01][新規作成]</para>
    /// </remarks>
    public class CalElementOriginalColumn
    {
        /// <summary> 変数名 </summary>
        public string Key;
        /// <summary> No </summary>
        public int No;
        /// <summary> 値 </summary>
        public string Value;

        /// <summary> スキーマ情報 </summary>
        public CalElementOriginalSchema Schema = null;
    }

    /// <summary><para>class outline:</para>
    /// <para>エラー情報データクラス</para>
    /// </summary>
    /// <remarks><para>history:</para>
    /// <para>[CommonMP][ver 1.0.0][2010/11/01][新規作成]</para>
    /// </remarks>
    public class ErrorItem
    {
        /// <summary> シート名 </summary>
        public string SheetName;
        /// <summary> 行 </summary>
        public int Row;
        /// <summary> 列 </summary>
        public int Col;
        /// <summary> 項目 </summary>
        public string ItemName;
        /// <summary> エラー内容 </summary>
        public string Message;

        /// <summary><para>method outline:</para>
        /// <para>コンストラクタ</para>
        /// </summary>
        public ErrorItem()
        {
        }
        /// <summary><para>method outline:</para>
        /// <para>コンストラクタ</para>
        /// </summary>
        /// <param name="sSheetName">シート名</param>
        /// <param name="iRow">行</param>
        /// <param name="iCol">列</param>
        /// <param name="sItemName">項目</param>
        /// <param name="sMessage">エラー内容</param>
        public ErrorItem(string sSheetName, int iRow, int iCol, string sItemName, string sMessage)
        {
            SheetName = sSheetName;
            Row = iRow;
            Col = iCol;
            ItemName = sItemName;
            Message = sMessage;
        }
    }

}
