Compare commits

...

No commits in common. "gh-pages" and "master" have entirely different histories.

200 changed files with 24240 additions and 38 deletions

View File

@ -0,0 +1,23 @@
### 您的使用环境(必填,不填写官方直接关闭issue)
maven和gradle版本信息根据个人使用情况填写
- maven版本号xxx
- smart-doc-maven-plugin版本号xxx
- gradle版本号xxx
- smart-doc-gradle-plugin版本号xxx
### 该问题是怎么引起的(如果最新版本已经修复的,会直接关闭)
编写关于整个issue描述前注意阅读下面的注意事项尤其是萌新的同学
1. 提issue时请认真阅读官方的wiki文档及相关配置说明少给开源软件提无效的issue是一个IT从业人的专业素养。
2. 提某些简单使用问题的issue时请先思考smart-doc从18年开源以来已经有很多企业使用码云的指数也很高。 很多问题都已解决,开源玩具是走不进企业的,这已经是一个偏向成熟的软件了。请仔细阅读文档找到相关解决方法。
3. 当你提出问题时尽量思考你的描述信息能否让官方人员复现。不要随便扔个报错信息出来就把开源人当神仙了。 smart-doc是一款很依赖你本地环境和代码数据的工具。官方人员并没有你的代码数据和模拟相同环境。
因此建议你先自己debug官方的wiki也有详细的介绍怎么去debug smart-doc或smart-doc的相关插件 文档把调试步骤都写了,不要说你不懂。
最后、祝你使用愉快!
### 重现步骤(必填,不填写官方直接关闭issue)
### 报错信息(必填,不填写官方直接关闭issue)

View File

@ -0,0 +1 @@
gitee不接收pull request,请前往[github](https://github.com/smart-doc-group/smart-doc)

39
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@ -0,0 +1,39 @@
---
name: Bug report 🐞
about: Create a report to help us improve
title: ''
labels: bug
assignees: ''
---
## Your Environment(您的使用环境)
<!--- Include as many relevant details about the environment you experienced the bug in -->
* smart-doc version:
* plugin version (e.g. smart-doc-maven-plugin or smart-doc-gradle-plugin):
* build tool version(maven or gradle):
## Expected Behavior(您期望的结果)
<!--- If you're describing a bug, tell us what should happen -->
<!--- If you're suggesting a change/improvement, tell us how it should work -->
## Current Behavior(当前结果)
<!--- If describing a bug, tell us what happens instead of the expected behavior -->
<!--- If suggesting a change/improvement, explain the difference from current behavior -->
## Possible Solution(bug解决建议)
<!--- Not obligatory, but suggest a fix/reason for the bug, -->
<!--- or ideas how to implement the addition or change -->
## Steps to Reproduce (Bug产生步骤请尽量提供用例代码)
<!--- Provide a link to a live example, or an unambiguous set of steps to -->
<!--- reproduce this bug. Include code to reproduce, if relevant -->
1.
2.
3.
4.
## Context(Bug影响描述)
<!--- How has this issue affected you? What are you trying to accomplish? -->
<!--- Providing context helps us come up with a solution that is most useful in the real world -->

View File

@ -0,0 +1,17 @@
---
name: Feature Request 💡
about: Suggest a new idea for the project.
labels: enhancement
---
## Summary(关于这个pr的描述)
Brief explanation of the feature.
### Basic example(pr的用例)
If the proposal involves a new or changed API, include a basic code example. Omit this section if it's not applicable.
### Motivation(提出这个pr目的)
Why are we doing this? What use cases does it support? What is the expected outcome?

25
.gitignore vendored Normal file
View File

@ -0,0 +1,25 @@
#Compiled class file
*.class
.idea
*.iml
target
# Log file
*.log
# BlueJ files
*.ctxt
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.war
*.ear
*.zip
*.tar.gz
*.rar
*.jar
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*

10
.travis.yml Normal file
View File

@ -0,0 +1,10 @@
language: java
jdk:
- oraclejdk8
install: mvn install -DskipTests=true -Dmaven.javadoc.skip=true
script: mvn test
after_success:
- mvn clean cobertura:cobertura coveralls:report
env:
global:
secure: xxx

697
CHANGELOG.md Normal file
View File

@ -0,0 +1,697 @@
## smart-doc版本
#### 版本号2.3.2
- 更新日期: 2021-11-21
- 更新内容:
1. 修复debug调试页搜索后目录锚点错误。
2. 修复生成openapi时List<String>等基本类型数组入参时类型转换错误。
3. 优化泛型类型显示,当泛型类型的实参类型是基本类型时直接显示为基本类型。
4. 新增对@RequestAttribute参数的忽略。
5. 修复@RequstBody使用基本类型时的请求参数示例错误
#### 版本号2.3.1
- 更新日期: 2021-11-13
- 更新内容:
1. 修复debug调试不支持请求头设置中文值的bug。
2. 修复response自定义tag设置返回未格式化换行问题。
3. 修复枚举类型字段指定mock不生效的问题。
4. 新增对@SessionAttribute参数做忽略。
5. 支持controller实现接口并使用default方法。
#### 版本号2.3.0
- 更新日期: 2021-11-07
- 更新内容:
1. 修复创建html文档丢失search.js文件问题。
2. 修复packageFilters配置多个包时只有第一个生效的问题。
3. 修复debug调试页面的curl指令错误。
4. 修复设置了下载文件接口加download标记后数据并未生效的bug。
5. 优化一些部分常见字段的随机值生成。
#### 版本号2.2.9
- 更新日期: 2021-10-31
- 更新内容:
1. 修复生成openapi文件上传错误问题。
2. 修复文件上传接口推送到torna参数被放置到query参数列表的问题。
3. 修改List<T>类型参数推送到torna错误的问题
4. 优化outPath配置只使用torna推送时可以不再要求配置outPath项。
#### 版本号2.2.8
- 更新日期: 2021-10-07
- 更新内容:
1. 修复html文档无接口注释时锚点跳转错误的问题。
2. 修复导出postman时服务端口配置成变量报错的问题。
#### 版本号2.2.7
- 更新日期: 2021-09-12
- 更新内容:
1. 修复dubbo文档css连接错误。
2. 修复分组后组归错误。
3. 修复路径常量相似度时替换错误的bug。
4. JSR303分组优化标记Null的分组字段将不再显示在文档中 。
#### 版本号2.2.6
- 更新日期: 2021-09-05
- 更新内容:
1. 修复html文档静态资源链接错误。
2. 不配置分组时不显示分组。
3. 修复分组后目录item搜索错误。
4. 优化maven插件提示 。
#### 版本号2.2.5
- 更新日期: 2021-08-08
- 更新内容:
1. 支持在html文档中不显示参数列表。
2. html文档使用的资源全部改成本地引用。
3. 修复Boolean类型字段命名为is前缀时is前缀被去除的bug。
4. 修复配置了字典码列表后枚举字段注释显示错误#139 。
5. 修复分析过程中出现的数组越界异常 。
6. 新增接口分组支持。
#### 版本号2.2.4
- 更新日期: 2021-08-08
- 更新内容:
1. 修复字典码推送torna错误 #https://gitee.com/smart-doc-team/smart-doc/issues/I43JQR。
2. 新增jsr303 @size和@length支持
3. 修改html的模板样式错误。
4. 修复postman错误#I41G2E 。
5. 新增isReplace配置 。
6. 修复当存在多个jsr注解时部分注解失效问题。
#### 版本号2.2.3
- 更新日期: 2021-07-18
- 更新内容:
1. 增加pathPrefix配置项用于配置上下文引入该配置项后serverUrl仅用于配置服务器地址。
2. 支持请求头常量设置解析。
3. 支持使用JsonIgnoreProperties和JSONType注解去忽略多字段。
4. 修改部分文档设置allInOneDocFileName无效的问题,#131 。
5. 修复dubbo rpc文档模板格式错误 #https://gitee.com/smart-doc-team/smart-doc/issues/I40ZGE .
6. 支持配置添加拦截器中设置全局请求参数,#https://github.com/smart-doc-group/smart-doc/issues/132 .
7. 修复部分类型mock未推送到torna的问题。
#### 版本号2.2.2
- 更新日期: 2021-07-04
- 更新内容:
1. 修复url中遇到正则表达解析错误问题.
2. 修复生成的json样例部分格式化后错误的bug,gitee #I3XSE5
3. 增强对文档中html特殊字符的处理防止html渲染后显示错误gitee #I3XO31
4. 请求头设置增强支持配置urlPatterns和excludePathPatterns两个属性去匹配对应的接口。
5. 优化了maven插件的提示优化后可以将加载了那些目录模块代码路径打印。
6. 提供了其它框架扩展文档解析的能力。
7. 修复doc模板错误gitee #I3Y640
8. 修复字典模板错误,#119。
9. 添加忽略HttpServlet对象。
10. 支持内置替换Jpa Pageable分页对象去除不必要的请求参数替换配置。
11. packageFilters增强可使用正则进行匹配gitee #I3YKZ4
12. 修复dubbo rpc文档推送到torna数据错误。
13. 修复customResponseFields和customRequestFields设置时不同类同名字段覆盖buggitee #I3Y6AL
14. 修复高版本gradle中使用implements添加依赖时gradle插件无法加载依赖导致返回空json的bug。
#### 版本号2.2.1
- 更新日期: 2021-06-20
- 更新内容:
1. 移除代码中System.out.print打印.
#### 版本号2.2.0
- 更新日期: 2021-06-20
- 更新内容:
1. 修复参数多行注释时注释提取错误gitee #I3TYYP.
2. 修复部分代码可能出现的空指针问题。
3. 添加@response tag。支持自己设置response example
4. 修复推送到torna请求或返回为数组时示例显示错误
5. Character类型解析支持。
6. 修复使用Quartz中JobDataMap类型解析错误。
7. 移除YapiBuilder。smart-doc不在支持其他第三方接口系统请使用torna.
#### 版本号2.1.9
- 更新日期: 2021-05-29
- 更新内容:
1. 修复inlineEnum为false时枚举展示在参数中的问题。
2. 返回Spring文件下载对象支持自动识别为文件下载减少手动标记@download tag。
3. smart-doc使用的css cdn更换默认使用国内cdn提升国内的加载速度切换英文环境使用google的cdn.
4. 添加多层泛型嵌套的解析支持。gitee #I3T6UV .
5. 修复父类是泛型时父类中LocalDateTime类型字段生成json样例错误。
6. 添加将接口排序order推送到torna中。
7. 修复类上的@ignore tag不生效bug.
8. 优化字典码推送空字典码不会像torna发起推送请求。
#### 版本号2.1.8
- 更新日期: 2021-05-22
- 更新内容:
1. 修复推送接口到torna丢失部分mock值的问题。
2. 修复在参数注释中配置类替换时将非类名解析成类名的bug 。
3. 支持父类上加@RestController注解的子类能够被识别和扫描
4. 新增将业务错误码和定义字典推送到torna。
5. 修复maven插件torna-rest和torna-rpc两个task未加编译前缀的问题。
6. 修复生成json用例中数组类型json错误的问题。
7. 修复customRequestFields中设置字段value在用例中不生效的bug。
8. 添加@JsonProperty支持,支持JsonProperty.Access控制字段。
#### 版本号2.1.7
- 更新日期: 2021-05-12
- 更新内容:
1. 添加推送接口作者信息到torna数据错误的bug。
2. 修复空参数curl命令多余号问题github 。
#### 版本号2.1.6
- 更新日期: 2021-05-10
- 更新内容:
1. 修复不允许List中放文件上传对象错误的bug。
2. 添加推送接口作者信息到torna,通过配置author设置推送人不配置默认为计算机用户名。
3. 添加推送queryParams参数到torna(需要使用torna 1.6.0+)
#### 版本号2.1.5
- 更新日期: 2021-05-05
- 更新内容:
1. 修复requestBodyAdvice请求样例丢之。
2. 添加dubbo文档到torna的推送。
#### 版本号2.1.4
- 更新日期: 2021-04-24
- 更新内容:
1. 修复Controller继承时父类的Mapping未继承的问题。
2. 修复配置responseBodyAdvice后controller中void方法返回显示错误。
3. 修复往torna推送漏掉pathParams的问题。
4. 修复非json请求集合中绑定枚举强制检查错误的问题。
5. 新增requestBodyAdvice支持可以实现请求参数包装。
6. 修复泛型为List数据时类型为object问题。
7. 修复customFiled为继承参数时配置失效问题。
#### 版本号2.1.3
- 更新日期: 2021-04-11
- 更新内容:
1. 增强对文件上传的支持。
2. 增加customRequestFields配置项#97。
3. 修复往torna推送漏掉pathParams的问题。
4. 修改debug测试页面支持post表单请求
5. 修改表单请求对象中枚举字段默认值错误的bug
#### 版本号2.1.2
- 更新日期: 2021-03-29
- 更新内容:
1. 修复Map嵌套在某些结构体中栈溢出问题gitee #I3CCLY
2. 修复Torna数据推送问题。
#### 版本号2.1.1
- 更新日期: 2021-03-24
- 更新内容:
1. 修复Map嵌套在某些结构体中栈溢出问题gitee #I3CCLY
2. 修复Torna数据推送问题。
#### 版本号2.1.0
- 更新日期: 2021-03-21
- 更新内容:
1. 导出的postman的url资源下添加缺失的protocol。
2. 增加@ignoreParams自定义tag来过滤掉不想显示在文档中参数。
3. 增加了自动生成版本记录的功能。
4. 修改torna推送的bug。
5. 支持旧的SpringMVC项目的url后缀新项目不建议加什么破玩意后缀。
#### 版本号2.0.9
- 更新日期: 2021-03-12
- 更新内容:
1. 支持UUID和ZonedDateTime字段类型#89。
2. 对map参数增加开关来兼容旧项目还是不建议使用map参数。
3. 完成和Torna的对接。
#### 版本号2.0.8
- 更新日期: 2021-02-26
- 更新内容:
1. 修复文件上传的参数丢失的注释。
2. 修复2.0.7新增忽略接口方法后解析父类字段缺失注释bug。
3. 修改byte类型的转换将过去的string转为int8。
#### 版本号2.0.7
- 更新日期: 2021-01-30
- 更新内容:
1. 修复postman的url中不附加的context-path的问题。
2. 修复带正则的path路径参数解析出现截取越界的问题。
3. 添加对默认接口实现中get方法重写忽略的能力解析。
4. 修改数组、map等字段类型的自定义mock值显示错误问题。
5. 修复对mapping中headers的处理。
#### 版本号2.0.6
- 更新日期: 2021-01-15
- 更新内容:
1. 修复带正则的path路径参数在postman中用例问题。
2. 增强对祖传不良代码的分析兼容。
#### 版本号2.0.5
- 更新日期: 2021-01-09
- 更新内容:
1. 修复集合类无泛型参数作为入参出参时的数组越界。
2. 修复新开tab访问的url拼接问题。
#### 版本号2.0.3-2.0.4
- 更新日期: 2021-01-01
- 更新内容:
1. 修改页面的错误列表标题显示。
2. 修改debug页面curl header语法错误。
3. 修改debug页面json参数输入框允许粘贴小段文本。
4. 解决使用dubbo 2.7+在provider中生成文档出错问题 github #77.
#### 版本号2.0.2
- 更新日期: 2020-12-27
- 更新内容:
1. 修改创建openapi时的空指针异常。
2. 修改debug页面时未使用mock值的问题。
3. debug页面可以根据请求动态更新curl命令。
4. 优化debug页面中的文件下载测试。
5. 优化enum入参mock错误的bug。
6. mock页面支持使用新窗口打开后端渲染的页面。
7. 修改生成一些字段值生成错误的bug。
8. 修改类中使用集合字段未指定泛型可能出错的bug。
9. 优化set等集合类在文档中的类型显示。
10. 添加对集合字段中枚举的处理。
11. 枚举序列化支持优化。
12. 调试页面新增Highlight支持。
#### 版本号2.0.1
- 更新日期: 2020-12-20
- 更新内容:
1. debug调试页面支持文件上传。
2. 修改简单请求参数mock值和类型不匹配问题。
3. debug页面完全支持文件下载测试。
4. 所有html的文档支持接口目录搜索。
5. 剔除flexmark依赖旧的非allInOne模板删除统一h5文档样式。
#### 版本号2.0.0
- 更新日期: 2020-12-13
- 更新内容:
1. 优化了文档的显示将query和path单独提出来做了展示
2. 优化openapi 3.0文档规范的支持可集成swagger ui等ui使用。
3. 优化postman collection 2.0的支持。
4. 添加分组支持group。
5. 修改mock的一些bug和增强使用
6. 支出创建debug页面
#### 版本号1.9.9.1
- 更新日期: 2020-11-23
- 更新内容:
1. 这是一个紧急修改版本。
2. 解决1.9.9版本controller中存在非路径映射方法时的错误。
#### 版本号1.9.9
- 更新日期: 2020-11-23
- 更新内容:
1. 修改1.9.8启用严格检查注释模式下的bug。
2. 修改使用泛型数组参数时解析错误。
3. 修复ResponseEntity中的数组解析错误。
4. 修复controller方法标注ignore后文档序号错误。
5. 增加对@RequestMapping注解的path属性的解析支持
6. 修复postman中formdata表单不显示描述信息的问题
7. html5 allInOne模板支持代码高亮。
#### 版本号1.9.8
- 更新日期: 2020-11-10
- 更新内容:
1. 忽略Class对象的解析。
2. 增加对抽象Controller方法的解析。
3. 修改阿里版本dubbo注解名称解析错误 。
4. 修改模拟值生成错误。
5. 支持ResponseBodyAdvice通用接口响应包装设置。
6. 修复类同时继承和基类和实现接口中可能出现字段重复的bug。
#### 版本号1.9.7
- 更新日期: 2020-10-24
- 更新内容:
1. 修复restful接口泛型中使用?时的解析错误。
2. 优化rpc html非all in one的问题。
3. 对rest query参数自动添加描述增加可读性。
4. support ali dubbo,#I22CF7 .
5. support @RequestMapping headers.
#### 版本号1.9.6
- 更新日期: 2020-10-09
- 更新内容:
1. 修复RequestParam 解析错误。
2. 修复泛型中使用?时的解析错误。
3. 修改服务url的地址为空字符串不再提供默认http前缀
4. 增加泛型实际类型的显示开关控制。
5. 修复类继承一个泛型类时的解析错误。
6. 优化smart-doc maven插件提升用户在多模块下的使用体验。
#### 版本号1.9.5
- 更新日期: 2020-09-19
- 更新内容:
1. 接口参数无注解时将required设置为false。
2. 修改html自适应。
#### 版本号1.9.4
- 更新日期: 2020-09-06
- 更新内容:
1. 添加order tag支持对api做排序。
2. 优化一些重复的代码。
3. 修改基础url中使用常量出现空格的问题。
4. 添加生成yapi文件的功能。
#### 版本号1.9.3
- 更新日期: 2020-08-30
- 更新内容:
1. 修复Get请求用例参数值被去空格问题。
2. 修改复杂参数表树型数据转化的错误。
3. 修复非allInOne模板使用渲染错误。
4. 修复一些泛型例子解析错误bug。
5. 优化MultipartFile文件上传参数处理不对该参数进行展开分析。
#### 版本号1.9.2
- 更新日期: 2020-08-23
- 更新内容:
1. 修改前面版本修改引发的普通jsr 303验证解析错误问题。
2. 新增忽略请求参数对象的配置gitee #I1RBJO
3. 修改smart-doc的beetl配置避免和用户的业务中beetl配置冲突。
4. 新增ApiDataBuilder中获取树形格式参数数据的接口#40。
5. 新增对Open Api 3.0的支持。
6. 修改字典表空时内部发生空指针的问题。
7. 优化curl用例增加请求头。
#### 版本号1.9.1
- 更新日期: 2020-08-02
- 更新内容:
1. 修改进去版本更新导致的泛型解析问题。
2. 修改1.8.9版本修改后带来的dubbo接口文档显示问题
2. 修改smart-doc-maven-plugin生成dubbo文档时缺乏配置文件错误问题。
3. 修改gradle插件的对多模块的支持。
#### 版本号1.9.0
- 更新日期: 2020-07-19
- 更新内容:
1. 修改dubbo html依赖部分错乱问题。
2. 新增自定义输出文件名称的配置。
3. 添加请求和响应示例的开关配置项。
4. 修改使用JSR303参数校验时默认分组验证被忽略问题。
5. 修改jackson JsonIgnore注解在参数对象中不生效的问题。
#### 版本号1.8.9
- 更新日期: 2020-07-05
- 更新内容:
1. 修改git #38
2. 修改gitee #I1LBKO
3. 修改fix #39多泛型解析顺序问题
4. 优化支持gitee #I1IQKY常量解析需求
#### 版本号1.8.8
- 更新日期: 2020-06-21
- 更新内容:
1. 修改忽略对LinkedHashMap的解析gitee #I1JI5W
2. 修改接口或和实现类合并分析是字段重复问题gitee #I1JHMW
3. 优化接口方法字段不能获取docletTag的问题。
4. 优化枚举参数展示,支持自定义控制显示。
5. 添加Feign的支持。
6. 优化递归执行,对外提供递归次数限制。
#### 版本号1.8.7
- 更新日期: 2020-06-01
- 更新内容:
1. 增加对java接口的分析例如Jpa的分页Page类。
2. 增强对使用@RequestBody绑定参数方法的解析。
3. 增加dubbo rpc文档生成支持。
4. 增加将驼峰字段格式转化为下划线格式。
5. maven插件和gradle插件提供includes支持方便自行配置加载第三方库。
6. fix #32.
7. 增加文档接口根据接口标题排序功能。
#### 版本号1.8.6
- 更新日期: 2020-05-09
- 更新内容:
1. 增加localTime支持[gitee #I1F7CW](https://gitee.com/sunyurepository/smart-doc/issues/I1F7CW)。
2. 优化smart-doc导入Postman
collection时的header问题[gitee #I1EX42](https://gitee.com/sunyurepository/smart-doc/issues/I1EX42)
3. 优化smart-doc-maven-plugin加载source的过滤支持使用通配符来过滤。
4. 首次发布gradle插件发布smart-doc-gradle-plugin插件
5. 修复通用泛型解析出错[git #28](https://github.com/smart-doc-group/smart-doc/issues/28)。
#### 版本号1.8.5
- 更新日期: 2020-04-19
- 更新内容:
1. maven插件错误码列表导出bug[git #I1EHXA](https://gitee.com/sunyurepository/smart-doc/issues/I1EHXA)。
2. 增加@PatchMapping支持[gitee #I1EDRF](https://gitee.com/sunyurepository/smart-doc/issues/I1EDRF)
3. 解决javadoc包含重复tag生成文档报错[gitee #I1ENNM](https://gitee.com/sunyurepository/smart-doc/issues/I1ENNM)。
4. 修改当请求参数为泛型时数据解析错误问题。
5. 修复分组验证空指针问题,不对返回对象做分组验证处理。
6. 优化smart-doc-maven-plugin对多级maven项目的加载。
7. 支持请求参数对象替换成另外的对象来渲染文档
#### 版本号1.8.4
- 更新日期: 2020-03-30
- 更新内容:
1. Controller新增时候@ignore
tag,可适应该tag忽略不需要生成文档的controller[git #24](https://github.com/smart-doc-group/smart-doc/issues/24)。
2. 参数中包含 HttpSession时smart-doc卡主[gitee #I1CA9M](https://gitee.com/sunyurepository/smart-doc/issues/I1CA9M)
3. 解决一些复杂分组场景smart-doc报错的问题[gitee #I1CPSM](https://gitee.com/sunyurepository/smart-doc/issues/I1CPSM)。
4. 解决smart-doc-maven-plugin插件读取配置乱码问题。
#### 版本号1.8.3
- 更新日期: 2020-03-21
- 更新内容:
1. 增加从接口方法getter或者setter方法中读取注释。
2. 修改smart-doc默认编码为utf-8解决生成文档乱码问题。
3. 增加对代码中@author tag的支持支持多作者。
#### 版本号1.8.2
- 更新日期: 2020-03-13
- 更新内容:
1. 修改gitee #I19IYW
2. 修改文档模板中的title设置错误。
3. 修改gitee #I191EO
4. 支持@Validated 分组
#### 版本号1.8.1
- 更新日期: 2020-01-22
- 更新内容:
1. 增加对接口get方法的分析。
2. 增加对第三方jar中list泛型数据的解析。
3. 删除原来冗长的SourceBuilder代码。
4. 修改AdocDocBuilder、HtmlApiDocBuilder、ApiDocBuilder的方法名规范化单元测试的升级需要做小部分变更。
5. 修改1.8.0重构后的请求示例将header放入普通参数的bug。
6. 修改参数加上@Validated注解后文档里没有该参数信息的bug。
7. 新增@Deprecated标注接口的支持(使用line through完成样式标记)
#### 版本号1.8.0
- 更新日期: 2020-01-01
- 更新内容:
1. 修改参数上多个验证注解不支持的问题。
2. 修改支持上传文件参数不列举到文档的问题。
3. 新增ApiDataBuilder用于获取smart-doc生成的文档数据包含header、字典、错误码等。
4. 合并fork分支的github book html5模板新增搜索和锚点。
5. 新增自定义@mock tag用于指定生成文档的字段值@param 的参数注释增加mock值的功能(@param name 姓名|张三)
6. 重点smart-doc的maven插件smart-doc-maven-plugin增强对maven标准项目的支持。
7. 全面支持spring的表单参数绑定解析。
8. postman json生成支持所有参数自动回填。再也不用自己建参数了。
9. 优化对实体类中枚举字段的支持。
10. 增加对实体中静态常量常量字段的过滤。
#### 版本号1.7.9
- 更新日期: 2019-12-16
- 更新内容:
1. 修改request请求参数中嵌套对象不能解析的bug参考gitee #I16AN2.
2. controller参数是数组时添加@PathVariable注解会报空指针,参考gitee #I16F6G
3. 新增ApiDataBuilder用于获取smart-doc生成的文档数据包含header、字典、错误码等。
4. 修改github #9 文档错误bug.
5. 新增接口的@author展示方法从文档中查到找到接口负责人生成文档可以选择关闭显示。
6. 重点smart-doc的maven插件smart-doc-maven-plugin 1.0.0版本发布。
#### 版本号1.7.8
- 更新日期: 2019-12-02
- 更新内容:
1. 修改Spring Controller使用非Spring Web注解时生成的响应示例出错的bug。
2. 修改使用mybatis-plus实体继承Model对象时将log字段输出到文档的问题。
3. 添加对transient修饰字段文档输出开关默认不输出。
4. html文档添加项目名称显示
5. 修改github #4 泛型中Void类型解析死循环
6. 修改github #5 简单枚举参数解析空指针异常
7. 添加导出PostMan json数据
#### 版本号1.7.7
- 更新日期2019-11-18
- 更新内容:
1. 修改timestamp类型字段创建json示例错误bug。
2. fix #I1545A 单接口多路径bug。
3. 修改部分url生成部署空格问题。
4. 优化对java.util.concurrent.ConcurrentMap的解析。
#### 版本号1.7.6
- 更新日期2019-11-13
- 更新内容:
1. fix #I14PT5 header重复渲染到文档
2. fix #I14MV7 不设置dataDictionaries出现空指针错误
3. 增加请求参数枚举字段解析(试用功能)
#### 版本号1.7.5
- 更新日期2019-11-06
- 更新内容:
1. 优化文档中错误列表的标题,可根据语言环境变化显示中文或因为。
2. 解决项目外jar中内部类生成文档错误的bug。
3. 支持环形依赖分析。只要你敢写!
4. 修改使用SpringMvc或者SpringBoot上传时接口的Content-Type显示错误。
5. 支持设置项目作为markdown的一级标题。
6. 修改方法注释相同引起的html链接跳转错误。
7. 添加生成AllInOne的覆盖配置项默认自动加版本号不覆盖。
8. 新增枚举字典码导出到文档的功能。
#### 版本号1.7.4
- 更新日期2019-10-29
- 更新内容:
1. 修改gitee上bug #I1426C
2. 修改gitee上bug #I13ZAL,1.7.0~1.7.3 结构优化后产生的bug建议用户升级。
3. 修改gitee上bug #I13U4C
4. 修改设置中文语言环境(默认中文)下错误码列表title显示英文的问题。
5. 优化AllInOne的markdown展示生成时带上自动产生的序号。
#### 版本号1.7.3
- 更新日期2019-10-24
- 更新内容:
1. 优化html5模板左侧文档目录展示能够展开和收缩。
2. 修改gitee上bug #I13R3K
3. 修改gitee上bug #I13NR1
4. 开放的文档数据获取接口添加返回方法的唯一id和方法名称方便一些企业自己做对接。
#### 版本号1.7.2
- 更新日期2019-10-19
- 更新内容:
1. 优化注释换行\n\r问题依赖common-util 1.8.7。
2. 修改gitee上bug #I135PG、#I13NR1。
3. 添加@requestHeader注解的支持文档自定将参数绑定到请求头列表中。
4. 增加javadoc apiNote tag的支持。
5. 解决扫描分析controller中private方法的问题。
6. 添加支持@RequestParam注解重写参数名和设置默认值的文档解析。
7. 支持使用@PostMapping和@PutMapping请求自定义注解接收单个json参数场景下生成json请求实例。
8. 新增对Spring ResponseEntity的解析。
9. 增加内部类返回结构解析。
10. 修改文档中显示的字段类型float、double等由原来的number直接变成具体类型。
#### 版本号1.7.1
- 更新日期:已废弃
- 更新内容:
1. 优化注释换行\n\r问题。
2. 修改bug #I135PG
3. 添加requestHeader功能
#### 版本号1.7.0
- 更新日期2019-09-30
- 更新内容:
1. 优化代码。
2. 添加生成HTML5和Asciidoctor文档的功能。
3. 增加开放API数据接口功能。
4. 支持Callable,Future,CompletableFuture等异步接口返回的推导。
5. 支持Spring Boot Web Flux(Controller方式书写)。
#### 版本号1.6.4
- 更新日期2019-09-23
- 更新内容:
1. 优化代码
2. 增加对普通的get请求参数拼装示例的生成
3. 增加spring mvc占位符restful url请求示例生成
#### 版本号1.6.2
- 更新日期2019-09-13
- 更新内容:
1. 修改字段注释多行显示错误bug
2. 字段描述文档增加@Since tag的支持
3. 解析代码忽略WebRequest类防止生产过多信息
4. 升级基础库依赖版本
#### 版本号1.3
- 更新日期2018-09-15
- 更新内容:
1. 增加PutMapping和DeleteMapping支持
2. 添加字符串date和Date类型时间的模拟值生成
#### 版本号1.2
- 更新日期2018-09-04
- 更新内容:
1. 根据用户反馈增加controller报名过滤功能该功能为可选项
#### 版本号1.1
- 更新日期2018-08-30
- 更新内容:
1. 修改PostMapping和GetMapping value为空报错的bug
2. 增强时间字段的mock数据创建
3. 修改smart-doc解析自引用对象出错的bug
#### 版本号1.0
- 更新日期2018-08-25
- 更新内容:
1. smart-doc增加将所有文档导出归档到一个markdown中件的功能
2. 参考阿里开发手册将直接提升到1.0,之前的版本主要是个人内部测试
#### 版本号0.5
- 更新日期2018-08-23
- 更新内容:
1. 将api-doc重命名为smart-doc并发布到中央仓库
#### 版本号0.4
- 更新日期2018-07-11
- 更新内容:
1. 修改api-doc对类继承属性的支持。
#### 版本号0.3
- 更新日期2018-07-10
- 更新内容:
1. api-doc增加对jackson和fastjson注解的支持可根据注解定义来生成返回信息。
### 版本号0.2
- 更新日期2018-07-07
- 更新内容:
1. 修改api-doc泛型推导的bug.
### 版本号0.1
- 更新日期2018-06-25
- 更新内容:
1. 手册将api-doc发布到中央仓库

201
LICENSE Normal file
View File

@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

82
README.md Normal file
View File

@ -0,0 +1,82 @@
<h1 align="center">Smart-Doc Project</h1>
![maven](https://img.shields.io/maven-central/v/com.github.shalousun/smart-doc)
[![License](https://img.shields.io/badge/license-Apache%202-green.svg)](https://www.apache.org/licenses/LICENSE-2.0)
![number of issues closed](https://img.shields.io/github/issues-closed-raw/shalousun/smart-doc)
![closed pull requests](https://img.shields.io/github/issues-pr-closed/shalousun/smart-doc)
![java version](https://img.shields.io/badge/JAVA-1.8+-green.svg)
[![chinese](https://img.shields.io/badge/chinese-中文文档-brightgreen)](https://smart-doc-group.github.io/#/zh-cn/)
## Introduce
smart-doc is a tool that supports both JAVA REST API and Apache Dubbo RPC interface document generation. Smart-doc is
based on interface source code analysis to generate interface documents, and zero annotation intrusion. You only need to
write Javadoc comments when developing, smart-doc can help you generate Markdown or HTML5 document. smart-doc does not
need to inject annotations into the code like Swagger.
[quick start](https://smart-doc-group.github.io/#/)
## Features
- Zero annotation, zero learning cost, only need to write standard JAVA document comments.
- Automatic derivation based on source code interface definition, powerful return structure derivation support.
- Support Spring MVC, Spring Boot, Spring Boot Web Flux (Not support endpoint), Feign.
- Supports the derivation of asynchronous interface returns such as Callable, Future, CompletableFuture.
- Support JSR-303 parameter verification specification.
- Support for automatic generation of request examples based on request parameters.
- Support for generating JSON return value examples.
- Support for loading source code from outside the project to generate field comments (including the sources jar
package).
- Support for generating multiple formats of documents: Markdown,HTML5,Asciidoctor,Postman Collection 2.0+,OpenAPI 3.0.
- Support for exporting error codes and data dictionary codes to API documentation.
- The debug html5 page fully supports file upload and download testing.
- Support Apache Dubbo RPC.
## Best Practice
smart-doc + [Torna](http://torna.cn) form an industry-leading document generation and management solution, using
smart-doc to complete Java source code analysis and extract annotations to generate API documents without intrusion, and
automatically push the documents to the Torna enterprise-level interface document management platform.
![smart-doc+torna](https://raw.githubusercontent.com/shalousun/smart-doc/master/images/smart-doc-torna-en.png)
## Building
You could build with the following commands. (Java 1.8 is required to build the master branch)
```
mvn clean install -Dmaven.test.skip=true
```
## TODO
- Jakarta RS-API 2.x
## Who is using
These are only part of the companies using smart-doc, for reference only. If you are using smart-doc,
please [add your company here](https://github.com/smart-doc-group/smart-doc/issues/12) to tell us your scenario to make
smart-doc better.
![IFLYTEK](https://raw.githubusercontent.com/shalousun/smart-doc/dev/images/known-users/iflytek.png)
&nbsp;&nbsp;<img src="https://raw.githubusercontent.com/shalousun/smart-doc/dev/images/known-users/oneplus.png" title="OnePlus" width="83px" height="83px"/>
&nbsp;&nbsp;<img src="https://raw.githubusercontent.com/shalousun/smart-doc/dev/images/known-users/xiaomi.png" title="Xiaomi" width="170px" height="83px"/>
&nbsp;&nbsp;<img src="https://raw.githubusercontent.com/shalousun/smart-doc/dev/images/known-users/neusoft.png" title="东软集团" width="170px" height="83px"/>
&nbsp;&nbsp;<img src="https://www.hand-china.com/static/img/hand-logo.svg" title="上海汉得信息技术股份有限公司" width="260px" height="83px"/>
&nbsp;&nbsp;<img src="https://raw.githubusercontent.com/shalousun/smart-doc/dev/images/known-users/shunfeng.png" title="顺丰" width="83px" height="83px"/>
<img src="https://raw.githubusercontent.com/shalousun/smart-doc/dev/images/known-users/zhongkezhilian.png" title="zhongkezhilian" width="272px" height="83px"/>
<img src="https://raw.githubusercontent.com/shalousun/smart-doc/dev/images/known-users/yuanmengjiankang.png" title="yuanmengjiankang" width="260px" height="83px"/>
<img src="https://raw.githubusercontent.com/shalousun/smart-doc/dev/images/known-users/puqie_gaitubao_100x100.jpg" title="puqie" width="83px" height="83px"/>
&nbsp;&nbsp;
<img src="https://raw.githubusercontent.com/shalousun/smart-doc/dev/images/known-users/tianbo-tech.png" title="tianbo tech" width="127px" height="70px"/>
## Acknowledgements
Thanks to [JetBrains SoftWare](https://www.jetbrains.com) for providing free Open Source license for this open source project.
<img src="https://raw.githubusercontent.com/shalousun/smart-doc/dev/images/jetbrains-variant-3.png" width="260px" height="220px"/>
## License
Smart-doc is under the Apache 2.0 license. See the [LICENSE](https://github.com/smart-doc-group/smart-doc/blob/master/LICENSE)
file for details.
## Contact
Email 836575280@qq.com

101
README_CN.md Normal file
View File

@ -0,0 +1,101 @@
<h1 align="center"><a href="https://github.com/shalousun/smart-doc" target="_blank">Smart-Doc Project</a></h1>
![maven](https://img.shields.io/maven-central/v/com.github.shalousun/smart-doc)
[![License](https://img.shields.io/badge/license-Apache%202-green.svg)](https://www.apache.org/licenses/LICENSE-2.0)
![closed pull requests](https://img.shields.io/github/issues-pr-closed/shalousun/smart-doc)
![java version](https://img.shields.io/badge/JAVA-1.8+-green.svg)
## Introduce
smart-doc是一款同时支持JAVA REST API和Apache Dubbo RPC接口文档生成的工具smart-doc在业内率先提出基于JAVA泛型定义推导的理念
完全基于接口源码来分析生成接口文档不采用任何注解侵入到业务代码中。你只需要按照java-doc标准编写注释 smart-doc就能帮你生成一个简易明了的Markdown、HTML5、Postman
Collection2.0+、OpenAPI 3.0+的文档。
$\color{red}{你给我的star胜过所有读过的诗—smart-doc}$
> 无论你是很有经验的大佬、还是刚入行的萌新。遇到使用疑惑时我们希望你能仔细阅读smart-doc官方码云的wiki文档。我们将smart-doc及其插件的 每一个配置项和可能在日常中遇到的问题都整理到了文档中。仔细阅读文档就是对开源项目最大的支持。
查看[快速开始](https://smart-doc-group.github.io/#/zh-cn/) 了解详情
## Features
- 零注解、零学习成本、只需要写标准JAVA注释。
- 基于源代码接口定义自动推导,强大的返回结构推导。
- 支持Spring MVC、Spring Boot、Spring Boot Web Flux(controller书写方式)、Feign。
- 支持Callable、Future、CompletableFuture等异步接口返回的推导。
- 支持JavaBean上的JSR303参数校验规范包括分组验证。
- 对JSON请求参数的接口能够自动生成模拟JSON参数。
- 对一些常用字段定义能够生成有效的模拟值。
- 支持生成JSON返回值示例。
- 支持从项目外部加载源代码来生成字段注释(包括标准规范发布的jar包)。
- 支持生成多种格式文档Markdown、HTML5、Asciidoctor、Postman Collection、OpenAPI 3.0。 Up- 开放文档数据,可自由实现接入文档管理系统。
- 支持导出错误码和定义在代码中的各种字典码到接口文档。
- 支持Maven、Gradle插件式轻松集成。
- 支持Apache Dubbo RPC接口文档生成。
- debug接口调试html5页面完全支持文件上传下载(@download tag标记下载方法)测试。
## Best Practice
smart-doc + [Torna](http://torna.cn) 组成行业领先的文档生成和管理解决方案使用smart-doc无侵入完成Java源代码分析和提取注释生成API文档自动将文档推送到Torna企业级接口文档管理平台。
![smart-doc+torna](https://gitee.com/smart-doc-team/smart-doc/raw/master/images/smart-doc-torna.png)
[smart-doc+Torna文档自动化](https://gitee.com/smart-doc-team/smart-doc/wikis/smart-doc与torna对接?sort_id=3695028)
> Torna是由smart-doc官方独家推动联合研发的企业级文档管理系统因此smart-doc官方不会对接其它任何的外部文档管理系统例如像showdoc、yapi 之类的对接请自定内部处理也不要再给我们提其他文档系统对接的PR。我们核心是把smart-doc+Torna的这套方案打造好。
## Building
如果你需要自己构建smart-doc那可以使用下面命令构建需要依赖Java 1.8。
```
mvn clean install -Dmaven.test.skip=true
```
## TODO
- Jakarta RS-API 2.x
## License
smart-doc is under the Apache 2.0 license. See
the [LICENSE](https://gitee.com/smart-doc-team/smart-doc/blob/master/LICENSE) file for details.
**注意:** smart-doc源代码文件全部带有版权注释使用关键代码二次开源请保留原始版权否则后果自负
## Who is using
> 排名不分先后,更多接入公司,欢迎在[https://gitee.com/smart-doc-team/smart-doc/issues/I1594T](https://gitee.com/smart-doc-team/smart-doc/issues/I1594T)登记(仅供开源用户参考)
![IFLYTEK](https://gitee.com/smart-doc-team/smart-doc/raw/master/images/known-users/iflytek.png)
&nbsp;&nbsp;<img src="https://gitee.com/smart-doc-team/smart-doc/raw/master/images/known-users/oneplus.png" title="一加" width="83px" height="83px"/>
&nbsp;&nbsp;<img src="https://gitee.com/smart-doc-team/smart-doc/raw/master/images/known-users/xiaomi.png" title="小米" width="170px" height="83px"/>
&nbsp;&nbsp;<img src="https://gitee.com/smart-doc-team/smart-doc/raw/master/images/known-users/neusoft.png" title="东软集团" width="180px" height="83px"/>
&nbsp;&nbsp;<img src="https://gitee.com/smart-doc-team/smart-doc/raw/master/images/known-users/zhongkezhilian.png" title="中科智链" width="272px" height="83px"/>
&nbsp;&nbsp;<img src="https://www.hand-china.com/static/img/hand-logo.svg" title="上海汉得信息技术股份有限公司" width="260px" height="83px"/>
&nbsp;&nbsp;<img src="https://gitee.com/smart-doc-team/smart-doc/raw/master/images/known-users/shunfeng.png" title="顺丰" width="83px" height="83px"/>
&nbsp;&nbsp;<img src="https://gitee.com/smart-doc-team/smart-doc/raw/master/images/known-users/yuanmengjiankang.png" title="远盟健康" width="260px" height="83px"/>
<img src="https://gitee.com/smart-doc-team/smart-doc/raw/master/images/known-users/puqie_gaitubao_100x100.jpg" title="普切信息科技" width="83px" height="83px"/>
&nbsp;&nbsp;
<img src="https://gitee.com/smart-doc-team/smart-doc/raw/master/images/known-users/tianbo-tech.png" title="杭州天铂云科" width="135px" height="83px"/>
&nbsp;&nbsp;
## Award situation
- 2020 年度 OSC 中国开源项目评选”活动中获得「最积极运营项目」
## Acknowledgements
感谢[JetBrains SoftWare](https://www.jetbrains.com) 为本开源项目提供的免费Open Source license。
<img src="https://gitee.com/smart-doc-team/smart-doc/raw/master/images/jetbrains-variant-3.png" width="260px" height="220px"/>
## Contact
愿意参与构建smart-doc或者是需要交流问题可以加入qq群
<img src="https://gitee.com/smart-doc-team/smart-doc/raw/master/images/smart-doc-qq.png" title="qq群" width="200px" height="210px"/>
<img src="https://gitee.com/smart-doc-team/smart-doc/raw/master/images/smart-doc-qq2.jpeg" title="qq群2" width="200px" height="210px"/>
> 1群已满有问题请加2群。
## Donate
如果您觉得我们的开源软件对你有所帮助,请扫下方二维码打赏我们一杯咖啡
<img src="https://images.gitee.com/uploads/images/2020/0831/225756_9aecdd4d_144669.png" width="200px" height="210px"/>

View File

@ -1 +0,0 @@
theme: jekyll-theme-cayman

7
css/AllInOne.css Normal file
View File

@ -0,0 +1,7 @@
article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,video{display:inline-block}audio:not([controls]){display:none;height:0}[hidden],template{display:none}script{display:none!important}html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}a{background:transparent}a:focus{outline:thin dotted}a:active,a:hover{outline:0}h1{font-size:2em;margin:.67em 0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}mark{background:#ff0;color:#000}code,kbd,pre,samp{font-family:monospace;font-size:1em}pre{white-space:pre-wrap}q{quotes:"\201C" "\201D" "\2018" "\2019"}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:0}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}button,input{line-height:normal}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}textarea{overflow:auto;vertical-align:top}table{border-collapse:collapse;border-spacing:0}*,*:before,*:after{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}html,body{font-size:100%}body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:"Noto Serif","DejaVu Serif",serif;font-weight:400;font-style:normal;line-height:1;position:relative;cursor:auto;tab-size:4;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}a:hover{cursor:pointer}img,object,embed{max-width:100%;height:auto}object,embed{height:100%}img{-ms-interpolation-mode:bicubic}.left{float:left!important}.right{float:right!important}.text-left{text-align:left!important}.text-right{text-align:right!important}.text-center{text-align:center!important}.text-justify{text-align:justify!important}.hide{display:none}img,object,svg{display:inline-block;vertical-align:middle}textarea{height:auto;min-height:50px}select{width:100%}.center{margin-left:auto;margin-right:auto}.spread{width:100%}p.lead,.paragraph.lead>p,#preamble>.sectionbody>.paragraph:first-of-type p{font-size:1.21875em;line-height:1.6}.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0;direction:ltr}a{color:#364149;text-decoration:underline;line-height:inherit}a:hover,a:focus{color:#364149}a img{border:0}p{font-family:inherit;font-weight:400;font-size:1em;line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}p aside{font-size:.875em;line-height:1.35;font-style:italic}h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:"Open Sans","DejaVu Sans",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}h1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}h1{font-size:2.125em}h2{font-size:1.6875em}h3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}h4,h5{font-size:1.125em}h6{font-size:1em}hr{border:solid #ddddd8;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em;height:0}em,i{font-style:italic;line-height:inherit}strong,b{font-weight:bold;line-height:inherit}small{font-size:60%;line-height:inherit}code{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;color:rgba(0,0,0,.9)}
ul,ol,dl{font-size:1em;line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}ul,ol{margin-left:1.5em}ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0;font-size:1em}ul.square li ul,ul.circle li ul,ul.disc li ul{list-style:inherit}ul.square{list-style-type:square}ul.circle{list-style-type:circle}ul.disc{list-style-type:disc}ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}dl dt{margin-bottom:.3125em;font-weight:bold}dl dd{margin-bottom:1.25em}abbr,acronym{text-transform:uppercase;font-size:90%;color:rgba(0,0,0,.8);border-bottom:1px dotted #ddd;cursor:help}abbr{text-transform:none}blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}blockquote cite{display:block;font-size:.9375em;color:rgba(0,0,0,.6)}blockquote cite:before{content:"\2014 \0020"}blockquote cite a,blockquote cite a:visited{color:rgba(0,0,0,.6)}blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}@media only screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}h1{font-size:2.75em}h2{font-size:2.3125em}h3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}h4{font-size:1.4375em}}table{background:#fff;margin-bottom:1.25em;border:solid 1px #dedede}table thead,table tfoot{background:#f7f8f7;font-weight:bold}table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}table tr.even,table tr.alt,table tr:nth-of-type(even){background:#f8f8f7}table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{display:table-cell;line-height:1.6}h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}.clearfix:before,.clearfix:after,.float-group:before,.float-group:after{content:" ";display:table}.clearfix:after,.float-group:after{clear:both}*:not(pre)>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background-color:#f7f7f8;-webkit-border-radius:4px;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed;word-wrap:break-word}*:not(pre)>code.nobreak{word-wrap:normal}*:not(pre)>code.nowrap{white-space:nowrap}pre,pre>code{line-height:1.45;color:rgba(0,0,0,.9);font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;text-rendering:optimizeSpeed}em em{font-style:normal}strong strong{font-weight:400}.keyseq{color:rgba(51,51,51,.8)}kbd{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background-color:#f7f7f7;border:1px solid #ccc;-webkit-border-radius:3px;border-radius:3px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em white inset;box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em #fff inset;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}.keyseq kbd:first-child{margin-left:0}.keyseq kbd:last-child{margin-right:0}.menuseq,.menuref{color:#000}.menuseq b:not(.caret),.menuref{font-weight:inherit}.menuseq{word-spacing:-.02em}.menuseq b.caret{font-size:1.25em;line-height:.8}.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}b.button:before,b.button:after{position:relative;top:-1px;font-weight:400}b.button:before{content:"[";padding:0 3px 0 2px}b.button:after{content:"]";padding:0 2px 0 3px}p a>code:hover{color:rgba(0,0,0,.9)}#header,#content,#footnotes,#footer{width:100%;margin-left:auto;margin-right:auto;margin-top:0;margin-bottom:0;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}#header:before,#header:after,#content:before,#content:after,#footnotes:before,#footnotes:after,#footer:before,#footer:after{content:" ";display:table}#header:after,#content:after,#footnotes:after,#footer:after{clear:both}#content{margin-top:1.25em}#content:before{content:none}#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #ddddd8}#header>h1:only-child,body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #ddddd8;padding-bottom:8px}#header .details{border-bottom:1px solid #ddddd8;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:-ms-flexbox;display:-webkit-flex;display:flex;-ms-flex-flow:row wrap;-webkit-flex-flow:row wrap;flex-flow:row wrap}#header .details span:first-child{margin-left:-.125em}#header .details span.email a{color:rgba(0,0,0,.85)}#header .details br{display:none}
#header .details br+span:before{content:"\00a0\2013\00a0"}#header .details br+span.author:before{content:"\00a0\22c5\00a0";color:rgba(0,0,0,.85)}#header .details br+span#revremark:before{content:"\00a0|\00a0"}#header #revnumber{text-transform:capitalize}#header #revnumber:after{content:"\00a0"}#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #ddddd8;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}#toc{border-bottom:1px solid #efefed;padding-bottom:.5em}#toc>ul{margin-left:.125em;padding-left:1.25em}#toc ul.sectlevel0>li>a{font-style:italic}#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}#toc ul{font-family:"Open Sans","DejaVu Sans",sans-serif;list-style-type:none}#toc li{line-height:1.3334;margin-top:.3334em;padding-bottom:4px;padding-top:4px}#toc a{text-decoration:none}#toc a:active{text-decoration:underline}#toctitle{color:#7a2518;font-size:1.2em}@media only screen and (min-width:768px){#toctitle{font-size:1.375em}body.toc2{padding-left:15em;padding-right:0}#toc.toc2{margin-top:0!important;background-color:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #efefed;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;#padding:1.25em 1em;height:100%;overflow:auto}#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}#toc.toc2>ul{font-size:.9em;margin-bottom:0}#toc.toc2 ul ul{margin-left:0;padding-left:1em}#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}body.toc2.toc-right{padding-left:0;padding-right:15em}body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #efefed;left:auto;right:0}}@media only screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}#toc.toc2{width:20em}#toc.toc2 #toctitle{font-size:1.375em;border-bottom:1px solid rgba(0,0,0,.07);padding-top:20px;padding-bottom:15px}#toc.toc2 #toctitle span{padding-left:1.25em;padding-bottom:15px}#toc.toc2>ul{font-size:.95em}#toc.toc2 ul ul{padding-left:1.25em}body.toc2.toc-right{padding-left:0;padding-right:20em}}#content #toc{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px}#content #toc>:first-child{margin-top:0}#content #toc>:last-child{margin-bottom:0}#footer{max-width:100%;background-color:rgba(0,0,0,.8);padding:1.25em}#footer-text{color:rgba(255,255,255,.8);line-height:1.44}.sect1{padding-bottom:.625em}@media only screen and (min-width:768px){.sect1{padding-bottom:1.25em}}.sect1+.sect1{border-top:1px solid #efefed}#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}#content h1>a.anchor:before,h2>a.anchor:before,h3>a.anchor:before,#toctitle>a.anchor:before,.sidebarblock>.content>.title>a.anchor:before,h4>a.anchor:before,h5>a.anchor:before,h6>a.anchor:before{content:"\00A7";font-size:.85em;display:block;padding-top:.1em}#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:"Noto Serif","DejaVu Serif",serif;font-size:1rem;font-style:italic}table.tableblock>caption.title{white-space:nowrap;overflow:visible;max-width:0}.paragraph.lead>p,#preamble>.sectionbody>.paragraph:first-of-type p{color:rgba(0,0,0,.85)}table.tableblock #preamble>.sectionbody>.paragraph:first-of-type p{font-size:inherit}.admonitionblock>table{border-collapse:separate;border:0;background:0;width:100%}
.admonitionblock>table td.icon{text-align:center;width:80px}.admonitionblock>table td.icon img{max-width:initial}.admonitionblock>table td.icon .title{font-weight:bold;font-family:"Open Sans","DejaVu Sans",sans-serif;text-transform:uppercase}.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #ddddd8;color:rgba(0,0,0,.6)}.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}.exampleblock>.content{border-style:solid;border-width:1px;border-color:#e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;-webkit-border-radius:4px;border-radius:4px}.exampleblock>.content>:first-child{margin-top:0}.exampleblock>.content>:last-child{margin-bottom:0}.sidebarblock{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px}.sidebarblock>:first-child{margin-top:0}.sidebarblock>:last-child{margin-bottom:0}.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}.literalblock pre,.listingblock pre:not(.highlight),.listingblock pre[class="highlight"],.listingblock pre[class^="highlight "],.listingblock pre.CodeRay,.listingblock pre.prettyprint{background:#f7f7f8}.sidebarblock .literalblock pre,.sidebarblock .listingblock pre:not(.highlight),.sidebarblock .listingblock pre[class="highlight"],.sidebarblock .listingblock pre[class^="highlight "],.sidebarblock .listingblock pre.CodeRay,.sidebarblock .listingblock pre.prettyprint{background:#f2f1f1}.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{-webkit-border-radius:4px;border-radius:4px;word-wrap:break-word;padding:1em;font-size:.8125em}.literalblock pre.nowrap,.literalblock pre[class].nowrap,.listingblock pre.nowrap,.listingblock pre[class].nowrap{overflow-x:auto;white-space:pre;word-wrap:normal}@media only screen and (min-width:768px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:.90625em}}@media only screen and (min-width:1280px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:1em}}.literalblock.output pre{color:#f7f7f8;background-color:rgba(0,0,0,.9)}.listingblock pre.highlightjs{padding:0}.listingblock pre.highlightjs>code{padding:1em;-webkit-border-radius:4px;border-radius:4px}.listingblock pre.prettyprint{border-width:0}.listingblock>.content{position:relative}.listingblock code[data-lang]:before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:#999}.listingblock:hover code[data-lang]:before{display:block}.listingblock.terminal pre .command:before{content:attr(data-prompt);padding-right:.5em;color:#999}.listingblock.terminal pre .command:not([data-prompt]):before{content:"$"}table.pyhltable{border-collapse:separate;border:0;margin-bottom:0;background:0}table.pyhltable td{vertical-align:top;padding-top:0;padding-bottom:0;line-height:1.45}table.pyhltable td.code{padding-left:.75em;padding-right:0}pre.pygments .lineno,table.pyhltable td:not(.code){color:#999;padding-left:0;padding-right:.5em;border-right:1px solid #ddddd8}pre.pygments .lineno{display:inline-block;margin-right:.25em}table.pyhltable .linenodiv{background:none!important;padding-right:0!important}.quoteblock{margin:0 1em 1.25em 1.5em;display:table}.quoteblock>.title{margin-left:-1.5em;margin-bottom:.75em}.quoteblock blockquote,.quoteblock blockquote p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}.quoteblock blockquote{margin:0;padding:0;border:0}.quoteblock blockquote:before{content:"\201c";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}.quoteblock .attribution{margin-top:.5em;margin-right:.5ex;text-align:right}.quoteblock .quoteblock{margin-left:0;margin-right:0;padding:.5em 0;border-left:3px solid rgba(0,0,0,.6)}.quoteblock .quoteblock blockquote{padding:0 0 0 .75em}.quoteblock .quoteblock blockquote:before{display:none}.verseblock{margin:0 1em 1.25em 1em}.verseblock pre{font-family:"Open Sans","DejaVu Sans",sans;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}
.verseblock pre strong{font-weight:400}.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}.quoteblock .attribution br,.verseblock .attribution br{display:none}.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}.quoteblock.abstract{margin:0 0 1.25em 0;display:block}.quoteblock.abstract blockquote,.quoteblock.abstract blockquote p{text-align:left;word-spacing:0}.quoteblock.abstract blockquote:before,.quoteblock.abstract blockquote p:first-of-type:before{display:none}table.tableblock{max-width:100%;border-collapse:separate}table.tableblock td>.paragraph:last-child p>p:last-child,table.tableblock th>p:last-child,table.tableblock td>p:last-child{margin-bottom:0}table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}table.grid-all>thead>tr>.tableblock,table.grid-all>tbody>tr>.tableblock{border-width:0 1px 1px 0}table.grid-all>tfoot>tr>.tableblock{border-width:1px 1px 0 0}table.grid-cols>*>tr>.tableblock{border-width:0 1px 0 0}table.grid-rows>thead>tr>.tableblock,table.grid-rows>tbody>tr>.tableblock{border-width:0 0 1px 0}table.grid-rows>tfoot>tr>.tableblock{border-width:1px 0 0 0}table.grid-all>*>tr>.tableblock:last-child,table.grid-cols>*>tr>.tableblock:last-child{border-right-width:0}table.grid-all>tbody>tr:last-child>.tableblock,table.grid-all>thead:last-child>tr>.tableblock,table.grid-rows>tbody>tr:last-child>.tableblock,table.grid-rows>thead:last-child>tr>.tableblock{border-bottom-width:0}table.frame-all{border-width:1px}table.frame-sides{border-width:0 1px}table.frame-topbot{border-width:1px 0}th.halign-left,td.halign-left{text-align:left}th.halign-right,td.halign-right{text-align:right}th.halign-center,td.halign-center{text-align:center}th.valign-top,td.valign-top{vertical-align:top}th.valign-bottom,td.valign-bottom{vertical-align:bottom}th.valign-middle,td.valign-middle{vertical-align:middle}table thead th,table tfoot th{font-weight:bold}tbody tr th{display:table-cell;line-height:1.6;background:#f7f8f7}tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}p.tableblock>code:only-child{background:0;padding:0}p.tableblock{font-size:1em}td>div.verse{white-space:pre}ol{margin-left:1.75em}ul li ol{margin-left:1.5em}dl dd{margin-left:1.125em}dl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}ol>li p,ul>li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}ul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}ul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}ul.unstyled,ol.unstyled{margin-left:0}ul.checklist{margin-left:.625em}ul.checklist li>p:first-child>.fa-square-o:first-child,ul.checklist li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}ul.checklist li>p:first-child>input[type="checkbox"]:first-child{margin-right:.25em}ul.inline{margin:0 auto .625em auto;margin-left:-1.375em;margin-right:0;padding:0;list-style:none;overflow:hidden}ul.inline>li{list-style:none;float:left;margin-left:1.375em;display:block}ul.inline>li>*{display:block}.unstyled dl dt{font-weight:400;font-style:normal}ol.arabic{list-style-type:decimal}ol.decimal{list-style-type:decimal-leading-zero}ol.loweralpha{list-style-type:lower-alpha}ol.upperalpha{list-style-type:upper-alpha}ol.lowerroman{list-style-type:lower-roman}ol.upperroman{list-style-type:upper-roman}ol.lowergreek{list-style-type:lower-greek}.hdlist>table,.colist>table{border:0;background:0}.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:0}td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}td.hdlist1{font-weight:bold;padding-bottom:1.25em}.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}.colist>table tr>td:first-of-type{padding:.4em .75em 0 .75em;line-height:1;vertical-align:top}.colist>table tr>td:first-of-type img{max-width:initial}.colist>table tr>td:last-of-type{padding:.25em 0}.thumb,.th{line-height:0;display:inline-block;border:solid 4px #fff;-webkit-box-shadow:0 0 0 1px #ddd;box-shadow:0 0 0 1px #ddd}.imageblock.left,.imageblock[style*="float:left"]{margin:.25em .625em 1.25em 0}.imageblock.right,.imageblock[style*="float:right"]{margin:.25em 0 1.25em .625em}.imageblock>.title{margin-bottom:0}.imageblock.thumb,.imageblock.th{border-width:6px}.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}.image.left{margin-right:.625em}.image.right{margin-left:.625em}a.image{text-decoration:none;display:inline-block}a.image object{pointer-events:none}sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}sup.footnote a,sup.footnoteref a{text-decoration:none}
sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em 0;border-width:1px 0 0 0}#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;text-indent:-1.05em;margin-bottom:.2em}#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none}#footnotes .footnote:last-of-type{margin-bottom:0}#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}.gist .file-data>table{border:0;background:#fff;width:100%;margin-bottom:0}.gist .file-data>table td.line-data{width:99%}div.unbreakable{page-break-inside:avoid}.big{font-size:larger}.small{font-size:smaller}.underline{text-decoration:underline}.overline{text-decoration:overline}.line-through{text-decoration:line-through}.aqua{color:#00bfbf}.aqua-background{background-color:#00fafa}.black{color:#000}.black-background{background-color:#000}.blue{color:#0000bf}.blue-background{background-color:#0000fa}.fuchsia{color:#bf00bf}.fuchsia-background{background-color:#fa00fa}.gray{color:#606060}.gray-background{background-color:#7d7d7d}.green{color:#006000}.green-background{background-color:#007d00}.lime{color:#00bf00}.lime-background{background-color:#00fa00}.maroon{color:#600000}.maroon-background{background-color:#7d0000}.navy{color:#000060}.navy-background{background-color:#00007d}.olive{color:#606000}.olive-background{background-color:#7d7d00}.purple{color:#600060}.purple-background{background-color:#7d007d}.red{color:#bf0000}.red-background{background-color:#fa0000}.silver{color:#909090}.silver-background{background-color:#bcbcbc}.teal{color:#006060}.teal-background{background-color:#007d7d}.white{color:#bfbfbf}.white-background{background-color:#fafafa}.yellow{color:#bfbf00}.yellow-background{background-color:#fafa00}span.icon>.fa{cursor:default}a span.icon>.fa{cursor:inherit}.admonitionblock td.icon [class^="fa icon-"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}.admonitionblock td.icon .icon-note:before{content:"\f05a";color:#19407c}.admonitionblock td.icon .icon-tip:before{content:"\f0eb";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}.admonitionblock td.icon .icon-warning:before{content:"\f071";color:#bf6900}.admonitionblock td.icon .icon-caution:before{content:"\f06d";color:#bf3400}.admonitionblock td.icon .icon-important:before{content:"\f06a";color:#bf0000}.conum[data-value]{display:inline-block;color:#fff!important;background-color:rgba(0,0,0,.8);-webkit-border-radius:100px;border-radius:100px;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:"Open Sans","DejaVu Sans",sans-serif;font-style:normal;font-weight:bold}.conum[data-value] *{color:#fff!important}.conum[data-value]+b{display:none}.conum[data-value]:after{content:attr(data-value)}pre .conum[data-value]{position:relative;top:-.125em}b.conum *{color:inherit!important}.conum:not([data-value]):empty{display:none}dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}h1,h2,p,td.content,span.alt{letter-spacing:-.01em}p strong,td.content strong,div.footnote strong{letter-spacing:-.005em}p,blockquote,dt,td.content,span.alt{font-size:1.0625rem}p{margin-bottom:1.25rem}.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}.exampleblock>.content{background-color:#fffef7;border-color:#e0e0dc;-webkit-box-shadow:0 1px 4px #e0e0dc;box-shadow:0 1px 4px #e0e0dc}.print-only{display:none!important}@media print{@page{margin:1.25cm .75cm}*{-webkit-box-shadow:none!important;box-shadow:none!important;text-shadow:none!important}a{color:inherit!important;text-decoration:underline!important}a.bare,a[href^="#"],a[href^="mailto:"]{text-decoration:none!important}a[href^="http:"]:not(.bare):after,a[href^="https:"]:not(.bare):after{content:"(" attr(href) ")";display:inline-block;font-size:.875em;padding-left:.25em}abbr[title]:after{content:" (" attr(title) ")"}pre,blockquote,tr,img,object,svg{page-break-inside:avoid}thead{display:table-header-group}svg{max-width:100%}p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}h2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}#toc,.sidebarblock,.exampleblock>.content{background:none!important}#toc{border-bottom:1px solid #ddddd8!important;padding-bottom:0!important}.sect1{padding-bottom:0!important}.sect1+.sect1{border:0!important}#header>h1:first-child{margin-top:1.25rem}
body.book #header{text-align:center}body.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em 0}body.book #header .details{border:0!important;display:block;padding:0!important}body.book #header .details span:first-child{margin-left:0!important}body.book #header .details br{display:block}body.book #header .details br+span:before{content:none!important}body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}.listingblock code[data-lang]:before{display:block}#footer{background:none!important;padding:0 .9375em}#footer-text{color:rgba(0,0,0,.6)!important;font-size:.9em}.hide-on-print{display:none!important}.print-only{display:block!important}.hide-for-print{display:none!important}.show-for-print{display:inherit!important}}#content .page-footer{height:100px;border-top:1px solid #ccc;overflow:hidden;padding:10px 0;font-size:14px;color:gray}#content .footer-modification{float:right}#content .footer-modification a{text-decoration:none}.sectlevel2{display:none}.submenu{background:#e7e7e6}.submenu li{border:0}.submenu a{color:#555}

232
css/index.css Normal file
View File

@ -0,0 +1,232 @@
.book-summary {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
position: absolute;
top: 0;
left: -300px;
bottom: 0;
z-index: 1;
overflow-y: auto;
width: 300px;
color: #364149;
background: #fafafa;
border-right: 1px solid rgba(0, 0, 0, .07);
-webkit-transition: left 250ms ease;
-moz-transition: left 250ms ease;
-o-transition: left 250ms ease;
transition: left 250ms ease
}
.book-summary ul.summary {
list-style: none;
margin: 0;
padding: 0;
-webkit-transition: top .5s ease;
-moz-transition: top .5s ease;
-o-transition: top .5s ease;
transition: top .5s ease
}
.book-summary ul.summary li {
list-style: none
}
.book-summary ul.summary li.header {
padding: 10px 15px;
padding-top: 20px;
text-transform: uppercase;
color: #939da3
}
.book-summary ul.summary li.divider {
height: 1px;
margin: 7px 0;
overflow: hidden;
background: rgba(0, 0, 0, .07)
}
.book-summary ul.summary li i.fa-check {
display: none;
position: absolute;
right: 9px;
top: 16px;
font-size: 9px;
color: #3c3
}
.book-summary ul.summary li.done > a {
color: #364149;
font-weight: 400
}
.book-summary ul.summary li.done > a i {
display: inline
}
.book-summary ul.summary li a, .book-summary {
display: block;
padding: 10px 15px;
border-bottom: 0;
color: #364149;
background: 0;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
position: relative
}
.book-summary ul.summary li a:hover {
text-decoration: underline
}
.book-summary ul.summary li a:focus {
outline: 0
}
.book-summary ul.summary li.active > a {
color: #008cff;
background: 0;
text-decoration: none
}
.book-summary ul.summary li ul {
padding-left: 20px
}
@media (max-width: 600px) {
.book-summary {
width: calc(100% - 60px);
bottom: 0;
left: -100%
}
}
.book.with-summary .book-summary {
left: 0
}
.book.without-animation .book-summary {
-webkit-transition: none !important;
-moz-transition: none !important;
-o-transition: none !important;
transition: none !important
}
.book {
position: relative;
width: 100%;
height: 100%
}
@media (min-width: 600px) {
.book.with-summary .book-body {
left: 300px
}
}
@media (max-width: 600px) {
.book.with-summary {
overflow: hidden
}
.book.with-summary .book-body {
-webkit-transform: translate(calc(100% - 60px), 0);
-moz-transform: translate(calc(100% - 60px), 0);
-ms-transform: translate(calc(100% - 60px), 0);
-o-transform: translate(calc(100% - 60px), 0);
transform: translate(calc(100% - 60px), 0)
}
}
.book.without-animation .book-body {
-webkit-transition: none !important;
-moz-transition: none !important;
-o-transition: none !important;
transition: none !important
}
.book-body {
position: absolute;
top: 0;
right: 0;
left: 0;
bottom: 0;
overflow-y: hidden;
color: #000;
background: #fff;
-webkit-transition: left 250ms ease;
-moz-transition: left 250ms ease;
-o-transition: left 250ms ease;
transition: left 250ms ease
}
@media (max-width: 1240px) {
.book-body {
-webkit-transition: -webkit-transform 250ms ease;
-moz-transition: -moz-transform 250ms ease;
-o-transition: -o-transform 250ms ease;
transition: transform 250ms ease;
padding-bottom: 20px
}
}
#book-search-input {
padding: 6px;
background: 0;
transition: top .5s ease;
border-bottom: 1px solid rgba(0, 0, 0, .07);
border-top: 1px solid rgba(0, 0, 0, .07);
margin-bottom: 10px;
margin-top: -1px
}
#book-search-input input, #book-search-input input:focus, #book-search-input input:hover {
width: 100%;
background: 0;
border: 1px solid transparent;
box-shadow: none;
outline: 0;
line-height: 22px;
padding: 7px 7px;
color: inherit
}
a {
text-decoration: none
}
body, html {
height: 100%
}
html {
font-size: 62.5%
}
body {
margin: 0
}
body {
text-rendering: optimizeLegibility;
font-smoothing: antialiased;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 14px;
letter-spacing: .2px;
text-size-adjust: 100%;
-ms-text-size-adjust: 100%;
-webkit-text-size-adjust: 100%
}
#reference {
padding-top: 10px;
padding-bottom: 10px;
padding-left: 15px
}
.footer_link {
margin-bottom: 45px
}
.line-through {
text-decoration: line-through;
}

1
css/markdown.css Normal file
View File

@ -0,0 +1 @@
body{margin:0;padding:0;height:auto;bottom:0;top:0;left:0;right:0;font-size:1rem;line-height:1.42857;overflow-x:hidden;background:inherit;tab-size:4}.margin-tb-zero,.markdown-body ol ol,.markdown-body ul ol,.markdown-body ol ul,.markdown-body ul ul,.markdown-body ol ul ol,.markdown-body ul ul ol,.markdown-body ol ul ul,.markdown-body ul ul ul{margin-top:0;margin-bottom:0}.markdown-body{font-family:"Helvetica Neue",Helvetica,"Segoe UI",Arial,freesans,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";font-size:16px;color:#333;line-height:1.6;word-wrap:break-word;padding:45px;background:#fff;#border-top:1px solid #ddd;-webkit-border-radius:0 0 3px 3px;#max-width:55%;#margin-left:15%;border-radius:0 0 3px 3px;max-width:800px;margin:0 auto;padding:30px 30px 100px}.markdown-body>*:first-child{margin-top:0!important}.markdown-body>*:last-child{margin-bottom:0!important}.markdown-body *{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.markdown-body h1,.markdown-body h2,.markdown-body h3,.markdown-body h4,.markdown-body h5,.markdown-body h6{margin-top:1em;margin-bottom:16px;font-weight:bold;line-height:1.4}.markdown-body p,.markdown-body blockquote,.markdown-body ul,.markdown-body ol,.markdown-body dl,.markdown-body table,.markdown-body pre{margin-top:0;margin-bottom:16px}.markdown-body h1{margin:.67em 0;padding-bottom:.3em;font-size:2.25em;line-height:1.2;border-bottom:1px solid #eee}.markdown-body h2{padding-bottom:.3em;font-size:1.75em;line-height:1.225;border-bottom:1px solid #eee}.markdown-body h3{font-size:1.5em;line-height:1.43}.markdown-body h4{font-size:1.25em}.markdown-body h5{font-size:1em}.markdown-body h6{font-size:1em;color:#777}.markdown-body ol,.markdown-body ul{padding-left:2em}.markdown-body ol ol,.markdown-body ul ol{list-style-type:lower-roman}.markdown-body ol ul,.markdown-body ul ul{list-style-type:circle}.markdown-body ol ul ul,.markdown-body ul ul ul{list-style-type:square}.markdown-body ol{list-style-type:decimal}.markdown-body ul{list-style-type:disc}.markdown-body blockquote{margin-left:0;margin-right:0;padding:0 15px;color:#777;border-left:4px solid #ddd}.markdown-body table{#display:block;width:100%;overflow:auto;word-break:normal;word-break:keep-all;border-collapse:collapse;border-spacing:0;text-align:left}thead{background-color:#f8f8f8}.markdown-body table tr{#background-color:#fff;border-top:1px solid #ccc}.markdown-body table tr:nth-child(2n){background-color:#f8f8f8}.markdown-body table th,.markdown-body table td{padding:6px 13px;border:1px solid #ddd}.markdown-body pre{word-wrap:normal;padding:16px;overflow:auto;font-size:85%;line-height:1.45;background-color:#f7f7f7;-webkit-border-radius:3px;border-radius:3px}.markdown-body pre code{display:inline;max-width:initial;padding:0;margin:0;overflow:initial;font-size:100%;line-height:inherit;word-wrap:normal;white-space:pre;border:0;-webkit-border-radius:3px;border-radius:3px;background-color:transparent}.markdown-body pre code:before,.markdown-body pre code:after{content:normal}.markdown-body code{font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace;padding:0;padding-top:.2em;padding-bottom:.2em;margin:0;font-size:85%;background-color:rgba(0,0,0,0.04);-webkit-border-radius:3px;border-radius:3px}.markdown-body code:before,.markdown-body code:after{letter-spacing:-0.2em;content:"\00a0"}.markdown-body a{color:#4078c0;text-decoration:none;background:transparent}.markdown-body img{max-width:100%;max-height:100%;-webkit-border-radius:4px;border-radius:4px;-webkit-box-shadow:0 0 10px #555;box-shadow:0 0 10px #555}.markdown-body strong{font-weight:bold}.markdown-body em{font-style:italic}.markdown-body del{text-decoration:line-through}.task-list-item{list-style-type:none}.task-list-item input{font:13px/1.4 Helvetica,arial,nimbussansl,liberationsans,freesans,clean,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";margin:0 .35em .25em -1.6em;vertical-align:middle}.task-list-item input[disabled]{cursor:default}.task-list-item input[type="checkbox"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}.task-list-item input[type="radio"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}.markdown-body .page-footer{margin-top:45px;height:50px;border-top:1px solid #ccc;overflow:hidden;padding:10px 0;font-size:14px;color:gray}.markdown-body .footer-modification{float:right}.markdown-body .footer-modification a{text-decoration:none}

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 KiB

BIN
images/known-users/akf.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

BIN
images/smart-doc-qq.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

BIN
images/smart-doc-qq2.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

BIN
images/smart-doc-torna.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 210 KiB

View File

@ -1,37 +0,0 @@
## Welcome to GitHub Pages
You can use the [editor on GitHub](https://github.com/smart-doc-group/smart-doc/edit/gh-pages/index.md) to maintain and preview the content for your website in Markdown files.
Whenever you commit to this repository, GitHub Pages will run [Jekyll](https://jekyllrb.com/) to rebuild the pages in your site, from the content in your Markdown files.
### Markdown
Markdown is a lightweight and easy-to-use syntax for styling your writing. It includes conventions for
```markdown
Syntax highlighted code block
# Header 1
## Header 2
### Header 3
- Bulleted
- List
1. Numbered
2. List
**Bold** and _Italic_ and `Code` text
[Link](url) and ![Image](src)
```
For more details see [GitHub Flavored Markdown](https://guides.github.com/features/mastering-markdown/).
### Jekyll Themes
Your Pages site will use the layout and styles from the Jekyll theme you have selected in your [repository settings](https://github.com/smart-doc-group/smart-doc/settings/pages). The name of this theme is saved in the Jekyll `_config.yml` configuration file.
### Support or Contact
Having trouble with Pages? Check out our [documentation](https://docs.github.com/categories/github-pages-basics/) or [contact support](https://support.github.com/contact) and well help you sort it out.

160
pom.xml Normal file
View File

@ -0,0 +1,160 @@
<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">
<groupId>com.github.shalousun</groupId>
<modelVersion>4.0.0</modelVersion>
<artifactId>smart-doc</artifactId>
<packaging>jar</packaging>
<version>2.3.2</version>
<name>smart-doc</name>
<url>https://github.com/smart-doc-group/smart-doc.git</url>
<description>Smart-doc is a tool that supports both JAVA RESTFUL API and Apache Dubbo RPC interface document
generation.
</description>
<licenses>
<license>
<name>The Apache Software License, Version 2.0</name>
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
<distribution>repo</distribution>
</license>
</licenses>
<scm>
<url>https://github.com/smart-doc-group/smart-doc.git</url>
<connection>scm:https://github.com/smart-doc-group/smart-doc.git</connection>
<developerConnection>scm:https://github.com/smart-doc-group/smart-doc.git</developerConnection>
</scm>
<developers>
<developer>
<name>shalousun</name>
<email>836575280@qq.com</email>
<url>https://github.com/shalousun</url>
</developer>
</developers>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<junit.jupiter.version>5.8.1</junit.jupiter.version>
</properties>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>${junit.jupiter.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.ibeetl</groupId>
<artifactId>beetl</artifactId>
<version>3.8.1.RELEASE</version>
</dependency>
<dependency>
<groupId>com.thoughtworks.qdox</groupId>
<artifactId>qdox</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>com.github.javafaker</groupId>
<artifactId>javafaker</artifactId>
<version>1.0.2</version>
<exclusions>
<exclusion>
<artifactId>commons-lang3</artifactId>
<groupId>org.apache.commons</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.github.shalousun</groupId>
<artifactId>common-util</artifactId>
<version>2.1.0</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.8</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.32</version>
</dependency>
</dependencies>
<build>
<plugins>
<!--compiler-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<!-- Source -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.2.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- JavaDoc -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.2.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
<finalName>smart-doc</finalName>
</build>
<profiles>
<profile>
<id>release</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.0.1</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<distributionManagement>
<snapshotRepository>
<id>oss</id>
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
</snapshotRepository>
<repository>
<id>oss</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
</profile>
</profiles>
</project>

BIN
screen/debug-console.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 355 KiB

BIN
screen/dubbo-all.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 169 KiB

BIN
screen/dubbo-api.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

BIN
screen/dubbo-invoke.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 177 KiB

BIN
screen/dubbo-response.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

BIN
screen/dubbo-top.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

BIN
screen/example.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 205 KiB

BIN
screen/mock.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 137 KiB

BIN
screen/request-body.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

BIN
screen/request-header.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

BIN
screen/request-response.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 139 KiB

View File

@ -0,0 +1,94 @@
/*
* smart-doc https://github.com/shalousun/smart-doc
*
* Copyright (C) 2018-2021 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.power.doc.factory.BuildTemplateFactory;
import com.power.doc.model.ApiConfig;
import com.power.doc.model.ApiDoc;
import com.power.doc.template.IDocBuildTemplate;
import com.thoughtworks.qdox.JavaProjectBuilder;
import java.util.List;
import static com.power.doc.constants.DocGlobalConstants.*;
/**
* Use to create Asciidoc
*
* @author yu 2019/9/26.
*/
public class AdocDocBuilder {
private static final String API_EXTENSION = "Api.adoc";
private static final String INDEX_DOC = "index.adoc";
/**
* build adoc
*
* @param config ApiConfig
*/
public static void buildApiDoc(ApiConfig config) {
JavaProjectBuilder javaProjectBuilder = new JavaProjectBuilder();
buildApiDoc(config, javaProjectBuilder);
}
/**
* Only for smart-doc maven plugin and gradle plugin.
*
* @param config ApiConfig
* @param javaProjectBuilder ProjectDocConfigBuilder
*/
public static void buildApiDoc(ApiConfig config, JavaProjectBuilder javaProjectBuilder) {
DocBuilderTemplate builderTemplate = new DocBuilderTemplate();
builderTemplate.checkAndInit(config,false);
config.setParamsDataToTree(false);
config.setAdoc(true);
ProjectDocConfigBuilder configBuilder = new ProjectDocConfigBuilder(config, javaProjectBuilder);
IDocBuildTemplate docBuildTemplate = BuildTemplateFactory.getDocBuildTemplate(config.getFramework());
List<ApiDoc> apiDocList = docBuildTemplate.getApiData(configBuilder);
if (config.isAllInOne()) {
String docName = builderTemplate.allInOneDocName(config,INDEX_DOC,".adoc");
apiDocList = docBuildTemplate.handleApiGroup(apiDocList, config);
builderTemplate.buildAllInOne(apiDocList, config, javaProjectBuilder, ALL_IN_ONE_ADOC_TPL, docName);
} else {
builderTemplate.buildApiDoc(apiDocList, config, API_DOC_ADOC_TPL, API_EXTENSION);
builderTemplate.buildErrorCodeDoc(config, ERROR_CODE_LIST_ADOC_TPL, ERROR_CODE_LIST_ADOC);
builderTemplate.buildDirectoryDataDoc(config, javaProjectBuilder, DICT_LIST_ADOC_TPL, DICT_LIST_ADOC);
}
}
/**
* Generate a single controller api document
*
* @param config ApiConfig
* @param controllerName controller name
*/
public static void buildSingleApiDoc(ApiConfig config, String controllerName) {
config.setAdoc(false);
ProjectDocConfigBuilder configBuilder = new ProjectDocConfigBuilder(config, new JavaProjectBuilder());
DocBuilderTemplate builderTemplate = new DocBuilderTemplate();
builderTemplate.checkAndInit(config,false);
builderTemplate.buildSingleApi(configBuilder, controllerName, API_DOC_ADOC_TPL, API_EXTENSION);
}
}

View File

@ -0,0 +1,63 @@
/*
* smart-doc https://github.com/shalousun/smart-doc
*
* Copyright (C) 2018-2021 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.power.doc.model.ApiAllData;
import com.power.doc.model.ApiConfig;
import com.thoughtworks.qdox.JavaProjectBuilder;
/**
* @author yu 2019/12/7.
* @since 1.7.9
*/
public class ApiDataBuilder {
/**
* Get list of ApiDoc
*
* @param config ApiConfig
* @return List of ApiDoc
*/
public static ApiAllData getApiData(ApiConfig config) {
return getApiData(config, Boolean.FALSE);
}
/**
* Get list of ApiDoc
*
* @param config ApiConfig
* @return List of ApiDoc
*/
public static ApiAllData getApiDataTree(ApiConfig config) {
return getApiData(config, Boolean.TRUE);
}
private static ApiAllData getApiData(ApiConfig config, boolean toTree) {
config.setParamsDataToTree(toTree);
DocBuilderTemplate builderTemplate = new DocBuilderTemplate();
builderTemplate.checkAndInitForGetApiData(config);
JavaProjectBuilder javaProjectBuilder = new JavaProjectBuilder();
ApiAllData apiAllData = builderTemplate.getApiData(config, javaProjectBuilder);
return apiAllData;
}
}

View File

@ -0,0 +1,95 @@
/*
* smart-doc https://github.com/shalousun/smart-doc
*
* Copyright (C) 2018-2021 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.power.common.util.DateTimeUtil;
import com.power.doc.factory.BuildTemplateFactory;
import com.power.doc.model.ApiConfig;
import com.power.doc.model.ApiDoc;
import com.power.doc.template.IDocBuildTemplate;
import com.thoughtworks.qdox.JavaProjectBuilder;
import java.util.List;
import static com.power.doc.constants.DocGlobalConstants.*;
/**
* use to create markdown doc
*
* @author yu 2019/09/20
*/
public class ApiDocBuilder {
private static final String API_EXTENSION = "Api.md";
private static final String DATE_FORMAT = "yyyyMMddHHmm";
/**
* @param config ApiConfig
*/
public static void buildApiDoc(ApiConfig config) {
JavaProjectBuilder javaProjectBuilder = new JavaProjectBuilder();
buildApiDoc(config, javaProjectBuilder);
}
/**
* Only for smart-doc maven plugin and gradle plugin.
*
* @param config ApiConfig
* @param javaProjectBuilder ProjectDocConfigBuilder
*/
public static void buildApiDoc(ApiConfig config, JavaProjectBuilder javaProjectBuilder) {
DocBuilderTemplate builderTemplate = new DocBuilderTemplate();
builderTemplate.checkAndInit(config,false);
config.setAdoc(false);
config.setParamsDataToTree(false);
ProjectDocConfigBuilder configBuilder = new ProjectDocConfigBuilder(config, javaProjectBuilder);
IDocBuildTemplate docBuildTemplate = BuildTemplateFactory.getDocBuildTemplate(config.getFramework());
List<ApiDoc> apiDocList = docBuildTemplate.getApiData(configBuilder);
if (config.isAllInOne()) {
String version = config.isCoverOld() ? "" : "-V" + DateTimeUtil.long2Str(System.currentTimeMillis(), DATE_FORMAT);
String docName = builderTemplate.allInOneDocName(config,"AllInOne" + version + ".md",".md");
apiDocList = docBuildTemplate.handleApiGroup(apiDocList, config);
builderTemplate.buildAllInOne(apiDocList, config, javaProjectBuilder, ALL_IN_ONE_MD_TPL, docName);
} else {
builderTemplate.buildApiDoc(apiDocList, config, API_DOC_MD_TPL, API_EXTENSION);
builderTemplate.buildErrorCodeDoc(config, ERROR_CODE_LIST_MD_TPL, ERROR_CODE_LIST_MD);
builderTemplate.buildDirectoryDataDoc(config, javaProjectBuilder, DICT_LIST_MD_TPL, DICT_LIST_MD);
}
}
/**
* Generate a single controller api document
*
* @param config (ApiConfig
* @param controllerName controller name
*/
public static void buildSingleApiDoc(ApiConfig config, String controllerName) {
config.setAdoc(false);
JavaProjectBuilder javaProjectBuilder = new JavaProjectBuilder();
ProjectDocConfigBuilder configBuilder = new ProjectDocConfigBuilder(config, javaProjectBuilder);
DocBuilderTemplate builderTemplate = new DocBuilderTemplate();
builderTemplate.checkAndInit(config,false);
builderTemplate.buildSingleApi(configBuilder, controllerName, API_DOC_MD_TPL, API_EXTENSION);
}
}

View File

@ -0,0 +1,167 @@
/*
* smart-doc https://github.com/shalousun/smart-doc
*
* Copyright (C) 2018-2021 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.power.common.util.DateTimeUtil;
import com.power.common.util.StringUtil;
import com.power.doc.constants.DocGlobalConstants;
import com.power.doc.constants.DocLanguage;
import com.power.doc.constants.FrameworkEnum;
import com.power.doc.constants.TemplateVariable;
import com.power.doc.model.ApiConfig;
import com.power.doc.model.RevisionLog;
import org.apache.commons.lang3.StringUtils;
import org.beetl.core.Resource;
import org.beetl.core.Template;
import org.beetl.core.resource.ClasspathResourceLoader;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import static com.power.doc.constants.DocGlobalConstants.CSS_CDN;
import static com.power.doc.constants.DocGlobalConstants.CSS_CDN_CH;
/**
* @author yu 2020/5/16.
*/
public class BaseDocBuilderTemplate {
public static long NOW = System.currentTimeMillis();
/**
* check condition and init
*
* @param config Api config
* @param checkOutPath check out path
*/
public void checkAndInit(ApiConfig config,boolean checkOutPath) {
this.checkAndInitForGetApiData(config);
if (StringUtil.isEmpty(config.getOutPath())&&!checkOutPath) {
throw new RuntimeException("doc output path can't be null or empty");
}
}
/**
* check condition and init for get Data
*
* @param config Api config
*/
public void checkAndInitForGetApiData(ApiConfig config) {
if (null == config) {
throw new NullPointerException("ApiConfig can't be null");
}
if (null != config.getLanguage()) {
System.setProperty(DocGlobalConstants.DOC_LANGUAGE, config.getLanguage().getCode());
} else {
//default is chinese
config.setLanguage(DocLanguage.CHINESE);
System.setProperty(DocGlobalConstants.DOC_LANGUAGE, DocLanguage.CHINESE.getCode());
}
if (Objects.isNull(config.getRevisionLogs())) {
String strTime = DateTimeUtil.long2Str(NOW, DateTimeUtil.DATE_FORMAT_SECOND);
config.setRevisionLogs(
RevisionLog.builder()
.setRevisionTime(strTime)
.setAuthor("@" + System.getProperty("user.name"))
.setVersion("v" + strTime)
.setRemarks("Created by smart-doc")
.setStatus("auto")
);
}
if (StringUtil.isEmpty(config.getFramework())) {
config.setFramework(FrameworkEnum.SPRING.getFramework());
}
}
public Map<String, String> setDirectoryLanguageVariable(ApiConfig config, Template mapper) {
Map<String, String> titleMap = new HashMap<>();
if (Objects.nonNull(config.getLanguage())) {
if (DocLanguage.CHINESE.code.equals(config.getLanguage().getCode())) {
mapper.binding(TemplateVariable.ERROR_LIST_TITLE.getVariable(), DocGlobalConstants.ERROR_CODE_LIST_CN_TITLE);
mapper.binding(TemplateVariable.DICT_LIST_TITLE.getVariable(), DocGlobalConstants.DICT_CN_TITLE);
titleMap.put(TemplateVariable.ERROR_LIST_TITLE.getVariable(), DocGlobalConstants.ERROR_CODE_LIST_CN_TITLE);
titleMap.put(TemplateVariable.DICT_LIST_TITLE.getVariable(), DocGlobalConstants.DICT_CN_TITLE);
} else {
mapper.binding(TemplateVariable.ERROR_LIST_TITLE.getVariable(), DocGlobalConstants.ERROR_CODE_LIST_EN_TITLE);
mapper.binding(TemplateVariable.DICT_LIST_TITLE.getVariable(), DocGlobalConstants.DICT_EN_TITLE);
titleMap.put(TemplateVariable.ERROR_LIST_TITLE.getVariable(), DocGlobalConstants.ERROR_CODE_LIST_EN_TITLE);
titleMap.put(TemplateVariable.DICT_LIST_TITLE.getVariable(), DocGlobalConstants.DICT_EN_TITLE);
}
} else {
mapper.binding(TemplateVariable.ERROR_LIST_TITLE.getVariable(), DocGlobalConstants.ERROR_CODE_LIST_CN_TITLE);
mapper.binding(TemplateVariable.DICT_LIST_TITLE.getVariable(), DocGlobalConstants.DICT_CN_TITLE);
titleMap.put(TemplateVariable.ERROR_LIST_TITLE.getVariable(), DocGlobalConstants.ERROR_CODE_LIST_CN_TITLE);
titleMap.put(TemplateVariable.DICT_LIST_TITLE.getVariable(), DocGlobalConstants.DICT_CN_TITLE);
}
return titleMap;
}
public void setCssCDN(ApiConfig config, Template template) {
if (DocLanguage.CHINESE.equals(config.getLanguage())) {
template.binding(TemplateVariable.CSS_CND.getVariable(), CSS_CDN_CH);
} else {
template.binding(TemplateVariable.CSS_CND.getVariable(), CSS_CDN);
}
}
public String allInOneDocName(ApiConfig apiConfig, String fileName, String suffix) {
String allInOneName = apiConfig.getAllInOneDocFileName();
if (StringUtils.isNotEmpty(apiConfig.getAllInOneDocFileName())) {
if (allInOneName.endsWith(suffix)) {
return allInOneName;
} else {
return allInOneName + suffix;
}
} else if (StringUtil.isNotEmpty(fileName) && fileName.endsWith(suffix)) {
return fileName;
} else {
return fileName + suffix;
}
}
public static void copyJarFile(String source, String target) {
ClasspathResourceLoader resourceLoader = new ClasspathResourceLoader("/template/");
Resource resource = resourceLoader.getResource(source);
try (FileWriter fileWriter = new FileWriter(target, false);
Reader reader = resource.openReader()) {
char[] c = new char[1024 * 1024];
int temp;
int len = 0;
while ((temp = reader.read()) != -1) {
c[len] = (char) temp;
len++;
}
reader.close();
BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
bufferedWriter.write(c, 0, len);
bufferedWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

View File

@ -0,0 +1,363 @@
/*
* smart-doc https://github.com/shalousun/smart-doc
*
* Copyright (C) 2018-2021 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.power.common.util.CollectionUtil;
import com.power.common.util.DateTimeUtil;
import com.power.common.util.FileUtil;
import com.power.doc.constants.DocLanguage;
import com.power.doc.constants.HighlightStyle;
import com.power.doc.constants.TemplateVariable;
import com.power.doc.factory.BuildTemplateFactory;
import com.power.doc.model.*;
import com.power.doc.template.IDocBuildTemplate;
import com.power.doc.utils.BeetlTemplateUtil;
import com.power.doc.utils.DocUtil;
import com.thoughtworks.qdox.JavaProjectBuilder;
import org.beetl.core.Template;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import static com.power.doc.constants.DocGlobalConstants.*;
/**
* @author yu 2019/9/26.
*/
public class DocBuilderTemplate extends BaseDocBuilderTemplate {
private static long now = System.currentTimeMillis();
/**
* get all api data
*
* @param config ApiConfig
* @param javaProjectBuilder JavaProjectBuilder
* @return ApiAllData
*/
public ApiAllData getApiData(ApiConfig config, JavaProjectBuilder javaProjectBuilder) {
ApiAllData apiAllData = new ApiAllData();
apiAllData.setProjectName(config.getProjectName());
apiAllData.setProjectId(DocUtil.generateId(config.getProjectName()));
apiAllData.setLanguage(config.getLanguage().getCode());
apiAllData.setApiDocList(listOfApiData(config, javaProjectBuilder));
apiAllData.setErrorCodeList(DocUtil.errorCodeDictToList(config));
apiAllData.setRevisionLogs(config.getRevisionLogs());
apiAllData.setApiDocDictList(DocUtil.buildDictionary(config, javaProjectBuilder));
return apiAllData;
}
/**
* Generate api documentation for all controllers.
*
* @param apiDocList list of api doc
* @param config api config
* @param template template
* @param fileExtension file extension
*/
public void buildApiDoc(List<ApiDoc> apiDocList, ApiConfig config, String template, String fileExtension) {
FileUtil.mkdirs(config.getOutPath());
for (ApiDoc doc : apiDocList) {
Template mapper = BeetlTemplateUtil.getByName(template);
mapper.binding(TemplateVariable.DESC.getVariable(), doc.getDesc());
mapper.binding(TemplateVariable.NAME.getVariable(), doc.getName());
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);
}
}
/**
* Merge all api doc into one document
*
* @param apiDocList list data of Api doc
* @param config api config
* @param javaProjectBuilder JavaProjectBuilder
* @param template template
* @param outPutFileName output file
*/
public void buildAllInOne(List<ApiDoc> apiDocList, ApiConfig config, JavaProjectBuilder javaProjectBuilder,
String template, String outPutFileName) {
buildDoc(apiDocList, config, javaProjectBuilder, template, outPutFileName, null, null);
}
/**
* Merge all api doc into one document
*
* @param apiDocList list data of Api doc
* @param config api config
* @param javaProjectBuilder JavaProjectBuilder
* @param template template
* @param outPutFileName output file
* @param apiDoc apiDoc
* @param index index html
*/
public void buildDoc(List<ApiDoc> apiDocList, ApiConfig config, JavaProjectBuilder javaProjectBuilder,
String template, String outPutFileName, ApiDoc apiDoc, String index) {
String outPath = config.getOutPath();
String strTime = DateTimeUtil.long2Str(now, DateTimeUtil.DATE_FORMAT_SECOND);
FileUtil.mkdirs(outPath);
List<ApiErrorCode> errorCodeList = DocUtil.errorCodeDictToList(config);
Template tpl = BeetlTemplateUtil.getByName(template);
String style = config.getStyle();
tpl.binding(TemplateVariable.STYLE.getVariable(), style);
tpl.binding(TemplateVariable.HIGH_LIGHT_CSS_LINK.getVariable(), config.getHighlightStyleLink());
tpl.binding(TemplateVariable.BACKGROUND.getVariable(), HighlightStyle.getBackgroundColor(style));
tpl.binding(TemplateVariable.API_DOC_LIST.getVariable(), apiDocList);
tpl.binding(TemplateVariable.ERROR_CODE_LIST.getVariable(), errorCodeList);
tpl.binding(TemplateVariable.VERSION_LIST.getVariable(), config.getRevisionLogs());
tpl.binding(TemplateVariable.VERSION.getVariable(), now);
tpl.binding(TemplateVariable.INDEX_ALIAS.getVariable(), index);
tpl.binding(TemplateVariable.CREATE_TIME.getVariable(), strTime);
tpl.binding(TemplateVariable.PROJECT_NAME.getVariable(), config.getProjectName());
tpl.binding(TemplateVariable.REQUEST_EXAMPLE.getVariable(), config.isRequestExample());
tpl.binding(TemplateVariable.RESPONSE_EXAMPLE.getVariable(), config.isResponseExample());
tpl.binding(TemplateVariable.DISPLAY_REQUEST_PARAMS.getVariable(), config.isRequestParamsTable());
tpl.binding(TemplateVariable.DISPLAY_RESPONSE_PARAMS.getVariable(), config.isResponseParamsTable());
setCssCDN(config, tpl);
if (CollectionUtil.isEmpty(errorCodeList)) {
tpl.binding(TemplateVariable.DICT_ORDER.getVariable(), apiDocList.size() + 1);
} else {
tpl.binding(TemplateVariable.DICT_ORDER.getVariable(), apiDocList.size() + 2);
}
if (Objects.nonNull(apiDoc)) {
tpl.binding(TemplateVariable.DESC.getVariable(), apiDoc.getDesc());
tpl.binding(TemplateVariable.ORDER.getVariable(), apiDoc.order);
tpl.binding(TemplateVariable.LIST.getVariable(), apiDoc.getList());//类名
}
setDirectoryLanguageVariable(config, tpl);
List<ApiDocDict> apiDocDictList = DocUtil.buildDictionary(config, javaProjectBuilder);
tpl.binding(TemplateVariable.DICT_LIST.getVariable(), apiDocDictList);
FileUtil.nioWriteFile(tpl.render(), outPath + FILE_SEPARATOR + outPutFileName);
}
public void buildSearchJs(ApiConfig config, JavaProjectBuilder javaProjectBuilder, List<ApiDoc> apiDocList, String template) {
List<ApiErrorCode> errorCodeList = DocUtil.errorCodeDictToList(config);
Template tpl = BeetlTemplateUtil.getByName(template);
// directory tree
List<ApiDoc> apiDocs = new ArrayList<>();
for (ApiDoc apiDoc1 : apiDocList) {
apiDoc1.setOrder(apiDocs.size() + 1);
apiDocs.add(apiDoc1);
}
boolean isOnlyDefaultGroup = apiDocList.size() == 1;
Map<String, String> titleMap = setDirectoryLanguageVariable(config, tpl);
// set error code
if (CollectionUtil.isNotEmpty(errorCodeList)) {
ApiDoc apiDoc1 = new ApiDoc();
apiDoc1.setOrder((isOnlyDefaultGroup ? apiDocs.get(0).getChildrenApiDocs().size() : apiDocs.size()) + 1);
apiDoc1.setDesc(titleMap.get(TemplateVariable.ERROR_LIST_TITLE.getVariable()));
apiDoc1.setList(new ArrayList<>(0));
apiDoc1.setLink("error_code_list");
apiDoc1.setAlias("error");
apiDoc1.setGroup(apiDoc1.getDesc());
if (isOnlyDefaultGroup) {
apiDocs.get(0).getChildrenApiDocs().add(apiDoc1);
} else {
apiDocs.add(apiDoc1);
}
}
// set dict list
List<ApiDocDict> apiDocDictList = DocUtil.buildDictionary(config, javaProjectBuilder);
if (CollectionUtil.isNotEmpty(apiDocDictList)) {
ApiDoc apiDoc1 = new ApiDoc();
apiDoc1.setOrder((isOnlyDefaultGroup ? apiDocs.get(0).getChildrenApiDocs().size() : apiDocs.size()) + 1);
apiDoc1.setLink("dict_list");
apiDoc1.setAlias("dict");
apiDoc1.setDesc(titleMap.get(TemplateVariable.DICT_LIST_TITLE.getVariable()));
apiDoc1.setGroup(apiDoc1.getDesc());
List<ApiMethodDoc> methodDocs = new ArrayList<>();
for (ApiDocDict apiDocDict : apiDocDictList) {
ApiMethodDoc methodDoc = new ApiMethodDoc();
methodDoc.setOrder(apiDocDict.getOrder());
methodDoc.setDesc(apiDocDict.getTitle());
methodDocs.add(methodDoc);
}
apiDoc1.setList(methodDocs);
if (isOnlyDefaultGroup) {
apiDocs.get(0).getChildrenApiDocs().add(apiDoc1);
} else {
apiDocs.add(apiDoc1);
}
}
tpl.binding(TemplateVariable.API_DOC_LIST.getVariable(), apiDocs);
FileUtil.nioWriteFile(tpl.render(), config.getOutPath() + FILE_SEPARATOR + SEARCH_JS_OUT);
}
/**
* build error_code adoc
*
* @param config api config
* @param template template
* @param outPutFileName output file
*/
public void buildErrorCodeDoc(ApiConfig config, String template, String outPutFileName) {
List<ApiErrorCode> errorCodeList = DocUtil.errorCodeDictToList(config);
String strTime = DateTimeUtil.long2Str(now, DateTimeUtil.DATE_FORMAT_SECOND);
Template tpl = BeetlTemplateUtil.getByName(template);
setCssCDN(config, tpl);
tpl.binding(TemplateVariable.CREATE_TIME.getVariable(), strTime);
tpl.binding(TemplateVariable.LIST.getVariable(), errorCodeList);
FileUtil.nioWriteFile(tpl.render(), config.getOutPath() + FILE_SEPARATOR + outPutFileName);
}
/**
* build error_code html
*
* @param config api config
* @param javaProjectBuilder javaProjectBuilder
* @param apiDocList list data of Api doc
* @param template template
* @param outPutFileName output file
* @param indexAlias index alias
*/
public void buildErrorCodeDoc(ApiConfig config, JavaProjectBuilder javaProjectBuilder,
List<ApiDoc> apiDocList, String template, String outPutFileName, String indexAlias) {
List<ApiErrorCode> errorCodeList = DocUtil.errorCodeDictToList(config);
String strTime = DateTimeUtil.long2Str(now, DateTimeUtil.DATE_FORMAT_SECOND);
Template errorTemplate = BeetlTemplateUtil.getByName(template);
errorTemplate.binding(TemplateVariable.PROJECT_NAME.getVariable(), config.getProjectName());
String style = config.getStyle();
errorTemplate.binding(TemplateVariable.HIGH_LIGHT_CSS_LINK.getVariable(), config.getHighlightStyleLink());
errorTemplate.binding(TemplateVariable.STYLE.getVariable(), style);
if (CollectionUtil.isEmpty(errorCodeList)) {
errorTemplate.binding(TemplateVariable.DICT_ORDER.getVariable(), apiDocList.size() + 1);
} else {
errorTemplate.binding(TemplateVariable.DICT_ORDER.getVariable(), apiDocList.size() + 2);
}
// set css cdn
setCssCDN(config, errorTemplate);
List<ApiDocDict> apiDocDictList = DocUtil.buildDictionary(config, javaProjectBuilder);
errorTemplate.binding(TemplateVariable.CREATE_TIME.getVariable(), strTime);
errorTemplate.binding(TemplateVariable.VERSION.getVariable(), now);
errorTemplate.binding(TemplateVariable.DICT_LIST.getVariable(), apiDocDictList);
errorTemplate.binding(TemplateVariable.INDEX_ALIAS.getVariable(), indexAlias);
errorTemplate.binding(TemplateVariable.API_DOC_LIST.getVariable(), apiDocList);
errorTemplate.binding(TemplateVariable.BACKGROUND.getVariable(), HighlightStyle.getBackgroundColor(style));
errorTemplate.binding(TemplateVariable.ERROR_CODE_LIST.getVariable(), errorCodeList);
setDirectoryLanguageVariable(config, errorTemplate);
FileUtil.nioWriteFile(errorTemplate.render(), config.getOutPath() + FILE_SEPARATOR + outPutFileName);
}
/**
* build common_data doc
*
* @param config api config
* @param javaProjectBuilder JavaProjectBuilder
* @param apiDocList list data of Api doc
* @param template template
* @param outPutFileName output file
* @param indexAlias index alias
*/
public void buildDirectoryDataDoc(ApiConfig config, JavaProjectBuilder javaProjectBuilder, List<ApiDoc> apiDocList,
String template, String outPutFileName, String indexAlias) {
List<ApiDocDict> directoryList = DocUtil.buildDictionary(config, javaProjectBuilder);
Template mapper = BeetlTemplateUtil.getByName(template);
String strTime = DateTimeUtil.long2Str(now, DateTimeUtil.DATE_FORMAT_SECOND);
mapper.binding(TemplateVariable.PROJECT_NAME.getVariable(), config.getProjectName());
String style = config.getStyle();
mapper.binding(TemplateVariable.HIGH_LIGHT_CSS_LINK.getVariable(), config.getHighlightStyleLink());
mapper.binding(TemplateVariable.STYLE.getVariable(), style);
List<ApiErrorCode> errorCodeList = DocUtil.errorCodeDictToList(config);
// set css cdn
setCssCDN(config, mapper);
if (DocLanguage.CHINESE.equals(config.getLanguage())) {
mapper.binding(TemplateVariable.CSS_CND.getVariable(), CSS_CDN_CH);
} else {
mapper.binding(TemplateVariable.CSS_CND.getVariable(), CSS_CDN);
}
if (CollectionUtil.isNotEmpty(errorCodeList)) {
mapper.binding(TemplateVariable.DICT_ORDER.getVariable(), apiDocList.size() + 2);
} else {
mapper.binding(TemplateVariable.DICT_ORDER.getVariable(), apiDocList.size() + 1);
}
mapper.binding(TemplateVariable.CREATE_TIME.getVariable(), strTime);
mapper.binding(TemplateVariable.VERSION.getVariable(), now);
mapper.binding(TemplateVariable.API_DOC_LIST.getVariable(), apiDocList);
mapper.binding(TemplateVariable.INDEX_ALIAS.getVariable(), indexAlias);
mapper.binding(TemplateVariable.BACKGROUND.getVariable(), HighlightStyle.getBackgroundColor(style));
mapper.binding(TemplateVariable.ERROR_CODE_LIST.getVariable(), errorCodeList);
setDirectoryLanguageVariable(config, mapper);
mapper.binding(TemplateVariable.DICT_LIST.getVariable(), directoryList);
FileUtil.nioWriteFile(mapper.render(), config.getOutPath() + FILE_SEPARATOR + outPutFileName);
}
/**
* build common_data doc
*
* @param config api config
* @param javaProjectBuilder JavaProjectBuilder
* @param template template
* @param outPutFileName output file
*/
public void buildDirectoryDataDoc(ApiConfig config, JavaProjectBuilder javaProjectBuilder, String template, String outPutFileName) {
List<ApiDocDict> directoryList = DocUtil.buildDictionary(config, javaProjectBuilder);
Template mapper = BeetlTemplateUtil.getByName(template);
setDirectoryLanguageVariable(config, mapper);
// set css cdn
setCssCDN(config, mapper);
String strTime = DateTimeUtil.long2Str(now, DateTimeUtil.DATE_FORMAT_SECOND);
mapper.binding(TemplateVariable.CREATE_TIME.getVariable(), strTime);
mapper.binding(TemplateVariable.DICT_LIST.getVariable(), directoryList);
FileUtil.nioWriteFile(mapper.render(), config.getOutPath() + FILE_SEPARATOR + outPutFileName);
}
/**
* Generate a single controller api document
*
* @param projectBuilder projectBuilder
* @param controllerName controller name
* @param template template
* @param fileExtension file extension
*/
public void buildSingleApi(ProjectDocConfigBuilder projectBuilder, String controllerName, String template, String fileExtension) {
ApiConfig config = projectBuilder.getApiConfig();
FileUtil.mkdirs(config.getOutPath());
IDocBuildTemplate<ApiDoc> docBuildTemplate = BuildTemplateFactory.getDocBuildTemplate(config.getFramework());
ApiDoc doc = docBuildTemplate.getSingleApiData(projectBuilder, controllerName);
Template mapper = BeetlTemplateUtil.getByName(template);
mapper.binding(TemplateVariable.DESC.getVariable(), doc.getDesc());
mapper.binding(TemplateVariable.NAME.getVariable(), doc.getName());
mapper.binding(TemplateVariable.LIST.getVariable(), doc.getList());
FileUtil.writeFileNotAppend(mapper.render(), config.getOutPath() + FILE_SEPARATOR + doc.getName() + fileExtension);
}
private List<ApiDoc> listOfApiData(ApiConfig config, JavaProjectBuilder javaProjectBuilder) {
this.checkAndInitForGetApiData(config);
config.setMd5EncryptedHtmlName(true);
ProjectDocConfigBuilder configBuilder = new ProjectDocConfigBuilder(config, javaProjectBuilder);
IDocBuildTemplate docBuildTemplate = BuildTemplateFactory.getDocBuildTemplate(config.getFramework());
return docBuildTemplate.getApiData(configBuilder);
}
}

View File

@ -0,0 +1,140 @@
/*
* smart-doc https://github.com/shalousun/smart-doc
*
* Copyright (C) 2018-2021 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.power.common.util.FileUtil;
import com.power.doc.factory.BuildTemplateFactory;
import com.power.doc.model.ApiConfig;
import com.power.doc.model.ApiDoc;
import com.power.doc.template.IDocBuildTemplate;
import com.power.doc.utils.BeetlTemplateUtil;
import com.thoughtworks.qdox.JavaProjectBuilder;
import org.apache.commons.lang3.StringUtils;
import org.beetl.core.Template;
import java.util.List;
import static com.power.doc.constants.DocGlobalConstants.*;
/**
* @author yu 2019/9/20.
* @since 1.7+
*/
public class HtmlApiDocBuilder {
private static final String ERROR_CODE_HTML = "error.html";
private static final String DICT_HTML = "dict.html";
private static long now = System.currentTimeMillis();
private static String INDEX_HTML = "index.html";
/**
* build controller api
*
* @param config config
*/
public static void buildApiDoc(ApiConfig config) {
JavaProjectBuilder javaProjectBuilder = new JavaProjectBuilder();
buildApiDoc(config, javaProjectBuilder);
}
/**
* Only for smart-doc maven plugin and gradle plugin.
*
* @param config ApiConfig
* @param javaProjectBuilder ProjectDocConfigBuilder
*/
public static void buildApiDoc(ApiConfig config, JavaProjectBuilder javaProjectBuilder) {
DocBuilderTemplate builderTemplate = new DocBuilderTemplate();
builderTemplate.checkAndInit(config,false);
config.setParamsDataToTree(false);
ProjectDocConfigBuilder configBuilder = new ProjectDocConfigBuilder(config, javaProjectBuilder);
IDocBuildTemplate docBuildTemplate = BuildTemplateFactory.getDocBuildTemplate(config.getFramework());
List<ApiDoc> apiDocList = docBuildTemplate.getApiData(configBuilder);
Template indexCssTemplate = BeetlTemplateUtil.getByName(ALL_IN_ONE_CSS);
FileUtil.nioWriteFile(indexCssTemplate.render(), config.getOutPath() + FILE_SEPARATOR + ALL_IN_ONE_CSS_OUT);
builderTemplate.copyJarFile("js/" + HIGH_LIGHT_JS, config.getOutPath() + FILE_SEPARATOR + HIGH_LIGHT_JS);
builderTemplate.copyJarFile("css/" + FONT_STYLE, config.getOutPath() + FILE_SEPARATOR + FONT_STYLE);
builderTemplate.copyJarFile("js/" + JQUERY, config.getOutPath() + FILE_SEPARATOR + JQUERY);
builderTemplate.copyJarFile("css/" + HIGH_LIGHT_STYLE, config.getOutPath() + FILE_SEPARATOR + HIGH_LIGHT_STYLE);
if (config.isAllInOne()) {
apiDocList = docBuildTemplate.handleApiGroup(apiDocList, config);
if (config.isCreateDebugPage()) {
INDEX_HTML = DEBUG_PAGE_ALL_TPL;
if (StringUtils.isNotEmpty(config.getAllInOneDocFileName())) {
INDEX_HTML = config.getAllInOneDocFileName();
}
builderTemplate.buildAllInOne(apiDocList, config, javaProjectBuilder, DEBUG_PAGE_ALL_TPL, INDEX_HTML);
Template mockJs = BeetlTemplateUtil.getByName(DEBUG_JS_TPL);
FileUtil.nioWriteFile(mockJs.render(), config.getOutPath() + FILE_SEPARATOR + DEBUG_JS_OUT);
} else {
if (StringUtils.isNotEmpty(config.getAllInOneDocFileName())) {
INDEX_HTML = config.getAllInOneDocFileName();
}
builderTemplate.buildAllInOne(apiDocList, config, javaProjectBuilder, ALL_IN_ONE_HTML_TPL, INDEX_HTML);
}
builderTemplate.buildSearchJs(config, javaProjectBuilder, apiDocList, SEARCH_ALL_JS_TPL);
} else {
String indexAlias;
if (config.isCreateDebugPage()) {
indexAlias = "debug";
buildDoc(builderTemplate, apiDocList, config, javaProjectBuilder, DEBUG_PAGE_SINGLE_TPL, indexAlias);
Template mockJs = BeetlTemplateUtil.getByName(DEBUG_JS_TPL);
FileUtil.nioWriteFile(mockJs.render(), config.getOutPath() + FILE_SEPARATOR + DEBUG_JS_OUT);
} else {
indexAlias = "api";
buildDoc(builderTemplate, apiDocList, config, javaProjectBuilder, SINGLE_INDEX_HTML_TPL, indexAlias);
}
builderTemplate.buildErrorCodeDoc(config, javaProjectBuilder, apiDocList, SINGLE_ERROR_HTML_TPL,
ERROR_CODE_HTML, indexAlias);
builderTemplate.buildDirectoryDataDoc(config, javaProjectBuilder, apiDocList,
SINGLE_DICT_HTML_TPL, DICT_HTML, indexAlias);
builderTemplate.buildSearchJs(config, javaProjectBuilder, apiDocList, SEARCH_JS_TPL);
}
}
/**
* build ever controller api
*
* @param builderTemplate DocBuilderTemplate
* @param apiDocList list of api doc
* @param config ApiConfig
* @param javaProjectBuilder ProjectDocConfigBuilder
* @param template template
* @param indexHtml indexHtml
*/
private static void buildDoc(DocBuilderTemplate builderTemplate, List<ApiDoc> apiDocList,
ApiConfig config, JavaProjectBuilder javaProjectBuilder,
String template, String indexHtml) {
FileUtil.mkdirs(config.getOutPath());
int index = 0;
for (ApiDoc doc : apiDocList) {
if (index == 0) {
doc.setAlias(indexHtml);
}
builderTemplate.buildDoc(apiDocList, config, javaProjectBuilder, template,
doc.getAlias() + ".html", doc, indexHtml);
index++;
}
}
}

View File

@ -0,0 +1,582 @@
/*
* smart-doc https://github.com/shalousun/smart-doc
*
* Copyright (C) 2018-2021 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.power.common.util.CollectionUtil;
import com.power.common.util.FileUtil;
import com.power.common.util.StringUtil;
import com.power.doc.constants.DocGlobalConstants;
import com.power.doc.constants.Methods;
import com.power.doc.factory.BuildTemplateFactory;
import com.power.doc.model.*;
import com.power.doc.template.IDocBuildTemplate;
import com.power.doc.utils.DocUtil;
import com.power.doc.utils.JsonUtil;
import com.thoughtworks.qdox.JavaProjectBuilder;
import java.util.*;
/**
* @author xingzi
*/
public class OpenApiBuilder {
private static final String PATH_REGEX = "[/{};\\t+]";
/**
* Build OpenApi json
*
* @param config ApiConfig
*/
public static void buildOpenApi(ApiConfig config) {
DocBuilderTemplate builderTemplate = new DocBuilderTemplate();
builderTemplate.checkAndInit(config, false);
JavaProjectBuilder javaProjectBuilder = new JavaProjectBuilder();
ProjectDocConfigBuilder configBuilder = new ProjectDocConfigBuilder(config, javaProjectBuilder);
openApiCreate(config, configBuilder);
}
/**
* Only for smart-doc maven plugin and gradle plugin.
*
* @param config ApiConfig Object
* @param projectBuilder QDOX JavaProjectBuilder
*/
public static void buildOpenApi(ApiConfig config, JavaProjectBuilder projectBuilder) {
DocBuilderTemplate builderTemplate = new DocBuilderTemplate();
builderTemplate.checkAndInit(config, false);
ProjectDocConfigBuilder configBuilder = new ProjectDocConfigBuilder(config, projectBuilder);
openApiCreate(config, configBuilder);
}
/**
* Build OpenApi
*
* @param config ApiConfig
* @param configBuilder
*/
private static void openApiCreate(ApiConfig config, ProjectDocConfigBuilder configBuilder) {
config.setParamsDataToTree(true);
IDocBuildTemplate docBuildTemplate = BuildTemplateFactory.getDocBuildTemplate(config.getFramework());
List<ApiDoc> apiDocList = docBuildTemplate.getApiData(configBuilder);
Map<String, Object> json = new HashMap<>(8);
json.put("openapi", "3.0.3");
json.put("info", buildInfo(config));
json.put("servers", buildServers(config));
json.put("paths", buildPaths(apiDocList));
json.put("components", buildComponentsSchema(apiDocList));
String filePath = config.getOutPath();
filePath = filePath + DocGlobalConstants.OPEN_API_JSON;
String data = JsonUtil.toPrettyJson(json);
FileUtil.nioWriteFile(data, filePath);
}
/**
* Build openapi info
*
* @param apiConfig ApiConfig
* @return
*/
private static Map<String, Object> buildInfo(ApiConfig apiConfig) {
Map<String, Object> infoMap = new HashMap<>(8);
infoMap.put("title", apiConfig.getProjectName() == null ? "Project Name is Null." : apiConfig.getProjectName());
infoMap.put("version", "1.0.0");
return infoMap;
}
/**
* Build Servers
*
* @param config ApiConfig
* @return
*/
private static List<Map<String, Object>> buildServers(ApiConfig config) {
List<Map<String, Object>> serverList = new ArrayList<>();
Map<String, Object> serverMap = new HashMap<>(8);
serverMap.put("url", config.getServerUrl() == null ? "" : config.getServerUrl());
serverList.add(serverMap);
return serverList;
}
/**
* Build openapi paths
*
* @param apiDocList List of api
* @return
*/
private static Map<String, Object> buildPaths(List<ApiDoc> apiDocList) {
Map<String, Object> pathMap = new HashMap<>(500);
apiDocList.forEach(
a -> {
List<ApiMethodDoc> apiMethodDocs = a.getList();
apiMethodDocs.forEach(
method -> {
//replace '//' to '/'
String url = method.getPath().replace("//", "/");
Map<String, Object> request = buildPathUrls(method, a);
//pathMap.put(method.getPath().replace("//", "/"), buildPathUrls(method, a));
if (!pathMap.containsKey(url)) {
pathMap.put(url, request);
} else {
Map<String, Object> oldRequest = (Map<String, Object>) pathMap.get(url);
oldRequest.putAll(request);
}
}
);
}
);
return pathMap;
}
/**
* Build path urls
*
* @param apiMethodDoc Method
* @param apiDoc ApiDoc
* @return
*/
private static Map<String, Object> buildPathUrls(ApiMethodDoc apiMethodDoc, ApiDoc apiDoc) {
Map<String, Object> request = new HashMap<>(4);
request.put(apiMethodDoc.getType().toLowerCase(), buildPathUrlsRequest(apiMethodDoc, apiDoc));
return request;
}
/**
* url的基本信息 信息简介summary 详情description 所属分类tags 请求参数parameter 请求体request 返回值responses
*
* @param apiMethodDoc 方法参数
* @param apiDoc 类参数
* @return
*/
private static Map<String, Object> buildPathUrlsRequest(ApiMethodDoc apiMethodDoc, ApiDoc apiDoc) {
Map<String, Object> request = new HashMap<>(20);
request.put("summary", apiMethodDoc.getDesc());
request.put("description", apiMethodDoc.getDetail());
if (StringUtil.isNotEmpty(apiMethodDoc.getGroup())) {
request.put("tags", new String[]{apiMethodDoc.getGroup()});
} else {
request.put("tags", new String[]{apiDoc.getDesc()});
}
request.put("requestBody", buildRequestBody(apiMethodDoc));
request.put("parameters", buildParameters(apiMethodDoc));
request.put("responses", buildResponses(apiMethodDoc));
request.put("deprecated", apiMethodDoc.isDeprecated());
request.put("operationId", apiMethodDoc.getMethodId());
return request;
}
/**
* Build request body
*
* @param apiMethodDoc ApiMethodDoc
* @return
*/
private static Map<String, Object> buildRequestBody(ApiMethodDoc apiMethodDoc) {
Map<String, Object> requestBody = new HashMap<>(8);
boolean isPost = (apiMethodDoc.getType().equals(Methods.POST.getValue())
|| apiMethodDoc.getType().equals(Methods.PUT.getValue()) ||
apiMethodDoc.getType().equals(Methods.PATCH.getValue()));
//add content of post method
if (isPost) {
requestBody.put("content", buildContent(apiMethodDoc, false));
return requestBody;
}
return null;
}
/**
* 构建content信息 responses requestBody 都需要content信息
*
* @param apiMethodDoc 方法参数
* @param isRep 是否是返回数据
* @return
*/
private static Map<String, Object> buildContent(ApiMethodDoc apiMethodDoc, boolean isRep) {
Map<String, Object> content = new HashMap<>(8);
String contentType = apiMethodDoc.getContentType();
if (isRep) {
contentType = "*/*";
}
content.put(contentType, buildContentBody(apiMethodDoc, isRep));
return content;
}
/**
* 构建content的数据内容
*
* @param apiMethodDoc 方法参数
* @param isRep 是否是返回数据
* @return
*/
private static Map<String, Object> buildContentBody(ApiMethodDoc apiMethodDoc, boolean isRep) {
Map<String, Object> content = new HashMap<>(8);
if (Objects.nonNull(apiMethodDoc.getReturnSchema()) && isRep) {
content.put("schema", apiMethodDoc.getReturnSchema());
} else {
if (!isRep && apiMethodDoc.getContentType().equals(DocGlobalConstants.MULTIPART_TYPE)) {
// formdata
Map<String, Object> map = new LinkedHashMap<>();
map.put("type", "object");
Map<String, Object> properties = new LinkedHashMap<>();
Map<String, Object> detail;
for (ApiParam apiParam : apiMethodDoc.getQueryParams()) {
detail = new HashMap<>();
detail.put("type", apiParam.getType());
detail.put("description", apiParam.getDesc());
detail.put("example", DocUtil.handleJsonStr(apiParam.getValue()));
if ("file".equals(apiParam.getType())) {
detail.remove("example");
if (apiParam.isHasItems()) {
detail.put("type", "array");
Map<String, Object> items = new HashMap<>();
items.put("type", "string");
items.put("format", "binary");
detail.put("items", items);
} else {
detail.put("format", "binary");
detail.put("type", "string");
}
}
properties.put(apiParam.getField(), detail);
}
map.put("properties", properties);
content.put("schema", map);
} else if (!isRep && Objects.nonNull(apiMethodDoc.getRequestSchema())) {
content.put("schema", apiMethodDoc.getRequestSchema());
} else {
content.put("schema", buildBodySchema(apiMethodDoc, isRep));
}
}
content.put("examples", buildBodyExample(apiMethodDoc, isRep));
return content;
}
/**
* content body 的schema 信息
*
* @param apiMethodDoc 请求方法参数 去除server
* @param isRep 是否是返回数据
* @return
*/
private static Map<String, Object> buildBodySchema(ApiMethodDoc apiMethodDoc, boolean isRep) {
Map<String, Object> schema = new HashMap<>(10);
//当类型为数组时使用
Map<String, Object> innerScheme = new HashMap<>(10);
//去除url中的特殊字符
String responseRef = "#/components/schemas/" + apiMethodDoc.getPath().replaceAll(PATH_REGEX, "_") + "response";
String requestRef = "#/components/schemas/" + apiMethodDoc.getPath().replaceAll(PATH_REGEX, "_") + "request";
//如果是数组类型
if (apiMethodDoc.isListParam()) {
schema.put("type", DocGlobalConstants.ARRAY);
if (isRep) {
innerScheme.put("$ref", responseRef);
} else {
innerScheme.put("$ref", requestRef);
}
schema.put("items", innerScheme);
} else {
if (isRep) {
schema.put("$ref", responseRef);
} else {
schema.put("$ref", requestRef);
}
}
return schema;
}
/**
* 信息样例 请求和返回的信息样例
*
* @param apiMethodDoc 方法参数
* @param isRep 是否是返回数据
* @return
*/
private static Map<String, Object> buildBodyExample(ApiMethodDoc apiMethodDoc, boolean isRep) {
Map<String, Object> content = new HashMap<>(8);
content.put("json", buildExampleData(apiMethodDoc, isRep));
return content;
}
/**
* 信息样例数据构建 此处请求体requestBody构建完成
*
* @param apiMethodDoc 方法参数
* @param isRep 是否为返回数据
* @return
*/
private static Map<String, Object> buildExampleData(ApiMethodDoc apiMethodDoc, boolean isRep) {
Map<String, Object> content = new HashMap<>(8);
content.put("summary", "test data");
if (!isRep) {
content.put("value", StringUtil.isEmpty(
apiMethodDoc.getRequestExample().getJsonBody()) ? apiMethodDoc.getRequestExample().getExampleBody() :
apiMethodDoc.getRequestExample().getJsonBody());
} else {
content.put("value", apiMethodDoc.getResponseUsage());
}
return content;
}
/**
* 构建请求参数 用于get请求 @PathVariable Header 参数构建
*
* @param apiMethodDoc 方法体
* @return
*/
private static List<Map<String, Object>> buildParameters(ApiMethodDoc apiMethodDoc) {
Map<String, Object> parameters;
List<Map<String, Object>> parametersList = new ArrayList<>();
for (ApiParam apiParam : apiMethodDoc.getPathParams()) {
parameters = getStringParams(apiParam);
parameters.put("in", "path");
List<ApiParam> children = apiParam.getChildren();
if (CollectionUtil.isEmpty(children)) {
parametersList.add(parameters);
}
}
// not handle form data
if (!apiMethodDoc.getContentType().equals(DocGlobalConstants.MULTIPART_TYPE)) {
for (ApiParam apiParam : apiMethodDoc.getQueryParams()) {
parameters = getStringParams(apiParam);
parameters.put("in", "query");
List<ApiParam> children = apiParam.getChildren();
if (CollectionUtil.isEmpty(children)) {
parametersList.add(parameters);
}
}
}
//如果包含请求头
if (!CollectionUtil.isEmpty(apiMethodDoc.getRequestHeaders())) {
for (ApiReqParam header : apiMethodDoc.getRequestHeaders()) {
parameters = new HashMap<>(20);
parameters.put("name", header.getName());
parameters.put("description", header.getDesc());
parameters.put("required", header.isRequired());
parameters.put("example", header.getValue());
parameters.put("schema", buildParametersSchema(header));
parameters.put("in", "header");
parametersList.add(parameters);
}
}
return parametersList;
}
private static Map<String, Object> getStringParams(ApiParam apiParam) {
Map<String, Object> parameters;
parameters = new HashMap<>(20);
parameters.put("name", apiParam.getField());
parameters.put("description", apiParam.getDesc());
parameters.put("required", apiParam.isRequired());
parameters.put("example", StringUtil.removeQuotes(apiParam.getValue()));
parameters.put("schema", buildParametersSchema(apiParam));
return parameters;
}
/**
* 如果是get请求或者是@PathVariable 设置请求参数
*
* @param apiParam 参数信息
* @return
*/
private static Map<String, Object> buildParametersSchema(ApiParam apiParam) {
Map<String, Object> schema = new HashMap<>(10);
String openApiType = DocUtil.javaTypeToOpenApiTypeConvert(apiParam.getType());
schema.put("type", openApiType);
if ("object".equals(openApiType) || "string".equals(openApiType)) {
if ("file".equals(apiParam.getType())) {
schema.put("format", "binary");
} else if ("enum".equals(apiParam.getType())) {
schema.put("enum", apiParam.getEnumValues());
}else if("array".equals(apiParam.getType())) {
schema.put("type","array");
schema.put("items",new HashMap<>());
}
} else {
schema.put("format", "int16".equals(apiParam.getType()) ? "int32" : apiParam.getType());
}
return schema;
}
/**
* 如果包含header 设置请求参数
*
* @param header 参数信息
* @return
*/
private static Map<String, Object> buildParametersSchema(ApiReqParam header) {
Map<String, Object> schema = new HashMap<>(10);
String openApiType = DocUtil.javaTypeToOpenApiTypeConvert(header.getType());
schema.put("type", openApiType);
schema.put("format", "int16".equals(header.getType()) ? "int32" : header.getType());
return schema;
}
/**
* build response
*
* @param apiMethodDoc ApiMethodDoc
* @return
*/
private static Map<String, Object> buildResponses(ApiMethodDoc apiMethodDoc) {
Map<String, Object> response = new HashMap<>(10);
response.put("200", buildResponsesBody(apiMethodDoc));
return response;
}
/**
* response body
*
* @param apiMethodDoc ApiMethodDoc
* @return
*/
private static Map<String, Object> buildResponsesBody(ApiMethodDoc apiMethodDoc) {
Map<String, Object> responseBody = new HashMap<>(10);
responseBody.put("description", "OK");
responseBody.put("content", buildContent(apiMethodDoc, true));
return responseBody;
}
/**
* component schema
*
* @param apiDocs List of ApiDoc
* @return
*/
private static Map<String, Object> buildComponentsSchema(List<ApiDoc> apiDocs) {
Map<String, Object> schemas = new HashMap<>(4);
Map<String, Object> component = new HashMap<>();
apiDocs.forEach(
a -> {
List<ApiMethodDoc> apiMethodDocs = a.getList();
apiMethodDocs.forEach(
method -> {
//request components
List<ApiParam> requestParams = method.getRequestParams();
if (CollectionUtil.isNotEmpty(requestParams)) {
Map<String, Object> prop = buildProperties(requestParams);
if (Objects.nonNull(prop) && prop.size() > 0) {
component.put(method.getPath().replaceAll(PATH_REGEX, "_") + "request", buildProperties(requestParams));
}
} else {
component.put(method.getPath().replaceAll(PATH_REGEX, "_") + "request", new HashMap<>(0));
}
//response components
List<ApiParam> responseParams = method.getResponseParams();
component.put(method.getPath().replaceAll(PATH_REGEX, "_") + "response", buildProperties(responseParams));
}
);
}
);
schemas.put("schemas", component);
return schemas;
}
/**
* component schema properties
*
* @param apiParam list of ApiParam
* @return
*/
private static Map<String, Object> buildProperties(List<ApiParam> apiParam) {
Map<String, Object> component = new HashMap<>();
Map<String, Object> propertiesData = new LinkedHashMap<>();
List<String> requiredList = new ArrayList<>();
if (apiParam != null) {
int paramsSize = apiParam.size();
for (ApiParam param : apiParam) {
if (param.isRequired()) {
requiredList.add(param.getField());
}
if (param.getType().equals("map") && paramsSize == 1) {
continue;
}
if (param.isQueryParam() || param.isPathParam()) {
continue;
}
String field = param.getField();
propertiesData.put(field, buildPropertiesData(param));
}
if (!propertiesData.isEmpty()) {
component.put("properties", propertiesData);
}
if (!CollectionUtil.isEmpty(requiredList)) {
component.put("required", requiredList);
}
return component;
} else {
return null;
}
}
/**
* component schema properties data
*
* @param apiParam ApiParam
* @return
*/
private static Map<String, Object> buildPropertiesData(ApiParam apiParam) {
Map<String, Object> propertiesData = new HashMap<>();
String openApiType = DocUtil.javaTypeToOpenApiTypeConvert(apiParam.getType());
//array object file map
propertiesData.put("description", apiParam.getDesc());
if (!"object".equals(openApiType)) {
propertiesData.put("type", openApiType);
propertiesData.put("format", "int16".equals(apiParam.getType()) ? "int32" : apiParam.getType());
}
if ("map".equals(apiParam.getType())) {
propertiesData.put("type", "object");
propertiesData.put("description", apiParam.getDesc() + "(map data)");
}
if ("object".equals(apiParam.getType())) {
if (apiParam.getChildren() != null) {
propertiesData.put("type", "object");
propertiesData.put("description", apiParam.getDesc() + "(object)");
propertiesData.put("properties", buildProperties(apiParam.getChildren()).get("properties"));
propertiesData.put("requires", buildProperties(apiParam.getChildren()).get("requires"));
}
}
if ("array".equals(apiParam.getType())) {
if (apiParam.getChildren() != null) {
propertiesData.put("type", "array");
propertiesData.put("items", buildProperties(apiParam.getChildren()));
}
}
if ("file".equals(apiParam.getType())) {
propertiesData.put("type", "string");
propertiesData.put("format", "binary");
}
return propertiesData;
}
}

View File

@ -0,0 +1,239 @@
/*
* smart-doc https://github.com/shalousun/smart-doc
*
* Copyright (C) 2018-2021 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.power.common.util.CollectionUtil;
import com.power.common.util.FileUtil;
import com.power.common.util.StringUtil;
import com.power.doc.constants.DocGlobalConstants;
import com.power.doc.factory.BuildTemplateFactory;
import com.power.doc.model.*;
import com.power.doc.model.postman.InfoBean;
import com.power.doc.model.postman.ItemBean;
import com.power.doc.model.postman.RequestItem;
import com.power.doc.model.postman.UrlBean;
import com.power.doc.model.postman.request.ParamBean;
import com.power.doc.model.postman.request.RequestBean;
import com.power.doc.model.postman.request.body.BodyBean;
import com.power.doc.model.postman.request.header.HeaderBean;
import com.power.doc.template.IDocBuildTemplate;
import com.power.doc.utils.DocPathUtil;
import com.power.doc.utils.JsonUtil;
import com.thoughtworks.qdox.JavaProjectBuilder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
/**
* @author yu 2019/11/21.
*/
public class PostmanJsonBuilder {
private static final String MSG = "Interface name is not set.";
/**
* build postman json
*
* @param config Smart-doc ApiConfig
*/
public static void buildPostmanCollection(ApiConfig config) {
DocBuilderTemplate builderTemplate = new DocBuilderTemplate();
builderTemplate.checkAndInit(config,false);
JavaProjectBuilder javaProjectBuilder = new JavaProjectBuilder();
ProjectDocConfigBuilder configBuilder = new ProjectDocConfigBuilder(config, javaProjectBuilder);
postManCreate(config, configBuilder);
}
/**
* Only for smart-doc maven plugin and gradle plugin.
*
* @param config ApiConfig Object
* @param projectBuilder QDOX avaProjectBuilder
*/
public static void buildPostmanCollection(ApiConfig config, JavaProjectBuilder projectBuilder) {
DocBuilderTemplate builderTemplate = new DocBuilderTemplate();
builderTemplate.checkAndInit(config,false);
config.setParamsDataToTree(false);
ProjectDocConfigBuilder configBuilder = new ProjectDocConfigBuilder(config, projectBuilder);
postManCreate(config, configBuilder);
}
/**
* Build the first layer of Postman Item
*
* @param apiDoc Documentation for each Controller
* @return First layer of Postman Item
*/
private static ItemBean buildItemBean(ApiDoc apiDoc) {
ItemBean itemBean = new ItemBean();
itemBean.setName(StringUtil.isEmpty(apiDoc.getDesc()) ? MSG : apiDoc.getDesc());
List<ItemBean> itemBeans = new ArrayList<>();
List<ApiMethodDoc> apiMethodDocs = apiDoc.getList();
apiMethodDocs.forEach(
apiMethodDoc -> {
ItemBean itemBean1 = buildItem(apiMethodDoc);
itemBeans.add(itemBean1);
}
);
itemBean.setItem(itemBeans);
return itemBean;
}
/**
* Build the second layer of Postman item
*
* @param apiMethodDoc Documentation for each method
* @return The second layer of Postman item
*/
private static ItemBean buildItem(ApiMethodDoc apiMethodDoc) {
ItemBean item = new ItemBean();
RequestBean requestBean = new RequestBean();
item.setName(StringUtil.isEmpty(apiMethodDoc.getDesc()) ? MSG : apiMethodDoc.getDesc());
item.setDescription(apiMethodDoc.getDetail());
requestBean.setDescription(apiMethodDoc.getDesc());
requestBean.setMethod(apiMethodDoc.getType());
requestBean.setHeader(buildHeaderBeanList(apiMethodDoc));
requestBean.setBody(buildBodyBean(apiMethodDoc));
requestBean.setUrl(buildUrlBean(apiMethodDoc));
item.setRequest(requestBean);
return item;
}
private static UrlBean buildUrlBean(ApiMethodDoc apiMethodDoc) {
UrlBean urlBean = new UrlBean(apiMethodDoc.getServerUrl());
String url = Optional.ofNullable(apiMethodDoc.getRequestExample().getUrl()).orElse(apiMethodDoc.getUrl());
urlBean.setRaw(DocPathUtil.toPostmanPath(url));
String shortUrl = DocPathUtil.toPostmanPath(apiMethodDoc.getPath());
String[] paths = shortUrl.split("/");
List<String> pathList = new ArrayList<>();
String serverPath = CollectionUtil.isNotEmpty(urlBean.getPath()) ? urlBean.getPath().get(0) : "";
// Add server path
if (CollectionUtil.isNotEmpty(urlBean.getPath()) && !shortUrl.contains(serverPath)) {
String[] serverPaths = serverPath.split("/");
pathList.addAll(Arrays.asList(serverPaths));
}
// Add mapping path
for (String str : paths) {
if (StringUtil.isNotEmpty(str)) {
pathList.add(str);
}
}
if (shortUrl.endsWith("/")) {
pathList.add("");
}
urlBean.setPath(pathList);
List<ParamBean> queryParams = new ArrayList<>();
for (ApiParam apiParam : apiMethodDoc.getQueryParams()) {
ParamBean queryParam = new ParamBean();
queryParam.setDescription(apiParam.getDesc());
queryParam.setKey(apiParam.getField());
queryParam.setValue(apiParam.getValue());
queryParams.add(queryParam);
}
List<ParamBean> variables = new ArrayList<>();
for (ApiParam apiParam : apiMethodDoc.getPathParams()) {
ParamBean queryParam = new ParamBean();
queryParam.setDescription(apiParam.getDesc());
queryParam.setKey(apiParam.getField());
queryParam.setValue(apiParam.getValue());
variables.add(queryParam);
}
urlBean.setVariable(variables);
urlBean.setQuery(queryParams);
return urlBean;
}
/**
* Build payload
*
* @return Body payload
*/
private static BodyBean buildBodyBean(ApiMethodDoc apiMethodDoc) {
BodyBean bodyBean;
if (apiMethodDoc.getContentType().contains(DocGlobalConstants.JSON_CONTENT_TYPE)) {
bodyBean = new BodyBean(Boolean.FALSE);// Json request
bodyBean.setMode(DocGlobalConstants.POSTMAN_MODE_RAW);
if (apiMethodDoc.getRequestExample() != null) {
bodyBean.setRaw(apiMethodDoc.getRequestExample().getJsonBody());
}
} else {
bodyBean = new BodyBean(Boolean.TRUE); //Formdata
bodyBean.setMode(DocGlobalConstants.POSTMAN_MODE_FORMDATA);
bodyBean.setFormdata(apiMethodDoc.getRequestExample().getFormDataList());
}
return bodyBean;
}
/**
* Build header
*
* @return List of header
*/
private static List<HeaderBean> buildHeaderBeanList(ApiMethodDoc apiMethodDoc) {
List<HeaderBean> headerBeans = new ArrayList<>();
List<ApiReqParam> headers = apiMethodDoc.getRequestHeaders();
headers.forEach(
apiReqHeader -> {
HeaderBean headerBean = new HeaderBean();
headerBean.setKey(apiReqHeader.getName());
headerBean.setName(apiReqHeader.getName());
headerBean.setValue(apiReqHeader.getValue());
headerBean.setDisabled(!apiReqHeader.isRequired());
headerBean.setDescription(apiReqHeader.getDesc());
headerBeans.add(headerBean);
}
);
return headerBeans;
}
private static void postManCreate(ApiConfig config, ProjectDocConfigBuilder configBuilder) {
IDocBuildTemplate docBuildTemplate = BuildTemplateFactory.getDocBuildTemplate(config.getFramework());
List<ApiDoc> apiDocList = docBuildTemplate.getApiData(configBuilder);
RequestItem requestItem = new RequestItem();
requestItem.setInfo(new InfoBean(config.getProjectName()));
List<ItemBean> itemBeans = new ArrayList<>();
apiDocList.forEach(
apiDoc -> {
ItemBean itemBean = buildItemBean(apiDoc);
itemBeans.add(itemBean);
}
);
requestItem.setItem(itemBeans);
String filePath = config.getOutPath();
filePath = filePath + DocGlobalConstants.POSTMAN_JSON;
String data = JsonUtil.toPrettyJson(requestItem);
FileUtil.nioWriteFile(data, filePath);
}
}

View File

@ -0,0 +1,264 @@
/*
* smart-doc https://github.com/shalousun/smart-doc
*
* Copyright (C) 2018-2021 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.power.common.constants.Charset;
import com.power.common.util.CollectionUtil;
import com.power.common.util.StringUtil;
import com.power.doc.constants.DocGlobalConstants;
import com.power.doc.constants.HighlightStyle;
import com.power.doc.model.*;
import com.power.doc.utils.JavaClassUtil;
import com.thoughtworks.qdox.JavaProjectBuilder;
import com.thoughtworks.qdox.model.JavaClass;
import java.io.File;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Logger;
import static com.power.doc.constants.DocGlobalConstants.DEFAULT_SERVER_URL;
/**
* @author yu 2019/12/21.
*/
public class ProjectDocConfigBuilder {
private static Logger log = Logger.getLogger(ProjectDocConfigBuilder.class.getName());
private JavaProjectBuilder javaProjectBuilder;
private Map<String, JavaClass> classFilesMap = new ConcurrentHashMap<>();
private Map<String, CustomField> customRespFieldMap = new ConcurrentHashMap<>();
private Map<String, CustomField> customReqFieldMap = new ConcurrentHashMap<>();
private Map<String, String> replaceClassMap = new ConcurrentHashMap<>();
private Map<String, String> constantsMap = new ConcurrentHashMap<>();
private String serverUrl;
private ApiConfig apiConfig;
public ProjectDocConfigBuilder(ApiConfig apiConfig, JavaProjectBuilder javaProjectBuilder) {
if (null == apiConfig) {
throw new NullPointerException("ApiConfig can't be null.");
}
this.apiConfig = apiConfig;
if (Objects.isNull(javaProjectBuilder)) {
javaProjectBuilder = new JavaProjectBuilder();
}
if (StringUtil.isEmpty(apiConfig.getServerUrl())) {
this.serverUrl = DEFAULT_SERVER_URL;
} else {
this.serverUrl = apiConfig.getServerUrl();
}
this.setHighlightStyle();
javaProjectBuilder.setEncoding(Charset.DEFAULT_CHARSET);
this.javaProjectBuilder = javaProjectBuilder;
try {
this.loadJavaSource(apiConfig.getSourceCodePaths(), this.javaProjectBuilder);
} catch (Exception e) {
log.warning(e.getMessage());
}
this.initClassFilesMap();
this.initCustomResponseFieldsMap(apiConfig);
this.initCustomRequestFieldsMap(apiConfig);
this.initReplaceClassMap(apiConfig);
this.initConstants(apiConfig);
this.checkBodyAdvice(apiConfig.getRequestBodyAdvice());
this.checkBodyAdvice(apiConfig.getResponseBodyAdvice());
}
public JavaClass getClassByName(String simpleName) {
JavaClass cls = javaProjectBuilder.getClassByName(simpleName);
List<DocJavaField> fieldList = JavaClassUtil.getFields(cls, 0, new LinkedHashMap<>());
// handle inner class
if (Objects.isNull(cls.getFields()) || fieldList.isEmpty()) {
cls = classFilesMap.get(simpleName);
} else {
List<JavaClass> classList = cls.getNestedClasses();
for (JavaClass javaClass : classList) {
classFilesMap.put(javaClass.getFullyQualifiedName(), javaClass);
}
}
return cls;
}
private void loadJavaSource(List<SourceCodePath> paths, JavaProjectBuilder builder) {
if (CollectionUtil.isEmpty(paths)) {
builder.addSourceTree(new File(DocGlobalConstants.PROJECT_CODE_PATH));
} else {
for (SourceCodePath path : paths) {
if (null == path) {
continue;
}
String strPath = path.getPath();
if (StringUtil.isNotEmpty(strPath)) {
strPath = strPath.replace("\\", "/");
builder.addSourceTree(new File(strPath));
}
}
}
}
private void initClassFilesMap() {
Collection<JavaClass> javaClasses = javaProjectBuilder.getClasses();
for (JavaClass cls : javaClasses) {
classFilesMap.put(cls.getFullyQualifiedName(), cls);
}
}
private void initCustomResponseFieldsMap(ApiConfig config) {
if (CollectionUtil.isNotEmpty(config.getCustomResponseFields())) {
for (CustomField field : config.getCustomResponseFields()) {
customRespFieldMap.put(field.getOwnerClassName() + "." + field.getName(), field);
}
}
}
private void initCustomRequestFieldsMap(ApiConfig config) {
if (CollectionUtil.isNotEmpty(config.getCustomRequestFields())) {
for (CustomField field : config.getCustomRequestFields()) {
customReqFieldMap.put(field.getOwnerClassName() + "." + field.getName(), field);
}
}
}
private void initReplaceClassMap(ApiConfig config) {
if (CollectionUtil.isNotEmpty(config.getApiObjectReplacements())) {
for (ApiObjectReplacement replace : config.getApiObjectReplacements()) {
replaceClassMap.put(replace.getClassName(), replace.getReplacementClassName());
}
}
}
private void initConstants(ApiConfig config) {
List<ApiConstant> apiConstants;
if (CollectionUtil.isEmpty(config.getApiConstants())) {
apiConstants = new ArrayList<>();
} else {
apiConstants = config.getApiConstants();
}
try {
for (ApiConstant apiConstant : apiConstants) {
Class<?> clzz = apiConstant.getConstantsClass();
if (Objects.isNull(clzz)) {
if (StringUtil.isEmpty(apiConstant.getConstantsClassName())) {
throw new RuntimeException("Enum class name can't be null.");
}
clzz = Class.forName(apiConstant.getConstantsClassName());
}
constantsMap.putAll(JavaClassUtil.getFinalFieldValue(clzz));
}
} catch (ClassNotFoundException | IllegalAccessException e) {
e.printStackTrace();
}
}
private void checkBodyAdvice(BodyAdvice bodyAdvice) {
if (Objects.nonNull(bodyAdvice) && StringUtil.isNotEmpty(bodyAdvice.getClassName())) {
if (Objects.nonNull(bodyAdvice.getWrapperClass())) {
return;
}
try {
Class.forName(bodyAdvice.getClassName());
} catch (ClassNotFoundException e) {
throw new RuntimeException("Can't find class " + bodyAdvice.getClassName() + " for ResponseBodyAdvice.");
}
}
}
private void setHighlightStyle() {
String style = apiConfig.getStyle();
if (DocGlobalConstants.HIGH_LIGHT_DEFAULT_STYLE.equals(style)) {
// use local css file
apiConfig.setHighlightStyleLink(DocGlobalConstants.HIGH_LIGHT_CSS_DEFAULT);
return;
}
if (HighlightStyle.containsStyle(style)) {
apiConfig.setHighlightStyleLink(String.format(DocGlobalConstants.HIGH_LIGHT_CSS_URL_FORMAT, style));
return;
}
Random random = new Random();
if (DocGlobalConstants.HIGH_LIGHT_CSS_RANDOM_LIGHT.equals(style)) {
// Eliminate styles that do not match the template
style = HighlightStyle.randomLight(random);
if (HighlightStyle.containsStyle(style)) {
apiConfig.setStyle(style);
apiConfig.setHighlightStyleLink(String.format(DocGlobalConstants.HIGH_LIGHT_CSS_URL_FORMAT, style));
} else {
apiConfig.setStyle(null);
}
} else if (DocGlobalConstants.HIGH_LIGHT_CSS_RANDOM_DARK.equals(style)) {
style = HighlightStyle.randomDark(random);
if (DocGlobalConstants.HIGH_LIGHT_DEFAULT_STYLE.equals(style)) {
apiConfig.setHighlightStyleLink(DocGlobalConstants.HIGH_LIGHT_CSS_DEFAULT);
} else {
apiConfig.setHighlightStyleLink(String.format(DocGlobalConstants.HIGH_LIGHT_CSS_URL_FORMAT, style));
}
apiConfig.setStyle(style);
} else {
// Eliminate styles that do not match the template
apiConfig.setStyle(null);
}
}
public JavaProjectBuilder getJavaProjectBuilder() {
return javaProjectBuilder;
}
public Map<String, JavaClass> getClassFilesMap() {
return classFilesMap;
}
public Map<String, CustomField> getCustomRespFieldMap() {
return customRespFieldMap;
}
public Map<String, CustomField> getCustomReqFieldMap() {
return customReqFieldMap;
}
public String getServerUrl() {
return serverUrl;
}
public ApiConfig getApiConfig() {
return apiConfig;
}
public Map<String, String> getReplaceClassMap() {
return replaceClassMap;
}
public Map<String, String> getConstantsMap() {
return constantsMap;
}
}

View File

@ -0,0 +1,143 @@
/*
* smart-doc https://github.com/shalousun/smart-doc
*
* Copyright (C) 2018-2021 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.power.common.util.CollectionUtil;
import com.power.common.util.OkHttp3Util;
import com.power.common.util.StringUtil;
import com.power.doc.constants.TornaConstants;
import com.power.doc.factory.BuildTemplateFactory;
import com.power.doc.model.ApiConfig;
import com.power.doc.model.ApiDoc;
import com.power.doc.model.torna.Apis;
import com.power.doc.model.torna.TornaApi;
import com.power.doc.model.torna.TornaDic;
import com.power.doc.template.IDocBuildTemplate;
import com.power.doc.utils.DocUtil;
import com.power.doc.utils.TornaUtil;
import com.thoughtworks.qdox.JavaProjectBuilder;
import org.apache.commons.lang3.StringUtils;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static com.power.doc.constants.TornaConstants.ENUM_PUSH;
import static com.power.doc.constants.TornaConstants.PUSH;
import static com.power.doc.utils.TornaUtil.buildApis;
import static com.power.doc.utils.TornaUtil.buildErrorCode;
/**
* @author xingzi 2021/2/2 18:05
**/
public class TornaBuilder {
/**
* build controller api
*
* @param config config
*/
public static void buildApiDoc(ApiConfig config) {
JavaProjectBuilder javaProjectBuilder = new JavaProjectBuilder();
buildApiDoc(config, javaProjectBuilder);
}
/**
* Only for smart-doc maven plugin and gradle plugin.
*
* @param config ApiConfig
* @param javaProjectBuilder ProjectDocConfigBuilder
*/
public static void buildApiDoc(ApiConfig config, JavaProjectBuilder javaProjectBuilder) {
config.setParamsDataToTree(true);
DocBuilderTemplate builderTemplate = new DocBuilderTemplate();
builderTemplate.checkAndInit(config,true);
ProjectDocConfigBuilder configBuilder = new ProjectDocConfigBuilder(config, javaProjectBuilder);
IDocBuildTemplate docBuildTemplate = BuildTemplateFactory.getDocBuildTemplate(config.getFramework());
List<ApiDoc> apiDocList = docBuildTemplate.getApiData(configBuilder);
apiDocList = docBuildTemplate.handleApiGroup(apiDocList, config);
buildTorna(apiDocList, config, javaProjectBuilder);
}
/**
* build torna Data
*
* @param apiDocs apiData
* @param apiConfig ApiConfig
* @param builder JavaProjectBuilder
*/
public static void buildTorna(List<ApiDoc> apiDocs, ApiConfig apiConfig, JavaProjectBuilder builder) {
TornaApi tornaApi = new TornaApi();
tornaApi.setAuthor(StringUtil.isEmpty(apiConfig.getAuthor()) ? System.getProperty("user.name") : apiConfig.getAuthor());
tornaApi.setIsReplace((apiConfig.getReplace() == null || apiConfig.getReplace()) ? 1 : 0);
Apis api;
List<Apis> groupApiList = new ArrayList<>();
//Convert ApiDoc to Apis
for (ApiDoc groupApi : apiDocs) {
List<Apis> apisList = new ArrayList<>();
List<ApiDoc> childrenApiDocs = groupApi.getChildrenApiDocs();
for (ApiDoc a : childrenApiDocs) {
api = new Apis();
api.setName(StringUtils.isBlank(a.getDesc()) ? a.getName() : a.getDesc());
api.setItems(buildApis(a.getList(), TornaUtil.setDebugEnv(apiConfig, tornaApi)));
api.setIsFolder(TornaConstants.YES);
api.setAuthor(a.getAuthor());
api.setOrderIndex(a.getOrder());
apisList.add(api);
}
api = new Apis();
api.setName(StringUtils.isBlank(groupApi.getDesc()) ? groupApi.getName() : groupApi.getDesc());
api.setAuthor(tornaApi.getAuthor());
api.setOrderIndex(groupApi.getOrder());
api.setIsFolder(TornaConstants.YES);
api.setItems(apisList);
groupApiList.add(api);
}
tornaApi.setCommonErrorCodes(buildErrorCode(apiConfig));
// delete default group when only default group
tornaApi.setApis(groupApiList.size() == 1 ? groupApiList.get(0).getItems() : groupApiList);
//Build push document information
Map<String, String> requestJson = TornaConstants.buildParams(PUSH, new Gson().toJson(tornaApi), apiConfig);
//Push dictionary information
Map<String, Object> dicMap = new HashMap<>(2);
List<TornaDic> docDicts = TornaUtil.buildTornaDic(DocUtil.buildDictionary(apiConfig, builder));
if (CollectionUtil.isNotEmpty(docDicts)) {
dicMap.put("enums", docDicts);
Map<String, String> dicRequestJson = TornaConstants.buildParams(ENUM_PUSH, new Gson().toJson(dicMap), apiConfig);
String dicResponseMsg = OkHttp3Util.syncPostJson(apiConfig.getOpenUrl(), new Gson().toJson(dicRequestJson));
TornaUtil.printDebugInfo(apiConfig, dicResponseMsg, dicRequestJson, ENUM_PUSH);
}
//Get the response result
String responseMsg = OkHttp3Util.syncPostJson(apiConfig.getOpenUrl(), new Gson().toJson(requestJson));
//Print the log of pushing documents to Torna
TornaUtil.printDebugInfo(apiConfig, responseMsg, requestJson, PUSH);
}
}

View File

@ -0,0 +1,80 @@
/*
* smart-doc https://github.com/shalousun/smart-doc
*
* Copyright (C) 2018-2021 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.rpc;
import com.power.doc.builder.ProjectDocConfigBuilder;
import com.power.doc.constants.FrameworkEnum;
import com.power.doc.factory.BuildTemplateFactory;
import com.power.doc.model.ApiConfig;
import com.power.doc.model.rpc.RpcApiDoc;
import com.power.doc.template.IDocBuildTemplate;
import com.thoughtworks.qdox.JavaProjectBuilder;
import java.util.List;
import static com.power.doc.constants.DocGlobalConstants.*;
/**
* @author yu 2020/5/17.
*/
public class RpcAdocBuilder {
private static final String API_EXTENSION = "RpcApi.adoc";
private static final String INDEX_DOC = "rpc-index.adoc";
/**
* build adoc
*
* @param config ApiConfig
*/
public static void buildApiDoc(ApiConfig config) {
JavaProjectBuilder javaProjectBuilder = new JavaProjectBuilder();
buildApiDoc(config, javaProjectBuilder);
}
/**
* Only for smart-doc maven plugin and gradle plugin.
*
* @param config ApiConfig
* @param javaProjectBuilder ProjectDocConfigBuilder
*/
public static void buildApiDoc(ApiConfig config, JavaProjectBuilder javaProjectBuilder) {
config.setFramework(FrameworkEnum.DUBBO.getFramework());
config.setAdoc(true);
config.setShowJavaType(true);
RpcDocBuilderTemplate builderTemplate = new RpcDocBuilderTemplate();
builderTemplate.checkAndInit(config);
ProjectDocConfigBuilder configBuilder = new ProjectDocConfigBuilder(config, javaProjectBuilder);
IDocBuildTemplate docBuildTemplate = BuildTemplateFactory.getDocBuildTemplate(config.getFramework());
List<RpcApiDoc> apiDocList = docBuildTemplate.getApiData(configBuilder);
if (config.isAllInOne()) {
String docName = builderTemplate.allInOneDocName(config, INDEX_DOC, ".adoc");
builderTemplate.buildAllInOne(apiDocList, config, javaProjectBuilder, RPC_ALL_IN_ONE_ADOC_TPL, docName);
} else {
builderTemplate.buildApiDoc(apiDocList, config, RPC_API_DOC_ADOC_TPL, API_EXTENSION);
builderTemplate.buildErrorCodeDoc(config, ERROR_CODE_LIST_ADOC_TPL, ERROR_CODE_LIST_ADOC);
}
}
}

View File

@ -0,0 +1,53 @@
/*
* smart-doc https://github.com/shalousun/smart-doc
*
* Copyright (C) 2018-2021 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.rpc;
import com.power.common.util.StringUtil;
import com.power.doc.constants.FrameworkEnum;
import com.power.doc.model.ApiConfig;
import com.power.doc.model.rpc.RpcApiAllData;
import com.thoughtworks.qdox.JavaProjectBuilder;
/**
* @author yu 2020/5/24.
*/
public class RpcApiDataBuilder {
/**
* Get list of ApiDoc
*
* @param config ApiConfig
* @return List of ApiDoc
*/
public static RpcApiAllData getApiData(ApiConfig config) {
config.setShowJavaType(true);
if (StringUtil.isEmpty(config.getFramework())) {
config.setFramework(FrameworkEnum.DUBBO.getFramework());
}
RpcDocBuilderTemplate builderTemplate = new RpcDocBuilderTemplate();
builderTemplate.checkAndInitForGetApiData(config);
JavaProjectBuilder javaProjectBuilder = new JavaProjectBuilder();
builderTemplate.getApiData(config, javaProjectBuilder);
return builderTemplate.getApiData(config, javaProjectBuilder);
}
}

View File

@ -0,0 +1,201 @@
/*
* smart-doc https://github.com/shalousun/smart-doc
*
* Copyright (C) 2018-2021 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.rpc;
import com.power.common.util.CollectionUtil;
import com.power.common.util.DateTimeUtil;
import com.power.common.util.FileUtil;
import com.power.common.util.StringUtil;
import com.power.doc.builder.BaseDocBuilderTemplate;
import com.power.doc.builder.ProjectDocConfigBuilder;
import com.power.doc.constants.FrameworkEnum;
import com.power.doc.constants.TemplateVariable;
import com.power.doc.factory.BuildTemplateFactory;
import com.power.doc.model.ApiConfig;
import com.power.doc.model.ApiErrorCode;
import com.power.doc.model.rpc.RpcApiAllData;
import com.power.doc.model.rpc.RpcApiDoc;
import com.power.doc.template.IDocBuildTemplate;
import com.power.doc.utils.BeetlTemplateUtil;
import com.power.doc.utils.DocUtil;
import com.thoughtworks.qdox.JavaProjectBuilder;
import org.beetl.core.Template;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import static com.power.doc.constants.DocGlobalConstants.FILE_SEPARATOR;
import static com.power.doc.constants.DocGlobalConstants.RPC_OUT_DIR;
/**
* @author yu 2020/5/16.
*/
public class RpcDocBuilderTemplate extends BaseDocBuilderTemplate {
private static final String DEPENDENCY_TITLE = "Add dependency";
private static long now = System.currentTimeMillis();
public void checkAndInit(ApiConfig config) {
if (StringUtil.isEmpty(config.getFramework())) {
config.setFramework(FrameworkEnum.DUBBO.getFramework());
}
super.checkAndInit(config,false);
config.setOutPath(config.getOutPath() + FILE_SEPARATOR + RPC_OUT_DIR);
}
/**
* Generate api documentation for all controllers.
*
* @param apiDocList list of api doc
* @param config api config
* @param template template
* @param fileExtension file extension
*/
public void buildApiDoc(List<RpcApiDoc> apiDocList, ApiConfig config, String template, String fileExtension) {
FileUtil.mkdirs(config.getOutPath());
for (RpcApiDoc rpcDoc : apiDocList) {
Template mapper = BeetlTemplateUtil.getByName(template);
mapper.binding(TemplateVariable.DESC.getVariable(), rpcDoc.getDesc());
mapper.binding(TemplateVariable.NAME.getVariable(), rpcDoc.getName());
mapper.binding(TemplateVariable.LIST.getVariable(), rpcDoc.getList());
mapper.binding(TemplateVariable.AUTHOR.getVariable(), rpcDoc.getAuthor());
mapper.binding(TemplateVariable.PROTOCOL.getVariable(), rpcDoc.getProtocol());
mapper.binding(TemplateVariable.VERSION.getVariable(), rpcDoc.getVersion());
mapper.binding(TemplateVariable.URI.getVariable(), rpcDoc.getUri());
FileUtil.nioWriteFile(mapper.render(), config.getOutPath() + FILE_SEPARATOR + rpcDoc.getShortName() + fileExtension);
}
}
/**
* Merge all api doc into one document
*
* @param apiDocList list data of Api doc
* @param config api config
* @param javaProjectBuilder JavaProjectBuilder
* @param template template
* @param outPutFileName output file
*/
public void buildAllInOne(List<RpcApiDoc> apiDocList, ApiConfig config, JavaProjectBuilder javaProjectBuilder, String template, String outPutFileName) {
String outPath = config.getOutPath();
String strTime = DateTimeUtil.long2Str(now, DateTimeUtil.DATE_FORMAT_SECOND);
String rpcConfig = config.getRpcConsumerConfig();
String rpcConfigConfigContent = null;
if (Objects.nonNull(rpcConfig)) {
rpcConfigConfigContent = FileUtil.getFileContent(rpcConfig);
}
FileUtil.mkdirs(outPath);
List<ApiErrorCode> errorCodeList = DocUtil.errorCodeDictToList(config);
Template tpl = BeetlTemplateUtil.getByName(template);
tpl.binding(TemplateVariable.API_DOC_LIST.getVariable(), apiDocList);
tpl.binding(TemplateVariable.ERROR_CODE_LIST.getVariable(), errorCodeList);
tpl.binding(TemplateVariable.VERSION_LIST.getVariable(), config.getRevisionLogs());
tpl.binding(TemplateVariable.DEPENDENCY_LIST.getVariable(), config.getRpcApiDependencies());
tpl.binding(TemplateVariable.VERSION.getVariable(), now);
tpl.binding(TemplateVariable.CREATE_TIME.getVariable(), strTime);
tpl.binding(TemplateVariable.PROJECT_NAME.getVariable(), config.getProjectName());
tpl.binding(TemplateVariable.RPC_CONSUMER_CONFIG.getVariable(), rpcConfigConfigContent);
setDirectoryLanguageVariable(config, tpl);
setCssCDN(config, tpl);
FileUtil.nioWriteFile(tpl.render(), outPath + FILE_SEPARATOR + outPutFileName);
}
/**
* Build search js
*
* @param apiDocList list data of Api doc
* @param config api config
* @param template template
* @param outPutFileName output file
*/
public void buildSearchJs(List<RpcApiDoc> apiDocList, ApiConfig config, String template, String outPutFileName) {
List<ApiErrorCode> errorCodeList = DocUtil.errorCodeDictToList(config);
Template tpl = BeetlTemplateUtil.getByName(template);
// directory tree
List<RpcApiDoc> apiDocs = new ArrayList<>();
RpcApiDoc apiDoc = new RpcApiDoc();
apiDoc.setAlias(DEPENDENCY_TITLE);
apiDoc.setOrder(1);
apiDoc.setDesc(DEPENDENCY_TITLE);
apiDoc.setList(new ArrayList<>(0));
apiDocs.add(apiDoc);
List<RpcApiDoc> apiDocs1 = apiDocList;
for (RpcApiDoc apiDoc1 : apiDocs1) {
apiDoc1.setOrder(apiDocs.size() + 1);
apiDocs.add(apiDoc1);
}
Map<String, String> titleMap = setDirectoryLanguageVariable(config, tpl);
if (CollectionUtil.isNotEmpty(errorCodeList)) {
RpcApiDoc apiDoc1 = new RpcApiDoc();
apiDoc1.setOrder(apiDocs.size() + 1);
apiDoc1.setDesc(titleMap.get(TemplateVariable.ERROR_LIST_TITLE.getVariable()));
apiDoc1.setList(new ArrayList<>(0));
apiDocs.add(apiDoc1);
}
tpl.binding(TemplateVariable.DIRECTORY_TREE.getVariable(), apiDocs);
FileUtil.nioWriteFile(tpl.render(), config.getOutPath() + FILE_SEPARATOR + outPutFileName);
}
/**
* build error_code adoc
*
* @param config api config
* @param template template
* @param outPutFileName output file
*/
public void buildErrorCodeDoc(ApiConfig config, String template, String outPutFileName) {
List<ApiErrorCode> errorCodeList = DocUtil.errorCodeDictToList(config);
Template mapper = BeetlTemplateUtil.getByName(template);
mapper.binding(TemplateVariable.LIST.getVariable(), errorCodeList);
FileUtil.nioWriteFile(mapper.render(), config.getOutPath() + FILE_SEPARATOR + outPutFileName);
}
/**
* get all api data
*
* @param config ApiConfig
* @param javaProjectBuilder JavaProjectBuilder
* @return ApiAllData
*/
public RpcApiAllData getApiData(ApiConfig config, JavaProjectBuilder javaProjectBuilder) {
RpcApiAllData apiAllData = new RpcApiAllData();
apiAllData.setLanguage(config.getLanguage().getCode());
apiAllData.setProjectName(config.getProjectName());
apiAllData.setProjectId(DocUtil.generateId(config.getProjectName()));
apiAllData.setApiDocList(listOfApiData(config, javaProjectBuilder));
apiAllData.setErrorCodeList(DocUtil.errorCodeDictToList(config));
apiAllData.setRevisionLogs(config.getRevisionLogs());
apiAllData.setDependencyList(config.getRpcApiDependencies());
return apiAllData;
}
private List<RpcApiDoc> listOfApiData(ApiConfig config, JavaProjectBuilder javaProjectBuilder) {
this.checkAndInitForGetApiData(config);
config.setMd5EncryptedHtmlName(true);
ProjectDocConfigBuilder configBuilder = new ProjectDocConfigBuilder(config, javaProjectBuilder);
IDocBuildTemplate docBuildTemplate = BuildTemplateFactory.getDocBuildTemplate(config.getFramework());
return docBuildTemplate.getApiData(configBuilder);
}
}

View File

@ -0,0 +1,83 @@
/*
* smart-doc https://github.com/shalousun/smart-doc
*
* Copyright (C) 2018-2021 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.rpc;
import com.power.common.util.FileUtil;
import com.power.doc.builder.ProjectDocConfigBuilder;
import com.power.doc.constants.FrameworkEnum;
import com.power.doc.factory.BuildTemplateFactory;
import com.power.doc.model.ApiConfig;
import com.power.doc.model.rpc.RpcApiDoc;
import com.power.doc.template.IDocBuildTemplate;
import com.power.doc.template.RpcDocBuildTemplate;
import com.power.doc.utils.BeetlTemplateUtil;
import com.thoughtworks.qdox.JavaProjectBuilder;
import org.beetl.core.Template;
import java.util.List;
import static com.power.doc.constants.DocGlobalConstants.*;
/**
* @author yu 2020/5/17.
*/
public class RpcHtmlBuilder {
private static long now = System.currentTimeMillis();
private static String INDEX_HTML = "rpc-index.html";
private static String SEARCH_JS = "search.js";
/**
* build controller api
*
* @param config config
*/
public static void buildApiDoc(ApiConfig config) {
JavaProjectBuilder javaProjectBuilder = new JavaProjectBuilder();
buildApiDoc(config, javaProjectBuilder);
}
/**
* Only for smart-doc maven plugin and gradle plugin.
*
* @param config ApiConfig
* @param javaProjectBuilder ProjectDocConfigBuilder
*/
public static void buildApiDoc(ApiConfig config, JavaProjectBuilder javaProjectBuilder) {
config.setShowJavaType(true);
RpcDocBuilderTemplate builderTemplate = new RpcDocBuilderTemplate();
builderTemplate.checkAndInit(config);
ProjectDocConfigBuilder configBuilder = new ProjectDocConfigBuilder(config, javaProjectBuilder);
IDocBuildTemplate docBuildTemplate = BuildTemplateFactory.getDocBuildTemplate(config.getFramework());
List<RpcApiDoc> apiDocList = docBuildTemplate.getApiData(configBuilder);
Template indexCssTemplate = BeetlTemplateUtil.getByName(ALL_IN_ONE_CSS);
FileUtil.nioWriteFile(indexCssTemplate.render(), config.getOutPath() + FILE_SEPARATOR + ALL_IN_ONE_CSS_OUT);
builderTemplate.copyJarFile("css/" + FONT_STYLE, config.getOutPath() + FILE_SEPARATOR + FONT_STYLE);
builderTemplate.copyJarFile("js/" + JQUERY, config.getOutPath() + FILE_SEPARATOR + JQUERY);
builderTemplate.buildAllInOne(apiDocList, config, javaProjectBuilder, RPC_ALL_IN_ONE_HTML_TPL, INDEX_HTML);
builderTemplate.buildSearchJs(apiDocList, config, RPC_ALL_IN_ONE_SEARCH_TPL, SEARCH_JS);
}
}

View File

@ -0,0 +1,77 @@
/*
* smart-doc https://github.com/shalousun/smart-doc
*
* Copyright (C) 2018-2021 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.rpc;
import com.power.common.util.DateTimeUtil;
import com.power.doc.builder.ProjectDocConfigBuilder;
import com.power.doc.factory.BuildTemplateFactory;
import com.power.doc.model.ApiConfig;
import com.power.doc.model.rpc.RpcApiDoc;
import com.power.doc.template.IDocBuildTemplate;
import com.thoughtworks.qdox.JavaProjectBuilder;
import java.util.List;
import static com.power.doc.constants.DocGlobalConstants.*;
/**
* @author yu 2020/5/16.
*/
public class RpcMarkdownBuilder {
private static final String API_EXTENSION = "Api.md";
private static final String DATE_FORMAT = "yyyyMMddHHmm";
/**
* @param config ApiConfig
*/
public static void buildApiDoc(ApiConfig config) {
JavaProjectBuilder javaProjectBuilder = new JavaProjectBuilder();
buildApiDoc(config, javaProjectBuilder);
}
/**
* Only for smart-doc maven plugin and gradle plugin.
*
* @param apiConfig ApiConfig
* @param javaProjectBuilder ProjectDocConfigBuilder
*/
public static void buildApiDoc(ApiConfig apiConfig, JavaProjectBuilder javaProjectBuilder) {
apiConfig.setAdoc(false);
apiConfig.setShowJavaType(true);
RpcDocBuilderTemplate builderTemplate = new RpcDocBuilderTemplate();
builderTemplate.checkAndInit(apiConfig);
ProjectDocConfigBuilder configBuilder = new ProjectDocConfigBuilder(apiConfig, javaProjectBuilder);
IDocBuildTemplate docBuildTemplate = BuildTemplateFactory.getDocBuildTemplate(apiConfig.getFramework());
List<RpcApiDoc> apiDocList = docBuildTemplate.getApiData(configBuilder);
if (apiConfig.isAllInOne()) {
String version = apiConfig.isCoverOld() ? "" : "-V" + DateTimeUtil.long2Str(System.currentTimeMillis(), DATE_FORMAT);
String docName = builderTemplate.allInOneDocName(apiConfig, "rpc-all" + version, ".md");
builderTemplate.buildAllInOne(apiDocList, apiConfig, javaProjectBuilder, RPC_ALL_IN_ONE_MD_TPL, docName);
} else {
builderTemplate.buildApiDoc(apiDocList, apiConfig, RPC_API_DOC_MD_TPL, API_EXTENSION);
builderTemplate.buildErrorCodeDoc(apiConfig, ERROR_CODE_LIST_MD_TPL, ERROR_CODE_LIST_MD);
}
}
}

View File

@ -0,0 +1,131 @@
/*
* smart-doc https://github.com/shalousun/smart-doc
*
* Copyright (C) 2018-2021 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.rpc;
import com.google.gson.Gson;
import com.power.common.util.CollectionUtil;
import com.power.common.util.OkHttp3Util;
import com.power.common.util.StringUtil;
import com.power.doc.builder.ProjectDocConfigBuilder;
import com.power.doc.constants.TornaConstants;
import com.power.doc.factory.BuildTemplateFactory;
import com.power.doc.model.ApiConfig;
import com.power.doc.model.rpc.RpcApiDoc;
import com.power.doc.model.torna.Apis;
import com.power.doc.model.torna.DubboInfo;
import com.power.doc.model.torna.TornaApi;
import com.power.doc.model.torna.TornaDic;
import com.power.doc.template.IDocBuildTemplate;
import com.power.doc.template.RpcDocBuildTemplate;
import com.power.doc.utils.DocUtil;
import com.power.doc.utils.TornaUtil;
import com.thoughtworks.qdox.JavaProjectBuilder;
import org.apache.commons.lang3.StringUtils;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static com.power.doc.constants.TornaConstants.ENUM_PUSH;
import static com.power.doc.constants.TornaConstants.PUSH;
import static com.power.doc.utils.TornaUtil.buildDubboApis;
import static com.power.doc.utils.TornaUtil.buildErrorCode;
/**
* @author xingzi 2021/4/28 16:14
**/
public class RpcTornaBuilder {
/**
* build controller api
*
* @param config config
*/
public static void buildApiDoc(ApiConfig config) {
JavaProjectBuilder javaProjectBuilder = new JavaProjectBuilder();
buildApiDoc(config, javaProjectBuilder);
}
/**
* Only for smart-doc maven plugin and gradle plugin.
*
* @param config ApiConfig
* @param javaProjectBuilder ProjectDocConfigBuilder
*/
public static void buildApiDoc(ApiConfig config, JavaProjectBuilder javaProjectBuilder) {
config.setParamsDataToTree(true);
RpcDocBuilderTemplate builderTemplate = new RpcDocBuilderTemplate();
builderTemplate.checkAndInit(config);
ProjectDocConfigBuilder configBuilder = new ProjectDocConfigBuilder(config, javaProjectBuilder);
IDocBuildTemplate docBuildTemplate = BuildTemplateFactory.getDocBuildTemplate(config.getFramework());
List<RpcApiDoc> apiDocList = docBuildTemplate.getApiData(configBuilder);
buildTorna(apiDocList, config, javaProjectBuilder);
}
public static void buildTorna(List<RpcApiDoc> apiDocs, ApiConfig apiConfig, JavaProjectBuilder builder) {
TornaApi tornaApi = new TornaApi();
tornaApi.setAuthor(StringUtil.isEmpty(apiConfig.getAuthor()) ? System.getProperty("user.name") : apiConfig.getAuthor());
tornaApi.setIsReplace((apiConfig.getReplace() == null || apiConfig.getReplace()) ? 1 : 0);
Apis api;
List<Apis> apisList = new ArrayList<>();
//添加接口数据
for (RpcApiDoc a : apiDocs) {
api = new Apis();
api.setName(StringUtils.isBlank(a.getDesc()) ? a.getName() : a.getDesc());
TornaUtil.setDebugEnv(apiConfig, tornaApi);
api.setItems(buildDubboApis(a.getList()));
api.setIsFolder(TornaConstants.YES);
api.setAuthor(a.getAuthor());
api.setDubboInfo(new DubboInfo().builder()
.setAuthor(a.getAuthor())
.setProtocol(a.getProtocol())
.setVersion(a.getVersion())
.setDependency(TornaUtil.buildDependencies(apiConfig.getRpcApiDependencies()))
.setInterfaceName(a.getName()));
api.setOrderIndex(a.getOrder());
apisList.add(api);
}
tornaApi.setCommonErrorCodes(buildErrorCode(apiConfig));
tornaApi.setApis(apisList);
//Build push document information
Map<String, String> requestJson = TornaConstants.buildParams(PUSH, new Gson().toJson(tornaApi), apiConfig);
//Push dictionary information
Map<String, Object> dicMap = new HashMap<>(2);
List<TornaDic> docDicts = TornaUtil.buildTornaDic(DocUtil.buildDictionary(apiConfig, builder));
if (CollectionUtil.isNotEmpty(docDicts)) {
dicMap.put("enums", docDicts);
Map<String, String> dicRequestJson = TornaConstants.buildParams(ENUM_PUSH, new Gson().toJson(dicMap), apiConfig);
String dicResponseMsg = OkHttp3Util.syncPostJson(apiConfig.getOpenUrl(), new Gson().toJson(dicRequestJson));
TornaUtil.printDebugInfo(apiConfig, dicResponseMsg, dicRequestJson, ENUM_PUSH);
}
Map<String, String> dicRequestJson = TornaConstants.buildParams(ENUM_PUSH, new Gson().toJson(dicMap), apiConfig);
//Get the response result
String responseMsg = OkHttp3Util.syncPostJson(apiConfig.getOpenUrl(), new Gson().toJson(requestJson));
//Print the log of pushing documents to Torna
TornaUtil.printDebugInfo(apiConfig, responseMsg, requestJson, PUSH);
}
}

View File

@ -0,0 +1,32 @@
package com.power.doc.constants;
/**
* @author chen qi 2021-07-15 10:55
**/
public enum ApiReqParamInTypeEnum {
/**
* header param
*/
HEADER("header"),
/**
* query param
*/
QUERY("query"),
/**
* path param
*/
PATH("path");
private final String value;
ApiReqParamInTypeEnum(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}

View File

@ -0,0 +1,90 @@
/*
* smart-doc https://github.com/shalousun/smart-doc
*
* Copyright (C) 2018-2021 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.constants;
/**
* java annotations
*
* @author yu 2019/9/19.
*/
public interface DocAnnotationConstants {
String SHORT_CONTROLLER = "Controller";
String SHORT_REST_CONTROLLER = "RestController";
String SHORT_PATH_VARIABLE = "PathVariable";
String SHORT_REQ_PARAM = "RequestParam";
String SHORT_JSON_IGNORE = "JsonIgnore";
/**
* jackson JsonIgnoreProperties annotation
*/
String SHORT_JSON_IGNORE_PROPERTIES = "JsonIgnoreProperties";
String SHORT_JSON_PROPERTY = "JsonProperty";
String SHORT_JSON_FIELD = "JSONField";
String REQUIRED_PROP = "required";
String SERIALIZE_PROP = "serialize";
String NAME_PROP = "name";
String VALUE_PROP = "value";
String PATH_PROP = "path";
String GROUP_PROP = "groups";
String DEFAULT_VALUE_PROP = "defaultValue";
String REQUEST_MAPPING = "RequestMapping";
String DEPRECATED = "Deprecated";
String JSON_VALUE = "JsonValue";
String JSON_CREATOR = "JsonCreator";
String MAX = "max";
String SIZE = "size";
String LENGTH = "length";
String JSON_PROPERTY = "JsonProperty";
/**
* Fastjson JSONType annotation
*/
String SHORT_JSON_TYPE = "JSONType";
/**
* Fastjson JSONType annotation ignores prop
*/
String IGNORE_PROP = "ignores";
}

View File

@ -0,0 +1,276 @@
/*
* smart-doc https://github.com/shalousun/smart-doc
*
* Copyright (C) 2018-2021 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.constants;
/**
* @author yu 2018/12/15.
*/
public interface DocGlobalConstants {
int API_ORDER = 0;
String FILE_SEPARATOR = System.getProperty("file.separator");
String HTML_DOC_OUT_PATH = "src/main/resources/static/doc";
String ADOC_OUT_PATH = "src/docs/asciidoc";
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 DOC_LANGUAGE = "smart-doc_language";
String API_DOC_MD_TPL = "ApiDoc.btl";
String API_DOC_ADOC_TPL = "ApiDoc.adoc";
String ALL_IN_ONE_MD_TPL = "AllInOne.btl";
String ALL_IN_ONE_ADOC_TPL = "AllInOne.adoc";
String ALL_IN_ONE_HTML_TPL = "AllInOne.html";
String HTML_API_DOC_TPL = "HtmlApiDoc.btl";
String ERROR_CODE_LIST_MD_TPL = "ErrorCodeList.btl";
String ERROR_CODE_LIST_ADOC_TPL = "ErrorCodeList.adoc";
String ERROR_CODE_LIST_MD = "ErrorCodeList.md";
String ERROR_CODE_LIST_ADOC = "ErrorCodeList.adoc";
String DICT_LIST_MD = "Dictionary.md";
String DICT_LIST_MD_TPL = "Dictionary.btl";
String DICT_LIST_ADOC = "Dictionary.adoc";
String DICT_LIST_ADOC_TPL = "Dictionary.btl";
String SEARCH_ALL_JS_TPL = "js/search_all.js.btl";
String SEARCH_JS_TPL = "js/search.js.btl";
String SEARCH_JS_OUT = "search.js";
String DEBUG_JS_TPL = "js/debug.js";
String DEBUG_JS_OUT = "debug.js";
String DEBUG_PAGE_TPL = "mock.html";
String DEBUG_PAGE_ALL_TPL = "debug-all.html";
String DEBUG_PAGE_SINGLE_TPL = "html/debug.html";
String SINGLE_INDEX_HTML_TPL = "html/index.html";
String SINGLE_ERROR_HTML_TPL = "html/error.html";
String SINGLE_DICT_HTML_TPL = "html/dict.html";
String ALL_IN_ONE_CSS = "css/AllInOne.css";
String ALL_IN_ONE_CSS_OUT = "AllInOne.css";
String FONT_STYLE = "font.css";
String HIGH_LIGHT_JS = "highlight.min.js";
String JQUERY = "jquery.min.js";
String HIGH_LIGHT_STYLE = "xt256.min.css";
String RPC_OUT_DIR = "rpc";
String RPC_API_DOC_ADOC_TPL = "dubbo/Dubbo.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_SEARCH_TPL = "dubbo/DubboSearch.btl";
String RPC_DEPENDENCY_MD_TPL = "dubbo/DubboApiDependency.md";
String RPC_DEPENDENCY_EMPTY_MD_TPL = "dubbo/DubboApiDependencyEmpty.md";
String RPC_API_DOC_MD_TPL = "dubbo/Dubbo.md";
String RPC_ALL_IN_ONE_MD_TPL = "dubbo/DubboAllInOne.md";
String RPC_INDEX_TPL = "dubbo/DubboIndex.btl";
String POSTMAN_JSON = "/postman.json";
String OPEN_API_JSON = "/openapi.json";
String CONTROLLER_FULLY = "org.springframework.stereotype.Controller";
String REST_CONTROLLER_FULLY = "org.springframework.web.bind.annotation.RestController";
String GET_MAPPING_FULLY = "org.springframework.web.bind.annotation.GetMapping";
String POST_MAPPING_FULLY = "org.springframework.web.bind.annotation.PostMapping";
String PUT_MAPPING_FULLY = "org.springframework.web.bind.annotation.PutMapping";
String PATCH_MAPPING_FULLY = "org.springframework.web.bind.annotation.PatchMapping";
String DELETE_MAPPING_FULLY = "org.springframework.web.bind.annotation.DeleteMapping";
String REQUEST_MAPPING_FULLY = "org.springframework.web.bind.annotation.RequestMapping";
String REQUEST_BODY_FULLY = "org.springframework.web.bind.annotation.RequestBody";
String MODE_AND_VIEW_FULLY = "org.springframework.web.servlet.ModelAndView";
String FEIGN_CLIENT_FULLY = "org.springframework.cloud.netflix.feign.FeignClient";
String FEIGN_CLIENT = "FeignClient";
String MULTIPART_FILE_FULLY = "org.springframework.web.multipart.MultipartFile";
String JAVA_OBJECT_FULLY = "java.lang.Object";
String JAVA_BOOLEAN = "java.lang.Boolean";
String JAVA_STRING_FULLY = "java.lang.String";
String JAVA_MAP_FULLY = "java.util.Map";
String JAVA_LIST_FULLY = "java.util.List";
String DEFAULT_VERSION = "-";
String ERROR_CODE_LIST_CN_TITLE = "错误码列表";
String ERROR_CODE_LIST_EN_TITLE = "Error Code List";
String DICT_CN_TITLE = "数据字典";
String DICT_EN_TITLE = "Data Dictionaries";
String FIELD_SPACE = "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
String ANY_OBJECT_MSG = "any object.";
String NO_COMMENTS_FOUND = "No comments found.";
String SPRING_WEB_ANNOTATION_PACKAGE = "org.springframework.web.bind.annotation";
String FILE_CONTENT_TYPE = "multipart/form-data";
String MULTIPART_TYPE = "multipart/form-data";
String APPLICATION_JSON = "application/json";
String JSON_CONTENT_TYPE = "application/json; charset=utf-8";
String URL_CONTENT_TYPE = "application/x-www-form-urlencoded;charset=utf-8";
String POSTMAN_MODE_FORMDATA = "formdata";
String POSTMAN_MODE_RAW = "raw";
String SHORT_MULTIPART_FILE_FULLY = "MultipartFile";
String DEFAULT_SERVER_URL = "";
String SHORT_REQUEST_BODY = "RequestBody";
String CURL_REQUEST_TYPE = "curl -X %s %s -i %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' %s -i %s --data '%s'";
String EMPTY = "";
String ENUM = "enum";
String YAPI_RESULT_TPL = "yapiJson.btl";
String YAPI_JSON = "/yapi.json";
String DUBBO_SWAGGER = "org.apache.dubbo.rpc.protocol.rest.integration.swagger.DubboSwaggerApiListingResource";
String ARRAY = "array";
String OBJECT = "object";
String JSON_PROPERTY_READ_WRITE = "JsonProperty.Access.READ_WRITE";
String JSON_PROPERTY_READ_ONLY = "JsonProperty.Access.READ_ONLY";
String JSON_PROPERTY_WRITE_ONLY = "JsonProperty.Access.WRITE_ONLY";
String CSS_CDN_CH = "https://fonts.googleapis.cnpmjs.org";
String CSS_CDN = "https://fonts.googleapis.com";
String PATH_DELIMITER = "/";
/**
* JAX-RS@PATH
*/
String JAX_PATH_FULLY = "javax.ws.rs.Path";
/**
* JAX-RS@Produces
*/
String JAX_PRODUCES_FULLY = "javax.ws.rs.Produces";
/**
* JAX-RS@Produces
*/
String JAX_CONSUMES_FULLY = "javax.ws.rs.Consumes";
/**
* JAX-RS@GET
*/
String JAX_GET_FULLY = "javax.ws.rs.GET";
/**
* JAX-RS@POST
*/
String JAX_POST_FULLY = "javax.ws.rs.POST";
/**
* JAX-RS@PUT
*/
String JAX_PUT_FULLY = "javax.ws.rs.PUT";
/**
* JAX-RS@DELETE
*/
String JAXB_DELETE_FULLY = "javax.ws.rs.DELETE";
String HIGH_LIGHT_CSS_URL_FORMAT = "https://cdn.bootcdn.net/ajax/libs/highlight.js/10.3.2/styles/%s.min.css";
String HIGH_LIGHT_DEFAULT_STYLE = "xt256";
String HIGH_LIGHT_CSS_DEFAULT = "xt256.min.css";
String HIGH_LIGHT_CSS_RANDOM_LIGHT = "randomLight";
String HIGH_LIGHT_CSS_RANDOM_DARK = "randomDark";
}

View File

@ -0,0 +1,43 @@
/*
* smart-doc https://github.com/shalousun/smart-doc
*
* Copyright (C) 2018-2021 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.constants;
/**
* language support
*
* @author yu 2019/9/21.
*/
public enum DocLanguage {
ENGLISH("en-US"),
CHINESE("zh-CN");
public String code;
DocLanguage(String code) {
this.code = code;
}
public String getCode() {
return this.code;
}
}

View File

@ -0,0 +1,132 @@
/*
* smart-doc https://github.com/shalousun/smart-doc
*
* Copyright (C) 2018-2021 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.constants;
/**
* @author yu 2019/9/13.
*/
public interface DocTags {
/**
* java since tag
*/
String SINCE = "since";
/**
* java required tag
*/
String REQUIRED = "required";
/**
* java param tag
*/
String PARAM = "param";
/**
* java apiNote tag for method detail
*/
String API_NOTE = "apiNote";
/**
* java author tag for method author
*/
String AUTHOR = "author";
/**
* java version tag
*/
String VERSION = "version";
/**
* java deprecated tag
*/
String DEPRECATED = "deprecated";
/**
* custom ignore tag
*/
String IGNORE = "ignore";
/**
* custom @mock tag
*/
String MOCK = "mock";
/**
* custom @dubbo tag
*/
String DUBBO = "dubbo";
/**
* custom @api tag
*/
String REST_API = "restApi";
/**
* custom @order tag
*/
String ORDER = "order";
/**
* custom @group tag
*/
String GROUP = "group";
/**
* custom @download tag
*/
String DOWNLOAD = "download";
/**
* custom @page tag
*/
String PAGE = "page";
/**
* custom @ignoreParams tag
*/
String IGNORE_PARAMS = "ignoreParams";
/**
* Ignore ResponseBodyAdvice
*/
String IGNORE_RESPONSE_BODY_ADVICE = "ignoreResponseBodyAdvice";
String IGNORE_REQUEST_BODY_ADVICE = "ignoreRequestBodyAdvice";
/**
* response tag @since 2.2.0
*/
String API_RESPONSE = "response";
/**
* custom @tag
*/
String TAG = "tag";
/**
* custom @dubboRest tag
*/
String DUBBO_REST = "dubboRest";
}

View File

@ -0,0 +1,87 @@
/*
* smart-doc https://github.com/shalousun/smart-doc
*
* Copyright (C) 2018-2021 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.constants;
import java.util.ArrayList;
import java.util.List;
/**
* spring validator annotations
*
* @author yu 2019/9/19.
*/
public enum DocValidatorAnnotationEnum {
NOT_EMPTY("NotEmpty"),
NOT_BLANK("NotBlank"),
NOT_NULL("NotNull"),
NULL("Null"),
ASSERT_TRUE("AssertTrue"),
ASSERT_FALSE("AssertFalse"),
MIN("Min"),
MAX("Max"),
DECIMAL_MIN("DecimalMin"),
DECIMAL_MAX("DecimalMax"),
SIZE("Size"),
DIGITS("Digits"),
PAST("Past"),
FUTURE("Future"),
PATTERN("Pattern"),
EMAIL("Email"),
LENGTH("Length"),
RANGE("Range"),
VALIDATED("Validated");
private String value;
DocValidatorAnnotationEnum(String value) {
this.value = value;
}
public static List<String> listValidatorAnnotations() {
List<String> annotations = new ArrayList<>();
for (DocValidatorAnnotationEnum annotation : DocValidatorAnnotationEnum.values()) {
annotations.add(annotation.value);
}
return annotations;
}
}

View File

@ -0,0 +1,43 @@
/*
* smart-doc https://github.com/shalousun/smart-doc
*
* Copyright (C) 2018-2021 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.constants;
/**
* dubbo annotation
*
* @author yu 2020/1/29.
*/
public interface DubboAnnotationConstants {
String SERVICE = "org.apache.dubbo.config.annotation.Service";
/**
* @since dubbo 2.7.7
*/
String DUBBO_SERVICE = "org.apache.dubbo.config.annotation.DubboService";
/**
* support ali dubbo
*/
String ALI_DUBBO_SERVICE = "com.alibaba.dubbo.config.annotation.Service";
}

View File

@ -0,0 +1,87 @@
/*
* smart-doc https://github.com/shalousun/smart-doc
*
* Copyright (C) 2018-2021 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.constants;
import com.power.common.util.StringUtil;
/**
* Smart-doc Supported Framework
*
* @author yu 2021/6/27.
*/
public enum FrameworkEnum {
/**
* Apache Dubbo
*/
DUBBO("dubbo", "com.power.doc.template.RpcDocBuildTemplate"),
/**
* Spring Framework
*/
SPRING("spring", "com.power.doc.template.SpringBootDocBuildTemplate"),
/**
* JAX-RS
*/
JAX_RS("JAX-RS", "com.power.doc.template.JaxrsDocBuildTemplate");
/**
* Framework name
*/
private String framework;
/**
* Framework IDocBuildTemplate implement
*/
private String className;
FrameworkEnum(String framework, String className) {
this.framework = framework;
this.className = className;
}
public static String getClassNameByFramework(String framework) {
String className = "";
if (StringUtil.isEmpty(framework)) {
return className;
}
for (FrameworkEnum e : FrameworkEnum.values()) {
if (e.framework.equalsIgnoreCase(framework)) {
className = e.className;
break;
}
}
return className;
}
public String getFramework() {
return framework;
}
public String getClassName() {
return className;
}
}

View File

@ -0,0 +1,282 @@
/*
* smart-doc https://github.com/shalousun/smart-doc
*
* Copyright (C) 2018-2021 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.constants;
import com.power.common.util.StringUtil;
import java.util.*;
/**
* @author jitmit 2020/11/16
*/
public class HighlightStyle {
public static final String DEFAULT_STYLE = "github";
private static final List<String> DARK_STYLE;
private static final List<String> LIGHT_STYLE;
/**
* key is style,value is color
*/
private static final Map<String, String> background = new HashMap<>();
static {
LIGHT_STYLE = Arrays.asList(
DEFAULT_STYLE,
"a11y-light",
"arduino-light",
"ascetic",
"atelier-cave-light",
"atelier-dune-light",
"atelier-estuary-light",
"atelier-forest-light",
"atelier-heath-light",
"atelier-lakeside-light",
"atelier-plateau-light",
"atelier-savanna-light",
"atelier-seaside-light",
"atelier-sulphurpool-light",
"atom-one-light",
"color-brewer",
"docco",
"github-gist",
"googlecode",
"grayscale",
"gruvbox-light",
"idea",
"isbl-editor-light",
"kimbie.light",
"lightfair",
"magula",
"mono-blue",
"nnfx",
"paraiso-light",
"purebasic",
"qtcreator_light",
"routeros",
"school-book",
"solarized-light",
"tomorrow",
"vs",
"xcode"
);
}
static {
DARK_STYLE = Arrays.asList(
"a11y-dark",
"agate",
"an-old-hope",
"androidstudio",
"arta",
"atelier-cave-dark",
"atelier-dune-dark",
"atelier-estuary-dark",
"atelier-forest-dark",
"atelier-heath-dark",
"atelier-lakeside-dark",
"atelier-plateau-dark",
"atelier-savanna-dark",
"atelier-seaside-dark",
"atelier-sulphurpool-dark",
"atom-one-dark-reasonable",
"atom-one-dark",
"brown-paper",
"codepen-embed",
"darcula",
"dark",
"default",
"dracula",
"far",
"foundation",
"gml",
"gradient-dark",
"gruvbox-dark",
"hopscotch",
"hybrid",
"ir-black",
"isbl-editor-dark",
"kimbie.dark",
"lioshi",
"monokai",
"monokai-sublime",
"night-owl",
"nnfx-dark",
"nord",
"obsidian",
"ocean",
"paraiso-dark",
"pojoaque",
"qtcreator_dark",
"railscasts",
"rainbow",
"shades-of-purple",
"solarized-dark",
"srcery", "sunburst",
"tomorrow-night",
"tomorrow-night-blue",
"tomorrow-night-bright",
"tomorrow-night-eighties",
"vs2015",
"xt256",
"zenburn"
);
}
static {
background.put("a11y-dark", "#2b2b2b");
background.put("agate", "#333");
background.put("androidstudio", "#282b2e");
background.put("atom-one-light", "#fafafa");
background.put("an-old-hope", "#1c1d21");
background.put("arta", "#222");
background.put("atelier-cave-dark", "#19171c");
background.put("atelier-cave-light", "#efecf4");
background.put("atelier-dune-dark", "#20201d");
background.put("atelier-dune-light", "#fefbec");
background.put("atelier-estuary-dark", "#22221b");
background.put("atelier-estuary-light", "#f4f3ec");
background.put("atelier-forest-dark", "#1b1918");
background.put("atelier-forest-light", "#f1efee");
background.put("atelier-heath-dark", "#1b181b");
background.put("atelier-heath-light", "#f7f3f7");
background.put("atelier-lakeside-dark", "#161b1d");
background.put("atelier-lakeside-light", "#ebf8ff");
background.put("atelier-plateau-dark", "#1b1818");
background.put("atelier-plateau-light", "#f4ecec");
background.put("atelier-savanna-dark", "#171c19");
background.put("atelier-savanna-light", "#ecf4ee");
background.put("atelier-seaside-dark", "#131513");
background.put("atelier-seaside-light", "#f4fbf4");
background.put("atelier-cave-light", "#efecf4");
background.put("atelier-sulphurpool-dark", "#202746");
background.put("atelier-sulphurpool-light", "#f5f7ff");
background.put("atom-one-dark", "#282c34");
background.put("atom-one-dark-reasonable", "#282c34");
background.put("codepen-embed", "#222");
background.put("darcula", "#2b2b2b");
background.put("dark", "#444");
background.put("default", "#F0F0F0");
background.put("docco", "#f8f8ff");
background.put("dracula", "#282a36");
background.put("far", "#000080");
background.put("foundation", "#eee");
background.put("github", "#f8f8f8");
background.put("gml", "#222222");
background.put("gradient-dark", "linear-gradient(166deg, rgba(80,31,122,1) 0%, rgba(40,32,179,1) 80%)");
background.put("gruvbox-dark", "#282828");
background.put("gruvbox-light", "#fbf1c7");
background.put("hopscotch", "#322931");
background.put("hybrid", "#1d1f21");
background.put("ir-black", "#000");
background.put("isbl-editor-dark", "#404040");
background.put("kimbie.dark", "#221a0f");
background.put("kimbie.light", "#fbebd4");
background.put("lioshi", "#303030");
background.put("magula", "#f4f4f4");
background.put("mono-blue", "#eaeef3");
background.put("monokai", "#272822");
background.put("monokai-sublime", "#23241f");
background.put("night-owl", "#011627");
background.put("nnfx-dark", "#333");
background.put("nord", "#2E3440");
background.put("obsidian", "#282b2e");
background.put("ocean", "#2b303b");
background.put("paraiso-dark", "#2f1e2e");
background.put("paraiso-light", "#e7e9db");
background.put("purebasic", "#FFFFDF");
background.put("qtcreator_dark", "#000000");
background.put("railscasts", "#232323");
background.put("rainbow", "#474949");
background.put("routeros", "#f0f0f0");
background.put("shades-of-purple", "#2d2b57");
background.put("solarized-dark", "#002b36");
background.put("solarized-light", "#fdf6e3");
background.put("srcery", "#1C1B19");
background.put("sunburst", "#000");
background.put("tomorrow-night", "#1d1f21");
background.put("tomorrow-night-blue", "#002451");
background.put("tomorrow-night-bright", "black");
background.put("tomorrow-night-eighties", "#2d2d2d");
background.put("xt256", "#000");
background.put("vs2015", "#1E1E1E");
background.put("zenburn", "#3f3f3f");
}
/**
* Randomly select a light style
*
* @param random Random
* @return String of random
*/
public static String randomLight(Random random) {
return LIGHT_STYLE.get(random.nextInt(LIGHT_STYLE.size()));
}
/**
* Randomly select a dark style
*
* @param random Random
* @return String of random
*/
public static String randomDark(Random random) {
return DARK_STYLE.get(random.nextInt(DARK_STYLE.size()));
}
/**
* Randomly select a style
*
* @param random Random
* @return String of random
*/
public static String randomAll(Random random) {
if (random.nextBoolean()) {
return randomLight(random);
} else {
return randomDark(random);
}
}
public static String getBackgroundColor(String style) {
String color = background.get(style);
if (StringUtil.isNotEmpty(color)) {
return color;
}
return "#f7f7f8";
}
/**
* Does the highlight style exist?
*
* @param style Highlight style
* @return boolean
*/
public static boolean containsStyle(String style) {
return background.containsKey(style);
}
}

View File

@ -0,0 +1,54 @@
package com.power.doc.constants;
/**
* JAX-RS Annotations
*
* @author Zxq
*/
public interface JAXRSAnnotations {
/**
* JAX-RS@PATH
*/
String JAX_PATH = "Path";
/**
* JAX-RS@Produces
*/
String JAX_PRODUCES = "Produces";
/**
* JAX-RS@HeaderParam
*/
String JAX_HEADER_PARAM = "HeaderParam";
/**
* JAX-RS@PathParam
*/
String JAX_PATH_PARAM = "PathParam";
/**
* JAX-RS@QueryParam
*/
String JAX_QUERY_PARAM = "QueryParam";
/**
* JAX-RS@FormParam
*/
String JAX_FORM_PARAM = "FormParam";
/**
* JAX-RS@Consumes
*/
String JAX_CONSUMES = "Consumes";
/**
* JAX-RS@GET
*/
String GET = "GET";
/**
* JAX-RS@POST
*/
String POST = "POST";
/**
* JAX-RS@PUT
*/
String PUT = "PUT";
/**
* JAX-RS@DELETE
*/
String DELETE = "DELETE";
}

View File

@ -0,0 +1,47 @@
/*
* smart-doc https://github.com/shalousun/smart-doc
*
* Copyright (C) 2018-2021 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.constants;
/**
* http methods
*
* @author yu 2019/11/21.
*/
public enum Methods {
POST("POST"),
GET("GET"),
PUT("PUT"),
PATCH("PATCH"),
DELETE("DELETE"),
OPTIONS("OPTIONS");
private String value;
Methods(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}

View File

@ -0,0 +1,57 @@
/*
* smart-doc https://github.com/shalousun/smart-doc
*
* Copyright (C) 2018-2021 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.constants;
/**
* @author yu 2019/12/21.
*/
public interface SpringMvcAnnotations {
String REQUEST_MAPPING = "RequestMapping";
String GET_MAPPING = "GetMapping";
String POST_MAPPING = "PostMapping";
String PUT_MAPPING = "PutMapping";
String PATCH_MAPPING = "PatchMapping";
String DELETE_MAPPING = "DeleteMapping";
String REQUEST_HERDER = "RequestHeader";
String REQUEST_PARAM = "RequestParam";
String REQUEST_BODY = "RequestBody";
String CONTROLLER = "Controller";
String REST_CONTROLLER = "RestController";
String PATH_VARIABLE = "PathVariable";
String SESSION_ATTRIBUTE = "SessionAttribute";
String REQUEST_ATTRIBUTE="RequestAttribute";
}

View File

@ -0,0 +1,55 @@
/*
* smart-doc https://github.com/shalousun/smart-doc
*
* Copyright (C) 2018-2021 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.constants;
import java.util.ArrayList;
import java.util.List;
/**
* @author yu 2019/12/20.
*/
public enum SpringMvcRequestAnnotationsEnum {
PATH_VARIABLE("PathVariable"),
PATH_VARIABLE_FULLY("org.springframework.web.bind.annotation.PathVariable"),
REQ_PARAM("RequestParam"),
REQ_PARAM_FULLY("org.springframework.web.bind.annotation.RequestParam"),
REQUEST_BODY("RequestBody"),
REQUEST_BODY_FULLY("org.springframework.web.bind.annotation.RequestBody"),
REQUEST_HERDER("RequestHeader"),
REQUEST_HERDER_FULLY("org.springframework.web.bind.annotation.RequestHeader"),
;
private String value;
SpringMvcRequestAnnotationsEnum(String value) {
this.value = value;
}
public static List<String> listSpringMvcRequestAnnotations() {
List<String> annotations = new ArrayList<>();
for (SpringMvcRequestAnnotationsEnum annotation : SpringMvcRequestAnnotationsEnum.values()) {
annotations.add(annotation.value);
}
return annotations;
}
}

View File

@ -0,0 +1,72 @@
/*
* smart-doc https://github.com/shalousun/smart-doc
*
* Copyright (C) 2018-2021 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.constants;
/**
* @author yu 2019/9/21.
*/
public enum TemplateVariable {
DESC("desc"),
NAME("name"),
LIST("list"),
API_DOC_LIST("apiDocList"),
ERROR_CODE_LIST("errorCodeList"),
VERSION_LIST("revisionLogList"),
DEPENDENCY_LIST("dependencyList"),
HOME_PAGE("homePage"),
HTML("html"),
TITLE("title"),
STYLE("style"),
BACKGROUND("background"),
ERROR_LIST_TITLE("errorListTitle"),
CREATE_TIME("createTime"),
PROJECT_NAME("projectName"),
DICT_LIST("dictList"),
DICT_LIST_TITLE("dictListTitle"),
DICT_ORDER("dictListOrder"),
VERSION("version"),
PROTOCOL("protocol"),
AUTHOR("author"),
URI("uri"),
RPC_CONSUMER_CONFIG("consumerConfigExample"),
REQUEST_EXAMPLE("isRequestExample"),
RESPONSE_EXAMPLE("isResponseExample"),
DISPLAY_REQUEST_PARAMS("displayRequestParams"),
DISPLAY_RESPONSE_PARAMS("displayResponseParams"),
RESPONSE_LIST("respList"),
ORDER("order"),
INDEX_ALIAS("alias"),
DIRECTORY_TREE("directoryTree"),
HIGH_LIGHT_CSS_LINK("highlightCssLink"),
CSS_CND("css_cdn");
private String variable;
TemplateVariable(String variable) {
this.variable = variable;
}
public String getVariable() {
return this.variable;
}
}

View File

@ -0,0 +1,151 @@
/*
* smart-doc https://github.com/shalousun/smart-doc
*
* Copyright (C) 2018-2021 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.constants;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.power.doc.model.ApiConfig;
import org.apache.commons.lang3.StringUtils;
import java.io.IOException;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.text.SimpleDateFormat;
import java.util.*;
/**
* @author xingzi 2020/2/2
*/
public class TornaConstants {
public static final String ID = "id";
public static final String CODE = "code";
public static final String MESSAGE = "msg";
public static final String DATA = "data";
public static final String SUCCESS_CODE = "0";
public static final String YES = "1";
public static final String NO = "0";
public static final String ARRAY = "array";
public static final String CATEGORY_CREATE = "doc.category.create";
public static final String PUSH = "doc.push";
public static final String ENUM_PUSH = "enum.batch.push";
public static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
/**
* build torna params
*
* @param name interface name
* @param data json
* @param config ApiConfig
* @return Map
*/
public static Map<String, String> buildParams(String name, String data, ApiConfig config) {
Map<String, String> param = new HashMap<>(8);
try {
if (StringUtils.isNotBlank(data)) {
data = URLEncoder.encode(data, "utf-8");
}
// Public request parameters for pushing documents to Torna
param.put("name", name);
param.put("app_key", config.getAppKey());
param.put("data", data);
param.put("timestamp", getTime());
param.put("version", "1.0");
param.put("access_token", config.getAppToken());
String sign = buildSign(param, config.getSecret());
param.put("sign", sign);
return param;
} catch (IOException e) {
e.printStackTrace();
}
return param;
}
/**
* 构建签名
*
* @param paramsMap 参数
* @param secret 密钥
* @return String
*/
public static String buildSign(Map<String, ?> paramsMap, String secret) {
Set<String> keySet = paramsMap.keySet();
List<String> paramNames = new ArrayList<>(keySet);
Collections.sort(paramNames);
StringBuilder paramNameValue = new StringBuilder();
for (String paramName : paramNames) {
Object value = paramsMap.get(paramName);
if (value != null) {
paramNameValue.append(paramName).append(value);
}
}
String source = secret + paramNameValue.toString() + secret;
return md5(source);
}
/**
* Generate md5 and convert to uppercase
*
* @param message message
* @return String
*/
public static String md5(String message) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] input = message.getBytes();
byte[] buff = md.digest(input);
return byte2hex(buff);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* Convert byte array to hex
* @param bytes byte array
* @return String
*/
private static String byte2hex(byte[] bytes) {
StringBuilder sign = new StringBuilder();
for (int i = 0; i < bytes.length; i++) {
String hex = Integer.toHexString(bytes[i] & 0xFF);
if (hex.length() == 1) {
sign.append("0");
}
sign.append(hex.toUpperCase());
}
return sign.toString();
}
public static String getTime() {
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
}
}

View File

@ -0,0 +1,35 @@
/*
* smart-doc https://github.com/shalousun/smart-doc
*
* Copyright (C) 2018-2021 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.constants;
/**
* @author yu 2019/12/22.
*/
public interface ValidatorAnnotations {
String VALID = "Valid";
String NULL = "Null";
String VALIDATED = "Validated";
}

View File

@ -0,0 +1,53 @@
/*
* smart-doc https://github.com/shalousun/smart-doc
*
* Copyright (C) 2018-2021 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.factory;
import com.power.doc.constants.FrameworkEnum;
import com.power.doc.template.IDocBuildTemplate;
/**
* @author yu 2021/6/27.
*/
public class BuildTemplateFactory {
/**
* Get Doc build template
*
* @param framework framework name
* @param <T> API doc type
* @return Implements of IDocBuildTemplate
*/
public static <T> IDocBuildTemplate<T> getDocBuildTemplate(String framework) {
String className = FrameworkEnum.getClassNameByFramework(framework);
try {
return (IDocBuildTemplate) Class.forName(className).newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
throw new RuntimeException("The class=>" + className + " is not found , smart-doc currently supported framework name can only be set in [dubbo, spring].");
}
return null;
}
}

View File

@ -0,0 +1,72 @@
/*
* smart-doc https://github.com/shalousun/smart-doc
*
* Copyright (C) 2018-2021 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.filter;
import com.power.doc.constants.DocGlobalConstants;
import com.power.doc.model.ApiReturn;
import com.power.doc.utils.DocClassUtil;
import java.util.HashSet;
import java.util.Set;
/**
* @author yu 2020/4/17.
*/
public class BoxReturnFilter implements ReturnTypeFilter {
private static final Set<String> TYPE_SET = new HashSet<>();
static {
TYPE_SET.add("java.util.concurrent.Callable");
TYPE_SET.add("java.util.concurrent.Future");
TYPE_SET.add("java.util.concurrent.CompletableFuture");
TYPE_SET.add("org.springframework.web.context.request.async.DeferredResult");
TYPE_SET.add("org.springframework.web.context.request.async.WebAsyncTask");
TYPE_SET.add("reactor.core.publisher.Mono");
TYPE_SET.add("org.springframework.http.ResponseEntity");
}
@Override
public ApiReturn doFilter(String fullyName) {
if (TYPE_SET.stream().anyMatch(fullyName::startsWith)) {
ApiReturn apiReturn = new ApiReturn();
if (fullyName.contains("<")) {
String[] strings = DocClassUtil.getSimpleGicName(fullyName);
String newFullName = strings[0];
if (newFullName.contains("<")) {
apiReturn.setGenericCanonicalName(newFullName);
apiReturn.setSimpleName(newFullName.substring(0, newFullName.indexOf("<")));
} else {
apiReturn.setGenericCanonicalName(newFullName);
apiReturn.setSimpleName(newFullName);
}
} else {
//directly return Java Object
apiReturn.setGenericCanonicalName(DocGlobalConstants.JAVA_OBJECT_FULLY);
apiReturn.setSimpleName(DocGlobalConstants.JAVA_OBJECT_FULLY);
}
return apiReturn;
}
return null;
}
}

View File

@ -0,0 +1,45 @@
/*
* smart-doc https://github.com/shalousun/smart-doc
*
* Copyright (C) 2018-2021 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.filter;
import com.power.doc.model.ApiReturn;
/**
* must be put last
*
* @author yu 2020/4/17.
*/
public class DefaultReturnFilter implements ReturnTypeFilter {
@Override
public ApiReturn doFilter(String fullyName) {
ApiReturn apiReturn = new ApiReturn();
apiReturn.setGenericCanonicalName(fullyName);
if (fullyName.contains("<")) {
apiReturn.setSimpleName(fullyName.substring(0, fullyName.indexOf("<")));
} else {
apiReturn.setSimpleName(fullyName);
}
return apiReturn;
}
}

View File

@ -0,0 +1,41 @@
/*
* smart-doc https://github.com/shalousun/smart-doc
*
* Copyright (C) 2018-2021 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.filter;
import com.power.doc.model.ApiReturn;
/**
* Chain Of Responsibility Pattern
*
* @author yu 2020/4/17.
*/
public interface ReturnTypeFilter {
/**
* filter return Type
*
* @param fullyName full type name
* @return ApiReturn
*/
ApiReturn doFilter(String fullyName);
}

View File

@ -0,0 +1,61 @@
/*
* smart-doc https://github.com/shalousun/smart-doc
*
* Copyright (C) 2018-2021 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.filter;
import com.power.doc.model.ApiReturn;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
/**
* @author yu 2020/4/17.
*/
public class ReturnTypeProcessor {
private List<ReturnTypeFilter> filters = new ArrayList<>();
private String typeName;
public String getTypeName() {
return typeName;
}
public void setTypeName(String typeName) {
this.typeName = typeName;
}
public ApiReturn process() {
filters.add(new WebFluxReturnFilter());
filters.add(new BoxReturnFilter());
filters.add(new DefaultReturnFilter());
ApiReturn apiReturn = null;
for (ReturnTypeFilter filter : filters) {
apiReturn = filter.doFilter(typeName);
if (Objects.nonNull(apiReturn)) {
return apiReturn;
}
}
return null;
}
}

View File

@ -0,0 +1,49 @@
/*
* smart-doc https://github.com/shalousun/smart-doc
*
* Copyright (C) 2018-2021 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.filter;
import com.power.doc.constants.DocGlobalConstants;
import com.power.doc.model.ApiReturn;
/**
* @author yu 2020/4/17.
*/
public class WebFluxReturnFilter implements ReturnTypeFilter {
private static final String FLUX = "reactor.core.publisher.Flux";
@Override
public ApiReturn doFilter(String fullyName) {
//support web flux
if (fullyName.startsWith(FLUX)) {
ApiReturn apiReturn = new ApiReturn();
// rewrite type name
fullyName = fullyName.replace(FLUX, DocGlobalConstants.JAVA_LIST_FULLY);
apiReturn.setGenericCanonicalName(fullyName);
apiReturn.setSimpleName(DocGlobalConstants.JAVA_LIST_FULLY);
return apiReturn;
}
return null;
}
}

View File

@ -0,0 +1,39 @@
/*
* smart-doc https://github.com/shalousun/smart-doc
*
* Copyright (C) 2018-2021 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.function;
import org.beetl.core.Context;
import org.beetl.core.Function;
/**
* @author yu 2021/6/26.
*/
public class HtmlEscape implements Function {
@Override
public String call(Object[] paras, Context ctx) {
String str = String.valueOf(paras[0]).replaceAll("&", "&amp;")
.replaceAll("\"","&quot;");
return str;
}
}

View File

@ -0,0 +1,18 @@
package com.power.doc.function;
import org.beetl.core.Context;
import org.beetl.core.Function;
/**
* @author yu 2021/7/24.
*/
public class RemoveLineBreaks implements Function {
@Override
public String call(Object[] paras, Context ctx) {
String str = String.valueOf(paras[0])
.replaceAll("\n", " ")
.replaceAll("\r"," ");
return str;
}
}

View File

@ -0,0 +1,65 @@
/*
* smart-doc https://github.com/shalousun/smart-doc
*
* Copyright (C) 2018-2021 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.handler;
import com.power.doc.builder.ProjectDocConfigBuilder;
import com.power.doc.constants.JAXRSAnnotations;
import com.power.doc.model.ApiReqParam;
import com.power.doc.utils.DocUtil;
import com.thoughtworks.qdox.model.JavaAnnotation;
import com.thoughtworks.qdox.model.JavaMethod;
import java.util.ArrayList;
import java.util.List;
/**
*
*
* @author Zxq
*/
public class JaxrsHeaderHandler {
/**
* Handle JAX RS Header
* @param method method
* @param projectBuilder ProjectDocConfigBuilder
* @return list of ApiReqParam
*/
public List<ApiReqParam> handle(JavaMethod method, ProjectDocConfigBuilder projectBuilder) {
List<JavaAnnotation> annotations = method.getAnnotations();
List<ApiReqParam> ApiReqParams = new ArrayList<>();
for (JavaAnnotation annotation : annotations) {
// hit target head annotation
if (JAXRSAnnotations.JAX_HEADER_PARAM.equals(annotation.getType().getName())) {
ApiReqParam ApiReqParam = new ApiReqParam();
// Obtain header value
ApiReqParam.setValue(DocUtil.getRequestHeaderValue(annotation).replaceAll("\"", ""));
ApiReqParam.setName(DocUtil.getRequestHeaderValue(annotation).replaceAll("\"", ""));
ApiReqParam.setType("string");
ApiReqParam.setDesc("desc");
ApiReqParams.add(ApiReqParam);
}
}
return ApiReqParams;
}
}

View File

@ -0,0 +1,144 @@
/*
* smart-doc https://github.com/shalousun/smart-doc
*
* Copyright (C) 2018-2021 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.handler;
import com.power.common.util.StringUtil;
import com.power.common.util.UrlUtil;
import com.power.doc.builder.ProjectDocConfigBuilder;
import com.power.doc.constants.*;
import com.power.doc.model.request.JaxrsPathMapping;
import com.power.doc.utils.DocUrlUtil;
import com.power.doc.utils.DocUtil;
import com.thoughtworks.qdox.model.JavaAnnotation;
import com.thoughtworks.qdox.model.JavaMethod;
import java.util.*;
import static com.power.doc.constants.DocTags.DEPRECATED;
import static com.power.doc.constants.DocTags.IGNORE;
/**
* dubbo Rest 注解处理器
*
* @author Zxq
*/
public class JaxrsPathHandler {
/**
* ANNOTATION_NAMES
*/
private static final Set<String> ANNOTATION_NAMES = Collections.unmodifiableSet(new HashSet<>(
Arrays.asList(JAXRSAnnotations.DELETE,
DocGlobalConstants.JAXB_DELETE_FULLY,
JAXRSAnnotations.PUT, DocGlobalConstants.JAX_PUT_FULLY,
JAXRSAnnotations.GET, DocGlobalConstants.JAX_GET_FULLY,
JAXRSAnnotations.POST, DocGlobalConstants.JAX_POST_FULLY
)));
Map<String, String> constantsMap;
public JaxrsPathMapping handle(ProjectDocConfigBuilder projectBuilder, String baseUrl, JavaMethod method) {
List<JavaAnnotation> annotations = method.getAnnotations();
this.constantsMap = projectBuilder.getConstantsMap();
String url;
String methodType = null;
String shortUrl = null;
String mediaType = null;
String serverUrl = projectBuilder.getServerUrl();
String contextPath = projectBuilder.getApiConfig().getPathPrefix();
boolean deprecated = false;
for (JavaAnnotation annotation : annotations) {
String annotationName = annotation.getType().getName();
if (JAXRSAnnotations.JAX_PRODUCES.equals(annotationName)) {
mediaType = DocUtil.getRequestHeaderValue(annotation);
}
// Deprecated annotation on method
if (DocAnnotationConstants.DEPRECATED.equals(annotationName)) {
deprecated = true;
}
if (JAXRSAnnotations.JAX_PATH.equals(annotationName) ||
JAXRSAnnotations.JAX_PATH_PARAM.equals(annotationName) ||
DocGlobalConstants.JAX_PATH_FULLY
.equals(annotationName)) {
shortUrl = DocUtil.handleMappingValue(annotation);
}
if (ANNOTATION_NAMES.contains(annotationName)) {
methodType = annotationName;
}
}
// @deprecated tag on method
if (Objects.nonNull(method.getTagByName(DEPRECATED))) {
deprecated = true;
}
JaxrsPathMapping jaxrsPathMapping = getJaxbPathMapping(projectBuilder, baseUrl, method, shortUrl, serverUrl, contextPath);
if (jaxrsPathMapping != null) {
return jaxrsPathMapping.setDeprecated(deprecated)
.setMethodType(methodType)
.setMediaType(mediaType);
}
return null;
}
private JaxrsPathMapping getJaxbPathMapping(ProjectDocConfigBuilder projectBuilder,
String baseUrl, JavaMethod method,
String shortUrl,
String serverUrl,
String contextPath) {
String url;
if (Objects.nonNull(shortUrl)) {
if (Objects.nonNull(method.getTagByName(IGNORE))) {
return null;
}
shortUrl = StringUtil.removeQuotes(shortUrl);
List<String> urls = DocUtil.split(shortUrl);
url = String.join(DocGlobalConstants.PATH_DELIMITER, serverUrl, contextPath, baseUrl, shortUrl);
shortUrl = String.join(DocGlobalConstants.PATH_DELIMITER, DocGlobalConstants.PATH_DELIMITER, contextPath, baseUrl, shortUrl);
if (urls.size() > 1) {
url = DocUrlUtil.getMvcUrls(serverUrl, contextPath + "/" + baseUrl, urls);
shortUrl = DocUrlUtil.getMvcUrls(DocGlobalConstants.EMPTY, contextPath + "/" + baseUrl, urls);
}
for (Map.Entry<String, String> entry : constantsMap.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
if (url.contains(key)) {
url = url.replace(key, value).replace("+", "");
}
if (shortUrl.contains(key)) {
shortUrl = shortUrl.replace(key, value).replace("+", "");
}
}
String urlSuffix = projectBuilder.getApiConfig().getUrlSuffix();
url = UrlUtil.simplifyUrl(url);
shortUrl = UrlUtil.simplifyUrl(shortUrl);
if (StringUtil.isNotEmpty(urlSuffix)) {
url += urlSuffix;
shortUrl += urlSuffix;
}
return JaxrsPathMapping.builder()
.setUrl(StringUtil.trim(url))
.setShortUrl(StringUtil.trim(shortUrl));
}
return null;
}
}

View File

@ -0,0 +1,179 @@
/*
* smart-doc https://github.com/shalousun/smart-doc
*
* Copyright (C) 2018-2021 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.handler;
import com.power.common.util.StringUtil;
import com.power.doc.builder.ProjectDocConfigBuilder;
import com.power.doc.constants.DocAnnotationConstants;
import com.power.doc.constants.DocTags;
import com.power.doc.constants.SpringMvcAnnotations;
import com.power.doc.model.ApiReqParam;
import com.power.doc.utils.DocClassUtil;
import com.power.doc.utils.DocUtil;
import com.thoughtworks.qdox.model.JavaAnnotation;
import com.thoughtworks.qdox.model.JavaMethod;
import com.thoughtworks.qdox.model.JavaParameter;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* @author yu 2019/12/22.
*/
public class SpringMVCRequestHeaderHandler {
/**
* handle Spring MVC Request Header
*
* @param method JavaMethod
* @param projectBuilder projectBuilder
* @return list of ApiReqHeader
*/
public List<ApiReqParam> handle(JavaMethod method, ProjectDocConfigBuilder projectBuilder) {
Map<String, String> constantsMap = projectBuilder.getConstantsMap();
List<ApiReqParam> mappingHeaders = new ArrayList<>();
List<JavaAnnotation> annotations = method.getAnnotations();
for (JavaAnnotation annotation : annotations) {
String annotationName = annotation.getType().getValue();
Object headersObject = annotation.getNamedParameter("headers");
if (!isMapping(annotationName) || Objects.isNull(headersObject)) {
continue;
}
String mappingHeader = StringUtil.removeQuotes(headersObject.toString());
if (!mappingHeader.startsWith("[")) {
processMappingHeaders(mappingHeader, mappingHeaders);
continue;
}
List<String> headers = (LinkedList) headersObject;
for (String str : headers) {
String header = StringUtil.removeQuotes(str);
if (header.startsWith("!")) {
continue;
}
processMappingHeaders(header, mappingHeaders);
}
}
List<ApiReqParam> reqHeaders = new ArrayList<>();
for (JavaParameter javaParameter : method.getParameters()) {
List<JavaAnnotation> javaAnnotations = javaParameter.getAnnotations();
String className = method.getDeclaringClass().getCanonicalName();
Map<String, String> paramMap = DocUtil.getParamsComments(method, DocTags.PARAM, className);
String paramName = javaParameter.getName();
ApiReqParam apiReqHeader;
for (JavaAnnotation annotation : javaAnnotations) {
String annotationName = annotation.getType().getValue();
if (SpringMvcAnnotations.REQUEST_HERDER.equals(annotationName)) {
apiReqHeader = new ApiReqParam();
Map<String, Object> requestHeaderMap = annotation.getNamedParameterMap();
if (requestHeaderMap.get(DocAnnotationConstants.VALUE_PROP) != null) {
String attribute = DocUtil.handleRequestHeaderValue(annotation);
String constValue = ((String) requestHeaderMap.get(DocAnnotationConstants.VALUE_PROP)).replaceAll("\"", "");
if (StringUtil.isEmpty(attribute)) {
apiReqHeader.setName(constValue);
} else {
Object value = constantsMap.get(attribute);
if (value == null) {
apiReqHeader.setName(constValue);
} else {
apiReqHeader.setName((String) value);
}
}
} else {
apiReqHeader.setName(paramName);
}
StringBuilder desc = new StringBuilder();
String comments = paramMap.get(paramName);
desc.append(comments);
if (requestHeaderMap.get(DocAnnotationConstants.DEFAULT_VALUE_PROP) != null) {
apiReqHeader.setValue(StringUtil.removeQuotes((String) requestHeaderMap.get(DocAnnotationConstants.DEFAULT_VALUE_PROP)));
desc.append("(defaultValue: ")
.append(StringUtil.removeQuotes((String) requestHeaderMap.get(DocAnnotationConstants.DEFAULT_VALUE_PROP)))
.append(")");
}
apiReqHeader.setDesc(desc.toString());
if (requestHeaderMap.get(DocAnnotationConstants.REQUIRED_PROP) != null) {
apiReqHeader.setRequired(!Boolean.FALSE.toString()
.equals(requestHeaderMap.get(DocAnnotationConstants.REQUIRED_PROP)));
} else {
apiReqHeader.setRequired(true);
}
String typeName = javaParameter.getType().getValue().toLowerCase();
apiReqHeader.setType(DocClassUtil.processTypeNameForParams(typeName));
reqHeaders.add(apiReqHeader);
break;
}
}
}
List<ApiReqParam> allApiReqHeaders = Stream.of(mappingHeaders, reqHeaders)
.flatMap(Collection::stream)
.distinct()
.collect(Collectors.toList());
return allApiReqHeaders;
}
private boolean isMapping(String annotationName) {
switch (annotationName) {
case "GetMapping":
case "RequestMapping":
case "PostMapping":
case "PutMapping":
case "PatchMapping":
case "DeleteMapping":
return true;
default:
return false;
}
}
public void processMappingHeaders(String header, List<ApiReqParam> mappingHeaders) {
if (header.contains("!=")) {
String headerName = header.substring(0, header.indexOf("!"));
ApiReqParam apiReqHeader = ApiReqParam.builder()
.setName(headerName)
.setRequired(true)
.setValue(null)
.setDesc("header condition")
.setType("string");
mappingHeaders.add(apiReqHeader);
} else {
String headerName;
String headerValue = null;
if (header.contains("=")) {
int index = header.indexOf("=");
headerName = header.substring(0, index);
headerValue = header.substring(index + 1);
} else {
headerName = header;
}
ApiReqParam apiReqHeader = ApiReqParam.builder()
.setName(headerName)
.setRequired(true)
.setValue(headerValue)
.setDesc("header condition")
.setType("string");
mappingHeaders.add(apiReqHeader);
}
}
}

View File

@ -0,0 +1,152 @@
/*
* smart-doc https://github.com/shalousun/smart-doc
*
* Copyright (C) 2018-2021 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.handler;
import com.power.common.util.StringUtil;
import com.power.common.util.UrlUtil;
import com.power.doc.builder.ProjectDocConfigBuilder;
import com.power.doc.constants.DocAnnotationConstants;
import com.power.doc.constants.DocGlobalConstants;
import com.power.doc.constants.Methods;
import com.power.doc.constants.SpringMvcAnnotations;
import com.power.doc.model.request.RequestMapping;
import com.power.doc.utils.DocUrlUtil;
import com.power.doc.utils.DocUtil;
import com.thoughtworks.qdox.model.JavaAnnotation;
import com.thoughtworks.qdox.model.JavaMethod;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import static com.power.doc.constants.DocTags.DEPRECATED;
import static com.power.doc.constants.DocTags.IGNORE;
/**
* @author yu 2019/12/22.
*/
public class SpringMVCRequestMappingHandler {
/**
* handle spring request mapping
*
* @param projectBuilder projectBuilder
* @param controllerBaseUrl spring mvc controller base url
* @param method JavaMethod
* @param constantsMap project constant container
* @return RequestMapping
*/
public RequestMapping handle(ProjectDocConfigBuilder projectBuilder, String controllerBaseUrl, JavaMethod method, Map<String, String> constantsMap) {
List<JavaAnnotation> annotations = method.getAnnotations();
String url;
String methodType = null;
String shortUrl = null;
String mediaType = null;
String serverUrl = projectBuilder.getServerUrl();
String contextPath = projectBuilder.getApiConfig().getPathPrefix();
boolean deprecated = false;
for (JavaAnnotation annotation : annotations) {
String annotationName = annotation.getType().getName();
Object produces = annotation.getNamedParameter("produces");
if (Objects.nonNull(produces)) {
mediaType = produces.toString();
}
if (DocAnnotationConstants.DEPRECATED.equals(annotationName)) {
deprecated = true;
}
if (SpringMvcAnnotations.REQUEST_MAPPING.equals(annotationName) || DocGlobalConstants.REQUEST_MAPPING_FULLY.equals(annotationName)) {
shortUrl = DocUtil.handleMappingValue(annotation);
Object nameParam = annotation.getNamedParameter("method");
if (Objects.nonNull(nameParam)) {
methodType = nameParam.toString();
methodType = DocUtil.handleHttpMethod(methodType);
} else {
methodType = Methods.GET.getValue();
}
} else if (SpringMvcAnnotations.GET_MAPPING.equals(annotationName) || DocGlobalConstants.GET_MAPPING_FULLY.equals(annotationName)) {
shortUrl = DocUtil.handleMappingValue(annotation);
methodType = Methods.GET.getValue();
} else if (SpringMvcAnnotations.POST_MAPPING.equals(annotationName) || DocGlobalConstants.POST_MAPPING_FULLY.equals(annotationName)) {
shortUrl = DocUtil.handleMappingValue(annotation);
methodType = Methods.POST.getValue();
} else if (SpringMvcAnnotations.PUT_MAPPING.equals(annotationName) || DocGlobalConstants.PUT_MAPPING_FULLY.equals(annotationName)) {
shortUrl = DocUtil.handleMappingValue(annotation);
methodType = Methods.PUT.getValue();
} else if (SpringMvcAnnotations.PATCH_MAPPING.equals(annotationName) || DocGlobalConstants.PATCH_MAPPING_FULLY.equals(annotationName)) {
shortUrl = DocUtil.handleMappingValue(annotation);
methodType = Methods.PATCH.getValue();
} else if (SpringMvcAnnotations.DELETE_MAPPING.equals(annotationName) || DocGlobalConstants.DELETE_MAPPING_FULLY.equals(annotationName)) {
shortUrl = DocUtil.handleMappingValue(annotation);
methodType = Methods.DELETE.getValue();
}
}
if (Objects.nonNull(method.getTagByName(DEPRECATED))) {
deprecated = true;
}
if (Objects.nonNull(shortUrl)) {
if (Objects.nonNull(method.getTagByName(IGNORE))) {
return null;
}
shortUrl = StringUtil.removeQuotes(shortUrl);
List<String> urls = DocUtil.split(shortUrl);
if (urls.size() > 1) {
url = DocUrlUtil.getMvcUrls(serverUrl, contextPath + "/" + controllerBaseUrl, urls);
shortUrl = DocUrlUtil.getMvcUrls(DocGlobalConstants.EMPTY, contextPath + "/" + controllerBaseUrl, urls);
} else {
url = String.join(DocGlobalConstants.PATH_DELIMITER, serverUrl, contextPath, controllerBaseUrl, shortUrl);
shortUrl = String.join(DocGlobalConstants.PATH_DELIMITER, DocGlobalConstants.PATH_DELIMITER, contextPath, controllerBaseUrl, shortUrl);
}
for (Map.Entry<String, String> entry : constantsMap.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
url = delConstantsUrl(url, key, value);
shortUrl = delConstantsUrl(shortUrl, key, value);
}
String urlSuffix = projectBuilder.getApiConfig().getUrlSuffix();
if (StringUtil.isNotEmpty(urlSuffix)) {
url = UrlUtil.simplifyUrl(StringUtil.trim(url)) + urlSuffix;
shortUrl = UrlUtil.simplifyUrl(StringUtil.trim(shortUrl)) + urlSuffix;
} else {
url = UrlUtil.simplifyUrl(StringUtil.trim(url));
shortUrl = UrlUtil.simplifyUrl(StringUtil.trim(shortUrl));
}
return RequestMapping.builder().setMediaType(mediaType).setMethodType(methodType)
.setUrl(url).setShortUrl(shortUrl).setDeprecated(deprecated);
}
return null;
}
public static String delConstantsUrl(String url, String replaceKey, String replaceValue) {
url = StringUtil.trim(url);
url = url.replace("+", "");
url = UrlUtil.simplifyUrl(url);
String[] pathWords = url.split("/");
for (String word : pathWords) {
if (word.equals(replaceKey)) {
url = url.replace(replaceKey, replaceValue);
return url;
}
}
return url;
}
}

View File

@ -0,0 +1,203 @@
/*
* smart-doc https://github.com/shalousun/smart-doc
*
* Copyright (C) 2018-2021 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.helper;
import com.power.common.util.RandomUtil;
import com.power.common.util.StringUtil;
import com.power.doc.builder.ProjectDocConfigBuilder;
import com.power.doc.constants.DocGlobalConstants;
import com.power.doc.constants.DocTags;
import com.power.doc.model.ApiConfig;
import com.power.doc.model.CustomField;
import com.power.doc.model.DocJavaField;
import com.power.doc.model.FormData;
import com.power.doc.utils.DocClassUtil;
import com.power.doc.utils.DocUtil;
import com.power.doc.utils.JavaClassUtil;
import com.power.doc.utils.JavaClassValidateUtil;
import com.thoughtworks.qdox.model.JavaClass;
import com.thoughtworks.qdox.model.JavaField;
import java.util.*;
/**
* @author yu 2019/12/25.
*/
public class FormDataBuildHelper {
/**
* build form data
*
* @param className class name
* @param registryClasses Class container
* @param counter invoked counter
* @param builder ProjectDocConfigBuilder
* @param pre pre
* @return list of FormData
*/
public static List<FormData> getFormData(String className, Map<String, String> registryClasses, int counter, ProjectDocConfigBuilder builder, String pre) {
if (StringUtil.isEmpty(className)) {
throw new RuntimeException("Class name can't be null or empty.");
}
ApiConfig apiConfig = builder.getApiConfig();
List<FormData> formDataList = new ArrayList<>();
if (counter > apiConfig.getRecursionLimit()) {
return formDataList;
}
// Check circular reference
if (registryClasses.containsKey(className) && counter > registryClasses.size()) {
return formDataList;
}
// Registry class
registryClasses.put(className, className);
counter++;
boolean skipTransientField = apiConfig.isSkipTransientField();
boolean requestFieldToUnderline = apiConfig.isRequestFieldToUnderline();
boolean responseFieldToUnderline = apiConfig.isResponseFieldToUnderline();
String simpleName = DocClassUtil.getSimpleName(className);
String[] globGicName = DocClassUtil.getSimpleGicName(className);
JavaClass cls = builder.getJavaProjectBuilder().getClassByName(simpleName);
List<DocJavaField> fields = JavaClassUtil.getFields(cls, 0, new LinkedHashMap<>());
if (JavaClassValidateUtil.isPrimitive(simpleName)) {
FormData formData = new FormData();
formData.setKey(pre);
formData.setType("text");
formData.setValue(StringUtil.removeQuotes(RandomUtil.randomValueByType(className)));
formDataList.add(formData);
return formDataList;
}
if (JavaClassValidateUtil.isCollection(simpleName) || JavaClassValidateUtil.isArray(simpleName)) {
String gicName = globGicName[0];
if (JavaClassValidateUtil.isArray(gicName)) {
gicName = gicName.substring(0, gicName.indexOf("["));
}
if (JavaClassValidateUtil.isPrimitive(gicName)) {
pre = pre.substring(0, pre.lastIndexOf("."));
}
formDataList.addAll(getFormData(gicName, registryClasses, counter, builder, pre + "[]"));
}
int n = 0;
out:
for (DocJavaField docField : fields) {
JavaField field = docField.getJavaField();
String fieldName = field.getName();
String subTypeName = docField.getFullyQualifiedName();
String fieldGicName = docField.getGenericCanonicalName();
JavaClass javaClass = field.getType();
if (field.isStatic() || "this$0".equals(fieldName) ||
JavaClassValidateUtil.isIgnoreFieldTypes(subTypeName)) {
continue;
}
if (field.isTransient() && skipTransientField) {
continue;
}
if (responseFieldToUnderline || requestFieldToUnderline) {
fieldName = StringUtil.camelToUnderline(fieldName);
}
Map<String, String> tagsMap = DocUtil.getFieldTagsValue(field, docField);
if (tagsMap.containsKey(DocTags.IGNORE)) {
continue out;
}
String typeSimpleName = field.getType().getSimpleName();
if (JavaClassValidateUtil.isMap(subTypeName)) {
continue;
}
String comment = docField.getComment();
if (StringUtil.isNotEmpty(comment)) {
comment = DocUtil.replaceNewLineToHtmlBr(comment);
}
if (JavaClassValidateUtil.isFile(fieldGicName)) {
FormData formData = new FormData();
formData.setKey(pre + fieldName);
formData.setType("file");
formData.setDescription(comment);
formData.setValue("");
formDataList.add(formData);
} else if (JavaClassValidateUtil.isPrimitive(subTypeName)) {
String fieldValue = "";
if (tagsMap.containsKey(DocTags.MOCK) && StringUtil.isNotEmpty(tagsMap.get(DocTags.MOCK))) {
fieldValue = tagsMap.get(DocTags.MOCK);
} else {
fieldValue = DocUtil.getValByTypeAndFieldName(typeSimpleName, field.getName());
}
CustomField customRequestField = builder.getCustomReqFieldMap().get(fieldName);
// cover request value
if (Objects.nonNull(customRequestField) && Objects.nonNull(customRequestField.getValue())
&& JavaClassUtil.isTargetChildClass(simpleName, customRequestField.getOwnerClassName())) {
fieldValue = String.valueOf(customRequestField.getValue());
}
FormData formData = new FormData();
formData.setKey(pre + fieldName);
formData.setType("text");
formData.setValue(StringUtil.removeQuotes(fieldValue));
formData.setDescription(comment);
formDataList.add(formData);
} else if (javaClass.isEnum()) {
Object value = JavaClassUtil.getEnumValue(javaClass, Boolean.TRUE);
if (tagsMap.containsKey(DocTags.MOCK) && StringUtil.isNotEmpty(tagsMap.get(DocTags.MOCK))) {
value = tagsMap.get(DocTags.MOCK);
}
FormData formData = new FormData();
formData.setKey(pre + fieldName);
formData.setType("text");
formData.setValue(StringUtil.removeQuotes(String.valueOf(value)));
formData.setDescription(comment);
formDataList.add(formData);
} else if (JavaClassValidateUtil.isCollection(subTypeName)) {
String gNameTemp = field.getType().getGenericCanonicalName();
String[] gNameArr = DocClassUtil.getSimpleGicName(gNameTemp);
if (gNameArr.length == 0) {
continue out;
}
String gName = DocClassUtil.getSimpleGicName(gNameTemp)[0];
if (!JavaClassValidateUtil.isPrimitive(gName)) {
if (!simpleName.equals(gName) && !gName.equals(simpleName)) {
if (gName.length() == 1) {
int len = globGicName.length;
if (len > 0) {
String gicName = (n < len) ? globGicName[n] : globGicName[len - 1];
if (!JavaClassValidateUtil.isPrimitive(gicName) && !simpleName.equals(gicName)) {
formDataList.addAll(getFormData(gicName, registryClasses, counter, builder, pre + fieldName + "[0]."));
}
}
} else {
formDataList.addAll(getFormData(gName, registryClasses, counter, builder, pre + fieldName + "[0]."));
}
}
}
} else if (subTypeName.length() == 1 || DocGlobalConstants.JAVA_OBJECT_FULLY.equals(subTypeName)) {
// For Generics,do nothing, spring mvc not support
// if (n < globGicName.length) {
// String gicName = globGicName[n];
// formDataList.addAll(getFormData(gicName, registryClasses, counter, builder, pre + fieldName + "."));
// }
// n++;
continue;
} else {
formDataList.addAll(getFormData(fieldGicName, registryClasses, counter, builder, pre + fieldName + "."));
}
}
return formDataList;
}
}

View File

@ -0,0 +1,465 @@
/*
* smart-doc https://github.com/shalousun/smart-doc
*
* Copyright (C) 2018-2021 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.helper;
import com.power.common.util.StringUtil;
import com.power.doc.builder.ProjectDocConfigBuilder;
import com.power.doc.constants.DocAnnotationConstants;
import com.power.doc.constants.DocGlobalConstants;
import com.power.doc.constants.DocTags;
import com.power.doc.constants.ValidatorAnnotations;
import com.power.doc.model.*;
import com.power.doc.utils.*;
import com.thoughtworks.qdox.model.*;
import com.thoughtworks.qdox.model.expression.AnnotationValue;
import java.util.*;
import static com.power.doc.constants.DocGlobalConstants.JSON_PROPERTY_READ_ONLY;
import static com.power.doc.constants.DocGlobalConstants.JSON_PROPERTY_WRITE_ONLY;
import static com.power.doc.constants.DocTags.IGNORE_RESPONSE_BODY_ADVICE;
/**
* @author yu 2019/12/21.
*/
public class JsonBuildHelper {
/**
* build return json
*
* @param docJavaMethod The JavaMethod object
* @param builder ProjectDocConfigBuilder builder
* @return String
*/
public static String buildReturnJson(DocJavaMethod docJavaMethod, ProjectDocConfigBuilder builder) {
JavaMethod method = docJavaMethod.getJavaMethod();
String responseBodyAdvice = null;
if (Objects.nonNull(builder.getApiConfig().getResponseBodyAdvice())) {
responseBodyAdvice = builder.getApiConfig().getResponseBodyAdvice().getClassName();
}
if (method.getReturns().isVoid() && Objects.isNull(responseBodyAdvice)) {
return "Return void.";
}
DocletTag downloadTag = method.getTagByName(DocTags.DOWNLOAD);
if (Objects.nonNull(downloadTag)) {
return "File download.";
}
if (method.getReturns().isEnum() && Objects.isNull(responseBodyAdvice)) {
return StringUtil.removeQuotes(String.valueOf(JavaClassUtil.getEnumValue(method.getReturns(), Boolean.FALSE)));
}
if (method.getReturns().isPrimitive() && Objects.isNull(responseBodyAdvice)) {
String typeName = method.getReturnType().getCanonicalName();
return StringUtil.removeQuotes(DocUtil.jsonValueByType(typeName));
}
if (DocGlobalConstants.JAVA_STRING_FULLY.equals(method.getReturnType().getGenericCanonicalName())
&& Objects.isNull(responseBodyAdvice)) {
return "string";
}
String returnTypeGenericCanonicalName = method.getReturnType().getGenericCanonicalName();
if (Objects.nonNull(responseBodyAdvice)
&& Objects.isNull(method.getTagByName(IGNORE_RESPONSE_BODY_ADVICE))) {
if (!returnTypeGenericCanonicalName.startsWith(responseBodyAdvice)) {
StringBuilder sb = new StringBuilder();
sb.append(responseBodyAdvice)
.append("<")
.append(returnTypeGenericCanonicalName).append(">");
returnTypeGenericCanonicalName = sb.toString();
}
}
ApiReturn apiReturn = DocClassUtil.processReturnType(returnTypeGenericCanonicalName);
String typeName = apiReturn.getSimpleName();
if (JavaClassValidateUtil.isFileDownloadResource(typeName)) {
docJavaMethod.setDownload(true);
return "File download.";
}
Map<String, JavaType> actualTypesMap = docJavaMethod.getActualTypesMap();
String returnType = apiReturn.getGenericCanonicalName();
if (Objects.nonNull(actualTypesMap)) {
for (Map.Entry<String, JavaType> entry : actualTypesMap.entrySet()) {
typeName = typeName.replace(entry.getKey(), entry.getValue().getCanonicalName());
returnType = returnType.replace(entry.getKey(), entry.getValue().getCanonicalName());
}
}
if (JavaClassValidateUtil.isPrimitive(typeName)) {
if (DocGlobalConstants.JAVA_STRING_FULLY.equals(typeName)) {
return "string";
}
return StringUtil.removeQuotes(DocUtil.jsonValueByType(typeName));
}
return JsonUtil.toPrettyFormat(buildJson(typeName, returnType, Boolean.TRUE, 0,
new HashMap<>(), new ArrayList<>(0), builder));
}
/**
* @param typeName type name
* @param genericCanonicalName genericCanonicalName
* @param isResp Response flag
* @param counter Recursive counter
* @param registryClasses class container
* @param groupClasses valid group class
* @param builder project config builder
* @return String
*/
public static String buildJson(String typeName, String genericCanonicalName,
boolean isResp, int counter, Map<String, String> registryClasses, List<String> groupClasses, ProjectDocConfigBuilder builder) {
Map<String, String> genericMap = new HashMap<>(10);
JavaClass javaClass = builder.getJavaProjectBuilder().getClassByName(typeName);
ApiConfig apiConfig = builder.getApiConfig();
if (counter > apiConfig.getRecursionLimit()) {
return "{\"$ref\":\"...\"}";
}
if (registryClasses.containsKey(typeName) && counter > registryClasses.size()) {
return "{\"$ref\":\"...\"}";
}
int nextLevel = counter + 1;
registryClasses.put(typeName, typeName);
if (JavaClassValidateUtil.isMvcIgnoreParams(typeName, builder.getApiConfig().getIgnoreRequestParams())) {
if (DocGlobalConstants.MODE_AND_VIEW_FULLY.equals(typeName)) {
return "Forward or redirect to a page view.";
} else {
return "Error restful return.";
}
}
if (JavaClassValidateUtil.isPrimitive(typeName)) {
return StringUtil.removeQuotes(DocUtil.jsonValueByType(typeName));
}
if (javaClass.isEnum()) {
return StringUtil.removeQuotes(String.valueOf(JavaClassUtil.getEnumValue(javaClass, Boolean.FALSE)));
}
boolean skipTransientField = apiConfig.isSkipTransientField();
StringBuilder data0 = new StringBuilder();
JavaClass cls = builder.getClassByName(typeName);
data0.append("{");
String[] globGicName = DocClassUtil.getSimpleGicName(genericCanonicalName);
if (Objects.isNull(globGicName) || globGicName.length < 1) {
// obtain generics from parent class
JavaClass superJavaClass = cls != null ? cls.getSuperJavaClass() : null;
if (Objects.nonNull(superJavaClass) && !"Object".equals(superJavaClass.getSimpleName())) {
globGicName = DocClassUtil.getSimpleGicName(superJavaClass.getGenericFullyQualifiedName());
}
}
JavaClassUtil.genericParamMap(genericMap, cls, globGicName);
StringBuilder data = new StringBuilder();
if (JavaClassValidateUtil.isCollection(typeName) || JavaClassValidateUtil.isArray(typeName)) {
data.append("[");
if (globGicName.length == 0) {
data.append("{\"object\":\"any object\"}");
data.append("]");
return data.toString();
}
String gNameTemp = globGicName[0];
String gName = JavaClassValidateUtil.isArray(gNameTemp) ? gNameTemp.substring(0, gNameTemp.indexOf("[")) : globGicName[0];
if (DocGlobalConstants.JAVA_OBJECT_FULLY.equals(gName)) {
data.append("{\"waring\":\"You may use java.util.Object instead of display generics in the List\"}");
} else if (JavaClassValidateUtil.isPrimitive(gName)) {
data.append(DocUtil.jsonValueByType(gName)).append(",");
data.append(DocUtil.jsonValueByType(gName));
} else if (gName.contains("<")) {
String simple = DocClassUtil.getSimpleName(gName);
String json = buildJson(simple, gName, isResp, nextLevel, registryClasses, groupClasses, builder);
data.append(json);
} else if (JavaClassValidateUtil.isCollection(gName)) {
data.append("\"any object\"");
} else {
String json = buildJson(gName, gName, isResp, nextLevel, registryClasses, groupClasses, builder);
data.append(json);
}
data.append("]");
return data.toString();
} else if (JavaClassValidateUtil.isMap(typeName)) {
String gNameTemp = genericCanonicalName;
String[] getKeyValType = DocClassUtil.getMapKeyValueType(gNameTemp);
if (getKeyValType.length == 0) {
data.append("{\"mapKey\":{}}");
return data.toString();
}
if ((!DocGlobalConstants.JAVA_STRING_FULLY.equals(getKeyValType[0])) && apiConfig.isStrict()) {
throw new RuntimeException("Map's key can only use String for json,but you use " + getKeyValType[0]);
}
String gicName = gNameTemp.substring(gNameTemp.indexOf(",") + 1, gNameTemp.lastIndexOf(">"));
if (DocGlobalConstants.JAVA_OBJECT_FULLY.equals(gicName)) {
data.append("{").append("\"mapKey\":").append("{\"waring\":\"You may use java.util.Object for Map value; smart-doc can't be handle.\"}")
.append("}");
} else if (JavaClassValidateUtil.isPrimitive(gicName)) {
data.append("{").append("\"mapKey1\":").append(DocUtil.jsonValueByType(gicName)).append(",");
data.append("\"mapKey2\":").append(DocUtil.jsonValueByType(gicName)).append("}");
} else if (gicName.contains("<")) {
String simple = DocClassUtil.getSimpleName(gicName);
String json = buildJson(simple, gicName, isResp, nextLevel, registryClasses, groupClasses, builder);
data.append("{").append("\"mapKey\":").append(json).append("}");
} else {
data.append("{").append("\"mapKey\":").append(buildJson(gicName, gNameTemp, isResp, counter + 1, registryClasses, groupClasses, builder)).append("}");
}
return data.toString();
} else if (DocGlobalConstants.JAVA_OBJECT_FULLY.equals(typeName)) {
data.append("{\"object\":\" any object\"},");
// throw new RuntimeException("Please do not return java.lang.Object directly in api interface.");
} else if (JavaClassValidateUtil.isReactor(typeName)) {
data.append(buildJson(globGicName[0], typeName, isResp, nextLevel, registryClasses, groupClasses, builder));
return data.toString();
} else {
boolean requestFieldToUnderline = builder.getApiConfig().isRequestFieldToUnderline();
boolean responseFieldToUnderline = builder.getApiConfig().isResponseFieldToUnderline();
List<DocJavaField> fields = JavaClassUtil.getFields(cls, 0, new LinkedHashMap<>());
Map<String, String> ignoreFields = JavaClassUtil.getClassJsonIgnoreFields(cls);
out:
for (DocJavaField docField : fields) {
JavaField field = docField.getJavaField();
if (field.isTransient() && skipTransientField) {
continue;
}
String fieldName = docField.getFieldName();
if (ignoreFields.containsKey(fieldName)) {
continue;
}
String subTypeName = docField.getFullyQualifiedName();
if ((responseFieldToUnderline && isResp) || (requestFieldToUnderline && !isResp)) {
fieldName = StringUtil.camelToUnderline(fieldName);
}
Map<String, String> tagsMap = DocUtil.getFieldTagsValue(field, docField);
if (!isResp) {
if (tagsMap.containsKey(DocTags.IGNORE)) {
continue out;
}
}
List<JavaAnnotation> annotations = docField.getAnnotations();
for (JavaAnnotation annotation : annotations) {
String annotationName = annotation.getType().getValue();
if (ValidatorAnnotations.NULL.equals(annotationName) && !isResp) {
List<String> groupClassList = JavaClassUtil.getParamGroupJavaClass(annotation);
for (String groupClass : groupClassList) {
if (groupClasses.contains(groupClass)) {
continue out;
}
}
}
if (DocAnnotationConstants.JSON_PROPERTY.equalsIgnoreCase(annotationName)) {
AnnotationValue value = annotation.getProperty("access");
if (Objects.nonNull(value)) {
if (JSON_PROPERTY_READ_ONLY.equals(value.getParameterValue()) && !isResp) {
continue out;
}
if (JSON_PROPERTY_WRITE_ONLY.equals(value.getParameterValue()) && isResp) {
continue out;
}
}
}
if (DocAnnotationConstants.SHORT_JSON_IGNORE.equals(annotationName)) {
continue out;
} else if (DocAnnotationConstants.SHORT_JSON_FIELD.equals(annotationName)) {
if (null != annotation.getProperty(DocAnnotationConstants.SERIALIZE_PROP)) {
if (Boolean.FALSE.toString().equals(annotation.getProperty(DocAnnotationConstants.SERIALIZE_PROP).toString())) {
continue out;
}
} else if (null != annotation.getProperty(DocAnnotationConstants.NAME_PROP)) {
fieldName = StringUtil.removeQuotes(annotation.getProperty(DocAnnotationConstants.NAME_PROP).toString());
}
} else if (DocAnnotationConstants.SHORT_JSON_PROPERTY.equals(annotationName)) {
if (null != annotation.getProperty(DocAnnotationConstants.VALUE_PROP)) {
fieldName = StringUtil.removeQuotes(annotation.getProperty(DocAnnotationConstants.VALUE_PROP).toString());
}
}
}
String typeSimpleName = field.getType().getSimpleName();
String fieldGicName = docField.getGenericCanonicalName();
CustomField customResponseField = builder.getCustomRespFieldMap().get(typeName + "." + fieldName);
CustomField customRequestField = builder.getCustomReqFieldMap().get(typeName + "." + fieldName);
if (customRequestField != null && JavaClassUtil.isTargetChildClass(typeName, customRequestField.getOwnerClassName()) && (customRequestField.isIgnore()) && !isResp) {
continue;
}
if (customResponseField != null && JavaClassUtil.isTargetChildClass(typeName, customResponseField.getOwnerClassName()) && (customResponseField.isIgnore()) && isResp) {
continue;
}
data0.append("\"").append(fieldName).append("\":");
String fieldValue = "";
if (tagsMap.containsKey(DocTags.MOCK) && StringUtil.isNotEmpty(tagsMap.get(DocTags.MOCK))) {
fieldValue = tagsMap.get(DocTags.MOCK);
if (!DocUtil.javaPrimaryType(typeSimpleName)
&& !JavaClassValidateUtil.isCollection(subTypeName)
&& !JavaClassValidateUtil.isMap(subTypeName)
&& !JavaClassValidateUtil.isArray(subTypeName)) {
fieldValue = DocUtil.handleJsonStr(fieldValue);
}
}
if (JavaClassValidateUtil.isPrimitive(subTypeName)) {
int data0Length = data0.length();
if (StringUtil.isEmpty(fieldValue)) {
fieldValue = DocUtil.getValByTypeAndFieldName(typeSimpleName, field.getName());
}
if (Objects.nonNull(customRequestField) && !isResp && typeName.equals(customRequestField.getOwnerClassName())) {
JavaFieldUtil.buildCustomField(data0, typeSimpleName, customRequestField);
}
if (Objects.nonNull(customResponseField) && isResp && typeName.equals(customResponseField.getOwnerClassName())) {
JavaFieldUtil.buildCustomField(data0, typeSimpleName, customResponseField);
}
if (data0.length() == data0Length) {
data0.append(fieldValue).append(",");
}
} else {
if (JavaClassValidateUtil.isCollection(subTypeName) || JavaClassValidateUtil.isArray(subTypeName)) {
if (StringUtil.isNotEmpty(fieldValue)) {
data0.append(fieldValue).append(",");
continue out;
}
if (globGicName.length > 0 && "java.util.List".equals(fieldGicName)) {
fieldGicName = fieldGicName + "<T>";
}
if (JavaClassValidateUtil.isArray(subTypeName)) {
fieldGicName = fieldGicName.substring(0, fieldGicName.lastIndexOf("["));
fieldGicName = "java.util.List<" + fieldGicName + ">";
}
String gicName = DocClassUtil.getSimpleGicName(fieldGicName)[0];
if (DocGlobalConstants.JAVA_STRING_FULLY.equals(gicName)) {
data0.append("[").append(DocUtil.jsonValueByType(gicName)).append("]").append(",");
} else if (DocGlobalConstants.JAVA_LIST_FULLY.equals(gicName)) {
data0.append("[{\"object\":\"any object\"}],");
} else if (gicName.length() == 1) {
if (globGicName.length == 0) {
data0.append("[{\"object\":\"any object\"}],");
continue out;
}
String gicName1 = genericMap.get(gicName) == null ? globGicName[0] : genericMap.get(gicName);
if (DocGlobalConstants.JAVA_STRING_FULLY.equals(gicName1)) {
data0.append("[").append(DocUtil.jsonValueByType(gicName1)).append("]").append(",");
} else {
if (!typeName.equals(gicName1)) {
data0.append("[").append(buildJson(DocClassUtil.getSimpleName(gicName1), gicName1, isResp, nextLevel, registryClasses, groupClasses, builder))
.append("]").append(",");
} else {
data0.append("[{\"$ref\":\"..\"}]").append(",");
}
}
} else {
if (!typeName.equals(gicName)) {
if (JavaClassValidateUtil.isMap(gicName)) {
data0.append("[{\"mapKey\":{}}],");
continue out;
}
JavaClass arraySubClass = builder.getJavaProjectBuilder().getClassByName(gicName);
if (arraySubClass.isEnum()) {
Object value = JavaClassUtil.getEnumValue(arraySubClass, Boolean.FALSE);
data0.append("[").append(value).append("],");
continue out;
}
data0.append("[").append(buildJson(gicName, fieldGicName, isResp, nextLevel, registryClasses, groupClasses, builder)).append("]").append(",");
} else {
data0.append("[{\"$ref\":\"..\"}]").append(",");
}
}
} else if (JavaClassValidateUtil.isMap(subTypeName)) {
if (StringUtil.isNotEmpty(fieldValue)) {
data0.append(fieldValue).append(",");
continue out;
}
if (JavaClassValidateUtil.isMap(fieldGicName)) {
data0.append("{").append("\"mapKey\":{}},");
continue out;
}
String gicName = fieldGicName.substring(fieldGicName.indexOf(",") + 1, fieldGicName.indexOf(">"));
if (gicName.length() == 1) {
String gicName1 = "";
if (Objects.nonNull(genericMap.get(gicName))) {
gicName1 = genericMap.get(gicName);
} else {
if (globGicName.length > 0) {
gicName1 = globGicName[0];
}
}
if (DocGlobalConstants.JAVA_STRING_FULLY.equals(gicName1)) {
data0.append("{").append("\"mapKey\":").append(DocUtil.jsonValueByType(gicName1)).append("},");
} else {
if (!typeName.equals(gicName1)) {
data0.append("{").append("\"mapKey\":")
.append(buildJson(DocClassUtil.getSimpleName(gicName1), gicName1, isResp, nextLevel, registryClasses, groupClasses, builder)).append("},");
} else {
data0.append("{\"mapKey\":{}},");
}
}
} else {
data0.append("{").append("\"mapKey\":").append(buildJson(gicName, fieldGicName, isResp, nextLevel, registryClasses, groupClasses, builder))
.append("},");
}
} else if (subTypeName.length() == 1) {
if (!typeName.equals(genericCanonicalName)) {
String gicName = genericMap.get(subTypeName) == null ? globGicName[0] : genericMap.get(subTypeName);
if (JavaClassValidateUtil.isPrimitive(gicName)) {
data0.append(DocUtil.jsonValueByType(gicName)).append(",");
} else {
String simple = DocClassUtil.getSimpleName(gicName);
data0.append(buildJson(simple, gicName, isResp, nextLevel, registryClasses, groupClasses, builder)).append(",");
}
} else {
data0.append("{},");
}
} else if (DocGlobalConstants.JAVA_OBJECT_FULLY.equals(subTypeName)) {
if (StringUtil.isNotEmpty(field.getComment())) {
// from source code
data0.append("{\"object\":\"any object\"},");
} else if (globGicName.length > 0) {
String gicName = genericMap.get(subTypeName) == null ? globGicName[0] : genericMap.get(subTypeName);
if (!typeName.equals(genericCanonicalName)) {
if (JavaClassValidateUtil.isPrimitive(gicName)) {
data0.append("\"").append(buildJson(gicName, genericCanonicalName, isResp, nextLevel, registryClasses, groupClasses, builder)).append("\",");
} else {
String simpleName = DocClassUtil.getSimpleName(gicName);
data0.append(buildJson(simpleName, gicName, isResp, nextLevel, registryClasses, groupClasses, builder)).append(",");
}
} else {
data0.append("{},");
}
} else {
data0.append("{},");
}
} else if (typeName.equals(subTypeName)) {
data0.append("{\"$ref\":\"...\"}").append(",");
} else {
javaClass = field.getType();
if (javaClass.isEnum()) {
// Override old value
if (tagsMap.containsKey(DocTags.MOCK) && StringUtil.isNotEmpty(tagsMap.get(DocTags.MOCK))) {
data0.append(tagsMap.get(DocTags.MOCK)).append(",");
} else {
Object value = JavaClassUtil.getEnumValue(javaClass, Boolean.FALSE);
data0.append(value).append(",");
}
} else {
fieldGicName = DocUtil.formatFieldTypeGicName(genericMap, globGicName, fieldGicName);
data0.append(buildJson(subTypeName, fieldGicName, isResp, nextLevel, registryClasses, groupClasses, builder)).append(",");
}
}
}
}
}
if (data0.toString().contains(",")) {
data0.deleteCharAt(data0.lastIndexOf(","));
}
data0.append("}");
return data0.toString();
}
}

View File

@ -0,0 +1,606 @@
/*
* smart-doc https://github.com/shalousun/smart-doc
*
* Copyright (C) 2018-2021 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.helper;
import com.power.common.model.EnumDictionary;
import com.power.common.util.CollectionUtil;
import com.power.common.util.StringUtil;
import com.power.doc.builder.ProjectDocConfigBuilder;
import com.power.doc.constants.DocAnnotationConstants;
import com.power.doc.constants.DocGlobalConstants;
import com.power.doc.constants.DocTags;
import com.power.doc.constants.ValidatorAnnotations;
import com.power.doc.model.*;
import com.power.doc.utils.DocClassUtil;
import com.power.doc.utils.DocUtil;
import com.power.doc.utils.JavaClassUtil;
import com.power.doc.utils.JavaClassValidateUtil;
import com.thoughtworks.qdox.model.JavaAnnotation;
import com.thoughtworks.qdox.model.JavaClass;
import com.thoughtworks.qdox.model.JavaField;
import com.thoughtworks.qdox.model.JavaMethod;
import com.thoughtworks.qdox.model.expression.AnnotationValue;
import org.apache.commons.lang3.StringUtils;
import java.util.*;
import java.util.stream.Collectors;
import static com.power.doc.constants.DocGlobalConstants.*;
/**
* @author yu 2019/12/21.
*/
public class ParamsBuildHelper {
public static List<ApiParam> buildParams(String className, String pre, int level, String isRequired, boolean isResp,
Map<String, String> registryClasses, ProjectDocConfigBuilder projectBuilder,
List<String> groupClasses, int pid, boolean jsonRequest) {
Map<String, String> genericMap = new HashMap<>(10);
if (StringUtil.isEmpty(className)) {
throw new RuntimeException("Class name can't be null or empty.");
}
ApiConfig apiConfig = projectBuilder.getApiConfig();
int nextLevel = level + 1;
// Check circular reference
List<ApiParam> paramList = new ArrayList<>();
if (level > apiConfig.getRecursionLimit()) {
return paramList;
}
if (registryClasses.containsKey(className) && level > registryClasses.size()) {
return paramList;
}
Map<String, CustomField> responseFieldMap = projectBuilder.getCustomRespFieldMap();
boolean skipTransientField = apiConfig.isSkipTransientField();
boolean isShowJavaType = projectBuilder.getApiConfig().getShowJavaType();
boolean requestFieldToUnderline = projectBuilder.getApiConfig().isRequestFieldToUnderline();
boolean responseFieldToUnderline = projectBuilder.getApiConfig().isResponseFieldToUnderline();
boolean displayActualType = projectBuilder.getApiConfig().isDisplayActualType();
// Registry class
registryClasses.put(className, className);
String simpleName = DocClassUtil.getSimpleName(className);
String[] globGicName = DocClassUtil.getSimpleGicName(className);
JavaClass cls = projectBuilder.getClassByName(simpleName);
if (Objects.isNull(globGicName) || globGicName.length < 1) {
// obtain generics from parent class
JavaClass superJavaClass = cls != null ? cls.getSuperJavaClass() : null;
if (superJavaClass != null && !"Object".equals(superJavaClass.getSimpleName())) {
globGicName = DocClassUtil.getSimpleGicName(superJavaClass.getGenericFullyQualifiedName());
}
}
JavaClassUtil.genericParamMap(genericMap, cls, globGicName);
List<DocJavaField> fields = JavaClassUtil.getFields(cls, 0, new LinkedHashMap<>());
if (JavaClassValidateUtil.isPrimitive(simpleName)) {
String processedType = isShowJavaType ? simpleName : DocClassUtil.processTypeNameForParams(simpleName.toLowerCase());
paramList.addAll(primitiveReturnRespComment(processedType));
} else if (JavaClassValidateUtil.isCollection(simpleName) || JavaClassValidateUtil.isArray(simpleName)) {
if (!JavaClassValidateUtil.isCollection(globGicName[0])) {
String gicName = globGicName[0];
if (JavaClassValidateUtil.isArray(gicName)) {
gicName = gicName.substring(0, gicName.indexOf("["));
}
paramList.addAll(buildParams(gicName, pre, nextLevel, isRequired, isResp,
registryClasses, projectBuilder, groupClasses, pid, jsonRequest));
}
} else if (JavaClassValidateUtil.isMap(simpleName)) {
if (globGicName.length == 2) {
paramList.addAll(buildParams(globGicName[1], pre, nextLevel, isRequired, isResp,
registryClasses, projectBuilder, groupClasses, pid, jsonRequest));
}
} else if (DocGlobalConstants.JAVA_OBJECT_FULLY.equals(className)) {
ApiParam param = ApiParam.of().setId(pid + 1).setField(pre + "any object").setType("object").setPid(pid);
if (StringUtil.isEmpty(isRequired)) {
param.setDesc(DocGlobalConstants.ANY_OBJECT_MSG).setVersion(DocGlobalConstants.DEFAULT_VERSION);
} else {
param.setDesc(DocGlobalConstants.ANY_OBJECT_MSG).setRequired(false).setVersion(DocGlobalConstants.DEFAULT_VERSION);
}
paramList.add(param);
} else if (JavaClassValidateUtil.isReactor(simpleName)) {
if (globGicName.length > 0) {
paramList.addAll(buildParams(globGicName[0], pre, nextLevel, isRequired, isResp,
registryClasses, projectBuilder, groupClasses, pid, jsonRequest));
}
} else {
Map<String, String> ignoreFields = JavaClassUtil.getClassJsonIgnoreFields(cls);
out:
for (DocJavaField docField : fields) {
String maxLength = null;
JavaField field = docField.getJavaField();
if (field.isTransient() && skipTransientField) {
continue;
}
String fieldName = docField.getFieldName();
if (ignoreFields.containsKey(fieldName)) {
continue;
}
String subTypeName = docField.getFullyQualifiedName();
if ((responseFieldToUnderline && isResp) || (requestFieldToUnderline && !isResp)) {
fieldName = StringUtil.camelToUnderline(fieldName);
}
String typeSimpleName = field.getType().getSimpleName();
String fieldGicName = docField.getGenericCanonicalName();
List<JavaAnnotation> javaAnnotations = docField.getAnnotations();
Map<String, String> tagsMap = DocUtil.getFieldTagsValue(field, docField);
String since = DocGlobalConstants.DEFAULT_VERSION;//since tag value
if (!isResp) {
pre:
if (tagsMap.containsKey(DocTags.IGNORE)) {
continue out;
} else if (tagsMap.containsKey(DocTags.SINCE)) {
since = tagsMap.get(DocTags.SINCE);
}
} else {
if (tagsMap.containsKey(DocTags.SINCE)) {
since = tagsMap.get(DocTags.SINCE);
}
}
boolean strRequired = false;
int annotationCounter = 0;
CustomField customResponseField = responseFieldMap.get(simpleName + "." + fieldName);
if (customResponseField != null && JavaClassUtil.isTargetChildClass(simpleName, customResponseField.getOwnerClassName())
&& (customResponseField.isIgnore()) && isResp) {
continue;
}
CustomField customRequestField = projectBuilder.getCustomReqFieldMap().get(simpleName + "." + fieldName);
if (customRequestField != null && JavaClassUtil.isTargetChildClass(simpleName, customRequestField.getOwnerClassName())
&& (customRequestField.isIgnore()) && !isResp) {
continue;
}
an:
for (JavaAnnotation annotation : javaAnnotations) {
String simpleAnnotationName = annotation.getType().getValue();
AnnotationValue annotationValue = null;
if (DocAnnotationConstants.MAX.equalsIgnoreCase(simpleAnnotationName)) {
annotationValue = annotation.getProperty(DocAnnotationConstants.VALUE_PROP);
}
if (DocAnnotationConstants.SIZE.equalsIgnoreCase(simpleAnnotationName)) {
annotationValue = annotation.getProperty(DocAnnotationConstants.MAX);
}
if (DocAnnotationConstants.LENGTH.equalsIgnoreCase(simpleAnnotationName)) {
annotationValue = annotation.getProperty(DocAnnotationConstants.MAX);
}
if (!Objects.isNull(annotationValue)) {
maxLength = annotationValue.toString();
}
if (DocAnnotationConstants.JSON_PROPERTY.equalsIgnoreCase(simpleAnnotationName)) {
AnnotationValue value = annotation.getProperty("access");
if (Objects.nonNull(value)) {
if (JSON_PROPERTY_READ_ONLY.equals(value.getParameterValue()) && !isResp) {
continue out;
}
if (JSON_PROPERTY_WRITE_ONLY.equals(value.getParameterValue()) && isResp) {
continue out;
}
}
}
if (DocAnnotationConstants.SHORT_JSON_IGNORE.equals(simpleAnnotationName)) {
continue out;
} else if (DocAnnotationConstants.SHORT_JSON_FIELD.equals(simpleAnnotationName)) {
if (null != annotation.getProperty(DocAnnotationConstants.SERIALIZE_PROP)) {
if (Boolean.FALSE.toString().equals(annotation.getProperty(DocAnnotationConstants.SERIALIZE_PROP).toString())) {
continue out;
}
} else if (null != annotation.getProperty(DocAnnotationConstants.NAME_PROP)) {
fieldName = StringUtil.removeQuotes(annotation.getProperty(DocAnnotationConstants.NAME_PROP).toString());
}
} else if (DocAnnotationConstants.SHORT_JSON_PROPERTY.equals(simpleAnnotationName)) {
if (null != annotation.getProperty(DocAnnotationConstants.VALUE_PROP)) {
fieldName = StringUtil.removeQuotes(annotation.getProperty(DocAnnotationConstants.VALUE_PROP).toString());
}
} else if (ValidatorAnnotations.NULL.equals(simpleAnnotationName) && !isResp) {
List<String> groupClassList = JavaClassUtil.getParamGroupJavaClass(annotation);
for (String javaClass : groupClassList) {
if (groupClasses.contains(javaClass)) {
strRequired = false;
continue out;
}
}
} else if (JavaClassValidateUtil.isJSR303Required(simpleAnnotationName) && !isResp) {
annotationCounter++;
boolean hasGroup = false;
List<String> groupClassList = JavaClassUtil.getParamGroupJavaClass(annotation);
for (String javaClass : groupClassList) {
if (groupClasses.contains(javaClass)) {
hasGroup = true;
}
}
if (hasGroup) {
strRequired = true;
} else if (CollectionUtil.isEmpty(groupClasses)) {
strRequired = true;
}
break an;
}
}
String fieldValue = "";
if (tagsMap.containsKey(DocTags.MOCK) && StringUtil.isNotEmpty(tagsMap.get(DocTags.MOCK))) {
fieldValue = tagsMap.get(DocTags.MOCK);
if (!DocUtil.javaPrimaryType(typeSimpleName)
&& !JavaClassValidateUtil.isCollection(subTypeName)
&& !JavaClassValidateUtil.isMap(subTypeName)
&& !JavaClassValidateUtil.isArray(subTypeName)) {
fieldValue = DocUtil.handleJsonStr(fieldValue);
}
}
if (annotationCounter < 1) {
doc:
if (tagsMap.containsKey(DocTags.REQUIRED)) {
strRequired = true;
break doc;
}
}
// cover response value
if (Objects.nonNull(customResponseField) && isResp && Objects.nonNull(customResponseField.getValue())
&& JavaClassUtil.isTargetChildClass(simpleName, customResponseField.getOwnerClassName())) {
fieldValue = String.valueOf(customResponseField.getValue());
}
// cover request value
if (Objects.nonNull(customRequestField) && !isResp && Objects.nonNull(customRequestField.getValue())
&& JavaClassUtil.isTargetChildClass(simpleName, customRequestField.getOwnerClassName())) {
fieldValue = String.valueOf(customRequestField.getValue());
}
//cover required
if (customRequestField != null && !isResp && JavaClassUtil.isTargetChildClass(simpleName, customRequestField.getOwnerClassName())
&& customRequestField.isRequire()) {
strRequired = true;
}
//cover comment
String comment = "";
if (null != customRequestField && StringUtil.isNotEmpty(customRequestField.getDesc())
&& JavaClassUtil.isTargetChildClass(simpleName, customRequestField.getOwnerClassName()) && !isResp) {
comment = customRequestField.getDesc();
}
if (null != customResponseField && StringUtil.isNotEmpty(customResponseField.getDesc())
&& JavaClassUtil.isTargetChildClass(simpleName, customResponseField.getOwnerClassName()) && isResp) {
comment = customResponseField.getDesc();
}
if (StringUtils.isBlank(comment)) {
comment = docField.getComment();
}
if (StringUtil.isNotEmpty(comment)) {
comment = DocUtil.replaceNewLineToHtmlBr(comment);
}
// file
if (JavaClassValidateUtil.isFile(fieldGicName)) {
ApiParam param = ApiParam.of().setField(pre + fieldName).setType("file")
.setPid(pid).setId(paramList.size() + pid + 1)
.setMaxLength(maxLength)
.setDesc(comment).setRequired(Boolean.valueOf(isRequired)).setVersion(since);
paramList.add(param);
continue;
}
if (JavaClassValidateUtil.isPrimitive(subTypeName)) {
if (StringUtil.isEmpty(fieldValue)) {
fieldValue = DocUtil.getValByTypeAndFieldName(typeSimpleName, field.getName());
}
ApiParam param = ApiParam.of().setField(pre + fieldName);
param.setPid(pid).setMaxLength(maxLength).setValue(fieldValue);
String processedType = isShowJavaType ? typeSimpleName : DocClassUtil.processTypeNameForParams(typeSimpleName.toLowerCase());
param.setType(processedType);
if (StringUtil.isNotEmpty(comment)) {
commonHandleParam(paramList, param, isRequired, comment, since, strRequired);
} else {
commonHandleParam(paramList, param, isRequired, NO_COMMENTS_FOUND, since, strRequired);
}
} else {
String appendComment = "";
if (displayActualType) {
if (globGicName.length > 0) {
String gicName = genericMap.get(subTypeName) != null ? genericMap.get(subTypeName) : globGicName[0];
if (!simpleName.equals(gicName)) {
appendComment = " (ActualType: " + JavaClassUtil.getClassSimpleName(gicName) + ")";
}
}
if (Objects.nonNull(docField.getActualJavaType())) {
appendComment = " (ActualType: " + JavaClassUtil.getClassSimpleName(docField.getActualJavaType()) + ")";
}
}
StringBuilder preBuilder = new StringBuilder();
for (int j = 0; j < level; j++) {
preBuilder.append(DocGlobalConstants.FIELD_SPACE);
}
preBuilder.append("└─");
int fieldPid;
ApiParam param = ApiParam.of().setField(pre + fieldName).setPid(pid).setMaxLength(maxLength);
String processedType;
if (typeSimpleName.length() == 1) {
String gicName = JAVA_OBJECT_FULLY;
if (Objects.nonNull(genericMap.get(typeSimpleName))) {
gicName = genericMap.get(subTypeName);
} else {
if (globGicName.length > 0) {
gicName = globGicName[0];
}
}
if (JavaClassValidateUtil.isPrimitive(gicName)) {
processedType = DocClassUtil.processTypeNameForParams(gicName);
} else {
processedType = DocClassUtil.processTypeNameForParams(typeSimpleName.toLowerCase());
}
} else {
processedType = isShowJavaType ? typeSimpleName : DocClassUtil.processTypeNameForParams(typeSimpleName.toLowerCase());
}
param.setType(processedType);
JavaClass javaClass = field.getType();
if (javaClass.isEnum()) {
comment = comment + handleEnumComment(javaClass, projectBuilder);
param.setType(DocGlobalConstants.ENUM);
if (!isResp) {
List<JavaMethod> methods = javaClass.getMethods();
int index = 0;
enumOut:
for (JavaMethod method : methods) {
List<JavaAnnotation> javaAnnotationList = method.getAnnotations();
for (JavaAnnotation annotation : javaAnnotationList) {
if (annotation.getType().getValue().contains("JsonValue")) {
break enumOut;
}
}
if (CollectionUtil.isEmpty(javaAnnotations) && index < 1) {
break enumOut;
}
index++;
}
Object value = JavaClassUtil.getEnumValue(javaClass, !jsonRequest);
param.setValue(String.valueOf(value));
param.setEnumValues(JavaClassUtil.getEnumValues(javaClass));
}
// Override old value
if (tagsMap.containsKey(DocTags.MOCK) && StringUtil.isNotEmpty(tagsMap.get(DocTags.MOCK))) {
param.setValue(tagsMap.get(DocTags.MOCK));
}
if (StringUtil.isNotEmpty(comment)) {
commonHandleParam(paramList, param, isRequired, comment + appendComment, since, strRequired);
} else {
commonHandleParam(paramList, param, isRequired, NO_COMMENTS_FOUND + appendComment, since, strRequired);
}
} else if (JavaClassValidateUtil.isCollection(subTypeName) || JavaClassValidateUtil.isArray(subTypeName)) {
param.setType("array");
if (tagsMap.containsKey(DocTags.MOCK) && StringUtil.isNotEmpty(tagsMap.get(DocTags.MOCK))) {
param.setValue(fieldValue);
}
if (globGicName.length > 0 && "java.util.List".equals(fieldGicName)) {
fieldGicName = fieldGicName + "<T>";
}
if (JavaClassValidateUtil.isArray(subTypeName)) {
fieldGicName = fieldGicName.substring(0, fieldGicName.lastIndexOf("["));
fieldGicName = "java.util.List<" + fieldGicName + ">";
}
String[] gNameArr = DocClassUtil.getSimpleGicName(fieldGicName);
if (gNameArr.length == 0) {
continue out;
}
if (gNameArr.length > 0) {
String gName = DocClassUtil.getSimpleGicName(fieldGicName)[0];
JavaClass javaClass1 = projectBuilder.getJavaProjectBuilder().getClassByName(gName);
comment = comment + handleEnumComment(javaClass1, projectBuilder);
}
String gName = gNameArr[0];
if (JavaClassValidateUtil.isPrimitive(gName)) {
String builder = DocUtil.jsonValueByType(gName) +
"," +
DocUtil.jsonValueByType(gName);
if (StringUtil.isEmpty(fieldValue)) {
param.setValue(DocUtil.handleJsonStr(builder));
} else {
param.setValue(fieldValue);
}
if (StringUtil.isNotEmpty(comment)) {
commonHandleParam(paramList, param, isRequired, comment + appendComment, since, strRequired);
} else {
commonHandleParam(paramList, param, isRequired, NO_COMMENTS_FOUND + appendComment, since, strRequired);
}
} else {
if (StringUtil.isNotEmpty(comment)) {
commonHandleParam(paramList, param, isRequired, comment + appendComment, since, strRequired);
} else {
commonHandleParam(paramList, param, isRequired, NO_COMMENTS_FOUND + appendComment, since, strRequired);
}
fieldPid = paramList.size() + pid;
if (!simpleName.equals(gName) && !gName.equals(simpleName)) {
JavaClass arraySubClass = projectBuilder.getJavaProjectBuilder().getClassByName(gName);
if (arraySubClass.isEnum()) {
Object value = JavaClassUtil.getEnumValue(arraySubClass, Boolean.FALSE);
StringBuilder sb = new StringBuilder();
sb.append("[\"").append(value).append("\"]");
param.setValue(sb.toString());
} else if (gName.length() == 1) {
// handle generic
int len = globGicName.length;
if (len < 1) {
continue out;
}
String gicName = genericMap.get(gName) != null ? genericMap.get(gName) : globGicName[0];
if (!JavaClassValidateUtil.isPrimitive(gicName) && !simpleName.equals(gicName)) {
paramList.addAll(buildParams(gicName, preBuilder.toString(), nextLevel, isRequired,
isResp, registryClasses, projectBuilder, groupClasses, fieldPid, jsonRequest));
}
} else {
paramList.addAll(buildParams(gName, preBuilder.toString(), nextLevel, isRequired,
isResp, registryClasses, projectBuilder, groupClasses, fieldPid, jsonRequest));
}
}
}
} else if (JavaClassValidateUtil.isMap(subTypeName)) {
if (tagsMap.containsKey(DocTags.MOCK) && StringUtil.isNotEmpty(tagsMap.get(DocTags.MOCK))) {
param.setType("map");
param.setValue(fieldValue);
}
if (StringUtil.isNotEmpty(comment)) {
commonHandleParam(paramList, param, isRequired, comment + appendComment, since, strRequired);
} else {
commonHandleParam(paramList, param, isRequired, NO_COMMENTS_FOUND + appendComment, since, strRequired);
}
fieldPid = paramList.size() + pid;
String gNameTemp = fieldGicName;
String valType = DocClassUtil.getMapKeyValueType(gNameTemp).length == 0 ? gNameTemp : DocClassUtil.getMapKeyValueType(gNameTemp)[1];
if (JavaClassValidateUtil.isMap(gNameTemp) || JAVA_OBJECT_FULLY.equals(valType)) {
ApiParam param1 = ApiParam.of().setField(preBuilder.toString() + "any object")
.setId(fieldPid + 1).setPid(fieldPid)
.setMaxLength(maxLength)
.setType("object").setDesc(DocGlobalConstants.ANY_OBJECT_MSG).setVersion(DocGlobalConstants.DEFAULT_VERSION);
paramList.add(param1);
continue;
}
if (!JavaClassValidateUtil.isPrimitive(valType)) {
if (valType.length() == 1) {
String gicName = genericMap.get(valType);
if (!JavaClassValidateUtil.isPrimitive(gicName) && !simpleName.equals(gicName)) {
paramList.addAll(buildParams(gicName, preBuilder.toString(), nextLevel, isRequired,
isResp, registryClasses, projectBuilder, groupClasses, fieldPid, jsonRequest));
}
} else {
paramList.addAll(buildParams(valType, preBuilder.toString(), nextLevel, isRequired,
isResp, registryClasses, projectBuilder, groupClasses, fieldPid, jsonRequest));
}
}
} else if (subTypeName.length() == 1 || DocGlobalConstants.JAVA_OBJECT_FULLY.equals(subTypeName)) {
if (StringUtil.isNotEmpty(comment)) {
commonHandleParam(paramList, param, isRequired, comment + appendComment, since, strRequired);
} else {
commonHandleParam(paramList, param, isRequired, NO_COMMENTS_FOUND + appendComment, since, strRequired);
}
fieldPid = paramList.size() + pid;
// handle java generic or object
if (DocGlobalConstants.JAVA_OBJECT_FULLY.equals(subTypeName) && StringUtil.isNotEmpty(field.getComment())) {
ApiParam param1 = ApiParam.of().setField(preBuilder.toString() + "any object")
.setId(paramList.size())
.setMaxLength(maxLength)
.setType("object").setDesc(DocGlobalConstants.ANY_OBJECT_MSG).setVersion(DocGlobalConstants.DEFAULT_VERSION);
paramList.add(param1);
} else if (!simpleName.equals(className)) {
if (globGicName.length > 0) {
String gicName = genericMap.get(subTypeName) != null ? genericMap.get(subTypeName) : globGicName[0];
String simple = DocClassUtil.getSimpleName(gicName);
if (JavaClassValidateUtil.isPrimitive(simple)) {
//do nothing
} else if (gicName.contains("<")) {
if (JavaClassValidateUtil.isCollection(simple)) {
param.setType(ARRAY);
String gName = DocClassUtil.getSimpleGicName(gicName)[0];
if (!JavaClassValidateUtil.isPrimitive(gName)) {
paramList.addAll(buildParams(gName, preBuilder.toString(), nextLevel, isRequired,
isResp, registryClasses, projectBuilder, groupClasses, fieldPid, jsonRequest));
}
} else if (JavaClassValidateUtil.isMap(simple)) {
String valType = DocClassUtil.getMapKeyValueType(gicName)[1];
if (!JavaClassValidateUtil.isPrimitive(valType)) {
paramList.addAll(buildParams(valType, preBuilder.toString(), nextLevel, isRequired,
isResp, registryClasses, projectBuilder, groupClasses, fieldPid, jsonRequest));
}
} else {
paramList.addAll(buildParams(gicName, preBuilder.toString(), nextLevel, isRequired,
isResp, registryClasses, projectBuilder, groupClasses, fieldPid, jsonRequest));
}
} else {
paramList.addAll(buildParams(gicName, preBuilder.toString(), nextLevel, isRequired,
isResp, registryClasses, projectBuilder, groupClasses, fieldPid, jsonRequest));
}
} else {
paramList.addAll(buildParams(subTypeName, preBuilder.toString(), nextLevel, isRequired,
isResp, registryClasses, projectBuilder, groupClasses, fieldPid, jsonRequest));
}
}
} else if (simpleName.equals(subTypeName)) {
//do nothing
} else {
if (StringUtil.isNotEmpty(comment)) {
commonHandleParam(paramList, param, isRequired, comment + appendComment, since, strRequired);
} else {
commonHandleParam(paramList, param, isRequired, NO_COMMENTS_FOUND + appendComment, since, strRequired);
}
fieldGicName = DocUtil.formatFieldTypeGicName(genericMap, globGicName, fieldGicName);
fieldPid = paramList.size() + pid;
paramList.addAll(buildParams(fieldGicName, preBuilder.toString(), nextLevel, isRequired,
isResp, registryClasses, projectBuilder, groupClasses, fieldPid, jsonRequest));
}
}
}//end field
}
return paramList;
}
public static String dictionaryListComment(ApiDataDictionary dictionary) {
List<EnumDictionary> enumDataDict = dictionary.getEnumDataDict();
return enumDataDict.stream().map(apiDataDictionary ->
apiDataDictionary.getName() + "-(\"" + apiDataDictionary.getValue() + "\",\""
+ apiDataDictionary.getDesc() + "\")"
).collect(Collectors.joining(","));
}
public static List<ApiParam> primitiveReturnRespComment(String typeName) {
StringBuilder comments = new StringBuilder();
comments.append("Return ").append(typeName).append(".");
ApiParam apiParam = ApiParam.of().setField("-")
.setType(typeName).setDesc(comments.toString()).setVersion(DocGlobalConstants.DEFAULT_VERSION);
List<ApiParam> paramList = new ArrayList<>();
paramList.add(apiParam);
return paramList;
}
private static void commonHandleParam(List<ApiParam> paramList, ApiParam param, String isRequired,
String comment, String since, boolean strRequired) {
if (StringUtil.isEmpty(isRequired)) {
param.setDesc(comment).setVersion(since);
} else {
param.setDesc(comment).setVersion(since).setRequired(strRequired);
}
param.setId(paramList.size() + param.getPid() + 1);
paramList.add(param);
}
private static String handleEnumComment(JavaClass javaClass, ProjectDocConfigBuilder projectBuilder) {
String comment = "";
if (!javaClass.isEnum()) {
return comment;
}
String enumComments = javaClass.getComment();
if (projectBuilder.getApiConfig().getInlineEnum()) {
ApiDataDictionary dataDictionary = projectBuilder.getApiConfig().getDataDictionary(javaClass.getCanonicalName());
if (Objects.isNull(dataDictionary)) {
comment = comment + "<br/>" + JavaClassUtil.getEnumParams(javaClass);
} else {
comment = comment + "[enum:" + dictionaryListComment(dataDictionary) + "]";
}
} else {
enumComments = DocUtil.replaceNewLineToHtmlBr(enumComments);
if (StringUtil.isNotEmpty(enumComments)) {
comment = comment + "(See: " + enumComments + ")";
}
comment = StringUtil.removeQuotes(comment);
}
return comment;
}
}

View File

@ -0,0 +1,124 @@
/*
* smart-doc
*
* Copyright (C) 2018-2021 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.model;
import java.util.List;
/**
* @author yu 2019/12/7.
* @since 1.7.9
*/
public class ApiAllData {
/**
* project name
*/
private String projectName;
/**
* project id
*/
private String projectId;
/**
* docLanguage
*/
private String language;
/**
* doc list
*/
private List<ApiDoc> apiDocList;
/**
*
*/
private List<ApiDocDict> apiDocDictList;
/**
* error code list
*/
private List<ApiErrorCode> errorCodeList;
/**
* List of change log
*/
private List<RevisionLog> revisionLogs;
public String getProjectName() {
return projectName;
}
public void setProjectName(String projectName) {
this.projectName = projectName;
}
public String getProjectId() {
return projectId;
}
public void setProjectId(String projectId) {
this.projectId = projectId;
}
public String getLanguage() {
return language;
}
public void setLanguage(String language) {
this.language = language;
}
public List<ApiDoc> getApiDocList() {
return apiDocList;
}
public void setApiDocList(List<ApiDoc> apiDocList) {
this.apiDocList = apiDocList;
}
public List<ApiErrorCode> getErrorCodeList() {
return errorCodeList;
}
public void setErrorCodeList(List<ApiErrorCode> errorCodeList) {
this.errorCodeList = errorCodeList;
}
public List<RevisionLog> getRevisionLogs() {
return revisionLogs;
}
public void setRevisionLogs(List<RevisionLog> revisionLogs) {
this.revisionLogs = revisionLogs;
}
public List<ApiDocDict> getApiDocDictList() {
return apiDocDictList;
}
public void setApiDocDictList(List<ApiDocDict> apiDocDictList) {
this.apiDocDictList = apiDocDictList;
}
}

View File

@ -0,0 +1,914 @@
/*
* smart-doc
*
* Copyright (C) 2018-2021 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.model;
import com.power.common.util.CollectionUtil;
import com.power.doc.constants.DocLanguage;
import com.power.doc.model.rpc.RpcApiDependency;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
/**
* Description:
* api config info
*
* @author yu 2018/06/18.
*/
public class ApiConfig {
/**
* Web server base url
*/
private String serverUrl;
/**
* Path Prefix, eg: Servlet ContextPath
*/
private String pathPrefix = "";
/**
* Set comments check mode
*/
private boolean isStrict;
/**
* Merge all api doc into one document
*/
private boolean allInOne;
/**
* output path
*/
private String outPath;
/**
* source path
*/
private List<SourceCodePath> sourceCodePaths;
/**
* list of Request headers
*/
private List<ApiReqParam> requestHeaders;
/**
* @since 2.2.2
* list of Request params
*/
private List<ApiReqParam> requestParams;
/**
* @since 1.7.5
* cover old all in one markdown
*/
private boolean coverOld;
/**
* list of custom response filed
*/
private List<CustomField> customResponseFields;
/**
* list of custom request field
*/
private List<CustomField> customRequestFields;
/**
* List of error code
*
* @return
*/
private List<ApiErrorCode> errorCodes;
/**
* controller package filters
*/
private String packageFilters;
/**
* List of change log
*/
private List<RevisionLog> revisionLogs;
/**
* @since 1.7+
*/
private boolean md5EncryptedHtmlName;
/**
* language support
*
* @since 1.7+
*/
private DocLanguage language;
/**
* adoc flag
*/
private boolean adoc;
/**
* api data dictionary
*/
private List<ApiDataDictionary> dataDictionaries;
/**
* @since 1.7.9
* api error code dictionary
*/
private List<ApiErrorCodeDictionary> errorCodeDictionaries;
/**
* list of custom response filed
*/
private List<ApiObjectReplacement> apiObjectReplacements;
/**
* list of rpc api dependencies
*/
private List<RpcApiDependency> rpcApiDependencies;
/**
* list of api constant
*/
private List<ApiConstant> apiConstants;
/**
* @since 2.0.7
* project group
*/
private String group;
/**
* @since 1.7.5
* project name
*/
private String projectName;
/**
* @since 2.0.7
* project cn name
*/
private String projectCName;
/**
* Skip Transient Field
*/
private boolean skipTransientField = true;
/**
* @since 1.7.10
* default show author
*/
private boolean showAuthor = true;
/**
* convert request field to underline
*
* @since 1.8.7
*/
private boolean requestFieldToUnderline;
/**
* convert response field to underline
*
* @since 1.8.7
*/
private boolean responseFieldToUnderline;
/**
* sort by title
*
* @since 1.8.7
*/
private boolean sortByTitle;
/**
* is rest api doc
*
* @since 1.8.7
*/
private Boolean showJavaType = Boolean.FALSE;
/**
* is inline enum field comment
*
* @since 1.8.8
*/
private Boolean inlineEnum = Boolean.FALSE;
/**
* rpc consumer config example
*
* @since 1.8.7
*/
private String rpcConsumerConfig;
/**
* recursion limit
*
* @since 1.8.8
*/
private int recursionLimit = 7;
/**
* request example
*
* @since 1.9.0
*/
private boolean requestExample = Boolean.TRUE;
/**
* response example
*
* @since 1.9.0
*/
private boolean responseExample = Boolean.TRUE;
/**
* custom setting api document name
*
* @since 1.9.0
*/
private String allInOneDocFileName;
/**
* convert param data to tree
*/
private boolean paramsDataToTree;
/**
* request ignore param
*
* @return
* @since 1.9.2
*/
private List<String> ignoreRequestParams;
/**
* display actual type of generic
*
* @since 1.9.6
*/
private boolean displayActualType;
/**
* Support Spring MVC ResponseBodyAdvice
*
* @since 1.9.8
*/
private BodyAdvice responseBodyAdvice;
/**
* @since 2.1.4
*/
private BodyAdvice requestBodyAdvice;
private String style;
private String highlightStyleLink;
/**
* create debug page
*/
private boolean createDebugPage;
/**
* Spring MVC url suffix
*
* @since 2.1.0
*/
private String urlSuffix;
/**
* public static final String APP_KEY = "20201216788835306945118208";
* public static final String SECRET = "W.ZyGMOB9Q0UqujVxnfi@.I#V&tUUYZR";
* public static final String APP_TOKEN = "2f9a7d3858a147b7845ebb48785d4dc7";
* public static final String OPEN_URL = "http://torna.opensphere.cn/api/";
* @return
*/
/**
* Torna appKey
*/
private String appKey;
/**
* Torna Secret
*/
private String secret;
/**
* Torna appToken
*/
private String appToken;
/**
* Torna openUrl
*/
private String openUrl;
/**
* Debugging environment name
*/
private String debugEnvName;
/**
* Url of the debugging environment
*/
private String debugEnvUrl;
/**
* Show log when pushing document to torna
*/
private boolean tornaDebug = true;
/**
* The operator who pushes the document to Torna
*/
private String author;
/**
* smart-doc supported framework, if not set default is spring,
*/
private String framework;
private List<ApiGroup> groups;
/**
* replace old document while push to torna
* @since 2.2.4
*/
private Boolean replace;
/**
* @since 2.2.5
*/
private boolean requestParamsTable = Boolean.TRUE;
/**
* @since 2.2.5
*/
private boolean responseParamsTable = Boolean.TRUE;
public String getPathPrefix() {
return pathPrefix;
}
public void setPathPrefix(String pathPrefix) {
this.pathPrefix = pathPrefix;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public boolean isTornaDebug() {
return tornaDebug;
}
public void setTornaDebug(boolean tornaDebug) {
this.tornaDebug = tornaDebug;
}
public String getAppKey() {
return appKey;
}
public void setAppKey(String appKey) {
this.appKey = appKey;
}
public String getSecret() {
return secret;
}
public void setSecret(String secret) {
this.secret = secret;
}
public String getAppToken() {
return appToken;
}
public void setAppToken(String appToken) {
this.appToken = appToken;
}
public String getOpenUrl() {
return openUrl;
}
public void setOpenUrl(String openUrl) {
this.openUrl = openUrl;
}
public String getServerUrl() {
return serverUrl;
}
public void setServerUrl(String serverUrl) {
this.serverUrl = serverUrl;
}
public boolean isStrict() {
return isStrict;
}
public void setStrict(boolean strict) {
isStrict = strict;
}
public String getOutPath() {
return outPath;
}
public void setOutPath(String outPath) {
this.outPath = outPath;
}
public List<ApiReqParam> getRequestHeaders() {
return requestHeaders;
}
public void setRequestHeaders(List<ApiReqParam> requestHeaders) {
this.requestHeaders = requestHeaders;
}
public void setRequestHeaders(ApiReqParam... requestHeaders) {
this.requestHeaders = CollectionUtil.asList(requestHeaders);
this.requestHeaders.forEach(header -> header.setDesc(header.getDesc() + "(Global)"));
}
public List<ApiGroup> getGroups() {
return groups;
}
public ApiConfig setGroups(List<ApiGroup> groups) {
this.groups = groups;
return this;
}
public ApiConfig setGroups(ApiGroup... groups) {
this.groups = CollectionUtil.asList(groups);
return this;
}
public List<ApiReqParam> getRequestParams() {
return requestParams;
}
public ApiConfig setRequestParams(List<ApiReqParam> requestParams) {
this.requestParams = requestParams;
return this;
}
public void setRequestParams(ApiReqParam... requestParams) {
this.requestParams = CollectionUtil.asList(requestParams);
this.requestParams.forEach(param -> param.setDesc(param.getDesc() + "(Global)"));
}
public List<CustomField> getCustomResponseFields() {
return customResponseFields;
}
public void setCustomResponseFields(List<CustomField> customResponseFields) {
this.customResponseFields = customResponseFields;
}
public void setCustomResponseFields(CustomField... customResponseFields) {
this.customResponseFields = CollectionUtil.asList(customResponseFields);
}
public List<ApiErrorCode> getErrorCodes() {
return errorCodes;
}
public void setErrorCodes(List<ApiErrorCode> errorCodes) {
this.errorCodes = errorCodes;
}
public List<SourceCodePath> getSourceCodePaths() {
return sourceCodePaths;
}
public void setSourceCodePaths(List<SourceCodePath> sourceCodePaths) {
this.sourceCodePaths = sourceCodePaths;
}
public void setSourceCodePaths(SourceCodePath... sourcePaths) {
this.sourceCodePaths = CollectionUtil.asList(sourcePaths);
}
public boolean isAllInOne() {
return allInOne;
}
public void setAllInOne(boolean allInOne) {
this.allInOne = allInOne;
}
public String getPackageFilters() {
return packageFilters;
}
public void setPackageFilters(String packageFilters) {
this.packageFilters = packageFilters;
}
public List<RevisionLog> getRevisionLogs() {
return revisionLogs;
}
public void setRevisionLogs(List<RevisionLog> revisionLogs) {
this.revisionLogs = revisionLogs;
}
public void setRevisionLogs(RevisionLog... revisionLogs) {
this.revisionLogs = CollectionUtil.asList(revisionLogs);
}
public boolean isMd5EncryptedHtmlName() {
return md5EncryptedHtmlName;
}
public void setMd5EncryptedHtmlName(boolean md5EncryptedHtmlName) {
this.md5EncryptedHtmlName = md5EncryptedHtmlName;
}
public DocLanguage getLanguage() {
return language;
}
public void setLanguage(DocLanguage language) {
this.language = language;
}
public boolean isAdoc() {
return adoc;
}
public void setAdoc(boolean adoc) {
this.adoc = adoc;
}
public List<ApiDataDictionary> getDataDictionaries() {
return dataDictionaries;
}
public void setDataDictionaries(List<ApiDataDictionary> dataDictionaries) {
this.dataDictionaries = dataDictionaries;
}
public void setDataDictionaries(ApiDataDictionary... dataDictConfigs) {
this.dataDictionaries = CollectionUtil.asList(dataDictConfigs);
}
public ApiDataDictionary getDataDictionary(String enumClassName) {
if (Objects.isNull(this.dataDictionaries)) {
return null;
}
return this.dataDictionaries.stream().filter((apiDataDictionary ->
enumClassName.equalsIgnoreCase(apiDataDictionary.getEnumClassName())))
.findFirst().orElse(null);
}
public List<ApiErrorCodeDictionary> getErrorCodeDictionaries() {
return errorCodeDictionaries;
}
public void setErrorCodeDictionaries(List<ApiErrorCodeDictionary> errorCodeDictionaries) {
this.errorCodeDictionaries = errorCodeDictionaries;
}
public void setErrorCodeDictionaries(ApiErrorCodeDictionary... errorCodeDictConfigs) {
this.errorCodeDictionaries = CollectionUtil.asList(errorCodeDictConfigs);
}
public List<ApiObjectReplacement> getApiObjectReplacements() {
return apiObjectReplacements;
}
public void setApiObjectReplacements(List<ApiObjectReplacement> apiObjectReplacements) {
this.apiObjectReplacements = apiObjectReplacements;
}
public void setApiObjectReplacements(ApiObjectReplacement... apiObjectReplaces) {
this.apiObjectReplacements = CollectionUtil.asList(apiObjectReplaces);
}
public List<RpcApiDependency> getRpcApiDependencies() {
return rpcApiDependencies;
}
public void setRpcApiDependencies(List<RpcApiDependency> rpcApiDependencies) {
this.rpcApiDependencies = rpcApiDependencies;
}
public void setRpcApiDependencies(RpcApiDependency... rpcApiDependencies) {
this.rpcApiDependencies = CollectionUtil.asList(rpcApiDependencies);
}
public List<ApiConstant> getApiConstants() {
return apiConstants;
}
public void setApiConstants(List<ApiConstant> apiConstants) {
this.apiConstants = apiConstants;
}
public void setApiConstants(ApiConstant... apiConstants) {
this.apiConstants = CollectionUtil.asList(apiConstants);
}
public boolean isCoverOld() {
return coverOld;
}
public void setCoverOld(boolean coverOld) {
this.coverOld = coverOld;
}
public String getProjectName() {
return projectName;
}
public void setProjectName(String projectName) {
this.projectName = projectName;
}
public String getProjectCName() {
return projectCName;
}
public void setProjectCName(String projectCName) {
this.projectCName = projectCName;
}
public String getGroup() {
return group;
}
public void setGroup(String group) {
this.group = group;
}
public boolean isSkipTransientField() {
return skipTransientField;
}
public void setSkipTransientField(boolean skipTransientField) {
this.skipTransientField = skipTransientField;
}
public boolean isShowAuthor() {
return showAuthor;
}
public void setShowAuthor(boolean showAuthor) {
this.showAuthor = showAuthor;
}
public boolean isRequestFieldToUnderline() {
return requestFieldToUnderline;
}
public void setRequestFieldToUnderline(boolean requestFieldToUnderline) {
this.requestFieldToUnderline = requestFieldToUnderline;
}
public boolean isResponseFieldToUnderline() {
return responseFieldToUnderline;
}
public void setResponseFieldToUnderline(boolean responseFieldToUnderline) {
this.responseFieldToUnderline = responseFieldToUnderline;
}
public boolean isSortByTitle() {
return sortByTitle;
}
public void setSortByTitle(boolean sortByTitle) {
this.sortByTitle = sortByTitle;
}
public Boolean getShowJavaType() {
return showJavaType;
}
public void setShowJavaType(Boolean showJavaType) {
this.showJavaType = showJavaType;
}
public String getRpcConsumerConfig() {
return rpcConsumerConfig;
}
public void setRpcConsumerConfig(String rpcConsumerConfig) {
this.rpcConsumerConfig = rpcConsumerConfig;
}
public Boolean getInlineEnum() {
return inlineEnum;
}
public void setInlineEnum(Boolean inlineEnum) {
this.inlineEnum = inlineEnum;
}
public int getRecursionLimit() {
return recursionLimit;
}
public void setRecursionLimit(int recursionLimit) {
this.recursionLimit = recursionLimit;
}
public boolean isRequestExample() {
return requestExample;
}
public void setRequestExample(boolean requestExample) {
this.requestExample = requestExample;
}
public boolean isResponseExample() {
return responseExample;
}
public void setResponseExample(boolean responseExample) {
this.responseExample = responseExample;
}
public String getAllInOneDocFileName() {
return allInOneDocFileName;
}
public void setAllInOneDocFileName(String allInOneDocFileName) {
this.allInOneDocFileName = allInOneDocFileName;
}
public boolean isParamsDataToTree() {
return paramsDataToTree;
}
public void setParamsDataToTree(boolean paramsDataToTree) {
this.paramsDataToTree = paramsDataToTree;
}
public List<String> getIgnoreRequestParams() {
return ignoreRequestParams;
}
public void setIgnoreRequestParams(List<String> ignoreRequestParams) {
this.ignoreRequestParams = ignoreRequestParams;
}
public boolean isDisplayActualType() {
return displayActualType;
}
public void setDisplayActualType(boolean displayActualType) {
this.displayActualType = displayActualType;
}
public BodyAdvice getResponseBodyAdvice() {
return responseBodyAdvice;
}
public void setResponseBodyAdvice(BodyAdvice responseBodyAdvice) {
this.responseBodyAdvice = responseBodyAdvice;
}
public BodyAdvice getRequestBodyAdvice() {
return requestBodyAdvice;
}
public void setRequestBodyAdvice(BodyAdvice requestBodyAdvice) {
this.requestBodyAdvice = requestBodyAdvice;
}
public String getStyle() {
return style;
}
public void setStyle(String style) {
this.style = style;
}
public boolean isCreateDebugPage() {
return createDebugPage;
}
public void setCreateDebugPage(boolean createDebugPage) {
this.createDebugPage = createDebugPage;
}
public String getDebugEnvName() {
return debugEnvName;
}
public void setDebugEnvName(String debugEnvName) {
this.debugEnvName = debugEnvName;
}
public String getDebugEnvUrl() {
return debugEnvUrl;
}
public void setDebugEnvUrl(String debugEnvUrl) {
this.debugEnvUrl = debugEnvUrl;
}
public String getUrlSuffix() {
return urlSuffix;
}
public void setUrlSuffix(String urlSuffix) {
this.urlSuffix = urlSuffix;
}
public List<CustomField> getCustomRequestFields() {
return customRequestFields;
}
public ApiConfig setCustomRequestFields(List<CustomField> customRequestFields) {
this.customRequestFields = customRequestFields;
return this;
}
public void setCustomRequestFields(CustomField... customRequestFields) {
this.customRequestFields = CollectionUtil.asList(customRequestFields);
}
public String getFramework() {
return framework;
}
public void setFramework(String framework) {
this.framework = framework;
}
public Boolean getReplace() {
return replace;
}
public void setReplace(Boolean replace) {
this.replace = replace;
}
public boolean isRequestParamsTable() {
return requestParamsTable;
}
public void setRequestParamsTable(boolean requestParamsTable) {
this.requestParamsTable = requestParamsTable;
}
public boolean isResponseParamsTable() {
return responseParamsTable;
}
public void setResponseParamsTable(boolean responseParamsTable) {
this.responseParamsTable = responseParamsTable;
}
public String getHighlightStyleLink() {
return highlightStyleLink;
}
public void setHighlightStyleLink(String highlightStyleLink) {
this.highlightStyleLink = highlightStyleLink;
}
}

View File

@ -0,0 +1,88 @@
/*
* smart-doc https://github.com/shalousun/smart-doc
*
* Copyright (C) 2018-2021 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.model;
/**
* @author yu 2020/7/2.
*/
public class ApiConstant {
/**
* Constants class
*/
private Class constantsClass;
/**
* Constants class name
*/
private String constantsClassName;
/**
* Description
*/
private String description;
public static ApiConstant builder() {
return new ApiConstant();
}
public Class getConstantsClass() {
return constantsClass;
}
public ApiConstant setConstantsClass(Class constantsClass) {
this.constantsClass = constantsClass;
return this;
}
public String getConstantsClassName() {
return constantsClassName;
}
public ApiConstant setConstantsClassName(String constantsClassName) {
this.constantsClassName = constantsClassName;
return this;
}
public String getDescription() {
return description;
}
public ApiConstant setDescription(String description) {
this.description = description;
return this;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("{");
sb.append("\"constantsClass\":")
.append(constantsClass);
sb.append(",\"constantsClassName\":\"")
.append(constantsClassName).append('\"');
sb.append(",\"description\":\"")
.append(description).append('\"');
sb.append('}');
return sb.toString();
}
}

View File

@ -0,0 +1,140 @@
/*
* smart-doc
*
* Copyright (C) 2018-2021 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.model;
import com.power.common.model.EnumDictionary;
import com.power.common.util.EnumUtil;
import org.apache.commons.lang3.StringUtils;
import java.util.ArrayList;
import java.util.List;
/**
* @author yu 2019/10/31.
*/
public class ApiDataDictionary {
/**
* Dictionary
*/
private String title;
/**
* enumClass
*/
private Class<? extends Enum> enumClass;
/**
* enum class name
*/
private String enumClassName;
/**
* code field
*/
private String codeField;
/**
* description field
*/
private String descField;
public static ApiDataDictionary builder() {
return new ApiDataDictionary();
}
public String getTitle() {
return title;
}
public ApiDataDictionary setTitle(String title) {
this.title = title;
return this;
}
public Class getEnumClass() {
return enumClass;
}
public ApiDataDictionary setEnumClass(Class enumClass) {
this.enumClass = enumClass;
if (StringUtils.isBlank(this.enumClassName)) {
this.enumClassName = enumClass.getSimpleName();
}
return this;
}
public String getCodeField() {
return codeField;
}
public ApiDataDictionary setCodeField(String codeField) {
this.codeField = codeField;
return this;
}
public String getDescField() {
return descField;
}
public ApiDataDictionary setDescField(String descField) {
this.descField = descField;
return this;
}
public String getEnumClassName() {
return enumClassName;
}
public ApiDataDictionary setEnumClassName(String enumClassName) {
this.enumClassName = enumClassName;
return this;
}
public List<EnumDictionary> getEnumDataDict() {
if (this.enumClass != null) {
return EnumUtil.getEnumInformation(this.enumClass, this.getCodeField(),
this.getDescField());
} else {
return new ArrayList<>();
}
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("{");
sb.append("\"title\":\"")
.append(title).append('\"');
sb.append(",\"enumClass\":")
.append(enumClass);
sb.append(",\"enumClassName\":\"")
.append(enumClassName).append('\"');
sb.append(",\"codeField\":\"")
.append(codeField).append('\"');
sb.append(",\"descField\":\"")
.append(descField).append('\"');
sb.append('}');
return sb.toString();
}
}

View File

@ -0,0 +1,249 @@
/*
* smart-doc
*
* Copyright (C) 2018-2021 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.model;
import com.power.common.util.StringUtil;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
public class ApiDoc implements Comparable<ApiDoc> {
/**
* Order of controller
*
* @since 1.7+
*/
public Integer order;
/**
* controller name
*/
private String name;
/**
* controller alias handled by md5
*
* @since 1.7+
*/
private String alias;
/**
* tags
*
* @author cqmike
*/
private String[] tags;
/**
* group
*
* @author cqmike
*/
private String group;
/**
* class in package name
*
*/
private String packageName;
/**
* List of method doc
*/
private List<ApiMethodDoc> list;
/**
* method description
*/
private String desc;
/**
* link
*/
private String link;
private String author;
/**
* if this is group, then is true
*/
private boolean isFolder;
/**
* children
*/
private List<ApiDoc> childrenApiDocs = new ArrayList<>();
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<ApiMethodDoc> getList() {
return list;
}
public void setList(List<ApiMethodDoc> list) {
this.list = list;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public Integer getOrder() {
return order;
}
public void setOrder(Integer order) {
this.order = order;
}
public String getAlias() {
return alias;
}
public void setAlias(String alias) {
this.alias = alias;
}
public String[] getTags() {
return tags;
}
public void setTags(String[] tags) {
this.tags = tags;
}
public String getLink() {
if (StringUtil.isNotEmpty(link)) {
return link;
}
return desc.replace(" ", "_").toLowerCase();
}
public void setLink(String link) {
this.link = link;
}
public String getPackageName() {
return packageName;
}
public void setPackageName(String packageName) {
this.packageName = packageName;
}
public String getGroup() {
return group;
}
public void setGroup(String group) {
this.group = group;
}
public boolean isFolder() {
return isFolder;
}
public void setFolder(boolean folder) {
isFolder = folder;
}
public List<ApiDoc> getChildrenApiDocs() {
return childrenApiDocs;
}
public void setChildrenApiDocs(List<ApiDoc> childrenApiDocs) {
this.childrenApiDocs = childrenApiDocs;
}
@Override
public int compareTo(ApiDoc o) {
if (Objects.nonNull(o.getDesc())) {
return desc.compareTo(o.getDesc());
}
return name.compareTo(o.getName());
}
public static ApiDoc buildTagApiDoc(ApiDoc source, String tag, ApiMethodDoc methodDoc) {
ApiDoc apiDoc = new ApiDoc();
apiDoc.setAlias(source.getAlias());
apiDoc.setLink(source.getLink());
apiDoc.setDesc(tag);
apiDoc.setAuthor(source.getAuthor());
apiDoc.setPackageName(source.getPackageName());
apiDoc.setName(tag);
apiDoc.setList(new ArrayList<>());
ApiMethodDoc clone = methodDoc.clone();
clone.setOrder(apiDoc.getList().size() + 1);
apiDoc.getList().add(clone);
return apiDoc;
}
public static ApiDoc buildGroupApiDoc(String group) {
ApiDoc apiDoc = new ApiDoc();
apiDoc.setFolder(true);
apiDoc.setGroup(group);
apiDoc.setName(group);
apiDoc.setDesc(group);
apiDoc.setChildrenApiDocs(new ArrayList<>());
return apiDoc;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("{");
sb.append("\"order\":")
.append(order);
sb.append(",\"name\":\"")
.append(name).append('\"');
sb.append(",\"alias\":\"")
.append(alias).append('\"');
sb.append(",\"list\":")
.append(list);
sb.append(",\"desc\":\"")
.append(desc).append('\"');
sb.append('}');
return sb.toString();
}
}

View File

@ -0,0 +1,85 @@
/*
* smart-doc
*
* Copyright (C) 2018-2021 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.model;
import java.util.List;
/**
* @author yu 2019/10/31.
*/
public class ApiDocDict {
/**
* order
*/
private int order;
/**
* dict title
*/
private String title;
/**
* data dict
*/
private List<DataDict> dataDictList;
public int getOrder() {
return order;
}
public void setOrder(int order) {
this.order = order;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public List<DataDict> getDataDictList() {
return dataDictList;
}
public void setDataDictList(List<DataDict> dataDictList) {
this.dataDictList = dataDictList;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("{");
sb.append("\"order\":")
.append(order);
sb.append(",\"title\":\"")
.append(title).append('\"');
sb.append(",\"dataDictList\":")
.append(dataDictList);
sb.append('}');
return sb.toString();
}
}

View File

@ -0,0 +1,34 @@
/*
* smart-doc
*
* Copyright (C) 2018-2021 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.model;
import com.power.common.model.EnumDictionary;
/**
* Description:
* restful api error code
*
* @author yu 2018/06/25.
*/
public class ApiErrorCode extends EnumDictionary {
}

View File

@ -0,0 +1,109 @@
/*
* smart-doc
*
* Copyright (C) 2018-2021 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.model;
/**
* @author yu 2019/12/7.
* @since 1.7.9
*/
public class ApiErrorCodeDictionary {
/**
* enumClass
*/
private Class<? extends Enum> enumClass;
/**
* enum class name
*/
private String enumClassName;
/**
* code field
*/
private String codeField;
/**
* description field
*/
private String descField;
@Deprecated
public static ApiErrorCodeDictionary dict() {
return new ApiErrorCodeDictionary();
}
public static ApiErrorCodeDictionary builder() {
return new ApiErrorCodeDictionary();
}
public Class getEnumClass() {
return enumClass;
}
public ApiErrorCodeDictionary setEnumClass(Class enumClass) {
this.enumClass = enumClass;
return this;
}
public String getCodeField() {
return codeField;
}
public ApiErrorCodeDictionary setCodeField(String codeField) {
this.codeField = codeField;
return this;
}
public String getDescField() {
return descField;
}
public ApiErrorCodeDictionary setDescField(String descField) {
this.descField = descField;
return this;
}
public String getEnumClassName() {
return enumClassName;
}
public ApiErrorCodeDictionary setEnumClassName(String enumClassName) {
this.enumClassName = enumClassName;
return this;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("{");
sb.append("\"enumClass\":")
.append(enumClass);
sb.append(",\"enumClassName\":\"")
.append(enumClassName).append('\"');
sb.append(",\"codeField\":\"")
.append(codeField).append('\"');
sb.append(",\"descField\":\"")
.append(descField).append('\"');
sb.append('}');
return sb.toString();
}
}

View File

@ -0,0 +1,55 @@
package com.power.doc.model;
/**
* api group
*
* @author cqmike
* @version 1.0.0
* @since 2021年07月31日 16:39:00
*/
public class ApiGroup {
/**
* group name
*/
private String name;
/**
* package name
* support patten
*/
private String apis;
/**
* url path
* support patten
*/
private String paths;
public String getName() {
return name;
}
public ApiGroup setName(String name) {
this.name = name;
return this;
}
public String getApis() {
return apis;
}
public ApiGroup setApis(String apis) {
this.apis = apis;
return this;
}
public String getPaths() {
return paths;
}
public ApiGroup setPaths(String paths) {
this.paths = paths;
return this;
}
}

View File

@ -0,0 +1,536 @@
/*
* smart-doc
*
* Copyright (C) 2018-2021 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.model;
import com.power.common.util.StringUtil;
import com.power.doc.constants.DocGlobalConstants;
import com.power.doc.model.request.ApiRequestExample;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
/**
* java api method info model.
*/
public class ApiMethodDoc implements Serializable, Cloneable {
private static final long serialVersionUID = 7211922919532562867L;
/**
* methodId handled by md5
*
* @since 1.7.3 +
*/
private String methodId;
/**
* method name
*
* @since 1.7.3 +
*/
private String name;
/**
* method order
*
* @since 1.7+
*/
private int order;
/**
* method description
*/
private String desc;
/**
* detailed introduction of the method
*/
private String detail;
/**
* server url
*/
private String serverUrl;
/**
* controller method url contains server
*/
private String url;
/**
* controller path
*/
private String path;
/**
* http request type
*/
private String type;
/**
* http request author
*/
private String author;
/**
* only used for generate markdown and adoc
* http readers
*/
private String headers;
/**
* http contentType
*/
private String contentType = DocGlobalConstants.URL_CONTENT_TYPE;
/**
* http request headers
*/
private List<ApiReqParam> requestHeaders;
/**
* path params
*/
private List<ApiParam> pathParams;
/**
* query params
*/
private List<ApiParam> queryParams;
/**
* http request params
*/
private List<ApiParam> requestParams;
/**
* http request-example usage(requestUrlParam + requestBody)
*/
private String requestUsage;
/**
* request example detail
*/
private ApiRequestExample requestExample;
/**
* http response usage
*/
private String responseUsage;
/**
* http response params
*/
private List<ApiParam> responseParams;
/**
* method deprecated
*/
private boolean deprecated;
/**
* return schema
*/
private Map<String, Object> returnSchema;
/**
* request schema
*/
private Map<String, Object> requestSchema;
/**
* api group
*/
private String group;
/**
* marking download
*/
private boolean download;
/**
* link
*/
private String link;
/**
* mark page
*/
private String page = "";
/**
* torna request is array
*/
private Integer isRequestArray;
/**
* torna request is array-type
*/
private String requestArrayType;
/**
* torna response is array
*/
private Integer isResponseArray;
/**
* torna request is array
*/
private String responseArrayType;
/**
* 是否为List数据 openApi
*/
private boolean listParam = false;
/**
* tags
*/
private String[] tags;
public Integer getIsRequestArray() {
return isRequestArray;
}
public void setIsRequestArray(Integer isRequestArray) {
this.isRequestArray = isRequestArray;
}
public String getRequestArrayType() {
return requestArrayType;
}
public void setRequestArrayType(String requestArrayType) {
this.requestArrayType = requestArrayType;
}
public Integer getIsResponseArray() {
return isResponseArray;
}
public void setIsResponseArray(Integer isResponseArray) {
this.isResponseArray = isResponseArray;
}
public String getResponseArrayType() {
return responseArrayType;
}
public void setResponseArrayType(String responseArrayType) {
this.responseArrayType = responseArrayType;
}
public boolean isListParam() {
return listParam;
}
public void setListParam(boolean listParam) {
this.listParam = listParam;
}
public String getMethodId() {
return methodId;
}
public void setMethodId(String methodId) {
this.methodId = methodId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getResponseUsage() {
return responseUsage;
}
public void setResponseUsage(String responseUsage) {
this.responseUsage = responseUsage;
}
public String getRequestUsage() {
return requestUsage;
}
public void setRequestUsage(String requestUsage) {
this.requestUsage = requestUsage;
}
public String getContentType() {
return contentType;
}
public void setContentType(String contentType) {
this.contentType = contentType;
}
public String getHeaders() {
return headers;
}
public void setHeaders(String headers) {
this.headers = headers;
}
public int getOrder() {
return order;
}
public void setOrder(int order) {
this.order = order;
}
public List<ApiParam> getRequestParams() {
return requestParams;
}
public void setRequestParams(List<ApiParam> requestParams) {
this.requestParams = requestParams;
}
public List<ApiParam> getResponseParams() {
return responseParams;
}
public void setResponseParams(List<ApiParam> responseParams) {
this.responseParams = responseParams;
}
public List<ApiReqParam> getRequestHeaders() {
return requestHeaders;
}
public void setRequestHeaders(List<ApiReqParam> requestHeaders) {
this.requestHeaders = requestHeaders;
}
public String getDetail() {
return detail;
}
public void setDetail(String detail) {
this.detail = detail;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public String getServerUrl() {
return serverUrl;
}
public void setServerUrl(String serverUrl) {
this.serverUrl = serverUrl;
}
public ApiRequestExample getRequestExample() {
return requestExample;
}
public void setRequestExample(ApiRequestExample requestExample) {
this.requestExample = requestExample;
}
public boolean isDeprecated() {
return deprecated;
}
public void setDeprecated(boolean deprecated) {
this.deprecated = deprecated;
}
public List<ApiParam> getPathParams() {
return pathParams;
}
public void setPathParams(List<ApiParam> pathParams) {
this.pathParams = pathParams;
}
public List<ApiParam> getQueryParams() {
return queryParams;
}
public void setQueryParams(List<ApiParam> queryParams) {
this.queryParams = queryParams;
}
public Map<String, Object> getReturnSchema() {
return returnSchema;
}
public void setReturnSchema(Map<String, Object> returnSchema) {
this.returnSchema = returnSchema;
}
public Map<String, Object> getRequestSchema() {
return requestSchema;
}
public void setRequestSchema(Map<String, Object> requestSchema) {
this.requestSchema = requestSchema;
}
public String getGroup() {
return group;
}
public void setGroup(String group) {
this.group = group;
}
public boolean isDownload() {
return download;
}
public void setDownload(boolean download) {
this.download = download;
}
public String getLink() {
if (StringUtil.isNotEmpty(link)) {
return link;
}
return desc.replace(" ", "_").toLowerCase();
}
public void setLink(String link) {
this.link = link;
}
public String getPage() {
return page;
}
public void setPage(String page) {
this.page = page;
}
public String[] getTags() {
return tags;
}
public ApiMethodDoc setTags(String[] tags) {
this.tags = tags;
return this;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("{");
sb.append("\"methodId\":\"")
.append(methodId).append('\"');
sb.append(",\"name\":\"")
.append(name).append('\"');
sb.append(",\"order\":")
.append(order);
sb.append(",\"desc\":\"")
.append(desc).append('\"');
sb.append(",\"detail\":\"")
.append(detail).append('\"');
sb.append(",\"serverUrl\":\"")
.append(serverUrl).append('\"');
sb.append(",\"url\":\"")
.append(url).append('\"');
sb.append(",\"path\":\"")
.append(path).append('\"');
sb.append(",\"type\":\"")
.append(type).append('\"');
sb.append(",\"author\":\"")
.append(author).append('\"');
sb.append(",\"headers\":\"")
.append(headers).append('\"');
sb.append(",\"contentType\":\"")
.append(contentType).append('\"');
sb.append(",\"requestHeaders\":")
.append(requestHeaders);
sb.append(",\"pathParams\":")
.append(pathParams);
sb.append(",\"queryParams\":")
.append(queryParams);
sb.append(",\"requestParams\":")
.append(requestParams);
sb.append(",\"requestUsage\":\"")
.append(requestUsage).append('\"');
sb.append(",\"requestExample\":")
.append(requestExample);
sb.append(",\"responseUsage\":\"")
.append(responseUsage).append('\"');
sb.append(",\"responseParams\":")
.append(responseParams);
sb.append(",\"deprecated\":")
.append(deprecated);
sb.append('}');
return sb.toString();
}
@Override
public ApiMethodDoc clone() {
try {
return (ApiMethodDoc) super.clone();
} catch (CloneNotSupportedException e) {
throw new RuntimeException("clone apiMethodDoc is error", e);
}
}
}

View File

@ -0,0 +1,77 @@
/*
* smart-doc
*
* Copyright (C) 2018-2021 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.model;
import java.util.List;
/**
* @author yu 2020/11/26.
*/
public class ApiMethodReqParam {
/**
* path params
*/
private List<ApiParam> pathParams;
/**
* query params
*/
private List<ApiParam> queryParams;
/**
* http request params
*/
private List<ApiParam> requestParams;
public static ApiMethodReqParam builder() {
return new ApiMethodReqParam();
}
public List<ApiParam> getPathParams() {
return pathParams;
}
public ApiMethodReqParam setPathParams(List<ApiParam> pathParams) {
this.pathParams = pathParams;
return this;
}
public List<ApiParam> getQueryParams() {
return queryParams;
}
public ApiMethodReqParam setQueryParams(List<ApiParam> queryParams) {
this.queryParams = queryParams;
return this;
}
public List<ApiParam> getRequestParams() {
return requestParams;
}
public ApiMethodReqParam setRequestParams(List<ApiParam> requestParams) {
this.requestParams = requestParams;
return this;
}
}

Some files were not shown because too many files have changed in this diff Show More