Merge branch 'master' into features/sparser-1.0.18

This commit is contained in:
Hugo de Paix de Coeur
2016-03-15 18:12:19 +01:00
77 changed files with 1763 additions and 3755 deletions

View File

@@ -14,17 +14,12 @@ buildscript {
}
description = 'swagger2markup Build'
version = '1.0.0-SNAPSHOT'
group = 'io.github.robwin'
group = 'io.github.swagger2markup'
apply plugin: 'java'
apply plugin: 'maven-publish'
apply plugin: 'org.asciidoctor.convert'
apply plugin: 'jacoco'
apply plugin: 'com.github.kt3k.coveralls'
apply plugin: 'com.jfrog.bintray'
apply plugin: "com.jfrog.artifactory"
apply from: 'gradle/publishing.gradle'
apply plugin: 'org.ajoberstar.github-pages'
apply from: 'gradle/coverage.gradle'
apply from: 'gradle/documentation.gradle'
tasks.withType(JavaCompile) {
sourceCompatibility = "1.7"
@@ -50,102 +45,20 @@ dependencies {
testCompile 'org.asciidoctor:asciidoctorj:1.5.4'
testCompile 'ch.qos.logback:logback-classic:1.1.2'
testCompile 'org.assertj:assertj-core:2.2.0'
testCompile 'com.sksamuel.diff:diff:1.1.11'
testCompile 'io.github.robwin:assertj-diff:0.1.1'
}
task sourcesJar(type: Jar, dependsOn: classes) {
classifier = 'sources'
from sourceSets.main.allSource
}
task javadocJar(type: Jar, dependsOn: javadoc) {
classifier = 'javadoc'
from javadoc.destinationDir
}
artifacts {
archives sourcesJar
archives javadocJar
}
ext {
generatedDocumentation = file('build/docs/asciidoc/generated')
}
asciidoctor {
sources {
include 'index.adoc'
test {
if (System.properties['http.proxyHost']) {
systemProperty 'http.proxyHost', System.properties['http.proxyHost']
systemProperty 'http.proxyPort', System.properties['http.proxyPort']
systemProperty 'http.nonProxyHosts', System.properties['http.nonProxyHosts']
}
backends = ['html5', 'pdf']
attributes = [
doctype: 'book',
toc: 'left',
toclevels: '3',
numbered: '',
sectlinks: '',
sectanchors: '',
hardbreaks: '',
generated: generatedDocumentation
]
systemProperty 'file.encoding', 'UTF-8'
ignoreFailures = true
}
artifactory {
contextUrl = 'https://oss.jfrog.org'
resolve {
repository {
repoKey = 'libs-release'
}
}
publish {
repository {
repoKey = 'oss-snapshot-local' //The Artifactory repository key to publish to
//when using oss.jfrog.org the credentials are from Bintray. For local build we expect them to be found in
//~/.gradle/gradle.properties, otherwise to be set in the build server
username = project.hasProperty('bintrayUsername') ? project.bintrayUsername : System.getenv('BINTRAY_USER')
password = project.hasProperty('bintrayApiKey') ? project.bintrayApiKey : System.getenv('BINTRAY_KEY')
}
defaults {
publications('mavenJava')
}
}
if (System.properties['https.proxyHost']) {
clientConfig.proxy.host = System.properties['https.proxyHost']
clientConfig.proxy.port = System.properties['https.proxyPort'].toInteger()
}
}
jacocoTestReport {
reports {
xml.enabled = true // coveralls plugin depends on xml format report
html.enabled = true
}
}
tasks.coveralls {
dependsOn 'check'
}
tasks.artifactoryPublish {
dependsOn 'check'
}
publishGhPages.dependsOn asciidoctor
githubPages {
repoUri = 'https://github.com/Swagger2Markup/swagger2markup.git'
credentials {
username = project.hasProperty('githubUser') ? project.githubUser : System.getenv('GITHUB_USER')
password = project.hasProperty('githubPassword') ? project.githubPassword : System.getenv('GITHUB_PASSWORD')
}
pages {
from file(asciidoctor.outputDir.path + '/html5')
into project.version
}
}
task wrapper(type: Wrapper) {
gradleVersion = '2.10'
gradleVersion = '2.11'
}

13
gradle/coverage.gradle Normal file
View File

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

View File

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

View File

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

View File

@@ -1,764 +0,0 @@
/*
* Copyright 2016 Robert Winkler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.robwin.swagger2markup;
import com.google.common.base.Function;
import com.google.common.collect.Ordering;
import io.github.robwin.markup.builder.LineSeparator;
import io.github.robwin.markup.builder.MarkupLanguage;
import io.github.robwin.swagger2markup.internal.model.PathOperation;
import io.github.robwin.swagger2markup.internal.utils.IOUtils;
import io.swagger.models.HttpMethod;
import io.swagger.models.parameters.Parameter;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.nio.file.Path;
import java.util.Comparator;
import java.util.Properties;
public class Swagger2MarkupConfig {
private static final Logger logger = LoggerFactory.getLogger(Swagger2MarkupConfig.class);
private MarkupLanguage markupLanguage;
private boolean generatedExamplesEnabled;
private boolean operationDescriptionsEnabled;
private URI operationDescriptionsUri;
private boolean definitionDescriptionsEnabled;
private URI definitionDescriptionsUri;
private boolean separatedDefinitionsEnabled;
private boolean separatedOperationsEnabled;
private GroupBy operationsGroupedBy;
private Language outputLanguage;
private int inlineSchemaDepthLevel;
private OrderBy tagOrderBy;
private Comparator<String> tagOrdering;
private OrderBy operationOrderBy;
private Comparator<PathOperation> operationOrdering;
private OrderBy definitionOrderBy;
private Comparator<String> definitionOrdering;
private OrderBy parameterOrderBy;
private Comparator<Parameter> parameterOrdering;
private OrderBy propertyOrderBy;
private Comparator<String> propertyOrdering;
private OrderBy responseOrderBy;
private Comparator<String> responseOrdering;
private boolean interDocumentCrossReferencesEnabled;
private String interDocumentCrossReferencesPrefix;
private boolean flatBodyEnabled;
private String anchorPrefix;
private LineSeparator lineSeparator;
private String overviewDocument;
private String pathsDocument;
private String definitionsDocument;
private String securityDocument;
private String separatedOperationsFolder;
private String separatedDefinitionsFolder;
public static Builder ofDefaults() {
return new Builder();
}
public static Builder ofProperties(Properties properties) {
return new Builder(properties);
}
/**
* Global context lazy initialization
*
* @param globalContext Partially initialized global context (globalContext.extensionRegistry == null)
*/
public void setGlobalContext(Swagger2MarkupConverter.Context globalContext) {
configureDefaultContentPaths(globalContext.getSwaggerLocation());
}
/**
* Automatically set default path for external content files based on specified {@code swaggerLocation}.<br/>
* If {@code swaggerLocation} is null, default path can't be set and features are disabled.<br/>
* Paths have to be explicitly set when swaggerLocation.scheme != 'file' to limit the number of URL requests.
*
* @param swaggerLocation base path to set default paths
* @throws RuntimeException if basePath == null and any path is not configured
*/
private void configureDefaultContentPaths(URI swaggerLocation) {
URI baseURI = null;
if (swaggerLocation != null) {
if (swaggerLocation.getScheme().equals("file"))
baseURI = IOUtils.uriParent(swaggerLocation);
}
if (operationDescriptionsEnabled && operationDescriptionsUri == null) {
if (baseURI == null) {
if (logger.isWarnEnabled())
logger.warn("Disable {} > No explicit '{}' set and no default available > Disable {}", "operationDescriptionsEnabled", "operationDescriptionsUri");
operationDescriptionsEnabled = false;
} else
operationDescriptionsUri = baseURI;
}
if (definitionDescriptionsEnabled && definitionDescriptionsUri == null) {
if (baseURI == null) {
if (logger.isWarnEnabled())
logger.warn("Disable {} > No explicit '{}' set and no default available > Disable {}", "definitionDescriptionsEnabled", "definitionDescriptionsUri");
definitionDescriptionsEnabled = false;
} else
definitionDescriptionsUri = baseURI;
}
}
public MarkupLanguage getMarkupLanguage() {
return markupLanguage;
}
public boolean isGeneratedExamplesEnabled() {
return generatedExamplesEnabled;
}
public boolean isOperationDescriptionsEnabled() {
return operationDescriptionsEnabled;
}
public URI getOperationDescriptionsUri() {
return operationDescriptionsUri;
}
public boolean isDefinitionDescriptionsEnabled() {
return definitionDescriptionsEnabled;
}
public URI getDefinitionDescriptionsUri() {
return definitionDescriptionsUri;
}
public boolean isSeparatedDefinitionsEnabled() {
return separatedDefinitionsEnabled;
}
public boolean isSeparatedOperationsEnabled() {
return separatedOperationsEnabled;
}
public GroupBy getOperationsGroupedBy() {
return operationsGroupedBy;
}
public Language getOutputLanguage() {
return outputLanguage;
}
public int getInlineSchemaDepthLevel() {
return inlineSchemaDepthLevel;
}
public OrderBy getTagOrderBy() {
return tagOrderBy;
}
public Comparator<String> getTagOrdering() {
return tagOrdering;
}
public OrderBy getOperationOrderBy() {
return operationOrderBy;
}
public Comparator<PathOperation> getOperationOrdering() {
return operationOrdering;
}
public OrderBy getDefinitionOrderBy() {
return definitionOrderBy;
}
public Comparator<String> getDefinitionOrdering() {
return definitionOrdering;
}
public OrderBy getParameterOrderBy() {
return parameterOrderBy;
}
public Comparator<Parameter> getParameterOrdering() {
return parameterOrdering;
}
public OrderBy getPropertyOrderBy() {
return propertyOrderBy;
}
public Comparator<String> getPropertyOrdering() {
return propertyOrdering;
}
public OrderBy getResponseOrderBy() {
return responseOrderBy;
}
public Comparator<String> getResponseOrdering() {
return responseOrdering;
}
public boolean isInterDocumentCrossReferencesEnabled() {
return interDocumentCrossReferencesEnabled;
}
public String getInterDocumentCrossReferencesPrefix() {
return interDocumentCrossReferencesPrefix;
}
public boolean isFlatBodyEnabled() {
return flatBodyEnabled;
}
public String getAnchorPrefix() {
return anchorPrefix;
}
public String getOverviewDocument() {
return overviewDocument;
}
public String getPathsDocument() {
return pathsDocument;
}
public String getDefinitionsDocument() {
return definitionsDocument;
}
public String getSecurityDocument() {
return securityDocument;
}
public String getSeparatedOperationsFolder() {
return separatedOperationsFolder;
}
public String getSeparatedDefinitionsFolder() {
return separatedDefinitionsFolder;
}
public LineSeparator getLineSeparator() {
return lineSeparator;
}
public static class Builder {
private static final String PROPERTIES_PREFIX = "swagger2markup.";
private static final String PROPERTIES_DEFAULT = "/io/github/robwin/swagger2markup/config/default.properties";
static final Ordering<PathOperation> OPERATION_METHOD_NATURAL_ORDERING = Ordering
.explicit(HttpMethod.POST, HttpMethod.GET, HttpMethod.PUT, HttpMethod.DELETE, HttpMethod.PATCH, HttpMethod.HEAD, HttpMethod.OPTIONS)
.onResultOf(new Function<PathOperation, HttpMethod>() {
public HttpMethod apply(PathOperation operation) {
return operation.getMethod();
}
});
static final Ordering<PathOperation> OPERATION_PATH_NATURAL_ORDERING = Ordering
.natural()
.onResultOf(new Function<PathOperation, String>() {
public String apply(PathOperation operation) {
return operation.getPath();
}
});
static final Ordering<Parameter> PARAMETER_IN_NATURAL_ORDERING = Ordering
.explicit("header", "path", "query", "formData", "body")
.onResultOf(new Function<Parameter, String>() {
public String apply(Parameter parameter) {
return parameter.getIn();
}
});
static final Ordering<Parameter> PARAMETER_NAME_NATURAL_ORDERING = Ordering
.natural()
.onResultOf(new Function<Parameter, String>() {
public String apply(Parameter parameter) {
return parameter.getName();
}
});
Swagger2MarkupConfig config = new Swagger2MarkupConfig();
Builder() {
this(new Properties());
}
Builder(Properties properties) {
Properties safeProperties = new Properties(defaultProperties());
safeProperties.putAll(properties);
config.markupLanguage = MarkupLanguage.valueOf(safeProperties.getProperty(PROPERTIES_PREFIX + "markupLanguage"));
config.generatedExamplesEnabled = Boolean.valueOf(safeProperties.getProperty(PROPERTIES_PREFIX + "generatedExamplesEnabled"));
config.operationDescriptionsEnabled = Boolean.valueOf(safeProperties.getProperty(PROPERTIES_PREFIX + "operationDescriptionsEnabled"));
if (safeProperties.containsKey(PROPERTIES_PREFIX + "operationDescriptionsUri"))
config.operationDescriptionsUri = URI.create(safeProperties.getProperty(PROPERTIES_PREFIX + "operationDescriptionsUri"));
config.definitionDescriptionsEnabled = Boolean.valueOf(safeProperties.getProperty(PROPERTIES_PREFIX + "definitionDescriptionsEnabled"));
if (safeProperties.containsKey(PROPERTIES_PREFIX + "definitionDescriptionsUri"))
config.definitionDescriptionsUri = URI.create(safeProperties.getProperty(PROPERTIES_PREFIX + "definitionDescriptionsUri"));
config.separatedDefinitionsEnabled = Boolean.valueOf(safeProperties.getProperty(PROPERTIES_PREFIX + "separatedDefinitionsEnabled"));
config.separatedOperationsEnabled = Boolean.valueOf(safeProperties.getProperty(PROPERTIES_PREFIX + "separatedOperationsEnabled"));
config.operationsGroupedBy = GroupBy.valueOf(safeProperties.getProperty(PROPERTIES_PREFIX + "operationsGroupedBy"));
config.outputLanguage = Language.valueOf(safeProperties.getProperty(PROPERTIES_PREFIX + "outputLanguage"));
config.inlineSchemaDepthLevel = Integer.valueOf(safeProperties.getProperty(PROPERTIES_PREFIX + "inlineSchemaDepthLevel"));
config.interDocumentCrossReferencesEnabled = Boolean.valueOf(safeProperties.getProperty(PROPERTIES_PREFIX + "interDocumentCrossReferencesEnabled"));
config.interDocumentCrossReferencesPrefix = safeProperties.getProperty(PROPERTIES_PREFIX + "interDocumentCrossReferencesPrefix");
config.flatBodyEnabled = Boolean.valueOf(safeProperties.getProperty(PROPERTIES_PREFIX + "flatBodyEnabled"));
config.anchorPrefix = safeProperties.getProperty(PROPERTIES_PREFIX + "anchorPrefix");
config.overviewDocument = safeProperties.getProperty(PROPERTIES_PREFIX + "overviewDocument");
config.pathsDocument = safeProperties.getProperty(PROPERTIES_PREFIX + "pathsDocument");
config.definitionsDocument = safeProperties.getProperty(PROPERTIES_PREFIX + "definitionsDocument");
config.securityDocument = safeProperties.getProperty(PROPERTIES_PREFIX + "securityDocument");
config.separatedOperationsFolder = safeProperties.getProperty(PROPERTIES_PREFIX + "separatedOperationsFolder");
config.separatedDefinitionsFolder = safeProperties.getProperty(PROPERTIES_PREFIX + "separatedDefinitionsFolder");
config.tagOrderBy = OrderBy.valueOf(safeProperties.getProperty(PROPERTIES_PREFIX + "tagOrderBy"));
config.operationOrderBy = OrderBy.valueOf(safeProperties.getProperty(PROPERTIES_PREFIX + "operationOrderBy"));
config.definitionOrderBy = OrderBy.valueOf(safeProperties.getProperty(PROPERTIES_PREFIX + "definitionOrderBy"));
config.parameterOrderBy = OrderBy.valueOf(safeProperties.getProperty(PROPERTIES_PREFIX + "parameterOrderBy"));
config.propertyOrderBy = OrderBy.valueOf(safeProperties.getProperty(PROPERTIES_PREFIX + "propertyOrderBy"));
config.responseOrderBy = OrderBy.valueOf(safeProperties.getProperty(PROPERTIES_PREFIX + "responseOrderBy"));
String lineSeparator = safeProperties.getProperty(PROPERTIES_PREFIX + "lineSeparator");
if(StringUtils.isNoneBlank(lineSeparator)){
config.lineSeparator = LineSeparator.valueOf(lineSeparator);
}
}
private Properties defaultProperties() {
Properties defaultProperties = new Properties();
try {
InputStream defaultPropertiesStream = Swagger2MarkupConfig.class.getResourceAsStream(PROPERTIES_DEFAULT);
if (defaultPropertiesStream == null)
throw new RuntimeException(String.format("Can't load default properties '%s'", PROPERTIES_DEFAULT));
defaultProperties.load(defaultPropertiesStream);
} catch (IOException e) {
throw new RuntimeException(String.format("Can't load default properties '%s'", PROPERTIES_DEFAULT), e);
}
return defaultProperties;
}
public Swagger2MarkupConfig build() {
buildNaturalOrdering();
return config;
}
private void buildNaturalOrdering() {
if (config.tagOrderBy == OrderBy.NATURAL)
config.tagOrdering = Ordering.natural();
if (config.operationOrderBy == OrderBy.NATURAL)
config.operationOrdering = OPERATION_PATH_NATURAL_ORDERING.compound(OPERATION_METHOD_NATURAL_ORDERING);
if (config.definitionOrderBy == OrderBy.NATURAL)
config.definitionOrdering = Ordering.natural();
if (config.parameterOrderBy == OrderBy.NATURAL)
config.parameterOrdering = PARAMETER_IN_NATURAL_ORDERING.compound(PARAMETER_NAME_NATURAL_ORDERING);
if (config.propertyOrderBy == OrderBy.NATURAL)
config.propertyOrdering = Ordering.natural();
if (config.responseOrderBy == OrderBy.NATURAL)
config.responseOrdering = Ordering.natural();
}
/**
* Specifies the markup language which should be used to generate the files
*
* @param markupLanguage the markup language which is used to generate the files
* @return this builder
*/
public Builder withMarkupLanguage(MarkupLanguage markupLanguage) {
Validate.notNull(markupLanguage, "%s must not be null", "markupLanguage");
config.markupLanguage = markupLanguage;
return this;
}
/**
* Include generated examples into the Paths document
*
* @return this builder
*/
public Builder withGeneratedExamples() {
config.generatedExamplesEnabled = true;
return this;
}
/**
* Include hand-written descriptions into the Paths document
*
* @param operationDescriptionsUri the URI to the folder where the description documents reside.
* @return this builder
*/
public Builder withOperationDescriptions(URI operationDescriptionsUri) {
Validate.notNull(operationDescriptionsUri, "%s must not be null", "operationDescriptionsUri");
config.operationDescriptionsEnabled = true;
config.operationDescriptionsUri = operationDescriptionsUri;
return this;
}
/**
* Include hand-written descriptions into the Paths document
*
* @param operationDescriptionsPath the path to the folder where the description documents reside.
* @return this builder
*/
public Builder withOperationDescriptions(Path operationDescriptionsPath) {
Validate.notNull(operationDescriptionsPath, "%s must not be null", "operationDescriptionsPath");
return withOperationDescriptions(operationDescriptionsPath.toUri());
}
/**
* Include hand-written descriptions into the Paths document.<br/>
* Use default URI.
*
* @return this builder
*/
public Builder withOperationDescriptions() {
config.operationDescriptionsEnabled = true;
return this;
}
/**
* Include hand-written descriptions into the Definitions document
*
* @param definitionDescriptionsUri the URI to the folder where the description documents reside.
* @return this builder
*/
public Builder withDefinitionDescriptions(URI definitionDescriptionsUri) {
Validate.notNull(definitionDescriptionsUri, "%s must not be null", "definitionDescriptionsUri");
config.definitionDescriptionsEnabled = true;
config.definitionDescriptionsUri = definitionDescriptionsUri;
return this;
}
/**
* Include hand-written descriptions into the Definitions document
*
* @param definitionDescriptionsPath the path to the folder where the description documents reside.
* @return this builder
*/
public Builder withDefinitionDescriptions(Path definitionDescriptionsPath) {
Validate.notNull(definitionDescriptionsPath, "%s must not be null", "definitionDescriptionsPath");
return withDefinitionDescriptions(definitionDescriptionsPath.toUri());
}
/**
* Include hand-written descriptions into the Definitions document.<br/>
* Use default URI.
*
* @return this builder
*/
public Builder withDefinitionDescriptions() {
config.definitionDescriptionsEnabled = true;
return this;
}
/**
* In addition to the definitions file, also create separate definition files for each model definition.
*
* @return this builder
*/
public Builder withSeparatedDefinitions() {
config.separatedDefinitionsEnabled = true;
return this;
}
/**
* In addition to the paths file, also create separate path files for each path.
*
* @return this builder
*/
public Builder withSeparatedOperations() {
config.separatedOperationsEnabled = true;
return this;
}
/**
* Specifies if the paths should be grouped by tags or stay as-is.
*
* @param pathsGroupedBy the GroupBy enum
* @return this builder
*/
public Builder withPathsGroupedBy(GroupBy pathsGroupedBy) {
Validate.notNull(pathsGroupedBy, "%s must not be null", "pathsGroupedBy");
config.operationsGroupedBy = pathsGroupedBy;
return this;
}
/**
* Specifies labels language of output files
*
* @param language the enum
* @return this builder
*/
public Builder withOutputLanguage(Language language) {
Validate.notNull(language, "%s must not be null", "language");
config.outputLanguage = language;
return this;
}
/**
* Specifies maximum depth level for inline object schema displaying (0 = no inline schemasEnabled)
*
* @param inlineSchemaDepthLevel number of recursion levels for inline schemasEnabled display
* @return this builder
*/
public Builder withInlineSchemaDepthLevel(int inlineSchemaDepthLevel) {
Validate.isTrue(inlineSchemaDepthLevel >= 0, "%s must be >= 0", "inlineSchemaDepthLevel");
config.inlineSchemaDepthLevel = inlineSchemaDepthLevel;
return this;
}
/**
* Specifies tag ordering.<br/>
* By default tag ordering == {@link io.github.robwin.swagger2markup.OrderBy#NATURAL}.<br/>
* Use {@link #withTagOrdering(Comparator)} to set a custom ordering.
*
* @param orderBy tag ordering
* @return this builder
*/
public Builder withTagOrdering(OrderBy orderBy) {
Validate.notNull(orderBy, "%s must not be null", "orderBy");
Validate.isTrue(orderBy != OrderBy.CUSTOM, "You must provide a custom comparator if orderBy == OrderBy.CUSTOM");
config.tagOrderBy = orderBy;
return this;
}
/**
* Specifies a custom comparator function to order tags.
*
* @param tagOrdering tag ordering
* @return this builder
*/
public Builder withTagOrdering(Comparator<String> tagOrdering) {
Validate.notNull(tagOrdering, "%s must not be null", "tagOrdering");
config.tagOrderBy = OrderBy.CUSTOM;
config.tagOrdering = tagOrdering;
return this;
}
/**
* Specifies operation ordering.<br/>
* By default operation ordering == {@link io.github.robwin.swagger2markup.OrderBy#AS_IS}.<br/>
* Use {@link #withOperationOrdering(Comparator)} to set a custom ordering.
*
* @param orderBy operation ordering
* @return this builder
*/
public Builder withOperationOrdering(OrderBy orderBy) {
Validate.notNull(orderBy, "%s must not be null", "orderBy");
Validate.isTrue(orderBy != OrderBy.CUSTOM, "You must provide a custom comparator if orderBy == OrderBy.CUSTOM");
config.operationOrderBy = orderBy;
return this;
}
/**
* Specifies a custom comparator function to order operations.
*
* @param operationOrdering operation ordering
* @return this builder
*/
public Builder withOperationOrdering(Comparator<PathOperation> operationOrdering) {
Validate.notNull(operationOrdering, "%s must not be null", "operationOrdering");
config.operationOrderBy = OrderBy.CUSTOM;
config.operationOrdering = operationOrdering;
return this;
}
/**
* Specifies definition ordering.<br/>
* By default definition ordering == {@link io.github.robwin.swagger2markup.OrderBy#NATURAL}.<br/>
* Use {@link #withDefinitionOrdering(Comparator)} to set a custom ordering.
*
* @param orderBy definition ordering
* @return this builder
*/
public Builder withDefinitionOrdering(OrderBy orderBy) {
Validate.notNull(orderBy, "%s must not be null", "orderBy");
Validate.isTrue(orderBy != OrderBy.CUSTOM, "You must provide a custom comparator if orderBy == OrderBy.CUSTOM");
config.definitionOrderBy = orderBy;
return this;
}
/**
* Specifies a custom comparator function to order definitions.
*
* @param definitionOrdering definition ordering
* @return this builder
*/
public Builder withDefinitionOrdering(Comparator<String> definitionOrdering) {
Validate.notNull(definitionOrdering, "%s must not be null", "definitionOrdering");
config.definitionOrderBy = OrderBy.CUSTOM;
config.definitionOrdering = definitionOrdering;
return this;
}
/**
* Specifies parameter ordering.<br/>
* By default parameter ordering == {@link io.github.robwin.swagger2markup.OrderBy#NATURAL}.<br/>
* Use {@link #withParameterOrdering(Comparator)} to set a custom ordering.
*
* @param orderBy parameter ordering
* @return this builder
*/
public Builder withParameterOrdering(OrderBy orderBy) {
Validate.notNull(orderBy, "%s must not be null", "orderBy");
Validate.isTrue(orderBy != OrderBy.CUSTOM, "You must provide a custom comparator if orderBy == OrderBy.CUSTOM");
config.parameterOrderBy = orderBy;
return this;
}
/**
* Specifies a custom comparator function to order parameters.
*
* @param parameterOrdering parameter ordering
* @return this builder
*/
public Builder withParameterOrdering(Comparator<Parameter> parameterOrdering) {
Validate.notNull(parameterOrdering, "%s must not be null", "parameterOrdering");
config.parameterOrderBy = OrderBy.CUSTOM;
config.parameterOrdering = parameterOrdering;
return this;
}
/**
* Specifies property ordering.<br/>
* By default property ordering == {@link io.github.robwin.swagger2markup.OrderBy#NATURAL}.<br/>
* Use {@link #withPropertyOrdering(Comparator)} to set a custom ordering.
*
* @param orderBy property ordering
* @return this builder
*/
public Builder withPropertyOrdering(OrderBy orderBy) {
Validate.notNull(orderBy, "%s must not be null", "orderBy");
Validate.isTrue(orderBy != OrderBy.CUSTOM, "You must provide a custom comparator if orderBy == OrderBy.CUSTOM");
config.propertyOrderBy = orderBy;
return this;
}
/**
* Specifies a custom comparator function to order propertys.
*
* @param propertyOrdering property ordering
* @return this builder
*/
public Builder withPropertyOrdering(Comparator<String> propertyOrdering) {
Validate.notNull(propertyOrdering, "%s must not be null", "propertyOrdering");
config.propertyOrderBy = OrderBy.CUSTOM;
config.propertyOrdering = propertyOrdering;
return this;
}
/**
* Specifies response ordering.<br/>
* By default response ordering == {@link io.github.robwin.swagger2markup.OrderBy#NATURAL}.<br/>
* Use {@link #withResponseOrdering(Comparator)} to set a custom ordering.
*
* @param orderBy response ordering
* @return this builder
*/
public Builder withResponseOrdering(OrderBy orderBy) {
Validate.notNull(orderBy, "%s must not be null", "orderBy");
Validate.isTrue(orderBy != OrderBy.CUSTOM, "You must provide a custom comparator if orderBy == OrderBy.CUSTOM");
config.responseOrderBy = orderBy;
return this;
}
/**
* Specifies a custom comparator function to order responses.
*
* @param responseOrdering response ordering
* @return this builder
*/
public Builder withResponseOrdering(Comparator<String> responseOrdering) {
Validate.notNull(responseOrdering, "%s must not be null", "responseOrdering");
config.responseOrderBy = OrderBy.CUSTOM;
config.responseOrdering = responseOrdering;
return this;
}
/**
* Enable use of inter-document cross-references when needed
*
* @param prefix Prefix to document in all inter-document cross-references.
* @return this builder
*/
public Builder withInterDocumentCrossReferences(String prefix) {
Validate.notNull(prefix, "%s must not be null", "prefix");
config.interDocumentCrossReferencesEnabled = true;
config.interDocumentCrossReferencesPrefix = prefix;
return this;
}
/**
* Enable use of inter-document cross-references when needed.
*
* @return this builder
*/
public Builder withInterDocumentCrossReferences() {
config.interDocumentCrossReferencesEnabled = true;
return this;
}
/**
* Optionally isolate the body parameter, if any, from other parameters
*
* @return this builder
*/
public Builder withFlatBody() {
config.flatBodyEnabled = true;
return this;
}
/**
* Optionally prefix all anchors for unicity
*.
* @param anchorPrefix anchor prefix.
* @return this builder
*/
public Builder withAnchorPrefix(String anchorPrefix) {
Validate.notNull(anchorPrefix, "%s must no be null", "anchorPrefix");
config.anchorPrefix = anchorPrefix;
return this;
}
/**
* Specifies the line separator which should be used .
*
* @param lineSeparator the lineSeparator
* @return this builder
*/
public Builder withLineSeparator(LineSeparator lineSeparator) {
Validate.notNull(lineSeparator, "%s must no be null", "lineSeparator");
config.lineSeparator = lineSeparator;
return this;
}
}
}

View File

@@ -1,112 +0,0 @@
/*
* Copyright 2016 Robert Winkler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.robwin.swagger2markup;
import com.google.common.collect.Multimap;
import com.google.common.collect.MultimapBuilder;
import io.github.robwin.swagger2markup.internal.extensions.DynamicDefinitionsDocumentExtension;
import io.github.robwin.swagger2markup.internal.extensions.DynamicPathsDocumentExtension;
import io.github.robwin.swagger2markup.internal.extensions.DynamicOverviewDocumentExtension;
import io.github.robwin.swagger2markup.internal.extensions.DynamicSecurityDocumentExtension;
import io.github.robwin.swagger2markup.spi.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
public class Swagger2MarkupExtensionRegistry {
protected static final List<Class<? extends Extension>> EXTENSION_POINTS = Arrays.<Class<? extends Extension>>asList(
SwaggerModelExtension.class,
OverviewDocumentExtension.class,
SecurityDocumentExtension.class,
DefinitionsDocumentExtension.class,
PathsDocumentExtension.class
);
protected final Multimap<Class<? extends Extension>, Extension> extensions;
public Swagger2MarkupExtensionRegistry(Multimap<Class<? extends Extension>, Extension> extensions) {
this.extensions = extensions;
}
public static Builder ofEmpty() {
return new Builder(false);
}
public static Builder ofDefaults() {
return new Builder(true);
}
public static class Builder {
private final Multimap<Class<? extends Extension>, Extension> extensions;
Builder(boolean useDefaults) {
extensions = MultimapBuilder.hashKeys().arrayListValues().build();
if (useDefaults) {
withExtension(new DynamicOverviewDocumentExtension());
withExtension(new DynamicSecurityDocumentExtension());
withExtension(new DynamicPathsDocumentExtension());
withExtension(new DynamicDefinitionsDocumentExtension());
}
}
public Swagger2MarkupExtensionRegistry build() {
return new Swagger2MarkupExtensionRegistry(extensions);
}
public Builder withExtension(Extension extension) {
registerExtension(extension);
return this;
}
public void registerExtension(Extension extension) {
for (Class<? extends Extension> extensionPoint : EXTENSION_POINTS) {
if (extensionPoint.isInstance(extension)) {
extensions.put(extensionPoint, extension);
return;
}
}
throw new IllegalArgumentException("Provided extension class does not extend any of the supported extension points");
}
}
@SuppressWarnings(value = "unchecked")
public <T extends Extension> List<T> getExtensions(Class<T> extensionClass) {
List<T> ret = new ArrayList<>();
for (Map.Entry<Class<? extends Extension>, Extension> entry : extensions.entries()) {
if (extensionClass.isAssignableFrom(entry.getKey())) {
if (extensionClass.isInstance(entry.getValue()))
ret.add((T) entry.getValue());
}
}
return ret;
}
/**
* Get all extensions
* @return all extensions
*/
public List<Extension> getExtensions() {
return getExtensions(Extension.class);
}
}

View File

@@ -1,98 +0,0 @@
/*
* Copyright 2016 Robert Winkler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.robwin.swagger2markup.internal.extensions;
import com.google.common.base.Optional;
import io.github.robwin.swagger2markup.Swagger2MarkupConverter;
import io.github.robwin.swagger2markup.spi.ContentContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.net.URI;
import java.nio.file.Files;
import java.nio.file.Path;
class ContentExtension {
private static final Logger logger = LoggerFactory.getLogger(ContentExtension.class);
protected final Swagger2MarkupConverter.Context globalContext;
protected final ContentContext contentContext;
ContentExtension(Swagger2MarkupConverter.Context globalContext, ContentContext contentContext) {
this.globalContext = globalContext;
this.contentContext = contentContext;
}
/**
* Reads contents from a file
*
* @param contentPath content file path
* @return content reader
*/
protected Optional<Reader> readContentPath(Path contentPath) {
if (Files.isReadable(contentPath)) {
if (logger.isInfoEnabled()) {
logger.info("Content file {} processed", contentPath);
}
try {
Reader contentReader = new FileReader(contentPath.toFile());
return Optional.of(contentReader);
} catch (IOException e) {
if (logger.isWarnEnabled()) {
logger.warn("Failed to read content file {} > {}", contentPath, e.getMessage());
}
}
} else {
if (logger.isDebugEnabled()) {
logger.debug("Failed to read content file {}", contentPath);
}
}
return Optional.absent();
}
/**
* Reads content from an Uri
*
* @param contentUri content file URI
* @return content reader
*/
protected Optional<Reader> readContentUri(URI contentUri) {
try {
Reader reader = io.github.robwin.swagger2markup.internal.utils.IOUtils.uriReader(contentUri);
if (logger.isInfoEnabled()) {
logger.info("Content URI {} processed", contentUri);
}
return Optional.of(reader);
} catch (IOException e) {
if (logger.isDebugEnabled()) {
logger.debug("Failed to read content URI {} > {}", contentUri, e.getMessage());
}
}
return Optional.absent();
}
}

