/**
 * Copyright 2008-2009. Chongqing Communications Industry Services Co.,Ltd Information Technology Branch. All rights reserved.
 * <a>http://www.crunii.com</a>
 */
package com.crunii.micro.common.utils;

import com.crunii.micro.common.exception.BusinessException;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.util.ClassUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author 田平 create 2022-04-29 09:42:45
 */
public class PackageUtil {

	private static final String RESOURCE_PATTERN = "/**/*.class";

	public static void main(String[] args) {
		String basePackage = "com.crunii.micro.im.controller";
		getAllPackages(basePackage).forEach(System.out::println);
	}

	public static Set<String> getAllPackages(String basePackage) {
		List<Class<?>> classes = getAllClasses(basePackage);
		return classes.stream()
				.map(c -> c.getPackage().getName())
				.sorted(Comparator.comparing(String::length))
				.collect(Collectors.toCollection(LinkedHashSet::new));

	}

	public static List<Class<?>> getAllClasses(String basePackage) {
		ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
		String pattern = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + ClassUtils.convertClassNameToResourcePath(basePackage) + RESOURCE_PATTERN;
		List<Class<?>> classes = new ArrayList<>(128);
		try {
			resourcePatternResolver.getResources(pattern);
			Resource[] resources = resourcePatternResolver.getResources(pattern);
			MetadataReaderFactory readerFactory = new CachingMetadataReaderFactory(resourcePatternResolver);
			for (Resource resource : resources) {
				MetadataReader reader = readerFactory.getMetadataReader(resource);
				//扫描到的class
				String classname = reader.getClassMetadata().getClassName();
				classes.add(Class.forName(classname));
			}
		} catch (Exception e) {
			throw new BusinessException("包解析错误！", e);
		}
		return classes;
	}
}
