diff --git a/pom.xml b/pom.xml index fd96d2c1b52dc03e28d53e6d5c0fcda5f541e11c..10d9fd7fff8d6c024c85c033cce25ebec6299e02 100644 --- a/pom.xml +++ b/pom.xml @@ -22,9 +22,9 @@ - junit - junit - 4.12 + org.junit.jupiter + junit-jupiter-api + 5.8.0-M1 test diff --git a/src/main/java/com/hy/java/uct/cdtocode/CDToCodeTracer.java b/src/main/java/com/hy/java/uct/cdtocode/CDToCodeTracer.java index 2c8fc65173fa29473536ecdb9317e55c662c7745..318502fe4ced9a0ea1e93cc4d35a1daf77082faa 100644 --- a/src/main/java/com/hy/java/uct/cdtocode/CDToCodeTracer.java +++ b/src/main/java/com/hy/java/uct/cdtocode/CDToCodeTracer.java @@ -34,49 +34,47 @@ public class CDToCodeTracer { /* * 1、读取模型信息 */ - // 读取完UML图识别结果后,将实体信息保存在classes_in_CD里 + // 读取完UML图识别结果后,将实体信息保存在classes_in_CD里。形式为 Map classes_in_CD = CDReader.read(cd_dir + "cd-eclipse_jetty.txt"); // 检查结果,可注释掉 // CDReader.check(classes_in_CD); /* * 2、读取文档信息 - * - * 应返回一个Map,保存每份文档及其内容 */ - List doc_ls = new ArrayList<>(); + List doc_dir_ls = new ArrayList<>(); // 在这儿添加多个文件 - doc_ls.add(doc_dir + "basic-architecture.adoc"); - // doc_ls.add(doc_dir + "Jetty10 Operations Guide _ The Eclipse Foundation.txt"); - Map> doc = DocReader.readDocs(doc_ls); + doc_dir_ls.add(doc_dir + "basic-architecture.adoc"); + doc_dir_ls.add(doc_dir + "Jetty10 Operations Guide _ The Eclipse Foundation.txt"); + // 实际使用的Map,保存每份文档地址及其内容 + Map> dir_sentences_map = DocReader.readDocs(doc_dir_ls); /* * 3、读取code path指定的目录下所有java文件 + * + * <类全称(包+类名), java_file_path> */ - Map java_files = CodeReader.read(code_dir + "code path"); + Map classFullName_javaFileDir_map = CodeReader.read(code_dir + "code path"); // 检查结果,可注释掉 - // CodeReader.check(java_files); + // CodeReader.check(classFullName_javaFileDir_map); /* * 4、分析文档信息。实际相当于增加类图中的UMLclass、类本身的内容、类之间关系 * * 核心思想:我们的目标是以模型为准,将模型元素追踪到代码。由于模型元素抽象层次较高,所以直接追踪未必追踪的到,因此需找与模型元素具有关系的其他元素(向下一层层找),将模型元素降维、直至能与代码元素对应上为止。 * - * 比较合理的设计应该是:如果有多份文档,则都读、都分析、且基于概率给出实体间关系。如果只有一份文档,则概率部分只局限于文档内。 + * 以下追踪实际包含3层:图中的类、文档中的实体、代码中的类。 * - * (1)概率部分:基于概率,如果两个实体多次“同时出现在同一句”,则大概率认为这两个实体间有关系。这可以在单文档分析或多文档分析中用。 + * 先将图中的类追踪到包含文档信息的实体(一对多),再将这些实体追踪到代码中的类(也是一对多),所以是“一→多→更多”。 * - * (2)规则部分:①单句:语义分析时,如果一个主语后紧跟了动宾短语,且如果宾语与主语语义相似度较高(但不完全相同),则如果动词是类似继承、实现的字眼,就根据主动或被动语态确定主语与宾语间具有继承、实现等关系。注意主语与宾语可以不是图中元素。②多句:记录单句的关系,然后找关系链,直到找到“两个图中元素通过一连串关系有了关系”为止。 + * 其中,实体间还会根据语义分析得到一些关系 */ - // 如果想对比有没有文档对追踪的影响,则注释掉下一行即可。注意下面几行也要注释和解锁 - Map possible_classes_to_be_mapped_in_doc = DocAnalyzer.analyze(classes_in_CD, doc); + Map classShortName_classObj_mappedByDoc = DocAnalyzer.analyze(classes_in_CD, dir_sentences_map); // 检查结果,可注释掉 - // DocMapper.check(possible_classes_to_be_mapped_in_doc); + // DocAnalyzer.check(classShortName_classObj_mappedByDoc); /* * 5、遍历模型中的实体元素(类或对象),针对每个元素,在code中寻找能匹配的java文件 * * 基于启发式模糊匹配的UML类图与代码追踪方法:首先针对类图中的类和代码中的类,基于类的名称进行字符串完全匹配,从而建立确定的初始追踪;基于同义词、 词缀词典等语料库,定义基于类名称匹配和关联关系的启发式匹配规则,研究基于模糊匹配技术的追踪关系建立方法,基于初始追踪和启发式规则, 对类名不一致的模型和代码元素进行启发式追踪,扩展初始追踪关系。 */ - Map mapped_classes = CodeRelationMapper.map(possible_classes_to_be_mapped_in_doc, java_files); - // 如果想对比有没有文档对追踪的影响,则注释掉上一行,并解开下一行 - // Map mapped_classes = CodeRelationMapper.map(classes_in_CD, java_files); + Map mapped_classes = CodeRelationMapper.map(classShortName_classObj_mappedByDoc, classFullName_javaFileDir_map); // 检查结果,可注释掉 CodeRelationMapper.check(mapped_classes); } diff --git a/src/main/java/com/hy/java/uct/cdtocode/mapper/CodeRelationMapper.java b/src/main/java/com/hy/java/uct/cdtocode/mapper/CodeRelationMapper.java index 77f0689eb3d4e25e51f2f9db52d43021e9a3bfd3..5369adebb0ef050c5fe63c5090802d32d308333e 100644 --- a/src/main/java/com/hy/java/uct/cdtocode/mapper/CodeRelationMapper.java +++ b/src/main/java/com/hy/java/uct/cdtocode/mapper/CodeRelationMapper.java @@ -21,8 +21,8 @@ import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration; import com.github.javaparser.ast.body.FieldDeclaration; import com.github.javaparser.ast.body.MethodDeclaration; import com.github.javaparser.ast.type.ClassOrInterfaceType; -import com.hy.java.uct.util.MappedFile; -import com.hy.java.uct.util.Relation; +import com.hy.java.uct.cdtocode.util.MappedFile; +import com.hy.java.uct.util.ImgRelation; import com.hy.java.uct.util.UMLClass; import com.hy.java.utility.common.Pair; @@ -87,7 +87,7 @@ public class CodeRelationMapper { } } else { // 针对UML_class的每条out_rela - for (Relation out_rela : UML_class.out_relas) { + for (ImgRelation out_rela : UML_class.out_relas) { // 记录其target_class UMLClass target_class = out_rela.target; // 看possible_java_files中的每个文件是否也有out_rela,且文件的out_rela目标文件也在target_class的possible_java_files中 diff --git a/src/main/java/com/hy/java/uct/cdtocode/mapper/DocAnalyzer.java b/src/main/java/com/hy/java/uct/cdtocode/mapper/DocAnalyzer.java index e5bc712e079322722eedcf2106e8571a5f7d592e..4a855b8449ba14c2cc484918938bde6bbedacb82 100644 --- a/src/main/java/com/hy/java/uct/cdtocode/mapper/DocAnalyzer.java +++ b/src/main/java/com/hy/java/uct/cdtocode/mapper/DocAnalyzer.java @@ -1,78 +1,128 @@ package com.hy.java.uct.cdtocode.mapper; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Properties; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.util.stream.Collectors; -import com.hy.java.uct.util.MappedFile; -import com.hy.java.uct.util.Relation; +import org.apache.commons.collections4.SetUtils; + +import com.hy.java.uct.cdtocode.util.Entity; +import com.hy.java.uct.util.EntityRelation; +import com.hy.java.uct.util.ImgRelation; import com.hy.java.uct.util.UMLClass; +import com.hy.java.utility.common.FileEditor; import com.hy.java.utility.common.Pair; -import edu.stanford.nlp.pipeline.CoreDocument; -import edu.stanford.nlp.pipeline.CoreSentence; -import edu.stanford.nlp.pipeline.StanfordCoreNLP; - +/** + * 分析文档信息。实际相当于增加类图中的UMLclass、类本身的内容、类之间关系 + * + * 核心思想:我们的目标是以模型为准,将模型元素追踪到代码。由于模型元素抽象层次较高,所以直接追踪未必追踪的到,因此需找与模型元素具有关系的其他元素(向下一层层找),将模型元素降维、直至能与代码元素对应上为止。 + * + * 比较合理的设计应该是:如果有多份文档,则都读、都分析、且基于概率给出实体间关系。如果只有一份文档,则概率部分只局限于文档内。 + * + * (1)规则部分:①单句:语义分析时,如果一个主语后紧跟了动宾短语,且如果宾语与主语语义相似度较高(但不完全相同),则如果动词是类似继承、实现的字眼,就根据主动或被动语态确定主语与宾语间具有继承、实现等关系。注意主语与宾语可以不是图中元素。②多句:记录单句的关系,然后找关系链,直到找到“两个图中元素通过一连串关系有了关系”为止。 + * + * (2)概率部分:基于概率,如果两个实体多次“同时出现在同一句”,则大概率认为这两个实体间有关系。这可以在单文档分析或多文档分析中用。 + * + * 实际是先用规则去匹配,然后用概率去修正 + */ public class DocAnalyzer { + /** - * 分析文档信息。实际相当于增加类图中的UMLclass、类本身的内容、类之间关系 + * classes_in_CD的形式: * - * 核心思想:我们的目标是以模型为准,将模型元素追踪到代码。由于模型元素抽象层次较高,所以直接追踪未必追踪的到,因此需找与模型元素具有关系的其他元素(向下一层层找),将模型元素降维、直至能与代码元素对应上为止。 + * dir_sentences_map的形式:<文档地址,文档句子列表> + */ + public static Map analyze(Map classes_in_CD, Map> dir_sentences_map) { + // 基于启发式匹配规则(模糊匹配和词性分析)和概率的追踪 + classInCD_to_entInDoc(classes_in_CD, dir_sentences_map); + // 基于规则匹配和概率分析提取类之间关系 + analyze_relationBetweenEnts(classes_in_CD, dir_sentences_map); + return classes_in_CD; + } + + /** + * 基于启发式匹配规则(模糊匹配和词性分析)和概率的追踪 * - * 比较合理的设计应该是:如果有多份文档,则都读、都分析、且基于概率给出实体间关系。如果只有一份文档,则概率部分只局限于文档内。 + * ①基于命名规范的模糊匹配、词性分析,将图中的类Cls_img追踪到文档中的Ent_doc,相似度为Sim(Cls_img,Ent_doc) * - * (1)概率部分:基于概率,如果两个实体多次“同时出现在同一句”,则大概率认为这两个实体间有关系。这可以在单文档分析或多文档分析中用。 + * ②统计多文档中的追踪概率 * - * (2)规则部分:①单句:语义分析时,如果一个主语后紧跟了动宾短语,且如果宾语与主语语义相似度较高(但不完全相同),则如果动词是类似继承、实现的字眼,就根据主动或被动语态确定主语与宾语间具有继承、实现等关系。注意主语与宾语可以不是图中元素。②多句:记录单句的关系,然后找关系链,直到找到“两个图中元素通过一连串关系有了关系”为止。 + * ③利用文档将图中的类Cls_img追踪到文档中的Ent_doc,追踪概率为PE_doc(Cls_img,Ent_doc) */ - public static Map analyze(Map classes_in_CD, Map> doc_map) { - /* - * (1)概率部分 - * - * 基于概率,如果两个实体多次“同时出现在同一句”,则大概率认为这两个实体间有关系。这可以在单文档分析或多文档分析中用。 - */ - Map> class_relas_with_prob_map = new HashMap<>(); - Collection UMLClasses = classes_in_CD.values(); - for (UMLClass UML_class : UMLClasses) { - class_relas_with_prob_map.put(UML_class.getTitle(), null); - } - // ①读取类图classes_in_CD中所有类,形成一个正则表达式,用于匹配文档中每句话、找至少包含某个类的句子 - String regex = getRegexOfClassesExceptOne(classes_in_CD, null); - // ②在设计文档doc中,根据类名查找相关语句,存到sentence_ls中 - List sentence_ls = getSentencesOfAllClasses(doc_map, regex); - // ③计算概率 - // 对每句话进行匹配,记录所有某两个类同时出现的句子 - for (String sentence : sentence_ls) { - if (!sentence.isBlank()) { - // 在每句话中,对每个类做如下检查:看该句话中除了当前类之外、是否还有其他类。如果有,则记录当前类与其他类具有关系 - for (UMLClass UML_class : UMLClasses) { - if (sentence.toLowerCase().contains(UML_class.getTitle().toLowerCase())) { - String regex_without_curr = getRegexOfClassesExceptOne(classes_in_CD, UML_class.getTitle()); - // 找除UML_class的其他类 - Pattern pattern = Pattern.compile(regex_without_curr, Pattern.CASE_INSENSITIVE); - Matcher matcher = pattern.matcher(sentence); - while (matcher.find()) { - String found_class = matcher.group(); - if (!UML_class.getTitle().equals(found_class)) { - // 如果在同一句话中找到了除UML_class的其他类,则将此关系存在class_relas_with_prob_map中 - Map relas_with_other_class = class_relas_with_prob_map.get(UML_class.getTitle()); - if (relas_with_other_class == null) { - relas_with_other_class = new HashMap<>(); - relas_with_other_class.put(found_class, 1.0); - class_relas_with_prob_map.put(UML_class.getTitle(), relas_with_other_class); - } else { - if (!relas_with_other_class.containsKey(found_class)) { - relas_with_other_class.put(found_class, 1.0); - } else { - Double new_count = relas_with_other_class.get(found_class) + 1.0; - relas_with_other_class.put(found_class, new_count); + private static void classInCD_to_entInDoc(Map classes_in_CD, Map> dir_sentences_map) { + Set classShortName_set = classes_in_CD.keySet(); + Set docDir_set = dir_sentences_map.keySet(); + // 如果有文档,则利用文档将图中的类Cls_img追踪到文档中的Ent_doc,追踪概率为PE_doc(Cls_img,Ent_doc) + if (docDir_set.size() > 0) { + /* + * 1、预处理赵子岩的相似词结果 + * + * 将相似词结果整理为clsImg_EntDoc_justZhao,形式为>> + */ + Map>> clsImg_EntDoc_justZhao = new HashMap<>(); + // 先将类图中的类名都填充进去 + for (String class_short_name : classShortName_set) { + clsImg_EntDoc_justZhao.put(class_short_name, new ArrayList<>()); + } + // 对每个相似词文件,遍历其中的<原词,相似词>对,以原词为key保存相似词。相似度为Jaccard相似度 + for (String doc_dir : docDir_set) { + FileEditor simEnts_doc = new FileEditor(doc_dir.substring(0, doc_dir.lastIndexOf(".")) + "-simEnts.txt"); + List similar_names_raw = simEnts_doc.readLines(); + // 遍历相似词文件中的<原词,相似词>对 + for (String clsName_similarName : similar_names_raw) { + String[] pair = clsName_similarName.split(" "); + if (clsImg_EntDoc_justZhao.containsKey(pair[0])) { + clsImg_EntDoc_justZhao.get(pair[0]).add(Pair.createPair(pair[1], sim_ClsImg_EntDoc(pair[0], pair[1]))); + } + } + } + /* + * 2、基于命名规范的模糊匹配、词性分析,将图中的类Cls_img追踪到文档中的Ent_doc,相似度为Sim(Cls_img,Ent_doc) + * + * 此步结束后,classes_in_CD中的每个UMLClass都找到了所有Ent_doc(即mappedEnt_ls已填完)。接下来再计算一下各Ent_doc的频率,即可得从图中的类到文档中的实体的追踪概率PE_doc + */ + // 第一部分:直接添加相似词结果 + for (String class_short_name : classShortName_set) { + UMLClass Cls_img = classes_in_CD.get(class_short_name); + List> Ent_doc_ls = clsImg_EntDoc_justZhao.get(class_short_name); + for (Pair Ent_doc : Ent_doc_ls) { + Entity ent = new Entity(); + ent.parent_class = Cls_img; + ent.name = Ent_doc.getLeft(); + ent.sim_ClsImg_EntDoc = Ent_doc.getRight(); + Cls_img.mappedEnt_ls.add(ent); + Cls_img.mappedEnt_names.add(ent.name); + } + } + // 第二部分:其他相似词算法未能检测出来的相似词,在这里添加 + for (String class_short_name : classShortName_set) { + UMLClass Cls_img = classes_in_CD.get(class_short_name); + // 对每份文档,一句句的去查找 + for (String doc_dir : docDir_set) { + List sentences = dir_sentences_map.get(doc_dir); + for (String sentence : sentences) { + // 对每句话,一个词一个词的去查找 + String[] words = sentence.split(" "); + for (String word : words) { + // 首先这得是个符合Java命名规范的词 + if (word_obeyRules(word)) { + // 如果找到了相似(可以相同)的词,则存在Cls_img.mappedEnt_ls中 + if (word.toLowerCase().contains(class_short_name.toLowerCase())) { + // 注意不要与第一部分的相似词重复 + if (!Cls_img.mappedEnt_names.contains(word)) { + Entity ent = new Entity(); + ent.parent_class = Cls_img; + ent.name = word; + ent.sim_ClsImg_EntDoc = sim_ClsImg_EntDoc(class_short_name, word); + Cls_img.mappedEnt_ls.add(ent); + Cls_img.mappedEnt_names.add(ent.name); } } } @@ -80,169 +130,249 @@ public class DocAnalyzer { } } } - } - // 针对class_relas_with_prob_map中的每个UMLClass,检索所有包含它自己或与其有关系的related_class的句子。然后计算这两个类出现在同一句话里的概率 - Set classes = class_relas_with_prob_map.keySet(); - for (String UML_Class : classes) { - Map related_class_map = class_relas_with_prob_map.get(UML_Class); - if (related_class_map != null) { - // 与UML_Class有关系的related_class们 - Set related_classes = related_class_map.keySet(); - for (String related_class : related_classes) { - // 记录包含UMLClass或related_class的句子总数 - int num_of_sentences_containing_one_of_these_two = 0; - // 从sentence_ls中找所有包含UMLClass或related_class的句子 - String reg_of_these_two = "\\b(" + UML_Class + "|" + related_class + ")\\b"; - Pattern pattern = Pattern.compile(reg_of_these_two, Pattern.CASE_INSENSITIVE); - Matcher matcher = null; - for (String sentence : sentence_ls) { - matcher = pattern.matcher(sentence); - // 若找到某句话至少包含一个类,则计数加一。然后立刻去找下一句话,防止重复计数 - while (matcher.find()) { - num_of_sentences_containing_one_of_these_two++; - break; + /* + * 3、统计多文档中的追踪概率 + */ + int N_doc = docDir_set.size(); + if (N_doc != 0) { + for (String class_short_name : classShortName_set) { + UMLClass Cls_img = classes_in_CD.get(class_short_name); + for (Entity Ent_doc : Cls_img.mappedEnt_ls) { + // 对每个Ent_doc,去所有文档中找它出现的次数。只要在文档中至少出现过一次,就将Ent_doc.F_N加一 + for (String doc_dir : docDir_set) { + List sentences = dir_sentences_map.get(doc_dir); + for (String sentence : sentences) { + if (sentence.contains(Ent_doc.name)) { + Ent_doc.F_N++; + break; + } + } } + // 所有文档找完后,计算F_N/N_doc + Ent_doc.Fn_Ndoc = (double) Ent_doc.F_N / (double) N_doc; } - // 计算它俩出现在同一句话里的概率 - if (num_of_sentences_containing_one_of_these_two != 0) { - double prob = related_class_map.get(related_class) / num_of_sentences_containing_one_of_these_two; - related_class_map.put(related_class, prob); + } + } + /* + * 4、利用文档将图中的类Cls_img追踪到文档中的Ent_doc,追踪概率为PE_doc(Cls_img,Ent_doc) + * + * 有了Fn_Ndoc和sim_ClsImg_EntDoc,即可计算追踪概率PE_doc(Cls_img,Ent_doc)了 + */ + for (String class_short_name : classShortName_set) { + UMLClass Cls_img = classes_in_CD.get(class_short_name); + for (Entity Ent_doc : Cls_img.mappedEnt_ls) { + Ent_doc.PE_doc = Ent_doc.Fn_Ndoc * Ent_doc.sim_ClsImg_EntDoc; + } + } + /* + * 5、最后可能还剩一些类,既没有用其他算法找到相似词、也没在“第二部分”中找到相似词。将这些类直接落成Ent_doc,其名称一致、追踪概率为1 + */ + for (String class_short_name : classShortName_set) { + UMLClass Cls_img = classes_in_CD.get(class_short_name); + if (Cls_img.mappedEnt_ls.size() <= 0) { + Entity ent = new Entity(); + ent.parent_class = Cls_img; + ent.name = Cls_img.getTitle(); + ent.PE_doc = 1.0; + Cls_img.mappedEnt_ls.add(ent); + Cls_img.mappedEnt_names.add(ent.name); + } + } + } + // 如果没有文档,则直接将图中的类Cls_img落到Ent_doc,其名称一致、追踪概率为1 + else { + for (String class_short_name : classShortName_set) { + UMLClass Cls_img = classes_in_CD.get(class_short_name); + Entity ent = new Entity(); + ent.parent_class = Cls_img; + ent.name = Cls_img.getTitle(); + ent.PE_doc = 1.0; + Cls_img.mappedEnt_ls.add(ent); + Cls_img.mappedEnt_names.add(ent.name); + } + } + // 检查PE_doc,可注释掉 + // check_PEdoc(classes_in_CD); + } + + /** + * 基于规则匹配和概率分析提取实体之间关系 + * + * ①杜佳诺的规则部分会直接给出概念间关系R,可信度为R(Ent_doc,Ent'_doc) + * + * ②在多句话、多文档中,计算两个Ent_doc之间具有某类关系的概率(即“交与并”) + * + * ③针对从图中的类Cls_img追踪到的Ent_doc,在文档中提取Ent_doc与其他Ent'_doc之间的关系 + * + * Ent_doc与Ent'_doc具有关系的概率为PR_doc(Ent_doc,Ent'_doc) + */ + private static void analyze_relationBetweenEnts(Map classes_in_CD, Map> dir_sentences_map) { + Set classShortName_set = classes_in_CD.keySet(); + Set docDir_set = dir_sentences_map.keySet(); + /* + * 1、杜佳诺的规则部分会直接给出概念间关系R,可信度为R(Ent_doc,Ent'_doc) + */ + Map> EntDoc_OtherEntDoc_justDu = new HashMap<>(); + // 先将每个类追踪到的Ent_doc都填充进去 + for (String class_short_name : classShortName_set) { + UMLClass Cls_img = classes_in_CD.get(class_short_name); + for (Entity ent : Cls_img.mappedEnt_ls) { + EntDoc_OtherEntDoc_justDu.put(ent.name, new ArrayList<>()); + } + } + // 对每个语义分析文件,遍历其中的<源,目标,关系类型>组,以源为key保存关系。追踪概率为R(Ent_doc,Ent'_doc),默认为1 + for (String doc_dir : docDir_set) { + FileEditor relation_doc = new FileEditor(doc_dir.substring(0, doc_dir.lastIndexOf(".")) + "-relation.txt"); + List relations_raw = relation_doc.readLines(); + // 遍历语义分析文件中的<源,目标,关系类型>组 + for (String relation : relations_raw) { + String[] group = relation.split(" "); + // 对每个组,看其“源”是否属于某个Cls_img追踪到的Ent_doc。如果有,则将该Ent_doc取出,为其添加一条EntityRelation,目标和关系类型分别在组的第二、三项 + for (String class_short_name : classShortName_set) { + // 遍历每个Cls_img,看其追踪到的Ent_doc是否包含“源” + UMLClass Cls_img = classes_in_CD.get(class_short_name); + if (Cls_img.mappedEnt_names.contains(group[0])) { + // 如果找到了,则取出该Ent_doc + for (Entity mappedEnt : Cls_img.mappedEnt_ls) { + // 为该Ent_doc添加一条EntityRelation,目标和关系类型分别在组的第二、三项 + EntityRelation entity_relation = new EntityRelation(); + Entity related_entity = new Entity(); + related_entity.name = group[1]; + entity_relation.related_ent = related_entity; + entity_relation.relation_type = group[2]; + // 追踪概率为R(Ent_doc,Ent'_doc),默认为1 + entity_relation.R_Entdoc_OtherEntdoc = 1.0; + mappedEnt.entRela_ls.add(entity_relation); + } } } - } else { - System.out.println("未在文档中发现" + UML_Class + "与其他类的关系"); } } - // 计算完概率后,针对每个类,放入out_rela中。利用Relation中的ratio暂时记录映射的概率 - for (String uml_class_name : classes) { - // 当前类 - UMLClass UML_class_obj = classes_in_CD.get(uml_class_name); - // 与当前类有关的其他类 - Map related_class_map = class_relas_with_prob_map.get(uml_class_name); - if (related_class_map != null) { - Set related_classes = related_class_map.keySet(); - // 将每个其他类都作为一条新关系存到UML_class_obj.out_relas中 - for (String related_class : related_classes) { - Double curr_prob = related_class_map.get(related_class); - // 如果原图中包含这个“其他类”,则直接用原图中的类对象。否则新建一个类对象 - if (classes_in_CD.containsKey(related_class)) { - UMLClass related_class_obj = classes_in_CD.get(related_class); - Relation new_rela = new Relation(UML_class_obj, related_class_obj); - new_rela.ratio = curr_prob; - UML_class_obj.out_relas.add(new_rela); - related_class_obj.out_relas.add(new_rela); - } else { - UMLClass new_cls = new UMLClass(); - new_cls.setTitle(related_class); - Relation new_rela = new Relation(UML_class_obj, new_cls); - new_rela.ratio = curr_prob; - UML_class_obj.out_relas.add(new_rela); - new_cls.out_relas.add(new_rela); - classes_in_CD.put(related_class, new_cls); + /* + * 2、在多句话、多文档中,计算两个Ent_doc之间具有某类关系的概率(即“交与并”) + */ + // 遍历每个Cls_img的每个Ent_doc的每条关系,利用文档更新其追踪概率 + for (String class_short_name : classShortName_set) { + // 每个Cls_img + UMLClass Cls_img = classes_in_CD.get(class_short_name); + // 每个Ent_doc + for (Entity Ent_doc : Cls_img.mappedEnt_ls) { + // 每条关系 + for (EntityRelation entity_relationship : Ent_doc.entRela_ls) { + Entity related_entity = entity_relationship.related_ent; + // 形成一个正则表达式,用于匹配文档的每句话、查找至少包含这两个词其一的句子 + String regex = "\\b(" + Ent_doc.name + "|" + related_entity.name + ")\\b"; + // 在所有设计文档中,根据名称查找相关语句,存到sentence_ls中 + List sentences_containing_at_least_one_ents = getSentencesMatchingRegex(dir_sentences_map, regex); + int and = 0; + for (String sentence : sentences_containing_at_least_one_ents) { + if (sentence.contains(Ent_doc.name) && sentence.contains(related_entity.name)) { + and++; + } + } + // 利用文档更新其追踪概率 + if (sentences_containing_at_least_one_ents.size() > 0 && and != 0) { + entity_relationship.and_or = (double) and / (double) sentences_containing_at_least_one_ents.size(); } } } } /* - * (2)规则部分 + * 3、针对从图中的类Cls_img追踪到的Ent_doc,在文档中提取Ent_doc与其他Ent'_doc之间的关系 * - * ①单句:语义分析时,如果一个主语后紧跟了动宾短语,且如果宾语与主语语义相似度较高(但不完全相同),则如果动词是类似继承、实现的字眼,就根据主动或被动语态确定主语与宾语间具有继承、实现等关系。注意主语与宾语可以不是图中元素。 - * - * ②多句:记录单句的关系,然后找关系链,直到找到“两个图中元素通过一连串关系有了关系”为止。 + * Ent_doc与Ent'_doc具有关系的概率为PR_doc(Ent_doc,Ent'_doc) */ - // ①单句:分析语句中对“类与其他类的‘继承实现依赖’关系”、“类的功能”、“类具有的属性或方法”的解释。其中,关系应最终被解释为our_rela - Set doc_dirs = doc_map.keySet(); - // 对每个文档单独分析 - for (String doc_dir : doc_dirs) { - List doc_raw_sentences = doc_map.get(doc_dir); - String text = ""; - // 遍历当前文档中的sentence_ls - for (String sentence : doc_raw_sentences) { - text = text + sentence; + for (String class_short_name : classShortName_set) { + // 每个Cls_img + UMLClass Cls_img = classes_in_CD.get(class_short_name); + // 每个Ent_doc + for (Entity Ent_doc : Cls_img.mappedEnt_ls) { + // 每条关系 + for (EntityRelation entity_relationship : Ent_doc.entRela_ls) { + // Ent_doc与Ent'_doc具有关系的概率为PR_doc(Ent_doc,Ent'_doc) + entity_relationship.PR_doc = entity_relationship.and_or * entity_relationship.R_Entdoc_OtherEntdoc; + } } - // 用StanfordCoreNLP为整篇文档标注词性 - // set up pipeline properties - Properties props = new Properties(); - // set the list of annotators to run - props.setProperty("annotators", "tokenize,ssplit,pos,lemma,ner,parse,depparse,coref,kbp"); - // set a property for an annotator, in this case the coref annotator is being set to use the neural algorithm - props.setProperty("coref.algorithm", "neural"); - // build pipeline - StanfordCoreNLP pipeline = new StanfordCoreNLP(props); - // create a document object - CoreDocument document = new CoreDocument(text); - // annnotate the document - if (!document.text().isBlank()) { - pipeline.annotate(document); - /* - * 开始语义分析 - */ - List annotated_sentences = document.sentences(); - // 用正则表达式匹配每句话中被标注出来的各种词,形如“(XXX XXX)”。 - String constituency_regex = "\\([A-Z]+\\s[\\w\\.]+\\)"; - Pattern constituency_pattern = Pattern.compile(constituency_regex); - Matcher constituency_matcher = null; - // 对每句话里的实体名词、实体间关系动词做分析,得到一句话里的实体间关系 - for (CoreSentence annotated_sentence : annotated_sentences) { - - // 做、做、做做;做、做、做做;做、做、做做;做、做1234:下—(下)下下下——// - System.out.println("====================每句话的constituency===================="); - System.out.println(annotated_sentence.text()); - String constituency = annotated_sentence.constituencyParse().toString(); - System.out.println(constituency); - if (!constituency.isBlank()) { - constituency_matcher = constituency_pattern.matcher(constituency); - while (constituency_matcher.find()) { - String matcher_string = constituency_matcher.group(); - System.out.println(matcher_string + "\t" + constituency.indexOf(matcher_string)); + } + /* + * 4、如果原图中的两个类之间就有某种关系,则将此关系记录到两个类的所有Ent_doc中,概率为1 + */ + for (String class_short_name : classShortName_set) { + // 每个Cls_img + UMLClass Cls_img = classes_in_CD.get(class_short_name); + // 遍历每条关系 + for (ImgRelation img_relation : Cls_img.out_relas) { + UMLClass related_Cls_img = img_relation.target; + // 将此关系记录到两个类的所有Ent_doc中 + for (Entity Ent_doc : Cls_img.mappedEnt_ls) { + // 记录此关系:针对当前Ent_doc,检查related_Cls_img追踪的所有related_Ent是否在Ent_doc的关系中。如果有,则概率改为1;如果没有,则添加 + for (Entity related_Ent : related_Cls_img.mappedEnt_ls) { + boolean related = false; + for (EntityRelation entity_relationship : Ent_doc.entRela_ls) { + if (entity_relationship.related_ent.name.equals(related_Ent.name) && entity_relationship.relation_type.equals(img_relation.type)) { + entity_relationship.PR_doc = 1.0; + related = true; + } + } + if (!related) { + // 为该Ent_doc添加数条EntityRelation,每条关系都指向related_Cls_img追踪到的Ent_doc + EntityRelation entity_relation = new EntityRelation(); + entity_relation.related_ent = related_Ent; + entity_relation.relation_type = img_relation.type; + entity_relation.PR_doc = 1.0; + Ent_doc.entRela_ls.add(entity_relation); } } - // 做、做、做做;做、做、做做;做、做、做做;做、做1234:下—(下)下下下——// - } + } + } + // 检查PE_doc,可注释掉 + // check_PRdoc(classes_in_CD); + } - // 上面的循环是对每句话里的实体名词、实体间关系动词做分析,得到一句话里的实体间关系。下面还需对多句话之间的实体间接关系做分析// - // 做、做、做做;做、做、做做;做、做、做做;做、做1234:下—(下)下下下——// - System.out.println("a temp Over"); - // 做、做、做做;做、做、做做;做、做、做做;做、做1234:下—(下)下下下——// + /** + * 检测一个单词是否符合Java类命名规范 + */ + private static boolean word_obeyRules(String word) { + return word.matches("([a-zA-Z_$][a-zA-Z\\d_$]*\\.)*[a-zA-Z_$][a-zA-Z\\d_$]*"); + } - /* - * 语义分析结束 - */ - } + /** + * 计算两个字符串的Jaccard相似度 + */ + private static double sim_ClsImg_EntDoc(String string1, String string2) { + double result = 0.0; + // 两个字符串的字符集 + Set chars_of_string1 = string1.chars().boxed().collect(Collectors.toSet()); + Set chars_of_string2 = string2.chars().boxed().collect(Collectors.toSet()); + // 交集大小 + int intersection = SetUtils.intersection(chars_of_string1, chars_of_string2).size(); + // 并集大小 + int union = SetUtils.union(chars_of_string1, chars_of_string2).size(); + // Jaccard相似度 + if (union != 0) { + result = ((double) intersection) / ((double) union); } - return classes_in_CD; + return result; } /** - * 读取图中所有的类,形成一个正则表达式,用于匹配文档的每句话、查找有这个类的句子 - * - * @param without_this_class 如果是{@code null},则用所有类生成正则表达式。如果不是{@code null},则用除了without_this_class的所有类生成正则表达式 + * 检查PE_doc,即基于启发式匹配规则(模糊匹配和词性分析)和概率的追踪结果 */ - private static String getRegexOfClassesExceptOne(Map classes_in_CD, String without_this_class) { - String result = "\\b("; - // 读取图中所有的类,形成一个正则表达式,用于匹配文档的每句话、查找有这个类的句子 - Set key_set = classes_in_CD.keySet(); - for (String key : key_set) { - UMLClass UML_class = classes_in_CD.get(key); - // 形成一个正则表达式,用于在文档中一句句匹配 - if (without_this_class == null) { - result = result + UML_class.getTitle() + "|"; - } else { - if (!UML_class.getTitle().equals(without_this_class)) { - result = result + UML_class.getTitle() + "|"; - } + private static void check_PEdoc(Map classes_in_CD) { + Set classShortName_set = classes_in_CD.keySet(); + for (String class_short_name : classShortName_set) { + UMLClass Cls_img = classes_in_CD.get(class_short_name); + for (Entity Ent_doc : Cls_img.mappedEnt_ls) { + System.out.println(Cls_img.getTitle() + "追踪到" + Ent_doc.name + "的概率是" + Ent_doc.PE_doc); } } - // 去掉最后一个多余的"|",并收尾 - result = result.substring(0, result.length() - 1) + ")\\b"; - return result; } /** * 在所有设计文档中,根据类名查找相关语句,存到sentence_ls中 */ - private static List getSentencesOfAllClasses(Map> doc_map, String regex) { + private static List getSentencesMatchingRegex(Map> doc_map, String regex) { List res = new ArrayList<>(); Pattern pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE); Matcher matcher = null; @@ -268,23 +398,26 @@ public class DocAnalyzer { return res; } - public static void check(Map mapped_classes) { - Set key_set = mapped_classes.keySet(); - for (String key : key_set) { - System.out.println("=============================="); - UMLClass UML_class = mapped_classes.get(key); - if (UML_class.mapped_java_files.isEmpty()) { - System.out.println(UML_class.getTitle() + "没有映射"); - } else { - for (MappedFile java_file_target_class : UML_class.mapped_java_files) { - if (java_file_target_class.source_or_target_class_with_mapped_file != null) { - System.out.println(UML_class.getTitle() + "(映射为" + java_file_target_class.java_file_dir + ")" + java_file_target_class.relation_type + "了" + java_file_target_class.source_or_target_class_with_mapped_file.getLeft().getTitle() + "(映射为" - + java_file_target_class.source_or_target_class_with_mapped_file.getRight() + ")"); - } else { - System.out.println(UML_class.getTitle() + "(映射为" + java_file_target_class.java_file_dir + ")"); - } + /** + * 检查PR_doc,即基于规则匹配和概率分析提取实体之间关系的追踪结果 + */ + private static void check_PRdoc(Map classes_in_CD) { + Set classShortName_set = classes_in_CD.keySet(); + for (String class_short_name : classShortName_set) { + // 每个Cls_img + UMLClass Cls_img = classes_in_CD.get(class_short_name); + // 每个Ent_doc + for (Entity Ent_doc : Cls_img.mappedEnt_ls) { + // 每条关系 + for (EntityRelation entity_relationship : Ent_doc.entRela_ls) { + System.out.println(class_short_name + "追踪到的" + Ent_doc.name + "与" + entity_relationship.related_ent.name + "有" + entity_relationship.PR_doc + "的概率具有" + entity_relationship.relation_type + "关系"); } } } } + + public static void check(Map mapped_classes) { + check_PEdoc(mapped_classes); + check_PRdoc(mapped_classes); + } } diff --git a/src/main/java/com/hy/java/uct/cdtocode/reader/CDReader.java b/src/main/java/com/hy/java/uct/cdtocode/reader/CDReader.java index 389957a899cdd2ef91da7887e950aa9f607a4bc4..f39bc272eefd50c9abeebac4d5c4075e1616ce13 100644 --- a/src/main/java/com/hy/java/uct/cdtocode/reader/CDReader.java +++ b/src/main/java/com/hy/java/uct/cdtocode/reader/CDReader.java @@ -4,7 +4,7 @@ import java.util.HashMap; import java.util.Map; import java.util.Set; -import com.hy.java.uct.util.Relation; +import com.hy.java.uct.util.ImgRelation; import com.hy.java.uct.util.UMLClass; import com.hy.java.utility.common.FileEditor; @@ -48,7 +48,7 @@ public class CDReader { // 关系用“¥”隔开 String[] out_relas = class_info_strs[3].split("¥"); for (String out_rela_str : out_relas) { - Relation relation = new Relation(); + ImgRelation relation = new ImgRelation(); String[] rela_info = out_rela_str.split("%"); relation.source = result.get(rela_info[0].substring(0, rela_info[0].length() - 1)); relation.target = result.get(rela_info[1].substring(0, rela_info[1].length() - 1)); @@ -62,7 +62,7 @@ public class CDReader { // 关系用“¥”隔开 String[] in_relas = class_info_strs[4].split("¥"); for (String in_rela_str : in_relas) { - Relation relation = new Relation(); + ImgRelation relation = new ImgRelation(); String[] rela_info = in_rela_str.split("%"); relation.source = result.get(rela_info[0].substring(0, rela_info[0].length() - 1)); relation.target = result.get(rela_info[1].substring(0, rela_info[1].length() - 1)); @@ -81,10 +81,10 @@ public class CDReader { System.out.println("类名:" + uc.getTitle()); System.out.println("属性:" + uc.getAttrisStr()); System.out.println("方法:" + uc.getMethodsStr()); - for (Relation r : uc.out_relas) { + for (ImgRelation r : uc.out_relas) { System.out.println("出关:" + r.source.getTitle() + "→" + r.target.getTitle() + "是" + r.type); } - for (Relation r : uc.in_relas) { + for (ImgRelation r : uc.in_relas) { System.out.println("入关:" + r.source.getTitle() + "→" + r.target.getTitle() + "是" + r.type); } System.out.println("======================="); diff --git a/src/main/java/com/hy/java/uct/cdtocode/util/Entity.java b/src/main/java/com/hy/java/uct/cdtocode/util/Entity.java new file mode 100644 index 0000000000000000000000000000000000000000..081f182b3241a4afe0fd21fc1aa2f591c036a574 --- /dev/null +++ b/src/main/java/com/hy/java/uct/cdtocode/util/Entity.java @@ -0,0 +1,20 @@ +package com.hy.java.uct.cdtocode.util; + +import java.util.ArrayList; +import java.util.List; + +import com.hy.java.uct.util.EntityRelation; +import com.hy.java.uct.util.UMLClass; + +public class Entity { + public UMLClass parent_class; + public String name; + // 基于启发式匹配规则(模糊匹配和词性分析)和概率的追踪 + public double sim_ClsImg_EntDoc; + public int F_N; + public double Fn_Ndoc; + public double PE_doc; + // 基于规则匹配和概率分析提取实体之间关系 + public List entRela_ls = new ArrayList<>(); + // Entity往下会追到代码 +} diff --git a/src/main/java/com/hy/java/uct/util/MappedFile.java b/src/main/java/com/hy/java/uct/cdtocode/util/MappedFile.java similarity index 74% rename from src/main/java/com/hy/java/uct/util/MappedFile.java rename to src/main/java/com/hy/java/uct/cdtocode/util/MappedFile.java index c41bb2184b6dc1a1ee5aa401df5c01570b9746d6..bfff30af37546b42ebed9a14ecc4365fb1892e51 100644 --- a/src/main/java/com/hy/java/uct/util/MappedFile.java +++ b/src/main/java/com/hy/java/uct/cdtocode/util/MappedFile.java @@ -1,5 +1,6 @@ -package com.hy.java.uct.util; +package com.hy.java.uct.cdtocode.util; +import com.hy.java.uct.util.UMLClass; import com.hy.java.utility.common.Pair; /** @@ -10,7 +11,7 @@ import com.hy.java.utility.common.Pair; public class MappedFile { // java文件地址 public String java_file_dir = null; - // <某种关系的目标或源UMLClass, 该关系下目标或源UMLClass映射的文件> + // <某种关系的目标或源UMLClass', 该关系下UMLClass'映射的文件> public Pair source_or_target_class_with_mapped_file = null; // 关系类型 public String relation_type = null; diff --git a/src/main/java/com/hy/java/uct/umlrecog/ClassDiagramRecognizer.java b/src/main/java/com/hy/java/uct/umlrecog/ClassDiagramRecognizer.java index 64d4d3eb20dd71e91beec37017693aa7dc253fc2..5af90cf5621ac674d5c2c596435496c6d3a97b15 100644 --- a/src/main/java/com/hy/java/uct/umlrecog/ClassDiagramRecognizer.java +++ b/src/main/java/com/hy/java/uct/umlrecog/ClassDiagramRecognizer.java @@ -7,7 +7,7 @@ import org.opencv.core.Mat; import com.hy.java.uct.umlrecog.cddetector.ClassDetector; import com.hy.java.uct.umlrecog.cddetector.ClassRelationDetector; -import com.hy.java.uct.util.Relation; +import com.hy.java.uct.util.ImgRelation; import com.hy.java.uct.util.UMLClass; import com.hy.java.utility.common.FileEditor; import com.hy.java.utility.common.Pair; @@ -57,11 +57,11 @@ public class ClassDiagramRecognizer { fe.write(UML_class.getTitle() + "@", true); fe.write(UML_class.getAttrisStr() + "@", true); fe.write(UML_class.getMethodsStr() + "@", true); - for (Relation out_rel : UML_class.out_relas) { + for (ImgRelation out_rel : UML_class.out_relas) { fe.write(out_rel.source.getTitle() + "%" + out_rel.target.getTitle() + "%" + out_rel.type, true); fe.write("¥", true); } - for (Relation in_rel : UML_class.in_relas) { + for (ImgRelation in_rel : UML_class.in_relas) { fe.write(in_rel.source.getTitle() + "%" + in_rel.target.getTitle() + "%" + in_rel.type, true); fe.write("¥", true); } diff --git a/src/main/java/com/hy/java/uct/umlrecog/cddetector/ClassRelationDetector.java b/src/main/java/com/hy/java/uct/umlrecog/cddetector/ClassRelationDetector.java index 5903f36dee7637f98c53ad6f7abee44ae8bba95c..5724172a4669eae4466aa548a5f7f97a574d9e3f 100644 --- a/src/main/java/com/hy/java/uct/umlrecog/cddetector/ClassRelationDetector.java +++ b/src/main/java/com/hy/java/uct/umlrecog/cddetector/ClassRelationDetector.java @@ -19,7 +19,7 @@ import org.opencv.imgproc.Imgproc; import com.hy.java.uct.umlrecog.util.ImgProcessor; import com.hy.java.uct.umlrecog.util.Line; import com.hy.java.uct.umlrecog.util.PolygonalLine; -import com.hy.java.uct.util.Relation; +import com.hy.java.uct.util.ImgRelation; import com.hy.java.uct.util.UMLClass; import com.hy.java.utility.common.Pair; @@ -37,15 +37,15 @@ public class ClassRelationDetector { public void recog() { // 先检测实线。检测结果需借助类的位置关系、去除“单纯的线” - Set solid_lines = detectLines(classes_in_cd, 0.0504, true); + Set solid_lines = detectLines(classes_in_cd, 0.0504, true); // 再检测虚线。虚线检测除了间隔设置与实线不同外,其他完全一样 - Set dash_lines = detectLines(classes_in_cd, 0.0504, false); + Set dash_lines = detectLines(classes_in_cd, 0.0504, false); // 再检测关系类型。由于会遍历所有关系,所以顺便将关系存在classes_in_cd中每个UMLClass的关系列表中 result = detectRelationType(classes_in_cd, solid_lines, dash_lines, 0.0001); } - private Set detectLines(Pair> classes_in_cd, double ratio, boolean detect_solid) { - Set result = new HashSet<>(); + private Set detectLines(Pair> classes_in_cd, double ratio, boolean detect_solid) { + Set result = new HashSet<>(); if (detect_solid) { System.out.println("开始识别" + cd_path + "中的实线"); } else { @@ -139,7 +139,7 @@ public class ClassRelationDetector { * 针对每条候选关系线,计算每个类方框的4根边框线,看哪个边框线与当前候选关系线相交(允许一定像素的误差),则认为这条线确实是关系线,且属于相交的类 */ for (PolygonalLine pl : poly_lines) { - Relation rela = new Relation(pl); + ImgRelation rela = new ImgRelation(pl); // 对pl.pt1和pl.pt2,需要将其延直线方向延长一点,检查延长后的端点。 for (UMLClass uml_class : UML_classes) { // 检查延长后的端点 @@ -165,7 +165,7 @@ public class ClassRelationDetector { */ if (detect_solid) { // 实线识别结果 - for (Relation rela : result) { + for (ImgRelation rela : result) { // 两端坐标 // System.out.println("(" + rela.poly_line.pt1.x + ", " + rela.poly_line.pt1.y + ")" + "(" + rela.poly_line.pt2.x + ", " + rela.poly_line.pt2.y + // ")"); @@ -180,7 +180,7 @@ public class ClassRelationDetector { System.out.println("完成对" + cd_path + "中的实线识别,共" + result.size() + "条"); } else { // 虚线识别结果 - for (Relation rela : result) { + for (ImgRelation rela : result) { // 两端坐标 // System.out.println("(" + rela.poly_line.pt1.x + ", " + rela.poly_line.pt1.y + ")" + "(" + rela.poly_line.pt2.x + ", " + rela.poly_line.pt2.y + // ")"); @@ -368,7 +368,7 @@ public class ClassRelationDetector { * @param dash_lines * @return */ - private Pair> detectRelationType(Pair> classes_in_cd, Set solid_lines, Set dash_lines, double ratio) { + private Pair> detectRelationType(Pair> classes_in_cd, Set solid_lines, Set dash_lines, double ratio) { System.out.println("开始识别" + cd_path + "中所有关系符号"); Mat cls_diagram = classes_in_cd.getLeft(); Mat origin_cls_diagram = Imgcodecs.imread(cd_path, Imgcodecs.IMREAD_GRAYSCALE); @@ -404,7 +404,7 @@ public class ClassRelationDetector { // 如果包络矩形包含某一条关系线的某一端,则检测该矩形内的符号 // 对于虚线,由于只可能是实现或生命线,所以只需要知道是否包含即可,不用检测矩形内部图形。belong_to_dash_rela为true表示当前关系符号属于某条虚线关系线 boolean belong_to_dash_rela = false; - for (Relation dash_rela : dash_lines) { + for (ImgRelation dash_rela : dash_lines) { // 如果dash_rela.source_pt_index != -1,则说明该dash_rela已经与某一包络矩形检测并对应上了,则跳过 if (dash_rela.source_pt_index != -1) { continue; @@ -455,7 +455,7 @@ public class ClassRelationDetector { // 如果该关系符号不属于任何虚线关系,则检测其是否属于某实线关系 if (!belong_to_dash_rela) { // 对于实线,需检测矩形内部图形,识别继承、聚合 - for (Relation solid_rela : solid_lines) { + for (ImgRelation solid_rela : solid_lines) { // 如果solid_line.source_pt_index != -1,则说明该solid_line已经与某一包络矩形检测并对应上了,则跳过 if (solid_rela.source_pt_index != -1) { continue; diff --git a/src/main/java/com/hy/java/uct/util/EntityRelation.java b/src/main/java/com/hy/java/uct/util/EntityRelation.java new file mode 100644 index 0000000000000000000000000000000000000000..d796d6d9cb4f90b2a103e5e7f85c3d3f248daa8f --- /dev/null +++ b/src/main/java/com/hy/java/uct/util/EntityRelation.java @@ -0,0 +1,11 @@ +package com.hy.java.uct.util; + +import com.hy.java.uct.cdtocode.util.Entity; + +public class EntityRelation { + public Entity related_ent = null; + public String relation_type = ""; + public double R_Entdoc_OtherEntdoc = 0.0; + public double and_or = 0.001; + public double PR_doc = 0.0; +} diff --git a/src/main/java/com/hy/java/uct/util/Relation.java b/src/main/java/com/hy/java/uct/util/ImgRelation.java similarity index 74% rename from src/main/java/com/hy/java/uct/util/Relation.java rename to src/main/java/com/hy/java/uct/util/ImgRelation.java index 05cbf8a06af88d6e174c62f9e7e206efb4cfd011..d8cd2286a71ab933398f3f09050e0dcddc0e4469 100644 --- a/src/main/java/com/hy/java/uct/util/Relation.java +++ b/src/main/java/com/hy/java/uct/util/ImgRelation.java @@ -2,7 +2,7 @@ package com.hy.java.uct.util; import com.hy.java.uct.umlrecog.util.PolygonalLine; -public class Relation { +public class ImgRelation { public PolygonalLine poly_line; public UMLClass source; public UMLClass target; @@ -18,14 +18,14 @@ public class Relation { */ public double ratio = 0.0; - public Relation(PolygonalLine poly_line) { + public ImgRelation(PolygonalLine poly_line) { this.poly_line = poly_line; } - public Relation() { + public ImgRelation() { } - public Relation(UMLClass source, UMLClass target) { + public ImgRelation(UMLClass source, UMLClass target) { this.source = source; this.target = target; } diff --git a/src/main/java/com/hy/java/uct/util/UMLClass.java b/src/main/java/com/hy/java/uct/util/UMLClass.java index 8c459f920cec43f350c486b543641b1c1b7a2528..475cc3ac950697259aec58d62c0ef133f768487d 100644 --- a/src/main/java/com/hy/java/uct/util/UMLClass.java +++ b/src/main/java/com/hy/java/uct/util/UMLClass.java @@ -1,8 +1,12 @@ package com.hy.java.uct.util; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; +import java.util.Set; +import com.hy.java.uct.cdtocode.util.Entity; +import com.hy.java.uct.cdtocode.util.MappedFile; import com.hy.java.uct.umlrecog.util.Rectangle; public class UMLClass { @@ -24,19 +28,23 @@ public class UMLClass { /** * 从该class出发的关系 */ - public List out_relas = new ArrayList<>(); + public List out_relas = new ArrayList<>(); /** * 指向该class的关系 */ - public List in_relas = new ArrayList<>(); + public List in_relas = new ArrayList<>(); /** - * 从文档中得到的该类的功能性解释。用于与代码中类的注释进行语义对比 + * 所有doc中名称与this.title相似的名词 + *

+ * 采用基于启发式匹配规则(模糊匹配和词性分析)和概率的追踪 */ - public String description = null; + public List mappedEnt_ls = new ArrayList<>(); + // 方便查找用的 + public Set mappedEnt_names = new HashSet<>(); /** - * java_files中类全称的类名与其相同的java文件 + * java_files中类名与this.title相似的java文件 * * 从这些文件中去找真正的映射(由于抽象层次不同,所以可能不止一个java文件是真正的映射)。寻找时要参考关系网 */ diff --git a/src/main/resources/cdtocode/doc/Jetty10 Operations Guide _ The Eclipse Foundation-relation.txt b/src/main/resources/cdtocode/doc/Jetty10 Operations Guide _ The Eclipse Foundation-relation.txt new file mode 100644 index 0000000000000000000000000000000000000000..116a499d744c8ea49fba7be0b1947a520604e3a5 --- /dev/null +++ b/src/main/resources/cdtocode/doc/Jetty10 Operations Guide _ The Eclipse Foundation-relation.txt @@ -0,0 +1,2 @@ +Eclipse License 依赖 +Connector AbstractConnector 实现 \ No newline at end of file diff --git a/src/main/resources/cdtocode/doc/Jetty10 Operations Guide _ The Eclipse Foundation-simEnts.txt b/src/main/resources/cdtocode/doc/Jetty10 Operations Guide _ The Eclipse Foundation-simEnts.txt new file mode 100644 index 0000000000000000000000000000000000000000..86c665a2f7c74d0426c8394c47869527b1c0f795 --- /dev/null +++ b/src/main/resources/cdtocode/doc/Jetty10 Operations Guide _ The Eclipse Foundation-simEnts.txt @@ -0,0 +1,2 @@ +License EclipseLicense +Connector ConnectorFactory \ No newline at end of file diff --git a/src/main/resources/cdtocode/doc/basic-architecture-relation.txt b/src/main/resources/cdtocode/doc/basic-architecture-relation.txt new file mode 100644 index 0000000000000000000000000000000000000000..af0c4e65c632e23e18708c5c3460c34535fe098d --- /dev/null +++ b/src/main/resources/cdtocode/doc/basic-architecture-relation.txt @@ -0,0 +1,2 @@ +Eclipse License 继承 +Handler AbstractHandler 继承 \ No newline at end of file diff --git a/src/main/resources/cdtocode/doc/basic-architecture-simEnts.txt b/src/main/resources/cdtocode/doc/basic-architecture-simEnts.txt new file mode 100644 index 0000000000000000000000000000000000000000..490efa0945e68bb01b3ea0391ab7225315830511 --- /dev/null +++ b/src/main/resources/cdtocode/doc/basic-architecture-simEnts.txt @@ -0,0 +1,3 @@ +License EclipseLicense +Connector Connection +Connector ServerConnector \ No newline at end of file diff --git a/src/test/java/com/hy/java/uct/cdtocode/CodeRelationMapperTest.java b/src/test/java/com/hy/java/uct/cdtocode/CodeRelationMapperTest.java index 4f6e3a4bf11f1fae6bd1e1bff42143f331228bff..34855befd87352a1c2daa148cc408872b494ca80 100644 --- a/src/test/java/com/hy/java/uct/cdtocode/CodeRelationMapperTest.java +++ b/src/test/java/com/hy/java/uct/cdtocode/CodeRelationMapperTest.java @@ -24,8 +24,8 @@ import com.github.javaparser.ast.body.MethodDeclaration; import com.github.javaparser.ast.type.ClassOrInterfaceType; import com.hy.java.uct.cdtocode.reader.CDReader; import com.hy.java.uct.cdtocode.reader.CodeReader; -import com.hy.java.uct.util.MappedFile; -import com.hy.java.uct.util.Relation; +import com.hy.java.uct.cdtocode.util.MappedFile; +import com.hy.java.uct.util.ImgRelation; import com.hy.java.uct.util.UMLClass; import com.hy.java.utility.common.Pair; @@ -83,7 +83,7 @@ public class CodeRelationMapperTest { } } else { // 针对UML_class的每条out_rela - for (Relation out_rela : UML_class.out_relas) { + for (ImgRelation out_rela : UML_class.out_relas) { // 记录其target_class UMLClass target_class = out_rela.target; // 看possible_java_files中的每个文件是否也有out_rela,且文件的out_rela目标文件也在target_class的possible_java_files中 diff --git a/src/test/java/com/hy/java/uct/cdtocode/DocAnalyzerTest.java b/src/test/java/com/hy/java/uct/cdtocode/DocAnalyzerTest.java index d66499a45b7a36e0883cb03a11300553a68579d3..fa3502905072462bc82fadb07c4552298b3f4624 100644 --- a/src/test/java/com/hy/java/uct/cdtocode/DocAnalyzerTest.java +++ b/src/test/java/com/hy/java/uct/cdtocode/DocAnalyzerTest.java @@ -8,7 +8,7 @@ import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; -import org.junit.Test; +import org.junit.jupiter.api.Test; import com.hy.java.uct.cdtocode.reader.CDReader; import com.hy.java.uct.cdtocode.reader.DocReader; @@ -29,11 +29,25 @@ public class DocAnalyzerTest { */ private static final String doc_dir = System.getProperty("user.dir") + "\\src\\main\\resources\\cdtocode\\doc\\"; + @Test + public void regexTest() { + boolean res = false; + Pattern pattern = Pattern.compile("([a-zA-Z_$][a-zA-Z\\d_$]*\\.)*[a-zA-Z_$][a-zA-Z\\d_$]*", Pattern.CASE_INSENSITIVE); + Matcher matcher = null; + // 检测 + matcher = pattern.matcher(":oejs.AbstractConnector:main:"); + ":oejs.AbstractConnector:main:".matches("([a-zA-Z_$][a-zA-Z\\d_$]*\\.)*[a-zA-Z_$][a-zA-Z\\d_$]*"); + while (matcher.find()) { + res = true; + break; + } + System.out.println(":oejs.AbstractConnector:main:".matches("([a-zA-Z_$][a-zA-Z\\d_$]*\\.)*[a-zA-Z_$][a-zA-Z\\d_$]*")); + } + /* * 测试规则部分 * - * ①单句:语义分析时,如果一个主语后紧跟了动宾短语,且如果宾语与主语语义相似度较高(但不完全相同),则如果动词是类似继承、实现的字眼, - * 就根据主动或被动语态确定主语与宾语间具有继承、实现等关系。注意主语与宾语可以不是图中元素。 + * ①单句:语义分析时,如果一个主语后紧跟了动宾短语,且如果宾语与主语语义相似度较高(但不完全相同),则如果动词是类似继承、实现的字眼, 就根据主动或被动语态确定主语与宾语间具有继承、实现等关系。注意主语与宾语可以不是图中元素。 * * ②多句:记录单句的关系,然后找关系链,直到找到“两个图中元素通过一连串关系有了关系”为止。 */ @@ -122,9 +136,7 @@ public class DocAnalyzerTest { /* * 3、分析文档信息。实际相当于增加类图中的UMLclass、类本身的内容、类之间关系 * - * (2)规则部分:①单句:语义分析时,如果一个主语后紧跟了动宾短语,且如果宾语与主语语义相似度较高(但不完全相同),则如果动词是类似继承、实现的字眼, - * 就根据主动或被动语态确定主语与宾语间具有继承、实现等关系。注意主语与宾语可以不是图中元素。②多句:记录单句的关系,然后找关系链,直到找到“ - * 两个图中元素通过一连串关系有了关系”为止。 + * (2)规则部分:①单句:语义分析时,如果一个主语后紧跟了动宾短语,且如果宾语与主语语义相似度较高(但不完全相同),则如果动词是类似继承、实现的字眼, 就根据主动或被动语态确定主语与宾语间具有继承、实现等关系。注意主语与宾语可以不是图中元素。②多句:记录单句的关系,然后找关系链,直到找到“ 两个图中元素通过一连串关系有了关系”为止。 */ DocAnalyzerTest.semanticAnalysisByRules(classes_in_CD, doc); }