Compare commits

...

596 Commits

Author SHA1 Message Date
Robert Winkler
81edab38f3 The notBlank validation of the type should tell which parameter is not valid. 2017-01-03 15:58:43 +01:00
Robert Winkler
039607a294 Updated version to 1.2.0-SNAPSHOT 2017-01-03 15:27:32 +01:00
Cas Eliëns
2f33522e6d Issue #214 Added support for page breaks (#226)
* Added support for page breaks
* Added documentation and config file support for page breaks and regex
2017-01-03 11:21:31 +01:00
Cas Eliëns
76c54a713a use raw JSON object instead of converting to string 2017-01-02 13:47:02 +01:00
Cas Eliëns
dcebed2d42 split reused code into methods 2017-01-02 13:47:02 +01:00
Cas Eliëns
dbf9afa8da Remove unused import 2017-01-02 13:47:02 +01:00
Cas Eliëns
f7f397b5f2 Improve printing for different ways of defining examples 2017-01-02 13:47:02 +01:00
Cas Eliëns
44f852ad42 Improve example printing for $ref'd examples 2017-01-02 13:47:02 +01:00
Cas Eliëns
e1be2f2130 Great Expectations 2017-01-02 13:47:02 +01:00
Cas Eliëns
8468607703 Improve example rendering for hardcoded examples 2017-01-02 13:47:02 +01:00
Cas Eliëns
f981318142 Example responses now display correctly 2017-01-02 13:47:02 +01:00
Cas Eliëns
e1d0d7b293 Add FIXME comment 2017-01-02 13:47:02 +01:00
Cas Eliëns
d118a0cf74 Further work on Swagger2Markup/swagger2markup#223 2017-01-02 13:47:02 +01:00
Cas Eliëns
7cb1095465 Begin work on Swagger2Markup/swagger2markup#223 2017-01-02 13:47:02 +01:00
Cas Eliëns
595b885b9a Close Swagger2Markup/swagger2markup#220 2016-12-20 14:07:27 +01:00
Cas Eliëns
b1c219bc1b Remove unused code, optimize imports, fix Codacy issues
* Begin working on Swagger2Markup/swagger2markup#215

* Begin looking for methods that need to be modified for Swagger2Markup/swagger2markup#215

* Begin working on Swagger2Markup/swagger2markup#215

* Begin looking for methods that need to be modified for Swagger2Markup/swagger2markup#215

* Work on implementing regex sorting

* Add regex ordering translations and unit test

* Improve Regex grouping

* Make regex sorting test more like a real-world example

* Remove unused imports

* Improve code style consistency

* Improve code style consistency

* Remove empty statement

* Resolve some Codacy issues

* Remove empty constructors

* Remove unused fields

* Merge nested IF statements

* Improve method scopes

* Remove unused classes

* Remove unused imports

* Remove fixed TODO comment

* Fix codacy issues

* Fix codacy issues (reverted from commit 43f27e7fc6)

* Improve code style consistency

* Resolve some Codacy issues

* Remove empty constructors

* Remove unused fields

* Merge nested IF statements

* Improve method scopes

* Remove unused classes

* Remove unused imports

* Remove fixed TODO comment

* Fix codacy issues
2016-12-19 16:04:17 +01:00
Cas Eliëns
852b2ac3b4 PR#218 Improve code style consistency
Improved code style consistency
2016-12-13 10:44:31 +01:00
Cas Eliëns
937cded2aa Issue #215: Path grouping via a RegEx pattern
* Begin working on Swagger2Markup/swagger2markup#215

* Begin looking for methods that need to be modified for Swagger2Markup/swagger2markup#215

* Begin working on Swagger2Markup/swagger2markup#215

* Begin looking for methods that need to be modified for Swagger2Markup/swagger2markup#215

* Work on implementing regex sorting

* Add regex ordering translations and unit test

* Improve Regex grouping

* Make regex sorting test more like a real-world example

* Remove unused imports
2016-12-13 09:58:12 +01:00
Robert Winkler
022d2453d2 Issee #216: Replace slash with system file separator in unit tests. 2016-12-09 09:17:55 +01:00
Robert Winkler
e5a187cc24 Updated version to 1.1.2-SNAPSHOT 2016-11-30 09:18:22 +01:00
Robert Winkler
83bb63321a Updated markup-document-builder from 1.0.0 to 1.1.0 2016-11-30 08:20:04 +01:00
Robert Winkler
cd5b5c9240 Refactored ParameterAdapter and created MarkupDocBuilderUtils. 2016-11-18 12:36:39 +01:00
Robert Winkler
2096ec0d5d Refactored ParameterAdapter and moved ParameterAdapter and PropertyAdapter into a new package. 2016-11-16 12:54:32 +01:00
Robert Winkler
25d4311237 Added a modularized Swagger spec test 2016-11-16 12:54:03 +01:00
Robert Winkler
7e07c2fc81 Fixed method name in DefinitionsDocument 2016-11-15 14:50:45 +01:00
Robert Winkler
5a8a618e6b Refactored document resolver and added tests. 2016-11-15 14:47:11 +01:00
Robert Winkler
f072fc99b9 Refactored Documents. Documents are also components now and can be composed of components. 2016-11-15 11:12:17 +01:00
Robert Winkler
54e881fc58 Fixed wrong import in SecuritySchemeComponent 2016-11-14 16:14:16 +01:00
Robert Winkler
cd6a3ed724 Refactored Components to be more functional. 2016-11-14 16:08:24 +01:00
Robert Winkler
5a00dde912 Refactored Components to be more functional. 2016-11-14 16:02:49 +01:00
Robert Winkler
876d7b2f7b Moved code into BodyParameterComponent 2016-11-11 14:21:43 +01:00
Robert Winkler
4b74ec0e54 Moved code into PathOperationComponent 2016-11-11 13:30:04 +01:00
Robert Winkler
a719e33332 Moved code into SecuritySchemeComponent 2016-11-11 10:29:51 +01:00
Robert Winkler
86a727f097 Refactored DocumentBuilder into components. 2016-11-10 15:48:03 +01:00
Robert Winkler
2670780076 Enhancement #206 Updated to markup-document-builder v1.1.0 which renders bold text as **text** and italic text as __text__. 2016-11-10 12:42:52 +01:00
Robert Winkler
ebf9912269 Bug #205: Fix ordering of operations when grouped by tags. 2016-11-10 12:41:26 +01:00
Robert Winkler
11549ab64e Bug #205: Fix ordering of operations when grouped by tags. 2016-11-10 10:43:12 +01:00
Robert Winkler
d128146952 Added a component API to split a document into components and improve component testability 2016-11-09 16:30:02 +01:00
Robert Winkler
686abd8842 Added a component API to split a document into components and improve component testability 2016-11-09 15:02:28 +01:00
Robert Winkler
551aeed835 Removed ListUtils and changed MapUtils.toKeySet to MapUtils.toSortedMap 2016-11-08 12:28:27 +01:00
Robert Winkler
5b1a1a2bcf Migrated some collections to Javaslang 2016-11-08 10:18:07 +01:00
Robert Winkler
09d2474a9a Added javaslang and paleo-core to improve Table rendering 2016-11-04 15:32:17 +01:00
Robert Winkler
5c00e5493c Removed ExternalLocation model from inlineSchema test. 2016-11-04 15:32:17 +01:00
Robert Winkler
c343af8f5a Updated Gradle to v3.1 2016-11-04 15:32:17 +01:00
yewton
4af7eb5b89 Add support for Japanese 2016-11-02 08:45:42 +01:00
Robert Winkler
aa9a340144 Added a config parameter which allows to prepend the basePath to all paths. 2016-11-01 14:42:46 +01:00
Robert Winkler
35ae68ceee Fixed german and spanish language files 2016-11-01 08:55:04 +01:00
Robert Winkler
560fb4ece6 Added language file for Portuguese (Brazilian) 2016-11-01 08:30:28 +01:00
Cleydson Júnior
8eb494cd5b Converting special characters to ASCII escape codes 2016-11-01 07:05:19 +01:00
Cleydson Júnior
0766336a56 Adding support for Brazilian Portuguese 2016-11-01 07:05:19 +01:00
TzeKai Lee
24352f4d1c Add format tests on request param in query and body 2016-10-28 09:07:56 +02:00
TzeKei Lee
adb0fee973 Added displaying format for string type and definitions only contains string or integer type. 2016-10-28 09:07:56 +02:00
Robert Winkler
13a7113aa7 Fixes #197 Converted ZH-language file from UTF-8 to latin1 using native2asciidoc 2016-10-25 15:25:27 +02:00
Robert Winkler
e882975726 Updated README 2016-10-18 15:27:06 +02:00
Robert Winkler
12209fe923 Updated version to 1.1.0 2016-10-18 15:14:05 +02:00
Robert Winkler
8a63744198 Updated releases notes 2016-10-18 15:11:52 +02:00
James Bassett
5871f0c9b0 Added support for exclusiveMin and exclusiveMax 2016-10-14 07:12:53 +02:00
James Bassett
908f524c64 Updated min/max value to format correctly based on the data type 2016-10-12 08:47:54 +02:00
Francisco José Bermejo Herrera
9fa0ee3def Add support for Spanish language 2016-10-03 13:46:12 +02:00
Robert Winkler
35e9450f74 Updated docker documentation 2016-09-23 10:29:46 +02:00
Robert Winkler
6033ea5a98 Updated docker documentation 2016-09-23 10:21:02 +02:00
Robert Winkler
6f24c3cb39 Merge remote-tracking branch 'origin/master' 2016-09-23 08:54:37 +02:00
Robert Winkler
e975e49d3e Added docker documentation 2016-09-23 08:54:18 +02:00
Robert Winkler
c5cfe10fa6 Merge pull request #187 from KristinaGen/master
update labels_ru
2016-09-14 09:55:56 +02:00
KristinaGen
7c988460f0 update labels_ru 2016-09-13 16:20:57 +02:00
Robert Winkler
21f1892de0 Added chinese language 2016-09-12 10:02:02 +02:00
Robert Winkler
b97344849d Merge pull request #186 from mingkaili/patch-1
labels_zh.properties
2016-09-12 09:49:43 +02:00
Mingkai Lee
935d48d4cc labels_zh.properties
Add chinese labels.properties. Add chinese language.
2016-09-12 10:26:16 +08:00
Robert Winkler
73ba233f9e Merge pull request #181 from iwannayoyo/Remove_empty_columns
eliminate empty columns in tables
2016-08-31 10:20:25 +02:00
Chris Hartman
ff955d392b eliminate empty columns in tables 2016-08-25 16:43:17 -04:00
Robert Winkler
19fde31f67 Merge pull request #177 from mhswisscom/Fix_without_reformat
recursive examples patch without reformatting
2016-08-25 13:49:45 +02:00
Marc Habegger
b3f368ac37 recursive examples patch without reformatting 2016-08-25 13:33:27 +02:00
Robert Winkler
c5efb401b4 Added releaseVersion to build.gradle and documentation.gradle scripts so that the AsciiDoc documentation always refers to the release version and not to the SNAPSHOT version. 2016-08-04 12:10:08 +02:00
Robert Winkler
f386e6ed91 Updated version to 1.0.2-SNAPSHOT 2016-08-04 10:28:30 +02:00
Robert Winkler
55b323c063 Merge pull request #171 from zerok/fix/emptycontact
Allow empty contact objects
2016-08-04 10:25:14 +02:00
Robert Winkler
6f286b52d8 Prepare release v1.0.1 2016-08-04 10:03:08 +02:00
Horst Gutmann
4850673b96 Allow empty contact objects
According to the spec the contact object can be empty (it doesn't have
any required properties). Previously, the markup generation failed in
that situation due to an empty paragraph being generated. This change
fixes that.
2016-08-04 10:00:33 +02:00
Robert Winkler
353af537ba Prepare release v1.0.1 2016-08-04 09:49:35 +02:00
Robert Winkler
2367d86eb7 Merge pull request #170 from zerok/fix/instagram-fenced-code-adoc
Fixes expected output of testSwagger2AsciiDocConversionInstagram
2016-08-03 10:11:43 +02:00
Horst Gutmann
1aec46a57c Fixes expected output of testSwagger2AsciiDocConversionInstagram
The fenced code block in the original specification was previously
converted to something resembling an inline code element, while
the new output now contains an actual code block.

This closes #168.
2016-08-03 09:38:33 +02:00
Robert Winkler
f650fb7b3e Fixed wrong expected test files after merging PR #149 and PR #156 2016-08-02 19:35:27 +02:00
Robert Winkler
568d6a6441 Failed tests shouldn't be ignored 2016-07-30 20:52:54 +02:00
Robert Winkler
630e86cd31 Merge pull request #167 from afdia/master
new property "pathSecuritySectionEnabled" (default: true)
2016-07-30 20:31:14 +02:00
Andreas
0e3e229434 + new property "pathSecuritySectionEnabled" (default: true)
The property decides whether to add the security section for every path
(introduced in pull request #63)
2016-07-30 12:18:12 +02:00
Hugo de Paix de Coeur
f41d1cbcb0 missing FR translations 2016-06-21 13:47:09 +02:00
Hugo de Paix de Coeur
20b653086d Merge pull request #156 from jfiala/master
validation constraints, german translations
2016-06-17 11:16:46 +02:00
Johannes Fiala
ae4cf35de4 validation constraints, german translations (#156) 2016-06-16 19:04:58 +02:00
Johannes Fiala
86fc9a9746 add expected results #160 2016-06-15 22:41:17 +02:00
Johannes Fiala
1b4626d9ca update test cases #160 2016-06-15 22:36:40 +02:00
Johannes Fiala
7528b34ba3 Merge branch 'master' of https://github.com/jfiala/swagger2markup 2016-06-15 22:35:23 +02:00
Johannes Fiala
ebecde1768 update test cases #160 2016-06-15 22:35:00 +02:00
Johannes Fiala
2301de6466 update test examples #160 2016-06-15 22:32:34 +02:00
Johannes Fiala
f7efad2480 Merge branch 'master' of https://github.com/jfiala/swagger2markup
Conflicts:
	src/test/resources/expected/asciidoc/validators/definitions.adoc
	src/test/resources/json/swagger_validators.json
2016-06-15 22:29:12 +02:00
Johannes Fiala
c23bd01495 add more cases to minimum/maximum tests 2016-06-15 22:28:42 +02:00
Johannes Fiala
7e5986237a Merge branch 'master' of https://github.com/jfiala/swagger2markup
Conflicts:
	src/test/resources/expected/asciidoc/validators/definitions.adoc
	src/test/resources/json/swagger_validators.json
2016-06-15 22:25:24 +02:00
Johannes Fiala
1bf26c95e3 Added simple json + test cases for validators #160´ 2016-06-15 22:19:56 +02:00
Johannes Fiala
3888e67d02 Added simple json + test cases for validators #160´ 2016-06-15 22:18:10 +02:00
Johannes Fiala
54e17321b6 Fixed check for description 2016-06-13 12:01:50 +02:00
Johannes Fiala
90f56cfe61 Merge branch 'master' of https://github.com/jfiala/swagger2markup 2016-06-13 11:56:21 +02:00
Johannes Fiala
44e33ad6f3 Fixed line-break issue if no description is present - should always
check for descriptionContent instead of description
2016-06-13 11:55:59 +02:00
Johannes Fiala
65d4e0c225 Merge branch 'master' of https://github.com/jfiala/swagger2markup 2016-06-12 18:53:59 +02:00
Johannes Fiala
d37a374d02 added example for min/max at order.quantity #160 2016-06-12 18:53:12 +02:00
Johannes Fiala
5bb5e5ff29 added new definition of swagger petstore #159 in separate file 2016-06-12 18:20:23 +02:00
Johannes Fiala
de1f84d2aa reseted to original swagger_petstore.yaml, added example for
minlength/maxlength/pattern
2016-06-12 18:12:55 +02:00
Johannes Fiala
aa35c0169c Update swagger_petstore.yaml to current version #159 2016-06-12 17:49:52 +02:00
Johannes Fiala
b53727842a Suggest adding eclipse plugin to support gradle eclipse #158 2016-06-12 17:17:56 +02:00
Johannes Fiala
f88e3d2ed4 added check if minlength equals maxlength 2016-06-12 17:15:07 +02:00
Johannes Fiala
eefda62d99 Added query if minlength equals maxlength #147 2016-06-12 17:08:56 +02:00
Johannes Fiala
592446f714 Removed quotes for Minlength/Maxlength #147 2016-06-12 17:05:45 +02:00
Johannes Fiala
3275a07325 German translations - fine tuning #157 2016-06-12 16:56:03 +02:00
Johannes Fiala
1c2b9eee26 validation constraints don't appear in generated docs #147 2016-06-12 16:50:25 +02:00
Hugo de Paix de Coeur
3a5533447b Merge pull request #149 from filip-owczarzak/Columns-Width-Too-Small
1st column in table extended width in order to avoid text wrapping
2016-06-01 14:59:50 +02:00
Filip Owczarzak
2fcd2d1a79 1st column in tables width set to 2 2016-06-01 13:49:15 +02:00
Robert Winkler
07d878be35 Added release Version to docs 2016-05-29 07:11:25 +02:00
Robert Winkler
7a75d7874b Added release Version to docs 2016-05-28 21:17:42 +02:00
Robert Winkler
99c3044218 Added release Version to docs 2016-05-28 20:49:46 +02:00
Robert Winkler
fec5fb54bb Added release Version to docs 2016-05-28 20:48:34 +02:00
Robert Winkler
031051f1f9 Added release Version to docs 2016-05-28 20:47:52 +02:00
Robert Winkler
d432c398cf Added release Version to docs 2016-05-28 20:35:07 +02:00
Robert Winkler
8eb44c26d2 Added release Version to docs 2016-05-28 20:25:23 +02:00
Robert Winkler
3a76a3e920 Added release Version to docs 2016-05-28 20:24:14 +02:00
Robert Winkler
52e80e7af6 Updated readme 2016-05-28 20:21:00 +02:00
Hugo de Paix de Coeur
1eac6a63d9 set development version to 1.0.1-SNAPSHOT 2016-05-26 16:21:42 +02:00
Hugo de Paix de Coeur
6e379042a0 #152 keep track of properties order in Composed models so that OrderBy.AS_IS works as expected 2016-05-26 13:22:37 +02:00
hdr
8367195315 fixes #150 create empty object when Swagger Parser fails to convert composed items
Added Instagram API conversion to tests next to PetStore
2016-05-26 11:23:26 +02:00
Hugo de Paix de Coeur
7de954958d Merge pull request #151 from johanhammar/master
Fix invalid XML in documentation
2016-05-26 08:24:39 +02:00
Johan Hammar
a161924a7f Fix invalid XML in documentation 2016-05-25 21:24:19 +02:00
hdr
9568f3a960 #148 Removed NPE in ExamplesUtil::exampleMapForProperties 2016-05-24 14:20:37 +02:00
Filip Owczarzak
fdb24fdf33 1st column in table extended width in order to avoid text wrapping 2016-05-24 10:28:12 +02:00
Robert Winkler
3c0f935e99 Merge remote-tracking branch 'origin/master' 2016-05-12 09:54:49 +02:00
Robert Winkler
826f4ff762 Updated images 2016-05-12 09:54:39 +02:00
Robert Winkler
ed926139b8 Updated readme 2016-05-04 21:05:59 +02:00
Robert Winkler
cb23bfe1a4 Updated Bintray badge 2016-05-02 13:22:04 +02:00
Robert Winkler
ab7d355fe4 Prepare release v1.0.0 2016-05-02 13:06:54 +02:00
Robert Winkler
87ccc182f1 Prepare release v1.0.0 2016-04-29 14:12:21 +02:00
Robert Winkler
ff21d7c985 Fixes #136: Moved default value of a property into the description column. 2016-04-19 13:09:03 +02:00
Robert Winkler
b69797ef51 Fixed levelOffset calculation when using paths grouped by TAGS 2016-04-19 10:52:38 +02:00
Robert Winkler
f1614fe81a Fixed levelOffset calculation when using paths grouped by TAGS 2016-04-19 10:38:54 +02:00
Robert Winkler
d5c9116dc7 Merge remote-tracking branch 'origin/master'
Conflicts:
	src/main/java/io/github/swagger2markup/spi/PathsDocumentExtension.java
2016-04-19 10:36:57 +02:00
Robert Winkler
5aaff59f71 Fixed levelOffset calculation when using paths grouped by TAGS 2016-04-19 10:30:57 +02:00
Robert Winkler
a20ed66400 Merge pull request #131 from ozanyildiz/master
Add Turkish language support
2016-04-15 12:24:53 +02:00
Ozan Yildiz
6312c2f3e0 add Turkish language support 2016-04-15 11:35:07 +03:00
Hugo de Paix de Coeur
2e2bd7d6c5 Enable inline schemas by default. No more depth level control. 2016-04-14 17:51:47 +02:00
Hugo de Paix de Coeur
dd7de8fe08 Added new DEFINITION_{BEFORE,AFTER} positions to DefinitionsDocumentExtension 2016-04-14 16:46:53 +02:00
Hugo de Paix de Coeur
934039bcd4 Renamed SecurityDocumentExtension positions DEFINITION -> SECURITY_SCHEME for clarity
Added new SECURITY_SCHEME_{BEFORE,AFTER} positions
2016-04-14 16:38:59 +02:00
Hugo de Paix de Coeur
98efe9543d #130 : Documentation for new PathsDocumentExtension positions 2016-04-14 15:52:24 +02:00
Hugo de Paix de Coeur
b68c0031a7 fix #130 : Supports for new PathsDocumentExtension positions (descriptions, responses, parameters, security) + OPERATION_{BEFORE,AFTER}
Fixed OPERATION_BEGIN hook call location
2016-04-14 15:32:54 +02:00
Hugo de Paix de Coeur
a587899976 Extension documentation : recommend to use different contentPaths for import files extension 2016-04-14 15:32:54 +02:00
Robert Winkler
4528f2aa0e Merge remote-tracking branch 'origin/master' 2016-04-14 12:37:35 +02:00
Robert Winkler
b2e6f498be Fixed credentials 2016-04-14 12:37:23 +02:00
Hugo de Paix de Coeur
d32179009d Created separate doc for extensions
Extensions documents enhancements
reverted to coderay until AsciiDoctor 1.5.5 (supports for highlightjs-langs attribute)
2016-04-14 12:04:17 +02:00
Hugo de Paix de Coeur
c815318972 missing language 2016-04-14 12:04:17 +02:00
Robert Winkler
7cbb52094d Changed documentation source-highlighter back to coderay, because groovy listings look strange with highlight.js 2016-04-13 14:25:12 +02:00
Hugo de Paix de Coeur
7c8dfb520f Dynamic file content extension detailed documentation 2016-04-13 14:05:01 +02:00
Hugo de Paix de Coeur
6395adddb6 Dynamic file content extension detailed documentation 2016-04-13 13:43:20 +02:00
Hugo de Paix de Coeur
01a63f895c always add space at the beginning and at the end of array/map < target type > for symmetry 2016-04-12 20:07:59 +02:00
Hugo de Paix de Coeur
5d2ba5b21e refactored PropertyUtils.getDefaultValue & ParameterUtils.getDefaultValue to return Objects.
default values are now displayed with literalText + Json.pretty
swaggerMarkupDescription now returns null when there's no description.
2016-04-12 19:16:03 +02:00
Hugo de Paix de Coeur
6e4c0c1498 refactored responses header display
fixed tests after column width update
fixed defaultString in swaggerMarkupDescription
2016-04-12 18:50:25 +02:00
Hugo de Paix de Coeur
dce6b4183a update column width using values sum = 20 for better granularity on col width 2016-04-12 18:50:25 +02:00
Hugo de Paix de Coeur
1bf36592ef advanced_usage documentation (cosmetic) 2016-04-12 18:50:25 +02:00
Robert Winkler
24d9218d14 Show stacktrace of TravisCI publishGhPages task 2016-04-12 16:07:09 +02:00
Robert Winkler
9ee6c96a3a Merge remote-tracking branch 'origin/master' 2016-04-12 15:57:10 +02:00
Robert Winkler
507307308d Fixed index.adoc 2016-04-12 15:57:03 +02:00
Hugo de Paix de Coeur
14d4268cc3 advanced_usage documentation (fixed index) 2016-04-12 15:56:24 +02:00
Hugo de Paix de Coeur
aade4453e1 advanced_usage documentation (fixed tests) 2016-04-12 15:51:19 +02:00
Robert Winkler
232a635c06 Merge remote-tracking branch 'origin/master' 2016-04-12 15:46:36 +02:00
Robert Winkler
545cf13584 Publish documentation on each commit 2016-04-12 15:46:26 +02:00
Hugo de Paix de Coeur
b7ef781fda advanced_usage documentation (cosmetic) 2016-04-12 15:06:35 +02:00
Hugo de Paix de Coeur
3f18a446af advanced_usage documentation (with examples) 2016-04-12 14:55:59 +02:00
Hugo de Paix de Coeur
391bb20de2 advanced_usage documentation (with all files) 2016-04-12 14:28:18 +02:00
Hugo de Paix de Coeur
aafac7821c advanced_usage documentation 2016-04-12 14:27:25 +02:00
Hugo de Paix de Coeur
103aef6cd6 issue template fix 2016-04-08 17:44:21 +02:00
Hugo de Paix de Coeur
6282459905 fixed #124 : fix inter-document cross-references in security schemes
Added inter-document cross-references tests in AsciiDoc and Markdown format
2016-04-08 17:39:52 +02:00
Robert Winkler
293132e6a4 Created an issue template 2016-04-08 16:59:18 +02:00
Hugo de Paix de Coeur
0e4b193d70 Use JSON schema title value to name inline schema intermediary objects, or, if not provided, generate a virtual name based on definition/property/parameter/response name
fixed column widths
fixed bug with <> and cross-references
added type to BasicType to clearly distinct type and name
refactored RefType to use referenced type name/uniqueName instead of a copy of them.
2016-04-08 15:44:38 +02:00
Robert Winkler
277e452a73 Changed gitter to slack integration 2016-04-08 14:40:13 +02:00
Hugo de Paix de Coeur
80e96933b0 missing expected files for inline_schema_flat_body test 2016-04-06 22:08:41 +02:00
Hugo de Paix de Coeur
1ab4f8ff6c fixed javadoc 2016-04-06 22:02:52 +02:00
Hugo de Paix de Coeur
9a67581ad9 fixed javadoc 2016-04-06 22:02:01 +02:00
Hugo de Paix de Coeur
9ef34dd853 fixed inlineSchema depth constant 1 -> configured depth level in definitions
fixed tests
2016-04-06 22:00:10 +02:00
Hugo de Paix de Coeur
b37c173e07 fixed inlineSchemas in collections (array and map, recursive collections, and object/collection mix) in parameters, responses and definitions
fixed missing support for withInlineSchemaDepth when withFlatBody enabled
fixed inline definitions unicity with depth > 1
2016-04-06 21:47:18 +02:00
Hugo de Paix de Coeur
105ac545b3 Moved Example column to description content 2016-04-06 19:16:17 +02:00
Hugo de Paix de Coeur
ae3f9aa353 Removed Required column and render required flag in NAME_COLUMN.
Removed header style on columns in tables.
Support for read-only property flags.
2016-04-06 18:15:09 +02:00
Hugo de Paix de Coeur
3e9fca8a0d SecurityDocument : WorkAround AsciiDoctor HTML conversion bug with + on the last paragraph line when using hardbreaks
SecurityDocument : Use italic for informations keys.
2016-04-06 14:27:04 +02:00
Hugo de Paix de Coeur
1a45054b5d fixed missing DOCUMENT_AFTER extension point call
fixed SecurityDocument DEFINITION_BEGIN->DEFINITION_END extension point call
2016-04-06 14:09:23 +02:00
Robert Winkler
be56290257 Updated documentation 2016-04-06 09:32:03 +02:00
Robert Winkler
64195e095b Updated documentation 2016-04-06 09:03:59 +02:00
Robert Winkler
5a33b3473e Merge remote-tracking branch 'origin/master' 2016-04-06 08:12:35 +02:00
Robert Winkler
df23dc09e8 Updated documentation 2016-04-06 08:12:07 +02:00
Robert Winkler
2a3ac1e6d0 Updated readme 2016-04-05 19:08:36 +02:00
Hugo de Paix de Coeur
bad8cde186 missing placeholder quoting 2016-04-05 16:08:07 +02:00
Hugo de Paix de Coeur
d9adcc2016 log normalized operation id to the console for external content, etc ... 2016-04-05 16:08:07 +02:00
Hugo de Paix de Coeur
7b59a069ef escape consume/produce in overview too (#28).
WorkAround AsciiDoctor HTML conversion bug with + on the last paragraph line.
Use italic for overview informations keys.
fixed termsOfService layout.
2016-04-05 16:08:07 +02:00
Robert Winkler
310a2e47b6 Updated documentation 2016-04-05 15:50:52 +02:00
Robert Winkler
954e302467 Updated documentation 2016-04-05 15:46:34 +02:00
Robert Winkler
abb77b7c5f Updated documentation 2016-04-05 15:36:13 +02:00
Robert Winkler
aaac78f985 Merge remote-tracking branch 'origin/master' 2016-04-05 15:05:53 +02:00
Robert Winkler
e959c9ed59 Updated documentation 2016-04-05 15:05:45 +02:00
Hugo de Paix de Coeur
1965110df9 typos 2016-04-05 15:04:39 +02:00
Hugo de Paix de Coeur
1300249555 cosmetic 2016-04-05 15:02:11 +02:00
Hugo de Paix de Coeur
05a4ee230c Remove hand-written definition/operation descriptions from code, to prepare extension (#108) 2016-04-05 14:53:41 +02:00
Robert Winkler
78411de398 Merge remote-tracking branch 'origin/master' 2016-04-05 14:52:49 +02:00
Robert Winkler
e697815c0c Updated documentation 2016-04-05 14:52:43 +02:00
Hugo de Paix de Coeur
fbd22779ee revert buildOperationTitle block from SIDEBAR to LITERAL style
fixed #28 : */* (consume/produce) not escaped
fixed tests
2016-04-05 14:25:01 +02:00
Robert Winkler
b13c57ea35 Merge remote-tracking branch 'origin/master' 2016-04-05 13:40:36 +02:00
Robert Winkler
0b38f2a91c Updated documentation 2016-04-05 13:40:30 +02:00
Robert Winkler
db36397e81 Fixed getRequiredURI and getURI in Swagger2MarkupProperties 2016-04-05 13:40:21 +02:00
Hugo de Paix de Coeur
066fd597da fix bad refactoring in URIUtils 2016-04-05 13:38:06 +02:00
Hugo de Paix de Coeur
e979d2b45b adapt to latest MDB modifications 2016-04-05 13:33:39 +02:00
Robert Winkler
4fa9f0d645 Updated documentation 2016-04-05 13:17:12 +02:00
Robert Winkler
fecf6c6161 Added a check to the static factory method fromPath to check if the input file does exist. 2016-04-05 11:12:46 +02:00
Robert Winkler
7eecba583d Added a static factory method in URIUtils to create a URI from a String representation of a URI or a Path. 2016-04-05 11:06:37 +02:00
Robert Winkler
9c6111da3e Removed checks to the static factory method fromPath to check if the input file does exist and is readable.
They are not working as expected.
2016-04-05 10:46:34 +02:00
Robert Winkler
f10882d14d Fixed checks to the static factory method fromPath to check if the input file does exist and is readable. 2016-04-05 10:25:39 +02:00
Robert Winkler
0ac9e13948 Fixed checks to the static factory method fromPath to check if the input file does exist and is readable. 2016-04-05 10:20:04 +02:00
Robert Winkler
fb3ef974a3 Added checks to the static factory method fromPath to check if the input file does exist and is readable. 2016-04-05 09:19:00 +02:00
Robert Winkler
65522e4569 Fixed static factory method fromUri so that it also excepts URIs without a scheme. 2016-04-05 08:30:59 +02:00
Hugo de Paix de Coeur
ae8961d43c fixed #44 : added a non-regression test 2016-04-04 20:14:52 +02:00
Robert Winkler
c131a8cad8 Merge pull request #123 from Swagger2Markup/features/polymorphism
fixed #22 : Add discriminator field to the output
2016-04-04 20:04:20 +02:00
Hugo de Paix de Coeur
7ad8ef8d18 fixed #22 : Add discriminator field to the output 2016-04-04 19:58:29 +02:00
Hugo de Paix de Coeur
539520903f enhanced maps test using integer with format int32 2016-04-04 17:55:53 +02:00
Hugo de Paix de Coeur
566300a598 fixed missing line breaks in overview document 2016-04-04 17:55:53 +02:00
Robert Winkler
b64bbee4b4 Merge pull request #122 from Swagger2Markup/features/enums
fixes #111 : Enum definition type values not rendered
2016-04-04 17:49:32 +02:00
Robert Winkler
8c005466c6 Updated documentation 2016-04-04 16:37:53 +02:00
Robert Winkler
d222e01466 Updated javadoc of toPath method in Swagger2MarkupConverter. 2016-04-04 16:26:17 +02:00
Hugo de Paix de Coeur
d692f616ba getTypeProperties documentation 2016-04-04 16:25:00 +02:00
Hugo de Paix de Coeur
656ebde58c fixes #111 : Enum definition type values not rendered
getAllProperties logic as been factored in ModelUtils
2016-04-04 16:16:41 +02:00
Robert Winkler
4973f9674a Added Gradle Plugin documentation 2016-04-04 13:55:52 +02:00
Robert Winkler
9fe3bf9ec0 Merge branch 'master' of https://github.com/Swagger2Markup/swagger2markup 2016-04-04 13:36:49 +02:00
Robert Winkler
074794830f Merge pull request #121 from Swagger2Markup/features/maps
fixes #113 : Support for maps (additionalProperties) in parameters, defs and responses
2016-04-04 13:36:17 +02:00
Hugo de Paix de Coeur
1f4fd9f115 cosmetic 2016-04-04 13:35:21 +02:00
Hugo de Paix de Coeur
82ac10c7a5 fixes #113 : Support for maps (additionalProperties) in parameters, definitions and responses 2016-04-04 13:31:56 +02:00
Robert Winkler
505b9047ba Updated javadoc of toPath 2016-04-04 13:04:05 +02:00
Robert Winkler
735123749e Added Gradle Plugin documentation 2016-04-04 12:18:22 +02:00
Robert Winkler
df3c8f51d5 Merge remote-tracking branch 'origin/master' 2016-04-04 12:15:16 +02:00
Robert Winkler
6de159fa7d Moved Swagger2MarkupProperties into another package. 2016-04-04 12:15:08 +02:00
Hugo de Paix de Coeur
119b190585 fixed content extensions positions documentation 2016-04-04 11:31:38 +02:00
Robert Winkler
14c0be59dd Updated documentation 2016-04-04 11:18:16 +02:00
Robert Winkler
fd2ae92663 Updated documentation 2016-04-04 11:16:29 +02:00
Robert Winkler
a57b16504f Added a check that the input file must not be a hidden file. 2016-04-04 10:49:01 +02:00
Robert Winkler
ee36c1b9f3 Added a toPath methods to the Swagger2MarkupConverter which converts the Swagger specification either into a folder or a file. 2016-04-04 10:42:25 +02:00
Robert Winkler
928ec8b325 Added a static factory method "fromURI" method to the Swagger2MarkupConverter 2016-04-04 10:31:43 +02:00
Robert Winkler
3d720f2c81 Merge branch 'master' of https://github.com/Swagger2Markup/swagger2markup 2016-04-04 08:11:03 +02:00
Robert Winkler
040c60a9ba Merged swagger-parser 1.0.18 2016-04-04 08:10:59 +02:00
Robert Winkler
2e874957fb Updated documentation 2016-04-02 20:16:40 +02:00
Robert Winkler
3ed94986ed Updated documentation 2016-04-02 20:09:21 +02:00
Robert Winkler
32f7561e26 Updated documentation 2016-04-02 20:02:07 +02:00
Robert Winkler
dbaaa195b5 Updated documentation 2016-04-02 19:56:11 +02:00
Robert Winkler
7f01e9beaa Updated documentation 2016-04-02 17:44:07 +02:00
Robert Winkler
2e95cf6b25 Updated documentation 2016-04-02 17:24:11 +02:00
Robert Winkler
23314507db Merge pull request #120 from Swagger2Markup/features/sparser-1.0.18
Features/sparser 1.0.18
2016-04-02 13:18:18 +02:00
Hugo de Paix de Coeur
cfbff5402c Reintroduce DOCUMENT_AFTER position for content extensions 2016-04-01 16:22:03 +02:00
Hugo de Paix de Coeur
6c6c625273 use released io.swagger:swagger-compat-spec-parser:1.0.18 2016-04-01 15:16:57 +02:00
Robert Winkler
a66560a255 Updated documentation 2016-04-01 14:59:27 +02:00
Robert Winkler
5ff5fc8f0f Updated documentation 2016-04-01 14:55:53 +02:00
Robert Winkler
f001b5bb7c Updated documentation 2016-04-01 14:53:56 +02:00
Hugo de Paix de Coeur
403b8fcfc7 Merge branch 'master' into features/sparser-1.0.18
# Conflicts:
#	build.gradle
2016-04-01 14:11:34 +02:00
Robert Winkler
456625ae4b Simplified loading of the default properties file. 2016-04-01 13:11:09 +02:00
Robert Winkler
5dd9163610 Merge remote-tracking branch 'origin/master' 2016-04-01 10:38:35 +02:00
Robert Winkler
3953b3328a Added commons-collections4:4.1 2016-04-01 10:38:28 +02:00
Robert Winkler
124be6c37a Added Codacy badge 2016-04-01 10:19:52 +02:00
Robert Winkler
6fc474ac09 Fixed JavaDoc 2016-04-01 10:00:57 +02:00
Robert Winkler
49ccad694e Fixed JavaDoc 2016-03-31 16:30:46 +02:00
Robert Winkler
370fa5eb8d Merge remote-tracking branch 'origin/master' 2016-03-31 16:25:12 +02:00
Robert Winkler
df61f140ca Upgrade to JDK8 2016-03-31 16:25:03 +02:00
Robert Winkler
b80b16d03f Updated readme 2016-03-24 20:08:24 +01:00
Robert Winkler
97c75c306f Updated readme 2016-03-24 20:04:21 +01:00
Robert Winkler
30258c7e75 Updated documentation. 2016-03-23 16:31:33 +01:00
Robert Winkler
e66feb5a27 Updated documentation. 2016-03-23 14:46:16 +01:00
Robert Winkler
972f2c2d6d Updated documentation. 2016-03-23 14:43:05 +01:00
Hugo de Paix de Coeur
fcf46c1588 small doc changes 2016-03-22 17:24:43 +01:00
Robert Winkler
cd38ed01a4 Updated documentation. 2016-03-22 16:38:20 +01:00
Robert Winkler
5f965e6378 Updated documentation. 2016-03-22 16:33:20 +01:00
Robert Winkler
d20bce81f0 Merge remote-tracking branch 'origin/master' 2016-03-21 16:44:52 +01:00
Robert Winkler
d9e2397f48 Updated documentation. 2016-03-21 16:43:42 +01:00
Robert Winkler
6fe35c34be Updated readme 2016-03-19 15:22:01 +01:00
Hugo de Paix de Coeur
05924c5813 Merge branch 'master' into features/sparser-1.0.18
# Conflicts:
#	build.gradle
2016-03-18 15:48:43 +01:00
Robert Winkler
b931d7f3af Fixes #116 Section titles of generated HTTP request/response have the same level 2016-03-18 15:39:03 +01:00
Robert Winkler
5b970eb2c8 Merge remote-tracking branch 'origin/master' 2016-03-18 15:06:24 +01:00
Robert Winkler
52b5bf2361 Renamed operationsGroupedBy to pathsGroupedBy to be backward compatible. 2016-03-18 15:06:17 +01:00
Hugo de Paix de Coeur
8eee21baf0 renamed intoFolder -> toFolder, asString -> toString for consistency 2016-03-18 13:20:36 +01:00
Robert Winkler
e99656704f Merge pull request #114 from ahus1/translation_to_german
translation of labels to German
2016-03-18 13:05:37 +01:00
Alexander Schwartz
235e5b7ddf translation of labels to German 2016-03-18 12:50:27 +01:00
Robert Winkler
69e7992f3e Updated markup-document-builder to 1.0.0-SNAPSHOT 2016-03-18 10:39:14 +01:00
Robert Winkler
29bfddc8d2 DiffUtils assertThatAllFilesAreEqual iterates over the expectedDirectory instead of the actualDirectory now. This allows to check only 2 files instead of always all 4 S2M documents. 2016-03-18 08:22:59 +01:00
Robert Winkler
3fc8a897a1 Removed mavenLocal() in build.gradle. 2016-03-18 08:12:41 +01:00
Hugo de Paix de Coeur
451e377cac inverted actual/expected in DiffUtils.assertThatAllFilesAreEqual for consistency with tests habits 2016-03-17 17:15:44 +01:00
Hugo de Paix de Coeur
6379b3ccf1 fixed #107 : Possibility to write the output into just one file instead of a folder 2016-03-17 17:10:53 +01:00
Hugo de Paix de Coeur
456f27c85b Merge branch 'master' into features/sparser-1.0.18 2016-03-17 15:38:06 +01:00
Hugo de Paix de Coeur
c739649f20 fixed typo bug in withSwaggerMarkupLanguage which was setting the bad markupLanguage variable 2016-03-17 15:37:37 +01:00
Hugo de Paix de Coeur
3dceb21bd5 Merge branch 'master' into features/sparser-1.0.18 2016-03-16 19:16:08 +01:00
Hugo de Paix de Coeur
23331930cc introduced .withSwaggerMarkupLanguage configuration to automatically convert Swagger file description into the target S2M language 2016-03-16 19:13:57 +01:00
Hugo de Paix de Coeur
da48f49a25 Merge branch 'master' into features/sparser-1.0.18 2016-03-16 16:32:36 +01:00
Hugo de Paix de Coeur
3775f26458 fixed refactoring bug in PathsDocumentBuilder::DefinitionDocumentResolverFromOperation 2016-03-16 16:30:20 +01:00
Robert Winkler
365d3278ff Added getRequiredMarkupLanguage method to Swagger2MarkupProperties 2016-03-16 16:09:01 +01:00
Robert Winkler
7cc9742530 Merge remote-tracking branch 'origin/master' 2016-03-16 15:51:01 +01:00
Robert Winkler
0648a9cbea Added two getPath methods to Swagger2MarkupProperties. 2016-03-16 15:50:48 +01:00
Hugo de Paix de Coeur
7766276abc Merge branch 'master' into features/sparser-1.0.18
# Conflicts:
#	build.gradle
2016-03-16 15:50:41 +01:00
Hugo de Paix de Coeur
19bc2dd0e2 moved generated test results to build/test for consistency with MDB 2016-03-16 15:37:37 +01:00
Robert Winkler
6126260aae Added a URIUtils class with a new convertUriWithoutSchemeToFileScheme method. 2016-03-16 15:15:30 +01:00
Robert Winkler
cdd0bc52e2 Added a getRequiredURI and updated the getURI method in Swagger2MarkupProperties 2016-03-16 14:07:24 +01:00
Hugo de Paix de Coeur
ccf3ee8e7d use new MDB .withHeaderColumn 2016-03-16 13:51:55 +01:00
Robert Winkler
54147bbddb Merge remote-tracking branch 'origin/master' 2016-03-16 12:42:33 +01:00
Robert Winkler
914fa2da0f Refactored Swagger2MarkupConfigBuilder to use Apache Commons configuration. 2016-03-16 12:42:27 +01:00
Hugo de Paix de Coeur
d41b14bbff added anchors for operations and definitions in !separated mode too
switched paths anchors to getId() instead of getTitle()
2016-03-16 11:39:37 +01:00
Robert Winkler
354d2167fb Added enum examples to swagger_petstore.yaml. 2016-03-16 08:52:09 +01:00
Hugo de Paix de Coeur
9eb7c671cd Merge branch 'master' into features/sparser-1.0.18 2016-03-15 18:14:48 +01:00
Hugo de Paix de Coeur
aee7708cd1 Use swagger-compat-spec-parser:1.0.18-SNAPSHOT 2016-03-15 18:07:20 +01:00
Robert Winkler
e3f946ecf8 Added missing javadoc to Swagger2MarkupConfig. 2016-03-15 15:51:08 +01:00
Robert Winkler
c25b6be1f3 Moved String constants PROPERTIES_PREFIX and EXTENSION_PREFIX into Swagger2MarkupConfig interfaces 2016-03-15 15:49:27 +01:00
Hugo de Paix de Coeur
eff69079a6 added Swagger2MarkupConfig, Swagger2MarkupExtensionRegistry documentation 2016-03-15 14:44:42 +01:00
Robert Winkler
8d8d4cd5d0 Added a method getExtensionsProperties to Swagger2MarkupConfig and withExtensionProperties to Swagger2MarkupConfigBuilder so that a user is able to configure its Swagger2Markup extension. 2016-03-15 13:42:36 +01:00
Hugo de Paix de Coeur
4bce1234af fixes package paths after massive package refactoring (2/2) 2016-03-15 12:12:44 +01:00
Hugo de Paix de Coeur
d892f0b39d fixes package paths after massive package refactoring 2016-03-15 11:23:52 +01:00
Robert Winkler
831e949d91 Uncommented tests which are not necessary anymore. 2016-03-15 11:04:53 +01:00
Robert Winkler
d48b9c217b The S2MConfig and S2MRegistry are interfaces now so that other users can develop their own implementations and don't have to use our default implementations. 2016-03-15 09:59:32 +01:00
Robert Winkler
124a66aaa9 Merge branch 'master' of https://github.com/Swagger2Markup/swagger2markup 2016-03-15 08:43:31 +01:00
Robert Winkler
08eb6841fc Refactor extension SPI to use the ServiceLoader by default 2016-03-15 08:43:26 +01:00
Hugo de Paix de Coeur
e74ac9fda5 fixes copy code to support last mdb commits 2016-03-14 19:28:07 +01:00
Robert Winkler
d4bbcc3acc Allow to use http proxy settings in unit tests. 2016-03-14 15:43:40 +01:00
Robert Winkler
9655e113c0 Fixed order of examples and security scheme definitions. 2016-03-14 15:43:20 +01:00
Robert Winkler
54c7682f00 Fixed compile issue in Swagger2MarkupConverter 2016-03-14 15:14:56 +01:00
Robert Winkler
7c8efa1060 Fixed failing Swagger2MarkupExtensionRegistryTest after moving the extensions into another repo. 2016-03-14 15:12:14 +01:00
Robert Winkler
0caf2d7a43 Merge remote-tracking branch 'origin/master' 2016-03-14 15:03:31 +01:00
Robert Winkler
533590656f Fixes #110 Move Extensions into swagger2markup-extensions repo 2016-03-14 15:03:19 +01:00
Robert Winkler
fe0fa8a9ce Moved classes from 'io.github.robwin.swagger2markup' to 'io.github.swagger2markup' 2016-03-14 15:01:32 +01:00
Robert Winkler
a85b695c80 Changed artifact group from group = 'io.github.robwin' to 'io.github.swagger2markup'.
Refactored gradle scripts.
2016-03-14 15:00:17 +01:00
Hugo de Paix de Coeur
251a6b7e73 fixes merge from master (missing some convertExample) 2016-03-14 12:10:31 +01:00
Hugo de Paix de Coeur
08b0d085db Merge branch 'master' into features/sparser-1.0.18
# Conflicts:
#	build.gradle
#	src/main/java/io/github/robwin/swagger2markup/Swagger2MarkupConfig.java
2016-03-14 11:43:04 +01:00
Hugo de Paix de Coeur
0b95f35a61 Removes formatting from RU localization 2016-03-14 11:28:23 +01:00
Robert Winkler
4073b7627d Fixes #60: Add support of Response Headers
The description of response headers was not rendered correctly.
2016-03-11 08:37:32 +01:00
Robert Winkler
2c2b599528 Fixed expected result files. 2016-03-10 16:14:31 +01:00
Robert Winkler
eb86d6f1d0 Moved buildDescriptionParagraph method ino MarkupDocumentBuilder so that it can be reused by all other builders. 2016-03-10 15:39:07 +01:00
Robert Winkler
2d74e441dc Replaced colon separator by a static final string. 2016-03-10 15:38:11 +01:00
Robert Winkler
8145dea0d5 Added gh-pages gradle-git plugin. 2016-03-10 15:37:38 +01:00
Robert Winkler
a4a217a223 Fixed security scheme title anchor. 2016-03-10 15:37:03 +01:00
Robert Winkler
cd023a99b5 Updated introduction. 2016-03-09 16:44:49 +01:00
Robert Winkler
a339e78135 Added initial AsciiDoc documentation for release v1.0.0. 2016-03-09 16:41:30 +01:00
Robert Winkler
1425414b4a Moved AsciiDoc and Markdown documents which are required by the test into "src/test/resources/docs". 2016-03-09 16:16:52 +01:00
Robert Winkler
a8e189408a Merge branch 'develop' of https://github.com/Swagger2Markup/swagger2markup into develop 2016-03-09 15:19:58 +01:00
Robert Winkler
fbb535d241 Removed new line from swagger_inlineSchema.yaml 2016-03-09 15:18:26 +01:00
Robert Winkler
7d6fc09c24 Fixed expected test results after adding support for HTTP headers in Responses 2016-03-09 13:58:06 +01:00
Robert Winkler
00f62124af Added missing JavaDoc to DynamicSecurityDocumentExtension
Added missing Enums in DynamicSecurityDocumentExtension::apply
2016-03-09 13:35:12 +01:00
Robert Winkler
138be996db Renamed MarkupDocumentBuilder::typeProperties to MarkupDocumentBuilder::buildPropertiesTable
Renamed DefinitionsDocumentBuilder::definition to DefinitionsDocumentBuilder::buildDefinition
Added a description paragraph to SecurityDocumentBuilder::buildSecuritySchemeDefinitionsSection
2016-03-09 13:34:26 +01:00
Robert Winkler
722b2b24b7 Added the name of the definition and the SecuritySchemeDefinition to the SecurityDocumentExtension.Context. 2016-03-09 13:04:53 +01:00
Robert Winkler
d90d68332f Updated version of Apache commons collection
Remove library dependencies which are already included in markup-document-builder
2016-03-09 12:39:04 +01:00
Robert Winkler
0470d984cc Updated version 2016-03-08 20:14:52 +01:00
Robert Winkler
c001452abf Renamed and refactored some methods in the document builder.
Fixed Javadoc.
2016-03-08 12:34:53 +01:00
Robert Winkler
b25378463c Renamed Position enums. 2016-03-08 12:32:25 +01:00
Robert Winkler
63d3a95529 Added global parameter and response to swagger_petstore to test #102 and #103 2016-03-08 11:10:14 +01:00
Robert Winkler
1c1eb106d6 Renamed and refactored some methods in the document builder. 2016-03-08 09:54:30 +01:00
Robert Winkler
916d2515b0 Renamed resource folder which contains the expected test results. 2016-03-08 09:53:08 +01:00
Robert Winkler
caff7db0d4 Merge branch 'master' of https://github.com/Swagger2Markup/swagger2markup into develop
Conflicts:
	src/main/resources/io/github/robwin/swagger2markup/lang/labels_ru.properties
2016-03-07 16:21:50 +01:00
Robert Winkler
85006b2c15 Merge pull request #104 from MeteorBoom/master
Russian propirties update
2016-03-07 16:11:51 +01:00
Maksim Myshkin
727c6c6467 Russian propirties update 2016-03-07 20:05:38 +05:00
Robert Winkler
12fc80c8b0 Fixes #101: Rename extensions. Content should be renamed to Document 2016-03-07 16:03:13 +01:00
Robert Winkler
97ae3df30d Refactored visibility of classes. 2016-03-07 15:58:43 +01:00
Robert Winkler
3189043b7f Refactored package structure into an API (root), a SPI (service provider interface) and internal classes which should not be used by a user directly. 2016-03-07 15:28:46 +01:00
Robert Winkler
9f01adfb25 Removed withLineSeparator from unit tests, because it fails on TravisCI. 2016-03-07 12:52:33 +01:00
Robert Winkler
5155e6510f Renamed MarkupDocument to MarkupDocumentBuilder which builds an MarkupDocument now. 2016-03-07 12:51:32 +01:00
Robert Winkler
37d99eb86f Renamed AbstractExtension::onUpdateGlobalContext to AbstractExtension::init 2016-03-07 12:50:40 +01:00
Robert Winkler
014e9354ce Merge pull request #99 from Swagger2Markup/features/schema-ext
moved definitions Schema implementation to SchemaExtension
2016-03-07 11:26:28 +01:00
Robert Winkler
c8ecab6d78 Fixed broken GeneralConverterTest 2016-03-07 11:20:18 +01:00
Robert Winkler
2e7e10aaae Merge branch 'develop' into features/schema-ext
Conflicts:
	src/test/java/io/github/robwin/swagger2markup/Swagger2MarkupConverterTest.java
2016-03-07 11:16:00 +01:00
Robert Winkler
9f197074ef The line separator which should be used can be configured now. 2016-03-07 11:10:28 +01:00
Robert Winkler
5b054761cf Added expected AsciiDoc and Markdown files. 2016-03-07 11:08:51 +01:00
Hugo de Paix de Coeur
be3ae6bd0d Merge branch 'develop' into features/schema-ext
# Conflicts:
#	src/main/java/io/github/robwin/swagger2markup/config/Swagger2MarkupConfig.java
2016-03-04 17:42:01 +01:00
Hugo de Paix de Coeur
71980aafeb moved definitions Schema implementation to SchemaExtension 2016-03-04 17:38:19 +01:00
Robert Winkler
d1c20ed325 Merge pull request #98 from atomfrede/master
add wescale as using company
2016-03-04 17:35:38 +01:00
Frederik Hahne
16f559cd70 add wescale as using company 2016-03-04 17:24:07 +01:00
Robert Winkler
d0dc6188cd Removed io.spring.gradle:dependency-management-plugin 2016-03-04 14:54:25 +01:00
Robert Winkler
e79f6c49a4 Moved testSwagger2MarkupConfigDefaultPathsWithoutFile from MarkdownConvertTest into GeneralConverterTest. 2016-03-04 13:32:37 +01:00
Robert Winkler
4ec11f8359 Separated AsciiDocConverterTest into three different files. 2016-03-04 13:30:03 +01:00
Robert Winkler
52c1780f79 AS_IS ordering of path operations does not work yet, because of https://github.com/swagger-api/swagger-core/issues/1696.
New default value is NATURAL.
2016-03-04 13:20:56 +01:00
Robert Winkler
c6becb9995 Merge remote-tracking branch 'origin/develop' into develop 2016-03-04 12:15:10 +01:00
Robert Winkler
194efab1f6 Added a DiffUtils class which can be used to assert that the content of the generated files are not different to the content of the expected files. 2016-03-04 12:14:37 +01:00
Hugo de Paix de Coeur
34af7a4899 Disabled inter-document cross-references when using withSeparatedOperations() without withInterDocumentCrossReferences(), for consistency with definitions cross-references. 2016-03-04 11:50:45 +01:00
Hugo de Paix de Coeur
2b6c699828 fixes configuration validators and doc 2016-03-04 11:40:39 +01:00
Robert Winkler
e376b972fe Merge pull request #97 from Swagger2Markup/master
Updated readme
2016-03-04 08:28:32 +01:00
Robert Winkler
445a04b9d6 Updated readme 2016-03-04 08:25:13 +01:00
Hugo de Paix de Coeur
4283b2489d Merge branch 'develop' into features/sparser-1.0.18 2016-03-03 18:05:06 +01:00
Hugo de Paix de Coeur
c6e21b9ed1 fixes configuration validators and doc 2016-03-03 18:04:15 +01:00
Hugo de Paix de Coeur
c61a94495f Merge branch 'develop' into features/sparser-1.0.18
# Conflicts:
#	src/main/java/io/github/robwin/swagger2markup/utils/ExamplesUtil.java
2016-03-03 17:49:53 +01:00
Robert Winkler
99049d156a Updated readme 2016-03-03 16:33:07 +01:00
Hugo de Paix de Coeur
f8d331fc8b fixes property examples pretty-printing when no examples provided 2016-03-03 15:42:25 +01:00
Hugo de Paix de Coeur
667a883fb0 labels_fr fix for headers_column 2016-03-03 15:26:40 +01:00
Robert Winkler
2bd1719637 Merge remote-tracking branch 'origin/develop' into develop 2016-03-03 15:22:06 +01:00
Robert Winkler
d9d62dec6b Removed testOldSwaggerSpec2AsciiDocConversion unit test. 2016-03-03 15:21:46 +01:00
Hugo de Paix de Coeur
f3fdd45019 Extend to basic properties/parameters types : Auto-generated examples are disabled by default. Swagger examples are always rendered. 2016-03-03 15:11:00 +01:00
Hugo de Paix de Coeur
ded1cd6b06 Cleanup and fixes examples pretty-printing 2016-03-03 15:11:00 +01:00
Robert Winkler
854dcf48b2 Added headers property to all language files. 2016-03-03 14:26:55 +01:00
Robert Winkler
0916fa38e2 Merge remote-tracking branch 'origin/develop' into develop 2016-03-03 14:14:12 +01:00
Robert Winkler
c590f5102c Added an Assertj DiffAssertions class which can be used to compare the generated AsciiDoc/Markdown files with files which contain the expected conten.
The DiffAssert generates a HTML report, if the files differ.
2016-03-03 14:14:02 +01:00
Robert Winkler
9bda5b7941 Removed unused, duplicated method normalizeName. 2016-03-03 14:12:19 +01:00
Robert Winkler
ebba92368a Updated asciidoctor plugins.
Added a diff library to compare the content of files.
2016-03-03 14:10:37 +01:00
Hugo de Paix de Coeur
3e5df92223 Merge branch 'develop' into features/sparser-1.0.18
# Conflicts:
#	src/main/java/io/github/robwin/swagger2markup/utils/ExamplesUtil.java
2016-03-03 14:04:43 +01:00
Hugo de Paix de Coeur
2d17071c8c Updated copyright headers 2016-03-03 11:58:50 +01:00
Robert Winkler
38d4bff7f4 Merge pull request #96 from Swagger2Markup/features/withGeneratedExamples
Auto-generated examples are disabled by default
2016-03-02 19:27:57 +01:00
Hugo de Paix de Coeur
fc5434cb3d Auto-generated examples are disabled by default. Swagger examples are always rendered. 2016-03-02 19:13:28 +01:00
Hugo de Paix de Coeur
3c0e545661 fixed ComposedModel definitions model bug when used with examples 2016-03-02 19:07:00 +01:00
Hugo de Paix de Coeur
c0f758ba9b Added some missing validation 2016-03-02 18:12:24 +01:00
Hugo de Paix de Coeur
e96dd94ee9 Support Swagger Parser 1.0.18 interfaces changes 2016-03-02 11:57:28 +01:00
Robert Winkler
8a913d075d Refactored the examplesSection method in PathsDocument to remove duplicated code. 2016-03-02 11:26:31 +01:00
Robert Winkler
bbaf3a05b3 Added a swagger_petstore.yaml and swagger_security.yaml and removed the outdated swagger.json 2016-03-02 11:25:50 +01:00
Robert Winkler
61c4f8861f Changed Asciidoctor toclevel from 2 to 3. 2016-03-02 11:24:25 +01:00
Hugo de Paix de Coeur
1e7c51a2cb Removed file prefixes from dynamic content extensions 2016-03-01 18:37:26 +01:00
Hugo de Paix de Coeur
21620917f7 Unknown security scheme localization 2016-03-01 18:05:47 +01:00
Hugo de Paix de Coeur
cc65055f3c Use OrderBy for all ordering configurations 2016-03-01 17:58:22 +01:00
Hugo de Paix de Coeur
71fab0ca94 Simplify SpringRestDocsExtension::operationFolderName, and documentation fixes 2016-03-01 16:10:06 +01:00
Hugo de Paix de Coeur
b272e812d0 Remove lower-casing in normalizeName 2016-03-01 15:56:17 +01:00
Hugo de Paix de Coeur
cb9092492f Removes formatting from localization
fixes FR locale
2016-03-01 14:44:23 +01:00
Robert Winkler
0a79020e59 Merge pull request #95 from glaforge/patch-1
Add Restlet as a user of Swagger2Markup
2016-03-01 11:02:45 +01:00
Guillaume Laforge
4e4fa960b6 Add Restlet as a user of Swagger2Markup 2016-03-01 10:12:33 +01:00
Robert Winkler
c28fddb4f6 Merge pull request #93 from Swagger2Markup/features/#91-examples-to-ext
fixes #91 : Move SpringRestDocs examples to extension
2016-03-01 08:57:11 +01:00
Hugo de Paix de Coeur
e36587f61a fix directories to lower case 2016-02-29 17:52:31 +01:00
Hugo de Paix de Coeur
40c53cf27b Merge remote-tracking branch 'origin/master' into features/#91-examples-to-ext
# Conflicts:
#	src/main/java/io/github/robwin/swagger2markup/builder/document/PathsDocument.java
#	src/main/java/io/github/robwin/swagger2markup/config/Swagger2MarkupConfig.java
#	src/test/java/io/github/robwin/swagger2markup/config/Swagger2MarkupConfigTest.java
#	src/test/resources/config/config.properties
2016-02-29 17:04:22 +01:00
Hugo de Paix de Coeur
09c78a1cee fixes #91 : Move SpringRestDocs examples to extension 2016-02-29 16:25:09 +01:00
Robert Winkler
b2d9e5ab73 Moved language property files into the package io.github.robwin.swagger2markup.
Renamed boolean config properties.  They end with *Enabled now.
2016-02-29 12:57:18 +01:00
Hugo de Paix de Coeur
a630c1a161 Merge pull request #90 from Kabhal/master
Added FR locale
2016-02-26 19:49:44 +01:00
Hugo de Paix de Coeur
1771330890 Added FR locale 2016-02-26 19:48:26 +01:00
Kabhal
02fed86851 Merge pull request #89 from Kabhal/master
fixed #72 : Render examples of response and schema objects
2016-02-26 18:52:46 +01:00
Hugo de Paix de Coeur
46ae248056 Merge branch 'erik/master'
# Conflicts:
#	src/main/java/io/github/robwin/swagger2markup/builder/document/DefinitionsDocument.java
#	src/main/java/io/github/robwin/swagger2markup/builder/document/PathsDocument.java
#	src/test/java/io/github/robwin/swagger2markup/Swagger2MarkupConverterTest.java
2016-02-26 18:29:02 +01:00
Robert Winkler
5730a3be09 Merge pull request #88 from Kabhal/master
fixed #46 : Support deprecated operations
2016-02-26 17:39:41 +01:00
Hugo de Paix de Coeur
462df0032e fixed #46 : Support deprecated operations 2016-02-26 16:30:45 +01:00
Robert Winkler
d058a99874 Renamed addfileExtension to addFileExtension 2016-02-26 16:29:24 +01:00
Robert Winkler
2399cc25ca Merge remote-tracking branch 'origin/master' 2016-02-26 13:27:05 +01:00
Robert Winkler
c7fe39bf21 Refactored Swagger2MarkupConverter builder. 2016-02-26 13:26:52 +01:00
Robert Winkler
a5bf4c64bb Updated readme 2016-02-26 12:48:14 +01:00
Robert Winkler
3fd97ea471 Merge pull request #87 from Kabhal/uri
Move remaining String directories to Path
2016-02-26 12:40:03 +01:00
Hugo de Paix de Coeur
3dae4dd155 Move remaining String directories to Path 2016-02-26 12:17:10 +01:00
Robert Winkler
a510740fa3 Introduced new Swagger2MarkupConverter.from factory methods for URL and Path instead of URI to make sure that URLs and Paths have the correct format. 2016-02-26 11:05:54 +01:00
Robert Winkler
91ba9e7fd3 Moved method registerExtension into the Swagger2MarkupExtensionRegistry.Builder to make the Swagger2MarkupExtensionRegistry immutable. 2016-02-25 20:49:41 +01:00
Robert Winkler
f3056d316f Removed method withConfig(Properties config) from Swagger2MarkupConverter.Builder 2016-02-25 20:48:36 +01:00
Robert Winkler
0e9f556994 Merge pull request #86 from Kabhal/uri
Support for URI for all content resources
2016-02-25 19:29:55 +01:00
Hugo de Paix de Coeur
b9727c9275 Switched all paths to URI (except DynamicExtensions because file listing is needed -> Path) 2016-02-25 19:20:59 +01:00
Hugo de Paix de Coeur
d649fb0d87 fixes tests 2016-02-25 14:11:30 +01:00
Hugo de Paix de Coeur
1aa8221931 fixed #83 : Pluggable extension support 2016-02-25 13:49:37 +01:00
Hugo de Paix de Coeur
cbb541f1a3 fixed #80 : External folder path consistency 2016-02-25 13:00:03 +01:00
Hugo de Paix de Coeur
8b215d7425 fixed #82 : Swagger2Markup configuration builder 2016-02-25 13:00:03 +01:00
Hugo de Paix de Coeur
52ef344ba4 fixed #79 : Support for dynamic extensions from files to operations. 2016-02-25 12:59:58 +01:00
Erik Håkansson
44eff18b3e Expanded example .json 2016-02-25 06:39:18 +01:00
Erik Håkansson
a0c8d47369 Added tests and fixed some issues 2016-02-24 15:24:34 +01:00
Erik Håkansson
d19a0020fd Updated to use latest markupdocument 2016-02-24 14:11:52 +01:00
Erik Håkansson
5494ad911e merge from upstream 2016-02-24 13:51:18 +01:00
Erik Håkansson
5ead0975c1 Updates to example handling to cover more scenarios 2016-02-24 13:41:53 +01:00
Robert Winkler
34cd890cd9 Fixed CharSet in Unit test "testSwagger2AsciiDocConversionWithRussianOutputLanguage" 2016-02-22 15:30:47 +01:00
Robert Winkler
329756d664 Merge pull request #78 from Kabhal/master
fixed #77 : Generated anchors should be prefixed with a configurable prefix
2016-02-19 16:57:49 +01:00
Hugo de Paix de Coeur
8ebc4f603f Missing custom anchor for security document 2016-02-19 16:55:17 +01:00
Hugo de Paix de Coeur
07bcdf220d Shorty parameter type 2016-02-19 16:39:13 +01:00
Hugo de Paix de Coeur
2f71a011c3 Use Markup-dependent specifiers on tables (AsciiDoc : header style on name column & vertically centered columns) 2016-02-19 16:23:43 +01:00
Hugo de Paix de Coeur
e6244fc3f8 fixed #77 : Generated anchors should be prefixed with a configurable prefix 2016-02-18 19:03:12 +01:00
Hugo de Paix de Coeur
9eb713cefb Generate title anchors only for unique titles (overview, paths, definitions, <all paths>, <all operations> and <all definitions>) 2016-02-18 17:13:16 +01:00
Robert Winkler
714c0aa8c9 Merge pull request #76 from Kabhal/master
Use new markup-document-builder *AsString replacements
2016-02-18 15:35:06 +01:00
Hugo de Paix de Coeur
91a0aeec9d Use new markup-document-builder *AsString replacements 2016-02-18 14:56:50 +01:00
Robert Winkler
a28c1d4efe Merge pull request #74 from Kabhal/master
fixed #73 : Optionally isolate body display from other parameters
2016-02-17 13:22:18 +01:00
Hugo de Paix de Coeur
a6af12ae06 Added configurable ordering for properties, parameters and responses 2016-02-16 15:47:22 +01:00
Hugo de Paix de Coeur
910b2ff187 cleanups 2016-02-16 14:48:16 +01:00
Hugo de Paix de Coeur
64adbfaab6 enhanced filename normalization 2016-02-15 20:41:54 +01:00
Hugo de Paix de Coeur
d60b8d4b83 Enhanced inline schema uniqueness (no more incremental ids) 2016-02-15 18:43:40 +01:00
Hugo de Paix de Coeur
684fc221b1 fixed #73 : Optionally isolate body display from other parameters 2016-02-15 18:11:26 +01:00
Erik Håkansson
cf96642db5 Reverted custom versioning 2016-02-15 13:19:22 +01:00
Erik Håkansson
ab6628b1ab Added option for auto-generating examples 2016-02-15 13:16:15 +01:00
Robert Winkler
06beab3865 Merge pull request #69 from Kabhal/master
fixed bug with hand-written description folders fallback
2016-02-12 18:20:20 +01:00
Hugo de Paix de Coeur
bd77f4400f fixed bug with hand-written description folders fallback 2016-02-12 18:08:07 +01:00
Robert Winkler
deebb2be9a Merge pull request #68 from Kabhal/master
refactor hand-written descriptions folder
2016-02-12 17:29:05 +01:00
Hugo de Paix de Coeur
22c6cab910 refactor hand-written descriptions folder : search in stable operation.getId() first, then in back-compatible operation.getSummary()
Fix title rendering (was in debug mode)
2016-02-12 17:24:20 +01:00
Robert Winkler
ea771c80d1 Merge pull request #67 from Kabhal/master
refactored path -> operation
2016-02-12 17:22:07 +01:00
Hugo de Paix de Coeur
861b97c4ff Refactor operation sorting and group by tags logic 2016-02-12 16:34:15 +01:00
Hugo de Paix de Coeur
b1ffe7cfc2 Decomposed method and path 2016-02-12 16:34:15 +01:00
Hugo de Paix de Coeur
852ea15dc2 Renamed path -> operation anywhere we work on an operation and not a path 2016-02-12 16:34:15 +01:00
Hugo de Paix de Coeur
45768a5bba Migrate to asciidoctorj:1.5.4 (testCompile) -> better support for inter-document cross-references with paths 2016-02-12 16:34:15 +01:00
Hugo de Paix de Coeur
76b5a83511 fix withInterDocumentCrossReferences to support null prefix 2016-02-12 16:34:15 +01:00
Robert Winkler
c0d1da781f Merge pull request #66 from Kabhal/master
Option to enable/disable inter-document cross-references
2016-02-11 15:41:17 +01:00
Hugo de Paix de Coeur
1a80a7a8eb missing documentation 2016-02-11 15:33:35 +01:00
Hugo de Paix de Coeur
cd66661026 Introduce withInterDocumentCrossReferences(prefix). By default inter-document cross-references are disabled (We assume all generated files will be included in a user .adoc file)
Fixed DefinitionsDocumentResolver*
2016-02-11 14:37:17 +01:00
Hugo de Paix de Coeur
b88e4eea56 cleanup the resolvers 2016-02-11 14:37:17 +01:00
Robert Winkler
f64a0d199d Added a test case which converts a Swagger file into an AsciiDoc String. 2016-02-11 14:05:13 +01:00
Robert Winkler
5f47f49cf4 Issue #65:
When you combine multiple AsciiDoc files in a index.adoc. The anchors to the definitions don't work anymore in the paths section, because they reference a definitions.adoc: <<definitions.adoc#_pet,Pet>>
AsciiDoctor converts this reference to a HTML anchor <a href="definitions.html#_pet">Pet</a>. But AsciiDoctor only generates an index.html and no definitions.html
The DefinitionDocumentResolver must return null, if separatedDefinitionsEnabled is not true. Otherwise we are not backward compatible.
2016-02-11 10:58:19 +01:00
Robert Winkler
7a0c8d81f6 Moved the securitySchemeSection above the examplesSection in the PathsDocument. 2016-02-11 10:02:19 +01:00
Robert Winkler
427efca6f8 Added security.adoc to index.adoc 2016-02-11 09:45:24 +01:00
Robert Winkler
54546185ab Added test for separated paths builder method. 2016-02-11 09:26:43 +01:00
Robert Winkler
493f045764 Merge pull request #63 from rostskadat/master
Adding a simple section for Swagger security definitions
2016-02-10 18:15:54 +01:00
N090536
fd79e98ed7 Merge remote-tracking branch 'origin/master'
Conflicts:
	src/main/java/io/github/robwin/swagger2markup/Swagger2MarkupConverter.java
	src/test/java/io/github/robwin/swagger2markup/Swagger2MarkupConverterTest.java
2016-02-10 16:23:05 +01:00
Robert Winkler
40bf5762bb Merge pull request #64 from Kabhal/idxref
Fixed tests (no way to compare output to definitions.<ext> as the gen…
2016-02-10 14:00:33 +01:00
Hugo de Paix de Coeur
c291991236 Fixed tests (no way to compare output to definitions.<ext> as the generation logic changed) : definitions.<ext> is now just a link list to separated files 2016-02-10 13:40:18 +01:00
Robert Winkler
7cb9b97bfb Updated swagger-compat-spec-parser from 1.0.16 to 1.0.17 2016-02-10 13:39:35 +01:00
Robert Winkler
eddbd9610e Updated RELEASENOTES 2016-02-10 13:32:14 +01:00
Robert Winkler
a66ebec28f Merge pull request #62 from Kabhal/idxref
fixed #61 Refactor separated documents logic to support inter-document xrefs
2016-02-10 13:25:51 +01:00
N090536
cdad18194e Fixing UTF8 string... 2016-02-10 13:11:56 +01:00
N090536
17f69b2bbc Adapted the unit test to account for the new security document 2016-02-10 13:04:04 +01:00
N090536
84176e5e27 Fixing english labels and sync the russian labels 2016-02-10 12:48:34 +01:00
N090536
67a3b924e8 Add the SecurityDocument class 2016-02-10 12:41:30 +01:00
N090536
84c86873fb Added a section for the securityDefinitionsObject.
As per the specification:
http://swagger.io/specification/#securityDefinitionsObject
2016-02-10 12:40:40 +01:00
Hugo de Paix de Coeur
2a486a2939 fixed #61 Refactor separated documents logic to support inter-document cross-references 2016-02-10 12:29:02 +01:00
Robert Winkler
0550128e1d Merge pull request #59 from johanhammar/master
Update Gradle wrapper to 2.10 and dependency-management-plugin to latest version.
2016-02-07 12:21:27 +01:00
Johan Hammar
ff867c9ba4 Update Gradle wrapper to 2.10 2016-02-07 12:04:16 +01:00
Johan Hammar
c5fada0a62 Upgrade dependency-management-plugin to latest version 2016-02-07 11:59:06 +01:00
Robert Winkler
7316ae0ce4 Merge pull request #58 from Kabhal/separatedBody
fixed #53 : support for tags, paths and methods ordering
2016-02-05 20:44:08 +01:00
Hugo de Paix de Coeur
c8919e9844 refactored orderBy system by generalizing ordering to all resources (tags, paths, definitions, path methods).
definitionsOrderBy and OrderBy are deprecated (set definitionsOrdering to Ordering.natural() for back-compatibility)
All orderings set to Ordering.natural() by default.
Support as-is ordering for all resources by setting config options to null.
2016-02-05 19:57:38 +01:00
Hugo de Paix de Coeur
4e340466de Merge remote-tracking branch 'upstream/master' into separatedBody 2016-02-05 18:02:37 +01:00
Hugo de Paix de Coeur
2fceda6f09 fixed #53 : support for tags, paths and methods ordering 2016-02-05 16:38:06 +01:00
Robert Winkler
2aa29fde8a Merge pull request #56 from Kabhal/multipaths
fixed #51 : Support for separated operations files
2016-02-05 00:41:23 +01:00
Hugo de Paix de Coeur
a76b7c545a Localized Response inline type prefix 2016-02-05 00:15:17 +01:00
Hugo de Paix de Coeur
8178bf1380 renamed withSeparatedOperations to withSeparatedPaths along with all related resources 2016-02-05 00:10:45 +01:00
Hugo de Paix de Coeur
63ca190a32 fixed #51 : Support for separated operations files 2016-02-04 18:51:22 +01:00
Hugo de Paix de Coeur
836d9fbae7 Migrate to markup-document-builder 0.1.6-SNAPSHOT 2016-02-04 17:34:10 +01:00
Hugo de Paix de Coeur
9df1c73641 fixed Markdown generation for inline schemas 2016-02-04 13:51:23 +01:00
Hugo de Paix de Coeur
1899efd209 Test cleanups 2016-02-04 13:51:23 +01:00
Hugo de Paix de Coeur
9d90766592 Workaround for https://github.com/swagger-api/swagger-parser/issues/177 2016-02-04 13:51:23 +01:00
Hugo de Paix de Coeur
bd9d3ee4c3 Cleanups 2016-02-04 13:51:23 +01:00
Robert Winkler
20fac6ab26 Fixed travis file 2016-02-04 13:22:25 +01:00
Robert Winkler
5be5a7d8e3 Fixed travis file 2016-02-04 13:11:02 +01:00
Robert Winkler
35f0192ecb Fixed Coveralls badge 2016-02-03 15:59:49 +01:00
Robert Winkler
69949d6257 Added artifactoryPublish task to TravisCI to publish SNAPSHOTS to OSS Artifactory 2016-02-03 15:56:00 +01:00
Robert Winkler
94ad45d2b0 Added Artifactory Gradle Plugin in order to deploy snapshots to oss.jfrog.org 2016-02-03 13:25:05 +01:00
Robert Winkler
c62f6085f7 Changed inlineSchemaDepthLevel from Integer to int
Changed default value of inlineSchemaDepthLevel from 0 to 1
2016-02-03 08:46:52 +01:00
Robert Winkler
2a300a2ef6 Merge pull request #55 from Kabhal/separatedBody
Enhancements
2016-02-02 21:01:08 +01:00
Hugo de Paix de Coeur
a77a0f281d Merge branch 'master' of github.com:Swagger2Markup/swagger2markup into separatedBody 2016-02-02 20:08:14 +01:00
Hugo de Paix de Coeur
d794cd989b Introduced columns width ratio in all tables to maximize description column width.
Refactored table generation.
MarkupDocBuilderUtils code should be replaced with markup-document-builder enhancements.
2016-02-02 20:04:33 +01:00
Hugo de Paix de Coeur
60c687f3f8 Introduced tableRow() to escape table contents 2016-02-02 18:46:07 +01:00
Hugo de Paix de Coeur
8da5d3a770 l10n : No Content
Cleaning
2016-02-02 18:04:52 +01:00
Hugo de Paix de Coeur
ead3e0bc22 Added .withInlineSchemaDepthLevel to converter configuration (default: 0 = disable feature)
Added inline schema support for global definitions.
Relayout inlineSchema feature : no mode distinct Definitions section in Paths, inline types are displayed right after each original type. This is for consistency with global definitions.
2016-02-02 11:45:22 +01:00
Robert Winkler
a0c1f20fc3 Added inline schema example Swagger YAML file 2016-02-02 10:36:29 +01:00
Robert Winkler
8e6586d4e4 Merge pull request #54 from Kabhal/separatedBody
Inline schemas support (issue #52)
2016-02-02 07:30:39 +01:00
Hugo de Paix de Coeur
b2f4229f70 Merge branch 'master' of github.com:Swagger2Markup/swagger2markup into separatedBody 2016-02-01 22:46:21 +01:00
Hugo de Paix de Coeur
2425074855 cleanup 2016-02-01 20:41:01 +01:00
Hugo de Paix de Coeur
7d53a8aedb Managed inline schemas in parameters and responses (depth level = 1)
Inline schemas in definitions are still to be managed.
2016-02-01 20:14:40 +01:00
Hugo de Paix de Coeur
a16617880f Factorized the display of type properties table 2016-02-01 17:38:06 +01:00
Hugo de Paix de Coeur
650431b8ce Support for response inline objects 2016-02-01 16:15:56 +01:00
Hugo de Paix de Coeur
a6654b65a9 Genericized the type system between models, parameters, properties, etc ... for further refactoring
*Utils display logic is removed from *Utils which are now just adapters from Swagger model to *Type.
 *Type now have the display logic.
2016-02-01 16:10:30 +01:00
Hugo de Paix de Coeur
4f15ea9ed7 Corrected warnings 2016-02-01 10:59:38 +01:00
Hugo de Paix de Coeur
aa34532b33 Factorized paths sections titles 2016-02-01 10:58:31 +01:00
Robert Winkler
3fe711a3ba Merge pull request #53 from Kabhal/fixedPathsNames
Base paths and fixed file names must not depend on translations
2016-01-29 14:19:04 +01:00
Hugo de Paix de Coeur
93e2175435 Base paths and fixed file names must not depend on translations 2016-01-29 14:00:20 +01:00
Robert Winkler
5c61006d11 Updated readme 2016-01-26 08:06:48 +01:00
Robert Winkler
6da74af830 Updated readme 2016-01-26 08:04:12 +01:00
Robert Winkler
93ba67c405 Updated swagger-parser from v1.0.13 to v1.0.16 2016-01-11 08:44:40 +01:00
Robert Winkler
04fed3d4d5 Prepare release v0.9.2 2016-01-05 14:35:12 +01:00
Robert Winkler
1ead6614ba Corrected russian labels file, because the files names of spring-restdocs are always english. 2016-01-05 14:31:11 +01:00
Robert Winkler
887e63464d Merge pull request #49 from MeteorBoom/master
Added output files language option
2016-01-04 16:47:33 +01:00
Maksim Myshkin
47e5d5e56e I have merged property files in one. ResourceBundle is now used. 2016-01-04 20:15:50 +05:00
Maksim Myshkin
c505c1e88e Added output files language option 2016-01-03 22:13:57 +05:00
Robert Winkler
6a8c04c031 Updated documentation 2015-11-24 08:27:15 +01:00
Robert Winkler
33f68a7f41 Updated documentation 2015-11-24 08:26:07 +01:00
Robert Winkler
c5af8676e5 Updated documentation 2015-11-24 08:20:22 +01:00
Robert Winkler
618898cb09 Updated documentation 2015-11-24 08:19:37 +01:00
Robert Winkler
36bdcc57d9 Added Swagger2MarkupConverter.fromString test case 2015-11-16 09:41:27 +01:00
Robert Winkler
eb418c07f5 Updated publishing gradle script 2015-11-12 14:37:50 +01:00
Robert Winkler
9a265fbbc3 Updated RELEASENOTES 2015-11-12 13:12:15 +01:00
Robert Winkler
cf32d6cf29 [New Feature] Added support to group the paths by tags or as-is
[New Feature] Added support to order the definitions by natural ordering or as-is
2015-11-12 13:10:33 +01:00
Robert Winkler
9d216e3dc2 [Bug] Fixed unit test issue with composed models 2015-11-09 15:49:35 +01:00
Robert Winkler
9d387b3e80 Merge remote-tracking branch 'origin/master' 2015-11-09 14:52:52 +01:00
Robert Winkler
1e6be2f26d Updated swagger-parser from v1.0.8 to v1.0.13
Support for global responses and parameters
2015-11-09 14:52:43 +01:00
Robert Winkler
e56f824cd2 Updated documentation 2015-10-01 08:40:44 +02:00
Robert Winkler
d38014f4b5 Updated documentation 2015-09-30 13:35:12 +02:00
Robert Winkler
b331062fa6 Updated documentation 2015-09-01 17:28:13 +02:00
Robert Winkler
88df748451 Merge pull request #35 from Relequestual/patch-1
Updated readme to better reflect alternatives listing
2015-09-01 17:19:44 +02:00
Ben Hutton
5384197bd1 Updated readme to better reflect alternatives listing
The list of alternative publishing libraries was missleading in the sense it lead me to believe that I could use this library to generate AsciiDoc or Markdown, which would work in all of the listed documentation hosting services / open source projects templates.
2015-09-01 14:53:22 +01:00
Robert Winkler
2b5d4b7fe9 Merge pull request #34 from johanhammar/urischeme
Do not render URI scheme if none of host, schemes or basePath are set
2015-08-29 01:32:59 +02:00
Johan Hammar
c15d074488 Do not render URI scheme if none of host, schemes or basePath are set 2015-08-28 22:18:49 +02:00
Robert Winkler
b0c3aa71b9 Merge pull request #32 from johanhammar/gradle25
Update the dependency-management-plugin to work with Gradle 2.5
2015-08-26 21:15:17 +02:00
Johan Hammar
32d85ffb55 Update the dependency-management-plugin to work with Gradle 2.5 2015-08-26 20:56:23 +02:00
Robert Winkler
59fcd61738 Updated documentation 2015-08-24 20:55:30 +02:00
Robert Winkler
7ce969882d Updated documentation 2015-08-24 20:54:39 +02:00
Robert Winkler
ee70cdb94f Update README.adoc 2015-08-24 20:52:32 +02:00
Robert Winkler
f21fce7730 * Enhancement #26 and #27: Added a pre-process hook to modify a Swagger Model before it is converted. 2015-08-24 20:44:46 +02:00
Robert Winkler
c426c7b341 Bugfix #29: Tags are rendered twice 2015-08-24 20:44:17 +02:00
Robert Winkler
1231d1e0c2 Merge pull request #27 from zmitrok/master
Added a hook to pre-process Swagger model before generating the marku…
2015-08-21 18:13:18 +02:00
zmitrok
66073aebb8 Added a hook to pre-process Swagger model before generating the markup. This approach heavily relies on the mutability of the Swagger class 2015-08-20 23:57:46 -07:00
Robert Winkler
882d9e5709 Merge pull request #23 from izeye/patch-1
Fix a broken link
2015-07-24 17:08:27 +02:00
izeye
ba9ec45d9e Fix a broken link 2015-07-24 21:07:36 +09:00
Robert Winkler
f2787a41ae Merge branch 'master' of https://github.com/Swagger2Markup/swagger2markup 2015-07-20 08:20:41 +02:00
Robert Winkler
3469523225 Workaround: If the type of a BodyParameter is String and not a Model, the schema is null and lost. Therefore the fallback type of a BodyParameter is String now. 2015-07-20 08:20:06 +02:00
Robert Winkler
1dc9a07cb9 Updated documentation 2015-07-14 08:33:46 +02:00
Robert Winkler
a34807e5c9 Updated Travis-CI Batch 2015-07-09 08:08:57 +02:00
Robert Winkler
85ef33a720 Updated documentation 2015-07-06 08:49:22 +02:00
Robert Winkler
3163c077a1 Updated documentation 2015-06-30 08:39:46 +02:00
Robert Winkler
fbb446875d Updated documentation 2015-06-30 08:38:54 +02:00
Robert Winkler
e8cdcabffe Updated documentation 2015-06-30 08:36:08 +02:00
Robert Winkler
832813d40a Updated documentation 2015-06-30 08:26:05 +02:00
Robert Winkler
e2f28bca7d Updated documentation 2015-06-29 15:29:06 +02:00
Robert Winkler
3ed894688c Updated documentation 2015-06-29 12:33:52 +02:00
Robert Winkler
bb7422d755 New Feature #21: Added support for both reference models and composed models 2015-06-29 09:32:47 +02:00
Robert Winkler
b2f3f4a6c7 Updated documentation 2015-06-28 09:02:09 +02:00
Robert Winkler
f21794a253 Updated documentation 2015-06-27 11:49:19 +02:00
Robert Winkler
ffa96e56a5 Updated documentation 2015-06-27 11:47:49 +02:00
Robert Winkler
38e50dfe77 Merge pull request #20 from redowl/add-composition-support
Adding support for composed model definitions
2015-06-27 11:38:20 +02:00
Russell Snyder
1d3ec2d5a3 Adding support for composed model definitions
Signed-off-by: Russell Snyder <russell@redowlanalytics.com>
2015-06-26 14:40:41 -04:00
Robert Winkler
495751433b Updated documentation 2015-06-24 19:32:23 +02:00
Robert Winkler
de7d73eae9 Updated documentation 2015-06-24 09:54:33 +02:00
Robert Winkler
f825cf9613 Updated documentation 2015-06-24 09:53:47 +02:00
Robert Winkler
6e32056c26 Updated documentation 2015-06-24 09:44:51 +02:00
Robert Winkler
85bc2aa8f9 Updated documentation 2015-06-23 09:44:07 +02:00
Robert Winkler
d56de83368 Updated documentation 2015-06-23 09:41:36 +02:00
Robert Winkler
065e65a31c Updated documentation 2015-06-23 09:38:33 +02:00
Robert Winkler
a68980bc76 Updated documentation 2015-06-23 09:32:47 +02:00
348 changed files with 37653 additions and 3080 deletions

4
.gitignore vendored
View File

@@ -2,3 +2,7 @@
*.iml
.gradle
build
/bin/
/.classpath
/.project
/.settings/

View File

@@ -1,15 +1,18 @@
language: java
jdk:
- oraclejdk7
- oraclejdk8
before_install:
- chmod +x gradlew
after_success:
- ./gradlew jacocoTestReport coveralls
- ./gradlew artifactoryPublish -PbintrayUsername="${BINTRAY_USER}" -PbintrayApiKey="${BINTRAY_KEY}"
- ./gradlew publishGhPages -PgithubUser="${GITHUB_USER}" -PgithubPassword="${GITHUB_PASSWORD}"
--stacktrace
notifications:
webhooks:
urls:
- https://webhooks.gitter.im/e/9c620e84679284b7d621
on_success: change # options: [always|never|change] default: always
on_failure: always # options: [always|never|change] default: always
on_start: false # default: false
Your unique webhook url for this service:
slack: swagger2markup:Zz5kz0SnvtG6aVvZUM8yMkER
env:
global:
- secure: SPKolgUdjIa/uJ+7/B/GPFlsa8IZg7NuZdFA8zROTaqew/xu+oX7qVGImseeBpPIEPJb02ac6hr7Y3/zvv0GJxIPtIbyDzVh73ImQUhT1ttLYGJfITAWqAPFF7RNNMtuOl3S2DLZ5OMJddkcFp00pa9nyI82Gk47B8GsaGIntAI=
- secure: nXXuHfvFACZwdiFM3Ta0x/f49N7cAgi0AMkgEnQrh/2xWlvQk2z2ySGJQLkhJ7Wy8LDY7Yt1b1GUt6DlP3PuFFMW/cT4iARewqiJRXZXxUQz8fpTDeTo1nmVmW/zzII6Qj3QHM3NRbR/xDOVSJiT30Hnq2hcCBQJWYsTICmzjRk=
- secure: Ia/wJ572M2II76roFeGEVCzIiktG4v2j/reSn60fpk1gnoEPQEObL4j1dbVCgXBLz54YWcaQ3mICvOfBPPEl9IIV3Y6DDE2sBOmB3soznfdA/YVnJx0h0f1pfXu1dwqoiv1sgc1wewQuUWq+FV7xeDhFE3cnh9CXIexe9ykip8k=
- secure: GWfhYDsHRmTfOuEOIcHY8kT4jKBTbdhNLDQ/2amY06xenFblb4pEn6pgmn4IdK3ytjNovnZPTOOK8HqdEjhbfIGoQt6PZwuyANn4Df+zdqOC0+V+7DFG2QhEhbRCyEwPlDqTPjxlOMfAmvjFuY/NvQywoF3PYUyMfJwUV8ehmYk=

5
ISSUE_TEMPLATE Normal file
View File

@@ -0,0 +1,5 @@
Thanks for raising a Swagger2Markup issue. Please provide a brief description of your problem along with the Swagger2Markup version you are using. If possible, please also consider putting together a complete Swagger specification that reproduces the issue. It's better if the Swagger specification is small and isolate the issue.
Swagger2Markup version:
Problem description:

View File

@@ -1,398 +1,59 @@
= Swagger2Markup
:author: Robert Winkler
:version: 0.6.3
:hardbreaks:
image:https://travis-ci.org/RobWin/swagger2markup.svg?branch=master["Build Status", link="https://travis-ci.org/RobWin/swagger2markup"] image:https://coveralls.io/repos/RobWin/swagger2markup/badge.svg["Coverage Status", link="https://coveralls.io/r/RobWin/swagger2markup"] image:https://api.bintray.com/packages/robwin/maven/swagger2markup/images/download.svg[link="https://bintray.com/robwin/maven/swagger2markup/_latestVersion"] image:http://img.shields.io/badge/license-ASF2-blue.svg["Apache License 2", link="http://www.apache.org/licenses/LICENSE-2.0.txt"] image:https://img.shields.io/badge/Twitter-rbrtwnklr-blue.svg["Twitter", link="https://twitter.com/rbrtwnklr"] image:https://badges.gitter.im/Join%20Chat.svg[link="https://gitter.im/RobWin/swagger2markup?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge"]
image:https://travis-ci.org/Swagger2Markup/swagger2markup.svg?branch=master["Build Status", link="https://travis-ci.org/Swagger2Markup/swagger2markup"] image:https://coveralls.io/repos/Swagger2Markup/swagger2markup/badge.svg["Coverage Status", link="https://coveralls.io/r/Swagger2Markup/swagger2markup"] image:https://api.codacy.com/project/badge/grade/498a6a39d7d84ff687546359f58ee18d["Codacy code quality", link="https://www.codacy.com/app/robwin/swagger2markup"] image:https://api.bintray.com/packages/swagger2markup/Maven/swagger2markup/images/download.svg[link="https://bintray.com/swagger2markup/Maven/swagger2markup/_latestVersion"] image:http://img.shields.io/badge/license-ASF2-blue.svg["Apache License 2", link="http://www.apache.org/licenses/LICENSE-2.0.txt"] image:https://img.shields.io/badge/Twitter-rbrtwnklr-blue.svg["Twitter", link="https://twitter.com/rbrtwnklr"] image:https://badges.gitter.im/Join%20Chat.svg[link="https://gitter.im/RobWin/swagger2markup?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge"]
== Overview
The primary goal of this project is to *simplify the generation of an up-to-date RESTful API documentation by combining documentation that's been hand-written with auto-generated API documentation* produced by https://github.com/swagger-api[Swagger]. The result is intended to be an *up-to-date, easy-to-read, on- and offline user guide*, comparable to https://developer.github.com/v3/[GitHub's API documentation]. The output of Swagger2Markup can be used as an alternative to https://github.com/swagger-api/swagger-ui[swagger-ui] and can be served as static content.
NOTE: The Swagger Specification has been donated to to the https://openapis.org/[Open API Initiative (OAI)] and has been renamed to the https://github.com/OAI/OpenAPI-Specification[OpenAPI Specification].
Swagger2Markup converts a Swagger JSON or YAML file into several *AsciiDoc* or *GitHub Flavored Markdown* documents which can be combined with hand-written documentation. The Swagger source file can be located locally or remotely via HTTP. Swagger2Markup supports the Swagger 1.2 and 2.0 specification. Internally it uses the _official_ https://github.com/swagger-api/swagger-parser[swagger-parser] and my https://github.com/RobWin/markup-document-builder[markup-document-builder].
You can use Swagger2Markup to convert your contract-first Swagger YAML file into a human-readable format and combine it with hand-written documentation. As an alternative, you can choose the code-first approach and use Swagger2Markup together with https://github.com/swagger-api/swagger-core/tree/master/samples/java-jersey2[Swagger JAX-RS], https://github.com/springfox/springfox[springfox] or https://github.com/spring-projects/spring-restdocs[spring-restdocs]. See https://github.com/RobWin/swagger2markup#usage-guide[usage guide] below. If you are are Gradle user, you can also use the https://github.com/RobWin/swagger2markup-gradle-plugin[Swagger2Markup Gradle Plugin].
You can use Swagger2Markup to convert your contract-first Swagger YAML file into a human-readable format and combine it with hand-written documentation. As an alternative, you can choose the code-first approach and use Swagger2Markup together with https://github.com/swagger-api/swagger-core/wiki/Swagger-Core-JAX-RS-Project-Setup-1.5.X[Swagger JAX-RS], https://github.com/springfox/springfox[springfox] or https://github.com/spring-projects/spring-restdocs[spring-restdocs]. If you are Gradle or Maven user, you can also use the https://github.com/RobWin/swagger2markup-gradle-plugin[Swagger2Markup Gradle Plugin] or https://github.com/redowl/swagger2markup-maven-plugin[Swagger2markup Maven Plugin].
http://asciidoctor.org/docs/asciidoc-writers-guide/[AsciiDoc] is preferable to Markdown as it has more features. AsciiDoc is a text document format for writing documentation, articles, books, ebooks, slideshows, web pages and blogs. AsciiDoc files can be converted to *HTML*, *PDF* and *EPUB*. AsciiDoc is much better suited for describing public APIs than *JavaDoc* or *Annotations*.
You can generate your HTML5, PDF and EPUB documentation via https://github.com/asciidoctor/asciidoctorj[asciidoctorj] or even better via the https://github.com/asciidoctor/asciidoctor-gradle-plugin[asciidoctor-gradle-plugin] or https://github.com/asciidoctor/asciidoctor-maven-plugin[asciidoctor-maven-plugin]. You can also use https://github.com/jbake-org/jbake[JBake], https://github.com/tomchristie/mkdocs[MkDocs], https://github.com/rtfd/readthedocs.org[ReadTheDocs] or https://github.com/tripit/slate[slate] to publish your AsciiDoc or Markdown documentation.
You can generate your HTML5, PDF and EPUB documentation via https://github.com/asciidoctor/asciidoctorj[asciidoctorj] or even better via the https://github.com/asciidoctor/asciidoctor-gradle-plugin[asciidoctor-gradle-plugin] or https://github.com/asciidoctor/asciidoctor-maven-plugin[asciidoctor-maven-plugin].
The project requires at least JDK 7.
The project requires at least JDK 8.
== Usage guide
== Example
=== Adding Swagger2Markup to your project
The project is published in JCenter and Maven Central.
image::src/docs/asciidoc/images/Swagger2Markup.PNG[]
==== Maven
image::src/docs/asciidoc/images/Swagger2Markup_definitions.PNG[]
[source,xml]
----
<repositories>
<repository>
<snapshots>
<enabled>false</enabled>
</snapshots>
<id>central</id>
<name>bintray</name>
<url>http://jcenter.bintray.com</url>
</repository>
</repositories>
== Reference documentation
- http://swagger2markup.github.io/swagger2markup/1.1.1/[Reference Documentation]
- https://github.com/Swagger2Markup/swagger2markup/blob/master/RELEASENOTES.adoc[Release notes]
- https://github.com/Swagger2Markup/spring-swagger2markup-demo[Demo using Swagger2Markup, Spring Boot, Springfox and spring-restdocs]
<dependency>
<groupId>io.github.robwin</groupId>
<artifactId>swagger2markup</artifactId>
<version>0.6.3</version>
</dependency>
----
== Contributing
==== Gradle
=== Community contributions
[source,groovy]
----
repositories {
jcenter()
}
Pull requests are welcome.
compile "io.github.robwin:swagger2markup:0.6.3"
----
=== Questions
You can ask questions about Swagger2Markup in https://gitter.im/Swagger2Markup/swagger2markup[Gitter].
=== Using Swagger2Markup
=== Bugs
If you believe you have found a bug, please take a moment to search the existing issues. If no one else has reported the problem, please open a new issue that describes the problem in detail and, ideally, includes a test that reproduces it.
Using the Swagger2MarkupConverter is simple. For example, if you are using https://github.com/spring-projects/spring-boot[Spring Boot] and https://github.com/springfox/springfox[springfox], you can generate your Swagger JSON file during the integration or unit test phase, convert the Swagger JSON file into AsciiDoc, convert AsciiDoc into HTML and PDF, copy the documentation into the Jar file and serve it as static content. That way there is no runtime overhead and there are no additional runtime libraries required.
The quickest way to get started is to look at the demo project https://github.com/RobWin/spring-swagger2markup-demo[spring-swagger2markup-demo]. The demo shows how to generate static docs (HTML5 and PDF) with the https://github.com/RobWin/swagger2markup-gradle-plugin[Swagger2Markup Gradle Plugin] and serve them as static content in a Spring Boot App under http://localhost:9080/docs/index.html and http://localhost:9080/docs/index.pdf.
=== Enhancements
If youd like an enhancement to be made to Swagger2Markup, pull requests are most welcome. The source code is on GitHub. You may want to search the existing issues and pull requests to see if the enhancement is already being worked on. You may also want to open a new issue to discuss a possible enhancement before work on it begins.
==== Generate Markup during an integration test
== Companies who use Swagger2Markup
Swagger2MarkupConverter can be used to make a request to a Swagger endpoint during an integration test. The Swagger2MarkupConverter writes the generated documents into the folder `src/docs/asciidoc/generated` or `src/docs/markdown/generated`.
[source,java]
----
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
@IntegrationTest
@WebAppConfiguration
public class Swagger2MarkupTest {
@Test
public void convertRemoteSwaggerToAsciiDoc() {
// Remote Swagger source
// Default is AsciiDoc
Swagger2MarkupConverter.from("http://localhost:8080/v2/api-docs").build()
.intoFolder("src/docs/asciidoc/generated");
// Then validate that three AsciiDoc files have been created
String[] files = new File("src/docs/asciidoc/generated").list();
assertThat(files).hasSize(3)
.containsAll(Arrays.asList("definitions.adoc", "overview.adoc", "paths.adoc"));
}
@Test
public void convertRemoteSwaggerToMarkdown() {
// Remote Swagger source
// Markdown
Swagger2MarkupConverter.from("http://localhost:8080/v2/api-docs")
.withMarkupLanguage(MarkupLanguage.MARKDOWN).build()
.intoFolder("src/docs/markdown/generated");
// Then validate that three Markdown files have been created
String[] files = new File("src/docs/markdown/generated").list();
assertThat(files).hasSize(3)
.containsAll(Arrays.asList("definitions.md", "overview.md", "paths.md"));
}
@Test
public void convertLocalSwaggerToAsciiDoc() {
//Local Swagger source
//Default is AsciiDoc
String location = Swagger2MarkupTest.class.getResource("/json/swagger.json").getPath();
Swagger2MarkupConverter.from(location).build()
.intoFolder("src/docs/asciidoc/generated");
}
}
----
==== Generate Markup during an unit test with springfox-staticdocs
Spring's MVC Test framework can also be used to make a request to a https://github.com/springfox/springfox[springfox] Swagger endpoint during an unit test. A custom ResultHandler `Swagger2MarkupResultHandler` is used to automatically convert the Swagger JSON response into an AsciiDoc document. The custom ResultHandler is part of `springfox-staticdocs`. That way you also verify that your Swagger endpoint is working.
[source,java]
----
@WebAppConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = Application.class, loader = SpringApplicationContextLoader.class)
public class Swagger2MarkupTest {
@Autowired
private WebApplicationContext context;
private MockMvc mockMvc;
@Before
public void setUp() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context).build();
}
@Test
public void convertSwaggerToAsciiDoc() throws Exception {
this.mockMvc.perform(get("/v2/api-docs")
.accept(MediaType.APPLICATION_JSON))
.andDo(Swagger2MarkupResultHandler.outputDirectory("src/docs/asciidoc/generated").build())
.andExpect(status().isOk());
}
@Test
public void convertSwaggerToMarkdown() throws Exception {
this.mockMvc.perform(get("/v2/api-docs")
.accept(MediaType.APPLICATION_JSON))
.andDo(Swagger2MarkupResultHandler.outputDirectory("src/docs/markdown/generated")
.withMarkupLanguage(MarkupLanguage.MARKDOWN).build())
.andExpect(status().isOk());
}
}
----
==== Gradle dependencies
[source,groovy]
----
dependencies {
...
compile 'io.springfox:springfox-swagger2:2.0.0'
testCompile 'io.springfox:springfox-staticdocs:2.0.0'
...
}
----
==== Springfox configuration
The following is a complete https://github.com/springfox/springfox[springfox] configuration to use Swagger in a Spring Boot Application.
[source,java]
----
@SpringBootApplication
@EnableSwagger2
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Bean
public Docket restApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.paths(ant("/api/**"))
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("Petstore API Title")
.description("Petstore API Description")
.contact("Petstore API Contact Email")
.version("1.0.0")
.build();
}
}
----
==== Combine generated documentation with your hand-written documentation
The following shows how you can combine the generated documentation with your hand-written AsciiDoc documentation. You have to create an `index.adoc` (it must not be necessarily called index). To include the programmatically generated snippets in your documentation, you use Asciidoc's `include` macro. The `generated` variable is configured below.
image::images/generated_docs.PNG[generated_docs]
You can generate your HTML5 and PDF documentation via the https://github.com/asciidoctor/asciidoctor-gradle-plugin[asciidoctor-gradle-plugin] or https://github.com/asciidoctor/asciidoctor-maven-plugin[asciidoctor-maven-plugin]. The following listing shows how to configure the Asciidoctor Gradle plugin. By default it searches for AsciiDoc files in `src/docs/asciidoc` and puts the HTML and PDF output into `build/asciidoc/html5` and `build/asciidoc/pdf`. The `generated` attribute is used to replace the variable in the `index.adoc` file and to provide configurable access to the generated snippets.
[source,groovy]
----
ext {
generatedDocumentation = file('src/docs/asciidoc/generated')
}
test {
outputs.dir generatedDocumentation
}
asciidoctor {
dependsOn test
sources {
include 'index.adoc'
}
backends = ['html5', 'pdf']
attributes = [
doctype: 'book',
toc: 'left',
toclevels: '2',
numbered: '',
sectlinks: '',
sectanchors: '',
generated: generatedDocumentation
]
}
----
You can copy the output into your Jar file and serve the documentation as static content under `http://localhost:9080/docs/index.html` and `http://localhost:9080/docs/index.pdf`.
[source,groovy]
----
jar {
dependsOn asciidoctor
from ("${asciidoctor.outputDir}/html5") {
into 'static/docs'
}
from ("${asciidoctor.outputDir}/pdf") {
into 'static/docs'
}
}
----
==== Include spring-restdocs example snippets
Swagger2Markup can be used together with https://github.com/spring-projects/spring-restdocs[spring-restdocs]. Swagger2Markup can include the generated CURL request, HTTP request and HTTP response example snippets from spring-restdocs into the generated AsciiDoc document. See https://github.com/spring-projects/spring-restdocs[spring-restdocs] how to configure it. Currently spring-restdocs does only support AsciiDoc.
Let's say you have a Swagger-annotated Spring RestController method with an ApiOperation value: `Add a new pet to the store`
[source,java]
----
@RequestMapping(method = POST)
@ApiOperation(value = "Add a new pet to the store")
@ApiResponses(value = {@ApiResponse(code = 405, message = "Invalid input")})
public ResponseEntity<String> addPet(
@ApiParam(value = "Pet object that needs to be added to the store", required = true) @RequestBody Pet pet) {
petData.add(pet);
return Responses.ok("SUCCESS");
}
----
By convention the target folder of the generated request and response example files must be similar to the value of the ApiOperation, but with underscores and lowercase. For example a folder for `@ApiOperation(value = "Add a new pet to the store")` must be called `add_a_new_pet_to_the_store`.
[source,java]
----
@Test
public void findPetById() throws Exception {
this.mockMvc.perform(post("/api/pet/").content(createPet())
.contentType(MediaType.APPLICATION_JSON))
.andDo(RestDocumentation.document("add_a_new_pet_to_the_store"))
.andExpect(status().isOk());
}
----
The system property `org.springframework.restdocs.outputDir` is used to control the output base directory where the folder `add_a_new_pet_to_the_store` and the generated snippets are written to. The spring-restdocs output base directory is configured as follows:
[source,groovy]
----
ext {
generatedDocumentation = file('src/docs/asciidoc/generated')
}
test {
systemProperty 'org.springframework.restdocs.outputDir', generatedDocumentation
outputs.dir generatedDocumentation
}
----
You must specify the base output directory of spring-restdocs with the builder method `withExamples("src/docs/asciidoc/generated")`.
[source,java]
----
@Test
public void convertToAsciiDoc() throws Exception {
this.mockMvc.perform(get("/v2/api-docs")
.accept(MediaType.APPLICATION_JSON))
.andDo(Swagger2MarkupResultHandler.outputDirectory("src/docs/asciidoc")
.withExamples("src/docs/asciidoc/generated").build())
.andExpect(status().isOk());
}
----
By convention the Swagger2MarkupConverter searches for a method annotated with `@ApiOperation(value = "Add a new pet to the store")` in a folder called `src/docs/asciidoc/generated/add_a_new_pet_to_the_store` and includes the `http-request.adoc` and `http-response.adoc` files, if they are available.
The AsciiDoc HTML output would look as follows:
image::images/springrestdocs_examples.PNG[springrestdocs]
==== Include hand-written descriptions into the generated documentation
If you don't want to pollute your source code with Swagger annotations just to add descriptions to Operations, Parameters and Model definitions. Like here:
[source, java]
----
@RequestMapping(method = PUT)
@ApiOperation(value = "Update an existing pet")
@ApiResponses(value = {@ApiResponse(code = 400, message = "Invalid ID supplied"),
@ApiResponse(code = 404, message = "Pet not found"),
@ApiResponse(code = 405, message = "Validation exception")})
public ResponseEntity<String> updatePet(
@ApiParam(value = "Pet object that needs to be added to the store", required = true) @RequestBody Pet pet) {
petData.add(pet);
return Responses.ok("SUCCESS");
}
----
You can create hand-written descriptions and include them with the builder method `withDescriptions()` into your documentation by specifying the base folder of your documentation.
[source, java]
----
Swagger2MarkupConverter.from(file.getAbsolutePath()).withDescriptions("src/docs/asciidoc").build()
.intoFolder("src/docs/asciidoc");
----
By convention you need two folders `paths` and `definitions` inside your description base folder.
The `paths` folder contains sub folders for all operations. The folder must be named similar to the value of the ApiOperation annotation, but with underscores and lowercase.
For example a folder for `@ApiOperation(value = "Update an existing pet")` must be called `update_an_existing_pet`.
The `definitions` folder contains sub folders for all models. The folder must be named similar to the name of the Model, but lowercase.
For example a folder for a model called `User` must be called `user`.
You can have a global description file for each operation or model. And you can have one description file per operation parameter or model property.
For example:
image::images/handwritten_descriptions.PNG[handwritten_descriptions]
The AsciiDoc HTML output would look as follows:
image::images/handwritten_descr_asciidoc.PNG[handwritten_descr_asciidoc]
==== Include JSON and XML Schema files.
Swagger2Markup can also include JSON and XML Schema files into the generated document.
[source,java]
----
Swagger2MarkupConverter.from("http://localhost:8080/api-docs").withSchemas("src/docs/schemas").build()
.intoFolder("src/docs/asciidoc");
----
You can create the schema files during a unit test as follows:
[source,java]
----
RestDocumented restDocumented = RestDocumented.fromProperties();
restDocumented.documentJsonSchema(MailStorageQuota.class, "src/docs/schemas");
restDocumented.documentXmlSchema(MailStorageQuota.class, "src/docs/schemas");
----
I will make RestDocumented public soon. RestDocumented creates a MailStorageQuota.xsd and MailStorageQuota.json file in the folder `src/docs/schemas`. The Swagger2MarkupConverter will include the JSON and XML Schemas, if a Swagger Operation uses the MailStorageQuota class as input or output.
== Screenshots
=== Swagger source
image::images/swagger_json.PNG[swagger_json]
=== Generated AsciiDoc
image::images/asciidoc.PNG[asciidoc]
=== Generated Markdown
image::images/markdown.PNG[markdown]
=== Generated HTML using AsciidoctorJ
image::images/asciidoc_html.PNG[asciidoc_html]
=== Generated PDF using AsciidoctorJ
image::images/asciidoc_pdf.PNG[asciidoc_pdf]
* Deutsche Telekom AG
* https://restlet.com/[Restlet] -- Restlet offers an API platform, covering the https://restlet.com/products/restlet-studio/[design], https://restlet.com/products/dhc/[test] and https://restlet.com/products/apispark/[operation] of Web APIs, and uses Swagger2Markup to generate appealing HTML documentation from API definitions.
* http://www.qaware.de/[QAware GmbH]
* http://www.appdirect.com/[AppDirect] -- The leading commerce platform for selling cloud services.
* http://www.wescale.com[wescale]
* http://taskassure.com[TaskAssure]
== License

View File

@@ -46,11 +46,80 @@
* Updated swagger-parser from v1.0.5 to v1.0.6
* Support for default values in Parameters and Model properties
== Version 0.6.1
=== Version 0.6.1
* Updated swagger-parser from v1.0.6 to v1.0.8
== Version 0.6.2
=== Version 0.6.2
* curl-request.adoc from spring-restdocs is also added to the example chapters
== Version 0.6.3
=== Version 0.6.3
* Added possibility to write object definitions to separate files. Issue #19
== Version 0.7.0
* Added support for both reference models and composed models
=== Version 0.7.1
* Workaround: If the type of a BodyParameter is String and not a Model, the schema is null and lost. Therefore the fallback type of a BodyParameter is String now.
== Version 0.8.0
* Enhancement #26 and #27: Added a pre-process hook to modify a Swagger Model before it is converted.
* Bugfix #29: Tags are rendered twice
== Version 0.9.0
* Updated swagger-parser from v1.0.8 to v1.0.13
* Support for global responses and parameters
=== Version 0.9.1
* Added support to group the paths by tags or as-is
* Added support to order the definitions by natural ordering or as-is
=== Version 0.9.2
* Multi language support. Added russian.
=== Version 0.9.3
* Updated swagger-parser from v1.0.13 to v1.0.16
* Enhancement #61: Refactor separated documents logic to support inter-document cross-references
* Enhancement #53: Support for tags, paths and methods ordering
* Enhancement #51: Support for separated operations files
* Enhancement #52: Markdown generation for inline schemas
== Version 1.0.0
* New configuration API
* New extension SPI
* Added new languages: turkish, german, france
* New security document
* Inline schema support
* New configuration options
* Support of deprecated path operations
=== Version 1.0.1
* Enhancement: Support to render validation constraints of properties
* Enhancement: Possibility to disable rendering of the security chapter below operations
== Version 1.1.0
* PR #177: Fixed rendering of recursive examples
* PR #186: Add support for Chinese language
* PR #190: Add support for Spanish language
* PR #192: Updated min/max value to format correctly based on the data type
* PR #193: Added support for exclusiveMin and exclusiveMax
=== Version 1.1.1
* Issue #194: Added a config parameter which allows to prepend the basePath to all paths.
* Updated swagger-parser from v1.0.16 to v1.0.23
* Added javslang v2.0.4 as a dependency
* Added paleo-core v0.10.1 as a dependency
* Updated markup-document-builder from 1.0.0 to 1.1.0
* PR #201: Add support for Brazilian Portuguese language
* PR #202: Add support for Japanese language
* Issue #205: Fixed the option to influence resource ordering
* Issue #198: Chinese chinese language encoding
* Issue #207: Properties that start with an underscore are displayed correctly now
* Refactored Swagger2Markup to use a Component-Based design. A document can be composed of components and components can be composed of other components.
=== Version 1.1.2
* Issue #214: Add page break locations
* Issue #223: Improve example rendering
* Issue #215: Add ability to group operations by RegEx
* Added new configuration options: pageBreakLocations, headerRegex
* Added new valid value for configuration headerRegex: REGEX
* Updated markup-document-builder from 1.1.0 to 1.1.1-SNAPSHOT

View File

@@ -4,118 +4,67 @@ buildscript {
mavenCentral()
}
dependencies {
classpath 'org.asciidoctor:asciidoctor-gradle-plugin:1.5.2'
classpath 'org.asciidoctor:asciidoctorj-pdf:1.5.0-alpha.7'
classpath 'io.spring.gradle:dependency-management-plugin:0.5.1.RELEASE'
classpath 'org.asciidoctor:asciidoctor-gradle-plugin:1.5.3'
classpath 'org.asciidoctor:asciidoctorj-pdf:1.5.0-alpha.10.1'
classpath 'org.kt3k.gradle.plugin:coveralls-gradle-plugin:2.0.1'
classpath 'org.asciidoctor:asciidoctorj:1.5.2'
classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.2'
classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.6'
classpath "org.jfrog.buildinfo:build-info-extractor-gradle:4.0.0"
classpath "org.ajoberstar:gradle-git:1.3.2"
}
}
description = 'swagger2markup Build'
version = '0.6.3'
group = 'io.github.robwin'
version = '1.2.0-SNAPSHOT'
ext.releaseVersion = '1.1.1'
group = 'io.github.swagger2markup'
apply plugin: 'java'
apply plugin: 'maven-publish'
apply plugin: 'org.asciidoctor.convert'
apply plugin: 'jacoco'
apply plugin: 'com.github.kt3k.coveralls'
apply plugin: 'io.spring.dependency-management'
apply plugin: 'com.jfrog.bintray'
apply plugin: 'eclipse'
apply from: 'gradle/publishing.gradle'
apply from: 'gradle/coverage.gradle'
apply from: 'gradle/documentation.gradle'
tasks.withType(JavaCompile) {
sourceCompatibility = "1.7"
targetCompatibility = "1.7"
sourceCompatibility = "1.8"
targetCompatibility = "1.8"
options.deprecation = true
options.encoding = 'UTF-8'
options.compilerArgs << "-Xlint:unchecked"
}
repositories {
maven {
url "https://oss.jfrog.org/artifactory/oss-snapshot-local"
}
jcenter()
mavenCentral()
mavenLocal()
//mavenLocal()
}
dependencies {
compile 'io.github.robwin:markup-document-builder'
compile 'io.swagger:swagger-compat-spec-parser'
compile 'commons-collections:commons-collections'
compile 'commons-io:commons-io'
compile 'org.slf4j:slf4j-api'
testCompile 'junit:junit'
testCompile 'org.asciidoctor:asciidoctorj:1.5.2'
testCompile 'ch.qos.logback:logback-classic'
testCompile 'org.assertj:assertj-core'
compile 'io.github.swagger2markup:markup-document-builder:1.1.1-SNAPSHOT'
compile 'io.swagger:swagger-compat-spec-parser:1.0.23'
compile 'org.apache.commons:commons-configuration2:2.1'
compile 'commons-beanutils:commons-beanutils:1.9.2'
compile 'org.apache.commons:commons-collections4:4.1'
compile 'io.javaslang:javaslang:2.0.4'
compile 'ch.netzwerg:paleo-core:0.10.1'
testCompile 'junit:junit:4.11'
testCompile 'org.asciidoctor:asciidoctorj:1.5.4'
testCompile 'ch.qos.logback:logback-classic:1.1.2'
testCompile 'org.assertj:assertj-core:3.5.2'
testCompile 'io.github.robwin:assertj-diff:0.1.1'
}
dependencyManagement {
dependencies {
dependency "io.github.robwin:markup-document-builder:0.1.4"
dependency "io.swagger:swagger-compat-spec-parser:1.0.8"
dependency "commons-collections:commons-collections:3.2.1"
dependency "commons-io:commons-io:2.4"
dependency "junit:junit:4.11"
dependency "org.slf4j:slf4j-api:1.7.12"
dependency "ch.qos.logback:logback-classic:1.1.2"
dependency "org.assertj:assertj-core:2.0.0"
test {
if (System.properties['http.proxyHost']) {
systemProperty 'http.proxyHost', System.properties['http.proxyHost']
systemProperty 'http.proxyPort', System.properties['http.proxyPort']
systemProperty 'http.nonProxyHosts', System.properties['http.nonProxyHosts']
}
systemProperty 'file.encoding', 'UTF-8'
}
task sourcesJar(type: Jar, dependsOn: classes) {
classifier = 'sources'
from sourceSets.main.allSource
}
task javadocJar(type: Jar, dependsOn: javadoc) {
classifier = 'javadoc'
from javadoc.destinationDir
}
artifacts {
archives sourcesJar
archives javadocJar
}
ext {
generatedDocumentation = file('build/docs/asciidoc/generated')
}
asciidoctor {
dependsOn test
sources {
include 'index.adoc'
}
backends = ['html5', 'pdf']
attributes = [
doctype: 'book',
toc: 'left',
toclevels: '2',
numbered: '',
sectlinks: '',
sectanchors: '',
hardbreaks: '',
generated: generatedDocumentation
]
}
jacocoTestReport {
reports {
xml.enabled = true // coveralls plugin depends on xml format report
html.enabled = true
}
}
tasks.coveralls {
dependsOn 'check'
}
tasks.asciidoctor {
dependsOn 'check'
}
task wrapper(type: Wrapper) {
gradleVersion = '2.4'
gradleVersion = '3.1'
}

13
gradle/coverage.gradle Normal file
View File

@@ -0,0 +1,13 @@
apply plugin: 'jacoco'
apply plugin: 'com.github.kt3k.coveralls'
jacocoTestReport {
reports {
xml.enabled = true // coveralls plugin depends on xml format report
html.enabled = true
}
}
tasks.coveralls {
dependsOn 'check'
}

View File

@@ -0,0 +1,35 @@
apply plugin: 'org.asciidoctor.convert'
apply plugin: 'org.ajoberstar.github-pages'
asciidoctor {
sources {
include 'index.adoc'
}
backends = ['html5', 'pdf']
attributes = [
doctype: 'book',
toc: 'left',
toclevels: '3',
numbered: '',
sectlinks: '',
sectanchors: '',
hardbreaks: '',
'release-version': project.releaseVersion
]
}
publishGhPages.dependsOn asciidoctor
githubPages {
repoUri = 'https://github.com/Swagger2Markup/swagger2markup.git'
credentials {
username = project.hasProperty('githubUser') ? project.githubUser : System.getenv('GITHUB_USER')
password = project.hasProperty('githubPassword') ? project.githubPassword : System.getenv('GITHUB_PASSWORD')
}
pages {
from file(asciidoctor.outputDir.path + '/html5')
into project.releaseVersion
}
}

View File

@@ -1,24 +1,44 @@
import java.text.SimpleDateFormat
apply plugin: 'maven-publish'
apply plugin: 'com.jfrog.bintray'
apply plugin: "com.jfrog.artifactory"
Date buildTimeAndDate = new Date()
ext {
buildDate = new SimpleDateFormat('yyyy-MM-dd').format(buildTimeAndDate)
buildTime = new SimpleDateFormat('HH:mm:ss.SSSZ').format(buildTimeAndDate)
projectUrl = 'https://github.com/Swagger2Markup/swagger2markup'
licenseUrl = 'https://github.com/Swagger2Markup/swagger2markup/blob/master/LICENSE.txt'
scmUrl = 'https://github.com/Swagger2Markup/swagger2markup.git'
issuesUrl = 'https://github.com/Swagger2Markup/swagger2markup/issues'
}
def projectArtifactId = 'swagger2markup'
task sourcesJar(type: Jar, dependsOn: classes) {
classifier = 'sources'
from sourceSets.main.allSource
}
task javadocJar(type: Jar, dependsOn: javadoc) {
classifier = 'javadoc'
from javadoc.destinationDir
}
artifacts {
archives sourcesJar
archives javadocJar
}
jar {
manifest {
attributes(
'Built-By': 'Robert Winkler',
'Created-By': System.properties['java.version'] + " (" + System.properties['java.vendor'] + " " + System.properties['java.vm.version'] + ")",
'Build-Date': project.buildDate,
'Build-Time': project.buildTime,
'Specification-Title': projectArtifactId,
'Specification-Version': project.version,
'Implementation-Title': projectArtifactId,
'Implementation-Version': project.version
'Built-With': "gradle-${project.getGradle().getGradleVersion()}, groovy-${GroovySystem.getVersion()}",
'Build-Time': "${new Date().format("yyyy-MM-dd'T'HH:mm:ssZ")}",
'Specification-Title': "${project.name}",
'Specification-Version': project.version.toString(),
'Implementation-Title': "${project.name}",
'Implementation-Version': project.version.toString()
)
}
}
@@ -29,35 +49,6 @@ if (!project.hasProperty('gpgPassphrase')) ext.gpgPassphrase = ''
if (!project.hasProperty('ossUser')) ext.ossUser = ''
if (!project.hasProperty('ossPassword')) ext.ossPassword = ''
bintray {
user = project.bintrayUsername
key = project.bintrayApiKey
dryRun = false //Whether to run this as dry-run, without deploying
publish = true //If version should be auto published after an upload
publications = ['mavenJava']
pkg {
repo = 'maven'
name = 'swagger2markup'
websiteUrl = 'https://github.com/RobWin/swagger2markup'
issueTrackerUrl = 'https://github.com/RobWin/swagger2markup/issues'
vcsUrl = 'https://github.com/RobWin/swagger2markup.git'
desc = 'A Swagger to Markup (AsciiDoc and Markdown) converter.'
licenses = ['Apache-2.0']
version {
vcsTag = project.version
gpg {
sign = true //Determines whether to GPG sign the files. The default is false
passphrase = project.gpgPassphrase //Optional. The passphrase for GPG signing'
}
mavenCentralSync {
sync = true //Optional (true by default). Determines whether to sync the version to Maven Central.
user = ossUser //OSS user token
password = ossPassword //OSS user password
}
}
}
}
publishing {
publications {
mavenJava(MavenPublication) {
@@ -74,17 +65,17 @@ publishing {
it.scope*.value = 'compile'
}
root.appendNode('name', 'swagger2markup')
root.appendNode('name', project.name)
root.appendNode('packaging', 'jar')
root.appendNode('url', 'https://github.com/RobWin/swagger2markup')
root.appendNode('description', 'A Swagger to Markup (AsciiDoc and Markdown) converter.')
root.appendNode('url', projectUrl)
root.appendNode('description', project.description)
def license = root.appendNode('licenses').appendNode('license')
license.appendNode('name', 'Apache-2.0')
license.appendNode('url', 'https://github.com/RobWin/swagger2markup/blob/master/LICENSE.txt')
license.appendNode('url', licenseUrl)
license.appendNode('distribution', 'repo')
root.appendNode('scm').appendNode('url', 'https://github.com/RobWin/swagger2markup.git')
root.appendNode('scm').appendNode('url', scmUrl)
def developers = root.appendNode('developers')
devs.each {
@@ -98,3 +89,63 @@ publishing {
}
}
}
bintray {
user = project.bintrayUsername
key = project.bintrayApiKey
dryRun = false //Whether to run this as dry-run, without deploying
publish = true //If version should be auto published after an upload
publications = ['mavenJava']
pkg {
repo = 'Maven'
name = 'swagger2markup'
userOrg = 'swagger2markup'
websiteUrl = projectUrl
issueTrackerUrl = issuesUrl
vcsUrl = scmUrl
desc = rootProject.description
licenses = ['Apache-2.0']
version {
vcsTag = rootProject.version
gpg {
sign = true //Determines whether to GPG sign the files. The default is false
passphrase = project.gpgPassphrase //Optional. The passphrase for GPG signing'
}
mavenCentralSync {
sync = true //Optional (true by default). Determines whether to sync the version to Maven Central.
user = ossUser //OSS user token
password = ossPassword //OSS user password
}
}
}
}
artifactory {
contextUrl = 'https://oss.jfrog.org'
resolve {
repository {
repoKey = 'libs-release'
}
}
publish {
repository {
repoKey = 'oss-snapshot-local' //The Artifactory repository key to publish to
//when using oss.jfrog.org the credentials are from Bintray. For local build we expect them to be found in
//~/.gradle/gradle.properties, otherwise to be set in the build server
username = project.hasProperty('bintrayUsername') ? project.bintrayUsername : System.getenv('BINTRAY_USER')
password = project.hasProperty('bintrayApiKey') ? project.bintrayApiKey : System.getenv('BINTRAY_KEY')
}
defaults {
publications('mavenJava')
}
}
if (System.properties['https.proxyHost']) {
clientConfig.proxy.host = System.properties['https.proxyHost']
clientConfig.proxy.port = System.properties['https.proxyPort'].toInteger()
}
}
tasks.artifactoryPublish {
dependsOn 'check'
}

Binary file not shown.

View File

@@ -1,6 +1,6 @@
#Mon Jun 08 08:20:09 CEST 2015
#Thu Nov 03 09:37:13 CET 2016
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.4-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-3.1-all.zip

10
gradlew vendored Normal file → Executable file
View File

@@ -42,11 +42,6 @@ case "`uname`" in
;;
esac
# For Cygwin, ensure paths are in UNIX format before anything is touched.
if $cygwin ; then
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
fi
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
@@ -61,9 +56,9 @@ while [ -h "$PRG" ] ; do
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >&-
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >&-
cd "$SAVED" >/dev/null
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
@@ -114,6 +109,7 @@ fi
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`

2
gradlew.bat vendored
View File

@@ -46,7 +46,7 @@ echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windowz variants
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 138 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

View File

@@ -0,0 +1,94 @@
== Advanced usage
[[swagger_operationId]]
=== Swagger operationId
Swagger2Markup uniquely identify each operations for multiple purposes :
* generating separated operation files : file name
* generating unique Markup anchors for operations and all sub-items.
* searching for extra content for operations : operation folder name for content plugins (Hand-written descriptions, Dynamic content, etc...)
* ...
Swagger specification supports the `operationId` field which create an unique name for each operation.
When provided, this `operationId` value will be used primarily. Otherwise Swagger2Markup generates an id using `normalize(operation.summary + " " + lowerCase(operation.HTTPmethod))`.
IMPORTANT: It is highly recommended to set an operationId for each operation, so that a lot of actions does not depend on operation `summary` which *can change at anytime*.
=== Swagger schema title
Swagger2Markup displays inline schemas by decomposing them (when schema is complex). In this process, some intermediate references are generated using field names which is not always the best choice.
The Swagger document supports JSON Schema `title` items in inline schemas.
It's recommended to use them in inline schemas so that they'll be used primarily to field names and this will lead to a better naming.
.Inline schema without title items
====
[source,yaml,subs="quotes"]
----
InlinePet:
type: object
required:
- id
properties:
id:
type: integer
format: int64
category:
type: object
properties:
id:
type: integer
format: int64
name:
type: string
tags:
type: array
items:
type: object
properties:
id:
type: integer
format: int64
name:
type: string
----
image::images/untitledSwagger.png[]
====
.Inline schema with title items
====
[source,yaml,subs="quotes"]
----
InlineTitlePet:
type: object
required:
- id
properties:
id:
type: integer
format: int64
category:
type: object
*title: CategoryModel*
properties:
id:
type: integer
format: int64
name:
type: string
tags:
type: array
items:
type: object
*title: TagModel*
properties:
id:
type: integer
format: int64
name:
type: string
----
image::images/titledSwagger.png[]
====

View File

@@ -0,0 +1,103 @@
== Command Line Interface
Swagger2Markup provides a Command line interface (CLI). The CLI is published in JCenter and Maven Central. The artifacts can be viewed at the following locations:
* Releases: https://jcenter.bintray.com/io/github/swagger2markup/swagger2markup-cli/
* Snapshots: https://oss.jfrog.org/artifactory/oss-snapshot-local/io/github/swagger2markup/swagger2markup-cli/
NOTE: The CLI requires at least JDK 8.
=== Usage guide
==== Show help
You can show the help:
[source, subs="attributes"]
----
java -jar swagger2markup-cli-{release-version}.jar help convert
----
Output:
----
NAME
swagger2markup convert - Converts a Swagger JSON or YAML file into
Markup documents.
SYNOPSIS
swagger2markup convert [(-c <configFile> | --config <configFile>)]
[(-d <outputDir> | --outputDir <outputDir>)]
[(-f <outputFile> | --outputFile <outputFile>)]
(-i <swaggerInput> | --swaggerInput <swaggerInput>)
OPTIONS
-c <configFile>, --config <configFile>
Config file.
-d <outputDir>, --outputDir <outputDir>
Output directory. Converts the Swagger specification into multiple
files.
-f <outputFile>, --outputFile <outputFile>
Output file. Converts the Swagger specification into one file.
-h, --help
Display help information
-i <swaggerInput>, --swaggerInput <swaggerInput>
Swagger input. Can either be a URL or a file path.
----
==== Conversion into a folder
You can convert a Swagger file into a folder as follows:
[source, subs="attributes"]
----
java -jar swagger2markup-cli-{release-version}.jar convert -i /path/to/swagger_petstore.yaml -d /tmp/asiidoc
----
It generates the Markup documents into the `/tmp/asiidoc` folder.
==== Conversion into a file
You can convert a local Swagger file into a file as follows:
[source, subs="attributes"]
----
java -jar swagger2markup-cli-{release-version}.jar convert -i /path/to/swagger_petstore.yaml -f /tmp/asiidoc/swagger
----
NOTE: The input file must not have a file extension
It generates the Markup documents into the file `/tmp/asiidoc/swagger.adoc`.
==== Conversion of a remote Swagger file
You can convert a remote Swagger specification which must be accessible via HTTP.
[source, subs="attributes"]
----
java -jar swagger2markup-cli-{release-version}.jar convert -i "http://petstore.swagger.io/v2/swagger.json" -d /tmp
----
=== Configuration
Create a `config.properties` file to customize the <<Swagger2Markup properties>>. For Example:
.config.properties
----
swagger2markup.markupLanguage=MARKDOWN
swagger2markup.outputLanguage=DE
----
Invoke the CLI as follows:
[source, subs="attributes"]
----
java -jar swagger2markup-cli-{release-version}.jar convert -i /path/to/swagger_petstore.yaml -o /tmp -c /path/to/config.properties
----

View File

@@ -0,0 +1,10 @@
== Contributing
=== Questions
You can ask questions about Swagger2Markup in https://gitter.im/Swagger2Markup/swagger2markup[Gitter].
=== Bugs
If you believe you have found a bug, please take a moment to search the existing issues. If no one else has reported the problem, please open a new issue that describes the problem in detail and, ideally, includes a test that reproduces it.
=== Enhancements
If youd like an enhancement to be made to Swagger2Markup, pull requests are most welcome. The source code is on GitHub. You may want to search the existing issues and pull requests to see if the enhancement is already being worked on. You may also want to open a new issue to discuss a possible enhancement before work on it begins.

View File

@@ -1,5 +0,0 @@
This is a hand-written description.
AsciiDoc is better suited for descriptions than:
* JavaDoc
* Annotations

View File

@@ -1 +0,0 @@
This is a hand-written description. AsciiDoc is better suited for descriptions than *JavaDoc* and *Annotations*

View File

@@ -1 +0,0 @@
This is a hand-written description. AsciiDoc is better suited for descriptions than *JavaDoc* and *Annotations*

View File

@@ -0,0 +1,82 @@
== Spring Boot and Springfox
If you use Spring Boot and Springfox or Swagger JAX-RS, you can do the following:
* generate an up-to-date Swagger JSON file during an unit or integration test
* convert the Swagger JSON file into AsciiDoc
* add hand-written AsciiDoc documentation
* convert AsciiDoc into HTML and PDF
* copy the HTML and PDF artifacts into an executable Spring Boot Jar file and serve it as static content
This transformation pipeline can be done with Gradle or Maven in the build phase. That way there is no runtime overhead and there are no additional runtime libraries required.
The Swagger2MarkupConverter can be used to make a request to a remote Swagger endpoint during an integration test. The Swagger2MarkupConverter allows to write the generated documents into any folder. In this this example it is ``src/docs/asciidoc/generated``.
[source,java]
----
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = {Application.class, SwaggerConfig.class})
@WebIntegrationTest
public class Swagger2MarkupTest {
@Test
public void convertRemoteSwaggerToAsciiDoc() {
// Remote Swagger source
Swagger2MarkupConverter.from(new URL("http://localhost:8080/v2/api-docs")).build()
.toFolder(Paths.get("src/docs/asciidoc/generated"));
}
}
----
Spring's MVC Test framework can also be used to make a request to a Springfox Swagger endpoint during an unit test. A custom ResultHandler ``Swagger2MarkupResultHandler`` can be used to write the Swagger JSON response into a directory. The custom ResultHandler is part of ``springfox-staticdocs``. That way you also verify that your Swagger endpoint is working.
The Swagger JSON response can be converted using the <<Gradle Plugin>> or <<Maven Plugin>>.
[source,java]
----
@WebAppConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = {Application.class, SwaggerConfig.class})
public class Swagger2MarkupTest {
@Autowired
private WebApplicationContext context;
private MockMvc mockMvc;
@Before
public void setUp() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context).build();
}
@Test
public void convertSwaggerToAsciiDoc() throws Exception {
this.mockMvc.perform(get("/v2/api-docs")
.accept(MediaType.APPLICATION_JSON))
.andDo(Swagger2MarkupResultHandler
.outputDirectory("src/docs/asciidoc/generated").build())
.andExpect(status().isOk());
}
}
----
=== Demo
The quickest way to get started is to look at the demo project https://github.com/Swagger2Markup/spring-swagger2markup-demo[spring-swagger2markup-demo]. The demo shows how to generate static docs (HTML5 and PDF) by using the Swagger2Markup Gradle Plugin and serve the generated documentation as static content in a Spring Boot App under http://localhost:9080/docs/index.html and http://localhost:9080/docs/index.pdf.
If you want to start the Spring Boot application, please run:
[source, java, subs="attributes"]
----
gradlew clean build
----
----
java -jar build/libs/spring-swagger2markup-demo-{project-version}.jar
----
If you only want to generate the HTML and PDF documentation, please run:
----
gradlew clean asciidoctor
----

View File

@@ -0,0 +1,13 @@
== Docker image
The Swagger2Markup-CLI has been published as a Docker image on DockerHub.
=== Usage guide
You can pull the Swagger2Markup image as follows:
`docker pull swagger2markup/swagger2markup`
You can convert a Swagger Spec by running a Docker container as follows:
`docker run --rm -v $(pwd):/opt swagger2markup/swagger2markup convert -i /opt/swagger.yaml -f /opt/swagger -c /opt/config.properties`

View File

@@ -0,0 +1,187 @@
== Extension SPI
Swagger2Markup provides an Extension SPI to extend the functionality of Swagger2Markup. Five types of extension are available. An extension is an abstract class which must be implemented.
[options="header"]
.Swagger2Markup extensions
|====
| Name | Class | Description
| <<OverviewDocumentExtension>> | io.github.swagger2markup.spi.OverviewDocumentExtension | Can be used to extend the content of the Overview document
| <<PathsDocumentExtension>> | io.github.swagger2markup.spi.PathsDocumentExtension | Can be used to extend the content of the Paths document
| <<SecurityDocumentExtension>> | io.github.swagger2markup.spi.SecurityDocumentExtension | Can be used to extend the content of the Security document
| <<DefinitionsDocumentExtension>> | io.github.swagger2markup.spi.DefinitionsDocumentExtension | Can be used to extend the content of the Definitions document
| <<SwaggerModelExtension>> | io.github.swagger2markup.spi.SwaggerModelExtension | Can be used to modify the Swagger model before it is converted
|====
=== Creation of an extension
To create a custom extension, you have to create a class (e.g. `io.myname.MyExtension`) which extends an extension, e.g. `io.github.swagger2markup.spi.DefinitionsDocumentExtension`. Every extension point provides two methods which must be implemented:
* `init`: This method is invoked once and can be used to initialize the extension.
* `apply`: This method is invoked multiple times depending on the type of the extension. The `Position` can be retrieved from the `Context` and can be used to extend the document at specific extension points.
[source,java,indent=0]
----
include::../../test/java/io/github/swagger2markup/builder/MyExtension.java[tags=MyExtension]
----
1. You can retrieve extension properties from the config to configure the extension.
2. You can retrieve a `MarkupDocBuilder` from the `Context`.
3. You can retrieve the current `Position` from the Context.
4. You can use a `MarkupDocBuilder` to add Markup using a fluent API or import Markup from files.
=== Registration of an extension
Swagger2Markup extensions must be registered in the `Swagger2MarkupExtensionRegistry`. The default `Swagger2MarkupExtensionRegistry` of Swagger2Markup uses the `java.util.ServiceLoader` to load and register Swagger2Markup extensions automatically.
==== Automatic registration
To register your extension automatically, the following steps are required:
* Create a file called `META-INF/services/io.github.swagger2markup.spi.DefinitionsDocumentExtension` which contains your extensionss full qualified name, e.g. `io.myname.MyExtension`.
* When a `.jar` file containing your extension is added to the classpath of Swagger2Markup, the extensions will be automatically registered.
==== Manual registration
To register your extension manually, you have to use the `Swagger2MarkupExtensionRegistryBuilder`.
[source,java,indent=0]
----
include::../../test/java/io/github/swagger2markup/DocumentationTest.java[tags=swagger2MarkupExtensionRegistryBuilder]
----
1. Create a ``Swagger2MarkupExtensionRegistryBuilder`` using the default constructor
2. Register your custom extension
3. Build an instance of `Swagger2MarkupExtensionRegistry`
4. Use the custom Swagger2MarkupExtensionRegistry
=== Extensions points
==== OverviewDocumentExtension
The OverviewDocumentExtension allows to extend the overview document at positions :
* DOCUMENT_BEFORE: Before the document title (title level offset = 0)
* DOCUMENT_BEGIN: After the document title (title level offset = 1)
* DOCUMENT_END: At the end of the document (title level offset = 1)
* DOCUMENT_AFTER: At the very end of the document (title level offset = 0)
NOTE: Extension content titles must always start from level *1*. The title level will be adapted depending on position.
==== PathsDocumentExtension
The PathsDocumentExtension allows to extend the paths document at positions :
* DOCUMENT_BEFORE: Before the document title (title level offset = 0)
* DOCUMENT_BEGIN: After the document title (title level offset = 1)
* OPERATION_BEFORE: Before each operation title (title level offset = 1)
* OPERATION_BEGIN: After each operation title (title level offset = 2)
* OPERATION_END: At the end of each operation (title level offset = 2)
* OPERATION_AFTER: At the very end of each operation (title level offset = 1)
* DOCUMENT_END: At the end of the document (title level offset = 1)
* DOCUMENT_AFTER: At the very end of the document (title level offset = 0)
Moreover, the PathsDocumentExtension allows to extend operation sections at positions :
* OPERATION_DESCRIPTION_BEFORE: Before each description section title (title level offset = 2)
* OPERATION_DESCRIPTION_BEGIN: After each description section title (title level offset = 3)
* OPERATION_DESCRIPTION_END: At the end of each description section (title level offset = 3)
* OPERATION_DESCRIPTION_AFTER: At the very end of each description section (title level offset = 2)
* OPERATION_PARAMETERS_BEFORE: Before each parameters section title (title level offset = 2)
* OPERATION_PARAMETERS_BEGIN: After each parameters section title (title level offset = 3)
* OPERATION_PARAMETERS_END: At the end of each parameters section (title level offset = 3)
* OPERATION_PARAMETERS_AFTER: At the very end of each parameters section (title level offset = 2)
* OPERATION_RESPONSES_BEFORE: Before each responses section title (title level offset = 2)
* OPERATION_RESPONSES_BEGIN: After each responses section title (title level offset = 3)
* OPERATION_RESPONSES_END: At the end of each responses section (title level offset = 3)
* OPERATION_RESPONSES_AFTER: At the very end of each responses section (title level offset = 2)
* OPERATION_SECURITY_BEFORE: Before each security section title (title level offset = 2)
* OPERATION_SECURITY_BEGIN: After each security section title (title level offset = 3)
* OPERATION_SECURITY_END: At the end of each security section (title level offset = 3)
* OPERATION_SECURITY_AFTER: At the very end of each security section (title level offset = 2)
NOTE: Extension content titles must always start from level *1*. The title level will be adapted depending on position.
==== SecurityDocumentExtension
The SecurityDocumentExtension allows to extend the security document at positions :
* DOCUMENT_BEFORE: Before the document title (title level offset = 0)
* DOCUMENT_BEGIN: After the document title (title level offset = 1)
* SECURITY_SCHEME_BEFORE: Before each security scheme title (title level offset = 1)
* SECURITY_SCHEME_BEGIN: After each security scheme title (title level offset = 2)
* SECURITY_SCHEME_END: At the end of each security scheme (title level offset = 2)
* SECURITY_SCHEME_AFTER: At the very end of each security scheme (title level offset = 1)
* DOCUMENT_END: At the end of the document (title level offset = 1)
* DOCUMENT_AFTER: At the very end of the document (title level offset = 0)
NOTE: Extension content titles must always start from level *1*. The title level will be adapted depending on position.
==== DefinitionsDocumentExtension
The DefinitionsDocumentExtension allows to extend the definitions document at positions :
* DOCUMENT_BEFORE: Before the document title (title level offset = 0)
* DOCUMENT_BEGIN: After the document title (title level offset = 1)
* DEFINITION_BEFORE: Before each definition title (title level offset = 1)
* DEFINITION_BEGIN: After each definition title (title level offset = 2)
* DEFINITION_END: At the end of each definition (title level offset = 2)
* DEFINITION_AFTER: At the very end of each definition (title level offset = 1)
* DOCUMENT_END: At the end of the document (title level offset = 1)
* DOCUMENT_AFTER: At the very end of the document (title level offset = 0)
NOTE: Extension content titles must always start from level *1*. The title level will be adapted depending on position.
==== SwaggerModelExtension
The SwaggerModelExtension allows to modify the Swagger model before it is processed by Swagger2Markup. For example, you could use this extension to delete Paths from the Swagger model which should not be rendered.
Example:
[source,java,indent=0]
----
include::../../test/java/io/github/swagger2markup/builder/MySwaggerModelExtension.java[tags=MySwaggerModelExtension]
----
1. You can change any Swagger model property
2. You could even remove elements from the Swagger model
[[extension_commons_content_markup]]
=== Content markup language
Most content extensions supports to provide content in any markup language which will be *converted, if needed, to configured Swagger2Markup converter markup language* at import.
The content files markup language can be any https://github.com/Swagger2Markup/markup-document-builder[markup-document-builder] supported language :
* ASCIIDOC : AsciiDoc. Mandatory content file extension : `adoc`
* MARKDOWN : Github Flavored Markdown. Mandatory content file extension : `md`
* CONFLUENCE_MARKUP : Confluence Wiki markup. Mandatory content file extension : `txt`
[IMPORTANT]
====
Currently supported conversions are :
* Markdown -> AsciiDoc
====
=== Provided Extensions
Swagger2Markup provides some extensions which can be used out-of-the-box. You just have to add the extension to your classpath.
[options="header"]
.Swagger2Markup extensions
|====
| Name | Description
| <<extension_import_files,Dynamic file import extension>> | Allows to dynamically import Markup from files.
| <<extension_spring_restdocs,Spring RestDocs extension>> | Allows to import Curl, HTTP request and response snippets from https://github.com/spring-projects/spring-restdocs[Spring Rest Docs].
| <<extension_import_schemas,Schema file import extension>> | Allows to import JSON or XML Schema files.
|====
include::extensions/import_files.adoc[leveloffset=+2]
include::extensions/spring_restdocs.adoc[leveloffset=+2]
include::extensions/import_schemas.adoc[leveloffset=+2]

View File

@@ -0,0 +1,117 @@
[[extension_import_files]]
== Dynamic file import extension
=== Usage guide
[source,groovy, subs="attributes"]
----
repositories {
jCenter()
}
compile "io.github.swagger2markup:swagger2markup-import-files-ext:{project-version}"
----
The extension searches for markup files in configurable paths to append the markup to the documents at supported positions.
The markup files must conform to a naming convention to be found. The files must start with the position where the document should be extended and end with the markup file extension (e.g `adoc` or `md`).
See documentation of <<Extensions points>>.
Here the list of all document naming conventions for each position. You have to replace `*` with an arbitrary, meaningful, identifier.
NOTE: You can provide multiple contents for the same position, just specify different identifiers in place of `*` in the file name. The concurrent contents for a given position will all be added to the document in a determinist order, sorting content file by natural order.
All extensions, relatively to each extension contentPath :
* DOCUMENT_BEFORE : `document-before-*.<<extension_import_files_markup,<markup.ext> >>`
* DOCUMENT_BEGIN : `document-begin-*.<<extension_import_files_markup,<markup.ext> >>`
* DOCUMENT_END : `document-end-*.<<extension_import_files_markup,<markup.ext> >>`
* DOCUMENT_AFTER : `document-after-*.<<extension_import_files_markup,<markup.ext> >>`
Paths extensions, relatively to each extension contentPath :
* OPERATION_BEFORE : `<<swagger_operationId,<operationId> >>/operation-before-*.<<extension_import_files_markup,<markup.ext> >>`
* OPERATION_BEGIN : `<<swagger_operationId,<operationId> >>/operation-begin-*.<<extension_import_files_markup,<markup.ext> >>`
* OPERATION_END : `<<swagger_operationId,<operationId> >>/operation-end-*.<<extension_import_files_markup,<markup.ext> >>`
* OPERATION_AFTER : `<<swagger_operationId,<operationId> >>/operation-after-*.<<extension_import_files_markup,<markup.ext> >>`
* OPERATION_DESCRIPTION_BEFORE: `<<swagger_operationId,<operationId> >>/operation-description-before-*.<<extension_import_files_markup,<markup.ext> >>`
* OPERATION_DESCRIPTION_BEGIN: `<<swagger_operationId,<operationId> >>/operation-description-begin-*.<<extension_import_files_markup,<markup.ext> >>`
* OPERATION_DESCRIPTION_END: `<<swagger_operationId,<operationId> >>/operation-description-end-*.<<extension_import_files_markup,<markup.ext> >>`
* OPERATION_DESCRIPTION_AFTER: `<<swagger_operationId,<operationId> >>/operation-description-after-*.<<extension_import_files_markup,<markup.ext> >>`
* OPERATION_PARAMETERS_BEFORE: `<<swagger_operationId,<operationId> >>/operation-parameters-before-*.<<extension_import_files_markup,<markup.ext> >>`
* OPERATION_PARAMETERS_BEGIN: `<<swagger_operationId,<operationId> >>/operation-parameters-begin-*.<<extension_import_files_markup,<markup.ext> >>`
* OPERATION_PARAMETERS_END: `<<swagger_operationId,<operationId> >>/operation-parameters-end-*.<<extension_import_files_markup,<markup.ext> >>`
* OPERATION_PARAMETERS_AFTER: `<<swagger_operationId,<operationId> >>/operation-parameters-after-*.<<extension_import_files_markup,<markup.ext> >>`
* OPERATION_RESPONSES_BEFORE: `<<swagger_operationId,<operationId> >>/operation-responses-before-*.<<extension_import_files_markup,<markup.ext> >>`
* OPERATION_RESPONSES_BEGIN: `<<swagger_operationId,<operationId> >>/operation-responses-begin-*.<<extension_import_files_markup,<markup.ext> >>`
* OPERATION_RESPONSES_END: `<<swagger_operationId,<operationId> >>/operation-responses-end-*.<<extension_import_files_markup,<markup.ext> >>`
* OPERATION_RESPONSES_AFTER: `<<swagger_operationId,<operationId> >>/operation-responses-after-*.<<extension_import_files_markup,<markup.ext> >>`
* OPERATION_SECURITY_BEFORE: `<<swagger_operationId,<operationId> >>/operation-security-before-*.<<extension_import_files_markup,<markup.ext> >>`
* OPERATION_SECURITY_BEGIN: `<<swagger_operationId,<operationId> >>/operation-security-begin*.<<extension_import_files_markup,<markup.ext> >>`
* OPERATION_SECURITY_END: `<<swagger_operationId,<operationId> >>/operation-security-end-*.<<extension_import_files_markup,<markup.ext> >>`
* OPERATION_SECURITY_AFTER: `<<swagger_operationId,<operationId> >>/operation-security-after-*.<<extension_import_files_markup,<markup.ext> >>`
Definitions extensions, relatively to each extension contentPath :
* DEFINITION_BEFORE : `<definitionName>/definition-before-*.<<extension_import_files_markup,<markup.ext> >>`
* DEFINITION_BEGIN : `<definitionName>/definition-begin-*.<<extension_import_files_markup,<markup.ext> >>`
* DEFINITION_END : `<definitionName>/definition-end-*.<<extension_import_files_markup,<markup.ext> >>`
* DEFINITION_AFTER : `<definitionName>/definition-after-*.<<extension_import_files_markup,<markup.ext> >>`
Security extensions, relatively to each extension contentPath :
* SECURITY_SCHEME_BEFORE : `<securitySchemeName>/security-scheme-before-*.<<extension_import_files_markup,<markup.ext> >>`
* SECURITY_SCHEME_BEGIN : `<securitySchemeName>/security-scheme-begin-*.<<extension_import_files_markup,<markup.ext> >>`
* SECURITY_SCHEME_END : `<securitySchemeName>/security-scheme-end-*.<<extension_import_files_markup,<markup.ext> >>`
* SECURITY_SCHEME_AFTER : `<securitySchemeName>/security-scheme-after-*.<<extension_import_files_markup,<markup.ext> >>`
IMPORTANT: `<operationId>` value depends on Swagger specification. If you provided an `operationId` for operations in the Swagger document, the value will be used primarily. *It is highly recommended to set operationId for operations* : see <<swagger_operationId,Swagger operationId>>. In all cases, all placeholder values are case-sensitive.
NOTE: It's *highly recommended* to configure a different contentPath for each extension (dynamicOverview, dynamicDefinitions, etc...) because content files for DOCUMENT_* positions have the same naming convention.
.Example of provided content files for petstore Swagger sample
====
....
overview/document-before-intro.adoc <1>
paths/document-before-intro.adoc <2>
paths/updatePet/operation-begin-description.adoc
paths/updatePet/operation-end-example1.adoc
paths/updatePet/operation-end-example2.adoc <3>
definitions/Pet/definition-begin-description.adoc
....
1. "overview", "paths" and "definitions" are different configured contentPath for different extensions.
2. the document name is the same but will be used only in Paths document because contentPath is different (cf 1.).
3. both example1 and example2 content files will be added to "updatePet" operation. They'll be applied consecutively, with their names sorted by natural order.
====
[[extension_import_files_markup]]
=== Content markup language
See <<extension_commons_content_markup,Extensions content markup language>>
By default, the markup language is set to *ASCIIDOC*. Set extension <<extension_import_files_configuration,Configuration>> to change content markup language.
[[extension_import_files_configuration]]
=== Configuration
The extension adds the following properties to Swagger2Markup which must be configured:
[options="header"]
.Extension properties
|====
| Name | Description | Default | Example
| `swagger2markup.extensions.dynamicOverview.contentPath` | The path to the files which should be imported | - | `src/test/resources/docs/asciidoc/overview`
| `swagger2markup.extensions.dynamicOverview.markupLanguage` | The markup language of the content files | `ASCIIDOC` | `MARKDOWN`
| `swagger2markup.extensions.dynamicDefinitions.contentPath` | The path to the files which should be imported | - | `src/test/resources/docs/asciidoc/definitions`
| `swagger2markup.extensions.dynamicDefinitions.markupLanguage` | The markup language of the content files | `ASCIIDOC` | `MARKDOWN`
| `swagger2markup.extensions.dynamicPaths.contentPath` | The path to the files which should be imported | - | `src/test/resources/docs/asciidoc/paths`
| `swagger2markup.extensions.dynamicPaths.markupLanguage` | The markup language of the content files | `ASCIIDOC` | `MARKDOWN`
| `swagger2markup.extensions.dynamicSecurity.contentPath` | TThe path to the files which should be imported | - | `src/test/resources/docs/asciidoc/security`
| `swagger2markup.extensions.dynamicSecurity.markupLanguage` | The markup language of the content files | `ASCIIDOC` | `MARKDOWN`
|====

View File

@@ -0,0 +1,29 @@
[[extension_import_schemas]]
== Schema file import extension
=== Usage guide
[source,groovy, subs="attributes"]
----
repositories {
jCenter()
}
compile "io.github.swagger2markup:swagger2markup-import-schemas-ext:{project-version}"
----
The extension searches for Schema files in a configurable path to append the Schema file content at the end of a definition section. The Schema files must conform to a naming convention to be found. The files must be called `schema.xsd` or `schema.json` and must be stored in a folder which matches the name of a definition.
Example: `/schemas/Pet/schema.json`.
=== Configuration
The extension adds the following properties to Swagger2Markup which must be configured:
[options="header"]
.Extension properties
|====
| Name | Description | Example
| `swagger2markup.extensions.schema.schemaBaseUri` | The path to the schema files | `src/test/resources/docs/asciidoc/schemas`
|====

View File

@@ -0,0 +1,74 @@
[[extension_spring_restdocs]]
== Spring RestDocs extension
Swagger2Markup can be used together with https://github.com/spring-projects/spring-restdocs[spring-restdocs]. Swagger2Markup can include the generated CURL request, HTTP request and HTTP response example snippets from spring-restdocs into the generated Markup documents. See spring-restdocs how to configure it.
=== Usage guide
[source,groovy,subs="attributes"]
----
repositories {
jCenter()
}
compile "io.github.swagger2markup:swagger2markup-spring-restdocs-ext:{project-version}"
----
The extension searches for https://github.com/spring-projects/spring-restdocs[Spring RestDocs] snippet files in a configurable path to append the snippets at the end of a path operation section. By default the following snippets are searched :
* `<<swagger_operationId,<operationId> >>/http-request.<<extension_spring_restdocs_markup,<markup.ext> >>`
* `<<swagger_operationId,<operationId> >>/http-response.<<extension_spring_restdocs_markup,<markup.ext> >>`
* `<<swagger_operationId,<operationId> >>/curl-request.<<extension_spring_restdocs_markup,<markup.ext> >>`
IMPORTANT: `<operationId>` value depends on Swagger specification. If you provided an `operationId` for operations in the Swagger document, the value will be used primarily. *It is highly recommended to set operationId for operations* : see <<swagger_operationId,Swagger operationId>>. In all cases, `<operationId>` is case-sensitive.
Swagger Example:
[source,yaml]
----
paths:
/pets:
post:
summary: Add a new pet to the store
operationId: addPet
...
----
The following Unit Test uses Spring RestDocs to tests the `/pets` endoint and writes the example files into the ``build/snippets`` folder. Have a look at the <<Spring Boot and Springfox>> chapter for a full example using https://github.com/spring-projects/spring-boot[Spring Boot], https://github.com/springfox/springfox[Springfox] and Spring RestDocs.
[source,java]
----
@Rule
public final RestDocumentation restDocumentation = new RestDocumentation("build/snippets");
@Test
public void addAPetToTheStore() throws Exception {
this.mockMvc.perform(post("/pets/").content(createPet())
.contentType(MediaType.APPLICATION_JSON))
.andDo(document("addPet", preprocessResponse(prettyPrint())))
.andExpect(status().isOk());
}
----
Example: `build/snippets/addPet/http-request.adoc`.
[[extension_spring_restdocs_markup]]
=== Content markup language
See <<extension_commons_content_markup,Extensions content markup language>>
By default, the markup language is set to *ASCIIDOC*. Set extension <<extension_spring_restdocs_configuration,Configuration>> to change content markup language.
[[extension_spring_restdocs_configuration]]
=== Configuration
The extension adds the following properties to Swagger2Markup which must be configured:
[options="header"]
.Extension properties
|====
| Name | Description | Default | Example
| `swagger2markup.extensions.springRestDocs.snippetBaseUri` | The path to the Spring RestDocs snippets | - | `src/test/resources/docs/asciidoc/paths`
| `swagger2markup.extensions.springRestDocs.markupLanguage` | The markup language of the content files | `ASCIIDOC` | `MARKDOWN`
| `swagger2markup.extensions.springRestDocs.defaultSnippets` | Boolean value. Set to false to disable default snippet files | `true` | `false`
|====

View File

@@ -0,0 +1,71 @@
== Getting started
Swagger2Markup is a standard .jar file. To start using it, you need to add the library to your projects classpath. Swagger2Markup is published in JCenter and Maven Central. The artifacts can be viewed at the following locations:
* Releases: https://jcenter.bintray.com/io/github/swagger2markup/swagger2markup/
* Snapshots: https://oss.jfrog.org/simple/oss-snapshot-local/io/github/swagger2markup/swagger2markup/
If you use Gradle or Maven, you can include Swagger2Markup as follows.
WARNING: The *groupId* has been changed from *io.github.robwin* to *io.github.swagger2markup*
=== Gradle
==== Release
[source,groovy, subs="attributes"]
----
repositories {
jCenter()
}
compile "io.github.swagger2markup:swagger2markup:{release-version}"
----
==== Snapshot
[source,groovy]
----
repositories {
maven { url 'http://oss.jfrog.org/artifactory/oss-snapshot-local/' }
}
----
=== Maven
==== Release
[source,xml, subs="specialcharacters,attributes"]
----
<repositories>
<repository>
<snapshots>
<enabled>false</enabled>
</snapshots>
<id>jcenter-releases</id>
<name>jcenter</name>
<url>http://jcenter.bintray.com</url>
</repository>
</repositories>
<dependency>
<groupId>io.github.swagger2markup</groupId>
<artifactId>swagger2markup</artifactId>
<version>{release-version}</version>
</dependency>
----
==== Snapshot
[source,java]
----
<repositories>
<repository>
<id>jcenter-snapshots</id>
<name>jcenter</name>
<url>http://oss.jfrog.org/artifactory/oss-snapshot-local/</url>
</repository>
</repositories>
----

View File

@@ -0,0 +1,62 @@
== Gradle Plugin
Swagger2Markup provides a Gradle plugin. The Gradle plugin is published in JCenter and Maven Central.
NOTE: The Gradle Plugin requires at least JDK 8.
=== Usage guide
Add the following snippet to your Gradle build file:
[source,java]
[source,groovy, subs="attributes"]
----
buildscript {
repositories {
jcenter()
maven { url 'http://oss.jfrog.org/artifactory/oss-snapshot-local/' }
}
dependencies {
classpath 'io.github.swagger2markup:swagger2markup-gradle-plugin:{release-version}'
}
}
apply plugin: 'io.github.swagger2markup'
----
The plugin adds a new task named ``convertSwagger2markup``. You can run the task as follows:
`gradlew convertSwagger2markup`
=== Configuration
You can customize the task by configuring a Map of <<Swagger2Markup properties>>.
[source,groovy]
----
convertSwagger2markup {
swaggerInput file("src/docs/swagger/swagger_petstore.yaml").getAbsolutePath()
outputDir file("${buildDir}/asciidoc")
config = ['swagger2markup.markupLanguage' : 'ASCIIDOC',
'swagger2markup.pathsGroupedBy' : 'TAGS']
}
----
[options="header"]
.Gradle Plugin properties
|====
| Name | Description | Type | Example
| swaggerInput | The URL or file path to the Swagger specification | String | `file("src/docs/swagger/swagger_petstore.yaml").getAbsolutePath()` or `http://petstore.swagger.io/v2/swagger.json`
| outputDir | The directory where the output should be stored. | File | `file("${buildDir}/asciidoc")`
| outputFile | The file path (without extension) where the output should be stored. | File | `file("${buildDir}/asciidoc/swagger")`
| config | The Swagger2Markup properties to configure the converter | Map | |
|====
=== Example
You can copy the template project from GitHub to get started.
https://github.com/Swagger2Markup/swagger2markup-gradle-project-template

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 133 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

View File

@@ -1,3 +1,36 @@
include::{generated}/overview.adoc[]
include::{generated}/paths.adoc[]
include::{generated}/definitions.adoc[]
= Swagger2Markup Documentation
Robert Winkler
:toc: left
:toclevels: 3
:source-highlighter: coderay
:numbered:
:hardbreaks:
:revnumber: {release-version}
:revdate: {localdate}
:icons: font
:pagenums:
include::introduction.adoc[]
include::getting_started.adoc[]
include::usage_guide.adoc[]
include::advanced_usage.adoc[]
include::extension_spi.adoc[]
include::gradle_plugin.adoc[]
include::maven_plugin.adoc[]
include::command_line_interface.adoc[]
include::docker.adoc[]
include::demo.adoc[]
include::contributing.adoc[]
include::license.adoc[]

View File

@@ -0,0 +1,23 @@
== Introduction
The primary goal of this project is to **simplify the generation of an up-to-date RESTful API documentation by combining documentation that's been hand-written with auto-generated API documentation** produced by https://github.com/swagger-api[Swagger]. The result is intended to be an **up-to-date, easy-to-read, on- and offline user guide**. The output of Swagger2Markup can be used as an alternative to https://github.com/swagger-api/swagger-ui[swagger-ui] and can be served as static content.
NOTE: The Swagger Specification has been donated to to the https://openapis.org/[Open API Initiative (OAI)] and has been renamed to https://github.com/OAI/OpenAPI-Specification[OpenAPI Specification].
Swagger2Markup converts a Swagger JSON or YAML specification into either **AsciiDoc**, **GitHub Flavored Markdown** or *Atlassian Confluence Wiki* documents which can be combined with hand-written Markup documentation. The Swagger source file can be located locally or remotely via HTTP. Internally Swagger2Markup uses the __official__ https://github.com/swagger-api/swagger-parser[swagger-parser] and https://github.com/Swagger2Markup/markup-document-builder[markup-document-builder].
You can use Swagger2Markup to convert your contract-first Swagger YAML file into Markup. As an alternative, you can choose the code-first approach and use Swagger2Markup together with https://github.com/swagger-api/swagger-core/wiki/Swagger-Core-JAX-RS-Project-Setup-1.5.X[Swagger JAX-RS], https://github.com/springfox/springfox[Springfox] or https://github.com/spring-projects/spring-restdocs[spring-restdocs]. If you are are Gradle or Maven user, you can also use the https://github.com/Swagger2Markup/swagger2markup-gradle-plugin[Swagger2Markup Gradle Plugin] or https://github.com/redowl/swagger2markup-maven-plugin[Swagger2markup Maven Plugin].
NOTE: The project requires at least JDK 8.
=== AsciiDoc
http://asciidoctor.org/docs/asciidoc-writers-guide/[AsciiDoc] is preferable to Markdown as it has more features. AsciiDoc is a text document format for writing documentation, articles, books, ebooks, slideshows, web pages and blogs. AsciiDoc files can be converted to **HTML**, **PDF** and **EPUB**. AsciiDoc is much better suited for describing public APIs than **JavaDoc** or **Annotations**.
You can generate your HTML5, PDF and EPUB documentation via https://github.com/asciidoctor/asciidoctorj[asciidoctorj] or even better via the https://github.com/asciidoctor/asciidoctor-gradle-plugin[asciidoctor-gradle-plugin] or https://github.com/asciidoctor/asciidoctor-maven-plugin[asciidoctor-maven-plugin].
.HTML example using AsciiDoctor - path section
image::images/Swagger2Markup.PNG[]
.HTML example using AsciiDoctor - definition section
image::images/Swagger2Markup_definitions.PNG[]

View File

@@ -0,0 +1,9 @@
== License
Copyright 2016 Robert Winkler
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.

View File

@@ -0,0 +1,86 @@
== Maven Plugin
Swagger2Markup provides a Maven plugin. The Maven plugin is published in JCenter and Maven Central.
NOTE: The Maven Plugin requires at least JDK 8.
=== Usage guide
Add the following snippet to your Maven POM file:
[source,xml, subs="specialcharacters,attributes"]
----
<pluginRepositories>
<pluginRepository>
<id>jcenter-snapshots</id>
<name>jcenter</name>
<url>http://oss.jfrog.org/artifactory/oss-snapshot-local/</url>
</pluginRepository>
<pluginRepository>
<snapshots>
<enabled>false</enabled>
</snapshots>
<id>jcenter-releases</id>
<name>jcenter</name>
<url>http://jcenter.bintray.com</url>
</pluginRepository>
</pluginRepositories>
<build>
<plugins>
<plugin>
<groupId>io.github.swagger2markup</groupId>
<artifactId>swagger2markup-maven-plugin</artifactId>
<version>{release-version}</version>
</plugin>
</plugins>
</build>
----
The plugin adds a new task goal `swagger2markup:convertSwagger2markup`. You can run the goal as follows:
`mvn swagger2markup:convertSwagger2markup`
=== Configuration
You can customize the task by configuring a Map of <<Swagger2Markup properties>>.
[source,xml, subs="specialcharacters,attributes"]
----
<build>
<plugins>
<plugin>
<groupId>io.github.swagger2markup</groupId>
<artifactId>swagger2markup-maven-plugin</artifactId>
<version>{release-version}</version>
<configuration>
<swaggerInput>${project.basedir}/src/docs/swagger/swagger_petstore.yaml</swaggerInput>
<outputDir>${project.build.directory}/asciidoc</outputDir>
<config>
<swagger2markup.markupLanguage>ASCIIDOC</swagger2markup.markupLanguage>
</config>
</configuration>
</plugin>
</plugins>
</build>
----
[options="header"]
.Maven Plugin properties
|====
| Name | Description | Type | Example
| swaggerInput | The URL or file path to the Swagger specification | String | `${project.basedir}/src/docs/swagger/swagger_petstore.yaml` or `http://petstore.swagger.io/v2/swagger.json`
| outputDir | The directory where the output should be stored. | File | `${project.build.directory}/asciidoc`
| outputFile | The file path (without extension) where the output should be stored. | File | `${project.build.directory}/asciidoc/swagger`
| config | The Swagger2Markup properties to configure the converter | Map | |
|====
=== Example
You can copy the template project from GitHub to get started.
https://github.com/Swagger2Markup/swagger2markup-maven-project-template

View File

@@ -1,2 +0,0 @@
This is a hand-written description.
AsciiDoc is better suited for descriptions than *JavaDoc* and *Annotations*

View File

@@ -1,5 +0,0 @@
This is a hand-written description.
AsciiDoc is better suited for descriptions than:
* JavaDoc
* Annotations

View File

@@ -0,0 +1,206 @@
== Swagger2Markup API
=== Usage guide
Swagger2Markup converts a Swagger JSON or YAML specification into either **AsciiDoc**, **GitHub Flavored Markdown** or **Atlassian Confluence Wiki** documents. By default the Swagger2Markup converts a Swagger specification into four AsciiDoc files: __overview.adoc__, __paths.adoc__ , __security.adoc__ and __definitions.adoc__. But you can also convert a Swagger specification into only one file or a String.
==== Conversion of a local Swagger file
The entry point of the Swagger2Markup API is the ``Swagger2MarkupConverter`` class. This class provides static factory methods to create a `Swagger2MarkupConverter.Builder`.
[source,java,indent=0]
----
include::../../test/java/io/github/swagger2markup/DocumentationTest.java[tags=localSwaggerSpec]
----
1. Create a ``Swagger2MarkupConverter.Builder`` by specifying the Path to the local file
2. Build an instance of the ``Swagger2MarkupConverter``
3. Invoke ``toFolder`` by specifying the output directory
==== Conversion of a remote Swagger file
You can convert a remote Swagger specification which must be accessible via HTTP.
[source,java,indent=0]
----
include::../../test/java/io/github/swagger2markup/DocumentationTest.java[tags=remoteSwaggerSpec]
----
1. Create a ``Swagger2MarkupConverter.Builder`` by specifying the URL to the remote file
2. Build an instance of the ``Swagger2MarkupConverter``
3. Invoke ``toFolder`` by specifying the output directory
==== Conversion into a file
You can convert the Swagger specification into a file.
[source,java,indent=0]
----
include::../../test/java/io/github/swagger2markup/DocumentationTest.java[tags=convertIntoOneFile]
----
==== Conversion to a String
You can convert the Swagger specification to a String.
[source,java,indent=0]
----
include::../../test/java/io/github/swagger2markup/DocumentationTest.java[tags=convertIntoString]
----
=== Configuration
Swagger2Markup provides several options to configure the Swagger2MarkupConverter:
* Using system properties
* Using a fluent API
* Using a properties file
* Using a Java Map
* Using Apache Commons Configuration
==== Configuration using the Builder
You can configure the Swagger2MarkupConverter by using the `Swagger2MarkupConfigBuilder` to build a custom `Swagger2MarkupConfig`. The `Swagger2MarkupConfigBuilder` can be used to define Swagger2Markup properties with a fluent API.
[source,java,indent=0]
----
include::../../test/java/io/github/swagger2markup/DocumentationTest.java[tags=swagger2MarkupConfigBuilder]
----
1. Create a `Swagger2MarkupConfigBuilder` using the default constructor.
2. Configure the output `MarkupLanguage`
3. Configure the output `Language`
4. Configure additional Swagger2Markup properties
5. Build an instance of the `Swagger2MarkupConfig`
6. Use the custom Swagger2MarkupConfig
You can also create a `Swagger2MarkupConfig` from a Properties file, a `Map` or a Apache Commons Configuration.
==== Configuration from a Properties file
[source,java,indent=0]
----
include::../../test/java/io/github/swagger2markup/DocumentationTest.java[tags=swagger2MarkupConfigFromProperties]
----
1. Load a `Properties` file from the classpath or local filesystem.
2. Create a `Swagger2MarkupConfigBuilder` using the proper constructor.
==== Configuration from a Map
[source,java,indent=0]
----
include::../../test/java/io/github/swagger2markup/DocumentationTest.java[tags=swagger2MarkupConfigFromMap]
----
1. Create a `Map` and configure the `Swagger2MarkupProperties`.
2. Create a `Swagger2MarkupConfigBuilder` using the proper constructor.
==== Configuration from a Apache Commons Configuration
Configuration parameters may be loaded from the following sources using Apache Commons Configuration:
* Properties files
* XML documents
* Property list files (plist)
* JDBC Datasource
* Servlet parameters
[source,java,indent=0]
----
include::../../test/java/io/github/swagger2markup/DocumentationTest.java[tags=swagger2MarkupConfigFromCommonsConfiguration]
----
1. Create an Apache Commons `Configuration` object using the proper ConfigurationBuilder.
2. Create a `Swagger2MarkupConfigBuilder` using the proper constructor.
==== Swagger2Markup properties
The properties of Swagger2Markup are defined in the class `io.github.swagger2markup.Swagger2MarkupProperties`.
The properties are considered in the following order:
1. Java System properties
2. Custom properties
3. Default properties (included in Swagger2Markup)
The following tables list all available properties of Swagger2Markup:
[options="header"]
.Mostly used properties
|===
|Name | Description | Possible Values | Default
|swagger2markup.markupLanguage| Specifies the markup language which should be used to generate the files. | ASCIIDOC, MARKDOWN, CONFLUENCE_MARKUP | ASCIIDOC
|swagger2markup.swaggerMarkupLanguage| Specifies the markup language used in Swagger descriptions. | ASCIIDOC, MARKDOWN, CONFLUENCE_MARKUP | MARKDOWN
|swagger2markup.pathsGroupedBy| Specifies how the paths should be grouped | AS_IS, TAGS, REGEX | AS_IS
|swagger2markup.outputLanguage| Specifies the language of the labels | EN, DE, FR, RU | EN
|swagger2markup.lineSeparator| Specifies the line separator which should be used | UNIX, WINDOWS, MAC | <System-dependent>
|swagger2markup.generatedExamplesEnabled| Specifies if HTTP request and response examples should be generated | true, false | false
|swagger2markup.flatBodyEnabled| Optionally isolate the body parameter, if any, from other parameters | true, false | false
|swagger2markup.pathSecuritySectionEnabled| Optionally disable the security section for path sections | true, false | true
|swagger2markup.anchorPrefix| Optionally prefix all anchors for uniqueness if you want to include generated documents into a global documentation | Any String |
|swagger2markup.basePathPrefixEnabled| Prepend the basePath to all paths | true, false | false
|swagger2markup.headerRegex | Regular expression to use when grouping by RegEx | Any valid RegEx pattern with at least one capture group |
|===
[options="header"]
.Properties which configure the order of Swagger Objects
|===
|Name | Description | Possible Values | Default
|swagger2markup.tagOrderBy| Specifies the order of global tags | AS_IS, NATURAL, CUSTOM | NATURAL
|swagger2markup.operationOrderBy| Specifies the order of path operations | AS_IS, NATURAL, CUSTOM | NATURAL
|swagger2markup.definitionOrderBy| Specifies the order of definitions | AS_IS, NATURAL, CUSTOM | NATURAL
|swagger2markup.parameterOrderBy| Specifies the order of operation parameters | AS_IS, NATURAL, CUSTOM | NATURAL
|swagger2markup.propertyOrderBy | Specifies the order of definition properties | AS_IS, NATURAL, CUSTOM | NATURAL
|swagger2markup.responseOrderBy| Specifies the order of responses | AS_IS, NATURAL, CUSTOM | NATURAL
|===
[options="header"]
.Properties which configure document file names
|===
|Name | Description | Possible Values | Default
|swagger2markup.overviewDocument| Specifies the file name of the overview document | Any String | "overview"
|swagger2markup.pathsDocument| Specifies the file name of the paths document | Any String | "paths"
|swagger2markup.definitionsDocument| Specifies the file name of the definitions document | Any String | "definitions"
|swagger2markup.securityDocument| Specifies the file name of the security document | Any String | "security"
|===
[options="header"]
.Properties which configure the generation of separate files
|===
|Name | Description | Possible Values | Default
|swagger2markup.separatedDefinitionsEnabled| In addition to the Definitions file, also create separate definition files for each model definition | true, false | false
|swagger2markup.separatedOperationsEnabled| In addition to the Paths file, also create separate operation files for each operation | true, false | false
|swagger2markup.separatedOperationsFolder| Specifies the target folder path for definition files| Any valid folder name | "operations"
|swagger2markup.separatedDefinitionsFolder| Specifies the target folder path for operation files | Any valid folder name | "definitions"
|===
[options="header"]
.Properties which configure inter-document cross references
|===
|Name | Description | Possible Values | Default
|swagger2markup.interDocumentCrossReferencesEnabled| Enable use of inter-document cross-references when needed | true, false | false
|swagger2markup.interDocumentCrossReferencesPrefix| Specifies a prefix for all inter-document cross-references for advanced usage | Any String |
|===
[options="header"]
.Properties which configure inline schema rendering
|===
|Name | Description | Possible Values | Default
|swagger2markup.inlineSchemaEnabled| Enable inline object schema support | true, false | true
|===
[options="header"]
.Properties which configure page breaking
|===
|Name | Description | Possible Values | Default
|swagger2markup.pageBreakLocations | Specifies where page breaks should be inserted. | BEFORE_OPERATION, BEFORE_OPERATION_DESCRIPTION, BEFORE_OPERATION_PARAMETERS, BEFORE_OPERATION_RESPONSES, BEFORE_OPERATION_CONSUMES, BEFORE_OPERATION_PRODUCES, BEFORE_OPERATION_EXAMPLE_REQUEST, BEFORE_OPERATION_EXAMPLE_RESPONSE, BEFORE_DEFINITION, AFTER_OPERATION, AFTER_OPERATION_DESCRIPTION, AFTER_OPERATION_PARAMETERS, AFTER_OPERATION_RESPONSES, AFTER_OPERATION_CONSUMES, AFTER_OPERATION_PRODUCES, AFTER_OPERATION_EXAMPLE_REQUEST, AFTER_OPERATION_EXAMPLE_RESPONSE, AFTER_DEFINITION | empty
|===
=== Logging
Swagger2Markup uses http://www.slf4j.org/[SLF4J] for all internal logging, but leaves the underlying log implementation open. To change the log level, you have the set the log level of the `io.github.swagger2markup` package.

View File

@@ -1,5 +0,0 @@
This is a hand-written description.
AsciiDoc is better suited for descriptions than:
* JavaDoc
* Annotations

View File

@@ -1 +0,0 @@
This is a hand-written description. AsciiDoc is better suited for descriptions than *JavaDoc* and *Annotations*

View File

@@ -1 +0,0 @@
This is a hand-written description. AsciiDoc is better suited for descriptions than *JavaDoc* and *Annotations*

View File

@@ -1 +0,0 @@
This is a hand-written description. AsciiDoc is better suited for descriptions than *JavaDoc* and *Annotations*

View File

@@ -1,5 +0,0 @@
This is a hand-written description.
It is better suited for adding descriptions than:
* JavaDoc
* Annotations

View File

@@ -1,251 +0,0 @@
/*
*
* Copyright 2015 Robert Winkler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*
*/
package io.github.robwin.swagger2markup;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.github.robwin.markup.builder.MarkupLanguage;
import io.github.robwin.swagger2markup.builder.document.DefinitionsDocument;
import io.github.robwin.swagger2markup.builder.document.OverviewDocument;
import io.github.robwin.swagger2markup.builder.document.PathsDocument;
import io.swagger.models.Swagger;
import io.swagger.parser.SwaggerParser;
import io.swagger.util.Json;
import io.swagger.util.Yaml;
import org.apache.commons.lang3.Validate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
/**
* @author Robert Winkler
*/
public class Swagger2MarkupConverter {
private static final Logger LOG = LoggerFactory.getLogger(Swagger2MarkupConverter.class);
private final Swagger swagger;
private final MarkupLanguage markupLanguage;
private final String examplesFolderPath;
private final String schemasFolderPath;
private final String descriptionsFolderPath;
private final boolean separatedDefinitions;
private static final String OVERVIEW_DOCUMENT = "overview";
private static final String PATHS_DOCUMENT = "paths";
private static final String DEFINITIONS_DOCUMENT = "definitions";
/**
* @param markupLanguage the markup language which is used to generate the files
* @param swagger the Swagger object
* @param examplesFolderPath the folderPath where examples are stored
* @param schemasFolderPath the folderPath where (XML, JSON)-Schema files are stored
* @param descriptionsFolderPath the folderPath where descriptions are stored
* @param separatedDefinitions create separate definition files for each model definition.
*/
Swagger2MarkupConverter(MarkupLanguage markupLanguage, Swagger swagger, String examplesFolderPath, String schemasFolderPath, String descriptionsFolderPath, boolean separatedDefinitions){
this.markupLanguage = markupLanguage;
this.swagger = swagger;
this.examplesFolderPath = examplesFolderPath;
this.schemasFolderPath = schemasFolderPath;
this.descriptionsFolderPath = descriptionsFolderPath;
this.separatedDefinitions = separatedDefinitions;
}
/**
* Creates a Swagger2MarkupConverter.Builder using a given Swagger source.
*
* @param swaggerLocation the Swagger location. Can be a HTTP url or a path to a local file.
* @return a Swagger2MarkupConverter
*/
public static Builder from(String swaggerLocation){
Validate.notEmpty(swaggerLocation, "swaggerLocation must not be empty!");
return new Builder(swaggerLocation);
}
/**
* Creates a Swagger2MarkupConverter.Builder from a given Swagger model.
*
* @param swagger the Swagger source.
* @return a Swagger2MarkupConverter
*/
public static Builder from(Swagger swagger){
Validate.notNull(swagger, "swagger must not be null!");
return new Builder(swagger);
}
/**
* Creates a Swagger2MarkupConverter.Builder from a given Swagger YAML or JSON String.
*
* @param swagger the Swagger YAML or JSON String.
* @return a Swagger2MarkupConverter
* @throws java.io.IOException if String can not be parsed
*/
public static Builder fromString(String swagger) throws IOException {
Validate.notEmpty(swagger, "swagger must not be null!");
ObjectMapper mapper;
if(swagger.trim().startsWith("{")) {
mapper = Json.mapper();
}else {
mapper = Yaml.mapper();
}
JsonNode rootNode = mapper.readTree(swagger);
// must have swagger node set
JsonNode swaggerNode = rootNode.get("swagger");
if(swaggerNode == null)
throw new IllegalArgumentException("Swagger String is in the wrong format");
return new Builder(mapper.convertValue(rootNode, Swagger.class));
}
/**
* Builds the document with the given markup language and stores
* the files in the given folder.
*
* @param targetFolderPath the target folder
* @throws IOException if the files cannot be written
*/
public void intoFolder(String targetFolderPath) throws IOException {
Validate.notEmpty(targetFolderPath, "folderPath must not be null!");
buildDocuments(targetFolderPath);
}
/**
* Builds the document with the given markup language and returns it as a String
*
* @return a the document as a String
* @throws java.io.IOException if files can not be read
*/
public String asString() throws IOException{
return buildDocuments();
}
/**
* Builds all documents and writes them to a directory
* @param directory the directory where the generated file should be stored
* @throws IOException if a file cannot be written
*/
private void buildDocuments(String directory) throws IOException {
new OverviewDocument(swagger, markupLanguage).build().writeToFile(directory, OVERVIEW_DOCUMENT, StandardCharsets.UTF_8);
new PathsDocument(swagger, markupLanguage, examplesFolderPath, descriptionsFolderPath).build().writeToFile(directory, PATHS_DOCUMENT, StandardCharsets.UTF_8);
new DefinitionsDocument(swagger, markupLanguage, schemasFolderPath, descriptionsFolderPath, separatedDefinitions, directory).build().writeToFile(directory, DEFINITIONS_DOCUMENT, StandardCharsets.UTF_8);
}
/**
* Returns all documents as a String
* @return a the document as a String
*/
private String buildDocuments() throws IOException {
return new OverviewDocument(swagger, markupLanguage).build().toString().concat(
new PathsDocument(swagger, markupLanguage, examplesFolderPath, schemasFolderPath).build().toString()
.concat(new DefinitionsDocument(swagger, markupLanguage, schemasFolderPath, schemasFolderPath, false, null).build().toString()));
}
public static class Builder{
private final Swagger swagger;
private String examplesFolderPath;
private String schemasFolderPath;
private String descriptionsFolderPath;
private boolean separatedDefinitions;
private MarkupLanguage markupLanguage = MarkupLanguage.ASCIIDOC;
/**
* Creates a Builder using a given Swagger source.
*
* @param swaggerLocation the Swagger location. Can be a HTTP url or a path to a local file.
*/
Builder(String swaggerLocation){
swagger = new SwaggerParser().read(swaggerLocation);
if(swagger == null){
throw new IllegalArgumentException("Failed to read the Swagger file. ");
}
}
/**
* Creates a Builder using a given Swagger model.
*
* @param swagger the Swagger source.
*/
Builder(Swagger swagger){
this.swagger = swagger;
}
public Swagger2MarkupConverter build(){
return new Swagger2MarkupConverter(markupLanguage, swagger, examplesFolderPath, schemasFolderPath, descriptionsFolderPath, separatedDefinitions);
}
/**
* Specifies the markup language which should be used to generate the files
*
* @param markupLanguage the markup language which is used to generate the files
* @return the Swagger2MarkupConverter.Builder
*/
public Builder withMarkupLanguage(MarkupLanguage markupLanguage){
this.markupLanguage = markupLanguage;
return this;
}
/**
* Include hand-written descriptions into the Paths and Definitions document
*
* @param descriptionsFolderPath the path to the folder where the description documents reside
* @return the Swagger2MarkupConverter.Builder
*/
public Builder withDescriptions(String descriptionsFolderPath){
this.descriptionsFolderPath = descriptionsFolderPath;
return this;
}
/**
* In addition to the definitions file, also create separate definition files for each model definition.
* @return the Swagger2MarkupConverter.Builder
*/
public Builder withSeparatedDefinitions() {
this.separatedDefinitions = true;
return this;
}
/**
* Include examples into the Paths document
*
* @param examplesFolderPath the path to the folder where the example documents reside
* @return the Swagger2MarkupConverter.Builder
*/
public Builder withExamples(String examplesFolderPath){
this.examplesFolderPath = examplesFolderPath;
return this;
}
/**
* Include (JSON, XML) schemas into the Definitions document
*
* @param schemasFolderPath the path to the folder where the schema documents reside
* @return the Swagger2MarkupConverter.Builder
*/
public Builder withSchemas(String schemasFolderPath){
this.schemasFolderPath = schemasFolderPath;
return this;
}
}
}

View File

@@ -1,283 +0,0 @@
/*
*
* Copyright 2015 Robert Winkler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*
*/
package io.github.robwin.swagger2markup.builder.document;
import io.github.robwin.markup.builder.MarkupDocBuilder;
import io.github.robwin.markup.builder.MarkupDocBuilders;
import io.swagger.models.Model;
import io.swagger.models.Swagger;
import io.swagger.models.properties.Property;
import io.github.robwin.markup.builder.MarkupLanguage;
import io.github.robwin.swagger2markup.utils.PropertyUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;
/**
* @author Robert Winkler
*/
public class DefinitionsDocument extends MarkupDocument {
private static final String DEFINITIONS = "Definitions";
private static final List<String> IGNORED_DEFINITIONS = Collections.singletonList("Void");
private static final String JSON_SCHEMA = "JSON Schema";
private static final String XML_SCHEMA = "XML Schema";
private static final String JSON_SCHEMA_EXTENSION = ".json";
private static final String XML_SCHEMA_EXTENSION = ".xsd";
private static final String JSON = "json";
private static final String XML = "xml";
private static final String DESCRIPTION_FILE_NAME = "description";
private boolean schemasEnabled;
private String schemasFolderPath;
private boolean handWrittenDescriptionsEnabled;
private String descriptionsFolderPath;
private boolean separatedDefinitionsEnabled;
private String outputDirectory;
public DefinitionsDocument(Swagger swagger, MarkupLanguage markupLanguage, String schemasFolderPath, String descriptionsFolderPath, boolean separatedDefinitionsEnabled, String outputDirectory){
super(swagger, markupLanguage);
if(StringUtils.isNotBlank(schemasFolderPath)){
this.schemasEnabled = true;
this.schemasFolderPath = schemasFolderPath;
}
if(StringUtils.isNotBlank(descriptionsFolderPath)){
this.handWrittenDescriptionsEnabled = true;
this.descriptionsFolderPath = descriptionsFolderPath + "/" + DEFINITIONS.toLowerCase();
}
if(schemasEnabled){
if (logger.isDebugEnabled()) {
logger.debug("Include schemas is enabled.");
}
}else{
if (logger.isDebugEnabled()) {
logger.debug("Include schemas is disabled.");
}
}
if(handWrittenDescriptionsEnabled){
if (logger.isDebugEnabled()) {
logger.debug("Include hand-written descriptions is enabled.");
}
}else{
if (logger.isDebugEnabled()) {
logger.debug("Include hand-written descriptions is disabled.");
}
}
this.separatedDefinitionsEnabled = separatedDefinitionsEnabled;
if(this.separatedDefinitionsEnabled){
if (logger.isDebugEnabled()) {
logger.debug("Create separated definition files is enabled.");
}
Validate.notEmpty(outputDirectory, "Output directory is required for separated definition files!");
}else{
if (logger.isDebugEnabled()) {
logger.debug("Create separated definition files is disabled.");
}
}
this.outputDirectory = outputDirectory;
}
@Override
public MarkupDocument build() throws IOException {
definitions(swagger.getDefinitions(), this.markupDocBuilder);
return this;
}
/**
* Builds the Swagger definitions.
*
* @param definitions the Swagger definitions
* @param docBuilder the doc builder to use for output
*/
private void definitions(Map<String, Model> definitions, MarkupDocBuilder docBuilder) throws IOException {
if(MapUtils.isNotEmpty(definitions)){
docBuilder.sectionTitleLevel1(DEFINITIONS);
for(Map.Entry<String, Model> definitionsEntry : definitions.entrySet()){
String definitionName = definitionsEntry.getKey();
if(StringUtils.isNotBlank(definitionName)) {
if (checkThatDefinitionIsNotInIgnoreList(definitionName)) {
definition(definitionName, definitionsEntry.getValue(), docBuilder);
definitionSchema(definitionName, docBuilder);
if (separatedDefinitionsEnabled) {
MarkupDocBuilder defDocBuilder = MarkupDocBuilders.documentBuilder(markupLanguage);
definition(definitionName, definitionsEntry.getValue(), defDocBuilder);
definitionSchema(definitionName, defDocBuilder);
defDocBuilder.writeToFile(outputDirectory, definitionName.toLowerCase(), StandardCharsets.UTF_8);
if (logger.isInfoEnabled()) {
logger.info("Separate definition file produced: {}", definitionName);
}
}
if (logger.isInfoEnabled()) {
logger.info("Definition processed: {}", definitionName);
}
}else{
if (logger.isDebugEnabled()) {
logger.debug("Definition was ignored: {}", definitionName);
}
}
}
}
}
}
/**
* Checks that the definition is not in the list of ignored definitions.
*
* @param definitionName the name of the definition
* @return true if the definition can be processed
*/
private boolean checkThatDefinitionIsNotInIgnoreList(String definitionName) {
return !IGNORED_DEFINITIONS.contains(definitionName);
}
/**
* Builds a concrete definition
*
* @param definitionName the name of the definition
* @param model the Swagger Model of the definition
* @param docBuilder the docbuilder do use for output
*/
private void definition(String definitionName, Model model, MarkupDocBuilder docBuilder) throws IOException {
docBuilder.sectionTitleLevel2(definitionName);
descriptionSection(definitionName, model, docBuilder);
propertiesSection(definitionName, model, docBuilder);
}
private void propertiesSection(String definitionName, Model model, MarkupDocBuilder docBuilder) throws IOException {
Map<String, Property> properties = model.getProperties();
List<String> headerAndContent = new ArrayList<>();
List<String> header = Arrays.asList(NAME_COLUMN, DESCRIPTION_COLUMN, REQUIRED_COLUMN, SCHEMA_COLUMN, DEFAULT_COLUMN);
headerAndContent.add(StringUtils.join(header, DELIMITER));
if(MapUtils.isNotEmpty(properties)){
for (Map.Entry<String, Property> propertyEntry : properties.entrySet()) {
Property property = propertyEntry.getValue();
String propertyName = propertyEntry.getKey();
List<String> content = Arrays.asList(
propertyName,
propertyDescription(definitionName, propertyName, property),
Boolean.toString(property.getRequired()),
PropertyUtils.getType(property, markupLanguage),
PropertyUtils.getDefaultValue(property));
headerAndContent.add(StringUtils.join(content, DELIMITER));
}
docBuilder.tableWithHeaderRow(headerAndContent);
}
}
private void descriptionSection(String definitionName, Model model, MarkupDocBuilder docBuilder) throws IOException {
if(handWrittenDescriptionsEnabled){
String description = handWrittenPathDescription(definitionName.toLowerCase(), DESCRIPTION_FILE_NAME);
if(StringUtils.isNotBlank(description)){
docBuilder.paragraph(description);
}else{
if (logger.isInfoEnabled()) {
logger.info("Hand-written description cannot be read. Trying to use description from Swagger source.");
}
modelDescription(model, docBuilder);
}
}
else{
modelDescription(model, docBuilder);
}
}
private void modelDescription(Model model, MarkupDocBuilder docBuilder) {
String description = model.getDescription();
if (StringUtils.isNotBlank(description)) {
docBuilder.paragraph(description);
}
}
private String propertyDescription(String definitionName, String propertyName, Property property) throws IOException {
String description;
if(handWrittenDescriptionsEnabled){
description = handWrittenPathDescription(definitionName.toLowerCase() + "/" + propertyName.toLowerCase(), DESCRIPTION_FILE_NAME);
if(StringUtils.isBlank(description)) {
if (logger.isInfoEnabled()) {
logger.info("Hand-written description file cannot be read. Trying to use description from Swagger source.");
}
description = StringUtils.defaultString(property.getDescription());
}
}
else{
description = StringUtils.defaultString(property.getDescription());
}
return description;
}
/**
* Reads a hand-written description
*
* @param descriptionFolder the name of the folder where the description file resides
* @param descriptionFileName the name of the description file
* @return the content of the file
* @throws IOException
*/
private String handWrittenPathDescription(String descriptionFolder, String descriptionFileName) throws IOException {
for (String fileNameExtension : markupLanguage.getFileNameExtensions()) {
java.nio.file.Path path = Paths.get(descriptionsFolderPath, descriptionFolder, descriptionFileName + fileNameExtension);
if (Files.isReadable(path)) {
if (logger.isInfoEnabled()) {
logger.info("Description file processed: {}", path);
}
return FileUtils.readFileToString(path.toFile(), StandardCharsets.UTF_8).trim();
} else {
if (logger.isDebugEnabled()) {
logger.debug("Description file is not readable: {}", path);
}
}
}
if (logger.isWarnEnabled()) {
logger.info("No description file found with correct file name extension in folder: {}", Paths.get(descriptionsFolderPath, descriptionFolder));
}
return null;
}
private void definitionSchema(String definitionName, MarkupDocBuilder docBuilder) throws IOException {
if(schemasEnabled) {
if (StringUtils.isNotBlank(definitionName)) {
schema(JSON_SCHEMA, schemasFolderPath, definitionName + JSON_SCHEMA_EXTENSION, JSON, docBuilder);
schema(XML_SCHEMA, schemasFolderPath, definitionName + XML_SCHEMA_EXTENSION, XML, docBuilder);
}
}
}
private void schema(String title, String schemasFolderPath, String schemaName, String language, MarkupDocBuilder docBuilder) throws IOException {
java.nio.file.Path path = Paths.get(schemasFolderPath, schemaName);
if (Files.isReadable(path)) {
docBuilder.sectionTitleLevel3(title);
docBuilder.source(FileUtils.readFileToString(path.toFile(), StandardCharsets.UTF_8).trim(), language);
if (logger.isInfoEnabled()) {
logger.info("Schema file processed: {}", path);
}
} else {
if (logger.isDebugEnabled()) {
logger.debug("Schema file is not readable: {}", path);
}
}
}
}

View File

@@ -1,83 +0,0 @@
/*
*
* Copyright 2015 Robert Winkler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*
*/
package io.github.robwin.swagger2markup.builder.document;
import io.swagger.models.Swagger;
import io.github.robwin.markup.builder.MarkupDocBuilder;
import io.github.robwin.markup.builder.MarkupDocBuilders;
import io.github.robwin.markup.builder.MarkupLanguage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.nio.charset.Charset;
/**
* @author Robert Winkler
*/
public abstract class MarkupDocument {
protected static final String DELIMITER = "|";
protected static final String DEFAULT_COLUMN = "Default";
protected static final String REQUIRED_COLUMN = "Required";
protected static final String SCHEMA_COLUMN = "Schema";
protected static final String NAME_COLUMN = "Name";
protected static final String DESCRIPTION_COLUMN = "Description";
protected static final String DESCRIPTION = DESCRIPTION_COLUMN;
protected static final String PRODUCES = "Produces";
protected static final String CONSUMES = "Consumes";
protected static final String TAGS = "Tags";
protected Logger logger = LoggerFactory.getLogger(getClass());
protected Swagger swagger;
protected MarkupLanguage markupLanguage;
protected MarkupDocBuilder markupDocBuilder;
MarkupDocument(Swagger swagger, MarkupLanguage markupLanguage){
this.swagger = swagger;
this.markupLanguage = markupLanguage;
this.markupDocBuilder = MarkupDocBuilders.documentBuilder(markupLanguage);
}
/**
* Builds the MarkupDocument.
*
* @return the built MarkupDocument
* @throws IOException if the files to include are not readable
*/
public abstract MarkupDocument build() throws IOException ;
/**
* Returns a string representation of the document.
*/
public String toString(){
return markupDocBuilder.toString();
}
/**
* Writes the content of the builder to a file and clears the builder.
*
* @param directory the directory where the generated file should be stored
* @param fileName the name of the file
* @param charset the the charset to use for encoding
* @throws IOException if the file cannot be written
*/
public void writeToFile(String directory, String fileName, Charset charset) throws IOException{
markupDocBuilder.writeToFile(directory, fileName, charset);
}
}

View File

@@ -1,153 +0,0 @@
/*
*
* Copyright 2015 Robert Winkler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*
*/
package io.github.robwin.swagger2markup.builder.document;
import io.swagger.models.*;
import io.github.robwin.markup.builder.MarkupLanguage;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class OverviewDocument extends MarkupDocument {
private static final String OVERVIEW = "Overview";
private static final String CURRENT_VERSION = "Version information";
private static final String VERSION = "Version: ";
private static final String CONTACT_INFORMATION = "Contact information";
private static final String CONTACT_NAME = "Contact: ";
private static final String CONTACT_EMAIL = "Contact Email: ";
private static final String LICENSE_INFORMATION = "License information";
private static final String LICENSE = "License: ";
private static final String LICENSE_URL = "License URL: ";
private static final String TERMS_OF_SERVICE = "Terms of service: ";
private static final String URI_SCHEME = "URI scheme";
private static final String HOST = "Host: ";
private static final String BASE_PATH = "BasePath: ";
private static final String SCHEMES = "Schemes: ";
public OverviewDocument(Swagger swagger, MarkupLanguage markupLanguage){
super(swagger, markupLanguage);
}
/**
* Builds the MarkupDocument.
*
* @return the built MarkupDocument
* @throws java.io.IOException if the files to include are not readable
*/
@Override
public MarkupDocument build() throws IOException {
overview();
return this;
}
/**
* Builds the document header of the swagger model
*/
private void overview() {
Info info = swagger.getInfo();
this.markupDocBuilder.documentTitle(info.getTitle());
this.markupDocBuilder.sectionTitleLevel1(OVERVIEW);
if(StringUtils.isNotBlank(info.getDescription())){
this.markupDocBuilder.textLine(info.getDescription());
this.markupDocBuilder.newLine();
}
if(StringUtils.isNotBlank(info.getVersion())){
this.markupDocBuilder.sectionTitleLevel2(CURRENT_VERSION);
this.markupDocBuilder.textLine(VERSION + info.getVersion());
this.markupDocBuilder.newLine();
}
Contact contact = info.getContact();
if(contact != null){
this.markupDocBuilder.sectionTitleLevel2(CONTACT_INFORMATION);
if(StringUtils.isNotBlank(contact.getName())){
this.markupDocBuilder.textLine(CONTACT_NAME + contact.getName());
}
if(StringUtils.isNotBlank(contact.getEmail())){
this.markupDocBuilder.textLine(CONTACT_EMAIL + contact.getEmail());
}
this.markupDocBuilder.newLine();
}
License license = info.getLicense();
if(license != null && (StringUtils.isNotBlank(license.getName()) || StringUtils.isNotBlank(license.getUrl()))) {
this.markupDocBuilder.sectionTitleLevel2(LICENSE_INFORMATION);
if (StringUtils.isNotBlank(license.getName())) {
this.markupDocBuilder.textLine(LICENSE + license.getName());
}
if (StringUtils.isNotBlank(license.getUrl())) {
this.markupDocBuilder.textLine(LICENSE_URL + license.getUrl());
}
this.markupDocBuilder.newLine();
}
if(StringUtils.isNotBlank(info.getTermsOfService())){
this.markupDocBuilder.textLine(TERMS_OF_SERVICE + info.getTermsOfService());
this.markupDocBuilder.newLine();
}
this.markupDocBuilder.sectionTitleLevel2(URI_SCHEME);
if(StringUtils.isNotBlank(swagger.getHost())){
this.markupDocBuilder.textLine(HOST + swagger.getHost());
}
if(StringUtils.isNotBlank(swagger.getBasePath())){
this.markupDocBuilder.textLine(BASE_PATH + swagger.getBasePath());
}
if(CollectionUtils.isNotEmpty(swagger.getSchemes())){
List<String> schemes = new ArrayList<>();
for(Scheme scheme : swagger.getSchemes()){
schemes.add(scheme.toString());
}
this.markupDocBuilder.textLine(SCHEMES + StringUtils.join(schemes, ", "));
}
this.markupDocBuilder.newLine();
if(CollectionUtils.isNotEmpty(swagger.getTags())){
this.markupDocBuilder.sectionTitleLevel2(TAGS);
List<String> tags = new ArrayList<>();
for(Tag tag : swagger.getTags()){
String name = tag.getName();
String description = tag.getDescription();
if(StringUtils.isNoneBlank(description)){
tags.add(name + ": " + description);
}
tags.add(name);
}
this.markupDocBuilder.unorderedList(tags);
this.markupDocBuilder.newLine();
}
if(CollectionUtils.isNotEmpty(swagger.getConsumes())){
this.markupDocBuilder.sectionTitleLevel2(CONSUMES);
this.markupDocBuilder.unorderedList(swagger.getConsumes());
this.markupDocBuilder.newLine();
}
if(CollectionUtils.isNotEmpty(swagger.getProduces())){
this.markupDocBuilder.sectionTitleLevel2(PRODUCES);
this.markupDocBuilder.unorderedList(swagger.getProduces());
this.markupDocBuilder.newLine();
}
}
}

View File

@@ -1,381 +0,0 @@
/*
*
* Copyright 2015 Robert Winkler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*
*/
package io.github.robwin.swagger2markup.builder.document;
import io.swagger.models.Operation;
import io.swagger.models.Path;
import io.swagger.models.Response;
import io.swagger.models.Swagger;
import io.swagger.models.parameters.Parameter;
import io.swagger.models.properties.Property;
import io.github.robwin.markup.builder.MarkupLanguage;
import io.github.robwin.swagger2markup.utils.ParameterUtils;
import io.github.robwin.swagger2markup.utils.PropertyUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.text.WordUtils;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
/**
* @author Robert Winkler
*/
public class PathsDocument extends MarkupDocument {
private static final String PATHS = "Paths";
private static final String PARAMETERS = "Parameters";
private static final String RESPONSES = "Responses";
private static final String EXAMPLE_CURL = "Example CURL request";
private static final String EXAMPLE_REQUEST = "Example HTTP request";
private static final String EXAMPLE_RESPONSE = "Example HTTP response";
private static final String TYPE_COLUMN = "Type";
private static final String HTTP_CODE_COLUMN = "HTTP Code";
private static final String REQUEST_EXAMPLE_FILE_NAME = "http-request";
private static final String RESPONSE_EXAMPLE_FILE_NAME = "http-response";
private static final String CURL_EXAMPLE_FILE_NAME = "curl-request";
private static final String DESCRIPTION_FILE_NAME = "description";
private static final String PARAMETER = "Parameter";
private boolean examplesEnabled;
private String examplesFolderPath;
private boolean handWrittenDescriptionsEnabled;
private String descriptionsFolderPath;
public PathsDocument(Swagger swagger, MarkupLanguage markupLanguage, String examplesFolderPath, String descriptionsFolderPath){
super(swagger, markupLanguage);
if(StringUtils.isNotBlank(examplesFolderPath)){
this.examplesEnabled = true;
this.examplesFolderPath = examplesFolderPath;
}
if(StringUtils.isNotBlank(descriptionsFolderPath)){
this.handWrittenDescriptionsEnabled = true;
this.descriptionsFolderPath = descriptionsFolderPath + "/" + PATHS.toLowerCase();
}
if(examplesEnabled){
if (logger.isDebugEnabled()) {
logger.debug("Include examples is enabled.");
}
}else{
if (logger.isDebugEnabled()) {
logger.debug("Include examples is disabled.");
}
}
if(handWrittenDescriptionsEnabled){
if (logger.isDebugEnabled()) {
logger.debug("Include hand-written descriptions is enabled.");
}
}else{
if (logger.isDebugEnabled()) {
logger.debug("Include hand-written descriptions is disabled.");
}
}
}
@Override
public MarkupDocument build() throws IOException {
paths();
return this;
}
/**
* Builds all paths of the Swagger model
*/
private void paths() throws IOException {
Map<String, Path> paths = swagger.getPaths();
if(MapUtils.isNotEmpty(paths)) {
this.markupDocBuilder.sectionTitleLevel1(PATHS);
for (Map.Entry<String, Path> entry : paths.entrySet()) {
Path path = entry.getValue();
if(path != null) {
path("GET", entry.getKey(), path.getGet());
path("PUT", entry.getKey(), path.getPut());
path("DELETE", entry.getKey(), path.getDelete());
path("POST", entry.getKey(), path.getPost());
path("PATCH", entry.getKey(), path.getPatch());
}
}
}
}
/**
* Builds a path
*
* @param httpMethod the HTTP method of the path
* @param resourcePath the URL of the path
* @param operation the Swagger Operation
*/
private void path(String httpMethod, String resourcePath, Operation operation) throws IOException {
if(operation != null){
pathTitle(httpMethod, resourcePath, operation);
descriptionSection(operation);
parametersSection(operation);
responsesSection(operation);
consumesSection(operation);
producesSection(operation);
tagsSection(operation);
examplesSection(operation);
}
}
private void pathTitle(String httpMethod, String resourcePath, Operation operation) {
String summary = operation.getSummary();
String title;
if(StringUtils.isNotBlank(summary)) {
title = summary;
this.markupDocBuilder.sectionTitleLevel2(title);
this.markupDocBuilder.listing(httpMethod + " " + resourcePath);
}else{
title = httpMethod + " " + resourcePath;
this.markupDocBuilder.sectionTitleLevel2(title);
}
if (logger.isInfoEnabled()) {
logger.info("Path processed: {}", title);
}
}
private void descriptionSection(Operation operation) throws IOException {
if(handWrittenDescriptionsEnabled){
String summary = operation.getSummary();
if(StringUtils.isNotBlank(summary)) {
String operationFolder = summary.replace(".", "").replace(" ", "_").toLowerCase();
String description = handWrittenPathDescription(operationFolder, DESCRIPTION_FILE_NAME);
if(StringUtils.isNotBlank(description)){
this.markupDocBuilder.sectionTitleLevel3(DESCRIPTION);
this.markupDocBuilder.paragraph(description);
}else{
if (logger.isInfoEnabled()) {
logger.info("Hand-written description cannot be read. Trying to use description from Swagger source.");
}
pathDescription(operation);
}
}else{
if (logger.isInfoEnabled()) {
logger.info("Hand-written description cannot be read, because summary of operation is empty. Trying to use description from Swagger source.");
}
pathDescription(operation);
}
}else {
pathDescription(operation);
}
}
private void pathDescription(Operation operation) {
String description = operation.getDescription();
if (StringUtils.isNotBlank(description)) {
this.markupDocBuilder.sectionTitleLevel3(DESCRIPTION);
this.markupDocBuilder.paragraph(description);
}
}
private void parametersSection(Operation operation) throws IOException {
List<Parameter> parameters = operation.getParameters();
if(CollectionUtils.isNotEmpty(parameters)){
List<String> headerAndContent = new ArrayList<>();
// Table header row
List<String> header = Arrays.asList(TYPE_COLUMN, NAME_COLUMN, DESCRIPTION_COLUMN, REQUIRED_COLUMN, SCHEMA_COLUMN, DEFAULT_COLUMN);
headerAndContent.add(StringUtils.join(header, DELIMITER));
for(Parameter parameter : parameters){
String type = ParameterUtils.getType(parameter, markupLanguage);
String parameterType = WordUtils.capitalize(parameter.getIn() + PARAMETER);
// Table content row
List<String> content = Arrays.asList(
parameterType,
parameter.getName(),
parameterDescription(operation, parameter),
Boolean.toString(parameter.getRequired()), type,
ParameterUtils.getDefaultValue(parameter));
headerAndContent.add(StringUtils.join(content, DELIMITER));
}
this.markupDocBuilder.sectionTitleLevel3(PARAMETERS);
this.markupDocBuilder.tableWithHeaderRow(headerAndContent);
}
}
private String parameterDescription(Operation operation, Parameter parameter) throws IOException {
String description;
if(handWrittenDescriptionsEnabled){
String summary = operation.getSummary();
String operationFolder = summary.replace(".", "").replace(" ", "_").toLowerCase();
String parameterName = parameter.getName();
if(StringUtils.isNotBlank(operationFolder) && StringUtils.isNotBlank(parameterName)) {
description = handWrittenPathDescription(operationFolder + "/" + parameterName, DESCRIPTION_FILE_NAME);
if(StringUtils.isBlank(description)) {
if (logger.isInfoEnabled()) {
logger.info("Hand-written description file cannot be read. Trying to use description from Swagger source.");
}
description = StringUtils.defaultString(parameter.getDescription());
}
}else{
if (logger.isInfoEnabled()) {
logger.info("Hand-written description file cannot be read, because summary of operation or name of parameter is empty. Trying to use description from Swagger source.");
}
description = StringUtils.defaultString(parameter.getDescription());
}
}else {
description = StringUtils.defaultString(parameter.getDescription());
}
return description;
}
private void consumesSection(Operation operation) {
List<String> consumes = operation.getConsumes();
if(CollectionUtils.isNotEmpty(consumes)){
this.markupDocBuilder.sectionTitleLevel3(CONSUMES);
this.markupDocBuilder.unorderedList(consumes);
}
}
private void producesSection(Operation operation) {
List<String> produces = operation.getProduces();
if(CollectionUtils.isNotEmpty(produces)){
this.markupDocBuilder.sectionTitleLevel3(PRODUCES);
this.markupDocBuilder.unorderedList(produces);
}
}
private void tagsSection(Operation operation) {
List<String> tags = operation.getTags();
if(CollectionUtils.isNotEmpty(tags)){
this.markupDocBuilder.sectionTitleLevel3(TAGS);
this.markupDocBuilder.unorderedList(tags);
}
}
/**
* Builds the example section of a Swagger Operation
*
* @param operation the Swagger Operation
* @throws IOException if the example file is not readable
*/
private void examplesSection(Operation operation) throws IOException {
if(examplesEnabled){
String summary = operation.getSummary();
if(StringUtils.isNotBlank(summary)) {
String exampleFolder = summary.replace(".", "").replace(" ", "_").toLowerCase();
String curlExample = example(exampleFolder, CURL_EXAMPLE_FILE_NAME);
if(StringUtils.isNotBlank(curlExample)){
this.markupDocBuilder.sectionTitleLevel3(EXAMPLE_CURL);
this.markupDocBuilder.paragraph(curlExample);
}
String requestExample = example(exampleFolder, REQUEST_EXAMPLE_FILE_NAME);
if(StringUtils.isNotBlank(requestExample)){
this.markupDocBuilder.sectionTitleLevel3(EXAMPLE_REQUEST);
this.markupDocBuilder.paragraph(requestExample);
}
String responseExample = example(exampleFolder, RESPONSE_EXAMPLE_FILE_NAME);
if(StringUtils.isNotBlank(responseExample)){
this.markupDocBuilder.sectionTitleLevel3(EXAMPLE_RESPONSE);
this.markupDocBuilder.paragraph(responseExample);
}
}else{
if (logger.isWarnEnabled()) {
logger.warn("Example file cannot be read, because summary of operation is empty.");
}
}
}
}
/**
* Reads an example
*
* @param exampleFolder the name of the folder where the example file resides
* @param exampleFileName the name of the example file
* @return the content of the file
* @throws IOException
*/
private String example(String exampleFolder, String exampleFileName) throws IOException {
for (String fileNameExtension : markupLanguage.getFileNameExtensions()) {
java.nio.file.Path path = Paths.get(examplesFolderPath, exampleFolder, exampleFileName + fileNameExtension);
if (Files.isReadable(path)) {
if (logger.isInfoEnabled()) {
logger.info("Example file processed: {}", path);
}
return FileUtils.readFileToString(path.toFile(), StandardCharsets.UTF_8).trim();
} else {
if (logger.isDebugEnabled()) {
logger.debug("Example file is not readable: {}", path);
}
}
}
if (logger.isWarnEnabled()) {
logger.info("No example file found with correct file name extension in folder: {}", Paths.get(examplesFolderPath, exampleFolder));
}
return null;
}
/**
* Reads a hand-written description
*
* @param descriptionFolder the name of the folder where the description file resides
* @param descriptionFileName the name of the description file
* @return the content of the file
* @throws IOException
*/
private String handWrittenPathDescription(String descriptionFolder, String descriptionFileName) throws IOException {
for (String fileNameExtension : markupLanguage.getFileNameExtensions()) {
java.nio.file.Path path = Paths.get(descriptionsFolderPath, descriptionFolder, descriptionFileName + fileNameExtension);
if (Files.isReadable(path)) {
if (logger.isInfoEnabled()) {
logger.info("Description file processed: {}", path);
}
return FileUtils.readFileToString(path.toFile(), StandardCharsets.UTF_8).trim();
} else {
if (logger.isDebugEnabled()) {
logger.debug("Description file is not readable: {}", path);
}
}
}
if (logger.isWarnEnabled()) {
logger.info("No description file found with correct file name extension in folder: {}", Paths.get(descriptionsFolderPath, descriptionFolder));
}
return null;
}
private void responsesSection(Operation operation) {
Map<String, Response> responses = operation.getResponses();
if(MapUtils.isNotEmpty(responses)){
List<String> csvContent = new ArrayList<>();
csvContent.add(HTTP_CODE_COLUMN + DELIMITER + DESCRIPTION_COLUMN + DELIMITER + SCHEMA_COLUMN);
for(Map.Entry<String, Response> entry : responses.entrySet()){
Response response = entry.getValue();
if(response.getSchema() != null){
Property property = response.getSchema();
String type = PropertyUtils.getType(property, markupLanguage);
csvContent.add(entry.getKey() + DELIMITER + response.getDescription() + DELIMITER + type);
}else{
csvContent.add(entry.getKey() + DELIMITER + response.getDescription() + DELIMITER + "No Content");
}
}
this.markupDocBuilder.sectionTitleLevel3(RESPONSES);
this.markupDocBuilder.tableWithHeaderRow(csvContent);
}
}
}

View File

@@ -1,45 +0,0 @@
/*
*
* Copyright 2015 Robert Winkler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*
*/
package io.github.robwin.swagger2markup.utils;
import io.swagger.models.ArrayModel;
import io.swagger.models.Model;
import io.swagger.models.ModelImpl;
import io.swagger.models.RefModel;
import io.github.robwin.markup.builder.MarkupLanguage;
import org.apache.commons.lang3.Validate;
public final class ModelUtils {
public static String getType(Model model, MarkupLanguage markupLanguage) {
Validate.notNull(model, "model must not be null!");
if (model instanceof ModelImpl) {
return ((ModelImpl) model).getType();
} else if (model instanceof RefModel) {
switch (markupLanguage){
case ASCIIDOC: return "<<" + ((RefModel) model).getSimpleRef() + ">>";
default: return ((RefModel) model).getSimpleRef();
}
} else if (model instanceof ArrayModel) {
ArrayModel arrayModel = ((ArrayModel) model);
return PropertyUtils.getType(arrayModel.getItems(), markupLanguage) + " " + arrayModel.getType();
}
return "NOT FOUND";
}
}

View File

@@ -1,87 +0,0 @@
/*
*
* Copyright 2015 Robert Winkler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*
*/
package io.github.robwin.swagger2markup.utils;
import io.swagger.models.Model;
import io.swagger.models.parameters.AbstractSerializableParameter;
import io.swagger.models.parameters.BodyParameter;
import io.swagger.models.parameters.Parameter;
import io.swagger.models.parameters.RefParameter;
import io.github.robwin.markup.builder.MarkupLanguage;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import java.util.List;
public final class ParameterUtils {
public static String getType(Parameter parameter, MarkupLanguage markupLanguage){
Validate.notNull(parameter, "property must not be null!");
String type = "NOT FOUND";
if(parameter instanceof BodyParameter){
BodyParameter bodyParameter = (BodyParameter)parameter;
Model model = bodyParameter.getSchema();
type = ModelUtils.getType(model, markupLanguage);
}
else if(parameter instanceof AbstractSerializableParameter){
AbstractSerializableParameter serializableParameter = (AbstractSerializableParameter)parameter;
List enums = serializableParameter.getEnum();
if(CollectionUtils.isNotEmpty(enums)){
type = "enum" + " (" + StringUtils.join(enums, ", ") + ")";
}else{
type = getTypeWithFormat(serializableParameter.getType(), serializableParameter.getFormat());
}
if(type.equals("array")){
String collectionFormat = serializableParameter.getCollectionFormat();
type = collectionFormat + " " + PropertyUtils.getType(serializableParameter.getItems(), markupLanguage) + " " + type;
}
}
else if(parameter instanceof RefParameter){
RefParameter refParameter = (RefParameter)parameter;
switch (markupLanguage){
case ASCIIDOC: return "<<" + refParameter.getSimpleRef() + ">>";
default: return refParameter.getSimpleRef();
}
}
return StringUtils.defaultString(type);
}
private static String getTypeWithFormat(String typeWithoutFormat, String format) {
String type;
if(StringUtils.isNotBlank(format)){
type = StringUtils.defaultString(typeWithoutFormat) + " (" + format + ")";
}else{
type = StringUtils.defaultString(typeWithoutFormat);
}
return type;
}
public static String getDefaultValue(Parameter parameter){
Validate.notNull(parameter, "property must not be null!");
String defaultValue = "";
if(parameter instanceof AbstractSerializableParameter){
AbstractSerializableParameter serializableParameter = (AbstractSerializableParameter)parameter;
defaultValue = serializableParameter.getDefaultValue();
}
return StringUtils.defaultString(defaultValue);
}
}

View File

@@ -1,93 +0,0 @@
/*
*
* Copyright 2015 Robert Winkler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*
*/
package io.github.robwin.swagger2markup.utils;
import io.swagger.models.properties.*;
import io.github.robwin.markup.builder.MarkupLanguage;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import java.util.List;
import java.util.Objects;
public final class PropertyUtils {
public static String getType(Property property, MarkupLanguage markupLanguage){
Validate.notNull(property, "property must not be null!");
String type;
if(property instanceof RefProperty){
RefProperty refProperty = (RefProperty)property;
switch (markupLanguage){
case ASCIIDOC: return "<<" + refProperty.getSimpleRef() + ">>";
default: return refProperty.getSimpleRef();
}
}else if(property instanceof ArrayProperty){
ArrayProperty arrayProperty = (ArrayProperty)property;
Property items = arrayProperty.getItems();
type = getType(items, markupLanguage) + " " + arrayProperty.getType();
}else if(property instanceof StringProperty){
StringProperty stringProperty = (StringProperty)property;
List<String> enums = stringProperty.getEnum();
if(CollectionUtils.isNotEmpty(enums)){
type = "enum" + " (" + StringUtils.join(enums, ", ") + ")";
}else{
type = property.getType();
}
}
else{
if(StringUtils.isNotBlank(property.getFormat())){
type = StringUtils.defaultString(property.getType()) + " (" + property.getFormat() + ")";
}else{
type = property.getType();
}
}
return StringUtils.defaultString(type);
}
public static String getDefaultValue(Property property){
Validate.notNull(property, "property must not be null!");
String defaultValue = "";
if(property instanceof BooleanProperty){
BooleanProperty booleanProperty = (BooleanProperty)property;
defaultValue = Objects.toString(booleanProperty.getDefault(), "");
}else if(property instanceof StringProperty){
StringProperty stringProperty = (StringProperty)property;
defaultValue = Objects.toString(stringProperty.getDefault(), "");
}else if(property instanceof DoubleProperty){
DoubleProperty doubleProperty = (DoubleProperty)property;
defaultValue = Objects.toString(doubleProperty.getDefault(), "");
}else if(property instanceof FloatProperty){
FloatProperty floatProperty = (FloatProperty)property;
defaultValue = Objects.toString(floatProperty.getDefault(), "");
}else if(property instanceof IntegerProperty){
IntegerProperty integerProperty = (IntegerProperty)property;
defaultValue = Objects.toString(integerProperty.getDefault(), "");
}
else if(property instanceof LongProperty){
LongProperty longProperty = (LongProperty)property;
defaultValue = Objects.toString(longProperty.getDefault(), "");
}
else if(property instanceof UUIDProperty){
UUIDProperty uuidProperty = (UUIDProperty)property;
defaultValue = Objects.toString(uuidProperty.getDefault(), "");
}
return defaultValue;
}
}

View File

@@ -0,0 +1,22 @@
/*
* Copyright 2016 Robert Winkler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.swagger2markup;
public enum GroupBy {
AS_IS,
TAGS,
REGEX
}

View File

@@ -0,0 +1,110 @@
/*
* Copyright 2016 Robert Winkler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.swagger2markup;
import java.util.ResourceBundle;
public class Labels {
public static final String DEFAULT_COLUMN = "default_column";
public static final String MAXLENGTH_COLUMN = "maxlength_column";
public static final String MINLENGTH_COLUMN = "minlength_column";
public static final String LENGTH_COLUMN = "length_column";
public static final String PATTERN_COLUMN = "pattern_column";
public static final String MINVALUE_COLUMN = "minvalue_column";
public static final String MINVALUE_EXCLUSIVE_COLUMN = "minvalue_exclusive_column";
public static final String MAXVALUE_COLUMN = "maxvalue_column";
public static final String MAXVALUE_EXCLUSIVE_COLUMN = "maxvalue_exclusive_column";
public static final String EXAMPLE_COLUMN = "example_column";
public static final String SCHEMA_COLUMN = "schema_column";
public static final String NAME_COLUMN = "name_column";
public static final String DESCRIPTION_COLUMN = "description_column";
public static final String SCOPES_COLUMN = "scopes_column";
public static final String DESCRIPTION = DESCRIPTION_COLUMN;
public static final String PRODUCES = "produces";
public static final String CONSUMES = "consumes";
public static final String TAGS = "tags";
public static final String NO_CONTENT = "no_content";
public static final String FLAGS_COLUMN = "flags.column";
public static final String FLAGS_REQUIRED = "flags.required";
public static final String FLAGS_OPTIONAL = "flags.optional";
public static final String FLAGS_READ_ONLY = "flags.read_only";
// Overview Document
public static final String CONTACT_INFORMATION = "contact_information";
public static final String CONTACT_NAME = "contact_name";
public static final String CONTACT_EMAIL = "contact_email";
public static final String LICENSE_INFORMATION = "license_information";
public static final String LICENSE = "license";
public static final String LICENSE_URL = "license_url";
public static final String TERMS_OF_SERVICE = "terms_of_service";
public static final String CURRENT_VERSION = "current_version";
public static final String VERSION = "version";
public static final String OVERVIEW = "overview";
public static final String URI_SCHEME = "uri_scheme";
public static final String HOST = "host";
public static final String BASE_PATH = "base_path";
public static final String SCHEMES = "schemes";
//Security Document
public static final String SECURITY = "security";
public static final String TYPE = "security_type";
public static final String NAME = "security_name";
public static final String IN = "security_in";
public static final String FLOW = "security_flow";
public static final String AUTHORIZATION_URL = "security_authorizationUrl";
public static final String TOKEN_URL = "security_tokenUrl";
//Definitions Document
public static final String DEFINITIONS = "definitions";
public static final String POLYMORPHISM_COLUMN = "polymorphism.column";
public static final String POLYMORPHISM_DISCRIMINATOR_COLUMN = "polymorphism.discriminator";
public static final String TYPE_COLUMN = "type_column";
public static final String POLYMORPHISM_NATURE_COMPOSITION = "polymorphism.nature.COMPOSITION";
public static final String POLYMORPHISM_NATURE_INHERITANCE = "polymorphism.nature.INHERITANCE";
//Paths Document
public static final String RESPONSE = "response";
public static final String REQUEST = "request";
public static final String PATHS = "paths";
public static final String RESOURCES = "resources";
public static final String OPERATIONS = "operations";
public static final String PARAMETERS = "parameters";
public static final String BODY_PARAMETER = "body_parameter";
public static final String RESPONSES = "responses";
public static final String HEADERS_COLUMN = "headers_column";
public static final String EXAMPLE_REQUEST = "example_request";
public static final String EXAMPLE_RESPONSE = "example_response";
public static final String HTTP_CODE_COLUMN = "http_code_column";
public static final String DEPRECATED_OPERATION = "operation.deprecated";
public static final String UNKNOWN = "unknown";
private ResourceBundle resourceBundle;
public Labels(Swagger2MarkupConfig config) {
this.resourceBundle = ResourceBundle.getBundle("io/github/swagger2markup/lang/labels", config.getOutputLanguage().toLocale());
}
/**
* Gets a label for the given key from this resource bundle.
*
* @param key the key for the desired label
* @return the label for the given key
*/
public String getLabel(String key) {
return resourceBundle.getString(key);
}
}

View File

@@ -0,0 +1,44 @@
/*
* Copyright 2016 Robert Winkler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.swagger2markup;
import java.util.Locale;
/**
* @author Maksim Myshkin
*/
public enum Language {
EN(Locale.ENGLISH),
RU(new Locale("ru")),
FR(Locale.FRENCH),
DE(Locale.GERMAN),
TR(new Locale("tr")),
ZH(Locale.CHINESE),
ES(new Locale("es")),
BR(new Locale("pt", "BR")),
JA(Locale.JAPANESE);
private final Locale lang;
Language(final Locale lang) {
this.lang = lang;
}
public Locale toLocale() {
return lang;
}
}

View File

@@ -0,0 +1,22 @@
/*
* Copyright 2016 Robert Winkler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.swagger2markup;
public enum OrderBy {
AS_IS,
NATURAL,
CUSTOM
}

View File

@@ -0,0 +1,37 @@
/*
* Copyright 2016 Robert Winkler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.swagger2markup;
public enum PageBreakLocations {
BEFORE_OPERATION,
BEFORE_OPERATION_DESCRIPTION,
BEFORE_OPERATION_PARAMETERS,
BEFORE_OPERATION_RESPONSES,
BEFORE_OPERATION_CONSUMES,
BEFORE_OPERATION_PRODUCES,
BEFORE_OPERATION_EXAMPLE_REQUEST,
BEFORE_OPERATION_EXAMPLE_RESPONSE,
BEFORE_DEFINITION,
AFTER_OPERATION,
AFTER_OPERATION_DESCRIPTION,
AFTER_OPERATION_PARAMETERS,
AFTER_OPERATION_RESPONSES,
AFTER_OPERATION_CONSUMES,
AFTER_OPERATION_PRODUCES,
AFTER_OPERATION_EXAMPLE_REQUEST,
AFTER_OPERATION_EXAMPLE_RESPONSE,
AFTER_DEFINITION
}

View File

@@ -0,0 +1,230 @@
/*
* Copyright 2016 Robert Winkler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.swagger2markup;
import io.github.swagger2markup.markup.builder.LineSeparator;
import io.github.swagger2markup.markup.builder.MarkupLanguage;
import io.github.swagger2markup.model.PathOperation;
import io.swagger.models.parameters.Parameter;
import java.util.Comparator;
import java.util.List;
import java.util.regex.Pattern;
/**
* Swagger2Markup configuration interface.
*/
public interface Swagger2MarkupConfig {
/**
* Specifies the markup language which should be used to generate the files.
*/
MarkupLanguage getMarkupLanguage();
/**
* Specifies the markup language used in Swagger descriptions.<br>
* By default, {@link io.github.swagger2markup.markup.builder.MarkupLanguage#MARKDOWN} is assumed.
*/
MarkupLanguage getSwaggerMarkupLanguage();
/**
* Include generated examples into the documents.
*/
boolean isGeneratedExamplesEnabled();
/**
* Prepend the base path to all paths.
*/
boolean isBasePathPrefixEnabled();
/**
* In addition to the Definitions file, also create separate definition files for each model definition.
*/
boolean isSeparatedDefinitionsEnabled();
/**
* In addition to the Paths file, also create separate operation files for each operation.
*/
boolean isSeparatedOperationsEnabled();
/**
* Specifies if the operations should be grouped by tags or stay as-is.
*/
GroupBy getPathsGroupedBy();
/**
* Specifies labels language of output files.
*/
Language getOutputLanguage();
/**
* Specifies if inline schemas are detailed
*/
boolean isInlineSchemaEnabled();
/**
* Specifies tag ordering.
*/
OrderBy getTagOrderBy();
/**
* Specifies the regex pattern used for header matching
*/
Pattern getHeaderPattern();
/**
* Specifies a custom comparator function to order tags.
*/
Comparator<String> getTagOrdering();
/**
* Specifies operation ordering.
*/
OrderBy getOperationOrderBy();
/**
* Specifies a custom comparator function to order operations.
*/
Comparator<PathOperation> getOperationOrdering();
/**
* Specifies definition ordering.
*/
OrderBy getDefinitionOrderBy();
/**
* Specifies a custom comparator function to order definitions.
*/
Comparator<String> getDefinitionOrdering();
/**
* Specifies parameter ordering.
*/
OrderBy getParameterOrderBy();
/**
* Specifies a custom comparator function to order parameters.
*/
Comparator<Parameter> getParameterOrdering();
/**
* Specifies property ordering.
*/
OrderBy getPropertyOrderBy();
/**
* Specifies a custom comparator function to order properties.
*/
Comparator<String> getPropertyOrdering();
/**
* Specifies response ordering.
*/
OrderBy getResponseOrderBy();
/**
* Specifies a custom comparator function to order responses.
*/
Comparator<String> getResponseOrdering();
/**
* Enable use of inter-document cross-references when needed.
*/
boolean isInterDocumentCrossReferencesEnabled();
/**
* Inter-document cross-references optional prefix.
*/
String getInterDocumentCrossReferencesPrefix();
/**
* Optionally isolate the body parameter, if any, from other parameters.
*/
boolean isFlatBodyEnabled();
/**
* Optionally disable the security section for path sections
*/
boolean isPathSecuritySectionEnabled();
/**
* Optionally prefix all anchors for uniqueness.
*/
String getAnchorPrefix();
/**
* Overview document name (without extension).
*
* @return the overview document name (without extension)
*/
String getOverviewDocument();
/**
* Paths document name (without extension).
*
* @return the paths document name (without extension)
*/
String getPathsDocument();
/**
* Definitions document name (without extension).
*
* @return the definitions document name (without extension)
*/
String getDefinitionsDocument();
/**
* Security document name (without extension).
*
* @return the security document name (without extension)
*/
String getSecurityDocument();
/**
* Separated operations sub-folder name.
*
* @return the operations sub-folder name
*/
String getSeparatedOperationsFolder();
/**
* Separated definitions sub-folder name.
*
* @return the definitions sub-folder name
*/
String getSeparatedDefinitionsFolder();
/**
* Specifies the line separator which should be used.
*
* @return the line separator
*/
LineSeparator getLineSeparator();
/**
* Returns properties for extensions.
*
* @return the extension properties
*/
Swagger2MarkupProperties getExtensionsProperties();
/**
* Returns the list of page break locations
*
* @return List of PageBreakLocations
*/
List<PageBreakLocations> getPageBreakLocations();
}

View File

@@ -0,0 +1,422 @@
/*
* Copyright 2016 Robert Winkler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.swagger2markup;
import io.github.swagger2markup.builder.Swagger2MarkupConfigBuilder;
import io.github.swagger2markup.builder.Swagger2MarkupExtensionRegistryBuilder;
import io.github.swagger2markup.internal.document.DefinitionsDocument;
import io.github.swagger2markup.internal.document.OverviewDocument;
import io.github.swagger2markup.internal.document.PathsDocument;
import io.github.swagger2markup.internal.document.SecurityDocument;
import io.github.swagger2markup.markup.builder.MarkupDocBuilder;
import io.github.swagger2markup.markup.builder.MarkupDocBuilders;
import io.github.swagger2markup.utils.URIUtils;
import io.swagger.models.Swagger;
import io.swagger.parser.SwaggerParser;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.Validate;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
/**
* @author Robert Winkler
*/
public class Swagger2MarkupConverter {
private final Context context;
private final OverviewDocument overviewDocument;
private final PathsDocument pathsDocument;
private final DefinitionsDocument definitionsDocument;
private final SecurityDocument securityDocument;
public Swagger2MarkupConverter(Context context) {
this.context = context;
this.overviewDocument = new OverviewDocument(context);
this.pathsDocument = new PathsDocument(context);
this.definitionsDocument = new DefinitionsDocument(context);
this.securityDocument = new SecurityDocument(context);
}
/**
* Creates a Swagger2MarkupConverter.Builder from a URI.
*
* @param swaggerUri the URI
* @return a Swagger2MarkupConverter
*/
public static Builder from(URI swaggerUri) {
Validate.notNull(swaggerUri, "swaggerUri must not be null");
String scheme = swaggerUri.getScheme();
if (scheme != null && swaggerUri.getScheme().startsWith("http")) {
try {
return from(swaggerUri.toURL());
} catch (MalformedURLException e) {
throw new RuntimeException("Failed to convert URI to URL", e);
}
} else if (scheme != null && swaggerUri.getScheme().startsWith("file")) {
return from(Paths.get(swaggerUri));
} else {
return from(URIUtils.convertUriWithoutSchemeToFileScheme(swaggerUri));
}
}
/**
* Creates a Swagger2MarkupConverter.Builder using a remote URL.
*
* @param swaggerURL the remote URL
* @return a Swagger2MarkupConverter
*/
public static Builder from(URL swaggerURL) {
Validate.notNull(swaggerURL, "swaggerURL must not be null");
return new Builder(swaggerURL);
}
/**
* Creates a Swagger2MarkupConverter.Builder using a local Path.
*
* @param swaggerPath the local Path
* @return a Swagger2MarkupConverter
*/
public static Builder from(Path swaggerPath) {
Validate.notNull(swaggerPath, "swaggerPath must not be null");
if (Files.notExists(swaggerPath)) {
throw new IllegalArgumentException(String.format("swaggerPath does not exist: %s", swaggerPath));
}
try {
if (Files.isHidden(swaggerPath)) {
throw new IllegalArgumentException("swaggerPath must not be a hidden file");
}
} catch (IOException e) {
throw new RuntimeException("Failed to check if swaggerPath is a hidden file", e);
}
return new Builder(swaggerPath);
}
/**
* Creates a Swagger2MarkupConverter.Builder from a given Swagger model.
*
* @param swagger the Swagger source.
* @return a Swagger2MarkupConverter
*/
public static Builder from(Swagger swagger) {
Validate.notNull(swagger, "swagger must not be null");
return new Builder(swagger);
}
/**
* Creates a Swagger2MarkupConverter.Builder from a given Swagger YAML or JSON String.
*
* @param swaggerString the Swagger YAML or JSON String.
* @return a Swagger2MarkupConverter
*/
public static Builder from(String swaggerString) {
Validate.notEmpty(swaggerString, "swaggerString must not be null");
return from(new StringReader(swaggerString));
}
/**
* Creates a Swagger2MarkupConverter.Builder from a given Swagger YAML or JSON reader.
*
* @param swaggerReader the Swagger YAML or JSON reader.
* @return a Swagger2MarkupConverter
*/
public static Builder from(Reader swaggerReader) {
Validate.notNull(swaggerReader, "swaggerReader must not be null");
Swagger swagger;
try {
swagger = new SwaggerParser().parse(IOUtils.toString(swaggerReader));
} catch (IOException e) {
throw new RuntimeException("Swagger source can not be parsed", e);
}
if (swagger == null)
throw new IllegalArgumentException("Swagger source is in a wrong format");
return new Builder(swagger);
}
/**
* Returns the global Context
*
* @return the global Context
*/
public Context getContext() {
return context;
}
/**
* Converts the Swagger specification into the given {@code outputDirectory}.
*
* @param outputDirectory the output directory path
*/
public void toFolder(Path outputDirectory) {
Validate.notNull(outputDirectory, "outputDirectory must not be null");
context.setOutputPath(outputDirectory);
applyOverviewDocument()
.writeToFile(outputDirectory.resolve(context.config.getOverviewDocument()), StandardCharsets.UTF_8);
applyPathsDocument()
.writeToFile(outputDirectory.resolve(context.config.getPathsDocument()), StandardCharsets.UTF_8);
applyDefinitionsDocument()
.writeToFile(outputDirectory.resolve(context.config.getDefinitionsDocument()), StandardCharsets.UTF_8);
applySecurityDocument()
.writeToFile(outputDirectory.resolve(context.config.getSecurityDocument()), StandardCharsets.UTF_8);
}
private MarkupDocBuilder applyOverviewDocument() {
return overviewDocument.apply(
context.createMarkupDocBuilder(),
OverviewDocument.parameters(context.getSwagger()));
}
private MarkupDocBuilder applyPathsDocument() {
return pathsDocument.apply(
context.createMarkupDocBuilder(),
PathsDocument.parameters(context.getSwagger().getPaths()));
}
private MarkupDocBuilder applyDefinitionsDocument() {
return definitionsDocument.apply(
context.createMarkupDocBuilder(),
DefinitionsDocument.parameters(context.getSwagger().getDefinitions()));
}
private MarkupDocBuilder applySecurityDocument() {
return securityDocument.apply(
context.createMarkupDocBuilder(),
SecurityDocument.parameters(context.getSwagger().getSecurityDefinitions()));
}
/**
* Converts the Swagger specification into the {@code outputPath} which can be either a directory (e.g /tmp) or a file without extension (e.g /tmp/swagger).
* Internally the method invokes either {@code toFolder} or {@code toFile}. If the {@code outputPath} is a directory, the directory must exist.
* Otherwise it cannot be determined if the {@code outputPath} is a directory or not.
*
* @param outputPath the output path
*/
public void toPath(Path outputPath) {
Validate.notNull(outputPath, "outputPath must not be null");
if (Files.isDirectory(outputPath)) {
toFolder(outputPath);
} else {
toFile(outputPath);
}
}
/**
* Converts the Swagger specification the given {@code outputFile}.<br>
* An extension identifying the markup language will be automatically added to file name.
*
* @param outputFile the output file
*/
public void toFile(Path outputFile) {
Validate.notNull(outputFile, "outputFile must not be null");
applyOverviewDocument().writeToFile(outputFile, StandardCharsets.UTF_8);
applyPathsDocument().writeToFile(outputFile, StandardCharsets.UTF_8, StandardOpenOption.APPEND);
applyDefinitionsDocument().writeToFile(outputFile, StandardCharsets.UTF_8, StandardOpenOption.APPEND);
applySecurityDocument().writeToFile(outputFile, StandardCharsets.UTF_8, StandardOpenOption.APPEND);
}
/**
* Converts the Swagger specification the given {@code outputFile}.
*
* @param outputFile the output file
*/
public void toFileWithoutExtension(Path outputFile) {
Validate.notNull(outputFile, "outputFile must not be null");
applyOverviewDocument().writeToFileWithoutExtension(outputFile, StandardCharsets.UTF_8);
applyPathsDocument().writeToFileWithoutExtension(outputFile, StandardCharsets.UTF_8, StandardOpenOption.APPEND);
applyDefinitionsDocument().writeToFileWithoutExtension(outputFile, StandardCharsets.UTF_8, StandardOpenOption.APPEND);
applySecurityDocument().writeToFileWithoutExtension(outputFile, StandardCharsets.UTF_8, StandardOpenOption.APPEND);
}
/**
* Builds the document returns it as a String.
*
* @return the document as a String
*/
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(applyOverviewDocument().toString());
sb.append(applyPathsDocument().toString());
sb.append(applyDefinitionsDocument().toString());
sb.append(applySecurityDocument().toString());
return sb.toString();
}
public static class Builder {
private final Swagger swagger;
private final URI swaggerLocation;
private Swagger2MarkupConfig config;
private Swagger2MarkupExtensionRegistry extensionRegistry;
/**
* Creates a Builder from a remote URL.
*
* @param swaggerUrl the remote URL
*/
Builder(URL swaggerUrl) {
try {
this.swaggerLocation = swaggerUrl.toURI();
} catch (URISyntaxException e) {
throw new IllegalArgumentException("swaggerURL is in a wrong format", e);
}
this.swagger = readSwagger(swaggerUrl.toString());
}
/**
* Creates a Builder from a local Path.
*
* @param swaggerPath the local Path
*/
Builder(Path swaggerPath) {
this.swaggerLocation = swaggerPath.toAbsolutePath().toUri();
this.swagger = readSwagger(swaggerPath.toString());
}
/**
* Creates a Builder using a given Swagger model.
*
* @param swagger the Swagger source.
*/
Builder(Swagger swagger) {
this.swagger = swagger;
this.swaggerLocation = null;
}
/**
* Uses the SwaggerParser to read the Swagger source.
*
* @param swaggerLocation the location of the Swagger source
* @return the Swagger model
*/
private Swagger readSwagger(String swaggerLocation) {
Swagger swagger = new SwaggerParser().read(swaggerLocation);
if (swagger == null) {
throw new IllegalArgumentException("Failed to read the Swagger source");
}
return swagger;
}
public Builder withConfig(Swagger2MarkupConfig config) {
Validate.notNull(config, "config must not be null");
this.config = config;
return this;
}
public Builder withExtensionRegistry(Swagger2MarkupExtensionRegistry registry) {
Validate.notNull(registry, "registry must not be null");
this.extensionRegistry = registry;
return this;
}
public Swagger2MarkupConverter build() {
if (config == null)
config = new Swagger2MarkupConfigBuilder().build();
if (extensionRegistry == null)
extensionRegistry = new Swagger2MarkupExtensionRegistryBuilder().build();
Context context = new Context(config, extensionRegistry, swagger, swaggerLocation);
initExtensions(context);
applySwaggerExtensions(context);
return new Swagger2MarkupConverter(context);
}
private void initExtensions(Context context) {
extensionRegistry.getSwaggerModelExtensions().forEach(extension -> extension.setGlobalContext(context));
extensionRegistry.getOverviewDocumentExtensions().forEach(extension -> extension.setGlobalContext(context));
extensionRegistry.getDefinitionsDocumentExtensions().forEach(extension -> extension.setGlobalContext(context));
extensionRegistry.getPathsDocumentExtensions().forEach(extension -> extension.setGlobalContext(context));
extensionRegistry.getSecurityDocumentExtensions().forEach(extension -> extension.setGlobalContext(context));
}
private void applySwaggerExtensions(Context context) {
extensionRegistry.getSwaggerModelExtensions().forEach(extension -> extension.apply(context.getSwagger()));
}
}
public static class Context {
private final Swagger2MarkupConfig config;
private final Swagger swagger;
private final URI swaggerLocation;
private final Swagger2MarkupExtensionRegistry extensionRegistry;
private final Labels labels;
private Path outputPath;
public Context(Swagger2MarkupConfig config,
Swagger2MarkupExtensionRegistry extensionRegistry,
Swagger swagger,
URI swaggerLocation) {
this.config = config;
this.extensionRegistry = extensionRegistry;
this.swagger = swagger;
this.swaggerLocation = swaggerLocation;
this.labels = new Labels(config);
}
public Swagger2MarkupConfig getConfig() {
return config;
}
public Swagger getSwagger() {
return swagger;
}
public URI getSwaggerLocation() {
return swaggerLocation;
}
public Swagger2MarkupExtensionRegistry getExtensionRegistry() {
return extensionRegistry;
}
public Labels getLabels() {
return labels;
}
public MarkupDocBuilder createMarkupDocBuilder() {
return MarkupDocBuilders.documentBuilder(config.getMarkupLanguage(),
config.getLineSeparator()).withAnchorPrefix(config.getAnchorPrefix());
}
public Path getOutputPath() {
return outputPath;
}
public void setOutputPath(Path outputPath) {
this.outputPath = outputPath;
}
}
}

View File

@@ -0,0 +1,60 @@
/*
* Copyright 2016 Robert Winkler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.swagger2markup;
import io.github.swagger2markup.spi.*;
import java.util.List;
/**
* Extension points registry interface.
*/
public interface Swagger2MarkupExtensionRegistry {
/**
* SwaggerModelExtension extension point can be used to preprocess the Swagger model.
*
* @return registered extensions extending SwaggerModelExtension extension point
*/
List<SwaggerModelExtension> getSwaggerModelExtensions();
/**
* OverviewDocumentExtension extension point can be used to extend the overview document content.
*
* @return registered extensions extending OverviewDocumentExtension extension point
*/
List<OverviewDocumentExtension> getOverviewDocumentExtensions();
/**
* DefinitionsDocumentExtension extension point can be used to extend the definitions document content.
*
* @return registered extensions extending DefinitionsDocumentExtension extension point
*/
List<DefinitionsDocumentExtension> getDefinitionsDocumentExtensions();
/**
* SecurityContentExtension extension point can be used to extend the security document content.
*
* @return registered extensions extending SecurityContentExtension extension point
*/
List<SecurityDocumentExtension> getSecurityDocumentExtensions();
/**
* PathsDocumentExtension extension point can be used to extend the paths document content.
*
* @return registered extensions extending PathsDocumentExtension extension point
*/
List<PathsDocumentExtension> getPathsDocumentExtensions();
}

View File

@@ -0,0 +1,355 @@
/*
* Copyright 2016 Robert Winkler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.swagger2markup;
import io.github.swagger2markup.markup.builder.MarkupLanguage;
import io.github.swagger2markup.utils.URIUtils;
import org.apache.commons.collections4.IteratorUtils;
import org.apache.commons.configuration2.Configuration;
import org.apache.commons.configuration2.ConfigurationConverter;
import org.apache.commons.configuration2.MapConfiguration;
import java.net.URI;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.regex.Pattern;
public class Swagger2MarkupProperties {
/**
* Prefix for Swagger2Markup properties
*/
public static final String PROPERTIES_PREFIX = "swagger2markup";
public static final String MARKUP_LANGUAGE = PROPERTIES_PREFIX + ".markupLanguage";
public static final String SWAGGER_MARKUP_LANGUAGE = PROPERTIES_PREFIX + ".swaggerMarkupLanguage";
public static final String GENERATED_EXAMPLES_ENABLED = PROPERTIES_PREFIX + ".generatedExamplesEnabled";
public static final String BASE_PATH_PREFIX_ENABLED = PROPERTIES_PREFIX + ".basePathPrefixEnabled";
public static final String SEPARATED_DEFINITIONS_ENABLED = PROPERTIES_PREFIX + ".separatedDefinitionsEnabled";
public static final String SEPARATED_OPERATIONS_ENABLED = PROPERTIES_PREFIX + ".separatedOperationsEnabled";
public static final String PATHS_GROUPED_BY = PROPERTIES_PREFIX + ".pathsGroupedBy";
public static final String HEADER_REGEX = PROPERTIES_PREFIX + ".headerRegex";
public static final String OUTPUT_LANGUAGE = PROPERTIES_PREFIX + ".outputLanguage";
public static final String INLINE_SCHEMA_ENABLED = PROPERTIES_PREFIX + ".inlineSchemaEnabled";
public static final String INTER_DOCUMENT_CROSS_REFERENCES_ENABLED = PROPERTIES_PREFIX + ".interDocumentCrossReferencesEnabled";
public static final String INTER_DOCUMENT_CROSS_REFERENCES_PREFIX = PROPERTIES_PREFIX + ".interDocumentCrossReferencesPrefix";
public static final String FLAT_BODY_ENABLED = PROPERTIES_PREFIX + ".flatBodyEnabled";
public static final String PATH_SECURITY_SECTION_ENABLED = PROPERTIES_PREFIX + ".pathSecuritySectionEnabled";
public static final String ANCHOR_PREFIX = PROPERTIES_PREFIX + ".anchorPrefix";
public static final String OVERVIEW_DOCUMENT = PROPERTIES_PREFIX + ".overviewDocument";
public static final String PATHS_DOCUMENT = PROPERTIES_PREFIX + ".pathsDocument";
public static final String DEFINITIONS_DOCUMENT = PROPERTIES_PREFIX + ".definitionsDocument";
public static final String SECURITY_DOCUMENT = PROPERTIES_PREFIX + ".securityDocument";
public static final String SEPARATED_OPERATIONS_FOLDER = PROPERTIES_PREFIX + ".separatedOperationsFolder";
public static final String SEPARATED_DEFINITIONS_FOLDER = PROPERTIES_PREFIX + ".separatedDefinitionsFolder";
public static final String TAG_ORDER_BY = PROPERTIES_PREFIX + ".tagOrderBy";
public static final String OPERATION_ORDER_BY = PROPERTIES_PREFIX + ".operationOrderBy";
public static final String DEFINITION_ORDER_BY = PROPERTIES_PREFIX + ".definitionOrderBy";
public static final String PARAMETER_ORDER_BY = PROPERTIES_PREFIX + ".parameterOrderBy";
public static final String PROPERTY_ORDER_BY = PROPERTIES_PREFIX + ".propertyOrderBy";
public static final String RESPONSE_ORDER_BY = PROPERTIES_PREFIX + ".responseOrderBy";
public static final String LINE_SEPARATOR = PROPERTIES_PREFIX + ".lineSeparator";
public static final String PAGE_BREAK_LOCATIONS = PROPERTIES_PREFIX + ".pageBreakLocations";
/**
* Prefix for Swagger2Markup extension properties
*/
public static final String EXTENSION_PREFIX = "extensions";
private final Configuration configuration;
public Swagger2MarkupProperties(Properties properties) {
this(ConfigurationConverter.getConfiguration(properties));
}
public Swagger2MarkupProperties(Map<String, String> map) {
this(new MapConfiguration(map));
}
public Swagger2MarkupProperties(Configuration configuration) {
this.configuration = configuration;
}
/**
* Returns an optional String property value associated with the given key.
*
* @param key the property name to resolve
* @return The string property
*/
public Optional<String> getString(String key) {
return Optional.ofNullable(configuration.getString(key));
}
/**
* Return the String property value associated with the given key, or
* {@code defaultValue} if the key cannot be resolved.
*
* @param key the property name to resolve
* @param defaultValue the default value to return if no value is found
* @return The string property
*/
public String getString(String key, String defaultValue) {
return configuration.getString(key, defaultValue);
}
/**
* Return the int property value associated with the given key, or
* {@code defaultValue} if the key cannot be resolved.
*
* @param key the property name to resolve
* @param defaultValue the default value to return if no value is found
* @return The int property
*/
public int getInt(String key, int defaultValue) {
return configuration.getInt(key, defaultValue);
}
/**
* Returns an optional Integer property value associated with the given key.
*
* @param key the property name to resolve
* @return An optional Integer property
*/
public Optional<Integer> getInteger(String key) {
return Optional.ofNullable(configuration.getInteger(key, null));
}
/**
* Return the int property value associated with the given key (never {@code null}).
*
* @return The int property
* @throws IllegalStateException if the key cannot be
*/
public int getRequiredInt(String key) {
Optional<Integer> value = getInteger(key);
if (value.isPresent()) {
return value.get();
}
throw new IllegalStateException(String.format("required key [%s] not found", key));
}
/**
* Return the boolean property value associated with the given key (never {@code null}).
*
* @return The boolean property
* @throws IllegalStateException if the key cannot be resolved
*/
public boolean getRequiredBoolean(String key) {
Boolean value = configuration.getBoolean(key, null);
if (value != null) {
return value;
} else {
throw new IllegalStateException(String.format("required key [%s] not found", key));
}
}
/**
* Return the boolean property value associated with the given key, or
* {@code defaultValue} if the key cannot be resolved.
*
* @param key the property name to resolve
* @param defaultValue the default value to return if no value is found
* @return The boolean property
*/
public boolean getBoolean(String key, boolean defaultValue) {
return configuration.getBoolean(key, defaultValue);
}
/**
* Return the URI property value associated with the given key, or
* {@code defaultValue} if the key cannot be resolved.
*
* @param key the property name to resolve
* @return The URI property
* @throws IllegalStateException if the value cannot be mapped to the enum
*/
public Optional<URI> getURI(String key) {
Optional<String> property = getString(key);
if (property.isPresent()) {
return Optional.of(URIUtils.create(property.get()));
} else {
return Optional.empty();
}
}
/**
* Return the URI property value associated with the given key (never {@code null}).
*
* @return The URI property
* @throws IllegalStateException if the key cannot be resolved
*/
public URI getRequiredURI(String key) {
Optional<String> property = getString(key);
if (property.isPresent()) {
return URIUtils.create(property.get());
} else {
throw new IllegalStateException(String.format("required key [%s] not found", key));
}
}
/**
* Return the Path property value associated with the given key, or
* {@code defaultValue} if the key cannot be resolved.
*
* @param key the property name to resolve
* @return The Path property
* @throws IllegalStateException if the value cannot be mapped to the enum
*/
public Optional<Path> getPath(String key) {
Optional<String> property = getString(key);
if (property.isPresent()) {
return Optional.of(Paths.get(property.get()));
} else {
return Optional.empty();
}
}
/**
* Return the Path property value associated with the given key (never {@code null}).
*
* @return The Path property
* @throws IllegalStateException if the key cannot be resolved
*/
public Path getRequiredPath(String key) {
Optional<String> property = getString(key);
if (property.isPresent()) {
return Paths.get(property.get());
} else {
throw new IllegalStateException(String.format("required key [%s] not found", key));
}
}
/**
* Return the MarkupLanguage property value associated with the given key, or
* {@code defaultValue} if the key cannot be resolved.
*
* @param key the property name to resolve
* @return The MarkupLanguage property
*/
public Optional<MarkupLanguage> getMarkupLanguage(String key) {
Optional<String> property = getString(key);
if (property.isPresent()) {
return Optional.of(MarkupLanguage.valueOf(property.get()));
} else {
return Optional.empty();
}
}
/**
* Return the MarkupLanguage property value associated with the given key (never {@code null}).
*
* @return The MarkupLanguage property
* @throws IllegalStateException if the key cannot be resolved
*/
public MarkupLanguage getRequiredMarkupLanguage(String key) {
return MarkupLanguage.valueOf(configuration.getString(key));
}
/**
* Return the Language property value associated with the given key, or
* {@code defaultValue} if the key cannot be resolved.
*
* @param key the property name to resolve
* @return The Language property
*/
public Language getLanguage(String key) {
return Language.valueOf(configuration.getString(key));
}
/**
* Return the GroupBy property value associated with the given key, or
* {@code defaultValue} if the key cannot be resolved.
*
* @param key the property name to resolve
* @return The GroupBy property
* @throws IllegalStateException if the value cannot be mapped to the enum
*/
public GroupBy getGroupBy(String key) {
return GroupBy.valueOf(configuration.getString(key));
}
/**
* Return the OrderBy property value associated with the given key, or
* {@code defaultValue} if the key cannot be resolved.
*
* @param key the property name to resolve
* @return The OrderBy property
* @throws IllegalStateException if the value cannot be mapped to the enum
*/
public OrderBy getOrderBy(String key) {
return OrderBy.valueOf(configuration.getString(key));
}
/**
* Return the String property value associated with the given key (never {@code null}).
*
* @return The String property
* @throws IllegalStateException if the key cannot be resolved
*/
public String getRequiredString(String key) throws IllegalStateException {
Optional<String> property = getString(key);
if (property.isPresent()) {
return property.get();
} else {
throw new IllegalStateException(String.format("required key [%s] not found", key));
}
}
/**
* Return the list of keys.
*
* @return the list of keys.
*/
public List<String> getKeys() {
return IteratorUtils.toList(configuration.getKeys());
}
/**
* Get the list of the keys contained in the configuration that match the
* specified prefix. For instance, if the configuration contains the
* following keys:<br>
* {@code swagger2markup.extensions.folder1, swagger2markup.extensions.folder2, swagger2markup.folder3},<br>
* an invocation of {@code getKeys("swagger2markup.extensions");}<br>
* will return the key below:<br>
* {@code swagger2markup.extensions.folder1, swagger2markup.extensions.folder2}.<br>
* Note that the prefix itself is included in the result set if there is a
* matching key. The exact behavior - how the prefix is actually
* interpreted - depends on a concrete implementation.
*
* @param prefix The prefix to test against.
* @return the list of keys.
*/
public List<String> getKeys(String prefix) {
return IteratorUtils.toList(configuration.getKeys(prefix));
}
public List<PageBreakLocations> getPageBreakLocations(String key) {
List result = configuration.getList(PageBreakLocations.class, key);
if(result == null) result = new ArrayList<PageBreakLocations>();
return result;
}
public Optional<Pattern> getHeaderPattern(String key) {
Optional<String> property = getString(key);
if (property.isPresent()) {
return Optional.of(Pattern.compile(property.get()));
} else {
return Optional.empty();
}
}
}

View File

@@ -0,0 +1,744 @@
/*
* Copyright 2016 Robert Winkler
* Modified December 12 2016 by Cas Eliëns
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.swagger2markup.builder;
import com.google.common.collect.Ordering;
import io.github.swagger2markup.*;
import io.github.swagger2markup.Swagger2MarkupProperties;
import io.github.swagger2markup.markup.builder.LineSeparator;
import io.github.swagger2markup.markup.builder.MarkupLanguage;
import io.github.swagger2markup.model.PathOperation;
import io.swagger.models.HttpMethod;
import io.swagger.models.parameters.Parameter;
import org.apache.commons.configuration2.*;
import org.apache.commons.configuration2.builder.fluent.Configurations;
import org.apache.commons.configuration2.ex.ConfigurationException;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import java.util.*;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import static io.github.swagger2markup.Swagger2MarkupProperties.*;
public class Swagger2MarkupConfigBuilder {
static final Ordering<PathOperation> OPERATION_METHOD_NATURAL_ORDERING = Ordering
.explicit(HttpMethod.POST, HttpMethod.GET, HttpMethod.PUT, HttpMethod.DELETE, HttpMethod.PATCH, HttpMethod.HEAD, HttpMethod.OPTIONS)
.onResultOf(PathOperation::getMethod);
static final Ordering<PathOperation> OPERATION_PATH_NATURAL_ORDERING = Ordering
.natural()
.onResultOf(PathOperation::getPath);
static final Ordering<Parameter> PARAMETER_IN_NATURAL_ORDERING = Ordering
.explicit("header", "path", "query", "formData", "body")
.onResultOf(Parameter::getIn);
static final Ordering<Parameter> PARAMETER_NAME_NATURAL_ORDERING = Ordering
.natural()
.onResultOf(Parameter::getName);
private static final String PROPERTIES_DEFAULT = "io/github/swagger2markup/config/default.properties";
DefaultSwagger2MarkupConfig config = new DefaultSwagger2MarkupConfig();
public Swagger2MarkupConfigBuilder() {
this(new PropertiesConfiguration());
}
public Swagger2MarkupConfigBuilder(Properties properties) {
this(ConfigurationConverter.getConfiguration(properties));
}
public Swagger2MarkupConfigBuilder(Map<String, String> map) {
this(new MapConfiguration(map));
}
public Swagger2MarkupConfigBuilder(Configuration configuration) {
CompositeConfiguration compositeConfiguration = new CompositeConfiguration();
compositeConfiguration.addConfiguration(new SystemConfiguration());
compositeConfiguration.addConfiguration(configuration);
compositeConfiguration.addConfiguration(getDefaultConfiguration());
Swagger2MarkupProperties swagger2MarkupProperties = new Swagger2MarkupProperties(compositeConfiguration);
config.markupLanguage = swagger2MarkupProperties.getRequiredMarkupLanguage(MARKUP_LANGUAGE);
config.swaggerMarkupLanguage = swagger2MarkupProperties.getRequiredMarkupLanguage(SWAGGER_MARKUP_LANGUAGE);
config.generatedExamplesEnabled = swagger2MarkupProperties.getRequiredBoolean(GENERATED_EXAMPLES_ENABLED);
config.basePathPrefixEnabled = swagger2MarkupProperties.getRequiredBoolean(BASE_PATH_PREFIX_ENABLED);
config.separatedDefinitionsEnabled = swagger2MarkupProperties.getRequiredBoolean(SEPARATED_DEFINITIONS_ENABLED);
config.separatedOperationsEnabled = swagger2MarkupProperties.getRequiredBoolean(SEPARATED_OPERATIONS_ENABLED);
config.pathsGroupedBy = swagger2MarkupProperties.getGroupBy(PATHS_GROUPED_BY);
config.outputLanguage = swagger2MarkupProperties.getLanguage(OUTPUT_LANGUAGE);
config.inlineSchemaEnabled = swagger2MarkupProperties.getRequiredBoolean(INLINE_SCHEMA_ENABLED);
config.interDocumentCrossReferencesEnabled = swagger2MarkupProperties.getRequiredBoolean(INTER_DOCUMENT_CROSS_REFERENCES_ENABLED);
config.interDocumentCrossReferencesPrefix = swagger2MarkupProperties.getString(INTER_DOCUMENT_CROSS_REFERENCES_PREFIX, null);
config.flatBodyEnabled = swagger2MarkupProperties.getRequiredBoolean(FLAT_BODY_ENABLED);
config.pathSecuritySectionEnabled = swagger2MarkupProperties.getRequiredBoolean(PATH_SECURITY_SECTION_ENABLED);
config.anchorPrefix = swagger2MarkupProperties.getString(ANCHOR_PREFIX, null);
config.overviewDocument = swagger2MarkupProperties.getRequiredString(OVERVIEW_DOCUMENT);
config.pathsDocument = swagger2MarkupProperties.getRequiredString(PATHS_DOCUMENT);
config.definitionsDocument = swagger2MarkupProperties.getRequiredString(DEFINITIONS_DOCUMENT);
config.securityDocument = swagger2MarkupProperties.getRequiredString(SECURITY_DOCUMENT);
config.separatedOperationsFolder = swagger2MarkupProperties.getRequiredString(SEPARATED_OPERATIONS_FOLDER);
config.separatedDefinitionsFolder = swagger2MarkupProperties.getRequiredString(SEPARATED_DEFINITIONS_FOLDER);
config.tagOrderBy = swagger2MarkupProperties.getOrderBy(TAG_ORDER_BY);
config.operationOrderBy = swagger2MarkupProperties.getOrderBy(OPERATION_ORDER_BY);
config.definitionOrderBy = swagger2MarkupProperties.getOrderBy(DEFINITION_ORDER_BY);
config.parameterOrderBy = swagger2MarkupProperties.getOrderBy(PARAMETER_ORDER_BY);
config.propertyOrderBy = swagger2MarkupProperties.getOrderBy(PROPERTY_ORDER_BY);
config.responseOrderBy = swagger2MarkupProperties.getOrderBy(RESPONSE_ORDER_BY);
Optional<String> lineSeparator = swagger2MarkupProperties.getString(LINE_SEPARATOR);
if (lineSeparator.isPresent() && StringUtils.isNoneBlank(lineSeparator.get())) {
config.lineSeparator = LineSeparator.valueOf(lineSeparator.get());
}
config.pageBreakLocations = swagger2MarkupProperties.getPageBreakLocations(PAGE_BREAK_LOCATIONS);
Optional<Pattern> headerPattern = swagger2MarkupProperties.getHeaderPattern(HEADER_REGEX);
config.headerPattern = headerPattern.orElse(null);
Configuration swagger2markupConfiguration = compositeConfiguration.subset(PROPERTIES_PREFIX);
Configuration extensionsConfiguration = swagger2markupConfiguration.subset(EXTENSION_PREFIX);
config.extensionsProperties = new Swagger2MarkupProperties(extensionsConfiguration);
}
/**
* Loads the default properties from the classpath.
*
* @return the default properties
*/
private Configuration getDefaultConfiguration() {
Configurations configs = new Configurations();
try {
return configs.properties(PROPERTIES_DEFAULT);
} catch (ConfigurationException e) {
throw new RuntimeException(String.format("Can't load default properties '%s'", PROPERTIES_DEFAULT), e);
}
}
/**
* Builds the Swagger2MarkupConfig.
*
* @return the Swagger2MarkupConfig
*/
public Swagger2MarkupConfig build() {
buildNaturalOrdering();
return config;
}
private void buildNaturalOrdering() {
if (config.tagOrderBy == OrderBy.NATURAL)
config.tagOrdering = Ordering.natural();
if (config.operationOrderBy == OrderBy.NATURAL)
config.operationOrdering = OPERATION_PATH_NATURAL_ORDERING.compound(OPERATION_METHOD_NATURAL_ORDERING);
if (config.definitionOrderBy == OrderBy.NATURAL)
config.definitionOrdering = Ordering.natural();
if (config.parameterOrderBy == OrderBy.NATURAL)
config.parameterOrdering = PARAMETER_IN_NATURAL_ORDERING.compound(PARAMETER_NAME_NATURAL_ORDERING);
if (config.propertyOrderBy == OrderBy.NATURAL)
config.propertyOrdering = Ordering.natural();
if (config.responseOrderBy == OrderBy.NATURAL)
config.responseOrdering = Ordering.natural();
}
/**
* Specifies the markup language which should be used to generate the files.
*
* @param markupLanguage the markup language which is used to generate the files
* @return this builder
*/
public Swagger2MarkupConfigBuilder withMarkupLanguage(MarkupLanguage markupLanguage) {
Validate.notNull(markupLanguage, "%s must not be null", "markupLanguage");
config.markupLanguage = markupLanguage;
return this;
}
/**
* Specifies the markup language used in Swagger descriptions.
*
* @param swaggerMarkupLanguage the markup language used in Swagger descriptions
* @return this builder
*/
public Swagger2MarkupConfigBuilder withSwaggerMarkupLanguage(MarkupLanguage swaggerMarkupLanguage) {
Validate.notNull(swaggerMarkupLanguage, "%s must not be null", "swaggerMarkupLanguage");
config.swaggerMarkupLanguage = swaggerMarkupLanguage;
return this;
}
/**
* Include generated examples into the documents.
*
* @return this builder
*/
public Swagger2MarkupConfigBuilder withGeneratedExamples() {
config.generatedExamplesEnabled = true;
return this;
}
/**
* In addition to the Definitions file, also create separate definition files for each model definition.
*
* @return this builder
*/
public Swagger2MarkupConfigBuilder withSeparatedDefinitions() {
config.separatedDefinitionsEnabled = true;
return this;
}
/**
* In addition to the Paths file, also create separate operation files for each operation.
*
* @return this builder
*/
public Swagger2MarkupConfigBuilder withSeparatedOperations() {
config.separatedOperationsEnabled = true;
return this;
}
/**
* Specifies if the paths should be grouped by tags or stay as-is.
*
* @param pathsGroupedBy the GroupBy enum
* @return this builder
*/
public Swagger2MarkupConfigBuilder withPathsGroupedBy(GroupBy pathsGroupedBy) {
Validate.notNull(pathsGroupedBy, "%s must not be null", "pathsGroupedBy");
config.pathsGroupedBy = pathsGroupedBy;
return this;
}
/**
* Specifies the regex pattern to use for grouping paths.
*
* @param headerRegex regex pattern string containing one capture group
* @return this builder
* @throws PatternSyntaxException when pattern cannot be compiled
*/
public Swagger2MarkupConfigBuilder withHeaderRegex(String headerRegex) {
Validate.notNull(headerRegex, "%s must not be null", headerRegex);
config.headerPattern = Pattern.compile(headerRegex);
return this;
}
/**
* Specifies labels language of output files.
*
* @param language the enum
* @return this builder
*/
public Swagger2MarkupConfigBuilder withOutputLanguage(Language language) {
Validate.notNull(language, "%s must not be null", "language");
config.outputLanguage = language;
return this;
}
/**
* Disable inline schema support.
*
* @return this builder
*/
public Swagger2MarkupConfigBuilder withoutInlineSchema() {
config.inlineSchemaEnabled = false;
return this;
}
/**
* Specifies tag ordering.<br>
* By default tag ordering == {@link io.github.swagger2markup.OrderBy#NATURAL}.<br>
* Use {@link #withTagOrdering(Comparator)} to set a custom ordering.
*
* @param orderBy tag ordering
* @return this builder
*/
public Swagger2MarkupConfigBuilder withTagOrdering(OrderBy orderBy) {
Validate.notNull(orderBy, "%s must not be null", "orderBy");
Validate.isTrue(orderBy != OrderBy.CUSTOM, "You must provide a custom comparator if orderBy == OrderBy.CUSTOM");
config.tagOrderBy = orderBy;
return this;
}
/**
* Specifies a custom comparator function to order tags.
*
* @param tagOrdering tag ordering
* @return this builder
*/
public Swagger2MarkupConfigBuilder withTagOrdering(Comparator<String> tagOrdering) {
Validate.notNull(tagOrdering, "%s must not be null", "tagOrdering");
config.tagOrderBy = OrderBy.CUSTOM;
config.tagOrdering = tagOrdering;
return this;
}
/**
* Specifies operation ordering.<br>
* By default operation ordering == {@link io.github.swagger2markup.OrderBy#AS_IS}.<br>
* Use {@link #withOperationOrdering(Comparator)} to set a custom ordering.
*
* @param orderBy operation ordering
* @return this builder
*/
public Swagger2MarkupConfigBuilder withOperationOrdering(OrderBy orderBy) {
Validate.notNull(orderBy, "%s must not be null", "orderBy");
Validate.isTrue(orderBy != OrderBy.CUSTOM, "You must provide a custom comparator if orderBy == OrderBy.CUSTOM");
config.operationOrderBy = orderBy;
return this;
}
/**
* Specifies a custom comparator function to order operations.
*
* @param operationOrdering operation ordering
* @return this builder
*/
public Swagger2MarkupConfigBuilder withOperationOrdering(Comparator<PathOperation> operationOrdering) {
Validate.notNull(operationOrdering, "%s must not be null", "operationOrdering");
config.operationOrderBy = OrderBy.CUSTOM;
config.operationOrdering = operationOrdering;
return this;
}
/**
* Specifies definition ordering.<br>
* By default definition ordering == {@link io.github.swagger2markup.OrderBy#NATURAL}.<br>
* Use {@link #withDefinitionOrdering(Comparator)} to set a custom ordering.
*
* @param orderBy definition ordering
* @return this builder
*/
public Swagger2MarkupConfigBuilder withDefinitionOrdering(OrderBy orderBy) {
Validate.notNull(orderBy, "%s must not be null", "orderBy");
Validate.isTrue(orderBy != OrderBy.CUSTOM, "You must provide a custom comparator if orderBy == OrderBy.CUSTOM");
config.definitionOrderBy = orderBy;
return this;
}
/**
* Specifies a custom comparator function to order definitions.
*
* @param definitionOrdering definition ordering
* @return this builder
*/
public Swagger2MarkupConfigBuilder withDefinitionOrdering(Comparator<String> definitionOrdering) {
Validate.notNull(definitionOrdering, "%s must not be null", "definitionOrdering");
config.definitionOrderBy = OrderBy.CUSTOM;
config.definitionOrdering = definitionOrdering;
return this;
}
/**
* Specifies parameter ordering.<br>
* By default parameter ordering == {@link OrderBy#NATURAL}.<br>
* Use {@link #withParameterOrdering(Comparator)} to set a custom ordering.
*
* @param orderBy parameter ordering
* @return this builder
*/
public Swagger2MarkupConfigBuilder withParameterOrdering(OrderBy orderBy) {
Validate.notNull(orderBy, "%s must not be null", "orderBy");
Validate.isTrue(orderBy != OrderBy.CUSTOM, "You must provide a custom comparator if orderBy == OrderBy.CUSTOM");
config.parameterOrderBy = orderBy;
return this;
}
/**
* Specifies a custom comparator function to order parameters.
*
* @param parameterOrdering parameter ordering
* @return this builder
*/
public Swagger2MarkupConfigBuilder withParameterOrdering(Comparator<Parameter> parameterOrdering) {
Validate.notNull(parameterOrdering, "%s must not be null", "parameterOrdering");
config.parameterOrderBy = OrderBy.CUSTOM;
config.parameterOrdering = parameterOrdering;
return this;
}
/**
* Specifies property ordering.<br>
* By default property ordering == {@link io.github.swagger2markup.OrderBy#NATURAL}.<br>
* Use {@link #withPropertyOrdering(Comparator)} to set a custom ordering.
*
* @param orderBy property ordering
* @return this builder
*/
public Swagger2MarkupConfigBuilder withPropertyOrdering(OrderBy orderBy) {
Validate.notNull(orderBy, "%s must not be null", "orderBy");
Validate.isTrue(orderBy != OrderBy.CUSTOM, "You must provide a custom comparator if orderBy == OrderBy.CUSTOM");
config.propertyOrderBy = orderBy;
return this;
}
/**
* Specifies a custom comparator function to order properties.
*
* @param propertyOrdering property ordering
* @return this builder
*/
public Swagger2MarkupConfigBuilder withPropertyOrdering(Comparator<String> propertyOrdering) {
Validate.notNull(propertyOrdering, "%s must not be null", "propertyOrdering");
config.propertyOrderBy = OrderBy.CUSTOM;
config.propertyOrdering = propertyOrdering;
return this;
}
/**
* Specifies response ordering.<br>
* By default response ordering == {@link io.github.swagger2markup.OrderBy#NATURAL}.<br>
* Use {@link #withResponseOrdering(Comparator)} to set a custom ordering.
*
* @param orderBy response ordering
* @return this builder
*/
public Swagger2MarkupConfigBuilder withResponseOrdering(OrderBy orderBy) {
Validate.notNull(orderBy, "%s must not be null", "orderBy");
Validate.isTrue(orderBy != OrderBy.CUSTOM, "You must provide a custom comparator if orderBy == OrderBy.CUSTOM");
config.responseOrderBy = orderBy;
return this;
}
/**
* Specifies a custom comparator function to order responses.
*
* @param responseOrdering response ordering
* @return this builder
*/
public Swagger2MarkupConfigBuilder withResponseOrdering(Comparator<String> responseOrdering) {
Validate.notNull(responseOrdering, "%s must not be null", "responseOrdering");
config.responseOrderBy = OrderBy.CUSTOM;
config.responseOrdering = responseOrdering;
return this;
}
/**
* Enable use of inter-document cross-references when needed.
*
* @param prefix Prefix to document in all inter-document cross-references.
* @return this builder
*/
public Swagger2MarkupConfigBuilder withInterDocumentCrossReferences(String prefix) {
Validate.notNull(prefix, "%s must not be null", "prefix");
config.interDocumentCrossReferencesEnabled = true;
config.interDocumentCrossReferencesPrefix = prefix;
return this;
}
/**
* Enable use of inter-document cross-references when needed.
*
* @return this builder
*/
public Swagger2MarkupConfigBuilder withInterDocumentCrossReferences() {
config.interDocumentCrossReferencesEnabled = true;
return this;
}
/**
* Optionally isolate the body parameter, if any, from other parameters.
*
* @return this builder
*/
public Swagger2MarkupConfigBuilder withFlatBody() {
config.flatBodyEnabled = true;
return this;
}
/**
* Optionally disable the security section for path sections
*
* @return this builder
*/
public Swagger2MarkupConfigBuilder withoutPathSecuritySection() {
config.pathSecuritySectionEnabled = false;
return this;
}
/**
* Prepend the base path to all paths.
*
* @return this builder
*/
public Swagger2MarkupConfigBuilder withBasePathPrefix() {
config.basePathPrefixEnabled = true;
return this;
}
/**
* Optionally prefix all anchors for uniqueness.
*
* @param anchorPrefix anchor prefix.
* @return this builder
*/
public Swagger2MarkupConfigBuilder withAnchorPrefix(String anchorPrefix) {
Validate.notNull(anchorPrefix, "%s must not be null", "anchorPrefix");
config.anchorPrefix = anchorPrefix;
return this;
}
/**
* Set the page break locations
*
* @param locations List of locations to create new pages
* @return this builder
*/
public Swagger2MarkupConfigBuilder withPageBreaks(List<PageBreakLocations> locations) {
Validate.notNull(locations, "%s must not be null", "locations");
config.pageBreakLocations = locations;
return this;
}
/**
* Specifies the line separator which should be used.
*
* @param lineSeparator the lineSeparator
* @return this builder
*/
public Swagger2MarkupConfigBuilder withLineSeparator(LineSeparator lineSeparator) {
Validate.notNull(lineSeparator, "%s must no be null", "lineSeparator");
config.lineSeparator = lineSeparator;
return this;
}
static class DefaultSwagger2MarkupConfig implements Swagger2MarkupConfig {
private MarkupLanguage markupLanguage;
private MarkupLanguage swaggerMarkupLanguage;
private boolean generatedExamplesEnabled;
private boolean basePathPrefixEnabled;
private boolean separatedDefinitionsEnabled;
private boolean separatedOperationsEnabled;
private GroupBy pathsGroupedBy;
private Language outputLanguage;
private boolean inlineSchemaEnabled;
private OrderBy tagOrderBy;
private Comparator<String> tagOrdering;
private OrderBy operationOrderBy;
private Comparator<PathOperation> operationOrdering;
private OrderBy definitionOrderBy;
private Comparator<String> definitionOrdering;
private OrderBy parameterOrderBy;
private Comparator<Parameter> parameterOrdering;
private OrderBy propertyOrderBy;
private Comparator<String> propertyOrdering;
private OrderBy responseOrderBy;
private Comparator<String> responseOrdering;
private boolean interDocumentCrossReferencesEnabled;
private String interDocumentCrossReferencesPrefix;
private boolean flatBodyEnabled;
private boolean pathSecuritySectionEnabled;
private String anchorPrefix;
private LineSeparator lineSeparator;
private String overviewDocument;
private String pathsDocument;
private String definitionsDocument;
private String securityDocument;
private String separatedOperationsFolder;
private String separatedDefinitionsFolder;
private List<PageBreakLocations> pageBreakLocations;
private Pattern headerPattern;
private Swagger2MarkupProperties extensionsProperties;
@Override
public MarkupLanguage getMarkupLanguage() {
return markupLanguage;
}
@Override
public MarkupLanguage getSwaggerMarkupLanguage() {
return swaggerMarkupLanguage;
}
@Override
public boolean isGeneratedExamplesEnabled() {
return generatedExamplesEnabled;
}
@Override
public boolean isSeparatedDefinitionsEnabled() {
return separatedDefinitionsEnabled;
}
@Override
public boolean isSeparatedOperationsEnabled() {
return separatedOperationsEnabled;
}
@Override
public GroupBy getPathsGroupedBy() {
return pathsGroupedBy;
}
@Override
public Language getOutputLanguage() {
return outputLanguage;
}
@Override
public boolean isInlineSchemaEnabled() {
return inlineSchemaEnabled;
}
@Override
public OrderBy getTagOrderBy() {
return tagOrderBy;
}
@Override
public Pattern getHeaderPattern() {
return headerPattern;
}
@Override
public Comparator<String> getTagOrdering() {
return tagOrdering;
}
@Override
public OrderBy getOperationOrderBy() {
return operationOrderBy;
}
@Override
public Comparator<PathOperation> getOperationOrdering() {
return operationOrdering;
}
@Override
public OrderBy getDefinitionOrderBy() {
return definitionOrderBy;
}
@Override
public Comparator<String> getDefinitionOrdering() {
return definitionOrdering;
}
@Override
public OrderBy getParameterOrderBy() {
return parameterOrderBy;
}
@Override
public Comparator<Parameter> getParameterOrdering() {
return parameterOrdering;
}
@Override
public OrderBy getPropertyOrderBy() {
return propertyOrderBy;
}
@Override
public Comparator<String> getPropertyOrdering() {
return propertyOrdering;
}
@Override
public OrderBy getResponseOrderBy() {
return responseOrderBy;
}
@Override
public Comparator<String> getResponseOrdering() {
return responseOrdering;
}
@Override
public boolean isInterDocumentCrossReferencesEnabled() {
return interDocumentCrossReferencesEnabled;
}
@Override
public String getInterDocumentCrossReferencesPrefix() {
return interDocumentCrossReferencesPrefix;
}
@Override
public boolean isFlatBodyEnabled() {
return flatBodyEnabled;
}
@Override
public boolean isPathSecuritySectionEnabled() {
return pathSecuritySectionEnabled;
}
@Override
public String getAnchorPrefix() {
return anchorPrefix;
}
@Override
public String getOverviewDocument() {
return overviewDocument;
}
@Override
public String getPathsDocument() {
return pathsDocument;
}
@Override
public String getDefinitionsDocument() {
return definitionsDocument;
}
@Override
public String getSecurityDocument() {
return securityDocument;
}
@Override
public String getSeparatedOperationsFolder() {
return separatedOperationsFolder;
}
@Override
public String getSeparatedDefinitionsFolder() {
return separatedDefinitionsFolder;
}
@Override
public LineSeparator getLineSeparator() {
return lineSeparator;
}
@Override
public Swagger2MarkupProperties getExtensionsProperties() {
return extensionsProperties;
}
@Override
public boolean isBasePathPrefixEnabled() {
return basePathPrefixEnabled;
}
@Override
public List<PageBreakLocations> getPageBreakLocations() {
return pageBreakLocations;
}
}
}

View File

@@ -0,0 +1,128 @@
/*
* Copyright 2016 Robert Winkler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.swagger2markup.builder;
import io.github.swagger2markup.Swagger2MarkupExtensionRegistry;
import io.github.swagger2markup.spi.*;
import java.util.List;
import static java.util.ServiceLoader.load;
import static org.apache.commons.collections4.IteratorUtils.toList;
public class Swagger2MarkupExtensionRegistryBuilder {
private final Context context;
public Swagger2MarkupExtensionRegistryBuilder() {
List<SwaggerModelExtension> swaggerModelExtensions = toList(load(SwaggerModelExtension.class).iterator());
List<OverviewDocumentExtension> overviewDocumentExtensions = toList(load(OverviewDocumentExtension.class).iterator());
List<DefinitionsDocumentExtension> definitionsDocumentExtensions = toList(load(DefinitionsDocumentExtension.class).iterator());
List<PathsDocumentExtension> pathsDocumentExtensions = toList(load(PathsDocumentExtension.class).iterator());
List<SecurityDocumentExtension> securityDocumentExtensions = toList(load(SecurityDocumentExtension.class).iterator());
context = new Context(
swaggerModelExtensions,
overviewDocumentExtensions,
definitionsDocumentExtensions,
pathsDocumentExtensions,
securityDocumentExtensions);
}
public Swagger2MarkupExtensionRegistry build() {
return new DefaultSwagger2MarkupExtensionRegistry(context);
}
public Swagger2MarkupExtensionRegistryBuilder withSwaggerModelExtension(SwaggerModelExtension extension) {
context.swaggerModelExtensions.add(extension);
return this;
}
public Swagger2MarkupExtensionRegistryBuilder withOverviewDocumentExtension(OverviewDocumentExtension extension) {
context.overviewDocumentExtensions.add(extension);
return this;
}
public Swagger2MarkupExtensionRegistryBuilder withDefinitionsDocumentExtension(DefinitionsDocumentExtension extension) {
context.definitionsDocumentExtensions.add(extension);
return this;
}
public Swagger2MarkupExtensionRegistryBuilder withPathsDocumentExtension(PathsDocumentExtension extension) {
context.pathsDocumentExtensions.add(extension);
return this;
}
public Swagger2MarkupExtensionRegistryBuilder withSecurityDocumentExtension(SecurityDocumentExtension extension) {
context.securityDocumentExtensions.add(extension);
return this;
}
static class DefaultSwagger2MarkupExtensionRegistry implements Swagger2MarkupExtensionRegistry {
private Context context;
DefaultSwagger2MarkupExtensionRegistry(Context context) {
this.context = context;
}
@Override
public List<SwaggerModelExtension> getSwaggerModelExtensions() {
return context.swaggerModelExtensions;
}
@Override
public List<OverviewDocumentExtension> getOverviewDocumentExtensions() {
return context.overviewDocumentExtensions;
}
@Override
public List<DefinitionsDocumentExtension> getDefinitionsDocumentExtensions() {
return context.definitionsDocumentExtensions;
}
@Override
public List<SecurityDocumentExtension> getSecurityDocumentExtensions() {
return context.securityDocumentExtensions;
}
@Override
public List<PathsDocumentExtension> getPathsDocumentExtensions() {
return context.pathsDocumentExtensions;
}
}
private static class Context {
public final List<SwaggerModelExtension> swaggerModelExtensions;
public final List<OverviewDocumentExtension> overviewDocumentExtensions;
public final List<DefinitionsDocumentExtension> definitionsDocumentExtensions;
public final List<PathsDocumentExtension> pathsDocumentExtensions;
public final List<SecurityDocumentExtension> securityDocumentExtensions;
public Context(List<SwaggerModelExtension> swaggerModelExtensions,
List<OverviewDocumentExtension> overviewDocumentExtensions,
List<DefinitionsDocumentExtension> definitionsDocumentExtensions,
List<PathsDocumentExtension> pathsDocumentExtensions,
List<SecurityDocumentExtension> securityDocumentExtensions) {
this.swaggerModelExtensions = swaggerModelExtensions;
this.overviewDocumentExtensions = overviewDocumentExtensions;
this.definitionsDocumentExtensions = definitionsDocumentExtensions;
this.pathsDocumentExtensions = pathsDocumentExtensions;
this.securityDocumentExtensions = securityDocumentExtensions;
}
}
}

View File

@@ -0,0 +1,205 @@
/*
* Copyright 2016 Robert Winkler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.swagger2markup.internal.adapter;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.github.swagger2markup.Swagger2MarkupConfig;
import io.github.swagger2markup.Swagger2MarkupConverter;
import io.github.swagger2markup.internal.resolver.DocumentResolver;
import io.github.swagger2markup.internal.type.*;
import io.github.swagger2markup.internal.utils.InlineSchemaUtils;
import io.github.swagger2markup.internal.utils.ModelUtils;
import io.github.swagger2markup.markup.builder.MarkupDocBuilder;
import io.github.swagger2markup.model.PathOperation;
import io.swagger.models.Model;
import io.swagger.models.parameters.AbstractSerializableParameter;
import io.swagger.models.parameters.BodyParameter;
import io.swagger.models.parameters.Parameter;
import io.swagger.models.parameters.RefParameter;
import io.swagger.util.Json;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.Validate;
import org.apache.commons.lang3.text.WordUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import static io.github.swagger2markup.internal.utils.MarkupDocBuilderUtils.*;
public class ParameterAdapter {
private final Parameter parameter;
private final List<ObjectType> inlineDefinitions = new ArrayList<>();
private final Swagger2MarkupConfig config;
private Type type;
public ParameterAdapter(Swagger2MarkupConverter.Context context,
PathOperation operation,
Parameter parameter,
DocumentResolver definitionDocumentResolver) {
Validate.notNull(parameter, "parameter must not be null");
this.parameter = parameter;
type = getType(context.getSwagger().getDefinitions(), definitionDocumentResolver);
config = context.getConfig();
if (config.isInlineSchemaEnabled()) {
if (config.isFlatBodyEnabled()) {
if (!(type instanceof ObjectType)) {
type = InlineSchemaUtils.createInlineType(type, parameter.getName(), operation.getId() + " " + parameter.getName(), inlineDefinitions);
}
} else {
type = InlineSchemaUtils.createInlineType(type, parameter.getName(), operation.getId() + " " + parameter.getName(), inlineDefinitions);
}
}
}
/**
* Generate a default example value for parameter.
*
* @param parameter parameter
* @return a generated example for the parameter
*/
public static Object generateExample(AbstractSerializableParameter parameter) {
switch (parameter.getType()) {
case "integer":
return 0;
case "number":
return 0.0;
case "boolean":
return true;
case "string":
return "string";
default:
return parameter.getType();
}
}
@JsonIgnore
public String getAccess() {
return parameter.getAccess();
}
public String getName() {
return parameter.getName();
}
public String getUniqueName() {
return type.getUniqueName();
}
public String displaySchema(MarkupDocBuilder docBuilder) {
return type.displaySchema(docBuilder);
}
public String displayDefaultValue(MarkupDocBuilder docBuilder) {
return getDefaultValue().map(value -> literalText(docBuilder, Json.pretty(value))).orElse("");
}
public String displayDescription(MarkupDocBuilder markupDocBuilder) {
return markupDescription(config.getSwaggerMarkupLanguage(), markupDocBuilder, getDescription());
}
public String displayType(MarkupDocBuilder markupDocBuilder) {
return boldText(markupDocBuilder, getIn());
}
public String getDescription() {
return parameter.getDescription();
}
public boolean getRequired() {
return parameter.getRequired();
}
public String getPattern() {
return parameter.getPattern();
}
public Map<String, Object> getVendorExtensions() {
return parameter.getVendorExtensions();
}
public String getIn() {
return WordUtils.capitalize(parameter.getIn());
}
public Type getType() {
return type;
}
public List<ObjectType> getInlineDefinitions() {
return inlineDefinitions;
}
/**
* Retrieves the type of a parameter, or otherwise null
*
* @param definitionDocumentResolver the definition document resolver
* @return the type of the parameter, or otherwise null
*/
private Type getType(Map<String, Model> definitions, DocumentResolver definitionDocumentResolver) {
Validate.notNull(parameter, "parameter must not be null!");
Type type = null;
if (parameter instanceof BodyParameter) {
BodyParameter bodyParameter = (BodyParameter) parameter;
Model model = bodyParameter.getSchema();
if (model != null) {
type = ModelUtils.getType(model, definitions, definitionDocumentResolver);
} else {
type = new BasicType("string", bodyParameter.getName());
}
} else if (parameter instanceof AbstractSerializableParameter) {
AbstractSerializableParameter serializableParameter = (AbstractSerializableParameter) parameter;
@SuppressWarnings("unchecked")
List<String> enums = serializableParameter.getEnum();
if (CollectionUtils.isNotEmpty(enums)) {
type = new EnumType(serializableParameter.getName(), enums);
} else {
type = new BasicType(serializableParameter.getType(), serializableParameter.getName(), serializableParameter.getFormat());
}
if (serializableParameter.getType().equals("array")) {
String collectionFormat = serializableParameter.getCollectionFormat();
type = new ArrayType(serializableParameter.getName(), new PropertyAdapter(serializableParameter.getItems()).getType(definitionDocumentResolver), collectionFormat);
}
} else if (parameter instanceof RefParameter) {
String refName = ((RefParameter) parameter).getSimpleRef();
type = new RefType(definitionDocumentResolver.apply(refName), new ObjectType(refName, null /* FIXME, not used for now */));
}
return type;
}
/**
* Retrieves the default value of a parameter
*
* @return the default value of the parameter
*/
public Optional<String> getDefaultValue() {
Validate.notNull(parameter, "parameter must not be null!");
if (parameter instanceof AbstractSerializableParameter) {
AbstractSerializableParameter serializableParameter = (AbstractSerializableParameter) parameter;
return Optional.ofNullable(serializableParameter.getDefaultValue());
}
return Optional.empty();
}
}

View File

@@ -0,0 +1,331 @@
/*
* Copyright 2016 Robert Winkler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.swagger2markup.internal.adapter;
import io.github.swagger2markup.internal.resolver.DocumentResolver;
import io.github.swagger2markup.internal.type.*;
import io.github.swagger2markup.markup.builder.MarkupDocBuilder;
import io.swagger.models.properties.*;
import io.swagger.models.refs.RefFormat;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.Validate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.*;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
public final class PropertyAdapter {
private final Property property;
private static Logger logger = LoggerFactory.getLogger(PropertyAdapter.class);
public PropertyAdapter(Property property) {
Validate.notNull(property, "property must not be null");
this.property = property;
}
/**
* Generate a default example value for property.
*
* @param property property
* @param markupDocBuilder doc builder
* @return a generated example for the property
*/
public static Object generateExample(Property property, MarkupDocBuilder markupDocBuilder) {
switch (property.getType()) {
case "integer":
return 0;
case "number":
return 0.0;
case "boolean":
return true;
case "string":
return "string";
case "ref":
if (property instanceof RefProperty) {
if (logger.isDebugEnabled()) logger.debug("generateExample RefProperty for " + property.getName());
return markupDocBuilder.copy(false).crossReference(((RefProperty) property).getSimpleRef()).toString();
} else {
if (logger.isDebugEnabled()) logger.debug("generateExample for ref not RefProperty");
}
default:
return property.getType();
}
}
/**
* Convert a string {@code value} to specified {@code type}.
*
* @param value value to convert
* @param type target conversion type
* @return converted value as object
*/
public static Object convertExample(String value, String type) {
if (value == null) {
return null;
}
try {
switch (type) {
case "integer":
return Integer.valueOf(value);
case "number":
return Float.valueOf(value);
case "boolean":
return Boolean.valueOf(value);
case "string":
return value;
default:
return value;
}
} catch (NumberFormatException e) {
throw new RuntimeException(String.format("Value '%s' cannot be converted to '%s'", value, type), e);
}
}
/**
* Retrieves the type and format of a property.
*
* @param definitionDocumentResolver the definition document resolver
* @return the type of the property
*/
public Type getType(DocumentResolver definitionDocumentResolver) {
Type type;
if (property instanceof RefProperty) {
RefProperty refProperty = (RefProperty) property;
if (refProperty.getRefFormat() == RefFormat.RELATIVE)
type = new ObjectType(refProperty.getTitle(), null); // FIXME : Workaround for https://github.com/swagger-api/swagger-parser/issues/177
else
type = new RefType(definitionDocumentResolver.apply(refProperty.getSimpleRef()), new ObjectType(refProperty.getSimpleRef(), null /* FIXME, not used for now */));
} else if (property instanceof ArrayProperty) {
ArrayProperty arrayProperty = (ArrayProperty) property;
Property items = arrayProperty.getItems();
if (items == null)
type = new ArrayType(arrayProperty.getTitle(), new ObjectType(null, null)); // FIXME : Workaround for Swagger parser issue with composed models (https://github.com/Swagger2Markup/swagger2markup/issues/150)
else
type = new ArrayType(arrayProperty.getTitle(), new PropertyAdapter(items).getType(definitionDocumentResolver));
} else if (property instanceof MapProperty) {
MapProperty mapProperty = (MapProperty) property;
Property additionalProperties = mapProperty.getAdditionalProperties();
if (additionalProperties == null)
type = new MapType(mapProperty.getTitle(), new ObjectType(null, null)); // FIXME : Workaround for Swagger parser issue with composed models (https://github.com/Swagger2Markup/swagger2markup/issues/150)
else
type = new MapType(mapProperty.getTitle(), new PropertyAdapter(additionalProperties).getType(definitionDocumentResolver));
} else if (property instanceof StringProperty) {
StringProperty stringProperty = (StringProperty) property;
List<String> enums = stringProperty.getEnum();
if (CollectionUtils.isNotEmpty(enums)) {
type = new EnumType(stringProperty.getTitle(), enums);
} else if (isNotBlank(stringProperty.getFormat())) {
type = new BasicType(stringProperty.getType(), stringProperty.getTitle(), stringProperty.getFormat());
} else {
type = new BasicType(stringProperty.getType(), stringProperty.getTitle());
}
} else if (property instanceof ObjectProperty) {
type = new ObjectType(property.getTitle(), ((ObjectProperty) property).getProperties());
} else {
if (isNotBlank(property.getFormat())) {
type = new BasicType(property.getType(), property.getTitle(), property.getFormat());
} else {
type = new BasicType(property.getType(), property.getTitle());
}
}
return type;
}
/**
* Retrieves the default value of a property
*
* @return the default value of the property
*/
public Optional<Object> getDefaultValue() {
if (property instanceof BooleanProperty) {
BooleanProperty booleanProperty = (BooleanProperty) property;
return Optional.ofNullable(booleanProperty.getDefault());
} else if (property instanceof StringProperty) {
StringProperty stringProperty = (StringProperty) property;
return Optional.ofNullable(stringProperty.getDefault());
} else if (property instanceof DoubleProperty) {
DoubleProperty doubleProperty = (DoubleProperty) property;
return Optional.ofNullable(doubleProperty.getDefault());
} else if (property instanceof FloatProperty) {
FloatProperty floatProperty = (FloatProperty) property;
return Optional.ofNullable(floatProperty.getDefault());
} else if (property instanceof IntegerProperty) {
IntegerProperty integerProperty = (IntegerProperty) property;
return Optional.ofNullable(integerProperty.getDefault());
} else if (property instanceof LongProperty) {
LongProperty longProperty = (LongProperty) property;
return Optional.ofNullable(longProperty.getDefault());
} else if (property instanceof UUIDProperty) {
UUIDProperty uuidProperty = (UUIDProperty) property;
return Optional.ofNullable(uuidProperty.getDefault());
}
return Optional.empty();
}
/**
* Retrieves the minLength of a property
*
* @return the minLength of the property
*/
public Optional<Integer> getMinlength() {
if (property instanceof StringProperty) {
StringProperty stringProperty = (StringProperty) property;
return Optional.ofNullable(stringProperty.getMinLength());
} else if (property instanceof UUIDProperty) {
UUIDProperty uuidProperty = (UUIDProperty) property;
return Optional.ofNullable(uuidProperty.getMinLength());
}
return Optional.empty();
}
/**
* Retrieves the maxLength of a property
*
* @return the maxLength of the property
*/
public Optional<Integer> getMaxlength() {
if (property instanceof StringProperty) {
StringProperty stringProperty = (StringProperty) property;
return Optional.ofNullable(stringProperty.getMaxLength());
} else if (property instanceof UUIDProperty) {
UUIDProperty uuidProperty = (UUIDProperty) property;
return Optional.ofNullable(uuidProperty.getMaxLength());
}
return Optional.empty();
}
/**
* Retrieves the pattern of a property
*
* @return the pattern of the property
*/
public Optional<String> getPattern() {
if (property instanceof StringProperty) {
StringProperty stringProperty = (StringProperty) property;
return Optional.ofNullable(stringProperty.getPattern());
} else if (property instanceof UUIDProperty) {
UUIDProperty uuidProperty = (UUIDProperty) property;
return Optional.ofNullable(uuidProperty.getPattern());
}
return Optional.empty();
}
/**
* Retrieves the minimum value of a property
*
* @return the minimum value of the property
*/
public Optional<Number> getMin() {
if (property instanceof BaseIntegerProperty) {
BaseIntegerProperty integerProperty = (BaseIntegerProperty) property;
return Optional.ofNullable(integerProperty.getMinimum() != null ? integerProperty.getMinimum().longValue() : null);
} else if (property instanceof AbstractNumericProperty) {
AbstractNumericProperty numericProperty = (AbstractNumericProperty) property;
return Optional.ofNullable(numericProperty.getMinimum());
}
return Optional.empty();
}
/**
* Retrieves the exclusiveMinimum value of a property
*
* @return the exclusiveMinimum value of the property
*/
public boolean getExclusiveMin() {
if (property instanceof AbstractNumericProperty) {
AbstractNumericProperty numericProperty = (AbstractNumericProperty) property;
return BooleanUtils.isTrue(numericProperty.getExclusiveMinimum());
}
return false;
}
/**
* Retrieves the minimum value of a property
*
* @return the minimum value of the property
*/
public Optional<Number> getMax() {
if (property instanceof BaseIntegerProperty) {
BaseIntegerProperty integerProperty = (BaseIntegerProperty) property;
return Optional.ofNullable(integerProperty.getMaximum() != null ? integerProperty.getMaximum().longValue() : null);
} else if (property instanceof AbstractNumericProperty) {
AbstractNumericProperty numericProperty = (AbstractNumericProperty) property;
return Optional.ofNullable(numericProperty.getMaximum());
}
return Optional.empty();
}
/**
* Retrieves the exclusiveMaximum value of a property
*
* @return the exclusiveMaximum value of the property
*/
public boolean getExclusiveMax() {
if (property instanceof AbstractNumericProperty) {
AbstractNumericProperty numericProperty = (AbstractNumericProperty) property;
return BooleanUtils.isTrue((numericProperty.getExclusiveMaximum()));
}
return false;
}
/**
* Return example display string for the given {@code property}.
*
* @param generateMissingExamples specifies if missing examples should be generated
* @param markupDocBuilder doc builder
* @return property example display string
*/
public Optional<Object> getExample(boolean generateMissingExamples, MarkupDocBuilder markupDocBuilder) {
if (property.getExample() != null) {
return Optional.ofNullable(property.getExample());
} else if (property instanceof MapProperty) {
Property additionalProperty = ((MapProperty) property).getAdditionalProperties();
if (additionalProperty.getExample() != null) {
return Optional.ofNullable(additionalProperty.getExample());
} else if (generateMissingExamples) {
Map<String, Object> exampleMap = new HashMap<>();
exampleMap.put("string", generateExample(additionalProperty, markupDocBuilder));
return Optional.of(exampleMap);
}
} else if (property instanceof ArrayProperty) {
if (generateMissingExamples) {
Property itemProperty = ((ArrayProperty) property).getItems();
List<Object> exampleArray = new ArrayList<>();
exampleArray.add(generateExample(itemProperty, markupDocBuilder));
return Optional.of(exampleArray);
}
} else if (generateMissingExamples) {
return Optional.of(generateExample(property, markupDocBuilder));
}
return Optional.empty();
}
/**
* Checks if a property is read-only.
*
* @return true if the property is read-only
*/
public boolean getReadOnly() {
return BooleanUtils.isTrue(property.getReadOnly());
}
}

View File

@@ -0,0 +1,127 @@
/*
* Copyright 2016 Robert Winkler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.swagger2markup.internal.component;
import io.github.swagger2markup.GroupBy;
import io.github.swagger2markup.Swagger2MarkupConverter;
import io.github.swagger2markup.internal.adapter.ParameterAdapter;
import io.github.swagger2markup.internal.resolver.DocumentResolver;
import io.github.swagger2markup.internal.type.ObjectType;
import io.github.swagger2markup.internal.type.Type;
import io.github.swagger2markup.markup.builder.MarkupDocBuilder;
import io.github.swagger2markup.model.PathOperation;
import io.github.swagger2markup.spi.MarkupComponent;
import io.swagger.models.parameters.Parameter;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import java.util.ArrayList;
import java.util.List;
import static io.github.swagger2markup.Labels.*;
import static io.github.swagger2markup.internal.utils.MarkupDocBuilderUtils.copyMarkupDocBuilder;
import static io.github.swagger2markup.internal.utils.MarkupDocBuilderUtils.markupDescription;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
public class BodyParameterComponent extends MarkupComponent<BodyParameterComponent.Parameters> {
private final DocumentResolver definitionDocumentResolver;
private final PropertiesTableComponent propertiesTableComponent;
public BodyParameterComponent(Swagger2MarkupConverter.Context context,
DocumentResolver definitionDocumentResolver) {
super(context);
this.definitionDocumentResolver = Validate.notNull(definitionDocumentResolver, "DocumentResolver must not be null");
this.propertiesTableComponent = new PropertiesTableComponent(context, definitionDocumentResolver);
}
public static BodyParameterComponent.Parameters parameters(PathOperation operation,
List<ObjectType> inlineDefinitions) {
return new BodyParameterComponent.Parameters(operation, inlineDefinitions);
}
@Override
public MarkupDocBuilder apply(MarkupDocBuilder markupDocBuilder, Parameters params) {
PathOperation operation = params.operation;
List<ObjectType> inlineDefinitions = params.inlineDefinitions;
if (config.isFlatBodyEnabled()) {
List<Parameter> parameters = operation.getOperation().getParameters();
if (CollectionUtils.isNotEmpty(parameters)) {
for (Parameter parameter : parameters) {
if (StringUtils.equals(parameter.getIn(), "body")) {
ParameterAdapter parameterAdapter = new ParameterAdapter(context,
operation, parameter, definitionDocumentResolver);
Type type = parameterAdapter.getType();
inlineDefinitions.addAll(parameterAdapter.getInlineDefinitions());
buildSectionTitle(markupDocBuilder, labels.getLabel(BODY_PARAMETER));
String description = parameter.getDescription();
if (isNotBlank(description)) {
markupDocBuilder.paragraph(markupDescription(config.getSwaggerMarkupLanguage(), markupDocBuilder, description));
}
MarkupDocBuilder typeInfos = copyMarkupDocBuilder(markupDocBuilder);
typeInfos.italicText(labels.getLabel(NAME_COLUMN)).textLine(COLON + parameter.getName());
typeInfos.italicText(labels.getLabel(FLAGS_COLUMN)).textLine(COLON + (BooleanUtils.isTrue(parameter.getRequired()) ? labels.getLabel(FLAGS_REQUIRED).toLowerCase() : labels.getLabel(FLAGS_OPTIONAL).toLowerCase()));
if (!(type instanceof ObjectType)) {
typeInfos.italicText(labels.getLabel(TYPE_COLUMN)).textLine(COLON + type.displaySchema(markupDocBuilder));
}
markupDocBuilder.paragraph(typeInfos.toString(), true);
if (type instanceof ObjectType) {
List<ObjectType> localDefinitions = new ArrayList<>();
propertiesTableComponent.apply(markupDocBuilder, PropertiesTableComponent.parameters(
((ObjectType) type).getProperties(),
operation.getId(),
localDefinitions
));
inlineDefinitions.addAll(localDefinitions);
}
}
}
}
}
return markupDocBuilder;
}
private void buildSectionTitle(MarkupDocBuilder markupDocBuilder, String title) {
if (config.getPathsGroupedBy() == GroupBy.AS_IS) {
markupDocBuilder.sectionTitleLevel3(title);
} else {
markupDocBuilder.sectionTitleLevel4(title);
}
}
public static class Parameters {
private final List<ObjectType> inlineDefinitions;
private PathOperation operation;
public Parameters(PathOperation operation,
List<ObjectType> inlineDefinitions) {
Validate.notNull(operation, "Operation must not be null");
this.operation = operation;
this.inlineDefinitions = inlineDefinitions;
}
}
}

View File

@@ -0,0 +1,59 @@
/*
* Copyright 2016 Robert Winkler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.swagger2markup.internal.component;
import io.github.swagger2markup.Labels;
import io.github.swagger2markup.Swagger2MarkupConverter;
import io.github.swagger2markup.markup.builder.MarkupDocBuilder;
import io.github.swagger2markup.spi.MarkupComponent;
import org.apache.commons.lang3.Validate;
import java.util.List;
import java.util.stream.Collectors;
import static io.github.swagger2markup.internal.utils.MarkupDocBuilderUtils.literalText;
public class ConsumesComponent extends MarkupComponent<ConsumesComponent.Parameters> {
public ConsumesComponent(Swagger2MarkupConverter.Context context) {
super(context);
}
public static ConsumesComponent.Parameters parameters(List<String> consumes,
int titleLevel) {
return new ConsumesComponent.Parameters(consumes, titleLevel);
}
@Override
public MarkupDocBuilder apply(MarkupDocBuilder markupDocBuilder, Parameters params) {
markupDocBuilder.sectionTitleLevel(params.titleLevel, labels.getLabel(Labels.CONSUMES));
markupDocBuilder.unorderedList(params.consumes.stream()
.map(value -> literalText(markupDocBuilder, value)).collect(Collectors.toList()));
return markupDocBuilder;
}
public static class Parameters {
private final List<String> consumes;
private final int titleLevel;
public Parameters(List<String> consumes,
int titleLevel) {
this.consumes = Validate.notNull(consumes, "Consumes must not be null");
this.titleLevel = titleLevel;
}
}
}

View File

@@ -0,0 +1,69 @@
/*
* Copyright 2016 Robert Winkler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.swagger2markup.internal.component;
import io.github.swagger2markup.Labels;
import io.github.swagger2markup.Swagger2MarkupConverter;
import io.github.swagger2markup.markup.builder.MarkupDocBuilder;
import io.github.swagger2markup.spi.MarkupComponent;
import io.swagger.models.Contact;
import org.apache.commons.lang3.Validate;
import static io.github.swagger2markup.internal.utils.MarkupDocBuilderUtils.copyMarkupDocBuilder;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
public class ContactInfoComponent extends MarkupComponent<ContactInfoComponent.Parameters> {
public ContactInfoComponent(Swagger2MarkupConverter.Context context) {
super(context);
}
public static ContactInfoComponent.Parameters parameters(Contact contact,
int titleLevel) {
return new ContactInfoComponent.Parameters(contact, titleLevel);
}
@Override
public MarkupDocBuilder apply(MarkupDocBuilder markupDocBuilder, Parameters params) {
Contact contact = params.contact;
if (isNotBlank(contact.getName()) || isNotBlank(contact.getEmail())) {
markupDocBuilder.sectionTitleLevel(params.titleLevel, labels.getLabel(Labels.CONTACT_INFORMATION));
MarkupDocBuilder paragraphBuilder = copyMarkupDocBuilder(markupDocBuilder);
if (isNotBlank(contact.getName())) {
paragraphBuilder.italicText(labels.getLabel(Labels.CONTACT_NAME))
.textLine(COLON + contact.getName());
}
if (isNotBlank(contact.getEmail())) {
paragraphBuilder.italicText(labels.getLabel(Labels.CONTACT_EMAIL))
.textLine(COLON + contact.getEmail());
}
markupDocBuilder.paragraph(paragraphBuilder.toString(), true);
}
return markupDocBuilder;
}
public static class Parameters {
private final Contact contact;
private final int titleLevel;
public Parameters(Contact contact,
int titleLevel) {
this.contact = Validate.notNull(contact, "Contact must not be null");
this.titleLevel = titleLevel;
}
}
}

View File

@@ -0,0 +1,199 @@
/*
* Copyright 2016 Robert Winkler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.swagger2markup.internal.component;
import io.github.swagger2markup.Swagger2MarkupConverter;
import io.github.swagger2markup.internal.resolver.DocumentResolver;
import io.github.swagger2markup.internal.type.ObjectType;
import io.github.swagger2markup.internal.type.ObjectTypePolymorphism;
import io.github.swagger2markup.internal.type.Type;
import io.github.swagger2markup.internal.utils.ModelUtils;
import io.github.swagger2markup.markup.builder.MarkupDocBuilder;
import io.github.swagger2markup.spi.DefinitionsDocumentExtension;
import io.github.swagger2markup.spi.MarkupComponent;
import io.swagger.models.Model;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.Validate;
import java.util.*;
import static io.github.swagger2markup.Labels.*;
import static io.github.swagger2markup.internal.utils.InlineSchemaUtils.createInlineType;
import static io.github.swagger2markup.internal.utils.MarkupDocBuilderUtils.copyMarkupDocBuilder;
import static io.github.swagger2markup.internal.utils.MarkupDocBuilderUtils.markupDescription;
import static io.github.swagger2markup.spi.DefinitionsDocumentExtension.Position;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
public class DefinitionComponent extends MarkupComponent<DefinitionComponent.Parameters> {
/* Discriminator is only displayed for inheriting definitions */
private static final boolean ALWAYS_DISPLAY_DISCRIMINATOR = false;
private final Map<String, Model> definitions;
private final Map<ObjectTypePolymorphism.Nature, String> POLYMORPHISM_NATURE;
private final DocumentResolver definitionsDocumentResolver;
private PropertiesTableComponent propertiesTableComponent;
public DefinitionComponent(Swagger2MarkupConverter.Context context,
DocumentResolver definitionsDocumentResolver) {
super(context);
this.definitions = context.getSwagger().getDefinitions();
this.definitionsDocumentResolver = definitionsDocumentResolver;
POLYMORPHISM_NATURE = new HashMap<ObjectTypePolymorphism.Nature, String>() {{
put(ObjectTypePolymorphism.Nature.COMPOSITION, labels.getLabel(POLYMORPHISM_NATURE_COMPOSITION));
put(ObjectTypePolymorphism.Nature.INHERITANCE, labels.getLabel(POLYMORPHISM_NATURE_INHERITANCE));
}};
propertiesTableComponent = new PropertiesTableComponent(context, definitionsDocumentResolver);
}
public static DefinitionComponent.Parameters parameters(String definitionName,
Model model,
int titleLevel) {
return new DefinitionComponent.Parameters(definitionName, model, titleLevel);
}
@Override
public MarkupDocBuilder apply(MarkupDocBuilder markupDocBuilder, Parameters params) {
String definitionName = params.definitionName;
Model model = params.model;
applyDefinitionsDocumentExtension(new DefinitionsDocumentExtension.Context(Position.DEFINITION_BEFORE, markupDocBuilder, definitionName, model));
markupDocBuilder.sectionTitleWithAnchorLevel(params.titleLevel, definitionName, definitionName);
applyDefinitionsDocumentExtension(new DefinitionsDocumentExtension.Context(Position.DEFINITION_BEGIN, markupDocBuilder, definitionName, model));
String description = model.getDescription();
if (isNotBlank(description)) {
markupDocBuilder.paragraph(markupDescription(config.getSwaggerMarkupLanguage(), markupDocBuilder, description));
}
inlineDefinitions(markupDocBuilder, typeSection(markupDocBuilder, definitionName, model), definitionName);
applyDefinitionsDocumentExtension(new DefinitionsDocumentExtension.Context(Position.DEFINITION_END, markupDocBuilder, definitionName, model));
applyDefinitionsDocumentExtension(new DefinitionsDocumentExtension.Context(Position.DEFINITION_AFTER, markupDocBuilder, definitionName, model));
return markupDocBuilder;
}
/**
* Builds the title of an inline schema.
* Inline definitions should never been referenced in TOC because they have no real existence, so they are just text.
*
* @param title inline schema title
* @param anchor inline schema anchor
* @param docBuilder the docbuilder do use for output
*/
private void addInlineDefinitionTitle(String title, String anchor, MarkupDocBuilder docBuilder) {
docBuilder.anchor(anchor, null);
docBuilder.newLine();
docBuilder.boldTextLine(title);
}
/**
* Builds inline schema definitions
*
* @param markupDocBuilder the docbuilder do use for output
* @param definitions all inline definitions to display
* @param uniquePrefix unique prefix to prepend to inline object names to enforce unicity
*/
private void inlineDefinitions(MarkupDocBuilder markupDocBuilder, List<ObjectType> definitions, String uniquePrefix) {
if (CollectionUtils.isNotEmpty(definitions)) {
for (ObjectType definition : definitions) {
addInlineDefinitionTitle(definition.getName(), definition.getUniqueName(), markupDocBuilder);
List<ObjectType> localDefinitions = new ArrayList<>();
propertiesTableComponent.apply(markupDocBuilder, new PropertiesTableComponent.Parameters(definition.getProperties(), uniquePrefix, localDefinitions));
for (ObjectType localDefinition : localDefinitions)
inlineDefinitions(markupDocBuilder, Collections.singletonList(localDefinition), localDefinition.getUniqueName());
}
}
}
/**
* Builds the type informations of a definition
*
* @param markupDocBuilder the docbuilder do use for output
* @param definitionName name of the definition to display
* @param model model of the definition to display
* @return a list of inlined types.
*/
private List<ObjectType> typeSection(MarkupDocBuilder markupDocBuilder, String definitionName, Model model) {
List<ObjectType> inlineDefinitions = new ArrayList<>();
Type modelType = ModelUtils.resolveRefType(ModelUtils.getType(model, definitions, definitionsDocumentResolver));
if (!(modelType instanceof ObjectType) && config.isInlineSchemaEnabled()) {
modelType = createInlineType(modelType, definitionName, definitionName + " " + "inline", inlineDefinitions);
}
if (modelType instanceof ObjectType) {
ObjectType objectType = (ObjectType) modelType;
MarkupDocBuilder typeInfos = copyMarkupDocBuilder(markupDocBuilder);
switch (objectType.getPolymorphism().getNature()) {
case COMPOSITION:
typeInfos.italicText(labels.getLabel(POLYMORPHISM_COLUMN)).textLine(COLON + POLYMORPHISM_NATURE.get(objectType.getPolymorphism().getNature()));
break;
case INHERITANCE:
typeInfos.italicText(labels.getLabel(POLYMORPHISM_COLUMN)).textLine(COLON + POLYMORPHISM_NATURE.get(objectType.getPolymorphism().getNature()));
typeInfos.italicText(labels.getLabel(POLYMORPHISM_DISCRIMINATOR_COLUMN)).textLine(COLON + objectType.getPolymorphism().getDiscriminator());
break;
case NONE:
if (ALWAYS_DISPLAY_DISCRIMINATOR && isNotBlank(objectType.getPolymorphism().getDiscriminator()))
typeInfos.italicText(labels.getLabel(POLYMORPHISM_DISCRIMINATOR_COLUMN)).textLine(COLON + objectType.getPolymorphism().getDiscriminator());
break;
default:
break;
}
String typeInfosString = typeInfos.toString();
if (isNotBlank(typeInfosString))
markupDocBuilder.paragraph(typeInfosString, true);
propertiesTableComponent.apply(markupDocBuilder,
PropertiesTableComponent.parameters(
((ObjectType) modelType).getProperties(),
definitionName,
inlineDefinitions));
} else if (modelType != null) {
MarkupDocBuilder typeInfos = copyMarkupDocBuilder(markupDocBuilder);
typeInfos.italicText(labels.getLabel(TYPE_COLUMN)).textLine(COLON + modelType.displaySchema(markupDocBuilder));
markupDocBuilder.paragraph(typeInfos.toString());
}
return inlineDefinitions;
}
/**
* Apply extension context to all DefinitionsContentExtension
*
* @param context context
*/
private void applyDefinitionsDocumentExtension(DefinitionsDocumentExtension.Context context) {
extensionRegistry.getDefinitionsDocumentExtensions().forEach(extension -> extension.apply(context));
}
public static class Parameters {
private final String definitionName;
private final Model model;
private final int titleLevel;
public Parameters(String definitionName,
Model model,
int titleLevel) {
this.definitionName = Validate.notBlank(definitionName, "DefinitionName must not be empty");
this.model = Validate.notNull(model, "Model must not be null");
this.titleLevel = titleLevel;
}
}
}

View File

@@ -0,0 +1,75 @@
/*
* Copyright 2016 Robert Winkler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.swagger2markup.internal.component;
import io.github.swagger2markup.Swagger2MarkupConverter;
import io.github.swagger2markup.markup.builder.MarkupDocBuilder;
import io.github.swagger2markup.spi.MarkupComponent;
import io.swagger.models.Info;
import io.swagger.models.License;
import org.apache.commons.lang3.Validate;
import static io.github.swagger2markup.Labels.*;
import static io.github.swagger2markup.internal.utils.MarkupDocBuilderUtils.copyMarkupDocBuilder;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
public class LicenseInfoComponent extends MarkupComponent<LicenseInfoComponent.Parameters> {
public LicenseInfoComponent(Swagger2MarkupConverter.Context context) {
super(context);
}
public static LicenseInfoComponent.Parameters parameters(Info info,
int titleLevel) {
return new LicenseInfoComponent.Parameters(info, titleLevel);
}
@Override
public MarkupDocBuilder apply(MarkupDocBuilder markupDocBuilder, Parameters params) {
Info info = params.info;
License license = info.getLicense();
String termOfService = info.getTermsOfService();
if ((license != null && (isNotBlank(license.getName()) || isNotBlank(license.getUrl()))) || isNotBlank(termOfService)) {
markupDocBuilder.sectionTitleLevel(params.titleLevel, labels.getLabel(LICENSE_INFORMATION));
MarkupDocBuilder paragraph = copyMarkupDocBuilder(markupDocBuilder);
if (license != null) {
if (isNotBlank(license.getName())) {
paragraph.italicText(labels.getLabel(LICENSE)).textLine(COLON + license.getName());
}
if (isNotBlank(license.getUrl())) {
paragraph.italicText(labels.getLabel(LICENSE_URL)).textLine(COLON + license.getUrl());
}
}
paragraph.italicText(labels.getLabel(TERMS_OF_SERVICE)).textLine(COLON + termOfService);
markupDocBuilder.paragraph(paragraph.toString(), true);
}
return markupDocBuilder;
}
public static class Parameters {
private final int titleLevel;
private final Info info;
public Parameters(Info info,
int titleLevel) {
this.info = Validate.notNull(info, "Info must not be null");
this.titleLevel = titleLevel;
}
}
}

View File

@@ -0,0 +1,166 @@
/*
* Copyright 2016 Robert Winkler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.swagger2markup.internal.component;
import ch.netzwerg.paleo.StringColumn;
import io.github.swagger2markup.Swagger2MarkupConverter;
import io.github.swagger2markup.internal.adapter.ParameterAdapter;
import io.github.swagger2markup.internal.resolver.DocumentResolver;
import io.github.swagger2markup.internal.type.ObjectType;
import io.github.swagger2markup.markup.builder.MarkupDocBuilder;
import io.github.swagger2markup.model.PathOperation;
import io.github.swagger2markup.spi.MarkupComponent;
import io.github.swagger2markup.spi.PathsDocumentExtension;
import io.swagger.models.parameters.Parameter;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import java.util.List;
import java.util.stream.Collectors;
import static ch.netzwerg.paleo.ColumnIds.StringColumnId;
import static io.github.swagger2markup.Labels.*;
import static io.github.swagger2markup.internal.utils.MarkupDocBuilderUtils.copyMarkupDocBuilder;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
public class ParameterTableComponent extends MarkupComponent<ParameterTableComponent.Parameters> {
private final DocumentResolver definitionDocumentResolver;
private final TableComponent tableComponent;
ParameterTableComponent(Swagger2MarkupConverter.Context context,
DocumentResolver definitionDocumentResolver) {
super(context);
this.definitionDocumentResolver = Validate.notNull(definitionDocumentResolver, "DocumentResolver must not be null");
this.tableComponent = new TableComponent(context);
}
public static ParameterTableComponent.Parameters parameters(PathOperation operation,
List<ObjectType> inlineDefinitions,
int titleLevel) {
return new ParameterTableComponent.Parameters(operation, inlineDefinitions, titleLevel);
}
@Override
public MarkupDocBuilder apply(MarkupDocBuilder markupDocBuilder, Parameters params) {
PathOperation operation = params.operation;
List<ObjectType> inlineDefinitions = params.inlineDefinitions;
List<Parameter> parameters = operation.getOperation().getParameters();
if (config.getParameterOrdering() != null)
parameters.sort(config.getParameterOrdering());
// Filter parameters to display in parameters section
List<Parameter> filteredParameters = parameters.stream()
.filter(this::filterParameter).collect(Collectors.toList());
MarkupDocBuilder parametersBuilder = copyMarkupDocBuilder(markupDocBuilder);
applyPathsDocumentExtension(new PathsDocumentExtension.Context(PathsDocumentExtension.Position.OPERATION_DESCRIPTION_BEGIN, parametersBuilder, operation));
if (CollectionUtils.isNotEmpty(filteredParameters)) {
StringColumn.Builder typeColumnBuilder = StringColumn.builder(StringColumnId.of(labels.getLabel(TYPE_COLUMN)))
.putMetaData(TableComponent.WIDTH_RATIO, "2");
StringColumn.Builder nameColumnBuilder = StringColumn.builder(StringColumnId.of(labels.getLabel(NAME_COLUMN)))
.putMetaData(TableComponent.WIDTH_RATIO, "3");
StringColumn.Builder descriptionColumnBuilder = StringColumn.builder(StringColumnId.of(labels.getLabel(DESCRIPTION_COLUMN)))
.putMetaData(TableComponent.WIDTH_RATIO, "9")
.putMetaData(TableComponent.HEADER_COLUMN, "true");
StringColumn.Builder schemaColumnBuilder = StringColumn.builder(StringColumnId.of(labels.getLabel(SCHEMA_COLUMN)))
.putMetaData(TableComponent.WIDTH_RATIO, "4")
.putMetaData(TableComponent.HEADER_COLUMN, "true");
StringColumn.Builder defaultColumnBuilder = StringColumn.builder(StringColumnId.of(labels.getLabel(DEFAULT_COLUMN)))
.putMetaData(TableComponent.WIDTH_RATIO, "2")
.putMetaData(TableComponent.HEADER_COLUMN, "true");
for (Parameter parameter : filteredParameters) {
ParameterAdapter parameterAdapter = new ParameterAdapter(context,
operation, parameter, definitionDocumentResolver);
inlineDefinitions.addAll(parameterAdapter.getInlineDefinitions());
typeColumnBuilder.add(parameterAdapter.displayType(markupDocBuilder));
nameColumnBuilder.add(getParameterNameColumnContent(markupDocBuilder, parameterAdapter));
descriptionColumnBuilder.add(parameterAdapter.displayDescription(markupDocBuilder));
schemaColumnBuilder.add(parameterAdapter.displaySchema(markupDocBuilder));
defaultColumnBuilder.add(parameterAdapter.displayDefaultValue(markupDocBuilder));
}
parametersBuilder = tableComponent.apply(parametersBuilder, TableComponent.parameters(
typeColumnBuilder.build(),
nameColumnBuilder.build(),
descriptionColumnBuilder.build(),
schemaColumnBuilder.build(),
defaultColumnBuilder.build()));
}
applyPathsDocumentExtension(new PathsDocumentExtension.Context(PathsDocumentExtension.Position.OPERATION_DESCRIPTION_END, parametersBuilder, operation));
String parametersContent = parametersBuilder.toString();
applyPathsDocumentExtension(new PathsDocumentExtension.Context(PathsDocumentExtension.Position.OPERATION_PARAMETERS_BEFORE, markupDocBuilder, operation));
if (isNotBlank(parametersContent)) {
markupDocBuilder.sectionTitleLevel(params.titleLevel, labels.getLabel(PARAMETERS));
markupDocBuilder.text(parametersContent);
}
applyPathsDocumentExtension(new PathsDocumentExtension.Context(PathsDocumentExtension.Position.OPERATION_PARAMETERS_AFTER, markupDocBuilder, operation));
return markupDocBuilder;
}
private String getParameterNameColumnContent(MarkupDocBuilder markupDocBuilder, ParameterAdapter parameter) {
MarkupDocBuilder parameterNameContent = copyMarkupDocBuilder(markupDocBuilder);
parameterNameContent.boldTextLine(parameter.getName(), true);
if (parameter.getRequired())
parameterNameContent.italicText(labels.getLabel(FLAGS_REQUIRED).toLowerCase());
else
parameterNameContent.italicText(labels.getLabel(FLAGS_OPTIONAL).toLowerCase());
return parameterNameContent.toString();
}
/**
* Filter parameters to display in parameters section
*
* @param parameter parameter to filter
* @return true if parameter can be displayed
*/
private boolean filterParameter(Parameter parameter) {
return (!config.isFlatBodyEnabled() || !StringUtils.equals(parameter.getIn(), "body"));
}
/**
* Apply extension context to all OperationsContentExtension.
*
* @param context context
*/
private void applyPathsDocumentExtension(PathsDocumentExtension.Context context) {
extensionRegistry.getPathsDocumentExtensions().forEach(extension -> extension.apply(context));
}
public static class Parameters {
private final PathOperation operation;
private final int titleLevel;
private final List<ObjectType> inlineDefinitions;
public Parameters(PathOperation operation,
List<ObjectType> inlineDefinitions,
int titleLevel) {
this.operation = Validate.notNull(operation, "PathOperation must not be null");
this.inlineDefinitions = Validate.notNull(inlineDefinitions, "InlineDefinitions must not be null");
this.titleLevel = titleLevel;
}
}
}

View File

@@ -0,0 +1,475 @@
/*
* Copyright 2016 Robert Winkler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.swagger2markup.internal.component;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.github.swagger2markup.GroupBy;
import io.github.swagger2markup.PageBreakLocations;
import io.github.swagger2markup.Swagger2MarkupConverter;
import io.github.swagger2markup.internal.resolver.DocumentResolver;
import io.github.swagger2markup.internal.type.ObjectType;
import io.github.swagger2markup.internal.utils.ExamplesUtil;
import io.github.swagger2markup.markup.builder.MarkupAdmonition;
import io.github.swagger2markup.markup.builder.MarkupBlockStyle;
import io.github.swagger2markup.markup.builder.MarkupDocBuilder;
import io.github.swagger2markup.model.PathOperation;
import io.github.swagger2markup.spi.MarkupComponent;
import io.github.swagger2markup.spi.PathsDocumentExtension;
import io.swagger.models.Model;
import io.swagger.util.Json;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.commons.lang3.Validate;
import org.apache.commons.lang3.math.NumberUtils;
import java.util.*;
import static io.github.swagger2markup.Labels.*;
import static io.github.swagger2markup.PageBreakLocations.*;
import static io.github.swagger2markup.internal.utils.MarkupDocBuilderUtils.copyMarkupDocBuilder;
import static io.github.swagger2markup.internal.utils.MarkupDocBuilderUtils.markupDescription;
import static io.github.swagger2markup.spi.PathsDocumentExtension.Position;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
public class PathOperationComponent extends MarkupComponent<PathOperationComponent.Parameters> {
private final DocumentResolver definitionDocumentResolver;
private final Map<String, Model> definitions;
private final PropertiesTableComponent propertiesTableComponent;
private final ParameterTableComponent parameterTableComponent;
private final ConsumesComponent consumesComponent;
private final ProducesComponent producesComponent;
private final SecuritySchemeComponent securitySchemeComponent;
private final BodyParameterComponent bodyParameterComponent;
private final ResponseComponent responseComponent;
public PathOperationComponent(Swagger2MarkupConverter.Context context,
DocumentResolver definitionDocumentResolver,
DocumentResolver securityDocumentResolver) {
super(context);
this.definitions = context.getSwagger().getDefinitions();
this.definitionDocumentResolver = Validate.notNull(definitionDocumentResolver, "DocumentResolver must not be null");
this.propertiesTableComponent = new PropertiesTableComponent(context, definitionDocumentResolver);
this.parameterTableComponent = new ParameterTableComponent(context, definitionDocumentResolver);
this.consumesComponent = new ConsumesComponent(context);
this.producesComponent = new ProducesComponent(context);
this.securitySchemeComponent = new SecuritySchemeComponent(context, securityDocumentResolver);
this.bodyParameterComponent = new BodyParameterComponent(context, definitionDocumentResolver);
this.responseComponent = new ResponseComponent(context, definitionDocumentResolver);
}
public static PathOperationComponent.Parameters parameters(PathOperation operation) {
return new PathOperationComponent.Parameters(operation);
}
@Override
public MarkupDocBuilder apply(MarkupDocBuilder markupDocBuilder, Parameters params) {
PathOperation operation = params.operation;
List<PageBreakLocations> locations = config.getPageBreakLocations();
applyPathsDocumentExtension(new PathsDocumentExtension.Context(Position.OPERATION_BEFORE, markupDocBuilder, operation));
if (locations.contains(BEFORE_OPERATION)) markupDocBuilder.pageBreak();
buildOperationTitle(markupDocBuilder, operation);
applyPathsDocumentExtension(new PathsDocumentExtension.Context(Position.OPERATION_BEGIN, markupDocBuilder, operation));
buildDeprecatedSection(markupDocBuilder, operation);
if (locations.contains(BEFORE_OPERATION_DESCRIPTION)) markupDocBuilder.pageBreak();
buildDescriptionSection(markupDocBuilder, operation);
if (locations.contains(AFTER_OPERATION_DESCRIPTION)) markupDocBuilder.pageBreak();
if (locations.contains(BEFORE_OPERATION_PARAMETERS)) markupDocBuilder.pageBreak();
inlineDefinitions(markupDocBuilder, buildParametersSection(markupDocBuilder, operation), operation.getPath() + " " + operation.getMethod());
if (locations.contains(AFTER_OPERATION_PARAMETERS)) markupDocBuilder.pageBreak();
inlineDefinitions(markupDocBuilder, buildBodyParameterSection(markupDocBuilder, operation), operation.getPath() + " " + operation.getMethod());
if (locations.contains(BEFORE_OPERATION_RESPONSES)) markupDocBuilder.pageBreak();
inlineDefinitions(markupDocBuilder, buildResponsesSection(markupDocBuilder, operation), operation.getPath() + " " + operation.getMethod());
if (locations.contains(AFTER_OPERATION_RESPONSES)) markupDocBuilder.pageBreak();
if (locations.contains(BEFORE_OPERATION_CONSUMES)) markupDocBuilder.pageBreak();
buildConsumesSection(markupDocBuilder, operation);
if (locations.contains(AFTER_OPERATION_CONSUMES)) markupDocBuilder.pageBreak();
if (locations.contains(BEFORE_OPERATION_PRODUCES)) markupDocBuilder.pageBreak();
buildProducesSection(markupDocBuilder, operation);
if (locations.contains(AFTER_OPERATION_PRODUCES)) markupDocBuilder.pageBreak();
buildTagsSection(markupDocBuilder, operation);
buildSecuritySchemeSection(markupDocBuilder, operation);
buildExamplesSection(markupDocBuilder, operation, locations);
applyPathsDocumentExtension(new PathsDocumentExtension.Context(Position.OPERATION_END, markupDocBuilder, operation));
applyPathsDocumentExtension(new PathsDocumentExtension.Context(Position.OPERATION_AFTER, markupDocBuilder, operation));
if (locations.contains(AFTER_OPERATION)) markupDocBuilder.pageBreak();
return markupDocBuilder;
}
/**
* Adds the operation title to the document. If the operation has a summary, the title is the summary.
* Otherwise the title is the method of the operation and the URL of the operation.
*
* @param operation the Swagger Operation
*/
private void buildOperationTitle(MarkupDocBuilder markupDocBuilder, PathOperation operation) {
buildOperationTitle(markupDocBuilder, operation.getTitle(), operation.getId());
if (operation.getTitle().equals(operation.getOperation().getSummary())) {
markupDocBuilder.block(operation.getMethod() + " " + operation.getPath(), MarkupBlockStyle.LITERAL);
}
}
/**
* Adds a operation title to the document.
*
* @param title the operation title
* @param anchor optional anchor (null => auto-generate from title)
*/
private void buildOperationTitle(MarkupDocBuilder markupDocBuilder, String title, String anchor) {
if (config.getPathsGroupedBy() == GroupBy.AS_IS) {
markupDocBuilder.sectionTitleWithAnchorLevel2(title, anchor);
} else {
markupDocBuilder.sectionTitleWithAnchorLevel3(title, anchor);
}
}
/**
* Builds a warning if method is deprecated.
*
* @param operation the Swagger Operation
*/
private void buildDeprecatedSection(MarkupDocBuilder markupDocBuilder, PathOperation operation) {
if (BooleanUtils.isTrue(operation.getOperation().isDeprecated())) {
markupDocBuilder.block(DEPRECATED_OPERATION, MarkupBlockStyle.EXAMPLE, null, MarkupAdmonition.CAUTION);
}
}
/**
* Adds a operation description to the document.
*
* @param operation the Swagger Operation
*/
private void buildDescriptionSection(MarkupDocBuilder markupDocBuilder, PathOperation operation) {
MarkupDocBuilder descriptionBuilder = copyMarkupDocBuilder(markupDocBuilder);
applyPathsDocumentExtension(new PathsDocumentExtension.Context(Position.OPERATION_DESCRIPTION_BEGIN, descriptionBuilder, operation));
String description = operation.getOperation().getDescription();
if (isNotBlank(description)) {
descriptionBuilder.paragraph(markupDescription(config.getSwaggerMarkupLanguage(), markupDocBuilder, description));
}
applyPathsDocumentExtension(new PathsDocumentExtension.Context(Position.OPERATION_DESCRIPTION_END, descriptionBuilder, operation));
String descriptionContent = descriptionBuilder.toString();
applyPathsDocumentExtension(new PathsDocumentExtension.Context(Position.OPERATION_DESCRIPTION_BEFORE, markupDocBuilder, operation));
if (isNotBlank(descriptionContent)) {
buildSectionTitle(markupDocBuilder, labels.getLabel(DESCRIPTION));
markupDocBuilder.text(descriptionContent);
}
applyPathsDocumentExtension(new PathsDocumentExtension.Context(Position.OPERATION_DESCRIPTION_AFTER, markupDocBuilder, operation));
}
/**
* Builds the parameters section
*
* @param operation the Swagger Operation
*/
private List<ObjectType> buildParametersSection(MarkupDocBuilder markupDocBuilder, PathOperation operation) {
List<ObjectType> inlineDefinitions = new ArrayList<>();
parameterTableComponent.apply(markupDocBuilder, ParameterTableComponent.parameters(
operation,
inlineDefinitions,
getSectionTitleLevel()
));
return inlineDefinitions;
}
/**
* Builds the body parameter section
*
* @param operation the Swagger Operation
* @return a list of inlined types.
*/
private List<ObjectType> buildBodyParameterSection(MarkupDocBuilder markupDocBuilder, PathOperation operation) {
List<ObjectType> inlineDefinitions = new ArrayList<>();
bodyParameterComponent.apply(markupDocBuilder, BodyParameterComponent.parameters(
operation,
inlineDefinitions
));
return inlineDefinitions;
}
private List<ObjectType> buildResponsesSection(MarkupDocBuilder markupDocBuilder, PathOperation operation) {
List<ObjectType> inlineDefinitions = new ArrayList<>();
responseComponent.apply(markupDocBuilder, ResponseComponent.parameters(
operation,
getSectionTitleLevel(),
inlineDefinitions
));
return inlineDefinitions;
}
/**
* Adds a operation section title to the document.
*
* @param title the section title
*/
private void buildSectionTitle(MarkupDocBuilder markupDocBuilder, String title) {
if (config.getPathsGroupedBy() == GroupBy.AS_IS) {
markupDocBuilder.sectionTitleLevel3(title);
} else {
markupDocBuilder.sectionTitleLevel4(title);
}
}
/**
* Builds the title of an inline schema.
* Inline definitions should never been referenced in TOC because they have no real existence, so they are just text.
*
* @param title inline schema title
* @param anchor inline schema anchor
*/
private void addInlineDefinitionTitle(MarkupDocBuilder markupDocBuilder, String title, String anchor) {
markupDocBuilder.anchor(anchor);
markupDocBuilder.newLine();
markupDocBuilder.boldTextLine(title);
}
/**
* Builds inline schema definitions
*
* @param markupDocBuilder the docbuilder do use for output
* @param definitions all inline definitions to display
* @param uniquePrefix unique prefix to prepend to inline object names to enforce unicity
*/
private void inlineDefinitions(MarkupDocBuilder markupDocBuilder, List<ObjectType> definitions, String uniquePrefix) {
if (CollectionUtils.isNotEmpty(definitions)) {
for (ObjectType definition : definitions) {
addInlineDefinitionTitle(markupDocBuilder, definition.getName(), definition.getUniqueName());
List<ObjectType> localDefinitions = new ArrayList<>();
propertiesTableComponent.apply(markupDocBuilder, PropertiesTableComponent.parameters(
definition.getProperties(),
uniquePrefix,
localDefinitions
));
for (ObjectType localDefinition : localDefinitions)
inlineDefinitions(markupDocBuilder, Collections.singletonList(localDefinition), localDefinition.getUniqueName());
}
}
}
private void buildConsumesSection(MarkupDocBuilder markupDocBuilder, PathOperation operation) {
List<String> consumes = operation.getOperation().getConsumes();
if (CollectionUtils.isNotEmpty(consumes)) {
consumesComponent.apply(markupDocBuilder, ConsumesComponent.parameters(consumes,
getSectionTitleLevel()));
}
}
private void buildProducesSection(MarkupDocBuilder markupDocBuilder, PathOperation operation) {
List<String> produces = operation.getOperation().getProduces();
if (CollectionUtils.isNotEmpty(produces)) {
producesComponent.apply(markupDocBuilder, ProducesComponent.parameters(produces,
getSectionTitleLevel()));
}
}
private void buildTagsSection(MarkupDocBuilder markupDocBuilder, PathOperation operation) {
if (config.getPathsGroupedBy() == GroupBy.AS_IS) {
List<String> tags = operation.getOperation().getTags();
if (CollectionUtils.isNotEmpty(tags)) {
buildSectionTitle(markupDocBuilder, labels.getLabel(TAGS));
if (config.getTagOrdering() != null) {
tags.sort(config.getTagOrdering());
}
markupDocBuilder.unorderedList(tags);
}
}
}
/**
* Builds the security section of a Swagger Operation.
*
* @param operation the Swagger Operation
*/
private void buildSecuritySchemeSection(MarkupDocBuilder markupDocBuilder, PathOperation operation) {
if (config.isPathSecuritySectionEnabled()) {
securitySchemeComponent.apply(markupDocBuilder, SecuritySchemeComponent.parameters(
operation,
getSectionTitleLevel()
));
}
}
/**
* Retrieves the title level for sections
*/
private int getSectionTitleLevel() {
if (config.getPathsGroupedBy() == GroupBy.AS_IS) {
return 3;
} else {
return 4;
}
}
/**
* Builds the example section of a Swagger Operation.
*
* @param operation the Swagger Operation
*/
private void buildExamplesSection(MarkupDocBuilder markupDocBuilder, PathOperation operation, List<PageBreakLocations> locations) {
Map<String, Object> generatedRequestExampleMap = ExamplesUtil.generateRequestExampleMap(config.isGeneratedExamplesEnabled(), operation, definitions, definitionDocumentResolver, markupDocBuilder);
Map<String, Object> generatedResponseExampleMap = ExamplesUtil.generateResponseExampleMap(config.isGeneratedExamplesEnabled(), operation, definitions, definitionDocumentResolver, markupDocBuilder);
boolean beforeExampleRequestBreak = locations.contains(BEFORE_OPERATION_EXAMPLE_REQUEST);
boolean afterExampleRequestBreak = locations.contains(AFTER_OPERATION_EXAMPLE_REQUEST);
boolean beforeExampleResponseBreak = locations.contains(BEFORE_OPERATION_EXAMPLE_RESPONSE);
boolean afterExampleResponseBreak = locations.contains(AFTER_OPERATION_EXAMPLE_RESPONSE);
exampleMap(markupDocBuilder, generatedRequestExampleMap, labels.getLabel(EXAMPLE_REQUEST), labels.getLabel(REQUEST), beforeExampleRequestBreak, afterExampleRequestBreak);
exampleMap(markupDocBuilder, generatedResponseExampleMap, labels.getLabel(EXAMPLE_RESPONSE), labels.getLabel(RESPONSE), beforeExampleResponseBreak, afterExampleResponseBreak);
}
private void exampleMap(MarkupDocBuilder markupDocBuilder, Map<String, Object> exampleMap, String operationSectionTitle, String sectionTitle, boolean beforeBreak, boolean afterBreak) {
if (exampleMap.size() > 0) {
if (beforeBreak) markupDocBuilder.pageBreak();
buildSectionTitle(markupDocBuilder, operationSectionTitle);
for (Map.Entry<String, Object> entry : exampleMap.entrySet()) {
// Example title, like "Response 200" or "Request Body"
buildExampleTitle(markupDocBuilder, sectionTitle + " " + entry.getKey());
if (NumberUtils.isNumber(entry.getKey())) {
// Section header is an HTTP status code (numeric)
JsonNode rootNode = parseExample(entry.getValue());
Iterator<Map.Entry<String, JsonNode>> fieldsIterator = rootNode.fields();
if (!fieldsIterator.hasNext()) {
// workaround for "array" example
//TODO: print $ref'd examples correctly instead of just "array"
String example = stripExampleQuotes(Json.pretty(entry.getValue()));
example = Json.pretty(example);
markupDocBuilder.listingBlock(example, "json");
}
while (fieldsIterator.hasNext()) {
Map.Entry<String, JsonNode> field = fieldsIterator.next();
if (field.getKey().equals("application/json")) {
String example = Json.pretty(field.getValue());
example = stripExampleQuotes(StringEscapeUtils.unescapeJson(example));
markupDocBuilder.listingBlock(example, "json");
} else if (field.getKey().equals("application/xml")) {
String example = stripExampleQuotes(field.getValue().toString());
example = StringEscapeUtils.unescapeJava(example);
//TODO: pretty print XML
markupDocBuilder.listingBlock(example, "xml");
} else {
String example = Json.pretty(entry.getValue());
markupDocBuilder.listingBlock(example, "json");
break; // No need to print the same example multiple times
}
}
} else if (entry.getKey().equals("path")) {
// Path shouldn't have quotes around it
markupDocBuilder.listingBlock(entry.getValue().toString());
} else {
markupDocBuilder.listingBlock(Json.pretty(entry.getValue()), "json");
}
}
if (afterBreak) markupDocBuilder.pageBreak();
}
}
/**
* Strip leading and trailing quotes from a string
*
* @param raw String containing leading or trailing quotes
* @return parsed String
*/
private String stripExampleQuotes(String raw) {
return raw
.replaceAll("^\"+", "") // Strip leading quotes
.replaceAll("\"+$", ""); // Strip trailing quotes
}
/**
* Parse a JSON array
*
* @param raw Object containing a JSON string
* @return JsonNode[contentType, example]
* @throws RuntimeException when the given JSON string cannot be parsed
*/
private JsonNode parseExample(Object raw) throws RuntimeException {
try {
JsonFactory factory = new JsonFactory();
ObjectMapper mapper = new ObjectMapper(factory);
return mapper.readTree(Json.pretty(raw));
} catch (Exception ex) {
throw new RuntimeException("Failed to read example", ex);
}
}
/**
* Adds a example title to the document.
*
* @param title the section title
*/
private void buildExampleTitle(MarkupDocBuilder markupDocBuilder, String title) {
if (config.getPathsGroupedBy() == GroupBy.AS_IS) {
markupDocBuilder.sectionTitleLevel4(title);
} else {
markupDocBuilder.sectionTitleLevel5(title);
}
}
/**
* Apply extension context to all OperationsContentExtension.
*
* @param context context
*/
private void applyPathsDocumentExtension(PathsDocumentExtension.Context context) {
extensionRegistry.getPathsDocumentExtensions().forEach(extension -> extension.apply(context));
}
public static class Parameters {
private final PathOperation operation;
public Parameters(PathOperation operation) {
this.operation = Validate.notNull(operation, "PathOperation must not be null");
}
}
}

View File

@@ -0,0 +1,59 @@
/*
* Copyright 2016 Robert Winkler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.swagger2markup.internal.component;
import io.github.swagger2markup.Labels;
import io.github.swagger2markup.Swagger2MarkupConverter;
import io.github.swagger2markup.markup.builder.MarkupDocBuilder;
import io.github.swagger2markup.spi.MarkupComponent;
import org.apache.commons.lang3.Validate;
import java.util.List;
import java.util.stream.Collectors;
import static io.github.swagger2markup.internal.utils.MarkupDocBuilderUtils.literalText;
public class ProducesComponent extends MarkupComponent<ProducesComponent.Parameters> {
public ProducesComponent(Swagger2MarkupConverter.Context context) {
super(context);
}
public static ProducesComponent.Parameters parameters(List<String> consumes,
int titleLevel) {
return new ProducesComponent.Parameters(consumes, titleLevel);
}
@Override
public MarkupDocBuilder apply(MarkupDocBuilder markupDocBuilder, Parameters params) {
markupDocBuilder.sectionTitleLevel(params.titleLevel, labels.getLabel(Labels.PRODUCES));
markupDocBuilder.unorderedList(params.produces.stream()
.map(value -> literalText(markupDocBuilder, value)).collect(Collectors.toList()));
return markupDocBuilder;
}
public static class Parameters {
private final List<String> produces;
private final int titleLevel;
public Parameters(List<String> produces, int titleLevel) {
this.produces = Validate.notNull(produces, "Produces must not be null");
this.titleLevel = titleLevel;
}
}
}

View File

@@ -0,0 +1,213 @@
/*
* Copyright 2016 Robert Winkler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.swagger2markup.internal.component;
import ch.netzwerg.paleo.ColumnIds;
import ch.netzwerg.paleo.StringColumn;
import io.github.swagger2markup.Swagger2MarkupConverter;
import io.github.swagger2markup.internal.adapter.PropertyAdapter;
import io.github.swagger2markup.internal.resolver.DocumentResolver;
import io.github.swagger2markup.internal.type.ObjectType;
import io.github.swagger2markup.internal.type.Type;
import io.github.swagger2markup.markup.builder.MarkupDocBuilder;
import io.github.swagger2markup.spi.MarkupComponent;
import io.swagger.models.properties.Property;
import io.swagger.util.Json;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.Validate;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import static io.github.swagger2markup.Labels.*;
import static io.github.swagger2markup.internal.utils.InlineSchemaUtils.createInlineType;
import static io.github.swagger2markup.internal.utils.MapUtils.toSortedMap;
import static io.github.swagger2markup.internal.utils.MarkupDocBuilderUtils.copyMarkupDocBuilder;
import static io.github.swagger2markup.internal.utils.MarkupDocBuilderUtils.markupDescription;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
public class PropertiesTableComponent extends MarkupComponent<PropertiesTableComponent.Parameters> {
private final DocumentResolver definitionDocumentResolver;
private final TableComponent tableComponent;
/**
* Build a generic property table
*
* @param definitionDocumentResolver definition document resolver to apply to property type cross-reference
*/
PropertiesTableComponent(Swagger2MarkupConverter.Context context,
DocumentResolver definitionDocumentResolver) {
super(context);
this.definitionDocumentResolver = definitionDocumentResolver;
this.tableComponent = new TableComponent(context);
}
public static PropertiesTableComponent.Parameters parameters(Map<String, Property> properties,
String parameterName,
List<ObjectType> inlineDefinitions) {
return new PropertiesTableComponent.Parameters(properties, parameterName, inlineDefinitions);
}
public MarkupDocBuilder apply(MarkupDocBuilder markupDocBuilder, Parameters params) {
//TODO: This method is too complex, split it up in smaller methods to increase readability
StringColumn.Builder nameColumnBuilder = StringColumn.builder(ColumnIds.StringColumnId.of(labels.getLabel(NAME_COLUMN)))
.putMetaData(TableComponent.WIDTH_RATIO, "3");
StringColumn.Builder descriptionColumnBuilder = StringColumn.builder(ColumnIds.StringColumnId.of(labels.getLabel(DESCRIPTION_COLUMN)))
.putMetaData(TableComponent.WIDTH_RATIO, "11")
.putMetaData(TableComponent.HEADER_COLUMN, "true");
StringColumn.Builder schemaColumnBuilder = StringColumn.builder(ColumnIds.StringColumnId.of(labels.getLabel(SCHEMA_COLUMN)))
.putMetaData(TableComponent.WIDTH_RATIO, "4")
.putMetaData(TableComponent.HEADER_COLUMN, "true");
Map<String, Property> properties = params.properties;
if (MapUtils.isNotEmpty(properties)) {
Map<String, Property> sortedProperties = toSortedMap(properties, config.getPropertyOrdering());
sortedProperties.forEach((String propertyName, Property property) -> {
PropertyAdapter propertyAdapter = new PropertyAdapter(property);
Type propertyType = propertyAdapter.getType(definitionDocumentResolver);
if (config.isInlineSchemaEnabled()) {
propertyType = createInlineType(propertyType, propertyName, params.parameterName + " " + propertyName, params.inlineDefinitions);
}
Optional<Object> optionalExample = propertyAdapter.getExample(config.isGeneratedExamplesEnabled(), markupDocBuilder);
Optional<Object> optionalDefaultValue = propertyAdapter.getDefaultValue();
Optional<Integer> optionalMaxLength = propertyAdapter.getMaxlength();
Optional<Integer> optionalMinLength = propertyAdapter.getMinlength();
Optional<String> optionalPattern = propertyAdapter.getPattern();
Optional<Number> optionalMinValue = propertyAdapter.getMin();
boolean exclusiveMin = propertyAdapter.getExclusiveMin();
Optional<Number> optionalMaxValue = propertyAdapter.getMax();
boolean exclusiveMax = propertyAdapter.getExclusiveMax();
MarkupDocBuilder propertyNameContent = copyMarkupDocBuilder(markupDocBuilder);
propertyNameContent.boldTextLine(propertyName, true);
if (property.getRequired())
propertyNameContent.italicText(labels.getLabel(FLAGS_REQUIRED).toLowerCase());
else
propertyNameContent.italicText(labels.getLabel(FLAGS_OPTIONAL).toLowerCase());
if (propertyAdapter.getReadOnly()) {
propertyNameContent.newLine(true);
propertyNameContent.italicText(labels.getLabel(FLAGS_READ_ONLY).toLowerCase());
}
MarkupDocBuilder descriptionContent = copyMarkupDocBuilder(markupDocBuilder);
String description = markupDescription(config.getSwaggerMarkupLanguage(), markupDocBuilder, property.getDescription());
if (isNotBlank(description))
descriptionContent.text(description);
if (optionalDefaultValue.isPresent()) {
if (isNotBlank(descriptionContent.toString())) {
descriptionContent.newLine(true);
}
descriptionContent.boldText(labels.getLabel(DEFAULT_COLUMN)).text(COLON).literalText(Json.pretty(optionalDefaultValue.get()));
}
if (optionalMinLength.isPresent() && optionalMaxLength.isPresent()) {
// combination of minlength/maxlength
Integer minLength = optionalMinLength.get();
Integer maxLength = optionalMaxLength.get();
if (isNotBlank(descriptionContent.toString())) {
descriptionContent.newLine(true);
}
String lengthRange = minLength + " - " + maxLength;
if (minLength.equals(maxLength)) {
lengthRange = minLength.toString();
}
descriptionContent.boldText(labels.getLabel(LENGTH_COLUMN)).text(COLON).literalText(lengthRange);
} else {
if (optionalMinLength.isPresent()) {
if (isNotBlank(descriptionContent.toString())) {
descriptionContent.newLine(true);
}
descriptionContent.boldText(labels.getLabel(MINLENGTH_COLUMN)).text(COLON).literalText(optionalMinLength.get().toString());
}
if (optionalMaxLength.isPresent()) {
if (isNotBlank(descriptionContent.toString())) {
descriptionContent.newLine(true);
}
descriptionContent.boldText(labels.getLabel(MAXLENGTH_COLUMN)).text(COLON).literalText(optionalMaxLength.get().toString());
}
}
if (optionalPattern.isPresent()) {
if (isNotBlank(descriptionContent.toString())) {
descriptionContent.newLine(true);
}
descriptionContent.boldText(labels.getLabel(PATTERN_COLUMN)).text(COLON).literalText(Json.pretty(optionalPattern.get()));
}
if (optionalMinValue.isPresent()) {
if (isNotBlank(descriptionContent.toString())) {
descriptionContent.newLine(true);
}
String minValueColumn = exclusiveMin ? labels.getLabel(MINVALUE_EXCLUSIVE_COLUMN) : labels.getLabel(MINVALUE_COLUMN);
descriptionContent.boldText(minValueColumn).text(COLON).literalText(optionalMinValue.get().toString());
}
if (optionalMaxValue.isPresent()) {
if (isNotBlank(descriptionContent.toString())) {
descriptionContent.newLine(true);
}
String maxValueColumn = exclusiveMax ? labels.getLabel(MAXVALUE_EXCLUSIVE_COLUMN) : labels.getLabel(MAXVALUE_COLUMN);
descriptionContent.boldText(maxValueColumn).text(COLON).literalText(optionalMaxValue.get().toString());
}
if (optionalExample.isPresent()) {
if (isNotBlank(description) || optionalDefaultValue.isPresent()) {
descriptionContent.newLine(true);
}
descriptionContent.boldText(labels.getLabel(EXAMPLE_COLUMN)).text(COLON).literalText(Json.pretty(optionalExample.get()));
}
nameColumnBuilder.add(propertyNameContent.toString());
descriptionColumnBuilder.add(descriptionContent.toString());
schemaColumnBuilder.add(propertyType.displaySchema(markupDocBuilder));
});
}
return tableComponent.apply(markupDocBuilder, TableComponent.parameters(
nameColumnBuilder.build(),
descriptionColumnBuilder.build(),
schemaColumnBuilder.build()));
}
public static class Parameters {
private final Map<String, Property> properties;
private final String parameterName;
private final List<ObjectType> inlineDefinitions;
public Parameters(Map<String, Property> properties,
String parameterName,
List<ObjectType> inlineDefinitions) {
this.properties = Validate.notNull(properties, "Properties must not be null");
this.parameterName = Validate.notBlank(parameterName, "ParameterName must not be blank");
this.inlineDefinitions = Validate.notNull(inlineDefinitions, "InlineDefinitions must not be null");
}
}
}

View File

@@ -0,0 +1,173 @@
/*
* Copyright 2016 Robert Winkler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.swagger2markup.internal.component;
import ch.netzwerg.paleo.StringColumn;
import io.github.swagger2markup.Swagger2MarkupConverter;
import io.github.swagger2markup.internal.adapter.PropertyAdapter;
import io.github.swagger2markup.internal.resolver.DocumentResolver;
import io.github.swagger2markup.internal.type.ObjectType;
import io.github.swagger2markup.internal.type.Type;
import io.github.swagger2markup.markup.builder.MarkupDocBuilder;
import io.github.swagger2markup.model.PathOperation;
import io.github.swagger2markup.spi.MarkupComponent;
import io.github.swagger2markup.spi.PathsDocumentExtension;
import io.swagger.models.Response;
import io.swagger.models.properties.Property;
import io.swagger.util.Json;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.Validate;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import static ch.netzwerg.paleo.ColumnIds.StringColumnId;
import static io.github.swagger2markup.Labels.*;
import static io.github.swagger2markup.internal.utils.InlineSchemaUtils.createInlineType;
import static io.github.swagger2markup.internal.utils.MapUtils.toSortedMap;
import static io.github.swagger2markup.internal.utils.MarkupDocBuilderUtils.*;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
public class ResponseComponent extends MarkupComponent<ResponseComponent.Parameters> {
private final TableComponent tableComponent;
private final DocumentResolver definitionDocumentResolver;
ResponseComponent(Swagger2MarkupConverter.Context context,
DocumentResolver definitionDocumentResolver) {
super(context);
this.definitionDocumentResolver = Validate.notNull(definitionDocumentResolver, "DocumentResolver must not be null");
this.tableComponent = new TableComponent(context);
}
public static ResponseComponent.Parameters parameters(PathOperation operation,
int titleLevel,
List<ObjectType> inlineDefinitions) {
return new ResponseComponent.Parameters(operation, titleLevel, inlineDefinitions);
}
@Override
public MarkupDocBuilder apply(MarkupDocBuilder markupDocBuilder, Parameters params) {
PathOperation operation = params.operation;
Map<String, Response> responses = operation.getOperation().getResponses();
MarkupDocBuilder responsesBuilder = copyMarkupDocBuilder(markupDocBuilder);
applyPathsDocumentExtension(new PathsDocumentExtension.Context(PathsDocumentExtension.Position.OPERATION_RESPONSES_BEGIN, responsesBuilder, operation));
if (MapUtils.isNotEmpty(responses)) {
StringColumn.Builder httpCodeColumnBuilder = StringColumn.builder(StringColumnId.of(labels.getLabel(HTTP_CODE_COLUMN)))
.putMetaData(TableComponent.WIDTH_RATIO, "2");
StringColumn.Builder descriptionColumnBuilder = StringColumn.builder(StringColumnId.of(labels.getLabel(DESCRIPTION_COLUMN)))
.putMetaData(TableComponent.WIDTH_RATIO, "14")
.putMetaData(TableComponent.HEADER_COLUMN, "true");
StringColumn.Builder schemaColumnBuilder = StringColumn.builder(StringColumnId.of(labels.getLabel(SCHEMA_COLUMN)))
.putMetaData(TableComponent.WIDTH_RATIO, "4")
.putMetaData(TableComponent.HEADER_COLUMN, "true");
Map<String, Response> sortedResponses = toSortedMap(responses, config.getResponseOrdering());
sortedResponses.forEach((String responseName, Response response) -> {
String schemaContent = labels.getLabel(NO_CONTENT);
if (response.getSchema() != null) {
Property property = response.getSchema();
Type type = new PropertyAdapter(property).getType(definitionDocumentResolver);
if (config.isInlineSchemaEnabled()) {
type = createInlineType(type, labels.getLabel(RESPONSE) + " " + responseName, operation.getId() + " " + labels.getLabel(RESPONSE) + " " + responseName, params.inlineDefinitions);
}
schemaContent = type.displaySchema(markupDocBuilder);
}
MarkupDocBuilder descriptionBuilder = copyMarkupDocBuilder(markupDocBuilder);
descriptionBuilder.text(markupDescription(config.getSwaggerMarkupLanguage(), markupDocBuilder, response.getDescription()));
Map<String, Property> headers = response.getHeaders();
if (MapUtils.isNotEmpty(headers)) {
descriptionBuilder.newLine(true).boldText(labels.getLabel(HEADERS_COLUMN)).text(COLON);
for (Map.Entry<String, Property> header : headers.entrySet()) {
descriptionBuilder.newLine(true);
Property headerProperty = header.getValue();
PropertyAdapter headerPropertyAdapter = new PropertyAdapter(headerProperty);
Type propertyType = headerPropertyAdapter.getType(null);
String headerDescription = markupDescription(config.getSwaggerMarkupLanguage(), markupDocBuilder, headerProperty.getDescription());
Optional<Object> optionalDefaultValue = headerPropertyAdapter.getDefaultValue();
descriptionBuilder
.literalText(header.getKey())
.text(String.format(" (%s)", propertyType.displaySchema(markupDocBuilder)));
if (isNotBlank(headerDescription) || optionalDefaultValue.isPresent()) {
descriptionBuilder.text(COLON);
if (isNotBlank(headerDescription) && !headerDescription.endsWith("."))
headerDescription += ".";
descriptionBuilder.text(headerDescription);
optionalDefaultValue.ifPresent(o -> descriptionBuilder.text(" ")
.boldText(labels.getLabel(DEFAULT_COLUMN))
.text(COLON).literalText(Json.pretty(o)));
}
}
}
httpCodeColumnBuilder.add(boldText(markupDocBuilder, responseName));
descriptionColumnBuilder.add(descriptionBuilder.toString());
schemaColumnBuilder.add(schemaContent);
});
responsesBuilder = tableComponent.apply(responsesBuilder, TableComponent.parameters(httpCodeColumnBuilder.build(),
descriptionColumnBuilder.build(),
schemaColumnBuilder.build()));
}
applyPathsDocumentExtension(new PathsDocumentExtension.Context(PathsDocumentExtension.Position.OPERATION_RESPONSES_END, responsesBuilder, operation));
String responsesContent = responsesBuilder.toString();
applyPathsDocumentExtension(new PathsDocumentExtension.Context(PathsDocumentExtension.Position.OPERATION_RESPONSES_BEFORE, markupDocBuilder, operation));
if (isNotBlank(responsesContent)) {
markupDocBuilder.sectionTitleLevel(params.titleLevel, labels.getLabel(RESPONSES));
markupDocBuilder.text(responsesContent);
}
applyPathsDocumentExtension(new PathsDocumentExtension.Context(PathsDocumentExtension.Position.OPERATION_RESPONSES_AFTER, markupDocBuilder, operation));
return markupDocBuilder;
}
/**
* Apply extension context to all OperationsContentExtension.
*
* @param context context
*/
private void applyPathsDocumentExtension(PathsDocumentExtension.Context context) {
extensionRegistry.getPathsDocumentExtensions().forEach(extension -> extension.apply(context));
}
public static class Parameters {
private final PathOperation operation;
private final int titleLevel;
private final List<ObjectType> inlineDefinitions;
public Parameters(PathOperation operation,
int titleLevel,
List<ObjectType> inlineDefinitions) {
this.operation = Validate.notNull(operation, "PathOperation must not be null");
this.titleLevel = titleLevel;
this.inlineDefinitions = Validate.notNull(inlineDefinitions, "InlineDefinitions must not be null");
}
}
}

View File

@@ -0,0 +1,123 @@
/*
* Copyright 2016 Robert Winkler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.swagger2markup.internal.component;
import ch.netzwerg.paleo.StringColumn;
import com.google.common.base.Joiner;
import io.github.swagger2markup.Swagger2MarkupConverter;
import io.github.swagger2markup.internal.resolver.DocumentResolver;
import io.github.swagger2markup.markup.builder.MarkupDocBuilder;
import io.github.swagger2markup.model.PathOperation;
import io.github.swagger2markup.spi.MarkupComponent;
import io.github.swagger2markup.spi.PathsDocumentExtension;
import io.swagger.models.auth.SecuritySchemeDefinition;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.Validate;
import java.util.List;
import java.util.Map;
import static ch.netzwerg.paleo.ColumnIds.StringColumnId;
import static io.github.swagger2markup.Labels.*;
import static io.github.swagger2markup.internal.utils.MarkupDocBuilderUtils.*;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
public class SecuritySchemeComponent extends MarkupComponent<SecuritySchemeComponent.Parameters> {
private final Map<String, SecuritySchemeDefinition> securityDefinitions;
private final DocumentResolver securityDocumentResolver;
private final TableComponent tableComponent;
public SecuritySchemeComponent(Swagger2MarkupConverter.Context context,
DocumentResolver securityDocumentResolver) {
super(context);
this.securityDefinitions = context.getSwagger().getSecurityDefinitions();
this.securityDocumentResolver = Validate.notNull(securityDocumentResolver, "SecurityDocumentResolver must not be null");
this.tableComponent = new TableComponent(context);
}
public static SecuritySchemeComponent.Parameters parameters(PathOperation operation,
int titleLevel) {
return new SecuritySchemeComponent.Parameters(operation, titleLevel);
}
@Override
public MarkupDocBuilder apply(MarkupDocBuilder markupDocBuilder, Parameters params) {
PathOperation operation = params.operation;
MarkupDocBuilder securityBuilder = copyMarkupDocBuilder(markupDocBuilder);
List<Map<String, List<String>>> securitySchemes = operation.getOperation().getSecurity();
applyPathsDocumentExtension(new PathsDocumentExtension.Context(PathsDocumentExtension.Position.OPERATION_SECURITY_BEGIN, securityBuilder, operation));
if (CollectionUtils.isNotEmpty(securitySchemes)) {
StringColumn.Builder typeColumnBuilder = StringColumn.builder(StringColumnId.of(labels.getLabel(TYPE_COLUMN)))
.putMetaData(TableComponent.WIDTH_RATIO, "3");
StringColumn.Builder nameColumnBuilder = StringColumn.builder(StringColumnId.of(labels.getLabel(NAME_COLUMN)))
.putMetaData(TableComponent.WIDTH_RATIO, "4");
StringColumn.Builder scopeColumnBuilder = StringColumn.builder(StringColumnId.of(labels.getLabel(SCOPES_COLUMN)))
.putMetaData(TableComponent.WIDTH_RATIO, "13")
.putMetaData(TableComponent.HEADER_COLUMN, "true");
for (Map<String, List<String>> securityScheme : securitySchemes) {
for (Map.Entry<String, List<String>> securityEntry : securityScheme.entrySet()) {
String securityKey = securityEntry.getKey();
String type = labels.getLabel(UNKNOWN);
if (securityDefinitions != null && securityDefinitions.containsKey(securityKey)) {
type = securityDefinitions.get(securityKey).getType();
}
typeColumnBuilder.add(boldText(markupDocBuilder, type));
nameColumnBuilder.add(boldText(markupDocBuilder, crossReference(markupDocBuilder, securityDocumentResolver.apply(securityKey), securityKey, securityKey)));
scopeColumnBuilder.add(Joiner.on(",").join(securityEntry.getValue()));
}
}
securityBuilder = tableComponent.apply(securityBuilder, TableComponent.parameters(typeColumnBuilder.build(),
nameColumnBuilder.build(),
scopeColumnBuilder.build()));
}
applyPathsDocumentExtension(new PathsDocumentExtension.Context(PathsDocumentExtension.Position.OPERATION_SECURITY_END, securityBuilder, operation));
String securityContent = securityBuilder.toString();
applyPathsDocumentExtension(new PathsDocumentExtension.Context(PathsDocumentExtension.Position.OPERATION_SECURITY_BEFORE, markupDocBuilder, operation));
if (isNotBlank(securityContent)) {
markupDocBuilder.sectionTitleLevel(params.titleLevel, labels.getLabel(SECURITY));
markupDocBuilder.text(securityContent);
}
applyPathsDocumentExtension(new PathsDocumentExtension.Context(PathsDocumentExtension.Position.OPERATION_SECURITY_AFTER, markupDocBuilder, operation));
return markupDocBuilder;
}
/**
* Apply extension context to all OperationsContentExtension.
*
* @param context context
*/
private void applyPathsDocumentExtension(PathsDocumentExtension.Context context) {
extensionRegistry.getPathsDocumentExtensions().forEach(extension -> extension.apply(context));
}
public static class Parameters {
private final PathOperation operation;
private final int titleLevel;
public Parameters(PathOperation operation,
int titleLevel) {
this.operation = Validate.notNull(operation, "PathOperation must not be null");
this.titleLevel = titleLevel;
}
}
}

View File

@@ -0,0 +1,135 @@
/*
* Copyright 2016 Robert Winkler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.swagger2markup.internal.component;
import ch.netzwerg.paleo.StringColumn;
import io.github.swagger2markup.Swagger2MarkupConverter;
import io.github.swagger2markup.markup.builder.MarkupDocBuilder;
import io.github.swagger2markup.spi.MarkupComponent;
import io.github.swagger2markup.spi.SecurityDocumentExtension;
import io.swagger.models.auth.ApiKeyAuthDefinition;
import io.swagger.models.auth.OAuth2Definition;
import io.swagger.models.auth.SecuritySchemeDefinition;
import org.apache.commons.lang3.Validate;
import java.util.Map;
import static ch.netzwerg.paleo.ColumnIds.StringColumnId;
import static io.github.swagger2markup.Labels.*;
import static io.github.swagger2markup.internal.utils.MarkupDocBuilderUtils.copyMarkupDocBuilder;
import static io.github.swagger2markup.internal.utils.MarkupDocBuilderUtils.markupDescription;
import static io.github.swagger2markup.spi.SecurityDocumentExtension.Position;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
public class SecuritySchemeDefinitionComponent extends MarkupComponent<SecuritySchemeDefinitionComponent.Parameters> {
private final TableComponent tableComponent;
public SecuritySchemeDefinitionComponent(Swagger2MarkupConverter.Context context) {
super(context);
this.tableComponent = new TableComponent(context);
}
public static SecuritySchemeDefinitionComponent.Parameters parameters(String securitySchemeDefinitionName,
SecuritySchemeDefinition securitySchemeDefinition,
int titleLevel) {
return new SecuritySchemeDefinitionComponent.Parameters(securitySchemeDefinitionName, securitySchemeDefinition, titleLevel);
}
@Override
public MarkupDocBuilder apply(MarkupDocBuilder markupDocBuilder, Parameters params) {
String securitySchemeDefinitionName = params.securitySchemeDefinitionName;
SecuritySchemeDefinition securitySchemeDefinition = params.securitySchemeDefinition;
applySecurityDocumentExtension(new SecurityDocumentExtension.Context(Position.SECURITY_SCHEME_BEFORE, markupDocBuilder, securitySchemeDefinitionName, securitySchemeDefinition));
markupDocBuilder.sectionTitleWithAnchorLevel(params.titleLevel, securitySchemeDefinitionName);
applySecurityDocumentExtension(new SecurityDocumentExtension.Context(Position.SECURITY_SCHEME_BEGIN, markupDocBuilder, securitySchemeDefinitionName, securitySchemeDefinition));
String description = securitySchemeDefinition.getDescription();
if (isNotBlank(description)) {
markupDocBuilder.paragraph(markupDescription(config.getSwaggerMarkupLanguage(), markupDocBuilder, description));
}
buildSecurityScheme(markupDocBuilder, securitySchemeDefinition);
applySecurityDocumentExtension(new SecurityDocumentExtension.Context(Position.SECURITY_SCHEME_END, markupDocBuilder, securitySchemeDefinitionName, securitySchemeDefinition));
applySecurityDocumentExtension(new SecurityDocumentExtension.Context(Position.SECURITY_SCHEME_AFTER, markupDocBuilder, securitySchemeDefinitionName, securitySchemeDefinition));
return markupDocBuilder;
}
private MarkupDocBuilder buildSecurityScheme(MarkupDocBuilder markupDocBuilder, SecuritySchemeDefinition securityScheme) {
String type = securityScheme.getType();
MarkupDocBuilder paragraphBuilder = copyMarkupDocBuilder(markupDocBuilder);
paragraphBuilder.italicText(labels.getLabel(TYPE)).textLine(COLON + type);
if (securityScheme instanceof ApiKeyAuthDefinition) {
paragraphBuilder.italicText(labels.getLabel(NAME)).textLine(COLON + ((ApiKeyAuthDefinition) securityScheme).getName());
paragraphBuilder.italicText(labels.getLabel(IN)).textLine(COLON + ((ApiKeyAuthDefinition) securityScheme).getIn());
return markupDocBuilder.paragraph(paragraphBuilder.toString(), true);
} else if (securityScheme instanceof OAuth2Definition) {
OAuth2Definition oauth2Scheme = (OAuth2Definition) securityScheme;
String flow = oauth2Scheme.getFlow();
paragraphBuilder.italicText(labels.getLabel(FLOW)).textLine(COLON + flow);
if (isNotBlank(oauth2Scheme.getAuthorizationUrl())) {
paragraphBuilder.italicText(labels.getLabel(AUTHORIZATION_URL)).textLine(COLON + oauth2Scheme.getAuthorizationUrl());
}
if (isNotBlank(oauth2Scheme.getTokenUrl())) {
paragraphBuilder.italicText(labels.getLabel(TOKEN_URL)).textLine(COLON + oauth2Scheme.getTokenUrl());
}
StringColumn.Builder nameColumnBuilder = StringColumn.builder(StringColumnId.of(labels.getLabel(NAME_COLUMN)))
.putMetaData(TableComponent.WIDTH_RATIO, "3")
.putMetaData(TableComponent.HEADER_COLUMN, "true");
StringColumn.Builder descriptionColumnBuilder = StringColumn.builder(StringColumnId.of(labels.getLabel(DESCRIPTION_COLUMN)))
.putMetaData(TableComponent.WIDTH_RATIO, "17")
.putMetaData(TableComponent.HEADER_COLUMN, "true");
if (oauth2Scheme.getScopes() != null) {
for (Map.Entry<String, String> scope : oauth2Scheme.getScopes().entrySet()) {
nameColumnBuilder.add(scope.getKey());
descriptionColumnBuilder.add(scope.getValue());
}
}
markupDocBuilder.paragraph(paragraphBuilder.toString(), true);
return tableComponent.apply(markupDocBuilder, TableComponent.parameters(nameColumnBuilder.build(),
descriptionColumnBuilder.build()));
} else {
return markupDocBuilder.paragraph(paragraphBuilder.toString(), true);
}
}
/**
* Apply extension context to all SecurityContentExtension
*
* @param context context
*/
private void applySecurityDocumentExtension(SecurityDocumentExtension.Context context) {
extensionRegistry.getSecurityDocumentExtensions().forEach(extension -> extension.apply(context));
}
public static class Parameters {
private final String securitySchemeDefinitionName;
private final SecuritySchemeDefinition securitySchemeDefinition;
private final int titleLevel;
public Parameters(String securitySchemeDefinitionName,
SecuritySchemeDefinition securitySchemeDefinition,
int titleLevel) {
this.securitySchemeDefinitionName = Validate.notBlank(securitySchemeDefinitionName, "SecuritySchemeDefinitionName must not be empty");
this.securitySchemeDefinition = Validate.notNull(securitySchemeDefinition, "SecuritySchemeDefinition must not be null");
this.titleLevel = titleLevel;
}
}
}

View File

@@ -0,0 +1,76 @@
/*
* Copyright 2016 Robert Winkler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.swagger2markup.internal.component;
import ch.netzwerg.paleo.DataFrame;
import ch.netzwerg.paleo.StringColumn;
import io.github.swagger2markup.Swagger2MarkupConverter;
import io.github.swagger2markup.markup.builder.MarkupDocBuilder;
import io.github.swagger2markup.markup.builder.MarkupLanguage;
import io.github.swagger2markup.markup.builder.MarkupTableColumn;
import io.github.swagger2markup.spi.MarkupComponent;
import javaslang.collection.Array;
import javaslang.collection.IndexedSeq;
import javaslang.collection.List;
import org.apache.commons.lang3.StringUtils;
public class TableComponent extends MarkupComponent<TableComponent.Parameters> {
public static final String WIDTH_RATIO = "widthRatio";
public static final String HEADER_COLUMN = "headerColumn";
public TableComponent(Swagger2MarkupConverter.Context context) {
super(context);
}
public static TableComponent.Parameters parameters(StringColumn... columns) {
return new TableComponent.Parameters(columns);
}
public static boolean isNotBlank(StringColumn column) {
return !column.getValues().filter(StringUtils::isNotBlank).isEmpty();
}
@Override
public MarkupDocBuilder apply(MarkupDocBuilder markupDocBuilder, Parameters params) {
DataFrame dataFrame = params.dataFrame;
java.util.List<MarkupTableColumn> columnSpecs = dataFrame.getColumns().map(column -> {
Integer widthRatio = Integer.valueOf(column.getMetaData().get(WIDTH_RATIO).getOrElse("0"));
return new MarkupTableColumn(column.getId().getName())
.withWidthRatio(widthRatio)
.withHeaderColumn(Boolean.parseBoolean(column.getMetaData().get(HEADER_COLUMN).getOrElse("false")))
.withMarkupSpecifiers(MarkupLanguage.ASCIIDOC, ".^" + widthRatio);
}
).toJavaList();
IndexedSeq<IndexedSeq<String>> columnValues = dataFrame.getColumns()
.map(column -> ((StringColumn) column).getValues());
java.util.List<java.util.List<String>> cells = Array.range(0, dataFrame.getRowCount())
.map(rowNumber -> columnValues.map(values -> values.get(rowNumber)).toJavaList()).toJavaList();
return markupDocBuilder.tableWithColumnSpecs(columnSpecs, cells);
}
public static class Parameters {
private final DataFrame dataFrame;
public Parameters(StringColumn... columns) {
this.dataFrame = DataFrame.ofAll(List.of(columns).filter(TableComponent::isNotBlank));
}
}
}

View File

@@ -0,0 +1,79 @@
/*
* Copyright 2016 Robert Winkler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.swagger2markup.internal.component;
import io.github.swagger2markup.Labels;
import io.github.swagger2markup.Swagger2MarkupConverter;
import io.github.swagger2markup.markup.builder.MarkupDocBuilder;
import io.github.swagger2markup.spi.MarkupComponent;
import io.swagger.models.Tag;
import org.apache.commons.lang3.Validate;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
public class TagsComponent extends MarkupComponent<TagsComponent.Parameters> {
public TagsComponent(Swagger2MarkupConverter.Context context) {
super(context);
}
public static TagsComponent.Parameters parameters(List<Tag> tags,
int titleLevel) {
return new TagsComponent.Parameters(tags, titleLevel);
}
@Override
public MarkupDocBuilder apply(MarkupDocBuilder markupDocBuilder, Parameters params) {
markupDocBuilder.sectionTitleLevel(params.titleLevel, labels.getLabel(Labels.TAGS));
List<String> tagsList = params.tags.stream()
.map(this::mapToString).collect(Collectors.toList());
if (config.getTagOrdering() != null)
Collections.sort(tagsList, config.getTagOrdering());
markupDocBuilder.unorderedList(tagsList);
return markupDocBuilder;
}
private String mapToString(Tag tag) {
String name = tag.getName();
String description = tag.getDescription();
if (isNotBlank(description)) {
return name + COLON + description;
} else {
return name;
}
}
public static class Parameters {
private final List<Tag> tags;
private final int titleLevel;
public Parameters(List<Tag> tags,
int titleLevel) {
this.tags = Validate.notNull(tags, "Tags must not be null");
this.titleLevel = titleLevel;
}
}
}

View File

@@ -0,0 +1,83 @@
/*
* Copyright 2016 Robert Winkler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.swagger2markup.internal.component;
import io.github.swagger2markup.Labels;
import io.github.swagger2markup.Swagger2MarkupConverter;
import io.github.swagger2markup.markup.builder.MarkupDocBuilder;
import io.github.swagger2markup.spi.MarkupComponent;
import io.swagger.models.Swagger;
import org.apache.commons.lang3.Validate;
import java.util.List;
import java.util.stream.Collectors;
import static io.github.swagger2markup.internal.utils.MarkupDocBuilderUtils.copyMarkupDocBuilder;
import static org.apache.commons.collections4.CollectionUtils.isNotEmpty;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import static org.apache.commons.lang3.StringUtils.join;
public class UriSchemeComponent extends MarkupComponent<UriSchemeComponent.Parameters> {
public UriSchemeComponent(Swagger2MarkupConverter.Context context) {
super(context);
}
public static UriSchemeComponent.Parameters parameters(Swagger swagger, int titleLevel) {
return new UriSchemeComponent.Parameters(swagger, titleLevel);
}
@Override
public MarkupDocBuilder apply(MarkupDocBuilder markupDocBuilder, Parameters params) {
Swagger swagger = params.swagger;
if (isNotBlank(swagger.getHost()) || isNotBlank(swagger.getBasePath()) || isNotEmpty(swagger.getSchemes())) {
markupDocBuilder.sectionTitleLevel(params.titleLevel, labels.getLabel(Labels.URI_SCHEME));
MarkupDocBuilder paragraphBuilder = copyMarkupDocBuilder(markupDocBuilder);
if (isNotBlank(swagger.getHost())) {
paragraphBuilder.italicText(labels.getLabel(Labels.HOST))
.textLine(COLON + swagger.getHost());
}
if (isNotBlank(swagger.getBasePath())) {
paragraphBuilder.italicText(labels.getLabel(Labels.BASE_PATH))
.textLine(COLON + swagger.getBasePath());
}
if (isNotEmpty(swagger.getSchemes())) {
List<String> schemes = swagger.getSchemes().stream()
.map(Enum::toString)
.collect(Collectors.toList());
paragraphBuilder.italicText(labels.getLabel(Labels.SCHEMES))
.textLine(COLON + join(schemes, ", "));
}
markupDocBuilder.paragraph(paragraphBuilder.toString(), true);
}
return markupDocBuilder;
}
public static class Parameters {
private final int titleLevel;
private final Swagger swagger;
public Parameters(Swagger swagger, int titleLevel) {
this.swagger = Validate.notNull(swagger);
this.titleLevel = titleLevel;
}
}
}

View File

@@ -0,0 +1,64 @@
/*
* Copyright 2016 Robert Winkler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.swagger2markup.internal.component;
import io.github.swagger2markup.Labels;
import io.github.swagger2markup.Swagger2MarkupConverter;
import io.github.swagger2markup.markup.builder.MarkupDocBuilder;
import io.github.swagger2markup.spi.MarkupComponent;
import io.swagger.models.Info;
import org.apache.commons.lang3.Validate;
import static io.github.swagger2markup.internal.utils.MarkupDocBuilderUtils.copyMarkupDocBuilder;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
public class VersionInfoComponent extends MarkupComponent<VersionInfoComponent.Parameters> {
public VersionInfoComponent(Swagger2MarkupConverter.Context context) {
super(context);
}
public static VersionInfoComponent.Parameters parameters(Info info,
int titleLevel) {
return new VersionInfoComponent.Parameters(info, titleLevel);
}
@Override
public MarkupDocBuilder apply(MarkupDocBuilder markupDocBuilder, Parameters params) {
String version = params.info.getVersion();
if (isNotBlank(version)) {
markupDocBuilder.sectionTitleLevel(params.titleLevel, labels.getLabel(Labels.CURRENT_VERSION));
MarkupDocBuilder paragraphBuilder = copyMarkupDocBuilder(markupDocBuilder);
paragraphBuilder.italicText(labels.getLabel(Labels.VERSION)).textLine(COLON + version);
markupDocBuilder.paragraph(paragraphBuilder.toString(), true);
}
return markupDocBuilder;
}
public static class Parameters {
private final int titleLevel;
private final Info info;
public Parameters(
Info info,
int titleLevel) {
this.info = Validate.notNull(info, "Info must not be null");
this.titleLevel = titleLevel;
}
}
}

View File

@@ -0,0 +1,194 @@
/*
* Copyright 2016 Robert Winkler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.swagger2markup.internal.document;
import io.github.swagger2markup.Labels;
import io.github.swagger2markup.Swagger2MarkupConverter;
import io.github.swagger2markup.internal.component.DefinitionComponent;
import io.github.swagger2markup.internal.resolver.DefinitionDocumentNameResolver;
import io.github.swagger2markup.internal.resolver.DefinitionDocumentResolverDefault;
import io.github.swagger2markup.internal.resolver.DefinitionDocumentResolverFromDefinition;
import io.github.swagger2markup.markup.builder.MarkupDocBuilder;
import io.github.swagger2markup.spi.MarkupComponent;
import io.swagger.models.Model;
import org.apache.commons.collections4.MapUtils;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import static io.github.swagger2markup.internal.utils.MapUtils.toSortedMap;
import static io.github.swagger2markup.internal.utils.MarkupDocBuilderUtils.copyMarkupDocBuilder;
import static io.github.swagger2markup.internal.utils.MarkupDocBuilderUtils.crossReference;
import static io.github.swagger2markup.spi.DefinitionsDocumentExtension.Context;
import static io.github.swagger2markup.spi.DefinitionsDocumentExtension.Position;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
/**
* @author Robert Winkler
*/
public class DefinitionsDocument extends MarkupComponent<DefinitionsDocument.Parameters> {
private static final String DEFINITIONS_ANCHOR = "definitions";
private static final List<String> IGNORED_DEFINITIONS = Collections.singletonList("Void");
private final DefinitionComponent definitionComponent;
private final DefinitionDocumentResolverDefault definitionDocumentResolverDefault;
private final DefinitionDocumentNameResolver definitionDocumentNameResolver;
public DefinitionsDocument(Swagger2MarkupConverter.Context context) {
super(context);
if (config.isSeparatedDefinitionsEnabled()) {
if (logger.isDebugEnabled()) {
logger.debug("Create separated definition files is enabled.");
}
} else {
if (logger.isDebugEnabled()) {
logger.debug("Create separated definition files is disabled.");
}
}
this.definitionDocumentNameResolver = new DefinitionDocumentNameResolver(context);
this.definitionComponent = new DefinitionComponent(context, new DefinitionDocumentResolverFromDefinition(context));
this.definitionDocumentResolverDefault = new DefinitionDocumentResolverDefault(context);
}
public static DefinitionsDocument.Parameters parameters(Map<String, Model> definitions) {
return new DefinitionsDocument.Parameters(definitions);
}
/**
* Builds the definitions MarkupDocument.
*
* @return the definitions MarkupDocument
*/
@Override
public MarkupDocBuilder apply(MarkupDocBuilder markupDocBuilder, DefinitionsDocument.Parameters params) {
Map<String, Model> definitions = params.definitions;
if (MapUtils.isNotEmpty(definitions)) {
applyDefinitionsDocumentExtension(new Context(Position.DOCUMENT_BEFORE, markupDocBuilder));
buildDefinitionsTitle(markupDocBuilder, labels.getLabel(Labels.DEFINITIONS));
applyDefinitionsDocumentExtension(new Context(Position.DOCUMENT_BEGIN, markupDocBuilder));
buildDefinitionsSection(markupDocBuilder, definitions);
applyDefinitionsDocumentExtension(new Context(Position.DOCUMENT_END, markupDocBuilder));
applyDefinitionsDocumentExtension(new Context(Position.DOCUMENT_AFTER, markupDocBuilder));
}
return markupDocBuilder;
}
private void buildDefinitionsTitle(MarkupDocBuilder markupDocBuilder, String title) {
markupDocBuilder.sectionTitleWithAnchorLevel1(title, DEFINITIONS_ANCHOR);
}
private void buildDefinitionsSection(MarkupDocBuilder markupDocBuilder, Map<String, Model> definitions) {
Map<String, Model> sortedMap = toSortedMap(definitions, config.getDefinitionOrdering());
sortedMap.forEach((String definitionName, Model model) -> {
if (isNotBlank(definitionName)
&& checkThatDefinitionIsNotInIgnoreList(definitionName)) {
buildDefinition(markupDocBuilder, definitionName, model);
}
});
}
/**
* Apply extension context to all DefinitionsContentExtension
*
* @param context context
*/
private void applyDefinitionsDocumentExtension(Context context) {
extensionRegistry.getDefinitionsDocumentExtensions().forEach(extension -> extension.apply(context));
}
/**
* Generate definition files depending on the generation mode
*
* @param definitionName definition name to process
* @param model definition model to process
*/
private void buildDefinition(MarkupDocBuilder markupDocBuilder, String definitionName, Model model) {
if (logger.isDebugEnabled()) {
logger.debug("Definition processed : '{}'", definitionName);
}
if (config.isSeparatedDefinitionsEnabled()) {
MarkupDocBuilder defDocBuilder = copyMarkupDocBuilder(markupDocBuilder);
applyDefinitionComponent(defDocBuilder, definitionName, model);
Path definitionFile = context.getOutputPath().resolve(definitionDocumentNameResolver.apply(definitionName));
defDocBuilder.writeToFileWithoutExtension(definitionFile, StandardCharsets.UTF_8);
if (logger.isDebugEnabled()) {
logger.debug("Separate definition file produced : '{}'", definitionFile);
}
definitionRef(markupDocBuilder, definitionName);
} else {
applyDefinitionComponent(markupDocBuilder, definitionName, model);
}
}
/**
* Checks that the definition is not in the list of ignored definitions.
*
* @param definitionName the name of the definition
* @return true if the definition can be processed
*/
private boolean checkThatDefinitionIsNotInIgnoreList(String definitionName) {
return !IGNORED_DEFINITIONS.contains(definitionName);
}
/**
* Builds a concrete definition
*
* @param markupDocBuilder the markupDocBuilder do use for output
* @param definitionName the name of the definition
* @param model the Swagger Model of the definition
*/
private void applyDefinitionComponent(MarkupDocBuilder markupDocBuilder, String definitionName, Model model) {
definitionComponent.apply(markupDocBuilder, DefinitionComponent.parameters(
definitionName,
model,
2));
}
/**
* Builds a cross-reference to a separated definition file.
*
* @param definitionName definition name to target
*/
private void definitionRef(MarkupDocBuilder markupDocBuilder, String definitionName) {
buildDefinitionTitle(markupDocBuilder, crossReference(markupDocBuilder, definitionDocumentResolverDefault.apply(definitionName), definitionName, definitionName), "ref-" + definitionName);
}
/**
* Builds definition title
*
* @param markupDocBuilder the markupDocBuilder do use for output
* @param title definition title
* @param anchor optional anchor (null => auto-generate from title)
*/
private void buildDefinitionTitle(MarkupDocBuilder markupDocBuilder, String title, String anchor) {
markupDocBuilder.sectionTitleWithAnchorLevel2(title, anchor);
}
public static class Parameters {
private final Map<String, Model> definitions;
public Parameters(Map<String, Model> definitions) {
this.definitions = definitions;
}
}
}

View File

@@ -0,0 +1,161 @@
/*
* Copyright 2016 Robert Winkler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.swagger2markup.internal.document;
import io.github.swagger2markup.Labels;
import io.github.swagger2markup.Swagger2MarkupConverter;
import io.github.swagger2markup.internal.component.*;
import io.github.swagger2markup.markup.builder.MarkupDocBuilder;
import io.github.swagger2markup.spi.MarkupComponent;
import io.swagger.models.Contact;
import io.swagger.models.Info;
import io.swagger.models.Swagger;
import io.swagger.models.Tag;
import org.apache.commons.lang3.Validate;
import java.util.List;
import static io.github.swagger2markup.internal.utils.MarkupDocBuilderUtils.markupDescription;
import static io.github.swagger2markup.spi.OverviewDocumentExtension.Context;
import static io.github.swagger2markup.spi.OverviewDocumentExtension.Position;
import static org.apache.commons.collections4.CollectionUtils.isNotEmpty;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
public class OverviewDocument extends MarkupComponent<OverviewDocument.Parameters> {
public static final int SECTION_TITLE_LEVEL = 2;
private static final String OVERVIEW_ANCHOR = "overview";
private final VersionInfoComponent versionInfoComponent;
private final ContactInfoComponent contactInfoComponent;
private final LicenseInfoComponent licenseInfoComponent;
private final UriSchemeComponent uriSchemeComponent;
private final TagsComponent tagsComponent;
private final ProducesComponent producesComponent;
private final ConsumesComponent consumesComponent;
public OverviewDocument(Swagger2MarkupConverter.Context context) {
super(context);
versionInfoComponent = new VersionInfoComponent(context);
contactInfoComponent = new ContactInfoComponent(context);
licenseInfoComponent = new LicenseInfoComponent(context);
uriSchemeComponent = new UriSchemeComponent(context);
tagsComponent = new TagsComponent(context);
producesComponent = new ProducesComponent(context);
consumesComponent = new ConsumesComponent(context);
}
public static OverviewDocument.Parameters parameters(Swagger swagger) {
return new OverviewDocument.Parameters(swagger);
}
/**
* Builds the overview MarkupDocument.
*
* @return the overview MarkupDocument
*/
@Override
public MarkupDocBuilder apply(MarkupDocBuilder markupDocBuilder, OverviewDocument.Parameters params) {
Swagger swagger = params.swagger;
Info info = swagger.getInfo();
buildDocumentTitle(markupDocBuilder, info.getTitle());
applyOverviewDocumentExtension(new Context(Position.DOCUMENT_BEFORE, markupDocBuilder));
buildOverviewTitle(markupDocBuilder, labels.getLabel(Labels.OVERVIEW));
applyOverviewDocumentExtension(new Context(Position.DOCUMENT_BEGIN, markupDocBuilder));
buildDescriptionParagraph(markupDocBuilder, info.getDescription());
buildVersionInfoSection(markupDocBuilder, info);
buildContactInfoSection(markupDocBuilder, info.getContact());
buildLicenseInfoSection(markupDocBuilder, info);
buildUriSchemeSection(markupDocBuilder, swagger);
buildTagsSection(markupDocBuilder, swagger.getTags());
buildConsumesSection(markupDocBuilder, swagger.getConsumes());
buildProducesSection(markupDocBuilder, swagger.getProduces());
applyOverviewDocumentExtension(new Context(Position.DOCUMENT_END, markupDocBuilder));
applyOverviewDocumentExtension(new Context(Position.DOCUMENT_AFTER, markupDocBuilder));
return markupDocBuilder;
}
private void buildDocumentTitle(MarkupDocBuilder markupDocBuilder, String title) {
markupDocBuilder.documentTitle(title);
}
private void buildOverviewTitle(MarkupDocBuilder markupDocBuilder, String title) {
markupDocBuilder.sectionTitleWithAnchorLevel1(title, OVERVIEW_ANCHOR);
}
void buildDescriptionParagraph(MarkupDocBuilder markupDocBuilder, String description) {
if (isNotBlank(description)) {
markupDocBuilder.paragraph(markupDescription(config.getSwaggerMarkupLanguage(), markupDocBuilder, description));
}
}
private void buildVersionInfoSection(MarkupDocBuilder markupDocBuilder, Info info) {
if (info != null) {
versionInfoComponent.apply(markupDocBuilder, VersionInfoComponent.parameters(info, SECTION_TITLE_LEVEL));
}
}
private void buildContactInfoSection(MarkupDocBuilder markupDocBuilder, Contact contact) {
if (contact != null) {
contactInfoComponent.apply(markupDocBuilder, ContactInfoComponent.parameters(contact, SECTION_TITLE_LEVEL));
}
}
private void buildLicenseInfoSection(MarkupDocBuilder markupDocBuilder, Info info) {
if (info != null) {
licenseInfoComponent.apply(markupDocBuilder, LicenseInfoComponent.parameters(info, SECTION_TITLE_LEVEL));
}
}
private void buildUriSchemeSection(MarkupDocBuilder markupDocBuilder, Swagger swagger) {
uriSchemeComponent.apply(markupDocBuilder, UriSchemeComponent.parameters(swagger, SECTION_TITLE_LEVEL));
}
private void buildTagsSection(MarkupDocBuilder markupDocBuilder, List<Tag> tags) {
if (isNotEmpty(tags)) {
tagsComponent.apply(markupDocBuilder, TagsComponent.parameters(tags, SECTION_TITLE_LEVEL));
}
}
private void buildConsumesSection(MarkupDocBuilder markupDocBuilder, List<String> consumes) {
if (isNotEmpty(consumes)) {
consumesComponent.apply(markupDocBuilder, ConsumesComponent.parameters(consumes, SECTION_TITLE_LEVEL));
}
}
private void buildProducesSection(MarkupDocBuilder markupDocBuilder, List<String> produces) {
if (isNotEmpty(produces)) {
producesComponent.apply(markupDocBuilder, ProducesComponent.parameters(produces, SECTION_TITLE_LEVEL));
}
}
/**
* Apply extension context to all OverviewContentExtension
*
* @param context context
*/
private void applyOverviewDocumentExtension(Context context) {
extensionRegistry.getOverviewDocumentExtensions().forEach(extension -> extension.apply(context));
}
public static class Parameters {
private final Swagger swagger;
public Parameters(Swagger swagger) {
this.swagger = Validate.notNull(swagger, "Swagger must not be null");
}
}
}

View File

@@ -0,0 +1,258 @@
/*
* Copyright 2016 Robert Winkler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.swagger2markup.internal.document;
import com.google.common.collect.Multimap;
import io.github.swagger2markup.GroupBy;
import io.github.swagger2markup.Labels;
import io.github.swagger2markup.Swagger2MarkupConfig;
import io.github.swagger2markup.Swagger2MarkupConverter;
import io.github.swagger2markup.internal.component.PathOperationComponent;
import io.github.swagger2markup.internal.resolver.DefinitionDocumentResolverFromOperation;
import io.github.swagger2markup.internal.resolver.OperationDocumentNameResolver;
import io.github.swagger2markup.internal.resolver.OperationDocumentResolverDefault;
import io.github.swagger2markup.internal.resolver.SecurityDocumentResolver;
import io.github.swagger2markup.internal.utils.PathUtils;
import io.github.swagger2markup.internal.utils.RegexUtils;
import io.github.swagger2markup.internal.utils.TagUtils;
import io.github.swagger2markup.markup.builder.MarkupDocBuilder;
import io.github.swagger2markup.model.PathOperation;
import io.github.swagger2markup.spi.MarkupComponent;
import io.swagger.models.Path;
import io.swagger.models.Tag;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.apache.commons.lang3.text.WordUtils;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
import static io.github.swagger2markup.internal.utils.MarkupDocBuilderUtils.copyMarkupDocBuilder;
import static io.github.swagger2markup.internal.utils.MarkupDocBuilderUtils.crossReference;
import static io.github.swagger2markup.spi.PathsDocumentExtension.Context;
import static io.github.swagger2markup.spi.PathsDocumentExtension.Position;
import static io.github.swagger2markup.utils.IOUtils.normalizeName;
/**
* @author Robert Winkler
*/
public class PathsDocument extends MarkupComponent<PathsDocument.Parameters> {
private static final String PATHS_ANCHOR = "paths";
private final PathOperationComponent pathOperationComponent;
private final OperationDocumentNameResolver operationDocumentNameResolver;
private final OperationDocumentResolverDefault operationDocumentResolverDefault;
public PathsDocument(Swagger2MarkupConverter.Context context) {
super(context);
this.pathOperationComponent = new PathOperationComponent(context,
new DefinitionDocumentResolverFromOperation(context),
new SecurityDocumentResolver(context));
this.operationDocumentNameResolver = new OperationDocumentNameResolver(context);
this.operationDocumentResolverDefault = new OperationDocumentResolverDefault(context);
if (logger.isDebugEnabled()) {
if (config.isGeneratedExamplesEnabled()) {
logger.debug("Generate examples is enabled.");
} else {
logger.debug("Generate examples is disabled.");
}
if (config.isSeparatedOperationsEnabled()) {
logger.debug("Create separated operation files is enabled.");
} else {
logger.debug("Create separated operation files is disabled.");
}
}
}
public static PathsDocument.Parameters parameters(Map<String, Path> paths) {
return new PathsDocument.Parameters(paths);
}
/**
* Builds the paths MarkupDocument.
*
* @return the paths MarkupDocument
*/
@Override
public MarkupDocBuilder apply(MarkupDocBuilder markupDocBuilder, PathsDocument.Parameters params) {
Map<String, Path> paths = params.paths;
if (MapUtils.isNotEmpty(paths)) {
applyPathsDocumentExtension(new Context(Position.DOCUMENT_BEFORE, markupDocBuilder));
buildPathsTitle(markupDocBuilder);
applyPathsDocumentExtension(new Context(Position.DOCUMENT_BEGIN, markupDocBuilder));
buildsPathsSection(markupDocBuilder, paths);
applyPathsDocumentExtension(new Context(Position.DOCUMENT_END, markupDocBuilder));
applyPathsDocumentExtension(new Context(Position.DOCUMENT_AFTER, markupDocBuilder));
}
return markupDocBuilder;
}
/**
* Builds the paths section. Groups the paths either as-is, by tags or using regex.
*
* @param paths the Swagger paths
*/
private void buildsPathsSection(MarkupDocBuilder markupDocBuilder, Map<String, Path> paths) {
List<PathOperation> pathOperations = PathUtils.toPathOperationsList(paths, getBasePath(), config.getOperationOrdering());
if (CollectionUtils.isNotEmpty(pathOperations)) {
if (config.getPathsGroupedBy() == GroupBy.AS_IS) {
pathOperations.forEach(operation -> buildOperation(markupDocBuilder, operation, config));
} else if (config.getPathsGroupedBy() == GroupBy.TAGS) {
Validate.notEmpty(context.getSwagger().getTags(), "Tags must not be empty, when operations are grouped by tags");
// Group operations by tag
Multimap<String, PathOperation> operationsGroupedByTag = TagUtils.groupOperationsByTag(pathOperations, config.getOperationOrdering());
Map<String, Tag> tagsMap = TagUtils.toSortedMap(context.getSwagger().getTags(), config.getTagOrdering());
tagsMap.forEach((String tagName, Tag tag) -> {
markupDocBuilder.sectionTitleWithAnchorLevel2(WordUtils.capitalize(tagName), tagName + "_resource");
String description = tag.getDescription();
if (StringUtils.isNotBlank(description)) {
markupDocBuilder.paragraph(description);
}
operationsGroupedByTag.get(tagName).forEach(operation -> buildOperation(markupDocBuilder, operation, config));
});
} else if (config.getPathsGroupedBy() == GroupBy.REGEX) {
Validate.notNull(config.getHeaderPattern(), "Header regex pattern must not be empty when operations are grouped using regex");
Pattern headerPattern = config.getHeaderPattern();
Multimap<String, PathOperation> operationsGroupedByRegex = RegexUtils.groupOperationsByRegex(pathOperations, headerPattern);
Set<String> keys = operationsGroupedByRegex.keySet();
String[] sortedHeaders = RegexUtils.toSortedArray(keys);
for (String header : sortedHeaders) {
markupDocBuilder.sectionTitleWithAnchorLevel2(WordUtils.capitalize(header), header + "_resource");
operationsGroupedByRegex.get(header).forEach(operation -> buildOperation(markupDocBuilder, operation, config));
}
}
}
}
/**
* Builds the path title depending on the operationsGroupedBy configuration setting.
*/
private void buildPathsTitle(MarkupDocBuilder markupDocBuilder) {
if (config.getPathsGroupedBy() == GroupBy.AS_IS) {
buildPathsTitle(markupDocBuilder, labels.getLabel(Labels.PATHS));
} else if (config.getPathsGroupedBy() == GroupBy.REGEX) {
buildPathsTitle(markupDocBuilder, labels.getLabel(Labels.OPERATIONS));
} else {
buildPathsTitle(markupDocBuilder, labels.getLabel(Labels.RESOURCES));
}
}
/**
* Returns the basePath which should be prepended to the relative path
*
* @return either the relative or the full path
*/
private String getBasePath() {
if (config.isBasePathPrefixEnabled()) {
return StringUtils.defaultString(context.getSwagger().getBasePath());
}
return "";
}
private void buildPathsTitle(MarkupDocBuilder markupDocBuilder, String title) {
markupDocBuilder.sectionTitleWithAnchorLevel1(title, PATHS_ANCHOR);
}
/**
* Apply extension context to all OperationsContentExtension.
*
* @param context context
*/
private void applyPathsDocumentExtension(Context context) {
extensionRegistry.getPathsDocumentExtensions().forEach(extension -> extension.apply(context));
}
/**
* Builds a path operation depending on generation mode.
*
* @param operation operation
*/
private void buildOperation(MarkupDocBuilder markupDocBuilder, PathOperation operation, Swagger2MarkupConfig config) {
if (config.isSeparatedOperationsEnabled()) {
MarkupDocBuilder pathDocBuilder = copyMarkupDocBuilder(markupDocBuilder);
applyPathOperationComponent(pathDocBuilder, operation);
java.nio.file.Path operationFile = context.getOutputPath().resolve(operationDocumentNameResolver.apply(operation));
pathDocBuilder.writeToFileWithoutExtension(operationFile, StandardCharsets.UTF_8);
if (logger.isDebugEnabled()) {
logger.debug("Separate operation file produced : '{}'", operationFile);
}
buildOperationRef(markupDocBuilder, operation);
} else {
applyPathOperationComponent(markupDocBuilder, operation);
}
if (logger.isDebugEnabled()) {
logger.debug("Operation processed : '{}' (normalized id = '{}')", operation, normalizeName(operation.getId()));
}
}
/**
* Builds a path operation.
*
* @param markupDocBuilder the docbuilder do use for output
* @param operation the Swagger Operation
*/
private void applyPathOperationComponent(MarkupDocBuilder markupDocBuilder, PathOperation operation) {
if (operation != null) {
pathOperationComponent.apply(markupDocBuilder, PathOperationComponent.parameters(operation));
}
}
/**
* Builds a cross-reference to a separated operation file
*
* @param markupDocBuilder the markupDocBuilder do use for output
* @param operation the Swagger Operation
*/
private void buildOperationRef(MarkupDocBuilder markupDocBuilder, PathOperation operation) {
buildOperationTitle(markupDocBuilder, crossReference(markupDocBuilder, operationDocumentResolverDefault.apply(operation), operation.getId(), operation.getTitle()), "ref-" + operation.getId());
}
/**
* Adds a operation title to the document.
*
* @param title the operation title
* @param anchor optional anchor (null => auto-generate from title)
*/
private void buildOperationTitle(MarkupDocBuilder markupDocBuilder, String title, String anchor) {
if (config.getPathsGroupedBy() == GroupBy.AS_IS) {
markupDocBuilder.sectionTitleWithAnchorLevel2(title, anchor);
} else {
markupDocBuilder.sectionTitleWithAnchorLevel3(title, anchor);
}
}
public static class Parameters {
private final Map<String, Path> paths;
public Parameters(Map<String, Path> paths) {
this.paths = paths;
}
}
}

View File

@@ -0,0 +1,96 @@
/*
* Copyright 2016 Robert Winkler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.swagger2markup.internal.document;
import io.github.swagger2markup.Swagger2MarkupConverter;
import io.github.swagger2markup.internal.component.SecuritySchemeDefinitionComponent;
import io.github.swagger2markup.markup.builder.MarkupDocBuilder;
import io.github.swagger2markup.spi.MarkupComponent;
import io.swagger.models.auth.SecuritySchemeDefinition;
import org.apache.commons.collections4.MapUtils;
import java.util.Map;
import static io.github.swagger2markup.Labels.SECURITY;
import static io.github.swagger2markup.internal.utils.MapUtils.toSortedMap;
import static io.github.swagger2markup.spi.SecurityDocumentExtension.Context;
import static io.github.swagger2markup.spi.SecurityDocumentExtension.Position;
/**
* @author Robert Winkler
*/
public class SecurityDocument extends MarkupComponent<SecurityDocument.Parameters> {
private static final String SECURITY_ANCHOR = "securityScheme";
private final SecuritySchemeDefinitionComponent securitySchemeDefinitionComponent;
public SecurityDocument(Swagger2MarkupConverter.Context context) {
super(context);
this.securitySchemeDefinitionComponent = new SecuritySchemeDefinitionComponent(context);
}
public static SecurityDocument.Parameters parameters(Map<String, SecuritySchemeDefinition> securitySchemeDefinitions) {
return new SecurityDocument.Parameters(securitySchemeDefinitions);
}
/**
* Builds the security MarkupDocument.
*
* @return the security MarkupDocument
*/
@Override
public MarkupDocBuilder apply(MarkupDocBuilder markupDocBuilder, SecurityDocument.Parameters params) {
Map<String, SecuritySchemeDefinition> definitions = params.securitySchemeDefinitions;
if (MapUtils.isNotEmpty(definitions)) {
applySecurityDocumentExtension(new Context(Position.DOCUMENT_BEFORE, markupDocBuilder));
buildSecurityTitle(markupDocBuilder, labels.getLabel(SECURITY));
applySecurityDocumentExtension(new Context(Position.DOCUMENT_BEGIN, markupDocBuilder));
buildSecuritySchemeDefinitionsSection(markupDocBuilder, definitions);
applySecurityDocumentExtension(new Context(Position.DOCUMENT_END, markupDocBuilder));
applySecurityDocumentExtension(new Context(Position.DOCUMENT_AFTER, markupDocBuilder));
}
return markupDocBuilder;
}
private void buildSecurityTitle(MarkupDocBuilder markupDocBuilder, String title) {
markupDocBuilder.sectionTitleWithAnchorLevel1(title, SECURITY_ANCHOR);
}
private void buildSecuritySchemeDefinitionsSection(MarkupDocBuilder markupDocBuilder, Map<String, SecuritySchemeDefinition> securitySchemes) {
Map<String, SecuritySchemeDefinition> securitySchemeNames = toSortedMap(securitySchemes, null); // TODO : provide a dedicated ordering configuration for security schemes
securitySchemeNames.forEach((String securitySchemeName, SecuritySchemeDefinition securityScheme) ->
securitySchemeDefinitionComponent.apply(markupDocBuilder, SecuritySchemeDefinitionComponent.parameters(
securitySchemeName, securityScheme, 2
)));
}
/**
* Apply extension context to all SecurityContentExtension
*
* @param context context
*/
private void applySecurityDocumentExtension(Context context) {
extensionRegistry.getSecurityDocumentExtensions().forEach(extension -> extension.apply(context));
}
public static class Parameters {
private final Map<String, SecuritySchemeDefinition> securitySchemeDefinitions;
public Parameters(Map<String, SecuritySchemeDefinition> securitySchemeDefinitions) {
this.securitySchemeDefinitions = securitySchemeDefinitions;
}
}
}

View File

@@ -0,0 +1,37 @@
/*
* Copyright 2016 Robert Winkler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.swagger2markup.internal.resolver;
import io.github.swagger2markup.Swagger2MarkupConverter;
import java.io.File;
import static io.github.swagger2markup.utils.IOUtils.normalizeName;
public class DefinitionDocumentNameResolver extends DocumentResolver {
public DefinitionDocumentNameResolver(Swagger2MarkupConverter.Context context) {
super(context);
}
public String apply(String definitionName) {
if (config.isSeparatedDefinitionsEnabled())
return new File(config.getSeparatedDefinitionsFolder(), markupDocBuilder.addFileExtension(normalizeName(definitionName))).getPath();
else
return markupDocBuilder.addFileExtension(config.getDefinitionsDocument());
}
}

View File

@@ -0,0 +1,40 @@
/*
* Copyright 2016 Robert Winkler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.swagger2markup.internal.resolver;
import io.github.swagger2markup.Swagger2MarkupConverter;
import static org.apache.commons.lang3.StringUtils.defaultString;
/**
* Default {@code DocumentResolver} functor
*/
public class DefinitionDocumentResolverDefault extends DocumentResolver {
private final DefinitionDocumentNameResolver definitionDocumentNameResolver;
public DefinitionDocumentResolverDefault(Swagger2MarkupConverter.Context context) {
super(context);
this.definitionDocumentNameResolver = new DefinitionDocumentNameResolver(context);
}
public String apply(String definitionName) {
if (!config.isInterDocumentCrossReferencesEnabled() || context.getOutputPath() == null)
return null;
else
return defaultString(config.getInterDocumentCrossReferencesPrefix()) + definitionDocumentNameResolver.apply(definitionName);
}
}

View File

@@ -0,0 +1,42 @@
/*
* Copyright 2016 Robert Winkler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.swagger2markup.internal.resolver;
import io.github.swagger2markup.Swagger2MarkupConverter;
import static io.github.swagger2markup.utils.IOUtils.normalizeName;
import static org.apache.commons.lang3.StringUtils.defaultString;
/**
* Overrides definition document resolver functor for inter-document cross-references from definitions files.
* This implementation simplifies the path between two definitions because all definitions are in the same path.
*/
public class DefinitionDocumentResolverFromDefinition extends DefinitionDocumentResolverDefault {
public DefinitionDocumentResolverFromDefinition(Swagger2MarkupConverter.Context context) {
super(context);
}
public String apply(String definitionName) {
String defaultResolver = super.apply(definitionName);
if (defaultResolver != null && config.isSeparatedDefinitionsEnabled())
return defaultString(config.getInterDocumentCrossReferencesPrefix()) + markupDocBuilder.addFileExtension(normalizeName(definitionName));
else
return defaultResolver;
}
}

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