//静态方法,根据指定的映射文件集生成所有克隆家系
        public static void BuildAndSaveAll(List <string> mapFileCollection)
        {
            //CloneGenealogy.genealogyList=new List<CloneGenealogy>();
            if (!IsMapFileCollectionSuccessive(mapFileCollection))  //判断版本集是否连续
            {
                MessageBox.Show("Map Files NOT Successive! Fix it and Try again!");
                return;
            }

            List <XmlDocument> mapXmlCollection = new List <XmlDocument>();

            //获得存放相邻版本映射信息的XmlDocument对象集合
            foreach (string fileName in mapFileCollection)
            {
                mapXmlCollection.Add(AdjacentVersionMapping.GetXmlDocument(fileName));
            }
            //寻找每个版本中新产生的CG,以其为根建立克隆家系
            int index = -1;
            int id    = 0;

            CloneGenealogy.SingleCgGenealogyList = new List <SingleCgGenealogy>();   //初始化单克隆群家系列表
            foreach (XmlDocument mapXml in mapXmlCollection)
            {
                index++;
                string srcFileName, destFileName;   //保存源和目标版本的CRD文件名(不含路径)
                srcFileName  = mapXml.DocumentElement.ChildNodes[0].InnerText;
                destFileName = mapXml.DocumentElement.ChildNodes[1].InnerText;
                string prev = "0";    //记录前一个被构造的CG的id,避免重复构造(针对分裂的情况)

                #region 如果是第一个mapXml,为源版本中所有克隆群构建以其为根的克隆家系
                if (index == 0)
                {
                    #region 对每个CGMap中的源CG,以其为根构建克隆家系
                    foreach (XmlElement cgMapNode in mapXml.DocumentElement.SelectNodes("CGMap"))
                    {
                        CloneGroupMapping cgMapping = new CloneGroupMapping();
                        cgMapping.CreateCGMapppingFromCGMapNode(cgMapNode);  //根据CGMap元素构造CloneGroupMapping对象
                        if (cgMapping.srcCGInfo.id != prev)
                        {
                            CloneGenealogy cloneGenealogy = new CloneGenealogy();
                            cloneGenealogy.BuildForCG(srcFileName, cgMapping.srcCGInfo, mapXmlCollection, ref id);
                            cloneGenealogy.SaveGenealogyToXml();
                            //CloneGenealogy.genealogyList.Add(cloneGenealogy);
                            prev = cgMapping.srcCGInfo.id;
                        }
                    }
                    #endregion

                    #region 为UnMappedSrcCG中每个CG构建克隆家系
                    if (mapXml.DocumentElement.SelectSingleNode("UnMappedSrcCG") != null)
                    {
                        foreach (XmlElement unMappedSrcCGNode in mapXml.DocumentElement.SelectSingleNode("UnMappedSrcCG").ChildNodes)
                        {
                            CGInfo cgInfo = new CGInfo();
                            cgInfo.id   = unMappedSrcCGNode.GetAttribute("id");
                            cgInfo.size = int.Parse(unMappedSrcCGNode.GetAttribute("size"));
                            CloneGenealogy cloneGenealogy = new CloneGenealogy();
                            //cloneGenealogy.BuildForCG(srcFileName, cgInfo, mapXmlCollection, ref id); //对于第一个版本中的UnMappedSrcCG,不需要此语句
                            SingleCgGenealogy sGenealogy = new CloneEvolutionAnalyzer.SingleCgGenealogy();
                            if (CloneGenealogy.granularity == GranularityType.BLOCKS)
                            {
                                sGenealogy.version = srcFileName.Substring(0, srcFileName.IndexOf("_blocks-"));
                            }
                            else
                            {
                                sGenealogy.version = srcFileName.Substring(0, srcFileName.IndexOf("_functions-"));
                            }
                            sGenealogy.cgInfo = cgInfo;
                            CloneGenealogy.SingleCgGenealogyList.Add(sGenealogy);
                            //cloneGenealogy.SaveGenealogyToXml();
                            //CloneGenealogy.genealogyList.Add(cloneGenealogy);
                        }
                    }
                    #endregion
                }
                #endregion

                #region 对于所有mapXml,为UnMappedDestCG中每个CG构建克隆家系
                if (mapXml.DocumentElement.SelectSingleNode("UnMappedDestCG") != null)
                {
                    foreach (XmlElement unMappedDestCGNode in mapXml.DocumentElement.SelectSingleNode("UnMappedDestCG").ChildNodes)
                    {
                        CGInfo cgInfo = new CGInfo();
                        cgInfo.id   = unMappedDestCGNode.GetAttribute("id");
                        cgInfo.size = int.Parse(unMappedDestCGNode.GetAttribute("size"));
                        CloneGenealogy cloneGenealogy = new CloneGenealogy();
                        cloneGenealogy.BuildForCG(destFileName, cgInfo, mapXmlCollection, ref id);
                        if (cloneGenealogy.evolutionList != null && cloneGenealogy.evolutionList.Count != 0)
                        {
                            cloneGenealogy.SaveGenealogyToXml();
                        }
                        else
                        {
                            SingleCgGenealogy sGenealogy = new CloneEvolutionAnalyzer.SingleCgGenealogy();
                            if (CloneGenealogy.granularity == GranularityType.BLOCKS)
                            {
                                sGenealogy.version = destFileName.Substring(0, destFileName.IndexOf("_blocks-"));
                            }
                            else
                            {
                                sGenealogy.version = destFileName.Substring(0, destFileName.IndexOf("_functions-"));
                            }
                            sGenealogy.cgInfo = cgInfo;
                            CloneGenealogy.SingleCgGenealogyList.Add(sGenealogy);
                        }
                        //CloneGenealogy.genealogyList.Add(cloneGenealogy);
                    }
                }
                #endregion
            }
            SaveSingleCgGenealogiesToXml(); //保存SingleCgGenealogies.xml文件
        }
        //要使用递归么?

        /// <summary>
        /// 生成以指定CG为根的克隆家系
        /// </summary>
        /// <param name="crdFileName">克隆群所在版本的CRD文件名名称(不含路径)</param>
        /// <param name="cgInfo">克隆群信息(id及size)</param>
        /// <param name="mapXmlCollection">所用表示相邻版本版本映射的xml文档集合</param>
        public void BuildForCG(string crdFileName, CGInfo cgInfo, List <XmlDocument> mapXmlCollection, ref int id)
        {
            List <XmlDocument> mapXmlDocs = new List <XmlDocument>();

            #region 获得从crdFileName版本开始的所有映射文档,保存在mapXmlDocs中
            bool flag = false;
            foreach (XmlDocument mapXml in mapXmlCollection)
            {
                if (!flag)
                {
                    if (mapXml.DocumentElement.ChildNodes[0].InnerText == crdFileName)
                    {
                        mapXmlDocs.Add(mapXml);
                        flag = true;
                    }
                }
                else//将从这一版本开始的所有mapXml加入mapXmlDocs中
                {
                    mapXmlDocs.Add(mapXml);
                }
            }
            #endregion

            if (mapXmlDocs.Count == 0)
            {
                return;
            }
            else
            {
                #region 构造克隆家系信息
                string startFile = mapXmlDocs[0].DocumentElement.ChildNodes[0].InnerText;
                bool   atBlocks; //粒度标识,在函数调用时传递粒度信息
                if (startFile.IndexOf("_blocks-") != -1)
                {
                    CloneGenealogy.granularity = GranularityType.BLOCKS;
                    atBlocks          = true;
                    this.startVersion = startFile.Substring(0, startFile.IndexOf("_blocks-"));
                }
                else
                {
                    CloneGenealogy.granularity = GranularityType.FUNCTIONS;
                    atBlocks          = false;
                    this.startVersion = startFile.Substring(0, startFile.IndexOf("_functions-"));
                }
                this.rootCGid      = cgInfo.id; //保存根克隆群在该版本中的id
                this.evolutionList = new List <Evolution>();
                #endregion

                #region 构造进化关系列表
                int           index      = -1;
                int           evoID      = 0;
                int           endIndex   = -1;                  //记录克隆家系停止生长的版本的位置
                List <CGInfo> cgInfoList = new List <CGInfo>(); //cgInfoList用来存放当前所关注的克隆群,可能是多个,因此用列表
                cgInfoList.Add(cgInfo);
                foreach (XmlDocument mapXml in mapXmlDocs)
                {
                    index++;
                    List <CloneGroupMapping> cgMapList = new List <CloneGroupMapping>(); //存放当前两个版本间相关映射集
                    foreach (CGInfo info in cgInfoList)                                  //这个循环是考虑分裂的情况而设
                    {
                        //找出mapXml中以info代表的CG为源的所有映射,多数情况下为1个,少数情况多于一个
                        foreach (XmlElement cgMapNode in mapXml.DocumentElement.SelectNodes("CGMap"))
                        {
                            CloneGroupMapping cgMap = new CloneGroupMapping();
                            cgMap.CreateCGMapppingFromCGMapNode(cgMapNode);
                            if (cgMap.srcCGInfo.id == info.id)
                            {
                                cgMapList.Add(cgMap);
                            }
                        }
                    }
                    string srcFileName  = mapXml.DocumentElement.ChildNodes[0].InnerText;
                    string destFileName = mapXml.DocumentElement.ChildNodes[1].InnerText;
                    cgInfoList = new List <CGInfo>();
                    if (cgMapList.Count != 0)
                    {
                        //为选出的每一个CGMap构造Evolution对象。同时更新cgInfoList
                        foreach (CloneGroupMapping cgMap in cgMapList)
                        {
                            Evolution evolution = new Evolution();
                            evolution.BuildFromCGMap(cgMap, srcFileName, destFileName, ref this.evolutionList, ref evoID, atBlocks);
                            this.evolutionList.Add(evolution);
                            cgInfoList.Add(cgMap.destCGInfo);
                            endIndex = index;   //更新endIndex的值
                        }
                    }
                    else//当cgMapList.Count为0时,说明此克隆家系停止生长
                    {
                        break;
                    }
                }
                #endregion

                #region 补全克隆家系信息
                this.age = endIndex + 2; //计算年龄(年龄指克隆群在几个版本中存在,等于它所发生的进化次数+1)
                if (this.age > 1)        //如果该克隆群寿命大于1(即不是只在单个版本出现)
                {
                    string endFile = mapXmlDocs[endIndex].DocumentElement.ChildNodes[1].InnerText;
                    if (atBlocks)
                    {
                        this.endVersion = endFile.Substring(0, endFile.IndexOf("_blocks-"));
                    }
                    else
                    {
                        this.endVersion = endFile.Substring(0, endFile.IndexOf("_functions-"));
                    }

                    if (this.evolutionList != null && this.evolutionList.Count != 0)
                    {
                        id++;
                        this.ID = id.ToString();
                    }

                    #region 统计各种进化模式出现的次数,保存在evoPatternCount数组中
                    this.evoPatternCount = new int[7] {
                        0, 0, 0, 0, 0, 0, 0
                    };
                    foreach (Evolution evolution in this.evolutionList)
                    {
                        if (evolution.CGMapInfo.pattern.IndexOf("STATIC") != -1)
                        {
                            this.evoPatternCount[0]++;
                        }
                        if (evolution.CGMapInfo.pattern.IndexOf("SAME") != -1)
                        {
                            this.evoPatternCount[1]++;
                        }
                        if (evolution.CGMapInfo.pattern.IndexOf("ADD") != -1)
                        {
                            this.evoPatternCount[2]++;
                        }
                        if (evolution.CGMapInfo.pattern.IndexOf("DELETE") != -1)
                        {
                            this.evoPatternCount[3]++;
                        }
                        if (evolution.CGMapInfo.pattern.IndexOf("CONSISTENTCHANGE") != -1)
                        {
                            this.evoPatternCount[4]++;
                        }
                        if (evolution.CGMapInfo.pattern.IndexOf("INCONSISTENTCHANGE") != -1)
                        {
                            this.evoPatternCount[5]++;
                        }
                        if (evolution.CGMapInfo.pattern.IndexOf("SPLIT") != -1)
                        {
                            this.evoPatternCount[6]++;
                        }
                    }
                    #endregion
                }

                #endregion
            }
        }