This commit is contained in:
xingzi 2020-08-28 20:50:20 +08:00
commit a57687e228
18 changed files with 1758 additions and 1475 deletions

View File

@ -9,6 +9,7 @@
4. 新增ApiDataBuilder中获取树形格式参数数据的接口#40。 4. 新增ApiDataBuilder中获取树形格式参数数据的接口#40。
5. 新增对Open Api 3.0的支持。 5. 新增对Open Api 3.0的支持。
6. 修改字典表空时内部发生空指针的问题。 6. 修改字典表空时内部发生空指针的问题。
7. 优化curl用例增加请求头。
#### 版本号1.9.1 #### 版本号1.9.1
- 更新日期: 2020-08-02 - 更新日期: 2020-08-02
- 更新内容: - 更新内容:

View File

@ -95,6 +95,9 @@ When you need to use smart-doc to generate more API document information, you ca
"allInOneDocFileName":"index.html",//Customize the output document name "allInOneDocFileName":"index.html",//Customize the output document name
"requestExample":"true",//Whether to display the request example in the document, the default value is true. "requestExample":"true",//Whether to display the request example in the document, the default value is true.
"responseExample":"true",//Whether to display the response example in the document, the default is true. "responseExample":"true",//Whether to display the response example in the document, the default is true.
"ignoreRequestParams":[ //The request parameter object will be discarded when generating the document.@since 1.9.2
"org.springframework.ui.ModelMap"
],
  "dataDictionaries": [// Configure the data dictionary, no need to set   "dataDictionaries": [// Configure the data dictionary, no need to set
    {     {
      "title": "Order Status", // The name of the data dictionary       "title": "Order Status", // The name of the data dictionary

View File

@ -4,7 +4,8 @@
smart-doc是一款同时支持JAVA RESTFUL API和Apache Dubbo RPC接口文档生成的工具smart-doc在业内率先提出基于java泛型定义推导的理念 smart-doc是一款同时支持JAVA RESTFUL API和Apache Dubbo RPC接口文档生成的工具smart-doc在业内率先提出基于java泛型定义推导的理念
完全基于接口源码来分析生成接口文档不采用任何注解侵入到业务代码中。你只需要按照java-doc标准编写注释 完全基于接口源码来分析生成接口文档不采用任何注解侵入到业务代码中。你只需要按照java-doc标准编写注释
smart-doc就能帮你生成一个简易明了的markdown、html5文档甚至可以直接生成postman collection导入到postman做api接口调试。 smart-doc就能帮你生成一个简易明了的markdown、html5文档甚至可以直接生成postman collection导入到postman做api接口调试。
如果你已经厌倦了swagger等文档工具的无数注解和强侵入污染那请拥抱smart-doc吧
$\color{red}{我因不将就而诞生,用了无数个日日夜夜来成长,无论现在还是将来也不会为了将就全世界!—smart-doc}$
## Features ## Features
- 零注解、零学习成本、只需要写标准java注释。 - 零注解、零学习成本、只需要写标准java注释。
- 基于源代码接口定义自动推导,强大的返回结构推导。 - 基于源代码接口定义自动推导,强大的返回结构推导。
@ -95,6 +96,9 @@ smart-doc官方目前已经开发完成[maven插件](https://gitee.com/sunyurepo
"allInOneDocFileName":"index.html",//自定义设置输出文档名称, @since 1.9.0 "allInOneDocFileName":"index.html",//自定义设置输出文档名称, @since 1.9.0
"requestExample":"true",//是否将请求示例展示在文档中默认true@since 1.9.0 "requestExample":"true",//是否将请求示例展示在文档中默认true@since 1.9.0
"responseExample":"true",//是否将响应示例展示在文档中默认为true@since 1.9.0 "responseExample":"true",//是否将响应示例展示在文档中默认为true@since 1.9.0
"ignoreRequestParams":[ //忽略请求参数对象,把不想生成文档的参数对象屏蔽掉,@since 1.9.2
"org.springframework.ui.ModelMap"
],
"dataDictionaries": [ //配置数据字典,没有需求可以不设置 "dataDictionaries": [ //配置数据字典,没有需求可以不设置
{ {
"title": "http状态码字典", //数据字典的名称 "title": "http状态码字典", //数据字典的名称
@ -103,14 +107,12 @@ smart-doc官方目前已经开发完成[maven插件](https://gitee.com/sunyurepo
"descField": "message"//数据字典对象的描述信息字典 "descField": "message"//数据字典对象的描述信息字典
} }
], ],
"errorCodeDictionaries": [{ //错误码列表,没有需求可以不设置 "errorCodeDictionaries": [{ //错误码列表,没有需求可以不设置
"title": "title", "title": "title",
"enumClassName": "com.power.common.enums.HttpCodeEnum", //错误码枚举类 "enumClassName": "com.power.common.enums.HttpCodeEnum", //错误码枚举类
"codeField": "code",//错误码的code码字段名称 "codeField": "code",//错误码的code码字段名称
"descField": "message"//错误码的描述信息对应的字段名 "descField": "message"//错误码的描述信息对应的字段名
}], }],
"revisionLogs": [ //设置文档变更记录,没有需求可以不设置 "revisionLogs": [ //设置文档变更记录,没有需求可以不设置
{ {
"version": "1.0", //文档版本号 "version": "1.0", //文档版本号
@ -181,7 +183,7 @@ mvn -Dfile.encoding = UTF-8 smart-doc:rpc-adoc
``` ```
**注意:** 尤其在window系统下如果实际使用maven命令行执行文档生成可能会出现乱码因此需要在执行时指定`-Dfile.encoding=UTF-8`。 **注意:** 尤其在window系统下如果实际使用maven命令行执行文档生成可能会出现乱码因此需要在执行时指定`-Dfile.encoding=UTF-8`。
#### Use Idea #### Use Idea
![idea中smart-doc-maven插件使用](https://images.gitee.com/uploads/images/2020/0602/213139_739a4d41_144669.png "maven_plugin_tasks.png") ![idea中smart-doc-maven插件使用](https://gitee.com/sunyurepository/smart-doc-maven-plugin/raw/master/images/idea.png "maven_plugin_tasks.png")
### Use gradle plugin ### Use gradle plugin
如果你使用gradle来构建项目你可以参考gradle插件的使用文档来集成 如果你使用gradle来构建项目你可以参考gradle插件的使用文档来集成

348
pom.xml
View File

@ -1,174 +1,174 @@
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" <project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<groupId>com.github.shalousun</groupId> <groupId>com.github.shalousun</groupId>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<artifactId>smart-doc</artifactId> <artifactId>smart-doc</artifactId>
<packaging>jar</packaging> <packaging>jar</packaging>
<version>1.9.1</version> <version>1.9.2.1</version>
<name>smart-doc</name> <name>smart-doc</name>
<url>https://github.com/shalousun/smart-doc.git</url> <url>https://github.com/shalousun/smart-doc.git</url>
<description>Smart-doc is a tool that supports both JAVA RESTFUL API and Apache Dubbo RPC interface document generation.</description> <description>Smart-doc is a tool that supports both JAVA RESTFUL API and Apache Dubbo RPC interface document generation.</description>
<licenses> <licenses>
<license> <license>
<name>The Apache Software License, Version 2.0</name> <name>The Apache Software License, Version 2.0</name>
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url> <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
<distribution>repo</distribution> <distribution>repo</distribution>
</license> </license>
</licenses> </licenses>
<scm> <scm>
<url>https://github.com/shalousun/smart-doc.git</url> <url>https://github.com/shalousun/smart-doc.git</url>
<connection>scm:https://github.com/shalousun/smart-doc.git</connection> <connection>scm:https://github.com/shalousun/smart-doc.git</connection>
<developerConnection>scm:https://github.com/shalousun/smart-doc.git</developerConnection> <developerConnection>scm:https://github.com/shalousun/smart-doc.git</developerConnection>
</scm> </scm>
<developers> <developers>
<developer> <developer>
<name>shalousun</name> <name>shalousun</name>
<email>836575280@qq.com</email> <email>836575280@qq.com</email>
<url>https://github.com/shalousun</url> <url>https://github.com/shalousun</url>
</developer> </developer>
</developers> </developers>
<properties> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<flexmark.version>0.62.2</flexmark.version> <flexmark.version>0.62.2</flexmark.version>
</properties> </properties>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>junit</groupId> <groupId>junit</groupId>
<artifactId>junit</artifactId> <artifactId>junit</artifactId>
<version>4.13</version> <version>4.13</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.ibeetl</groupId> <groupId>com.ibeetl</groupId>
<artifactId>beetl</artifactId> <artifactId>beetl</artifactId>
<version>3.1.8.RELEASE</version> <version>3.1.8.RELEASE</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.thoughtworks.qdox</groupId> <groupId>com.thoughtworks.qdox</groupId>
<artifactId>qdox</artifactId> <artifactId>qdox</artifactId>
<version>2.0.0</version> <version>2.0.0</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.github.javafaker</groupId> <groupId>com.github.javafaker</groupId>
<artifactId>javafaker</artifactId> <artifactId>javafaker</artifactId>
<version>1.0.2</version> <version>1.0.2</version>
<exclusions> <exclusions>
<exclusion> <exclusion>
<artifactId>commons-lang3</artifactId> <artifactId>commons-lang3</artifactId>
<groupId>org.apache.commons</groupId> <groupId>org.apache.commons</groupId>
</exclusion> </exclusion>
</exclusions> </exclusions>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.github.shalousun</groupId> <groupId>com.github.shalousun</groupId>
<artifactId>common-util</artifactId> <artifactId>common-util</artifactId>
<version>1.9.6</version> <version>1.9.7</version>
</dependency> </dependency>
<!--markdown to html--> <!--markdown to html-->
<dependency> <dependency>
<groupId>com.vladsch.flexmark</groupId> <groupId>com.vladsch.flexmark</groupId>
<artifactId>flexmark</artifactId> <artifactId>flexmark</artifactId>
<version>${flexmark.version}</version> <version>${flexmark.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.vladsch.flexmark</groupId> <groupId>com.vladsch.flexmark</groupId>
<artifactId>flexmark-util</artifactId> <artifactId>flexmark-util</artifactId>
<version>${flexmark.version}</version> <version>${flexmark.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.vladsch.flexmark</groupId> <groupId>com.vladsch.flexmark</groupId>
<artifactId>flexmark-ext-tables</artifactId> <artifactId>flexmark-ext-tables</artifactId>
<version>${flexmark.version}</version> <version>${flexmark.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.vladsch.flexmark</groupId> <groupId>com.vladsch.flexmark</groupId>
<artifactId>flexmark-ext-gfm-strikethrough</artifactId> <artifactId>flexmark-ext-gfm-strikethrough</artifactId>
<version>${flexmark.version}</version> <version>${flexmark.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.google.code.gson</groupId> <groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId> <artifactId>gson</artifactId>
<version>2.8.6</version> <version>2.8.6</version>
</dependency> </dependency>
</dependencies> </dependencies>
<build> <build>
<plugins> <plugins>
<!--compiler--> <!--compiler-->
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId> <artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version> <version>3.8.1</version>
<configuration> <configuration>
<source>1.8</source> <source>1.8</source>
<target>1.8</target> <target>1.8</target>
<encoding>UTF-8</encoding> <encoding>UTF-8</encoding>
</configuration> </configuration>
</plugin> </plugin>
<!-- Source --> <!-- Source -->
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId> <artifactId>maven-source-plugin</artifactId>
<version>3.2.1</version> <version>3.2.1</version>
<executions> <executions>
<execution> <execution>
<phase>package</phase> <phase>package</phase>
<goals> <goals>
<goal>jar-no-fork</goal> <goal>jar-no-fork</goal>
</goals> </goals>
</execution> </execution>
</executions> </executions>
</plugin> </plugin>
<!-- JavaDoc --> <!-- JavaDoc -->
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId> <artifactId>maven-javadoc-plugin</artifactId>
<version>3.2.0</version> <version>3.2.0</version>
<executions> <executions>
<execution> <execution>
<phase>package</phase> <phase>package</phase>
<goals> <goals>
<goal>jar</goal> <goal>jar</goal>
</goals> </goals>
</execution> </execution>
</executions> </executions>
</plugin> </plugin>
</plugins> </plugins>
<finalName>smart-doc</finalName> <finalName>smart-doc</finalName>
</build> </build>
<profiles> <profiles>
<profile> <profile>
<id>release</id> <id>release</id>
<build> <build>
<plugins> <plugins>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId> <artifactId>maven-gpg-plugin</artifactId>
<version>1.6</version> <version>1.6</version>
<executions> <executions>
<execution> <execution>
<id>sign-artifacts</id> <id>sign-artifacts</id>
<phase>verify</phase> <phase>verify</phase>
<goals> <goals>
<goal>sign</goal> <goal>sign</goal>
</goals> </goals>
</execution> </execution>
</executions> </executions>
</plugin> </plugin>
</plugins> </plugins>
</build> </build>
<distributionManagement> <distributionManagement>
<snapshotRepository> <snapshotRepository>
<id>oss</id> <id>oss</id>
<url>https://oss.sonatype.org/content/repositories/snapshots/</url> <url>https://oss.sonatype.org/content/repositories/snapshots/</url>
</snapshotRepository> </snapshotRepository>
<repository> <repository>
<id>oss</id> <id>oss</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url> <url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository> </repository>
</distributionManagement> </distributionManagement>
</profile> </profile>
</profiles> </profiles>
</project> </project>

View File

@ -48,7 +48,7 @@ public class AdocDocBuilder {
* *
* @param config ApiConfig * @param config ApiConfig
*/ */
public static void builderApiDoc(ApiConfig config) { public static void buildApiDoc(ApiConfig config) {
JavaProjectBuilder javaProjectBuilder = new JavaProjectBuilder(); JavaProjectBuilder javaProjectBuilder = new JavaProjectBuilder();
buildApiDoc(config, javaProjectBuilder); buildApiDoc(config, javaProjectBuilder);
} }

View File

@ -80,6 +80,8 @@ public class DocBuilderTemplate extends BaseDocBuilderTemplate {
mapper.binding(TemplateVariable.DESC.getVariable(), doc.getDesc()); mapper.binding(TemplateVariable.DESC.getVariable(), doc.getDesc());
mapper.binding(TemplateVariable.NAME.getVariable(), doc.getName()); mapper.binding(TemplateVariable.NAME.getVariable(), doc.getName());
mapper.binding(TemplateVariable.LIST.getVariable(), doc.getList()); mapper.binding(TemplateVariable.LIST.getVariable(), doc.getList());
mapper.binding(TemplateVariable.REQUEST_EXAMPLE.getVariable(), config.isRequestExample());
mapper.binding(TemplateVariable.RESPONSE_EXAMPLE.getVariable(), config.isResponseExample());
FileUtil.nioWriteFile(mapper.render(), config.getOutPath() + FILE_SEPARATOR + doc.getName() + fileExtension); FileUtil.nioWriteFile(mapper.render(), config.getOutPath() + FILE_SEPARATOR + doc.getName() + fileExtension);
} }
} }

View File

@ -93,7 +93,7 @@ public class HtmlApiDocBuilder {
List<ApiDocDict> apiDocDictList = builderTemplate.buildDictionary(config, javaProjectBuilder); List<ApiDocDict> apiDocDictList = builderTemplate.buildDictionary(config, javaProjectBuilder);
buildIndex(apiDocList, config); buildIndex(apiDocList, config);
copyCss(config.getOutPath()); copyCss(config.getOutPath());
buildDoc(apiDocList, config.getOutPath()); buildDoc(apiDocList, config);
buildErrorCodeDoc(config.getErrorCodes(), config.getOutPath()); buildErrorCodeDoc(config.getErrorCodes(), config.getOutPath());
buildDictionary(apiDocDictList, config.getOutPath()); buildDictionary(apiDocDictList, config.getOutPath());
} }
@ -149,20 +149,22 @@ public class HtmlApiDocBuilder {
* build ever controller api * build ever controller api
* *
* @param apiDocList list of api doc * @param apiDocList list of api doc
* @param outPath output path * @param config ApiConfig
*/ */
private static void buildDoc(List<ApiDoc> apiDocList, String outPath) { private static void buildDoc(List<ApiDoc> apiDocList, ApiConfig config) {
FileUtil.mkdirs(outPath); FileUtil.mkdirs(config.getOutPath());
Template htmlApiDoc; Template htmlApiDoc;
for (ApiDoc doc : apiDocList) { for (ApiDoc doc : apiDocList) {
Template apiTemplate = BeetlTemplateUtil.getByName(API_DOC_MD_TPL); Template apiTemplate = BeetlTemplateUtil.getByName(API_DOC_MD_TPL);
apiTemplate.binding(TemplateVariable.REQUEST_EXAMPLE.getVariable(), config.isRequestExample());
apiTemplate.binding(TemplateVariable.RESPONSE_EXAMPLE.getVariable(), config.isResponseExample());
apiTemplate.binding(TemplateVariable.DESC.getVariable(), doc.getDesc()); apiTemplate.binding(TemplateVariable.DESC.getVariable(), doc.getDesc());
apiTemplate.binding(TemplateVariable.NAME.getVariable(), doc.getName()); apiTemplate.binding(TemplateVariable.NAME.getVariable(), doc.getName());
apiTemplate.binding(TemplateVariable.LIST.getVariable(), doc.getList());//类名 apiTemplate.binding(TemplateVariable.LIST.getVariable(), doc.getList());//类名
Map<String, Object> templateVariables = new HashMap<>(); Map<String, Object> templateVariables = new HashMap<>();
templateVariables.put(TemplateVariable.TITLE.getVariable(), doc.getDesc()); templateVariables.put(TemplateVariable.TITLE.getVariable(), doc.getDesc());
htmlApiDoc = initTemplate(apiTemplate, HTML_API_DOC_TPL, templateVariables); htmlApiDoc = initTemplate(apiTemplate, HTML_API_DOC_TPL, templateVariables);
FileUtil.nioWriteFile(htmlApiDoc.render(), outPath + FILE_SEPARATOR + doc.getAlias() + ".html"); FileUtil.nioWriteFile(htmlApiDoc.render(), config.getOutPath() + FILE_SEPARATOR + doc.getAlias() + ".html");
} }
} }

View File

@ -0,0 +1,251 @@
/*
* smart-doc https://github.com/shalousun/smart-doc
*
* Copyright (C) 2019-2020 smart-doc
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 com.power.doc.builder;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.power.common.util.FileUtil;
import com.power.common.util.StringUtil;
import com.power.doc.constants.DocGlobalConstants;
import com.power.doc.constants.TemplateVariable;
import com.power.doc.model.ApiConfig;
import com.power.doc.model.ApiDoc;
import com.power.doc.model.ApiParam;
import com.power.doc.template.IDocBuildTemplate;
import com.power.doc.template.SpringBootDocBuildTemplate;
import com.power.doc.utils.BeetlTemplateUtil;
import com.power.doc.utils.Iterables;
import com.thoughtworks.qdox.JavaProjectBuilder;
import org.beetl.core.Template;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static com.power.doc.constants.DocGlobalConstants.YAPI_RESULT_TPL;
/**
* generate yapi's yapi json
*
* @author dai19470 2020/08/20.
*/
public class YapiJsonBuilder {
/**
* 构建yapi json
*
* @param config 配置文件
*/
public static void buildYapiCollection(ApiConfig config) {
DocBuilderTemplate builderTemplate = new DocBuilderTemplate();
builderTemplate.checkAndInit(config);
JavaProjectBuilder javaProjectBuilder = new JavaProjectBuilder();
ProjectDocConfigBuilder configBuilder = new ProjectDocConfigBuilder(config, javaProjectBuilder);
yapiJsonCreate(config, configBuilder);
}
private static Set<String> getUrl(String url, String patter) {
Pattern pattern = Pattern.compile(patter);
Matcher matcher = pattern.matcher(url);
Set<String> result = new HashSet<>();
while (matcher.find()) {
result.add(matcher.group());
}
return result;
}
private static void yapiJsonCreate(ApiConfig config, ProjectDocConfigBuilder configBuilder) {
config.setParamsDataToTree(true);
IDocBuildTemplate docBuildTemplate = new SpringBootDocBuildTemplate();
List<ApiDoc> apiDocList = docBuildTemplate.getApiData(configBuilder);
List<Map<String, Object>> requestItem = new ArrayList<>();
Iterables.forEach(apiDocList, (index, apiDoc) -> {
Map<String, Object> module = new HashMap<>();
module.put("index", index);
module.put("name", apiDoc.getDesc());
module.put("parent_id", -1);
module.put("desc", apiDoc.getDesc());
module.put("add_time", System.currentTimeMillis() / 1000);
module.put("up_time", System.currentTimeMillis() / 1000);
List<Map<String, Object>> methods = new ArrayList();
Iterables.forEach(apiDoc.getList(), (idx, apiMethodDoc) -> {
Map<String, Object> method = new HashMap<>();
Map<String, Object> map = new HashMap<>();
map.put("path", apiMethodDoc.getPath());
map.put("params", new Object[]{});
method.put("query_path", map);
// method.put("owners",new String[]{apiMethodDoc.getAuthor()});
method.put("owners", new String[]{});
method.put("edit_uid", 0);
method.put("status", "done");
method.put("type", "static");
method.put("req_body_is_json_schema", true);
method.put("res_body_is_json_schema", true);
method.put("api_opened", false);
method.put("index", idx);
method.put("tag", new Object[]{});
method.put("method", apiMethodDoc.getType());
method.put("title", apiMethodDoc.getDesc());
method.put("desc", apiMethodDoc.getDetail());
method.put("name", apiMethodDoc.getName());
method.put("path", apiMethodDoc.getPath().replace("//", "/"));
method.put("req_body_form", Arrays.asList());
List<Map<String, Object>> req_params = new ArrayList();
Set<String> req_param = getUrl(apiMethodDoc.getPath(), "(?<=\\{)(.+?)(?=\\})");
Iterables.forEach(req_param, (j, param) -> {
ApiParam temp = apiMethodDoc.getRequestParams().stream().filter(apiParam -> apiParam.getField().equals(param)).findFirst().orElse(null);
if (temp != null) {
Map<String, Object> h = new HashMap<>();
h.put("example", "");
h.put("name", temp.getField());
h.put("type", temp.getType());
h.put("desc", temp.getDesc());
req_params.add(j, h);
}
});
method.put("req_params", req_params);
method.put("res_body_type", "json");
List<Map<String, Object>> querys = new ArrayList();
Iterables.forEach(apiMethodDoc.getRequestParams(), (j, res) -> {
Map<String, Object> h = new HashMap<>();
h.put("required", res.isRequired() ? "1" : "0");
h.put("desc", res.getDesc());
h.put("name", res.getField());
h.put("example", "");
h.put("type", res.getType());
querys.add(j, h);
});
method.put("req_query", querys);
List<Map<String, Object>> headers = new ArrayList();
Iterables.forEach(apiMethodDoc.getRequestHeaders(), (j, res) -> {
Map<String, Object> h = new HashMap<>();
h.put("required", res.isRequired() ? "1" : "0");
h.put("value", res.getValue());
h.put("name", res.getName());
h.put("desc", res.getDesc());
headers.add(j, h);
});
method.put("req_headers", headers);
Template apiTemplate = BeetlTemplateUtil.getByName(YAPI_RESULT_TPL);
apiTemplate.binding(TemplateVariable.RESPONSELIST.getVariable(), generateJson(apiMethodDoc.getResponseParams()));
String json = apiTemplate.render();
method.put("res_body", json);
if (StringUtil.isNotEmpty(apiMethodDoc.getResponseUsage())) {
method.put("desc", "<pre><code>\n" + apiMethodDoc.getResponseUsage() + "\n</code></pre>\n");
}
methods.add(idx, method);
});
module.put("list", methods);
requestItem.add(module);
});
String filePath = config.getOutPath();
filePath = filePath + DocGlobalConstants.YAPI_JSON;
Gson gson = new GsonBuilder().setPrettyPrinting().create();
String data = gson.toJson(requestItem);
FileUtil.nioWriteFile(data, filePath);
}
private static String generateJson(List<ApiParam> responseParams) {
StringBuffer re = new StringBuffer("\"type\":\"object\",\n\"properties\":{\n");
HashSet<String> required = new HashSet<>();
responseParams.stream().forEach(apiParam -> {
re.append(getTypeAndPropertiesJson(apiParam));
if (apiParam.isRequired()) {
required.add(apiParam.getField());
}
});
Gson gs = new Gson();
re.append("\"required\":\"" + gs.toJson(required.toArray()) + "\"");
re.append("\t}");
return re.toString();
}
/**
* 将字段类型转换为yapi的字段类型
*
* @param type java type
* @return String
*/
public static String changeType(String type) {
switch (type) {
case "boolean":
return "boolean";
case "int32":
return "integer";
case "int64":
return "number";
default:
return type;
}
}
/**
* 单个参数拼接字符串
*
* @param param ApiParam
* @return String
*/
public static String getTypeAndPropertiesJson(ApiParam param) {
StringBuffer resultJson = new StringBuffer();
resultJson.append("\"" + param.getField() + "\":{");
resultJson.append("\"type\":\"" + changeType(param.getType()) + "\", ");
if (param.getChildren() != null && param.getChildren().size() > 0) {
if (param.getType().equals("object")) {
resultJson.append(" \"properties\":{");
param.getChildren().forEach(child -> {
resultJson.append(getTypeAndPropertiesJson(child));
});
} else if (param.getType().equals("array")) {
resultJson.append(" \"items\":{");
resultJson.append("\"type\":\"object\",\n\"properties\":{\n");
param.getChildren().forEach(child -> {
resultJson.append(getTypeAndPropertiesJson(child));
});
resultJson.append("\t},");
}
resultJson.append("},");
}
resultJson.append("},");
return resultJson.toString();
}
}

View File

@ -1,149 +1,151 @@
package com.power.doc.constants; package com.power.doc.constants;
/** /**
* @author yu 2018/12/15. * @author yu 2018/12/15.
*/ */
public interface DocGlobalConstants { public interface DocGlobalConstants {
String FILE_SEPARATOR = System.getProperty("file.separator"); String FILE_SEPARATOR = System.getProperty("file.separator");
String HTML_DOC_OUT_PATH = "src/main/resources/static/doc"; String HTML_DOC_OUT_PATH = "src/main/resources/static/doc";
String ADOC_OUT_PATH = "src/docs/asciidoc"; String ADOC_OUT_PATH = "src/docs/asciidoc";
String PROJECT_CODE_PATH = "src" + FILE_SEPARATOR + "main" + FILE_SEPARATOR + "java"; String PROJECT_CODE_PATH = "src" + FILE_SEPARATOR + "main" + FILE_SEPARATOR + "java";
String ABSOLUTE_CODE_PATH = System.getProperty("user.dir") + FILE_SEPARATOR + PROJECT_CODE_PATH; String ABSOLUTE_CODE_PATH = System.getProperty("user.dir") + FILE_SEPARATOR + PROJECT_CODE_PATH;
String DOC_LANGUAGE = "smart-doc_language"; String DOC_LANGUAGE = "smart-doc_language";
String API_DOC_MD_TPL = "ApiDoc.btl"; String API_DOC_MD_TPL = "ApiDoc.btl";
String API_DOC_ADOC_TPL = "ApiDoc.adoc"; String API_DOC_ADOC_TPL = "ApiDoc.adoc";
String ALL_IN_ONE_MD_TPL = "AllInOne.btl"; String ALL_IN_ONE_MD_TPL = "AllInOne.btl";
String ALL_IN_ONE_ADOC_TPL = "AllInOne.adoc"; String ALL_IN_ONE_ADOC_TPL = "AllInOne.adoc";
String ALL_IN_ONE_HTML_TPL = "AllInOne.html"; String ALL_IN_ONE_HTML_TPL = "AllInOne.html";
String HTML_API_DOC_TPL = "HtmlApiDoc.btl"; String HTML_API_DOC_TPL = "HtmlApiDoc.btl";
String ERROR_CODE_LIST_MD_TPL = "ErrorCodeList.btl"; String ERROR_CODE_LIST_MD_TPL = "ErrorCodeList.btl";
String ERROR_CODE_LIST_ADOC_TPL = "ErrorCodeList.adoc"; String ERROR_CODE_LIST_ADOC_TPL = "ErrorCodeList.adoc";
String ERROR_CODE_LIST_MD = "ErrorCodeList.md"; String ERROR_CODE_LIST_MD = "ErrorCodeList.md";
String ERROR_CODE_LIST_ADOC = "ErrorCodeList.adoc"; String ERROR_CODE_LIST_ADOC = "ErrorCodeList.adoc";
String DICT_LIST_MD = "Dictionary.md"; String DICT_LIST_MD = "Dictionary.md";
String DICT_LIST_MD_TPL = "Dictionary.btl"; String DICT_LIST_MD_TPL = "Dictionary.btl";
String DICT_LIST_ADOC = "Dictionary.adoc"; String DICT_LIST_ADOC = "Dictionary.adoc";
String DICT_LIST_ADOC_TPL = "Dictionary.btl"; String DICT_LIST_ADOC_TPL = "Dictionary.btl";
String INDEX_TPL = "Index.btl"; String INDEX_TPL = "Index.btl";
String INDEX_CSS_TPL = "index.css"; String INDEX_CSS_TPL = "index.css";
String MARKDOWN_CSS_TPL = "markdown.css"; String MARKDOWN_CSS_TPL = "markdown.css";
String ALL_IN_ONE_CSS = "AllInOne.css"; String ALL_IN_ONE_CSS = "AllInOne.css";
String RPC_API_DOC_ADOC_TPL = "dubbo/Dubbo.adoc"; String RPC_API_DOC_ADOC_TPL = "dubbo/Dubbo.adoc";
String RPC_ALL_IN_ONE_ADOC_TPL = "dubbo/DubboAllInOne.adoc"; String RPC_ALL_IN_ONE_ADOC_TPL = "dubbo/DubboAllInOne.adoc";
String RPC_ALL_IN_ONE_HTML_TPL = "dubbo/DubboAllInOne.html"; String RPC_ALL_IN_ONE_HTML_TPL = "dubbo/DubboAllInOne.html";
String RPC_DEPENDENCY_MD_TPL = "dubbo/DubboApiDependency.md"; String RPC_DEPENDENCY_MD_TPL = "dubbo/DubboApiDependency.md";
String RPC_API_DOC_MD_TPL = "dubbo/Dubbo.md"; String RPC_API_DOC_MD_TPL = "dubbo/Dubbo.md";
String RPC_ALL_IN_ONE_MD_TPL = "dubbo/DubboAllInOne.md"; String RPC_ALL_IN_ONE_MD_TPL = "dubbo/DubboAllInOne.md";
String RPC_INDEX_TPL = "dubbo/DubboIndex.btl"; String RPC_INDEX_TPL = "dubbo/DubboIndex.btl";
String POSTMAN_JSON = "/postman.json"; String POSTMAN_JSON = "/postman.json";
String OPEN_API_JSON = "/openApi3.0.json"; String OPEN_API_JSON = "/openApi3.0.json";
String CONTROLLER_FULLY = "org.springframework.stereotype.Controller"; String CONTROLLER_FULLY = "org.springframework.stereotype.Controller";
String REST_CONTROLLER_FULLY = "org.springframework.web.bind.annotation.RestController"; String REST_CONTROLLER_FULLY = "org.springframework.web.bind.annotation.RestController";
String GET_MAPPING_FULLY = "org.springframework.web.bind.annotation.GetMapping"; String GET_MAPPING_FULLY = "org.springframework.web.bind.annotation.GetMapping";
String POST_MAPPING_FULLY = "org.springframework.web.bind.annotation.PostMapping"; String POST_MAPPING_FULLY = "org.springframework.web.bind.annotation.PostMapping";
String PUT_MAPPING_FULLY = "org.springframework.web.bind.annotation.PutMapping"; String PUT_MAPPING_FULLY = "org.springframework.web.bind.annotation.PutMapping";
String PATCH_MAPPING_FULLY = "org.springframework.web.bind.annotation.PatchMapping"; String PATCH_MAPPING_FULLY = "org.springframework.web.bind.annotation.PatchMapping";
String DELETE_MAPPING_FULLY = "org.springframework.web.bind.annotation.DeleteMapping"; String DELETE_MAPPING_FULLY = "org.springframework.web.bind.annotation.DeleteMapping";
String REQUEST_MAPPING_FULLY = "org.springframework.web.bind.annotation.RequestMapping"; String REQUEST_MAPPING_FULLY = "org.springframework.web.bind.annotation.RequestMapping";
String REQUEST_BODY_FULLY = "org.springframework.web.bind.annotation.RequestBody"; String REQUEST_BODY_FULLY = "org.springframework.web.bind.annotation.RequestBody";
String MODE_AND_VIEW_FULLY = "org.springframework.web.servlet.ModelAndView"; String MODE_AND_VIEW_FULLY = "org.springframework.web.servlet.ModelAndView";
String MULTIPART_FILE_FULLY = "org.springframework.web.multipart.MultipartFile"; String MULTIPART_FILE_FULLY = "org.springframework.web.multipart.MultipartFile";
String JAVA_OBJECT_FULLY = "java.lang.Object"; String JAVA_OBJECT_FULLY = "java.lang.Object";
String JAVA_STRING_FULLY = "java.lang.String"; String JAVA_STRING_FULLY = "java.lang.String";
String JAVA_MAP_FULLY = "java.util.Map"; String JAVA_MAP_FULLY = "java.util.Map";
String JAVA_LIST_FULLY = "java.util.List"; String JAVA_LIST_FULLY = "java.util.List";
String DEFAULT_VERSION = "-"; String DEFAULT_VERSION = "-";
String ERROR_CODE_LIST_CN_TITLE = "错误码列表"; String ERROR_CODE_LIST_CN_TITLE = "错误码列表";
String ERROR_CODE_LIST_EN_TITLE = "Error Code List"; String ERROR_CODE_LIST_EN_TITLE = "Error Code List";
String DICT_CN_TITLE = "数据字典"; String DICT_CN_TITLE = "数据字典";
String DICT_EN_TITLE = "Data Dictionaries"; String DICT_EN_TITLE = "Data Dictionaries";
String FIELD_SPACE = "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"; String FIELD_SPACE = "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
String ANY_OBJECT_MSG = "any object."; String ANY_OBJECT_MSG = "any object.";
String NO_COMMENTS_FOUND = "No comments found."; String NO_COMMENTS_FOUND = "No comments found.";
String SPRING_WEB_ANNOTATION_PACKAGE = "org.springframework.web.bind.annotation"; String SPRING_WEB_ANNOTATION_PACKAGE = "org.springframework.web.bind.annotation";
String FILE_CONTENT_TYPE = "multipart/form-data"; String FILE_CONTENT_TYPE = "multipart/form-data";
String MULTIPART_TYPE = "multipart/form-data"; String MULTIPART_TYPE = "multipart/form-data";
String APPLICATION_JSON = "application/json"; String APPLICATION_JSON = "application/json";
String JSON_CONTENT_TYPE = "application/json; charset=utf-8"; String JSON_CONTENT_TYPE = "application/json; charset=utf-8";
String POSTMAN_MODE_FORMDATA = "formdata"; String POSTMAN_MODE_FORMDATA = "formdata";
String POSTMAN_MODE_RAW = "raw"; String POSTMAN_MODE_RAW = "raw";
String SHORT_MULTIPART_FILE_FULLY = "MultipartFile"; String SHORT_MULTIPART_FILE_FULLY = "MultipartFile";
String DEFAULT_SERVER_URL = "http://{server}"; String DEFAULT_SERVER_URL = "http://{server}";
String SHORT_REQUEST_BODY = "RequestBody"; String SHORT_REQUEST_BODY = "RequestBody";
String CURL_REQUEST_TYPE = "curl -X %s -i %s"; String CURL_REQUEST_TYPE = "curl -X %s %s -i %s";
String CURL_REQUEST_TYPE_DATA = "curl -X %s -i %s --data '%s'"; String CURL_REQUEST_TYPE_DATA = "curl -X %s %s -i %s --data '%s'";
String CURL_POST_PUT_JSON = "curl -X %s -H 'Content-Type: application/json; charset=utf-8' -i %s --data '%s'"; String CURL_POST_PUT_JSON = "curl -X %s -H 'Content-Type: application/json; charset=utf-8' %s -i %s --data '%s'";
String EMPTY = ""; String EMPTY = "";
String ENUM = "enum"; String ENUM = "enum";
} String YAPI_RESULT_TPL = "yapiJson.btl";
String YAPI_JSON="/yapi.json";
}

View File

@ -48,7 +48,8 @@ public enum TemplateVariable {
URI("uri"), URI("uri"),
RPC_CONSUMER_CONFIG("consumerConfigExample"), RPC_CONSUMER_CONFIG("consumerConfigExample"),
REQUEST_EXAMPLE("isRequestExample"), REQUEST_EXAMPLE("isRequestExample"),
RESPONSE_EXAMPLE("isResponseExample"); RESPONSE_EXAMPLE("isResponseExample"),
RESPONSELIST("respList");
private String variable; private String variable;

View File

@ -1,429 +1,429 @@
/* /*
* smart-doc https://github.com/shalousun/smart-doc * smart-doc https://github.com/shalousun/smart-doc
* *
* Copyright (C) 2018-2020 smart-doc * Copyright (C) 2018-2020 smart-doc
* *
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file * or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information * distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file * regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the * to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance * "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at * with the License. You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, * Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an * software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the * KIND, either express or implied. See the License for the
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * under the License.
*/ */
package com.power.doc.helper; package com.power.doc.helper;
import com.power.common.model.EnumDictionary; import com.power.common.model.EnumDictionary;
import com.power.common.util.CollectionUtil; import com.power.common.util.CollectionUtil;
import com.power.common.util.StringUtil; import com.power.common.util.StringUtil;
import com.power.doc.builder.ProjectDocConfigBuilder; import com.power.doc.builder.ProjectDocConfigBuilder;
import com.power.doc.constants.DocAnnotationConstants; import com.power.doc.constants.DocAnnotationConstants;
import com.power.doc.constants.DocGlobalConstants; import com.power.doc.constants.DocGlobalConstants;
import com.power.doc.constants.DocTags; import com.power.doc.constants.DocTags;
import com.power.doc.constants.ValidatorAnnotations; import com.power.doc.constants.ValidatorAnnotations;
import com.power.doc.model.*; import com.power.doc.model.*;
import com.power.doc.utils.*; import com.power.doc.utils.*;
import com.thoughtworks.qdox.model.*; import com.thoughtworks.qdox.model.*;
import java.util.*; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static com.power.doc.constants.DocGlobalConstants.NO_COMMENTS_FOUND; import static com.power.doc.constants.DocGlobalConstants.NO_COMMENTS_FOUND;
/** /**
* @author yu 2019/12/21. * @author yu 2019/12/21.
*/ */
public class ParamsBuildHelper { public class ParamsBuildHelper {
public static List<ApiParam> buildParams(String className, String pre, int level, String isRequired, public static List<ApiParam> buildParams(String className, String pre, int level, String isRequired,
Map<String, CustomRespField> responseFieldMap, boolean isResp, Map<String, CustomRespField> responseFieldMap, boolean isResp,
Map<String, String> registryClasses, ProjectDocConfigBuilder projectBuilder, Map<String, String> registryClasses, ProjectDocConfigBuilder projectBuilder,
List<String> groupClasses, int pid) { List<String> groupClasses, int pid) {
//存储泛型所对应的实体类 //存储泛型所对应的实体类
Map<String, String> genericMap = new HashMap<>(10); Map<String, String> genericMap = new HashMap<>(10);
if (StringUtil.isEmpty(className)) { if (StringUtil.isEmpty(className)) {
throw new RuntimeException("Class name can't be null or empty."); throw new RuntimeException("Class name can't be null or empty.");
} }
ApiConfig apiConfig = projectBuilder.getApiConfig(); ApiConfig apiConfig = projectBuilder.getApiConfig();
int nextLevel = level + 1; int nextLevel = level + 1;
// Check circular reference // Check circular reference
List<ApiParam> paramList = new ArrayList<>(); List<ApiParam> paramList = new ArrayList<>();
if (level > apiConfig.getRecursionLimit()) { if (level > apiConfig.getRecursionLimit()) {
return paramList; return paramList;
} }
if (registryClasses.containsKey(className) && level > registryClasses.size()) { if (registryClasses.containsKey(className) && level > registryClasses.size()) {
return paramList; return paramList;
} }
boolean skipTransientField = apiConfig.isSkipTransientField(); boolean skipTransientField = apiConfig.isSkipTransientField();
boolean isShowJavaType = projectBuilder.getApiConfig().getShowJavaType(); boolean isShowJavaType = projectBuilder.getApiConfig().getShowJavaType();
boolean requestFieldToUnderline = projectBuilder.getApiConfig().isRequestFieldToUnderline(); boolean requestFieldToUnderline = projectBuilder.getApiConfig().isRequestFieldToUnderline();
boolean responseFieldToUnderline = projectBuilder.getApiConfig().isResponseFieldToUnderline(); boolean responseFieldToUnderline = projectBuilder.getApiConfig().isResponseFieldToUnderline();
// Registry class // Registry class
registryClasses.put(className, className); registryClasses.put(className, className);
String simpleName = DocClassUtil.getSimpleName(className); String simpleName = DocClassUtil.getSimpleName(className);
String[] globGicName = DocClassUtil.getSimpleGicName(className); String[] globGicName = DocClassUtil.getSimpleGicName(className);
JavaClass cls = projectBuilder.getClassByName(simpleName); JavaClass cls = projectBuilder.getClassByName(simpleName);
//如果存在泛型 则将泛型与类名的对应关系存起来 //如果存在泛型 则将泛型与类名的对应关系存起来
if (cls != null && null != cls.getTypeParameters()) { if (cls != null && null != cls.getTypeParameters()) {
List<JavaTypeVariable<JavaGenericDeclaration>> variables = cls.getTypeParameters(); List<JavaTypeVariable<JavaGenericDeclaration>> variables = cls.getTypeParameters();
for (int i = 0; i < cls.getTypeParameters().size() && i<globGicName.length; i++) { for (int i = 0; i < cls.getTypeParameters().size() && i<globGicName.length; i++) {
genericMap.put(variables.get(i).getName(), globGicName[i]); genericMap.put(variables.get(i).getName(), globGicName[i]);
} }
} }
List<DocJavaField> fields = JavaClassUtil.getFields(cls, 0, new HashSet<>()); List<DocJavaField> fields = JavaClassUtil.getFields(cls, 0, new HashSet<>());
if (JavaClassValidateUtil.isPrimitive(simpleName)) { if (JavaClassValidateUtil.isPrimitive(simpleName)) {
String processedType = isShowJavaType ? simpleName : DocClassUtil.processTypeNameForParams(simpleName.toLowerCase()); String processedType = isShowJavaType ? simpleName : DocClassUtil.processTypeNameForParams(simpleName.toLowerCase());
paramList.addAll(primitiveReturnRespComment(processedType)); paramList.addAll(primitiveReturnRespComment(processedType));
} else if (JavaClassValidateUtil.isCollection(simpleName) || JavaClassValidateUtil.isArray(simpleName)) { } else if (JavaClassValidateUtil.isCollection(simpleName) || JavaClassValidateUtil.isArray(simpleName)) {
if (!JavaClassValidateUtil.isCollection(globGicName[0])) { if (!JavaClassValidateUtil.isCollection(globGicName[0])) {
String gicName = globGicName[0]; String gicName = globGicName[0];
if (JavaClassValidateUtil.isArray(gicName)) { if (JavaClassValidateUtil.isArray(gicName)) {
gicName = gicName.substring(0, gicName.indexOf("[")); gicName = gicName.substring(0, gicName.indexOf("["));
} }
paramList.addAll(buildParams(gicName, pre, nextLevel, isRequired, responseFieldMap, isResp, paramList.addAll(buildParams(gicName, pre, nextLevel, isRequired, responseFieldMap, isResp,
registryClasses, projectBuilder, groupClasses, pid)); registryClasses, projectBuilder, groupClasses, pid));
} }
} else if (JavaClassValidateUtil.isMap(simpleName)) { } else if (JavaClassValidateUtil.isMap(simpleName)) {
if (globGicName.length == 2) { if (globGicName.length == 2) {
paramList.addAll(buildParams(globGicName[1], pre, nextLevel, isRequired, responseFieldMap, isResp, paramList.addAll(buildParams(globGicName[1], pre, nextLevel, isRequired, responseFieldMap, isResp,
registryClasses, projectBuilder, groupClasses, pid)); registryClasses, projectBuilder, groupClasses, pid));
} }
} else if (DocGlobalConstants.JAVA_OBJECT_FULLY.equals(className)) { } else if (DocGlobalConstants.JAVA_OBJECT_FULLY.equals(className)) {
ApiParam param = ApiParam.of().setField(pre + "any object").setType("object").setPid(pid); ApiParam param = ApiParam.of().setField(pre + "any object").setType("object").setPid(pid);
if (StringUtil.isEmpty(isRequired)) { if (StringUtil.isEmpty(isRequired)) {
param.setDesc(DocGlobalConstants.ANY_OBJECT_MSG).setVersion(DocGlobalConstants.DEFAULT_VERSION); param.setDesc(DocGlobalConstants.ANY_OBJECT_MSG).setVersion(DocGlobalConstants.DEFAULT_VERSION);
} else { } else {
param.setDesc(DocGlobalConstants.ANY_OBJECT_MSG).setRequired(false).setVersion(DocGlobalConstants.DEFAULT_VERSION); param.setDesc(DocGlobalConstants.ANY_OBJECT_MSG).setRequired(false).setVersion(DocGlobalConstants.DEFAULT_VERSION);
} }
paramList.add(param); paramList.add(param);
} }
// if (className.contains(DocGlobalConstants.MULTIPART_FILE_FULLY)) { // if (className.contains(DocGlobalConstants.MULTIPART_FILE_FULLY)) {
// ApiParam param = ApiParam.of().setField("").setType("file") // ApiParam param = ApiParam.of().setField("").setType("file")
// .setPid(pid) // .setPid(pid)
// .setDesc("comment").setRequired(true).setVersion(DocGlobalConstants.DEFAULT_VERSION); // .setDesc("comment").setRequired(true).setVersion(DocGlobalConstants.DEFAULT_VERSION);
// paramList.add(param); // paramList.add(param);
// } // }
else { else {
boolean isGenerics = JavaFieldUtil.checkGenerics(fields); boolean isGenerics = JavaFieldUtil.checkGenerics(fields);
out: out:
for (DocJavaField docField : fields) { for (DocJavaField docField : fields) {
JavaField field = docField.getJavaField(); JavaField field = docField.getJavaField();
String fieldName = field.getName(); String fieldName = field.getName();
String subTypeName = field.getType().getFullyQualifiedName(); String subTypeName = field.getType().getFullyQualifiedName();
if (field.isStatic() || "this$0".equals(fieldName) || if (field.isStatic() || "this$0".equals(fieldName) ||
JavaClassValidateUtil.isIgnoreFieldTypes(subTypeName)) { JavaClassValidateUtil.isIgnoreFieldTypes(subTypeName)) {
continue; continue;
} }
if (field.isTransient() && skipTransientField) { if (field.isTransient() && skipTransientField) {
continue; continue;
} }
if ((responseFieldToUnderline && isResp) || (requestFieldToUnderline && !isResp)) { if ((responseFieldToUnderline && isResp) || (requestFieldToUnderline && !isResp)) {
fieldName = StringUtil.camelToUnderline(fieldName); fieldName = StringUtil.camelToUnderline(fieldName);
} }
String typeSimpleName = field.getType().getSimpleName(); String typeSimpleName = field.getType().getSimpleName();
String fieldGicName = field.getType().getGenericCanonicalName(); String fieldGicName = field.getType().getGenericCanonicalName();
List<JavaAnnotation> javaAnnotations = docField.getAnnotations(); List<JavaAnnotation> javaAnnotations = docField.getAnnotations();
Map<String, String> tagsMap = DocUtil.getFieldTagsValue(field, docField); Map<String, String> tagsMap = DocUtil.getFieldTagsValue(field, docField);
String since = DocGlobalConstants.DEFAULT_VERSION;//since tag value String since = DocGlobalConstants.DEFAULT_VERSION;//since tag value
if (!isResp) { if (!isResp) {
pre: pre:
if (tagsMap.containsKey(DocTags.IGNORE)) { if (tagsMap.containsKey(DocTags.IGNORE)) {
continue out; continue out;
} else if (tagsMap.containsKey(DocTags.SINCE)) { } else if (tagsMap.containsKey(DocTags.SINCE)) {
since = tagsMap.get(DocTags.SINCE); since = tagsMap.get(DocTags.SINCE);
} }
} else { } else {
if (tagsMap.containsKey(DocTags.SINCE)) { if (tagsMap.containsKey(DocTags.SINCE)) {
since = tagsMap.get(DocTags.SINCE); since = tagsMap.get(DocTags.SINCE);
} }
} }
boolean strRequired = false; boolean strRequired = false;
int annotationCounter = 0; int annotationCounter = 0;
an: an:
for (JavaAnnotation annotation : javaAnnotations) { for (JavaAnnotation annotation : javaAnnotations) {
String simpleAnnotationName = annotation.getType().getValue(); String simpleAnnotationName = annotation.getType().getValue();
if (DocAnnotationConstants.SHORT_JSON_IGNORE.equals(simpleAnnotationName)) { if (DocAnnotationConstants.SHORT_JSON_IGNORE.equals(simpleAnnotationName)) {
continue out; continue out;
} else if (DocAnnotationConstants.SHORT_JSON_FIELD.equals(simpleAnnotationName)) { } else if (DocAnnotationConstants.SHORT_JSON_FIELD.equals(simpleAnnotationName)) {
if (null != annotation.getProperty(DocAnnotationConstants.SERIALIZE_PROP)) { if (null != annotation.getProperty(DocAnnotationConstants.SERIALIZE_PROP)) {
if (Boolean.FALSE.toString().equals(annotation.getProperty(DocAnnotationConstants.SERIALIZE_PROP).toString())) { if (Boolean.FALSE.toString().equals(annotation.getProperty(DocAnnotationConstants.SERIALIZE_PROP).toString())) {
continue out; continue out;
} }
} else if (null != annotation.getProperty(DocAnnotationConstants.NAME_PROP)) { } else if (null != annotation.getProperty(DocAnnotationConstants.NAME_PROP)) {
fieldName = StringUtil.removeQuotes(annotation.getProperty(DocAnnotationConstants.NAME_PROP).toString()); fieldName = StringUtil.removeQuotes(annotation.getProperty(DocAnnotationConstants.NAME_PROP).toString());
} }
} else if (DocAnnotationConstants.SHORT_JSON_PROPERTY.equals(simpleAnnotationName)) { } else if (DocAnnotationConstants.SHORT_JSON_PROPERTY.equals(simpleAnnotationName)) {
if (null != annotation.getProperty(DocAnnotationConstants.VALUE_PROP)) { if (null != annotation.getProperty(DocAnnotationConstants.VALUE_PROP)) {
fieldName = StringUtil.removeQuotes(annotation.getProperty(DocAnnotationConstants.VALUE_PROP).toString()); fieldName = StringUtil.removeQuotes(annotation.getProperty(DocAnnotationConstants.VALUE_PROP).toString());
} }
} else if (ValidatorAnnotations.NULL.equals(simpleAnnotationName) && !isResp) { } else if (ValidatorAnnotations.NULL.equals(simpleAnnotationName) && !isResp) {
List<String> groupClassList = JavaClassUtil.getParamGroupJavaClass(annotation); List<String> groupClassList = JavaClassUtil.getParamGroupJavaClass(annotation);
for (String javaClass : groupClassList) { for (String javaClass : groupClassList) {
if (groupClasses.contains(javaClass)) { if (groupClasses.contains(javaClass)) {
strRequired = false; strRequired = false;
break an; break an;
} }
} }
} else if (JavaClassValidateUtil.isJSR303Required(simpleAnnotationName) && !isResp) { } else if (JavaClassValidateUtil.isJSR303Required(simpleAnnotationName) && !isResp) {
annotationCounter++; annotationCounter++;
boolean hasGroup = false; boolean hasGroup = false;
List<String> groupClassList = JavaClassUtil.getParamGroupJavaClass(annotation); List<String> groupClassList = JavaClassUtil.getParamGroupJavaClass(annotation);
for (String javaClass : groupClassList) { for (String javaClass : groupClassList) {
if (groupClasses.contains(javaClass)) { if (groupClasses.contains(javaClass)) {
hasGroup = true; hasGroup = true;
} }
} }
if (hasGroup) { if (hasGroup) {
strRequired = true; strRequired = true;
} else if (CollectionUtil.isEmpty(groupClasses)) { } else if (CollectionUtil.isEmpty(groupClasses)) {
strRequired = true; strRequired = true;
} }
break an; break an;
} }
} }
if (annotationCounter < 1) { if (annotationCounter < 1) {
doc: doc:
if (tagsMap.containsKey(DocTags.REQUIRED)) { if (tagsMap.containsKey(DocTags.REQUIRED)) {
strRequired = true; strRequired = true;
break doc; break doc;
} }
} }
//cover comment //cover comment
CustomRespField customResponseField = responseFieldMap.get(field.getName()); CustomRespField customResponseField = responseFieldMap.get(field.getName());
String comment; String comment;
if (null != customResponseField && StringUtil.isNotEmpty(customResponseField.getDesc())) { if (null != customResponseField && StringUtil.isNotEmpty(customResponseField.getDesc())) {
comment = customResponseField.getDesc(); comment = customResponseField.getDesc();
} else { } else {
comment = docField.getComment(); comment = docField.getComment();
} }
if (StringUtil.isNotEmpty(comment)) { if (StringUtil.isNotEmpty(comment)) {
comment = DocUtil.replaceNewLineToHtmlBr(comment); comment = DocUtil.replaceNewLineToHtmlBr(comment);
} }
if (JavaClassValidateUtil.isPrimitive(subTypeName)) { if (JavaClassValidateUtil.isPrimitive(subTypeName)) {
ApiParam param = ApiParam.of().setField(pre + fieldName); ApiParam param = ApiParam.of().setField(pre + fieldName);
param.setPid(pid); param.setPid(pid);
String processedType = isShowJavaType ? typeSimpleName : DocClassUtil.processTypeNameForParams(typeSimpleName.toLowerCase()); String processedType = isShowJavaType ? typeSimpleName : DocClassUtil.processTypeNameForParams(typeSimpleName.toLowerCase());
param.setType(processedType); param.setType(processedType);
if (StringUtil.isNotEmpty(comment)) { if (StringUtil.isNotEmpty(comment)) {
commonHandleParam(paramList, param, isRequired, comment, since, strRequired); commonHandleParam(paramList, param, isRequired, comment, since, strRequired);
} else { } else {
commonHandleParam(paramList, param, isRequired, NO_COMMENTS_FOUND, since, strRequired); commonHandleParam(paramList, param, isRequired, NO_COMMENTS_FOUND, since, strRequired);
} }
} else { } else {
ApiParam param = ApiParam.of().setField(pre + fieldName); ApiParam param = ApiParam.of().setField(pre + fieldName).setPid(pid);
JavaClass javaClass = projectBuilder.getJavaProjectBuilder().getClassByName(subTypeName); JavaClass javaClass = projectBuilder.getJavaProjectBuilder().getClassByName(subTypeName);
String enumComments = javaClass.getComment(); String enumComments = javaClass.getComment();
if (javaClass.isEnum()) { if (javaClass.isEnum()) {
if (projectBuilder.getApiConfig().getInlineEnum()) { if (projectBuilder.getApiConfig().getInlineEnum()) {
ApiDataDictionary dataDictionary = projectBuilder.getApiConfig().getDataDictionary(javaClass.getSimpleName()); ApiDataDictionary dataDictionary = projectBuilder.getApiConfig().getDataDictionary(javaClass.getSimpleName());
if (dataDictionary == null) { if (dataDictionary == null) {
comment = comment + JavaClassUtil.getEnumParams(javaClass); comment = comment + JavaClassUtil.getEnumParams(javaClass);
} else { } else {
comment = comment + "(enum:" + dictionaryListComment(dataDictionary) + ")"; comment = comment + "(enum:" + dictionaryListComment(dataDictionary) + ")";
} }
} else { } else {
enumComments = DocUtil.replaceNewLineToHtmlBr(enumComments); enumComments = DocUtil.replaceNewLineToHtmlBr(enumComments);
comment = comment + "<br/>" + JavaClassUtil.getEnumParams(javaClass) + "<br/>"; comment = comment + "<br/>" + JavaClassUtil.getEnumParams(javaClass) + "<br/>";
if (enumComments != null) { if (enumComments != null) {
comment = comment + "(See: " + enumComments + ")"; comment = comment + "(See: " + enumComments + ")";
} }
comment = StringUtil.removeQuotes(comment); comment = StringUtil.removeQuotes(comment);
} }
param.setType(DocGlobalConstants.ENUM); param.setType(DocGlobalConstants.ENUM);
} }
//如果是文件 //如果是文件
if(typeSimpleName.contains(DocGlobalConstants.MULTIPART_FILE_FULLY)){ if(typeSimpleName.contains(DocGlobalConstants.MULTIPART_FILE_FULLY)){
param.setType("file"); param.setType("file");
} }
//如果已经设置返回类型 不需要再次设置 //如果已经设置返回类型 不需要再次设置
if (param.getType() == null) { if (param.getType() == null) {
String processedType; String processedType;
if (typeSimpleName.length() == 1) { if (typeSimpleName.length() == 1) {
processedType = DocClassUtil.processTypeNameForParams(typeSimpleName.toLowerCase()); processedType = DocClassUtil.processTypeNameForParams(typeSimpleName.toLowerCase());
} else { } else {
processedType = isShowJavaType ? typeSimpleName : DocClassUtil.processTypeNameForParams(typeSimpleName.toLowerCase()); processedType = isShowJavaType ? typeSimpleName : DocClassUtil.processTypeNameForParams(typeSimpleName.toLowerCase());
} }
param.setType(processedType); param.setType(processedType);
} }
if (!isResp && javaClass.isEnum()) { if (!isResp && javaClass.isEnum()) {
List<JavaMethod> methods = javaClass.getMethods(); List<JavaMethod> methods = javaClass.getMethods();
int index = 0; int index = 0;
enumOut: enumOut:
for (JavaMethod method : methods) { for (JavaMethod method : methods) {
List<JavaAnnotation> javaAnnotationList = method.getAnnotations(); List<JavaAnnotation> javaAnnotationList = method.getAnnotations();
for (JavaAnnotation annotation : javaAnnotationList) { for (JavaAnnotation annotation : javaAnnotationList) {
if (annotation.getType().getValue().contains("JsonValue")) { if (annotation.getType().getValue().contains("JsonValue")) {
break enumOut; break enumOut;
} }
} }
if (CollectionUtil.isEmpty(javaAnnotations) && index < 1) { if (CollectionUtil.isEmpty(javaAnnotations) && index < 1) {
break enumOut; break enumOut;
} }
index++; index++;
} }
param.setType(DocGlobalConstants.ENUM); param.setType(DocGlobalConstants.ENUM);
} }
if (StringUtil.isNotEmpty(comment)) { if (StringUtil.isNotEmpty(comment)) {
commonHandleParam(paramList, param, isRequired, comment, since, strRequired); commonHandleParam(paramList, param, isRequired, comment, since, strRequired);
} else { } else {
commonHandleParam(paramList, param, isRequired, NO_COMMENTS_FOUND, since, strRequired); commonHandleParam(paramList, param, isRequired, NO_COMMENTS_FOUND, since, strRequired);
} }
StringBuilder preBuilder = new StringBuilder(); StringBuilder preBuilder = new StringBuilder();
for (int j = 0; j < level; j++) { for (int j = 0; j < level; j++) {
preBuilder.append(DocGlobalConstants.FIELD_SPACE); preBuilder.append(DocGlobalConstants.FIELD_SPACE);
} }
preBuilder.append("└─"); preBuilder.append("└─");
int fieldPid = paramList.size(); int fieldPid = paramList.size()+pid;
if (JavaClassValidateUtil.isMap(subTypeName)) { if (JavaClassValidateUtil.isMap(subTypeName)) {
String gNameTemp = field.getType().getGenericCanonicalName(); String gNameTemp = field.getType().getGenericCanonicalName();
if (JavaClassValidateUtil.isMap(gNameTemp)) { if (JavaClassValidateUtil.isMap(gNameTemp)) {
ApiParam param1 = ApiParam.of().setField(preBuilder.toString() + "any object") ApiParam param1 = ApiParam.of().setField(preBuilder.toString() + "any object")
.setId(paramList.size()+1).setPid(fieldPid) .setId(paramList.size()+1).setPid(fieldPid)
.setType("object").setDesc(DocGlobalConstants.ANY_OBJECT_MSG).setVersion(DocGlobalConstants.DEFAULT_VERSION); .setType("object").setDesc(DocGlobalConstants.ANY_OBJECT_MSG).setVersion(DocGlobalConstants.DEFAULT_VERSION);
paramList.add(param1); paramList.add(param1);
continue; continue;
} }
String valType = DocClassUtil.getMapKeyValueType(gNameTemp)[1]; String valType = DocClassUtil.getMapKeyValueType(gNameTemp)[1];
if (!JavaClassValidateUtil.isPrimitive(valType)) { if (!JavaClassValidateUtil.isPrimitive(valType)) {
if (valType.length() == 1) { if (valType.length() == 1) {
String gicName = genericMap.get(valType); String gicName = genericMap.get(valType);
if (!JavaClassValidateUtil.isPrimitive(gicName) && !simpleName.equals(gicName)) { if (!JavaClassValidateUtil.isPrimitive(gicName) && !simpleName.equals(gicName)) {
paramList.addAll(buildParams(gicName, preBuilder.toString(), nextLevel, isRequired, paramList.addAll(buildParams(gicName, preBuilder.toString(), nextLevel, isRequired,
responseFieldMap, isResp, registryClasses, projectBuilder, groupClasses, fieldPid)); responseFieldMap, isResp, registryClasses, projectBuilder, groupClasses, fieldPid));
} }
} else { } else {
paramList.addAll(buildParams(valType, preBuilder.toString(), nextLevel, isRequired, paramList.addAll(buildParams(valType, preBuilder.toString(), nextLevel, isRequired,
responseFieldMap, isResp, registryClasses, projectBuilder, groupClasses, fieldPid)); responseFieldMap, isResp, registryClasses, projectBuilder, groupClasses, fieldPid));
} }
} }
} else if (JavaClassValidateUtil.isCollection(subTypeName)) { } else if (JavaClassValidateUtil.isCollection(subTypeName)) {
String gNameTemp = field.getType().getGenericCanonicalName(); String gNameTemp = field.getType().getGenericCanonicalName();
if (globGicName.length > 0 && "java.util.List".equals(gNameTemp)) { if (globGicName.length > 0 && "java.util.List".equals(gNameTemp)) {
gNameTemp = gNameTemp + "<T>"; gNameTemp = gNameTemp + "<T>";
} }
String[] gNameArr = DocClassUtil.getSimpleGicName(gNameTemp); String[] gNameArr = DocClassUtil.getSimpleGicName(gNameTemp);
if (gNameArr.length == 0) { if (gNameArr.length == 0) {
continue out; continue out;
} }
String gName = DocClassUtil.getSimpleGicName(gNameTemp)[0]; String gName = DocClassUtil.getSimpleGicName(gNameTemp)[0];
if (!JavaClassValidateUtil.isPrimitive(gName)) { if (!JavaClassValidateUtil.isPrimitive(gName)) {
if (!simpleName.equals(gName) && !gName.equals(simpleName)) { if (!simpleName.equals(gName) && !gName.equals(simpleName)) {
if (gName.length() == 1) { if (gName.length() == 1) {
int len = globGicName.length; int len = globGicName.length;
if (len > 0) { if (len > 0) {
String gicName = genericMap.get(gName) != null ? genericMap.get(gName) : globGicName[0]; String gicName = genericMap.get(gName) != null ? genericMap.get(gName) : globGicName[0];
if (!JavaClassValidateUtil.isPrimitive(gicName) && !simpleName.equals(gicName)) { if (!JavaClassValidateUtil.isPrimitive(gicName) && !simpleName.equals(gicName)) {
paramList.addAll(buildParams(gicName, preBuilder.toString(), nextLevel, isRequired, paramList.addAll(buildParams(gicName, preBuilder.toString(), nextLevel, isRequired,
responseFieldMap, isResp, registryClasses, projectBuilder, groupClasses, fieldPid)); responseFieldMap, isResp, registryClasses, projectBuilder, groupClasses, fieldPid));
} }
} }
} else { } else {
paramList.addAll(buildParams(gName, preBuilder.toString(), nextLevel, isRequired, paramList.addAll(buildParams(gName, preBuilder.toString(), nextLevel, isRequired,
responseFieldMap, isResp, registryClasses, projectBuilder, groupClasses, fieldPid)); responseFieldMap, isResp, registryClasses, projectBuilder, groupClasses, fieldPid));
} }
} }
} }
} else } else
if (subTypeName.length() == 1 || DocGlobalConstants.JAVA_OBJECT_FULLY.equals(subTypeName)) { if (subTypeName.length() == 1 || DocGlobalConstants.JAVA_OBJECT_FULLY.equals(subTypeName)) {
if (isGenerics && DocGlobalConstants.JAVA_OBJECT_FULLY.equals(subTypeName)) { if (isGenerics && DocGlobalConstants.JAVA_OBJECT_FULLY.equals(subTypeName)) {
ApiParam param1 = ApiParam.of().setField(preBuilder.toString() + "any object") ApiParam param1 = ApiParam.of().setField(preBuilder.toString() + "any object")
.setId(paramList.size()) .setId(paramList.size())
.setType("object").setDesc(DocGlobalConstants.ANY_OBJECT_MSG).setVersion(DocGlobalConstants.DEFAULT_VERSION); .setType("object").setDesc(DocGlobalConstants.ANY_OBJECT_MSG).setVersion(DocGlobalConstants.DEFAULT_VERSION);
paramList.add(param1); paramList.add(param1);
} else if (!simpleName.equals(className)) { } else if (!simpleName.equals(className)) {
if (globGicName.length > 0) { if (globGicName.length > 0) {
String gicName = genericMap.get(subTypeName) != null ? genericMap.get(subTypeName) : globGicName[0]; String gicName = genericMap.get(subTypeName) != null ? genericMap.get(subTypeName) : globGicName[0];
String simple = DocClassUtil.getSimpleName(gicName); String simple = DocClassUtil.getSimpleName(gicName);
if (JavaClassValidateUtil.isPrimitive(simple)) { if (JavaClassValidateUtil.isPrimitive(simple)) {
//do nothing //do nothing
} else if (gicName.contains("<")) { } else if (gicName.contains("<")) {
if (JavaClassValidateUtil.isCollection(simple)) { if (JavaClassValidateUtil.isCollection(simple)) {
String gName = DocClassUtil.getSimpleGicName(gicName)[0]; String gName = DocClassUtil.getSimpleGicName(gicName)[0];
if (!JavaClassValidateUtil.isPrimitive(gName)) { if (!JavaClassValidateUtil.isPrimitive(gName)) {
paramList.addAll(buildParams(gName, preBuilder.toString(), nextLevel, isRequired, paramList.addAll(buildParams(gName, preBuilder.toString(), nextLevel, isRequired,
responseFieldMap, isResp, registryClasses, projectBuilder, groupClasses, fieldPid)); responseFieldMap, isResp, registryClasses, projectBuilder, groupClasses, fieldPid));
} }
} else if (JavaClassValidateUtil.isMap(simple)) { } else if (JavaClassValidateUtil.isMap(simple)) {
String valType = DocClassUtil.getMapKeyValueType(gicName)[1]; String valType = DocClassUtil.getMapKeyValueType(gicName)[1];
if (!JavaClassValidateUtil.isPrimitive(valType)) { if (!JavaClassValidateUtil.isPrimitive(valType)) {
paramList.addAll(buildParams(valType, preBuilder.toString(), nextLevel, isRequired, paramList.addAll(buildParams(valType, preBuilder.toString(), nextLevel, isRequired,
responseFieldMap, isResp, registryClasses, projectBuilder, groupClasses, fieldPid)); responseFieldMap, isResp, registryClasses, projectBuilder, groupClasses, fieldPid));
} }
} else { } else {
paramList.addAll(buildParams(gicName, preBuilder.toString(), nextLevel, isRequired, paramList.addAll(buildParams(gicName, preBuilder.toString(), nextLevel, isRequired,
responseFieldMap, isResp, registryClasses, projectBuilder, groupClasses, fieldPid)); responseFieldMap, isResp, registryClasses, projectBuilder, groupClasses, fieldPid));
} }
} else { } else {
paramList.addAll(buildParams(gicName, preBuilder.toString(), nextLevel, isRequired, paramList.addAll(buildParams(gicName, preBuilder.toString(), nextLevel, isRequired,
responseFieldMap, isResp, registryClasses, projectBuilder, groupClasses, fieldPid)); responseFieldMap, isResp, registryClasses, projectBuilder, groupClasses, fieldPid));
} }
} else { } else {
paramList.addAll(buildParams(subTypeName, preBuilder.toString(), nextLevel, isRequired, paramList.addAll(buildParams(subTypeName, preBuilder.toString(), nextLevel, isRequired,
responseFieldMap, isResp, registryClasses, projectBuilder, groupClasses, fieldPid)); responseFieldMap, isResp, registryClasses, projectBuilder, groupClasses, fieldPid));
} }
} }
} else if (JavaClassValidateUtil.isArray(subTypeName)) { } else if (JavaClassValidateUtil.isArray(subTypeName)) {
fieldGicName = fieldGicName.substring(0, fieldGicName.indexOf("[")); fieldGicName = fieldGicName.substring(0, fieldGicName.indexOf("["));
if (className.equals(fieldGicName)) { if (className.equals(fieldGicName)) {
//do nothing //do nothing
} else if (!JavaClassValidateUtil.isPrimitive(fieldGicName)) { } else if (!JavaClassValidateUtil.isPrimitive(fieldGicName)) {
paramList.addAll(buildParams(fieldGicName, preBuilder.toString(), nextLevel, isRequired, paramList.addAll(buildParams(fieldGicName, preBuilder.toString(), nextLevel, isRequired,
responseFieldMap, isResp, registryClasses, projectBuilder, groupClasses, fieldPid)); responseFieldMap, isResp, registryClasses, projectBuilder, groupClasses, fieldPid));
} }
} else if (simpleName.equals(subTypeName)) { } else if (simpleName.equals(subTypeName)) {
//do nothing //do nothing
} else { } else {
if (!javaClass.isEnum()) { if (!javaClass.isEnum()) {
paramList.addAll(buildParams(fieldGicName, preBuilder.toString(), nextLevel, isRequired, paramList.addAll(buildParams(fieldGicName, preBuilder.toString(), nextLevel, isRequired,
responseFieldMap, isResp, registryClasses, projectBuilder, groupClasses, fieldPid)); responseFieldMap, isResp, registryClasses, projectBuilder, groupClasses, fieldPid));
} }
} }
} }
} }
} }
return paramList; return paramList;
} }
public static String dictionaryListComment(ApiDataDictionary dictionary) { public static String dictionaryListComment(ApiDataDictionary dictionary) {
List<EnumDictionary> enumDataDict = dictionary.getEnumDataDict(); List<EnumDictionary> enumDataDict = dictionary.getEnumDataDict();
return enumDataDict.stream().map(apiDataDictionary -> return enumDataDict.stream().map(apiDataDictionary ->
apiDataDictionary.getValue() + ":" + apiDataDictionary.getDesc() apiDataDictionary.getValue() + ":" + apiDataDictionary.getDesc()
).collect(Collectors.joining(",")); ).collect(Collectors.joining(","));
} }
public static List<ApiParam> primitiveReturnRespComment(String typeName) { public static List<ApiParam> primitiveReturnRespComment(String typeName) {
StringBuilder comments = new StringBuilder(); StringBuilder comments = new StringBuilder();
comments.append("The api directly returns the ").append(typeName).append(" type value."); comments.append("The api directly returns the ").append(typeName).append(" type value.");
ApiParam apiParam = ApiParam.of().setField("No field") ApiParam apiParam = ApiParam.of().setField("No field")
.setType(typeName).setDesc(comments.toString()).setVersion(DocGlobalConstants.DEFAULT_VERSION); .setType(typeName).setDesc(comments.toString()).setVersion(DocGlobalConstants.DEFAULT_VERSION);
List<ApiParam> paramList = new ArrayList<>(); List<ApiParam> paramList = new ArrayList<>();
paramList.add(apiParam); paramList.add(apiParam);
return paramList; return paramList;
} }
private static void commonHandleParam(List<ApiParam> paramList, ApiParam param, String isRequired, String comment, String since, boolean strRequired) { private static void commonHandleParam(List<ApiParam> paramList, ApiParam param, String isRequired, String comment, String since, boolean strRequired) {
if (StringUtil.isEmpty(isRequired)) { if (StringUtil.isEmpty(isRequired)) {
param.setDesc(comment).setVersion(since); param.setDesc(comment).setVersion(since);
} else { } else {
param.setDesc(comment).setVersion(since).setRequired(strRequired); param.setDesc(comment).setVersion(since).setRequired(strRequired);
} }
param.setId(paramList.size() + param.getPid() + 1); param.setId(paramList.size() + param.getPid() + 1);
paramList.add(param); paramList.add(param);
} }
} }

View File

@ -1,157 +1,162 @@
/* /*
* smart-doc * smart-doc
* *
* Copyright (C) 2018-2020 smart-doc * Copyright (C) 2018-2020 smart-doc
* *
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file * or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information * distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file * regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the * to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance * "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at * with the License. You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, * Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an * software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the * KIND, either express or implied. See the License for the
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * under the License.
*/ */
package com.power.doc.model; package com.power.doc.model;
import java.util.List; import java.util.ArrayList;
import java.util.List;
/**
* @author yu 2019/9/27. /**
*/ * @author yu 2019/9/27.
public class ApiParam { */
public class ApiParam {
/**
* field id /**
*/ * field id
private int id = 1; */
private int id = 1;
/**
* field /**
*/ * field
private String field; */
private String field;
/**
* field type /**
*/ * field type
private String type; */
private String type;
/**
* description /**
*/ * description
private String desc; */
private String desc;
/**
* require flag /**
*/ * require flag
private boolean required; */
private boolean required;
/**
* version /**
*/ * version
private String version; */
private String version;
/**
* field pid /**
*/ * field pid
private int pid; */
/** private int pid;
* PathVariableParams flag
*/ /**
private boolean isPathParams; * PathVariableParams flag
*/
private List<ApiParam> children; private boolean isPathParams;
public static ApiParam of(){ /**
return new ApiParam(); * children params
} */
private List<ApiParam> children;
public String getField() {
return field; public static ApiParam of(){
} return new ApiParam();
}
public ApiParam setField(String field) {
this.field = field; public String getField() {
return this; return field;
} }
public String getType() { public ApiParam setField(String field) {
return type; this.field = field;
} return this;
}
public ApiParam setType(String type) {
this.type = type; public String getType() {
return this; return type;
} }
public String getDesc() { public ApiParam setType(String type) {
return desc; this.type = type;
} return this;
}
public ApiParam setDesc(String desc) {
this.desc = desc; public String getDesc() {
return this; return desc;
} }
public boolean isRequired() { public ApiParam setDesc(String desc) {
return required; this.desc = desc;
} return this;
}
public ApiParam setRequired(boolean required) {
this.required = required; public boolean isRequired() {
return this; return required;
} }
public String getVersion() { public ApiParam setRequired(boolean required) {
return version; this.required = required;
} return this;
}
public ApiParam setVersion(String version) {
this.version = version; public String getVersion() {
return this; return version;
} }
public int getId() { public ApiParam setVersion(String version) {
return id; this.version = version;
} return this;
}
public ApiParam setId(int id) {
this.id = id; public int getId() {
return this; return id;
} }
public int getPid() { public ApiParam setId(int id) {
return pid; this.id = id;
} return this;
}
public ApiParam setPid(int pid) {
this.pid = pid; public int getPid() {
return this; return pid;
} }
public List<ApiParam> getChildren() { public ApiParam setPid(int pid) {
return children; this.pid = pid;
} return this;
}
public boolean isPathParams() {
return isPathParams; public List<ApiParam> getChildren() {
} return children;
}
public ApiParam setPathParams(boolean pathParams) {
isPathParams = pathParams; public boolean isPathParams() {
return this; return isPathParams;
} }
public ApiParam setChildren(List<ApiParam> children) { public ApiParam setPathParams(boolean pathParams) {
this.children = children; isPathParams = pathParams;
return this; return this;
} }
}
public ApiParam setChildren(List<ApiParam> children) {
this.children = children;
return this;
}
}

View File

@ -22,7 +22,10 @@
*/ */
package com.power.doc.template; package com.power.doc.template;
import com.power.common.util.*; import com.power.common.util.JsonFormatUtil;
import com.power.common.util.RandomUtil;
import com.power.common.util.StringUtil;
import com.power.common.util.UrlUtil;
import com.power.doc.builder.ProjectDocConfigBuilder; import com.power.doc.builder.ProjectDocConfigBuilder;
import com.power.doc.constants.*; import com.power.doc.constants.*;
import com.power.doc.handler.SpringMVCRequestHeaderHandler; import com.power.doc.handler.SpringMVCRequestHeaderHandler;
@ -44,7 +47,6 @@ import java.util.stream.Stream;
import static com.power.doc.constants.DocGlobalConstants.FILE_CONTENT_TYPE; import static com.power.doc.constants.DocGlobalConstants.FILE_CONTENT_TYPE;
import static com.power.doc.constants.DocGlobalConstants.JSON_CONTENT_TYPE; import static com.power.doc.constants.DocGlobalConstants.JSON_CONTENT_TYPE;
import static com.power.doc.constants.DocTags.IGNORE; import static com.power.doc.constants.DocTags.IGNORE;
import static com.power.doc.constants.DocTags.PARAM;
/** /**
* @author yu 2019/12/21. * @author yu 2019/12/21.
@ -90,8 +92,8 @@ public class SpringBootDocBuildTemplate implements IDocBuildTemplate<ApiDoc> {
} }
@Override @Override
public boolean ignoreReturnObject(String typeName,List<String> ignoreParams) { public boolean ignoreReturnObject(String typeName, List<String> ignoreParams) {
if (JavaClassValidateUtil.isMvcIgnoreParams(typeName,ignoreParams)) { if (JavaClassValidateUtil.isMvcIgnoreParams(typeName, ignoreParams)) {
return DocGlobalConstants.MODE_AND_VIEW_FULLY.equals(typeName); return DocGlobalConstants.MODE_AND_VIEW_FULLY.equals(typeName);
} }
return false; return false;
@ -165,6 +167,17 @@ public class SpringBootDocBuildTemplate implements IDocBuildTemplate<ApiDoc> {
requestParams = ApiParamTreeUtil.apiParamToTree(requestParams); requestParams = ApiParamTreeUtil.apiParamToTree(requestParams);
} }
apiMethodDoc.setRequestParams(requestParams); apiMethodDoc.setRequestParams(requestParams);
List<ApiReqHeader> allApiReqHeaders;
if (this.headers != null) {
allApiReqHeaders = Stream.of(this.headers, apiReqHeaders)
.flatMap(Collection::stream).distinct().collect(Collectors.toList());
} else {
allApiReqHeaders = apiReqHeaders;
}
//reduce create in template
apiMethodDoc.setHeaders(this.createDocRenderHeaders(allApiReqHeaders, apiConfig.isAdoc()));
apiMethodDoc.setRequestHeaders(allApiReqHeaders);
// build request json // build request json
ApiRequestExample requestExample = buildReqJson(method, apiMethodDoc, requestMapping.getMethodType(), ApiRequestExample requestExample = buildReqJson(method, apiMethodDoc, requestMapping.getMethodType(),
projectBuilder); projectBuilder);
@ -180,16 +193,6 @@ public class SpringBootDocBuildTemplate implements IDocBuildTemplate<ApiDoc> {
responseParams = ApiParamTreeUtil.apiParamToTree(responseParams); responseParams = ApiParamTreeUtil.apiParamToTree(responseParams);
} }
apiMethodDoc.setResponseParams(responseParams); apiMethodDoc.setResponseParams(responseParams);
List<ApiReqHeader> allApiReqHeaders;
if (this.headers != null) {
allApiReqHeaders = Stream.of(this.headers, apiReqHeaders)
.flatMap(Collection::stream).distinct().collect(Collectors.toList());
} else {
allApiReqHeaders = apiReqHeaders;
}
//reduce create in template
apiMethodDoc.setHeaders(this.createDocRenderHeaders(allApiReqHeaders, apiConfig.isAdoc()));
apiMethodDoc.setRequestHeaders(allApiReqHeaders);
methodDocList.add(apiMethodDoc); methodDocList.add(apiMethodDoc);
} }
} }
@ -199,9 +202,18 @@ public class SpringBootDocBuildTemplate implements IDocBuildTemplate<ApiDoc> {
private ApiRequestExample buildReqJson(JavaMethod method, ApiMethodDoc apiMethodDoc, String methodType, private ApiRequestExample buildReqJson(JavaMethod method, ApiMethodDoc apiMethodDoc, String methodType,
ProjectDocConfigBuilder configBuilder) { ProjectDocConfigBuilder configBuilder) {
List<JavaParameter> parameterList = method.getParameters(); List<JavaParameter> parameterList = method.getParameters();
if (parameterList.size() < 1) { List<ApiReqHeader> reqHeaderList = apiMethodDoc.getRequestHeaders();
return ApiRequestExample.builder().setUrl(apiMethodDoc.getUrl()); StringBuilder header = new StringBuilder(reqHeaderList.size());
for (ApiReqHeader reqHeader : reqHeaderList) {
header.append(" -H ").append("'").append(reqHeader.getName())
.append(":").append(reqHeader.getValue()).append("'");
} }
if (parameterList.size() < 1) {
String format = String.format(DocGlobalConstants.CURL_REQUEST_TYPE, methodType,
header.toString(), apiMethodDoc.getUrl());
return ApiRequestExample.builder().setUrl(apiMethodDoc.getUrl()).setExampleBody(format);
}
Map<String, String> constantsMap = configBuilder.getConstantsMap(); Map<String, String> constantsMap = configBuilder.getConstantsMap();
boolean requestFieldToUnderline = configBuilder.getApiConfig().isRequestFieldToUnderline(); boolean requestFieldToUnderline = configBuilder.getApiConfig().isRequestFieldToUnderline();
Map<String, String> replacementMap = configBuilder.getReplaceClassMap(); Map<String, String> replacementMap = configBuilder.getReplaceClassMap();
@ -210,7 +222,6 @@ public class SpringBootDocBuildTemplate implements IDocBuildTemplate<ApiDoc> {
List<String> springMvcRequestAnnotations = SpringMvcRequestAnnotationsEnum.listSpringMvcRequestAnnotations(); List<String> springMvcRequestAnnotations = SpringMvcRequestAnnotationsEnum.listSpringMvcRequestAnnotations();
List<FormData> formDataList = new ArrayList<>(); List<FormData> formDataList = new ArrayList<>();
ApiRequestExample requestExample = ApiRequestExample.builder(); ApiRequestExample requestExample = ApiRequestExample.builder();
Set<String> jsonParamSet = this.jsonParamSet(parameterList);
out: out:
for (JavaParameter parameter : parameterList) { for (JavaParameter parameter : parameterList) {
JavaType javaType = parameter.getType(); JavaType javaType = parameter.getType();
@ -218,12 +229,9 @@ public class SpringBootDocBuildTemplate implements IDocBuildTemplate<ApiDoc> {
String typeName = javaType.getFullyQualifiedName(); String typeName = javaType.getFullyQualifiedName();
String gicTypeName = javaType.getGenericCanonicalName(); String gicTypeName = javaType.getGenericCanonicalName();
String rewriteClassName = null; String rewriteClassName = null;
if (jsonParamSet.size() > 0 && !jsonParamSet.contains(paramName)) {
continue;
}
String commentClass = paramsComments.get(paramName); String commentClass = paramsComments.get(paramName);
//ignore request params //ignore request params
if(Objects.nonNull(commentClass) && commentClass.contains(IGNORE)){ if (Objects.nonNull(commentClass) && commentClass.contains(IGNORE)) {
continue; continue;
} }
if (Objects.nonNull(commentClass) && !DocGlobalConstants.NO_COMMENTS_FOUND.equals(commentClass)) { if (Objects.nonNull(commentClass) && !DocGlobalConstants.NO_COMMENTS_FOUND.equals(commentClass)) {
@ -237,7 +245,7 @@ public class SpringBootDocBuildTemplate implements IDocBuildTemplate<ApiDoc> {
gicTypeName = rewriteClassName; gicTypeName = rewriteClassName;
typeName = DocClassUtil.getSimpleName(rewriteClassName); typeName = DocClassUtil.getSimpleName(rewriteClassName);
} }
if (JavaClassValidateUtil.isMvcIgnoreParams(typeName,configBuilder.getApiConfig().getIgnoreRequestParams())) { if (JavaClassValidateUtil.isMvcIgnoreParams(typeName, configBuilder.getApiConfig().getIgnoreRequestParams())) {
continue; continue;
} }
String simpleTypeName = javaType.getValue().toLowerCase(); String simpleTypeName = javaType.getValue().toLowerCase();
@ -380,18 +388,19 @@ public class SpringBootDocBuildTemplate implements IDocBuildTemplate<ApiDoc> {
body = StringUtil.removeQuotes(body); body = StringUtil.removeQuotes(body);
url = apiMethodDoc.getServerUrl() + "/" + path; url = apiMethodDoc.getServerUrl() + "/" + path;
url = UrlUtil.simplifyUrl(url); url = UrlUtil.simplifyUrl(url);
String format = String.format(DocGlobalConstants.CURL_REQUEST_TYPE, methodType, header.toString(), url);
if (requestExample.isJson()) { if (requestExample.isJson()) {
if (StringUtil.isNotEmpty(requestExample.getJsonBody())) { if (StringUtil.isNotEmpty(requestExample.getJsonBody())) {
exampleBody = String.format(DocGlobalConstants.CURL_POST_PUT_JSON, methodType, url, exampleBody = String.format(DocGlobalConstants.CURL_POST_PUT_JSON, methodType,header.toString(), url,
requestExample.getJsonBody()); requestExample.getJsonBody());
} else { } else {
exampleBody = String.format(DocGlobalConstants.CURL_REQUEST_TYPE, methodType, url); exampleBody = format;
} }
} else { } else {
if (StringUtil.isNotEmpty(body)) { if (StringUtil.isNotEmpty(body)) {
exampleBody = String.format(DocGlobalConstants.CURL_REQUEST_TYPE_DATA, methodType, url, body); exampleBody = String.format(DocGlobalConstants.CURL_REQUEST_TYPE_DATA, methodType,header.toString(), url, body);
} else { } else {
exampleBody = String.format(DocGlobalConstants.CURL_REQUEST_TYPE, methodType, url); exampleBody = format;
} }
} }
requestExample.setExampleBody(exampleBody).setUrl(url); requestExample.setExampleBody(exampleBody).setUrl(url);
@ -403,7 +412,7 @@ public class SpringBootDocBuildTemplate implements IDocBuildTemplate<ApiDoc> {
url = StringUtil.removeQuotes(url); url = StringUtil.removeQuotes(url);
url = apiMethodDoc.getServerUrl() + "/" + url; url = apiMethodDoc.getServerUrl() + "/" + url;
url = UrlUtil.simplifyUrl(url); url = UrlUtil.simplifyUrl(url);
exampleBody = String.format(DocGlobalConstants.CURL_REQUEST_TYPE, methodType, url); exampleBody = String.format(DocGlobalConstants.CURL_REQUEST_TYPE, methodType,header.toString(), url);
requestExample.setExampleBody(exampleBody) requestExample.setExampleBody(exampleBody)
.setJsonBody(DocGlobalConstants.EMPTY) .setJsonBody(DocGlobalConstants.EMPTY)
.setUrl(url); .setUrl(url);
@ -424,15 +433,11 @@ public class SpringBootDocBuildTemplate implements IDocBuildTemplate<ApiDoc> {
} }
Map<String, String> constantsMap = builder.getConstantsMap(); Map<String, String> constantsMap = builder.getConstantsMap();
boolean requestFieldToUnderline = builder.getApiConfig().isRequestFieldToUnderline(); boolean requestFieldToUnderline = builder.getApiConfig().isRequestFieldToUnderline();
Set<String> jsonParamSet = this.jsonParamSet(parameterList);
List<ApiParam> paramList = new ArrayList<>(); List<ApiParam> paramList = new ArrayList<>();
int requestBodyCounter = 0; int requestBodyCounter = 0;
out: out:
for (JavaParameter parameter : parameterList) { for (JavaParameter parameter : parameterList) {
String paramName = parameter.getName(); String paramName = parameter.getName();
if (jsonParamSet.size() > 0 && !jsonParamSet.contains(paramName)) {
continue;
}
String typeName = parameter.getType().getGenericCanonicalName(); String typeName = parameter.getType().getGenericCanonicalName();
String simpleName = parameter.getType().getValue().toLowerCase(); String simpleName = parameter.getType().getValue().toLowerCase();
String fullTypeName = parameter.getType().getFullyQualifiedName(); String fullTypeName = parameter.getType().getFullyQualifiedName();
@ -449,7 +454,7 @@ public class SpringBootDocBuildTemplate implements IDocBuildTemplate<ApiDoc> {
typeName = rewriteClassName; typeName = rewriteClassName;
fullTypeName = DocClassUtil.getSimpleName(rewriteClassName); fullTypeName = DocClassUtil.getSimpleName(rewriteClassName);
} }
if (JavaClassValidateUtil.isMvcIgnoreParams(typeName,builder.getApiConfig().getIgnoreRequestParams())) { if (JavaClassValidateUtil.isMvcIgnoreParams(typeName, builder.getApiConfig().getIgnoreRequestParams())) {
continue out; continue out;
} }
fullTypeName = DocClassUtil.rewriteRequestParam(fullTypeName); fullTypeName = DocClassUtil.rewriteRequestParam(fullTypeName);
@ -482,7 +487,7 @@ public class SpringBootDocBuildTemplate implements IDocBuildTemplate<ApiDoc> {
} }
if (SpringMvcAnnotations.REQUEST_PARAM.equals(annotationName) || if (SpringMvcAnnotations.REQUEST_PARAM.equals(annotationName) ||
DocAnnotationConstants.SHORT_PATH_VARIABLE.equals(annotationName)) { DocAnnotationConstants.SHORT_PATH_VARIABLE.equals(annotationName)) {
if(DocAnnotationConstants.SHORT_PATH_VARIABLE.equals(annotationName)){ if (DocAnnotationConstants.SHORT_PATH_VARIABLE.equals(annotationName)) {
isPathVariable = true; isPathVariable = true;
} }
paramName = getParamName(paramName, annotation); paramName = getParamName(paramName, annotation);
@ -508,8 +513,8 @@ public class SpringBootDocBuildTemplate implements IDocBuildTemplate<ApiDoc> {
} }
} }
Boolean required = Boolean.parseBoolean(strRequired); Boolean required = Boolean.parseBoolean(strRequired);
if(isPathVariable){ if (isPathVariable) {
comment = comment +" (This is path param)"; comment = comment + " (This is path param)";
} }
if (JavaClassValidateUtil.isCollection(fullTypeName) || JavaClassValidateUtil.isArray(fullTypeName)) { if (JavaClassValidateUtil.isCollection(fullTypeName) || JavaClassValidateUtil.isArray(fullTypeName)) {
String[] gicNameArr = DocClassUtil.getSimpleGicName(typeName); String[] gicNameArr = DocClassUtil.getSimpleGicName(typeName);
@ -600,19 +605,4 @@ public class SpringBootDocBuildTemplate implements IDocBuildTemplate<ApiDoc> {
} }
return false; return false;
} }
public Set<String> jsonParamSet(List<JavaParameter> parameterList) {
Set<String> jsonParamSet = new HashSet<>();
for (JavaParameter parameter : parameterList) {
String paramName = parameter.getName();
List<JavaAnnotation> annotations = parameter.getAnnotations();
for (JavaAnnotation annotation : annotations) {
String annotationName = annotation.getType().getValue();
if (SpringMvcAnnotations.REQUEST_BODY.equals(annotationName)) {
jsonParamSet.add(paramName);
}
}
}
return jsonParamSet;
}
} }

View File

@ -46,6 +46,9 @@ public class ApiParamTreeUtil {
childList.add(param); childList.add(param);
} }
} }
for (ApiParam param : childList) {
param.setChildren(getChild(param.getId(), apiParamList));
}
if (childList.size() == 0) { if (childList.size() == 0) {
return null; return null;
} }

View File

@ -1,254 +1,254 @@
/* /*
* smart-doc * smart-doc
* *
* Copyright (C) 2018-2020 smart-doc * Copyright (C) 2018-2020 smart-doc
* *
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file * or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information * distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file * regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the * to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance * "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at * with the License. You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, * Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an * software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the * KIND, either express or implied. See the License for the
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * under the License.
*/ */
package com.power.doc.utils; package com.power.doc.utils;
import com.power.common.util.StringUtil; import com.power.common.util.StringUtil;
import com.power.doc.filter.ReturnTypeProcessor; import com.power.doc.filter.ReturnTypeProcessor;
import com.power.doc.model.ApiReturn; import com.power.doc.model.ApiReturn;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Stack;
/**
/** * Description:
* Description: * Doc class handle util
* Doc class handle util *
* * @author yu 2018//14.
* @author yu 2018//14. */
*/ public class DocClassUtil {
public class DocClassUtil {
/**
/** * get class names by generic class name
* get class names by generic class name *
* * @param returnType generic class name
* @param returnType generic class name * @return array of string
* @return array of string */
*/ public static String[] getSimpleGicName(String returnType) {
public static String[] getSimpleGicName(String returnType) { if (returnType.contains("<")) {
if (returnType.contains("<")) { String pre = returnType.substring(0, returnType.indexOf("<"));
String pre = returnType.substring(0, returnType.indexOf("<")); if (JavaClassValidateUtil.isMap(pre)) {
if (JavaClassValidateUtil.isMap(pre)) { return getMapKeyValueType(returnType);
return getMapKeyValueType(returnType); }
} String type = returnType.substring(returnType.indexOf("<") + 1, returnType.lastIndexOf(">"));
String type = returnType.substring(returnType.indexOf("<") + 1, returnType.lastIndexOf(">")); if (JavaClassValidateUtil.isCollection(pre)) {
if (JavaClassValidateUtil.isCollection(pre)) { return type.split(" ");
return type.split(" "); }
} String[] arr = type.split(",");
String[] arr = type.split(","); return classNameFix(arr);
return classNameFix(arr); } else {
} else { return returnType.split(" ");
return returnType.split(" "); }
} }
}
/**
/** * Get a simple type name from a generic class name
* Get a simple type name from a generic class name *
* * @param gicName Generic class name
* @param gicName Generic class name * @return String
* @return String */
*/ public static String getSimpleName(String gicName) {
public static String getSimpleName(String gicName) { if (gicName.contains("<")) {
if (gicName.contains("<")) { return gicName.substring(0, gicName.indexOf("<"));
return gicName.substring(0, gicName.indexOf("<")); } else {
} else { return gicName;
return gicName; }
} }
}
/**
/** * Automatic repair of generic split class names
* Automatic repair of generic split class names *
* * @param arr arr of class name
* @param arr arr of class name * @return array of String
* @return array of String */
*/ private static String[] classNameFix(String[] arr) {
private static String[] classNameFix(String[] arr) { List<String> classes = new ArrayList<>();
List<String> classes = new ArrayList<>(); List<Integer> indexList = new ArrayList<>();
List<Integer> indexList = new ArrayList<>(); int globIndex = 0;
int globIndex = 0; int length = arr.length;
int length = arr.length; for (int i = 0; i < length; i++) {
for (int i = 0; i < length; i++) { if (classes.size() > 0) {
if (classes.size() > 0) { int index = classes.size() - 1;
int index = classes.size() - 1; if (!isClassName(classes.get(index))) {
if (!isClassName(classes.get(index))) { globIndex = globIndex + 1;
globIndex = globIndex + 1; if (globIndex < length) {
if (globIndex < length) { indexList.add(globIndex);
indexList.add(globIndex); String className = classes.get(index) + "," + arr[globIndex];
String className = classes.get(index) + "," + arr[globIndex]; classes.set(index, className);
classes.set(index, className); }
} } else {
} else { globIndex = globIndex + 1;
globIndex = globIndex + 1; if (globIndex < length) {
if (globIndex < length) { if (isClassName(arr[globIndex])) {
if (isClassName(arr[globIndex])) { indexList.add(globIndex);
indexList.add(globIndex); classes.add(arr[globIndex]);
classes.add(arr[globIndex]); } else {
} else { if (!indexList.contains(globIndex) && !indexList.contains(globIndex + 1)) {
if (!indexList.contains(globIndex) && !indexList.contains(globIndex + 1)) { indexList.add(globIndex);
indexList.add(globIndex); classes.add(arr[globIndex] + "," + arr[globIndex + 1]);
classes.add(arr[globIndex] + "," + arr[globIndex + 1]); globIndex = globIndex + 1;
globIndex = globIndex + 1; indexList.add(globIndex);
indexList.add(globIndex); }
} }
} }
} }
} } else {
} else { if (isClassName(arr[i])) {
if (isClassName(arr[i])) { indexList.add(i);
indexList.add(i); classes.add(arr[i]);
classes.add(arr[i]); } else {
} else { if (!indexList.contains(i) && !indexList.contains(i + 1)) {
if (!indexList.contains(i) && !indexList.contains(i + 1)) { globIndex = i + 1;
globIndex = i + 1; classes.add(arr[i] + "," + arr[globIndex]);
classes.add(arr[i] + "," + arr[globIndex]); indexList.add(i);
indexList.add(i); indexList.add(i + 1);
indexList.add(i + 1); }
} }
} }
} }
} return classes.toArray(new String[classes.size()]);
return classes.toArray(new String[classes.size()]); }
}
/**
/** * get map key and value type name populate into array.
* get map key and value type name populate into array. *
* * @param gName generic class name
* @param gName generic class name * @return array of string
* @return array of string */
*/ public static String[] getMapKeyValueType(String gName) {
public static String[] getMapKeyValueType(String gName) { if (gName.contains("<")) {
if (gName.contains("<")) { String[] arr = new String[2];
String[] arr = new String[2]; String key = gName.substring(gName.indexOf("<") + 1, gName.indexOf(","));
String key = gName.substring(gName.indexOf("<") + 1, gName.indexOf(",")); String value = gName.substring(gName.indexOf(",") + 1, gName.lastIndexOf(">"));
String value = gName.substring(gName.indexOf(",") + 1, gName.lastIndexOf(">")); arr[0] = key;
arr[0] = key; arr[1] = value;
arr[1] = value; return arr;
return arr; } else {
} else { return new String[0];
return new String[0]; }
}
}
}
/**
/** * Convert the parameter types exported to the api document
* Convert the parameter types exported to the api document *
* * @param javaTypeName java simple typeName
* @param javaTypeName java simple typeName * @return String
* @return String */
*/ public static String processTypeNameForParams(String javaTypeName) {
public static String processTypeNameForParams(String javaTypeName) { if (StringUtil.isEmpty(javaTypeName)) {
if (StringUtil.isEmpty(javaTypeName)) { return "object";
return "object"; }
} if (javaTypeName.length() == 1) {
if (javaTypeName.length() == 1) { return "object";
return "object"; }
} if (javaTypeName.contains("[]")) {
if (javaTypeName.contains("[]")) { return "array";
return "array"; }
} switch (javaTypeName) {
switch (javaTypeName) { case "java.lang.String":
case "java.lang.String": case "string":
case "string": case "char":
case "char": case "java.util.Byte":
case "java.util.Byte": case "byte":
case "byte": case "date":
case "date": case "localdatetime":
case "localdatetime": case "localdate":
case "localdate": case "localtime":
case "localtime": case "timestamp":
case "timestamp": return "string";
return "string"; case "java.util.List":
case "java.util.List": case "list":
case "list": return "array";
return "array"; case "java.lang.Integer":
case "java.lang.Integer": case "integer":
case "integer": case "int":
case "int": return "int32";
return "int32"; case "short":
case "short": case "java.lang.Short":
case "java.lang.Short": return "int16";
return "int16"; case "double":
case "double": return "double";
return "double"; case "java.lang.Long":
case "java.lang.Long": case "long":
case "long": return "int64";
return "int64"; case "java.lang.Float":
case "java.lang.Float": case "float":
case "float": return "float";
return "float"; case "bigdecimal":
case "bigdecimal": case "biginteger":
case "biginteger": return "number";
return "number"; case "java.lang.Boolean":
case "java.lang.Boolean": case "boolean":
case "boolean": return "boolean";
return "boolean"; case "map":
case "map": return "map";
return "map"; case "multipartfile":
case "multipartfile": return "file";
return "file"; default:
default: return "object";
return "object"; }
}
}
}
/**
/** * process return type
* process return type *
* * @param fullyName fully name
* @param fullyName fully name * @return ApiReturn
* @return ApiReturn */
*/ public static ApiReturn processReturnType(String fullyName) {
public static ApiReturn processReturnType(String fullyName) { ReturnTypeProcessor processor = new ReturnTypeProcessor();
ReturnTypeProcessor processor = new ReturnTypeProcessor(); processor.setTypeName(fullyName);
processor.setTypeName(fullyName); return processor.process();
return processor.process(); }
}
/**
/** * rewrite request param
* rewrite request param *
* * @param typeName param type name
* @param typeName param type name * @return String
* @return String */
*/ public static String rewriteRequestParam(String typeName) {
public static String rewriteRequestParam(String typeName) { switch (typeName) {
switch (typeName) { case "org.springframework.data.domain.Pageable":
case "org.springframework.data.domain.Pageable": return "org.springframework.data.domain.PageRequest";
return "org.springframework.data.domain.PageRequest"; default:
default: return typeName;
return typeName; }
} }
}
private static boolean isClassName(String className) {
private static boolean isClassName(String className) { if (StringUtil.isEmpty(className)) {
className = className.replaceAll("[^<>]", ""); return false;
Stack<Character> stack = new Stack<>(); }
for (char c : className.toCharArray()) { if (className.contains("<") && !className.contains(">")) {
if (c == '<') { return false;
stack.push('>'); } else if (className.contains(">") && !className.contains("<")) {
} else if (stack.isEmpty() || c != stack.pop()) { return false;
return false; } else {
} return true;
} }
return stack.isEmpty(); }
} }
}

View File

@ -0,0 +1,14 @@
package com.power.doc.utils;
import java.util.function.BiConsumer;
public class Iterables {
public static <E> void forEach(
Iterable<? extends E> elements, BiConsumer<Integer, ? super E> action) {
if(elements==null||action==null) return;
int index = 0;
for (E element : elements) {
action.accept(index++, element);
}
}
}

View File

@ -1,251 +1,253 @@
/* /*
* smart-doc * smart-doc
* *
* Copyright (C) 2018-2020 smart-doc * Copyright (C) 2018-2020 smart-doc
* *
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file * or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information * distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file * regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the * to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance * "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at * with the License. You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, * Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an * software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the * KIND, either express or implied. See the License for the
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * under the License.
*/ */
package com.power.doc.utils; package com.power.doc.utils;
import com.power.common.util.CollectionUtil; import com.power.common.util.CollectionUtil;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
/** /**
* @author yu 2019/12/25. * @author yu 2019/12/25.
*/ */
public class JavaClassValidateUtil { public class JavaClassValidateUtil {
/** /**
* Check if it is the basic data array type of json data * Check if it is the basic data array type of json data
* *
* @param type0 java class name * @param type0 java class name
* @return boolean * @return boolean
*/ */
public static boolean isPrimitiveArray(String type0) { public static boolean isPrimitiveArray(String type0) {
String type = type0.contains("java.lang") ? type0.substring(type0.lastIndexOf(".") + 1, type0.length()) : type0; String type = type0.contains("java.lang") ? type0.substring(type0.lastIndexOf(".") + 1, type0.length()) : type0;
type = type.toLowerCase(); type = type.toLowerCase();
switch (type) { switch (type) {
case "integer[]": case "integer[]":
case "void": case "void":
case "int[]": case "int[]":
case "long[]": case "long[]":
case "double[]": case "double[]":
case "float[]": case "float[]":
case "short[]": case "short[]":
case "bigdecimal[]": case "bigdecimal[]":
case "char[]": case "char[]":
case "string[]": case "string[]":
case "boolean[]": case "boolean[]":
case "byte[]": case "byte[]":
return true; return true;
default: default:
return false; return false;
} }
} }
/** /**
* Check if it is the basic data type of json data * Check if it is the basic data type of json data
* *
* @param type0 java class name * @param type0 java class name
* @return boolean * @return boolean
*/ */
public static boolean isPrimitive(String type0) { public static boolean isPrimitive(String type0) {
if (Objects.isNull(type0)) { if (Objects.isNull(type0)) {
return true; return true;
} }
String type = type0.contains("java.lang") ? type0.substring(type0.lastIndexOf(".") + 1, type0.length()) : type0; String type = type0.contains("java.lang") ? type0.substring(type0.lastIndexOf(".") + 1, type0.length()) : type0;
type = type.toLowerCase(); type = type.toLowerCase();
switch (type) { switch (type) {
case "integer": case "integer":
case "void": case "void":
case "int": case "int":
case "long": case "long":
case "double": case "double":
case "float": case "float":
case "short": case "short":
case "bigdecimal": case "bigdecimal":
case "char": case "char":
case "string": case "string":
case "boolean": case "boolean":
case "byte": case "byte":
case "java.sql.timestamp": case "java.sql.timestamp":
case "java.util.date": case "java.util.date":
case "java.time.localdatetime": case "java.time.localdatetime":
case "java.time.localtime": case "java.time.localtime":
case "localdatetime": case "localdatetime":
case "localdate": case "localdate":
case "java.time.localdate": case "java.time.localdate":
case "java.math.bigdecimal": case "java.math.bigdecimal":
case "java.math.biginteger": case "java.math.biginteger":
case "java.io.serializable": case "java.io.serializable":
return true; return true;
default: default:
return false; return false;
} }
} }
/** /**
* validate java collection * validate java collection
* *
* @param type java typeName * @param type java typeName
* @return boolean * @return boolean
*/ */
public static boolean isCollection(String type) { public static boolean isCollection(String type) {
switch (type) { switch (type) {
case "java.util.List": case "java.util.List":
case "java.util.LinkedList": case "java.util.LinkedList":
case "java.util.ArrayList": case "java.util.ArrayList":
case "java.util.Set": case "java.util.Set":
case "java.util.TreeSet": case "java.util.TreeSet":
case "java.util.HashSet": case "java.util.HashSet":
case "java.util.SortedSet": case "java.util.SortedSet":
case "java.util.Collection": case "java.util.Collection":
case "java.util.ArrayDeque": case "java.util.ArrayDeque":
case "java.util.PriorityQueue": case "java.util.PriorityQueue":
return true; return true;
default: default:
return false; return false;
} }
} }
/** /**
* Check if it is an map * Check if it is an map
* *
* @param type java type * @param type java type
* @return boolean * @return boolean
*/ */
public static boolean isMap(String type) { public static boolean isMap(String type) {
switch (type) { switch (type) {
case "java.util.Map": case "java.util.Map":
case "java.util.SortedMap": case "java.util.SortedMap":
case "java.util.TreeMap": case "java.util.TreeMap":
case "java.util.LinkedHashMap": case "java.util.LinkedHashMap":
case "java.util.HashMap": case "java.util.HashMap":
case "java.util.concurrent.ConcurrentHashMap": case "java.util.concurrent.ConcurrentHashMap":
case "java.util.concurrent.ConcurrentMap": case "java.util.concurrent.ConcurrentMap":
case "java.util.Properties": case "java.util.Properties":
case "java.util.Hashtable": case "java.util.Hashtable":
return true; return true;
default: default:
return false; return false;
} }
} }
/** /**
* check array * check array
* *
* @param type type name * @param type type name
* @return boolean * @return boolean
*/ */
public static boolean isArray(String type) { public static boolean isArray(String type) {
return type.contains("[]"); return type.contains("[]");
} }
/** /**
* check JSR303 * check JSR303
* *
* @param annotationSimpleName annotation name * @param annotationSimpleName annotation name
* @return boolean * @return boolean
*/ */
public static boolean isJSR303Required(String annotationSimpleName) { public static boolean isJSR303Required(String annotationSimpleName) {
switch (annotationSimpleName) { switch (annotationSimpleName) {
case "NotNull": case "NotNull":
case "NotEmpty": case "NotEmpty":
case "NotBlank": case "NotBlank":
case "Required": case "Required":
return true; return true;
default: default:
return false; return false;
} }
} }
/** /**
* custom tag * custom tag
* *
* @param tagName custom field tag * @param tagName custom field tag
* @return boolean * @return boolean
*/ */
public static boolean isRequiredTag(String tagName) { public static boolean isRequiredTag(String tagName) {
switch (tagName) { switch (tagName) {
case "required": case "required":
return true; return true;
default: default:
return false; return false;
} }
} }
/** /**
* ignore tag request field * ignore tag request field
* *
* @param tagName custom field tag * @param tagName custom field tag
* @return boolean * @return boolean
*/ */
public static boolean isIgnoreTag(String tagName) { public static boolean isIgnoreTag(String tagName) {
switch (tagName) { switch (tagName) {
case "ignore": case "ignore":
return true; return true;
default: default:
return false; return false;
} }
} }
/** /**
* ignore param of spring mvc * ignore param of spring mvc
* *
* @param paramType param type name * @param paramType param type name
* @return boolean * @param ignoreParams ignore param list
*/ * @return boolean
public static boolean isMvcIgnoreParams(String paramType,List<String> ignoreParams) { */
if(CollectionUtil.isNotEmpty(ignoreParams) && ignoreParams.contains(paramType)){ public static boolean isMvcIgnoreParams(String paramType, List<String> ignoreParams) {
return true; if (CollectionUtil.isNotEmpty(ignoreParams) && ignoreParams.contains(paramType)) {
} return true;
switch (paramType) { }
case "org.springframework.ui.Model": switch (paramType) {
case "org.springframework.ui.ModelMap": case "org.springframework.ui.Model":
case "org.springframework.web.servlet.ModelAndView": case "org.springframework.ui.ModelMap":
case "org.springframework.validation.BindingResult": case "org.springframework.web.servlet.ModelAndView":
case "javax.servlet.http.HttpServletRequest": case "org.springframework.validation.BindingResult":
case "org.springframework.web.context.request.WebRequest": case "javax.servlet.http.HttpServletRequest":
case "javax.servlet.http.HttpSession": case "org.springframework.web.context.request.WebRequest":
case "javax.servlet.http.HttpServletResponse": case "javax.servlet.http.HttpSession":
case "org.springframework.web.reactive.function.server.ServerRequest": case "javax.servlet.http.HttpServletResponse":
return true; case "org.springframework.web.reactive.function.server.ServerRequest":
default: case "org.springframework.web.multipart.MultipartHttpServletRequest":
return false; return true;
} default:
} return false;
}
/** }
* ignore field type name
* /**
* @param typeName field type name * ignore field type name
* @return String *
*/ * @param typeName field type name
public static boolean isIgnoreFieldTypes(String typeName) { * @return String
switch (typeName) { */
case "org.slf4j.Logger": public static boolean isIgnoreFieldTypes(String typeName) {
case "org.apache.ibatis.logging.Log": switch (typeName) {
return true; case "org.slf4j.Logger":
default: case "org.apache.ibatis.logging.Log":
return false; return true;
} default:
} return false;
} }
}
}

View File

@ -0,0 +1,5 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
${respList}
}