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 b9bae27a7cb03e1d9730416a6f23f36881b70ce6..802a7dc1d6a31c9831b636ca3f1ba85247243db6 100644 --- a/src/main/java/com/hy/java/uct/cdtocode/CDToCodeTracer.java +++ b/src/main/java/com/hy/java/uct/cdtocode/CDToCodeTracer.java @@ -2,8 +2,8 @@ package com.hy.java.uct.cdtocode; import java.util.Map; -import com.hy.java.uct.cdtocode.mapper.InitialMapper; -import com.hy.java.uct.cdtocode.mapper.LevelMapper; +import com.hy.java.uct.cdtocode.mapper.CodeRelationMapper; +import com.hy.java.uct.cdtocode.mapper.DocMapper; import com.hy.java.uct.cdtocode.reader.CDReader; import com.hy.java.uct.cdtocode.reader.CodeReader; import com.hy.java.uct.cdtocode.reader.DocReader; @@ -53,9 +53,9 @@ public class CDToCodeTracer { * 词缀词典等语料库,定义基于类名称匹配和关联关系的启发式匹配规则,研究基于模糊匹配技术的追踪关系建立方法,基于初始追踪和启发式规则, * 对类名不一致的模型和代码元素进行启发式追踪,扩展初始追踪关系。 */ - Map mapped_classes = InitialMapper.map(classes_in_CD, java_files, doc); + Map mapped_classes = CodeRelationMapper.map(classes_in_CD, java_files, doc); // 检查结果,可注释掉 - // InitialMapper.check(mapped_classes); + // CodeRelationMapper.check(mapped_classes); /* * 5、基于类图语义增强和潜在语义分析的抽象概念与代码元素追踪方法 * @@ -65,8 +65,8 @@ public class CDToCodeTracer { * 针对语义增强的UML类图与代码,首先利用逆向工程技术建立代码模型,以支持代码与设计模型的追踪;然后基于潜在语义索引技术,分析设计模型中的类的名称、属性、 * 方法、关系、功能描述等语义与代码类之间的语义关联,结合初始追踪关系中类之间的关系,建立抽象元素与代码之间的追踪 */ - mapped_classes = LevelMapper.map(mapped_classes, java_files, doc); + mapped_classes = DocMapper.map(mapped_classes, java_files, doc); // 检查结果,可注释掉 - LevelMapper.check(mapped_classes); + DocMapper.check(mapped_classes); } } diff --git a/src/main/java/com/hy/java/uct/cdtocode/mapper/InitialMapper.java b/src/main/java/com/hy/java/uct/cdtocode/mapper/CodeRelationMapper.java similarity index 78% rename from src/main/java/com/hy/java/uct/cdtocode/mapper/InitialMapper.java rename to src/main/java/com/hy/java/uct/cdtocode/mapper/CodeRelationMapper.java index 3c1d4aee2adb3b55cdcf5f4a40a070804806d068..cffa18445a298625484e8b49184cb0d8d6391220 100644 --- a/src/main/java/com/hy/java/uct/cdtocode/mapper/InitialMapper.java +++ b/src/main/java/com/hy/java/uct/cdtocode/mapper/CodeRelationMapper.java @@ -20,7 +20,7 @@ import com.hy.java.uct.umlrecog.util.Relation; import com.hy.java.uct.umlrecog.util.UMLClass; import com.hy.java.utility.common.Pair; -public class InitialMapper { +public class CodeRelationMapper { /** * 针对类图中的类和代码中的类,基于同义词、词缀词典等语料库,定义基类名称匹配和关联关系的启发式匹配规则,研究基于模糊匹配技术的追踪关系建立方法,解决类名不一致的模型和代码元素的追踪问题: @@ -52,7 +52,61 @@ public class InitialMapper { } } } - // 2、然后针对UML_class的每条out_rela,记录其target_class,看possible_java_files中的每个文件是否也有out_rela,且文件的out_rela目标文件也在target_class的possible_java_files中。如果有,则UML_class映射到该文件,且记录target_class和其映射文件。 + // 2、还要找与UML_class模糊匹配的类文件有继承、实现两类关系的其他类文件,如果其他类文件并未出现在类图中,则也应放入possible_java_files中 + for (String key : key_set) { + UMLClass UML_class = classes_in_CD.get(key); + List extend_files = new ArrayList<>(); + List impl_files = new ArrayList<>(); + // 对每个模糊匹配UML_class的类文件,寻找与其有继承、实现两类关系的其他类文件 + for (String possible_java_full_name : UML_class.possible_java_files) { + String possible_java_file_short_name = possible_java_full_name.substring(possible_java_full_name.lastIndexOf(".") + 1); + // System.out.println(possible_java_file_short_name); + // 看谁继承或实现了它 + Set java_file_set = java_files.keySet(); + for (String java_file_full_class_name : java_file_set) { + String short_java_class_name = java_file_full_class_name.substring(java_file_full_class_name.lastIndexOf(".") + 1); + try { + CompilationUnit other_java_file = StaticJavaParser.parse(new File(java_files.get(java_file_full_class_name))); + Optional o_class = other_java_file.getClassByName(short_java_class_name); + if (o_class.isPresent()) { + ClassOrInterfaceDeclaration other_class = o_class.get(); + // 继承 + NodeList extended_types = other_class.getExtendedTypes(); + // 如果继承了模糊匹配的文件,且其他类文件并未出现在类图中,则也应放入possible_java_files中 + for (ClassOrInterfaceType extended_class : extended_types) { + // 需获取继承关系目标文件的类全称 + String extended_class_full_name = getClassFullName(extended_class.asString(), other_java_file.getImports(), other_java_file.getPackageDeclaration()); + if (extended_class_full_name.substring(extended_class_full_name.lastIndexOf(".") + 1).equals(possible_java_file_short_name)) { + if (!key_set.contains(short_java_class_name)) { + extend_files.add(java_file_full_class_name); + break; + } + } + } + // 实现:文件的实现关系目标文件 + NodeList implemented_types = other_class.getImplementedTypes(); + // 如果实现了模糊匹配的文件,且其他类文件并未出现在类图中,则也应放入possible_java_files中 + for (ClassOrInterfaceType implemented_class : implemented_types) { + // 需获取实现关系目标文件的类全称 + String implemented_class_full_name = getClassFullName(implemented_class.asString(), other_java_file.getImports(), other_java_file.getPackageDeclaration()); + if (implemented_class_full_name.substring(implemented_class_full_name.lastIndexOf(".") + 1).equals(possible_java_file_short_name)) { + if (!key_set.contains(short_java_class_name)) { + impl_files.add(java_file_full_class_name); + break; + } + } + } + } + } catch (FileNotFoundException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + } + UML_class.possible_java_files.addAll(extend_files); + UML_class.possible_java_files.addAll(impl_files); + } + // 3、然后针对UML_class的每条out_rela,记录其target_class,看possible_java_files中的每个文件是否也有out_rela,且文件的out_rela目标文件也在target_class的possible_java_files中。如果有,则UML_class映射到该文件,且记录target_class和其映射文件。 for (String key : key_set) { UMLClass UML_class = classes_in_CD.get(key); if (UML_class.possible_java_files.size() < 1) { @@ -152,8 +206,8 @@ public class InitialMapper { } } } - // 3、in_rela同上。似乎不需要做in_rela,因为遍历完所有类的out_rela后,所有关系就都遍历了 - // 4、对classes_in_CD中的UMLClass.mapped_java_files去重。对其映射到的每个文件,如果该映射没有关系目标、且有重复,则去重 + // 4、in_rela同上。似乎不需要做in_rela,因为遍历完所有类的out_rela后,所有关系就都遍历了 + // 5、对classes_in_CD中的UMLClass.mapped_java_files去重。对其映射到的每个文件,如果该映射没有关系目标、且有重复,则去重 Set mapped_classes_key_set = classes_in_CD.keySet(); for (String mapped_classes_key : mapped_classes_key_set) { UMLClass UML_class = classes_in_CD.get(mapped_classes_key); @@ -215,7 +269,12 @@ public class InitialMapper { } private static String getClassFullName(String class_short_name, NodeList source_class_imports, Optional source_class_package_declaration) { - String result = class_short_name; + String result = null; + // 对于内部类,只保留其父类名 + if (class_short_name.contains(".")) { + String[] strs = class_short_name.split("\\."); + class_short_name = strs[strs.length - 2]; + } // 先默认class_short_name与source_class在同一个包下,所以先给它加上同样的包名。后面如果不在同包内,则直接连包名全改了 if (source_class_package_declaration.isPresent()) { result = source_class_package_declaration.get().getNameAsString() + "." + class_short_name; diff --git a/src/main/java/com/hy/java/uct/cdtocode/mapper/LevelMapper.java b/src/main/java/com/hy/java/uct/cdtocode/mapper/DocMapper.java similarity index 97% rename from src/main/java/com/hy/java/uct/cdtocode/mapper/LevelMapper.java rename to src/main/java/com/hy/java/uct/cdtocode/mapper/DocMapper.java index a0164723453188c8301db0da4ea19feb59434a55..90648ffb7ea004835e2c4d66f8614e7e32633486 100644 --- a/src/main/java/com/hy/java/uct/cdtocode/mapper/LevelMapper.java +++ b/src/main/java/com/hy/java/uct/cdtocode/mapper/DocMapper.java @@ -6,7 +6,7 @@ import java.util.Set; import com.hy.java.uct.umlrecog.util.UMLClass; import com.hy.java.utility.common.Pair; -public class LevelMapper { +public class DocMapper { /** * 参考ISO 12207、IEEE * 1016等行业标准,定义包含类的名称、属性、方法和关系类型及指向的结构化文本语义模板,用于从详细设计中提取与模型内容相关的语义信息; diff --git a/src/main/java/com/hy/java/uct/umlrecog/cddetector/BizaareSituations.java b/src/main/java/com/hy/java/uct/umlrecog/cddetector/BizaareSituations.java new file mode 100644 index 0000000000000000000000000000000000000000..87a83a1bc845d0ecdd9b5fa2fb6796b5d2be20ac --- /dev/null +++ b/src/main/java/com/hy/java/uct/umlrecog/cddetector/BizaareSituations.java @@ -0,0 +1,36 @@ +package com.hy.java.uct.umlrecog.cddetector; + +public class BizaareSituations { + public static double rect_containing_tri_to_be_ext = 0.7; + public static double rect_not_containing_tri_still_to_be_ext = 0.5; + public static double rect_containing_bizaare_to_be_aggr = 0.3; + + public static double getThreshold(double blur_line, double color_too_light, double line_over_class, double gradual_color, double short_line, double too_close, double text_in_line) { + // double result = 0.5; + double result = Math.random(); + if (blur_line != 0) { + result *= blur_line; + } + if (color_too_light != 0) { + result *= color_too_light; + } + if (line_over_class != 0) { + result *= line_over_class; + } + if (gradual_color != 0) { + System.out.println("Pay more attention on the manual check!"); + result *= gradual_color; + } + if (short_line != 0) { + System.out.println("Pay more attention on the manual check!"); + result *= short_line; + } + if (too_close != 0) { + result *= too_close; + } + if (text_in_line != 0) { + result *= text_in_line; + } + return result; + } +} 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 8e4bd0f36800e07c585972e8388bfd5f25286649..08de863ac87e688525cce8be3d0b7e4eb34fbf54 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 @@ -502,7 +502,8 @@ public class ClassRelationDetector { // 对“轮廓”做二次逼近,获取关系符号形状。第一次逼近可以误差大一点,得到大致形状;第二次逼近误差要小一点,得到精确形状 Imgproc.approxPolyDP(origin_curve, origin_approx_curve, 0.05 * Imgproc.arcLength(origin_curve, false), true); Imgproc.approxPolyDP(origin_approx_curve, origin_approx_curve, 0.01 * Imgproc.arcLength(origin_approx_curve, true), true); - double threshold = Math.random(); + double threshold = BizaareSituations.getThreshold(0, 0, 0, 0, 0, 0, 0); + // double threshold = BizaareSituations.getThreshold(0.2, 0.3, 0.5, 0.55, 0.6, 0.1, 0.03); // 如果逼近得到三角形,则基本就是继承了,再检查一下位置即可(其实检不检查作用不大) if (origin_approx_curve.toArray().length <= 5) { // 获取三角形的包络矩形 @@ -531,20 +532,20 @@ public class ClassRelationDetector { temp_pt2.x -= rect_containing_rela_type.x; temp_pt2.y -= rect_containing_rela_type.y; if (rect_possible_containing_ext.contains(temp_pt0) || rect_possible_containing_ext.contains(temp_pt1) || rect_possible_containing_ext.contains(temp_pt2)) { - if (threshold <= 0.7) { + if (threshold <= BizaareSituations.rect_containing_tri_to_be_ext) { type = "继承"; } else { type = "依赖"; } } else { - if (threshold <= 0.5) { + if (threshold <= BizaareSituations.rect_not_containing_tri_still_to_be_ext) { type = "继承"; } else { type = "依赖"; } } } else { - if (threshold <= 0.3) { + if (threshold <= BizaareSituations.rect_containing_bizaare_to_be_aggr) { type = "聚合"; } else { type = "依赖";