From 32c6a983e5f4cb19856ab0551135919fb08e5ed3 Mon Sep 17 00:00:00 2001 From: Fio Date: Sun, 18 Jun 2023 23:11:40 +0800 Subject: [PATCH] =?UTF-8?q?feature=20#519=20packageFilters=20=E5=8F=82?= =?UTF-8?q?=E6=95=B0=E6=94=AF=E6=8C=81=E5=88=B0=E6=96=B9=E6=B3=95=E7=BA=A7?= =?UTF-8?q?=E5=88=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../doc/constants/DocGlobalConstants.java | 2 + .../power/doc/template/IRestDocTemplate.java | 13 +- .../doc/template/JaxrsDocBuildTemplate.java | 9 +- .../doc/template/RpcDocBuildTemplate.java | 12 +- .../java/com/power/doc/utils/DocUtil.java | 130 ++++++++++++++++-- 5 files changed, 146 insertions(+), 20 deletions(-) diff --git a/src/main/java/com/power/doc/constants/DocGlobalConstants.java b/src/main/java/com/power/doc/constants/DocGlobalConstants.java index 0c09fd1a..ef0cea59 100644 --- a/src/main/java/com/power/doc/constants/DocGlobalConstants.java +++ b/src/main/java/com/power/doc/constants/DocGlobalConstants.java @@ -258,4 +258,6 @@ public interface DocGlobalConstants { String SWAGGER_FILE_TAG = "formData"; String OPENAPI_TAG = "default"; + + String DEFAULT_FILTER_METHOD = "*"; } diff --git a/src/main/java/com/power/doc/template/IRestDocTemplate.java b/src/main/java/com/power/doc/template/IRestDocTemplate.java index d480266a..fcde637c 100644 --- a/src/main/java/com/power/doc/template/IRestDocTemplate.java +++ b/src/main/java/com/power/doc/template/IRestDocTemplate.java @@ -47,7 +47,7 @@ default List processApiData(ProjectDocConfigBuilder projectBuilder, Fram for (JavaClass cls : classes) { if (StringUtil.isNotEmpty(apiConfig.getPackageFilters())) { // from smart config - if (!DocUtil.isMatch(apiConfig.getPackageFilters(), cls.getCanonicalName())) { + if (!DocUtil.isMatch(apiConfig.getPackageFilters(), cls)) { continue; } } @@ -62,6 +62,7 @@ default List processApiData(ProjectDocConfigBuilder projectBuilder, Fram setCustomOrder = true; order = Integer.parseInt(strOrder); } + List apiMethodDocs = buildEntryPointMethod(cls, apiConfig, projectBuilder, frameworkAnnotations, configApiReqParams, baseMappingHandler, headerHandler); this.handleApiDoc(cls, apiDocList, apiMethodDocs, order, apiConfig.isMd5EncryptedHtmlName()); @@ -277,8 +278,7 @@ default List buildEntryPointMethod( FrameworkAnnotations frameworkAnnotations, List configApiReqParams, IRequestMappingHandler baseMappingHandler, - IHeaderHandler headerHandler - ) { + IHeaderHandler headerHandler) { String clazName = cls.getCanonicalName(); boolean paramsDataToTree = projectBuilder.getApiConfig().isParamsDataToTree(); String group = JavaClassUtil.getClassTagsValue(cls, DocTags.GROUP, Boolean.TRUE); @@ -306,6 +306,9 @@ default List buildEntryPointMethod( } } + Set filterMethods = DocUtil.findFilterMethods(clazName); + boolean needAllMethods = filterMethods.contains(DocGlobalConstants.DEFAULT_FILTER_METHOD); + List methods = cls.getMethods(); List docJavaMethods = new ArrayList<>(methods.size()); for (JavaMethod method : methods) { @@ -315,7 +318,9 @@ default List buildEntryPointMethod( if (Objects.nonNull(method.getTagByName(IGNORE))) { continue; } - docJavaMethods.add(convertToDocJavaMethod(apiConfig, projectBuilder, method, null)); + if (needAllMethods || filterMethods.contains(method.getName())) { + docJavaMethods.add(convertToDocJavaMethod(apiConfig, projectBuilder, method, null)); + } } // add parent class methods docJavaMethods.addAll(getParentsClassMethods(apiConfig, projectBuilder, cls)); diff --git a/src/main/java/com/power/doc/template/JaxrsDocBuildTemplate.java b/src/main/java/com/power/doc/template/JaxrsDocBuildTemplate.java index 755b5fef..fa051823 100644 --- a/src/main/java/com/power/doc/template/JaxrsDocBuildTemplate.java +++ b/src/main/java/com/power/doc/template/JaxrsDocBuildTemplate.java @@ -84,7 +84,7 @@ public List getApiData(ProjectDocConfigBuilder projectBuilder) { for (JavaClass cls : classes) { if (StringUtil.isNotEmpty(apiConfig.getPackageFilters())) { // from smart config - if (!DocUtil.isMatch(apiConfig.getPackageFilters(), cls.getCanonicalName())) { + if (!DocUtil.isMatch(apiConfig.getPackageFilters(), cls)) { continue; } } @@ -147,6 +147,9 @@ private List buildControllerMethod(final JavaClass cls, ApiConfig } } + Set filterMethods = DocUtil.findFilterMethods(clzName); + boolean needAllMethods = filterMethods.contains(DocGlobalConstants.DEFAULT_FILTER_METHOD); + List methods = cls.getMethods(); List docJavaMethods = new ArrayList<>(methods.size()); // filter private method @@ -154,7 +157,9 @@ private List buildControllerMethod(final JavaClass cls, ApiConfig if (method.isPrivate()) { continue; } - docJavaMethods.add(convertToDocJavaMethod(apiConfig, projectBuilder, method, null)); + if (needAllMethods || filterMethods.contains(method.getName())) { + docJavaMethods.add(convertToDocJavaMethod(apiConfig, projectBuilder, method, null)); + } } // add parent class methods docJavaMethods.addAll(getParentsClassMethods(apiConfig, projectBuilder, cls)); diff --git a/src/main/java/com/power/doc/template/RpcDocBuildTemplate.java b/src/main/java/com/power/doc/template/RpcDocBuildTemplate.java index 7c7dbab4..86c1cb42 100644 --- a/src/main/java/com/power/doc/template/RpcDocBuildTemplate.java +++ b/src/main/java/com/power/doc/template/RpcDocBuildTemplate.java @@ -82,7 +82,7 @@ public List getApiData(ProjectDocConfigBuilder projectBuilder) { for (JavaClass cls : projectBuilder.getJavaProjectBuilder().getClasses()) { if (StringUtil.isNotEmpty(apiConfig.getPackageFilters())) { // check package - if (!DocUtil.isMatch(apiConfig.getPackageFilters(), cls.getCanonicalName())) { + if (!DocUtil.isMatch(apiConfig.getPackageFilters(), cls)) { continue; } } @@ -119,6 +119,10 @@ private List buildServiceMethod(final JavaClass cls, ApiConfig ap String clazName = cls.getCanonicalName(); List methods = cls.getMethods(); List methodDocList = new ArrayList<>(methods.size()); + + Set filterMethods = DocUtil.findFilterMethods(clazName); + boolean needAllMethods = filterMethods.contains(DocGlobalConstants.DEFAULT_FILTER_METHOD); + for (JavaMethod method : methods) { if (method.isPrivate()) { continue; @@ -129,8 +133,10 @@ private List buildServiceMethod(final JavaClass cls, ApiConfig ap if (StringUtil.isEmpty(method.getComment()) && apiConfig.isStrict()) { throw new RuntimeException("Unable to find comment for method " + method.getName() + " in " + cls.getCanonicalName()); } - RpcJavaMethod apiMethodDoc = convertToRpcJavaMethod(apiConfig, method, null); - methodDocList.add(apiMethodDoc); + if (needAllMethods || filterMethods.contains(method.getName())) { + RpcJavaMethod apiMethodDoc = convertToRpcJavaMethod(apiConfig, method, null); + methodDocList.add(apiMethodDoc); + } } diff --git a/src/main/java/com/power/doc/utils/DocUtil.java b/src/main/java/com/power/doc/utils/DocUtil.java index a8ba7d7c..00226f51 100644 --- a/src/main/java/com/power/doc/utils/DocUtil.java +++ b/src/main/java/com/power/doc/utils/DocUtil.java @@ -39,8 +39,6 @@ import org.apache.commons.lang3.StringUtils; import java.time.LocalDateTime; -import java.time.OffsetDateTime; -import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; import java.util.*; import java.util.regex.Pattern; @@ -58,10 +56,10 @@ */ public class DocUtil { - private static Faker faker = new Faker(new Locale("en-US")); - private static Faker enFaker = new Faker(new Locale("en-US")); + private static final Faker faker = new Faker(new Locale("en-US")); + private static final Faker enFaker = new Faker(new Locale("en-US")); - private static Map fieldValue = new LinkedHashMap<>(); + private static final Map fieldValue = new LinkedHashMap<>(); static { fieldValue.put("uuid-string", UUID.randomUUID().toString()); @@ -126,6 +124,16 @@ public class DocUtil { fieldValue.put("version-string", enFaker.app().version()); } + /** + * Cache the regex and its pattern object + */ + private static final Map patternCache = new HashMap<>(); + + /** + * "packageFilters" cache + */ + private static final Map> filterMethodCache = new HashMap<>(); + /** * Generate a random value based on java type name. * @@ -147,9 +155,7 @@ public static String jsonValueByType(String typeName) { } else if ("Void".equals(type)) { return "null"; } else { - StringBuilder builder = new StringBuilder(); - builder.append("\"").append(value).append("\""); - return builder.toString(); + return "\"" + value + "\""; } } @@ -238,6 +244,110 @@ public static boolean isMatch(String packageFilters, String controllerName) { return false; } + /** + * match the controller package + * + * @param packageFilters package filter + * @param controllerClass controller class + * @return boolean + */ + public static boolean isMatch(String packageFilters, JavaClass controllerClass) { + if (StringUtil.isEmpty(packageFilters)) { + return false; + } + + String controllerName = controllerClass.getCanonicalName(); + + String[] filters = packageFilters.split(","); + + for (String filter : filters) { + if (filter.contains("*")) { + Pattern pattern = getPattern(filter); + + // if the pattern matches the controller canonical name, + // that means the user want all methods in this controller + boolean matchControllerName = pattern.matcher(controllerName).matches(); + if (matchControllerName) { + cacheFilterMethods(controllerName, Collections.singleton(DocGlobalConstants.DEFAULT_FILTER_METHOD)); + return true; + } else { + // try to match the methods in this controller + List controllerMethods = controllerClass.getMethods() + .stream() + .map(JavaMember::getName) + .collect(Collectors.toList()); + Set methodsMatch = controllerMethods.stream() + .filter(method -> pattern.matcher(controllerName + "." + method).matches()) + .collect(Collectors.toSet()); + if (!methodsMatch.isEmpty()) { + cacheFilterMethods(controllerName, methodsMatch); + return true; + } + } + } else if (controllerName.equals(filter) || controllerName.contains(filter)) { + // the filter is just the controller canonical name, + // or the controller is in a sub package + cacheFilterMethods(controllerName, Collections.singleton(DocGlobalConstants.DEFAULT_FILTER_METHOD)); + return true; + } else if (filter.contains(controllerName)) { + // the filter is point to a method + String method = filter.replace(controllerName, "").replace(".", ""); + cacheFilterMethods(controllerName, Collections.singleton(method)); + return true; + } + } + + return false; + } + + /** + * Get pattern from the cache by a regex string. + * If there is no cache, then compile a new pattern object and put it into cache + * + * @param regex a regex string + * @return a usable pattern object + */ + private static Pattern getPattern(String regex) { + Pattern pattern = patternCache.get(regex); + if (pattern == null) { + pattern = Pattern.compile(regex); + patternCache.put(regex, pattern); + } + return pattern; + } + + /** + * Put the specified method names into a cache. + * + * @param controller the controller canonical name + * @param methods the methods will be cached + */ + private static void cacheFilterMethods(String controller, Set methods) { + filterMethodCache.put(controller, methods); + } + + /** + * Get filter method name from cache, no cache will return "*", which means all methods. + * + * @param controller the controller canonical name + * @return the cached methods or "*" + */ + private static Set getFilterMethodsCache(String controller) { + return filterMethodCache.getOrDefault(controller, Collections.singleton(DocGlobalConstants.DEFAULT_FILTER_METHOD)); + } + + /** + * Find methods if the user specified in "packageFilters". + * If not specified, return "*" by default, which means need all methods. + * + * @param controllerName controllerName + * @return the methods user specified + * @see #cacheFilterMethods(String, Set) + * @see #isMatch(String, JavaClass) + */ + public static Set findFilterMethods(String controllerName) { + return getFilterMethodsCache(controllerName); + } /** * An interpreter for strings with named placeholders. @@ -541,9 +651,7 @@ public static String replaceNewLineToHtmlBr(String content) { } public static String handleJsonStr(String content) { - StringBuilder builder = new StringBuilder(); - builder.append("\"").append(content).append("\""); - return builder.toString(); + return "\"" + content + "\""; } public static Map formDataToMap(List formDataList) {