Skip to content

Commit

Permalink
Route with lambdas (functional methods)
Browse files Browse the repository at this point in the history
  • Loading branch information
jjlauer committed Sep 9, 2016
1 parent b9c79c8 commit 2232015
Show file tree
Hide file tree
Showing 19 changed files with 1,225 additions and 251 deletions.
182 changes: 182 additions & 0 deletions ninja-core/src/main/java/ninja/ControllerMethods.java
@@ -0,0 +1,182 @@
/*
* Copyright 2016 ninjaframework.
*
* 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 ninja;

import java.io.Serializable;

/**
* Functional interfaces for Ninja controller methods accepting up to X
* number of arguments with type inference.
*/
public class ControllerMethods {

/**
* Marker interface that all functional interfaces will extend. Useful for
* simple validation an object is a ControllerMethod.
*/
static public interface ControllerMethod extends Serializable { }

@FunctionalInterface
static public interface ControllerMethod0 extends ControllerMethod {
Result apply() throws Exception;
}

@FunctionalInterface
static public interface ControllerMethod1<A> extends ControllerMethod {
Result apply(A a) throws Exception;
}

@FunctionalInterface
static public interface ControllerMethod2<A,B> extends ControllerMethod {
Result apply(A a, B b) throws Exception;
}

@FunctionalInterface
static public interface ControllerMethod3<A,B,C> extends ControllerMethod {
Result apply(A a, B b, C c) throws Exception;
}

@FunctionalInterface
static public interface ControllerMethod4<A,B,C,D> extends ControllerMethod {
Result apply(A a, B b, C c, D d) throws Exception;
}

@FunctionalInterface
static public interface ControllerMethod5<A,B,C,D,E> extends ControllerMethod {
Result apply(A a, B b, C c, D d, E e) throws Exception;
}

@FunctionalInterface
static public interface ControllerMethod6<A,B,C,D,E,F> extends ControllerMethod {
Result apply(A a, B b, C c, D d, E e, F f) throws Exception;
}

@FunctionalInterface
static public interface ControllerMethod7<A,B,C,D,E,F,G> extends ControllerMethod {
Result apply(A a, B b, C c, D d, E e, F f, G g) throws Exception;
}

@FunctionalInterface
static public interface ControllerMethod8<A,B,C,D,E,F,G,H> extends ControllerMethod {
Result apply(A a, B b, C c, D d, E e, F f, G g, H h) throws Exception;
}

@FunctionalInterface
static public interface ControllerMethod9<A,B,C,D,E,F,G,H,I> extends ControllerMethod {
Result apply(A a, B b, C c, D d, E e, F f, G g, H h, I i) throws Exception;
}

@FunctionalInterface
static public interface ControllerMethod10<A,B,C,D,E,F,G,H,I,J> extends ControllerMethod {
Result apply(A a, B b, C c, D d, E e, F f, G g, H h, I i, J j) throws Exception;
}

@FunctionalInterface
static public interface ControllerMethod11<A,B,C,D,E,F,G,H,I,J,K> extends ControllerMethod {
Result apply(A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k) throws Exception;
}

@FunctionalInterface
static public interface ControllerMethod12<A,B,C,D,E,F,G,H,I,J,K,L> extends ControllerMethod {
Result apply(A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k, L l) throws Exception;
}

@FunctionalInterface
static public interface ControllerMethod13<A,B,C,D,E,F,G,H,I,J,K,L,M> extends ControllerMethod {
Result apply(A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k, L l, M m) throws Exception;
}

@FunctionalInterface
static public interface ControllerMethod14<A,B,C,D,E,F,G,H,I,J,K,L,M,N> extends ControllerMethod {
Result apply(A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k, L l, M m, N n) throws Exception;
}

@FunctionalInterface
static public interface ControllerMethod15<A,B,C,D,E,F,G,H,I,J,K,L,M,N,O> extends ControllerMethod {
Result apply(A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k, L l, M m, N n, O o) throws Exception;
}

// if you need more than 15 arguments then we recommend using the
// legacy Class, methodName strategy

// helper methods to allow classes to accept `ControllerMethod` but still
// have the compiler create the correct functional method under-the-hood

static public ControllerMethod0 of(ControllerMethod0 functionalMethod) {
return functionalMethod;
}

static public <A> ControllerMethod1<A> of(ControllerMethod1<A> functionalMethod) {
return functionalMethod;
}

static public <A,B> ControllerMethod2<A,B> of(ControllerMethod2<A,B> functionalMethod) {
return functionalMethod;
}

static public <A,B,C> ControllerMethod3<A,B,C> of(ControllerMethod3<A,B,C> functionalMethod) {
return functionalMethod;
}

static public <A,B,C,D> ControllerMethod4<A,B,C,D> of(ControllerMethod4<A,B,C,D> functionalMethod) {
return functionalMethod;
}

static public <A,B,C,D,E> ControllerMethod5<A,B,C,D,E> of(ControllerMethod5<A,B,C,D,E> functionalMethod) {
return functionalMethod;
}

static public <A,B,C,D,E,F> ControllerMethod6<A,B,C,D,E,F> of(ControllerMethod6<A,B,C,D,E,F> functionalMethod) {
return functionalMethod;
}

static public <A,B,C,D,E,F,G> ControllerMethod7<A,B,C,D,E,F,G> of(ControllerMethod7<A,B,C,D,E,F,G> functionalMethod) {
return functionalMethod;
}

static public <A,B,C,D,E,F,G,H> ControllerMethod8<A,B,C,D,E,F,G,H> of(ControllerMethod8<A,B,C,D,E,F,G,H> functionalMethod) {
return functionalMethod;
}

static public <A,B,C,D,E,F,G,H,I> ControllerMethod9<A,B,C,D,E,F,G,H,I> of(ControllerMethod9<A,B,C,D,E,F,G,H,I> functionalMethod) {
return functionalMethod;
}

static public <A,B,C,D,E,F,G,H,I,J> ControllerMethod10<A,B,C,D,E,F,G,H,I,J> of(ControllerMethod10<A,B,C,D,E,F,G,H,I,J> functionalMethod) {
return functionalMethod;
}

static public <A,B,C,D,E,F,G,H,I,J,K> ControllerMethod11<A,B,C,D,E,F,G,H,I,J,K> of(ControllerMethod11<A,B,C,D,E,F,G,H,I,J,K> functionalMethod) {
return functionalMethod;
}

static public <A,B,C,D,E,F,G,H,I,J,K,L> ControllerMethod12<A,B,C,D,E,F,G,H,I,J,K,L> of(ControllerMethod12<A,B,C,D,E,F,G,H,I,J,K,L> functionalMethod) {
return functionalMethod;
}

static public <A,B,C,D,E,F,G,H,I,J,K,L,M> ControllerMethod13<A,B,C,D,E,F,G,H,I,J,K,L,M> of(ControllerMethod13<A,B,C,D,E,F,G,H,I,J,K,L,M> functionalMethod) {
return functionalMethod;
}

static public <A,B,C,D,E,F,G,H,I,J,K,L,M,N> ControllerMethod14<A,B,C,D,E,F,G,H,I,J,K,L,M,N> of(ControllerMethod14<A,B,C,D,E,F,G,H,I,J,K,L,M,N> functionalMethod) {
return functionalMethod;
}

static public <A,B,C,D,E,F,G,H,I,J,K,L,M,N,O> ControllerMethod15<A,B,C,D,E,F,G,H,I,J,K,L,M,N,O> of(ControllerMethod15<A,B,C,D,E,F,G,H,I,J,K,L,M,N,O> functionalMethod) {
return functionalMethod;
}

}
6 changes: 4 additions & 2 deletions ninja-core/src/main/java/ninja/FilterChain.java
Expand Up @@ -20,11 +20,13 @@
* A filter chain * A filter chain
*/ */
public interface FilterChain { public interface FilterChain {

/** /**
* Pass the request to the next filter * Pass the request to the next filter
* *
* @param context * @param context The context for the request
* The context for the request * @return The result
*/ */
Result next(Context context); Result next(Context context);

} }
22 changes: 7 additions & 15 deletions ninja-core/src/main/java/ninja/FilterChainEnd.java
Expand Up @@ -26,28 +26,20 @@
* @author James Roper * @author James Roper
*/ */
class FilterChainEnd implements FilterChain { class FilterChainEnd implements FilterChain {
private Provider<?> controllerProvider;
private ControllerMethodInvoker controllerMethodInvoker; private final Provider<?> targetObjectProvider;
private Result result; private final ControllerMethodInvoker controllerMethodInvoker;


FilterChainEnd(Result result) { FilterChainEnd(Provider<?> targetObjectProvider,
this.result = result;
}

FilterChainEnd(Provider<?> controllerProvider,
ControllerMethodInvoker controllerMethodInvoker) { ControllerMethodInvoker controllerMethodInvoker) {
this.controllerProvider = controllerProvider; this.targetObjectProvider = targetObjectProvider;
this.controllerMethodInvoker = controllerMethodInvoker; this.controllerMethodInvoker = controllerMethodInvoker;
} }


@Override @Override
public Result next(Context context) { public Result next(Context context) {
if(result != null) { Result controllerResult = (Result)controllerMethodInvoker.invoke(
return result; targetObjectProvider.get(), context);
}

Result controllerResult = (Result) controllerMethodInvoker.invoke(
controllerProvider.get(), context);


if (controllerResult instanceof AsyncResult) { if (controllerResult instanceof AsyncResult) {
// Make sure handle async has been called // Make sure handle async has been called
Expand Down
1 change: 1 addition & 0 deletions ninja-core/src/main/java/ninja/FilterChainImpl.java
Expand Up @@ -22,6 +22,7 @@
* Implementation of the filter chain * Implementation of the filter chain
*/ */
class FilterChainImpl implements FilterChain { class FilterChainImpl implements FilterChain {

private final Provider<? extends Filter> filterProvider; private final Provider<? extends Filter> filterProvider;
private final FilterChain next; private final FilterChain next;


Expand Down
6 changes: 1 addition & 5 deletions ninja-core/src/main/java/ninja/Route.java
Expand Up @@ -45,7 +45,6 @@ public class Route {
//private static final String PATTERN_FOR_VARIABLE_PARTS_OF_ROUTE = "\\{.*?:\\s(.*?)\\}"; //private static final String PATTERN_FOR_VARIABLE_PARTS_OF_ROUTE = "\\{.*?:\\s(.*?)\\}";
private final String httpMethod; private final String httpMethod;
private final String uri; private final String uri;
private final Class controllerClass;
private final Method controllerMethod; private final Method controllerMethod;
private final FilterChain filterChain; private final FilterChain filterChain;


Expand All @@ -54,15 +53,12 @@ public class Route {


public Route(String httpMethod, public Route(String httpMethod,
String uri, String uri,
Class controllerClass,
Method controllerMethod, Method controllerMethod,
FilterChain filterChain) { FilterChain filterChain) {
this.httpMethod = httpMethod; this.httpMethod = httpMethod;
this.uri = uri; this.uri = uri;
this.controllerClass = controllerClass;
this.controllerMethod = controllerMethod; this.controllerMethod = controllerMethod;
this.filterChain = filterChain; this.filterChain = filterChain;

parameterNames = ImmutableList.copyOf(doParseParameters(uri)); parameterNames = ImmutableList.copyOf(doParseParameters(uri));
regex = Pattern.compile(convertRawUriToRegex(uri)); regex = Pattern.compile(convertRawUriToRegex(uri));
} }
Expand All @@ -80,7 +76,7 @@ public String getUri() {
} }


public Class<?> getControllerClass() { public Class<?> getControllerClass() {
return controllerClass; return controllerMethod != null ? controllerMethod.getDeclaringClass() : null;
} }


public FilterChain getFilterChain() { public FilterChain getFilterChain() {
Expand Down
35 changes: 34 additions & 1 deletion ninja-core/src/main/java/ninja/RouteBuilder.java
Expand Up @@ -16,16 +16,49 @@


package ninja; package ninja;


import ninja.ControllerMethods.*;
import ninja.utils.MethodReference; import ninja.utils.MethodReference;


public interface RouteBuilder { public interface RouteBuilder {


RouteBuilder route(String uri); RouteBuilder route(String uri);


void with(Class controller, String controllerMethod); void with(Class<?> controllerClass, String controllerMethod);


@Deprecated
void with(MethodReference controllerMethodRef); void with(MethodReference controllerMethodRef);


/**
* A static result to return for this route.
* @param result The result to return on every request.
* @deprecated Use the functional interface methods to supply a new result
* for each route request. Its recommended to use <code>() -> Results.redirect("/")</code>.
*/
@Deprecated
void with(Result result); void with(Result result);


void with(ControllerMethod functionalMethod);

void with(ControllerMethod0 functionalMethod);

<A> void with(ControllerMethod1<A> functionalMethod);

<A,B> void with(ControllerMethod2<A,B> functionalMethod);

<A,B,C> void with(ControllerMethod3<A,B,C> functionalMethod);

<A,B,C,D> void with(ControllerMethod4<A,B,C,D> functionalMethod);

<A,B,C,D,E> void with(ControllerMethod5<A,B,C,D,E> functionalMethod);

<A,B,C,D,E,F> void with(ControllerMethod6<A,B,C,D,E,F> functionalMethod);

<A,B,C,D,E,F,G> void with(ControllerMethod7<A,B,C,D,E,F,G> functionalMethod);

<A,B,C,D,E,F,G,H> void with(ControllerMethod8<A,B,C,D,E,F,G,H> functionalMethod);

<A,B,C,D,E,F,G,H,I> void with(ControllerMethod9<A,B,C,D,E,F,G,H,I> functionalMethod);

<A,B,C,D,E,F,G,H,I,J> void with(ControllerMethod10<A,B,C,D,E,F,G,H,I,J> functionalMethod);

} }

0 comments on commit 2232015

Please sign in to comment.