org.nanoframework.core.component.scan.ComponentScan.java Source code

Java tutorial

Introduction

Here is the source code for org.nanoframework.core.component.scan.ComponentScan.java

Source

/*
 * Copyright 2015-2016 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 org.nanoframework.core.component.scan;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;
import org.nanoframework.commons.support.logging.Logger;
import org.nanoframework.commons.support.logging.LoggerFactory;
import org.nanoframework.commons.util.Assert;
import org.nanoframework.commons.util.CollectionUtils;
import org.nanoframework.core.component.exception.ComponentServiceRepeatException;
import org.nanoframework.core.component.stereotype.bind.RequestMapper;
import org.nanoframework.core.component.stereotype.bind.RequestMapping;
import org.nanoframework.core.component.stereotype.bind.RequestMethod;

import com.google.common.collect.Sets;

/**
 * ?????
 * @author yanghe
 * @since 1.0
 */
public class ComponentScan {

    private static final Logger LOGGER = LoggerFactory.getLogger(ComponentScan.class);

    private static Set<Class<?>> classes;

    /**
     * ?
     * @param annotationClass 
     * @return ?
     */
    public static Set<Class<?>> filter(final Class<? extends Annotation> annotationClass) {
        if (classes == null) {
            classes = Sets.newLinkedHashSet();
        }

        if (classes.size() > 0) {
            final Set<Class<?>> annClasses = Sets.newLinkedHashSet();
            classes.stream().filter(clz -> clz.isAnnotationPresent(annotationClass))
                    .forEach(clz -> annClasses.add(clz));
            return annClasses;

        }

        return Collections.emptySet();
    }

    /**
     * RequestMapping
     * @param obj 
     * @param methods 
     * @param annotationClass RequestMapping
     * @param componentURI URI
     * @return 
     */
    public static Map<String, Map<RequestMethod, RequestMapper>> filter(Object obj, Method[] methods,
            Class<? extends RequestMapping> annotationClass, String componentURI) {
        if (methods == null)
            return Collections.emptyMap();

        Map<String, Map<RequestMethod, RequestMapper>> methodMaps = new HashMap<>();
        for (Iterator<Map<String, Map<RequestMethod, RequestMapper>>> iter = Arrays.asList(methods).stream()
                .filter(method -> method.isAnnotationPresent(annotationClass)).filter(method -> {
                    RequestMapping mapping = method.getAnnotation(annotationClass);
                    if (mapping != null && !"".equals(mapping.value()))
                        return true;
                    else {
                        LOGGER.debug("Unknown component mapper define: {}.{}:{}", obj.getClass().getName(),
                                method.getName(), (componentURI + mapping.value()));
                        return false;
                    }
                }).map(method -> {
                    Map<String, Map<RequestMethod, RequestMapper>> methodMap = new HashMap<>();
                    RequestMapping mapping = method.getAnnotation(annotationClass);
                    RequestMapper mapper = RequestMapper.create().setObject(obj).setClz(obj.getClass())
                            .setMethod(method).setRequestMethods(mapping.method());
                    Map<RequestMethod, RequestMapper> mappers = new HashMap<>();
                    final RequestMethod[] mths = mapper.getRequestMethods();
                    for (RequestMethod _method : mths) {
                        mappers.put(_method, mapper);
                    }

                    methodMap.put((componentURI + mapping.value()).toLowerCase(), mappers);
                    if (LOGGER.isDebugEnabled())
                        LOGGER.debug("URI Mapper: " + obj.getClass().getName() + '.' + method.getName() + ':'
                                + (componentURI + mapping.value()));

                    return methodMap;
                }).iterator();iter.hasNext();) {
            Map<String, Map<RequestMethod, RequestMapper>> methodMap = iter.next();
            String uri = null;
            if (!CollectionUtils.isEmpty(methodMap)
                    && methodMaps.containsKey(uri = methodMap.keySet().iterator().next())) {
                Set<RequestMethod> before = methodMap.get(uri).keySet();
                Set<RequestMethod> after = methodMaps.get(uri).keySet();
                if (!isIntersectionRequestMethod(before, after)) {
                    methodMap.forEach((_uri, _methodMapper) -> {
                        Map<RequestMethod, RequestMapper> methodMapper;
                        if ((methodMapper = methodMaps.get(_uri)) == null) {
                            methodMaps.put(_uri, _methodMapper);
                        } else {
                            methodMapper.putAll(_methodMapper);
                            methodMaps.put(_uri, methodMapper);
                        }
                    });
                } else
                    throw new ComponentServiceRepeatException(uri);

            } else {
                methodMap.forEach((_uri, _methodMapper) -> {
                    Map<RequestMethod, RequestMapper> methodMapper;
                    if ((methodMapper = methodMaps.get(_uri)) == null) {
                        methodMaps.put(_uri, _methodMapper);
                    } else {
                        methodMapper.putAll(_methodMapper);
                        methodMaps.put(_uri, methodMapper);
                    }
                });
            }
        }

        return methodMaps;
    }

    public static boolean isIntersectionRequestMethod(Set<RequestMethod> before, Set<RequestMethod> after) {
        Assert.notEmpty(before);
        Assert.notEmpty(after);
        for (RequestMethod beforeMethod : before) {
            for (RequestMethod afterMethod : after) {
                if (beforeMethod == afterMethod)
                    return true;
            }
        }

        return false;
    }

    public static void scan(String packageName) {
        if (StringUtils.isEmpty(packageName)) {
            LOGGER.warn("packageName, ??");
            return;
        }

        if (classes == null) {
            classes = Sets.newHashSet();
        }

        classes.addAll(getClasses(packageName));
    }

    public static void clear() {
        if (classes != null) {
            classes.clear();
        }
    }

    /**
     * Return a set of all classes contained in the given package.
     *
     * @param packageName the package has to be analyzed.
     * @return a set of all classes contained in the given package.
     */
    private static Set<Class<?>> getClasses(String packageName) {
        return getClasses(new ResolverUtil.IsA(Object.class), packageName);
    }

    /**
     * Return a set of all classes contained in the given package that match with
     * the given test requirement.
     *
     * @param test the class filter on the given package.
     * @param packageName the package has to be analyzed.
     * @return a set of all classes contained in the given package.
     */
    private static Set<Class<?>> getClasses(ResolverUtil.Test test, String packageName) {
        Assert.notNull(test, "Parameter 'test' must not be null");
        Assert.notNull(packageName, "Parameter 'packageName' must not be null");
        return new ResolverUtil<Object>().find(test, packageName).getClasses();
    }
}