package com.sora.util.akatsuki;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
public class Utils {
private Utils() {
// no
}
public static String listSuperclass(TypeMirror mirror) {
TypeMirror superclass = mirror;
StringBuilder builder = new StringBuilder("Superclasses:[");
while (superclass != null && superclass.getKind() == TypeKind.DECLARED) {
builder.append(superclass.toString()).append(" <- ");
superclass = ((TypeElement) ((DeclaredType) superclass).asElement()).getSuperclass();
}
builder.append("(42)]");
return builder.toString();
}
public static String toCapitalCase(String source) {
source = source.toLowerCase();
source = Character.toString(source.charAt(0)).toUpperCase() + source.substring(1);
return source;
}
@SuppressWarnings("unchecked")
static class Defaults implements InvocationHandler {
public static <A extends Annotation> A of(Class<A> annotation) {
return (A) Proxy.newProxyInstance(annotation.getClassLoader(),
new Class[] { annotation }, new Defaults());
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return method.getDefaultValue();
}
}
@SuppressWarnings("unchecked")
static class Values<A extends Annotation> implements InvocationHandler {
private final A defaults;
private final Map<String, String> map;
private final Function<String, String> nameTransformation;
public Values(A defaults, Map<String, String> map,
Function<String, String> nameTransformation) {
this.defaults = defaults;
this.map = Collections.unmodifiableMap(new HashMap<>(map));
this.nameTransformation = nameTransformation;
}
public static <A extends Annotation> A of(Class<A> annotation, A defaults,
Map<String, String> map, Function<String, String> nameTransformation) {
return (A) Proxy.newProxyInstance(annotation.getClassLoader(),
new Class[] { annotation }, new Values<>(defaults, map, nameTransformation));
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String methodName = nameTransformation != null
? nameTransformation.apply(method.getName()) : method.getName();
if (!map.containsKey(methodName)) {
if (defaults == null)
throw new RuntimeException(
"map does not contain method " + methodName + " map=" + map);
return method.invoke(defaults);
}
String value = map.get(methodName);
Class<?> returnType = method.getReturnType();
if (returnType == String.class) {
return value;
} else if (returnType.isEnum()) {
return Enum.valueOf((Class<Enum>) returnType, value);
}else if(returnType.isArray() && returnType.getComponentType().isEnum()){
// TODO test me
return Arrays.stream(value.split(",")).map(s -> Enum.valueOf((Class<Enum>)returnType, s.trim())).toArray(Enum[]::new);
} else {
throw new UnsupportedOperationException(
"return type of " + returnType + "is not implemented");
}
}
}
}