Created
December 1, 2016 21:16
-
-
Save guilherfp/811bc7b1ee0f431752cb4415fd6c2cd8 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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