Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6c50292563 | ||
|
|
3d116dd7f8 | ||
|
|
e6f7372c9f | ||
|
|
0ca91ea930 | ||
|
|
efea76d243 | ||
|
|
cd4ef60cc3 | ||
|
|
6ed557b4ac | ||
|
|
139c294f25 | ||
|
|
68a433b76b | ||
|
|
b0dba05b48 | ||
|
|
55bb2bdd71 | ||
|
|
3d4d87c0b0 | ||
|
|
ad0d03c95c | ||
|
|
0675beaa45 | ||
|
|
cb6526d0e5 | ||
|
|
f5a8454817 | ||
|
|
5bf8270f2e | ||
|
|
6c794e75fd | ||
|
|
b472bf97bb |
82
README.adoc
@@ -3,9 +3,7 @@
|
|||||||
:version: 0.1.0
|
:version: 0.1.0
|
||||||
:hardbreaks:
|
:hardbreaks:
|
||||||
|
|
||||||
image:https://travis-ci.org/RobWin/swagger2markup.svg["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:http://img.shields.io/:version-{version}-blue.svg["Semantic Versioning", link="http://semver.org"] 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://travis-ci.org/RobWin/swagger2markup.svg["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:http://img.shields.io/:version-{version}-blue.svg["Semantic Versioning", link="https://bintray.com/robwin/maven/swagger2markup/0.1.0/view"] image:http://img.shields.io/badge/license-ASF2-blue.svg["Apache License 2", link="http://www.apache.org/licenses/LICENSE-2.0.txt"]
|
||||||
|
|
||||||
WARNING: Still under heavy development
|
|
||||||
|
|
||||||
== Overview
|
== Overview
|
||||||
|
|
||||||
@@ -15,7 +13,42 @@ The primary goal of this project is to simplify the documentation of RESTful API
|
|||||||
|
|
||||||
== Usage
|
== Usage
|
||||||
|
|
||||||
Using the Swagger2MarkupConverter is simple. For instance, you can generate your AsciiDoc/Markdown documentation using https://github.com/spring-projects/spring-boot[Spring Boot] and https://github.com/martypitt/swagger-springmvc[swagger-springmvc] as follows:
|
=== Adding Swagger2Markup to your project
|
||||||
|
|
||||||
|
==== Maven
|
||||||
|
|
||||||
|
[source,xml]
|
||||||
|
----
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<id>jcenter-release</id>
|
||||||
|
<name>jcenter</name>
|
||||||
|
<url>http://oss.jfrog.org/artifactory/oss-release-local/</url>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.github.robwin.swagger2markup</groupId>
|
||||||
|
<artifactId>swagger2markup</artifactId>
|
||||||
|
<version>0.2.0</version>
|
||||||
|
</dependency>
|
||||||
|
----
|
||||||
|
|
||||||
|
==== Gradle
|
||||||
|
|
||||||
|
[source,groovy]
|
||||||
|
----
|
||||||
|
repositories {
|
||||||
|
jcenter()
|
||||||
|
}
|
||||||
|
|
||||||
|
compile "io.github.robwin:swagger2markup:0.2.0"
|
||||||
|
----
|
||||||
|
|
||||||
|
=== Using Swagger2Markup
|
||||||
|
|
||||||
|
Using the Swagger2MarkupConverter is simple. For instance, you can generate your AsciiDoc/Markdown documentation using https://github.com/spring-projects/spring-boot[Spring Boot] and https://github.com/martypitt/swagger-springmvc[swagger-springmvc] as follows.
|
||||||
|
See demo project https://github.com/RobWin/spring-swagger2markup-demo[spring-swagger2markup-demo].
|
||||||
|
|
||||||
[source,java]
|
[source,java]
|
||||||
----
|
----
|
||||||
@@ -29,16 +62,19 @@ public class Swagger2MarkupTest {
|
|||||||
public void convertSwaggerToMarkup() {
|
public void convertSwaggerToMarkup() {
|
||||||
//Remote
|
//Remote
|
||||||
Swagger2MarkupConverter.from("http://localhost:8080/api-docs").
|
Swagger2MarkupConverter.from("http://localhost:8080/api-docs").
|
||||||
toAsciiDoc("src/docs/asciidoc/example.adoc");
|
withMarkupLanguage(MarkupLanguage.MARKDOWN).
|
||||||
|
withExamples("docs/generated").withSchemas("docs/schemas").build()
|
||||||
|
.intoFolder("src/docs/markdown");
|
||||||
|
|
||||||
Swagger2MarkupConverter.from("http://localhost:8080/api-docs").
|
Swagger2MarkupConverter.from("http://localhost:8080/api-docs").
|
||||||
toMarkdown("src/docs/markdown/example.md");
|
withExamples("docs").withSchemas("docs/schemas").build()
|
||||||
|
.intoFolder("src/docs/asciidoc");
|
||||||
|
|
||||||
//Local
|
//Local
|
||||||
File file = new File(Swagger2MarkupTest.class.getResource("/json/swagger.json").getFile());
|
File file = new File(Swagger2MarkupTest.class.getResource("/json/swagger.json").getFile());
|
||||||
Swagger2MarkupConverter.from(file.getAbsolutePath()).toAsciiDoc("src/docs/asciidoc/swagger.adoc")
|
Swagger2MarkupConverter.from(file.getAbsolutePath()).build()
|
||||||
|
.intoFolder("src/docs/asciidoc");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
@@ -75,30 +111,36 @@ public class SpringBootSwaggerConfig {
|
|||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
You can then generate HTML5 and PDF documentation via https://github.com/asciidoctor/asciidoctorj[asciidoctorj] or even better via the https://github.com/asciidoctor/asciidoctor-gradle-plugin[asciidoctor-gradle-plugin] and https://github.com/aalmiray/markdown-gradle-plugin[markdown-gradle-plugin].
|
You can generate your HTML5 and PDF 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/aalmiray/markdown-gradle-plugin[markdown-gradle-plugin].
|
||||||
|
You can also use https://github.com/tomchristie/mkdocs[MkDocs] and https://github.com/rtfd/readthedocs.org[ReadTheDocs] to publish your Markdown documentation.
|
||||||
|
See http://spring-swagger2markup-demo.readthedocs.org/[ReadTheDocs-demo]
|
||||||
|
|
||||||
== Example
|
== Examples
|
||||||
== swagger.json
|
== Swagger source file
|
||||||
image::images/swagger_json.PNG[swagger_json]
|
image::images/swagger_json.PNG[swagger_json]
|
||||||
|
|
||||||
=== Generated AsciiDoc file
|
=== Generated AsciiDoc file
|
||||||
image::images/asciidoc.PNG[asciidoc]
|
image::images/asciidoc.PNG[asciidoc]
|
||||||
|
|
||||||
=== Generated Markdown file
|
=== Generated Markdown file
|
||||||
image::images/markdown.PNG[asciidoc]
|
image::images/markdown.PNG[markdown]
|
||||||
|
|
||||||
=== Generated HTML
|
=== Generated HTML using AsciidoctorJ
|
||||||
image::images/asciidoc_html.PNG[asciidoc_html]
|
image::images/asciidoc_html.PNG[asciidoc_html]
|
||||||
|
|
||||||
|
=== Generated HTML using Mkdocs
|
||||||
|
image::images/mkdocs_html.PNG[mkdocs_html]
|
||||||
|
|
||||||
|
=== Generated PDF using AsciidoctorJ
|
||||||
|
image::images/asciidoc_pdf.PNG[asciidoc_pdf]
|
||||||
|
|
||||||
== Document Builder
|
== Document Builder
|
||||||
The converter allows to build an AsciiDoc or Markdown document via the Builder pattern:
|
The Swagger2Markup library allows to build an AsciiDoc or Markdown document via the Builder pattern:
|
||||||
[source,java]
|
[source,java]
|
||||||
----
|
----
|
||||||
String asciiDoc = new AsciiDocBuilder().documentTitle("Title")
|
DocumentBuilder builder = DocumentBuilders.documentBuilder(MarkupLanguage.ASCIIDOC);
|
||||||
.sectionTitleLevel1("Section1").paragraph("Text text")
|
builder.documentTitle("Test title").textLine("Text line").writeToFile("/tmp", "test.adoc", StandardCharsets.UTF_8);
|
||||||
.sectionTitleLevel2("Code examples").listing("Code example").toString();
|
|
||||||
|
|
||||||
String markdown = new MarkdownBuilder().documentTitle("Title")
|
DocumentBuilder builder = DocumentBuilders.documentBuilder(MarkupLanguage.MARKDOWN);
|
||||||
.sectionTitleLevel1("Section1").paragraph("Text text")
|
builder.documentTitle("Test title").textLine("Text line").writeToFile("/tmp", "test.adoc", StandardCharsets.UTF_8);
|
||||||
.sectionTitleLevel2("Code examples").listing("Code example").toString();
|
|
||||||
----
|
----
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
= Release Notes
|
= Release Notes
|
||||||
|
|
||||||
== Version 0.1.0
|
== Version 0.1.0
|
||||||
* Initial version with support for AsciiDoc and Markdown
|
* Initial version with support for AsciiDoc and Markdown
|
||||||
|
|
||||||
|
== Version 0.2.0
|
||||||
|
* This version is not downward compatible. This version supports includes of example files and JSON/XML Schema files. See documentation.
|
||||||
23
build.gradle
@@ -8,20 +8,16 @@ buildscript {
|
|||||||
classpath 'org.asciidoctor:asciidoctorj-pdf:1.5.0-alpha.6'
|
classpath 'org.asciidoctor:asciidoctorj-pdf:1.5.0-alpha.6'
|
||||||
classpath 'io.spring.gradle:dependency-management-plugin:0.3.1.RELEASE'
|
classpath 'io.spring.gradle:dependency-management-plugin:0.3.1.RELEASE'
|
||||||
classpath 'org.kt3k.gradle.plugin:coveralls-gradle-plugin:2.0.1'
|
classpath 'org.kt3k.gradle.plugin:coveralls-gradle-plugin:2.0.1'
|
||||||
classpath 'me.champeau.gradle:jbake-gradle-plugin:0.2'
|
|
||||||
classpath 'org.jbake:jbake-core:2.3.2'
|
|
||||||
classpath 'org.asciidoctor:asciidoctorj:1.5.2'
|
classpath 'org.asciidoctor:asciidoctorj:1.5.2'
|
||||||
classpath 'org.freemarker:freemarker:2.3.19'
|
|
||||||
classpath 'org.springframework.boot:spring-boot-gradle-plugin:1.2.1.RELEASE'
|
|
||||||
classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.0'
|
classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.0'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
description = 'swagger2markup Build'
|
description = 'swagger2markup Build'
|
||||||
version = '0.1.0'
|
version = '0.2.0'
|
||||||
group = 'io.swagger2markup'
|
group = 'io.github.robwin'
|
||||||
|
|
||||||
apply plugin: 'java'
|
apply plugin: 'java'
|
||||||
apply plugin: 'maven'
|
apply plugin: 'maven-publish'
|
||||||
apply plugin: 'org.asciidoctor.convert'
|
apply plugin: 'org.asciidoctor.convert'
|
||||||
apply plugin: 'jacoco'
|
apply plugin: 'jacoco'
|
||||||
apply plugin: 'com.github.kt3k.coveralls'
|
apply plugin: 'com.github.kt3k.coveralls'
|
||||||
@@ -40,12 +36,13 @@ tasks.withType(JavaCompile) {
|
|||||||
repositories {
|
repositories {
|
||||||
jcenter()
|
jcenter()
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
mavenLocal()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile 'io.swagger:swagger-compat-spec-parser'
|
compile 'io.swagger:swagger-compat-spec-parser'
|
||||||
compile 'commons-collections:commons-collections'
|
compile 'commons-collections:commons-collections'
|
||||||
|
compile 'commons-io:commons-io'
|
||||||
|
compile 'ch.qos.logback:logback-classic'
|
||||||
testCompile 'junit:junit'
|
testCompile 'junit:junit'
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,17 +50,21 @@ dependencyManagement {
|
|||||||
dependencies {
|
dependencies {
|
||||||
"io.swagger:swagger-compat-spec-parser" "1.0.0"
|
"io.swagger:swagger-compat-spec-parser" "1.0.0"
|
||||||
"commons-collections:commons-collections" "3.2.1"
|
"commons-collections:commons-collections" "3.2.1"
|
||||||
|
"commons-io:commons-io" "2.4"
|
||||||
"com.mangofactory:swagger-springmvc" "0.9.5"
|
"com.mangofactory:swagger-springmvc" "0.9.5"
|
||||||
"com.jayway.restassured:spring-mock-mvc" "2.4.0"
|
"com.jayway.restassured:spring-mock-mvc" "2.4.0"
|
||||||
|
"ch.qos.logback:logback-classic" "1.1.2"
|
||||||
"junit:junit" "4.11"
|
"junit:junit" "4.11"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
asciidoctor {
|
asciidoctor {
|
||||||
|
backends = ['html5', 'pdf']
|
||||||
attributes = [
|
attributes = [
|
||||||
doctype: 'book',
|
doctype: 'book',
|
||||||
toc: 'left',
|
toc: 'left',
|
||||||
toclevels: '1'
|
toclevels: '2',
|
||||||
|
numbered: ''
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,6 +79,10 @@ tasks.coveralls {
|
|||||||
dependsOn 'check'
|
dependsOn 'check'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tasks.asciidoctor {
|
||||||
|
dependsOn 'check'
|
||||||
|
}
|
||||||
|
|
||||||
task wrapper(type: Wrapper) {
|
task wrapper(type: Wrapper) {
|
||||||
gradleVersion = '2.2.1'
|
gradleVersion = '2.2.1'
|
||||||
}
|
}
|
||||||
@@ -29,5 +29,47 @@ if (!project.hasProperty('bintrayApiKey')) ext.bintrayApiKey = ''
|
|||||||
bintray {
|
bintray {
|
||||||
user = project.bintrayUsername
|
user = project.bintrayUsername
|
||||||
key = project.bintrayApiKey
|
key = project.bintrayApiKey
|
||||||
pkg.repo = 'swagger2markup'
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
publishing {
|
||||||
|
publications {
|
||||||
|
mavenJava(MavenPublication) {
|
||||||
|
from components.java
|
||||||
|
pom.withXml {
|
||||||
|
def devs = ['RobWin': 'Robert Winkler']
|
||||||
|
def root = asNode()
|
||||||
|
root.appendNode('name', 'swagger2markup')
|
||||||
|
root.appendNode('packaging', 'jar')
|
||||||
|
root.appendNode('url', 'https://github.com/RobWin/swagger2markup')
|
||||||
|
root.appendNode('description', 'A Swagger to Markup (AsciiDoc and Markdown) converter.')
|
||||||
|
|
||||||
|
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('distribution', 'repo')
|
||||||
|
|
||||||
|
root.appendNode('scm').appendNode('url', 'https://github.com/RobWin/swagger2markup.git')
|
||||||
|
|
||||||
|
def developers = root.appendNode('developers')
|
||||||
|
devs.each {
|
||||||
|
def d = developers.appendNode('developer')
|
||||||
|
d.appendNode('id', it.key)
|
||||||
|
d.appendNode('name', it.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 96 KiB After Width: | Height: | Size: 105 KiB |
BIN
images/asciidoc_pdf.PNG
Normal file
|
After Width: | Height: | Size: 153 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 21 KiB |
BIN
images/mkdocs_html.PNG
Normal file
|
After Width: | Height: | Size: 87 KiB |
@@ -1,534 +0,0 @@
|
|||||||
= Swagger Petstore
|
|
||||||
This is a sample server Petstore server.
|
|
||||||
|
|
||||||
[Learn about Swagger](http://swagger.wordnik.com) or join the IRC channel `#swagger` on irc.freenode.net.
|
|
||||||
|
|
||||||
For this sample, you can use the api key `special-key` to test the authorization filters
|
|
||||||
|
|
||||||
Version: 1.0.0
|
|
||||||
|
|
||||||
== Update an existing pet
|
|
||||||
----
|
|
||||||
PUT /pets
|
|
||||||
----
|
|
||||||
|
|
||||||
=== Parameters
|
|
||||||
[format="csv", options="header"]
|
|
||||||
|===
|
|
||||||
Name,Located in,Description,Required
|
|
||||||
body,body,Pet object that needs to be added to the store,false
|
|
||||||
|===
|
|
||||||
|
|
||||||
=== Responses
|
|
||||||
[format="csv", options="header"]
|
|
||||||
|===
|
|
||||||
Code,Description
|
|
||||||
400,Invalid ID supplied
|
|
||||||
404,Pet not found
|
|
||||||
405,Validation exception
|
|
||||||
|===
|
|
||||||
|
|
||||||
=== Consumes
|
|
||||||
* application/json
|
|
||||||
* application/xml
|
|
||||||
|
|
||||||
=== Produces
|
|
||||||
* application/json
|
|
||||||
* application/xml
|
|
||||||
|
|
||||||
== Add a new pet to the store
|
|
||||||
----
|
|
||||||
POST /pets
|
|
||||||
----
|
|
||||||
|
|
||||||
=== Parameters
|
|
||||||
[format="csv", options="header"]
|
|
||||||
|===
|
|
||||||
Name,Located in,Description,Required
|
|
||||||
body,body,Pet object that needs to be added to the store,false
|
|
||||||
|===
|
|
||||||
|
|
||||||
=== Responses
|
|
||||||
[format="csv", options="header"]
|
|
||||||
|===
|
|
||||||
Code,Description
|
|
||||||
405,Invalid input
|
|
||||||
|===
|
|
||||||
|
|
||||||
=== Consumes
|
|
||||||
* application/json
|
|
||||||
* application/xml
|
|
||||||
|
|
||||||
=== Produces
|
|
||||||
* application/json
|
|
||||||
* application/xml
|
|
||||||
|
|
||||||
== Finds Pets by status
|
|
||||||
----
|
|
||||||
GET /pets/findByStatus
|
|
||||||
----
|
|
||||||
|
|
||||||
=== Description
|
|
||||||
:hardbreaks:
|
|
||||||
Multiple status values can be provided with comma seperated strings
|
|
||||||
|
|
||||||
=== Parameters
|
|
||||||
[format="csv", options="header"]
|
|
||||||
|===
|
|
||||||
Name,Located in,Description,Required
|
|
||||||
status,query,Status values that need to be considered for filter,false
|
|
||||||
|===
|
|
||||||
|
|
||||||
=== Responses
|
|
||||||
[format="csv", options="header"]
|
|
||||||
|===
|
|
||||||
Code,Description
|
|
||||||
200,successful operation
|
|
||||||
400,Invalid status value
|
|
||||||
|===
|
|
||||||
|
|
||||||
=== Produces
|
|
||||||
* application/json
|
|
||||||
* application/xml
|
|
||||||
|
|
||||||
== Finds Pets by tags
|
|
||||||
----
|
|
||||||
GET /pets/findByTags
|
|
||||||
----
|
|
||||||
|
|
||||||
=== Description
|
|
||||||
:hardbreaks:
|
|
||||||
Muliple tags can be provided with comma seperated strings. Use tag1, tag2, tag3 for testing.
|
|
||||||
|
|
||||||
=== Parameters
|
|
||||||
[format="csv", options="header"]
|
|
||||||
|===
|
|
||||||
Name,Located in,Description,Required
|
|
||||||
tags,query,Tags to filter by,false
|
|
||||||
|===
|
|
||||||
|
|
||||||
=== Responses
|
|
||||||
[format="csv", options="header"]
|
|
||||||
|===
|
|
||||||
Code,Description
|
|
||||||
200,successful operation
|
|
||||||
400,Invalid tag value
|
|
||||||
|===
|
|
||||||
|
|
||||||
=== Produces
|
|
||||||
* application/json
|
|
||||||
* application/xml
|
|
||||||
|
|
||||||
== Find pet by ID
|
|
||||||
----
|
|
||||||
GET /pets/{petId}
|
|
||||||
----
|
|
||||||
|
|
||||||
=== Description
|
|
||||||
:hardbreaks:
|
|
||||||
Returns a pet when ID < 10. ID > 10 or nonintegers will simulate API error conditions
|
|
||||||
|
|
||||||
=== Parameters
|
|
||||||
[format="csv", options="header"]
|
|
||||||
|===
|
|
||||||
Name,Located in,Description,Required
|
|
||||||
petId,path,ID of pet that needs to be fetched,true
|
|
||||||
|===
|
|
||||||
|
|
||||||
=== Responses
|
|
||||||
[format="csv", options="header"]
|
|
||||||
|===
|
|
||||||
Code,Description
|
|
||||||
200,successful operation
|
|
||||||
400,Invalid ID supplied
|
|
||||||
404,Pet not found
|
|
||||||
|===
|
|
||||||
|
|
||||||
=== Produces
|
|
||||||
* application/json
|
|
||||||
* application/xml
|
|
||||||
|
|
||||||
== Deletes a pet
|
|
||||||
----
|
|
||||||
DELETE /pets/{petId}
|
|
||||||
----
|
|
||||||
|
|
||||||
=== Parameters
|
|
||||||
[format="csv", options="header"]
|
|
||||||
|===
|
|
||||||
Name,Located in,Description,Required
|
|
||||||
api_key,header,,true
|
|
||||||
petId,path,Pet id to delete,true
|
|
||||||
|===
|
|
||||||
|
|
||||||
=== Responses
|
|
||||||
[format="csv", options="header"]
|
|
||||||
|===
|
|
||||||
Code,Description
|
|
||||||
400,Invalid pet value
|
|
||||||
|===
|
|
||||||
|
|
||||||
=== Produces
|
|
||||||
* application/json
|
|
||||||
* application/xml
|
|
||||||
|
|
||||||
== Updates a pet in the store with form data
|
|
||||||
----
|
|
||||||
POST /pets/{petId}
|
|
||||||
----
|
|
||||||
|
|
||||||
=== Parameters
|
|
||||||
[format="csv", options="header"]
|
|
||||||
|===
|
|
||||||
Name,Located in,Description,Required
|
|
||||||
petId,path,ID of pet that needs to be updated,true
|
|
||||||
name,formData,Updated name of the pet,true
|
|
||||||
status,formData,Updated status of the pet,true
|
|
||||||
|===
|
|
||||||
|
|
||||||
=== Responses
|
|
||||||
[format="csv", options="header"]
|
|
||||||
|===
|
|
||||||
Code,Description
|
|
||||||
405,Invalid input
|
|
||||||
|===
|
|
||||||
|
|
||||||
=== Consumes
|
|
||||||
* application/x-www-form-urlencoded
|
|
||||||
|
|
||||||
=== Produces
|
|
||||||
* application/json
|
|
||||||
* application/xml
|
|
||||||
|
|
||||||
== Place an order for a pet
|
|
||||||
----
|
|
||||||
POST /stores/order
|
|
||||||
----
|
|
||||||
|
|
||||||
=== Parameters
|
|
||||||
[format="csv", options="header"]
|
|
||||||
|===
|
|
||||||
Name,Located in,Description,Required
|
|
||||||
body,body,order placed for purchasing the pet,false
|
|
||||||
|===
|
|
||||||
|
|
||||||
=== Responses
|
|
||||||
[format="csv", options="header"]
|
|
||||||
|===
|
|
||||||
Code,Description
|
|
||||||
200,successful operation
|
|
||||||
400,Invalid Order
|
|
||||||
|===
|
|
||||||
|
|
||||||
=== Produces
|
|
||||||
* application/json
|
|
||||||
* application/xml
|
|
||||||
|
|
||||||
== Find purchase order by ID
|
|
||||||
----
|
|
||||||
GET /stores/order/{orderId}
|
|
||||||
----
|
|
||||||
|
|
||||||
=== Description
|
|
||||||
:hardbreaks:
|
|
||||||
For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions
|
|
||||||
|
|
||||||
=== Parameters
|
|
||||||
[format="csv", options="header"]
|
|
||||||
|===
|
|
||||||
Name,Located in,Description,Required
|
|
||||||
orderId,path,ID of pet that needs to be fetched,true
|
|
||||||
|===
|
|
||||||
|
|
||||||
=== Responses
|
|
||||||
[format="csv", options="header"]
|
|
||||||
|===
|
|
||||||
Code,Description
|
|
||||||
200,successful operation
|
|
||||||
400,Invalid ID supplied
|
|
||||||
404,Order not found
|
|
||||||
|===
|
|
||||||
|
|
||||||
=== Produces
|
|
||||||
* application/json
|
|
||||||
* application/xml
|
|
||||||
|
|
||||||
== Delete purchase order by ID
|
|
||||||
----
|
|
||||||
DELETE /stores/order/{orderId}
|
|
||||||
----
|
|
||||||
|
|
||||||
=== Description
|
|
||||||
:hardbreaks:
|
|
||||||
For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors
|
|
||||||
|
|
||||||
=== Parameters
|
|
||||||
[format="csv", options="header"]
|
|
||||||
|===
|
|
||||||
Name,Located in,Description,Required
|
|
||||||
orderId,path,ID of the order that needs to be deleted,true
|
|
||||||
|===
|
|
||||||
|
|
||||||
=== Responses
|
|
||||||
[format="csv", options="header"]
|
|
||||||
|===
|
|
||||||
Code,Description
|
|
||||||
400,Invalid ID supplied
|
|
||||||
404,Order not found
|
|
||||||
|===
|
|
||||||
|
|
||||||
=== Produces
|
|
||||||
* application/json
|
|
||||||
* application/xml
|
|
||||||
|
|
||||||
== Create user
|
|
||||||
----
|
|
||||||
POST /users
|
|
||||||
----
|
|
||||||
|
|
||||||
=== Description
|
|
||||||
:hardbreaks:
|
|
||||||
This can only be done by the logged in user.
|
|
||||||
|
|
||||||
=== Parameters
|
|
||||||
[format="csv", options="header"]
|
|
||||||
|===
|
|
||||||
Name,Located in,Description,Required
|
|
||||||
body,body,Created user object,false
|
|
||||||
|===
|
|
||||||
|
|
||||||
=== Responses
|
|
||||||
[format="csv", options="header"]
|
|
||||||
|===
|
|
||||||
Code,Description
|
|
||||||
default,successful operation
|
|
||||||
|===
|
|
||||||
|
|
||||||
=== Produces
|
|
||||||
* application/json
|
|
||||||
* application/xml
|
|
||||||
|
|
||||||
== Creates list of users with given input array
|
|
||||||
----
|
|
||||||
POST /users/createWithArray
|
|
||||||
----
|
|
||||||
|
|
||||||
=== Parameters
|
|
||||||
[format="csv", options="header"]
|
|
||||||
|===
|
|
||||||
Name,Located in,Description,Required
|
|
||||||
body,body,List of user object,false
|
|
||||||
|===
|
|
||||||
|
|
||||||
=== Responses
|
|
||||||
[format="csv", options="header"]
|
|
||||||
|===
|
|
||||||
Code,Description
|
|
||||||
default,successful operation
|
|
||||||
|===
|
|
||||||
|
|
||||||
=== Produces
|
|
||||||
* application/json
|
|
||||||
* application/xml
|
|
||||||
|
|
||||||
== Creates list of users with given input array
|
|
||||||
----
|
|
||||||
POST /users/createWithList
|
|
||||||
----
|
|
||||||
|
|
||||||
=== Parameters
|
|
||||||
[format="csv", options="header"]
|
|
||||||
|===
|
|
||||||
Name,Located in,Description,Required
|
|
||||||
body,body,List of user object,false
|
|
||||||
|===
|
|
||||||
|
|
||||||
=== Responses
|
|
||||||
[format="csv", options="header"]
|
|
||||||
|===
|
|
||||||
Code,Description
|
|
||||||
default,successful operation
|
|
||||||
|===
|
|
||||||
|
|
||||||
=== Produces
|
|
||||||
* application/json
|
|
||||||
* application/xml
|
|
||||||
|
|
||||||
== Logs user into the system
|
|
||||||
----
|
|
||||||
GET /users/login
|
|
||||||
----
|
|
||||||
|
|
||||||
=== Parameters
|
|
||||||
[format="csv", options="header"]
|
|
||||||
|===
|
|
||||||
Name,Located in,Description,Required
|
|
||||||
username,query,The user name for login,false
|
|
||||||
password,query,The password for login in clear text,false
|
|
||||||
|===
|
|
||||||
|
|
||||||
=== Responses
|
|
||||||
[format="csv", options="header"]
|
|
||||||
|===
|
|
||||||
Code,Description
|
|
||||||
200,successful operation
|
|
||||||
400,Invalid username/password supplied
|
|
||||||
|===
|
|
||||||
|
|
||||||
=== Produces
|
|
||||||
* application/json
|
|
||||||
* application/xml
|
|
||||||
|
|
||||||
== Logs out current logged in user session
|
|
||||||
----
|
|
||||||
GET /users/logout
|
|
||||||
----
|
|
||||||
|
|
||||||
=== Responses
|
|
||||||
[format="csv", options="header"]
|
|
||||||
|===
|
|
||||||
Code,Description
|
|
||||||
default,successful operation
|
|
||||||
|===
|
|
||||||
|
|
||||||
=== Produces
|
|
||||||
* application/json
|
|
||||||
* application/xml
|
|
||||||
|
|
||||||
== Get user by user name
|
|
||||||
----
|
|
||||||
GET /users/{username}
|
|
||||||
----
|
|
||||||
|
|
||||||
=== Parameters
|
|
||||||
[format="csv", options="header"]
|
|
||||||
|===
|
|
||||||
Name,Located in,Description,Required
|
|
||||||
username,path,The name that needs to be fetched. Use user1 for testing.,true
|
|
||||||
|===
|
|
||||||
|
|
||||||
=== Responses
|
|
||||||
[format="csv", options="header"]
|
|
||||||
|===
|
|
||||||
Code,Description
|
|
||||||
200,successful operation
|
|
||||||
400,Invalid username supplied
|
|
||||||
404,User not found
|
|
||||||
|===
|
|
||||||
|
|
||||||
=== Produces
|
|
||||||
* application/json
|
|
||||||
* application/xml
|
|
||||||
|
|
||||||
== Updated user
|
|
||||||
----
|
|
||||||
PUT /users/{username}
|
|
||||||
----
|
|
||||||
|
|
||||||
=== Description
|
|
||||||
:hardbreaks:
|
|
||||||
This can only be done by the logged in user.
|
|
||||||
|
|
||||||
=== Parameters
|
|
||||||
[format="csv", options="header"]
|
|
||||||
|===
|
|
||||||
Name,Located in,Description,Required
|
|
||||||
username,path,name that need to be deleted,true
|
|
||||||
body,body,Updated user object,false
|
|
||||||
|===
|
|
||||||
|
|
||||||
=== Responses
|
|
||||||
[format="csv", options="header"]
|
|
||||||
|===
|
|
||||||
Code,Description
|
|
||||||
400,Invalid user supplied
|
|
||||||
404,User not found
|
|
||||||
|===
|
|
||||||
|
|
||||||
=== Produces
|
|
||||||
* application/json
|
|
||||||
* application/xml
|
|
||||||
|
|
||||||
== Delete user
|
|
||||||
----
|
|
||||||
DELETE /users/{username}
|
|
||||||
----
|
|
||||||
|
|
||||||
=== Description
|
|
||||||
:hardbreaks:
|
|
||||||
This can only be done by the logged in user.
|
|
||||||
|
|
||||||
=== Parameters
|
|
||||||
[format="csv", options="header"]
|
|
||||||
|===
|
|
||||||
Name,Located in,Description,Required
|
|
||||||
username,path,The name that needs to be deleted,true
|
|
||||||
|===
|
|
||||||
|
|
||||||
=== Responses
|
|
||||||
[format="csv", options="header"]
|
|
||||||
|===
|
|
||||||
Code,Description
|
|
||||||
400,Invalid username supplied
|
|
||||||
404,User not found
|
|
||||||
|===
|
|
||||||
|
|
||||||
=== Produces
|
|
||||||
* application/json
|
|
||||||
* application/xml
|
|
||||||
|
|
||||||
== Definitions
|
|
||||||
=== User
|
|
||||||
[format="csv", options="header"]
|
|
||||||
|===
|
|
||||||
Name,Type,Required
|
|
||||||
id,integer,false
|
|
||||||
username,string,false
|
|
||||||
firstName,string,false
|
|
||||||
lastName,string,false
|
|
||||||
email,string,false
|
|
||||||
password,string,false
|
|
||||||
phone,string,false
|
|
||||||
userStatus,integer,false
|
|
||||||
|===
|
|
||||||
|
|
||||||
=== Category
|
|
||||||
[format="csv", options="header"]
|
|
||||||
|===
|
|
||||||
Name,Type,Required
|
|
||||||
id,integer,false
|
|
||||||
name,string,false
|
|
||||||
|===
|
|
||||||
|
|
||||||
=== Pet
|
|
||||||
[format="csv", options="header"]
|
|
||||||
|===
|
|
||||||
Name,Type,Required
|
|
||||||
id,integer,false
|
|
||||||
category,ref,false
|
|
||||||
name,string,true
|
|
||||||
photoUrls,array,true
|
|
||||||
tags,array,false
|
|
||||||
status,string,false
|
|
||||||
|===
|
|
||||||
|
|
||||||
=== Tag
|
|
||||||
[format="csv", options="header"]
|
|
||||||
|===
|
|
||||||
Name,Type,Required
|
|
||||||
id,integer,false
|
|
||||||
name,string,false
|
|
||||||
|===
|
|
||||||
|
|
||||||
=== Order
|
|
||||||
[format="csv", options="header"]
|
|
||||||
|===
|
|
||||||
Name,Type,Required
|
|
||||||
id,integer,false
|
|
||||||
petId,integer,false
|
|
||||||
quantity,integer,false
|
|
||||||
shipDate,string,false
|
|
||||||
status,string,false
|
|
||||||
complete,boolean,false
|
|
||||||
|===
|
|
||||||
|
|
||||||
@@ -1,494 +0,0 @@
|
|||||||
# Swagger Petstore
|
|
||||||
This is a sample server Petstore server.
|
|
||||||
|
|
||||||
[Learn about Swagger](http://swagger.wordnik.com) or join the IRC channel `#swagger` on irc.freenode.net.
|
|
||||||
|
|
||||||
For this sample, you can use the api key `special-key` to test the authorization filters
|
|
||||||
|
|
||||||
Version: 1.0.0
|
|
||||||
|
|
||||||
## Update an existing pet
|
|
||||||
```
|
|
||||||
PUT /pets
|
|
||||||
```
|
|
||||||
|
|
||||||
### Parameters
|
|
||||||
|Name|Located in|Description|Required|
|
|
||||||
|----|----|----|----|
|
|
||||||
|body|body|Pet object that needs to be added to the store|false|
|
|
||||||
|
|
||||||
|
|
||||||
### Responses
|
|
||||||
|Code|Description|
|
|
||||||
|----|----|
|
|
||||||
|400|Invalid ID supplied|
|
|
||||||
|404|Pet not found|
|
|
||||||
|405|Validation exception|
|
|
||||||
|
|
||||||
|
|
||||||
### Consumes
|
|
||||||
* application/json
|
|
||||||
* application/xml
|
|
||||||
|
|
||||||
### Produces
|
|
||||||
* application/json
|
|
||||||
* application/xml
|
|
||||||
|
|
||||||
## Add a new pet to the store
|
|
||||||
```
|
|
||||||
POST /pets
|
|
||||||
```
|
|
||||||
|
|
||||||
### Parameters
|
|
||||||
|Name|Located in|Description|Required|
|
|
||||||
|----|----|----|----|
|
|
||||||
|body|body|Pet object that needs to be added to the store|false|
|
|
||||||
|
|
||||||
|
|
||||||
### Responses
|
|
||||||
|Code|Description|
|
|
||||||
|----|----|
|
|
||||||
|405|Invalid input|
|
|
||||||
|
|
||||||
|
|
||||||
### Consumes
|
|
||||||
* application/json
|
|
||||||
* application/xml
|
|
||||||
|
|
||||||
### Produces
|
|
||||||
* application/json
|
|
||||||
* application/xml
|
|
||||||
|
|
||||||
## Finds Pets by status
|
|
||||||
```
|
|
||||||
GET /pets/findByStatus
|
|
||||||
```
|
|
||||||
|
|
||||||
### Description
|
|
||||||
|
|
||||||
Multiple status values can be provided with comma seperated strings
|
|
||||||
|
|
||||||
### Parameters
|
|
||||||
|Name|Located in|Description|Required|
|
|
||||||
|----|----|----|----|
|
|
||||||
|status|query|Status values that need to be considered for filter|false|
|
|
||||||
|
|
||||||
|
|
||||||
### Responses
|
|
||||||
|Code|Description|
|
|
||||||
|----|----|
|
|
||||||
|200|successful operation|
|
|
||||||
|400|Invalid status value|
|
|
||||||
|
|
||||||
|
|
||||||
### Produces
|
|
||||||
* application/json
|
|
||||||
* application/xml
|
|
||||||
|
|
||||||
## Finds Pets by tags
|
|
||||||
```
|
|
||||||
GET /pets/findByTags
|
|
||||||
```
|
|
||||||
|
|
||||||
### Description
|
|
||||||
|
|
||||||
Muliple tags can be provided with comma seperated strings. Use tag1, tag2, tag3 for testing.
|
|
||||||
|
|
||||||
### Parameters
|
|
||||||
|Name|Located in|Description|Required|
|
|
||||||
|----|----|----|----|
|
|
||||||
|tags|query|Tags to filter by|false|
|
|
||||||
|
|
||||||
|
|
||||||
### Responses
|
|
||||||
|Code|Description|
|
|
||||||
|----|----|
|
|
||||||
|200|successful operation|
|
|
||||||
|400|Invalid tag value|
|
|
||||||
|
|
||||||
|
|
||||||
### Produces
|
|
||||||
* application/json
|
|
||||||
* application/xml
|
|
||||||
|
|
||||||
## Find pet by ID
|
|
||||||
```
|
|
||||||
GET /pets/{petId}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Description
|
|
||||||
|
|
||||||
Returns a pet when ID < 10. ID > 10 or nonintegers will simulate API error conditions
|
|
||||||
|
|
||||||
### Parameters
|
|
||||||
|Name|Located in|Description|Required|
|
|
||||||
|----|----|----|----|
|
|
||||||
|petId|path|ID of pet that needs to be fetched|true|
|
|
||||||
|
|
||||||
|
|
||||||
### Responses
|
|
||||||
|Code|Description|
|
|
||||||
|----|----|
|
|
||||||
|200|successful operation|
|
|
||||||
|400|Invalid ID supplied|
|
|
||||||
|404|Pet not found|
|
|
||||||
|
|
||||||
|
|
||||||
### Produces
|
|
||||||
* application/json
|
|
||||||
* application/xml
|
|
||||||
|
|
||||||
## Deletes a pet
|
|
||||||
```
|
|
||||||
DELETE /pets/{petId}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Parameters
|
|
||||||
|Name|Located in|Description|Required|
|
|
||||||
|----|----|----|----|
|
|
||||||
|api_key|header||true|
|
|
||||||
|petId|path|Pet id to delete|true|
|
|
||||||
|
|
||||||
|
|
||||||
### Responses
|
|
||||||
|Code|Description|
|
|
||||||
|----|----|
|
|
||||||
|400|Invalid pet value|
|
|
||||||
|
|
||||||
|
|
||||||
### Produces
|
|
||||||
* application/json
|
|
||||||
* application/xml
|
|
||||||
|
|
||||||
## Updates a pet in the store with form data
|
|
||||||
```
|
|
||||||
POST /pets/{petId}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Parameters
|
|
||||||
|Name|Located in|Description|Required|
|
|
||||||
|----|----|----|----|
|
|
||||||
|petId|path|ID of pet that needs to be updated|true|
|
|
||||||
|name|formData|Updated name of the pet|true|
|
|
||||||
|status|formData|Updated status of the pet|true|
|
|
||||||
|
|
||||||
|
|
||||||
### Responses
|
|
||||||
|Code|Description|
|
|
||||||
|----|----|
|
|
||||||
|405|Invalid input|
|
|
||||||
|
|
||||||
|
|
||||||
### Consumes
|
|
||||||
* application/x-www-form-urlencoded
|
|
||||||
|
|
||||||
### Produces
|
|
||||||
* application/json
|
|
||||||
* application/xml
|
|
||||||
|
|
||||||
## Place an order for a pet
|
|
||||||
```
|
|
||||||
POST /stores/order
|
|
||||||
```
|
|
||||||
|
|
||||||
### Parameters
|
|
||||||
|Name|Located in|Description|Required|
|
|
||||||
|----|----|----|----|
|
|
||||||
|body|body|order placed for purchasing the pet|false|
|
|
||||||
|
|
||||||
|
|
||||||
### Responses
|
|
||||||
|Code|Description|
|
|
||||||
|----|----|
|
|
||||||
|200|successful operation|
|
|
||||||
|400|Invalid Order|
|
|
||||||
|
|
||||||
|
|
||||||
### Produces
|
|
||||||
* application/json
|
|
||||||
* application/xml
|
|
||||||
|
|
||||||
## Find purchase order by ID
|
|
||||||
```
|
|
||||||
GET /stores/order/{orderId}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Description
|
|
||||||
|
|
||||||
For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions
|
|
||||||
|
|
||||||
### Parameters
|
|
||||||
|Name|Located in|Description|Required|
|
|
||||||
|----|----|----|----|
|
|
||||||
|orderId|path|ID of pet that needs to be fetched|true|
|
|
||||||
|
|
||||||
|
|
||||||
### Responses
|
|
||||||
|Code|Description|
|
|
||||||
|----|----|
|
|
||||||
|200|successful operation|
|
|
||||||
|400|Invalid ID supplied|
|
|
||||||
|404|Order not found|
|
|
||||||
|
|
||||||
|
|
||||||
### Produces
|
|
||||||
* application/json
|
|
||||||
* application/xml
|
|
||||||
|
|
||||||
## Delete purchase order by ID
|
|
||||||
```
|
|
||||||
DELETE /stores/order/{orderId}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Description
|
|
||||||
|
|
||||||
For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors
|
|
||||||
|
|
||||||
### Parameters
|
|
||||||
|Name|Located in|Description|Required|
|
|
||||||
|----|----|----|----|
|
|
||||||
|orderId|path|ID of the order that needs to be deleted|true|
|
|
||||||
|
|
||||||
|
|
||||||
### Responses
|
|
||||||
|Code|Description|
|
|
||||||
|----|----|
|
|
||||||
|400|Invalid ID supplied|
|
|
||||||
|404|Order not found|
|
|
||||||
|
|
||||||
|
|
||||||
### Produces
|
|
||||||
* application/json
|
|
||||||
* application/xml
|
|
||||||
|
|
||||||
## Create user
|
|
||||||
```
|
|
||||||
POST /users
|
|
||||||
```
|
|
||||||
|
|
||||||
### Description
|
|
||||||
|
|
||||||
This can only be done by the logged in user.
|
|
||||||
|
|
||||||
### Parameters
|
|
||||||
|Name|Located in|Description|Required|
|
|
||||||
|----|----|----|----|
|
|
||||||
|body|body|Created user object|false|
|
|
||||||
|
|
||||||
|
|
||||||
### Responses
|
|
||||||
|Code|Description|
|
|
||||||
|----|----|
|
|
||||||
|default|successful operation|
|
|
||||||
|
|
||||||
|
|
||||||
### Produces
|
|
||||||
* application/json
|
|
||||||
* application/xml
|
|
||||||
|
|
||||||
## Creates list of users with given input array
|
|
||||||
```
|
|
||||||
POST /users/createWithArray
|
|
||||||
```
|
|
||||||
|
|
||||||
### Parameters
|
|
||||||
|Name|Located in|Description|Required|
|
|
||||||
|----|----|----|----|
|
|
||||||
|body|body|List of user object|false|
|
|
||||||
|
|
||||||
|
|
||||||
### Responses
|
|
||||||
|Code|Description|
|
|
||||||
|----|----|
|
|
||||||
|default|successful operation|
|
|
||||||
|
|
||||||
|
|
||||||
### Produces
|
|
||||||
* application/json
|
|
||||||
* application/xml
|
|
||||||
|
|
||||||
## Creates list of users with given input array
|
|
||||||
```
|
|
||||||
POST /users/createWithList
|
|
||||||
```
|
|
||||||
|
|
||||||
### Parameters
|
|
||||||
|Name|Located in|Description|Required|
|
|
||||||
|----|----|----|----|
|
|
||||||
|body|body|List of user object|false|
|
|
||||||
|
|
||||||
|
|
||||||
### Responses
|
|
||||||
|Code|Description|
|
|
||||||
|----|----|
|
|
||||||
|default|successful operation|
|
|
||||||
|
|
||||||
|
|
||||||
### Produces
|
|
||||||
* application/json
|
|
||||||
* application/xml
|
|
||||||
|
|
||||||
## Logs user into the system
|
|
||||||
```
|
|
||||||
GET /users/login
|
|
||||||
```
|
|
||||||
|
|
||||||
### Parameters
|
|
||||||
|Name|Located in|Description|Required|
|
|
||||||
|----|----|----|----|
|
|
||||||
|username|query|The user name for login|false|
|
|
||||||
|password|query|The password for login in clear text|false|
|
|
||||||
|
|
||||||
|
|
||||||
### Responses
|
|
||||||
|Code|Description|
|
|
||||||
|----|----|
|
|
||||||
|200|successful operation|
|
|
||||||
|400|Invalid username/password supplied|
|
|
||||||
|
|
||||||
|
|
||||||
### Produces
|
|
||||||
* application/json
|
|
||||||
* application/xml
|
|
||||||
|
|
||||||
## Logs out current logged in user session
|
|
||||||
```
|
|
||||||
GET /users/logout
|
|
||||||
```
|
|
||||||
|
|
||||||
### Responses
|
|
||||||
|Code|Description|
|
|
||||||
|----|----|
|
|
||||||
|default|successful operation|
|
|
||||||
|
|
||||||
|
|
||||||
### Produces
|
|
||||||
* application/json
|
|
||||||
* application/xml
|
|
||||||
|
|
||||||
## Get user by user name
|
|
||||||
```
|
|
||||||
GET /users/{username}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Parameters
|
|
||||||
|Name|Located in|Description|Required|
|
|
||||||
|----|----|----|----|
|
|
||||||
|username|path|The name that needs to be fetched. Use user1 for testing.|true|
|
|
||||||
|
|
||||||
|
|
||||||
### Responses
|
|
||||||
|Code|Description|
|
|
||||||
|----|----|
|
|
||||||
|200|successful operation|
|
|
||||||
|400|Invalid username supplied|
|
|
||||||
|404|User not found|
|
|
||||||
|
|
||||||
|
|
||||||
### Produces
|
|
||||||
* application/json
|
|
||||||
* application/xml
|
|
||||||
|
|
||||||
## Updated user
|
|
||||||
```
|
|
||||||
PUT /users/{username}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Description
|
|
||||||
|
|
||||||
This can only be done by the logged in user.
|
|
||||||
|
|
||||||
### Parameters
|
|
||||||
|Name|Located in|Description|Required|
|
|
||||||
|----|----|----|----|
|
|
||||||
|username|path|name that need to be deleted|true|
|
|
||||||
|body|body|Updated user object|false|
|
|
||||||
|
|
||||||
|
|
||||||
### Responses
|
|
||||||
|Code|Description|
|
|
||||||
|----|----|
|
|
||||||
|400|Invalid user supplied|
|
|
||||||
|404|User not found|
|
|
||||||
|
|
||||||
|
|
||||||
### Produces
|
|
||||||
* application/json
|
|
||||||
* application/xml
|
|
||||||
|
|
||||||
## Delete user
|
|
||||||
```
|
|
||||||
DELETE /users/{username}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Description
|
|
||||||
|
|
||||||
This can only be done by the logged in user.
|
|
||||||
|
|
||||||
### Parameters
|
|
||||||
|Name|Located in|Description|Required|
|
|
||||||
|----|----|----|----|
|
|
||||||
|username|path|The name that needs to be deleted|true|
|
|
||||||
|
|
||||||
|
|
||||||
### Responses
|
|
||||||
|Code|Description|
|
|
||||||
|----|----|
|
|
||||||
|400|Invalid username supplied|
|
|
||||||
|404|User not found|
|
|
||||||
|
|
||||||
|
|
||||||
### Produces
|
|
||||||
* application/json
|
|
||||||
* application/xml
|
|
||||||
|
|
||||||
## Definitions
|
|
||||||
### User
|
|
||||||
|Name|Type|Required|
|
|
||||||
|----|----|----|
|
|
||||||
|id|integer|false|
|
|
||||||
|username|string|false|
|
|
||||||
|firstName|string|false|
|
|
||||||
|lastName|string|false|
|
|
||||||
|email|string|false|
|
|
||||||
|password|string|false|
|
|
||||||
|phone|string|false|
|
|
||||||
|userStatus|integer|false|
|
|
||||||
|
|
||||||
|
|
||||||
### Category
|
|
||||||
|Name|Type|Required|
|
|
||||||
|----|----|----|
|
|
||||||
|id|integer|false|
|
|
||||||
|name|string|false|
|
|
||||||
|
|
||||||
|
|
||||||
### Pet
|
|
||||||
|Name|Type|Required|
|
|
||||||
|----|----|----|
|
|
||||||
|id|integer|false|
|
|
||||||
|category|ref|false|
|
|
||||||
|name|string|true|
|
|
||||||
|photoUrls|array|true|
|
|
||||||
|tags|array|false|
|
|
||||||
|status|string|false|
|
|
||||||
|
|
||||||
|
|
||||||
### Tag
|
|
||||||
|Name|Type|Required|
|
|
||||||
|----|----|----|
|
|
||||||
|id|integer|false|
|
|
||||||
|name|string|false|
|
|
||||||
|
|
||||||
|
|
||||||
### Order
|
|
||||||
|Name|Type|Required|
|
|
||||||
|----|----|----|
|
|
||||||
|id|integer|false|
|
|
||||||
|petId|integer|false|
|
|
||||||
|quantity|integer|false|
|
|
||||||
|shipDate|string|false|
|
|
||||||
|status|string|false|
|
|
||||||
|complete|boolean|false|
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,130 @@
|
|||||||
|
package io.github.robwin.swagger2markup;
|
||||||
|
|
||||||
|
import com.wordnik.swagger.models.Swagger;
|
||||||
|
import io.github.robwin.swagger2markup.builder.document.DefinitionsDocument;
|
||||||
|
import io.github.robwin.swagger2markup.builder.document.PathsDocument;
|
||||||
|
import io.github.robwin.swagger2markup.builder.markup.MarkupLanguage;
|
||||||
|
import io.swagger.parser.SwaggerParser;
|
||||||
|
import org.apache.commons.lang.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 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
|
||||||
|
*/
|
||||||
|
Swagger2MarkupConverter(MarkupLanguage markupLanguage, Swagger swagger, String examplesFolderPath, String schemasFolderPath){
|
||||||
|
this.markupLanguage = markupLanguage;
|
||||||
|
this.swagger = swagger;
|
||||||
|
this.examplesFolderPath = examplesFolderPath;
|
||||||
|
this.schemasFolderPath = schemasFolderPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a Swagger2MarkupConverter.Builder using a given Swagger source.
|
||||||
|
*
|
||||||
|
* @param swaggerSource the Swagger source. Can be a HTTP url or a path to a local file.
|
||||||
|
* @return a Swagger2MarkupConverter
|
||||||
|
*/
|
||||||
|
public static Builder from(String swaggerSource){
|
||||||
|
Validate.notEmpty(swaggerSource, "swaggerSource must not be null!");
|
||||||
|
return new Builder(swaggerSource);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes a file for the Paths (API) and a file for the Definitions (Model)
|
||||||
|
|
||||||
|
* @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 PathsDocument(swagger, markupLanguage, examplesFolderPath).build().writeToFile(directory, PATHS_DOCUMENT, StandardCharsets.UTF_8);
|
||||||
|
new DefinitionsDocument(swagger, markupLanguage, schemasFolderPath).build().writeToFile(directory, DEFINITIONS_DOCUMENT, StandardCharsets.UTF_8);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static class Builder{
|
||||||
|
private final Swagger swagger;
|
||||||
|
private String examplesFolderPath;
|
||||||
|
private String schemasFolderPath;
|
||||||
|
private MarkupLanguage markupLanguage = MarkupLanguage.ASCIIDOC;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a Builder using a given Swagger source.
|
||||||
|
*
|
||||||
|
* @param swaggerSource the Swagger source. Can be a HTTP url or a path to a local file.
|
||||||
|
*/
|
||||||
|
Builder(String swaggerSource){
|
||||||
|
swagger = new SwaggerParser().read(swaggerSource);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Swagger2MarkupConverter build(){
|
||||||
|
return new Swagger2MarkupConverter(markupLanguage, swagger, examplesFolderPath, schemasFolderPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,144 @@
|
|||||||
|
package io.github.robwin.swagger2markup.builder.document;
|
||||||
|
|
||||||
|
import com.wordnik.swagger.models.Model;
|
||||||
|
import com.wordnik.swagger.models.Swagger;
|
||||||
|
import com.wordnik.swagger.models.properties.Property;
|
||||||
|
import io.github.robwin.swagger2markup.builder.markup.MarkupLanguage;
|
||||||
|
import org.apache.commons.collections.MapUtils;
|
||||||
|
import org.apache.commons.io.FileUtils;
|
||||||
|
import org.apache.commons.lang.StringUtils;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Project: swagger2markup
|
||||||
|
* Copyright: Deutsche Telekom AG
|
||||||
|
*
|
||||||
|
* @author Robert Winkler <robert.winkler@telekom.de>
|
||||||
|
* @since 2.0.0
|
||||||
|
*/
|
||||||
|
public class DefinitionsDocument extends MarkupDocument {
|
||||||
|
|
||||||
|
private static final String DEFINITIONS = "Definitions";
|
||||||
|
private static final List<String> IGNORED_DEFINITIONS = Arrays.asList("Void");
|
||||||
|
private static final String JSON_SCHEMA = "JSON Schema";
|
||||||
|
private static final String XML_SCHEMA = "XML Schema";
|
||||||
|
private static final String NAME_COLUMN = "Name";
|
||||||
|
private static final String TYPE_COLUMN = "Type";
|
||||||
|
public static final String JSON_SCHEMA_EXTENSION = ".json";
|
||||||
|
public static final String XML_SCHEMA_EXTENSION = ".xsd";
|
||||||
|
public static final String JSON = "json";
|
||||||
|
public static final String XML = "xml";
|
||||||
|
private boolean schemasEnabled;
|
||||||
|
private String schemasFolderPath;
|
||||||
|
|
||||||
|
public DefinitionsDocument(Swagger swagger, MarkupLanguage markupLanguage, String schemasFolderPath){
|
||||||
|
super(swagger, markupLanguage);
|
||||||
|
if(StringUtils.isNotBlank(schemasFolderPath)){
|
||||||
|
this.schemasEnabled = true;
|
||||||
|
this.schemasFolderPath = schemasFolderPath;
|
||||||
|
}
|
||||||
|
if(schemasEnabled){
|
||||||
|
if (logger.isDebugEnabled()) {
|
||||||
|
logger.debug("Include schemas is enabled.");
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
if (logger.isDebugEnabled()) {
|
||||||
|
logger.debug("Include schemas is disabled.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MarkupDocument build() throws IOException {
|
||||||
|
definitions(swagger.getDefinitions());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds the Swagger definitions.
|
||||||
|
*
|
||||||
|
* @param definitions the Swagger definitions
|
||||||
|
*/
|
||||||
|
private void definitions(Map<String, Model> definitions) throws IOException {
|
||||||
|
if(MapUtils.isNotEmpty(definitions)){
|
||||||
|
this.documentBuilder.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());
|
||||||
|
definitionSchema(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
|
||||||
|
*/
|
||||||
|
private void definition(String definitionName, Model model) {
|
||||||
|
this.documentBuilder.sectionTitleLevel2(definitionName);
|
||||||
|
Map<String, Property> properties = model.getProperties();
|
||||||
|
List<String> csvContent = new ArrayList<>();
|
||||||
|
csvContent.add(NAME_COLUMN + DELIMITER + TYPE_COLUMN + DELIMITER + REQUIRED_COLUMN);
|
||||||
|
for (Map.Entry<String, Property> propertyEntry : properties.entrySet()) {
|
||||||
|
Property property = propertyEntry.getValue();
|
||||||
|
csvContent.add(propertyEntry.getKey() + DELIMITER + property.getType() + DELIMITER + property.getRequired());
|
||||||
|
}
|
||||||
|
this.documentBuilder.tableWithHeaderRow(csvContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void definitionSchema(String definitionName) throws IOException {
|
||||||
|
if(schemasEnabled) {
|
||||||
|
if (StringUtils.isNotBlank(definitionName)) {
|
||||||
|
schema(JSON_SCHEMA, schemasFolderPath, definitionName + JSON_SCHEMA_EXTENSION, JSON);
|
||||||
|
schema(XML_SCHEMA, schemasFolderPath, definitionName + XML_SCHEMA_EXTENSION, XML);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void schema(String title, String schemasFolderPath, String schemaName, String language) throws IOException {
|
||||||
|
java.nio.file.Path path = Paths.get(schemasFolderPath, schemaName);
|
||||||
|
if (Files.isReadable(path)) {
|
||||||
|
this.documentBuilder.sectionTitleLevel3(title);
|
||||||
|
this.documentBuilder.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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
package io.github.robwin.swagger2markup.builder.document;
|
||||||
|
|
||||||
|
import com.wordnik.swagger.models.Swagger;
|
||||||
|
import io.github.robwin.swagger2markup.builder.markup.DocumentBuilder;
|
||||||
|
import io.github.robwin.swagger2markup.builder.markup.DocumentBuilders;
|
||||||
|
import io.github.robwin.swagger2markup.builder.markup.MarkupLanguage;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Project: swagger2markup
|
||||||
|
* Copyright: Deutsche Telekom AG
|
||||||
|
*
|
||||||
|
* @author Robert Winkler <robert.winkler@telekom.de>
|
||||||
|
* @since 2.0.0
|
||||||
|
*/
|
||||||
|
public abstract class MarkupDocument {
|
||||||
|
|
||||||
|
protected static final String DELIMITER = ",";
|
||||||
|
protected static final String REQUIRED_COLUMN = "Required";
|
||||||
|
protected Logger logger = LoggerFactory.getLogger(getClass());
|
||||||
|
protected Swagger swagger;
|
||||||
|
protected MarkupLanguage markupLanguage;
|
||||||
|
protected DocumentBuilder documentBuilder;
|
||||||
|
|
||||||
|
MarkupDocument(Swagger swagger, MarkupLanguage markupLanguage){
|
||||||
|
this.swagger = swagger;
|
||||||
|
this.markupLanguage = markupLanguage;
|
||||||
|
this.documentBuilder = DocumentBuilders.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 documentBuilder.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{
|
||||||
|
documentBuilder.writeToFile(directory, fileName, charset);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,233 @@
|
|||||||
|
package io.github.robwin.swagger2markup.builder.document;
|
||||||
|
|
||||||
|
import com.wordnik.swagger.models.*;
|
||||||
|
import com.wordnik.swagger.models.parameters.Parameter;
|
||||||
|
import io.github.robwin.swagger2markup.builder.markup.MarkupLanguage;
|
||||||
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
|
import org.apache.commons.collections.MapUtils;
|
||||||
|
import org.apache.commons.io.FileUtils;
|
||||||
|
import org.apache.commons.lang.StringUtils;
|
||||||
|
|
||||||
|
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.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Project: swagger2markup
|
||||||
|
* Copyright: Deutsche Telekom AG
|
||||||
|
*
|
||||||
|
* @author Robert Winkler <robert.winkler@telekom.de>
|
||||||
|
* @since 2.0.0
|
||||||
|
*/
|
||||||
|
public class PathsDocument extends MarkupDocument {
|
||||||
|
|
||||||
|
private static final String VERSION = "Version: ";
|
||||||
|
private static final String DESCRIPTION_COLUMN = "Description";
|
||||||
|
private static final String DESCRIPTION = DESCRIPTION_COLUMN;
|
||||||
|
private static final String PARAMETERS = "Parameters";
|
||||||
|
private static final String PRODUCES = "Produces";
|
||||||
|
private static final String CONSUMES = "Consumes";
|
||||||
|
private static final String RESPONSES = "Responses";
|
||||||
|
private static final String EXAMPLE_REQUEST = "Example request";
|
||||||
|
private static final String EXAMPLE_RESPONSE = "Example response";
|
||||||
|
private static final String NAME_COLUMN = "Name";
|
||||||
|
private static final String LOCATED_IN_COLUMN = "Located in";
|
||||||
|
private static final String CODE_COLUMN = "Code";
|
||||||
|
public static final String REQUEST_EXAMPLE_FILE_NAME = "request";
|
||||||
|
public static final String RESPONSE_EXAMPLE_FILE_NAME = "response";
|
||||||
|
|
||||||
|
private boolean examplesEnabled;
|
||||||
|
private String examplesFolderPath;
|
||||||
|
|
||||||
|
public PathsDocument(Swagger swagger, MarkupLanguage markupLanguage, String examplesFolderPath){
|
||||||
|
super(swagger, markupLanguage);
|
||||||
|
if(StringUtils.isNotBlank(examplesFolderPath)){
|
||||||
|
this.examplesEnabled = true;
|
||||||
|
this.examplesFolderPath = examplesFolderPath;
|
||||||
|
}
|
||||||
|
if(examplesEnabled){
|
||||||
|
if (logger.isDebugEnabled()) {
|
||||||
|
logger.debug("Include examples is enabled.");
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
if (logger.isDebugEnabled()) {
|
||||||
|
logger.debug("Include examples is disabled.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MarkupDocument build() throws IOException {
|
||||||
|
documentHeader(swagger.getInfo());
|
||||||
|
paths(swagger.getPaths());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds the document header
|
||||||
|
*
|
||||||
|
* @param info the Swagger Info
|
||||||
|
*/
|
||||||
|
private void documentHeader(Info info) {
|
||||||
|
this.documentBuilder
|
||||||
|
.documentTitle(info.getTitle())
|
||||||
|
.textLine(info.getDescription())
|
||||||
|
.textLine(VERSION + info.getVersion())
|
||||||
|
.newLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds all paths of the Swagger file
|
||||||
|
*
|
||||||
|
* @param paths a Map of Swagger Paths
|
||||||
|
*/
|
||||||
|
private void paths(Map<String, Path> paths) throws IOException {
|
||||||
|
if(MapUtils.isNotEmpty(paths)) {
|
||||||
|
//this.documentBuilder.sectionTitleLevel1(FEATURES);
|
||||||
|
for (Map.Entry<String, Path> entry : paths.entrySet()) {
|
||||||
|
Path path = entry.getValue();
|
||||||
|
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);
|
||||||
|
examplesSection(operation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void pathTitle(String httpMethod, String resourcePath, Operation operation) {
|
||||||
|
String summary = operation.getSummary();
|
||||||
|
String title;
|
||||||
|
if(StringUtils.isNotBlank(summary)) {
|
||||||
|
title = summary;
|
||||||
|
this.documentBuilder.sectionTitleLevel1(title);
|
||||||
|
this.documentBuilder.listing(httpMethod + " " + resourcePath);
|
||||||
|
}else{
|
||||||
|
title = httpMethod + " " + resourcePath;
|
||||||
|
this.documentBuilder.sectionTitleLevel1(title);
|
||||||
|
}
|
||||||
|
if (logger.isInfoEnabled()) {
|
||||||
|
logger.info("Path processed: {}", title);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void descriptionSection(Operation operation) {
|
||||||
|
String description = operation.getDescription();
|
||||||
|
if(StringUtils.isNotBlank(description)){
|
||||||
|
this.documentBuilder.sectionTitleLevel2(DESCRIPTION);
|
||||||
|
this.documentBuilder.paragraph(description);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void parametersSection(Operation operation) {
|
||||||
|
List<Parameter> parameters = operation.getParameters();
|
||||||
|
if(CollectionUtils.isNotEmpty(parameters)){
|
||||||
|
List<String> csvContent = new ArrayList<>();
|
||||||
|
csvContent.add(NAME_COLUMN + DELIMITER + LOCATED_IN_COLUMN + DELIMITER + DESCRIPTION_COLUMN + DELIMITER + REQUIRED_COLUMN);
|
||||||
|
for(Parameter parameter : parameters){
|
||||||
|
csvContent.add(parameter.getName() + DELIMITER + parameter.getIn() + DELIMITER + parameter.getDescription() + DELIMITER + parameter.getRequired());
|
||||||
|
}
|
||||||
|
this.documentBuilder.sectionTitleLevel2(PARAMETERS);
|
||||||
|
this.documentBuilder.tableWithHeaderRow(csvContent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void consumesSection(Operation operation) {
|
||||||
|
List<String> consumes = operation.getConsumes();
|
||||||
|
if(CollectionUtils.isNotEmpty(consumes)){
|
||||||
|
this.documentBuilder.sectionTitleLevel2(CONSUMES);
|
||||||
|
this.documentBuilder.unorderedList(consumes);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void producesSection(Operation operation) {
|
||||||
|
List<String> produces = operation.getProduces();
|
||||||
|
if(CollectionUtils.isNotEmpty(produces)){
|
||||||
|
this.documentBuilder.sectionTitleLevel2(PRODUCES);
|
||||||
|
this.documentBuilder.unorderedList(produces);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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();
|
||||||
|
example(EXAMPLE_REQUEST, exampleFolder, REQUEST_EXAMPLE_FILE_NAME);
|
||||||
|
example(EXAMPLE_RESPONSE, exampleFolder, RESPONSE_EXAMPLE_FILE_NAME);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds a concrete example
|
||||||
|
*
|
||||||
|
* @param title the title of the example
|
||||||
|
* @param exampleFolder the name of the folder where the example file resides
|
||||||
|
* @param exampleFileName the name of the example file
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
private void example(String title, 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)) {
|
||||||
|
this.documentBuilder.sectionTitleLevel2(title);
|
||||||
|
this.documentBuilder.paragraph(FileUtils.readFileToString(path.toFile(), StandardCharsets.UTF_8).trim());
|
||||||
|
if (logger.isInfoEnabled()) {
|
||||||
|
logger.info("Example file processed: {}", path);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
if (logger.isDebugEnabled()) {
|
||||||
|
logger.debug("Example file is not readable: {}", path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void responsesSection(Operation operation) {
|
||||||
|
Map<String, Response> responses = operation.getResponses();
|
||||||
|
if(MapUtils.isNotEmpty(responses)){
|
||||||
|
List<String> csvContent = new ArrayList<>();
|
||||||
|
csvContent.add(CODE_COLUMN + DELIMITER + DESCRIPTION_COLUMN);
|
||||||
|
for(Map.Entry<String, Response> entry : responses.entrySet()){
|
||||||
|
Response response = entry.getValue();
|
||||||
|
csvContent.add(entry.getKey() + DELIMITER + response.getDescription());
|
||||||
|
}
|
||||||
|
this.documentBuilder.sectionTitleLevel2(RESPONSES);
|
||||||
|
this.documentBuilder.tableWithHeaderRow(csvContent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,5 +1,13 @@
|
|||||||
package io.swagger2markup.builder;
|
package io.github.robwin.swagger2markup.builder.markup;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.io.BufferedWriter;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Paths;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -9,6 +17,7 @@ public abstract class AbstractDocumentBuilder implements DocumentBuilder {
|
|||||||
|
|
||||||
protected StringBuilder documentBuilder = new StringBuilder();
|
protected StringBuilder documentBuilder = new StringBuilder();
|
||||||
protected String newLine = System.getProperty("line.separator");
|
protected String newLine = System.getProperty("line.separator");
|
||||||
|
protected Logger logger = LoggerFactory.getLogger(getClass());
|
||||||
|
|
||||||
protected void documentTitle(Markup markup, String title){
|
protected void documentTitle(Markup markup, String title){
|
||||||
documentBuilder.append(markup).append(title).append(newLine);
|
documentBuilder.append(markup).append(title).append(newLine);
|
||||||
@@ -26,6 +35,7 @@ public abstract class AbstractDocumentBuilder implements DocumentBuilder {
|
|||||||
documentBuilder.append(markup).append(title).append(newLine);
|
documentBuilder.append(markup).append(title).append(newLine);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public DocumentBuilder textLine(String text){
|
public DocumentBuilder textLine(String text){
|
||||||
documentBuilder.append(text).append(newLine);
|
documentBuilder.append(text).append(newLine);
|
||||||
return this;
|
return this;
|
||||||
@@ -39,7 +49,7 @@ public abstract class AbstractDocumentBuilder implements DocumentBuilder {
|
|||||||
delimitedTextLine(markup, text);
|
delimitedTextLine(markup, text);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void delimitedTextLine(Markup markup, String text){
|
protected void delimitedTextLine(Markup markup, String text){
|
||||||
documentBuilder.append(markup).append(newLine).append(text).append(newLine).append(markup).append(newLine).append(newLine);
|
documentBuilder.append(markup).append(newLine).append(text).append(newLine).append(markup).append(newLine).append(newLine);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,6 +72,7 @@ public abstract class AbstractDocumentBuilder implements DocumentBuilder {
|
|||||||
documentBuilder.append(newLine);
|
documentBuilder.append(newLine);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public DocumentBuilder newLine(){
|
public DocumentBuilder newLine(){
|
||||||
documentBuilder.append(newLine);
|
documentBuilder.append(newLine);
|
||||||
return this;
|
return this;
|
||||||
@@ -71,4 +82,16 @@ public abstract class AbstractDocumentBuilder implements DocumentBuilder {
|
|||||||
public String toString(){
|
public String toString(){
|
||||||
return documentBuilder.toString();
|
return documentBuilder.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeToFile(String directory, String fileNameWithExtension, Charset charset) throws IOException {
|
||||||
|
Files.createDirectories(Paths.get(directory));
|
||||||
|
try (BufferedWriter writer = Files.newBufferedWriter(Paths.get(directory, fileNameWithExtension), charset)){
|
||||||
|
writer.write(documentBuilder.toString());
|
||||||
|
}
|
||||||
|
if (logger.isInfoEnabled()) {
|
||||||
|
logger.info("{} was written to: {}", fileNameWithExtension, directory);
|
||||||
|
}
|
||||||
|
documentBuilder = new StringBuilder();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
package io.swagger2markup.builder;
|
package io.github.robwin.swagger2markup.builder.markup;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -20,6 +22,8 @@ public interface DocumentBuilder {
|
|||||||
|
|
||||||
DocumentBuilder listing(String text);
|
DocumentBuilder listing(String text);
|
||||||
|
|
||||||
|
DocumentBuilder source(String text, String language);
|
||||||
|
|
||||||
DocumentBuilder boldTextLine(String text);
|
DocumentBuilder boldTextLine(String text);
|
||||||
|
|
||||||
DocumentBuilder italicTextLine(String text);
|
DocumentBuilder italicTextLine(String text);
|
||||||
@@ -30,5 +34,18 @@ public interface DocumentBuilder {
|
|||||||
|
|
||||||
DocumentBuilder newLine();
|
DocumentBuilder newLine();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a string representation of the document.
|
||||||
|
*/
|
||||||
String toString();
|
String 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
|
||||||
|
*/
|
||||||
|
void writeToFile(String directory, String fileName, Charset charset) throws IOException;
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package io.github.robwin.swagger2markup.builder.markup;
|
||||||
|
|
||||||
|
import io.github.robwin.swagger2markup.builder.markup.asciidoc.AsciiDocBuilder;
|
||||||
|
import io.github.robwin.swagger2markup.builder.markup.markdown.MarkdownBuilder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Project: swagger2markup
|
||||||
|
* Copyright: Deutsche Telekom AG
|
||||||
|
*
|
||||||
|
* @author Robert Winkler <robert.winkler@telekom.de>
|
||||||
|
* @since 2.0.0
|
||||||
|
*/
|
||||||
|
public final class DocumentBuilders {
|
||||||
|
|
||||||
|
private DocumentBuilders(){};
|
||||||
|
|
||||||
|
public static DocumentBuilder documentBuilder(MarkupLanguage markupLanguage){
|
||||||
|
switch(markupLanguage){
|
||||||
|
case MARKDOWN: return new MarkdownBuilder();
|
||||||
|
case ASCIIDOC: return new AsciiDocBuilder();
|
||||||
|
default: return new AsciiDocBuilder();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package io.swagger2markup.builder;
|
package io.github.robwin.swagger2markup.builder.markup;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Project: swagger2asciidoc
|
* Project: swagger2asciidoc
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package io.github.robwin.swagger2markup.builder.markup;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Robert Winkler
|
||||||
|
*/
|
||||||
|
public enum MarkupLanguage {
|
||||||
|
ASCIIDOC(".adoc,.asciidoc"),
|
||||||
|
MARKDOWN(".md,.markdown");
|
||||||
|
|
||||||
|
private final String fileNameExtensions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param fileNameExtensions file name suffix
|
||||||
|
*/
|
||||||
|
private MarkupLanguage(final String fileNameExtensions) {
|
||||||
|
this.fileNameExtensions = fileNameExtensions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getFileNameExtensions() {
|
||||||
|
return Arrays.asList(fileNameExtensions.split(","));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
package io.swagger2markup.builder.asciidoc;
|
package io.github.robwin.swagger2markup.builder.markup.asciidoc;
|
||||||
|
|
||||||
import io.swagger2markup.builder.Markup;
|
import io.github.robwin.swagger2markup.builder.markup.Markup;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Robert Winkler
|
* @author Robert Winkler
|
||||||
@@ -1,8 +1,10 @@
|
|||||||
package io.swagger2markup.builder.asciidoc;
|
package io.github.robwin.swagger2markup.builder.markup.asciidoc;
|
||||||
|
|
||||||
import io.swagger2markup.builder.AbstractDocumentBuilder;
|
import io.github.robwin.swagger2markup.builder.markup.AbstractDocumentBuilder;
|
||||||
import io.swagger2markup.builder.DocumentBuilder;
|
import io.github.robwin.swagger2markup.builder.markup.DocumentBuilder;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -64,6 +66,13 @@ public class AsciiDocBuilder extends AbstractDocumentBuilder{
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DocumentBuilder source(String text, String language){
|
||||||
|
documentBuilder.append(String.format("[source,%s]", language)).append(newLine);
|
||||||
|
listing(AsciiDoc.LISTING, text);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DocumentBuilder tableWithHeaderRow(List<String> rowsInCSV){
|
public DocumentBuilder tableWithHeaderRow(List<String> rowsInCSV){
|
||||||
documentBuilder.append("[format=\"csv\", options=\"header\"]").append(newLine);
|
documentBuilder.append("[format=\"csv\", options=\"header\"]").append(newLine);
|
||||||
@@ -74,4 +83,11 @@ public class AsciiDocBuilder extends AbstractDocumentBuilder{
|
|||||||
documentBuilder.append(AsciiDoc.TABLE).append(newLine).append(newLine);
|
documentBuilder.append(AsciiDoc.TABLE).append(newLine).append(newLine);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeToFile(String directory, String fileName, Charset charset) throws IOException {
|
||||||
|
String fileNameWithExtension = fileName + ".adoc";
|
||||||
|
super.writeToFile(directory, fileNameWithExtension, charset);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
package io.swagger2markup.builder.markdown;
|
package io.github.robwin.swagger2markup.builder.markup.markdown;
|
||||||
|
|
||||||
import io.swagger2markup.builder.Markup;
|
import io.github.robwin.swagger2markup.builder.markup.Markup;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Project: swagger2asciidoc
|
* Project: swagger2asciidoc
|
||||||
@@ -1,8 +1,10 @@
|
|||||||
package io.swagger2markup.builder.markdown;
|
package io.github.robwin.swagger2markup.builder.markup.markdown;
|
||||||
|
|
||||||
import io.swagger2markup.builder.AbstractDocumentBuilder;
|
import io.github.robwin.swagger2markup.builder.markup.AbstractDocumentBuilder;
|
||||||
import io.swagger2markup.builder.DocumentBuilder;
|
import io.github.robwin.swagger2markup.builder.markup.DocumentBuilder;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -51,6 +53,14 @@ public class MarkdownBuilder extends AbstractDocumentBuilder
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DocumentBuilder source(String text, String language){
|
||||||
|
documentBuilder.append(Markdown.LISTING).append(language).append(newLine).
|
||||||
|
append(text).append(newLine).
|
||||||
|
append(Markdown.LISTING).append(newLine).append(newLine);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DocumentBuilder boldTextLine(String text){
|
public DocumentBuilder boldTextLine(String text){
|
||||||
boldTextLine(Markdown.BOLD, text);
|
boldTextLine(Markdown.BOLD, text);
|
||||||
@@ -101,4 +111,10 @@ public class MarkdownBuilder extends AbstractDocumentBuilder
|
|||||||
newLine().newLine();
|
newLine().newLine();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeToFile(String directory, String fileName, Charset charset) throws IOException {
|
||||||
|
String fileNameWithExtension = fileName + ".md";
|
||||||
|
super.writeToFile(directory, fileNameWithExtension, charset);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,203 +0,0 @@
|
|||||||
package io.swagger2markup;
|
|
||||||
|
|
||||||
import com.wordnik.swagger.models.*;
|
|
||||||
import com.wordnik.swagger.models.parameters.Parameter;
|
|
||||||
import com.wordnik.swagger.models.properties.Property;
|
|
||||||
import io.swagger.parser.SwaggerParser;
|
|
||||||
import io.swagger2markup.builder.DocumentBuilder;
|
|
||||||
import io.swagger2markup.builder.asciidoc.AsciiDocBuilder;
|
|
||||||
import io.swagger2markup.builder.markdown.MarkdownBuilder;
|
|
||||||
import org.apache.commons.collections.CollectionUtils;
|
|
||||||
import org.apache.commons.collections.MapUtils;
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.io.BufferedWriter;
|
|
||||||
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 Swagger2MarkupConverter {
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(Swagger2MarkupConverter.class);
|
|
||||||
private static final String VERSION = "Version: ";
|
|
||||||
private static final String SUMMARY = "Summary";
|
|
||||||
private static final String DESCRIPTION = "Description";
|
|
||||||
private static final String PARAMETERS = "Parameters";
|
|
||||||
private static final String PRODUCES = "Produces";
|
|
||||||
private static final String CONSUMES = "Consumes";
|
|
||||||
private static final String RESPONSES = "Responses";
|
|
||||||
private static final String DEFINITIONS = "Definitions";
|
|
||||||
private static final List<String> IGNORED_DEFINITIONS = Arrays.asList("Void");
|
|
||||||
private final Swagger swagger;
|
|
||||||
private DocumentBuilder documentBuilder;
|
|
||||||
|
|
||||||
private Swagger2MarkupConverter(String swaggerFileLocation){
|
|
||||||
swagger = new SwaggerParser().read(swaggerFileLocation);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Swagger2MarkupConverter from(String swaggerFileLocation){
|
|
||||||
return new Swagger2MarkupConverter(swaggerFileLocation);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void toAsciiDoc(String fileLocation) throws IOException {
|
|
||||||
documentBuilder = new AsciiDocBuilder();
|
|
||||||
buildDocument();
|
|
||||||
writeAsciiDocFile(fileLocation);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void toMarkdown(String fileLocation) throws IOException {
|
|
||||||
documentBuilder = new MarkdownBuilder();
|
|
||||||
buildDocument();
|
|
||||||
writeAsciiDocFile(fileLocation);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void buildDocument(){
|
|
||||||
documentHeader(swagger.getInfo());
|
|
||||||
paths(swagger.getPaths());
|
|
||||||
definitions(swagger.getDefinitions());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void writeAsciiDocFile(String asciiDocFileLocation) throws IOException {
|
|
||||||
try (BufferedWriter writer = Files.newBufferedWriter(Paths.get(asciiDocFileLocation),
|
|
||||||
StandardCharsets.UTF_8)){
|
|
||||||
writer.write(documentBuilder.toString());
|
|
||||||
} catch (IOException e) {
|
|
||||||
logger.warn("Failed to convert Swagger file to AsciiDoc", e);
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void paths(Map<String, Path> paths) {
|
|
||||||
for(Map.Entry<String, Path> entry : paths.entrySet()){
|
|
||||||
Path path = entry.getValue();
|
|
||||||
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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void documentHeader(Info info) {
|
|
||||||
documentBuilder
|
|
||||||
.documentTitle(info.getTitle())
|
|
||||||
.textLine(info.getDescription())
|
|
||||||
.textLine(VERSION + info.getVersion())
|
|
||||||
.newLine();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void path(String httpMethod, String resourcePath, Operation operation) {
|
|
||||||
if(operation != null){
|
|
||||||
pathTitle(httpMethod, resourcePath, operation);
|
|
||||||
descriptionSection(operation);
|
|
||||||
parametersSection(operation);
|
|
||||||
responsesSection(operation);
|
|
||||||
consumesSection(operation);
|
|
||||||
producesSection(operation);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void pathTitle(String httpMethod, String resourcePath, Operation operation) {
|
|
||||||
String summary = operation.getSummary();
|
|
||||||
if(StringUtils.isNotBlank(summary)) {
|
|
||||||
documentBuilder.sectionTitleLevel1(operation.getSummary());
|
|
||||||
documentBuilder.listing(httpMethod + " " + resourcePath);
|
|
||||||
}else{
|
|
||||||
documentBuilder.sectionTitleLevel1(httpMethod + " " + resourcePath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void descriptionSection(Operation operation) {
|
|
||||||
String description = operation.getDescription();
|
|
||||||
if(StringUtils.isNotBlank(description)){
|
|
||||||
documentBuilder.sectionTitleLevel2(DESCRIPTION);
|
|
||||||
documentBuilder.paragraph(description);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void consumesSection(Operation operation) {
|
|
||||||
List<String> consumes = operation.getConsumes();
|
|
||||||
if(CollectionUtils.isNotEmpty(consumes)){
|
|
||||||
documentBuilder.sectionTitleLevel2(CONSUMES);
|
|
||||||
documentBuilder.unorderedList(consumes);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void producesSection(Operation operation) {
|
|
||||||
List<String> produces = operation.getProduces();
|
|
||||||
if(CollectionUtils.isNotEmpty(produces)){
|
|
||||||
documentBuilder.sectionTitleLevel2(PRODUCES);
|
|
||||||
documentBuilder.unorderedList(produces);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void parametersSection(Operation operation) {
|
|
||||||
List<Parameter> parameters = operation.getParameters();
|
|
||||||
if(CollectionUtils.isNotEmpty(parameters)){
|
|
||||||
List<String> csvContent = new ArrayList<>();
|
|
||||||
csvContent.add("Name,Located in,Description,Required");
|
|
||||||
for(Parameter parameter : parameters){
|
|
||||||
StringBuilder rowBuilder = new StringBuilder();
|
|
||||||
rowBuilder.append(parameter.getName()).append(",").
|
|
||||||
append(parameter.getIn()).append(",").
|
|
||||||
append(parameter.getDescription()).append(",").
|
|
||||||
append(parameter.getRequired());
|
|
||||||
csvContent.add(rowBuilder.toString());
|
|
||||||
}
|
|
||||||
documentBuilder.sectionTitleLevel2(PARAMETERS);
|
|
||||||
documentBuilder.tableWithHeaderRow(csvContent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void responsesSection(Operation operation) {
|
|
||||||
Map<String, Response> responses = operation.getResponses();
|
|
||||||
if(MapUtils.isNotEmpty(responses)){
|
|
||||||
List<String> csvContent = new ArrayList<>();
|
|
||||||
csvContent.add("Code,Description");
|
|
||||||
for(Map.Entry<String, Response> entry : responses.entrySet()){
|
|
||||||
Response response = entry.getValue();
|
|
||||||
StringBuilder rowBuilder = new StringBuilder();
|
|
||||||
rowBuilder.append(entry.getKey()).append(",").
|
|
||||||
append(response.getDescription());
|
|
||||||
csvContent.add(rowBuilder.toString());
|
|
||||||
}
|
|
||||||
documentBuilder.sectionTitleLevel2(RESPONSES);
|
|
||||||
documentBuilder.tableWithHeaderRow(csvContent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void definitions(Map<String, Model> definitions) {
|
|
||||||
if(MapUtils.isNotEmpty(definitions)){
|
|
||||||
documentBuilder.sectionTitleLevel1(DEFINITIONS);
|
|
||||||
for(Map.Entry<String, Model> definitionsEntry : definitions.entrySet()){
|
|
||||||
String definitionName = definitionsEntry.getKey();
|
|
||||||
if(!IGNORED_DEFINITIONS.contains(definitionName)) {
|
|
||||||
documentBuilder.sectionTitleLevel2(definitionName);
|
|
||||||
Model model = definitionsEntry.getValue();
|
|
||||||
Map<String, Property> properties = model.getProperties();
|
|
||||||
List<String> csvContent = new ArrayList<>();
|
|
||||||
csvContent.add("Name,Type,Required");
|
|
||||||
for (Map.Entry<String, Property> propertyEntry : properties.entrySet()) {
|
|
||||||
Property property = propertyEntry.getValue();
|
|
||||||
StringBuilder rowBuilder = new StringBuilder();
|
|
||||||
rowBuilder.append(propertyEntry.getKey()).append(",").
|
|
||||||
append(property.getType()).append(",").append(property.getRequired());
|
|
||||||
csvContent.add(rowBuilder.toString());
|
|
||||||
}
|
|
||||||
documentBuilder.tableWithHeaderRow(csvContent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
12
src/main/resources/logback.xml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<configuration scan="true">
|
||||||
|
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
|
<encoder>
|
||||||
|
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
|
||||||
|
</encoder>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<root level="DEBUG">
|
||||||
|
<appender-ref ref="CONSOLE" />
|
||||||
|
</root>
|
||||||
|
</configuration>
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package io.github.robwin.swagger2markup;
|
||||||
|
|
||||||
|
import io.github.robwin.swagger2markup.builder.markup.MarkupLanguage;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Robert Winkler
|
||||||
|
*/
|
||||||
|
public class Swagger2MarkupConverterTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSwagger2AsciiDocConverter() throws IOException {
|
||||||
|
File file = new File(Swagger2MarkupConverterTest.class.getResource("/json/swagger.json").getFile());
|
||||||
|
|
||||||
|
Swagger2MarkupConverter.from(file.getAbsolutePath()).
|
||||||
|
withMarkupLanguage(MarkupLanguage.MARKDOWN).
|
||||||
|
withExamples("docs").withSchemas("docs/schemas").build()
|
||||||
|
.intoFolder("src/docs/markdown");
|
||||||
|
|
||||||
|
Swagger2MarkupConverter.from(file.getAbsolutePath()).
|
||||||
|
withExamples("docs").withSchemas("docs/schemas").build()
|
||||||
|
.intoFolder("src/docs/asciidoc");
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package io.github.robwin.swagger2markup.builder;
|
||||||
|
|
||||||
|
import io.github.robwin.swagger2markup.builder.markup.DocumentBuilder;
|
||||||
|
import io.github.robwin.swagger2markup.builder.markup.DocumentBuilders;
|
||||||
|
import io.github.robwin.swagger2markup.builder.markup.MarkupLanguage;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Project: swagger2markup
|
||||||
|
* Copyright: Deutsche Telekom AG
|
||||||
|
*
|
||||||
|
* @author Robert Winkler <robert.winkler@telekom.de>
|
||||||
|
* @since 2.0.0
|
||||||
|
*/
|
||||||
|
public class DocumentBuilderTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testToFile() throws IOException {
|
||||||
|
DocumentBuilder builder = DocumentBuilders.documentBuilder(MarkupLanguage.ASCIIDOC);
|
||||||
|
builder.documentTitle("Test title").textLine("Text line").writeToFile("/tmp", "test.adoc", StandardCharsets.UTF_8);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
package io.swagger2markup;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Robert Winkler
|
|
||||||
*/
|
|
||||||
public class Swagger2MarkupConverterTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSwagger2AsciiDocConverter() throws IOException {
|
|
||||||
File file = new File(Swagger2MarkupConverterTest.class.getResource("/json/swagger.json").getFile());
|
|
||||||
Swagger2MarkupConverter.from(file.getAbsolutePath()).toAsciiDoc("src/docs/asciidoc/swagger.adoc");
|
|
||||||
|
|
||||||
Swagger2MarkupConverter.from(file.getAbsolutePath()).toMarkdown("src/docs/markdown/swagger.md");
|
|
||||||
}
|
|
||||||
}
|
|
||||||