Skip to content

Instantly share code, notes, and snippets.

@guilherfp
Created December 1, 2016 21:16
Show Gist options
  • Save guilherfp/811bc7b1ee0f431752cb4415fd6c2cd8 to your computer and use it in GitHub Desktop.
Save guilherfp/811bc7b1ee0f431752cb4415fd6c2cd8 to your computer and use it in GitHub Desktop.
package br.com.pcsist.winthor.core.autenticacao;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Method;
import java.util.AbstractMap;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map.Entry;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* @author guilherme.pacheco
*/
public final class RestPathExtractor<R> {
private final Function<Entry<String, List<String>>, R> mapper;
public RestPathExtractor(Function<Entry<String, List<String>>, R> mapper) {
this.mapper = mapper;
}
public List<R> paths(Collection<Class<?>> classes) {
return paths(classes.stream());
}
public List<R> paths(Stream<Class<?>> stream) {
return streamPaths(stream).collect(Collectors.toList());
}
public Stream<R> streamPaths(Stream<Class<?>> stream) {
return stream.map(ClassPaths::new).flatMap(this::pathsMethods);
}
private Stream<R> pathsMethods(ClassPaths classPath) {
return classPath.getPaths().flatMap(mapMethod(classPath));
}
private Function<String, Stream<R>> mapMethod(ClassPaths classPath) {
return path -> classPath.methods().filter(hasRole()).flatMap(paths(path));
}
private Predicate<Method> hasRole() {
return m -> m.isAnnotationPresent(RequiresRoles.class);
}
private Function<Method, Stream<R>> paths(String path) {
return method -> {
RequiresRoles roles = method.getAnnotation(RequiresRoles.class);
return paths(method).map(rolePath(path, roles));
};
}
private Function<String, R> rolePath(String pathController, RequiresRoles roles) {
return pathMethod -> {
String fullPath = formatPath(pathController, pathMethod);
return map(fullPath, Arrays.asList(roles.value()));
};
}
private R map(String fullPath, List<String> names) {
return mapper.apply(new AbstractMap.SimpleEntry<>(fullPath, names));
}
private String formatPath(String pathClass, String pathMethod) {
String classPath = StringUtils.appendIfMissing(pathClass, "/");
String methodPath = StringUtils.removeStart(pathMethod, "/");
return classPath.concat(methodPath);
}
private static Stream<String> paths(AnnotatedElement element) {
if (element.isAnnotationPresent(RequestMapping.class)) {
return Stream.of(element.getAnnotation(RequestMapping.class).value());
} else {
return Stream.empty();
}
}
private static class ClassPaths {
private final Class<?> clazz;
public ClassPaths(Class<?> clazz) {
this.clazz = clazz;
}
public Stream<String> getPaths() {
return paths(clazz);
}
public Stream<Method> methods() {
return Stream.of(clazz.getDeclaredMethods());
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment