Compare commits
33 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eb418c07f5 | ||
|
|
9a265fbbc3 | ||
|
|
cf32d6cf29 | ||
|
|
9d216e3dc2 | ||
|
|
9d387b3e80 | ||
|
|
1e6be2f26d | ||
|
|
e56f824cd2 | ||
|
|
d38014f4b5 | ||
|
|
b331062fa6 | ||
|
|
88df748451 | ||
|
|
5384197bd1 | ||
|
|
2b5d4b7fe9 | ||
|
|
c15d074488 | ||
|
|
b0c3aa71b9 | ||
|
|
32d85ffb55 | ||
|
|
59fcd61738 | ||
|
|
7ce969882d | ||
|
|
ee70cdb94f | ||
|
|
f21fce7730 | ||
|
|
c426c7b341 | ||
|
|
1231d1e0c2 | ||
|
|
66073aebb8 | ||
|
|
882d9e5709 | ||
|
|
ba9ec45d9e | ||
|
|
f2787a41ae | ||
|
|
1dc9a07cb9 | ||
|
|
a34807e5c9 | ||
|
|
85ef33a720 | ||
|
|
3163c077a1 | ||
|
|
fbb446875d | ||
|
|
e8cdcabffe | ||
|
|
832813d40a | ||
|
|
e2f28bca7d |
40
README.adoc
40
README.adoc
@@ -2,7 +2,7 @@
|
||||
:author: Robert Winkler
|
||||
: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/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"]
|
||||
|
||||
|
||||
== Overview
|
||||
@@ -11,17 +11,47 @@ The primary goal of this project is to *simplify the generation of an up-to-date
|
||||
|
||||
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 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].
|
||||
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]. You can publish your AsciiDoc documentation using https://github.com/RobWin/asciidocular[Asciidocular]. Asciidocular is a small AngularJS web app that loads your AsciiDoc files via Ajax and renders them as a full web site.
|
||||
|
||||
Advantages:
|
||||
|
||||
* No server-side components needed to convert your AsciiDoc files into HTML
|
||||
* No build process and tools needed
|
||||
* Deployable via GitHub Pages
|
||||
* Responsive Bootswatch (Bootstrap) theme
|
||||
|
||||
You can publish your Markdown documentation using https://github.com/jbake-org/jbake[JBake], https://github.com/tomchristie/mkdocs[MkDocs] or https://github.com/rtfd/readthedocs.org[ReadTheDocs].
|
||||
|
||||
The project requires at least JDK 7.
|
||||
|
||||
== Reference documentation
|
||||
- http://swagger2markup.readme.io/[Reference Documentation]
|
||||
- https://github.com/Swagger2Markup/swagger2markup/blob/master/RELEASENOTES.adoc[Release notes]
|
||||
|
||||
The documentation can be found at http://swagger2markup.github.io/swagger2markup-docs/[Reference documentation]
|
||||
== Contributing
|
||||
|
||||
=== Community contributions
|
||||
|
||||
Pull requests are welcome.
|
||||
|
||||
* New feature https://github.com/Swagger2Markup/swagger2markup/issues/18[RobWin/Swagger2Markup#18] by https://github.com/sg-ad[@sg-ad]: In addition to the definitions.adoc you can also generate separate files for each definition model (ex: person.adoc, address.adoc, purchase.adoc).
|
||||
|
||||
* New feature https://github.com/Swagger2Markup/swagger2markup/issues/21[RobWin/Swagger2Markup#21] by https://github.com/redowl[@redowl]: Support for both reference models and composed models.
|
||||
|
||||
* New feature https://github.com/Swagger2Markup/swagger2markup/issues/27[RobWin/Swagger2Markup#27] by https://github.com/zmitrok[@zmitrok]: Added a hook to preprocess a Swagger Model before it is converted.
|
||||
|
||||
=== 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 you’d 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.
|
||||
|
||||
== License
|
||||
|
||||
@@ -31,4 +61,4 @@ Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
@@ -58,5 +58,17 @@
|
||||
== 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.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
|
||||
10
build.gradle
10
build.gradle
@@ -6,14 +6,14 @@ buildscript {
|
||||
dependencies {
|
||||
classpath 'org.asciidoctor:asciidoctor-gradle-plugin:1.5.2'
|
||||
classpath 'org.asciidoctor:asciidoctorj-pdf:1.5.0-alpha.8'
|
||||
classpath 'io.spring.gradle:dependency-management-plugin:0.5.1.RELEASE'
|
||||
classpath 'io.spring.gradle:dependency-management-plugin:0.5.3.RELEASE'
|
||||
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'
|
||||
}
|
||||
}
|
||||
description = 'swagger2markup Build'
|
||||
version = '0.7.1'
|
||||
version = '0.9.1'
|
||||
group = 'io.github.robwin'
|
||||
|
||||
apply plugin: 'java'
|
||||
@@ -53,14 +53,14 @@ dependencies {
|
||||
|
||||
dependencyManagement {
|
||||
dependencies {
|
||||
dependency "io.github.robwin:markup-document-builder:0.1.4"
|
||||
dependency "io.swagger:swagger-compat-spec-parser:1.0.8"
|
||||
dependency "io.github.robwin:markup-document-builder:0.1.5"
|
||||
dependency "io.swagger:swagger-compat-spec-parser:1.0.13"
|
||||
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"
|
||||
dependency "org.assertj:assertj-core:2.2.0"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -38,9 +38,9 @@ bintray {
|
||||
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'
|
||||
websiteUrl = 'https://github.com/Swagger2Markup/swagger2markup'
|
||||
issueTrackerUrl = 'https://github.com/Swagger2Markup/swagger2markup/issues'
|
||||
vcsUrl = 'https://github.com/Swagger2Markup/swagger2markup.git'
|
||||
desc = 'A Swagger to Markup (AsciiDoc and Markdown) converter.'
|
||||
licenses = ['Apache-2.0']
|
||||
version {
|
||||
@@ -76,15 +76,15 @@ publishing {
|
||||
|
||||
root.appendNode('name', 'swagger2markup')
|
||||
root.appendNode('packaging', 'jar')
|
||||
root.appendNode('url', 'https://github.com/RobWin/swagger2markup')
|
||||
root.appendNode('url', 'https://github.com/Swagger2Markup/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('url', 'https://github.com/Swagger2Markup/swagger2markup/blob/master/LICENSE.txt')
|
||||
license.appendNode('distribution', 'repo')
|
||||
|
||||
root.appendNode('scm').appendNode('url', 'https://github.com/RobWin/swagger2markup.git')
|
||||
root.appendNode('scm').appendNode('url', 'https://github.com/Swagger2Markup/swagger2markup.git')
|
||||
|
||||
def developers = root.appendNode('developers')
|
||||
devs.each {
|
||||
|
||||
24
src/main/java/io/github/robwin/swagger2markup/GroupBy.java
Normal file
24
src/main/java/io/github/robwin/swagger2markup/GroupBy.java
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
*
|
||||
* 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;
|
||||
|
||||
public enum GroupBy {
|
||||
AS_IS,
|
||||
TAGS
|
||||
}
|
||||
23
src/main/java/io/github/robwin/swagger2markup/OrderBy.java
Normal file
23
src/main/java/io/github/robwin/swagger2markup/OrderBy.java
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
*
|
||||
* 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;
|
||||
public enum OrderBy {
|
||||
AS_IS,
|
||||
NATURAL
|
||||
}
|
||||
@@ -17,17 +17,12 @@
|
||||
*
|
||||
*/
|
||||
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.github.robwin.swagger2markup.config.Swagger2MarkupConfig;
|
||||
import io.github.robwin.swagger2markup.builder.document.*;
|
||||
import io.github.robwin.swagger2markup.utils.Consumer;
|
||||
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;
|
||||
@@ -41,31 +36,16 @@ import java.nio.charset.StandardCharsets;
|
||||
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 final Swagger2MarkupConfig swagger2MarkupConfig;
|
||||
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.
|
||||
* @param swagger2MarkupConfig the configuration
|
||||
*/
|
||||
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;
|
||||
Swagger2MarkupConverter(Swagger2MarkupConfig swagger2MarkupConfig){
|
||||
this.swagger2MarkupConfig = swagger2MarkupConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -86,33 +66,24 @@ public class Swagger2MarkupConverter {
|
||||
* @return a Swagger2MarkupConverter
|
||||
*/
|
||||
public static Builder from(Swagger swagger){
|
||||
Validate.notNull(swagger, "swagger must not be null!");
|
||||
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.
|
||||
* @param swaggerAsString 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)
|
||||
public static Builder fromString(String swaggerAsString) throws IOException {
|
||||
Validate.notEmpty(swaggerAsString, "Swagger String must not be null!");
|
||||
Swagger swagger = new SwaggerParser().parse(swaggerAsString);
|
||||
if(swagger == null)
|
||||
throw new IllegalArgumentException("Swagger String is in the wrong format");
|
||||
|
||||
return new Builder(mapper.convertValue(rootNode, Swagger.class));
|
||||
return new Builder(swagger);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -144,9 +115,9 @@ public class Swagger2MarkupConverter {
|
||||
* @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);
|
||||
new OverviewDocument(swagger2MarkupConfig).build().writeToFile(directory, OVERVIEW_DOCUMENT, StandardCharsets.UTF_8);
|
||||
new PathsDocument(swagger2MarkupConfig).build().writeToFile(directory, PATHS_DOCUMENT, StandardCharsets.UTF_8);
|
||||
new DefinitionsDocument(swagger2MarkupConfig, directory).build().writeToFile(directory, DEFINITIONS_DOCUMENT, StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -154,10 +125,10 @@ public class Swagger2MarkupConverter {
|
||||
|
||||
* @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()));
|
||||
private String buildDocuments() {
|
||||
return new OverviewDocument(swagger2MarkupConfig).build().toString()
|
||||
.concat(new PathsDocument(swagger2MarkupConfig).build().toString()
|
||||
.concat(new DefinitionsDocument(swagger2MarkupConfig, null).build().toString()));
|
||||
}
|
||||
|
||||
|
||||
@@ -167,6 +138,8 @@ public class Swagger2MarkupConverter {
|
||||
private String schemasFolderPath;
|
||||
private String descriptionsFolderPath;
|
||||
private boolean separatedDefinitions;
|
||||
private GroupBy pathsGroupedBy = GroupBy.AS_IS;
|
||||
private OrderBy definitionsOrderedBy = OrderBy.NATURAL;
|
||||
private MarkupLanguage markupLanguage = MarkupLanguage.ASCIIDOC;
|
||||
|
||||
/**
|
||||
@@ -191,7 +164,7 @@ public class Swagger2MarkupConverter {
|
||||
}
|
||||
|
||||
public Swagger2MarkupConverter build(){
|
||||
return new Swagger2MarkupConverter(markupLanguage, swagger, examplesFolderPath, schemasFolderPath, descriptionsFolderPath, separatedDefinitions);
|
||||
return new Swagger2MarkupConverter(new Swagger2MarkupConfig(swagger, markupLanguage, examplesFolderPath, schemasFolderPath, descriptionsFolderPath, separatedDefinitions, pathsGroupedBy, definitionsOrderedBy));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -246,6 +219,39 @@ public class Swagger2MarkupConverter {
|
||||
this.schemasFolderPath = schemasFolderPath;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Customize the Swagger data in any useful way
|
||||
*
|
||||
* @param preProcessor function object to mutate the swagger object
|
||||
* @return the Swagger2MarkupConverter.Builder
|
||||
*/
|
||||
public Builder preProcessSwagger(Consumer<Swagger> preProcessor) {
|
||||
preProcessor.accept(this.swagger);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies if the paths should be grouped by tags or stay as-is.
|
||||
*
|
||||
* @param pathsGroupedBy the GroupBy enum
|
||||
* @return the Swagger2MarkupConverter.Builder
|
||||
*/
|
||||
public Builder withPathsGroupedBy(GroupBy pathsGroupedBy) {
|
||||
this.pathsGroupedBy = pathsGroupedBy;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies if the definitions should be ordered by natural ordering or stay as-is.
|
||||
*
|
||||
* @param definitionsOrderedBy the OrderBy enum
|
||||
* @return the Swagger2MarkupConverter.Builder
|
||||
*/
|
||||
public Builder withDefinitionsOrderedBy(OrderBy definitionsOrderedBy) {
|
||||
this.definitionsOrderedBy = definitionsOrderedBy;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -21,16 +21,16 @@ package io.github.robwin.swagger2markup.builder.document;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import io.github.robwin.markup.builder.MarkupDocBuilder;
|
||||
import io.github.robwin.markup.builder.MarkupDocBuilders;
|
||||
import io.github.robwin.swagger2markup.OrderBy;
|
||||
import io.github.robwin.swagger2markup.config.Swagger2MarkupConfig;
|
||||
import io.github.robwin.swagger2markup.utils.PropertyUtils;
|
||||
import io.swagger.models.ComposedModel;
|
||||
import io.swagger.models.Model;
|
||||
import io.swagger.models.RefModel;
|
||||
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 io.swagger.models.refs.RefFormat;
|
||||
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;
|
||||
@@ -39,6 +39,8 @@ import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.*;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.*;
|
||||
|
||||
/**
|
||||
* @author Robert Winkler
|
||||
*/
|
||||
@@ -59,16 +61,18 @@ public class DefinitionsDocument extends MarkupDocument {
|
||||
private String descriptionsFolderPath;
|
||||
private boolean separatedDefinitionsEnabled;
|
||||
private String outputDirectory;
|
||||
private final OrderBy definitionsOrderedBy;
|
||||
|
||||
public DefinitionsDocument(Swagger swagger, MarkupLanguage markupLanguage, String schemasFolderPath, String descriptionsFolderPath, boolean separatedDefinitionsEnabled, String outputDirectory){
|
||||
super(swagger, markupLanguage);
|
||||
if(StringUtils.isNotBlank(schemasFolderPath)){
|
||||
public DefinitionsDocument(Swagger2MarkupConfig swagger2MarkupConfig, String outputDirectory){
|
||||
super(swagger2MarkupConfig);
|
||||
this.definitionsOrderedBy = swagger2MarkupConfig.getDefinitionsOrderedBy();
|
||||
if(isNotBlank(swagger2MarkupConfig.getSchemasFolderPath())){
|
||||
this.schemasEnabled = true;
|
||||
this.schemasFolderPath = schemasFolderPath;
|
||||
this.schemasFolderPath = swagger2MarkupConfig.getSchemasFolderPath();
|
||||
}
|
||||
if(StringUtils.isNotBlank(descriptionsFolderPath)){
|
||||
if(isNotBlank(swagger2MarkupConfig.getDescriptionsFolderPath())){
|
||||
this.handWrittenDescriptionsEnabled = true;
|
||||
this.descriptionsFolderPath = descriptionsFolderPath + "/" + DEFINITIONS.toLowerCase();
|
||||
this.descriptionsFolderPath = swagger2MarkupConfig.getDescriptionsFolderPath() + "/" + DEFINITIONS.toLowerCase();
|
||||
}
|
||||
if(schemasEnabled){
|
||||
if (logger.isDebugEnabled()) {
|
||||
@@ -88,7 +92,7 @@ public class DefinitionsDocument extends MarkupDocument {
|
||||
logger.debug("Include hand-written descriptions is disabled.");
|
||||
}
|
||||
}
|
||||
this.separatedDefinitionsEnabled = separatedDefinitionsEnabled;
|
||||
this.separatedDefinitionsEnabled = swagger2MarkupConfig.isSeparatedDefinitions();
|
||||
if(this.separatedDefinitionsEnabled){
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Create separated definition files is enabled.");
|
||||
@@ -103,7 +107,7 @@ public class DefinitionsDocument extends MarkupDocument {
|
||||
}
|
||||
|
||||
@Override
|
||||
public MarkupDocument build() throws IOException {
|
||||
public MarkupDocument build(){
|
||||
definitions(swagger.getDefinitions(), this.markupDocBuilder);
|
||||
return this;
|
||||
}
|
||||
@@ -114,20 +118,32 @@ public class DefinitionsDocument extends MarkupDocument {
|
||||
* @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 {
|
||||
private void definitions(Map<String, Model> definitions, MarkupDocBuilder docBuilder){
|
||||
if(MapUtils.isNotEmpty(definitions)){
|
||||
docBuilder.sectionTitleLevel1(DEFINITIONS);
|
||||
for(Map.Entry<String, Model> definitionsEntry : definitions.entrySet()){
|
||||
String definitionName = definitionsEntry.getKey();
|
||||
if(StringUtils.isNotBlank(definitionName)) {
|
||||
Set<String> definitionNames;
|
||||
if(definitionsOrderedBy.equals(OrderBy.AS_IS)){
|
||||
definitionNames = definitions.keySet();
|
||||
}else{
|
||||
definitionNames = new TreeSet<>(definitions.keySet());
|
||||
}
|
||||
for(String definitionName : definitionNames){
|
||||
Model model = definitions.get(definitionName);
|
||||
if(isNotBlank(definitionName)) {
|
||||
if (checkThatDefinitionIsNotInIgnoreList(definitionName)) {
|
||||
definition(definitions, definitionName, definitionsEntry.getValue(), docBuilder);
|
||||
definition(definitions, definitionName, model, docBuilder);
|
||||
definitionSchema(definitionName, docBuilder);
|
||||
if (separatedDefinitionsEnabled) {
|
||||
MarkupDocBuilder defDocBuilder = MarkupDocBuilders.documentBuilder(markupLanguage);
|
||||
definition(definitions, definitionName, definitionsEntry.getValue(), defDocBuilder);
|
||||
definition(definitions, definitionName, model, defDocBuilder);
|
||||
definitionSchema(definitionName, defDocBuilder);
|
||||
defDocBuilder.writeToFile(outputDirectory, definitionName.toLowerCase(), StandardCharsets.UTF_8);
|
||||
try {
|
||||
defDocBuilder.writeToFile(outputDirectory, definitionName.toLowerCase(), StandardCharsets.UTF_8);
|
||||
} catch (IOException e) {
|
||||
if (logger.isWarnEnabled()) {
|
||||
logger.warn(String.format("Failed to write definition file: %s", definitionName), e);
|
||||
}
|
||||
}
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Separate definition file produced: {}", definitionName);
|
||||
}
|
||||
@@ -162,17 +178,17 @@ public class DefinitionsDocument extends MarkupDocument {
|
||||
* @param model the Swagger Model of the definition
|
||||
* @param docBuilder the docbuilder do use for output
|
||||
*/
|
||||
private void definition(Map<String, Model> definitions, String definitionName, Model model, MarkupDocBuilder docBuilder) throws IOException {
|
||||
private void definition(Map<String, Model> definitions, String definitionName, Model model, MarkupDocBuilder docBuilder){
|
||||
docBuilder.sectionTitleLevel2(definitionName);
|
||||
descriptionSection(definitionName, model, docBuilder);
|
||||
propertiesSection(definitions, definitionName, model, docBuilder);
|
||||
}
|
||||
|
||||
private void propertiesSection(Map<String, Model> definitions, String definitionName, Model model, MarkupDocBuilder docBuilder) throws IOException {
|
||||
private void propertiesSection(Map<String, Model> definitions, String definitionName, Model model, MarkupDocBuilder docBuilder){
|
||||
Map<String, Property> properties = getAllProperties(definitions, model);
|
||||
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));
|
||||
headerAndContent.add(join(header, DELIMITER));
|
||||
if(MapUtils.isNotEmpty(properties)){
|
||||
for (Map.Entry<String, Property> propertyEntry : properties.entrySet()) {
|
||||
Property property = propertyEntry.getValue();
|
||||
@@ -183,7 +199,7 @@ public class DefinitionsDocument extends MarkupDocument {
|
||||
Boolean.toString(property.getRequired()),
|
||||
PropertyUtils.getType(property, markupLanguage),
|
||||
PropertyUtils.getDefaultValue(property));
|
||||
headerAndContent.add(StringUtils.join(content, DELIMITER));
|
||||
headerAndContent.add(join(content, DELIMITER));
|
||||
}
|
||||
docBuilder.tableWithHeaderRow(headerAndContent);
|
||||
}
|
||||
@@ -191,9 +207,15 @@ public class DefinitionsDocument extends MarkupDocument {
|
||||
|
||||
private Map<String, Property> getAllProperties(Map<String, Model> definitions, Model model) {
|
||||
if(model instanceof RefModel) {
|
||||
final String ref = model.getReference();
|
||||
RefModel refModel = (RefModel)model;
|
||||
String ref;
|
||||
if(refModel.getRefFormat().equals(RefFormat.INTERNAL)){
|
||||
ref = refModel.getSimpleRef();
|
||||
}else{
|
||||
ref = model.getReference();
|
||||
}
|
||||
return definitions.containsKey(ref)
|
||||
? getAllProperties(definitions, definitions.get(model.getReference()))
|
||||
? getAllProperties(definitions, definitions.get(ref))
|
||||
: null;
|
||||
}
|
||||
if(model instanceof ComposedModel) {
|
||||
@@ -214,10 +236,10 @@ public class DefinitionsDocument extends MarkupDocument {
|
||||
}
|
||||
}
|
||||
|
||||
private void descriptionSection(String definitionName, Model model, MarkupDocBuilder docBuilder) throws IOException {
|
||||
private void descriptionSection(String definitionName, Model model, MarkupDocBuilder docBuilder){
|
||||
if(handWrittenDescriptionsEnabled){
|
||||
String description = handWrittenPathDescription(definitionName.toLowerCase(), DESCRIPTION_FILE_NAME);
|
||||
if(StringUtils.isNotBlank(description)){
|
||||
if(isNotBlank(description)){
|
||||
docBuilder.paragraph(description);
|
||||
}else{
|
||||
if (logger.isInfoEnabled()) {
|
||||
@@ -233,24 +255,24 @@ public class DefinitionsDocument extends MarkupDocument {
|
||||
|
||||
private void modelDescription(Model model, MarkupDocBuilder docBuilder) {
|
||||
String description = model.getDescription();
|
||||
if (StringUtils.isNotBlank(description)) {
|
||||
if (isNotBlank(description)) {
|
||||
docBuilder.paragraph(description);
|
||||
}
|
||||
}
|
||||
|
||||
private String propertyDescription(String definitionName, String propertyName, Property property) throws IOException {
|
||||
private String propertyDescription(String definitionName, String propertyName, Property property) {
|
||||
String description;
|
||||
if(handWrittenDescriptionsEnabled){
|
||||
description = handWrittenPathDescription(definitionName.toLowerCase() + "/" + propertyName.toLowerCase(), DESCRIPTION_FILE_NAME);
|
||||
if(StringUtils.isBlank(description)) {
|
||||
if(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());
|
||||
description = defaultString(property.getDescription());
|
||||
}
|
||||
}
|
||||
else{
|
||||
description = StringUtils.defaultString(property.getDescription());
|
||||
description = defaultString(property.getDescription());
|
||||
}
|
||||
return description;
|
||||
}
|
||||
@@ -262,16 +284,21 @@ public class DefinitionsDocument extends MarkupDocument {
|
||||
* @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 {
|
||||
private String handWrittenPathDescription(String descriptionFolder, String descriptionFileName){
|
||||
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();
|
||||
try {
|
||||
return FileUtils.readFileToString(path.toFile(), StandardCharsets.UTF_8).trim();
|
||||
} catch (IOException e) {
|
||||
if (logger.isWarnEnabled()) {
|
||||
logger.warn(String.format("Failed to read description file: %s", path), e);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Description file is not readable: {}", path);
|
||||
@@ -284,20 +311,26 @@ public class DefinitionsDocument extends MarkupDocument {
|
||||
return null;
|
||||
}
|
||||
|
||||
private void definitionSchema(String definitionName, MarkupDocBuilder docBuilder) throws IOException {
|
||||
private void definitionSchema(String definitionName, MarkupDocBuilder docBuilder) {
|
||||
if(schemasEnabled) {
|
||||
if (StringUtils.isNotBlank(definitionName)) {
|
||||
if (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 {
|
||||
private void schema(String title, String schemasFolderPath, String schemaName, String language, MarkupDocBuilder docBuilder) {
|
||||
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);
|
||||
try {
|
||||
docBuilder.source(FileUtils.readFileToString(path.toFile(), StandardCharsets.UTF_8).trim(), language);
|
||||
} catch (IOException e) {
|
||||
if (logger.isWarnEnabled()) {
|
||||
logger.warn(String.format("Failed to read schema file: %s", path), e);
|
||||
}
|
||||
}
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Schema file processed: {}", path);
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
*/
|
||||
package io.github.robwin.swagger2markup.builder.document;
|
||||
|
||||
import io.github.robwin.swagger2markup.config.Swagger2MarkupConfig;
|
||||
import io.swagger.models.Swagger;
|
||||
import io.github.robwin.markup.builder.MarkupDocBuilder;
|
||||
import io.github.robwin.markup.builder.MarkupDocBuilders;
|
||||
@@ -48,9 +49,9 @@ public abstract class MarkupDocument {
|
||||
protected MarkupLanguage markupLanguage;
|
||||
protected MarkupDocBuilder markupDocBuilder;
|
||||
|
||||
MarkupDocument(Swagger swagger, MarkupLanguage markupLanguage){
|
||||
this.swagger = swagger;
|
||||
this.markupLanguage = markupLanguage;
|
||||
MarkupDocument(Swagger2MarkupConfig swagger2MarkupConfig){
|
||||
this.swagger = swagger2MarkupConfig.getSwagger();
|
||||
this.markupLanguage = swagger2MarkupConfig.getMarkupLanguage();
|
||||
this.markupDocBuilder = MarkupDocBuilders.documentBuilder(markupLanguage);
|
||||
}
|
||||
|
||||
|
||||
@@ -18,15 +18,15 @@
|
||||
*/
|
||||
package io.github.robwin.swagger2markup.builder.document;
|
||||
|
||||
import io.github.robwin.swagger2markup.config.Swagger2MarkupConfig;
|
||||
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;
|
||||
|
||||
import static org.apache.commons.collections.CollectionUtils.isNotEmpty;
|
||||
import static org.apache.commons.lang3.StringUtils.*;
|
||||
|
||||
public class OverviewDocument extends MarkupDocument {
|
||||
|
||||
private static final String OVERVIEW = "Overview";
|
||||
@@ -44,18 +44,17 @@ public class OverviewDocument extends MarkupDocument {
|
||||
private static final String BASE_PATH = "BasePath: ";
|
||||
private static final String SCHEMES = "Schemes: ";
|
||||
|
||||
public OverviewDocument(Swagger swagger, MarkupLanguage markupLanguage){
|
||||
super(swagger, markupLanguage);
|
||||
public OverviewDocument(Swagger2MarkupConfig swagger2MarkupConfig){
|
||||
super(swagger2MarkupConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
public MarkupDocument build(){
|
||||
overview();
|
||||
return this;
|
||||
}
|
||||
@@ -68,11 +67,11 @@ public class OverviewDocument extends MarkupDocument {
|
||||
Info info = swagger.getInfo();
|
||||
this.markupDocBuilder.documentTitle(info.getTitle());
|
||||
this.markupDocBuilder.sectionTitleLevel1(OVERVIEW);
|
||||
if(StringUtils.isNotBlank(info.getDescription())){
|
||||
if(isNotBlank(info.getDescription())){
|
||||
this.markupDocBuilder.textLine(info.getDescription());
|
||||
this.markupDocBuilder.newLine();
|
||||
}
|
||||
if(StringUtils.isNotBlank(info.getVersion())){
|
||||
if(isNotBlank(info.getVersion())){
|
||||
this.markupDocBuilder.sectionTitleLevel2(CURRENT_VERSION);
|
||||
this.markupDocBuilder.textLine(VERSION + info.getVersion());
|
||||
this.markupDocBuilder.newLine();
|
||||
@@ -80,70 +79,72 @@ public class OverviewDocument extends MarkupDocument {
|
||||
Contact contact = info.getContact();
|
||||
if(contact != null){
|
||||
this.markupDocBuilder.sectionTitleLevel2(CONTACT_INFORMATION);
|
||||
if(StringUtils.isNotBlank(contact.getName())){
|
||||
if(isNotBlank(contact.getName())){
|
||||
this.markupDocBuilder.textLine(CONTACT_NAME + contact.getName());
|
||||
}
|
||||
if(StringUtils.isNotBlank(contact.getEmail())){
|
||||
if(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()))) {
|
||||
if(license != null && (isNotBlank(license.getName()) || isNotBlank(license.getUrl()))) {
|
||||
this.markupDocBuilder.sectionTitleLevel2(LICENSE_INFORMATION);
|
||||
if (StringUtils.isNotBlank(license.getName())) {
|
||||
if (isNotBlank(license.getName())) {
|
||||
this.markupDocBuilder.textLine(LICENSE + license.getName());
|
||||
}
|
||||
if (StringUtils.isNotBlank(license.getUrl())) {
|
||||
if (isNotBlank(license.getUrl())) {
|
||||
this.markupDocBuilder.textLine(LICENSE_URL + license.getUrl());
|
||||
}
|
||||
this.markupDocBuilder.newLine();
|
||||
}
|
||||
if(StringUtils.isNotBlank(info.getTermsOfService())){
|
||||
if(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());
|
||||
if(isNotBlank(swagger.getHost()) || isNotBlank(swagger.getBasePath()) || isNotEmpty(swagger.getSchemes())) {
|
||||
this.markupDocBuilder.sectionTitleLevel2(URI_SCHEME);
|
||||
if (isNotBlank(swagger.getHost())) {
|
||||
this.markupDocBuilder.textLine(HOST + swagger.getHost());
|
||||
}
|
||||
this.markupDocBuilder.textLine(SCHEMES + StringUtils.join(schemes, ", "));
|
||||
|
||||
if (isNotBlank(swagger.getBasePath())) {
|
||||
this.markupDocBuilder.textLine(BASE_PATH + swagger.getBasePath());
|
||||
}
|
||||
if (isNotEmpty(swagger.getSchemes())) {
|
||||
List<String> schemes = new ArrayList<>();
|
||||
for (Scheme scheme : swagger.getSchemes()) {
|
||||
schemes.add(scheme.toString());
|
||||
}
|
||||
this.markupDocBuilder.textLine(SCHEMES + join(schemes, ", "));
|
||||
}
|
||||
this.markupDocBuilder.newLine();
|
||||
}
|
||||
this.markupDocBuilder.newLine();
|
||||
|
||||
if(CollectionUtils.isNotEmpty(swagger.getTags())){
|
||||
if(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)){
|
||||
if(isNoneBlank(description)){
|
||||
tags.add(name + ": " + description);
|
||||
}else{
|
||||
tags.add(name);
|
||||
}
|
||||
tags.add(name);
|
||||
}
|
||||
this.markupDocBuilder.unorderedList(tags);
|
||||
this.markupDocBuilder.newLine();
|
||||
}
|
||||
|
||||
if(CollectionUtils.isNotEmpty(swagger.getConsumes())){
|
||||
if(isNotEmpty(swagger.getConsumes())){
|
||||
this.markupDocBuilder.sectionTitleLevel2(CONSUMES);
|
||||
this.markupDocBuilder.unorderedList(swagger.getConsumes());
|
||||
this.markupDocBuilder.newLine();
|
||||
}
|
||||
|
||||
if(CollectionUtils.isNotEmpty(swagger.getProduces())){
|
||||
if(isNotEmpty(swagger.getProduces())){
|
||||
this.markupDocBuilder.sectionTitleLevel2(PRODUCES);
|
||||
this.markupDocBuilder.unorderedList(swagger.getProduces());
|
||||
this.markupDocBuilder.newLine();
|
||||
|
||||
@@ -18,29 +18,29 @@
|
||||
*/
|
||||
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 com.google.common.base.Optional;
|
||||
import com.google.common.collect.Multimap;
|
||||
import io.github.robwin.swagger2markup.GroupBy;
|
||||
import io.github.robwin.swagger2markup.config.Swagger2MarkupConfig;
|
||||
import io.github.robwin.swagger2markup.utils.ParameterUtils;
|
||||
import io.github.robwin.swagger2markup.utils.PropertyUtils;
|
||||
import io.swagger.models.*;
|
||||
import io.swagger.models.parameters.Parameter;
|
||||
import io.swagger.models.properties.Property;
|
||||
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 org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
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;
|
||||
import java.util.*;
|
||||
|
||||
import static io.github.robwin.swagger2markup.utils.TagUtils.*;
|
||||
import static org.apache.commons.lang3.StringUtils.*;
|
||||
|
||||
/**
|
||||
* @author Robert Winkler
|
||||
@@ -48,6 +48,7 @@ import java.util.Map;
|
||||
public class PathsDocument extends MarkupDocument {
|
||||
|
||||
private static final String PATHS = "Paths";
|
||||
private static final String RESOURCES = "Resources";
|
||||
private static final String PARAMETERS = "Parameters";
|
||||
private static final String RESPONSES = "Responses";
|
||||
private static final String EXAMPLE_CURL = "Example CURL request";
|
||||
@@ -65,16 +66,18 @@ public class PathsDocument extends MarkupDocument {
|
||||
private String examplesFolderPath;
|
||||
private boolean handWrittenDescriptionsEnabled;
|
||||
private String descriptionsFolderPath;
|
||||
private final GroupBy pathsGroupedBy;
|
||||
|
||||
public PathsDocument(Swagger swagger, MarkupLanguage markupLanguage, String examplesFolderPath, String descriptionsFolderPath){
|
||||
super(swagger, markupLanguage);
|
||||
if(StringUtils.isNotBlank(examplesFolderPath)){
|
||||
public PathsDocument(Swagger2MarkupConfig swagger2MarkupConfig){
|
||||
super(swagger2MarkupConfig);
|
||||
this.pathsGroupedBy = swagger2MarkupConfig.getPathsGroupedBy();
|
||||
if(isNotBlank(swagger2MarkupConfig.getExamplesFolderPath())){
|
||||
this.examplesEnabled = true;
|
||||
this.examplesFolderPath = examplesFolderPath;
|
||||
this.examplesFolderPath = swagger2MarkupConfig.getExamplesFolderPath();
|
||||
}
|
||||
if(StringUtils.isNotBlank(descriptionsFolderPath)){
|
||||
if(isNotBlank(swagger2MarkupConfig.getDescriptionsFolderPath())){
|
||||
this.handWrittenDescriptionsEnabled = true;
|
||||
this.descriptionsFolderPath = descriptionsFolderPath + "/" + PATHS.toLowerCase();
|
||||
this.descriptionsFolderPath = swagger2MarkupConfig.getDescriptionsFolderPath() + "/" + PATHS.toLowerCase();
|
||||
}
|
||||
if(examplesEnabled){
|
||||
if (logger.isDebugEnabled()) {
|
||||
@@ -96,42 +99,70 @@ public class PathsDocument extends MarkupDocument {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the paths markup document.
|
||||
*
|
||||
* @return the the paths markup document
|
||||
* @throws IOException
|
||||
*/
|
||||
@Override
|
||||
public MarkupDocument build() throws IOException {
|
||||
public MarkupDocument build(){
|
||||
paths();
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds all paths of the Swagger model
|
||||
* Builds all paths of the Swagger model. Either grouped as-is or by tags.
|
||||
*/
|
||||
private void paths() throws IOException {
|
||||
private void paths(){
|
||||
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());
|
||||
if(pathsGroupedBy.equals(GroupBy.AS_IS)){
|
||||
this.markupDocBuilder.sectionTitleLevel1(PATHS);
|
||||
for (Map.Entry<String, Path> pathEntry : paths.entrySet()) {
|
||||
Path path = pathEntry.getValue();
|
||||
if(path != null) {
|
||||
createPathSections(pathEntry.getKey(), path);
|
||||
}
|
||||
}
|
||||
}else{
|
||||
this.markupDocBuilder.sectionTitleLevel1(RESOURCES);
|
||||
Multimap<String, Pair<String, Path>> pathsGroupedByTag = groupPathsByTag(paths);
|
||||
Map<String, Tag> tagsMap = convertTagsListToMap(swagger.getTags());
|
||||
for(String tagName : pathsGroupedByTag.keySet()){
|
||||
this.markupDocBuilder.sectionTitleLevel2(WordUtils.capitalize(tagName));
|
||||
Optional<String> tagDescription = getTagDescription(tagsMap, tagName);
|
||||
if(tagDescription.isPresent()) {
|
||||
this.markupDocBuilder.paragraph(tagDescription.get());
|
||||
}
|
||||
Collection<Pair<String, Path>> pathsOfTag = pathsGroupedByTag.get(tagName);
|
||||
for(Pair<String, Path> pathPair : pathsOfTag){
|
||||
Path path = pathPair.getValue();
|
||||
if(path != null) {
|
||||
createPathSections(pathPair.getKey(), path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void createPathSections(String pathUrl, Path path){
|
||||
for(Map.Entry<HttpMethod, Operation> operationEntry : path.getOperationMap().entrySet()){
|
||||
String methodAndPath = operationEntry.getKey() + " " + pathUrl;
|
||||
path(methodAndPath, operationEntry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a path
|
||||
* Builds a path.
|
||||
*
|
||||
* @param httpMethod the HTTP method of the path
|
||||
* @param resourcePath the URL of the path
|
||||
* @param methodAndPath the Method of the operation and the URL of the path
|
||||
* @param operation the Swagger Operation
|
||||
*/
|
||||
private void path(String httpMethod, String resourcePath, Operation operation) throws IOException {
|
||||
private void path(String methodAndPath, Operation operation) {
|
||||
if(operation != null){
|
||||
pathTitle(httpMethod, resourcePath, operation);
|
||||
pathTitle(methodAndPath, operation);
|
||||
descriptionSection(operation);
|
||||
parametersSection(operation);
|
||||
responsesSection(operation);
|
||||
@@ -142,63 +173,89 @@ public class PathsDocument extends MarkupDocument {
|
||||
}
|
||||
}
|
||||
|
||||
private void pathTitle(String httpMethod, String resourcePath, Operation operation) {
|
||||
/**
|
||||
* Adds the path 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 path.
|
||||
*
|
||||
* @param methodAndPath the Method of the operation and the URL of the path
|
||||
* @param operation the Swagger Operation
|
||||
*/
|
||||
private void pathTitle(String methodAndPath, Operation operation) {
|
||||
String summary = operation.getSummary();
|
||||
String title;
|
||||
if(StringUtils.isNotBlank(summary)) {
|
||||
if(isNotBlank(summary)) {
|
||||
title = summary;
|
||||
this.markupDocBuilder.sectionTitleLevel2(title);
|
||||
this.markupDocBuilder.listing(httpMethod + " " + resourcePath);
|
||||
addPathTitle(title);
|
||||
this.markupDocBuilder.listing(methodAndPath);
|
||||
}else{
|
||||
title = httpMethod + " " + resourcePath;
|
||||
this.markupDocBuilder.sectionTitleLevel2(title);
|
||||
addPathTitle(methodAndPath);
|
||||
}
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Path processed: {}", title);
|
||||
logger.info("Path processed: {}", methodAndPath);
|
||||
}
|
||||
}
|
||||
|
||||
private void descriptionSection(Operation operation) throws IOException {
|
||||
/**
|
||||
* Adds a path title to the document.
|
||||
*
|
||||
* @param title the path title
|
||||
*/
|
||||
private void addPathTitle(String title) {
|
||||
if(pathsGroupedBy.equals(GroupBy.AS_IS)){
|
||||
this.markupDocBuilder.sectionTitleLevel2(title);
|
||||
}else{
|
||||
this.markupDocBuilder.sectionTitleLevel3(title);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a path description to the document.
|
||||
*
|
||||
* @param operation the Swagger Operation
|
||||
*/
|
||||
private void descriptionSection(Operation operation) {
|
||||
if(handWrittenDescriptionsEnabled){
|
||||
String summary = operation.getSummary();
|
||||
if(StringUtils.isNotBlank(summary)) {
|
||||
if(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);
|
||||
Optional<String> description = handWrittenPathDescription(operationFolder, DESCRIPTION_FILE_NAME);
|
||||
if(description.isPresent()){
|
||||
pathDescription(description.get());
|
||||
}else{
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Hand-written description cannot be read. Trying to use description from Swagger source.");
|
||||
}
|
||||
pathDescription(operation);
|
||||
pathDescription(operation.getDescription());
|
||||
}
|
||||
}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);
|
||||
pathDescription(operation.getDescription());
|
||||
}
|
||||
}else {
|
||||
pathDescription(operation);
|
||||
pathDescription(operation.getDescription());
|
||||
}
|
||||
}
|
||||
|
||||
private void pathDescription(Operation operation) {
|
||||
String description = operation.getDescription();
|
||||
if (StringUtils.isNotBlank(description)) {
|
||||
this.markupDocBuilder.sectionTitleLevel3(DESCRIPTION);
|
||||
private void pathDescription(String description) {
|
||||
if (isNotBlank(description)) {
|
||||
if(pathsGroupedBy.equals(GroupBy.AS_IS)){
|
||||
this.markupDocBuilder.sectionTitleLevel3(DESCRIPTION);
|
||||
}else{
|
||||
this.markupDocBuilder.sectionTitleLevel4(DESCRIPTION);
|
||||
}
|
||||
this.markupDocBuilder.paragraph(description);
|
||||
}
|
||||
}
|
||||
|
||||
private void parametersSection(Operation operation) throws IOException {
|
||||
private void parametersSection(Operation operation) {
|
||||
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));
|
||||
headerAndContent.add(join(header, DELIMITER));
|
||||
for(Parameter parameter : parameters){
|
||||
String type = ParameterUtils.getType(parameter, markupLanguage);
|
||||
String parameterType = WordUtils.capitalize(parameter.getIn() + PARAMETER);
|
||||
@@ -209,43 +266,61 @@ public class PathsDocument extends MarkupDocument {
|
||||
parameterDescription(operation, parameter),
|
||||
Boolean.toString(parameter.getRequired()), type,
|
||||
ParameterUtils.getDefaultValue(parameter));
|
||||
headerAndContent.add(StringUtils.join(content, DELIMITER));
|
||||
headerAndContent.add(join(content, DELIMITER));
|
||||
}
|
||||
if(pathsGroupedBy.equals(GroupBy.AS_IS)){
|
||||
this.markupDocBuilder.sectionTitleLevel3(PARAMETERS);
|
||||
}else{
|
||||
this.markupDocBuilder.sectionTitleLevel4(PARAMETERS);
|
||||
}
|
||||
this.markupDocBuilder.sectionTitleLevel3(PARAMETERS);
|
||||
this.markupDocBuilder.tableWithHeaderRow(headerAndContent);
|
||||
}
|
||||
}
|
||||
|
||||
private String parameterDescription(Operation operation, Parameter parameter) throws IOException {
|
||||
String description;
|
||||
/**
|
||||
* Retrieves the description of a parameter, or otherwise an empty String.
|
||||
* If hand-written descriptions are enabled, it tries to load the description from a file.
|
||||
* If the file cannot be read, the description the parameter is returned.
|
||||
*
|
||||
* @param operation the Swagger Operation
|
||||
* @param parameter the Swagger Parameter
|
||||
* @return the description of a parameter.
|
||||
*/
|
||||
private String parameterDescription(Operation operation, Parameter parameter){
|
||||
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.");
|
||||
if(isNotBlank(operationFolder) && isNotBlank(parameterName)) {
|
||||
Optional<String> description = handWrittenPathDescription(operationFolder + "/" + parameterName, DESCRIPTION_FILE_NAME);
|
||||
if(description.isPresent()){
|
||||
return description.get();
|
||||
}
|
||||
else{
|
||||
if (logger.isWarnEnabled()) {
|
||||
logger.warn("Hand-written description file cannot be read. Trying to use description from Swagger source.");
|
||||
}
|
||||
description = StringUtils.defaultString(parameter.getDescription());
|
||||
return 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.");
|
||||
if (logger.isWarnEnabled()) {
|
||||
logger.warn("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());
|
||||
return defaultString(parameter.getDescription());
|
||||
}
|
||||
}else {
|
||||
description = StringUtils.defaultString(parameter.getDescription());
|
||||
return defaultString(parameter.getDescription());
|
||||
}
|
||||
return description;
|
||||
}
|
||||
|
||||
private void consumesSection(Operation operation) {
|
||||
List<String> consumes = operation.getConsumes();
|
||||
if(CollectionUtils.isNotEmpty(consumes)){
|
||||
this.markupDocBuilder.sectionTitleLevel3(CONSUMES);
|
||||
if(pathsGroupedBy.equals(GroupBy.AS_IS)){
|
||||
this.markupDocBuilder.sectionTitleLevel3(CONSUMES);
|
||||
}else{
|
||||
this.markupDocBuilder.sectionTitleLevel4(CONSUMES);
|
||||
}
|
||||
this.markupDocBuilder.unorderedList(consumes);
|
||||
}
|
||||
|
||||
@@ -254,45 +329,64 @@ public class PathsDocument extends MarkupDocument {
|
||||
private void producesSection(Operation operation) {
|
||||
List<String> produces = operation.getProduces();
|
||||
if(CollectionUtils.isNotEmpty(produces)){
|
||||
this.markupDocBuilder.sectionTitleLevel3(PRODUCES);
|
||||
if(pathsGroupedBy.equals(GroupBy.AS_IS)){
|
||||
this.markupDocBuilder.sectionTitleLevel3(PRODUCES);
|
||||
}else{
|
||||
this.markupDocBuilder.sectionTitleLevel4(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);
|
||||
if(pathsGroupedBy.equals(GroupBy.AS_IS)) {
|
||||
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
|
||||
* Builds the example section of a Swagger Operation. Tries to load the examples from
|
||||
* curl-request.adoc, http-request.adoc and http-response.adoc or
|
||||
* curl-request.md, http-request.md and http-response.md.
|
||||
*
|
||||
* @param operation the Swagger Operation
|
||||
* @throws IOException if the example file is not readable
|
||||
*/
|
||||
private void examplesSection(Operation operation) throws IOException {
|
||||
private void examplesSection(Operation operation) {
|
||||
if(examplesEnabled){
|
||||
String summary = operation.getSummary();
|
||||
if(StringUtils.isNotBlank(summary)) {
|
||||
if(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);
|
||||
Optional<String> curlExample = example(exampleFolder, CURL_EXAMPLE_FILE_NAME);
|
||||
if(curlExample.isPresent()){
|
||||
if(pathsGroupedBy.equals(GroupBy.AS_IS)){
|
||||
this.markupDocBuilder.sectionTitleLevel3(EXAMPLE_CURL);
|
||||
}else{
|
||||
this.markupDocBuilder.sectionTitleLevel4(EXAMPLE_CURL);
|
||||
}
|
||||
this.markupDocBuilder.paragraph(curlExample.get());
|
||||
}
|
||||
|
||||
String requestExample = example(exampleFolder, REQUEST_EXAMPLE_FILE_NAME);
|
||||
if(StringUtils.isNotBlank(requestExample)){
|
||||
this.markupDocBuilder.sectionTitleLevel3(EXAMPLE_REQUEST);
|
||||
this.markupDocBuilder.paragraph(requestExample);
|
||||
Optional<String> requestExample = example(exampleFolder, REQUEST_EXAMPLE_FILE_NAME);
|
||||
if(requestExample.isPresent()){
|
||||
if(pathsGroupedBy.equals(GroupBy.AS_IS)){
|
||||
this.markupDocBuilder.sectionTitleLevel3(EXAMPLE_REQUEST);
|
||||
}else{
|
||||
this.markupDocBuilder.sectionTitleLevel4(EXAMPLE_REQUEST);
|
||||
}
|
||||
this.markupDocBuilder.paragraph(requestExample.get());
|
||||
}
|
||||
String responseExample = example(exampleFolder, RESPONSE_EXAMPLE_FILE_NAME);
|
||||
if(StringUtils.isNotBlank(responseExample)){
|
||||
this.markupDocBuilder.sectionTitleLevel3(EXAMPLE_RESPONSE);
|
||||
this.markupDocBuilder.paragraph(responseExample);
|
||||
Optional<String> responseExample = example(exampleFolder, RESPONSE_EXAMPLE_FILE_NAME);
|
||||
if(responseExample.isPresent()){
|
||||
if(pathsGroupedBy.equals(GroupBy.AS_IS)){
|
||||
this.markupDocBuilder.sectionTitleLevel3(EXAMPLE_RESPONSE);
|
||||
}else{
|
||||
this.markupDocBuilder.sectionTitleLevel4(EXAMPLE_RESPONSE);
|
||||
}
|
||||
this.markupDocBuilder.paragraph(responseExample.get());
|
||||
}
|
||||
}else{
|
||||
if (logger.isWarnEnabled()) {
|
||||
@@ -308,26 +402,31 @@ public class PathsDocument extends MarkupDocument {
|
||||
* @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 {
|
||||
private Optional<String> example(String exampleFolder, String exampleFileName) {
|
||||
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();
|
||||
try {
|
||||
return Optional.fromNullable(FileUtils.readFileToString(path.toFile(), StandardCharsets.UTF_8).trim());
|
||||
} catch (IOException e) {
|
||||
if (logger.isWarnEnabled()) {
|
||||
logger.warn(String.format("Failed to read example file: %s", path), e);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Example file is not readable: {}", path);
|
||||
if (logger.isWarnEnabled()) {
|
||||
logger.warn("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));
|
||||
logger.warn("No example file found with correct file name extension in folder: {}", Paths.get(examplesFolderPath, exampleFolder));
|
||||
}
|
||||
return null;
|
||||
return Optional.absent();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -336,26 +435,31 @@ public class PathsDocument extends MarkupDocument {
|
||||
* @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 {
|
||||
private Optional<String> handWrittenPathDescription(String descriptionFolder, String descriptionFileName){
|
||||
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();
|
||||
try {
|
||||
return Optional.fromNullable(FileUtils.readFileToString(path.toFile(), StandardCharsets.UTF_8).trim());
|
||||
} catch (IOException e) {
|
||||
if (logger.isWarnEnabled()) {
|
||||
logger.warn(String.format("Failed to read description file: %s", path), e);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Description file is not readable: {}", path);
|
||||
if (logger.isWarnEnabled()) {
|
||||
logger.warn("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));
|
||||
logger.warn("No description file found with correct file name extension in folder: {}", Paths.get(descriptionsFolderPath, descriptionFolder));
|
||||
}
|
||||
return null;
|
||||
return Optional.absent();
|
||||
}
|
||||
|
||||
private void responsesSection(Operation operation) {
|
||||
@@ -373,7 +477,11 @@ public class PathsDocument extends MarkupDocument {
|
||||
csvContent.add(entry.getKey() + DELIMITER + response.getDescription() + DELIMITER + "No Content");
|
||||
}
|
||||
}
|
||||
this.markupDocBuilder.sectionTitleLevel3(RESPONSES);
|
||||
if(pathsGroupedBy.equals(GroupBy.AS_IS)){
|
||||
this.markupDocBuilder.sectionTitleLevel3(RESPONSES);
|
||||
}else{
|
||||
this.markupDocBuilder.sectionTitleLevel4(RESPONSES);
|
||||
}
|
||||
this.markupDocBuilder.tableWithHeaderRow(csvContent);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
*
|
||||
* 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.config;
|
||||
|
||||
import io.github.robwin.markup.builder.MarkupLanguage;
|
||||
import io.github.robwin.swagger2markup.GroupBy;
|
||||
import io.github.robwin.swagger2markup.OrderBy;
|
||||
import io.swagger.models.Swagger;
|
||||
|
||||
public class Swagger2MarkupConfig {
|
||||
|
||||
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 final GroupBy pathsGroupedBy;
|
||||
private final OrderBy definitionsOrderedBy;
|
||||
|
||||
/**
|
||||
* @param swagger the Swagger source
|
||||
* @param markupLanguage the markup language which is used to generate the files
|
||||
* @param examplesFolderPath examplesFolderPath the path to the folder where the example documents reside
|
||||
* @param schemasFolderPath the path to the folder where the schema documents reside
|
||||
* @param descriptionsFolderPath the path to the folder where the description documents reside
|
||||
* @param separatedDefinitions specified if in addition to the definitions file, also separate definition files for each model definition should be created
|
||||
* @param pathsGroupedBy specifies if the paths should be grouped by tags or stay as-is
|
||||
* @param definitionsOrderedBy specifies if the definitions should be ordered by natural ordering or stay as-is
|
||||
*/
|
||||
public Swagger2MarkupConfig(Swagger swagger, MarkupLanguage markupLanguage, String examplesFolderPath, String schemasFolderPath, String descriptionsFolderPath, boolean separatedDefinitions, GroupBy pathsGroupedBy, OrderBy definitionsOrderedBy) {
|
||||
this.swagger = swagger;
|
||||
this.markupLanguage = markupLanguage;
|
||||
this.examplesFolderPath = examplesFolderPath;
|
||||
this.schemasFolderPath = schemasFolderPath;
|
||||
this.descriptionsFolderPath = descriptionsFolderPath;
|
||||
this.separatedDefinitions = separatedDefinitions;
|
||||
this.pathsGroupedBy = pathsGroupedBy;
|
||||
this.definitionsOrderedBy = definitionsOrderedBy;
|
||||
}
|
||||
|
||||
public Swagger getSwagger() {
|
||||
return swagger;
|
||||
}
|
||||
|
||||
public MarkupLanguage getMarkupLanguage() {
|
||||
return markupLanguage;
|
||||
}
|
||||
|
||||
public String getExamplesFolderPath() {
|
||||
return examplesFolderPath;
|
||||
}
|
||||
|
||||
public String getSchemasFolderPath() {
|
||||
return schemasFolderPath;
|
||||
}
|
||||
|
||||
public String getDescriptionsFolderPath() {
|
||||
return descriptionsFolderPath;
|
||||
}
|
||||
|
||||
public boolean isSeparatedDefinitions() {
|
||||
return separatedDefinitions;
|
||||
}
|
||||
|
||||
public GroupBy getPathsGroupedBy() {
|
||||
return pathsGroupedBy;
|
||||
}
|
||||
|
||||
|
||||
public OrderBy getDefinitionsOrderedBy() {
|
||||
return definitionsOrderedBy;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package io.github.robwin.swagger2markup.utils;
|
||||
|
||||
/**
|
||||
* Java 8 style Consumer functional interface
|
||||
*/
|
||||
public interface Consumer<T> {
|
||||
|
||||
/**
|
||||
* The function itself
|
||||
* @param t the function argument
|
||||
*/
|
||||
void accept(T t);
|
||||
|
||||
}
|
||||
@@ -27,6 +27,13 @@ import org.apache.commons.lang3.Validate;
|
||||
|
||||
public final class ModelUtils {
|
||||
|
||||
/**
|
||||
* Retrieves the type of a model, or otherwise "NOT FOUND"
|
||||
*
|
||||
* @param model the model
|
||||
* @param markupLanguage the markup language which is used to generate the files
|
||||
* @return the type of the model, or otherwise "NOT FOUND"
|
||||
*/
|
||||
public static String getType(Model model, MarkupLanguage markupLanguage) {
|
||||
Validate.notNull(model, "model must not be null!");
|
||||
if (model instanceof ModelImpl) {
|
||||
|
||||
@@ -18,21 +18,29 @@
|
||||
*/
|
||||
package io.github.robwin.swagger2markup.utils;
|
||||
|
||||
import io.github.robwin.markup.builder.MarkupLanguage;
|
||||
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;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.*;
|
||||
|
||||
|
||||
public final class ParameterUtils {
|
||||
|
||||
/**
|
||||
* Retrieves the type of a parameter, or otherwise an empty String
|
||||
*
|
||||
* @param parameter the parameter
|
||||
* @param markupLanguage the markup language which is used to generate the files
|
||||
* @return the type of the parameter, or otherwise an empty String
|
||||
*/
|
||||
public static String getType(Parameter parameter, MarkupLanguage markupLanguage){
|
||||
Validate.notNull(parameter, "property must not be null!");
|
||||
String type = "NOT FOUND";
|
||||
@@ -50,7 +58,7 @@ public final class ParameterUtils {
|
||||
AbstractSerializableParameter serializableParameter = (AbstractSerializableParameter)parameter;
|
||||
List enums = serializableParameter.getEnum();
|
||||
if(CollectionUtils.isNotEmpty(enums)){
|
||||
type = "enum" + " (" + StringUtils.join(enums, ", ") + ")";
|
||||
type = "enum" + " (" + join(enums, ", ") + ")";
|
||||
}else{
|
||||
type = getTypeWithFormat(serializableParameter.getType(), serializableParameter.getFormat());
|
||||
}
|
||||
@@ -66,19 +74,32 @@ public final class ParameterUtils {
|
||||
default: return refParameter.getSimpleRef();
|
||||
}
|
||||
}
|
||||
return StringUtils.defaultString(type);
|
||||
return defaultString(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the format to the type, if a format is available
|
||||
*
|
||||
* @param typeWithoutFormat the type
|
||||
* @param format the format
|
||||
* @return returns the type and format, if a format is available
|
||||
*/
|
||||
private static String getTypeWithFormat(String typeWithoutFormat, String format) {
|
||||
String type;
|
||||
if(StringUtils.isNotBlank(format)){
|
||||
type = StringUtils.defaultString(typeWithoutFormat) + " (" + format + ")";
|
||||
if(isNotBlank(format)){
|
||||
type = defaultString(typeWithoutFormat) + " (" + format + ")";
|
||||
}else{
|
||||
type = StringUtils.defaultString(typeWithoutFormat);
|
||||
type = defaultString(typeWithoutFormat);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the default value of a parameter, or otherwise an empty String
|
||||
*
|
||||
* @param parameter the parameter
|
||||
* @return the default value of the parameter, or otherwise an empty String
|
||||
*/
|
||||
public static String getDefaultValue(Parameter parameter){
|
||||
Validate.notNull(parameter, "property must not be null!");
|
||||
String defaultValue = "";
|
||||
@@ -86,7 +107,7 @@ public final class ParameterUtils {
|
||||
AbstractSerializableParameter serializableParameter = (AbstractSerializableParameter)parameter;
|
||||
defaultValue = serializableParameter.getDefaultValue();
|
||||
}
|
||||
return StringUtils.defaultString(defaultValue);
|
||||
return defaultString(defaultValue);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,17 +18,25 @@
|
||||
*/
|
||||
package io.github.robwin.swagger2markup.utils;
|
||||
|
||||
import io.swagger.models.properties.*;
|
||||
import io.github.robwin.markup.builder.MarkupLanguage;
|
||||
import io.swagger.models.properties.*;
|
||||
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;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.*;
|
||||
|
||||
public final class PropertyUtils {
|
||||
|
||||
/**
|
||||
* Retrieves the type and format of a property.
|
||||
*
|
||||
* @param property the property
|
||||
* @param markupLanguage the markup language which is used to generate the files
|
||||
* @return the type of the property
|
||||
*/
|
||||
public static String getType(Property property, MarkupLanguage markupLanguage){
|
||||
Validate.notNull(property, "property must not be null!");
|
||||
String type;
|
||||
@@ -46,21 +54,27 @@ public final class PropertyUtils {
|
||||
StringProperty stringProperty = (StringProperty)property;
|
||||
List<String> enums = stringProperty.getEnum();
|
||||
if(CollectionUtils.isNotEmpty(enums)){
|
||||
type = "enum" + " (" + StringUtils.join(enums, ", ") + ")";
|
||||
type = "enum" + " (" + join(enums, ", ") + ")";
|
||||
}else{
|
||||
type = property.getType();
|
||||
}
|
||||
}
|
||||
else{
|
||||
if(StringUtils.isNotBlank(property.getFormat())){
|
||||
type = StringUtils.defaultString(property.getType()) + " (" + property.getFormat() + ")";
|
||||
if(isNotBlank(property.getFormat())){
|
||||
type = defaultString(property.getType()) + " (" + property.getFormat() + ")";
|
||||
}else{
|
||||
type = property.getType();
|
||||
}
|
||||
}
|
||||
return StringUtils.defaultString(type);
|
||||
return defaultString(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the default value of a property, or otherwise returns an empty String.
|
||||
*
|
||||
* @param property the property
|
||||
* @return the default value of the property, or otherwise an empty String
|
||||
*/
|
||||
public static String getDefaultValue(Property property){
|
||||
Validate.notNull(property, "property must not be null!");
|
||||
String defaultValue = "";
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
*
|
||||
* 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 com.google.common.base.Optional;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.common.collect.MultimapBuilder;
|
||||
import io.swagger.models.HttpMethod;
|
||||
import io.swagger.models.Operation;
|
||||
import io.swagger.models.Path;
|
||||
import io.swagger.models.Tag;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class TagUtils {
|
||||
|
||||
private static Logger LOG = LoggerFactory.getLogger(TagUtils.class);
|
||||
|
||||
/**
|
||||
* Converts the global Tag list into a Map where the tag name is the key and the Tag the value.
|
||||
*
|
||||
* @param tags the List of tags
|
||||
* @return the Map of tags
|
||||
*/
|
||||
public static Map<String, Tag> convertTagsListToMap(List<Tag> tags) {
|
||||
if (tags == null) {
|
||||
tags = new ArrayList<>();
|
||||
}
|
||||
Map<String, Tag> tagsMap = new HashMap<>();
|
||||
for (Tag tag : tags) tagsMap.put(tag.getName(), tag);
|
||||
return tagsMap;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the optional description of a tag.
|
||||
*
|
||||
* @param tagsMap the Map of tags
|
||||
* @param tagName the name of the tag
|
||||
* @return the optional description of the tag
|
||||
*/
|
||||
public static Optional<String> getTagDescription(Map<String, Tag> tagsMap, String tagName) {
|
||||
Tag tag = tagsMap.get(tagName);
|
||||
if(tag != null){
|
||||
return Optional.fromNullable(tag.getDescription());
|
||||
}
|
||||
return Optional.absent();
|
||||
}
|
||||
|
||||
/**
|
||||
* Groups the paths by tag. The key of the Multimap is the tag name.
|
||||
* The value of the Multimap is a Pair which contains the Method and the Path.
|
||||
*
|
||||
* @param paths the Paths
|
||||
* @return Paths grouped by Tag
|
||||
*/
|
||||
public static Multimap<String, Pair<String, Path>> groupPathsByTag(Map<String, Path> paths) {
|
||||
Multimap<String, Pair<String, Path>> pathsGroupedByTag = MultimapBuilder.SortedSetMultimapBuilder.treeKeys().hashSetValues().build();
|
||||
for (Map.Entry<String, Path> pathEntry : paths.entrySet()) {
|
||||
String resourcePath = pathEntry.getKey();
|
||||
Path path = pathEntry.getValue();
|
||||
for(Map.Entry<HttpMethod, Operation> operationEntry : path.getOperationMap().entrySet()){
|
||||
HttpMethod httpMethod = operationEntry.getKey();
|
||||
Operation operation = operationEntry.getValue();
|
||||
if(operation != null) {
|
||||
List<String> tags = operation.getTags();
|
||||
Validate.notEmpty(tags, "Path operations must have tags, if you want to group by tags! The operation '%s %s' has not tags.", httpMethod, resourcePath);
|
||||
for (String tag : tags) {
|
||||
if (LOG.isInfoEnabled()) {
|
||||
LOG.info("Added path operation '{} {}' to tag '{}'", httpMethod, resourcePath, tag);
|
||||
}
|
||||
pathsGroupedByTag.put(tag, Pair.of(resourcePath, pathEntry.getValue()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return pathsGroupedByTag;
|
||||
}
|
||||
}
|
||||
@@ -37,6 +37,7 @@ import java.util.Set;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static org.assertj.core.api.Assertions.fail;
|
||||
import static org.assertj.core.api.Assertions.failBecauseExceptionWasNotThrown;
|
||||
import static org.assertj.core.api.BDDAssertions.assertThat;
|
||||
|
||||
public class Swagger2MarkupConverterTest {
|
||||
@@ -57,11 +58,46 @@ public class Swagger2MarkupConverterTest {
|
||||
assertThat(directories).hasSize(3).containsAll(asList("definitions.adoc", "overview.adoc", "paths.adoc"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSwagger2AsciiDocGroupedByTags() throws IOException {
|
||||
//Given
|
||||
File file = new File(Swagger2MarkupConverterTest.class.getResource("/json/swagger.json").getFile());
|
||||
File outputDirectory = new File("build/docs/asciidoc/generated");
|
||||
FileUtils.deleteQuietly(outputDirectory);
|
||||
//When
|
||||
Swagger2MarkupConverter.from(file.getAbsolutePath())
|
||||
.withPathsGroupedBy(GroupBy.TAGS)
|
||||
.build()
|
||||
.intoFolder(outputDirectory.getAbsolutePath());
|
||||
|
||||
//Then
|
||||
String[] directories = outputDirectory.list();
|
||||
assertThat(directories).hasSize(3).containsAll(asList("definitions.adoc", "overview.adoc", "paths.adoc"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSwagger2AsciiDocGroupedByTagsWithMissingTag() throws IOException {
|
||||
//Given
|
||||
File file = new File(Swagger2MarkupConverterTest.class.getResource("/json/swagger_missing_tag.json").getFile());
|
||||
File outputDirectory = new File("build/docs/asciidoc/generated");
|
||||
FileUtils.deleteQuietly(outputDirectory);
|
||||
//When
|
||||
try {
|
||||
Swagger2MarkupConverter.from(file.getAbsolutePath())
|
||||
.withPathsGroupedBy(GroupBy.TAGS)
|
||||
.build()
|
||||
.intoFolder(outputDirectory.getAbsolutePath());
|
||||
// If NullPointerException was not thrown, test would fail the specified message
|
||||
failBecauseExceptionWasNotThrown(NullPointerException.class);
|
||||
} catch (Exception e) {
|
||||
assertThat(e).hasMessage("Path operations must have tags, if you want to group by tags! The operation 'PUT /pets' has not tags.");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOldSwaggerSpec2AsciiDocConversion() throws IOException {
|
||||
//Given
|
||||
File file = new File(Swagger2MarkupConverterTest.class.getResource("/json/swagger_12.json").getFile());
|
||||
File file = new File(Swagger2MarkupConverterTest.class.getResource("/json/error_swagger_12.json").getFile());
|
||||
File outputDirectory = new File("build/docs/asciidoc/generated");
|
||||
FileUtils.deleteQuietly(outputDirectory);
|
||||
|
||||
@@ -91,6 +127,44 @@ public class Swagger2MarkupConverterTest {
|
||||
assertThat(directories).hasSize(3).containsAll(asList("definitions.adoc", "overview.adoc", "paths.adoc"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSwagger2AsciiDocConversionDoesNotContainUriScheme() throws IOException {
|
||||
//Given
|
||||
File file = new File(Swagger2MarkupConverterTest.class.getResource("/yaml/swagger_should_not_contain_uri_scheme.yaml").getFile());
|
||||
File outputDirectory = new File("build/docs/asciidoc/generated");
|
||||
FileUtils.deleteQuietly(outputDirectory);
|
||||
|
||||
//When
|
||||
Swagger2MarkupConverter.from(file.getAbsolutePath()).build()
|
||||
.intoFolder(outputDirectory.getAbsolutePath());
|
||||
|
||||
//Then
|
||||
String[] directories = outputDirectory.list();
|
||||
assertThat(directories).hasSize(3).containsAll(asList("definitions.adoc", "overview.adoc", "paths.adoc"));
|
||||
|
||||
assertThat(new String(Files.readAllBytes(Paths.get(outputDirectory + File.separator + "overview.adoc"))))
|
||||
.doesNotContain("=== URI scheme");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSwagger2AsciiDocConversionContainsUriScheme() throws IOException {
|
||||
//Given
|
||||
File file = new File(Swagger2MarkupConverterTest.class.getResource("/yaml/swagger_should_contain_uri_scheme.yaml").getFile());
|
||||
File outputDirectory = new File("build/docs/asciidoc/generated");
|
||||
FileUtils.deleteQuietly(outputDirectory);
|
||||
|
||||
//When
|
||||
Swagger2MarkupConverter.from(file.getAbsolutePath()).build()
|
||||
.intoFolder(outputDirectory.getAbsolutePath());
|
||||
|
||||
//Then
|
||||
String[] directories = outputDirectory.list();
|
||||
assertThat(directories).hasSize(3).containsAll(asList("definitions.adoc", "overview.adoc", "paths.adoc"));
|
||||
|
||||
assertThat(new String(Files.readAllBytes(Paths.get(outputDirectory + File.separator + "overview.adoc"))))
|
||||
.contains("=== URI scheme");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSwagger2MarkdownConversion() throws IOException {
|
||||
//Given
|
||||
@@ -149,7 +223,7 @@ public class Swagger2MarkupConverterTest {
|
||||
public void testSwagger2MarkdownConversionWithSeparatedDefinitions() throws IOException {
|
||||
//Given
|
||||
File file = new File(Swagger2MarkupConverterTest.class.getResource("/json/swagger.json").getFile());
|
||||
File outputDirectory = new File("build/docs/asciidoc/generated");
|
||||
File outputDirectory = new File("build/docs/markdown/generated");
|
||||
FileUtils.deleteQuietly(outputDirectory);
|
||||
|
||||
//When
|
||||
@@ -170,7 +244,7 @@ public class Swagger2MarkupConverterTest {
|
||||
public void testSwagger2MarkdownConversionHandlesComposition() throws IOException {
|
||||
//Given
|
||||
File file = new File(Swagger2MarkupConverterTest.class.getResource("/json/swagger.json").getFile());
|
||||
File outputDirectory = new File("build/docs/asciidoc/generated");
|
||||
File outputDirectory = new File("build/docs/markdown/generated");
|
||||
FileUtils.deleteQuietly(outputDirectory);
|
||||
|
||||
//When
|
||||
|
||||
108
src/test/resources/json/error_swagger_12.json
Normal file
108
src/test/resources/json/error_swagger_12.json
Normal file
@@ -0,0 +1,108 @@
|
||||
{
|
||||
"apiVersion": "1",
|
||||
"swaggerVersion": "1.2",
|
||||
"basePath": "http://localhost:8082/query-rs",
|
||||
"resourcePath": "/query-services",
|
||||
"apis": [
|
||||
{
|
||||
"path": "/query-services/timesheet",
|
||||
"operations": [
|
||||
{
|
||||
"method": "GET",
|
||||
"summary": "testTimesheet",
|
||||
"responseClass": "void",
|
||||
"nickname": "testTimeSheet",
|
||||
"position": 0,
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "body",
|
||||
"required": false,
|
||||
"allowMultiple": false,
|
||||
"dataType": "TimesheetEntryWireBase",
|
||||
"paramType": "body"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"models": {
|
||||
"TimesheetEntryWireBase": {
|
||||
"id": "TimesheetEntryWireBase",
|
||||
"name": "TimesheetEntryWireBase",
|
||||
"qualifiedType": "com.yt.nss.rest.domain.test.TimesheetEntryWireBase",
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"qualifiedType": "java.lang.String",
|
||||
"position": 0,
|
||||
"allowableValues": {
|
||||
"values": [
|
||||
"STRING"
|
||||
],
|
||||
"valueType": "LIST"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Basic class for timesheet entry",
|
||||
"baseModel": "java.lang.Void",
|
||||
"discriminator": "type",
|
||||
"subTypes": [
|
||||
"com.yt.nss.rest.domain.test.TimesheetProjectEntryWire",
|
||||
"com.yt.nss.rest.domain.test.TimesheetAdminEntryWire"
|
||||
]
|
||||
},
|
||||
"TimesheetProjectEntryWire": {
|
||||
"id": "TimesheetProjectEntryWire",
|
||||
"name": "TimesheetProjectEntryWire",
|
||||
"qualifiedType": "com.yt.nss.rest.domain.test.TimesheetProjectEntryWire",
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"qualifiedType": "java.lang.String",
|
||||
"position": 0,
|
||||
"allowableValues": {
|
||||
"values": [
|
||||
"STRING"
|
||||
],
|
||||
"valueType": "LIST"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"TimesheetAdminEntryWire": {
|
||||
"id": "TimesheetAdminEntryWire",
|
||||
"name": "TimesheetAdminEntryWire",
|
||||
"qualifiedType": "com.yt.nss.rest.domain.test.TimesheetAdminEntryWire",
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"qualifiedType": "java.lang.String",
|
||||
"position": 0,
|
||||
"allowableValues": {
|
||||
"values": [
|
||||
"STRING"
|
||||
],
|
||||
"valueType": "LIST"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"position": 1
|
||||
}
|
||||
@@ -18,6 +18,20 @@
|
||||
"schemes": [
|
||||
"http"
|
||||
],
|
||||
"tags": [
|
||||
{
|
||||
"name": "pet",
|
||||
"description": "Pet resource"
|
||||
},
|
||||
{
|
||||
"name": "store",
|
||||
"description": "Store resource"
|
||||
},
|
||||
{
|
||||
"name": "user",
|
||||
"description": "User resource"
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"/pets": {
|
||||
"post": {
|
||||
@@ -134,13 +148,7 @@
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "successful operation",
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/Pet"
|
||||
}
|
||||
}
|
||||
"$ref": "#/responses/FoundPets"
|
||||
},
|
||||
"400": {
|
||||
"description": "Invalid status value"
|
||||
@@ -183,13 +191,7 @@
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "successful operation",
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/Pet"
|
||||
}
|
||||
}
|
||||
"$ref": "#/responses/FoundPets"
|
||||
},
|
||||
"400": {
|
||||
"description": "Invalid tag value"
|
||||
@@ -219,12 +221,7 @@
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"in": "path",
|
||||
"name": "petId",
|
||||
"description": "ID of pet that needs to be fetched",
|
||||
"required": true,
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
"$ref": "#/parameters/petId"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
@@ -729,6 +726,27 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses":{
|
||||
"FoundPets": {
|
||||
"description": "successful operation",
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/Pet"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"parameters":{
|
||||
"petId": {
|
||||
"in": "path",
|
||||
"name": "petId",
|
||||
"description": "ID of the pet",
|
||||
"required": true,
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
"Identified": {
|
||||
"properties": {
|
||||
@@ -767,6 +785,13 @@
|
||||
"type": "integer",
|
||||
"format": "int32",
|
||||
"description": "User Status"
|
||||
},
|
||||
"pictures": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"format": "byte"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
883
src/test/resources/json/swagger_missing_tag.json
Normal file
883
src/test/resources/json/swagger_missing_tag.json
Normal file
@@ -0,0 +1,883 @@
|
||||
{
|
||||
"swagger": "2.0",
|
||||
"info": {
|
||||
"description": "This is a sample server Petstore server.\n\n[Learn about Swagger](http://swagger.wordnik.com) or join the IRC channel `#swagger` on irc.freenode.net.\n\nFor this sample, you can use the api key `special-key` to test the authorization filters\n",
|
||||
"version": "1.0.0",
|
||||
"title": "Swagger Petstore API",
|
||||
"termsOfService": "http://helloreverb.com/terms/",
|
||||
"contact": {
|
||||
"name": "apiteam@wordnik.com"
|
||||
},
|
||||
"license": {
|
||||
"name": "Apache 2.0",
|
||||
"url": "http://www.apache.org/licenses/LICENSE-2.0.html"
|
||||
}
|
||||
},
|
||||
"host": "petstore.swagger.wordnik.com",
|
||||
"basePath": "/v2",
|
||||
"schemes": [
|
||||
"http"
|
||||
],
|
||||
"tags": [
|
||||
{
|
||||
"name": "pet",
|
||||
"description": "Pet resource"
|
||||
},
|
||||
{
|
||||
"name": "store",
|
||||
"description": "Store resource"
|
||||
},
|
||||
{
|
||||
"name": "user",
|
||||
"description": "User resource"
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"/pets": {
|
||||
"post": {
|
||||
"tags": [
|
||||
"pet"
|
||||
],
|
||||
"summary": "Add a new pet to the store",
|
||||
"description": "",
|
||||
"operationId": "addPet",
|
||||
"consumes": [
|
||||
"application/json",
|
||||
"application/xml"
|
||||
],
|
||||
"produces": [
|
||||
"application/json",
|
||||
"application/xml"
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"in": "body",
|
||||
"name": "body",
|
||||
"description": "Pet object that needs to be added to the store",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/Pet"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"405": {
|
||||
"description": "Invalid input"
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"petstore_auth": [
|
||||
"write_pets",
|
||||
"read_pets"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"put": {
|
||||
"summary": "Update an existing pet",
|
||||
"description": "",
|
||||
"operationId": "updatePet",
|
||||
"consumes": [
|
||||
"application/json",
|
||||
"application/xml"
|
||||
],
|
||||
"produces": [
|
||||
"application/json",
|
||||
"application/xml"
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"in": "body",
|
||||
"name": "body",
|
||||
"description": "Pet object that needs to be added to the store",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/Pet"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"400": {
|
||||
"description": "Invalid ID supplied"
|
||||
},
|
||||
"404": {
|
||||
"description": "Pet not found"
|
||||
},
|
||||
"405": {
|
||||
"description": "Validation exception"
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"petstore_auth": [
|
||||
"write_pets",
|
||||
"read_pets"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"/pets/findByStatus": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"pet"
|
||||
],
|
||||
"summary": "Finds Pets by status",
|
||||
"description": "Multiple status values can be provided with comma seperated strings",
|
||||
"operationId": "findPetsByStatus",
|
||||
"produces": [
|
||||
"application/json",
|
||||
"application/xml"
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"in": "query",
|
||||
"name": "status",
|
||||
"description": "Status values that need to be considered for filter",
|
||||
"required": false,
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"collectionFormat": "multi"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"$ref": "#/responses/FoundPets"
|
||||
},
|
||||
"400": {
|
||||
"description": "Invalid status value"
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"petstore_auth": [
|
||||
"write_pets",
|
||||
"read_pets"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"/pets/findByTags": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"pet"
|
||||
],
|
||||
"summary": "Finds Pets by tags",
|
||||
"description": "Muliple tags can be provided with comma seperated strings. Use tag1, tag2, tag3 for testing.",
|
||||
"operationId": "findPetsByTags",
|
||||
"produces": [
|
||||
"application/json",
|
||||
"application/xml"
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"in": "query",
|
||||
"name": "tags",
|
||||
"description": "Tags to filter by",
|
||||
"required": false,
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"collectionFormat": "multi"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"$ref": "#/responses/FoundPets"
|
||||
},
|
||||
"400": {
|
||||
"description": "Invalid tag value"
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"petstore_auth": [
|
||||
"write_pets",
|
||||
"read_pets"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"/pets/{petId}": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"pet"
|
||||
],
|
||||
"summary": "Find pet by ID",
|
||||
"description": "Returns a pet when ID < 10. ID > 10 or nonintegers will simulate API error conditions",
|
||||
"operationId": "getPetById",
|
||||
"produces": [
|
||||
"application/json",
|
||||
"application/xml"
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"$ref": "#/parameters/petId"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "successful operation",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/Pet"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Invalid ID supplied"
|
||||
},
|
||||
"404": {
|
||||
"description": "Pet not found"
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"api_key": []
|
||||
},
|
||||
{
|
||||
"petstore_auth": [
|
||||
"write_pets",
|
||||
"read_pets"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"post": {
|
||||
"tags": [
|
||||
"pet"
|
||||
],
|
||||
"summary": "Updates a pet in the store with form data",
|
||||
"description": "",
|
||||
"operationId": "updatePetWithForm",
|
||||
"consumes": [
|
||||
"application/x-www-form-urlencoded"
|
||||
],
|
||||
"produces": [
|
||||
"application/json",
|
||||
"application/xml"
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"in": "path",
|
||||
"name": "petId",
|
||||
"description": "ID of pet that needs to be updated",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"in": "formData",
|
||||
"name": "name",
|
||||
"description": "Updated name of the pet",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"in": "formData",
|
||||
"name": "status",
|
||||
"description": "Updated status of the pet",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"405": {
|
||||
"description": "Invalid input"
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"petstore_auth": [
|
||||
"write_pets",
|
||||
"read_pets"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"delete": {
|
||||
"tags": [
|
||||
"pet"
|
||||
],
|
||||
"summary": "Deletes a pet",
|
||||
"description": "",
|
||||
"operationId": "deletePet",
|
||||
"produces": [
|
||||
"application/json",
|
||||
"application/xml"
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"in": "header",
|
||||
"name": "api_key",
|
||||
"description": "",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"in": "path",
|
||||
"name": "petId",
|
||||
"description": "Pet id to delete",
|
||||
"required": true,
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"400": {
|
||||
"description": "Invalid pet value"
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"petstore_auth": [
|
||||
"write_pets",
|
||||
"read_pets"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"/stores/order": {
|
||||
"post": {
|
||||
"tags": [
|
||||
"store"
|
||||
],
|
||||
"summary": "Place an order for a pet",
|
||||
"description": "",
|
||||
"operationId": "placeOrder",
|
||||
"produces": [
|
||||
"application/json",
|
||||
"application/xml"
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"in": "body",
|
||||
"name": "body",
|
||||
"description": "order placed for purchasing the pet",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/Order"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "successful operation",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/Order"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Invalid Order"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/stores/order/{orderId}": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"store"
|
||||
],
|
||||
"summary": "Find purchase order by ID",
|
||||
"description": "For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions",
|
||||
"operationId": "getOrderById",
|
||||
"produces": [
|
||||
"application/json",
|
||||
"application/xml"
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"in": "path",
|
||||
"name": "orderId",
|
||||
"description": "ID of pet that needs to be fetched",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "successful operation",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/Order"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Invalid ID supplied"
|
||||
},
|
||||
"404": {
|
||||
"description": "Order not found"
|
||||
}
|
||||
}
|
||||
},
|
||||
"delete": {
|
||||
"tags": [
|
||||
"store"
|
||||
],
|
||||
"summary": "Delete purchase order by ID",
|
||||
"description": "For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors",
|
||||
"operationId": "deleteOrder",
|
||||
"produces": [
|
||||
"application/json",
|
||||
"application/xml"
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"in": "path",
|
||||
"name": "orderId",
|
||||
"description": "ID of the order that needs to be deleted",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"400": {
|
||||
"description": "Invalid ID supplied"
|
||||
},
|
||||
"404": {
|
||||
"description": "Order not found"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/users": {
|
||||
"post": {
|
||||
"tags": [
|
||||
"user"
|
||||
],
|
||||
"summary": "Create user",
|
||||
"description": "This can only be done by the logged in user.",
|
||||
"operationId": "createUser",
|
||||
"produces": [
|
||||
"application/json",
|
||||
"application/xml"
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"in": "body",
|
||||
"name": "body",
|
||||
"description": "Created user object",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/User"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"default": {
|
||||
"description": "successful operation"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/users/createWithArray": {
|
||||
"post": {
|
||||
"tags": [
|
||||
"user"
|
||||
],
|
||||
"summary": "Creates list of users with given input array",
|
||||
"description": "",
|
||||
"operationId": "createUsersWithArrayInput",
|
||||
"produces": [
|
||||
"application/json",
|
||||
"application/xml"
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"in": "body",
|
||||
"name": "body",
|
||||
"description": "List of user object",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/User"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"default": {
|
||||
"description": "successful operation"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/users/createWithList": {
|
||||
"post": {
|
||||
"tags": [
|
||||
"user"
|
||||
],
|
||||
"summary": "Creates list of users with given input array",
|
||||
"description": "",
|
||||
"operationId": "createUsersWithListInput",
|
||||
"produces": [
|
||||
"application/json",
|
||||
"application/xml"
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"in": "body",
|
||||
"name": "body",
|
||||
"description": "List of user object",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/User"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"default": {
|
||||
"description": "successful operation"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/users/login": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"user"
|
||||
],
|
||||
"summary": "Logs user into the system",
|
||||
"description": "",
|
||||
"operationId": "loginUser",
|
||||
"produces": [
|
||||
"application/json",
|
||||
"application/xml"
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"in": "query",
|
||||
"name": "username",
|
||||
"description": "The user name for login",
|
||||
"required": false,
|
||||
"type": "string",
|
||||
"default": "testUser"
|
||||
},
|
||||
{
|
||||
"in": "query",
|
||||
"name": "password",
|
||||
"description": "The password for login in clear text",
|
||||
"required": false,
|
||||
"type": "string",
|
||||
"default": "testPassword"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "successful operation",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Invalid username/password supplied"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/users/logout": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"user"
|
||||
],
|
||||
"summary": "Logs out current logged in user session",
|
||||
"description": "",
|
||||
"operationId": "logoutUser",
|
||||
"produces": [
|
||||
"application/json",
|
||||
"application/xml"
|
||||
],
|
||||
"responses": {
|
||||
"default": {
|
||||
"description": "successful operation"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/users/{username}": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"user"
|
||||
],
|
||||
"summary": "Get user by user name",
|
||||
"description": "",
|
||||
"operationId": "getUserByName",
|
||||
"produces": [
|
||||
"application/json",
|
||||
"application/xml"
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"in": "path",
|
||||
"name": "username",
|
||||
"description": "The name that needs to be fetched. Use user1 for testing.",
|
||||
"required": true,
|
||||
"type": "string",
|
||||
"default": "testUser"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "successful operation",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/User"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Invalid username supplied"
|
||||
},
|
||||
"404": {
|
||||
"description": "User not found"
|
||||
}
|
||||
}
|
||||
},
|
||||
"put": {
|
||||
"tags": [
|
||||
"user"
|
||||
],
|
||||
"summary": "Updated user",
|
||||
"description": "This can only be done by the logged in user.",
|
||||
"operationId": "updateUser",
|
||||
"produces": [
|
||||
"application/json",
|
||||
"application/xml"
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"in": "path",
|
||||
"name": "username",
|
||||
"description": "name that need to be deleted",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"in": "body",
|
||||
"name": "body",
|
||||
"description": "Updated user object",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/User"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"400": {
|
||||
"description": "Invalid user supplied"
|
||||
},
|
||||
"404": {
|
||||
"description": "User not found"
|
||||
}
|
||||
}
|
||||
},
|
||||
"delete": {
|
||||
"tags": [
|
||||
"user"
|
||||
],
|
||||
"summary": "Delete user",
|
||||
"description": "This can only be done by the logged in user.",
|
||||
"operationId": "deleteUser",
|
||||
"produces": [
|
||||
"application/json",
|
||||
"application/xml"
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"in": "path",
|
||||
"name": "username",
|
||||
"description": "The name that needs to be deleted",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"400": {
|
||||
"description": "Invalid username supplied"
|
||||
},
|
||||
"404": {
|
||||
"description": "User not found"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"securityDefinitions": {
|
||||
"api_key": {
|
||||
"type": "apiKey",
|
||||
"name": "api_key",
|
||||
"in": "header"
|
||||
},
|
||||
"petstore_auth": {
|
||||
"type": "oauth2",
|
||||
"authorizationUrl": "http://petstore.swagger.wordnik.com/api/oauth/dialog",
|
||||
"flow": "implicit",
|
||||
"scopes": {
|
||||
"write_pets": "modify pets in your account",
|
||||
"read_pets": "read your pets"
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses":{
|
||||
"FoundPets": {
|
||||
"description": "successful operation",
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/Pet"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"parameters":{
|
||||
"petId": {
|
||||
"in": "path",
|
||||
"name": "petId",
|
||||
"description": "ID of the pet",
|
||||
"required": true,
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
"Identified": {
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
}
|
||||
}
|
||||
},
|
||||
"User": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/Identified"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"username": {
|
||||
"type": "string"
|
||||
},
|
||||
"firstName": {
|
||||
"type": "string"
|
||||
},
|
||||
"lastName": {
|
||||
"type": "string"
|
||||
},
|
||||
"email": {
|
||||
"type": "string"
|
||||
},
|
||||
"password": {
|
||||
"type": "string"
|
||||
},
|
||||
"phone": {
|
||||
"type": "string"
|
||||
},
|
||||
"userStatus": {
|
||||
"type": "integer",
|
||||
"format": "int32",
|
||||
"description": "User Status"
|
||||
},
|
||||
"pictures": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"format": "byte"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"Category": {
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Pet": {
|
||||
"description" : "Test description",
|
||||
"required": [
|
||||
"name",
|
||||
"photoUrls"
|
||||
],
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"category": {
|
||||
"$ref": "#/definitions/Category"
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"example": "doggie"
|
||||
},
|
||||
"photoUrls": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"tags": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/Tag"
|
||||
}
|
||||
},
|
||||
"status": {
|
||||
"type": "string",
|
||||
"description": "pet status in the store"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Tag": {
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Order": {
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"petId": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"quantity": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"shipDate": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"status": {
|
||||
"type": "string",
|
||||
"description": "Order Status"
|
||||
},
|
||||
"complete": {
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
48
src/test/resources/yaml/swagger_overwrites.yml
Normal file
48
src/test/resources/yaml/swagger_overwrites.yml
Normal file
@@ -0,0 +1,48 @@
|
||||
swagger: '2.0'
|
||||
info:
|
||||
description: TODO
|
||||
version: 0.0.1
|
||||
title: API Spec
|
||||
termsOfService: TODO
|
||||
basePath: /v1
|
||||
schemes:
|
||||
- http
|
||||
paths:
|
||||
/aaa:
|
||||
post:
|
||||
tags:
|
||||
- AAA
|
||||
summary: TODO
|
||||
description: TODO
|
||||
operationId: aaa
|
||||
consumes:
|
||||
- application/json
|
||||
produces:
|
||||
- application/json
|
||||
parameters:
|
||||
- in: body
|
||||
name: body
|
||||
description: TODO
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/AAA'
|
||||
responses:
|
||||
'200':
|
||||
description: Success
|
||||
'405':
|
||||
description: Invalid data
|
||||
definitions:
|
||||
AAA:
|
||||
allOf:
|
||||
- $ref: '#/definitions/BBB'
|
||||
- type: object
|
||||
properties:
|
||||
propA:
|
||||
type: string
|
||||
propB:
|
||||
type: string
|
||||
BBB:
|
||||
type: object
|
||||
properties:
|
||||
propA:
|
||||
type: string
|
||||
@@ -0,0 +1,21 @@
|
||||
swagger: '2.0'
|
||||
info:
|
||||
version: "0.0.0"
|
||||
title: Test - Should contain URI scheme
|
||||
|
||||
host: localhost
|
||||
|
||||
schemes:
|
||||
- http
|
||||
- https
|
||||
|
||||
basePath: /api
|
||||
|
||||
paths:
|
||||
/test:
|
||||
get:
|
||||
responses:
|
||||
200:
|
||||
description: OK
|
||||
schema:
|
||||
type: string
|
||||
@@ -0,0 +1,13 @@
|
||||
swagger: '2.0'
|
||||
info:
|
||||
version: "0.0.0"
|
||||
title: Test - Should not contain URI scheme
|
||||
|
||||
paths:
|
||||
/test:
|
||||
get:
|
||||
responses:
|
||||
200:
|
||||
description: OK
|
||||
schema:
|
||||
type: string
|
||||
Reference in New Issue
Block a user