com.github.aidensuen.mongo.reflection.ParamNameResolver Maven / Gradle / Ivy
package com.github.aidensuen.mongo.reflection;
import com.github.aidensuen.mongo.exception.BindingException;
import com.github.aidensuen.mongo.session.Configuration;
import org.springframework.core.*;
import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.query.Param;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.*;
public class ParamNameResolver {
private static final String GENERIC_NAME_PREFIX = "param";
private static final ParameterNameDiscoverer DISCOVERER = new DefaultParameterNameDiscoverer();
private final SortedMap names;
private final SortedMap paramResolvableTypeSortedMap;
private final Method method;
private final Class> implementationClass;
private boolean hasParamAnnotation;
public ParamNameResolver(Configuration config, Method method, Class> implementationClass) {
this.method = method;
this.implementationClass = implementationClass;
final Annotation[][] paramAnnotations = method.getParameterAnnotations();
final SortedMap map = new TreeMap<>();
final SortedMap map1 = new TreeMap<>();
int paramCount = paramAnnotations.length;
String[] paramNames = DISCOVERER.getParameterNames(method);
// get names from @Param annotations
for (int paramIndex = 0; paramIndex < paramCount; paramIndex++) {
ResolvableType resolvableType = ResolvableType.forMethodParameter(method, paramIndex, implementationClass);
map1.put(paramIndex, resolvableType);
if (isSpecialParameter(resolvableType.resolve())) {
// skip special parameters
continue;
}
String name = null;
for (Annotation annotation : paramAnnotations[paramIndex]) {
if (annotation instanceof Param) {
hasParamAnnotation = true;
name = ((Param) annotation).value();
}
}
if (name == null) {
// @Param was not specified.
if (config.isUseActualParamName()) {
name = paramNames != null ? paramNames[paramIndex] : null;
}
if (name == null) {
// use the parameter index as the name ("0", "1", ...)
// gcode issue #71
name = String.valueOf(map.size());
}
}
map.put(paramIndex, name);
}
names = Collections.unmodifiableSortedMap(map);
paramResolvableTypeSortedMap = Collections.unmodifiableSortedMap(map1);
}
public Method getMethod() {
return method;
}
public ResolvableType getResolvableType(int paramIndex) {
return paramResolvableTypeSortedMap.get(paramIndex);
}
public Class> getImplementationClass() {
return implementationClass;
}
public String[] getMethodClassNames() {
List names = new ArrayList<>();
names.add("-");
for (ResolvableType resolvableType : paramResolvableTypeSortedMap.values()) {
names.add(new ParamInfo(resolvableType).toString().toLowerCase().replaceAll("\\.", "/"));
names.add("-");
}
names.remove(names.size() - 1);
return names.toArray(new String[]{});
}
private static boolean isSpecialParameter(Class> clazz) {
return Pageable.class.isAssignableFrom(clazz);
}
public boolean hasParamAnnotation() {
return hasParamAnnotation;
}
public String[] getNames() {
return names.values().toArray(new String[0]);
}
public SortedMap getParamResolvableTypeSortedMap() {
return paramResolvableTypeSortedMap;
}
public Object getNamedParams(Object[] args) {
final int paramCount = names.size();
if (args == null || paramCount == 0) {
return null;
} else if (!hasParamAnnotation && paramCount == 1) {
return args[names.firstKey()];
} else {
final Map param = new ParamMap<>();
int i = 0;
for (Map.Entry entry : names.entrySet()) {
param.put(entry.getValue(), args[entry.getKey()]);
// add generic param names (param1, param2, ...)
final String genericParamName = GENERIC_NAME_PREFIX + String.valueOf(i + 1);
// ensure not to overwrite parameter named with @Param
if (!names.containsValue(genericParamName)) {
param.put(genericParamName, args[entry.getKey()]);
}
i++;
}
return param;
}
}
public static class ParamMap extends HashMap {
private static final long serialVersionUID = -2212268410512043556L;
@Override
public V get(Object key) {
if (!super.containsKey(key)) {
throw new BindingException("Parameter '" + key + "' not found. Available parameters are " + keySet());
}
return super.get(key);
}
}
}