View File

@@ -1,97 +0,0 @@
/*
* Copyright 2016 Robert Winkler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.robwin.swagger2markup.internal.extensions;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.collect.Collections2;
import com.google.common.collect.Lists;
import com.google.common.collect.Ordering;
import io.github.robwin.swagger2markup.Swagger2MarkupConverter;
import io.github.robwin.swagger2markup.spi.ContentContext;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.Reader;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
class DynamicContentExtension extends ContentExtension {
private static final Logger logger = LoggerFactory.getLogger(DynamicContentExtension.class);
DynamicContentExtension(Swagger2MarkupConverter.Context globalContext, ContentContext contentContext) {
super(globalContext, contentContext);
}
/**
* Builds extension sections
*
* @param contentPath the path where the content files reside
* @param prefix extension file prefix
* @param levelOffset import markup level offset
*/
public void extensionsSection(Path contentPath, final String prefix, int levelOffset) {
final Collection<String> filenameExtensions = Collections2.transform(globalContext.getConfig().getMarkupLanguage().getFileNameExtensions(), new Function<String, String>() {
public String apply(String input) {
return StringUtils.stripStart(input, ".");
}
});
DirectoryStream.Filter<Path> filter = new DirectoryStream.Filter<Path>() {
@Override
public boolean accept(Path entry) throws IOException {
String fileName = entry.getFileName().toString();
return fileName.startsWith(prefix) && FilenameUtils.isExtension(fileName, filenameExtensions);
}
};
try (DirectoryStream<Path> extensionFiles = Files.newDirectoryStream(contentPath, filter)) {
if (extensionFiles != null) {
List<Path> extensions = Lists.newArrayList(extensionFiles);
Collections.sort(extensions, Ordering.natural());
for (Path extension : extensions) {
Optional<Reader> extensionContent = readContentPath(extension);
if (extensionContent.isPresent()) {
try {
contentContext.getMarkupDocBuilder().importMarkup(extensionContent.get(), levelOffset);
} catch (IOException e) {
throw new RuntimeException(String.format("Failed to read extension file %s", extension), e);
} finally {
extensionContent.get().close();
}
}
}
}
} catch (IOException e) {
if (logger.isDebugEnabled())
logger.debug("Failed to read extension files from directory {}", contentPath);
}
}
}

View File

@@ -1,100 +0,0 @@
/*
* Copyright 2016 Robert Winkler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.robwin.swagger2markup.internal.extensions;
import io.github.robwin.swagger2markup.Swagger2MarkupConverter;
import io.github.robwin.swagger2markup.internal.utils.IOUtils;
import io.github.robwin.swagger2markup.spi.DefinitionsDocumentExtension;
import org.apache.commons.lang3.Validate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.nio.file.Path;
import java.nio.file.Paths;
/**
* Dynamically search for markup files in {@code contentPath} to append in Definitions, with the format :<br/>
* - {@code document-before-*.<markup.ext>} : import before Definitions document with levelOffset = 0<br/>
* - {@code document-begin-*.<markup.ext>} : import just after Definitions document main title with levelOffset = 1<br/>
* - {@code document-end-*.<markup.ext>} : import at the end of Definitions document with levelOffset = 1<br/>
* - {@code definition-begin-*.<markup.ext>} : import just after each definition title with levelOffset = 2<br/>
* - {@code definition-end-*.<markup.ext>} : import at the end of each definition with levelOffset = 2<br/>
* <p/>
* Markup files are appended in the natural order of their names, for each category.
*/
public final class DynamicDefinitionsDocumentExtension extends DefinitionsDocumentExtension {
private static final Logger logger = LoggerFactory.getLogger(DynamicDefinitionsDocumentExtension.class);
protected Path contentPath;
public DynamicDefinitionsDocumentExtension(Path contentPath) {
super();
Validate.notNull(contentPath);
this.contentPath = contentPath;
}
public DynamicDefinitionsDocumentExtension() {
super();
}
@Override
public void init(Swagger2MarkupConverter.Context globalContext) {
if (contentPath == null) {
if (globalContext.getSwaggerLocation() == null || !globalContext.getSwaggerLocation().getScheme().equals("file")) {
if (logger.isWarnEnabled())
logger.warn("Disable DynamicDefinitionsContentExtension > Can't set default contentPath from swaggerLocation. You have to explicitly configure the content path.");
} else {
contentPath = Paths.get(globalContext.getSwaggerLocation()).getParent();
}
}
}
@Override
public void apply(Context context) {
Validate.notNull(context);
if (contentPath != null) {
DynamicContentExtension dynamicContent = new DynamicContentExtension(globalContext, context);
DynamicDefinitionsDocumentExtension.Position position = context.getPosition();
switch (position) {
case DOCUMENT_BEFORE:
dynamicContent.extensionsSection(contentPath, contentPrefix(position), levelOffset(context));
break;
case DOCUMENT_BEGIN:
dynamicContent.extensionsSection(contentPath, contentPrefix(position), levelOffset(context));
break;
case DOCUMENT_END:
dynamicContent.extensionsSection(contentPath, contentPrefix(position), levelOffset(context));
break;
case DEFINITION_BEGIN:
dynamicContent.extensionsSection(contentPath.resolve(Paths.get(IOUtils.normalizeName(context.getDefinitionName().get()))), contentPrefix(position), levelOffset(context));
break;
case DEFINITION_END:
dynamicContent.extensionsSection(contentPath.resolve(Paths.get(IOUtils.normalizeName(context.getDefinitionName().get()))), contentPrefix(position), levelOffset(context));
break;
default:
throw new RuntimeException(String.format("Unknown position '%s'", position));
}
}
}
public String contentPrefix(Position position) {
return position.name().toLowerCase().replace('_', '-');
}
}

View File

@@ -1,92 +0,0 @@
/*
* Copyright 2016 Robert Winkler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.robwin.swagger2markup.internal.extensions;
import io.github.robwin.swagger2markup.Swagger2MarkupConverter;
import io.github.robwin.swagger2markup.spi.OverviewDocumentExtension;
import org.apache.commons.lang3.Validate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.nio.file.Path;
import java.nio.file.Paths;
/**
* Dynamically search for markup files in {@code contentPath} to append to Overview, with the format :<br/>
* - {@code document-before-*.<markup.ext>} : import before Overview document with levelOffset = 0<br/>
* - {@code document-begin-*.<markup.ext>} : import just after Overview document main title with levelOffset = 1<br/>
* - {@code document-end-*.<markup.ext>} : import at the end of Overview document with levelOffset = 1<br/>
* <p/>
* Markup files are appended in the natural order of their names, for each category.
*/
public final class DynamicOverviewDocumentExtension extends OverviewDocumentExtension {
private static final Logger logger = LoggerFactory.getLogger(DynamicOverviewDocumentExtension.class);
protected Path contentPath;
public DynamicOverviewDocumentExtension() {
super();
}
public DynamicOverviewDocumentExtension(Path contentPath) {
super();
Validate.notNull(contentPath);
this.contentPath = contentPath;
}
@Override
public void init(Swagger2MarkupConverter.Context globalContext) {
if (contentPath == null) {
if (globalContext.getSwaggerLocation() == null || !globalContext.getSwaggerLocation().getScheme().equals("file")) {
if (logger.isWarnEnabled())
logger.warn("Disable > DynamicOverviewContentExtension > Can't set default contentPath from swaggerLocation. You have to explicitly configure the content path.");
} else {
contentPath = Paths.get(globalContext.getSwaggerLocation()).getParent();
}
}
}
@Override
public void apply(Context context) {
Validate.notNull(context);
if (contentPath != null) {
DynamicContentExtension dynamicContent = new DynamicContentExtension(globalContext, context);
OverviewDocumentExtension.Position position = context.getPosition();
switch (position) {
case DOCUMENT_BEFORE:
dynamicContent.extensionsSection(contentPath, contentPrefix(position), levelOffset(context));
break;
case DOCUMENT_BEGIN:
dynamicContent.extensionsSection(contentPath, contentPrefix(position), levelOffset(context));
break;
case DOCUMENT_END:
dynamicContent.extensionsSection(contentPath, contentPrefix(position), levelOffset(context));
break;
default:
throw new RuntimeException(String.format("Unknown position '%s'", position));
}
}
}
private String contentPrefix(Position position) {
return position.name().toLowerCase().replace('_', '-');
}
}

View File

