package cn.sh.ideal;
import cn.sh.ideal.autocode.util.AutoCodeUtil;
import cn.sh.ideal.smkey.service.ISMKeyService;
import cn.sh.ideal.unittest.entity.ClassProperty;
import cn.sh.ideal.unittest.entity.MethodProperty;
import cn.sh.ideal.util.ComponentUtil;
import freemarker.template.Template;
import java.io.*;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Execute {
public static void main(String[] args) throws Exception {
Class clazz = ISMKeyService.class;
Map<Type, Type> typeMap = getGenericMap(clazz);
ClassProperty classProperty = new ClassProperty();
classProperty.setInterface(clazz.isInterface());
classProperty.setPackageName(clazz.getPackage().getName());
if (classProperty.isInterface()) {
classProperty.setInterfaceName(clazz.getSimpleName());
classProperty.addImportPackage(clazz.getName());
classProperty.setPackageName(classProperty.getPackageName() + ".impl");
}
classProperty.setName("Mock" + clazz.getSimpleName() + (classProperty.isInterface() ? "Impl" : ""));
for (Method method : clazz.getMethods()) {
MethodProperty methodProperty = new MethodProperty();
String methodStr = method.toGenericString();
methodStr = methodStr.replace("abstract ", "");
for (Map.Entry<Type, Type> entry : typeMap.entrySet()) {
Matcher matcher = Pattern.compile("[(<,\\s]" + entry.getKey().getTypeName() + "[)>,\\s]").matcher(methodStr);
classProperty.addImportPackage(entry.getValue().getTypeName());
while (matcher.find()) {
String match = matcher.group();
String replace = match.charAt(0) + entry.getValue().getTypeName() + match.charAt(match.length() - 1);
methodStr = methodStr.replace(match, replace);
}
}
Matcher matcher = Pattern.compile("[a-zA-Z0-9]+(\\.)+[\\.a-zA-Z0-9]+").matcher(methodStr);
while (matcher.find()) {
String match = matcher.group();
classProperty.addImportPackage(match);
match = match.substring(0, match.lastIndexOf('.') + 1);
methodStr = methodStr.replaceAll(match.replaceAll("\\.", "\\\\."), "");
}
matcher = Pattern.compile(",[a-zA-Z]").matcher(methodStr);
int i = 0;
while (matcher.find()) {
String match = matcher.group();
methodStr = methodStr.replace(match, " arg" + i++ + match);
}
if (!methodStr.contains("()")) {
methodStr = methodStr.replace(")", " arg" + i + ")");
}
methodProperty.setMethodStr(methodStr);
methodProperty.setReturnTypeStr(method.getReturnType().getSimpleName());
classProperty.addImportPackage(method.getReturnType().getName());
classProperty.addMethodProperties(methodProperty);
}
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("classProperty", classProperty);
write("D:\\IdealProject\\product\\rely\\rely-system\\src\\test\\java\\cn\\sh\\ideal\\smkey\\service\\impl\\" + classProperty.getName() + ".java",
getTemplate(), paramMap);
}
public static Template getTemplate() throws FileNotFoundException {
String filePath = "D:\\IdealProject\\product\\unittest\\src\\main\\resources\\template\\template.ftl";
String fileStream = ComponentUtil.inputStreamToString(new FileInputStream(filePath));
return AutoCodeUtil.getTemplate("template.ftl", fileStream);
}
public static boolean write(String path, Template template, Map<String, Object> param) {
Writer out = null;
try {
out = new OutputStreamWriter(new FileOutputStream(path), "UTF-8");
template.process(param, out);
out.flush();
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
} finally {
if (out != null) {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static Map<Type, Type> getGenericMap(Class clazz) {
if (clazz.isInterface()) {
return getGenericMapForInterface(clazz);
}
return getGenericMapForClass(clazz);
}
public static Map<Type, Type> getGenericMapForClass(Class clazz) {
Map<Type, Type> map = new HashMap<>();
while (clazz != null) {
Type superclass = clazz.getGenericSuperclass();
if (superclass != null && superclass instanceof ParameterizedType) {
Type[] typeParameters = ((ParameterizedType) superclass).getActualTypeArguments();
Type[] genericTypes = clazz.getSuperclass().getTypeParameters();
for (int i = 0; i < genericTypes.length; i++) {
if (!(typeParameters[i] instanceof TypeVariable)) {
map.put(genericTypes[i], typeParameters[i]);
}
}
} else {
break;
}
clazz = clazz.getSuperclass();
}
return map;
}
public static Map<Type, Type> getGenericMapForInterface(Class clazz) {
Type[] types = clazz.getGenericInterfaces();
if (types == null) {
return new HashMap<>();
}
Map<Type, Type> map = new HashMap<>();
for (int i = 0; i < types.length; i++) {
Type type = types[i];
if (type instanceof ParameterizedType) {
Class parentClass = (Class) ((ParameterizedType) type).getRawType();
map.putAll(getGenericMapForInterface(parentClass));
Type[] actualTypeArguments = ((ParameterizedType) type).getActualTypeArguments();
Type[] typeParameters = parentClass.getTypeParameters();
for (int j = 0; j < actualTypeArguments.length; j++) {
if (!(actualTypeArguments[j] instanceof TypeVariable)) {
map.put(typeParameters[j], actualTypeArguments[j]);
}
}
}
}
return map;
}
}
package cn.sh.ideal.unittest.entity;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
public class MethodProperty {
private String methodStr;
private String returnTypeStr;
public String getMethodStr() {
return methodStr;
}
public void setMethodStr(String methodStr) {
this.methodStr = methodStr;
}
public String getReturnTypeStr() {
if (returnTypeStr == "void") {
return "";
}
return "return null;";
}
public void setReturnTypeStr(String returnTypeStr) {
this.returnTypeStr = returnTypeStr;
}
}
package cn.sh.ideal.unittest.entity;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
public class ClassProperty {
private List<MethodProperty> methodProperties = new ArrayList<>();
private Set<String> importPackages = new TreeSet<>();
private String name;
private String packageName;
private boolean isInterface;
private String interfaceName;
public List<MethodProperty> getMethodProperties() {
return methodProperties;
}
public void setMethodProperties(List<MethodProperty> methodProperties) {
this.methodProperties = methodProperties;
}
public void addMethodProperties(MethodProperty methodProperty) {
this.methodProperties.add(methodProperty);
}
public Set<String> getImportPackages() {
return importPackages;
}
public void setImportPackages(Set<String> importPackages) {
this.importPackages = importPackages;
}
public void addImportPackage(String importPackage) {
if (importPackage.startsWith("java.lang")) {
return;
}
try {
Class clazz = Class.forName(importPackage);
this.importPackages.add(importPackage);
} catch (ClassNotFoundException e) {
System.out.println(importPackage);
}
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPackageName() {
return packageName;
}
public void setPackageName(String packageName) {
this.packageName = packageName;
}
public boolean isInterface() {
return isInterface;
}
public void setInterface(boolean anInterface) {
isInterface = anInterface;
}
public String getInterfaceName() {
return interfaceName;
}
public void setInterfaceName(String interfaceName) {
this.interfaceName = interfaceName;
}
}
package ${classProperty.packageName};
import cn.sh.ideal.unittest.annotation.MockBean;
<#list classProperty.importPackages as importPackage>
import ${importPackage};
</#list>
public class ${classProperty.name}<#if classProperty.interface> implements ${classProperty.interfaceName}</#if> {
<#list classProperty.methodProperties as methodProperty>
${methodProperty.methodStr} {
${methodProperty.returnTypeStr}
}
</#list>
}