All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.test4j.mock.faking.meta.MethodId Maven / Gradle / Ivy
package org.test4j.mock.faking.meta;
import g_asm.org.objectweb.asm.Type;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import lombok.experimental.Accessors;
import org.test4j.annotations.Mock;
import org.test4j.mock.faking.util.ClassLoad;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.stream.Stream;
import static g_asm.org.objectweb.asm.Type.getMethodDescriptor;
import static org.test4j.mock.faking.util.ReflectUtility.getCorrespondingFakeName;
import static org.test4j.mock.faking.util.TypeDesc.T_Invocation;
import static org.test4j.mock.faking.util.TypeUtility.classPath;
/**
* 从class文件中解析出的方法元数据
*
* @author darui.wu
*/
@SuppressWarnings({"unused", "rawtypes"})
@Accessors(chain = true)
@EqualsAndHashCode(of = {"methodDesc"})
public class MethodId {
/**
* 声明mock行为的类 new MockUp
*/
public final String realClassDesc;
public int targetHashCode = 0;
/**
* 实际实现方法逻辑的类, 可以是realClass或其父类
* null: 表示是抽象方法, 在realClass和其父类中无实现逻辑
*/
public final String declaredClassDesc;
public final String name;
public final String desc;
/**
* Mock方法参数是否包含{@link org.test4j.mock.Invocation}
*/
public final boolean hasInvocation;
/**
* Mock 方法签名(如果 desc 第一个参数是Invocation, 去掉 Invocation参数)
*/
public final String descNoInvocation;
/**
* 是否定义了 {@link Mock} 注解的方法
*/
@Getter
@Setter
private boolean isMockMethod = false;
/**
* method name + para desc
*/
public final String methodDesc;
public MethodId(Class realClassDesc, Method method) {
this(realClassDesc, method.getDeclaringClass(), method.getName(), getMethodDescriptor(method));
}
public MethodId(Class realClassDesc, Class declaredClassDesc, String name, String desc) {
this(classPath(realClassDesc), classPath(declaredClassDesc), name, desc);
}
public MethodId(String realClassDesc, String declaredClassDesc, String name, String desc) {
this.realClassDesc = realClassDesc;
this.declaredClassDesc = declaredClassDesc;
this.name = name;
this.desc = desc;
this.hasInvocation = this.desc.contains(T_Invocation.DESC);
if (this.hasInvocation) {
descNoInvocation = '(' + this.desc.substring(T_Invocation.DESC.length() + 1);
} else {
descNoInvocation = this.desc;
}
this.methodDesc = buildMethodDesc(this.name, this.descNoInvocation);
}
public static String buildMethodDesc(String name, String desc) {
String _name = getCorrespondingFakeName(name);
int end = desc.lastIndexOf(')') + 1;
if (desc.contains(T_Invocation.DESC)) {
return _name + '(' + desc.substring(T_Invocation.DESC.length() + 1, end);
} else {
return _name + desc.substring(0, end);
}
}
private Type[] params = null;
public static String getName(String methodDesc) {
int index = methodDesc.indexOf("(");
return methodDesc.substring(0, index);
}
public static String getDesc(String methodDesc) {
int index = methodDesc.indexOf("(");
return methodDesc.substring(index);
}
public Type[] getParams() {
try {
if (params == null) {
params = Type.getArgumentTypes(desc);
}
return this.params;
} catch (Throwable e) {
throw new RuntimeException("getParams[" + desc + "] error:" + e.getMessage(), e);
}
}
public String[] getParaTypeNames() {
return Stream.of(this.getParams())
.map(Type::getClassName)
.toArray(String[]::new);
}
private Type returnType = null;
public Type getReturnType() {
if (returnType == null) {
this.returnType = Type.getReturnType(desc);
}
return this.returnType;
}
private Class realClass;
public Class realClass() {
if (realClass == null) {
this.realClass = ClassLoad.loadClass(this.realClassDesc);
}
return realClass;
}
public MethodId setTarget(Class declaredClass, Object target) {
this.realClass = declaredClass;
this.targetHashCode = target == null ? 0 : System.identityHashCode(target);
return this;
}
/**
* 参数列表
*/
private Map parameters;
public Map getParameters() {
if (this.parameters != null) {
return this.parameters;
}
this.parameters = new LinkedHashMap<>();
Type[] types = Type.getArgumentTypes(this.descNoInvocation);
for (int index = 0; index < types.length; index++) {
this.parameters.put(index, new ParaNameType(String.format("arg%d", index), types[index].getDescriptor()));
}
return this.parameters;
}
public void addParaNameType(int index, String name, String type) {
if (this.parameters == null) {
this.parameters = new HashMap<>();
}
parameters.put(index, new ParaNameType(name, type));
}
@Override
public String toString() {
return this.realClassDesc + "#" + methodDesc;
}
@ToString
public static class ParaNameType {
public final String name;
public final String type;
public ParaNameType(String name, String type) {
this.name = name;
this.type = type;
}
}
}