package com.biasedbit.http.client.processor;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.handler.codec.http.HttpResponse;
/**
* HTTP response body consumer.
* <p/>
* A {@code ResponseProcessor} is a class the is fed with the contents of the HTTP response body and returns the
* result of converting that body into an object.
* <p/>
* A response processor is given the choice to decide whether it wants to process the response body for a given request
* by having its {@link #willProcessResponse(org.jboss.netty.handler.codec.http.HttpResponse)} called prior to any of
* the data appending methods.
* <p/>
* An example would be a processor that only wants to consume the body if the content type is 'text/plain'.
* <p/>
* <pre class="code">
* boolean willProcessResponse(HttpResponse response) {
* if ("text/plain".equals(HttpHeaders.getHeader(response, HttpHeaders.Names.CONTENT_TYPE))) {
* return true;
* }
* return false;
* }</pre>
* Processors may also choose to perform some kind of setup when {@link
* #willProcessResponse(org.jboss.netty.handler.codec.http.HttpResponse)} is called:
* <pre class="code">
* boolean willProcessResponse(HttpResponse response) {
* if ("text/plain".equals(HttpHeaders.getHeader(response, HttpHeaders.Names.CONTENT_TYPE))) {
* this.processPlainText = true;
* return true;
* }
* if ("text/html".equals(HttpHeaders.getHeader(response, HttpHeaders.Names.CONTENT_TYPE))) {
* this.processPlainText = false;
* return true;
* }
* return false;
* }</pre>
* <p/>
* Since the body can be split into {@code org.jboss.netty.handler.codec.http.HttpChunk}s, methods {@link
* #addData(org.jboss.netty.buffer.ChannelBuffer)} and {@link #addLastData(org.jboss.netty.buffer.ChannelBuffer)}
* provide a simple way to append data that is not fully available when the request headers are read.
* <div class="note">
* <div class="header">Note:</div>
* A {@code ResponseProcessor} is tipically stateful. Unless you're using a completely stateless response processor
* such as {@link DiscardProcessor}, you <strong>must</strong> provide a different instance for each {@link
* com.biasedbit.http.client.HttpClient#execute(String, int, org.jboss.netty.handler.codec.http.HttpRequest,
* ResponseProcessor)} call.
* </div>
*
* @see DiscardProcessor
* @see BodyAsStringProcessor
*
* @author <a href="http://biasedbit.com/">Bruno de Carvalho</a>
*/
public interface ResponseProcessor<T> {
/**
* Query to determine if this processor has the necessary conditions to process this response.
* <p/>
* More complex stateful response processors may use some of the information on the headers to determine how they
* will parse the data provided.
*
* @param response The HTTP response received.
*
* @return {@code true} if this processor will process the provided response, {@code false} otherwise.
*
* @throws Exception Thrown on underlying processing exception.
*/
boolean willProcessResponse(HttpResponse response)
throws Exception;
/**
* Append data to the processor's buffer.
*
* @param content Data received as part of the HTTP response body.
*
* @throws Exception Thrown on underlying processing exception.
*/
void addData(ChannelBuffer content)
throws Exception;
/**
* Append the last piece of data to the processor's buffer.
* <p/>
* The processor may choose to perform its operations on the buffer and transforming it the object to return once
* this last piece of data is received. Alternatively, it can also perform that operation only when {@link
* #getProcessedResponse()} is called.
*
* @param content Data received as part of the HTTP response body.
*
* @throws Exception Thrown on underlying processing exception.
*/
void addLastData(ChannelBuffer content)
throws Exception;
/**
* Returns the result of processing the HTTP response body. Result varies according to implementation.
* <p/>
* <div class="note">
* <div class="header">Note:</div>
* Implementations may choose to return non-{@code null} results
* when no data is consumed so {@link com.biasedbit.http.client.future.RequestFuture#setSuccess(Object,
* org.jboss.netty.handler.codec.http.HttpResponse)} should always be called with {@code getProcessedResponse()}
* rather than {@code null}.
* </div>
*
* @return The result of processing the HTTP response body or some default value in case of failure
* (can be {@code null}).
*/
T getProcessedResponse();
}