Java tutorial
/* * 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(); } }