// Path: src/main/java/info/jdavid/ok/server/handler/RegexHandler.java
// @SuppressWarnings({ "WeakerAccess", "unused" })
// public abstract class RegexHandler implements Handler {
// 
//   final Pattern pattern;
//   final List<String> methods;
// 
//   /**
//    * Creates an handler that will accept a request with the specified methods,
//    * whose path matches the specified regular expression.
//    * @param methods the request methods.
//    * @param regex the regular expression.
//    */
//   protected RegexHandler(final Collection<String> methods, final String regex) {
//     if (methods.isEmpty()) {
//       throw new NullPointerException("The accepted request method cannot be null.");
//     }
//     final List<String> list = this.methods = new ArrayList<>(methods.size());
//     for (final String method: methods) {
//       list.add(method.toUpperCase());
//     }
//     pattern = Pattern.compile(regex);
//   }
// 
//   /**
//    * Creates an handler that will accept a request with the specified method, whose path matches the specified
//    * regular expression.
//    * @param method the request method.
//    * @param regex the regular expression.
//    */
//   protected RegexHandler(final String method, final String regex) {
//     methods = Collections.singletonList(method.toUpperCase());
//     pattern = Pattern.compile(regex);
//   }
// 
//   @Override public Handler setup() { return this; }
// 
//   @Override
//   public @Nullable String[] matches(final String method, final HttpUrl url) {
//     if (methods.contains(method)) {
//       final String encodedPath = url.encodedPath();
//       final Matcher matcher = pattern.matcher(url.encodedPath());
//       if (matcher.find()) {
//         if (matcher.start() > 0) return null;
//         if (matcher.end() < encodedPath.length()) return null;
//         final int n = matcher.groupCount();
//         final String[] params = new String[n];
//         for (int i=0; i<n; ++i) {
//           params[i] = matcher.group(i + 1);
//         }
//         return params;
//       }
//     }
//     return null;
//   }
// 
//   /**
//    * Adds a check on the request methods and path to the specified handler.
//    * @param methods the accepted methods.
//    * @param regex the regular expression that the the url path should match.
//    * @param delegate the delegate handler.
//    * @return the handler with the additional requirements.
//    */
//   public static Handler create(final Collection<String> methods, final String regex, final Handler delegate) {
//     return new RegexHandlerWrapper(methods, regex, delegate);
//   }
// 
//   /**
//    * Adds a check on the request method and path to the specified handler.
//    * @param method the accepted method.
//    * @param regex the regular expression that the the url path should match.
//    * @param delegate the delegate handler.
//    * @return the handler with the additional requirements.
//    */
//   public static Handler create(final String method, final String regex, final Handler delegate) {
//     //noinspection Duplicates
//     return new RegexHandlerWrapper(method, regex, delegate);
//   }
// 
//   static class RegexHandlerWrapper extends RegexHandler {
// 
//     final Handler delegate;
// 
//     protected RegexHandlerWrapper(final Collection<String> methods, final String regex, final Handler delegate) {
//       super(methods, regex);
//       this.delegate = delegate;
//     }
// 
//     protected RegexHandlerWrapper(final String method, final String regex, final Handler delegate) {
//       super(method, regex);
//       this.delegate = delegate;
//     }
// 
//     @Override public Handler setup() {
//       delegate.setup();
//       return this;
//     }
// 
//     @Override public String[] matches(final String method, final HttpUrl url) {
//       return super.matches(method, url) == null ? null : delegate.matches(method, url);
//     }
// 
//     @Override public Response.Builder handle(final Request request, final String[] params) {
//       return delegate.handle(request, params);
//     }
// 
//   }
// 
// }
// 
// Path: src/main/java/info/jdavid/ok/server/handler/Request.java
// public final class Request {
// 
//   /**
//    * The client ip.
//    */
//   public final String clientIp;
//   /**
//    * true when the request is being served with the HTTP 2 protocol rather than HTTP 1.1.
//    */
//   public final boolean http2;
//   /**
//    * The request method.
//    */
//   public final String method;
//   /**
//    * The request url.
//    */
//   public final HttpUrl url;
//   /**
//    * The request headers.
//    */
//   public final Headers headers;
//   /**
//    * The request body.
//    */
//   public @Nullable final Buffer body;
// 
//   public Request(final String clientIp, final boolean http2,
//                  final String method, final HttpUrl url,
//                  final Headers headers, @Nullable final Buffer body) {
//     this.clientIp = clientIp;
//     this.method = method;
//     this.http2 = http2;
//     this.url = url;
//     this.headers = headers;
//     this.body = body;
//   }
// 
// }


import java.io.IOException;
import java.util.concurrent.TimeUnit;
import info.jdavid.ok.server.handler.RegexHandler;
import info.jdavid.ok.server.handler.Request;
import okhttp3.ConnectionPool;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.RequestBody;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.*;
package info.jdavid.ok.server;





@SuppressWarnings("ConstantConditions")
public class RegexHandlerTest {

  private static final HttpServer SERVER = new HttpServer(); //.dispatcher(new Dispatcher.Logged());

  private static final OkHttpClient client = new OkHttpClient();

  private static OkHttpClient client() {
    return  client.newBuilder().
      readTimeout(0, TimeUnit.SECONDS).
      retryOnConnectionFailure(false).
      connectTimeout(60, TimeUnit.SECONDS).
      connectionPool(new ConnectionPool(0, 1L, TimeUnit.SECONDS)).
      build();
  }