@@ -1,101 +0,0 @@
/*
* Copyright 2016 Robert Winkler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.robwin.swagger2markup.internal.extensions;
import io.github.robwin.swagger2markup.Swagger2MarkupConverter;
import io.github.robwin.swagger2markup.internal.utils.IOUtils;
import io.github.robwin.swagger2markup.spi.PathsDocumentExtension;
import org.apache.commons.lang3.Validate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.nio.file.Path;
import java.nio.file.Paths;
/**
* Dynamically search for markup files in {@code contentPath} to append to Operations, with the format :<br/>
* - {@code document-before-*.<markup.ext>} : import before Paths document with levelOffset = 0<br/>
* - {@code document-begin-*.<markup.ext>} : import just after Paths document main title with levelOffset = 1<br/>
* - {@code document-end-*.<markup.ext>} : import at the end of Paths document with levelOffset = 1<br/>
* - {@code operation-begin-*.<markup.ext>} : import just after each operation title with levelOffset = 2(GroupBy.AS_IS) | 3(GroupBy.TAGS)<br/>
* - {@code operation-end-*.<markup.ext>} : import at the end of each operation with levelOffset = 2(GroupBy.AS_IS) | 3(GroupBy.TAGS)<br/>
* <p/>
* Markup files are appended in the natural order of their names, for each category.
*/
public final class DynamicPathsDocumentExtension extends PathsDocumentExtension {
private static final Logger logger = LoggerFactory.getLogger(DynamicPathsDocumentExtension.class);
protected Path contentPath;
public DynamicPathsDocumentExtension() {
super();
}
public DynamicPathsDocumentExtension(Path contentPath) {
super();
Validate.notNull(contentPath);
this.contentPath = contentPath;
}
@Override
public void init(Swagger2MarkupConverter.Context globalContext) {
if (contentPath == null) {
if (globalContext.getSwaggerLocation() == null || !globalContext.getSwaggerLocation().getScheme().equals("file")) {
if (logger.isWarnEnabled())
logger.warn("Disable DynamicOperationsContentExtension > Can't set default contentPath from swaggerLocation. You have to explicitly configure the content path.");
} else {
contentPath = Paths.get(globalContext.getSwaggerLocation()).getParent();
}
}
}
@Override
public void apply(Context context) {
Validate.notNull(context);
if (contentPath != null) {
DynamicContentExtension dynamicContent = new DynamicContentExtension(globalContext, context);
PathsDocumentExtension.Position position = context.getPosition();
switch (position) {
case DOCUMENT_BEFORE:
dynamicContent.extensionsSection(contentPath, contentPrefix(position), levelOffset(context));
break;
case DOCUMENT_BEGIN:
dynamicContent.extensionsSection(contentPath, contentPrefix(position), levelOffset(context));
break;
case DOCUMENT_END:
dynamicContent.extensionsSection(contentPath, contentPrefix(position), levelOffset(context));
break;
case OPERATION_BEGIN:
dynamicContent.extensionsSection(contentPath.resolve(IOUtils.normalizeName(context.getOperation().get().getId())), contentPrefix(position), levelOffset(context));
break;
case OPERATION_END:
dynamicContent.extensionsSection(contentPath.resolve(IOUtils.normalizeName(context.getOperation().get().getId())), contentPrefix(position), levelOffset(context));
break;
default:
throw new RuntimeException(String.format("Unknown position '%s'", position));
}
}
}
private String contentPrefix(Position position) {
return position.name().toLowerCase().replace('_', '-');
}
}

View File

@@ -1,100 +0,0 @@
/*
* Copyright 2016 Robert Winkler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.robwin.swagger2markup.internal.extensions;
import io.github.robwin.swagger2markup.Swagger2MarkupConverter;
import io.github.robwin.swagger2markup.internal.utils.IOUtils;
import io.github.robwin.swagger2markup.spi.SecurityDocumentExtension;
import org.apache.commons.lang3.Validate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.nio.file.Path;
import java.nio.file.Paths;
/**
* Dynamically search for markup files in {@code contentPath} to append to Overview, with the format :<br/>
* - {@code document-before-*.<markup.ext>} : import before Overview document with levelOffset = 0<br/>
* - {@code document-begin-*.<markup.ext>} : import just after Overview document main title with levelOffset = 1<br/>
* - {@code document-end-*.<markup.ext>} : import at the end of Overview document with levelOffset = 1<br/>
* - {@code definition-begin-*.<markup.ext>} : import just after each definition title with levelOffset = 2<br/>
* - {@code definition-end-*.<markup.ext>} : import at the end of each definition with levelOffset = 2<br/>
* <p/>
* Markup files are appended in the natural order of their names, for each category.
*/
public final class DynamicSecurityDocumentExtension extends SecurityDocumentExtension {
private static final Logger logger = LoggerFactory.getLogger(DynamicSecurityDocumentExtension.class);
protected Path contentPath;
public DynamicSecurityDocumentExtension() {
super();
}
public DynamicSecurityDocumentExtension(Path contentPath) {
super();
Validate.notNull(contentPath);
this.contentPath = contentPath;
}
@Override
public void init(Swagger2MarkupConverter.Context globalContext) {
if (contentPath == null) {
if (globalContext.getSwaggerLocation() == null || !globalContext.getSwaggerLocation().getScheme().equals("file")) {
if (logger.isWarnEnabled())
logger.warn("Disable > DynamicSecurityContentExtension > Can't set default contentPath from swaggerLocation. You have to explicitly configure the content path.");
} else {
contentPath = Paths.get(globalContext.getSwaggerLocation()).getParent();
}
}
}
@Override
public void apply(Context context) {
Validate.notNull(context);
if (contentPath != null) {
DynamicContentExtension dynamicContent = new DynamicContentExtension(globalContext, context);
SecurityDocumentExtension.Position position = context.getPosition();
switch (position) {
case DOCUMENT_BEFORE:
dynamicContent.extensionsSection(contentPath, contentPrefix(position), levelOffset(context));
break;
case DOCUMENT_BEGIN:
dynamicContent.extensionsSection(contentPath, contentPrefix(position), levelOffset(context));
break;
case DOCUMENT_END:
dynamicContent.extensionsSection(contentPath, contentPrefix(position), levelOffset(context));
break;
case DEFINITION_BEGIN:
dynamicContent.extensionsSection(contentPath.resolve(IOUtils.normalizeName(context.getDefinitionName().get())), contentPrefix(position), levelOffset(context));
break;
case DEFINITION_END:
dynamicContent.extensionsSection(contentPath.resolve(IOUtils.normalizeName(context.getDefinitionName().get())), contentPrefix(position), levelOffset(context));
break;
default:
throw new RuntimeException(String.format("Unknown position '%s'", position));
}
}
}
private String contentPrefix(Position position) {
return position.name().toLowerCase().replace('_', '-');
}
}

View File

@@ -1,168 +0,0 @@
/*
* Copyright 2016 Robert Winkler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.robwin.swagger2markup.internal.extensions;
import com.google.common.base.Optional;
import io.github.robwin.swagger2markup.Swagger2MarkupConverter;
import io.github.robwin.swagger2markup.spi.DefinitionsDocumentExtension;
import io.github.robwin.swagger2markup.internal.utils.IOUtils;
import org.apache.commons.lang3.Validate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.Reader;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
/**
* Add external schemas to content.<br/>
* Supported formats are :
* <ul>
* <li>XML Schema (.xsd)</li>
* <li>JSON Schema (.json)</li>
* </ul>
*/
public final class SchemaExtension extends DefinitionsDocumentExtension {
private static final Logger logger = LoggerFactory.getLogger(SchemaExtension.class);
private static final List<SchemaMetadata> DEFAULT_SCHEMAS = new ArrayList<SchemaMetadata>() {{
add(new SchemaMetadata("JSON Schema", "json", "json"));
add(new SchemaMetadata("XML Schema", "xsd", "xml"));
}};
protected List<SchemaMetadata> schemas = new ArrayList<>();
protected URI schemaBaseUri;
public SchemaExtension(URI schemaBaseUri) {
super();
Validate.notNull(schemaBaseUri);
this.schemaBaseUri = schemaBaseUri;
}
public SchemaExtension() {
super();
}
public SchemaExtension withDefaultSchemas() {
schemas.addAll(DEFAULT_SCHEMAS);
return this;
}
public SchemaExtension withSchemas(List<SchemaMetadata> schemas) {
schemas.addAll(schemas);
return this;
}
@Override
public void init(Swagger2MarkupConverter.Context globalContext) {
if (schemaBaseUri == null) {
if (globalContext.getSwaggerLocation() == null) {
if (logger.isWarnEnabled())
logger.warn("Disable SchemaExtension > Can't set default schemaBaseUri from swaggerLocation. You have to explicitly configure the schemaBaseUri.");
} else {
schemaBaseUri = IOUtils.uriParent(globalContext.getSwaggerLocation());
}
}
}
@Override
public void apply(Context context) {
Validate.notNull(context);
if (schemaBaseUri != null) {
switch (context.getPosition()) {
case DOCUMENT_BEFORE:
case DOCUMENT_BEGIN:
case DOCUMENT_END:
case DEFINITION_BEGIN:
break;
case DEFINITION_END:
for (SchemaMetadata schema : DEFAULT_SCHEMAS) {
schemaSection(context, schema, levelOffset(context));
}
break;
default:
throw new RuntimeException(String.format("Unknown position '%s'", context.getPosition()));
}
}
}
/**
* Builds snippet URI for the given {@code definitionName} and {@code schema}.<br/>
* Default implementation use {@code <schemaBaseUri>/normalizeName(<definitionName>)/schema.<schema.extension>}.<br/>
* You can override this method to configure your own folder normalization.
*
* @param context current context
* @param definitionName current definition name
* @return subdirectory normalized name
*/
public URI definitionSchemaUri(Context context, String definitionName, SchemaMetadata schema) {
return schemaBaseUri.resolve(IOUtils.normalizeName(definitionName) + "/").resolve("schema" + (schema.extension != null ? "." + schema.extension : ""));
}
private void schemaSection(Context context, SchemaMetadata schema, int levelOffset) {
ContentExtension contentExtension = new ContentExtension(globalContext, context);
URI schemaUri = definitionSchemaUri(context, context.getDefinitionName().get(), schema);
try {
Optional<Reader> extensionContent = contentExtension.readContentUri(schemaUri);
if (extensionContent.isPresent()) {
try {
context.getMarkupDocBuilder().sectionTitleLevel(1 + levelOffset, schema.title);
context.getMarkupDocBuilder().listing(org.apache.commons.io.IOUtils.toString(extensionContent.get()).trim(), schema.language);
} catch (IOException e) {
throw new RuntimeException(String.format("Failed to read schema URI : %s", schemaUri), e);
} finally {
extensionContent.get().close();
}
}
} catch (IOException e) {
if (logger.isDebugEnabled())
logger.debug("Failed to read schema URI {}", schemaUri);
}
}
public static class SchemaMetadata {
/**
* Schema title
*/
public String title;
/**
* Schema file extension, without dot (e.g.: xsd).<br/>
* Set to null if there's no extension
*/
public String extension;
/**
* Schema content language (e.g.: xml)
*/
public String language;
public SchemaMetadata(String title, String extension, String language) {
this.title = title;
this.extension = extension;
this.language = language;
}
}
}

View File

