/*
 * Copyright 2002-2015 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.web.reactive.method.annotation;

import java.net.URI;
import java.net.URISyntaxException;
import java.nio.ByteBuffer;

import org.junit.Before;
import org.junit.Test;
import org.reactivestreams.Publisher;

import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.server.ReactiveServerHttpRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.context.support.StaticWebApplicationContext;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.reactive.method.annotation.RequestMappingHandlerMapping;

import static org.junit.Assert.assertEquals;

/**
 * @author Sebastien Deleuze
 */
public class RequestMappingHandlerMappingTests {

	private RequestMappingHandlerMapping mapping;

	@Before
	public void setup() {
		StaticWebApplicationContext wac = new StaticWebApplicationContext();
		wac.registerSingleton("handlerMapping", RequestMappingHandlerMapping.class);
		wac.registerSingleton("controller", TestController.class);
		wac.refresh();
		this.mapping = (RequestMappingHandlerMapping)wac.getBean("handlerMapping");
	}

	@Test
	public void path() throws Exception {
		ReactiveServerHttpRequest request = new MockServerHttpRequest(HttpMethod.GET, "boo");
		HandlerMethod handler = (HandlerMethod) this.mapping.getHandler(request);
		assertEquals(TestController.class.getMethod("boo"), handler.getMethod());
	}

	@Test
	public void method() throws Exception {
		ReactiveServerHttpRequest request = new MockServerHttpRequest(HttpMethod.POST, "foo");
		HandlerMethod handler = (HandlerMethod) this.mapping.getHandler(request);
		assertEquals(TestController.class.getMethod("postFoo"), handler.getMethod());

		request = new MockServerHttpRequest(HttpMethod.GET, "foo");
		handler = (HandlerMethod) this.mapping.getHandler(request);
		assertEquals(TestController.class.getMethod("getFoo"), handler.getMethod());

		request = new MockServerHttpRequest(HttpMethod.PUT, "foo");
		handler = (HandlerMethod) this.mapping.getHandler(request);
		assertEquals(TestController.class.getMethod("foo"), handler.getMethod());
	}


	@Controller
	@SuppressWarnings("unused")
	private static class TestController {

		@RequestMapping("foo")
		public String foo() {
			return "foo";
		}

		@RequestMapping(path = "foo", method = RequestMethod.POST)
		public String postFoo() {
			return "postFoo";
		}

		@RequestMapping(path = "foo", method = RequestMethod.GET)
		public String getFoo() {
			return "getFoo";
		}

		@RequestMapping("bar")
		public String bar() {
			return "bar";
		}

		@RequestMapping("boo")
		public String boo() {
			return "boo";
		}

	}

	private static class MockServerHttpRequest implements ReactiveServerHttpRequest{

		private HttpMethod method;

		private URI uri;

		public MockServerHttpRequest(HttpMethod method, String path) {
			this.method = method;
			try {
				this.uri = new URI(path);
			} catch (URISyntaxException ex) {
				throw new IllegalStateException("Could not get URI: " + ex.getMessage(), ex);
			}
		}

		@Override
		public Publisher<ByteBuffer> getBody() {
			return null;
		}

		@Override
		public HttpMethod getMethod() {
			return this.method;
		}

		@Override
		public URI getURI() {
			return this.uri;
		}

		@Override
		public HttpHeaders getHeaders() {
			return null;
		}
	}

}

@@ -1311,96 +1311,8 @@
 hod;
-%0Aimport org.springframework.web.reactive.method.annotation.RequestMappingHandlerMapping;
 %0A%0Aim
@@ -1490,16 +1490,17 @@
 pping;%0A%0A
+%0A
 %09@Before
@@ -1829,24 +1829,25 @@
 ping%22);%0A%09%7D%0A%0A
+%0A
 %09@Test%0A%09publ
@@ -2624,209 +2624,8 @@
 ());
-%0A%0A%09%09request = new MockServerHttpRequest(HttpMethod.PUT, %22foo%22);%0A%09%09handler = (HandlerMethod) this.mapping.getHandler(request);%0A%09%09assertEquals(TestController.class.getMethod(%22foo%22), handler.getMethod());
 %0A%09%7D%0A
@@ -2712,79 +2712,8 @@
  %7B%0A%0A
-%09%09@RequestMapping(%22foo%22)%0A%09%09public String foo() %7B%0A%09%09%09return %22foo%22;%0A%09%09%7D%0A%0A
 %09%09@R
@@ -3081,16 +3081,65 @@
 %09%7D%0A%0A%09%7D%0A%0A
+%0A%09/**%0A%09 * TODO: this is more widely needed.%0A%09 */%0A
 %09private
@@ -3210,16 +3210,17 @@
 pRequest
+ 
 %7B%0A%0A%09%09pri

Remove @MVC test with multiple matches