|
5 | 5 | import com.github.javaparser.ast.ImportDeclaration; |
6 | 6 | import com.github.javaparser.ast.Node; |
7 | 7 | import com.github.javaparser.ast.NodeList; |
8 | | -import com.github.javaparser.ast.body.FieldDeclaration; |
9 | | -import com.github.javaparser.ast.body.MethodDeclaration; |
10 | | -import com.github.javaparser.ast.body.TypeDeclaration; |
| 8 | +import com.github.javaparser.ast.body.*; |
11 | 9 | import org.mybatis.generator.api.ShellCallback; |
12 | 10 | import org.mybatis.generator.config.MergeConstants; |
13 | 11 | import org.mybatis.generator.exception.ShellException; |
|
16 | 14 | import java.io.FileNotFoundException; |
17 | 15 | import java.util.*; |
18 | 16 |
|
19 | | -import static org.mybatis.generator.api.dom.OutputUtilities.newLine; |
20 | 17 | import static org.mybatis.generator.internal.util.messages.Messages.getString; |
21 | 18 |
|
22 | 19 | /** |
23 | 20 | * Created By [email protected] 2018-04-15 |
24 | 21 | * |
25 | | - * @author BenBenShang [email protected] |
| 22 | + * @author BenBenShang [email protected] 版权所有,盗用必究 |
26 | 23 | */ |
27 | 24 | public class MyShellCallback implements ShellCallback { |
28 | 25 |
|
@@ -90,116 +87,210 @@ public String mergeJavaFile(String newFileSource, |
90 | 87 | try { |
91 | 88 | CompilationUnit newCompilationUnit = JavaParser.parse(newFileSource); |
92 | 89 | CompilationUnit existingCompilationUnit = JavaParser.parse(existingFile); |
93 | | - return mergerFile(newCompilationUnit, existingCompilationUnit); |
| 90 | + return mergeCompilationUnit(existingCompilationUnit, newCompilationUnit).toString(); |
94 | 91 | } catch (FileNotFoundException e) { |
95 | 92 | throw new UnsupportedOperationException(); |
96 | 93 | } |
97 | 94 | } |
98 | 95 |
|
99 | | - public String mergerFile(CompilationUnit newCompilationUnit, CompilationUnit existingCompilationUnit) { |
| 96 | + /** |
| 97 | + * 合并可编译单元(即合并两个Java文件) |
| 98 | + */ |
| 99 | + private CompilationUnit mergeCompilationUnit(CompilationUnit oldCompilationUnit, CompilationUnit newCompilationUnit) { |
| 100 | + CompilationUnit finalCompilationUnit = new CompilationUnit(); |
100 | 101 |
|
101 | | - System.out.println("合并java代码..."); |
102 | | - StringBuilder sb = new StringBuilder(newCompilationUnit.getPackageDeclaration().get().toString()); |
103 | | - newCompilationUnit.removePackageDeclaration(); |
| 102 | + //修改包名为新类的包名 |
| 103 | + if (newCompilationUnit.getPackageDeclaration().isPresent()) |
| 104 | + finalCompilationUnit.setPackageDeclaration(newCompilationUnit.getPackageDeclaration().get()); |
104 | 105 |
|
105 | | - //合并imports |
106 | | - NodeList<ImportDeclaration> imports = newCompilationUnit.getImports(); |
107 | | - imports.addAll(existingCompilationUnit.getImports()); |
| 106 | + //合并import |
108 | 107 | Set<ImportDeclaration> importSet = new HashSet<>(); |
109 | | - importSet.addAll(imports); |
| 108 | + importSet.addAll(oldCompilationUnit.getImports()); |
| 109 | + importSet.addAll(newCompilationUnit.getImports()); |
110 | 110 |
|
111 | | - NodeList<ImportDeclaration> newImports = new NodeList<>(); |
112 | | - newImports.addAll(importSet); |
113 | | - newCompilationUnit.setImports(newImports); |
114 | | - for (ImportDeclaration i : newCompilationUnit.getImports()) { |
115 | | - sb.append(i.toString()); |
| 111 | + NodeList<ImportDeclaration> imports = new NodeList<>(); |
| 112 | + imports.addAll(importSet); |
| 113 | + finalCompilationUnit.setImports(imports); |
| 114 | + |
| 115 | + //合并topLevelClass |
| 116 | + finalCompilationUnit.setTypes(mergeTypes(oldCompilationUnit.getTypes(), newCompilationUnit.getTypes())); |
| 117 | + |
| 118 | + |
| 119 | + return finalCompilationUnit; |
| 120 | + } |
| 121 | + |
| 122 | + /** |
| 123 | + * 合并Java类(一个Java文件可能有多个类) |
| 124 | + */ |
| 125 | + private NodeList<TypeDeclaration<?>> mergeTypes(NodeList<TypeDeclaration<?>> oldTypes, NodeList<TypeDeclaration<?>> newTypes) { |
| 126 | + Map<String, TypeDeclaration<?>> finalTypes = new Hashtable<>(); |
| 127 | + for (TypeDeclaration<?> newType : newTypes) { |
| 128 | + finalTypes.put(newType.getNameAsString(), newType); |
116 | 129 | } |
117 | | - newLine(sb); |
118 | | - NodeList<TypeDeclaration<?>> types = newCompilationUnit.getTypes(); |
119 | | - NodeList<TypeDeclaration<?>> oldTypes = existingCompilationUnit.getTypes(); |
120 | | - |
121 | | - for (int i = 0; i < types.size(); i++) { |
122 | | - //截取Class |
123 | | - String classNameInfo = types.get(i).toString().substring(0, types.get(i).toString().indexOf("{") + 1); |
124 | | - sb.append(classNameInfo); |
125 | | - newLine(sb); |
126 | | - newLine(sb); |
127 | | - |
128 | | - //合并fields |
129 | | - Map<String, FieldDeclaration> newFieldsToWrite = new Hashtable<>();//将要写入的 |
130 | | - |
131 | | - for (FieldDeclaration fieldDeclaration : oldTypes.get(i).getFields()) {//之前存在的 |
132 | | - boolean flag = true; |
133 | | - for (String tag : MergeConstants.OLD_ELEMENT_TAGS) |
134 | | - if (fieldDeclaration.toString().contains(tag)) { |
135 | | - flag = false; |
136 | | - break; |
137 | | - } |
138 | | - if (flag) {//如果该字段不是自动生成的,则重新加入 |
139 | | - newFieldsToWrite.put(fieldDeclaration.getVariables().toString(), fieldDeclaration); |
140 | | - } |
141 | | - } |
142 | | - for (FieldDeclaration fieldDeclaration : types.get(i).getFields()) {//新生成的 |
143 | | - newFieldsToWrite.put(fieldDeclaration.getVariables().toString(), fieldDeclaration); |
144 | | - } |
145 | | - for (FieldDeclaration f : newFieldsToWrite.values()) { |
146 | | - sb.append("\t" + f.toString()); |
147 | | - newLine(sb); |
148 | | - newLine(sb); |
| 130 | + |
| 131 | + for (TypeDeclaration<?> oldType : oldTypes) {//对于旧CompilationUnit中的每一个TopLevelClass |
| 132 | + if (finalTypes.containsKey(oldType.getNameAsString())) {//如果存在同名类则合并 |
| 133 | + finalTypes.put(oldType.getNameAsString(), mergeType(oldType, finalTypes.get(oldType.getNameAsString()))); |
| 134 | + } else if (!isGeneratedNode(oldType)) {//如果不存在同名类且不是生成的类 |
| 135 | + finalTypes.put(oldType.getNameAsString(), mergeType(oldType, finalTypes.get(oldType.getNameAsString()))); |
149 | 136 | } |
| 137 | + } |
150 | 138 |
|
151 | | - //合并methods |
152 | | - List<MethodDeclaration> methods = types.get(i).getMethods(); |
153 | | - List<MethodDeclaration> existingMethods = oldTypes.get(i).getMethods(); |
154 | | - List<String> newMethods = new ArrayList<String>(); |
| 139 | + return new NodeList<>(finalTypes.values()); |
| 140 | + } |
155 | 141 |
|
156 | | - for (MethodDeclaration f : methods) { |
157 | | - String res = f.toString().replaceAll("\r\n", "\r\n "); |
158 | | - sb.append(" " + res); |
159 | | - newLine(sb); |
160 | | - newLine(sb); |
| 142 | + /** |
| 143 | + * 合并两个同名类 |
| 144 | + */ |
| 145 | + private TypeDeclaration<?> mergeType(TypeDeclaration<?> oldType, TypeDeclaration<?> newType) { |
| 146 | + TypeDeclaration<?> finalTypeDeclaration; |
| 147 | + if (newType.isClassOrInterfaceDeclaration() && oldType.isClassOrInterfaceDeclaration()) { |
| 148 | + finalTypeDeclaration = new ClassOrInterfaceDeclaration(); |
| 149 | + ClassOrInterfaceDeclaration oldClass = oldType.asClassOrInterfaceDeclaration(); |
| 150 | + ClassOrInterfaceDeclaration newClass = newType.asClassOrInterfaceDeclaration(); |
| 151 | + |
| 152 | + //设置修饰符及类名 |
| 153 | + finalTypeDeclaration.setModifiers(newClass.getModifiers());//修饰符 |
| 154 | + finalTypeDeclaration.asClassOrInterfaceDeclaration().setInterface(//是否为接口 |
| 155 | + newClass.isInterface() |
| 156 | + ); |
| 157 | + finalTypeDeclaration.setName(newClass.getName());//类名 |
| 158 | + finalTypeDeclaration.asClassOrInterfaceDeclaration().setExtendedTypes(newClass.getExtendedTypes());//继承的类 |
| 159 | + finalTypeDeclaration.asClassOrInterfaceDeclaration().setImplementedTypes(newClass.getImplementedTypes());//继承的接口 |
| 160 | + finalTypeDeclaration.asClassOrInterfaceDeclaration().setAnnotations(newClass.getAnnotations());//注解 |
| 161 | + if (newClass.getComment().isPresent())//注释 |
| 162 | + finalTypeDeclaration.asClassOrInterfaceDeclaration().setComment(newClass.getComment().get()); |
| 163 | + |
| 164 | + |
| 165 | + //合并initializer(possibly static) |
| 166 | + //保留所有旧类中的initializer(MBG并不会生成initializer,不考虑保留旧initializer会出现的问题) |
| 167 | + for (BodyDeclaration<?> bodyDeclaration : oldClass.getMembers()) |
| 168 | + if (bodyDeclaration.isInitializerDeclaration()) |
| 169 | + finalTypeDeclaration.addMember(bodyDeclaration); |
| 170 | + |
| 171 | + //合并构造函数 |
| 172 | + for (ConstructorDeclaration constructorDeclaration : mergeConstructors(oldClass.getConstructors(), newClass.getConstructors())) { |
| 173 | + finalTypeDeclaration.addMember(constructorDeclaration); |
161 | 174 | } |
162 | 175 |
|
163 | | - for (MethodDeclaration m : methods) { |
164 | | - newMethods.add(m.getName().toString()); |
| 176 | + //合并Field |
| 177 | + for (FieldDeclaration fieldDeclaration : mergeFields(oldClass.getFields(), newClass.getFields())) { |
| 178 | + finalTypeDeclaration.addMember(fieldDeclaration); |
165 | 179 | } |
166 | | - newMethods.add("toString"); |
167 | | - newMethods.add("hashCode"); |
168 | | - newMethods.add("equals"); |
169 | 180 |
|
170 | | - for (MethodDeclaration m : existingMethods) { |
171 | | - if (newMethods.contains(m.getName().toString())) { |
172 | | - continue; |
173 | | - } |
| 181 | + //合并Method |
| 182 | + for (MethodDeclaration methodDeclaration : mergeMethods(oldClass.getMethods(), newClass.getMethods())) { |
| 183 | + finalTypeDeclaration.addMember(methodDeclaration); |
| 184 | + } |
174 | 185 |
|
175 | | - boolean flag = true; |
176 | | - for (String tag : MergeConstants.OLD_ELEMENT_TAGS) { |
177 | | - if (m.toString().contains(tag)) { |
178 | | - flag = false; |
179 | | - break; |
180 | | - } |
| 186 | + //合并内部类(class/enum/interface) |
| 187 | + NodeList<TypeDeclaration<?>> oldTypes = new NodeList<>(); |
| 188 | + NodeList<TypeDeclaration<?>> newTypes = new NodeList<>(); |
| 189 | + for (BodyDeclaration<?> bodyDeclaration : oldClass.getMembers()) { |
| 190 | + if (bodyDeclaration.isClassOrInterfaceDeclaration() || |
| 191 | + bodyDeclaration.isEnumDeclaration() || |
| 192 | + bodyDeclaration.isAnnotationDeclaration()) { |
| 193 | + oldTypes.add(bodyDeclaration.asTypeDeclaration()); |
| 194 | +// System.out.println("旧内部类:" + bodyDeclaration.asTypeDeclaration().getNameAsString()); |
181 | 195 | } |
182 | | - if (flag) { |
183 | | - String res = m.toString().replaceAll("\r\n", "\r\n "); |
184 | | - sb.append(" " + res); |
185 | | - newLine(sb); |
186 | | - newLine(sb); |
| 196 | + } |
| 197 | + for (BodyDeclaration<?> bodyDeclaration : newClass.getMembers()) { |
| 198 | + if (bodyDeclaration.isClassOrInterfaceDeclaration() || |
| 199 | + bodyDeclaration.isEnumDeclaration() || |
| 200 | + bodyDeclaration.isAnnotationDeclaration()) { |
| 201 | + newTypes.add(bodyDeclaration.asTypeDeclaration()); |
| 202 | +// System.out.println("新内部类:" + bodyDeclaration.asTypeDeclaration().getNameAsString()); |
| 203 | +// System.out.println("新内部类修饰符:" + bodyDeclaration.asTypeDeclaration().getModifiers()); |
187 | 204 | } |
188 | 205 | } |
| 206 | + for (TypeDeclaration<?> typeDeclaration : mergeTypes(oldTypes, newTypes)) { |
| 207 | + finalTypeDeclaration.addMember(typeDeclaration); |
| 208 | + } |
189 | 209 |
|
190 | | - //判断是否有内部类 |
191 | | - types.get(i).getChildNodes(); |
192 | | - for (Node n : types.get(i).getChildNodes()) { |
193 | | - if (n.toString().contains("static class") || n.toString().contains("public enum Column")) { |
194 | | - String res = n.toString().replaceAll("\r\n", "\r\n "); |
195 | | - sb.append(" " + res); |
196 | | - } |
| 210 | + return finalTypeDeclaration; |
| 211 | + } else if (newType.isEnumDeclaration() && oldType.isEnumDeclaration()) { |
| 212 | + finalTypeDeclaration = new EnumDeclaration(); |
| 213 | + return newType; |
| 214 | + } else if (newType.isAnnotationDeclaration() && oldType.isAnnotationDeclaration()) { |
| 215 | + finalTypeDeclaration = new AnnotationDeclaration(); |
| 216 | + return newType; |
| 217 | + } else { |
| 218 | + throw new RuntimeException(String.format("新类和旧类的类型不一样,无法判断该以何种方式合并,请删除旧文件或者将旧文件更改为正确的类型 (类名:%s)", newType.getNameAsString())); |
| 219 | +// return newType; |
| 220 | + } |
| 221 | + } |
| 222 | + |
| 223 | + /** |
| 224 | + * 合并构造函数 |
| 225 | + */ |
| 226 | + private List<ConstructorDeclaration> mergeConstructors(List<ConstructorDeclaration> oldConstructors, List<ConstructorDeclaration> newConstructors) { |
| 227 | + |
| 228 | + Map<String, ConstructorDeclaration> constructorDeclarationMap = new Hashtable<>();// |
| 229 | + for (ConstructorDeclaration newConstructor : newConstructors) { |
| 230 | + if (!constructorDeclarationMap.containsKey(newConstructor.getDeclarationAsString(false, false, false)) |
| 231 | + && !isGeneratedNode(newConstructor)) {//如果新生成的类中不包含该构造函数且该构造函数不是自动生成的 |
| 232 | + constructorDeclarationMap.put(newConstructor.getDeclarationAsString(false, false, false), newConstructor); |
197 | 233 | } |
| 234 | + } |
| 235 | + for (ConstructorDeclaration oldConstructor : oldConstructors) { |
| 236 | + constructorDeclarationMap.put(oldConstructor.getDeclarationAsString(false, false, false), oldConstructor); |
| 237 | +// System.out.println("构造函数:" + oldConstructor.getDeclarationAsString(true, true, false)); |
| 238 | + } |
| 239 | + return new ArrayList<>(constructorDeclarationMap.values()); |
| 240 | + } |
198 | 241 |
|
| 242 | + /** |
| 243 | + * 合并字段 |
| 244 | + */ |
| 245 | + private List<FieldDeclaration> mergeFields(List<FieldDeclaration> oldFields, List<FieldDeclaration> newFields) { |
| 246 | + Map<String, FieldDeclaration> fieldDeclarationMap = new Hashtable<>();// |
| 247 | + for (FieldDeclaration newField : newFields) { |
| 248 | + //mbg生成的一个变量声明不会包含多个变量 |
| 249 | + String key = ""; |
| 250 | + for (VariableDeclarator variableDeclarator : newField.getVariables()) { |
| 251 | + key += variableDeclarator.getNameAsString() + ","; |
| 252 | + } |
| 253 | + fieldDeclarationMap.put(key, newField); |
| 254 | + } |
| 255 | + for (FieldDeclaration oldField : oldFields) { |
| 256 | + String key = ""; |
| 257 | + for (VariableDeclarator variableDeclarator : oldField.getVariables()) { |
| 258 | + key += variableDeclarator.getNameAsString() + ","; |
| 259 | + } |
| 260 | + if (!fieldDeclarationMap.containsKey(key) && !isGeneratedNode(oldField)) { |
| 261 | + fieldDeclarationMap.put(key, oldField); |
| 262 | + } |
199 | 263 | } |
| 264 | + return new ArrayList<>(fieldDeclarationMap.values()); |
| 265 | + } |
200 | 266 |
|
201 | | - return sb.append(System.getProperty("line.separator") + "}").toString(); |
| 267 | + /** |
| 268 | + * 合并方法 |
| 269 | + */ |
| 270 | + private List<MethodDeclaration> mergeMethods(List<MethodDeclaration> oldMethods, List<MethodDeclaration> newMethods) { |
| 271 | + Map<String, MethodDeclaration> methodDeclarationMap = new Hashtable<>(); |
| 272 | + for (MethodDeclaration newMethod : newMethods) { |
| 273 | + methodDeclarationMap.put(newMethod.getDeclarationAsString(false, false, false), newMethod); |
| 274 | + } |
| 275 | + for (MethodDeclaration oldMethod : oldMethods) { |
| 276 | + if (!methodDeclarationMap.containsKey(oldMethod.getDeclarationAsString(false, false, false)) && !isGeneratedNode(oldMethod)) { |
| 277 | + methodDeclarationMap.put(oldMethod.getDeclarationAsString(false, false, false), oldMethod); |
| 278 | + } |
| 279 | + } |
| 280 | + return new ArrayList<>(methodDeclarationMap.values()); |
202 | 281 | } |
203 | 282 |
|
| 283 | + |
| 284 | + /** |
| 285 | + * 判断是否为自动生成的节点(即注释中包含指定tag) |
| 286 | + */ |
| 287 | + private boolean isGeneratedNode(Node node) { |
| 288 | + for (String tag : MergeConstants.OLD_ELEMENT_TAGS) { |
| 289 | + if (node.getComment().toString().contains(tag)) { |
| 290 | + return true; |
| 291 | + } |
| 292 | + } |
| 293 | + return false; |
| 294 | + } |
204 | 295 | } |
205 | 296 |
|
0 commit comments