// Path: src/main/java/tech/greenfield/vertx/irked/Controller.java
// protected interface WebHandler extends Handler<Request> {}
// 
// Path: src/main/java/tech/greenfield/vertx/irked/auth/AuthorizationToken.java
// public class AuthorizationToken {
// 	
// 	private String token;
// 	private String type;
// 
// 	/**
// 	 * Constructor for token implementations is internal - use {@link #parse(String)} to create tokens
// 	 */
// 	protected AuthorizationToken() {
// 	}
// 	
// 	/**
// 	 * Parse an Authorization header text to create a specific token implementation
// 	 * 
// 	 * This method uses the convention of the first word in the Authorization value being the
// 	 * IANA HTTP Authentication Scheme Name, to dynamically load an appropriate implementation
// 	 * from the tech.greenfield.vertx.irked.auth.AuthorizationToken service loader. If the
// 	 * header value is incompatible (i.e. contains only one "word") then a token with the type
// 	 * "simple" will be returned. Otherwise if no supporting implementation is found, an instance
// 	 * of the {@link AuthorizationToken} class will be created.
// 	 * @param authorizationHeader value of the HTTP Authorization header
// 	 * @return a 
// 	 */
// 	public static AuthorizationToken parse(String authorizationHeader) {
// 		if (Objects.isNull(authorizationHeader))
// 			return new NullAuthorizationToken();
// 		String[] parts = authorizationHeader.split("\\s+",2);
// 		if (parts.length == 1)
// 			return new SimpleAuthrizationToken(parts[0]);
// 		for (AuthorizationToken a : ServiceLoader.load(AuthorizationToken.class)) {
// 			if (a.supports(parts[0]))
// 				return a.update(parts[0], parts[1]);
// 		}
// 		return new AuthorizationToken().update(parts[0], parts[1]);
// 	}
// 
// 	/**
// 	 * Update a service-loader loaded implementation with the actual details
// 	 * @param type IANA HTTP Authentication Scheme Name
// 	 * @param token token text
// 	 * @return itself for fluent calling
// 	 */
// 	protected AuthorizationToken update(String type, String token) {
// 		this.type = type;
// 		this.token = token;
// 		return this;
// 	}
// 
// 	/**
// 	 * Check whether an AuthorizationToken implementation supports the speciefied IANA HTTP Authentication Scheme Name
// 	 * @param type IANA HTTP Authentication Scheme Name
// 	 * @return whether this implementation supports the specified name
// 	 */
// 	protected boolean supports(String type) {
// 		return false;
// 	}
// 	
// 	/**
// 	 * Check whether the token implementation implements the specified IANA HTTP Authentication Scheme Name
// 	 * @param type IANA HTTP Authentication Scheme Name
// 	 * @return whether the implementation is valid for that scheme name
// 	 */
// 	public boolean is(String type) {
// 		return Objects.isNull(type) ? Objects.isNull(this.type) : type.equalsIgnoreCase(this.type);
// 	}
// 
// 	/**
// 	 * Retrieve the authorization token text
// 	 * @return authorization token text
// 	 */
// 	public String getToken() {
// 		return token;
// 	}
// 
// 	/**
// 	 * Retrieve the IANA HTTP Authentication Scheme Name this token is an implementation of
// 	 * @return IANA HTTP Authentication Scheme Name
// 	 */
// 	public String getType() {
// 		return type;
// 	}
// 	
// 	public String toString() {
// 		return type + " " + token;
// 	}
// }
// 
// Path: src/main/java/tech/greenfield/vertx/irked/exceptions/MissingBodyException.java
// public class MissingBodyException extends BadRequest {
// 
// 	private static final long serialVersionUID = 4458613845508649207L;
// 	
// 	public MissingBodyException() {
// 		super("Required request body is missing");
// 	}
// 
// }


import java.util.*;
import java.util.Map.Entry;
import java.util.stream.Stream;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.vertx.core.Future;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.http.HttpMethod;
import io.vertx.core.http.HttpServerRequest;
import io.vertx.core.http.HttpServerResponse;
import io.vertx.core.json.*;
import io.vertx.ext.web.RoutingContext;
import io.vertx.ext.web.impl.RoutingContextDecorator;
import io.vertx.ext.web.impl.RoutingContextInternal;
import tech.greenfield.vertx.irked.Controller.WebHandler;
import tech.greenfield.vertx.irked.auth.AuthorizationToken;
import tech.greenfield.vertx.irked.exceptions.MissingBodyException;
import tech.greenfield.vertx.irked.status.BadRequest;
import tech.greenfield.vertx.irked.status.OK;
	
	/**
	 * Helper method to terminate request processing with a custom response
	 * containing some text and the specifeid status line.
	 * @param content Text content to send in the response
	 * @param status An HttpError object representing the HTTP status to be sent
	 * @return a promise that will complete when the body was sent successfully
	 */
	public Future<Void> sendContent(String content, HttpError status) {
		return sendContent(content, status, "text/plain");
	}
	
	/**
	 * Helper method to terminate request processing with a custom response
	 * containing some text and the specifeid status line.
	 * @param content Text content to send in the response
	 * @return a promise that will complete when the body was sent successfully
	 */
	public Future<Void> sendContent(String content) {
		return sendContent(content, new OK(), "text/plain");
	}
	
	/**
	 * Helper method to terminate request processing with an HTTP error (non-200 OK) response.
	 * The resulting HTTP response will have the correct status line and an application/json content
	 * with a JSON encoded object containing the fields "status" set to "false" and "message" set
	 * to the {@link HttpError}'s message.
	 * @param status An HttpError object representing the HTTP status to be sent
	 * @return a promise that will complete when the body was sent successfully
	 */