@@ -1,150 +0,0 @@
/*
* Copyright 2016 Robert Winkler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.robwin.swagger2markup.internal.extensions;
import com.google.common.base.Optional;
import com.google.common.base.Throwables;
import io.github.robwin.swagger2markup.internal.model.PathOperation;
import io.github.robwin.swagger2markup.Swagger2MarkupConverter;
import io.github.robwin.swagger2markup.spi.PathsDocumentExtension;
import io.github.robwin.swagger2markup.internal.utils.IOUtils;
import org.apache.commons.lang3.Validate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.Reader;
import java.net.URI;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* Append Spring Rest docs generated snippets to Operations content.
*/
public final class SpringRestDocsExtension extends PathsDocumentExtension {
private static final Logger logger = LoggerFactory.getLogger(SpringRestDocsExtension.class);
private static final Map<String, String> DEFAULT_SNIPPETS = new LinkedHashMap<String, String>() {{
put("http-request", "HTTP request");
put("http-response", "HTTP response");
put("curl-request", "Curl request");
}};
protected URI snippetBaseUri;
protected Map<String, String> snippets = new LinkedHashMap<>();
/**
* Instantiate extension
* @param snippetBaseUri base URI where are snippets are stored
*/
public SpringRestDocsExtension(URI snippetBaseUri) {
super();
Validate.notNull(snippetBaseUri);
this.snippetBaseUri = snippetBaseUri;
}
public SpringRestDocsExtension() {
super();
}
@Override
public void init(Swagger2MarkupConverter.Context globalContext) {
if (snippetBaseUri == null) {
if (globalContext.getSwaggerLocation() == null) {
if (logger.isWarnEnabled())
logger.warn("Disable SpringRestDocsExtension > Can't set default snippetBaseUri from swaggerLocation. You have to explicitly configure the snippetBaseUri.");
} else {
snippetBaseUri = IOUtils.uriParent(globalContext.getSwaggerLocation());
}
}
}
/**
* Add SpringRestDocs default snippets to list
* @return this instance
*/
public SpringRestDocsExtension withDefaultSnippets() {
snippets.putAll(DEFAULT_SNIPPETS);
return this;
}
/**
* Add an explicit list of snippets to display.
* @param snippets snippets to add. key is snippet name (without extension, e.g.: 'http-request'), value is a custom section title for the snippet.
* @return this instance
*/
public SpringRestDocsExtension withExplicitSnippets(Map<String, String> snippets) {
this.snippets.putAll(snippets);
return this;
}
/**
* Builds snippet URI for the given {@code operation} and {@code snippetName}.<br/>
* Default implementation use {@code <snippetBaseUri>/<normalizeName(<operation id>)>/<snippetName>.<markup ext>}.<br/>
* You can override this method to configure your own folder normalization.
*
* @param context current context
* @param operation current operation
* @return subdirectory normalized name
*/
public URI operationSnippetUri(Context context, PathOperation operation, String snippetName) {
return snippetBaseUri.resolve(IOUtils.normalizeName(operation.getId()) + "/").resolve(context.getMarkupDocBuilder().addFileExtension(snippetName));
}
@Override
public void apply(Context context) {
Validate.notNull(context);
switch (context.getPosition()) {
case OPERATION_END:
snippets(context);
break;
}
}
public void snippets(Context context) {
for (Map.Entry<String, String> snippets : this.snippets.entrySet()) {
snippetSection(context, snippets.getKey(), snippets.getValue());
}
}
public void snippetSection(Context context, String snippetName, String title) {
ContentExtension content = new ContentExtension(globalContext, context);
URI snippetUri = operationSnippetUri(context, context.getOperation().get(), snippetName);
Optional<Reader> snippetContent = content.readContentUri(snippetUri);
if (snippetContent.isPresent()) {
try {
context.getMarkupDocBuilder().sectionTitleLevel(1 + levelOffset(context), title);
context.getMarkupDocBuilder().importMarkup(snippetContent.get(), levelOffset(context) + 1);
} catch (IOException e) {
throw new RuntimeException(String.format("Failed to process snippet URI : %s", snippetUri), e);
} finally {
try {
snippetContent.get().close();
} catch (IOException e) {
Throwables.propagate(e);
}
}
}
}
}

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.robwin.swagger2markup;
package io.github.swagger2markup;
public enum GroupBy {
AS_IS,

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package io.github.robwin.swagger2markup;
package io.github.swagger2markup;
import java.util.Locale;

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.robwin.swagger2markup;
package io.github.swagger2markup;
public enum OrderBy {
AS_IS,

View File

@@ -0,0 +1,202 @@
package io.github.swagger2markup;
import io.github.robwin.markup.builder.LineSeparator;
import io.github.robwin.markup.builder.MarkupLanguage;
import io.github.swagger2markup.model.PathOperation;
import io.swagger.models.parameters.Parameter;
import java.net.URI;
import java.util.Comparator;
import java.util.Map;
/**
* Swagger2Markup configuration interface.
*/
public interface Swagger2MarkupConfig {
/**
* Prefix for Swagger2Markup properties
*/
String PROPERTIES_PREFIX = "swagger2markup.";
/**
* Prefix for Swagger2Markup extension properties
*/
String EXTENSION_PREFIX = PROPERTIES_PREFIX + "extensions.";
/**
* Specifies the markup language which should be used to generate the files.
*/
MarkupLanguage getMarkupLanguage();
/**
* Include generated examples into the documents.
*/
boolean isGeneratedExamplesEnabled();
/**
* Include hand-written descriptions into the Paths document.
*/
boolean isOperationDescriptionsEnabled();
/**
* Hand-written operation descriptions URI.
*/
URI getOperationDescriptionsUri();
/**
* Include hand-written descriptions into the Definitions document.
*/
boolean isDefinitionDescriptionsEnabled();
/**
* Hand-written definition descriptions URI.
*/
URI getDefinitionDescriptionsUri();
/**
* In addition to the Definitions file, also create separate definition files for each model definition.
*/
boolean isSeparatedDefinitionsEnabled();
/**
* In addition to the Paths file, also create separate operation files for each operation.
*/
boolean isSeparatedOperationsEnabled();
/**
* Specifies if the operations should be grouped by tags or stay as-is.
*/
GroupBy getOperationsGroupedBy();
/**
* Specifies labels language of output files.
*/
Language getOutputLanguage();
/**
* Specifies maximum depth level for inline object schema displaying (0 = no inline schemasEnabled).
*/
int getInlineSchemaDepthLevel();
/**
* Specifies tag ordering.
*/
OrderBy getTagOrderBy();
/**
* Specifies a custom comparator function to order tags.
*/
Comparator<String> getTagOrdering();
/**
* Specifies operation ordering.
*/
OrderBy getOperationOrderBy();
/**
* Specifies a custom comparator function to order operations.
*/
Comparator<PathOperation> getOperationOrdering();
/**
* Specifies definition ordering.
*/
OrderBy getDefinitionOrderBy();
/**
* Specifies a custom comparator function to order definitions.
*/
Comparator<String> getDefinitionOrdering();
/**
* Specifies parameter ordering.
*/
OrderBy getParameterOrderBy();
/**
* Specifies a custom comparator function to order parameters.
*/
Comparator<Parameter> getParameterOrdering();
/**
* Specifies property ordering.
*/
OrderBy getPropertyOrderBy();
/**
* Specifies a custom comparator function to order properties.
*/
Comparator<String> getPropertyOrdering();
/**
* Specifies response ordering.
*/
OrderBy getResponseOrderBy();
/**
* Specifies a custom comparator function to order responses.
*/
Comparator<String> getResponseOrdering();
/**
* Enable use of inter-document cross-references when needed.
*/
boolean isInterDocumentCrossReferencesEnabled();
/**
* Inter-document cross-references optional prefix.
*/
String getInterDocumentCrossReferencesPrefix();
/**
* Optionally isolate the body parameter, if any, from other parameters.
*/
boolean isFlatBodyEnabled();
/**
* Optionally prefix all anchors for uniqueness.
*/
String getAnchorPrefix();
/**
* Overview document name (without extension).
*/
String getOverviewDocument();
/**
* Paths document name (without extension).
*/
String getPathsDocument();
/**
* Definitions document name (without extension).
*/
String getDefinitionsDocument();
/**
* Security document name (without extension).
*/
String getSecurityDocument();
/**
* Separated operations sub-folder name.
*/
String getSeparatedOperationsFolder();
/**
* Separated definitions sub-folder name.
*/
String getSeparatedDefinitionsFolder();
/**
* Specifies the line separator which should be used.
*/
LineSeparator getLineSeparator();
/**
* Returns properties for extensions.
*/
Map<String, String> getExtensionsProperties();
}

View File

@@ -13,15 +13,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.robwin.swagger2markup;
package io.github.swagger2markup;
import com.google.common.annotations.VisibleForTesting;
import io.github.robwin.swagger2markup.internal.document.builder.DefinitionsDocumentBuilder;
import io.github.robwin.swagger2markup.internal.document.builder.OverviewDocumentBuilder;
import io.github.robwin.swagger2markup.internal.document.builder.PathsDocumentBuilder;
import io.github.robwin.swagger2markup.internal.document.builder.SecurityDocumentBuilder;
import io.github.robwin.swagger2markup.spi.Extension;
import io.github.robwin.swagger2markup.spi.SwaggerModelExtension;
import io.github.swagger2markup.builder.Swagger2MarkupConfigBuilder;
import io.github.swagger2markup.builder.Swagger2MarkupExtensionRegistryBuilder;
import io.github.swagger2markup.internal.document.builder.DefinitionsDocumentBuilder;
import io.github.swagger2markup.internal.document.builder.OverviewDocumentBuilder;
import io.github.swagger2markup.internal.document.builder.PathsDocumentBuilder;
import io.github.swagger2markup.internal.document.builder.SecurityDocumentBuilder;
import io.github.swagger2markup.spi.*;
import io.swagger.models.Swagger;
import io.swagger.parser.SwaggerParser;
import org.apache.commons.io.IOUtils;
@@ -145,7 +146,7 @@ public class Swagger2MarkupConverter {
}
private void applySwaggerExtensions() {
for (SwaggerModelExtension swaggerModelExtension : context.extensionRegistry.getExtensions(SwaggerModelExtension.class)) {
for (SwaggerModelExtension swaggerModelExtension : context.extensionRegistry.getSwaggerModelExtensions()) {
swaggerModelExtension.apply(context.getSwagger());
}
}
@@ -245,18 +246,34 @@ public class Swagger2MarkupConverter {
public Swagger2MarkupConverter build() {
if (config == null)
config = Swagger2MarkupConfig.ofDefaults().build();
config = new Swagger2MarkupConfigBuilder().build();
if (extensionRegistry == null)
extensionRegistry = Swagger2MarkupExtensionRegistry.ofDefaults().build();
extensionRegistry = new Swagger2MarkupExtensionRegistryBuilder().build();
Context context = new Context(config, extensionRegistry, swagger, swaggerLocation);
config.setGlobalContext(context);
for (Extension extension : extensionRegistry.getExtensions())
extension.setGlobalContext(context);
initExtensions(context);
return new Swagger2MarkupConverter(context);
}
private void initExtensions(Context context) {
for (SwaggerModelExtension extension : extensionRegistry.getSwaggerModelExtensions())
extension.setGlobalContext(context);
for (OverviewDocumentExtension extension : extensionRegistry.getOverviewDocumentExtensions())
extension.setGlobalContext(context);
for (DefinitionsDocumentExtension extension : extensionRegistry.getDefinitionsDocumentExtensions())
extension.setGlobalContext(context);
for (PathsDocumentExtension extension : extensionRegistry.getPathsDocumentExtensions())
extension.setGlobalContext(context);
for (SecurityDocumentExtension extension : extensionRegistry.getSecurityDocumentExtensions())
extension.setGlobalContext(context);
}
}
public static class Context {

View File

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

View File

@@ -0,0 +1,784 @@
/*
* Copyright 2016 Robert Winkler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.swagger2markup.builder;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.Maps;
import com.google.common.collect.Ordering;
import io.github.robwin.markup.builder.LineSeparator;
import io.github.robwin.markup.builder.MarkupLanguage;
import io.github.swagger2markup.GroupBy;
import io.github.swagger2markup.Language;
import io.github.swagger2markup.OrderBy;
import io.github.swagger2markup.Swagger2MarkupConfig;
import io.github.swagger2markup.model.PathOperation;
import io.swagger.models.HttpMethod;
import io.swagger.models.parameters.Parameter;
import org.apache.commons.collections4.map.HashedMap;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.Nullable;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.nio.file.Path;
import java.util.Comparator;
import java.util.Map;
import java.util.Properties;
import static io.github.swagger2markup.Swagger2MarkupConfig.*;
public class Swagger2MarkupConfigBuilder {
private static final Logger logger = LoggerFactory.getLogger(Swagger2MarkupConfigBuilder.class);
private static final String PROPERTIES_DEFAULT = "/io/github/swagger2markup/config/default.properties";
static final Ordering<PathOperation> OPERATION_METHOD_NATURAL_ORDERING = Ordering
.explicit(HttpMethod.POST, HttpMethod.GET, HttpMethod.PUT, HttpMethod.DELETE, HttpMethod.PATCH, HttpMethod.HEAD, HttpMethod.OPTIONS)
.onResultOf(new Function<PathOperation, HttpMethod>() {
public HttpMethod apply(PathOperation operation) {
return operation.getMethod();
}
});
static final Ordering<PathOperation> OPERATION_PATH_NATURAL_ORDERING = Ordering
.natural()
.onResultOf(new Function<PathOperation, String>() {
public String apply(PathOperation operation) {
return operation.getPath();
}
});
static final Ordering<Parameter> PARAMETER_IN_NATURAL_ORDERING = Ordering
.explicit("header", "path", "query", "formData", "body")
.onResultOf(new Function<Parameter, String>() {
public String apply(Parameter parameter) {
return parameter.getIn();
}
});
static final Ordering<Parameter> PARAMETER_NAME_NATURAL_ORDERING = Ordering
.natural()
.onResultOf(new Function<Parameter, String>() {
public String apply(Parameter parameter) {
return parameter.getName();
}
});
DefaultSwagger2MarkupConfig config = new DefaultSwagger2MarkupConfig();
public Swagger2MarkupConfigBuilder() {
this(new HashedMap<String, String>());
}
public Swagger2MarkupConfigBuilder(Properties properties) {
this(convertPropertiesToMap(properties));
}
private static Map<String, String> convertPropertiesToMap(Properties properties) {
Map<String, String> propertiesMap = new HashedMap<>();
for(String propertyName : properties.stringPropertyNames()){
propertiesMap.put(propertyName, properties.getProperty(propertyName));
}
return propertiesMap;
}
public Swagger2MarkupConfigBuilder(Map<String, String> properties) {
Map<String, String> safeProperties = convertPropertiesToMap(defaultProperties());
safeProperties.putAll(properties);
config.markupLanguage = MarkupLanguage.valueOf(safeProperties.get(PROPERTIES_PREFIX + "markupLanguage"));
config.generatedExamplesEnabled = Boolean.valueOf(safeProperties.get(PROPERTIES_PREFIX + "generatedExamplesEnabled"));
config.operationDescriptionsEnabled = Boolean.valueOf(safeProperties.get(PROPERTIES_PREFIX + "operationDescriptionsEnabled"));
if (safeProperties.containsKey(PROPERTIES_PREFIX + "operationDescriptionsUri"))
config.operationDescriptionsUri = URI.create(safeProperties.get(PROPERTIES_PREFIX + "operationDescriptionsUri"));
config.definitionDescriptionsEnabled = Boolean.valueOf(safeProperties.get(PROPERTIES_PREFIX + "definitionDescriptionsEnabled"));
if (safeProperties.containsKey(PROPERTIES_PREFIX + "definitionDescriptionsUri"))
config.definitionDescriptionsUri = URI.create(safeProperties.get(PROPERTIES_PREFIX + "definitionDescriptionsUri"));
config.separatedDefinitionsEnabled = Boolean.valueOf(safeProperties.get(PROPERTIES_PREFIX + "separatedDefinitionsEnabled"));
config.separatedOperationsEnabled = Boolean.valueOf(safeProperties.get(PROPERTIES_PREFIX + "separatedOperationsEnabled"));
config.operationsGroupedBy = GroupBy.valueOf(safeProperties.get(PROPERTIES_PREFIX + "operationsGroupedBy"));
config.outputLanguage = Language.valueOf(safeProperties.get(PROPERTIES_PREFIX + "outputLanguage"));
config.inlineSchemaDepthLevel = Integer.valueOf(safeProperties.get(PROPERTIES_PREFIX + "inlineSchemaDepthLevel"));
config.interDocumentCrossReferencesEnabled = Boolean.valueOf(safeProperties.get(PROPERTIES_PREFIX + "interDocumentCrossReferencesEnabled"));
config.interDocumentCrossReferencesPrefix = safeProperties.get(PROPERTIES_PREFIX + "interDocumentCrossReferencesPrefix");
config.flatBodyEnabled = Boolean.valueOf(safeProperties.get(PROPERTIES_PREFIX + "flatBodyEnabled"));
config.anchorPrefix = safeProperties.get(PROPERTIES_PREFIX + "anchorPrefix");
config.overviewDocument = safeProperties.get(PROPERTIES_PREFIX + "overviewDocument");
config.pathsDocument = safeProperties.get(PROPERTIES_PREFIX + "pathsDocument");
config.definitionsDocument = safeProperties.get(PROPERTIES_PREFIX + "definitionsDocument");
config.securityDocument = safeProperties.get(PROPERTIES_PREFIX + "securityDocument");
config.separatedOperationsFolder = safeProperties.get(PROPERTIES_PREFIX + "separatedOperationsFolder");
config.separatedDefinitionsFolder = safeProperties.get(PROPERTIES_PREFIX + "separatedDefinitionsFolder");
config.tagOrderBy = OrderBy.valueOf(safeProperties.get(PROPERTIES_PREFIX + "tagOrderBy"));
config.operationOrderBy = OrderBy.valueOf(safeProperties.get(PROPERTIES_PREFIX + "operationOrderBy"));
config.definitionOrderBy = OrderBy.valueOf(safeProperties.get(PROPERTIES_PREFIX + "definitionOrderBy"));
config.parameterOrderBy = OrderBy.valueOf(safeProperties.get(PROPERTIES_PREFIX + "parameterOrderBy"));
config.propertyOrderBy = OrderBy.valueOf(safeProperties.get(PROPERTIES_PREFIX + "propertyOrderBy"));
config.responseOrderBy = OrderBy.valueOf(safeProperties.get(PROPERTIES_PREFIX + "responseOrderBy"));
String lineSeparator = safeProperties.get(PROPERTIES_PREFIX + "lineSeparator");
if(StringUtils.isNoneBlank(lineSeparator)){
config.lineSeparator = LineSeparator.valueOf(lineSeparator);
}
config.extensionsProperties = Maps.filterKeys(safeProperties, new Predicate<String>(){
@Override
public boolean apply(@Nullable String propertyName) {
return StringUtils.startsWith(propertyName, EXTENSION_PREFIX);
}
});
}
private Properties defaultProperties() {
Properties defaultProperties = new Properties();
try {
InputStream defaultPropertiesStream = Swagger2MarkupConfigBuilder.class.getResourceAsStream(PROPERTIES_DEFAULT);
if (defaultPropertiesStream == null)
throw new RuntimeException(String.format("Can't load default properties '%s'", PROPERTIES_DEFAULT));
defaultProperties.load(defaultPropertiesStream);
} catch (IOException e) {
throw new RuntimeException(String.format("Can't load default properties '%s'", PROPERTIES_DEFAULT), e);
}
return defaultProperties;
}
public Swagger2MarkupConfig build() {
buildNaturalOrdering();
return config;
}
private void buildNaturalOrdering() {
if (config.tagOrderBy == OrderBy.NATURAL)
config.tagOrdering = Ordering.natural();
if (config.operationOrderBy == OrderBy.NATURAL)
config.operationOrdering = OPERATION_PATH_NATURAL_ORDERING.compound(OPERATION_METHOD_NATURAL_ORDERING);
if (config.definitionOrderBy == OrderBy.NATURAL)
config.definitionOrdering = Ordering.natural();
if (config.parameterOrderBy == OrderBy.NATURAL)
config.parameterOrdering = PARAMETER_IN_NATURAL_ORDERING.compound(PARAMETER_NAME_NATURAL_ORDERING);
if (config.propertyOrderBy == OrderBy.NATURAL)
config.propertyOrdering = Ordering.natural();
if (config.responseOrderBy == OrderBy.NATURAL)
config.responseOrdering = Ordering.natural();
}
/**
* Specifies the markup language which should be used to generate the files.
*
* @param markupLanguage the markup language which is used to generate the files
* @return this builder
*/
public Swagger2MarkupConfigBuilder withMarkupLanguage(MarkupLanguage markupLanguage) {
Validate.notNull(markupLanguage, "%s must not be null", "markupLanguage");
config.markupLanguage = markupLanguage;
return this;
}
/**
* Include generated examples into the documents.
*
* @return this builder
*/
public Swagger2MarkupConfigBuilder withGeneratedExamples() {
config.generatedExamplesEnabled = true;
return this;
}
/**
* Include hand-written descriptions into the Paths document.
*
* @param operationDescriptionsUri the URI to the folder where the description documents reside.
* @return this builder
*/
public Swagger2MarkupConfigBuilder withOperationDescriptions(URI operationDescriptionsUri) {
Validate.notNull(operationDescriptionsUri, "%s must not be null", "operationDescriptionsUri");
config.operationDescriptionsEnabled = true;
config.operationDescriptionsUri = operationDescriptionsUri;
return this;
}
/**
* Include hand-written descriptions into the Paths document.
*
* @param operationDescriptionsPath the path to the folder where the description documents reside.
* @return this builder
*/
public Swagger2MarkupConfigBuilder withOperationDescriptions(Path operationDescriptionsPath) {
Validate.notNull(operationDescriptionsPath, "%s must not be null", "operationDescriptionsPath");
return withOperationDescriptions(operationDescriptionsPath.toUri());
}
/**
* Include hand-written descriptions into the Paths document.<br>
* Use default URI.
*
* @return this builder
*/
public Swagger2MarkupConfigBuilder withOperationDescriptions() {
config.operationDescriptionsEnabled = true;
return this;
}
/**
* Include hand-written descriptions into the Definitions document.
*
* @param definitionDescriptionsUri the URI to the folder where the description documents reside.
* @return this builder
*/
public Swagger2MarkupConfigBuilder withDefinitionDescriptions(URI definitionDescriptionsUri) {
Validate.notNull(definitionDescriptionsUri, "%s must not be null", "definitionDescriptionsUri");
config.definitionDescriptionsEnabled = true;
config.definitionDescriptionsUri = definitionDescriptionsUri;
return this;
}
/**
* Include hand-written descriptions into the Definitions document.
*
* @param definitionDescriptionsPath the path to the folder where the description documents reside.
* @return this builder
*/
public Swagger2MarkupConfigBuilder withDefinitionDescriptions(Path definitionDescriptionsPath) {
Validate.notNull(definitionDescriptionsPath, "%s must not be null", "definitionDescriptionsPath");
return withDefinitionDescriptions(definitionDescriptionsPath.toUri());
}
/**
* Include hand-written descriptions into the Definitions document.<br>
* Use default URI.
*
* @return this builder
*/
public Swagger2MarkupConfigBuilder withDefinitionDescriptions() {
config.definitionDescriptionsEnabled = true;
return this;
}
/**
* In addition to the Definitions file, also create separate definition files for each model definition.
*
* @return this builder
*/
public Swagger2MarkupConfigBuilder withSeparatedDefinitions() {
config.separatedDefinitionsEnabled = true;
return this;
}
/**
* In addition to the Paths file, also create separate operation files for each operation.
*
* @return this builder
*/
public Swagger2MarkupConfigBuilder withSeparatedOperations() {
config.separatedOperationsEnabled = true;
return this;
}
/**
* Specifies if the operations should be grouped by tags or stay as-is.
*
* @param pathsGroupedBy the GroupBy enum
* @return this builder
*/
public Swagger2MarkupConfigBuilder withPathsGroupedBy(GroupBy pathsGroupedBy) {
Validate.notNull(pathsGroupedBy, "%s must not be null", "pathsGroupedBy");
config.operationsGroupedBy = pathsGroupedBy;
return this;
}
/**
* Specifies labels language of output files.
*
* @param language the enum
* @return this builder
*/
public Swagger2MarkupConfigBuilder withOutputLanguage(Language language) {
Validate.notNull(language, "%s must not be null", "language");
config.outputLanguage = language;
return this;
}
/**
* Specifies maximum depth level for inline object schema displaying (0 = no inline schemasEnabled).
*
* @param inlineSchemaDepthLevel number of recursion levels for inline schemasEnabled display
* @return this builder
*/
public Swagger2MarkupConfigBuilder withInlineSchemaDepthLevel(int inlineSchemaDepthLevel) {
Validate.isTrue(inlineSchemaDepthLevel >= 0, "%s must be >= 0", "inlineSchemaDepthLevel");
config.inlineSchemaDepthLevel = inlineSchemaDepthLevel;
return this;
}
/**
* Specifies tag ordering.<br>
* By default tag ordering == {@link io.github.swagger2markup.OrderBy#NATURAL}.<br>
* Use {@link #withTagOrdering(Comparator)} to set a custom ordering.
*
* @param orderBy tag ordering
* @return this builder
*/
public Swagger2MarkupConfigBuilder withTagOrdering(OrderBy orderBy) {
Validate.notNull(orderBy, "%s must not be null", "orderBy");
Validate.isTrue(orderBy != OrderBy.CUSTOM, "You must provide a custom comparator if orderBy == OrderBy.CUSTOM");
config.tagOrderBy = orderBy;
return this;
}
/**
* Specifies a custom comparator function to order tags.
*
* @param tagOrdering tag ordering
* @return this builder
*/
public Swagger2MarkupConfigBuilder withTagOrdering(Comparator<String> tagOrdering) {
Validate.notNull(tagOrdering, "%s must not be null", "tagOrdering");
config.tagOrderBy = OrderBy.CUSTOM;
config.tagOrdering = tagOrdering;
return this;
}
/**
* Specifies operation ordering.<br>
* By default operation ordering == {@link io.github.swagger2markup.OrderBy#AS_IS}.<br>
* Use {@link #withOperationOrdering(Comparator)} to set a custom ordering.
*
* @param orderBy operation ordering
* @return this builder
*/
public Swagger2MarkupConfigBuilder withOperationOrdering(OrderBy orderBy) {
Validate.notNull(orderBy, "%s must not be null", "orderBy");
Validate.isTrue(orderBy != OrderBy.CUSTOM, "You must provide a custom comparator if orderBy == OrderBy.CUSTOM");
config.operationOrderBy = orderBy;
return this;
}
/**
* Specifies a custom comparator function to order operations.
*
* @param operationOrdering operation ordering
* @return this builder
*/
public Swagger2MarkupConfigBuilder withOperationOrdering(Comparator<PathOperation> operationOrdering) {
Validate.notNull(operationOrdering, "%s must not be null", "operationOrdering");
config.operationOrderBy = OrderBy.CUSTOM;
config.operationOrdering = operationOrdering;
return this;
}
/**
* Specifies definition ordering.<br>
* By default definition ordering == {@link io.github.swagger2markup.OrderBy#NATURAL}.<br>
* Use {@link #withDefinitionOrdering(Comparator)} to set a custom ordering.
*
* @param orderBy definition ordering
* @return this builder
*/
public Swagger2MarkupConfigBuilder withDefinitionOrdering(OrderBy orderBy) {
Validate.notNull(orderBy, "%s must not be null", "orderBy");
Validate.isTrue(orderBy != OrderBy.CUSTOM, "You must provide a custom comparator if orderBy == OrderBy.CUSTOM");
config.definitionOrderBy = orderBy;
return this;
}
/**
* Specifies a custom comparator function to order definitions.
*
* @param definitionOrdering definition ordering
* @return this builder
*/
public Swagger2MarkupConfigBuilder withDefinitionOrdering(Comparator<String> definitionOrdering) {
Validate.notNull(definitionOrdering, "%s must not be null", "definitionOrdering");
config.definitionOrderBy = OrderBy.CUSTOM;
config.definitionOrdering = definitionOrdering;
return this;
}
/**
* Specifies parameter ordering.<br>
* By default parameter ordering == {@link OrderBy#NATURAL}.<br>
* Use {@link #withParameterOrdering(Comparator)} to set a custom ordering.
*
* @param orderBy parameter ordering
* @return this builder
*/
public Swagger2MarkupConfigBuilder withParameterOrdering(OrderBy orderBy) {
Validate.notNull(orderBy, "%s must not be null", "orderBy");
Validate.isTrue(orderBy != OrderBy.CUSTOM, "You must provide a custom comparator if orderBy == OrderBy.CUSTOM");
config.parameterOrderBy = orderBy;
return this;
}
/**
* Specifies a custom comparator function to order parameters.
*
* @param parameterOrdering parameter ordering
* @return this builder
*/
public Swagger2MarkupConfigBuilder withParameterOrdering(Comparator<Parameter> parameterOrdering) {
Validate.notNull(parameterOrdering, "%s must not be null", "parameterOrdering");
config.parameterOrderBy = OrderBy.CUSTOM;
config.parameterOrdering = parameterOrdering;
return this;
}
/**
* Specifies property ordering.<br>
* By default property ordering == {@link io.github.swagger2markup.OrderBy#NATURAL}.<br>
* Use {@link #withPropertyOrdering(Comparator)} to set a custom ordering.
*
* @param orderBy property ordering
* @return this builder
*/
public Swagger2MarkupConfigBuilder withPropertyOrdering(OrderBy orderBy) {
Validate.notNull(orderBy, "%s must not be null", "orderBy");
Validate.isTrue(orderBy != OrderBy.CUSTOM, "You must provide a custom comparator if orderBy == OrderBy.CUSTOM");
config.propertyOrderBy = orderBy;
return this;
}
/**
* Specifies a custom comparator function to order properties.
*
* @param propertyOrdering property ordering
* @return this builder
*/
public Swagger2MarkupConfigBuilder withPropertyOrdering(Comparator<String> propertyOrdering) {
Validate.notNull(propertyOrdering, "%s must not be null", "propertyOrdering");
config.propertyOrderBy = OrderBy.CUSTOM;
config.propertyOrdering = propertyOrdering;
return this;
}
/**
* Specifies response ordering.<br>
* By default response ordering == {@link io.github.swagger2markup.OrderBy#NATURAL}.<br>
* Use {@link #withResponseOrdering(Comparator)} to set a custom ordering.
*
* @param orderBy response ordering
* @return this builder
*/
public Swagger2MarkupConfigBuilder withResponseOrdering(OrderBy orderBy) {
Validate.notNull(orderBy, "%s must not be null", "orderBy");
Validate.isTrue(orderBy != OrderBy.CUSTOM, "You must provide a custom comparator if orderBy == OrderBy.CUSTOM");
config.responseOrderBy = orderBy;
return this;
}
/**
* Specifies a custom comparator function to order responses.
*
* @param responseOrdering response ordering
* @return this builder
*/
public Swagger2MarkupConfigBuilder withResponseOrdering(Comparator<String> responseOrdering) {
Validate.notNull(responseOrdering, "%s must not be null", "responseOrdering");
config.responseOrderBy = OrderBy.CUSTOM;
config.responseOrdering = responseOrdering;
return this;
}
/**
* Enable use of inter-document cross-references when needed.
*
* @param prefix Prefix to document in all inter-document cross-references.
* @return this builder
*/
public Swagger2MarkupConfigBuilder withInterDocumentCrossReferences(String prefix) {
Validate.notNull(prefix, "%s must not be null", "prefix");
config.interDocumentCrossReferencesEnabled = true;
config.interDocumentCrossReferencesPrefix = prefix;
return this;
}
/**
* Enable use of inter-document cross-references when needed.
*
* @return this builder
*/
public Swagger2MarkupConfigBuilder withInterDocumentCrossReferences() {
config.interDocumentCrossReferencesEnabled = true;
return this;
}
/**
* Optionally isolate the body parameter, if any, from other parameters.
*
* @return this builder
*/
public Swagger2MarkupConfigBuilder withFlatBody() {
config.flatBodyEnabled = true;
return this;
}
/**
* Optionally prefix all anchors for uniqueness.
*
* @param anchorPrefix anchor prefix.
* @return this builder
*/
public Swagger2MarkupConfigBuilder withAnchorPrefix(String anchorPrefix) {
Validate.notNull(anchorPrefix, "%s must no be null", "anchorPrefix");
config.anchorPrefix = anchorPrefix;
return this;
}
/**
* Specifies the line separator which should be used.
*
* @param lineSeparator the lineSeparator
* @return this builder
*/
public Swagger2MarkupConfigBuilder withLineSeparator(LineSeparator lineSeparator) {
Validate.notNull(lineSeparator, "%s must no be null", "lineSeparator");
config.lineSeparator = lineSeparator;
return this;
}
public Swagger2MarkupConfigBuilder withExtensionsProperties(Map<String, String> extensionsProperties) {
Validate.notEmpty(extensionsProperties, "%s must no be null", "extensionsProperties");
config.extensionsProperties = extensionsProperties;
return this;
}
static class DefaultSwagger2MarkupConfig implements Swagger2MarkupConfig{
private MarkupLanguage markupLanguage;
private boolean generatedExamplesEnabled;
private boolean operationDescriptionsEnabled;
private URI operationDescriptionsUri;
private boolean definitionDescriptionsEnabled;
private URI definitionDescriptionsUri;
private boolean separatedDefinitionsEnabled;
private boolean separatedOperationsEnabled;
private GroupBy operationsGroupedBy;
private Language outputLanguage;
private int inlineSchemaDepthLevel;
private OrderBy tagOrderBy;
private Comparator<String> tagOrdering;
private OrderBy operationOrderBy;
private Comparator<PathOperation> operationOrdering;
private OrderBy definitionOrderBy;
private Comparator<String> definitionOrdering;
private OrderBy parameterOrderBy;
private Comparator<Parameter> parameterOrdering;
private OrderBy propertyOrderBy;
private Comparator<String> propertyOrdering;
private OrderBy responseOrderBy;
private Comparator<String> responseOrdering;
private boolean interDocumentCrossReferencesEnabled;
private String interDocumentCrossReferencesPrefix;
private boolean flatBodyEnabled;
private String anchorPrefix;
private LineSeparator lineSeparator;
private String overviewDocument;
private String pathsDocument;
private String definitionsDocument;
private String securityDocument;
private String separatedOperationsFolder;
private String separatedDefinitionsFolder;
private Map<String, String> extensionsProperties;
@Override
public MarkupLanguage getMarkupLanguage() {
return markupLanguage;
}
@Override
public boolean isGeneratedExamplesEnabled() {
return generatedExamplesEnabled;
}
@Override
public boolean isOperationDescriptionsEnabled() {
return operationDescriptionsEnabled;
}
@Override
public URI getOperationDescriptionsUri() {
return operationDescriptionsUri;
}
@Override
public boolean isDefinitionDescriptionsEnabled() {
return definitionDescriptionsEnabled;
}
@Override
public URI getDefinitionDescriptionsUri() {
return definitionDescriptionsUri;
}
@Override
public boolean isSeparatedDefinitionsEnabled() {
return separatedDefinitionsEnabled;
}
@Override
public boolean isSeparatedOperationsEnabled() {
return separatedOperationsEnabled;
}
@Override
public GroupBy getOperationsGroupedBy() {
return operationsGroupedBy;
}
@Override
public Language getOutputLanguage() {
return outputLanguage;
}
@Override
public int getInlineSchemaDepthLevel() {
return inlineSchemaDepthLevel;
}
@Override
public OrderBy getTagOrderBy() {
return tagOrderBy;
}
@Override
public Comparator<String> getTagOrdering() {
return tagOrdering;
}
@Override
public OrderBy getOperationOrderBy() {
return operationOrderBy;
}
@Override
public Comparator<PathOperation> getOperationOrdering() {
return operationOrdering;
}
@Override
public OrderBy getDefinitionOrderBy() {
return definitionOrderBy;
}
@Override
public Comparator<String> getDefinitionOrdering() {
return definitionOrdering;
}
@Override
public OrderBy getParameterOrderBy() {
return parameterOrderBy;
}
@Override
public Comparator<Parameter> getParameterOrdering() {
return parameterOrdering;
}
@Override
public OrderBy getPropertyOrderBy() {
return propertyOrderBy;
}
@Override
public Comparator<String> getPropertyOrdering() {
return propertyOrdering;
}
@Override
public OrderBy getResponseOrderBy() {
return responseOrderBy;
}
@Override
public Comparator<String> getResponseOrdering() {
return responseOrdering;
}
@Override
public boolean isInterDocumentCrossReferencesEnabled() {
return interDocumentCrossReferencesEnabled;
}
@Override
public String getInterDocumentCrossReferencesPrefix() {
return interDocumentCrossReferencesPrefix;
}
@Override
public boolean isFlatBodyEnabled() {
return flatBodyEnabled;
}
@Override
public String getAnchorPrefix() {
return anchorPrefix;
}
@Override
public String getOverviewDocument() {
return overviewDocument;
}
@Override
public String getPathsDocument() {
return pathsDocument;
}
@Override
public String getDefinitionsDocument() {
return definitionsDocument;
}
@Override
public String getSecurityDocument() {
return securityDocument;
}
@Override
public String getSeparatedOperationsFolder() {
return separatedOperationsFolder;
}
@Override
public String getSeparatedDefinitionsFolder() {
return separatedDefinitionsFolder;
}
@Override
public LineSeparator getLineSeparator() {
return lineSeparator;
}
@Override
public Map<String, String> getExtensionsProperties() {
return extensionsProperties;
}
}
}

View File

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

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.robwin.swagger2markup.internal.document;
package io.github.swagger2markup.internal.document;
import io.github.robwin.markup.builder.MarkupDocBuilder;

View File

@@ -13,16 +13,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.robwin.swagger2markup.internal.document.builder;
package io.github.swagger2markup.internal.document.builder;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableMap;
import io.github.robwin.markup.builder.MarkupDocBuilder;
import io.github.robwin.swagger2markup.Swagger2MarkupConverter;
import io.github.robwin.swagger2markup.internal.document.MarkupDocument;
import io.github.robwin.swagger2markup.spi.DefinitionsDocumentExtension;
import io.github.robwin.swagger2markup.internal.type.ObjectType;
import io.github.robwin.swagger2markup.internal.type.Type;
import io.github.swagger2markup.Swagger2MarkupConverter;
import io.github.swagger2markup.internal.document.MarkupDocument;
import io.github.swagger2markup.internal.type.ObjectType;
import io.github.swagger2markup.internal.type.Type;
import io.github.swagger2markup.spi.DefinitionsDocumentExtension;
import io.swagger.models.ComposedModel;
import io.swagger.models.Model;
import io.swagger.models.RefModel;
@@ -33,7 +33,6 @@ import org.apache.commons.collections4.MapUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.Validate;
import java.io.File;
import java.io.IOException;
import java.io.Reader;
@@ -42,11 +41,12 @@ import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.util.*;
import static io.github.robwin.swagger2markup.internal.utils.IOUtils.normalizeName;
import static io.github.robwin.swagger2markup.spi.DefinitionsDocumentExtension.*;
import static io.github.swagger2markup.internal.utils.MapUtils.toKeySet;
import static io.github.swagger2markup.spi.DefinitionsDocumentExtension.Context;
import static io.github.swagger2markup.spi.DefinitionsDocumentExtension.Position;
import static io.github.swagger2markup.utils.IOUtils.normalizeName;
import static org.apache.commons.lang3.StringUtils.defaultString;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import static io.github.robwin.swagger2markup.internal.utils.MapUtils.toKeySet;
/**
* @author Robert Winkler
@@ -61,7 +61,7 @@ public class DefinitionsDocumentBuilder extends MarkupDocumentBuilder {
public DefinitionsDocumentBuilder(Swagger2MarkupConverter.Context context, Path outputPath) {
super(context, outputPath);
ResourceBundle labels = ResourceBundle.getBundle("io/github/robwin/swagger2markup/lang/labels", config.getOutputLanguage().toLocale());
ResourceBundle labels = ResourceBundle.getBundle("io/github/swagger2markup/lang/labels", config.getOutputLanguage().toLocale());
DEFINITIONS = labels.getString("definitions");
if (config.isDefinitionDescriptionsEnabled()) {
@@ -132,7 +132,7 @@ public class DefinitionsDocumentBuilder extends MarkupDocumentBuilder {
* @param context context
*/
private void applyDefinitionsDocumentExtension(Context context) {
for (DefinitionsDocumentExtension extension : globalContext.getExtensionRegistry().getExtensions(DefinitionsDocumentExtension.class)) {
for (DefinitionsDocumentExtension extension : globalContext.getExtensionRegistry().getDefinitionsDocumentExtensions()) {
extension.apply(context);
}
}
@@ -160,7 +160,7 @@ public class DefinitionsDocumentBuilder extends MarkupDocumentBuilder {
private void buildDefinition(Map<String, Model> definitions, String definitionName, Model model) {
if (config.isSeparatedDefinitionsEnabled()) {
MarkupDocBuilder defDocBuilder = this.markupDocBuilder.copy();
MarkupDocBuilder defDocBuilder = this.markupDocBuilder.copy(false);
buildDefinition(definitions, definitionName, model, defDocBuilder);
Path definitionFile = outputPath.resolve(resolveDefinitionDocument(definitionName));
try {
@@ -213,7 +213,7 @@ public class DefinitionsDocumentBuilder extends MarkupDocumentBuilder {
* @param docBuilder the docbuilder do use for output
*/
private void definitionRef(String definitionName, MarkupDocBuilder docBuilder) {
buildDefinitionTitle(docBuilder.copy().crossReference(new DefinitionDocumentResolverDefault().apply(definitionName), definitionName, definitionName).toString(), "ref-" + definitionName, docBuilder);
buildDefinitionTitle(docBuilder.copy(false).crossReference(new DefinitionDocumentResolverDefault().apply(definitionName), definitionName, definitionName).toString(), "ref-" + definitionName, docBuilder);
}
/**
@@ -328,7 +328,7 @@ public class DefinitionsDocumentBuilder extends MarkupDocumentBuilder {
for (String fileNameExtension : config.getMarkupLanguage().getFileNameExtensions()) {
URI contentUri = config.getDefinitionDescriptionsUri().resolve(descriptionFolder).resolve(descriptionFileName + fileNameExtension);
try (Reader reader = io.github.robwin.swagger2markup.internal.utils.IOUtils.uriReader(contentUri)) {
try (Reader reader = io.github.swagger2markup.utils.IOUtils.uriReader(contentUri)) {
if (logger.isInfoEnabled()) {
logger.info("Definition description content processed {}", contentUri);
}

View File

@@ -13,21 +13,21 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.robwin.swagger2markup.internal.document.builder;
package io.github.swagger2markup.internal.document.builder;
import io.github.robwin.markup.builder.MarkupDocBuilder;
import io.github.robwin.markup.builder.MarkupDocBuilders;
import io.github.robwin.markup.builder.MarkupLanguage;
import io.github.robwin.markup.builder.MarkupTableColumn;
import io.github.robwin.swagger2markup.Swagger2MarkupConfig;
import io.github.robwin.swagger2markup.Swagger2MarkupConverter;
import io.github.robwin.swagger2markup.internal.document.MarkupDocument;
import io.github.robwin.swagger2markup.internal.type.DefinitionDocumentResolver;
import io.github.robwin.swagger2markup.internal.type.ObjectType;
import io.github.robwin.swagger2markup.internal.type.RefType;
import io.github.robwin.swagger2markup.internal.type.Type;
import io.github.robwin.swagger2markup.internal.utils.IOUtils;
import io.github.robwin.swagger2markup.internal.utils.PropertyUtils;
import io.github.swagger2markup.Swagger2MarkupConfig;
import io.github.swagger2markup.Swagger2MarkupConverter;
import io.github.swagger2markup.internal.document.MarkupDocument;
import io.github.swagger2markup.internal.type.DefinitionDocumentResolver;
import io.github.swagger2markup.internal.type.ObjectType;
import io.github.swagger2markup.internal.type.RefType;
import io.github.swagger2markup.internal.type.Type;
import io.github.swagger2markup.internal.utils.PropertyUtils;
import io.github.swagger2markup.utils.IOUtils;
import io.swagger.models.properties.Property;
import io.swagger.util.Json;
import org.apache.commons.collections4.MapUtils;
@@ -39,7 +39,7 @@ import java.io.IOException;
import java.nio.file.Path;
import java.util.*;
import static io.github.robwin.swagger2markup.internal.utils.MapUtils.toKeySet;
import static io.github.swagger2markup.internal.utils.MapUtils.toKeySet;
import static org.apache.commons.lang3.StringUtils.defaultString;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
@@ -75,7 +75,7 @@ public abstract class MarkupDocumentBuilder {
this.markupDocBuilder = MarkupDocBuilders.documentBuilder(config.getMarkupLanguage(), config.getLineSeparator()).withAnchorPrefix(config.getAnchorPrefix());
ResourceBundle labels = ResourceBundle.getBundle("io/github/robwin/swagger2markup/lang/labels", config.getOutputLanguage().toLocale());
ResourceBundle labels = ResourceBundle.getBundle("io/github/swagger2markup/lang/labels", config.getOutputLanguage().toLocale());
DEFAULT_COLUMN = labels.getString("default_column");
EXAMPLE_COLUMN = labels.getString("example_column");
REQUIRED_COLUMN = labels.getString("required_column");

View File

@@ -13,11 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.robwin.swagger2markup.internal.document.builder;
package io.github.swagger2markup.internal.document.builder;
import io.github.robwin.swagger2markup.Swagger2MarkupConverter;
import io.github.robwin.swagger2markup.internal.document.MarkupDocument;
import io.github.robwin.swagger2markup.spi.OverviewDocumentExtension;
import io.github.swagger2markup.Swagger2MarkupConverter;
import io.github.swagger2markup.internal.document.MarkupDocument;
import io.github.swagger2markup.spi.OverviewDocumentExtension;
import io.swagger.models.*;
import java.nio.file.Path;
@@ -25,7 +25,8 @@ import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;
import static io.github.robwin.swagger2markup.spi.OverviewDocumentExtension.*;
import static io.github.swagger2markup.spi.OverviewDocumentExtension.Context;
import static io.github.swagger2markup.spi.OverviewDocumentExtension.Position;
import static org.apache.commons.collections4.CollectionUtils.isNotEmpty;
import static org.apache.commons.lang3.StringUtils.*;
@@ -51,7 +52,7 @@ public class OverviewDocumentBuilder extends MarkupDocumentBuilder {
public OverviewDocumentBuilder(Swagger2MarkupConverter.Context context, Path outputPath){
super(context, outputPath);
ResourceBundle labels = ResourceBundle.getBundle("io/github/robwin/swagger2markup/lang/labels", config.getOutputLanguage().toLocale());
ResourceBundle labels = ResourceBundle.getBundle("io/github/swagger2markup/lang/labels", config.getOutputLanguage().toLocale());
OVERVIEW = labels.getString("overview");
CURRENT_VERSION = labels.getString("current_version");
VERSION = labels.getString("version");
@@ -191,7 +192,7 @@ public class OverviewDocumentBuilder extends MarkupDocumentBuilder {
* @param context context
*/
private void applyOverviewDocumentExtension(Context context) {
for (OverviewDocumentExtension extension : globalContext.getExtensionRegistry().getExtensions(OverviewDocumentExtension.class)) {
for (OverviewDocumentExtension extension : globalContext.getExtensionRegistry().getOverviewDocumentExtensions()) {
extension.apply(context);
}
}

View File

@@ -13,21 +13,24 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.robwin.swagger2markup.internal.document.builder;
package io.github.swagger2markup.internal.document.builder;
import com.google.common.base.Joiner;
import com.google.common.base.Optional;
import com.google.common.collect.Multimap;
import io.github.robwin.markup.builder.*;
import io.github.robwin.swagger2markup.GroupBy;
import io.github.robwin.swagger2markup.Swagger2MarkupConverter;
import io.github.robwin.swagger2markup.internal.document.MarkupDocument;
import io.github.robwin.swagger2markup.internal.model.PathOperation;
import io.github.robwin.swagger2markup.internal.type.ObjectType;
import io.github.robwin.swagger2markup.internal.type.RefType;
import io.github.robwin.swagger2markup.internal.type.Type;
import io.github.robwin.swagger2markup.internal.utils.*;
import io.github.robwin.swagger2markup.spi.PathsDocumentExtension;
import io.github.swagger2markup.GroupBy;
import io.github.swagger2markup.Swagger2MarkupConverter;
import io.github.swagger2markup.internal.document.MarkupDocument;
import io.github.swagger2markup.internal.type.ObjectType;
import io.github.swagger2markup.internal.type.RefType;
import io.github.swagger2markup.internal.type.Type;
import io.github.swagger2markup.internal.utils.ExamplesUtil;
import io.github.swagger2markup.internal.utils.ParameterUtils;
import io.github.swagger2markup.internal.utils.PropertyUtils;
import io.github.swagger2markup.internal.utils.TagUtils;
import io.github.swagger2markup.model.PathOperation;
import io.github.swagger2markup.spi.PathsDocumentExtension;
import io.swagger.models.*;
import io.swagger.models.auth.SecuritySchemeDefinition;
import io.swagger.models.parameters.Parameter;
@@ -47,12 +50,13 @@ import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.*;
import static io.github.robwin.swagger2markup.internal.utils.IOUtils.normalizeName;
import static io.github.robwin.swagger2markup.internal.utils.ListUtils.*;
import static io.github.robwin.swagger2markup.internal.utils.MapUtils.toKeySet;
import static io.github.robwin.swagger2markup.internal.utils.TagUtils.convertTagsListToMap;
import static io.github.robwin.swagger2markup.internal.utils.TagUtils.getTagDescription;
import static io.github.robwin.swagger2markup.spi.PathsDocumentExtension.*;
import static io.github.swagger2markup.internal.utils.ListUtils.toSet;
import static io.github.swagger2markup.internal.utils.MapUtils.toKeySet;
import static io.github.swagger2markup.internal.utils.TagUtils.convertTagsListToMap;
import static io.github.swagger2markup.internal.utils.TagUtils.getTagDescription;
import static io.github.swagger2markup.spi.PathsDocumentExtension.Context;
import static io.github.swagger2markup.spi.PathsDocumentExtension.Position;
import static io.github.swagger2markup.utils.IOUtils.normalizeName;
import static org.apache.commons.lang3.StringUtils.defaultString;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
@@ -86,7 +90,7 @@ public class PathsDocumentBuilder extends MarkupDocumentBuilder {
public PathsDocumentBuilder(Swagger2MarkupConverter.Context globalContext, java.nio.file.Path outputPath) {
super(globalContext, outputPath);
ResourceBundle labels = ResourceBundle.getBundle("io/github/robwin/swagger2markup/lang/labels", config.getOutputLanguage().toLocale());
ResourceBundle labels = ResourceBundle.getBundle("io/github/swagger2markup/lang/labels", config.getOutputLanguage().toLocale());
RESPONSE = labels.getString("response");
REQUEST = labels.getString("request");
PATHS = labels.getString("paths");
@@ -223,7 +227,7 @@ public class PathsDocumentBuilder extends MarkupDocumentBuilder {
* @param context context
*/
private void applyPathsDocumentExtension(Context context) {
for (PathsDocumentExtension extension : globalContext.getExtensionRegistry().getExtensions(PathsDocumentExtension.class)) {
for (PathsDocumentExtension extension : globalContext.getExtensionRegistry().getPathsDocumentExtensions()) {
extension.apply(context);
}
}
@@ -248,7 +252,7 @@ public class PathsDocumentBuilder extends MarkupDocumentBuilder {
*/
private void buildOperation(PathOperation operation) {
if (config.isSeparatedOperationsEnabled()) {
MarkupDocBuilder pathDocBuilder = this.markupDocBuilder.copy();
MarkupDocBuilder pathDocBuilder = this.markupDocBuilder.copy(false);
buildOperation(operation, pathDocBuilder);
java.nio.file.Path operationFile = outputPath.resolve(resolveOperationDocument(operation));
@@ -325,7 +329,7 @@ public class PathsDocumentBuilder extends MarkupDocumentBuilder {
document = defaultString(config.getInterDocumentCrossReferencesPrefix()) + resolveOperationDocument(operation);
String operationName = operationName(operation);
buildOperationTitle(docBuilder.copy().crossReference(document, operationName, operationName).toString(), "ref-" + operationName, docBuilder);
buildOperationTitle(docBuilder.copy(false).crossReference(document, operationName, operationName).toString(), "ref-" + operationName, docBuilder);
}
/**
@@ -655,7 +659,7 @@ public class PathsDocumentBuilder extends MarkupDocumentBuilder {
if (securityDefinitions != null && securityDefinitions.containsKey(securityKey)) {
type = securityDefinitions.get(securityKey).getType();
}
List<String> content = Arrays.asList(type, docBuilder.copy().crossReference(securityKey, securityKey).toString(),
List<String> content = Arrays.asList(type, docBuilder.copy(false).crossReference(securityKey, securityKey).toString(),
Joiner.on(",").join(securityEntry.getValue()));
cells.add(content);
}
@@ -675,7 +679,7 @@ public class PathsDocumentBuilder extends MarkupDocumentBuilder {
for (String fileNameExtension : config.getMarkupLanguage().getFileNameExtensions()) {
URI contentUri = config.getOperationDescriptionsUri().resolve(descriptionFolder).resolve(descriptionFileName + fileNameExtension);
try (Reader reader = io.github.robwin.swagger2markup.internal.utils.IOUtils.uriReader(contentUri)) {
try (Reader reader = io.github.swagger2markup.utils.IOUtils.uriReader(contentUri)) {
if (logger.isInfoEnabled()) {
logger.info("Operation description content processed {}", contentUri);
}
@@ -804,7 +808,7 @@ public class PathsDocumentBuilder extends MarkupDocumentBuilder {
String defaultResolver = super.apply(definitionName);
if (defaultResolver != null && config.isSeparatedOperationsEnabled())
return defaultString(config.getInterDocumentCrossReferencesPrefix()) + new File("..", defaultResolver).getPath();
return defaultString(config.getInterDocumentCrossReferencesPrefix()) + new File("src/main", defaultResolver).getPath();
else
return defaultResolver;
}

View File

@@ -13,13 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.robwin.swagger2markup.internal.document.builder;
package io.github.swagger2markup.internal.document.builder;
import io.github.robwin.markup.builder.MarkupDocBuilder;
import io.github.robwin.markup.builder.MarkupTableColumn;
import io.github.robwin.swagger2markup.Swagger2MarkupConverter;
import io.github.robwin.swagger2markup.internal.document.MarkupDocument;
import io.github.robwin.swagger2markup.spi.SecurityDocumentExtension;
import io.github.swagger2markup.Swagger2MarkupConverter;
import io.github.swagger2markup.internal.document.MarkupDocument;
import io.github.swagger2markup.spi.SecurityDocumentExtension;
import io.swagger.models.auth.ApiKeyAuthDefinition;
import io.swagger.models.auth.OAuth2Definition;
import io.swagger.models.auth.SecuritySchemeDefinition;
@@ -28,8 +28,9 @@ import org.apache.commons.collections4.MapUtils;
import java.nio.file.Path;
import java.util.*;
import static io.github.robwin.swagger2markup.spi.SecurityDocumentExtension.Context;
import static io.github.robwin.swagger2markup.spi.SecurityDocumentExtension.Position;
import static io.github.swagger2markup.internal.utils.MapUtils.toKeySet;
import static io.github.swagger2markup.spi.SecurityDocumentExtension.Context;
import static io.github.swagger2markup.spi.SecurityDocumentExtension.Position;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
/**
@@ -49,7 +50,7 @@ public class SecurityDocumentBuilder extends MarkupDocumentBuilder {
public SecurityDocumentBuilder(Swagger2MarkupConverter.Context context, Path outputPath) {
super(context, outputPath);
ResourceBundle labels = ResourceBundle.getBundle("io/github/robwin/swagger2markup/lang/labels", config.getOutputLanguage().toLocale());
ResourceBundle labels = ResourceBundle.getBundle("io/github/swagger2markup/lang/labels", config.getOutputLanguage().toLocale());
SECURITY = labels.getString("security");
TYPE = labels.getString("security_type");
NAME = labels.getString("security_name");
@@ -82,9 +83,9 @@ public class SecurityDocumentBuilder extends MarkupDocumentBuilder {
}
private void buildSecuritySchemeDefinitionsSection(Map<String, SecuritySchemeDefinition> definitions) {
for (Map.Entry<String, SecuritySchemeDefinition> entry : definitions.entrySet()) {
String definitionName = entry.getKey();
SecuritySchemeDefinition definition = entry.getValue();
Set<String> definitionNames = toKeySet(definitions, config.getDefinitionOrdering());
for (String definitionName : definitionNames) {
SecuritySchemeDefinition definition = definitions.get(definitionName);
buildSecuritySchemeDefinitionTitle(definitionName);
applySecurityDocumentExtension(new Context(Position.DEFINITION_BEGIN, markupDocBuilder, definitionName, definition));
buildDescriptionParagraph(definition.getDescription());
@@ -130,7 +131,7 @@ public class SecurityDocumentBuilder extends MarkupDocumentBuilder {
* @param context context
*/
private void applySecurityDocumentExtension(Context context) {
for (SecurityDocumentExtension extension : globalContext.getExtensionRegistry().getExtensions(SecurityDocumentExtension.class)) {
for (SecurityDocumentExtension extension : globalContext.getExtensionRegistry().getSecurityDocumentExtensions()) {
extension.apply(context);
}
}

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package io.github.robwin.swagger2markup.internal.type;
package io.github.swagger2markup.internal.type;
import io.github.robwin.markup.builder.MarkupDocBuilder;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package io.github.robwin.swagger2markup.internal.type;
package io.github.swagger2markup.internal.type;
import io.github.robwin.markup.builder.MarkupDocBuilder;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package io.github.robwin.swagger2markup.internal.type;
package io.github.swagger2markup.internal.type;
import com.google.common.base.Function;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package io.github.robwin.swagger2markup.internal.type;
package io.github.swagger2markup.internal.type;
import io.github.robwin.markup.builder.MarkupDocBuilder;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package io.github.robwin.swagger2markup.internal.type;
package io.github.swagger2markup.internal.type;
import io.github.robwin.markup.builder.MarkupDocBuilder;
import io.swagger.models.properties.Property;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package io.github.robwin.swagger2markup.internal.type;
package io.github.swagger2markup.internal.type;
import io.github.robwin.markup.builder.MarkupDocBuilder;
@@ -36,7 +36,7 @@ public class RefType extends Type {
@Override
public String displaySchema(MarkupDocBuilder docBuilder) {
return docBuilder.copy().crossReference(getDocument(), getUniqueName(), getName()).toString();
return docBuilder.copy(false).crossReference(getDocument(), getUniqueName(), getName()).toString();
}
public String getDocument() {

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package io.github.robwin.swagger2markup.internal.type;
package io.github.swagger2markup.internal.type;
import io.github.robwin.markup.builder.MarkupDocBuilder;
import org.apache.commons.lang3.Validate;

View File

@@ -14,10 +14,10 @@
* limitations under the License.
*/
package io.github.robwin.swagger2markup.internal.utils;
package io.github.swagger2markup.internal.utils;
import io.github.robwin.markup.builder.MarkupDocBuilder;
import io.github.robwin.swagger2markup.internal.model.PathOperation;
import io.github.swagger2markup.model.PathOperation;
import io.swagger.models.*;
import io.swagger.models.parameters.*;
import io.swagger.models.properties.ArrayProperty;
@@ -27,7 +27,6 @@ import io.swagger.models.properties.RefProperty;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@@ -39,11 +38,14 @@ public class ExamplesUtil {
/**
* Generates a Map of response examples
*
* @param generateMissingExamples specifies the missing examples should be generated
* @param operation the Swagger Operation
* @param definitions the map of definitions
* @param markupDocBuilder the markup builder
* @return map containing response examples.
*/
public static Map<String, Object> generateResponseExampleMap(boolean generateMissingExamples, Operation operation, Map<String, Model> definitions, MarkupDocBuilder markupDocBuilder) {
Map<String, Object> examples = new HashMap<>();
Map<String, Object> examples = new LinkedHashMap<>();
Map<String, Response> responses = operation.getResponses();
for (Map.Entry<String, Response> responseEntry : responses.entrySet()) {
Response response = responseEntry.getValue();
@@ -74,13 +76,16 @@ public class ExamplesUtil {
/**
* Generates examples for request
*
* @param generateMissingExamples specifies the missing examples should be generated
* @param pathOperation the Swagger Operation
* @param definitions the map of definitions
* @param markupDocBuilder the markup builder
* @return an Optional with the example content
*/
public static Map<String, Object> generateRequestExampleMap(boolean generateMissingExamples, PathOperation pathOperation, Map<String, Model> definitions, MarkupDocBuilder markupDocBuilder) {
Operation operation = pathOperation.getOperation();
List<Parameter> parameters = operation.getParameters();
Map<String, Object> examples = new HashMap<>();
Map<String, Object> examples = new LinkedHashMap<>();
// Path example should always be included (if generateMissingExamples):
if (generateMissingExamples)
@@ -115,7 +120,7 @@ public class ExamplesUtil {
if (abstractSerializableParameterExample == null) {
Property item = ((AbstractSerializableParameter) parameter).getItems();
if (item != null) {
abstractSerializableParameterExample = PropertyUtils.convertExample(item.getExample(), item.getType());
abstractSerializableParameterExample = item.getExample();
if (abstractSerializableParameterExample == null) {
abstractSerializableParameterExample = PropertyUtils.generateExample(item, markupDocBuilder);
}
@@ -136,7 +141,7 @@ public class ExamplesUtil {
@SuppressWarnings("unchecked")
Map<String, Object> queryExampleMap = (Map<String, Object>) examples.get("query");
if (queryExampleMap == null) {
queryExampleMap = new HashMap<>();
queryExampleMap = new LinkedHashMap<>();
}
queryExampleMap.put(parameter.getName(), abstractSerializableParameterExample);
example = queryExampleMap;
@@ -157,7 +162,10 @@ public class ExamplesUtil {
/**
* Generates an example object from a simple reference
*
* @param generateMissingExamples specifies the missing examples should be generated
* @param simpleRef the simple reference string
* @param definitions the map of definitions
* @param markupDocBuilder the markup builder
* @return returns an Object or Map of examples
*/
public static Object generateExampleForRefModel(boolean generateMissingExamples, String simpleRef, Map<String, Model> definitions, MarkupDocBuilder markupDocBuilder) {
@@ -205,13 +213,16 @@ public class ExamplesUtil {
* Generates a map of examples from a map of properties. If defined examples are found, those are used. Otherwise,
* examples are generated from the type.
*
* @param properties map of properties
* @param properties the map of properties
* @param definitions the map of definitions
* @param markupDocBuilder the markup builder
*
* @return a Map of examples
*/
public static Map<String, Object> exampleMapForProperties(Map<String, Property> properties, Map<String, Model> definitions, MarkupDocBuilder markupDocBuilder) {
Map<String, Object> exampleMap = new HashMap<>();
Map<String, Object> exampleMap = new LinkedHashMap<>();
for (Map.Entry<String, Property> property : properties.entrySet()) {
Object exampleObject = PropertyUtils.convertExample(property.getValue().getExample(), property.getValue().getType());
Object exampleObject = property.getValue().getExample();
if (exampleObject == null) {
if (property.getValue() instanceof RefProperty) {
exampleObject = generateExampleForRefModel(true, ((RefProperty) property.getValue()).getSimpleRef(), definitions, markupDocBuilder);
@@ -234,7 +245,7 @@ public class ExamplesUtil {
if (property.getExample() != null) {
return property.getExample();
}
Map<String, Object> exampleMap = new HashMap<>();
Map<String, Object> exampleMap = new LinkedHashMap<>();
Property valueProperty = property.getAdditionalProperties();
if (valueProperty.getExample() != null) {
return valueProperty.getExample();
@@ -251,7 +262,7 @@ public class ExamplesUtil {
} else {
Property itemProperty = model.getItems();
if (itemProperty.getExample() != null) {
return new Object[]{PropertyUtils.convertExample(itemProperty.getExample(), itemProperty.getType())};
return new Object[]{itemProperty.getExample()};
} else if (itemProperty instanceof ArrayProperty) {
return new Object[]{generateExampleForArrayProperty((ArrayProperty) itemProperty, definitions, markupDocBuilder)};
} else if (itemProperty instanceof RefProperty) {
@@ -266,12 +277,14 @@ public class ExamplesUtil {
* Generates examples from an ArrayProperty
*
* @param value ArrayProperty
* @param definitions map of definitions
* @param markupDocBuilder the markup builder
* @return array of Object
*/
public static Object[] generateExampleForArrayProperty(ArrayProperty value, Map<String, Model> definitions, MarkupDocBuilder markupDocBuilder) {
Property property = value.getItems();
if (property.getExample() != null) {
return new Object[]{PropertyUtils.convertExample(property.getExample(), property.getType())};
return new Object[]{property.getExample()};
} else if (property instanceof ArrayProperty) {
return new Object[]{generateExampleForArrayProperty((ArrayProperty) property, definitions, markupDocBuilder)};
} else if (property instanceof RefProperty) {

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.robwin.swagger2markup.internal.utils;
package io.github.swagger2markup.internal.utils;
import java.util.*;

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.robwin.swagger2markup.internal.utils;
package io.github.swagger2markup.internal.utils;
import java.util.*;

View File

@@ -13,13 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.robwin.swagger2markup.internal.utils;
package io.github.swagger2markup.internal.utils;
import com.google.common.base.Function;
import io.github.robwin.swagger2markup.internal.type.ArrayType;
import io.github.robwin.swagger2markup.internal.type.ObjectType;
import io.github.robwin.swagger2markup.internal.type.RefType;
import io.github.robwin.swagger2markup.internal.type.Type;
import io.github.swagger2markup.internal.type.ArrayType;
import io.github.swagger2markup.internal.type.ObjectType;
import io.github.swagger2markup.internal.type.RefType;
import io.github.swagger2markup.internal.type.Type;
import io.swagger.models.ArrayModel;
import io.swagger.models.Model;
import io.swagger.models.ModelImpl;
@@ -32,6 +32,7 @@ public final class ModelUtils {
* Retrieves the type of a model, or otherwise null
*
* @param model the model
* @param definitionDocumentResolver the definition document resolver
* @return the type of the model, or otherwise null
*/
public static Type getType(Model model, Function<String, String> definitionDocumentResolver) {

View File

@@ -13,11 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.robwin.swagger2markup.internal.utils;
package io.github.swagger2markup.internal.utils;
import com.google.common.base.Function;
import io.github.robwin.markup.builder.MarkupDocBuilder;
import io.github.robwin.swagger2markup.internal.type.*;
import io.github.swagger2markup.internal.type.*;
import io.swagger.models.Model;
import io.swagger.models.parameters.AbstractSerializableParameter;
import io.swagger.models.parameters.BodyParameter;
@@ -37,6 +37,7 @@ public final class ParameterUtils {
* Retrieves the type of a parameter, or otherwise null
*
* @param parameter the parameter
* @param definitionDocumentResolver the defintion document resolver
* @return the type of the parameter, or otherwise null
*/
public static Type getType(Parameter parameter, Function<String, String> definitionDocumentResolver){

View File

@@ -13,11 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.robwin.swagger2markup.internal.utils;
package io.github.swagger2markup.internal.utils;
import com.google.common.base.Function;
import io.github.robwin.markup.builder.MarkupDocBuilder;
import io.github.robwin.swagger2markup.internal.type.*;
import io.github.swagger2markup.internal.type.*;
import io.swagger.models.properties.*;
import io.swagger.models.refs.RefFormat;
import org.apache.commons.collections4.CollectionUtils;
@@ -33,6 +33,7 @@ public final class PropertyUtils {
* Retrieves the type and format of a property.
*
* @param property the property
* @param definitionDocumentResolver the definition document resolver
* @return the type of the property
*/
public static Type getType(Property property, Function<String, String> definitionDocumentResolver) {
@@ -105,6 +106,7 @@ public final class PropertyUtils {
/**
* Return example display string for the given {@code property}.
*
* @param generateMissingExamples specifies if missing examples should be generated
* @param property property
* @param markupDocBuilder doc builder
* @return property example display string
@@ -113,7 +115,7 @@ public final class PropertyUtils {
Validate.notNull(property, "property must not be null");
Object examplesValue = null;
if (property.getExample() != null) {
examplesValue = convertExample(property.getExample(), property.getType());
examplesValue = property.getExample();
} else if (property instanceof MapProperty) {
Property additionalProperty = ((MapProperty) property).getAdditionalProperties();
if (additionalProperty.getExample() != null) {
@@ -156,7 +158,7 @@ public final class PropertyUtils {
return "string";
case "ref":
if (property instanceof RefProperty) {
return markupDocBuilder.copy().crossReference(((RefProperty) property).getSimpleRef()).toString();
return markupDocBuilder.copy(false).crossReference(((RefProperty) property).getSimpleRef()).toString();
}
default:
return property.getType();

View File

@@ -13,13 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.robwin.swagger2markup.internal.utils;
package io.github.swagger2markup.internal.utils;
import com.google.common.base.Optional;
import com.google.common.collect.Multimap;
import com.google.common.collect.MultimapBuilder;
import com.google.common.collect.Ordering;
import io.github.robwin.swagger2markup.internal.model.PathOperation;
import io.github.swagger2markup.model.PathOperation;
import io.swagger.models.Tag;
import org.apache.commons.lang3.Validate;
import org.slf4j.Logger;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package io.github.robwin.swagger2markup.internal.model;
package io.github.swagger2markup.model;
import io.swagger.models.HttpMethod;
import io.swagger.models.Operation;
@@ -54,7 +54,7 @@ public class PathOperation {
}
/**
* Returns an unique id for the operation.<br/>
* Returns an unique id for the operation.<br>
* Use {@code <operation id>}, then {@code <operation path> lowercase(<operation method>)} if operation id is not set.
*
* @return operation unique id

View File

@@ -14,9 +14,9 @@
* limitations under the License.
*/
package io.github.robwin.swagger2markup.spi;
package io.github.swagger2markup.spi;
import io.github.robwin.swagger2markup.Swagger2MarkupConverter;
import io.github.swagger2markup.Swagger2MarkupConverter;
/**
* An abstract extension which must be extended by an extension

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package io.github.robwin.swagger2markup.spi;
package io.github.swagger2markup.spi;
import io.github.robwin.markup.builder.MarkupDocBuilder;

View File

@@ -14,17 +14,15 @@
* limitations under the License.
*/
package io.github.robwin.swagger2markup.spi;
import org.apache.commons.lang3.Validate;
package io.github.swagger2markup.spi;
import com.google.common.base.Optional;
import io.github.robwin.markup.builder.MarkupDocBuilder;
import io.swagger.models.Model;
import org.apache.commons.lang3.Validate;
/**
* A SecurityContentExtension can be used to extend the definitions document.
* DefinitionsDocumentExtension extension point can be used to extend the definitions document content.
*/
public abstract class DefinitionsDocumentExtension extends AbstractExtension {

View File

@@ -14,14 +14,14 @@
* limitations under the License.
*/
package io.github.robwin.swagger2markup.spi;
package io.github.swagger2markup.spi;
import io.github.robwin.swagger2markup.Swagger2MarkupConverter;
import io.github.swagger2markup.Swagger2MarkupConverter;
/**
* A marker interface which must be implemented by an extension
*/
public interface Extension {
interface Extension {
/**
* Global context lazy initialization

View File

@@ -14,12 +14,12 @@
* limitations under the License.
*/
package io.github.robwin.swagger2markup.spi;
package io.github.swagger2markup.spi;
import io.github.robwin.markup.builder.MarkupDocBuilder;
/**
* A SecurityContentExtension can be used to extend the overview document.
* OverviewDocumentExtension extension point can be used to extend the overview document content.
*/
public abstract class OverviewDocumentExtension extends AbstractExtension {

View File

@@ -14,16 +14,16 @@
* limitations under the License.
*/
package io.github.robwin.swagger2markup.spi;
package io.github.swagger2markup.spi;
import com.google.common.base.Optional;
import io.github.robwin.markup.builder.MarkupDocBuilder;
import io.github.robwin.swagger2markup.GroupBy;
import io.github.robwin.swagger2markup.internal.model.PathOperation;
import io.github.swagger2markup.GroupBy;
import io.github.swagger2markup.model.PathOperation;
import org.apache.commons.lang3.Validate;
/**
* A SecurityContentExtension can be used to extend the paths document.
* PathsDocumentExtension extension point can be used to extend the paths document content.
*/
public abstract class PathsDocumentExtension extends AbstractExtension {

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package io.github.robwin.swagger2markup.spi;
package io.github.swagger2markup.spi;
import com.google.common.base.Optional;
import io.github.robwin.markup.builder.MarkupDocBuilder;
@@ -22,7 +22,7 @@ import io.swagger.models.auth.SecuritySchemeDefinition;
import org.apache.commons.lang3.Validate;
/**
* A SecurityContentExtension can be used to extend the security document.
* SecurityContentExtension extension point can be used to extend the security document content.
*/
public abstract class SecurityDocumentExtension extends AbstractExtension {
@@ -32,7 +32,6 @@ public abstract class SecurityDocumentExtension extends AbstractExtension {
DOCUMENT_END,
DEFINITION_BEGIN,
DEFINITION_END
}
public static class Context extends ContentContext {

View File

@@ -14,12 +14,12 @@
* limitations under the License.
*/
package io.github.robwin.swagger2markup.spi;
package io.github.swagger2markup.spi;
import io.swagger.models.Swagger;
/**
* A SwaggerExtension can be used to preprocess the Swagger model.
* SwaggerModelExtension extension point can be used to preprocess the Swagger model.
*/
public abstract class SwaggerModelExtension extends AbstractExtension {

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package io.github.robwin.swagger2markup.internal.utils;
package io.github.swagger2markup.utils;
import org.apache.commons.lang3.StringUtils;
@@ -30,7 +30,7 @@ public class IOUtils {
private static final Pattern NAME_FORBIDDEN_PATTERN = Pattern.compile("[^0-9A-Za-z-_]+");
/**
* Create a normalized name from an arbitrary string.<br/>
* Create a normalized name from an arbitrary string.<br>
* Paths separators are replaced, so this function can't be applied on a whole path, but must be called on each path sections.
*
* @param name current name of the file
@@ -45,12 +45,12 @@ public class IOUtils {
}
/**
* Create a reader from specified {@code source}.<br/>
* Create a reader from specified {@code source}.<br>
* Returned reader should be explicitly closed after use.
*
* @param uri source URI
* @return reader
* @throws IOException
* @throws IOException if the connection cannot be opened
*/
public static Reader uriReader(URI uri) throws IOException {
return new BufferedReader(new InputStreamReader(uri.toURL().openStream(), StandardCharsets.UTF_8));
@@ -62,6 +62,6 @@ public class IOUtils {
* @return URI parent
*/
public static URI uriParent(URI uri) {
return uri.getPath().endsWith("/") ? uri.resolve("..") : uri.resolve(".");
return uri.getPath().endsWith("/") ? uri.resolve("src/main") : uri.resolve(".");
}
}

View File

@@ -1,88 +0,0 @@
/*
*
* Copyright 2016 Robert Winkler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*
*/
package io.github.robwin.swagger2markup.assertions;
import com.sksamuel.diffpatch.DiffMatchPatch;
import org.apache.commons.io.IOUtils;
import org.assertj.core.api.AbstractAssert;
import java.io.BufferedWriter;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.LinkedList;
import static org.assertj.core.api.Assertions.assertThat;
public class DiffAssert extends AbstractAssert<DiffAssert, Path>{
public DiffAssert(Path actual) {
super(actual, DiffAssert.class);
}
/**
* Verifies that the content of the actual File is equal to the given one.
*
* @param expected the given value to compare the actual value to.
* @param reportPath the path to the report which should be generated if the files differ.
* @return {@code this} assertion object.
* @throws AssertionError if the actual value is not equal to the given one or if the actual value is {@code null}..
*/
public DiffAssert isEqualTo(Path expected, Path reportPath) {
LinkedList<DiffMatchPatch.Diff> diffs = diff(actual, expected);
boolean allDiffsAreEqual = assertThatAllDiffsAreEqual(diffs);
if(!allDiffsAreEqual){
writeHtmlReport(reportPath, diffs);
}
assertThat(allDiffsAreEqual).as("The content of the following files differ. Actual: %s, Expected %s. Check the HTML report for more details: %s", actual.toAbsolutePath(), expected.toAbsolutePath(), reportPath.toAbsolutePath()).isTrue();
return myself;
}
public boolean assertThatAllDiffsAreEqual(LinkedList<DiffMatchPatch.Diff> diffs){
for(DiffMatchPatch.Diff diff : diffs){
if(diff.operation == DiffMatchPatch.Operation.DELETE || diff.operation == DiffMatchPatch.Operation.INSERT){
return false;
}
}
return true;
}
private static LinkedList<DiffMatchPatch.Diff> diff(Path actual, Path expected){
DiffMatchPatch differ = new DiffMatchPatch();
try {
return differ.diff_main(IOUtils.toString(expected.toUri()), IOUtils.toString(actual.toUri()), false);
} catch (IOException e) {
throw new RuntimeException("Failed to diff files.", e);
}
}
private static void writeHtmlReport(Path reportPath, LinkedList<DiffMatchPatch.Diff> diffs){
DiffMatchPatch differ = new DiffMatchPatch();
try {
Files.createDirectories(reportPath.getParent());
try (BufferedWriter writer = Files.newBufferedWriter(reportPath, Charset.forName("UTF-8"))) {
writer.write(differ.diff_prettyHtml(diffs));
}
} catch (IOException e) {
throw new RuntimeException(String.format("Failed to write report %s", reportPath.toAbsolutePath()), e);
}
}
}

View File

@@ -1,43 +0,0 @@
/*
*
* Copyright 2016 Robert Winkler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*
*/
package io.github.robwin.swagger2markup.assertions;
import org.apache.commons.lang3.Validate;
import java.nio.file.Path;
/**
* Entry point for assertion methods for diffing files.
*
* @author Robert Winkler
*/
public class DiffAssertions {
/**
* Creates a new instance of <code>{@link DiffAssert}</code>.
*
* @param actual the the actual File path.
* @return the created assertion object.
*/
public static DiffAssert assertThat(Path actual) {
Validate.notNull(actual, "actual must not be null");
return new DiffAssert(actual);
}
}

View File

@@ -1,69 +0,0 @@
/*
* Copyright 2016 Robert Winkler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.robwin.swagger2markup.spi;
import io.github.robwin.swagger2markup.Swagger2MarkupExtensionRegistry;
import io.github.robwin.swagger2markup.internal.extensions.DynamicDefinitionsDocumentExtension;
import io.github.robwin.swagger2markup.internal.extensions.DynamicPathsDocumentExtension;
import io.swagger.models.Swagger;
import org.junit.Test;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.fail;
public class Swagger2MarkupExtensionRegistryTest {
@Test
public void testRegistering() {
Swagger2MarkupExtensionRegistry.Builder registryBuilder = Swagger2MarkupExtensionRegistry.ofDefaults();
registryBuilder.withExtension(new MySwaggerModelExtension());
registryBuilder.withExtension(new DynamicDefinitionsDocumentExtension(Paths.get("src/test/resources/docs/asciidoc/extensions")));
registryBuilder.withExtension(new DynamicPathsDocumentExtension(Paths.get("src/test/resources/docs/asciidoc/extensions")));
try {
registryBuilder.withExtension(new AbstractExtension() {
});
fail("No IllegalArgumentException thrown");
} catch (IllegalArgumentException e) {
assertThat(e.getMessage()).isEqualTo("Provided extension class does not extend any of the supported extension points");
}
}
@Test
public void testListing() {
Extension ext1 = new MySwaggerModelExtension();
Extension ext2 = new MySwaggerModelExtension();
Extension ext3 = new SwaggerModelExtension() {
public void apply(Swagger swagger) {
}
};
Swagger2MarkupExtensionRegistry registry = Swagger2MarkupExtensionRegistry.ofDefaults()
.withExtension(ext2)
.withExtension(ext3)
.withExtension(ext1)
.build();
List<Extension> extensions = registry.getExtensions(Extension.class);
assertThat(extensions.size()).isEqualTo(7);
assertThat(extensions).contains(ext1, ext2, ext3);
assertThat(registry.getExtensions(SwaggerModelExtension.class)).isEqualTo(Arrays.asList(ext2, ext3, ext1));
}
}

View File

@@ -13,13 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.robwin.swagger2markup;
package io.github.swagger2markup;
import io.github.robwin.swagger2markup.assertions.DiffUtils;
import io.github.robwin.swagger2markup.internal.extensions.DynamicDefinitionsDocumentExtension;
import io.github.robwin.swagger2markup.internal.extensions.DynamicPathsDocumentExtension;
import io.github.robwin.swagger2markup.internal.extensions.SchemaExtension;
import io.github.robwin.swagger2markup.internal.extensions.SpringRestDocsExtension;
import io.github.swagger2markup.assertions.DiffUtils;
import io.github.swagger2markup.builder.Swagger2MarkupConfigBuilder;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.junit.Before;
@@ -72,7 +69,7 @@ public class AsciidocConverterTest {
FileUtils.deleteQuietly(outputDirectory.toFile());
//When
Swagger2MarkupConfig config = Swagger2MarkupConfig.ofDefaults()
Swagger2MarkupConfig config = new Swagger2MarkupConfigBuilder()
.build();
Swagger2MarkupConverter.from(file).withConfig(config).build()
@@ -94,7 +91,7 @@ public class AsciidocConverterTest {
FileUtils.deleteQuietly(outputDirectory.toFile());
//When
Swagger2MarkupConfig config = Swagger2MarkupConfig.ofDefaults()
Swagger2MarkupConfig config = new Swagger2MarkupConfigBuilder()
.build();
Swagger2MarkupConverter.from(swaggerJsonString).withConfig(config).build()
@@ -108,35 +105,6 @@ public class AsciidocConverterTest {
DiffUtils.assertThatAllFilesAreEqual(outputDirectory, expectedFilesDirectory, "testSwagger2AsciiDocConversion.html");
}
@Test
public void testSwagger2AsciiDocConversionWithSpringRestDocsExtension() throws IOException, URISyntaxException {
//Given
String swaggerJsonString = IOUtils.toString(getClass().getResourceAsStream("/yaml/swagger_petstore.yaml"));
Path outputDirectory = Paths.get("build/docs/asciidoc/spring_rest_docs");
FileUtils.deleteQuietly(outputDirectory.toFile());
//When
Swagger2MarkupExtensionRegistry registry = Swagger2MarkupExtensionRegistry.ofEmpty()
.withExtension(new SpringRestDocsExtension(Paths.get("src/test/resources/docs/asciidoc/paths").toUri()).withDefaultSnippets())
.build();
Swagger2MarkupConfig config = Swagger2MarkupConfig.ofDefaults()
.build();
Swagger2MarkupConverter.from(swaggerJsonString)
.withConfig(config)
.withExtensionRegistry(registry)
.build()
.intoFolder(outputDirectory);
//Then
String[] files = outputDirectory.toFile().list();
assertThat(files).hasSize(4).containsAll(expectedFiles);
Path expectedFilesDirectory = Paths.get(AsciidocConverterTest.class.getResource("/expected_results/asciidoc/spring_rest_docs").toURI());
DiffUtils.assertThatAllFilesAreEqual(outputDirectory, expectedFilesDirectory, "testSwagger2AsciiDocConversionWithSpringRestDocsExtension.html");
}
@Test
public void testSwagger2AsciiDocConversionWithExamples() throws IOException, URISyntaxException {
//Given
@@ -145,7 +113,7 @@ public class AsciidocConverterTest {
FileUtils.deleteQuietly(outputDirectory.toFile());
//When
Swagger2MarkupConfig config = Swagger2MarkupConfig.ofDefaults()
Swagger2MarkupConfig config = new Swagger2MarkupConfigBuilder()
.build();
Swagger2MarkupConverter.from(swaggerJsonString)
@@ -168,7 +136,7 @@ public class AsciidocConverterTest {
FileUtils.deleteQuietly(outputDirectory.toFile());
//When
Swagger2MarkupConfig config = Swagger2MarkupConfig.ofDefaults()
Swagger2MarkupConfig config = new Swagger2MarkupConfigBuilder()
.withGeneratedExamples()
.build();
@@ -192,7 +160,7 @@ public class AsciidocConverterTest {
FileUtils.deleteQuietly(outputDirectory.toFile());
//When
Swagger2MarkupConfig config = Swagger2MarkupConfig.ofDefaults()
Swagger2MarkupConfig config = new Swagger2MarkupConfigBuilder()
.withInlineSchemaDepthLevel(1)
.build();
Swagger2MarkupConverter.from(file)
@@ -214,7 +182,7 @@ public class AsciidocConverterTest {
Path outputDirectory = Paths.get("build/docs/asciidoc/group_by_tags");
FileUtils.deleteQuietly(outputDirectory.toFile());
//When
Swagger2MarkupConfig config = Swagger2MarkupConfig.ofDefaults()
Swagger2MarkupConfig config = new Swagger2MarkupConfigBuilder()
.withPathsGroupedBy(GroupBy.TAGS)
.build();
Swagger2MarkupConverter.from(file)
@@ -237,7 +205,7 @@ public class AsciidocConverterTest {
FileUtils.deleteQuietly(outputDirectory.toFile());
//When
try {
Swagger2MarkupConfig config = Swagger2MarkupConfig.ofDefaults()
Swagger2MarkupConfig config = new Swagger2MarkupConfigBuilder()
.withPathsGroupedBy(GroupBy.TAGS)
.build();
@@ -260,7 +228,7 @@ public class AsciidocConverterTest {
FileUtils.deleteQuietly(outputDirectory.toFile());
//When
Swagger2MarkupConfig config = Swagger2MarkupConfig.ofDefaults()
Swagger2MarkupConfig config = new Swagger2MarkupConfigBuilder()
.withDefinitionDescriptions(Paths.get("src/test/resources/docs/asciidoc/definitions"))
.build();
@@ -320,7 +288,7 @@ public class AsciidocConverterTest {
FileUtils.deleteQuietly(outputDirectory.toFile());
//When
Swagger2MarkupConfig config = Swagger2MarkupConfig.ofDefaults()
Swagger2MarkupConfig config = new Swagger2MarkupConfigBuilder()
.withSeparatedDefinitions()
.build();
Swagger2MarkupConverter.from(file).withConfig(config).build()
@@ -345,7 +313,7 @@ public class AsciidocConverterTest {
FileUtils.deleteQuietly(outputDirectory.toFile());
//When
Swagger2MarkupConfig config = Swagger2MarkupConfig.ofDefaults()
Swagger2MarkupConfig config = new Swagger2MarkupConfigBuilder()
.withSeparatedOperations()
.build();
Swagger2MarkupConverter.from(file).withConfig(config).build()
@@ -369,7 +337,7 @@ public class AsciidocConverterTest {
FileUtils.deleteQuietly(outputDirectory.toFile());
//When
Swagger2MarkupConfig config = Swagger2MarkupConfig.ofDefaults()
Swagger2MarkupConfig config = new Swagger2MarkupConfigBuilder()
.withOutputLanguage(Language.RU)
.build();
Swagger2MarkupConverter.from(file)
@@ -390,7 +358,7 @@ public class AsciidocConverterTest {
FileUtils.deleteQuietly(outputDirectory.toFile());
//When
Swagger2MarkupConfig config = Swagger2MarkupConfig.ofDefaults()
Swagger2MarkupConfig config = new Swagger2MarkupConfigBuilder()
.withOutputLanguage(Language.FR)
.build();
Swagger2MarkupConverter.from(file)
@@ -402,58 +370,4 @@ public class AsciidocConverterTest {
assertThat(new String(Files.readAllBytes(outputDirectory.resolve("overview.adoc")), Charset.forName("UTF-8")))
.contains("== Sch\u00E9ma d'URI");
}
@Test
public void testSwagger2AsciiDocExtensions() throws IOException, URISyntaxException {
//Given
Path file = Paths.get(AsciidocConverterTest.class.getResource("/yaml/swagger_petstore.yaml").toURI());
Path outputDirectory = Paths.get("build/docs/asciidoc/generated");
FileUtils.deleteQuietly(outputDirectory.toFile());
//When
Swagger2MarkupConfig config = Swagger2MarkupConfig.ofDefaults()
.build();
Swagger2MarkupExtensionRegistry registry = Swagger2MarkupExtensionRegistry.ofEmpty()
.withExtension(new DynamicDefinitionsDocumentExtension(Paths.get("src/test/resources/docs/asciidoc/extensions")))
.withExtension(new DynamicPathsDocumentExtension(Paths.get("src/test/resources/docs/asciidoc/extensions")))
.build();
Swagger2MarkupConverter.from(file)
.withConfig(config)
.withExtensionRegistry(registry)
.build()
.intoFolder(outputDirectory);
//Then
assertThat(new String(Files.readAllBytes(outputDirectory.resolve("paths.adoc")))).contains(
"Pet update request extension");
assertThat(new String(Files.readAllBytes(outputDirectory.resolve("definitions.adoc")))).contains(
"Pet extension");
}
@Test
public void testSwagger2AsciiDocSchemaExtension() throws IOException, URISyntaxException {
//Given
Path file = Paths.get(AsciidocConverterTest.class.getResource("/yaml/swagger_petstore.yaml").toURI());
Path outputDirectory = Paths.get("build/docs/asciidoc/generated");
FileUtils.deleteQuietly(outputDirectory.toFile());
//When
Swagger2MarkupConfig config = Swagger2MarkupConfig.ofDefaults()
.build();
Swagger2MarkupExtensionRegistry registry = Swagger2MarkupExtensionRegistry.ofEmpty()
.withExtension(new SchemaExtension(Paths.get("src/test/resources/docs/asciidoc/extensions").toUri()))
.build();
Swagger2MarkupConverter.from(file)
.withConfig(config)
.withExtensionRegistry(registry)
.build()
.intoFolder(outputDirectory);
//Then
assertThat(new String(Files.readAllBytes(outputDirectory.resolve("definitions.adoc")))).contains(
"=== Pet");
assertThat(new String(Files.readAllBytes(outputDirectory.resolve("definitions.adoc")))).contains(
"==== XML Schema");
}
}

View File

@@ -13,28 +13,26 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.robwin.swagger2markup;
package io.github.swagger2markup;
import io.swagger.models.Swagger;
import io.github.swagger2markup.builder.Swagger2MarkupConfigBuilder;
import org.junit.Test;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.file.Path;
import java.nio.file.Paths;
import static org.assertj.core.api.Assertions.assertThat;
public class GeneralConverterTest {
/*
@Test
public void testConfigDefaultPaths() throws URISyntaxException {
//Given
Path file = Paths.get(GeneralConverterTest.class.getResource("/yaml/swagger_petstore.yaml").toURI());
//When
Swagger2MarkupConfig config = Swagger2MarkupConfig.ofDefaults()
Swagger2MarkupConfig config = new Swagger2MarkupConfigBuilder()
.withDefinitionDescriptions()
.withOperationDescriptions()
.build();
@@ -44,17 +42,18 @@ public class GeneralConverterTest {
.build();
//Then
URI baseUri = io.github.robwin.swagger2markup.internal.utils.IOUtils.uriParent(converter.getContext().getSwaggerLocation());
URI baseUri = IOUtils.uriParent(converter.getContext().getSwaggerLocation());
assertThat(converter.getContext().getConfig().getDefinitionDescriptionsUri()).isEqualTo(baseUri);
assertThat(converter.getContext().getConfig().getOperationDescriptionsUri()).isEqualTo(baseUri);
}
*/
@Test
public void testConfigDefaultPathsWithUri() throws MalformedURLException {
//Given
//When
Swagger2MarkupConfig config = Swagger2MarkupConfig.ofDefaults()
Swagger2MarkupConfig config = new Swagger2MarkupConfigBuilder()
.withDefinitionDescriptions()
.withOperationDescriptions()
.build();
@@ -68,11 +67,12 @@ public class GeneralConverterTest {
assertThat(converterBuilder.getContext().getConfig().getOperationDescriptionsUri()).isNull();
}
/*
@Test
public void testDefaultPathsWithoutFile() {
//Given
//When
Swagger2MarkupConfig config = Swagger2MarkupConfig.ofDefaults()
Swagger2MarkupConfig config = new Swagger2MarkupConfigBuilder()
.withDefinitionDescriptions()
.build();
@@ -82,4 +82,5 @@ public class GeneralConverterTest {
.build();
assertThat(converter.getContext().getConfig().isDefinitionDescriptionsEnabled()).isFalse();
}
*/
}

View File

@@ -13,16 +13,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.robwin.swagger2markup;
package io.github.swagger2markup;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import io.github.robwin.markup.builder.MarkupLanguage;
import io.github.robwin.swagger2markup.assertions.DiffUtils;
import io.github.robwin.swagger2markup.internal.extensions.DynamicDefinitionsDocumentExtension;
import io.github.robwin.swagger2markup.internal.extensions.DynamicPathsDocumentExtension;
import io.github.swagger2markup.assertions.DiffUtils;
import io.github.swagger2markup.builder.Swagger2MarkupConfigBuilder;
import org.apache.commons.io.FileUtils;
import org.junit.Before;
import org.junit.Test;
@@ -66,7 +65,7 @@ public class MarkdownConverterTest {
FileUtils.deleteQuietly(outputDirectory.toFile());
//When
Swagger2MarkupConfig config = Swagger2MarkupConfig.ofDefaults()
Swagger2MarkupConfig config = new Swagger2MarkupConfigBuilder()
.withMarkupLanguage(MarkupLanguage.MARKDOWN)
.build();
Swagger2MarkupConverter.from(file)
@@ -90,7 +89,7 @@ public class MarkdownConverterTest {
FileUtils.deleteQuietly(outputDirectory.toFile());
//When
Swagger2MarkupConfig config = Swagger2MarkupConfig.ofDefaults()
Swagger2MarkupConfig config = new Swagger2MarkupConfigBuilder()
.withDefinitionDescriptions(Paths.get("src/test/resources/docs/markdown/definitions"))
.withMarkupLanguage(MarkupLanguage.MARKDOWN)
.build();
@@ -112,7 +111,7 @@ public class MarkdownConverterTest {
FileUtils.deleteQuietly(outputDirectory.toFile());
//When
Swagger2MarkupConfig config = Swagger2MarkupConfig.ofDefaults()
Swagger2MarkupConfig config = new Swagger2MarkupConfigBuilder()
.withSeparatedDefinitions()
.withMarkupLanguage(MarkupLanguage.MARKDOWN)
.build();
@@ -140,7 +139,7 @@ public class MarkdownConverterTest {
FileUtils.deleteQuietly(outputDirectory.toFile());
//When
Swagger2MarkupConfig config = Swagger2MarkupConfig.ofDefaults()
Swagger2MarkupConfig config = new Swagger2MarkupConfigBuilder()
.withSeparatedDefinitions()
.withMarkupLanguage(MarkupLanguage.MARKDOWN)
.build();
@@ -164,35 +163,6 @@ public class MarkdownConverterTest {
}
@Test
public void testSwagger2MarkdownExtensions() throws IOException, URISyntaxException {
//Given
Path file = Paths.get(MarkdownConverterTest.class.getResource("/yaml/swagger_petstore.yaml").toURI());
Path outputDirectory = Paths.get("build/docs/markdown/generated");
FileUtils.deleteQuietly(outputDirectory.toFile());
//When
Swagger2MarkupConfig config = Swagger2MarkupConfig.ofDefaults()
.withMarkupLanguage(MarkupLanguage.MARKDOWN)
.build();
Swagger2MarkupExtensionRegistry registry = Swagger2MarkupExtensionRegistry.ofEmpty()
.withExtension(new DynamicDefinitionsDocumentExtension(Paths.get("src/test/resources/docs/markdown/extensions")))
.withExtension(new DynamicPathsDocumentExtension(Paths.get("src/test/resources/docs/markdown/extensions")))
.build();
Swagger2MarkupConverter.from(file)
.withConfig(config)
.withExtensionRegistry(registry)
.build()
.intoFolder(outputDirectory);
//Then
assertThat(new String(Files.readAllBytes(outputDirectory.resolve("paths.md")))).contains(
"Pet update request extension");
assertThat(new String(Files.readAllBytes(outputDirectory.resolve("definitions.md")))).contains(
"Pet extension");
}
/**
* Given a markdown document to search, this checks to see if the specified tables
* have all of the expected fields listed.

View File

@@ -16,8 +16,9 @@
*
*
*/
package io.github.robwin.swagger2markup.assertions;
package io.github.swagger2markup.assertions;
import io.github.robwin.diff.DiffAssertions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

View File

@@ -13,8 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.robwin.swagger2markup.spi;
package io.github.swagger2markup.builder;
import io.github.swagger2markup.spi.SwaggerModelExtension;
import io.swagger.models.Swagger;
public class MySwaggerModelExtension extends SwaggerModelExtension {

View File

@@ -13,23 +13,35 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.robwin.swagger2markup;
package io.github.swagger2markup.builder;
import com.google.common.collect.Ordering;
import io.github.robwin.markup.builder.MarkupLanguage;
import io.github.swagger2markup.GroupBy;
import io.github.swagger2markup.Language;
import io.github.swagger2markup.OrderBy;
import io.github.swagger2markup.Swagger2MarkupConfig;
import org.junit.Test;
import java.io.IOException;
import java.net.URI;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import static org.assertj.core.api.BDDAssertions.assertThat;
public class Swagger2MarkupConfigTest {
public class Swagger2MarkupConfigBuilderTest {
@Test
public void testConfigOfDefaults() {
Swagger2MarkupConfig config = Swagger2MarkupConfig.ofDefaults().build();
Map<String, String> extensionsProperties = new HashMap<>();
extensionsProperties.put("swagger2markup.extensions.uniqueId1.customProperty1", "123");
extensionsProperties.put("swagger2markup.extensions.uniqueId1.customProperty2", "123");
Swagger2MarkupConfig config = new Swagger2MarkupConfigBuilder()
.withExtensionsProperties(extensionsProperties)
.build();
assertThat(config.getAnchorPrefix()).isNull();
assertThat(config.getDefinitionOrderBy()).isEqualTo(OrderBy.NATURAL);
@@ -48,7 +60,7 @@ public class Swagger2MarkupConfigTest {
assertThat(config.getOutputLanguage()).isEqualTo(Language.EN);
assertThat(config.getOverviewDocument()).isEqualTo("overview");
assertThat(config.getParameterOrderBy()).isEqualTo(OrderBy.NATURAL);
assertThat(config.getParameterOrdering()).isEqualTo(Swagger2MarkupConfig.Builder.PARAMETER_IN_NATURAL_ORDERING.compound(Swagger2MarkupConfig.Builder.PARAMETER_NAME_NATURAL_ORDERING));
assertThat(config.getParameterOrdering()).isEqualTo(Swagger2MarkupConfigBuilder.PARAMETER_IN_NATURAL_ORDERING.compound(Swagger2MarkupConfigBuilder.PARAMETER_NAME_NATURAL_ORDERING));
assertThat(config.getPathsDocument()).isEqualTo("paths");
assertThat(config.getOperationsGroupedBy()).isEqualTo(GroupBy.AS_IS);
assertThat(config.getPropertyOrderBy()).isEqualTo(OrderBy.NATURAL);
@@ -64,6 +76,10 @@ public class Swagger2MarkupConfigTest {
assertThat(config.isInterDocumentCrossReferencesEnabled()).isFalse();
assertThat(config.isSeparatedDefinitionsEnabled()).isFalse();
assertThat(config.isSeparatedOperationsEnabled()).isFalse();
assertThat(config.getExtensionsProperties()).hasSize(2)
.containsKeys("swagger2markup.extensions.uniqueId1.customProperty1",
"swagger2markup.extensions.uniqueId1.customProperty2"
);
}
@@ -71,9 +87,9 @@ public class Swagger2MarkupConfigTest {
public void testConfigOfProperties() throws IOException {
Properties properties = new Properties();
properties.load(Swagger2MarkupConfigTest.class.getResourceAsStream("/config/config.properties"));
properties.load(Swagger2MarkupConfigBuilderTest.class.getResourceAsStream("/config/config.properties"));
Swagger2MarkupConfig config = Swagger2MarkupConfig.ofProperties(properties).build();
Swagger2MarkupConfig config = new Swagger2MarkupConfigBuilder(properties).build();
assertThat(config.getAnchorPrefix()).isEqualTo("anchorPrefix");
assertThat(config.getDefinitionOrderBy()).isEqualTo(OrderBy.AS_IS);
@@ -88,7 +104,7 @@ public class Swagger2MarkupConfigTest {
assertThat(config.getInterDocumentCrossReferencesPrefix()).isEqualTo("xrefPrefix");
assertThat(config.getMarkupLanguage()).isEqualTo(MarkupLanguage.MARKDOWN);
assertThat(config.getOperationOrderBy()).isEqualTo(OrderBy.NATURAL);
assertThat(config.getOperationOrdering()).isEqualTo(Swagger2MarkupConfig.Builder.OPERATION_PATH_NATURAL_ORDERING.compound(Swagger2MarkupConfig.Builder.OPERATION_METHOD_NATURAL_ORDERING));
assertThat(config.getOperationOrdering()).isEqualTo(Swagger2MarkupConfigBuilder.OPERATION_PATH_NATURAL_ORDERING.compound(Swagger2MarkupConfigBuilder.OPERATION_METHOD_NATURAL_ORDERING));
assertThat(config.getOutputLanguage()).isEqualTo(Language.RU);
assertThat(config.getOverviewDocument()).isEqualTo("overviewTest");
assertThat(config.getParameterOrderBy()).isEqualTo(OrderBy.AS_IS);
@@ -108,11 +124,17 @@ public class Swagger2MarkupConfigTest {
assertThat(config.isInterDocumentCrossReferencesEnabled()).isTrue();
assertThat(config.isSeparatedDefinitionsEnabled()).isTrue();
assertThat(config.isSeparatedOperationsEnabled()).isTrue();
assertThat(config.getExtensionsProperties()).hasSize(4)
.containsKeys("swagger2markup.extensions.uniqueId1.customProperty1",
"swagger2markup.extensions.uniqueId1.customProperty2",
"swagger2markup.extensions.uniqueId2.customProperty1",
"swagger2markup.extensions.uniqueId2.customProperty2"
);
}
@Test
public void testConfigBuilder() {
Swagger2MarkupConfig.Builder builder = Swagger2MarkupConfig.ofDefaults();
Swagger2MarkupConfigBuilder builder = new Swagger2MarkupConfigBuilder();
try {
builder.withTagOrdering(OrderBy.CUSTOM);
@@ -128,9 +150,9 @@ public class Swagger2MarkupConfigTest {
} catch (IllegalArgumentException e) {
assertThat(e.getMessage()).isEqualTo("You must provide a custom comparator if orderBy == OrderBy.CUSTOM");
}
builder.withOperationOrdering(Swagger2MarkupConfig.Builder.OPERATION_PATH_NATURAL_ORDERING);
builder.withOperationOrdering(Swagger2MarkupConfigBuilder.OPERATION_PATH_NATURAL_ORDERING);
assertThat(builder.config.getOperationOrderBy()).isEqualTo(OrderBy.CUSTOM);
assertThat(builder.config.getOperationOrdering()).isEqualTo(Swagger2MarkupConfig.Builder.OPERATION_PATH_NATURAL_ORDERING);
assertThat(builder.config.getOperationOrdering()).isEqualTo(Swagger2MarkupConfigBuilder.OPERATION_PATH_NATURAL_ORDERING);
try {
builder.withDefinitionOrdering(OrderBy.CUSTOM);
@@ -146,9 +168,9 @@ public class Swagger2MarkupConfigTest {
} catch (IllegalArgumentException e) {
assertThat(e.getMessage()).isEqualTo("You must provide a custom comparator if orderBy == OrderBy.CUSTOM");
}
builder.withParameterOrdering(Swagger2MarkupConfig.Builder.PARAMETER_NAME_NATURAL_ORDERING);
builder.withParameterOrdering(Swagger2MarkupConfigBuilder.PARAMETER_NAME_NATURAL_ORDERING);
assertThat(builder.config.getParameterOrderBy()).isEqualTo(OrderBy.CUSTOM);
assertThat(builder.config.getParameterOrdering()).isEqualTo(Swagger2MarkupConfig.Builder.PARAMETER_NAME_NATURAL_ORDERING);
assertThat(builder.config.getParameterOrdering()).isEqualTo(Swagger2MarkupConfigBuilder.PARAMETER_NAME_NATURAL_ORDERING);
try {
builder.withPropertyOrdering(OrderBy.CUSTOM);

View File

@@ -0,0 +1,53 @@
/*
* Copyright 2016 Robert Winkler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.swagger2markup.builder;
import io.github.swagger2markup.Swagger2MarkupExtensionRegistry;
import io.github.swagger2markup.spi.SwaggerModelExtension;
import io.swagger.models.Swagger;
import org.junit.Test;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
public class Swagger2MarkupExtensionRegistryBuilderTest {
@Test
public void testRegistering() {
Swagger2MarkupExtensionRegistryBuilder registryBuilder = new Swagger2MarkupExtensionRegistryBuilder();
registryBuilder.withSwaggerModelExtension(new MySwaggerModelExtension());
}
@Test
public void testListing() {
SwaggerModelExtension ext1 = new MySwaggerModelExtension();
SwaggerModelExtension ext2 = new MySwaggerModelExtension();
SwaggerModelExtension ext3 = new SwaggerModelExtension() {
public void apply(Swagger swagger) {
}
};
Swagger2MarkupExtensionRegistry registry = new Swagger2MarkupExtensionRegistryBuilder()
.withSwaggerModelExtension(ext2)
.withSwaggerModelExtension(ext3)
.withSwaggerModelExtension(ext1)
.build();
List<SwaggerModelExtension> extensions = registry.getSwaggerModelExtensions();
assertThat(extensions.size()).isEqualTo(3);
assertThat(extensions).contains(ext1, ext2, ext3);
}
}

View File

@@ -25,4 +25,8 @@ swagger2markup.definitionOrderBy=AS_IS
swagger2markup.parameterOrderBy=AS_IS
swagger2markup.propertyOrderBy=AS_IS
swagger2markup.responseOrderBy=AS_IS
swagger2markup.extensions.uniqueId1.customProperty1=test
swagger2markup.extensions.uniqueId1.customProperty2=test
swagger2markup.extensions.uniqueId2.customProperty1=test
swagger2markup.extensions.uniqueId2.customProperty2=test

View File

@@ -1,3 +0,0 @@
== Pet extension
This is an extension for this definition

View File

@@ -1,2 +0,0 @@
<?xml version="1.0" encoding="" ?>
<xsd>This is an XML Schema</xsd>

View File

@@ -1,11 +0,0 @@
== Pet update request extension
----
Request
----
== Pet update response extension
----
Response
----

View File

@@ -1,3 +0,0 @@
## Pet extension
This is an extension for this definition

View File

@@ -1,11 +0,0 @@
## Pet update request extension
```
Request
```
## Pet update response extension
```
Response
```

View File

@@ -56,35 +56,35 @@ POST /pets
==== Example HTTP request
==== Request path
----
"/pets"
----
==== Request body
----
{
"tags" : [ {
"id" : 0,
"name" : "string"
} ],
"id" : 0,
"nicknames" : {
"string" : "string"
},
"category" : {
"id" : 123,
"name" : "Canines"
},
"weight" : 0.0,
"status" : "string",
"name" : "doggie",
"photoUrls" : [ "string" ]
"nicknames" : {
"string" : "string"
},
"photoUrls" : [ "string" ],
"tags" : [ {
"id" : 0,
"name" : "string"
} ],
"status" : "string",
"weight" : 0.0
}
----
==== Request path
----
"/pets"
----
==== Example HTTP response
==== Response 405
@@ -173,35 +173,35 @@ PUT /pets
==== Example HTTP request
==== Request path
----
"/pets"
----
==== Request body
----
{
"tags" : [ {
"id" : 0,
"name" : "string"
} ],
"id" : 0,
"nicknames" : {
"string" : "string"
},
"category" : {
"id" : 123,
"name" : "Canines"
},
"weight" : 0.0,
"status" : "string",
"name" : "doggie",
"photoUrls" : [ "string" ]
"nicknames" : {
"string" : "string"
},
"photoUrls" : [ "string" ],
"tags" : [ {
"id" : 0,
"name" : "string"
} ],
"status" : "string",
"weight" : 0.0
}
----
==== Request path
----
"/pets"
----
=== Finds Pets by status
----
GET /pets/findByStatus
@@ -264,6 +264,12 @@ Multiple status values can be provided with comma seperated strings
==== Example HTTP request
==== Request path
----
"/pets/findByStatus"
----
==== Request query
----
{
@@ -272,12 +278,6 @@ Multiple status values can be provided with comma seperated strings
----
==== Request path
----
"/pets/findByStatus"
----
==== Example HTTP response
==== Response 200
@@ -348,6 +348,12 @@ Muliple tags can be provided with comma seperated strings. Use tag1, tag2, tag3
==== Example HTTP request
==== Request path
----
"/pets/findByTags"
----
==== Request query
----
{
@@ -356,12 +362,6 @@ Muliple tags can be provided with comma seperated strings. Use tag1, tag2, tag3
----
==== Request path
----
"/pets/findByTags"
----
==== Example HTTP response
==== Response 200
@@ -425,18 +425,18 @@ POST /pets/{petId}
==== Example HTTP request
==== Request formData
----
"string"
----
==== Request path
----
"/pets/string"
----
==== Request formData
----
"string"
----
=== Find pet by ID
----
GET /pets/{petId}
@@ -520,22 +520,22 @@ Returns a pet when ID < 10. ID > 10 or nonintegers will simulate API error cond
==== Response 200
----
{
"tags" : [ {
"id" : 0,
"name" : "string"
} ],
"id" : 0,
"nicknames" : {
"string" : "string"
},
"category" : {
"id" : 123,
"name" : "Canines"
},
"weight" : 0.0,
"status" : "string",
"name" : "doggie",
"photoUrls" : [ "string" ]
"nicknames" : {
"string" : "string"
},
"photoUrls" : [ "string" ],
"tags" : [ {
"id" : 0,
"name" : "string"
} ],
"status" : "string",
"weight" : 0.0
}
----
@@ -649,6 +649,12 @@ POST /stores/order
==== Example HTTP request
==== Request path
----
"/stores/order"
----
==== Request body
----
{
@@ -662,12 +668,6 @@ POST /stores/order
----
==== Request path
----
"/stores/order"
----
==== Example HTTP response
==== Response 200
@@ -869,28 +869,28 @@ This can only be done by the logged in user.
==== Example HTTP request
==== Request path
----
"/users"
----
==== Request body
----
{
"id" : 0,
"lastName" : "string",
"phone" : "string",
"username" : "string",
"email" : "string",
"userStatus" : 0,
"pictures" : [ "string" ],
"firstName" : "string",
"password" : "string"
"lastName" : "string",
"email" : "string",
"password" : "string",
"phone" : "string",
"userStatus" : 0,
"pictures" : [ "string" ]
}
----
==== Request path
----
"/users"
----
=== Creates list of users with given input array
----
POST /users/createWithArray
@@ -930,28 +930,28 @@ POST /users/createWithArray
==== Example HTTP request
==== Request path
----
"/users/createWithArray"
----
==== Request body
----
[ {
"id" : 0,
"lastName" : "string",
"phone" : "string",
"username" : "string",
"email" : "string",
"userStatus" : 0,
"pictures" : [ "string" ],
"firstName" : "string",
"password" : "string"
"lastName" : "string",
"email" : "string",
"password" : "string",
"phone" : "string",
"userStatus" : 0,
"pictures" : [ "string" ]
} ]
----
==== Request path
----
"/users/createWithArray"
----
=== Creates list of users with given input array
----
POST /users/createWithList
@@ -991,28 +991,28 @@ POST /users/createWithList
==== Example HTTP request
==== Request path
----
"/users/createWithList"
----
==== Request body
----
[ {
"id" : 0,
"lastName" : "string",
"phone" : "string",
"username" : "string",
"email" : "string",
"userStatus" : 0,
"pictures" : [ "string" ],
"firstName" : "string",
"password" : "string"
"lastName" : "string",
"email" : "string",
"password" : "string",
"phone" : "string",
"userStatus" : 0,
"pictures" : [ "string" ]
} ]
----
==== Request path
----
"/users/createWithList"
----
=== Logs user into the system
----
GET /users/login
@@ -1062,21 +1062,21 @@ GET /users/login
==== Example HTTP request
==== Request query
----
{
"username" : "string",
"password" : "string"
}
----
==== Request path
----
"/users/login"
----
==== Request query
----
{
"password" : "string",
"username" : "string"
}
----
==== Example HTTP response
==== Response 200
@@ -1190,14 +1190,14 @@ GET /users/{username}
----
{
"id" : 0,
"lastName" : "string",
"phone" : "string",
"username" : "string",
"email" : "string",
"userStatus" : 0,
"pictures" : [ "string" ],
"firstName" : "string",
"password" : "string"
"lastName" : "string",
"email" : "string",
"password" : "string",
"phone" : "string",
"userStatus" : 0,
"pictures" : [ "string" ]
}
----
@@ -1256,28 +1256,28 @@ This can only be done by the logged in user.
==== Example HTTP request
==== Request path
----
"/users/string"
----
==== Request body
----
{
"id" : 0,
"lastName" : "string",
"phone" : "string",
"username" : "string",
"email" : "string",
"userStatus" : 0,
"pictures" : [ "string" ],
"firstName" : "string",
"password" : "string"
"lastName" : "string",
"email" : "string",
"password" : "string",
"phone" : "string",
"userStatus" : 0,
"pictures" : [ "string" ]
}
----
==== Request path
----
"/users/string"
----
=== Delete user
----
DELETE /users/{username}

View File

@@ -1,69 +0,0 @@
[[_definitions]]
== Definitions
=== Category
[options="header", cols=".^1h,.^6,.^1,.^1,.^1,.^1"]
|===
|Name|Description|Required|Schema|Default|Example
|id||false|integer(int64)||
|name||false|string||
|===
=== Order
[options="header", cols=".^1h,.^6,.^1,.^1,.^1,.^1"]
|===
|Name|Description|Required|Schema|Default|Example
|complete||false|boolean||
|id||false|integer(int64)||
|petId||false|integer(int64)||
|quantity||false|integer(int32)||
|shipDate||false|string(date-time)||
|status|Order Status|false|string||
|===
=== Pet
[options="header", cols=".^1h,.^6,.^1,.^1,.^1,.^1"]
|===
|Name|Description|Required|Schema|Default|Example
|category||false|<<_category,Category>>||
|id||false|integer(int64)||
|name||true|string||"doggie"
|photoUrls||true|string array||
|status|pet status in the store|false|string||
|tags||false|<<_tag,Tag>> array||
|===
=== Tag
[options="header", cols=".^1h,.^6,.^1,.^1,.^1,.^1"]
|===
|Name|Description|Required|Schema|Default|Example
|id||false|integer(int64)||
|name||false|string||
|===
=== User
[options="header", cols=".^1h,.^6,.^1,.^1,.^1,.^1"]
|===
|Name|Description|Required|Schema|Default|Example
|email||false|string||
|firstName||false|string||
|id||false|integer(int64)||
|lastName||false|string||
|password||false|string||
|phone||false|string||
|userStatus|User Status|false|integer(int32)||
|username||false|string||
|===

View File

@@ -1,38 +0,0 @@
= Swagger Petstore
[[_overview]]
== Overview
[%hardbreaks]
This is a sample server Petstore server.
[Learn about Swagger](http://swagger.io) or join the IRC channel `#swagger` on irc.freenode.net.
For this sample, you can use the api key `special-key` to test the authorization filters
=== Version information
Version : 1.0.0
=== Contact information
Contact : apiteam@swagger.io
=== License information
License : Apache 2.0
License URL : http://www.apache.org/licenses/LICENSE-2.0.html
Terms of service : http://helloreverb.com/terms/
=== URI scheme
Host : petstore.swagger.io
BasePath : /v2
Schemes : HTTP
=== Tags
* pet : Pet resource
* store : Store resource
* user : User resource

View File

@@ -1,23 +0,0 @@
[[_securityscheme]]
== Security
=== api_key
Type : apiKey
Name : api_key
In : HEADER
=== petstore_auth
Type : oauth2
Flow : implicit
Token URL : http://petstore.swagger.io/api/oauth/dialog
[options="header", cols="1,6"]
|===
|Name|Description
|write_pets|modify pets in your account
|read_pets|read your pets
|===