io.dyn.core.handler.AnnotationHandlerMethodResolver.java Source code

Java tutorial

Introduction

Here is the source code for io.dyn.core.handler.AnnotationHandlerMethodResolver.java

Source

/*
 * Copyright (c) 2011-2012 by 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 io.dyn.core.handler;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;

import io.dyn.core.handler.anno.Handler;
import io.dyn.core.handler.anno.On;
import io.dyn.core.handler.anno.Value;
import io.dyn.core.handler.anno.When;
import io.dyn.el.SpelExpression;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.expression.BeanFactoryResolver;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.expression.Expression;
import org.springframework.expression.ParserContext;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.util.ReflectionUtils;

/**
 * @author Jon Brisbin <jon@jbrisbin.com>
 */
public class AnnotationHandlerMethodResolver implements HandlerMethodResolver, ApplicationContextAware {

    //protected static final Logger log = Logger.logger(AnnotationHandlerMethodResolver.class);
    protected static ParameterNameDiscoverer PARAMETER_NAME_DISCOVERER = new LocalVariableTableParameterNameDiscoverer();

    protected ApplicationContext applicationContext;
    protected StandardEvaluationContext evalCtx = new StandardEvaluationContext();

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        if (null != applicationContext) {
            this.applicationContext = applicationContext;
            evalCtx.setBeanResolver(new BeanFactoryResolver(this.applicationContext));
        }
    }

    @Override
    public boolean supports(final Class<?> aClass) {
        boolean classLevelAnno = (null != AnnotationUtils.findAnnotation(aClass, Handler.class));
        final AtomicBoolean hasHandlerMethod = new AtomicBoolean(false);
        Class<?> clazz = aClass;
        while (null != clazz && clazz != Object.class) {
            ReflectionUtils.doWithMethods(clazz, new ReflectionUtils.MethodCallback() {
                @Override
                public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
                    if (!hasHandlerMethod.get()) {
                        hasHandlerMethod.set(true);
                    }
                }
            }, Handlers.USER_METHODS);
            clazz = clazz.getSuperclass();
        }

        return (hasHandlerMethod.get() || classLevelAnno);
    }

    @Override
    public Map<Object, HandlerMethod> resolve(Class<?> aClass, Object... args) {
        final Map<Object, HandlerMethod> handlerMethods = new HashMap<>();
        //log.debug("Finding handler methods in %s", aClass);
        Class<?> clazz = aClass;
        while (null != clazz && clazz != Object.class) {
            ReflectionUtils.doWithMethods(clazz, new ReflectionUtils.MethodCallback() {
                @Override
                public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {

                    Class<?>[] paramTypes = method.getParameterTypes();
                    String[] paramNames = PARAMETER_NAME_DISCOVERER.getParameterNames(method);
                    HandlerMethodArgument[] handlerMethodArgs = new HandlerMethodArgument[paramTypes.length];
                    Annotation[][] paramAnnos = method.getParameterAnnotations();
                    Expression[] valueExpressions = new Expression[paramTypes.length];
                    for (int i = 0; i < paramTypes.length; i++) {
                        String paramName = (null != paramNames ? paramNames[i] : "arg" + i);
                        if (paramAnnos[i].length > 0) {
                            for (int j = 0; j < paramAnnos[i].length; j++) {
                                if (paramAnnos[i][j] instanceof Value) {
                                    valueExpressions[i] = SpelExpression.DEFAULT_PARSER
                                            .parseExpression(((Value) paramAnnos[i][j]).value());
                                    break;
                                }
                            }
                        }
                        handlerMethodArgs[i] = new HandlerMethodArgument(i, paramName, paramTypes[i],
                                valueExpressions[i]);
                    }

                    Guard guard = null;
                    When when = Handlers.find(When.class, method);
                    if (null != when) {
                        guard = new Guard(SpelExpression.DEFAULT_PARSER.parseExpression(when.value()));
                    }

                    On on = Handlers.find(On.class, method);
                    String eventName = Handlers.findEventName(method);
                    if (null != eventName) {
                        Object key = eventName;
                        if (eventName.contains("#{")) {
                            key = SpelExpression.DEFAULT_PARSER.parseExpression(eventName,
                                    ParserContext.TEMPLATE_EXPRESSION);
                        }
                        handlerMethods.put(key, new HandlerMethod(method, handlerMethodArgs, guard));

                    }
                }
            }, Handlers.USER_METHODS);
            clazz = clazz.getSuperclass();
        }
        return (handlerMethods.size() > 0 ? handlerMethods : null);
    }

}