//静态方法,根据指定的映射文件集生成所有克隆家系 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 } }