From 09c78a1ceebe477300f2ce7c9f9fbad2b77b3cf8 Mon Sep 17 00:00:00 2001 From: Hugo de Paix de Coeur Date: Mon, 29 Feb 2016 16:22:44 +0100 Subject: [PATCH 1/2] fixes #91 : Move SpringRestDocs examples to extension --- .../curl-request.adoc | 1 + .../http-request.adoc | 0 .../http-response.adoc | 0 .../body/description.adoc | 0 .../description.adoc | 0 .../body/description.md | 0 .../description.md | 0 .../builder/document/PathsDocument.java | 114 +----------------- .../config/Swagger2MarkupConfig.java | 42 +------ .../DefinitionsContentExtension.java | 27 +++++ .../extension/OperationsContentExtension.java | 31 +++++ .../extension/OverviewContentExtension.java | 24 ++++ .../extension/SecurityContentExtension.java | 24 ++++ .../repository/ContentExtension.java | 82 +++++++++++++ .../repository/DynamicContentExtension.java | 42 +------ .../DynamicDefinitionsContentExtension.java | 10 +- .../DynamicOperationsContentExtension.java | 14 +-- .../DynamicOverviewContentExtension.java | 7 +- .../DynamicSecurityContentExtension.java | 7 +- .../repository/SpringRestDocsExtension.java | 113 +++++++++++++++++ src/main/resources/lang/labels_en.properties | 1 - src/main/resources/lang/labels_fr.properties | 1 - src/main/resources/lang/labels_ru.properties | 1 - .../Swagger2MarkupConverterTest.java | 34 +++++- .../config/Swagger2MarkupConfigTest.java | 2 - src/test/resources/config/config.properties | 1 - 26 files changed, 354 insertions(+), 224 deletions(-) rename src/docs/asciidoc/paths/{add_a_new_pet_to_the_store => addPet}/curl-request.adoc (94%) rename src/docs/asciidoc/paths/{add_a_new_pet_to_the_store => addPet}/http-request.adoc (100%) rename src/docs/asciidoc/paths/{add_a_new_pet_to_the_store => addPet}/http-response.adoc (100%) rename src/docs/asciidoc/paths/{update_an_existing_pet => updatePet}/body/description.adoc (100%) rename src/docs/asciidoc/paths/{update_an_existing_pet => updatePet}/description.adoc (100%) rename src/docs/markdown/paths/{update_an_existing_pet => updatePet}/body/description.md (100%) rename src/docs/markdown/paths/{update_an_existing_pet => updatePet}/description.md (100%) create mode 100644 src/main/java/io/github/robwin/swagger2markup/extension/repository/ContentExtension.java create mode 100644 src/main/java/io/github/robwin/swagger2markup/extension/repository/SpringRestDocsExtension.java diff --git a/src/docs/asciidoc/paths/add_a_new_pet_to_the_store/curl-request.adoc b/src/docs/asciidoc/paths/addPet/curl-request.adoc similarity index 94% rename from src/docs/asciidoc/paths/add_a_new_pet_to_the_store/curl-request.adoc rename to src/docs/asciidoc/paths/addPet/curl-request.adoc index f2037c3c..51b9378e 100644 --- a/src/docs/asciidoc/paths/add_a_new_pet_to_the_store/curl-request.adoc +++ b/src/docs/asciidoc/paths/addPet/curl-request.adoc @@ -1,3 +1,4 @@ +== curl-request [source,bash] ---- diff --git a/src/docs/asciidoc/paths/add_a_new_pet_to_the_store/http-request.adoc b/src/docs/asciidoc/paths/addPet/http-request.adoc similarity index 100% rename from src/docs/asciidoc/paths/add_a_new_pet_to_the_store/http-request.adoc rename to src/docs/asciidoc/paths/addPet/http-request.adoc diff --git a/src/docs/asciidoc/paths/add_a_new_pet_to_the_store/http-response.adoc b/src/docs/asciidoc/paths/addPet/http-response.adoc similarity index 100% rename from src/docs/asciidoc/paths/add_a_new_pet_to_the_store/http-response.adoc rename to src/docs/asciidoc/paths/addPet/http-response.adoc diff --git a/src/docs/asciidoc/paths/update_an_existing_pet/body/description.adoc b/src/docs/asciidoc/paths/updatePet/body/description.adoc similarity index 100% rename from src/docs/asciidoc/paths/update_an_existing_pet/body/description.adoc rename to src/docs/asciidoc/paths/updatePet/body/description.adoc diff --git a/src/docs/asciidoc/paths/update_an_existing_pet/description.adoc b/src/docs/asciidoc/paths/updatePet/description.adoc similarity index 100% rename from src/docs/asciidoc/paths/update_an_existing_pet/description.adoc rename to src/docs/asciidoc/paths/updatePet/description.adoc diff --git a/src/docs/markdown/paths/update_an_existing_pet/body/description.md b/src/docs/markdown/paths/updatePet/body/description.md similarity index 100% rename from src/docs/markdown/paths/update_an_existing_pet/body/description.md rename to src/docs/markdown/paths/updatePet/body/description.md diff --git a/src/docs/markdown/paths/update_an_existing_pet/description.md b/src/docs/markdown/paths/updatePet/description.md similarity index 100% rename from src/docs/markdown/paths/update_an_existing_pet/description.md rename to src/docs/markdown/paths/updatePet/description.md diff --git a/src/main/java/io/github/robwin/swagger2markup/builder/document/PathsDocument.java b/src/main/java/io/github/robwin/swagger2markup/builder/document/PathsDocument.java index 4a5648be..9bea2808 100644 --- a/src/main/java/io/github/robwin/swagger2markup/builder/document/PathsDocument.java +++ b/src/main/java/io/github/robwin/swagger2markup/builder/document/PathsDocument.java @@ -69,7 +69,6 @@ public class PathsDocument extends MarkupDocument { private final String PARAMETERS; private final String BODY_PARAMETER; private final String RESPONSES; - private final String EXAMPLE_CURL; private final String EXAMPLE_REQUEST; private final String EXAMPLE_RESPONSE; @@ -80,9 +79,6 @@ public class PathsDocument extends MarkupDocument { private final String DEPRECATED_OPERATION; private static final String PATHS_ANCHOR = "paths"; - private static final String REQUEST_EXAMPLE_FILE_NAME = "http-request"; - private static final String RESPONSE_EXAMPLE_FILE_NAME = "http-response"; - private static final String CURL_EXAMPLE_FILE_NAME = "curl-request"; private static final String DESCRIPTION_FILE_NAME = "description"; @@ -97,7 +93,6 @@ public class PathsDocument extends MarkupDocument { PARAMETERS = labels.getString("parameters"); BODY_PARAMETER = labels.getString("body_parameter"); RESPONSES = labels.getString("responses"); - EXAMPLE_CURL = labels.getString("example_curl"); EXAMPLE_REQUEST = labels.getString("example_request"); EXAMPLE_RESPONSE = labels.getString("example_response"); SECURITY = labels.getString("security"); @@ -589,56 +584,7 @@ public class PathsDocument extends MarkupDocument { } /** - * Builds the example section of a Swagger Operation. Tries to load the examples from - * curl-request.adoc, http-request.adoc and http-response.adoc or - * curl-request.md, http-request.md and http-response.md. - * Operation folder search order : - * - normalizeOperationFileName(operation.operationId) - * - then, normalizeOperationFileName(operation.method + " " + operation.path) - * - then, normalizeOperationFileName(operation.summary) - * - * @param operation the Swagger Operation - * @param docBuilder the docbuilder do use for output - */ - private void examplesSection1(PathOperation operation, MarkupDocBuilder docBuilder) { - if (config.isExamples()) { - Optional curlExample = example(normalizeName(operation.getId()), CURL_EXAMPLE_FILE_NAME); - if (!curlExample.isPresent()) - curlExample = example(normalizeName(operation.getTitle()), CURL_EXAMPLE_FILE_NAME); - - if (curlExample.isPresent()) { - addOperationSectionTitle(EXAMPLE_CURL, docBuilder); - docBuilder.paragraph(curlExample.get()); - } - - Optional requestExample = example(normalizeName(operation.getId()), REQUEST_EXAMPLE_FILE_NAME); - if (!requestExample.isPresent()) - requestExample = example(normalizeName(operation.getTitle()), REQUEST_EXAMPLE_FILE_NAME); - - if (requestExample.isPresent()) { - addOperationSectionTitle(EXAMPLE_REQUEST, docBuilder); - docBuilder.paragraph(requestExample.get()); - } - - Optional responseExample = example(normalizeName(operation.getId()), RESPONSE_EXAMPLE_FILE_NAME); - if (!responseExample.isPresent()) - responseExample = example(normalizeName(operation.getTitle()), RESPONSE_EXAMPLE_FILE_NAME); - - if (responseExample.isPresent()) { - addOperationSectionTitle(EXAMPLE_RESPONSE, docBuilder); - docBuilder.paragraph(responseExample.get()); - } - } - } - - /** - * Builds the example section of a Swagger Operation. Tries to load the examples from - * curl-request.adoc, http-request.adoc and http-response.adoc or - * curl-request.md, http-request.md and http-response.md. - * Operation folder search order : - * - normalizeOperationFileName(operation.operationId) - * - then, normalizeOperationFileName(operation.method + " " + operation.path) - * - then, normalizeOperationFileName(operation.summary) + * Builds the example section of a Swagger Operation. * * @param operation the Swagger Operation * @param docBuilder the docbuilder do use for output @@ -646,35 +592,17 @@ public class PathsDocument extends MarkupDocument { private void examplesSection(PathOperation operation, MarkupDocBuilder docBuilder) { if (globalContext.config.isExamples()) { - Optional curlExample; - Optional requestExample; - Optional responseExample; Optional> generatedRequestExampleMap; Optional> generatedResponseExampleMap; - curlExample = example(normalizeName(operation.getId()), CURL_EXAMPLE_FILE_NAME); - if (!curlExample.isPresent()) - curlExample = example(normalizeName(operation.getTitle()), CURL_EXAMPLE_FILE_NAME); - requestExample = example(normalizeName(operation.getId()), REQUEST_EXAMPLE_FILE_NAME); - if (!requestExample.isPresent()) - requestExample = example(normalizeName(operation.getTitle()), REQUEST_EXAMPLE_FILE_NAME); - responseExample = example(normalizeName(operation.getId()), RESPONSE_EXAMPLE_FILE_NAME); - if (!responseExample.isPresent()) - responseExample = example(normalizeName(operation.getTitle()), RESPONSE_EXAMPLE_FILE_NAME); - generatedRequestExampleMap = ExamplesUtil.generateRequestExampleMap(operation, globalContext.swagger.getDefinitions(), markupDocBuilder); generatedResponseExampleMap = ExamplesUtil.generateResponseExampleMap(operation.getOperation(), globalContext.swagger.getDefinitions(), markupDocBuilder); - if (curlExample.isPresent()) { - addOperationSectionTitle(EXAMPLE_CURL, docBuilder); - docBuilder.paragraph(curlExample.get()); - } - if (requestExample.isPresent() || generatedRequestExampleMap.isPresent()) { + + if (generatedRequestExampleMap.isPresent()) { addOperationSectionTitle(EXAMPLE_REQUEST, docBuilder); - if (requestExample.isPresent()) { - docBuilder.paragraph(requestExample.get()); - } + if (generatedRequestExampleMap.isPresent() && generatedRequestExampleMap.get().size() > 0) { for (Map.Entry request : generatedRequestExampleMap.get().entrySet()) { docBuilder.sectionTitleLevel4(REQUEST + " " + request.getKey() + " :"); @@ -683,11 +611,8 @@ public class PathsDocument extends MarkupDocument { } } - if (responseExample.isPresent() || generatedResponseExampleMap.isPresent()) { + if (generatedResponseExampleMap.isPresent()) { addOperationSectionTitle(EXAMPLE_RESPONSE, docBuilder); - if (responseExample.isPresent()) { - docBuilder.paragraph(responseExample.get()); - } if (generatedResponseExampleMap.isPresent() && generatedResponseExampleMap.get().size() > 0) { for (Map.Entry response : generatedResponseExampleMap.get().entrySet()) { docBuilder.sectionTitleLevel4(RESPONSE + " " + response.getKey() + " :"); @@ -698,33 +623,6 @@ public class PathsDocument extends MarkupDocument { } } - /** - * Reads an example - * - * @param exampleFolder the name of the folder where the example file resides - * @param exampleFileName the name of the example file - * @return the content of the file - */ - private Optional example(String exampleFolder, String exampleFileName) { - for (String fileNameExtension : config.getMarkupLanguage().getFileNameExtensions()) { - URI contentUri = config.getExamplesUri().resolve(exampleFolder).resolve(exampleFileName + fileNameExtension); - - try (Reader reader = io.github.robwin.swagger2markup.utils.IOUtils.uriReader(contentUri)) { - if (logger.isInfoEnabled()) { - logger.info("Example content processed {}", contentUri); - } - - return Optional.of(IOUtils.toString(reader).trim()); - } catch (IOException e) { - if (logger.isDebugEnabled()) { - logger.debug("Failed to read example content {} > {}", contentUri, e.getMessage()); - } - } - } - - return Optional.absent(); - } - /** * Builds the security section of a Swagger Operation. * @@ -744,7 +642,7 @@ public class PathsDocument extends MarkupDocument { for (Map> securityScheme : securitySchemes) { for (Map.Entry> securityEntry : securityScheme.entrySet()) { String securityKey = securityEntry.getKey(); - String type = "UNKNOWN"; + String type = "UNKNOWN"; // FIXME -> labels if (securityDefinitions != null && securityDefinitions.containsKey(securityKey)) { type = securityDefinitions.get(securityKey).getType(); } diff --git a/src/main/java/io/github/robwin/swagger2markup/config/Swagger2MarkupConfig.java b/src/main/java/io/github/robwin/swagger2markup/config/Swagger2MarkupConfig.java index 72315c03..2e2c5432 100644 --- a/src/main/java/io/github/robwin/swagger2markup/config/Swagger2MarkupConfig.java +++ b/src/main/java/io/github/robwin/swagger2markup/config/Swagger2MarkupConfig.java @@ -41,7 +41,6 @@ public class Swagger2MarkupConfig { private MarkupLanguage markupLanguage; private boolean examples; - private URI examplesUri; private boolean schemas; private URI schemasUri; private boolean operationDescriptions; @@ -106,15 +105,6 @@ public class Swagger2MarkupConfig { baseURI = IOUtils.uriParent(swaggerLocation); } - if (examples && examplesUri == null) { - if (baseURI == null) { - if (logger.isWarnEnabled()) - logger.warn("Disable {} > No explicit '{}' set and no default available", "examples", "examplesUri"); - examples = false; - } else - examplesUri = baseURI; - } - if (schemas && schemasUri == null) { if (baseURI == null) { if (logger.isWarnEnabled()) @@ -151,10 +141,6 @@ public class Swagger2MarkupConfig { return examples; } - public URI getExamplesUri() { - return examplesUri; - } - public boolean isSchemas() { return schemas; } @@ -317,8 +303,6 @@ public class Swagger2MarkupConfig { config.markupLanguage = MarkupLanguage.valueOf(safeProperties.getProperty(PROPERTIES_PREFIX + "markupLanguage")); config.examples = Boolean.valueOf(safeProperties.getProperty(PROPERTIES_PREFIX + "examples")); - if (safeProperties.containsKey(PROPERTIES_PREFIX + "examplesUri")) - config.examplesUri = URI.create(safeProperties.getProperty(PROPERTIES_PREFIX + "examplesUri")); config.schemas = Boolean.valueOf(safeProperties.getProperty(PROPERTIES_PREFIX + "schemas")); if (safeProperties.containsKey(PROPERTIES_PREFIX + "schemasUri")) config.schemasUri = URI.create(safeProperties.getProperty(PROPERTIES_PREFIX + "schemasUri")); @@ -385,34 +369,10 @@ public class Swagger2MarkupConfig { /** * Include examples into the Paths document * - * @param examplesUri the URI to the folder where the example documents reside. Use default URI if null. - * @return this builder - */ - public Builder withExamples(URI examplesUri) { - config.examples = true; - - config.examplesUri = examplesUri; - return this; - } - - /** - * Include examples into the Paths document - * - * @param examplesPath the path to the folder where the example documents reside. Use default path if null. - * @return this builder - */ - public Builder withExamples(Path examplesPath) { - return withExamples(examplesPath.toUri()); - } - - /** - * Include examples into the Paths document.
- * This is an alias for {@link #withExamples(URI) withExamples(null)}. - * * @return this builder */ public Builder withExamples() { - withExamples((URI) null); + config.examples = true; return this; } diff --git a/src/main/java/io/github/robwin/swagger2markup/extension/DefinitionsContentExtension.java b/src/main/java/io/github/robwin/swagger2markup/extension/DefinitionsContentExtension.java index 078ed9aa..e10fed5d 100644 --- a/src/main/java/io/github/robwin/swagger2markup/extension/DefinitionsContentExtension.java +++ b/src/main/java/io/github/robwin/swagger2markup/extension/DefinitionsContentExtension.java @@ -31,4 +31,31 @@ public abstract class DefinitionsContentExtension extends AbstractExtension { } public abstract void apply(Context context); + + /** + * Returns title level offset from 1 to apply to content + * @param context context + * @return title level offset + */ + protected int levelOffset(Context context) { + int levelOffset; + switch (context.position) { + case DOC_BEFORE: + case DOC_AFTER: + levelOffset = 0; + break; + case DOC_BEGIN: + case DOC_END: + levelOffset = 1; + break; + case DEF_BEGIN: + case DEF_END: + levelOffset = 2; + break; + default: + throw new RuntimeException(String.format("Unknown position '%s'", context.position)); + } + + return levelOffset; + } } diff --git a/src/main/java/io/github/robwin/swagger2markup/extension/OperationsContentExtension.java b/src/main/java/io/github/robwin/swagger2markup/extension/OperationsContentExtension.java index e7186cca..6098f0c9 100644 --- a/src/main/java/io/github/robwin/swagger2markup/extension/OperationsContentExtension.java +++ b/src/main/java/io/github/robwin/swagger2markup/extension/OperationsContentExtension.java @@ -1,6 +1,7 @@ package io.github.robwin.swagger2markup.extension; import io.github.robwin.markup.builder.MarkupDocBuilder; +import io.github.robwin.swagger2markup.GroupBy; import io.github.robwin.swagger2markup.PathOperation; public abstract class OperationsContentExtension extends AbstractExtension { @@ -32,4 +33,34 @@ public abstract class OperationsContentExtension extends AbstractExtension { } public abstract void apply(Context context); + + /** + * Returns title level offset from 1 to apply to content + * @param context context + * @return title level offset + */ + protected int levelOffset(Context context) { + int levelOffset; + switch (context.position) { + case DOC_BEFORE: + case DOC_AFTER: + levelOffset = 0; + break; + case DOC_BEGIN: + case DOC_END: + levelOffset = 1; + break; + case OP_BEGIN: + case OP_END: + levelOffset = 2; + break; + default: + throw new RuntimeException(String.format("Unknown position '%s'", context.position)); + } + if (globalContext.config.getOperationsGroupedBy() == GroupBy.TAGS) { + levelOffset++; + } + return levelOffset; + } + } diff --git a/src/main/java/io/github/robwin/swagger2markup/extension/OverviewContentExtension.java b/src/main/java/io/github/robwin/swagger2markup/extension/OverviewContentExtension.java index 2ccd7c97..dc5e7ab4 100644 --- a/src/main/java/io/github/robwin/swagger2markup/extension/OverviewContentExtension.java +++ b/src/main/java/io/github/robwin/swagger2markup/extension/OverviewContentExtension.java @@ -24,4 +24,28 @@ public abstract class OverviewContentExtension extends AbstractExtension { } public abstract void apply(Context context); + + /** + * Returns title level offset from 1 to apply to content + * @param context context + * @return title level offset + */ + protected int levelOffset(Context context) { + int levelOffset; + switch (context.position) { + case DOC_BEFORE: + case DOC_AFTER: + levelOffset = 0; + break; + case DOC_BEGIN: + case DOC_END: + levelOffset = 1; + break; + default: + throw new RuntimeException(String.format("Unknown position '%s'", context.position)); + } + + return levelOffset; + } + } diff --git a/src/main/java/io/github/robwin/swagger2markup/extension/SecurityContentExtension.java b/src/main/java/io/github/robwin/swagger2markup/extension/SecurityContentExtension.java index eb21bc24..018baa63 100644 --- a/src/main/java/io/github/robwin/swagger2markup/extension/SecurityContentExtension.java +++ b/src/main/java/io/github/robwin/swagger2markup/extension/SecurityContentExtension.java @@ -24,4 +24,28 @@ public abstract class SecurityContentExtension extends AbstractExtension { } public abstract void apply(Context context); + + /** + * Returns title level offset from 1 to apply to content + * @param context context + * @return title level offset + */ + protected int levelOffset(Context context) { + int levelOffset; + switch (context.position) { + case DOC_BEFORE: + case DOC_AFTER: + levelOffset = 0; + break; + case DOC_BEGIN: + case DOC_END: + levelOffset = 1; + break; + default: + throw new RuntimeException(String.format("Unknown position '%s'", context.position)); + } + + return levelOffset; + } + } diff --git a/src/main/java/io/github/robwin/swagger2markup/extension/repository/ContentExtension.java b/src/main/java/io/github/robwin/swagger2markup/extension/repository/ContentExtension.java new file mode 100644 index 00000000..15b96f98 --- /dev/null +++ b/src/main/java/io/github/robwin/swagger2markup/extension/repository/ContentExtension.java @@ -0,0 +1,82 @@ +package io.github.robwin.swagger2markup.extension.repository; + +import com.google.common.base.Optional; +import io.github.robwin.swagger2markup.Swagger2MarkupConverter; +import io.github.robwin.swagger2markup.extension.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; + +public class ContentExtension { + + private static final Logger logger = LoggerFactory.getLogger(ContentExtension.class); + + protected final Swagger2MarkupConverter.Context globalContext; + protected final ContentContext contentContext; + + + public 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 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(String.format("Failed to read content file: %s", contentPath), e); + } + } + } else { + if (logger.isWarnEnabled()) { + logger.warn("Content file is not readable: {}", contentPath); + } + } + + return Optional.absent(); + } + + /** + * Reads content from an Uri + * + * @param contentUri content file URI + * @return content reader + */ + protected Optional readContentUri(URI contentUri) { + try { + Reader reader = io.github.robwin.swagger2markup.utils.IOUtils.uriReader(contentUri); + + if (logger.isInfoEnabled()) { + logger.info("Content URI processed {}", contentUri); + } + + return Optional.of(reader); + } catch (IOException e) { + if (logger.isWarnEnabled()) { + logger.warn("Failed to read URI content {} > {}", contentUri, e.getMessage()); + } + } + + return Optional.absent(); + } +} diff --git a/src/main/java/io/github/robwin/swagger2markup/extension/repository/DynamicContentExtension.java b/src/main/java/io/github/robwin/swagger2markup/extension/repository/DynamicContentExtension.java index 1a06cbcd..579c23a7 100644 --- a/src/main/java/io/github/robwin/swagger2markup/extension/repository/DynamicContentExtension.java +++ b/src/main/java/io/github/robwin/swagger2markup/extension/repository/DynamicContentExtension.java @@ -12,8 +12,8 @@ import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.FileReader; import java.io.IOException; +import java.io.Reader; import java.nio.file.DirectoryStream; import java.nio.file.Files; import java.nio.file.Path; @@ -21,17 +21,12 @@ import java.util.Collection; import java.util.Collections; import java.util.List; -public class DynamicContentExtension { +public class DynamicContentExtension extends ContentExtension { private static final Logger logger = LoggerFactory.getLogger(DynamicContentExtension.class); - private final Swagger2MarkupConverter.Context globalContext; - private final ContentContext contentContext; - - public DynamicContentExtension(Swagger2MarkupConverter.Context globalContext, ContentContext contentContext) { - this.globalContext = globalContext; - this.contentContext = contentContext; + super(globalContext, contentContext); } /** @@ -63,13 +58,15 @@ public class DynamicContentExtension { Collections.sort(extensions, Ordering.natural()); for (Path extension : extensions) { - Optional extensionContent = operationExtension(extension); + Optional extensionContent = readContentPath(extension); if (extensionContent.isPresent()) { try { contentContext.docBuilder.importMarkup(extensionContent.get(), levelOffset); } catch (IOException e) { throw new RuntimeException(String.format("Failed to read extension file: %s", extension), e); + } finally { + extensionContent.get().close(); } } } @@ -81,31 +78,4 @@ public class DynamicContentExtension { } } - /** - * Reads an extension - * - * @param extension extension file - * @return extension content reader - */ - protected Optional operationExtension(Path extension) { - - if (Files.isReadable(extension)) { - if (logger.isInfoEnabled()) { - logger.info("Extension file processed: {}", extension); - } - try { - return Optional.of(new FileReader(extension.toFile())); - } catch (IOException e) { - if (logger.isWarnEnabled()) { - logger.warn(String.format("Failed to read extension file: %s", extension), e); - } - } - } else { - if (logger.isWarnEnabled()) { - logger.warn("Extension file is not readable: {}", extension); - } - } - return Optional.absent(); - } - } diff --git a/src/main/java/io/github/robwin/swagger2markup/extension/repository/DynamicDefinitionsContentExtension.java b/src/main/java/io/github/robwin/swagger2markup/extension/repository/DynamicDefinitionsContentExtension.java index 058d0cc6..ff979cb9 100644 --- a/src/main/java/io/github/robwin/swagger2markup/extension/repository/DynamicDefinitionsContentExtension.java +++ b/src/main/java/io/github/robwin/swagger2markup/extension/repository/DynamicDefinitionsContentExtension.java @@ -58,23 +58,19 @@ public class DynamicDefinitionsContentExtension extends DefinitionsContentExtens if (contentPath != null) { DynamicContentExtension dynamicContent = new DynamicContentExtension(globalContext, context); - int levelOffset; switch (context.position) { case DOC_BEFORE: case DOC_AFTER: - levelOffset = 0; - dynamicContent.extensionsSection(contentPath, contentPrefix(context.position), levelOffset); + dynamicContent.extensionsSection(contentPath, contentPrefix(context.position), levelOffset(context)); break; case DOC_BEGIN: case DOC_END: - levelOffset = 1; - dynamicContent.extensionsSection(contentPath, contentPrefix(context.position), levelOffset); + dynamicContent.extensionsSection(contentPath, contentPrefix(context.position), levelOffset(context)); break; case DEF_BEGIN: case DEF_END: - levelOffset = 2; - dynamicContent.extensionsSection(contentPath.resolve(Paths.get(IOUtils.normalizeName(context.definitionName))), contentPrefix(context.position), levelOffset); + dynamicContent.extensionsSection(contentPath.resolve(Paths.get(IOUtils.normalizeName(context.definitionName))), contentPrefix(context.position), levelOffset(context)); break; default: throw new RuntimeException(String.format("Unknown position '%s'", context.position)); diff --git a/src/main/java/io/github/robwin/swagger2markup/extension/repository/DynamicOperationsContentExtension.java b/src/main/java/io/github/robwin/swagger2markup/extension/repository/DynamicOperationsContentExtension.java index 708d4e79..18992aa4 100644 --- a/src/main/java/io/github/robwin/swagger2markup/extension/repository/DynamicOperationsContentExtension.java +++ b/src/main/java/io/github/robwin/swagger2markup/extension/repository/DynamicOperationsContentExtension.java @@ -1,6 +1,5 @@ package io.github.robwin.swagger2markup.extension.repository; -import io.github.robwin.swagger2markup.GroupBy; import io.github.robwin.swagger2markup.Swagger2MarkupConverter; import io.github.robwin.swagger2markup.extension.OperationsContentExtension; import io.github.robwin.swagger2markup.utils.IOUtils; @@ -59,26 +58,19 @@ public class DynamicOperationsContentExtension extends OperationsContentExtensio if (contentPath != null) { DynamicContentExtension dynamicContent = new DynamicContentExtension(globalContext, context); - int levelOffset; switch (context.position) { case DOC_BEFORE: case DOC_AFTER: - levelOffset = 0; - dynamicContent.extensionsSection(contentPath, contentPrefix(context.position), levelOffset); + dynamicContent.extensionsSection(contentPath, contentPrefix(context.position), levelOffset(context)); break; case DOC_BEGIN: case DOC_END: - levelOffset = 1; - dynamicContent.extensionsSection(contentPath, contentPrefix(context.position), levelOffset); + dynamicContent.extensionsSection(contentPath, contentPrefix(context.position), levelOffset(context)); break; case OP_BEGIN: case OP_END: - levelOffset = 3; - if (globalContext.config.getOperationsGroupedBy() == GroupBy.AS_IS) { - levelOffset = 2; - } - dynamicContent.extensionsSection(contentPath.resolve(IOUtils.normalizeName(context.operation.getId())), contentPrefix(context.position), levelOffset); + dynamicContent.extensionsSection(contentPath.resolve(IOUtils.normalizeName(context.operation.getId())), contentPrefix(context.position), levelOffset(context)); break; default: throw new RuntimeException(String.format("Unknown position '%s'", context.position)); diff --git a/src/main/java/io/github/robwin/swagger2markup/extension/repository/DynamicOverviewContentExtension.java b/src/main/java/io/github/robwin/swagger2markup/extension/repository/DynamicOverviewContentExtension.java index bb231a71..41c09ff9 100644 --- a/src/main/java/io/github/robwin/swagger2markup/extension/repository/DynamicOverviewContentExtension.java +++ b/src/main/java/io/github/robwin/swagger2markup/extension/repository/DynamicOverviewContentExtension.java @@ -55,18 +55,15 @@ public class DynamicOverviewContentExtension extends OverviewContentExtension { if (contentPath != null) { DynamicContentExtension dynamicContent = new DynamicContentExtension(globalContext, context); - int levelOffset; switch (context.position) { case DOC_BEFORE: case DOC_AFTER: - levelOffset = 0; - dynamicContent.extensionsSection(contentPath, contentPrefix(context.position), levelOffset); + dynamicContent.extensionsSection(contentPath, contentPrefix(context.position), levelOffset(context)); break; case DOC_BEGIN: case DOC_END: - levelOffset = 1; - dynamicContent.extensionsSection(contentPath, contentPrefix(context.position), levelOffset); + dynamicContent.extensionsSection(contentPath, contentPrefix(context.position), levelOffset(context)); break; default: throw new RuntimeException(String.format("Unknown position '%s'", context.position)); diff --git a/src/main/java/io/github/robwin/swagger2markup/extension/repository/DynamicSecurityContentExtension.java b/src/main/java/io/github/robwin/swagger2markup/extension/repository/DynamicSecurityContentExtension.java index f3eef7ce..f6c4ef0b 100644 --- a/src/main/java/io/github/robwin/swagger2markup/extension/repository/DynamicSecurityContentExtension.java +++ b/src/main/java/io/github/robwin/swagger2markup/extension/repository/DynamicSecurityContentExtension.java @@ -55,18 +55,15 @@ public class DynamicSecurityContentExtension extends SecurityContentExtension { if (contentPath != null) { DynamicContentExtension dynamicContent = new DynamicContentExtension(globalContext, context); - int levelOffset; switch (context.position) { case DOC_BEFORE: case DOC_AFTER: - levelOffset = 0; - dynamicContent.extensionsSection(contentPath, contentPrefix(context.position), levelOffset); + dynamicContent.extensionsSection(contentPath, contentPrefix(context.position), levelOffset(context)); break; case DOC_BEGIN: case DOC_END: - levelOffset = 1; - dynamicContent.extensionsSection(contentPath, contentPrefix(context.position), levelOffset); + dynamicContent.extensionsSection(contentPath, contentPrefix(context.position), levelOffset(context)); break; default: throw new RuntimeException(String.format("Unknown position '%s'", context.position)); diff --git a/src/main/java/io/github/robwin/swagger2markup/extension/repository/SpringRestDocsExtension.java b/src/main/java/io/github/robwin/swagger2markup/extension/repository/SpringRestDocsExtension.java new file mode 100644 index 00000000..7d4f27b0 --- /dev/null +++ b/src/main/java/io/github/robwin/swagger2markup/extension/repository/SpringRestDocsExtension.java @@ -0,0 +1,113 @@ +package io.github.robwin.swagger2markup.extension.repository; + +import com.google.common.base.Optional; +import com.google.common.base.Throwables; +import io.github.robwin.swagger2markup.PathOperation; +import io.github.robwin.swagger2markup.extension.OperationsContentExtension; +import io.github.robwin.swagger2markup.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 class SpringRestDocsExtension extends OperationsContentExtension { + + private static final Logger logger = LoggerFactory.getLogger(SpringRestDocsExtension.class); + + protected URI snippetUri; + protected Map snippets = new LinkedHashMap<>(); + + /** + * Instantiate extension + * @param snippetUri base URI where are snippets are stored + */ + public SpringRestDocsExtension(URI snippetUri) { + super(); + + Validate.notNull(snippetUri); + this.snippetUri = snippetUri; + } + + /** + * Add SpringRestDocs default snippets to list + * @return this instance + */ + public SpringRestDocsExtension withDefaultSnippets() { + snippets.put("http-request", "HTTP request"); + snippets.put("http-response", "HTTP response"); + snippets.put("curl-request", "Curl request"); + + return this; + } + + /** + * Builds the subdirectory name where are stored snippets for the given {@code operation}.
+ * Default implementation use {@code normalizeName()}, or {@code normalizeName(_)} if operation id is not set.
+ * You can override this method to configure your own folder normalization. + * + * @param operation current operation + * @return subdirectory normalized name + */ + public String operationFolderName(PathOperation operation) { + String id = operation.getOperation().getOperationId(); + if (id == null) + id = operation.getId(); + return IOUtils.normalizeName(id); + } + + /** + * 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 snippets) { + this.snippets.putAll(snippets); + + return this; + } + + public void apply(Context context) { + Validate.notNull(context); + + switch (context.position) { + case OP_END: + snippets(context); + break; + } + } + + public void snippets(Context context) { + for (Map.Entry 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); + + Optional snippetContent = content.readContentUri(snippetUri.resolve(operationFolderName(context.operation) + "/").resolve(context.docBuilder.addFileExtension(snippetName))); + + if (snippetContent.isPresent()) { + try { + context.docBuilder.sectionTitleLevel(1 + levelOffset(context), title); + context.docBuilder.importMarkup(snippetContent.get(), levelOffset(context) + 1); + } catch (IOException e) { + throw new RuntimeException(String.format("Failed to process snippet file: %s", snippetName), e); + } finally { + try { + snippetContent.get().close(); + } catch (IOException e) { + Throwables.propagate(e); + } + } + } + } +} diff --git a/src/main/resources/lang/labels_en.properties b/src/main/resources/lang/labels_en.properties index 1ad90b91..39c2333f 100644 --- a/src/main/resources/lang/labels_en.properties +++ b/src/main/resources/lang/labels_en.properties @@ -42,7 +42,6 @@ body_parameter=Body parameter responses=Responses response=Response request=Request -example_curl=Example CURL request example_request=Example HTTP request example_response=Example HTTP response type_column=Type diff --git a/src/main/resources/lang/labels_fr.properties b/src/main/resources/lang/labels_fr.properties index b0b19a42..ef184c94 100644 --- a/src/main/resources/lang/labels_fr.properties +++ b/src/main/resources/lang/labels_fr.properties @@ -42,7 +42,6 @@ body_parameter=Contenu responses=R\u0233ponses response=R\u0233ponse request=Requête -example_curl=Exemple de requête Curl example_request=Exemple de requête HTTP example_response=Exemple de r\u0233ponse HTTP type_column=Type diff --git a/src/main/resources/lang/labels_ru.properties b/src/main/resources/lang/labels_ru.properties index 1efba531..80b44fe7 100644 --- a/src/main/resources/lang/labels_ru.properties +++ b/src/main/resources/lang/labels_ru.properties @@ -42,7 +42,6 @@ request=Request parameters=\u041F\u0430\u0440\u0430\u043C\u0435\u0442\u0440\u044B body_parameter=Body parameter responses=\u041E\u0442\u0432\u0435\u0442\u044B -example_curl=\u041F\u0440\u0438\u043C\u0435\u0440 CURL \u0437\u0430\u043F\u0440\u043E\u0441\u0430 example_request=\u041F\u0440\u0438\u043C\u0435\u0440 HTTP \u0437\u0430\u043F\u0440\u043E\u0441\u0430 example_response=\u041F\u0440\u0438\u043C\u0435\u0440 HTTP \u0437\u0430\u043F\u0440\u043E\u0441\u0430 type_column=\u0422\u0438\u043F diff --git a/src/test/java/io/github/robwin/swagger2markup/Swagger2MarkupConverterTest.java b/src/test/java/io/github/robwin/swagger2markup/Swagger2MarkupConverterTest.java index 6513e0c9..31ca1f1e 100644 --- a/src/test/java/io/github/robwin/swagger2markup/Swagger2MarkupConverterTest.java +++ b/src/test/java/io/github/robwin/swagger2markup/Swagger2MarkupConverterTest.java @@ -27,6 +27,7 @@ import io.github.robwin.swagger2markup.config.Swagger2MarkupConfig; import io.github.robwin.swagger2markup.extension.Swagger2MarkupExtensionRegistry; import io.github.robwin.swagger2markup.extension.repository.DynamicDefinitionsContentExtension; import io.github.robwin.swagger2markup.extension.repository.DynamicOperationsContentExtension; +import io.github.robwin.swagger2markup.extension.repository.SpringRestDocsExtension; import io.swagger.models.Swagger; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; @@ -73,6 +74,33 @@ public class Swagger2MarkupConverterTest { asList("definitions.adoc", "overview.adoc", "paths.adoc", "security.adoc")); } + @Test + public void testSwagger2AsciiDocConversionWithSpringRestDocsExtension() throws IOException { + //Given + String swaggerJsonString = IOUtils.toString(getClass().getResourceAsStream("/json/swagger.json")); + Path outputDirectory = Paths.get("build/docs/asciidoc/generated"); + FileUtils.deleteQuietly(outputDirectory.toFile()); + + //When + Swagger2MarkupExtensionRegistry registry = Swagger2MarkupExtensionRegistry.ofEmpty() + .withExtension(new SpringRestDocsExtension(Paths.get("src/docs/asciidoc/paths").toUri()).withDefaultSnippets()) + .build(); + + Swagger2MarkupConfig config = Swagger2MarkupConfig.ofDefaults() + .build(); + + Swagger2MarkupConverter.from(swaggerJsonString) + .withConfig(config) + .withExtensionRegistry(registry) + .build() + .intoFolder(outputDirectory); + + //Then + String[] directories = outputDirectory.toFile().list(); + assertThat(new String(Files.readAllBytes(outputDirectory.resolve("paths.adoc")))) + .contains("==== HTTP request", "==== HTTP response", "==== Curl request", "===== curl-request"); + } + @Test public void testSwagger2AsciiDocConversionWithExamples() throws IOException { //Given @@ -82,7 +110,7 @@ public class Swagger2MarkupConverterTest { //When Swagger2MarkupConfig config = Swagger2MarkupConfig.ofDefaults() - .withExamples(Paths.get("src/docs/asciidoc/paths")) + .withExamples() .build(); Swagger2MarkupConverter.from(swaggerJsonString) @@ -534,7 +562,6 @@ public class Swagger2MarkupConverterTest { //When Swagger2MarkupConfig config = Swagger2MarkupConfig.ofDefaults() .withDefinitionDescriptions() - .withExamples() .withOperationDescriptions() .withSchemas() .build(); @@ -546,7 +573,6 @@ public class Swagger2MarkupConverterTest { //Then URI baseUri = io.github.robwin.swagger2markup.utils.IOUtils.uriParent(converterBuilder.globalContext.swaggerLocation); assertThat(converterBuilder.globalContext.config.getDefinitionDescriptionsUri()).isEqualTo(baseUri); - assertThat(converterBuilder.globalContext.config.getExamplesUri()).isEqualTo(baseUri); assertThat(converterBuilder.globalContext.config.getOperationDescriptionsUri()).isEqualTo(baseUri); assertThat(converterBuilder.globalContext.config.getSchemasUri()).isEqualTo(baseUri); } @@ -558,7 +584,6 @@ public class Swagger2MarkupConverterTest { //When Swagger2MarkupConfig config = Swagger2MarkupConfig.ofDefaults() .withDefinitionDescriptions() - .withExamples() .withOperationDescriptions() .withSchemas() .build(); @@ -569,7 +594,6 @@ public class Swagger2MarkupConverterTest { //Then assertThat(converterBuilder.globalContext.config.getDefinitionDescriptionsUri()).isNull(); - assertThat(converterBuilder.globalContext.config.getExamplesUri()).isNull(); assertThat(converterBuilder.globalContext.config.getOperationDescriptionsUri()).isNull(); assertThat(converterBuilder.globalContext.config.getSchemasUri()).isNull(); } diff --git a/src/test/java/io/github/robwin/swagger2markup/config/Swagger2MarkupConfigTest.java b/src/test/java/io/github/robwin/swagger2markup/config/Swagger2MarkupConfigTest.java index 6cbc856b..4e23c348 100644 --- a/src/test/java/io/github/robwin/swagger2markup/config/Swagger2MarkupConfigTest.java +++ b/src/test/java/io/github/robwin/swagger2markup/config/Swagger2MarkupConfigTest.java @@ -46,7 +46,6 @@ public class Swagger2MarkupConfigTest { assertThat(config.isDefinitionDescriptions()).isFalse(); assertThat(config.getDefinitionDescriptionsUri()).isNull(); assertThat(config.isExamples()).isFalse(); - assertThat(config.getExamplesUri()).isNull(); assertThat(config.getInlineSchemaDepthLevel()).isEqualTo(0); assertThat(config.getInterDocumentCrossReferencesPrefix()).isNull(); assertThat(config.getMarkupLanguage()).isEqualTo(MarkupLanguage.ASCIIDOC); @@ -88,7 +87,6 @@ public class Swagger2MarkupConfigTest { assertThat(config.isDefinitionDescriptions()).isTrue(); assertThat(config.getDefinitionDescriptionsUri()).isEqualTo(URI.create("definitionDescriptions")); assertThat(config.isExamples()).isTrue(); - assertThat(config.getExamplesUri()).isEqualTo(URI.create("examples")); assertThat(config.getInlineSchemaDepthLevel()).isEqualTo(2); assertThat(config.getInterDocumentCrossReferencesPrefix()).isEqualTo("xrefPrefix"); assertThat(config.getMarkupLanguage()).isEqualTo(MarkupLanguage.MARKDOWN); diff --git a/src/test/resources/config/config.properties b/src/test/resources/config/config.properties index 1d9e7db2..7fd61369 100644 --- a/src/test/resources/config/config.properties +++ b/src/test/resources/config/config.properties @@ -1,6 +1,5 @@ swagger2markup.markupLanguage=MARKDOWN swagger2markup.examples=true -swagger2markup.examplesUri=examples swagger2markup.schemasUri=schemas swagger2markup.schemas=true swagger2markup.operationDescriptions=true From e36587f61ad13147f5f4a36e60ca9d6873b2dd88 Mon Sep 17 00:00:00 2001 From: Hugo de Paix de Coeur Date: Mon, 29 Feb 2016 17:52:31 +0100 Subject: [PATCH 2/2] fix directories to lower case --- src/docs/asciidoc/paths/{addPet => addpet}/curl-request.adoc | 0 src/docs/asciidoc/paths/{addPet => addpet}/http-request.adoc | 0 src/docs/asciidoc/paths/{addPet => addpet}/http-response.adoc | 0 .../asciidoc/paths/{updatePet => updatepet}/body/description.adoc | 0 src/docs/asciidoc/paths/{updatePet => updatepet}/description.adoc | 0 .../markdown/paths/{updatePet => updatepet}/body/description.md | 0 src/docs/markdown/paths/{updatePet => updatepet}/description.md | 0 7 files changed, 0 insertions(+), 0 deletions(-) rename src/docs/asciidoc/paths/{addPet => addpet}/curl-request.adoc (100%) rename src/docs/asciidoc/paths/{addPet => addpet}/http-request.adoc (100%) rename src/docs/asciidoc/paths/{addPet => addpet}/http-response.adoc (100%) rename src/docs/asciidoc/paths/{updatePet => updatepet}/body/description.adoc (100%) rename src/docs/asciidoc/paths/{updatePet => updatepet}/description.adoc (100%) rename src/docs/markdown/paths/{updatePet => updatepet}/body/description.md (100%) rename src/docs/markdown/paths/{updatePet => updatepet}/description.md (100%) diff --git a/src/docs/asciidoc/paths/addPet/curl-request.adoc b/src/docs/asciidoc/paths/addpet/curl-request.adoc similarity index 100% rename from src/docs/asciidoc/paths/addPet/curl-request.adoc rename to src/docs/asciidoc/paths/addpet/curl-request.adoc diff --git a/src/docs/asciidoc/paths/addPet/http-request.adoc b/src/docs/asciidoc/paths/addpet/http-request.adoc similarity index 100% rename from src/docs/asciidoc/paths/addPet/http-request.adoc rename to src/docs/asciidoc/paths/addpet/http-request.adoc diff --git a/src/docs/asciidoc/paths/addPet/http-response.adoc b/src/docs/asciidoc/paths/addpet/http-response.adoc similarity index 100% rename from src/docs/asciidoc/paths/addPet/http-response.adoc rename to src/docs/asciidoc/paths/addpet/http-response.adoc diff --git a/src/docs/asciidoc/paths/updatePet/body/description.adoc b/src/docs/asciidoc/paths/updatepet/body/description.adoc similarity index 100% rename from src/docs/asciidoc/paths/updatePet/body/description.adoc rename to src/docs/asciidoc/paths/updatepet/body/description.adoc diff --git a/src/docs/asciidoc/paths/updatePet/description.adoc b/src/docs/asciidoc/paths/updatepet/description.adoc similarity index 100% rename from src/docs/asciidoc/paths/updatePet/description.adoc rename to src/docs/asciidoc/paths/updatepet/description.adoc diff --git a/src/docs/markdown/paths/updatePet/body/description.md b/src/docs/markdown/paths/updatepet/body/description.md similarity index 100% rename from src/docs/markdown/paths/updatePet/body/description.md rename to src/docs/markdown/paths/updatepet/body/description.md diff --git a/src/docs/markdown/paths/updatePet/description.md b/src/docs/markdown/paths/updatepet/description.md similarity index 100% rename from src/docs/markdown/paths/updatePet/description.md rename to src/docs/markdown/paths/updatepet/description.md