restx.RestxRouting Maven / Gradle / Ivy
package restx;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableMultimap.Builder;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Ordering;
import restx.factory.Factory;
import restx.factory.NamedComponent;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import static com.google.common.collect.Iterables.transform;
/**
* User: xavierhanin
* Date: 4/1/13
* Time: 11:28 PM
*/
public class RestxRouting {
private final ImmutableList> filters;
private final ImmutableMultimap> routeFilters;
private final ImmutableList routes;
public RestxRouting(ImmutableList> filters,
ImmutableList> routeFilters,
ImmutableList routes) {
this.filters = filters;
Builder> builder = ImmutableListMultimap.builder();
for (RestxRoute route : routes) {
for (NamedComponent routeFilter : routeFilters) {
Optional m = routeFilter.getComponent().match(route);
if (m.isPresent()) {
RestxHandlerMatch restxHandlerMatch = m.get();
builder.put(route, NamedComponent.of(
RestxHandlerMatch.class, routeFilter.getName().getName(),
routeFilter.getPriority(), restxHandlerMatch));
}
}
}
this.routeFilters = builder.build();
this.routes = routes;
}
public ImmutableList getFilters() {
return ImmutableList.copyOf(transform(filters, NamedComponent.toComponent()));
}
public ImmutableCollection extends RestxHandlerMatch> getRouteFilters(RestxRoute route) {
return ImmutableList.copyOf(transform(
routeFilters.get(route), NamedComponent.toComponent()));
}
public ImmutableList getRoutes() {
return routes;
}
public Optional match(RestxRequest restxRequest) {
for (RestxRoute route : routes) {
Optional extends RestxHandlerMatch> match = route.match(restxRequest);
if (match.isPresent()) {
// here we need to:
// - check which filters apply
// - order all filters (route filters and regular filters) by priority
// so we put all matches as NamedComponents (to preserve the filter priority) in a list,
// and finally sort the list by priority before returning it as a Match
ImmutableCollection> routeFilters = this.routeFilters.get(route);
List> matches = Lists.newArrayListWithCapacity(
filters.size() + routeFilters.size() + 1);
matches.addAll(routeFilters);
for (NamedComponent filter : filters) {
Optional extends RestxHandlerMatch> filterMatch = filter.getComponent().match(restxRequest);
if (filterMatch.isPresent()) {
matches.add(NamedComponent.of(
RestxHandlerMatch.class, filter.getName().getName(),
filter.getPriority(), filterMatch.get()));
}
}
return Optional.of(new Match(
ImmutableList.builder()
.addAll(
transform(Ordering.from(Factory.NAMED_COMPONENT_COMPARATOR).sortedCopy(matches),
NamedComponent.toComponent()))
.add(match.get())
.build(),
match));
}
}
return Optional.absent();
}
public static class Match {
private final ImmutableList matches;
private final Optional extends RestxHandlerMatch> match;
private Match(ImmutableList matches, Optional extends RestxHandlerMatch> match) {
this.matches = matches;
this.match = match;
}
public ImmutableList getMatches() {
return matches;
}
public Optional extends RestxHandlerMatch> getMatch() {
return match;
}
@Override
public String toString() {
return "Match{" +
"matches=" + matches +
", match=" + match +
'}';
}
}
}