  @BeforeClass
  public static void startServer() throws IOException {
    SERVER.
      port(8080).
      maxRequestSize(512).
      requestHandler(new RequestHandlerChain().
        add(new RegexHandler("GET", "/r1") {
// Path: src/main/java/info/jdavid/ok/server/handler/RegexHandler.java
// @SuppressWarnings({ "WeakerAccess", "unused" })
// public abstract class RegexHandler implements Handler {
// 
//   final Pattern pattern;
//   final List<String> methods;
// 
//   /**
//    * Creates an handler that will accept a request with the specified methods,
//    * whose path matches the specified regular expression.
//    * @param methods the request methods.
//    * @param regex the regular expression.
//    */
//   protected RegexHandler(final Collection<String> methods, final String regex) {
//     if (methods.isEmpty()) {
//       throw new NullPointerException("The accepted request method cannot be null.");
//     }
//     final List<String> list = this.methods = new ArrayList<>(methods.size());
//     for (final String method: methods) {
//       list.add(method.toUpperCase());
//     }
//     pattern = Pattern.compile(regex);
//   }
// 
//   /**
//    * Creates an handler that will accept a request with the specified method, whose path matches the specified
//    * regular expression.
//    * @param method the request method.
//    * @param regex the regular expression.
//    */
//   protected RegexHandler(final String method, final String regex) {
//     methods = Collections.singletonList(method.toUpperCase());
//     pattern = Pattern.compile(regex);
//   }
// 
//   @Override public Handler setup() { return this; }
// 
//   @Override
//   public @Nullable String[] matches(final String method, final HttpUrl url) {
//     if (methods.contains(method)) {
//       final String encodedPath = url.encodedPath();
//       final Matcher matcher = pattern.matcher(url.encodedPath());
//       if (matcher.find()) {
//         if (matcher.start() > 0) return null;
//         if (matcher.end() < encodedPath.length()) return null;
//         final int n = matcher.groupCount();
//         final String[] params = new String[n];
//         for (int i=0; i<n; ++i) {
//           params[i] = matcher.group(i + 1);
//         }
//         return params;
//       }
//     }
//     return null;
//   }
// 
//   /**
//    * Adds a check on the request methods and path to the specified handler.
//    * @param methods the accepted methods.
//    * @param regex the regular expression that the the url path should match.
//    * @param delegate the delegate handler.
//    * @return the handler with the additional requirements.
//    */
//   public static Handler create(final Collection<String> methods, final String regex, final Handler delegate) {
//     return new RegexHandlerWrapper(methods, regex, delegate);
//   }
// 
//   /**
//    * Adds a check on the request method and path to the specified handler.
//    * @param method the accepted method.
//    * @param regex the regular expression that the the url path should match.
//    * @param delegate the delegate handler.
//    * @return the handler with the additional requirements.
//    */
//   public static Handler create(final String method, final String regex, final Handler delegate) {
//     //noinspection Duplicates
//     return new RegexHandlerWrapper(method, regex, delegate);
//   }
// 
//   static class RegexHandlerWrapper extends RegexHandler {
// 
//     final Handler delegate;
// 
//     protected RegexHandlerWrapper(final Collection<String> methods, final String regex, final Handler delegate) {
//       super(methods, regex);
//       this.delegate = delegate;
//     }
// 
//     protected RegexHandlerWrapper(final String method, final String regex, final Handler delegate) {
//       super(method, regex);
//       this.delegate = delegate;
//     }
// 
//     @Override public Handler setup() {
//       delegate.setup();
//       return this;
//     }
// 
//     @Override public String[] matches(final String method, final HttpUrl url) {
//       return super.matches(method, url) == null ? null : delegate.matches(method, url);
//     }
// 
//     @Override public Response.Builder handle(final Request request, final String[] params) {
//       return delegate.handle(request, params);
//     }
// 
//   }
// 
// }
// 
// Path: src/main/java/info/jdavid/ok/server/handler/Request.java
// public final class Request {
// 
//   /**
//    * The client ip.
//    */
//   public final String clientIp;
//   /**
//    * true when the request is being served with the HTTP 2 protocol rather than HTTP 1.1.
//    */
//   public final boolean http2;
//   /**
//    * The request method.
//    */
//   public final String method;
//   /**
//    * The request url.
//    */
//   public final HttpUrl url;
//   /**
//    * The request headers.
//    */
//   public final Headers headers;
//   /**
//    * The request body.
//    */
//   public @Nullable final Buffer body;
// 
//   public Request(final String clientIp, final boolean http2,
//                  final String method, final HttpUrl url,
//                  final Headers headers, @Nullable final Buffer body) {
//     this.clientIp = clientIp;
//     this.method = method;
//     this.http2 = http2;
//     this.url = url;
//     this.headers = headers;
//     this.body = body;
//   }
// 
// }


// Path: src/test/java/info/jdavid/ok/server/RegexHandlerTest.java
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import info.jdavid.ok.server.handler.RegexHandler;
import info.jdavid.ok.server.handler.Request;
import okhttp3.ConnectionPool;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.RequestBody;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.*;

package info.jdavid.ok.server;





@SuppressWarnings("ConstantConditions")
public class RegexHandlerTest {

  private static final HttpServer SERVER = new HttpServer(); //.dispatcher(new Dispatcher.Logged());

  private static final OkHttpClient client = new OkHttpClient();

  private static OkHttpClient client() {
    return  client.newBuilder().
      readTimeout(0, TimeUnit.SECONDS).
      retryOnConnectionFailure(false).
      connectTimeout(60, TimeUnit.SECONDS).
      connectionPool(new ConnectionPool(0, 1L, TimeUnit.SECONDS)).
      build();
  }

  @BeforeClass
  public static void startServer() throws IOException {
    SERVER.
      port(8080).
      maxRequestSize(512).
      requestHandler(new RequestHandlerChain().
        add(new RegexHandler("GET", "/r1") {
          @Override public Response.Builder handle(final Request request, final String[] params) {