commit 7cf682e4869b71ecf258480839a45b6b2624efa5 Author: Robert Winkler Date: Wed Feb 11 12:09:39 2015 +0100 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..27709626 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +.idea +*.iml +.gradle +build diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 00000000..e06d2081 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,202 @@ +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + 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. + diff --git a/README.md b/README.md new file mode 100644 index 00000000..dd13ce78 --- /dev/null +++ b/README.md @@ -0,0 +1,16 @@ +# swagger2AsciiDoc +This is a Swagger to AsciiDoc converter. It takes an swagger.json or swagger.yaml as an input file +and generates an AsciiDoc file. + +``` +Swagger2AsciiDocConverter.newInstance("/tmp/swagger.json", "/tmp/swagger.adoc").convertSwagger2AsciiDoc(); +``` + +Example swagger.json +![](https://github.com/RobWin/swagger2AsciiDoc/blob/master/images/swagger_json.PNG) + +Example generated AsciiDoc file +![](https://github.com/RobWin/swagger2AsciiDoc/blob/master/images/asciidoc.PNG) + +Example generated HTML +![](https://github.com/RobWin/swagger2AsciiDoc/blob/master/images/asciidoc_html.PNG) diff --git a/build.gradle b/build.gradle new file mode 100644 index 00000000..350ba109 --- /dev/null +++ b/build.gradle @@ -0,0 +1,38 @@ +buildscript { + repositories { + jcenter() + mavenCentral() + } + dependencies { + classpath 'org.asciidoctor:asciidoctor-gradle-plugin:1.5.2' + classpath 'org.asciidoctor:asciidoctorj-pdf:1.5.0-alpha.6' + } +} + +apply plugin: 'java' +apply plugin: 'maven' +apply plugin: 'org.asciidoctor.convert' + +version = '0.1.0' +group = 'io.swagger2AsciiDoc' + +repositories { + jcenter() + mavenCentral() + mavenLocal() + maven {url "https://oss.sonatype.org/content/repositories/snapshots"} +} + +dependencies { + compile 'io.swagger:swagger-legacy-spec-parser:1.0.0-SNAPSHOT' + compile 'commons-collections:commons-collections:3.2.1' + testCompile 'junit:junit:4.11' +} + +asciidoctor { + attributes = [ + doctype: 'book', + toc: 'left', + toclevels: '1' + ] +} \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 00000000..b7612167 Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..49bf250a --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Fri Feb 06 13:31:11 CET 2015 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-2.0-all.zip diff --git a/gradlew b/gradlew new file mode 100644 index 00000000..91a7e269 --- /dev/null +++ b/gradlew @@ -0,0 +1,164 @@ +#!/usr/bin/env bash + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn ( ) { + echo "$*" +} + +die ( ) { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; +esac + +# For Cygwin, ensure paths are in UNIX format before anything is touched. +if $cygwin ; then + [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` +fi + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >&- +APP_HOME="`pwd -P`" +cd "$SAVED" >&- + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules +function splitJvmOpts() { + JVM_OPTS=("$@") +} +eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS +JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" + +exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 00000000..8a0b282a --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,90 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windowz variants + +if not "%OS%" == "Windows_NT" goto win9xME_args +if "%@eval[2+2]" == "4" goto 4NT_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* +goto execute + +:4NT_args +@rem Get arguments from the 4NT Shell from JP Software +set CMD_LINE_ARGS=%$ + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/images/asciidoc.PNG b/images/asciidoc.PNG new file mode 100644 index 00000000..a64faac4 Binary files /dev/null and b/images/asciidoc.PNG differ diff --git a/images/asciidoc_html.PNG b/images/asciidoc_html.PNG new file mode 100644 index 00000000..46962bb6 Binary files /dev/null and b/images/asciidoc_html.PNG differ diff --git a/images/swagger_json.PNG b/images/swagger_json.PNG new file mode 100644 index 00000000..5b7f9532 Binary files /dev/null and b/images/swagger_json.PNG differ diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 00000000..a1c50378 --- /dev/null +++ b/settings.gradle @@ -0,0 +1,2 @@ +rootProject.name = 'swagger2asciidoc' + diff --git a/src/docs/asciidoc/swagger.adoc b/src/docs/asciidoc/swagger.adoc new file mode 100644 index 00000000..53bb18e2 --- /dev/null +++ b/src/docs/asciidoc/swagger.adoc @@ -0,0 +1,516 @@ += Swagger Petstore +This is a sample server Petstore server. + +[Learn about Swagger](http://swagger.wordnik.com) or join the IRC channel `#swagger` on irc.freenode.net. + +For this sample, you can use the api key `special-key` to test the authorization filters + +Version: 1.0.0 + +== Update an existing pet +---- +PUT /pets +---- +=== Parameters +[format="csv", options="header"] +|=== +Name,Located in,Description,Required +body,body,Pet object that needs to be added to the store,false +|=== + +=== Responses +[format="csv", options="header"] +|=== +Code,Description,Schema +400,Invalid ID supplied,null +404,Pet not found,null +405,Validation exception,null +|=== + +=== Consumes +* application/json +* application/xml + +=== Produces +* application/json +* application/xml + +== Add a new pet to the store +---- +POST /pets +---- +=== Parameters +[format="csv", options="header"] +|=== +Name,Located in,Description,Required +body,body,Pet object that needs to be added to the store,false +|=== + +=== Responses +[format="csv", options="header"] +|=== +Code,Description,Schema +405,Invalid input,null +|=== + +=== Consumes +* application/json +* application/xml + +=== Produces +* application/json +* application/xml + +== Finds Pets by status +=== Description +:hardbreaks: +Multiple status values can be provided with comma seperated strings + +---- +GET /pets/findByStatus +---- +=== Parameters +[format="csv", options="header"] +|=== +Name,Located in,Description,Required +status,query,Status values that need to be considered for filter,false +|=== + +=== Responses +[format="csv", options="header"] +|=== +Code,Description,Schema +200,successful operation,com.wordnik.swagger.models.properties.ArrayProperty@699bc508 +400,Invalid status value,null +|=== + +=== Produces +* application/json +* application/xml + +== Finds Pets by tags +=== Description +:hardbreaks: +Muliple tags can be provided with comma seperated strings. Use tag1, tag2, tag3 for testing. + +---- +GET /pets/findByTags +---- +=== Parameters +[format="csv", options="header"] +|=== +Name,Located in,Description,Required +tags,query,Tags to filter by,false +|=== + +=== Responses +[format="csv", options="header"] +|=== +Code,Description,Schema +200,successful operation,com.wordnik.swagger.models.properties.ArrayProperty@5f259e0f +400,Invalid tag value,null +|=== + +=== Produces +* application/json +* application/xml + +== Find pet by ID +=== Description +:hardbreaks: +Returns a pet when ID < 10. ID > 10 or nonintegers will simulate API error conditions + +---- +GET /pets/{petId} +---- +=== Parameters +[format="csv", options="header"] +|=== +Name,Located in,Description,Required +petId,path,ID of pet that needs to be fetched,true +|=== + +=== Responses +[format="csv", options="header"] +|=== +Code,Description,Schema +200,successful operation,com.wordnik.swagger.models.properties.RefProperty@7db471e1 +400,Invalid ID supplied,null +404,Pet not found,null +|=== + +=== Produces +* application/json +* application/xml + +== Deletes a pet +---- +DELETE /pets/{petId} +---- +=== Parameters +[format="csv", options="header"] +|=== +Name,Located in,Description,Required +api_key,header,,true +petId,path,Pet id to delete,true +|=== + +=== Responses +[format="csv", options="header"] +|=== +Code,Description,Schema +400,Invalid pet value,null +|=== + +=== Produces +* application/json +* application/xml + +== Updates a pet in the store with form data +---- +POST /pets/{petId} +---- +=== Parameters +[format="csv", options="header"] +|=== +Name,Located in,Description,Required +petId,path,ID of pet that needs to be updated,true +name,formData,Updated name of the pet,true +status,formData,Updated status of the pet,true +|=== + +=== Responses +[format="csv", options="header"] +|=== +Code,Description,Schema +405,Invalid input,null +|=== + +=== Consumes +* application/x-www-form-urlencoded + +=== Produces +* application/json +* application/xml + +== Place an order for a pet +---- +POST /stores/order +---- +=== Parameters +[format="csv", options="header"] +|=== +Name,Located in,Description,Required +body,body,order placed for purchasing the pet,false +|=== + +=== Responses +[format="csv", options="header"] +|=== +Code,Description,Schema +200,successful operation,com.wordnik.swagger.models.properties.RefProperty@e2df24b +400,Invalid Order,null +|=== + +=== Produces +* application/json +* application/xml + +== Find purchase order by ID +=== Description +:hardbreaks: +For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions + +---- +GET /stores/order/{orderId} +---- +=== Parameters +[format="csv", options="header"] +|=== +Name,Located in,Description,Required +orderId,path,ID of pet that needs to be fetched,true +|=== + +=== Responses +[format="csv", options="header"] +|=== +Code,Description,Schema +200,successful operation,com.wordnik.swagger.models.properties.RefProperty@3929d503 +400,Invalid ID supplied,null +404,Order not found,null +|=== + +=== Produces +* application/json +* application/xml + +== Delete purchase order by ID +=== Description +:hardbreaks: +For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors + +---- +DELETE /stores/order/{orderId} +---- +=== Parameters +[format="csv", options="header"] +|=== +Name,Located in,Description,Required +orderId,path,ID of the order that needs to be deleted,true +|=== + +=== Responses +[format="csv", options="header"] +|=== +Code,Description,Schema +400,Invalid ID supplied,null +404,Order not found,null +|=== + +=== Produces +* application/json +* application/xml + +== Create user +=== Description +:hardbreaks: +This can only be done by the logged in user. + +---- +POST /users +---- +=== Parameters +[format="csv", options="header"] +|=== +Name,Located in,Description,Required +body,body,Created user object,false +|=== + +=== Responses +[format="csv", options="header"] +|=== +Code,Description,Schema +default,successful operation,null +|=== + +=== Produces +* application/json +* application/xml + +== Creates list of users with given input array +---- +POST /users/createWithArray +---- +=== Parameters +[format="csv", options="header"] +|=== +Name,Located in,Description,Required +body,body,List of user object,false +|=== + +=== Responses +[format="csv", options="header"] +|=== +Code,Description,Schema +default,successful operation,null +|=== + +=== Produces +* application/json +* application/xml + +== Creates list of users with given input array +---- +POST /users/createWithList +---- +=== Parameters +[format="csv", options="header"] +|=== +Name,Located in,Description,Required +body,body,List of user object,false +|=== + +=== Responses +[format="csv", options="header"] +|=== +Code,Description,Schema +default,successful operation,null +|=== + +=== Produces +* application/json +* application/xml + +== Logs user into the system +---- +GET /users/login +---- +=== Parameters +[format="csv", options="header"] +|=== +Name,Located in,Description,Required +username,query,The user name for login,false +password,query,The password for login in clear text,false +|=== + +=== Responses +[format="csv", options="header"] +|=== +Code,Description,Schema +200,successful operation,com.wordnik.swagger.models.properties.StringProperty@4a8fe1cf +400,Invalid username/password supplied,null +|=== + +=== Produces +* application/json +* application/xml + +== Logs out current logged in user session +---- +GET /users/logout +---- +=== Responses +[format="csv", options="header"] +|=== +Code,Description,Schema +default,successful operation,null +|=== + +=== Produces +* application/json +* application/xml + +== Get user by user name +---- +GET /users/{username} +---- +=== Parameters +[format="csv", options="header"] +|=== +Name,Located in,Description,Required +username,path,The name that needs to be fetched. Use user1 for testing.,true +|=== + +=== Responses +[format="csv", options="header"] +|=== +Code,Description,Schema +200,successful operation,com.wordnik.swagger.models.properties.RefProperty@146aaa06 +400,Invalid username supplied,null +404,User not found,null +|=== + +=== Produces +* application/json +* application/xml + +== Updated user +=== Description +:hardbreaks: +This can only be done by the logged in user. + +---- +PUT /users/{username} +---- +=== Parameters +[format="csv", options="header"] +|=== +Name,Located in,Description,Required +username,path,name that need to be deleted,true +body,body,Updated user object,false +|=== + +=== Responses +[format="csv", options="header"] +|=== +Code,Description,Schema +400,Invalid user supplied,null +404,User not found,null +|=== + +=== Produces +* application/json +* application/xml + +== Delete user +=== Description +:hardbreaks: +This can only be done by the logged in user. + +---- +DELETE /users/{username} +---- +=== Parameters +[format="csv", options="header"] +|=== +Name,Located in,Description,Required +username,path,The name that needs to be deleted,true +|=== + +=== Responses +[format="csv", options="header"] +|=== +Code,Description,Schema +400,Invalid username supplied,null +404,User not found,null +|=== + +=== Produces +* application/json +* application/xml + +== Definitions +=== User +[format="csv", options="header"] +|=== +Name,Type,Required +id,integer,false +username,string,false +firstName,string,false +lastName,string,false +email,string,false +password,string,false +phone,string,false +userStatus,integer,false +|=== + +=== Category +[format="csv", options="header"] +|=== +Name,Type,Required +id,integer,false +name,string,false +|=== + +=== Pet +[format="csv", options="header"] +|=== +Name,Type,Required +id,integer,false +category,ref,false +name,string,true +photoUrls,array,true +tags,array,false +status,string,false +|=== + +=== Tag +[format="csv", options="header"] +|=== +Name,Type,Required +id,integer,false +name,string,false +|=== + +=== Order +[format="csv", options="header"] +|=== +Name,Type,Required +id,integer,false +petId,integer,false +quantity,integer,false +shipDate,string,false +status,string,false +complete,boolean,false +|=== + diff --git a/src/main/java/io/swagger2asciidoc/AsciiDocBuilder.java b/src/main/java/io/swagger2asciidoc/AsciiDocBuilder.java new file mode 100644 index 00000000..14c28610 --- /dev/null +++ b/src/main/java/io/swagger2asciidoc/AsciiDocBuilder.java @@ -0,0 +1,104 @@ +package io.swagger2asciidoc; + +import java.util.List; + +/** + * @author Robert Winkler + */ +public class AsciiDocBuilder { + + private StringBuilder asciiDocBuilder = new StringBuilder(); + private String newLine = System.getProperty("line.separator"); + private static final String LABEL_DELIMITER = ":: "; + private static final String TABLE_DELIMITER = "|==="; + private static final String LISTING_DELIMITER = "----"; + private static final String HARDBREAKS_ATTRIBUTE = ":hardbreaks:"; + private static final String DOCUMENT_TITLE = "= "; + private static final String SECTION_TITLE_LEVEL1 = "== "; + private static final String SECTION_TITLE_LEVEL2 = "=== "; + private static final String SECTION_TITLE_LEVEL3 = "==== "; + private static final String BOLD_DELIMITER = "*"; + private static final String LIST_ENTRY = "* "; + + public AsciiDocBuilder documentTitle(String title){ + asciiDocBuilder.append(DOCUMENT_TITLE).append(title).append(newLine); + return this; + } + + public AsciiDocBuilder sectionTitleLevel1(String title){ + asciiDocBuilder.append(SECTION_TITLE_LEVEL1).append(title).append(newLine); + return this; + } + + public AsciiDocBuilder sectionTitleLevel2(String title){ + asciiDocBuilder.append(SECTION_TITLE_LEVEL2).append(title).append(newLine); + return this; + } + + public AsciiDocBuilder sectionTitleLevel3(String title){ + asciiDocBuilder.append(SECTION_TITLE_LEVEL3).append(title).append(newLine); + return this; + } + + public AsciiDocBuilder textLine(String text){ + asciiDocBuilder.append(text).append(newLine); + return this; + } + + public AsciiDocBuilder paragraph(String text){ + asciiDocBuilder.append(HARDBREAKS_ATTRIBUTE).append(newLine).append(text).append(newLine).append(newLine); + return this; + } + + public AsciiDocBuilder listing(String text){ + delimitedText(LISTING_DELIMITER, text); + return this; + } + + private AsciiDocBuilder delimitedText(String delimiter, String text){ + asciiDocBuilder.append(delimiter).append(newLine).append(text).append(newLine).append(delimiter).append(newLine); + return this; + } + + public AsciiDocBuilder preserveLineBreaks(){ + asciiDocBuilder.append(HARDBREAKS_ATTRIBUTE).append(newLine); + return this; + } + + public AsciiDocBuilder boldTextLine(String text){ + delimitedText(BOLD_DELIMITER, text); + return this; + } + + public AsciiDocBuilder textLineWithTitle(String title, String text){ + asciiDocBuilder.append(title).append(LABEL_DELIMITER).append(text).append(newLine); + return this; + } + + public AsciiDocBuilder unorderedList(List list){ + for(String listEntry : list){ + asciiDocBuilder.append(LIST_ENTRY).append(listEntry).append(newLine); + } + asciiDocBuilder.append(newLine); + return this; + } + + public AsciiDocBuilder tableWithHeaderRow(List csvContent){ + asciiDocBuilder.append("[format=\"csv\", options=\"header\"]").append(newLine); + asciiDocBuilder.append(TABLE_DELIMITER).append(newLine); + for(String row : csvContent){ + asciiDocBuilder.append(row).append(newLine); + } + asciiDocBuilder.append(TABLE_DELIMITER).append(newLine).append(newLine); + return this; + } + + public AsciiDocBuilder lineBreak(){ + asciiDocBuilder.append(newLine); + return this; + } + + public String toString(){ + return asciiDocBuilder.toString(); + } +} diff --git a/src/main/java/io/swagger2asciidoc/Swagger2AsciiDocConverter.java b/src/main/java/io/swagger2asciidoc/Swagger2AsciiDocConverter.java new file mode 100644 index 00000000..f419664c --- /dev/null +++ b/src/main/java/io/swagger2asciidoc/Swagger2AsciiDocConverter.java @@ -0,0 +1,192 @@ +package io.swagger2asciidoc; + +import com.wordnik.swagger.models.*; +import com.wordnik.swagger.models.parameters.Parameter; +import com.wordnik.swagger.models.properties.Property; +import io.swagger.parser.SwaggerParser; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections.MapUtils; +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.BufferedWriter; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * @author Robert Winkler + */ +public class Swagger2AsciiDocConverter { + private static final Logger logger = LoggerFactory.getLogger(Swagger2AsciiDocConverter.class); + public static final String VERSION = "Version: "; + public static final String SUMMARY = "Summary"; + public static final String DESCRIPTION = "Description"; + public static final String PARAMETERS = "Parameters"; + public static final String PRODUCES = "Produces"; + public static final String CONSUMES = "Consumes"; + public static final String RESPONSES = "Responses"; + public static final String DEFINITIONS = "Definitions"; + private final AsciiDocBuilder asciiDocBuilder; + private final Swagger swagger; + private final String asciiDocFileLocation; + + private Swagger2AsciiDocConverter(String swaggerFileLocation, String asciiDocFileLocation){ + swagger = new SwaggerParser().read(swaggerFileLocation); + this.asciiDocFileLocation = asciiDocFileLocation; + asciiDocBuilder = new AsciiDocBuilder(); + } + + public static Swagger2AsciiDocConverter newInstance(String swaggerFileLocation, String asciiDocFileLocation){ + return new Swagger2AsciiDocConverter(swaggerFileLocation, asciiDocFileLocation); + } + + public void convertSwagger2AsciiDoc(){ + documentHeader(swagger.getInfo()); + paths(swagger.getPaths()); + definitions(swagger.getDefinitions()); + writeAsciiDocFile(asciiDocFileLocation); + } + + private void writeAsciiDocFile(String asciiDocFileLocation) { + try (BufferedWriter writer = Files.newBufferedWriter(Paths.get(asciiDocFileLocation), + StandardCharsets.UTF_8)){ + writer.write(asciiDocBuilder.toString()); + } catch (IOException e) { + logger.warn("Failed to convert Swagger file to AsciiDoc", e); + } + } + + private void paths(Map paths) { + for(Map.Entry entry : paths.entrySet()){ + Path path = entry.getValue(); + path("GET", entry.getKey(), path.getGet()); + path("PUT", entry.getKey(), path.getPut()); + path("DELETE", entry.getKey(), path.getDelete()); + path("POST", entry.getKey(), path.getPost()); + path("PATCH", entry.getKey(), path.getPatch()); + } + } + + private void documentHeader(Info info) { + asciiDocBuilder + .documentTitle(info.getTitle()) + .textLine(info.getDescription()) + .textLine(VERSION + info.getVersion()) + .lineBreak(); + + } + + private void path(String httpMethod, String resourcePath, Operation operation) { + if(operation != null){ + pathTitleAndDescription(httpMethod, resourcePath, operation); + parameters(operation); + responses(operation); + consumes(operation); + produces(operation); + } + } + + private void pathTitleAndDescription(String httpMethod, String resourcePath, Operation operation) { + String summary = operation.getSummary(); + if(StringUtils.isNotBlank(summary)) { + asciiDocBuilder.sectionTitleLevel1(operation.getSummary()); + description(operation); + asciiDocBuilder.listing(httpMethod + " " + resourcePath); + }else{ + asciiDocBuilder.sectionTitleLevel1(httpMethod + " " + resourcePath); + description(operation); + } + } + + private void description(Operation operation) { + String description = operation.getDescription(); + if(StringUtils.isNotBlank(description)){ + asciiDocBuilder.sectionTitleLevel2(DESCRIPTION); + asciiDocBuilder.paragraph(description); + } + } + + private void consumes(Operation operation) { + List consumes = operation.getConsumes(); + if(CollectionUtils.isNotEmpty(consumes)){ + asciiDocBuilder.sectionTitleLevel2(CONSUMES); + asciiDocBuilder.unorderedList(consumes); + } + + } + + private void produces(Operation operation) { + List consumes = operation.getProduces(); + if(CollectionUtils.isNotEmpty(consumes)){ + asciiDocBuilder.sectionTitleLevel2(PRODUCES); + asciiDocBuilder.unorderedList(consumes); + } + } + + private void parameters(Operation operation) { + List parameters = operation.getParameters(); + if(CollectionUtils.isNotEmpty(parameters)){ + List csvContent = new ArrayList<>(); + csvContent.add("Name,Located in,Description,Required"); + for(Parameter parameter : parameters){ + StringBuilder rowBuilder = new StringBuilder(); + rowBuilder.append(parameter.getName()).append(","). + append(parameter.getIn()).append(","). + append(parameter.getDescription()).append(","). + append(parameter.getRequired()); + csvContent.add(rowBuilder.toString()); + } + asciiDocBuilder.sectionTitleLevel2(PARAMETERS); + asciiDocBuilder.tableWithHeaderRow(csvContent); + } + } + + + + private void responses(Operation operation) { + Map responses = operation.getResponses(); + if(MapUtils.isNotEmpty(responses)){ + List csvContent = new ArrayList<>(); + csvContent.add("Code,Description,Schema"); + for(Map.Entry entry : responses.entrySet()){ + Response response = entry.getValue(); + StringBuilder rowBuilder = new StringBuilder(); + rowBuilder.append(entry.getKey()).append(","). + append(response.getDescription()).append(","). + append(response.getSchema()); + csvContent.add(rowBuilder.toString()); + } + asciiDocBuilder.sectionTitleLevel2(RESPONSES); + asciiDocBuilder.tableWithHeaderRow(csvContent); + } + } + + private void definitions(Map definitions) { + if(MapUtils.isNotEmpty(definitions)){ + asciiDocBuilder.sectionTitleLevel1(DEFINITIONS); + for(Map.Entry definitionsEntry : definitions.entrySet()){ + String definitionName = definitionsEntry.getKey(); + asciiDocBuilder.sectionTitleLevel2(definitionName); + Model response = definitionsEntry.getValue(); + Map properties = response.getProperties(); + List csvContent = new ArrayList<>(); + csvContent.add("Name,Type,Required"); + for(Map.Entry propertyEntry : properties.entrySet()){ + Property property = propertyEntry.getValue(); + StringBuilder rowBuilder = new StringBuilder(); + rowBuilder.append(propertyEntry.getKey()).append(","). + append(property.getType()).append(",").append(property.getRequired()); + csvContent.add(rowBuilder.toString()); + } + asciiDocBuilder.tableWithHeaderRow(csvContent); + } + } + } + +} diff --git a/src/test/java/io/swagger2asciidoc/Swagger2AsciiDocConverterTest.java b/src/test/java/io/swagger2asciidoc/Swagger2AsciiDocConverterTest.java new file mode 100644 index 00000000..20a664ab --- /dev/null +++ b/src/test/java/io/swagger2asciidoc/Swagger2AsciiDocConverterTest.java @@ -0,0 +1,24 @@ +package io.swagger2asciidoc; + +import org.junit.Test; + +import java.io.File; + +/** + * Project: swagger2AsciiDoc + * Copyright: Deutsche Telekom AG + * + * @author Robert Winkler + * @since 2.0.0 + */ +public class Swagger2AsciiDocConverterTest { + + @Test + public void testSwagger2AsciiDocConverter(){ + File file = new File(Swagger2AsciiDocConverterTest.class.getResource("/json/swagger.json").getFile()); + Swagger2AsciiDocConverter.newInstance( + file.getAbsolutePath(), + "C:\\Users\\robert.winkler\\Documents\\git\\swagger2asciidoc\\src\\docs\\asciidoc\\swagger.adoc") + .convertSwagger2AsciiDoc(); + } +} diff --git a/src/test/resources/json/swagger.json b/src/test/resources/json/swagger.json new file mode 100644 index 00000000..abd39a5a --- /dev/null +++ b/src/test/resources/json/swagger.json @@ -0,0 +1,846 @@ +{ + "swagger": "2.0", + "info": { + "description": "This is a sample server Petstore server.\n\n[Learn about Swagger](http://swagger.wordnik.com) or join the IRC channel `#swagger` on irc.freenode.net.\n\nFor this sample, you can use the api key `special-key` to test the authorization filters\n", + "version": "1.0.0", + "title": "Swagger Petstore", + "termsOfService": "http://helloreverb.com/terms/", + "contact": { + "name": "apiteam@wordnik.com" + }, + "license": { + "name": "Apache 2.0", + "url": "http://www.apache.org/licenses/LICENSE-2.0.html" + } + }, + "host": "petstore.swagger.wordnik.com", + "basePath": "/v2", + "schemes": [ + "http" + ], + "paths": { + "/pets": { + "post": { + "tags": [ + "pet" + ], + "summary": "Add a new pet to the store", + "description": "", + "operationId": "addPet", + "consumes": [ + "application/json", + "application/xml" + ], + "produces": [ + "application/json", + "application/xml" + ], + "parameters": [ + { + "in": "body", + "name": "body", + "description": "Pet object that needs to be added to the store", + "required": false, + "schema": { + "$ref": "#/definitions/Pet" + } + } + ], + "responses": { + "405": { + "description": "Invalid input" + } + }, + "security": [ + { + "petstore_auth": [ + "write_pets", + "read_pets" + ] + } + ] + }, + "put": { + "tags": [ + "pet" + ], + "summary": "Update an existing pet", + "description": "", + "operationId": "updatePet", + "consumes": [ + "application/json", + "application/xml" + ], + "produces": [ + "application/json", + "application/xml" + ], + "parameters": [ + { + "in": "body", + "name": "body", + "description": "Pet object that needs to be added to the store", + "required": false, + "schema": { + "$ref": "#/definitions/Pet" + } + } + ], + "responses": { + "400": { + "description": "Invalid ID supplied" + }, + "404": { + "description": "Pet not found" + }, + "405": { + "description": "Validation exception" + } + }, + "security": [ + { + "petstore_auth": [ + "write_pets", + "read_pets" + ] + } + ] + } + }, + "/pets/findByStatus": { + "get": { + "tags": [ + "pet" + ], + "summary": "Finds Pets by status", + "description": "Multiple status values can be provided with comma seperated strings", + "operationId": "findPetsByStatus", + "produces": [ + "application/json", + "application/xml" + ], + "parameters": [ + { + "in": "query", + "name": "status", + "description": "Status values that need to be considered for filter", + "required": false, + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "multi" + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/Pet" + } + } + }, + "400": { + "description": "Invalid status value" + } + }, + "security": [ + { + "petstore_auth": [ + "write_pets", + "read_pets" + ] + } + ] + } + }, + "/pets/findByTags": { + "get": { + "tags": [ + "pet" + ], + "summary": "Finds Pets by tags", + "description": "Muliple tags can be provided with comma seperated strings. Use tag1, tag2, tag3 for testing.", + "operationId": "findPetsByTags", + "produces": [ + "application/json", + "application/xml" + ], + "parameters": [ + { + "in": "query", + "name": "tags", + "description": "Tags to filter by", + "required": false, + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "multi" + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/Pet" + } + } + }, + "400": { + "description": "Invalid tag value" + } + }, + "security": [ + { + "petstore_auth": [ + "write_pets", + "read_pets" + ] + } + ] + } + }, + "/pets/{petId}": { + "get": { + "tags": [ + "pet" + ], + "summary": "Find pet by ID", + "description": "Returns a pet when ID < 10. ID > 10 or nonintegers will simulate API error conditions", + "operationId": "getPetById", + "produces": [ + "application/json", + "application/xml" + ], + "parameters": [ + { + "in": "path", + "name": "petId", + "description": "ID of pet that needs to be fetched", + "required": true, + "type": "integer", + "format": "int64" + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "$ref": "#/definitions/Pet" + } + }, + "400": { + "description": "Invalid ID supplied" + }, + "404": { + "description": "Pet not found" + } + }, + "security": [ + { + "api_key": [] + }, + { + "petstore_auth": [ + "write_pets", + "read_pets" + ] + } + ] + }, + "post": { + "tags": [ + "pet" + ], + "summary": "Updates a pet in the store with form data", + "description": "", + "operationId": "updatePetWithForm", + "consumes": [ + "application/x-www-form-urlencoded" + ], + "produces": [ + "application/json", + "application/xml" + ], + "parameters": [ + { + "in": "path", + "name": "petId", + "description": "ID of pet that needs to be updated", + "required": true, + "type": "string" + }, + { + "in": "formData", + "name": "name", + "description": "Updated name of the pet", + "required": true, + "type": "string" + }, + { + "in": "formData", + "name": "status", + "description": "Updated status of the pet", + "required": true, + "type": "string" + } + ], + "responses": { + "405": { + "description": "Invalid input" + } + }, + "security": [ + { + "petstore_auth": [ + "write_pets", + "read_pets" + ] + } + ] + }, + "delete": { + "tags": [ + "pet" + ], + "summary": "Deletes a pet", + "description": "", + "operationId": "deletePet", + "produces": [ + "application/json", + "application/xml" + ], + "parameters": [ + { + "in": "header", + "name": "api_key", + "description": "", + "required": true, + "type": "string" + }, + { + "in": "path", + "name": "petId", + "description": "Pet id to delete", + "required": true, + "type": "integer", + "format": "int64" + } + ], + "responses": { + "400": { + "description": "Invalid pet value" + } + }, + "security": [ + { + "petstore_auth": [ + "write_pets", + "read_pets" + ] + } + ] + } + }, + "/stores/order": { + "post": { + "tags": [ + "store" + ], + "summary": "Place an order for a pet", + "description": "", + "operationId": "placeOrder", + "produces": [ + "application/json", + "application/xml" + ], + "parameters": [ + { + "in": "body", + "name": "body", + "description": "order placed for purchasing the pet", + "required": false, + "schema": { + "$ref": "#/definitions/Order" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "$ref": "#/definitions/Order" + } + }, + "400": { + "description": "Invalid Order" + } + } + } + }, + "/stores/order/{orderId}": { + "get": { + "tags": [ + "store" + ], + "summary": "Find purchase order by ID", + "description": "For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions", + "operationId": "getOrderById", + "produces": [ + "application/json", + "application/xml" + ], + "parameters": [ + { + "in": "path", + "name": "orderId", + "description": "ID of pet that needs to be fetched", + "required": true, + "type": "string" + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "$ref": "#/definitions/Order" + } + }, + "400": { + "description": "Invalid ID supplied" + }, + "404": { + "description": "Order not found" + } + } + }, + "delete": { + "tags": [ + "store" + ], + "summary": "Delete purchase order by ID", + "description": "For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors", + "operationId": "deleteOrder", + "produces": [ + "application/json", + "application/xml" + ], + "parameters": [ + { + "in": "path", + "name": "orderId", + "description": "ID of the order that needs to be deleted", + "required": true, + "type": "string" + } + ], + "responses": { + "400": { + "description": "Invalid ID supplied" + }, + "404": { + "description": "Order not found" + } + } + } + }, + "/users": { + "post": { + "tags": [ + "user" + ], + "summary": "Create user", + "description": "This can only be done by the logged in user.", + "operationId": "createUser", + "produces": [ + "application/json", + "application/xml" + ], + "parameters": [ + { + "in": "body", + "name": "body", + "description": "Created user object", + "required": false, + "schema": { + "$ref": "#/definitions/User" + } + } + ], + "responses": { + "default": { + "description": "successful operation" + } + } + } + }, + "/users/createWithArray": { + "post": { + "tags": [ + "user" + ], + "summary": "Creates list of users with given input array", + "description": "", + "operationId": "createUsersWithArrayInput", + "produces": [ + "application/json", + "application/xml" + ], + "parameters": [ + { + "in": "body", + "name": "body", + "description": "List of user object", + "required": false, + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/User" + } + } + } + ], + "responses": { + "default": { + "description": "successful operation" + } + } + } + }, + "/users/createWithList": { + "post": { + "tags": [ + "user" + ], + "summary": "Creates list of users with given input array", + "description": "", + "operationId": "createUsersWithListInput", + "produces": [ + "application/json", + "application/xml" + ], + "parameters": [ + { + "in": "body", + "name": "body", + "description": "List of user object", + "required": false, + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/User" + } + } + } + ], + "responses": { + "default": { + "description": "successful operation" + } + } + } + }, + "/users/login": { + "get": { + "tags": [ + "user" + ], + "summary": "Logs user into the system", + "description": "", + "operationId": "loginUser", + "produces": [ + "application/json", + "application/xml" + ], + "parameters": [ + { + "in": "query", + "name": "username", + "description": "The user name for login", + "required": false, + "type": "string" + }, + { + "in": "query", + "name": "password", + "description": "The password for login in clear text", + "required": false, + "type": "string" + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "type": "string" + } + }, + "400": { + "description": "Invalid username/password supplied" + } + } + } + }, + "/users/logout": { + "get": { + "tags": [ + "user" + ], + "summary": "Logs out current logged in user session", + "description": "", + "operationId": "logoutUser", + "produces": [ + "application/json", + "application/xml" + ], + "responses": { + "default": { + "description": "successful operation" + } + } + } + }, + "/users/{username}": { + "get": { + "tags": [ + "user" + ], + "summary": "Get user by user name", + "description": "", + "operationId": "getUserByName", + "produces": [ + "application/json", + "application/xml" + ], + "parameters": [ + { + "in": "path", + "name": "username", + "description": "The name that needs to be fetched. Use user1 for testing.", + "required": true, + "type": "string" + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "$ref": "#/definitions/User" + } + }, + "400": { + "description": "Invalid username supplied" + }, + "404": { + "description": "User not found" + } + } + }, + "put": { + "tags": [ + "user" + ], + "summary": "Updated user", + "description": "This can only be done by the logged in user.", + "operationId": "updateUser", + "produces": [ + "application/json", + "application/xml" + ], + "parameters": [ + { + "in": "path", + "name": "username", + "description": "name that need to be deleted", + "required": true, + "type": "string" + }, + { + "in": "body", + "name": "body", + "description": "Updated user object", + "required": false, + "schema": { + "$ref": "#/definitions/User" + } + } + ], + "responses": { + "400": { + "description": "Invalid user supplied" + }, + "404": { + "description": "User not found" + } + } + }, + "delete": { + "tags": [ + "user" + ], + "summary": "Delete user", + "description": "This can only be done by the logged in user.", + "operationId": "deleteUser", + "produces": [ + "application/json", + "application/xml" + ], + "parameters": [ + { + "in": "path", + "name": "username", + "description": "The name that needs to be deleted", + "required": true, + "type": "string" + } + ], + "responses": { + "400": { + "description": "Invalid username supplied" + }, + "404": { + "description": "User not found" + } + } + } + } + }, + "securityDefinitions": { + "api_key": { + "type": "apiKey", + "name": "api_key", + "in": "header" + }, + "petstore_auth": { + "type": "oauth2", + "authorizationUrl": "http://petstore.swagger.wordnik.com/api/oauth/dialog", + "flow": "implicit", + "scopes": { + "write_pets": "modify pets in your account", + "read_pets": "read your pets" + } + } + }, + "definitions": { + "User": { + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "username": { + "type": "string" + }, + "firstName": { + "type": "string" + }, + "lastName": { + "type": "string" + }, + "email": { + "type": "string" + }, + "password": { + "type": "string" + }, + "phone": { + "type": "string" + }, + "userStatus": { + "type": "integer", + "format": "int32", + "description": "User Status" + } + } + }, + "Category": { + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "name": { + "type": "string" + } + } + }, + "Pet": { + "required": [ + "name", + "photoUrls" + ], + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "category": { + "$ref": "#/definitions/Category" + }, + "name": { + "type": "string", + "example": "doggie" + }, + "photoUrls": { + "type": "array", + "items": { + "type": "string" + } + }, + "tags": { + "type": "array", + "items": { + "$ref": "#/definitions/Tag" + } + }, + "status": { + "type": "string", + "description": "pet status in the store" + } + } + }, + "Tag": { + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "name": { + "type": "string" + } + } + }, + "Order": { + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "petId": { + "type": "integer", + "format": "int64" + }, + "quantity": { + "type": "integer", + "format": "int32" + }, + "shipDate": { + "type": "string", + "format": "date-time" + }, + "status": { + "type": "string", + "description": "Order Status" + }, + "complete": { + "type": "boolean" + } + } + } + } +} \ No newline at end of file