package co.gongzh.procbridge;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.json.JSONObject;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
/**
* @author Gong Zhang
*/
final class ReflectiveDelegate implements ProcBridgeServer.Delegate {
@NotNull
private final Object target;
@NotNull
private final Map<String, Method> apiMap;
ReflectiveDelegate(@NotNull Object target) {
this.target = target;
this.apiMap = new HashMap<>();
for (Method m : target.getClass().getDeclaredMethods()) {
if (m.getAnnotation(APIHandler.class) != null) {
String api = m.getName();
if (apiMap.containsKey(api)) {
throw new RuntimeException("duplicate api: " + api);
}
if (m.getParameterCount() == 1) {
Class<?> cl = m.getParameterTypes()[0];
if (cl != JSONObject.class) {
throw new RuntimeException("parameter is not a JSON object for api: " + api);
}
} else if (m.getParameterCount() > 1) {
throw new RuntimeException("too many parameters for api: " + api);
}
if (m.getReturnType() != JSONObject.class &&
m.getReturnType() != String.class &&
m.getReturnType() != void.class) {
throw new RuntimeException("return type is not a JSON object/text for api: " + api);
}
m.setAccessible(true);
apiMap.put(api, m);
}
}
}
@Override
public @Nullable JSONObject handleRequest(@NotNull String api, @NotNull JSONObject body) throws Exception {
Method m = apiMap.get(api);
if (m == null) {
throw new RuntimeException("unknown api: " + api);
}
Object ret;
if (m.getParameterCount() == 1) {
ret = m.invoke(target, body);
} else {
ret = m.invoke(target);
}
if (ret instanceof JSONObject) {
return (JSONObject) ret;
} else if (ret instanceof String) {
String jsonText = (String) ret;
return new JSONObject(jsonText);
} else {
return null;
}
}
}