From 42270b127c0b26730e5148e8c9195055f1becd79 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Mon, 16 Feb 2015 16:46:56 +0000 Subject: [PATCH] Improve code structure, javadoc, and build configuration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit makes extensive changes to the structure of the code. It introduces a number of separate packages to provide better separation of the various areas of functionality. Alongside this change the project has been renamed from spring-restdocs-core to spring-restdocs. The build has been improved to provide support for building the samples from the main build using the buildSamples task. While this change has been made, the samples remain standalone projects so that their configuration is not dependent on the main project’s build. Running buildSamples will build the samples using both Maven and Gradle. All of the main project’s classes now have javadoc and licence/copyright headers. --- build.gradle | 85 +++-- gradle/wrapper/gradle-wrapper.properties | 4 +- .../.settings/org.eclipse.jdt.core.prefs | 0 .../.settings/org.eclipse.jdt.ui.prefs | 0 .../rest-notes-spring-data-rest}/build.gradle | 2 +- .../gradle/wrapper/gradle-wrapper.jar | Bin .../gradle/wrapper/gradle-wrapper.properties | 0 .../rest-notes-spring-data-rest}/gradlew | 0 .../rest-notes-spring-data-rest}/gradlew.bat | 0 .../rest-notes-spring-data-rest}/pom.xml | 2 +- .../src/main/asciidoc/api-guide.asciidoc | 0 .../asciidoc/getting-started-guide.asciidoc | 0 .../src/main/java/com/example/notes/Note.java | 0 .../com/example/notes/NoteRepository.java | 0 .../notes/RestNotesSpringDataRest.java | 0 .../src/main/java/com/example/notes/Tag.java | 0 .../java/com/example/notes/TagRepository.java | 0 .../com/example/notes/ApiDocumentation.java | 8 +- .../notes/GettingStartedDocumentation.java | 6 +- .../.settings/org.eclipse.jdt.core.prefs | 0 .../.settings/org.eclipse.jdt.ui.prefs | 0 .../rest-notes-spring-hateoas}/build.gradle | 4 +- .../gradle/wrapper/gradle-wrapper.jar | Bin .../gradle/wrapper/gradle-wrapper.properties | 0 .../rest-notes-spring-hateoas}/gradlew | 0 .../rest-notes-spring-hateoas}/gradlew.bat | 0 .../rest-notes-spring-hateoas}/pom.xml | 2 +- .../src/main/asciidoc/api-guide.asciidoc | 0 .../asciidoc/getting-started-guide.asciidoc | 0 .../com/example/notes/AbstractNoteInput.java | 0 .../com/example/notes/AbstractTagInput.java | 0 .../ExceptionSupressingErrorAttributes.java | 0 .../com/example/notes/IndexController.java | 0 .../example/notes/NestedContentResource.java | 0 .../src/main/java/com/example/notes/Note.java | 0 .../java/com/example/notes/NoteInput.java | 0 .../com/example/notes/NotePatchInput.java | 0 .../com/example/notes/NoteRepository.java | 0 .../example/notes/NoteResourceAssembler.java | 0 .../com/example/notes/NotesController.java | 0 .../com/example/notes/NullOrNotBlank.java | 0 .../notes/ResourceDoesNotExistException.java | 0 .../notes/RestNotesControllerAdvice.java | 0 .../example/notes/RestNotesSpringHateoas.java | 0 .../src/main/java/com/example/notes/Tag.java | 0 .../main/java/com/example/notes/TagInput.java | 0 .../java/com/example/notes/TagPatchInput.java | 0 .../java/com/example/notes/TagRepository.java | 0 .../example/notes/TagResourceAssembler.java | 0 .../com/example/notes/TagsController.java | 0 .../src/main/resources/application.properties | 0 .../com/example/notes/ApiDocumentation.java | 8 +- .../notes/GettingStartedDocumentation.java | 6 +- settings.gradle | 4 +- .../core/RestDocumentationConfiguration.java | 65 ---- .../core/RestDocumentationResultHandler.java | 61 ---- .../core/RestDocumentationResultHandlers.java | 319 ------------------ .../.settings/org.eclipse.jdt.core.prefs | 0 .../.settings/org.eclipse.jdt.ui.prefs | 0 .../restdocs/RestDocumentation.java | 45 +++ .../restdocs/RestDocumentationConfigurer.java | 112 ++++++ .../RestDocumentationResultHandler.java | 100 ++++++ .../restdocs/curl/CurlConfiguration.java | 23 +- .../restdocs/curl/CurlDocumentation.java | 189 +++++++++++ .../curl/CurlSnippetResultHandler.java | 44 +++ .../hypermedia/HypermediaDocumentation.java | 63 ++++ .../restdocs/hypermedia}/Link.java | 2 +- .../restdocs/hypermedia}/LinkDescriptor.java | 19 +- .../restdocs/hypermedia}/LinkExtractor.java | 2 +- .../restdocs/hypermedia}/LinkExtractors.java | 10 +- .../hypermedia/LinkSnippetResultHandler.java | 113 +++++++ .../restdocs/snippet/AsciidoctorWriter.java | 45 +-- .../snippet}/DocumentationProperties.java | 4 +- .../restdocs/snippet/DocumentationWriter.java | 74 ++++ .../snippet/SnippetWritingResultHandler.java | 79 +++++ .../restdocs/util}/IterableEnumeration.java | 22 +- .../restdocs/core/LinkExtractorsTests.java | 3 + .../RestDocumentationConfigurerTests.java | 78 +++++ .../snippet/AsciidoctorWriterTests.java | 67 ++++ .../atom/multiple-links-different-rels.json | 0 .../atom/multiple-links-same-rels.json | 0 .../link-payloads/atom/no-links.json | 0 .../link-payloads/atom/single-link.json | 0 .../link-payloads/atom/wrong-format.json | 0 .../hal/multiple-links-different-rels.json | 0 .../hal/multiple-links-same-rels.json | 0 .../resources/link-payloads/hal/no-links.json | 0 .../link-payloads/hal/single-link.json | 0 .../link-payloads/hal/wrong-format.json | 0 89 files changed, 1137 insertions(+), 533 deletions(-) rename {rest-notes-spring-data-rest => samples/rest-notes-spring-data-rest}/.settings/org.eclipse.jdt.core.prefs (100%) rename {rest-notes-spring-data-rest => samples/rest-notes-spring-data-rest}/.settings/org.eclipse.jdt.ui.prefs (100%) rename {rest-notes-spring-data-rest => samples/rest-notes-spring-data-rest}/build.gradle (93%) rename {rest-notes-spring-data-rest => samples/rest-notes-spring-data-rest}/gradle/wrapper/gradle-wrapper.jar (100%) rename {rest-notes-spring-data-rest => samples/rest-notes-spring-data-rest}/gradle/wrapper/gradle-wrapper.properties (100%) rename {rest-notes-spring-data-rest => samples/rest-notes-spring-data-rest}/gradlew (100%) rename {rest-notes-spring-data-rest => samples/rest-notes-spring-data-rest}/gradlew.bat (100%) rename {rest-notes-spring-data-rest => samples/rest-notes-spring-data-rest}/pom.xml (98%) rename {rest-notes-spring-data-rest => samples/rest-notes-spring-data-rest}/src/main/asciidoc/api-guide.asciidoc (100%) rename {rest-notes-spring-data-rest => samples/rest-notes-spring-data-rest}/src/main/asciidoc/getting-started-guide.asciidoc (100%) rename {rest-notes-spring-data-rest => samples/rest-notes-spring-data-rest}/src/main/java/com/example/notes/Note.java (100%) rename {rest-notes-spring-data-rest => samples/rest-notes-spring-data-rest}/src/main/java/com/example/notes/NoteRepository.java (100%) rename {rest-notes-spring-data-rest => samples/rest-notes-spring-data-rest}/src/main/java/com/example/notes/RestNotesSpringDataRest.java (100%) rename {rest-notes-spring-data-rest => samples/rest-notes-spring-data-rest}/src/main/java/com/example/notes/Tag.java (100%) rename {rest-notes-spring-data-rest => samples/rest-notes-spring-data-rest}/src/main/java/com/example/notes/TagRepository.java (100%) rename {rest-notes-spring-data-rest => samples/rest-notes-spring-data-rest}/src/test/java/com/example/notes/ApiDocumentation.java (97%) rename {rest-notes-spring-data-rest => samples/rest-notes-spring-data-rest}/src/test/java/com/example/notes/GettingStartedDocumentation.java (97%) rename {rest-notes-spring-hateoas => samples/rest-notes-spring-hateoas}/.settings/org.eclipse.jdt.core.prefs (100%) rename {rest-notes-spring-hateoas => samples/rest-notes-spring-hateoas}/.settings/org.eclipse.jdt.ui.prefs (100%) rename {rest-notes-spring-hateoas => samples/rest-notes-spring-hateoas}/build.gradle (91%) rename {rest-notes-spring-hateoas => samples/rest-notes-spring-hateoas}/gradle/wrapper/gradle-wrapper.jar (100%) rename {rest-notes-spring-hateoas => samples/rest-notes-spring-hateoas}/gradle/wrapper/gradle-wrapper.properties (100%) rename {rest-notes-spring-hateoas => samples/rest-notes-spring-hateoas}/gradlew (100%) rename {rest-notes-spring-hateoas => samples/rest-notes-spring-hateoas}/gradlew.bat (100%) rename {rest-notes-spring-hateoas => samples/rest-notes-spring-hateoas}/pom.xml (98%) rename {rest-notes-spring-hateoas => samples/rest-notes-spring-hateoas}/src/main/asciidoc/api-guide.asciidoc (100%) rename {rest-notes-spring-hateoas => samples/rest-notes-spring-hateoas}/src/main/asciidoc/getting-started-guide.asciidoc (100%) rename {rest-notes-spring-hateoas => samples/rest-notes-spring-hateoas}/src/main/java/com/example/notes/AbstractNoteInput.java (100%) rename {rest-notes-spring-hateoas => samples/rest-notes-spring-hateoas}/src/main/java/com/example/notes/AbstractTagInput.java (100%) rename {rest-notes-spring-hateoas => samples/rest-notes-spring-hateoas}/src/main/java/com/example/notes/ExceptionSupressingErrorAttributes.java (100%) rename {rest-notes-spring-hateoas => samples/rest-notes-spring-hateoas}/src/main/java/com/example/notes/IndexController.java (100%) rename {rest-notes-spring-hateoas => samples/rest-notes-spring-hateoas}/src/main/java/com/example/notes/NestedContentResource.java (100%) rename {rest-notes-spring-hateoas => samples/rest-notes-spring-hateoas}/src/main/java/com/example/notes/Note.java (100%) rename {rest-notes-spring-hateoas => samples/rest-notes-spring-hateoas}/src/main/java/com/example/notes/NoteInput.java (100%) rename {rest-notes-spring-hateoas => samples/rest-notes-spring-hateoas}/src/main/java/com/example/notes/NotePatchInput.java (100%) rename {rest-notes-spring-hateoas => samples/rest-notes-spring-hateoas}/src/main/java/com/example/notes/NoteRepository.java (100%) rename {rest-notes-spring-hateoas => samples/rest-notes-spring-hateoas}/src/main/java/com/example/notes/NoteResourceAssembler.java (100%) rename {rest-notes-spring-hateoas => samples/rest-notes-spring-hateoas}/src/main/java/com/example/notes/NotesController.java (100%) rename {rest-notes-spring-hateoas => samples/rest-notes-spring-hateoas}/src/main/java/com/example/notes/NullOrNotBlank.java (100%) rename {rest-notes-spring-hateoas => samples/rest-notes-spring-hateoas}/src/main/java/com/example/notes/ResourceDoesNotExistException.java (100%) rename {rest-notes-spring-hateoas => samples/rest-notes-spring-hateoas}/src/main/java/com/example/notes/RestNotesControllerAdvice.java (100%) rename {rest-notes-spring-hateoas => samples/rest-notes-spring-hateoas}/src/main/java/com/example/notes/RestNotesSpringHateoas.java (100%) rename {rest-notes-spring-hateoas => samples/rest-notes-spring-hateoas}/src/main/java/com/example/notes/Tag.java (100%) rename {rest-notes-spring-hateoas => samples/rest-notes-spring-hateoas}/src/main/java/com/example/notes/TagInput.java (100%) rename {rest-notes-spring-hateoas => samples/rest-notes-spring-hateoas}/src/main/java/com/example/notes/TagPatchInput.java (100%) rename {rest-notes-spring-hateoas => samples/rest-notes-spring-hateoas}/src/main/java/com/example/notes/TagRepository.java (100%) rename {rest-notes-spring-hateoas => samples/rest-notes-spring-hateoas}/src/main/java/com/example/notes/TagResourceAssembler.java (100%) rename {rest-notes-spring-hateoas => samples/rest-notes-spring-hateoas}/src/main/java/com/example/notes/TagsController.java (100%) rename {rest-notes-spring-hateoas => samples/rest-notes-spring-hateoas}/src/main/resources/application.properties (100%) rename {rest-notes-spring-hateoas => samples/rest-notes-spring-hateoas}/src/test/java/com/example/notes/ApiDocumentation.java (97%) rename {rest-notes-spring-hateoas => samples/rest-notes-spring-hateoas}/src/test/java/com/example/notes/GettingStartedDocumentation.java (97%) delete mode 100644 spring-restdocs-core/src/main/java/org/springframework/restdocs/core/RestDocumentationConfiguration.java delete mode 100644 spring-restdocs-core/src/main/java/org/springframework/restdocs/core/RestDocumentationResultHandler.java delete mode 100644 spring-restdocs-core/src/main/java/org/springframework/restdocs/core/RestDocumentationResultHandlers.java rename {spring-restdocs-core => spring-restdocs}/.settings/org.eclipse.jdt.core.prefs (100%) rename {spring-restdocs-core => spring-restdocs}/.settings/org.eclipse.jdt.ui.prefs (100%) create mode 100644 spring-restdocs/src/main/java/org/springframework/restdocs/RestDocumentation.java create mode 100644 spring-restdocs/src/main/java/org/springframework/restdocs/RestDocumentationConfigurer.java create mode 100644 spring-restdocs/src/main/java/org/springframework/restdocs/RestDocumentationResultHandler.java rename spring-restdocs-core/src/main/java/org/springframework/restdocs/core/RestDocumentation.java => spring-restdocs/src/main/java/org/springframework/restdocs/curl/CurlConfiguration.java (60%) create mode 100644 spring-restdocs/src/main/java/org/springframework/restdocs/curl/CurlDocumentation.java create mode 100644 spring-restdocs/src/main/java/org/springframework/restdocs/curl/CurlSnippetResultHandler.java create mode 100644 spring-restdocs/src/main/java/org/springframework/restdocs/hypermedia/HypermediaDocumentation.java rename {spring-restdocs-core/src/main/java/org/springframework/restdocs/core => spring-restdocs/src/main/java/org/springframework/restdocs/hypermedia}/Link.java (97%) rename {spring-restdocs-core/src/main/java/org/springframework/restdocs/core => spring-restdocs/src/main/java/org/springframework/restdocs/hypermedia}/LinkDescriptor.java (68%) rename {spring-restdocs-core/src/main/java/org/springframework/restdocs/core => spring-restdocs/src/main/java/org/springframework/restdocs/hypermedia}/LinkExtractor.java (96%) rename {spring-restdocs-core/src/main/java/org/springframework/restdocs/core => spring-restdocs/src/main/java/org/springframework/restdocs/hypermedia}/LinkExtractors.java (96%) create mode 100644 spring-restdocs/src/main/java/org/springframework/restdocs/hypermedia/LinkSnippetResultHandler.java rename spring-restdocs-core/src/main/java/org/springframework/restdocs/core/DocumentationWriter.java => spring-restdocs/src/main/java/org/springframework/restdocs/snippet/AsciidoctorWriter.java (50%) rename {spring-restdocs-core/src/main/java/org/springframework/restdocs/core => spring-restdocs/src/main/java/org/springframework/restdocs/snippet}/DocumentationProperties.java (93%) create mode 100644 spring-restdocs/src/main/java/org/springframework/restdocs/snippet/DocumentationWriter.java create mode 100644 spring-restdocs/src/main/java/org/springframework/restdocs/snippet/SnippetWritingResultHandler.java rename {spring-restdocs-core/src/main/java/org/springframework/restdocs/core => spring-restdocs/src/main/java/org/springframework/restdocs/util}/IterableEnumeration.java (65%) rename {spring-restdocs-core => spring-restdocs}/src/test/java/org/springframework/restdocs/core/LinkExtractorsTests.java (95%) create mode 100644 spring-restdocs/src/test/java/org/springframework/restdocs/core/RestDocumentationConfigurerTests.java create mode 100644 spring-restdocs/src/test/java/org/springframework/restdocs/snippet/AsciidoctorWriterTests.java rename {spring-restdocs-core => spring-restdocs}/src/test/resources/link-payloads/atom/multiple-links-different-rels.json (100%) rename {spring-restdocs-core => spring-restdocs}/src/test/resources/link-payloads/atom/multiple-links-same-rels.json (100%) rename {spring-restdocs-core => spring-restdocs}/src/test/resources/link-payloads/atom/no-links.json (100%) rename {spring-restdocs-core => spring-restdocs}/src/test/resources/link-payloads/atom/single-link.json (100%) rename {spring-restdocs-core => spring-restdocs}/src/test/resources/link-payloads/atom/wrong-format.json (100%) rename {spring-restdocs-core => spring-restdocs}/src/test/resources/link-payloads/hal/multiple-links-different-rels.json (100%) rename {spring-restdocs-core => spring-restdocs}/src/test/resources/link-payloads/hal/multiple-links-same-rels.json (100%) rename {spring-restdocs-core => spring-restdocs}/src/test/resources/link-payloads/hal/no-links.json (100%) rename {spring-restdocs-core => spring-restdocs}/src/test/resources/link-payloads/hal/single-link.json (100%) rename {spring-restdocs-core => spring-restdocs}/src/test/resources/link-payloads/hal/wrong-format.json (100%) diff --git a/build.gradle b/build.gradle index e61cbffe..3337251d 100644 --- a/build.gradle +++ b/build.gradle @@ -1,33 +1,25 @@ -allprojects { - ext { - springVersion = '4.1.1.RELEASE' - } - group = 'org.springframework.restdocs' -} +project(':spring-restdocs') { + + ext { + jacksonVersion = '2.3.4' + junitVersion = '4.11' + servletApiVersion = '3.1.0' + springVersion = '4.1.4.RELEASE' + } + + group = 'org.springframework.restdocs' -project(':spring-restdocs-core') { apply plugin: 'java' + apply plugin: 'eclipse' + apply plugin: 'maven' sourceCompatibility = 1.7 targetCompatibility = 1.7 - dependencies { - compile 'junit:junit:4.11' - compile "org.springframework:spring-test:$springVersion" - compile "org.springframework:spring-web:$springVersion" - compile 'javax.servlet:javax.servlet-api:3.1.0' - compile 'com.fasterxml.jackson.core:jackson-databind:2.3.4' - } -} - -subprojects { repositories { jcenter() } - apply plugin: 'eclipse' - apply plugin: 'maven' - task sourcesJar(type: Jar) { classifier = 'sources' from project.sourceSets.main.allSource @@ -45,4 +37,57 @@ subprojects { eclipseJdt.onlyIf { false } cleanEclipseJdt.onlyIf { false } + + dependencies { + compile "junit:junit:$junitVersion" + compile "org.springframework:spring-test:$springVersion" + compile "org.springframework:spring-web:$springVersion" + compile "javax.servlet:javax.servlet-api:$servletApiVersion" + compile "com.fasterxml.jackson.core:jackson-databind:$jacksonVersion" + } +} + +task buildSamples { + description = 'Assembles and tests the sample projects using both Maven and Gradle' + group = 'Build' + dependsOn 'buildMavenSamples' + dependsOn 'buildGradleSamples' +} + +task buildMavenSamples { + dependsOn 'buildRestNotesSpringHateoasSampleWithMaven' + dependsOn 'buildRestNotesSpringDataRestSampleWithMaven' +} + +task buildGradleSamples { + dependsOn 'buildRestNotesSpringHateoasSampleWithGradle' + dependsOn 'buildRestNotesSpringDataRestSampleWithGradle' +} + +task buildRestNotesSpringHateoasSampleWithGradle(type: GradleBuild) { + dependsOn 'spring-restdocs:install' + dir = 'samples/rest-notes-spring-hateoas' + tasks = ['clean', 'build'] +} + +task buildRestNotesSpringDataRestSampleWithGradle(type: GradleBuild) { + dependsOn 'spring-restdocs:install' + dir = 'samples/rest-notes-spring-data-rest' + tasks = ['clean', 'build'] +} + +task buildRestNotesSpringHateoasSampleWithMaven(type: Exec) { + dependsOn 'spring-restdocs:install' + workingDir 'samples/rest-notes-spring-hateoas' + commandLine 'mvn', 'clean', 'package' +} + +task buildRestNotesSpringDataRestSampleWithMaven(type: Exec) { + dependsOn 'spring-restdocs:install' + workingDir 'samples/rest-notes-spring-data-rest' + commandLine 'mvn', 'clean', 'package' +} + +wrapper { + gradleVersion = '2.2' } \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index a8952509..0cf48989 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Wed Oct 08 10:04:39 BST 2014 +#Mon Feb 16 13:50:18 GMT 2015 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-2.2-bin.zip diff --git a/rest-notes-spring-data-rest/.settings/org.eclipse.jdt.core.prefs b/samples/rest-notes-spring-data-rest/.settings/org.eclipse.jdt.core.prefs similarity index 100% rename from rest-notes-spring-data-rest/.settings/org.eclipse.jdt.core.prefs rename to samples/rest-notes-spring-data-rest/.settings/org.eclipse.jdt.core.prefs diff --git a/rest-notes-spring-data-rest/.settings/org.eclipse.jdt.ui.prefs b/samples/rest-notes-spring-data-rest/.settings/org.eclipse.jdt.ui.prefs similarity index 100% rename from rest-notes-spring-data-rest/.settings/org.eclipse.jdt.ui.prefs rename to samples/rest-notes-spring-data-rest/.settings/org.eclipse.jdt.ui.prefs diff --git a/rest-notes-spring-data-rest/build.gradle b/samples/rest-notes-spring-data-rest/build.gradle similarity index 93% rename from rest-notes-spring-data-rest/build.gradle rename to samples/rest-notes-spring-data-rest/build.gradle index fa6262c9..21ba3459 100644 --- a/rest-notes-spring-data-rest/build.gradle +++ b/samples/rest-notes-spring-data-rest/build.gradle @@ -31,7 +31,7 @@ dependencies { testCompile 'com.jayway.jsonpath:json-path' testCompile 'org.springframework.boot:spring-boot-starter-test' - testCompile 'org.springframework.restdocs:spring-restdocs-core:0.1.0.BUILD-SNAPSHOT' + testCompile 'org.springframework.restdocs:spring-restdocs:0.1.0.BUILD-SNAPSHOT' } diff --git a/rest-notes-spring-data-rest/gradle/wrapper/gradle-wrapper.jar b/samples/rest-notes-spring-data-rest/gradle/wrapper/gradle-wrapper.jar similarity index 100% rename from rest-notes-spring-data-rest/gradle/wrapper/gradle-wrapper.jar rename to samples/rest-notes-spring-data-rest/gradle/wrapper/gradle-wrapper.jar diff --git a/rest-notes-spring-data-rest/gradle/wrapper/gradle-wrapper.properties b/samples/rest-notes-spring-data-rest/gradle/wrapper/gradle-wrapper.properties similarity index 100% rename from rest-notes-spring-data-rest/gradle/wrapper/gradle-wrapper.properties rename to samples/rest-notes-spring-data-rest/gradle/wrapper/gradle-wrapper.properties diff --git a/rest-notes-spring-data-rest/gradlew b/samples/rest-notes-spring-data-rest/gradlew similarity index 100% rename from rest-notes-spring-data-rest/gradlew rename to samples/rest-notes-spring-data-rest/gradlew diff --git a/rest-notes-spring-data-rest/gradlew.bat b/samples/rest-notes-spring-data-rest/gradlew.bat similarity index 100% rename from rest-notes-spring-data-rest/gradlew.bat rename to samples/rest-notes-spring-data-rest/gradlew.bat diff --git a/rest-notes-spring-data-rest/pom.xml b/samples/rest-notes-spring-data-rest/pom.xml similarity index 98% rename from rest-notes-spring-data-rest/pom.xml rename to samples/rest-notes-spring-data-rest/pom.xml index 37b10e6b..1cc246de 100644 --- a/rest-notes-spring-data-rest/pom.xml +++ b/samples/rest-notes-spring-data-rest/pom.xml @@ -48,7 +48,7 @@ org.springframework.restdocs - spring-restdocs-core + spring-restdocs 0.1.0.BUILD-SNAPSHOT test diff --git a/rest-notes-spring-data-rest/src/main/asciidoc/api-guide.asciidoc b/samples/rest-notes-spring-data-rest/src/main/asciidoc/api-guide.asciidoc similarity index 100% rename from rest-notes-spring-data-rest/src/main/asciidoc/api-guide.asciidoc rename to samples/rest-notes-spring-data-rest/src/main/asciidoc/api-guide.asciidoc diff --git a/rest-notes-spring-data-rest/src/main/asciidoc/getting-started-guide.asciidoc b/samples/rest-notes-spring-data-rest/src/main/asciidoc/getting-started-guide.asciidoc similarity index 100% rename from rest-notes-spring-data-rest/src/main/asciidoc/getting-started-guide.asciidoc rename to samples/rest-notes-spring-data-rest/src/main/asciidoc/getting-started-guide.asciidoc diff --git a/rest-notes-spring-data-rest/src/main/java/com/example/notes/Note.java b/samples/rest-notes-spring-data-rest/src/main/java/com/example/notes/Note.java similarity index 100% rename from rest-notes-spring-data-rest/src/main/java/com/example/notes/Note.java rename to samples/rest-notes-spring-data-rest/src/main/java/com/example/notes/Note.java diff --git a/rest-notes-spring-data-rest/src/main/java/com/example/notes/NoteRepository.java b/samples/rest-notes-spring-data-rest/src/main/java/com/example/notes/NoteRepository.java similarity index 100% rename from rest-notes-spring-data-rest/src/main/java/com/example/notes/NoteRepository.java rename to samples/rest-notes-spring-data-rest/src/main/java/com/example/notes/NoteRepository.java diff --git a/rest-notes-spring-data-rest/src/main/java/com/example/notes/RestNotesSpringDataRest.java b/samples/rest-notes-spring-data-rest/src/main/java/com/example/notes/RestNotesSpringDataRest.java similarity index 100% rename from rest-notes-spring-data-rest/src/main/java/com/example/notes/RestNotesSpringDataRest.java rename to samples/rest-notes-spring-data-rest/src/main/java/com/example/notes/RestNotesSpringDataRest.java diff --git a/rest-notes-spring-data-rest/src/main/java/com/example/notes/Tag.java b/samples/rest-notes-spring-data-rest/src/main/java/com/example/notes/Tag.java similarity index 100% rename from rest-notes-spring-data-rest/src/main/java/com/example/notes/Tag.java rename to samples/rest-notes-spring-data-rest/src/main/java/com/example/notes/Tag.java diff --git a/rest-notes-spring-data-rest/src/main/java/com/example/notes/TagRepository.java b/samples/rest-notes-spring-data-rest/src/main/java/com/example/notes/TagRepository.java similarity index 100% rename from rest-notes-spring-data-rest/src/main/java/com/example/notes/TagRepository.java rename to samples/rest-notes-spring-data-rest/src/main/java/com/example/notes/TagRepository.java diff --git a/rest-notes-spring-data-rest/src/test/java/com/example/notes/ApiDocumentation.java b/samples/rest-notes-spring-data-rest/src/test/java/com/example/notes/ApiDocumentation.java similarity index 97% rename from rest-notes-spring-data-rest/src/test/java/com/example/notes/ApiDocumentation.java rename to samples/rest-notes-spring-data-rest/src/test/java/com/example/notes/ApiDocumentation.java index c7ae0946..55fe34e8 100644 --- a/rest-notes-spring-data-rest/src/test/java/com/example/notes/ApiDocumentation.java +++ b/samples/rest-notes-spring-data-rest/src/test/java/com/example/notes/ApiDocumentation.java @@ -18,8 +18,8 @@ package com.example.notes; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; -import static org.springframework.restdocs.core.RestDocumentation.document; -import static org.springframework.restdocs.core.RestDocumentation.linkWithRel; +import static org.springframework.restdocs.RestDocumentation.document; +import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.linkWithRel; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; @@ -39,7 +39,7 @@ import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.SpringApplicationConfiguration; import org.springframework.hateoas.MediaTypes; -import org.springframework.restdocs.core.RestDocumentationConfiguration; +import org.springframework.restdocs.RestDocumentationConfigurer; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.web.WebAppConfiguration; import org.springframework.test.web.servlet.MockMvc; @@ -70,7 +70,7 @@ public class ApiDocumentation { @Before public void setUp() { this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context) - .apply(new RestDocumentationConfiguration()).build(); + .apply(new RestDocumentationConfigurer()).build(); } @Test diff --git a/rest-notes-spring-data-rest/src/test/java/com/example/notes/GettingStartedDocumentation.java b/samples/rest-notes-spring-data-rest/src/test/java/com/example/notes/GettingStartedDocumentation.java similarity index 97% rename from rest-notes-spring-data-rest/src/test/java/com/example/notes/GettingStartedDocumentation.java rename to samples/rest-notes-spring-data-rest/src/test/java/com/example/notes/GettingStartedDocumentation.java index 8687ff2a..ec54ff5d 100644 --- a/rest-notes-spring-data-rest/src/test/java/com/example/notes/GettingStartedDocumentation.java +++ b/samples/rest-notes-spring-data-rest/src/test/java/com/example/notes/GettingStartedDocumentation.java @@ -19,7 +19,7 @@ package com.example.notes; import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; -import static org.springframework.restdocs.core.RestDocumentation.document; +import static org.springframework.restdocs.RestDocumentation.document; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; @@ -38,7 +38,7 @@ import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.SpringApplicationConfiguration; import org.springframework.hateoas.MediaTypes; -import org.springframework.restdocs.core.RestDocumentationConfiguration; +import org.springframework.restdocs.RestDocumentationConfigurer; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.web.WebAppConfiguration; import org.springframework.test.web.servlet.MockMvc; @@ -66,7 +66,7 @@ public class GettingStartedDocumentation { @Before public void setUp() { this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context) - .apply(new RestDocumentationConfiguration()).build(); + .apply(new RestDocumentationConfigurer()).build(); } @Test diff --git a/rest-notes-spring-hateoas/.settings/org.eclipse.jdt.core.prefs b/samples/rest-notes-spring-hateoas/.settings/org.eclipse.jdt.core.prefs similarity index 100% rename from rest-notes-spring-hateoas/.settings/org.eclipse.jdt.core.prefs rename to samples/rest-notes-spring-hateoas/.settings/org.eclipse.jdt.core.prefs diff --git a/rest-notes-spring-hateoas/.settings/org.eclipse.jdt.ui.prefs b/samples/rest-notes-spring-hateoas/.settings/org.eclipse.jdt.ui.prefs similarity index 100% rename from rest-notes-spring-hateoas/.settings/org.eclipse.jdt.ui.prefs rename to samples/rest-notes-spring-hateoas/.settings/org.eclipse.jdt.ui.prefs diff --git a/rest-notes-spring-hateoas/build.gradle b/samples/rest-notes-spring-hateoas/build.gradle similarity index 91% rename from rest-notes-spring-hateoas/build.gradle rename to samples/rest-notes-spring-hateoas/build.gradle index fff6d0e1..6f324f81 100644 --- a/rest-notes-spring-hateoas/build.gradle +++ b/samples/rest-notes-spring-hateoas/build.gradle @@ -8,7 +8,7 @@ buildscript { } plugins { - id "org.asciidoctor.convert" version "1.5.2" + id "org.asciidoctor.convert" version "1.5.2" } apply plugin: 'java' @@ -34,7 +34,7 @@ dependencies { testCompile 'com.jayway.jsonpath:json-path' testCompile 'org.springframework.boot:spring-boot-starter-test' - testCompile 'org.springframework.restdocs:spring-restdocs-core:0.1.0.BUILD-SNAPSHOT' + testCompile 'org.springframework.restdocs:spring-restdocs:0.1.0.BUILD-SNAPSHOT' } ext { diff --git a/rest-notes-spring-hateoas/gradle/wrapper/gradle-wrapper.jar b/samples/rest-notes-spring-hateoas/gradle/wrapper/gradle-wrapper.jar similarity index 100% rename from rest-notes-spring-hateoas/gradle/wrapper/gradle-wrapper.jar rename to samples/rest-notes-spring-hateoas/gradle/wrapper/gradle-wrapper.jar diff --git a/rest-notes-spring-hateoas/gradle/wrapper/gradle-wrapper.properties b/samples/rest-notes-spring-hateoas/gradle/wrapper/gradle-wrapper.properties similarity index 100% rename from rest-notes-spring-hateoas/gradle/wrapper/gradle-wrapper.properties rename to samples/rest-notes-spring-hateoas/gradle/wrapper/gradle-wrapper.properties diff --git a/rest-notes-spring-hateoas/gradlew b/samples/rest-notes-spring-hateoas/gradlew similarity index 100% rename from rest-notes-spring-hateoas/gradlew rename to samples/rest-notes-spring-hateoas/gradlew diff --git a/rest-notes-spring-hateoas/gradlew.bat b/samples/rest-notes-spring-hateoas/gradlew.bat similarity index 100% rename from rest-notes-spring-hateoas/gradlew.bat rename to samples/rest-notes-spring-hateoas/gradlew.bat diff --git a/rest-notes-spring-hateoas/pom.xml b/samples/rest-notes-spring-hateoas/pom.xml similarity index 98% rename from rest-notes-spring-hateoas/pom.xml rename to samples/rest-notes-spring-hateoas/pom.xml index 1193a258..1c9bfbba 100644 --- a/rest-notes-spring-hateoas/pom.xml +++ b/samples/rest-notes-spring-hateoas/pom.xml @@ -64,7 +64,7 @@ org.springframework.restdocs - spring-restdocs-core + spring-restdocs 0.1.0.BUILD-SNAPSHOT test diff --git a/rest-notes-spring-hateoas/src/main/asciidoc/api-guide.asciidoc b/samples/rest-notes-spring-hateoas/src/main/asciidoc/api-guide.asciidoc similarity index 100% rename from rest-notes-spring-hateoas/src/main/asciidoc/api-guide.asciidoc rename to samples/rest-notes-spring-hateoas/src/main/asciidoc/api-guide.asciidoc diff --git a/rest-notes-spring-hateoas/src/main/asciidoc/getting-started-guide.asciidoc b/samples/rest-notes-spring-hateoas/src/main/asciidoc/getting-started-guide.asciidoc similarity index 100% rename from rest-notes-spring-hateoas/src/main/asciidoc/getting-started-guide.asciidoc rename to samples/rest-notes-spring-hateoas/src/main/asciidoc/getting-started-guide.asciidoc diff --git a/rest-notes-spring-hateoas/src/main/java/com/example/notes/AbstractNoteInput.java b/samples/rest-notes-spring-hateoas/src/main/java/com/example/notes/AbstractNoteInput.java similarity index 100% rename from rest-notes-spring-hateoas/src/main/java/com/example/notes/AbstractNoteInput.java rename to samples/rest-notes-spring-hateoas/src/main/java/com/example/notes/AbstractNoteInput.java diff --git a/rest-notes-spring-hateoas/src/main/java/com/example/notes/AbstractTagInput.java b/samples/rest-notes-spring-hateoas/src/main/java/com/example/notes/AbstractTagInput.java similarity index 100% rename from rest-notes-spring-hateoas/src/main/java/com/example/notes/AbstractTagInput.java rename to samples/rest-notes-spring-hateoas/src/main/java/com/example/notes/AbstractTagInput.java diff --git a/rest-notes-spring-hateoas/src/main/java/com/example/notes/ExceptionSupressingErrorAttributes.java b/samples/rest-notes-spring-hateoas/src/main/java/com/example/notes/ExceptionSupressingErrorAttributes.java similarity index 100% rename from rest-notes-spring-hateoas/src/main/java/com/example/notes/ExceptionSupressingErrorAttributes.java rename to samples/rest-notes-spring-hateoas/src/main/java/com/example/notes/ExceptionSupressingErrorAttributes.java diff --git a/rest-notes-spring-hateoas/src/main/java/com/example/notes/IndexController.java b/samples/rest-notes-spring-hateoas/src/main/java/com/example/notes/IndexController.java similarity index 100% rename from rest-notes-spring-hateoas/src/main/java/com/example/notes/IndexController.java rename to samples/rest-notes-spring-hateoas/src/main/java/com/example/notes/IndexController.java diff --git a/rest-notes-spring-hateoas/src/main/java/com/example/notes/NestedContentResource.java b/samples/rest-notes-spring-hateoas/src/main/java/com/example/notes/NestedContentResource.java similarity index 100% rename from rest-notes-spring-hateoas/src/main/java/com/example/notes/NestedContentResource.java rename to samples/rest-notes-spring-hateoas/src/main/java/com/example/notes/NestedContentResource.java diff --git a/rest-notes-spring-hateoas/src/main/java/com/example/notes/Note.java b/samples/rest-notes-spring-hateoas/src/main/java/com/example/notes/Note.java similarity index 100% rename from rest-notes-spring-hateoas/src/main/java/com/example/notes/Note.java rename to samples/rest-notes-spring-hateoas/src/main/java/com/example/notes/Note.java diff --git a/rest-notes-spring-hateoas/src/main/java/com/example/notes/NoteInput.java b/samples/rest-notes-spring-hateoas/src/main/java/com/example/notes/NoteInput.java similarity index 100% rename from rest-notes-spring-hateoas/src/main/java/com/example/notes/NoteInput.java rename to samples/rest-notes-spring-hateoas/src/main/java/com/example/notes/NoteInput.java diff --git a/rest-notes-spring-hateoas/src/main/java/com/example/notes/NotePatchInput.java b/samples/rest-notes-spring-hateoas/src/main/java/com/example/notes/NotePatchInput.java similarity index 100% rename from rest-notes-spring-hateoas/src/main/java/com/example/notes/NotePatchInput.java rename to samples/rest-notes-spring-hateoas/src/main/java/com/example/notes/NotePatchInput.java diff --git a/rest-notes-spring-hateoas/src/main/java/com/example/notes/NoteRepository.java b/samples/rest-notes-spring-hateoas/src/main/java/com/example/notes/NoteRepository.java similarity index 100% rename from rest-notes-spring-hateoas/src/main/java/com/example/notes/NoteRepository.java rename to samples/rest-notes-spring-hateoas/src/main/java/com/example/notes/NoteRepository.java diff --git a/rest-notes-spring-hateoas/src/main/java/com/example/notes/NoteResourceAssembler.java b/samples/rest-notes-spring-hateoas/src/main/java/com/example/notes/NoteResourceAssembler.java similarity index 100% rename from rest-notes-spring-hateoas/src/main/java/com/example/notes/NoteResourceAssembler.java rename to samples/rest-notes-spring-hateoas/src/main/java/com/example/notes/NoteResourceAssembler.java diff --git a/rest-notes-spring-hateoas/src/main/java/com/example/notes/NotesController.java b/samples/rest-notes-spring-hateoas/src/main/java/com/example/notes/NotesController.java similarity index 100% rename from rest-notes-spring-hateoas/src/main/java/com/example/notes/NotesController.java rename to samples/rest-notes-spring-hateoas/src/main/java/com/example/notes/NotesController.java diff --git a/rest-notes-spring-hateoas/src/main/java/com/example/notes/NullOrNotBlank.java b/samples/rest-notes-spring-hateoas/src/main/java/com/example/notes/NullOrNotBlank.java similarity index 100% rename from rest-notes-spring-hateoas/src/main/java/com/example/notes/NullOrNotBlank.java rename to samples/rest-notes-spring-hateoas/src/main/java/com/example/notes/NullOrNotBlank.java diff --git a/rest-notes-spring-hateoas/src/main/java/com/example/notes/ResourceDoesNotExistException.java b/samples/rest-notes-spring-hateoas/src/main/java/com/example/notes/ResourceDoesNotExistException.java similarity index 100% rename from rest-notes-spring-hateoas/src/main/java/com/example/notes/ResourceDoesNotExistException.java rename to samples/rest-notes-spring-hateoas/src/main/java/com/example/notes/ResourceDoesNotExistException.java diff --git a/rest-notes-spring-hateoas/src/main/java/com/example/notes/RestNotesControllerAdvice.java b/samples/rest-notes-spring-hateoas/src/main/java/com/example/notes/RestNotesControllerAdvice.java similarity index 100% rename from rest-notes-spring-hateoas/src/main/java/com/example/notes/RestNotesControllerAdvice.java rename to samples/rest-notes-spring-hateoas/src/main/java/com/example/notes/RestNotesControllerAdvice.java diff --git a/rest-notes-spring-hateoas/src/main/java/com/example/notes/RestNotesSpringHateoas.java b/samples/rest-notes-spring-hateoas/src/main/java/com/example/notes/RestNotesSpringHateoas.java similarity index 100% rename from rest-notes-spring-hateoas/src/main/java/com/example/notes/RestNotesSpringHateoas.java rename to samples/rest-notes-spring-hateoas/src/main/java/com/example/notes/RestNotesSpringHateoas.java diff --git a/rest-notes-spring-hateoas/src/main/java/com/example/notes/Tag.java b/samples/rest-notes-spring-hateoas/src/main/java/com/example/notes/Tag.java similarity index 100% rename from rest-notes-spring-hateoas/src/main/java/com/example/notes/Tag.java rename to samples/rest-notes-spring-hateoas/src/main/java/com/example/notes/Tag.java diff --git a/rest-notes-spring-hateoas/src/main/java/com/example/notes/TagInput.java b/samples/rest-notes-spring-hateoas/src/main/java/com/example/notes/TagInput.java similarity index 100% rename from rest-notes-spring-hateoas/src/main/java/com/example/notes/TagInput.java rename to samples/rest-notes-spring-hateoas/src/main/java/com/example/notes/TagInput.java diff --git a/rest-notes-spring-hateoas/src/main/java/com/example/notes/TagPatchInput.java b/samples/rest-notes-spring-hateoas/src/main/java/com/example/notes/TagPatchInput.java similarity index 100% rename from rest-notes-spring-hateoas/src/main/java/com/example/notes/TagPatchInput.java rename to samples/rest-notes-spring-hateoas/src/main/java/com/example/notes/TagPatchInput.java diff --git a/rest-notes-spring-hateoas/src/main/java/com/example/notes/TagRepository.java b/samples/rest-notes-spring-hateoas/src/main/java/com/example/notes/TagRepository.java similarity index 100% rename from rest-notes-spring-hateoas/src/main/java/com/example/notes/TagRepository.java rename to samples/rest-notes-spring-hateoas/src/main/java/com/example/notes/TagRepository.java diff --git a/rest-notes-spring-hateoas/src/main/java/com/example/notes/TagResourceAssembler.java b/samples/rest-notes-spring-hateoas/src/main/java/com/example/notes/TagResourceAssembler.java similarity index 100% rename from rest-notes-spring-hateoas/src/main/java/com/example/notes/TagResourceAssembler.java rename to samples/rest-notes-spring-hateoas/src/main/java/com/example/notes/TagResourceAssembler.java diff --git a/rest-notes-spring-hateoas/src/main/java/com/example/notes/TagsController.java b/samples/rest-notes-spring-hateoas/src/main/java/com/example/notes/TagsController.java similarity index 100% rename from rest-notes-spring-hateoas/src/main/java/com/example/notes/TagsController.java rename to samples/rest-notes-spring-hateoas/src/main/java/com/example/notes/TagsController.java diff --git a/rest-notes-spring-hateoas/src/main/resources/application.properties b/samples/rest-notes-spring-hateoas/src/main/resources/application.properties similarity index 100% rename from rest-notes-spring-hateoas/src/main/resources/application.properties rename to samples/rest-notes-spring-hateoas/src/main/resources/application.properties diff --git a/rest-notes-spring-hateoas/src/test/java/com/example/notes/ApiDocumentation.java b/samples/rest-notes-spring-hateoas/src/test/java/com/example/notes/ApiDocumentation.java similarity index 97% rename from rest-notes-spring-hateoas/src/test/java/com/example/notes/ApiDocumentation.java rename to samples/rest-notes-spring-hateoas/src/test/java/com/example/notes/ApiDocumentation.java index 7e201ed2..d82451c8 100644 --- a/rest-notes-spring-hateoas/src/test/java/com/example/notes/ApiDocumentation.java +++ b/samples/rest-notes-spring-hateoas/src/test/java/com/example/notes/ApiDocumentation.java @@ -18,8 +18,8 @@ package com.example.notes; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; -import static org.springframework.restdocs.core.RestDocumentation.document; -import static org.springframework.restdocs.core.RestDocumentation.linkWithRel; +import static org.springframework.restdocs.RestDocumentation.document; +import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.linkWithRel; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; @@ -39,7 +39,7 @@ import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.SpringApplicationConfiguration; import org.springframework.hateoas.MediaTypes; -import org.springframework.restdocs.core.RestDocumentationConfiguration; +import org.springframework.restdocs.RestDocumentationConfigurer; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.web.WebAppConfiguration; import org.springframework.test.web.servlet.MockMvc; @@ -70,7 +70,7 @@ public class ApiDocumentation { @Before public void setUp() { this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context) - .apply(new RestDocumentationConfiguration()).build(); + .apply(new RestDocumentationConfigurer()).build(); } @Test diff --git a/rest-notes-spring-hateoas/src/test/java/com/example/notes/GettingStartedDocumentation.java b/samples/rest-notes-spring-hateoas/src/test/java/com/example/notes/GettingStartedDocumentation.java similarity index 97% rename from rest-notes-spring-hateoas/src/test/java/com/example/notes/GettingStartedDocumentation.java rename to samples/rest-notes-spring-hateoas/src/test/java/com/example/notes/GettingStartedDocumentation.java index a37e573e..49892b52 100644 --- a/rest-notes-spring-hateoas/src/test/java/com/example/notes/GettingStartedDocumentation.java +++ b/samples/rest-notes-spring-hateoas/src/test/java/com/example/notes/GettingStartedDocumentation.java @@ -19,7 +19,7 @@ package com.example.notes; import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; -import static org.springframework.restdocs.core.RestDocumentation.document; +import static org.springframework.restdocs.RestDocumentation.document; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; @@ -39,7 +39,7 @@ import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.SpringApplicationConfiguration; import org.springframework.hateoas.MediaTypes; -import org.springframework.restdocs.core.RestDocumentationConfiguration; +import org.springframework.restdocs.RestDocumentationConfigurer; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.web.WebAppConfiguration; import org.springframework.test.web.servlet.MockMvc; @@ -67,7 +67,7 @@ public class GettingStartedDocumentation { @Before public void setUp() { this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context) - .apply(new RestDocumentationConfiguration()).build(); + .apply(new RestDocumentationConfigurer()).build(); } @Test diff --git a/settings.gradle b/settings.gradle index c74ec6c2..80e754ca 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,3 +1,3 @@ -rootProject.name = 'spring-restdocs' +rootProject.name = 'spring-restdocs-build' -include 'spring-restdocs-core' \ No newline at end of file +include 'spring-restdocs' \ No newline at end of file diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/core/RestDocumentationConfiguration.java b/spring-restdocs-core/src/main/java/org/springframework/restdocs/core/RestDocumentationConfiguration.java deleted file mode 100644 index 70a7c70e..00000000 --- a/spring-restdocs-core/src/main/java/org/springframework/restdocs/core/RestDocumentationConfiguration.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2014 the original author or authors. - * - * 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 org.springframework.restdocs.core; - -import org.springframework.mock.web.MockHttpServletRequest; -import org.springframework.test.web.servlet.request.RequestPostProcessor; -import org.springframework.test.web.servlet.setup.ConfigurableMockMvcBuilder; -import org.springframework.test.web.servlet.setup.MockMvcConfigurerAdapter; -import org.springframework.web.context.WebApplicationContext; - -public class RestDocumentationConfiguration extends MockMvcConfigurerAdapter { - - private String scheme = "http"; - - private String host = "localhost"; - - private int port = 8080; - - public RestDocumentationConfiguration withScheme(String scheme) { - this.scheme = scheme; - return this; - } - - public RestDocumentationConfiguration withHost(String host) { - this.host = host; - return this; - } - - public RestDocumentationConfiguration withPort(int port) { - this.port = port; - return this; - } - - @Override - public RequestPostProcessor beforeMockMvcCreated( - ConfigurableMockMvcBuilder builder, WebApplicationContext context) { - return new RequestPostProcessor() { - - @Override - public MockHttpServletRequest postProcessRequest( - MockHttpServletRequest request) { - request.setScheme(RestDocumentationConfiguration.this.scheme); - request.setRemotePort(RestDocumentationConfiguration.this.port); - request.setServerPort(RestDocumentationConfiguration.this.port); - request.setRemoteHost(RestDocumentationConfiguration.this.host); - return request; - } - }; - } - -} diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/core/RestDocumentationResultHandler.java b/spring-restdocs-core/src/main/java/org/springframework/restdocs/core/RestDocumentationResultHandler.java deleted file mode 100644 index a5464bfd..00000000 --- a/spring-restdocs-core/src/main/java/org/springframework/restdocs/core/RestDocumentationResultHandler.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2014 the original author or authors. - * - * 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 org.springframework.restdocs.core; - -import static org.springframework.restdocs.core.RestDocumentationResultHandlers.documentCurlRequest; -import static org.springframework.restdocs.core.RestDocumentationResultHandlers.documentCurlRequestAndResponse; -import static org.springframework.restdocs.core.RestDocumentationResultHandlers.documentCurlResponse; - -import java.util.Arrays; - -import org.springframework.restdocs.core.RestDocumentationResultHandlers.LinkDocumentingResultHandler; -import org.springframework.test.web.servlet.MvcResult; -import org.springframework.test.web.servlet.ResultHandler; - -public class RestDocumentationResultHandler implements ResultHandler { - - private final String outputDir; - - private ResultHandler linkDocumentingResultHandler; - - public RestDocumentationResultHandler(String outputDir) { - this.outputDir = outputDir; - } - - @Override - public void handle(MvcResult result) throws Exception { - documentCurlRequest(this.outputDir).includeResponseHeaders().handle(result); - documentCurlResponse(this.outputDir).includeResponseHeaders().handle(result); - documentCurlRequestAndResponse(this.outputDir).includeResponseHeaders().handle( - result); - if (this.linkDocumentingResultHandler != null) { - this.linkDocumentingResultHandler.handle(result); - } - } - - public RestDocumentationResultHandler withLinks(LinkDescriptor... descriptors) { - return withLinks(null, descriptors); - } - - public RestDocumentationResultHandler withLinks(LinkExtractor linkExtractor, - LinkDescriptor... descriptors) { - this.linkDocumentingResultHandler = new LinkDocumentingResultHandler( - this.outputDir, linkExtractor, Arrays.asList(descriptors)); - return this; - } - -} diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/core/RestDocumentationResultHandlers.java b/spring-restdocs-core/src/main/java/org/springframework/restdocs/core/RestDocumentationResultHandlers.java deleted file mode 100644 index 7b066cc2..00000000 --- a/spring-restdocs-core/src/main/java/org/springframework/restdocs/core/RestDocumentationResultHandlers.java +++ /dev/null @@ -1,319 +0,0 @@ -/* - * Copyright 2014-2015 the original author or authors. - * - * 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 org.springframework.restdocs.core; - -import static org.junit.Assert.fail; -import static org.springframework.restdocs.core.IterableEnumeration.iterable; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.PrintStream; -import java.io.StringWriter; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; - -import org.springframework.http.HttpStatus; -import org.springframework.mock.web.MockHttpServletRequest; -import org.springframework.restdocs.core.DocumentationWriter.DocumentationAction; -import org.springframework.test.web.servlet.MvcResult; -import org.springframework.test.web.servlet.ResultHandler; -import org.springframework.util.Assert; -import org.springframework.util.FileCopyUtils; -import org.springframework.web.bind.annotation.RequestMethod; - -public abstract class RestDocumentationResultHandlers { - - public static CurlResultHandler documentCurlRequest(String outputDir) { - return new CurlResultHandler(outputDir, "request") { - - @Override - public void handle(MvcResult result, DocumentationWriter writer) - throws Exception { - writer.shellCommand(new CurlRequestDocumentationAction(writer, result, - getCurlConfiguration())); - } - }; - } - - public static CurlResultHandler documentCurlResponse(String outputDir) { - return new CurlResultHandler(outputDir, "response") { - - @Override - public void handle(MvcResult result, DocumentationWriter writer) - throws Exception { - writer.codeBlock("http", new CurlResponseDocumentationAction(writer, - result, getCurlConfiguration())); - } - }; - } - - public static CurlResultHandler documentCurlRequestAndResponse(String outputDir) { - return new CurlResultHandler(outputDir, "request-response") { - - @Override - public void handle(MvcResult result, DocumentationWriter writer) - throws Exception { - writer.shellCommand(new CurlRequestDocumentationAction(writer, result, - getCurlConfiguration())); - writer.codeBlock("http", new CurlResponseDocumentationAction(writer, - result, getCurlConfiguration())); - } - }; - } - - private static final class CurlRequestDocumentationAction implements - DocumentationAction { - - private final DocumentationWriter writer; - - private final MvcResult result; - - private final CurlConfiguration curlConfiguration; - - CurlRequestDocumentationAction(DocumentationWriter writer, MvcResult result, - CurlConfiguration curlConfiguration) { - this.writer = writer; - this.result = result; - this.curlConfiguration = curlConfiguration; - } - - @Override - public void perform() throws Exception { - MockHttpServletRequest request = this.result.getRequest(); - this.writer.print(String.format("curl %s://%s:%d%s", request.getScheme(), - request.getRemoteHost(), request.getRemotePort(), - request.getRequestURI())); - - if (this.curlConfiguration.includeResponseHeaders) { - this.writer.print(" -i"); - } - - RequestMethod requestMethod = RequestMethod.valueOf(request.getMethod()); - if (requestMethod != RequestMethod.GET) { - this.writer.print(String.format(" -X %s", requestMethod.toString())); - } - - for (String headerName : iterable(request.getHeaderNames())) { - for (String header : iterable(request.getHeaders(headerName))) { - this.writer - .print(String.format(" -H \"%s: %s\"", headerName, header)); - } - } - - if (request.getContentLengthLong() > 0) { - this.writer.print(String.format(" -d '%s'", getContent(request))); - } - - this.writer.println(); - } - - private String getContent(MockHttpServletRequest request) throws IOException { - StringWriter writer = new StringWriter(); - FileCopyUtils.copy(request.getReader(), writer); - return writer.toString(); - } - } - - private static final class CurlResponseDocumentationAction implements - DocumentationAction { - - private final DocumentationWriter writer; - - private final MvcResult result; - - private final CurlConfiguration curlConfiguration; - - CurlResponseDocumentationAction(DocumentationWriter writer, MvcResult result, - CurlConfiguration curlConfiguration) { - this.writer = writer; - this.result = result; - this.curlConfiguration = curlConfiguration; - } - - @Override - public void perform() throws Exception { - if (this.curlConfiguration.includeResponseHeaders) { - HttpStatus status = HttpStatus.valueOf(this.result.getResponse() - .getStatus()); - this.writer.println(String.format("HTTP/1.1 %d %s", status.value(), - status.getReasonPhrase())); - for (String headerName : this.result.getResponse().getHeaderNames()) { - for (String header : this.result.getResponse().getHeaders(headerName)) { - this.writer.println(String.format("%s: %s", headerName, header)); - } - } - this.writer.println(); - } - this.writer.println(this.result.getResponse().getContentAsString()); - } - } - - private static class CurlConfiguration { - - private boolean includeResponseHeaders = false; - - } - - public static abstract class RestDocumentationResultHandler implements ResultHandler { - - private String outputDir; - - private String fileName; - - public RestDocumentationResultHandler(String outputDir, String fileName) { - this.outputDir = outputDir; - this.fileName = fileName; - } - - abstract void handle(MvcResult result, DocumentationWriter writer) - throws Exception; - - @Override - public void handle(MvcResult result) throws Exception { - PrintStream printStream = createPrintStream(); - try { - handle(result, new DocumentationWriter(printStream)); - } - finally { - printStream.close(); - } - } - - protected PrintStream createPrintStream() throws FileNotFoundException { - - File outputFile = new File(this.outputDir, this.fileName + ".asciidoc"); - if (!outputFile.isAbsolute()) { - outputFile = makeAbsolute(outputFile); - } - - if (outputFile != null) { - outputFile.getParentFile().mkdirs(); - return new PrintStream(new FileOutputStream(outputFile)); - } - - return System.out; - } - - private static File makeAbsolute(File outputFile) { - File outputDir = new DocumentationProperties().getOutputDir(); - if (outputDir != null) { - return new File(outputDir, outputFile.getPath()); - } - return null; - } - } - - public static abstract class CurlResultHandler extends RestDocumentationResultHandler { - - private final CurlConfiguration curlConfiguration = new CurlConfiguration(); - - public CurlResultHandler(String outputDir, String fileName) { - super(outputDir, fileName); - } - - CurlConfiguration getCurlConfiguration() { - return this.curlConfiguration; - } - - public CurlResultHandler includeResponseHeaders() { - this.curlConfiguration.includeResponseHeaders = true; - return this; - } - } - - static class LinkDocumentingResultHandler extends RestDocumentationResultHandler { - - private final Map descriptorsByRel = new HashMap(); - - private final LinkExtractor extractor; - - public LinkDocumentingResultHandler(String outputDir, - LinkExtractor linkExtractor, List descriptors) { - super(outputDir, "links"); - this.extractor = linkExtractor; - for (LinkDescriptor descriptor : descriptors) { - Assert.hasText(descriptor.getRel()); - Assert.hasText(descriptor.getDescription()); - this.descriptorsByRel.put(descriptor.getRel(), descriptor); - } - } - - @Override - void handle(MvcResult result, DocumentationWriter writer) throws Exception { - Map> links; - if (this.extractor != null) { - links = this.extractor.extractLinks(result.getResponse()); - } - else { - String contentType = result.getResponse().getContentType(); - LinkExtractor extractorForContentType = LinkExtractors - .extractorForContentType(contentType); - if (extractorForContentType != null) { - links = extractorForContentType.extractLinks(result.getResponse()); - } - else { - throw new IllegalStateException( - "No LinkExtractor has been provided and one is not available for the content type " - + contentType); - } - - } - - Set actualRels = links.keySet(); - Set expectedRels = this.descriptorsByRel.keySet(); - - Set undocumentedRels = new HashSet(actualRels); - undocumentedRels.removeAll(expectedRels); - - Set missingRels = new HashSet(expectedRels); - missingRels.removeAll(actualRels); - - if (!undocumentedRels.isEmpty() || !missingRels.isEmpty()) { - String message = ""; - if (!undocumentedRels.isEmpty()) { - message += "Links with the following relations were not documented: " - + undocumentedRels; - } - if (!missingRels.isEmpty()) { - message += "Links with the following relations were not found in the response: " - + missingRels; - } - fail(message); - } - - Assert.isTrue(actualRels.equals(expectedRels)); - - writer.println("|==="); - writer.println("| Relation | Description"); - - for (Entry entry : this.descriptorsByRel.entrySet()) { - writer.println(); - writer.println("| " + entry.getKey()); - writer.println("| " + entry.getValue().getDescription()); - } - - writer.println("|==="); - } - - } -} diff --git a/spring-restdocs-core/.settings/org.eclipse.jdt.core.prefs b/spring-restdocs/.settings/org.eclipse.jdt.core.prefs similarity index 100% rename from spring-restdocs-core/.settings/org.eclipse.jdt.core.prefs rename to spring-restdocs/.settings/org.eclipse.jdt.core.prefs diff --git a/spring-restdocs-core/.settings/org.eclipse.jdt.ui.prefs b/spring-restdocs/.settings/org.eclipse.jdt.ui.prefs similarity index 100% rename from spring-restdocs-core/.settings/org.eclipse.jdt.ui.prefs rename to spring-restdocs/.settings/org.eclipse.jdt.ui.prefs diff --git a/spring-restdocs/src/main/java/org/springframework/restdocs/RestDocumentation.java b/spring-restdocs/src/main/java/org/springframework/restdocs/RestDocumentation.java new file mode 100644 index 00000000..87cd79e4 --- /dev/null +++ b/spring-restdocs/src/main/java/org/springframework/restdocs/RestDocumentation.java @@ -0,0 +1,45 @@ +/* + * Copyright 2014-2015 the original author or authors. + * + * 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 org.springframework.restdocs; + +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.ResultActions; + +/** + * Static factory methods for documenting RESTful APIs using Spring MVC Test + * + * @author Andy Wilkinson + */ +public abstract class RestDocumentation { + + private RestDocumentation() { + + } + + /** + * Documents the API call to the given {@code outputDir}. + * + * @param outputDir The directory to which the documentation will be written + * @return a Mock MVC {@code ResultHandler} that will produce the documentation + * @see MockMvc#perform(org.springframework.test.web.servlet.RequestBuilder) + * @see ResultActions#andDo(org.springframework.test.web.servlet.ResultHandler) + */ + public static RestDocumentationResultHandler document(String outputDir) { + return new RestDocumentationResultHandler(outputDir); + } + +} diff --git a/spring-restdocs/src/main/java/org/springframework/restdocs/RestDocumentationConfigurer.java b/spring-restdocs/src/main/java/org/springframework/restdocs/RestDocumentationConfigurer.java new file mode 100644 index 00000000..f644cbbd --- /dev/null +++ b/spring-restdocs/src/main/java/org/springframework/restdocs/RestDocumentationConfigurer.java @@ -0,0 +1,112 @@ +/* + * Copyright 2014-2015 the original author or authors. + * + * 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 org.springframework.restdocs; + +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.test.web.servlet.request.RequestPostProcessor; +import org.springframework.test.web.servlet.setup.ConfigurableMockMvcBuilder; +import org.springframework.test.web.servlet.setup.MockMvcConfigurer; +import org.springframework.test.web.servlet.setup.MockMvcConfigurerAdapter; +import org.springframework.web.context.WebApplicationContext; + +/** + * A {@link MockMvcConfigurer} that can be used to configure the documentation + * + * @author Andy Wilkinson + * @see ConfigurableMockMvcBuilder#apply(MockMvcConfigurer) + * + */ +public class RestDocumentationConfigurer extends MockMvcConfigurerAdapter { + + /** + * The default scheme for documented URIs + * @see #withScheme(String) + */ + public static final String DEFAULT_SCHEME = "http"; + + /** + * The defalt host for documented URIs + * @see #withHost(String) + */ + public static final String DEFAULT_HOST = "localhost"; + + /** + * The default port for documented URIs + * @see #withPort(int) + */ + public static final int DEFAULT_PORT = 8080; + + private String scheme = DEFAULT_SCHEME; + + private String host = DEFAULT_HOST; + + private int port = DEFAULT_PORT; + + /** + * Configures any documented URIs to use the given {@code scheme}. The default is + * {@code http}. + * + * @param scheme The URI scheme + * @return {@code this} + */ + public RestDocumentationConfigurer withScheme(String scheme) { + this.scheme = scheme; + return this; + } + + /** + * Configures any documented URIs to use the given {@code host}. The default is + * {@code localhost}. + * + * @param host The URI host + * @return {@code this} + */ + public RestDocumentationConfigurer withHost(String host) { + this.host = host; + return this; + } + + /** + * Configures any documented URIs to use the given {@code port}. The default is + * {@code 8080}. + * + * @param port The URI port + * @return {@code this} + */ + public RestDocumentationConfigurer withPort(int port) { + this.port = port; + return this; + } + + @Override + public RequestPostProcessor beforeMockMvcCreated( + ConfigurableMockMvcBuilder builder, WebApplicationContext context) { + return new RequestPostProcessor() { + + @Override + public MockHttpServletRequest postProcessRequest( + MockHttpServletRequest request) { + request.setScheme(RestDocumentationConfigurer.this.scheme); + request.setRemotePort(RestDocumentationConfigurer.this.port); + request.setServerPort(RestDocumentationConfigurer.this.port); + request.setRemoteHost(RestDocumentationConfigurer.this.host); + return request; + } + }; + } + +} diff --git a/spring-restdocs/src/main/java/org/springframework/restdocs/RestDocumentationResultHandler.java b/spring-restdocs/src/main/java/org/springframework/restdocs/RestDocumentationResultHandler.java new file mode 100644 index 00000000..571f2bec --- /dev/null +++ b/spring-restdocs/src/main/java/org/springframework/restdocs/RestDocumentationResultHandler.java @@ -0,0 +1,100 @@ +/* + * Copyright 2014-2015 the original author or authors. + * + * 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 org.springframework.restdocs; + +import static org.springframework.restdocs.curl.CurlDocumentation.documentCurlRequest; +import static org.springframework.restdocs.curl.CurlDocumentation.documentCurlRequestAndResponse; +import static org.springframework.restdocs.curl.CurlDocumentation.documentCurlResponse; +import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.documentLinks; + +import java.util.ArrayList; +import java.util.List; + +import org.springframework.restdocs.hypermedia.HypermediaDocumentation; +import org.springframework.restdocs.hypermedia.LinkDescriptor; +import org.springframework.restdocs.hypermedia.LinkExtractor; +import org.springframework.restdocs.hypermedia.LinkExtractors; +import org.springframework.test.web.servlet.MvcResult; +import org.springframework.test.web.servlet.ResultHandler; + +/** + * A Spring MVC Test {@code ResultHandler} for documenting RESTful APIs. + * + * @author Andy Wilkinson + * @see RestDocumentation#document(String) + */ +public class RestDocumentationResultHandler implements ResultHandler { + + private final String outputDir; + + private List delegates; + + RestDocumentationResultHandler(String outputDir) { + this.outputDir = outputDir; + + this.delegates = new ArrayList(); + this.delegates.add(documentCurlRequest(this.outputDir)); + this.delegates.add(documentCurlResponse(this.outputDir)); + this.delegates.add(documentCurlRequestAndResponse(this.outputDir)); + } + + @Override + public void handle(MvcResult result) throws Exception { + for (ResultHandler delegate : this.delegates) { + delegate.handle(result); + } + } + + /** + * Document the links in the response using the given {@code descriptors}. The links + * are extracted from the response based on its content type. + *

+ * If a link is present in the response but is not described by one of the descriptors + * a failure will occur when this handler is invoked. Similarly, if a link is + * described but is not present in the response a failure will also occur when this + * handler is invoked. + * + * @param descriptors the link descriptors + * @return {@code this} + * @see HypermediaDocumentation#linkWithRel(String) + * @see LinkExtractors#extractorForContentType(String) + */ + public RestDocumentationResultHandler withLinks(LinkDescriptor... descriptors) { + return withLinks(null, descriptors); + } + + /** + * Document the links in the response using the given {@code descriptors}. The links + * are extracted from the response using the given {@code linkExtractor}. + *

+ * If a link is present in the response but is not described by one of the descriptors + * a failure will occur when this handler is invoked. Similarly, if a link is + * described but is not present in the response a failure will also occur when this + * handler is invoked. + * + * @param linkExtractor used to extract the links from the response + * @param descriptors the link descriptors + * @return {@code this} + * @see HypermediaDocumentation#linkWithRel(String) + */ + public RestDocumentationResultHandler withLinks(LinkExtractor linkExtractor, + LinkDescriptor... descriptors) { + this.delegates.add(documentLinks(this.outputDir, linkExtractor, descriptors)); + return this; + } + +} diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/core/RestDocumentation.java b/spring-restdocs/src/main/java/org/springframework/restdocs/curl/CurlConfiguration.java similarity index 60% rename from spring-restdocs-core/src/main/java/org/springframework/restdocs/core/RestDocumentation.java rename to spring-restdocs/src/main/java/org/springframework/restdocs/curl/CurlConfiguration.java index 974e1dbb..c8c8c944 100644 --- a/spring-restdocs-core/src/main/java/org/springframework/restdocs/core/RestDocumentation.java +++ b/spring-restdocs/src/main/java/org/springframework/restdocs/curl/CurlConfiguration.java @@ -14,17 +14,22 @@ * limitations under the License. */ -package org.springframework.restdocs.core; +package org.springframework.restdocs.curl; -public class RestDocumentation { +/** + * Configuration for documenting Curl requests and responses + * + * @author Andy Wilkinson + */ +class CurlConfiguration { - public static RestDocumentationResultHandler document(String outputDir) - throws Exception { - return new RestDocumentationResultHandler(outputDir); + private boolean includeResponseHeaders = true; + + boolean isIncludeResponseHeaders() { + return this.includeResponseHeaders; } - public static LinkDescriptor linkWithRel(String rel) { - return new LinkDescriptor(rel); + void setIncludeResponseHeaders(boolean includeResponseHeaders) { + this.includeResponseHeaders = includeResponseHeaders; } - -} +} \ No newline at end of file diff --git a/spring-restdocs/src/main/java/org/springframework/restdocs/curl/CurlDocumentation.java b/spring-restdocs/src/main/java/org/springframework/restdocs/curl/CurlDocumentation.java new file mode 100644 index 00000000..82005876 --- /dev/null +++ b/spring-restdocs/src/main/java/org/springframework/restdocs/curl/CurlDocumentation.java @@ -0,0 +1,189 @@ +/* + * Copyright 2014-2015 the original author or authors. + * + * 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 org.springframework.restdocs.curl; + +import static org.springframework.restdocs.util.IterableEnumeration.iterable; + +import java.io.IOException; +import java.io.StringWriter; + +import org.springframework.http.HttpStatus; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.restdocs.snippet.DocumentationWriter; +import org.springframework.restdocs.snippet.DocumentationWriter.DocumentationAction; +import org.springframework.test.web.servlet.MvcResult; +import org.springframework.util.FileCopyUtils; +import org.springframework.web.bind.annotation.RequestMethod; + +/** + * Static factory methods for documenting a RESTful API as if it were being driven using + * the cURL command-line utility. + * + * @author Andy Wilkinson + */ +public abstract class CurlDocumentation { + + private CurlDocumentation() { + + } + + /** + * Produces a documentation snippet containing the request formatted as a cURL command + * + * @param outputDir The directory to which snippet should be written + * @return the handler that will produce the snippet + */ + public static CurlSnippetResultHandler documentCurlRequest(String outputDir) { + return new CurlSnippetResultHandler(outputDir, "request") { + + @Override + public void handle(MvcResult result, DocumentationWriter writer) + throws Exception { + writer.shellCommand(new CurlRequestDocumentationAction(writer, result, + getCurlConfiguration())); + } + }; + } + + /** + * Produces a documentation snippet containing the response formatted as the response + * to a cURL command + * + * @param outputDir The directory to which snippet should be written + * @return the handler that will produce the snippet + */ + public static CurlSnippetResultHandler documentCurlResponse(String outputDir) { + return new CurlSnippetResultHandler(outputDir, "response") { + + @Override + public void handle(MvcResult result, DocumentationWriter writer) + throws Exception { + writer.codeBlock("http", new CurlResponseDocumentationAction(writer, + result, getCurlConfiguration())); + } + }; + } + + /** + * Produces a documentation snippet containing both the request formatted as a cURL + * command and the response formatted formatted s the response to a cURL command. + * + * @param outputDir The directory to which the snippet should be written + * @return the handler that will produce the snippet + */ + public static CurlSnippetResultHandler documentCurlRequestAndResponse(String outputDir) { + return new CurlSnippetResultHandler(outputDir, "request-response") { + + @Override + public void handle(MvcResult result, DocumentationWriter writer) + throws Exception { + writer.shellCommand(new CurlRequestDocumentationAction(writer, result, + getCurlConfiguration())); + writer.codeBlock("http", new CurlResponseDocumentationAction(writer, + result, getCurlConfiguration())); + } + }; + } + + private static final class CurlRequestDocumentationAction implements + DocumentationAction { + + private final DocumentationWriter writer; + + private final MvcResult result; + + private final CurlConfiguration curlConfiguration; + + CurlRequestDocumentationAction(DocumentationWriter writer, MvcResult result, + CurlConfiguration curlConfiguration) { + this.writer = writer; + this.result = result; + this.curlConfiguration = curlConfiguration; + } + + @Override + public void perform() throws Exception { + MockHttpServletRequest request = this.result.getRequest(); + this.writer.print(String.format("curl %s://%s:%d%s", request.getScheme(), + request.getRemoteHost(), request.getRemotePort(), + request.getRequestURI())); + + if (this.curlConfiguration.isIncludeResponseHeaders()) { + this.writer.print(" -i"); + } + + RequestMethod requestMethod = RequestMethod.valueOf(request.getMethod()); + if (requestMethod != RequestMethod.GET) { + this.writer.print(String.format(" -X %s", requestMethod.toString())); + } + + for (String headerName : iterable(request.getHeaderNames())) { + for (String header : iterable(request.getHeaders(headerName))) { + this.writer + .print(String.format(" -H \"%s: %s\"", headerName, header)); + } + } + + if (request.getContentLengthLong() > 0) { + this.writer.print(String.format(" -d '%s'", getContent(request))); + } + + this.writer.println(); + } + + private String getContent(MockHttpServletRequest request) throws IOException { + StringWriter bodyWriter = new StringWriter(); + FileCopyUtils.copy(request.getReader(), bodyWriter); + return bodyWriter.toString(); + } + } + + private static final class CurlResponseDocumentationAction implements + DocumentationAction { + + private final DocumentationWriter writer; + + private final MvcResult result; + + private final CurlConfiguration curlConfiguration; + + CurlResponseDocumentationAction(DocumentationWriter writer, MvcResult result, + CurlConfiguration curlConfiguration) { + this.writer = writer; + this.result = result; + this.curlConfiguration = curlConfiguration; + } + + @Override + public void perform() throws Exception { + if (this.curlConfiguration.isIncludeResponseHeaders()) { + HttpStatus status = HttpStatus.valueOf(this.result.getResponse() + .getStatus()); + this.writer.println(String.format("HTTP/1.1 %d %s", status.value(), + status.getReasonPhrase())); + for (String headerName : this.result.getResponse().getHeaderNames()) { + for (String header : this.result.getResponse().getHeaders(headerName)) { + this.writer.println(String.format("%s: %s", headerName, header)); + } + } + this.writer.println(); + } + this.writer.println(this.result.getResponse().getContentAsString()); + } + } + +} diff --git a/spring-restdocs/src/main/java/org/springframework/restdocs/curl/CurlSnippetResultHandler.java b/spring-restdocs/src/main/java/org/springframework/restdocs/curl/CurlSnippetResultHandler.java new file mode 100644 index 00000000..31a687cf --- /dev/null +++ b/spring-restdocs/src/main/java/org/springframework/restdocs/curl/CurlSnippetResultHandler.java @@ -0,0 +1,44 @@ +/* + * Copyright 2014-2015 the original author or authors. + * + * 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 org.springframework.restdocs.curl; + +import org.springframework.restdocs.snippet.SnippetWritingResultHandler; +import org.springframework.test.web.servlet.ResultHandler; + +/** + * Abstract base class for Spring Mock MVC {@link ResultHandler ResultHandlers} that + * produce documentation snippets relating to cURL. + * + * @author Andy Wilkinson + */ +public abstract class CurlSnippetResultHandler extends SnippetWritingResultHandler { + + private final CurlConfiguration curlConfiguration = new CurlConfiguration(); + + public CurlSnippetResultHandler(String outputDir, String fileName) { + super(outputDir, fileName); + } + + CurlConfiguration getCurlConfiguration() { + return this.curlConfiguration; + } + + public CurlSnippetResultHandler includeResponseHeaders() { + this.curlConfiguration.setIncludeResponseHeaders(true); + return this; + } +} \ No newline at end of file diff --git a/spring-restdocs/src/main/java/org/springframework/restdocs/hypermedia/HypermediaDocumentation.java b/spring-restdocs/src/main/java/org/springframework/restdocs/hypermedia/HypermediaDocumentation.java new file mode 100644 index 00000000..65a51bd0 --- /dev/null +++ b/spring-restdocs/src/main/java/org/springframework/restdocs/hypermedia/HypermediaDocumentation.java @@ -0,0 +1,63 @@ +/* + * Copyright 2014-2015 the original author or authors. + * + * 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 org.springframework.restdocs.hypermedia; + +import java.util.Arrays; + +import org.springframework.restdocs.RestDocumentationResultHandler; + +/** + * Static factory methods for documenting a RESTful API that utilises Hypermedia. + * + * @author Andy Wilkinson + */ +public abstract class HypermediaDocumentation { + + private HypermediaDocumentation() { + + } + + /** + * Creates a {@code LinkDescriptor} that describes a link with the given {@code rel}. + * + * @param rel The rel of the link + * @return a {@code LinkDescriptor} ready for further configuration + * @see RestDocumentationResultHandler#withLinks(LinkDescriptor...) + * @see RestDocumentationResultHandler#withLinks(LinkExtractor, LinkDescriptor...) + */ + public static LinkDescriptor linkWithRel(String rel) { + return new LinkDescriptor(rel); + } + + /** + * Creates a {@code LinkSnippetResultHandler} that will produce a documentation + * snippet for a response's links. + * + * @param outputDir The directory to which the snippet should be written + * @param linkExtractor Used to extract the links from the response + * @param descriptors The descriptions of the response's links + * @return the handler + * @see RestDocumentationResultHandler#withLinks(LinkDescriptor...) + * @see RestDocumentationResultHandler#withLinks(LinkExtractor, LinkDescriptor...) + */ + public static LinkSnippetResultHandler documentLinks(String outputDir, + LinkExtractor linkExtractor, LinkDescriptor... descriptors) { + return new LinkSnippetResultHandler(outputDir, linkExtractor, + Arrays.asList(descriptors)); + } + +} diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/core/Link.java b/spring-restdocs/src/main/java/org/springframework/restdocs/hypermedia/Link.java similarity index 97% rename from spring-restdocs-core/src/main/java/org/springframework/restdocs/core/Link.java rename to spring-restdocs/src/main/java/org/springframework/restdocs/hypermedia/Link.java index ef153487..694eec9e 100644 --- a/spring-restdocs-core/src/main/java/org/springframework/restdocs/core/Link.java +++ b/spring-restdocs/src/main/java/org/springframework/restdocs/hypermedia/Link.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.restdocs.core; +package org.springframework.restdocs.hypermedia; import org.springframework.core.style.ToStringCreator; diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/core/LinkDescriptor.java b/spring-restdocs/src/main/java/org/springframework/restdocs/hypermedia/LinkDescriptor.java similarity index 68% rename from spring-restdocs-core/src/main/java/org/springframework/restdocs/core/LinkDescriptor.java rename to spring-restdocs/src/main/java/org/springframework/restdocs/hypermedia/LinkDescriptor.java index e28a8af4..24a2044c 100644 --- a/spring-restdocs-core/src/main/java/org/springframework/restdocs/core/LinkDescriptor.java +++ b/spring-restdocs/src/main/java/org/springframework/restdocs/hypermedia/LinkDescriptor.java @@ -1,5 +1,5 @@ /* - * Copyright 2014 the original author or authors. + * Copyright 2014-2015 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,18 +14,31 @@ * limitations under the License. */ -package org.springframework.restdocs.core; +package org.springframework.restdocs.hypermedia; +/** + * A description of a link found in a hypermedia API + * + * @see HypermediaDocumentation#linkWithRel(String) + * + * @author Andy Wilkinson + */ public class LinkDescriptor { private final String rel; private String description; - public LinkDescriptor(String rel) { + LinkDescriptor(String rel) { this.rel = rel; } + /** + * Specifies the description of the link + * + * @param description The link's description + * @return {@code this} + */ public LinkDescriptor description(String description) { this.description = description; return this; diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/core/LinkExtractor.java b/spring-restdocs/src/main/java/org/springframework/restdocs/hypermedia/LinkExtractor.java similarity index 96% rename from spring-restdocs-core/src/main/java/org/springframework/restdocs/core/LinkExtractor.java rename to spring-restdocs/src/main/java/org/springframework/restdocs/hypermedia/LinkExtractor.java index f63d2c4f..0627a306 100644 --- a/spring-restdocs-core/src/main/java/org/springframework/restdocs/core/LinkExtractor.java +++ b/spring-restdocs/src/main/java/org/springframework/restdocs/hypermedia/LinkExtractor.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.restdocs.core; +package org.springframework.restdocs.hypermedia; import java.io.IOException; import java.util.List; diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/core/LinkExtractors.java b/spring-restdocs/src/main/java/org/springframework/restdocs/hypermedia/LinkExtractors.java similarity index 96% rename from spring-restdocs-core/src/main/java/org/springframework/restdocs/core/LinkExtractors.java rename to spring-restdocs/src/main/java/org/springframework/restdocs/hypermedia/LinkExtractors.java index df35102e..07ffd203 100644 --- a/spring-restdocs-core/src/main/java/org/springframework/restdocs/core/LinkExtractors.java +++ b/spring-restdocs/src/main/java/org/springframework/restdocs/hypermedia/LinkExtractors.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.restdocs.core; +package org.springframework.restdocs.hypermedia; import java.io.IOException; import java.util.ArrayList; @@ -35,7 +35,11 @@ import com.fasterxml.jackson.databind.ObjectMapper; * * @author Andy Wilkinson */ -public class LinkExtractors { +public abstract class LinkExtractors { + + private LinkExtractors() { + + } /** * Returns a {@code LinkExtractor} capable of extracting links in Hypermedia @@ -75,7 +79,7 @@ public class LinkExtractors { return null; } - private static abstract class JsonContentLinkExtractor implements LinkExtractor { + private abstract static class JsonContentLinkExtractor implements LinkExtractor { private final ObjectMapper objectMapper = new ObjectMapper(); diff --git a/spring-restdocs/src/main/java/org/springframework/restdocs/hypermedia/LinkSnippetResultHandler.java b/spring-restdocs/src/main/java/org/springframework/restdocs/hypermedia/LinkSnippetResultHandler.java new file mode 100644 index 00000000..ee8fc828 --- /dev/null +++ b/spring-restdocs/src/main/java/org/springframework/restdocs/hypermedia/LinkSnippetResultHandler.java @@ -0,0 +1,113 @@ +/* + * Copyright 2014-2015 the original author or authors. + * + * 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 org.springframework.restdocs.hypermedia; + +import static org.junit.Assert.fail; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +import org.springframework.restdocs.snippet.DocumentationWriter; +import org.springframework.restdocs.snippet.SnippetWritingResultHandler; +import org.springframework.test.web.servlet.MvcResult; +import org.springframework.util.Assert; + +/** + * A {@link SnippetWritingResultHandler} that produces a snippet documenting a RESTful + * resource's links. + * + * @author Andy Wilkinson + */ +public class LinkSnippetResultHandler extends SnippetWritingResultHandler { + + private final Map descriptorsByRel = new HashMap(); + + private final LinkExtractor extractor; + + LinkSnippetResultHandler(String outputDir, LinkExtractor linkExtractor, + List descriptors) { + super(outputDir, "links"); + this.extractor = linkExtractor; + for (LinkDescriptor descriptor : descriptors) { + Assert.hasText(descriptor.getRel()); + Assert.hasText(descriptor.getDescription()); + this.descriptorsByRel.put(descriptor.getRel(), descriptor); + } + } + + @Override + protected void handle(MvcResult result, DocumentationWriter writer) throws Exception { + Map> links; + if (this.extractor != null) { + links = this.extractor.extractLinks(result.getResponse()); + } + else { + String contentType = result.getResponse().getContentType(); + LinkExtractor extractorForContentType = LinkExtractors + .extractorForContentType(contentType); + if (extractorForContentType != null) { + links = extractorForContentType.extractLinks(result.getResponse()); + } + else { + throw new IllegalStateException( + "No LinkExtractor has been provided and one is not available for the content type " + + contentType); + } + + } + + Set actualRels = links.keySet(); + Set expectedRels = this.descriptorsByRel.keySet(); + + Set undocumentedRels = new HashSet(actualRels); + undocumentedRels.removeAll(expectedRels); + + Set missingRels = new HashSet(expectedRels); + missingRels.removeAll(actualRels); + + if (!undocumentedRels.isEmpty() || !missingRels.isEmpty()) { + String message = ""; + if (!undocumentedRels.isEmpty()) { + message += "Links with the following relations were not documented: " + + undocumentedRels; + } + if (!missingRels.isEmpty()) { + message += "Links with the following relations were not found in the response: " + + missingRels; + } + fail(message); + } + + Assert.isTrue(actualRels.equals(expectedRels)); + + writer.println("|==="); + writer.println("| Relation | Description"); + + for (Entry entry : this.descriptorsByRel.entrySet()) { + writer.println(); + writer.println("| " + entry.getKey()); + writer.println("| " + entry.getValue().getDescription()); + } + + writer.println("|==="); + } + +} \ No newline at end of file diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/core/DocumentationWriter.java b/spring-restdocs/src/main/java/org/springframework/restdocs/snippet/AsciidoctorWriter.java similarity index 50% rename from spring-restdocs-core/src/main/java/org/springframework/restdocs/core/DocumentationWriter.java rename to spring-restdocs/src/main/java/org/springframework/restdocs/snippet/AsciidoctorWriter.java index 178bb37b..5791694b 100644 --- a/spring-restdocs-core/src/main/java/org/springframework/restdocs/core/DocumentationWriter.java +++ b/spring-restdocs/src/main/java/org/springframework/restdocs/snippet/AsciidoctorWriter.java @@ -1,5 +1,5 @@ /* - * Copyright 2014 the original author or authors. + * Copyright 2014-2015 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,47 +14,48 @@ * limitations under the License. */ -package org.springframework.restdocs.core; +package org.springframework.restdocs.snippet; -import java.io.OutputStream; -import java.io.PrintWriter; +import java.io.Writer; -public class DocumentationWriter extends PrintWriter { +/** + * A {@link DocumentationWriter} that produces output in Asciidoctor. + * + * @author Andy Wilkinson + */ +public class AsciidoctorWriter extends DocumentationWriter { - public DocumentationWriter(OutputStream stream) { - super(stream, true); + /** + * Creates a new {@code AsciidoctorWriter} that will write to the given {@code writer} + * @param writer The writer to which output will be written + */ + public AsciidoctorWriter(Writer writer) { + super(writer); } - public void shellCommand(final DocumentationAction... actions) throws Exception { + @Override + public void shellCommand(final DocumentationAction action) throws Exception { codeBlock("bash", new DocumentationAction() { @Override public void perform() throws Exception { - DocumentationWriter.this.print("$ "); - for (DocumentationAction action : actions) { - action.perform(); - } + AsciidoctorWriter.this.print("$ "); + action.perform(); } }); } - public void codeBlock(String language, DocumentationAction... actions) - throws Exception { + @Override + public void codeBlock(String language, DocumentationAction action) throws Exception { println(); if (language != null) { println("[source," + language + "]"); } println("----"); - for (DocumentationAction action : actions) { - action.perform(); - } + action.perform(); println("----"); println(); } - public interface DocumentationAction { - - void perform() throws Exception; - } - } diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/core/DocumentationProperties.java b/spring-restdocs/src/main/java/org/springframework/restdocs/snippet/DocumentationProperties.java similarity index 93% rename from spring-restdocs-core/src/main/java/org/springframework/restdocs/core/DocumentationProperties.java rename to spring-restdocs/src/main/java/org/springframework/restdocs/snippet/DocumentationProperties.java index fe644def..f8ca87b1 100644 --- a/spring-restdocs-core/src/main/java/org/springframework/restdocs/core/DocumentationProperties.java +++ b/spring-restdocs/src/main/java/org/springframework/restdocs/snippet/DocumentationProperties.java @@ -1,5 +1,5 @@ /* - * Copyright 2014 the original author or authors. + * Copyright 2014-2015 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.restdocs.core; +package org.springframework.restdocs.snippet; import java.io.File; import java.io.IOException; diff --git a/spring-restdocs/src/main/java/org/springframework/restdocs/snippet/DocumentationWriter.java b/spring-restdocs/src/main/java/org/springframework/restdocs/snippet/DocumentationWriter.java new file mode 100644 index 00000000..83d0ee01 --- /dev/null +++ b/spring-restdocs/src/main/java/org/springframework/restdocs/snippet/DocumentationWriter.java @@ -0,0 +1,74 @@ +/* + * Copyright 2014-2015 the original author or authors. + * + * 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 org.springframework.restdocs.snippet; + +import java.io.PrintWriter; +import java.io.Writer; + +/** + * A {@link PrintWriter} that provides additional methods which are useful for producing + * API documentation. + * + * @author Andy Wilkinson + */ +public abstract class DocumentationWriter extends PrintWriter { + + protected DocumentationWriter(Writer writer) { + super(writer, true); + } + + /** + * Calls the given {@code action} to document a shell command. Any prefix necessary + * for the documentation format is written prior to calling the {@code action}. Having + * called the action, any necessary suffix is then written. + * + * @param action the action that will produce the shell command + * @throws Exception if the documentation fails + */ + public abstract void shellCommand(DocumentationAction action) throws Exception; + + /** + * Calls the given {@code action} to document a code block. The code block will be + * annotated as containing code written in the given {@code language}. Any prefix + * necessary for the documentation format is written prior to calling the + * {@code action}. Having called the action, any necessary suffix is the written. + * + * @param language the language in which the code is written + * @param action the action that will produce the code + * @throws Exception if the documentation fails + */ + public abstract void codeBlock(String language, DocumentationAction action) + throws Exception; + + /** + * Encapsulates an action that outputs some documentation. Typically implemented as a + * lamda or, pre-Java 8, as an anonymous inner class. + * + * @author Andy Wilkinson + * @see DocumentationWriter#shellCommand + * @see DocumentationWriter#codeBlock + */ + public interface DocumentationAction { + + /** + * Perform the encapsulated action + * + * @throws Exception if the action fails + */ + void perform() throws Exception; + } +} diff --git a/spring-restdocs/src/main/java/org/springframework/restdocs/snippet/SnippetWritingResultHandler.java b/spring-restdocs/src/main/java/org/springframework/restdocs/snippet/SnippetWritingResultHandler.java new file mode 100644 index 00000000..5785cc8d --- /dev/null +++ b/spring-restdocs/src/main/java/org/springframework/restdocs/snippet/SnippetWritingResultHandler.java @@ -0,0 +1,79 @@ +/* + * Copyright 2014-2015 the original author or authors. + * + * 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 org.springframework.restdocs.snippet; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.Writer; + +import org.springframework.test.web.servlet.MvcResult; +import org.springframework.test.web.servlet.ResultHandler; + +/** + * Base class for a {@link ResultHandler} that writes a documentation snippet + * + * @author Andy Wilkinson + */ +public abstract class SnippetWritingResultHandler implements ResultHandler { + + private String outputDir; + + private String fileName; + + protected SnippetWritingResultHandler(String outputDir, String fileName) { + this.outputDir = outputDir; + this.fileName = fileName; + } + + protected abstract void handle(MvcResult result, DocumentationWriter writer) + throws Exception; + + @Override + public void handle(MvcResult result) throws Exception { + Writer writer = createWriter(); + try { + handle(result, new AsciidoctorWriter(writer)); + } + finally { + writer.close(); + } + } + + private Writer createWriter() throws IOException { + File outputFile = new File(this.outputDir, this.fileName + ".asciidoc"); + if (!outputFile.isAbsolute()) { + outputFile = makeRelativeToConfiguredOutputDir(outputFile); + } + + if (outputFile != null) { + outputFile.getParentFile().mkdirs(); + return new FileWriter(outputFile); + } + + return new OutputStreamWriter(System.out); + } + + private File makeRelativeToConfiguredOutputDir(File outputFile) { + File configuredOutputDir = new DocumentationProperties().getOutputDir(); + if (configuredOutputDir != null) { + return new File(configuredOutputDir, outputFile.getPath()); + } + return null; + } +} \ No newline at end of file diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/core/IterableEnumeration.java b/spring-restdocs/src/main/java/org/springframework/restdocs/util/IterableEnumeration.java similarity index 65% rename from spring-restdocs-core/src/main/java/org/springframework/restdocs/core/IterableEnumeration.java rename to spring-restdocs/src/main/java/org/springframework/restdocs/util/IterableEnumeration.java index b374fbc0..0dc04bb1 100644 --- a/spring-restdocs-core/src/main/java/org/springframework/restdocs/core/IterableEnumeration.java +++ b/spring-restdocs/src/main/java/org/springframework/restdocs/util/IterableEnumeration.java @@ -1,5 +1,5 @@ /* - * Copyright 2014 the original author or authors. + * Copyright 2014-2015 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,16 +14,23 @@ * limitations under the License. */ -package org.springframework.restdocs.core; +package org.springframework.restdocs.util; import java.util.Enumeration; import java.util.Iterator; -public final class IterableEnumeration implements Iterable { +/** + * An adapter to expose an {@link Enumeration} as an {@link Iterable}. + * + * @author Andy Wilkinson + * + * @param the type of the Enumeration's contents + */ +public class IterableEnumeration implements Iterable { private final Enumeration enumeration; - public IterableEnumeration(Enumeration enumeration) { + private IterableEnumeration(Enumeration enumeration) { this.enumeration = enumeration; } @@ -49,6 +56,13 @@ public final class IterableEnumeration implements Iterable { }; } + /** + * Creates a new {@code Iterable} that will iterate over the given {@code enumeration} + * + * @param the type of the enumeration's elements + * @param enumeration The enumeration to expose as an {@code Iterable} + * @return the iterable + */ public static Iterable iterable(Enumeration enumeration) { return new IterableEnumeration(enumeration); } diff --git a/spring-restdocs-core/src/test/java/org/springframework/restdocs/core/LinkExtractorsTests.java b/spring-restdocs/src/test/java/org/springframework/restdocs/core/LinkExtractorsTests.java similarity index 95% rename from spring-restdocs-core/src/test/java/org/springframework/restdocs/core/LinkExtractorsTests.java rename to spring-restdocs/src/test/java/org/springframework/restdocs/core/LinkExtractorsTests.java index 1794b7d1..f4a77439 100644 --- a/spring-restdocs-core/src/test/java/org/springframework/restdocs/core/LinkExtractorsTests.java +++ b/spring-restdocs/src/test/java/org/springframework/restdocs/core/LinkExtractorsTests.java @@ -34,6 +34,9 @@ import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameters; import org.springframework.mock.web.MockHttpServletResponse; +import org.springframework.restdocs.hypermedia.Link; +import org.springframework.restdocs.hypermedia.LinkExtractor; +import org.springframework.restdocs.hypermedia.LinkExtractors; import org.springframework.util.FileCopyUtils; /** diff --git a/spring-restdocs/src/test/java/org/springframework/restdocs/core/RestDocumentationConfigurerTests.java b/spring-restdocs/src/test/java/org/springframework/restdocs/core/RestDocumentationConfigurerTests.java new file mode 100644 index 00000000..5ff872ba --- /dev/null +++ b/spring-restdocs/src/test/java/org/springframework/restdocs/core/RestDocumentationConfigurerTests.java @@ -0,0 +1,78 @@ +/* + * Copyright 2014-2015 the original author or authors. + * + * 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 org.springframework.restdocs.core; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.restdocs.RestDocumentationConfigurer; +import org.springframework.test.web.servlet.request.RequestPostProcessor; + +/** + * Tests for {@link RestDocumentationConfigurer}. + * + * @author Andy Wilkinson + */ +public class RestDocumentationConfigurerTests { + + private MockHttpServletRequest request = new MockHttpServletRequest(); + + @Test + public void defaultConfiguration() { + RequestPostProcessor postProcessor = new RestDocumentationConfigurer() + .beforeMockMvcCreated(null, null); + postProcessor.postProcessRequest(this.request); + + assertUriConfiguration("http", "localhost", 8080); + } + + @Test + public void customScheme() { + RequestPostProcessor postProcessor = new RestDocumentationConfigurer() + .withScheme("https").beforeMockMvcCreated(null, null); + postProcessor.postProcessRequest(this.request); + + assertUriConfiguration("https", "localhost", 8080); + } + + @Test + public void customHost() { + RequestPostProcessor postProcessor = new RestDocumentationConfigurer().withHost( + "api.example.com").beforeMockMvcCreated(null, null); + postProcessor.postProcessRequest(this.request); + + assertUriConfiguration("http", "api.example.com", 8080); + } + + @Test + public void customPort() { + RequestPostProcessor postProcessor = new RestDocumentationConfigurer().withPort( + 8081).beforeMockMvcCreated(null, null); + postProcessor.postProcessRequest(this.request); + + assertUriConfiguration("http", "localhost", 8081); + } + + private void assertUriConfiguration(String scheme, String host, int port) { + assertEquals(scheme, this.request.getScheme()); + assertEquals(host, this.request.getRemoteHost()); + assertEquals(port, this.request.getRemotePort()); + assertEquals(port, this.request.getServerPort()); + } + +} diff --git a/spring-restdocs/src/test/java/org/springframework/restdocs/snippet/AsciidoctorWriterTests.java b/spring-restdocs/src/test/java/org/springframework/restdocs/snippet/AsciidoctorWriterTests.java new file mode 100644 index 00000000..33831d0b --- /dev/null +++ b/spring-restdocs/src/test/java/org/springframework/restdocs/snippet/AsciidoctorWriterTests.java @@ -0,0 +1,67 @@ +/* + * Copyright 2014-2015 the original author or authors. + * + * 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 org.springframework.restdocs.snippet; + +import static org.junit.Assert.assertEquals; + +import java.io.StringWriter; +import java.io.Writer; + +import org.junit.Test; +import org.springframework.restdocs.snippet.AsciidoctorWriter; +import org.springframework.restdocs.snippet.DocumentationWriter; +import org.springframework.restdocs.snippet.DocumentationWriter.DocumentationAction; + +/** + * Tests for {@link AsciidoctorWriter} + * + * @author Andy Wilkinson + */ +public class AsciidoctorWriterTests { + + private Writer output = new StringWriter(); + + private DocumentationWriter documentationWriter = new AsciidoctorWriter(this.output); + + @Test + public void codeBlock() throws Exception { + this.documentationWriter.codeBlock("java", new DocumentationAction() { + + @Override + public void perform() throws Exception { + AsciidoctorWriterTests.this.documentationWriter.println("foo"); + } + }); + + String expectedOutput = String.format("\n[source,java]\n----\nfoo\n----\n\n"); + assertEquals(expectedOutput, this.output.toString()); + } + + @Test + public void shellCommand() throws Exception { + this.documentationWriter.shellCommand(new DocumentationAction() { + + @Override + public void perform() throws Exception { + AsciidoctorWriterTests.this.documentationWriter.println("foo"); + } + }); + + String expectedOutput = String.format("\n[source,bash]\n----\n$ foo\n----\n\n"); + assertEquals(expectedOutput, this.output.toString()); + } +} diff --git a/spring-restdocs-core/src/test/resources/link-payloads/atom/multiple-links-different-rels.json b/spring-restdocs/src/test/resources/link-payloads/atom/multiple-links-different-rels.json similarity index 100% rename from spring-restdocs-core/src/test/resources/link-payloads/atom/multiple-links-different-rels.json rename to spring-restdocs/src/test/resources/link-payloads/atom/multiple-links-different-rels.json diff --git a/spring-restdocs-core/src/test/resources/link-payloads/atom/multiple-links-same-rels.json b/spring-restdocs/src/test/resources/link-payloads/atom/multiple-links-same-rels.json similarity index 100% rename from spring-restdocs-core/src/test/resources/link-payloads/atom/multiple-links-same-rels.json rename to spring-restdocs/src/test/resources/link-payloads/atom/multiple-links-same-rels.json diff --git a/spring-restdocs-core/src/test/resources/link-payloads/atom/no-links.json b/spring-restdocs/src/test/resources/link-payloads/atom/no-links.json similarity index 100% rename from spring-restdocs-core/src/test/resources/link-payloads/atom/no-links.json rename to spring-restdocs/src/test/resources/link-payloads/atom/no-links.json diff --git a/spring-restdocs-core/src/test/resources/link-payloads/atom/single-link.json b/spring-restdocs/src/test/resources/link-payloads/atom/single-link.json similarity index 100% rename from spring-restdocs-core/src/test/resources/link-payloads/atom/single-link.json rename to spring-restdocs/src/test/resources/link-payloads/atom/single-link.json diff --git a/spring-restdocs-core/src/test/resources/link-payloads/atom/wrong-format.json b/spring-restdocs/src/test/resources/link-payloads/atom/wrong-format.json similarity index 100% rename from spring-restdocs-core/src/test/resources/link-payloads/atom/wrong-format.json rename to spring-restdocs/src/test/resources/link-payloads/atom/wrong-format.json diff --git a/spring-restdocs-core/src/test/resources/link-payloads/hal/multiple-links-different-rels.json b/spring-restdocs/src/test/resources/link-payloads/hal/multiple-links-different-rels.json similarity index 100% rename from spring-restdocs-core/src/test/resources/link-payloads/hal/multiple-links-different-rels.json rename to spring-restdocs/src/test/resources/link-payloads/hal/multiple-links-different-rels.json diff --git a/spring-restdocs-core/src/test/resources/link-payloads/hal/multiple-links-same-rels.json b/spring-restdocs/src/test/resources/link-payloads/hal/multiple-links-same-rels.json similarity index 100% rename from spring-restdocs-core/src/test/resources/link-payloads/hal/multiple-links-same-rels.json rename to spring-restdocs/src/test/resources/link-payloads/hal/multiple-links-same-rels.json diff --git a/spring-restdocs-core/src/test/resources/link-payloads/hal/no-links.json b/spring-restdocs/src/test/resources/link-payloads/hal/no-links.json similarity index 100% rename from spring-restdocs-core/src/test/resources/link-payloads/hal/no-links.json rename to spring-restdocs/src/test/resources/link-payloads/hal/no-links.json diff --git a/spring-restdocs-core/src/test/resources/link-payloads/hal/single-link.json b/spring-restdocs/src/test/resources/link-payloads/hal/single-link.json similarity index 100% rename from spring-restdocs-core/src/test/resources/link-payloads/hal/single-link.json rename to spring-restdocs/src/test/resources/link-payloads/hal/single-link.json diff --git a/spring-restdocs-core/src/test/resources/link-payloads/hal/wrong-format.json b/spring-restdocs/src/test/resources/link-payloads/hal/wrong-format.json similarity index 100% rename from spring-restdocs-core/src/test/resources/link-payloads/hal/wrong-format.json rename to spring-restdocs/src/test/resources/link-payloads/hal/wrong-format.json