private static ExternalConnection ParseExternalConnection(string line)
        {
            if (string.IsNullOrEmpty(line) || !line.EndsWith("*)"))
            {
                return(null);
            }

            string             name     = string.Empty;
            string             dataType = string.Empty;
            ExternalConnection variable = null;

            int nameStart;
            int typeStart;
            int typeEnd;

            if (line.StartsWith(sInvalidGlobVarPrefix))
            {
                //非法
                nameStart = sInvalidGlobVarPrefix.Length;
                typeStart = line.IndexOf(':', nameStart) + 1;
                if (typeStart <= nameStart)
                {
                    return(null);
                }
                name = line.Substring(nameStart, typeStart - nameStart - 1);

                typeEnd = line.IndexOf(';', typeStart);
                if (typeEnd <= typeStart)
                {
                    return(null);
                }
                dataType = line.Substring(typeStart, typeEnd - typeStart);

                variable            = new ExternalConnection(name, ViDataType.GetDataType(dataType));
                variable.ValidState = false;
            }
            else
            {
                // 合法
                nameStart = 0;
                typeStart = line.IndexOf(':') + 1;
                if (typeStart <= nameStart)
                {
                    return(null);
                }
                name = line.Substring(nameStart, typeStart - nameStart - 1);

                typeEnd = line.IndexOf(';', typeStart);
                if (typeEnd <= typeStart)
                {
                    return(null);
                }
                dataType = line.Substring(typeStart, typeEnd - typeStart);

                variable            = new ExternalConnection(name, ViDataType.GetDataType(dataType));
                variable.ValidState = true;
            }

            return(variable);
        }
        protected override bool OnVariableLine(string line)
        {
            int i = line.IndexOf("Next Index:");

            if (i >= 0)
            {
                i = line.IndexOf("(", i);
                int    j     = line.IndexOf(")", i);
                string index = line.Substring(i + 1, j - i - 1);
                if (j > i)
                {
                    try
                    {
                        this.NextVariableID = int.Parse(index);
                    }
                    catch (System.Exception ee)
                    {
                        Trace.WriteLine("### [" + ee.Source + "] Exception: " + ee.Message);
                        Trace.WriteLine("### " + ee.StackTrace);
                    }
                }
            }
            else
            {
                ExternalConnection connType = ExternalConnection.Parse(line, ViTypeCreation.Create);
                if (connType == null || connType.Type == null)
                {
                    return(false);
                }

                this.AddChild(connType);
            }

            return(true);
        }
        /// <summary>
        /// 将文本行描述的变量定义,解析为变量对象。
        /// </summary>
        /// <param name="line">变量的文本行描述</param>
        /// <param name="typeCreation">自动创建变量数据类型的方式</param>
        /// <returns>变量对象,null 表示解析失败</returns>
        public static new ExternalConnection Parse(string line, ViTypeCreation typeCreation)
        {
            ExternalConnection variable = ParseExternalConnection(line);

            if (variable == null)
            {
                return(null);
            }

            int targetPathStart      = line.IndexOf(sTargetPathIdentifier);
            int sourcePathStart      = line.IndexOf(sSourcePathIdentifier);
            int targetTaskStart      = line.IndexOf(sTargetTaskTypeIdentifier);
            int sourceTaskStart      = line.IndexOf(sSourceTaskTypeIdentifier);
            int targetBlockModeStart = line.IndexOf(sTargetBlockModeIdentifier);
            int sourceBlockModeStart = line.IndexOf(sSourceBlockModeIdentifier);
            int uuidStart            = line.IndexOf(sUuidIdentifier);
            int endIndex             = line.IndexOf("*)");

            //targetPath
            if (sourcePathStart > targetPathStart + sTargetPathIdentifier.Length)
            {
                variable.TargetPath = line.Substring(targetPathStart + sTargetPathIdentifier.Length, sourcePathStart - targetPathStart - sTargetPathIdentifier.Length).Trim();
            }
            //sourcePath
            if (targetTaskStart > sourcePathStart + sSourcePathIdentifier.Length)
            {
                variable.SourcePath = line.Substring(sourcePathStart + sSourcePathIdentifier.Length, targetTaskStart - sourcePathStart - sSourcePathIdentifier.Length).Trim();
            }
            //targetTask
            if (sourceTaskStart > targetTaskStart + sTargetTaskTypeIdentifier.Length)
            {
                variable.TargetTaskType = line.Substring(targetTaskStart + sTargetTaskTypeIdentifier.Length, sourceTaskStart - targetTaskStart - sTargetTaskTypeIdentifier.Length).Trim();
            }
            //sourceTask
            if (targetBlockModeStart > sourceTaskStart + sSourceTaskTypeIdentifier.Length)
            {
                variable.SourceTaskType = line.Substring(sourceTaskStart + sSourceTaskTypeIdentifier.Length, targetBlockModeStart - sourceTaskStart - sSourceTaskTypeIdentifier.Length).Trim();
            }
            //targetBlockMode
            if (sourceBlockModeStart > targetBlockModeStart + sTargetBlockModeIdentifier.Length)
            {
                variable.TargetBlockModes = line.Substring(targetBlockModeStart + sTargetBlockModeIdentifier.Length, sourceBlockModeStart - targetBlockModeStart - sTargetBlockModeIdentifier.Length).Trim();
            }
            //sourceBlockMode
            if (uuidStart > sourceBlockModeStart + sSourceBlockModeIdentifier.Length)
            {
                variable.SourceBlockModes = line.Substring(sourceBlockModeStart + sSourceBlockModeIdentifier.Length, uuidStart - sourceBlockModeStart - sSourceBlockModeIdentifier.Length).Trim();
            }
            //UUID
            if (endIndex > uuidStart + sUuidIdentifier.Length)
            {
                variable.UUID = line.Substring(uuidStart + sUuidIdentifier.Length, endIndex - uuidStart - sUuidIdentifier.Length).Trim();
            }

            return(variable);
        }
        /// <summary>
        /// 创建一个变量。变量名称和UUID会自动生成。
        /// </summary>
        /// <param name="dataType">变量类型</param>
        /// <returns>创建的变量。</returns>
        /// @infor 创建的变量已经被加入到 Children 数组中。
        public ExternalConnection CreateVariable(ViDataType dataType)
        {
            // 生成变量名称
            string             name     = this.NextVariableName();
            ExternalConnection variable = new ExternalConnection(name, dataType);

            // 生成变量 UUID
            variable.UUID = ViGuid.NewGuid();

            // 将变量加入 Children 数组
            this.AddChild(variable);

            // 大功告成
            return(variable);
        }
        /// <summary>
        /// 对给定管脚路径中的 Program 部分进行重命名操作。
        /// </summary>
        private string RenameProgramInPath(string oldName, string newName, string path)
        {
            if (string.IsNullOrEmpty(oldName) || string.IsNullOrEmpty(newName) || string.IsNullOrEmpty(path))
            {
                return(path);
            }
            if (ExternalConnection.RetrievePlanName(path) != oldName)
            {
                return(path);
            }

            int firstPathSeparator  = path.IndexOf(ViNamedObject.PathSeperator);
            int secondPathSeparator = path.IndexOf(ViNamedObject.PathSeperator, firstPathSeparator + 1);

            string programName = path.Substring(firstPathSeparator + 1, secondPathSeparator - firstPathSeparator - 1);

            programName = programName.Replace(oldName, newName);

            return(string.Format("{0}{1}{2}", path.Substring(0, firstPathSeparator + 1), programName, path.Substring(secondPathSeparator)));
        }