package restx.http;
import com.google.common.base.Optional;
import restx.AbstractRouteLifecycleListener;
import restx.RestxContext;
import restx.RestxHandler;
import restx.RestxHandlerMatch;
import restx.RestxRequest;
import restx.RestxRequestMatch;
import restx.RestxResponse;
import restx.RestxRoute;
import restx.RestxRouteFilter;
import restx.StdRestxRequestMatch;
import restx.WebException;
import restx.entity.StdEntityRoute;
import restx.factory.Component;
import java.io.IOException;
import java.util.Collection;
/**
* Date: 22/5/14
* Time: 20:54
*/
@Component(priority = -90)
public class ETagFilter implements RestxRouteFilter {
private final Collection<ETagProvider> providers;
public ETagFilter(Collection<ETagProvider> providers) {
this.providers = providers;
}
@Override
public Optional<RestxHandlerMatch> match(RestxRoute route) {
if (!(route instanceof StdEntityRoute)) {
return Optional.absent();
}
StdEntityRoute stdEntityRoute = (StdEntityRoute) route;
if (!(stdEntityRoute.getEntityResponseType() instanceof Class)) {
return Optional.absent();
}
Class<?> clazz = (Class<?>) stdEntityRoute.getEntityResponseType();
for (ETagProvider<?> provider : providers) {
if (provider.getEntityType().isAssignableFrom(clazz)) {
return Optional.of(new RestxHandlerMatch(new StdRestxRequestMatch("/*"), new ETagHandler<>(provider)));
}
}
return Optional.absent();
}
private static class ETagHandler<T> implements RestxHandler {
private final ETagProvider<T> provider;
public ETagHandler(ETagProvider<T> provider) {
this.provider = provider;
}
@Override
public void handle(RestxRequestMatch match, RestxRequest req, RestxResponse resp, RestxContext ctx) throws IOException {
ctx.nextHandlerMatch().handle(req, resp, ctx.withListener(new AbstractRouteLifecycleListener() {
@Override
@SuppressWarnings("unchecked")
public void onEntityOutput(RestxRoute route, RestxRequest req, RestxResponse resp, Optional<?> input, Optional<?> output) {
if (output.isPresent()) {
provider.provideETagFor((T) output.get()).handleIn(req, resp);
}
}
}));
}
}
}