org.wisdom.api.router.RouteBuilder Maven / Gradle / Ivy
/*
* #%L
* Wisdom-Framework
* %%
* Copyright (C) 2013 - 2014 Wisdom Framework
* %%
* 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.
* #L%
*/
package org.wisdom.api.router;
import com.google.common.base.Preconditions;
import org.wisdom.api.Controller;
import org.wisdom.api.http.HttpMethod;
import org.wisdom.api.http.Result;
import java.lang.reflect.Method;
/**
* Builder object to create routes.
* Example:
*
*
* Route route = new RouteBuilder().route(HttpMethod.GET).on("/foo/{id}").to(MyController, "index");
*
*
* Notice that route builder cannot be reused, and so can generate only one route object.
*/
public class RouteBuilder {
private static final String ERROR_CTRL = "Cannot find the controller method `";
private static final String ERROR_IN = "` in `";
private Controller controller;
private Method controllerMethod;
private HttpMethod httpMethod;
private String uri;
/**
* Sets the HTTP Method of the resulting route.
*
* @param method the HTTP method, must not be {@literal null}.
* @return the current route builder
*/
public RouteBuilder route(HttpMethod method) {
httpMethod = method;
return this;
}
/**
* Sets the URI (pattern) of the resulting route.
*
* @param uri the uri that can use the route uri pattern, must not be {@literal null}.
* @return the current route builder
*/
public RouteBuilder on(String uri) {
if (!uri.startsWith("/")) {
this.uri = "/" + uri;
} else {
this.uri = uri;
}
return this;
}
/**
* Sets the targeted action method of the resulting route.
*
* @param controller the controller object, must not be {@literal null}.
* @param method the method name, must not be {@literal null}.
* @return the current route builder
*/
public Route to(Controller controller, String method) {
Preconditions.checkNotNull(controller);
Preconditions.checkNotNull(method);
this.controller = controller;
try {
this.controllerMethod = verifyThatControllerAndMethodExists(controller.getClass(),
method);
} catch (Exception e) {
throw new IllegalArgumentException(ERROR_CTRL + method + ERROR_IN + controller
.getClass() + "`, or the method is invalid", e);
}
return _build();
}
/**
* Sets the targeted action method of the resulting route.
*
* @param controller the controller object, must not be {@literal null}.
* @param method the method name, must not be {@literal null}.
* @return the current route builder
*/
public Route to(Controller controller, Method method) {
Preconditions.checkNotNull(controller);
Preconditions.checkNotNull(method);
this.controller = controller;
try {
this.controllerMethod = method;
if (!method.getReturnType().isAssignableFrom(Result.class)) {
throw new NoSuchMethodException();
}
} catch (NoSuchMethodException e) {
throw new IllegalArgumentException(ERROR_CTRL + method + ERROR_IN + controller
.getClass() + "`, or the method does not return a " + Result.class.getName() + " object", e);
}
return _build();
}
/**
* Internal method building the route.
*
* @return the route.
*/
private Route _build() {
Preconditions.checkNotNull(controller);
Preconditions.checkNotNull(httpMethod);
Preconditions.checkNotNull(uri);
Preconditions.checkNotNull(httpMethod);
return new Route(httpMethod, uri, controller, controllerMethod);
}
/**
* Checks that the action method really exists.
*
* @param controller the controller object
* @param controllerMethod the method name
* @return the Method object.
* @throws NoSuchMethodException if the action method does not exist in the given controller object.
*/
private Method verifyThatControllerAndMethodExists(Class> controller,
String controllerMethod) throws NoSuchMethodException {
Method methodFromQueryingClass = null;
// 1. Make sure method is in class
// 2. Make sure only one method is there. Otherwise we cannot really
// know what to do with the parameters.
for (Method method : controller.getMethods()) {
if (method.getName().equals(controllerMethod)) {
if (methodFromQueryingClass == null) {
methodFromQueryingClass = method;
} else {
throw new NoSuchMethodException();
}
}
}
if (methodFromQueryingClass == null) {
throw new NoSuchMethodException("The method " + controllerMethod + " does not exist in " + controller.getName());
}
// make sure that the return type of that controller method
// is of type Result.
if (methodFromQueryingClass.getReturnType().isAssignableFrom(Result.class)) {
return methodFromQueryingClass;
} else {
throw new NoSuchMethodException("The method " + controllerMethod + " is declared in " + controller
.getName() + " but does not return a " + Result.class.getName() + " object.");
}
}
}