// Path: src/main/java/tech/greenfield/vertx/irked/Controller.java
// protected interface WebHandler extends Handler<Request> {}
// 
// Path: src/main/java/tech/greenfield/vertx/irked/auth/AuthorizationToken.java
// public class AuthorizationToken {
// 	
// 	private String token;
// 	private String type;
// 
// 	/**
// 	 * Constructor for token implementations is internal - use {@link #parse(String)} to create tokens
// 	 */
// 	protected AuthorizationToken() {
// 	}
// 	
// 	/**
// 	 * Parse an Authorization header text to create a specific token implementation
// 	 * 
// 	 * This method uses the convention of the first word in the Authorization value being the
// 	 * IANA HTTP Authentication Scheme Name, to dynamically load an appropriate implementation
// 	 * from the tech.greenfield.vertx.irked.auth.AuthorizationToken service loader. If the
// 	 * header value is incompatible (i.e. contains only one "word") then a token with the type
// 	 * "simple" will be returned. Otherwise if no supporting implementation is found, an instance
// 	 * of the {@link AuthorizationToken} class will be created.
// 	 * @param authorizationHeader value of the HTTP Authorization header
// 	 * @return a 
// 	 */
// 	public static AuthorizationToken parse(String authorizationHeader) {
// 		if (Objects.isNull(authorizationHeader))
// 			return new NullAuthorizationToken();
// 		String[] parts = authorizationHeader.split("\\s+",2);
// 		if (parts.length == 1)
// 			return new SimpleAuthrizationToken(parts[0]);
// 		for (AuthorizationToken a : ServiceLoader.load(AuthorizationToken.class)) {
// 			if (a.supports(parts[0]))
// 				return a.update(parts[0], parts[1]);
// 		}
// 		return new AuthorizationToken().update(parts[0], parts[1]);
// 	}
// 
// 	/**
// 	 * Update a service-loader loaded implementation with the actual details
// 	 * @param type IANA HTTP Authentication Scheme Name
// 	 * @param token token text
// 	 * @return itself for fluent calling
// 	 */
// 	protected AuthorizationToken update(String type, String token) {
// 		this.type = type;
// 		this.token = token;
// 		return this;
// 	}
// 
// 	/**
// 	 * Check whether an AuthorizationToken implementation supports the speciefied IANA HTTP Authentication Scheme Name
// 	 * @param type IANA HTTP Authentication Scheme Name
// 	 * @return whether this implementation supports the specified name
// 	 */
// 	protected boolean supports(String type) {
// 		return false;
// 	}
// 	
// 	/**
// 	 * Check whether the token implementation implements the specified IANA HTTP Authentication Scheme Name
// 	 * @param type IANA HTTP Authentication Scheme Name
// 	 * @return whether the implementation is valid for that scheme name
// 	 */
// 	public boolean is(String type) {
// 		return Objects.isNull(type) ? Objects.isNull(this.type) : type.equalsIgnoreCase(this.type);
// 	}
// 
// 	/**
// 	 * Retrieve the authorization token text
// 	 * @return authorization token text
// 	 */
// 	public String getToken() {
// 		return token;
// 	}
// 
// 	/**
// 	 * Retrieve the IANA HTTP Authentication Scheme Name this token is an implementation of
// 	 * @return IANA HTTP Authentication Scheme Name
// 	 */
// 	public String getType() {
// 		return type;
// 	}
// 	
// 	public String toString() {
// 		return type + " " + token;
// 	}
// }
// 
// Path: src/main/java/tech/greenfield/vertx/irked/exceptions/MissingBodyException.java
// public class MissingBodyException extends BadRequest {
// 
// 	private static final long serialVersionUID = 4458613845508649207L;
// 	
// 	public MissingBodyException() {
// 		super("Required request body is missing");
// 	}
// 
// }


// Path: src/main/java/tech/greenfield/vertx/irked/Request.java
import java.util.*;
import java.util.Map.Entry;
import java.util.stream.Stream;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.vertx.core.Future;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.http.HttpMethod;
import io.vertx.core.http.HttpServerRequest;
import io.vertx.core.http.HttpServerResponse;
import io.vertx.core.json.*;
import io.vertx.ext.web.RoutingContext;
import io.vertx.ext.web.impl.RoutingContextDecorator;
import io.vertx.ext.web.impl.RoutingContextInternal;
import tech.greenfield.vertx.irked.Controller.WebHandler;
import tech.greenfield.vertx.irked.auth.AuthorizationToken;
import tech.greenfield.vertx.irked.exceptions.MissingBodyException;
import tech.greenfield.vertx.irked.status.BadRequest;
import tech.greenfield.vertx.irked.status.OK;

	
	/**
	 * Helper method to terminate request processing with a custom response
	 * containing some text and the specifeid status line.
	 * @param content Text content to send in the response
	 * @param status An HttpError object representing the HTTP status to be sent
	 * @return a promise that will complete when the body was sent successfully
	 */
	public Future<Void> sendContent(String content, HttpError status) {
		return sendContent(content, status, "text/plain");
	}
	
	/**
	 * Helper method to terminate request processing with a custom response
	 * containing some text and the specifeid status line.
	 * @param content Text content to send in the response
	 * @return a promise that will complete when the body was sent successfully
	 */
	public Future<Void> sendContent(String content) {
		return sendContent(content, new OK(), "text/plain");
	}
	
	/**
	 * Helper method to terminate request processing with an HTTP error (non-200 OK) response.
	 * The resulting HTTP response will have the correct status line and an application/json content
	 * with a JSON encoded object containing the fields "status" set to "false" and "message" set
	 * to the {@link HttpError}'s message.
	 * @param status An HttpError object representing the HTTP status to be sent
	 * @return a promise that will complete when the body was sent successfully
	 */
	public Future<Void> sendError(HttpError status) {