Permalink
Browse files

linkTo support to overloaded methods

  • Loading branch information...
1 parent 5966ba6 commit 8545f8c2cb269fc715dcc2887f4b32c8625e9817 Nykolas Lima committed Nov 13, 2012
@@ -0,0 +1,98 @@
+/***
+ * Copyright (c) 2009 Caelum - www.caelum.com.br/opensource
+ * All rights reserved.
+ *
+ * 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 br.com.caelum.vraptor.util;
+
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Utility methods to handle with reflection
+ *
+ * @author Nykolas Lima
+ *
+ */
+public class ReflectionUtils {
+ @SuppressWarnings("serial")
+ private static final Map<Class<?>, Class<?>> PRIMITIVE_TO_WRAPPERS = new HashMap<Class<?>, Class<?>>() {{
+ put(boolean.class, Boolean.class);
+ put(byte.class, Byte.class);
+ put(char.class, Character.class);
+ put(double.class, Double.class);
+ put(float.class, Float.class);
+ put(int.class, Integer.class);
+ put(long.class, Long.class);
+ put(short.class, Short.class);
+ }};
+
+ public static Method findMethodWithName(Class<?> type, String name, List<Object> args) {
+ return findMethodWithName(type, name, getClasses(args));
+ }
+
+ public static Method findMethodWithName(Class<?> type, String name, Class<?>[] args) {
+ if (args != null && args.length > 0)
+ return findMethodWithNameAndArgs(type, name, args);
+ else
+ return findMethodWithNameAndNoArgs(type, name);
+ }
+
+ public static Method findMethodWithNameAndArgs(Class<?> type, String name, Class<?>[] args) {
+ for (Method method : type.getDeclaredMethods()) {
+ if (!method.isBridge() && method.getName().equals(name) && isParamsEquals(method.getParameterTypes(), args)) {
+ return method;
+ }
+ }
+ if (type.getSuperclass().equals(Object.class)) {
+ throw new IllegalArgumentException("There are no methods on " + type + " named " + name);
+ }
+ return findMethodWithNameAndNoArgs(type.getSuperclass(), name);
+ }
+
+ public static Method findMethodWithNameAndNoArgs(Class<?> type, String name) {
+ for (Method method : type.getDeclaredMethods()) {
+ if (!method.isBridge() && method.getName().equals(name)) {
+ return method;
+ }
+ }
+ if (type.getSuperclass().equals(Object.class)) {
+ throw new IllegalArgumentException("There are no methods on " + type + " named " + name);
+ }
+ return findMethodWithNameAndNoArgs(type.getSuperclass(), name);
+ }
+
+ public static boolean isParamsEquals(Class<?>[] params1, Class<?>[] params2) {
+ if (params1.length != params2.length) return false;
+ for (int i = 0; i < params1.length; i++) {
+ if(params1[i].isPrimitive()) {
+ if (!PRIMITIVE_TO_WRAPPERS.get(params1[i]).isAssignableFrom(params2[i])) return false;
+ } else {
+ if (!params1[i].isAssignableFrom(params2[i])) return false;
+ }
+ }
+ return true;
+ }
+
+ public static Class<?>[] getClasses(List<Object> params) {
+ Class<?>[] classes = new Class<?>[params.size()];
+ for(int i = 0; i < params.size(); i ++) {
+ classes[i] = params.get(i).getClass();
+ }
+ return classes;
+ }
+}
@@ -16,7 +16,9 @@
package br.com.caelum.vraptor.view;
import java.lang.reflect.Method;
+import java.util.ArrayList;
import java.util.Collections;
+import java.util.List;
import java.util.Map;
import javax.servlet.ServletContext;
@@ -25,6 +27,7 @@
import org.slf4j.LoggerFactory;
import br.com.caelum.vraptor.http.route.Router;
+import br.com.caelum.vraptor.util.ReflectionUtils;
import com.google.common.collect.ForwardingMap;
@@ -74,22 +77,10 @@ public LinkMethod(Class<?> controller) {
@Override
public Linker get(Object key) {
- Method method = findMethodWithName(controller, (String) key);
-
- return new Linker(controller, method);
- }
- private Method findMethodWithName(Class<?> type, String name) {
- for (Method method : type.getDeclaredMethods()) {
- if (!method.isBridge() && method.getName().equals(name)) {
- return method;
- }
- }
- if (type.getSuperclass().equals(Object.class)) {
- throw new IllegalArgumentException("There are no methods on " + controller + " named " + name);
- }
- return findMethodWithName(type.getSuperclass(), name);
+ return new Linker(controller, key.toString());
}
+
@Override
public String toString() {
throw new IllegalArgumentException("uncomplete linkTo[" + controller.getSimpleName() + "]. You must specify the method.");
@@ -98,27 +89,25 @@ public String toString() {
class Linker extends ForwardingMap<Object, Linker> {
- private final Object[] args;
- private final Method method;
+ private final List<Object> args;
+ private final String methodName;
private final Class<?> controller;
- private final int filled;
- public Linker(Class<?> controller, Method method) {
- this(controller, method, new Object[method.getParameterTypes().length], 0);
+ public Linker(Class<?> controller, String methodName) {
+ this(controller, methodName, new ArrayList<Object>());
}
- public Linker(Class<?> controller, Method method, Object[] args, int filled) {
+ public Linker(Class<?> controller, String methodName, List<Object> args) {
this.controller = controller;
- this.method = method;
+ this.methodName = methodName;
this.args = args;
- this.filled = filled;
}
@Override
public Linker get(Object key) {
- Object[] newArgs = args.clone();
- newArgs[filled] = key;
- return new Linker(controller, method, newArgs, filled + 1);
+ List<Object> newArgs = new ArrayList<Object>(args);
+ newArgs.add(key);
+ return new Linker(controller, methodName, newArgs);
}
@Override
@@ -128,7 +117,8 @@ public Linker get(Object key) {
@Override
public String toString() {
- return context.getContextPath() + router.urlFor(controller, method, args);
+ Method method = ReflectionUtils.findMethodWithName(controller, methodName, args);
+ return context.getContextPath() + router.urlFor(controller, method, args.toArray());
}
}
}
@@ -38,7 +38,7 @@ public void shouldThrowExceptionWhenInvokingInexistantMethod() {
}
@Test
public void shouldReturnWantedUrlWithoutArgs() {
- when(router.urlFor(TestController.class, TestController.class.getDeclaredMethods()[0], new Object[2])).thenReturn("/expectedURL");
+ when(router.urlFor(TestController.class, TestController.class.getDeclaredMethods()[0], new Object[0])).thenReturn("/expectedURL");
//${linkTo[TestController].method}
String uri = handler.get(TestController.class).get("method").toString();
@@ -63,10 +63,22 @@ public void shouldReturnWantedUrlForOverrideMethodWithParamArgs() throws NoSuchM
String uri = handler.get(SubGenericController.class).get("method").get(a).toString();
assertThat(uri, is("/path/expectedURL"));
}
+
+ @Test
+ public void shouldReturnWantedUrlForMethodsWithSameName() {
+ String a = "test";
+ when(router.urlFor(TestController.class, TestController.class.getDeclaredMethods()[1], a)).thenReturn("/expectedUrl");
+ //${linkTo[TestController].method['test']}
+ String uri = handler.get(TestController.class).get("method").get(a).toString();
+ assertThat(uri, is("/path/expectedUrl"));
+ }
static class TestController {
void method(String a, int b) {
}
+ void method(String a) {
+
+ }
}
}

0 comments on commit 8545f8c

Please sign in to comment.