/* * 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.utils; import java.lang.reflect.Method; import java.util.Optional; import ninja.ControllerMethods.ControllerMethod; public class LambdaRoute { private final Method functionalMethod; private final Optional<Method> implementationMethod; private final Optional<Object> targetObject; public LambdaRoute(Method functionalMethod, Method implementationMethod, Object targetObject) { this.functionalMethod = functionalMethod; this.implementationMethod = Optional.ofNullable(implementationMethod); this.targetObject = Optional.ofNullable(targetObject); } public Method getFunctionalMethod() { return functionalMethod; } public Optional<Method> getImplementationMethod() { return implementationMethod; } public Optional<Object> getTargetObject() { return targetObject; } static public LambdaRoute resolve(ControllerMethod controllerMethod) { try { Lambdas.LambdaInfo lambdaInfo = Lambdas.reflect(controllerMethod); switch (lambdaInfo.getKind()) { case ANY_INSTANCE_METHOD_REFERENCE: case STATIC_METHOD_REFERENCE: // call impl method just like before Java 8 return new LambdaRoute(lambdaInfo.getImplementationMethod(), null, null); case SPECIFIC_INSTANCE_METHOD_REFERENCE: case ANONYMOUS_METHOD_REFERENCE: // only safe to use the impl method for argument types if // the number of arguments matches between the methods if (lambdaInfo.areMethodParameterCountsEqual()) { return new LambdaRoute( lambdaInfo.getFunctionalMethod(), lambdaInfo.getImplementationMethod(), controllerMethod); } } } catch (IllegalArgumentException e) { // unable to detect lambda (e.g. such as anonymous/concrete class) } // fallback to simple call the "apply" method on the supplied method instance try { Method functionalMethod = Lambdas.getMethod(controllerMethod.getClass(), "apply"); functionalMethod.setAccessible(true); return new LambdaRoute(functionalMethod, null, controllerMethod); } catch (NoSuchMethodException | ClassNotFoundException e) { throw new RuntimeException(e); } } }