Merge remote-tracking branch 'main/master'

This commit is contained in:
Tommy Alander 2016-02-29 08:24:31 +01:00
commit a2be66d492
1738 changed files with 71972 additions and 42877 deletions

View File

@ -30,7 +30,7 @@ samples/client/petstore/qt5cpp/build-*
samples/client/petstore/qt5cpp/PetStore/PetStore samples/client/petstore/qt5cpp/PetStore/PetStore
samples/client/petstore/qt5cpp/PetStore/Makefile samples/client/petstore/qt5cpp/PetStore/Makefile
samples/client/petstore/java/hello.txt samples/client/petstore/java/hello.txt
samples/client/petstore/android-java/hello.txt samples/client/petstore/android/default/hello.txt
samples/client/petstore/objc/Build samples/client/petstore/objc/Build
samples/client/petstore/objc/Pods samples/client/petstore/objc/Pods
samples/server/petstore/nodejs/node_modules samples/server/petstore/nodejs/node_modules

22
.gitignore vendored
View File

@ -31,7 +31,7 @@ samples/client/petstore/qt5cpp/build-*
samples/client/petstore/qt5cpp/PetStore/PetStore samples/client/petstore/qt5cpp/PetStore/PetStore
samples/client/petstore/qt5cpp/PetStore/Makefile samples/client/petstore/qt5cpp/PetStore/Makefile
samples/client/petstore/java/hello.txt samples/client/petstore/java/hello.txt
samples/client/petstore/android-java/hello.txt samples/client/petstore/android/default/hello.txt
samples/client/petstore/objc/SwaggerClientTests/Build samples/client/petstore/objc/SwaggerClientTests/Build
samples/client/petstore/objc/SwaggerClientTests/Pods samples/client/petstore/objc/SwaggerClientTests/Pods
samples/client/petstore/objc/SwaggerClientTests/SwaggerClient.xcworkspace samples/client/petstore/objc/SwaggerClientTests/SwaggerClient.xcworkspace
@ -48,6 +48,7 @@ atlassian-ide-plugin.xml
packages/ packages/
.pub .pub
.packages .packages
.vagrant/
samples/client/petstore/php/SwaggerClient-php/composer.lock samples/client/petstore/php/SwaggerClient-php/composer.lock
samples/client/petstore/php/SwaggerClient-php/vendor/ samples/client/petstore/php/SwaggerClient-php/vendor/
@ -55,13 +56,30 @@ samples/client/petstore/php/SwaggerClient-php/vendor/
samples/client/petstore/silex/SwaggerServer/composer.lock samples/client/petstore/silex/SwaggerServer/composer.lock
samples/client/petstore/silex/SwaggerServer/venodr/ samples/client/petstore/silex/SwaggerServer/venodr/
samples/client/petstore/perl/deep_module_test/
samples/client/petstore/python/.projectile samples/client/petstore/python/.projectile
samples/client/petstore/python/.venv/ samples/client/petstore/python/.venv/
samples/client/petstore/python/dev-requirements.txt.log
*/.settings samples/client/petstore/objc/SwaggerClientTests/SwaggerClient.xcodeproj/xcuserdata
samples/client/petstore/swift/SwaggerClientTests/SwaggerClient.xcodeproj/xcuserdata
samples/client/petstore/swift/SwaggerClientTests/SwaggerClient.xcworkspace/xcuserdata
samples/client/petstore/swift/SwaggerClientTests/Pods/Pods.xcodeproj/xcuserdata
samples/client/petstore/swift/SwaggerClientTests/Pods/Pods.xcodeproj/xcshareddata/xcschemes
.settings
*.mustache~ *.mustache~
*.java~ *.java~
*.pm~ *.pm~
*.xml~ *.xml~
*.t~ *.t~
samples/client/petstore/csharp/SwaggerClientTest/bin/Debug/
samples/client/petstore/csharp/SwaggerClientTest/obj/Debug/
**/.gradle/
samples/client/petstore/python/dev-requirements.txt.log
samples/client/petstore/python/swagger_client.egg-info/SOURCES.txt
samples/client/petstore/python/.coverage

View File

@ -1,5 +1,21 @@
sudo: false sudo: required
language: java language: java
script: mvn verify -Psamples
jdk: jdk:
- oraclejdk7 - oraclejdk7
- oraclejdk8
services:
- docker
before_install:
# required when sudo: required for the Ruby petstore tests
- gem install bundler
install:
script:
- mvn verify -Psamples
- if [ $DOCKER_HUB_USERNAME ]; then docker login --email=$DOCKER_HUB_EMAIL --username=$DOCKER_HUB_USERNAME --password=$DOCKER_HUB_PASSWORD && docker build -t $DOCKER_IMAGE_NAME ./modules/swagger-generator && if [ ! -z "$TRAVIS_TAG" ]; then docker tag $DOCKER_IMAGE_NAME:latest $DOCKER_IMAGE_NAME:$TRAVIS_TAG; fi && docker push $DOCKER_IMAGE_NAME; fi
env:
- DOCKER_IMAGE_NAME=swaggerapi/swagger-generator

View File

@ -2,9 +2,9 @@
## Before submitting an issue ## Before submitting an issue
- Before submitting an issue, search the [open issue](https://github.com/swagger-api/swagger-codegen/issues) and [closed issue](https://github.com/swagger-api/swagger-codegen/issues?q=is%3Aissue+is%3Aclosed) to ensure no one else has reported something similar before. - Search the [open issue](https://github.com/swagger-api/swagger-codegen/issues) and [closed issue](https://github.com/swagger-api/swagger-codegen/issues?q=is%3Aissue+is%3Aclosed) to ensure no one else has reported something similar before.
- The issue should contain details on how to repeat the issue, e.g. - The issue should contain details on how to repeat the issue, e.g.
- the Swagger spec for reproducing the issue (:bulb: use [Gist](https://gist.github.com) to share). If the Swagger spec cannot be shared publicly, it will be hard for the community to help - the OpenAPI Spec for reproducing the issue (:bulb: use [Gist](https://gist.github.com) to share). If the OpenAPI Spec cannot be shared publicly, it will be hard for the community to help
- version of Swagger Codegen - version of Swagger Codegen
- language (`-l` in the command line, e.g. java, csharp, php) - language (`-l` in the command line, e.g. java, csharp, php)
- You can also make a suggestion or ask a question by opening an "issue" - You can also make a suggestion or ask a question by opening an "issue"
@ -31,10 +31,12 @@ For a list of variables available in the template, please refer to this [page](h
Code change should conform to the programming style guide of the respective langauages: Code change should conform to the programming style guide of the respective langauages:
- C#: https://msdn.microsoft.com/en-us/library/vstudio/ff926074.aspx - C#: https://msdn.microsoft.com/en-us/library/vstudio/ff926074.aspx
- Java: https://google.github.io/styleguide/javaguide.html - Java: https://google.github.io/styleguide/javaguide.html
- JavaScript - https://github.com/airbnb/javascript/tree/master/es5
- ObjC: https://github.com/NYTimes/objective-c-style-guide - ObjC: https://github.com/NYTimes/objective-c-style-guide
- PHP: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md - PHP: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md
- Python: https://www.python.org/dev/peps/pep-0008/ - Python: https://www.python.org/dev/peps/pep-0008/
- Ruby: https://github.com/bbatsov/ruby-style-guide - Ruby: https://github.com/bbatsov/ruby-style-guide
- Swift: https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/TheBasics.html
- TypeScript: https://github.com/Microsoft/TypeScript/wiki/Coding-guidelines - TypeScript: https://github.com/Microsoft/TypeScript/wiki/Coding-guidelines
@ -56,7 +58,7 @@ To start the CI tests, you can run `mvn verify -Psamples` (assuming you've all t
### Tips ### Tips
- Smaller changes are easier to review - Smaller changes are easier to review
- [Optional] For bug fixes, provide a Swagger spec to repeat the issue so that the reviewer can use it to confirm the fix - [Optional] For bug fixes, provide a OpenAPI Spec to repeat the issue so that the reviewer can use it to confirm the fix
- Add test case(s) to cover the change - Add test case(s) to cover the change
- Document the fix in the code to make the code more readable - Document the fix in the code to make the code more readable
- Make sure test cases passed after the change (one way is to leverage https://travis-ci.org/ to run the CI tests) - Make sure test cases passed after the change (one way is to leverage https://travis-ci.org/ to run the CI tests)

View File

@ -1,4 +1,4 @@
Copyright 2015 SmartBear Software Copyright 2016 SmartBear Software
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.

271
README.md
View File

@ -1,14 +1,15 @@
# Swagger Code Generator # Swagger Code Generator
[![Build Status](https://travis-ci.org/swagger-api/swagger-codegen.png)](https://travis-ci.org/swagger-api/swagger-codegen) [![Build Status](https://travis-ci.org/swagger-api/swagger-codegen.svg)](https://travis-ci.org/swagger-api/swagger-codegen)
[![Maven Central](https://maven-badges.herokuapp.com/maven-central/io.swagger/swagger-codegen-project/badge.svg?style=plastic)](https://maven-badges.herokuapp.com/maven-central/io.swagger/swagger-codegen-project) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/io.swagger/swagger-codegen-project/badge.svg?style=plastic)](https://maven-badges.herokuapp.com/maven-central/io.swagger/swagger-codegen-project)
[![PR Stats](http://issuestats.com/github/swagger-api/swagger-codegen/badge/pr)](http://issuestats.com/github/swagger-api/swagger-codegen) [![Issue Stats](http://issuestats.com/github/swagger-api/swagger-codegen/badge/issue)](http://issuestats.com/github/swagger-api/swagger-codegen)
:star::star::star: If you would like to contribute, please refer to [guidelines](https://github.com/swagger-api/swagger-codegen/blob/master/CONTRIBUTING.md) and a list of [open tasks](https://github.com/swagger-api/swagger-codegen/issues?q=is%3Aopen+is%3Aissue+label%3A%22Need+community+contribution%22).:star::star::star: :star::star::star: If you would like to contribute, please refer to [guidelines](https://github.com/swagger-api/swagger-codegen/blob/master/CONTRIBUTING.md) and a list of [open tasks](https://github.com/swagger-api/swagger-codegen/issues?q=is%3Aopen+is%3Aissue+label%3A%22Need+community+contribution%22).:star::star::star:
## Overview ## Overview
This is the swagger codegen project, which allows generation of client libraries automatically from a Swagger-compliant server. This is the swagger codegen project, which allows generation of client libraries automatically from a Swagger-compliant server.
Check out [Swagger-Spec](https://github.com/swagger-api/swagger-spec) for additional information about the Swagger project, including additional libraries with support for other languages and more. Check out [Swagger-Spec](https://github.com/OAI/OpenAPI-Specification) for additional information about the Swagger project, including additional libraries with support for other languages and more.
# Table of contents # Table of contents
@ -22,7 +23,8 @@ Check out [Swagger-Spec](https://github.com/swagger-api/swagger-spec) for additi
- [Building](#building) - [Building](#building)
- [Docker](#docker) - [Docker](#docker)
- [Build and run](#build-and-run-using-docker) - [Build and run](#build-and-run-using-docker)
- [Build a Node.js server stub](#build-a-nodejs-server-stub) - [Run docker in Vagrant](#run-docker-in-vagrant)
- [Public Docker image](#public-docker-image)
- [Homebrew](#homebrew) - [Homebrew](#homebrew)
- Generators - Generators
- [To generate a sample client library](#to-generate-a-sample-client-library) - [To generate a sample client library](#to-generate-a-sample-client-library)
@ -32,47 +34,66 @@ Check out [Swagger-Spec](https://github.com/swagger-api/swagger-spec) for additi
- [Where is Javascript???](#where-is-javascript) - [Where is Javascript???](#where-is-javascript)
- [Generating a client from local files](#generating-a-client-from-local-files) - [Generating a client from local files](#generating-a-client-from-local-files)
- [Customizing the generator](#customizing-the-generator) - [Customizing the generator](#customizing-the-generator)
- [Validating your swagger spec](#validating-your-swagger-spec) - [Validating your OpenAPI Spec](#validating-your-openapi-spec)
- [Generating dynamic html api documentation](#generating-dynamic-html-api-documentation) - [Generating dynamic html api documentation](#generating-dynamic-html-api-documentation)
- [Generating static html api documentation](#generating-static-html-api-documentation) - [Generating static html api documentation](#generating-static-html-api-documentation)
- [To build a server stub](#to-build-a-server-stub) - [To build a server stub](#to-build-a-server-stub)
- [Node.js](#nodejs) - [Node.js](#nodejs)
- [PHP Slim](#php-slim)
- [PHP Silex](#php-silex) - [PHP Silex](#php-silex)
- [Python Flask (Connexion)](#python-flask-connexion) - [Python Flask (Connexion)](#python-flask-connexion)
- [Ruby Sinatra](#ruby-sinatra) - [Ruby Sinatra](#ruby-sinatra)
- [Scala Scalatra](#scala-scalatra) - [Scala Scalatra](#scala-scalatra)
- [Java JAX-RS](#java-jax-rs) - [Java JAX-RS (Java JAX-RS (Jersey v1.18)](#java-jax-rs-jersey-v118)
- [Java JAX-RS (Apache CXF 3)](#java-jax-rs-apache-cxf-3)
- [Java Spring MVC](#java-spring-mvc) - [Java Spring MVC](#java-spring-mvc)
- [Haskell Servant](#haskell-servant)
- [ASP.NET 5 Web API](#aspnet-5-web-api)
- [To build the codegen library](#to-build-the-codegen-library) - [To build the codegen library](#to-build-the-codegen-library)
- [Workflow Integration](#workflow-integration)
- [Online Generators](#online-generators) - [Online Generators](#online-generators)
- [Guidelines for Contribution](https://github.com/swagger-api/swagger-codegen/wiki/Guidelines-for-Contribution) - [Guidelines for Contribution](https://github.com/swagger-api/swagger-codegen/wiki/Guidelines-for-Contribution)
- [Companies/Projects using Swagger Codegen](#companiesprojects-using-swagger-codegen)
- [License](#license) - [License](#license)
## Compatibility ## Compatibility
The Swagger Specification has undergone 3 revisions since initial creation in 2010. The swagger-codegen project has the following compatibilies with the swagger specification: The OpenAPI Specification has undergone 3 revisions since initial creation in 2010. The swagger-codegen project has the following compatibilies with the OpenAPI Specification:
Swagger Codegen Version | Release Date | Swagger Spec compatibility | Notes Swagger Codegen Version | Release Date | OpenAPI Spec compatibility | Notes
-------------------------- | ------------ | -------------------------- | ----- -------------------------- | ------------ | -------------------------- | -----
2.1.5-SNAPSHOT | | 1.0, 1.1, 1.2, 2.0 | [master](https://github.com/swagger-api/swagger-codegen) 2.1.6-SNAPSHOT | | 1.0, 1.1, 1.2, 2.0 | [master](https://github.com/swagger-api/swagger-codegen)
2.1.4 (**current stable**) | 2015-10-25 | 1.0, 1.1, 1.2, 2.0 | [tag v2.1.4](https://github.com/swagger-api/swagger-codegen/tree/v2.1.4) 2.1.5 (**current stable**) | 2015-01-06 | 1.0, 1.1, 1.2, 2.0 | [tag v2.1.5](https://github.com/swagger-api/swagger-codegen/tree/v2.1.5)
2.0.17 | 2014-08-22 | 1.1, 1.2 | [tag v2.0.17](https://github.com/swagger-api/swagger-codegen/tree/v2.0.17) 2.0.17 | 2014-08-22 | 1.1, 1.2 | [tag v2.0.17](https://github.com/swagger-api/swagger-codegen/tree/v2.0.17)
1.0.4 | 2012-04-12 | 1.0, 1.1 | [tag v1.0.4](https://github.com/swagger-api/swagger-codegen/tree/swagger-codegen_2.9.1-1.1) 1.0.4 | 2012-04-12 | 1.0, 1.1 | [tag v1.0.4](https://github.com/swagger-api/swagger-codegen/tree/swagger-codegen_2.9.1-1.1)
### Prerequisites ### Prerequisites
You need the following installed and available in your $PATH: If you're looking for the latest stable version, you can grab it directly from maven central (you'll need java 7 runtime at a minimum):
* [Java 7](http://java.oracle.com) ```
wget http://repo1.maven.org/maven2/io/swagger/swagger-codegen-cli/2.1.5/swagger-codegen-cli-2.1.5.jar -o swagger-codegen-cli.jar
java -jar swagger-codegen-cli.jar help
```
On a mac, it's even easier with `brew`:
```
brew install swagger-codegen
```
To build from source, you need the following installed and available in your $PATH:
* [Java 7 or 8](http://java.oracle.com)
* [Apache maven 3.0.3 or greater](http://maven.apache.org/) * [Apache maven 3.0.3 or greater](http://maven.apache.org/)
#### OS X Users #### OS X Users
Don't forget to install Java 7. You probably have 1.6 or 1.8. Don't forget to install Java 7 or 8. You probably have 1.6.
Export JAVA_HOME in order to use the supported Java version: Export JAVA_HOME in order to use the supported Java version:
``` ```
export JAVA_HOME=`/usr/libexec/java_home -v 1.7` export JAVA_HOME=`/usr/libexec/java_home -v 1.8`
export PATH=${JAVA_HOME}/bin:$PATH export PATH=${JAVA_HOME}/bin:$PATH
``` ```
@ -88,21 +109,27 @@ mvn package
``` ```
git clone https://github.com/swagger-api/swagger-codegen git clone https://github.com/swagger-api/swagger-codegen
cd swagger-codegen cd swagger-codegen
./run-in-docker.sh mvn package ./run-in-docker.sh mvn package
``` ```
#### Build a Node.js server stub
#### Run Docker in Vagrant
Prerequisite: install [Vagrant](https://www.vagrantup.com/downloads.html) and [VirtualBox](https://www.virtualbox.org/wiki/Downloads).
``` ```
./run-in-docker.sh generate \ git clone http://github.com/swagger-api/swagger-codegen.git
-i http://petstore.swagger.io/v2/swagger.json \ cd swagger-codegen
-l nodejs \ vagrant up
-o samples/server/petstore/nodejs vagrant ssh
cd /vagrant
./run-in-docker.sh mvn package
``` ```
#### Public Docker image
https://hub.docker.com/r/swaggerapi/swagger-generator/
### Homebrew ### Homebrew
To install, run `brew install swagger-codegen` To install, run `brew install swagger-codegen`
@ -134,18 +161,27 @@ with a number of options. You can get the options with the `help generate` comm
``` ```
NAME NAME
swagger generate - Generate code with chosen lang swagger-codegen-cli generate - Generate code with chosen lang
SYNOPSIS SYNOPSIS
swagger generate [(-a <authorization> | --auth <authorization>)] swagger-codegen-cli generate
[(-a <authorization> | --auth <authorization>)]
[--additional-properties <additional properties>]
[--api-package <api package>] [--artifact-id <artifact id>]
[--artifact-version <artifact version>]
[(-c <configuration file> | --config <configuration file>)] [(-c <configuration file> | --config <configuration file>)]
[-D <system properties>] [-D <system properties>] [--group-id <group id>]
(-i <spec file> | --input-spec <spec file>) (-i <spec file> | --input-spec <spec file>)
[--import-mappings <import mappings>]
[--instantiation-types <instantiation types>]
[--invoker-package <invoker package>]
(-l <language> | --lang <language>) (-l <language> | --lang <language>)
[--language-specific-primitives <language specific primitives>]
[--library <library>] [--model-package <model package>]
[(-o <output directory> | --output <output directory>)] [(-o <output directory> | --output <output directory>)]
[(-t <template directory> | --template-dir <template directory>)]
[(-v | --verbose)]
[(-s | --skip-overwrite)] [(-s | --skip-overwrite)]
[(-t <template directory> | --template-dir <template directory>)]
[--type-mappings <type mappings>] [(-v | --verbose)]
OPTIONS OPTIONS
-a <authorization>, --auth <authorization> -a <authorization>, --auth <authorization>
@ -153,6 +189,19 @@ OPTIONS
remotely. Pass in a URL-encoded string of name:header with a comma remotely. Pass in a URL-encoded string of name:header with a comma
separating multiple values separating multiple values
--additional-properties <additional properties>
sets additional properties that can be referenced by the mustache
templates in the format of name=value,name=value
--api-package <api package>
package for generated api classes
--artifact-id <artifact id>
artifactId in generated pom.xml
--artifact-version <artifact version>
artifact version in generated pom.xml
-c <configuration file>, --config <configuration file> -c <configuration file>, --config <configuration file>
Path to json configuration file. File content should be in a json Path to json configuration file. File content should be in a json
format {"optionKey":"optionValue", "optionKey1":"optionValue1"...} format {"optionKey":"optionValue", "optionKey1":"optionValue1"...}
@ -163,25 +212,59 @@ OPTIONS
sets specified system properties in the format of sets specified system properties in the format of
name=value,name=value name=value,name=value
--group-id <group id>
groupId in generated pom.xml
-i <spec file>, --input-spec <spec file> -i <spec file>, --input-spec <spec file>
location of the swagger spec, as URL or file (required) location of the swagger spec, as URL or file (required)
--import-mappings <import mappings>
specifies mappings between a given class and the import that should
be used for that class in the format of type=import,type=import
--instantiation-types <instantiation types>
sets instantiation type mappings in the format of
type=instantiatedType,type=instantiatedType.For example (in Java):
array=ArrayList,map=HashMap. In other words array types will get
instantiated as ArrayList in generated code.
--invoker-package <invoker package>
root package for generated code
-l <language>, --lang <language> -l <language>, --lang <language>
client language to generate (maybe class name in classpath, client language to generate (maybe class name in classpath,
required) required)
--language-specific-primitives <language specific primitives>
specifies additional language specific primitive types in the format
of type1,type2,type3,type3. For example:
String,boolean,Boolean,Double
--library <library>
library template (sub-template)
--model-package <model package>
package for generated models
-o <output directory>, --output <output directory> -o <output directory>, --output <output directory>
where to write the generated files (current dir by default) where to write the generated files (current dir by default)
-s, --skip-overwrite
specifies if the existing files should be overwritten during the
generation.
-t <template directory>, --template-dir <template directory> -t <template directory>, --template-dir <template directory>
folder containing the template files folder containing the template files
--type-mappings <type mappings>
sets mappings between swagger spec types and generated code types in
the format of swaggerType=generatedType,swaggerType=generatedType.
For example: array=List,map=Map,string=String
-v, --verbose -v, --verbose
verbose mode verbose mode
-s , --skip-overwrite
specifies if the existing files should be overwritten during
the generation
``` ```
You can then compile and run the client, as well as unit tests against it: You can then compile and run the client, as well as unit tests against it:
@ -218,16 +301,15 @@ This will write, in the folder `output/myLibrary`, all the files you need to get
You would then compile your library in the `output/myLibrary` folder with `mvn package` and execute the codegen like such: You would then compile your library in the `output/myLibrary` folder with `mvn package` and execute the codegen like such:
``` ```
java -cp output/myLibrary/target/myClientCodegen-swagger-codegen-1.0.0.jar:modules/swagger-codegen-cli/target/swagger-codegen-cli.jar io.swagger.codegen.Codegen java -cp output/myLibrary/target/myClientCodegen-swagger-codegen-1.0.0.jar:modules/swagger-codegen-cli/target/swagger-codegen-cli.jar io.swagger.codegen.SwaggerCodegen
``` ```
Note the `myClientCodegen` is an option now, and you can use the usual arguments for generating your library: Note the `myClientCodegen` is an option now, and you can use the usual arguments for generating your library:
``` ```
java -cp output/myLibrary/target/myClientCodegen-swagger-codegen-1.0.0.jar:modules/swagger-codegen-cli/target/swagger-codegen-cli.jar \ java -cp output/myLibrary/target/myClientCodegen-swagger-codegen-1.0.0.jar:modules/swagger-codegen-cli/target/swagger-codegen-cli.jar \
io.swagger.codegen.Codegen generate -l myClientCodegen\ io.swagger.codegen.SwaggerCodegen generate -l myClientCodegen\
-i http://petstore.swagger.io/v2/swagger.json \ -i http://petstore.swagger.io/v2/swagger.json \
-o myClient -o myClient
``` ```
@ -235,12 +317,12 @@ java -cp output/myLibrary/target/myClientCodegen-swagger-codegen-1.0.0.jar:modul
### Where is Javascript??? ### Where is Javascript???
See our [javascript library](http://github.com/swagger-api/swagger-js)--it's completely dynamic and doesn't require See our [javascript library](http://github.com/swagger-api/swagger-js)--it's completely dynamic and doesn't require
static code generation. static code generation.
There is a third-party component called [swagger-js-codegen](https://github.com/wcandillon/swagger-js-codegen) that can generate angularjs or nodejs source code from a swagger specification. There is a third-party component called [swagger-js-codegen](https://github.com/wcandillon/swagger-js-codegen) that can generate angularjs or nodejs source code from a OpenAPI Specification.
:exclamation: On Dec 7th 2015, a Javascript API client generator has been added by @jfiala. :exclamation: On Dec 7th 2015, a Javascript API client generator has been added by @jfiala.
### Generating a client from local files ### Generating a client from local files
If you don't want to call your server, you can save the swagger spec files into a directory and pass an argument If you don't want to call your server, you can save the OpenAPI Spec files into a directory and pass an argument
to the code generator like this: to the code generator like this:
``` ```
@ -285,9 +367,11 @@ There are different aspects of customizing the code generator beyond just creati
``` ```
$ ls -1 modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/ $ ls -1 modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/
AbstractJavaJAXRSServerCodegen.java
AbstractTypeScriptClientCodegen.java AbstractTypeScriptClientCodegen.java
AkkaScalaClientCodegen.java AkkaScalaClientCodegen.java
AndroidClientCodegen.java AndroidClientCodegen.java
AspNet5ServerCodegen.java
AsyncScalaClientCodegen.java AsyncScalaClientCodegen.java
CSharpClientCodegen.java CSharpClientCodegen.java
ClojureClientCodegen.java ClojureClientCodegen.java
@ -295,11 +379,14 @@ CsharpDotNet2ClientCodegen.java
DartClientCodegen.java DartClientCodegen.java
FlashClientCodegen.java FlashClientCodegen.java
FlaskConnexionCodegen.java FlaskConnexionCodegen.java
GoClientCodegen.java
HaskellServantCodegen.java
JMeterCodegen.java
JavaCXFServerCodegen.java
JavaClientCodegen.java JavaClientCodegen.java
JavaInflectorServerCodegen.java JavaInflectorServerCodegen.java
JavaJerseyServerCodegen.java
JavascriptClientCodegen.java JavascriptClientCodegen.java
JaxRSServerCodegen.java
JMeterCodegen.java
NodeJSServerCodegen.java NodeJSServerCodegen.java
ObjcClientCodegen.java ObjcClientCodegen.java
PerlClientCodegen.java PerlClientCodegen.java
@ -332,7 +419,7 @@ java -jar modules/swagger-codegen-cli/target/swagger-codegen-cli.jar generate \
-o samples/client/petstore/java \ -o samples/client/petstore/java \
-c path/to/config.json -c path/to/config.json
``` ```
Supported config options can be different per language. Running `config-help -l {lang}` will show available options. **These options are applied Supported config options can be different per language. Running `config-help -l {lang}` will show available options. **These options are applied
by passing them with `-D{optionName}={optionValue}**. by passing them with `-D{optionName}={optionValue}**.
``` ```
@ -383,12 +470,12 @@ CONFIG OPTIONS
retrofit2 - HTTP client: OkHttp 2.5.0. JSON processing: Gson 2.4 (Retrofit 2.0.0-beta2) retrofit2 - HTTP client: OkHttp 2.5.0. JSON processing: Gson 2.4 (Retrofit 2.0.0-beta2)
``` ```
Your config file for java can look like Your config file for Java can look like
``` ```json
{ {
"groupId":"com.my.company", "groupId":"com.my.company",
"artifactId":"MyClent", "artifactId":"MyClient",
"artifactVersion":"1.2.0", "artifactVersion":"1.2.0",
"library":"feign" "library":"feign"
} }
@ -399,15 +486,15 @@ For all the unspecified options default values will be used.
Another way to override default options is to extend the config class for the specific language. Another way to override default options is to extend the config class for the specific language.
To change, for example, the prefix for the Objective-C generated files, simply subclass the ObjcClientCodegen.java: To change, for example, the prefix for the Objective-C generated files, simply subclass the ObjcClientCodegen.java:
``` ```java
package com.mycompany.swagger.codegen; package com.mycompany.swagger.codegen;
import io.swagger.codegen.languages.*; import io.swagger.codegen.languages.*;
public class MyObjcCodegen extends ObjcClientCodegen { public class MyObjcCodegen extends ObjcClientCodegen {
static { static {
PREFIX = "HELO"; PREFIX = "HELO";
} }
} }
``` ```
@ -419,7 +506,25 @@ and specify the `classname` when running the generator:
Your subclass will now be loaded and overrides the `PREFIX` value in the superclass. Your subclass will now be loaded and overrides the `PREFIX` value in the superclass.
### Validating your swagger spec ### Bringing your own models
Sometimes you don't want a model generated. In this case, you can simply specify an import mapping to tell
the codegen what _not_ to create. When doing this, every location that references a specific model will
refer back to your classes. Note, this may not apply to all languages...
To specify an import mapping, use the `--import-mappings` argument and specify the model-to-import logic as such:
```
--import-mappings Pet=my.models.MyPet
```
Or for multiple mappings:
```
Pet=my.models.MyPet,Order=my.models.MyOrder
```
### Validating your OpenAPI Spec
You have options. The easiest is to use our [online validator](https://github.com/swagger-api/validator-badge) which not only will let you validate your spec, but with the debug flag, you can see what's wrong with your spec. For example: You have options. The easiest is to use our [online validator](https://github.com/swagger-api/validator-badge) which not only will let you validate your spec, but with the debug flag, you can see what's wrong with your spec. For example:
@ -461,6 +566,15 @@ java -jar modules/swagger-codegen-cli/target/swagger-codegen-cli.jar generate \
-o samples/server/petstore/nodejs -o samples/server/petstore/nodejs
``` ```
### PHP Slim
```
java -jar modules/swagger-codegen-cli/target/swagger-codegen-cli.jar generate \
-i http://petstore.swagger.io/v2/swagger.json \
-l slim \
-o samples/server/petstore/slim
```
### PHP Silex ### PHP Silex
``` ```
@ -475,7 +589,7 @@ java -jar modules/swagger-codegen-cli/target/swagger-codegen-cli.jar generate \
``` ```
java -jar modules/swagger-codegen-cli/target/swagger-codegen-cli.jar generate \ java -jar modules/swagger-codegen-cli/target/swagger-codegen-cli.jar generate \
-i http://petstore.swagger.io/v2/swagger.json \ -i http://petstore.swagger.io/v2/swagger.json \
-l flaskConnexion \ -l python-flask \
-o samples/server/petstore/flaskConnexion -o samples/server/petstore/flaskConnexion
``` ```
@ -496,13 +610,22 @@ java -jar modules/swagger-codegen-cli/target/swagger-codegen-cli.jar generate \
-o samples/server/petstore/scalatra -o samples/server/petstore/scalatra
``` ```
### Java JAX-RS ### Java JAX-RS (Jersey v1.18)
``` ```
java -jar modules/swagger-codegen-cli/target/swagger-codegen-cli.jar generate \ java -jar modules/swagger-codegen-cli/target/swagger-codegen-cli.jar generate \
-i http://petstore.swagger.io/v2/swagger.json \ -i http://petstore.swagger.io/v2/swagger.json \
-l jaxrs \ -l jaxrs \
-o samples/server/petstore/jaxrs -o samples/server/petstore/jaxrs-jersey
```
### Java JAX-RS (Apache CXF 3)
```
java -jar modules/swagger-codegen-cli/target/swagger-codegen-cli.jar generate \
-i http://petstore.swagger.io/v2/swagger.json \
-l jaxrs-cxf \
-o samples/server/petstore/jaxrs-cxf
``` ```
### Java Spring MVC ### Java Spring MVC
@ -514,9 +637,27 @@ java -jar modules/swagger-codegen-cli/target/swagger-codegen-cli.jar generate \
-o samples/server/petstore/spring-mvc -o samples/server/petstore/spring-mvc
``` ```
### Haskell Servant
```
java -jar modules/swagger-codegen-cli/target/swagger-codegen-cli.jar generate \
-i http://petstore.swagger.io/v2/swagger.json \
-l haskell-servant \
-o samples/server/petstore/haskell-servant
```
### ASP.NET 5 Web API
```
java -jar modules/swagger-codegen-cli/target/swagger-codegen-cli.jar generate \
-i http://petstore.swagger.io/v2/swagger.json \
-l aspnet5 \
-o samples/server/petstore/aspnet5
```
### To build the codegen library ### To build the codegen library
This will create the swagger-codegen library from source. This will create the swagger-codegen library from source.
``` ```
mvn package mvn package
@ -524,6 +665,11 @@ mvn package
Note! The templates are included in the library generated. If you want to modify the templates, you'll need to either repackage the library OR specify a path to your scripts Note! The templates are included in the library generated. If you want to modify the templates, you'll need to either repackage the library OR specify a path to your scripts
## Workflow integration
You can use the [swagger-codegen-maven-plugin](modules/swagger-codegen-maven-plugin/README.md) for integrating with your workflow, and generating any codegen target.
## Online generators ## Online generators
One can also generate API client or server using the online generators (https://generator.swagger.io) One can also generate API client or server using the online generators (https://generator.swagger.io)
@ -539,10 +685,32 @@ Guidelines for Contribution
Please refer to this [page](https://github.com/swagger-api/swagger-codegen/blob/master/CONTRIBUTING.md) Please refer to this [page](https://github.com/swagger-api/swagger-codegen/blob/master/CONTRIBUTING.md)
Companies/Projects using Swagger Codegen
----------------------------------------
Here are some companies/projects using Swagger Codegen in production. To add your company/project to the list, please visit [README.md](https://github.com/swagger-api/swagger-codegen/blob/master/README.md) and click on the icon to edit the page.
- [Activehours](https://www.activehours.com/)
- [Acunetix](https://www.acunetix.com/)
- [Atlassian](https://www.atlassian.com/)
- [Cupix](http://www.cupix.com)
- [DocuSign](https://www.docusign.com)
- [Ergon](http://www.ergon.ch/)
- [everystory.us](http://everystory.us)
- [Expected Behavior](http://www.expectedbehavior.com/)
- [nViso](http://www.nviso.ch/)
- [Okiok](https://www.okiok.com)
- [OSDN](https://osdn.jp)
- [Reload! A/S](https://reload.dk/)
- [Royal Bank of Canada (RBC)](http://www.rbc.com/canada.html)
- [SmartRecruiters](https://www.smartrecruiters.com/)
- [StyleRecipe](http://stylerecipe.co.jp)
- [ThoughtWorks](https://www.thoughtworks.com)
- [uShip](https://www.uship.com/)
- [ZEEF.com](https://zeef.com/)
License License
------- -------
Copyright 2015 SmartBear Software Copyright 2016 SmartBear Software
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -553,3 +721,6 @@ distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
---
<img src="http://swagger.io/wp-content/uploads/2016/02/logo.jpg"/>

36
Vagrantfile vendored Normal file
View File

@ -0,0 +1,36 @@
# -*- mode: ruby -*-
# vi: set ft=ruby :
# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
VAGRANTFILE_API_VERSION = "2"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.box = "ubuntu/trusty64"
config.vm.provider "virtualbox" do |v|
v.name = "swagger-codegen"
v.memory = 2048
v.cpus = 2
end
config.vm.box_check_update = true
#SSH
config.ssh.forward_agent = true
config.ssh.shell = "bash -c 'BASH_ENV=/etc/profile exec bash'"
#Provision
config.vm.provision "shell", inline: <<-SHELL
sudo touch /var/lib/cloud/instance/locale-check.skip
sudo apt-key adv --keyserver hkp://pgp.mit.edu:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D
sudo sh -c 'echo "deb https://apt.dockerproject.org/repo ubuntu-trusty main" > /etc/apt/sources.list.d/docker.list'
sudo apt-cache policy docker-engine
sudo apt-get update
sudo apt-get upgrade -y
sudo apt-get install -y docker-engine
sudo usermod -aG docker vagrant
SHELL
end

View File

@ -19,10 +19,11 @@ fi
cd $APP_DIR cd $APP_DIR
./bin/akka-scala-petstore.sh ./bin/akka-scala-petstore.sh
./bin/android-java-petstore.sh ./bin/android-petstore.sh
./bin/clojure-petstore.sh ./bin/clojure-petstore.sh
./bin/csharp-petstore.sh ./bin/csharp-petstore.sh
./bin/dynamic-html.sh ./bin/dynamic-html.sh
./bin/haskell-petstore.sh
./bin/html-petstore.sh ./bin/html-petstore.sh
./bin/java-petstore.sh ./bin/java-petstore.sh
./bin/java-petstore-jersey2.sh ./bin/java-petstore-jersey2.sh
@ -43,6 +44,7 @@ cd $APP_DIR
./bin/silex-petstore-server.sh ./bin/silex-petstore-server.sh
./bin/slim-petstore-server.sh ./bin/slim-petstore-server.sh
./bin/spring-mvc-petstore-server.sh ./bin/spring-mvc-petstore-server.sh
./bin/spring-mvc-petstore-j8-async-server.sh
./bin/swift-petstore.sh ./bin/swift-petstore.sh
./bin/tizen-petstore.sh ./bin/tizen-petstore.sh
./bin/typescript-angular-petstore.sh ./bin/typescript-angular-petstore.sh

View File

@ -0,0 +1,4 @@
{
"library": "volley",
"artifactId": "swagger-petstore-android-volley"
}

31
bin/android-petstore-volley.sh Executable file
View File

@ -0,0 +1,31 @@
#!/bin/sh
SCRIPT="$0"
while [ -h "$SCRIPT" ] ; do
ls=`ls -ld "$SCRIPT"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
SCRIPT="$link"
else
SCRIPT=`dirname "$SCRIPT"`/"$link"
fi
done
if [ ! -d "${APP_DIR}" ]; then
APP_DIR=`dirname "$SCRIPT"`/..
APP_DIR=`cd "${APP_DIR}"; pwd`
fi
executable="./modules/swagger-codegen-cli/target/swagger-codegen-cli.jar"
if [ ! -f "$executable" ]
then
mvn clean package
fi
# if you've executed sbt assembly previously it will use that instead.
export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties"
ags="$@ generate -i modules/swagger-codegen/src/test/resources/2_0/petstore.json -l android -c bin/android-petstore-volley.json -o samples/client/petstore/android/volley"
java $JAVA_OPTS -jar $executable $ags

View File

@ -26,6 +26,6 @@ fi
# if you've executed sbt assembly previously it will use that instead. # if you've executed sbt assembly previously it will use that instead.
export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties" export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties"
ags="$@ generate -t modules/swagger-codegen/src/main/resources/android-java -i modules/swagger-codegen/src/test/resources/2_0/petstore.json -l android -o samples/client/petstore/android-java" ags="$@ generate -t modules/swagger-codegen/src/main/resources/android -i modules/swagger-codegen/src/test/resources/2_0/petstore.json -l android -o samples/client/petstore/android/default"
java $JAVA_OPTS -jar $executable $ags java $JAVA_OPTS -jar $executable $ags

31
bin/aspnet5-petstore-server.sh Executable file
View File

@ -0,0 +1,31 @@
#!/usr/bin/env bash
SCRIPT="$0"
while [ -h "$SCRIPT" ] ; do
ls=`ls -ld "$SCRIPT"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
SCRIPT="$link"
else
SCRIPT=`dirname "$SCRIPT"`/"$link"
fi
done
if [ ! -d "${APP_DIR}" ]; then
APP_DIR=`dirname "$SCRIPT"`/..
APP_DIR=`cd "${APP_DIR}"; pwd`
fi
executable="./modules/swagger-codegen-cli/target/swagger-codegen-cli.jar"
if [ ! -f "$executable" ]
then
mvn clean package
fi
# if you've executed sbt assembly previously it will use that instead.
export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties"
ags="$@ generate -l aspnet5 -i modules/swagger-codegen/src/test/resources/2_0/petstore.json -o samples/server/petstore/aspnet5"
java $JAVA_OPTS -jar $executable $ags

31
bin/go-petstore.sh Executable file
View File

@ -0,0 +1,31 @@
#!/bin/sh
SCRIPT="$0"
while [ -h "$SCRIPT" ] ; do
ls=`ls -ld "$SCRIPT"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
SCRIPT="$link"
else
SCRIPT=`dirname "$SCRIPT"`/"$link"
fi
done
if [ ! -d "${APP_DIR}" ]; then
APP_DIR=`dirname "$SCRIPT"`/..
APP_DIR=`cd "${APP_DIR}"; pwd`
fi
executable="./modules/swagger-codegen-cli/target/swagger-codegen-cli.jar"
if [ ! -f "$executable" ]
then
mvn clean package
fi
# if you've executed sbt assembly previously it will use that instead.
export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties"
ags="$@ generate -t modules/swagger-codegen/src/main/resources/go -i modules/swagger-codegen/src/test/resources/2_0/petstore.json -l go -o samples/client/petstore/go"
java $JAVA_OPTS -jar $executable $ags

31
bin/haskell-servant-petstore.sh Executable file
View File

@ -0,0 +1,31 @@
#!/bin/sh
SCRIPT="$0"
while [ -h "$SCRIPT" ] ; do
ls=`ls -ld "$SCRIPT"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
SCRIPT="$link"
else
SCRIPT=`dirname "$SCRIPT"`/"$link"
fi
done
if [ ! -d "${APP_DIR}" ]; then
APP_DIR=`dirname "$SCRIPT"`/..
APP_DIR=`cd "${APP_DIR}"; pwd`
fi
executable="./modules/swagger-codegen-cli/target/swagger-codegen-cli.jar"
if [ ! -f "$executable" ]
then
mvn clean package
fi
# if you've executed sbt assembly previously it will use that instead.
export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties"
ags="$@ generate -t modules/swagger-codegen/src/main/resources/haskell-servant -i modules/swagger-codegen/src/test/resources/2_0/petstore.json -l haskell-servant -o samples/server/petstore/haskell-servant"
java $JAVA_OPTS -jar $executable $ags

9
bin/java-petstore-all.sh Executable file
View File

@ -0,0 +1,9 @@
#!/bin/sh
# update java petstore for all supported http libraries
./bin/java-petstore.sh
./bin/java-petstore-jersey2.sh
./bin/java-petstore-feign.sh
./bin/java-petstore-okhttp-gson.sh
./bin/java-petstore-retrofit.sh
./bin/java-petstore-retrofit2.sh

View File

@ -0,0 +1,4 @@
{
"library": "retrofit2",
"artifactId": "swagger-petstore-retrofit2-rx"
}

View File

@ -0,0 +1,31 @@
#!/bin/sh
SCRIPT="$0"
while [ -h "$SCRIPT" ] ; do
ls=`ls -ld "$SCRIPT"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
SCRIPT="$link"
else
SCRIPT=`dirname "$SCRIPT"`/"$link"
fi
done
if [ ! -d "${APP_DIR}" ]; then
APP_DIR=`dirname "$SCRIPT"`/..
APP_DIR=`cd "${APP_DIR}"; pwd`
fi
executable="./modules/swagger-codegen-cli/target/swagger-codegen-cli.jar"
if [ ! -f "$executable" ]
then
mvn clean package
fi
# if you've executed sbt assembly previously it will use that instead.
export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties"
ags="$@ generate -i modules/swagger-codegen/src/test/resources/2_0/petstore.json -l java -c bin/java-petstore-retrofit2rx.json -o samples/client/petstore/java/retrofit2rx -DuseRxJava=true"
java $JAVA_OPTS -jar $executable $ags

View File

@ -0,0 +1,31 @@
#!/bin/sh
SCRIPT="$0"
while [ -h "$SCRIPT" ] ; do
ls=`ls -ld "$SCRIPT"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
SCRIPT="$link"
else
SCRIPT=`dirname "$SCRIPT"`/"$link"
fi
done
if [ ! -d "${APP_DIR}" ]; then
APP_DIR=`dirname "$SCRIPT"`/..
APP_DIR=`cd "${APP_DIR}"; pwd`
fi
executable="./modules/swagger-codegen-cli/target/swagger-codegen-cli.jar"
if [ ! -f "$executable" ]
then
mvn clean package
fi
# if you've executed sbt assembly previously it will use that instead.
export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties"
ags="$@ generate -i modules/swagger-codegen/src/test/resources/2_0/petstore.json -l javascript-closure-angular -o samples/client/petstore/javascript-closure-angular"
java $JAVA_OPTS -jar $executable $ags

View File

@ -26,6 +26,6 @@ fi
# if you've executed sbt assembly previously it will use that instead. # if you've executed sbt assembly previously it will use that instead.
export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties" export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties"
ags="$@ generate -t modules/swagger-codegen/src/main/resources/javascript -i modules/swagger-codegen/src/test/resources/2_0/petstore.json -l javascript -o samples/client/petstore/javascript" ags="$@ generate -t modules/swagger-codegen/src/main/resources/Javascript -i modules/swagger-codegen/src/test/resources/2_0/petstore.json -l javascript -o samples/client/petstore/javascript"
java -DappName=PetstoreClient $JAVA_OPTS -jar $executable $ags java -DappName=PetstoreClient $JAVA_OPTS -jar $executable $ags

View File

@ -0,0 +1,34 @@
#!/bin/sh
SCRIPT="$0"
while [ -h "$SCRIPT" ] ; do
ls=`ls -ld "$SCRIPT"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
SCRIPT="$link"
else
SCRIPT=`dirname "$SCRIPT"`/"$link"
fi
done
if [ ! -d "${APP_DIR}" ]; then
APP_DIR=`dirname "$SCRIPT"`/..
APP_DIR=`cd "${APP_DIR}"; pwd`
fi
executable="./modules/swagger-codegen-cli/target/swagger-codegen-cli.jar"
if [ ! -f "$executable" ]
then
mvn clean package
fi
# if you've executed sbt assembly previously it will use that instead.
export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties"
ags="$@ generate -t modules/swagger-codegen/src/main/resources/Javascript \
-i modules/swagger-codegen/src/test/resources/2_0/petstore.json -l javascript \
-o samples/client/petstore/javascript-promise \
--additional-properties usePromises=true"
java -DappName=PetstoreClient $JAVA_OPTS -jar $executable $ags

View File

@ -0,0 +1,31 @@
#!/bin/sh
SCRIPT="$0"
while [ -h "$SCRIPT" ] ; do
ls=`ls -ld "$SCRIPT"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
SCRIPT="$link"
else
SCRIPT=`dirname "$SCRIPT"`/"$link"
fi
done
if [ ! -d "${APP_DIR}" ]; then
APP_DIR=`dirname "$SCRIPT"`/..
APP_DIR=`cd "${APP_DIR}"; pwd`
fi
executable="./modules/swagger-codegen-cli/target/swagger-codegen-cli.jar"
if [ ! -f "$executable" ]
then
mvn clean package
fi
# if you've executed sbt assembly previously it will use that instead.
export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties"
ags="$@ generate -t modules/swagger-codegen/src/main/resources/JavaJaxRS -i modules/swagger-codegen/src/test/resources/2_0/petstore.json -l jaxrs-cxf -o samples/server/petstore/jaxrs-cxf"
java $JAVA_OPTS -jar $executable $ags

View File

@ -26,6 +26,6 @@ fi
# if you've executed sbt assembly previously it will use that instead. # if you've executed sbt assembly previously it will use that instead.
export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties" export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties"
ags="$@ generate -t modules/swagger-codegen/src/main/resources/JavaJaxRS -i modules/swagger-codegen/src/test/resources/2_0/petstore.json -l jaxrs -o samples/server/petstore/jaxrs -Dswagger.codegen.jaxrs.impl.source=src/main/java" ags="$@ generate -t modules/swagger-codegen/src/main/resources/JavaJaxRS -i modules/swagger-codegen/src/test/resources/2_0/petstore.json -l jaxrs -o samples/server/petstore/jaxrs"
java $JAVA_OPTS -jar $executable $ags java $JAVA_OPTS -jar $executable $ags

View File

@ -0,0 +1,31 @@
#!/bin/sh
SCRIPT="$0"
while [ -h "$SCRIPT" ] ; do
ls=`ls -ld "$SCRIPT"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
SCRIPT="$link"
else
SCRIPT=`dirname "$SCRIPT"`/"$link"
fi
done
if [ ! -d "${APP_DIR}" ]; then
APP_DIR=`dirname "$SCRIPT"`/..
APP_DIR=`cd "${APP_DIR}"; pwd`
fi
executable="./modules/swagger-codegen-cli/target/swagger-codegen-cli.jar"
if [ ! -f "$executable" ]
then
mvn clean package
fi
# if you've executed sbt assembly previously it will use that instead.
export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties"
ags="$@ generate -t modules/swagger-codegen/src/main/resources/JavaJaxRS -i modules/swagger-codegen/src/test/resources/2_0/petstore.json -l jaxrs-resteasy -o samples/server/petstore/jaxrs-resteasy"
java $JAVA_OPTS -jar $executable $ags

View File

@ -26,6 +26,9 @@ fi
# if you've executed sbt assembly previously it will use that instead. # if you've executed sbt assembly previously it will use that instead.
export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties" export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties"
# complex module name used for testing
ags="$@ generate -i modules/swagger-codegen/src/test/resources/2_0/petstore.json -l perl -o samples/client/petstore/perl" ags="$@ generate -i modules/swagger-codegen/src/test/resources/2_0/petstore.json -l perl -o samples/client/petstore/perl"
java $JAVA_OPTS -jar $executable $ags java $JAVA_OPTS -jar $executable $ags
java $JAVA_OPTS -jar $executable $ags --additional-properties moduleName=Something::Deep -o samples/client/petstore/perl/deep_module_test

View File

@ -26,6 +26,6 @@ fi
# if you've executed sbt assembly previously it will use that instead. # if you've executed sbt assembly previously it will use that instead.
export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties" export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties"
ags="$@ generate -t modules/swagger-codegen/src/main/resources/silex -i modules/swagger-codegen/src/test/resources/2_0/petstore.json -l silex -o samples/server/petstore/silex" ags="$@ generate -t modules/swagger-codegen/src/main/resources/silex -i modules/swagger-codegen/src/test/resources/2_0/petstore.json -l silex-PHP -o samples/server/petstore/silex"
java $JAVA_OPTS -jar $executable $ags java $JAVA_OPTS -jar $executable $ags

0
bin/slim-petstore-server.sh Normal file → Executable file
View File

View File

@ -0,0 +1,31 @@
#!/bin/sh
SCRIPT="$0"
while [ -h "$SCRIPT" ] ; do
ls=`ls -ld "$SCRIPT"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
SCRIPT="$link"
else
SCRIPT=`dirname "$SCRIPT"`/"$link"
fi
done
if [ ! -d "${APP_DIR}" ]; then
APP_DIR=`dirname "$SCRIPT"`/..
APP_DIR=`cd "${APP_DIR}"; pwd`
fi
executable="./modules/swagger-codegen-cli/target/swagger-codegen-cli.jar"
if [ ! -f "$executable" ]
then
mvn clean package
fi
# if you've executed sbt assembly previously it will use that instead.
export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties"
ags="$@ generate -t modules/swagger-codegen/src/main/resources/JavaSpringMVC -i modules/swagger-codegen/src/test/resources/2_0/petstore.json -l spring-mvc -o samples/server/petstore/spring-mvc-j8-async -c bin/spring-mvc-petstore-j8-async.json"
java $JAVA_OPTS -jar $executable $ags

View File

@ -0,0 +1,3 @@
{
"library": "j8-async"
}

View File

@ -5,6 +5,6 @@ If Not Exist %executable% (
) )
set JAVA_OPTS=%JAVA_OPTS% -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties set JAVA_OPTS=%JAVA_OPTS% -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties
set ags=generate -t modules\swagger-codegen\src\main\resources\android-java -i modules\swagger-codegen\src\test\resources\2_0\petstore.json -l android -o samples\client\petstore\android-java set ags=generate -t modules\swagger-codegen\src\main\resources\android -i modules\swagger-codegen\src\test\resources\2_0\petstore.json -l android -o samples\client\petstore\android\default
java %JAVA_OPTS% -jar %executable% %ags% java %JAVA_OPTS% -jar %executable% %ags%

View File

@ -0,0 +1,10 @@
set executable=.\modules\swagger-codegen-cli\target\swagger-codegen-cli.jar
If Not Exist %executable% (
mvn clean package
)
set JAVA_OPTS=%JAVA_OPTS% -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties
set ags=generate -t modules\swagger-codegen\src\main\resources\aspnet5 -i modules\swagger-codegen\src\test\resources\2_0\petstore.json -l aspnet5 -o samples\server\petstore\aspnet5\
java %JAVA_OPTS% -jar %executable% %ags%

10
bin/windows/go-petstore.bat Executable file
View File

@ -0,0 +1,10 @@
set executable=.\modules\swagger-codegen-cli\target\swagger-codegen-cli.jar
If Not Exist %executable% (
mvn clean package
)
set JAVA_OPTS=%JAVA_OPTS% -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties
set ags=generate -t modules\swagger-codegen\src\main\resources\go -i modules\swagger-codegen\src\test\resources\2_0\petstore.json -l go -o samples\client\petstore\go
java %JAVA_OPTS% -jar %executable% %ags%

View File

@ -1 +0,0 @@
{"library":"feign"}

View File

@ -3,7 +3,7 @@
<parent> <parent>
<groupId>io.swagger</groupId> <groupId>io.swagger</groupId>
<artifactId>swagger-codegen-project</artifactId> <artifactId>swagger-codegen-project</artifactId>
<version>2.1.5-SNAPSHOT</version> <version>2.1.6-SNAPSHOT</version>
<relativePath>../..</relativePath> <relativePath>../..</relativePath>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@ -89,13 +89,13 @@
<dependency> <dependency>
<groupId>org.testng</groupId> <groupId>org.testng</groupId>
<artifactId>testng</artifactId> <artifactId>testng</artifactId>
<version>${testng-version}</version> <!-- <version>${testng-version}</version> -->
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.jmockit</groupId> <groupId>org.jmockit</groupId>
<artifactId>jmockit</artifactId> <artifactId>jmockit</artifactId>
<version>${jmockit-version}</version> <!-- <version>${jmockit-version}</version> -->
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
</dependencies> </dependencies>

View File

@ -21,7 +21,8 @@ public class SwaggerCodegen {
public static void main(String[] args) { public static void main(String[] args) {
Cli.CliBuilder<Runnable> builder = Cli.<Runnable>builder("swagger") @SuppressWarnings("unchecked")
Cli.CliBuilder<Runnable> builder = Cli.<Runnable>builder("swagger-codegen-cli")
.withDescription("Swagger code generator CLI. More info on swagger.io") .withDescription("Swagger code generator CLI. More info on swagger.io")
.withDefaultCommand(Langs.class) .withDefaultCommand(Langs.class)
.withCommands( .withCommands(

View File

@ -5,7 +5,7 @@ import io.airlift.airline.Option;
import io.swagger.codegen.ClientOptInput; import io.swagger.codegen.ClientOptInput;
import io.swagger.codegen.CodegenConstants; import io.swagger.codegen.CodegenConstants;
import io.swagger.codegen.DefaultGenerator; import io.swagger.codegen.DefaultGenerator;
import io.swagger.codegen.cmd.utils.OptionUtils; import io.swagger.codegen.utils.OptionUtils;
import io.swagger.codegen.config.CodegenConfigurator; import io.swagger.codegen.config.CodegenConfigurator;
import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Pair;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -73,6 +73,12 @@ public class Generate implements Runnable {
@Option(name = {"--model-package"}, title = "model package", description = CodegenConstants.MODEL_PACKAGE_DESC) @Option(name = {"--model-package"}, title = "model package", description = CodegenConstants.MODEL_PACKAGE_DESC)
private String modelPackage; private String modelPackage;
@Option(name = {"--model-name-prefix"}, title = "model name prefix", description = CodegenConstants.MODEL_NAME_PREFIX_DESC)
private String modelNamePrefix;
@Option(name = {"--model-name-suffix"}, title = "model name suffix", description = CodegenConstants.MODEL_NAME_SUFFIX_DESC)
private String modelNameSuffix;
@Option(name = {"--instantiation-types"}, title = "instantiation types", description = "sets instantiation type mappings in the format of type=instantiatedType,type=instantiatedType." + @Option(name = {"--instantiation-types"}, title = "instantiation types", description = "sets instantiation type mappings in the format of type=instantiatedType,type=instantiatedType." +
"For example (in Java): array=ArrayList,map=HashMap. In other words array types will get instantiated as ArrayList in generated code.") "For example (in Java): array=ArrayList,map=HashMap. In other words array types will get instantiated as ArrayList in generated code.")
private String instantiationTypes; private String instantiationTypes;
@ -156,6 +162,14 @@ public class Generate implements Runnable {
configurator.setModelPackage(modelPackage); configurator.setModelPackage(modelPackage);
} }
if(isNotEmpty(modelNamePrefix)){
configurator.setModelNamePrefix(modelNamePrefix);
}
if(isNotEmpty(modelNameSuffix)){
configurator.setModelNameSuffix(modelNameSuffix);
}
if(isNotEmpty(invokerPackage)) { if(isNotEmpty(invokerPackage)) {
configurator.setInvokerPackage(invokerPackage); configurator.setInvokerPackage(invokerPackage);
} }
@ -230,15 +244,15 @@ public class Generate implements Runnable {
} }
} }
private Set<String> createSetFromCsvList(String csvProperty) { private static Set<String> createSetFromCsvList(String csvProperty) {
final List<String> values = OptionUtils.splitCommaSeparatedList(csvProperty); final List<String> values = OptionUtils.splitCommaSeparatedList(csvProperty);
return new HashSet<String>(values); return new HashSet<String>(values);
} }
private Map createMapFromKeyValuePairs(String commaSeparatedKVPairs) { private static Map<String, String> createMapFromKeyValuePairs(String commaSeparatedKVPairs) {
final List<Pair<String, String>> pairs = OptionUtils.parseCommaSeparatedTuples(commaSeparatedKVPairs); final List<Pair<String, String>> pairs = OptionUtils.parseCommaSeparatedTuples(commaSeparatedKVPairs);
Map result = new HashMap(); Map<String, String> result = new HashMap<String, String>();
for (Pair<String, String> pair : pairs) { for (Pair<String, String> pair : pairs) {
result.put(pair.getLeft(), pair.getRight()); result.put(pair.getLeft(), pair.getRight());

View File

@ -33,7 +33,7 @@ import static com.google.common.base.Joiner.on;
"specify, and includes default templates to include.") "specify, and includes default templates to include.")
public class Meta implements Runnable { public class Meta implements Runnable {
private static final Logger LOG = LoggerFactory.getLogger(Meta.class); private static final Logger LOGGER = LoggerFactory.getLogger(Meta.class);
private static final String TEMPLATE_DIR_CLASSPATH = "codegen"; private static final String TEMPLATE_DIR_CLASSPATH = "codegen";
private static final String MUSTACHE_EXTENSION = ".mustache"; private static final String MUSTACHE_EXTENSION = ".mustache";
@ -53,7 +53,7 @@ public class Meta implements Runnable {
@Override @Override
public void run() { public void run() {
final File targetDir = new File(outputFolder); final File targetDir = new File(outputFolder);
LOG.info("writing to folder [{}]", targetDir.getAbsolutePath()); LOGGER.info("writing to folder [{}]", targetDir.getAbsolutePath());
String mainClass = CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_CAMEL, name) + "Generator"; String mainClass = CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_CAMEL, name) + "Generator";
@ -93,7 +93,7 @@ public class Meta implements Runnable {
* @param data - map with additional params needed to process templates * @param data - map with additional params needed to process templates
* @return converter object to pass to lambdaj * @return converter object to pass to lambdaj
*/ */
private Converter<SupportingFile, File> processFiles(final File targetDir, final Map<String, Object> data) { private static Converter<SupportingFile, File> processFiles(final File targetDir, final Map<String, Object> data) {
return new Converter<SupportingFile, File>() { return new Converter<SupportingFile, File>() {
private DefaultGenerator generator = new DefaultGenerator(); private DefaultGenerator generator = new DefaultGenerator();
@ -108,13 +108,13 @@ public class Meta implements Runnable {
String formatted = template; String formatted = template;
if (support.templateFile.endsWith(MUSTACHE_EXTENSION)) { if (support.templateFile.endsWith(MUSTACHE_EXTENSION)) {
LOG.info("writing file to {}", outputFile.getAbsolutePath()); LOGGER.info("writing file to {}", outputFile.getAbsolutePath());
formatted = Mustache.compiler().withLoader(loader(generator)) formatted = Mustache.compiler().withLoader(loader(generator))
.defaultValue("") .defaultValue("")
.compile(template) .compile(template)
.execute(data); .execute(data);
} else { } else {
LOG.info("copying file to {}", outputFile.getAbsolutePath()); LOGGER.info("copying file to {}", outputFile.getAbsolutePath());
} }
FileUtils.writeStringToFile(outputFile, formatted); FileUtils.writeStringToFile(outputFile, formatted);
@ -133,8 +133,9 @@ public class Meta implements Runnable {
* @param generator - class with reader getter * @param generator - class with reader getter
* @return loader for template * @return loader for template
*/ */
private Mustache.TemplateLoader loader(final DefaultGenerator generator) { private static Mustache.TemplateLoader loader(final DefaultGenerator generator) {
return new Mustache.TemplateLoader() { return new Mustache.TemplateLoader() {
@Override
public Reader getTemplate(String name) { public Reader getTemplate(String name) {
return generator.getTemplateReader(TEMPLATE_DIR_CLASSPATH return generator.getTemplateReader(TEMPLATE_DIR_CLASSPATH
+ File.separator + name.concat(MUSTACHE_EXTENSION)); + File.separator + name.concat(MUSTACHE_EXTENSION));
@ -148,7 +149,7 @@ public class Meta implements Runnable {
* @param packageName - package name to convert * @param packageName - package name to convert
* @return relative path * @return relative path
*/ */
private String asPath(String packageName) { private static String asPath(String packageName) {
return packageName.replace(".", File.separator); return packageName.replace(".", File.separator);
} }
} }

View File

@ -12,6 +12,7 @@ import mockit.Verifications;
import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.ArrayUtils;
import org.testng.annotations.Test; import org.testng.annotations.Test;
@SuppressWarnings("unused")
public class GenerateTest { public class GenerateTest {
@Mocked @Mocked

View File

@ -1,5 +1,6 @@
package io.swagger.codegen.cmd.utils; package io.swagger.codegen.cmd.utils;
import io.swagger.codegen.utils.OptionUtils;
import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Pair;
import org.junit.Test; import org.junit.Test;
@ -10,6 +11,7 @@ import java.util.List;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNotNull;
@SuppressWarnings("static-method")
public class OptionUtilsTest { public class OptionUtilsTest {
@Test @Test
@ -30,7 +32,7 @@ public class OptionUtilsTest {
doTupleListTest(null, new ArrayList<Pair<String, String>>()); doTupleListTest(null, new ArrayList<Pair<String, String>>());
} }
private void doTupleListTest(String input, List<Pair<String, String>> expectedResults) { private static void doTupleListTest(String input, List<Pair<String, String>> expectedResults) {
final List<Pair<String, String>> result = OptionUtils.parseCommaSeparatedTuples(input); final List<Pair<String, String>> result = OptionUtils.parseCommaSeparatedTuples(input);
assertNotNull(result); assertNotNull(result);
assertEquals(result.size(), expectedResults.size()); assertEquals(result.size(), expectedResults.size());
@ -41,7 +43,7 @@ public class OptionUtilsTest {
} }
} }
private void doCommaSeparatedListTest(String csvStr, List<String> expectedResults) { private static void doCommaSeparatedListTest(String csvStr, List<String> expectedResults) {
final List<String> result = OptionUtils.splitCommaSeparatedList(csvStr); final List<String> result = OptionUtils.splitCommaSeparatedList(csvStr);
assertNotNull(result); assertNotNull(result);
assertEquals(result.size(), expectedResults.size()); assertEquals(result.size(), expectedResults.size());

View File

@ -11,7 +11,7 @@ Add to your `build->plugins` section (default phase is `generate-sources` phase)
<plugin> <plugin>
<groupId>io.swagger</groupId> <groupId>io.swagger</groupId>
<artifactId>swagger-codegen-maven-plugin</artifactId> <artifactId>swagger-codegen-maven-plugin</artifactId>
<version>${project.version}</version> <version>2.1.5-SNAPSHOT</version>
<executions> <executions>
<execution> <execution>
<goals> <goals>
@ -37,7 +37,7 @@ mvn clean compile
### General Configuration parameters ### General Configuration parameters
- `inputSpec` - swagger spec file path - `inputSpec` - OpenAPI Spec file path
- `language` - target generation language - `language` - target generation language
- `output` - target output path (default is `${project.build.directory}/generated-sources/swagger`) - `output` - target output path (default is `${project.build.directory}/generated-sources/swagger`)
- `templateDirectory` - directory with mustache templates - `templateDirectory` - directory with mustache templates
@ -46,10 +46,8 @@ mvn clean compile
- `apiPackage` - the package to use for generated api objects/classes - `apiPackage` - the package to use for generated api objects/classes
- `invokerPackage` - the package to use for the generated invoker objects - `invokerPackage` - the package to use for the generated invoker objects
- `configOptions` - a map of language-specific parameters (see below) - `configOptions` - a map of language-specific parameters (see below)
- `configHelp` - dumps the configuration help for the specified library (generates no sources)
### Java-specific parameters (under configOptions) ### Sample configuration
- `sourceFolder` - the folder to use for generated sources under the output folder - Please see [an example configuration](examples) for using the plugin
- `groupId` - groupId in generated pom.xml
- `artifactId` - artifactId in generated pom.xml
- `artifactVersion` - artifact version in generated pom.xml

View File

@ -0,0 +1,115 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>io.swagger</groupId>
<artifactId>sample-project</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>sample-project</name>
<url>http://maven.apache.org</url>
<build>
<plugins>
<!-- activate the plugin -->
<plugin>
<groupId>io.swagger</groupId>
<artifactId>swagger-codegen-maven-plugin</artifactId>
<version>2.1.5-SNAPSHOT</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<!-- specify the swagger yaml -->
<inputSpec>swagger.yaml</inputSpec>
<!-- target to generate -->
<language>java</language>
<!-- pass any necessary config options -->
<configOptions>
<dateLibrary>java8</dateLibrary>
</configOptions>
<!-- override the default library to jersey2 -->
<library>jersey2</library>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<!-- dependencies are needed for the client being generated -->
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
<version>${swagger-annotations-version}</version>
</dependency>
<!-- HTTP client: jersey-client -->
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<version>${jersey-version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-multipart</artifactId>
<version>${jersey-version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.22.1</version>
</dependency>
<!-- JSON processing: jackson -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson-version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>${jackson-version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson-version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-joda</artifactId>
<version>2.1.5</version>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>${jodatime-version}</version>
</dependency>
<!-- Base64 encoding that works in both JVM and Android -->
<dependency>
<groupId>com.brsanthu</groupId>
<artifactId>migbase64</artifactId>
<version>2.2</version>
</dependency>
<!-- test dependencies -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit-version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<properties>
<swagger-annotations-version>1.5.0</swagger-annotations-version>
<jersey-version>2.12</jersey-version>
<jackson-version>2.4.2</jackson-version>
<jodatime-version>2.3</jodatime-version>
<maven-plugin-version>1.0.0</maven-plugin-version>
<junit-version>4.8.1</junit-version>
</properties>
</project>

View File

@ -0,0 +1,702 @@
---
swagger: "2.0"
info:
description: "This is a sample server Petstore server. You can find out more about\
\ Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/).\
\ For this sample, you can use the api key `special-key` to test the authorization\
\ filters."
version: "1.0.0"
title: "Swagger Petstore"
termsOfService: "http://swagger.io/terms/"
contact:
email: "apiteam@swagger.io"
license:
name: "Apache 2.0"
url: "http://www.apache.org/licenses/LICENSE-2.0.html"
host: "petstore.swagger.io"
basePath: "/v2"
tags:
- name: "pet"
description: "Everything about your Pets"
externalDocs:
description: "Find out more"
url: "http://swagger.io"
- name: "store"
description: "Access to Petstore orders"
- name: "user"
description: "Operations about user"
externalDocs:
description: "Find out more about our store"
url: "http://swagger.io"
schemes:
- "http"
paths:
/pet:
post:
tags:
- "pet"
summary: "Add a new pet to the store"
description: ""
operationId: "addPet"
consumes:
- "application/json"
- "application/xml"
produces:
- "application/xml"
- "application/json"
parameters:
- in: "body"
name: "body"
description: "Pet object that needs to be added to the store"
required: true
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/xml"
- "application/json"
parameters:
- in: "body"
name: "body"
description: "Pet object that needs to be added to the store"
required: true
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"
/pet/findByStatus:
get:
tags:
- "pet"
summary: "Finds Pets by status"
description: "Multiple status values can be provided with comma seperated strings"
operationId: "findPetsByStatus"
produces:
- "application/xml"
- "application/json"
parameters:
- name: "status"
in: "query"
description: "Status values that need to be considered for filter"
required: true
type: "array"
items:
type: "string"
enum:
- "available"
- "pending"
- "sold"
default: "available"
collectionFormat: "csv"
responses:
200:
description: "successful operation"
schema:
type: "array"
items:
$ref: "#/definitions/Pet"
400:
description: "Invalid status value"
security:
- petstore_auth:
- "write:pets"
- "read:pets"
/pet/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/xml"
- "application/json"
parameters:
- name: "tags"
in: "query"
description: "Tags to filter by"
required: true
type: "array"
items:
type: "string"
collectionFormat: "csv"
responses:
200:
description: "successful operation"
schema:
type: "array"
items:
$ref: "#/definitions/Pet"
400:
description: "Invalid tag value"
security:
- petstore_auth:
- "write:pets"
- "read:pets"
/pet/{petId}:
get:
tags:
- "pet"
summary: "Find pet by ID"
description: "Returns a single pet"
operationId: "getPetById"
produces:
- "application/xml"
- "application/json"
parameters:
- name: "petId"
in: "path"
description: "ID of pet to return"
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: []
post:
tags:
- "pet"
summary: "Updates a pet in the store with form data"
description: ""
operationId: "updatePetWithForm"
consumes:
- "application/x-www-form-urlencoded"
produces:
- "application/xml"
- "application/json"
parameters:
- name: "petId"
in: "path"
description: "ID of pet that needs to be updated"
required: true
type: "integer"
format: "int64"
- name: "name"
in: "formData"
description: "Updated name of the pet"
required: false
type: "string"
- name: "status"
in: "formData"
description: "Updated status of the pet"
required: false
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/xml"
- "application/json"
parameters:
- name: "api_key"
in: "header"
required: false
type: "string"
- name: "petId"
in: "path"
description: "Pet id to delete"
required: true
type: "integer"
format: "int64"
responses:
400:
description: "Invalid pet value"
security:
- petstore_auth:
- "write:pets"
- "read:pets"
/pet/{petId}/uploadImage:
post:
tags:
- "pet"
summary: "uploads an image"
description: ""
operationId: "uploadFile"
consumes:
- "multipart/form-data"
produces:
- "application/json"
parameters:
- name: "petId"
in: "path"
description: "ID of pet to update"
required: true
type: "integer"
format: "int64"
- name: "additionalMetadata"
in: "formData"
description: "Additional data to pass to server"
required: false
type: "string"
- name: "file"
in: "formData"
description: "file to upload"
required: false
type: "file"
responses:
200:
description: "successful operation"
schema:
$ref: "#/definitions/ApiResponse"
security:
- petstore_auth:
- "write:pets"
- "read:pets"
/store/inventory:
get:
tags:
- "store"
summary: "Returns pet inventories by status"
description: "Returns a map of status codes to quantities"
operationId: "getInventory"
produces:
- "application/json"
parameters: []
responses:
200:
description: "successful operation"
schema:
type: "object"
additionalProperties:
type: "integer"
format: "int32"
security:
- api_key: []
/store/order:
post:
tags:
- "store"
summary: "Place an order for a pet"
description: ""
operationId: "placeOrder"
produces:
- "application/xml"
- "application/json"
parameters:
- in: "body"
name: "body"
description: "order placed for purchasing the pet"
required: true
schema:
$ref: "#/definitions/Order"
responses:
200:
description: "successful operation"
schema:
$ref: "#/definitions/Order"
400:
description: "Invalid Order"
/store/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/xml"
- "application/json"
parameters:
- name: "orderId"
in: "path"
description: "ID of pet that needs to be fetched"
required: true
type: "integer"
maximum: 5.0
minimum: 1.0
format: "int64"
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/xml"
- "application/json"
parameters:
- name: "orderId"
in: "path"
description: "ID of the order that needs to be deleted"
required: true
type: "string"
minimum: 1.0
responses:
400:
description: "Invalid ID supplied"
404:
description: "Order not found"
/user:
post:
tags:
- "user"
summary: "Create user"
description: "This can only be done by the logged in user."
operationId: "createUser"
produces:
- "application/xml"
- "application/json"
parameters:
- in: "body"
name: "body"
description: "Created user object"
required: true
schema:
$ref: "#/definitions/User"
responses:
default:
description: "successful operation"
/user/createWithArray:
post:
tags:
- "user"
summary: "Creates list of users with given input array"
description: ""
operationId: "createUsersWithArrayInput"
produces:
- "application/xml"
- "application/json"
parameters:
- in: "body"
name: "body"
description: "List of user object"
required: true
schema:
type: "array"
items:
$ref: "#/definitions/User"
responses:
default:
description: "successful operation"
/user/createWithList:
post:
tags:
- "user"
summary: "Creates list of users with given input array"
description: ""
operationId: "createUsersWithListInput"
produces:
- "application/xml"
- "application/json"
parameters:
- in: "body"
name: "body"
description: "List of user object"
required: true
schema:
type: "array"
items:
$ref: "#/definitions/User"
responses:
default:
description: "successful operation"
/user/login:
get:
tags:
- "user"
summary: "Logs user into the system"
description: ""
operationId: "loginUser"
produces:
- "application/xml"
- "application/json"
parameters:
- name: "username"
in: "query"
description: "The user name for login"
required: true
type: "string"
- name: "password"
in: "query"
description: "The password for login in clear text"
required: true
type: "string"
responses:
200:
description: "successful operation"
schema:
type: "string"
headers:
X-Rate-Limit:
type: "integer"
format: "int32"
description: "calls per hour allowed by the user"
X-Expires-After:
type: "string"
format: "date-time"
description: "date in UTC when toekn expires"
400:
description: "Invalid username/password supplied"
/user/logout:
get:
tags:
- "user"
summary: "Logs out current logged in user session"
description: ""
operationId: "logoutUser"
produces:
- "application/xml"
- "application/json"
parameters: []
responses:
default:
description: "successful operation"
/user/{username}:
get:
tags:
- "user"
summary: "Get user by user name"
description: ""
operationId: "getUserByName"
produces:
- "application/xml"
- "application/json"
parameters:
- name: "username"
in: "path"
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/xml"
- "application/json"
parameters:
- name: "username"
in: "path"
description: "name that need to be deleted"
required: true
type: "string"
- in: "body"
name: "body"
description: "Updated user object"
required: true
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/xml"
- "application/json"
parameters:
- name: "username"
in: "path"
description: "The name that needs to be deleted"
required: true
type: "string"
responses:
400:
description: "Invalid username supplied"
404:
description: "User not found"
securityDefinitions:
petstore_auth:
type: "oauth2"
authorizationUrl: "http://petstore.swagger.io/api/oauth/dialog"
flow: "implicit"
scopes:
write:pets: "modify pets in your account"
read:pets: "read your pets"
api_key:
type: "apiKey"
name: "api_key"
in: "header"
definitions:
Order:
type: "object"
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"
enum:
- "placed"
- "approved"
- "delivered"
complete:
type: "boolean"
default: false
xml:
name: "Order"
Category:
type: "object"
properties:
id:
type: "integer"
format: "int64"
name:
type: "string"
xml:
name: "Category"
User:
type: "object"
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"
xml:
name: "User"
Tag:
type: "object"
properties:
id:
type: "integer"
format: "int64"
name:
type: "string"
xml:
name: "Tag"
Pet:
type: "object"
required:
- "name"
- "photoUrls"
properties:
id:
type: "integer"
format: "int64"
category:
$ref: "#/definitions/Category"
name:
type: "string"
example: "doggie"
photoUrls:
type: "array"
xml:
name: "photoUrl"
wrapped: true
items:
type: "string"
tags:
type: "array"
xml:
name: "tag"
wrapped: true
items:
$ref: "#/definitions/Tag"
status:
type: "string"
description: "pet status in the store"
enum:
- "available"
- "pending"
- "sold"
xml:
name: "Pet"
ApiResponse:
type: "object"
properties:
code:
type: "integer"
format: "int32"
type:
type: "string"
message:
type: "string"
externalDocs:
description: "Find out more about Swagger"
url: "http://swagger.io"

View File

@ -6,7 +6,7 @@
<parent> <parent>
<groupId>io.swagger</groupId> <groupId>io.swagger</groupId>
<artifactId>swagger-codegen-project</artifactId> <artifactId>swagger-codegen-project</artifactId>
<version>2.1.5-SNAPSHOT</version> <version>2.1.6-SNAPSHOT</version>
<relativePath>../..</relativePath> <relativePath>../..</relativePath>
</parent> </parent>
<artifactId>swagger-codegen-maven-plugin</artifactId> <artifactId>swagger-codegen-maven-plugin</artifactId>
@ -51,7 +51,7 @@
<dependency> <dependency>
<groupId>junit</groupId> <groupId>junit</groupId>
<artifactId>junit</artifactId> <artifactId>junit</artifactId>
<version>4.12</version> <!-- <version>4.12</version> -->
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
</dependencies> </dependencies>

View File

@ -10,7 +10,7 @@ public final class AdditionalParams {
public static final String MODEL_PACKAGE_PARAM = "modelPackage"; public static final String MODEL_PACKAGE_PARAM = "modelPackage";
public static final String API_PACKAGE_PARAM = "apiPackage"; public static final String API_PACKAGE_PARAM = "apiPackage";
public static final String INVOKER_PACKAGE_PARAM = "invokerPackage"; public static final String INVOKER_PACKAGE_PARAM = "invokerPackage";
public static final String LIBRARY_PARAM = "library";
private AdditionalParams() { private AdditionalParams() {}
} }
}

View File

@ -16,15 +16,13 @@ package io.swagger.codegen.plugin;
* limitations under the License. * limitations under the License.
*/ */
import io.swagger.codegen.CliOption; import config.Config;
import io.swagger.codegen.ClientOptInput; import config.ConfigParser;
import io.swagger.codegen.ClientOpts; import io.swagger.codegen.*;
import io.swagger.codegen.CodegenConfig; import io.swagger.codegen.utils.OptionUtils;
import io.swagger.codegen.CodegenConfigLoader;
import io.swagger.codegen.DefaultGenerator;
import io.swagger.models.Swagger; import io.swagger.models.Swagger;
import io.swagger.parser.SwaggerParser; import io.swagger.parser.SwaggerParser;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.LifecyclePhase; import org.apache.maven.plugins.annotations.LifecyclePhase;
@ -32,18 +30,14 @@ import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject; import org.apache.maven.project.MavenProject;
import config.Config;
import config.ConfigParser;
import java.io.File; import java.io.File;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.ServiceLoader; import java.util.Set;
import static io.swagger.codegen.plugin.AdditionalParams.API_PACKAGE_PARAM; import static io.swagger.codegen.plugin.AdditionalParams.*;
import static io.swagger.codegen.plugin.AdditionalParams.INVOKER_PACKAGE_PARAM;
import static io.swagger.codegen.plugin.AdditionalParams.MODEL_PACKAGE_PARAM;
import static io.swagger.codegen.plugin.AdditionalParams.TEMPLATE_DIR_PARAM;
/** /**
* Goal which generates client/server code from a swagger json/yaml definition. * Goal which generates client/server code from a swagger json/yaml definition.
@ -100,11 +94,17 @@ public class CodeGenMojo extends AbstractMojo {
@Parameter(name = "configurationFile", required = false) @Parameter(name = "configurationFile", required = false)
private String configurationFile; private String configurationFile;
/**
* Sets the library
*/
@Parameter(name = "library", required = false)
private String library;
/** /**
* A map of language-specific parameters as passed with the -c option to the command line * A map of language-specific parameters as passed with the -c option to the command line
*/ */
@Parameter(name = "configOptions") @Parameter(name = "configOptions")
private Map configOptions; private Map<?, ?> configOptions;
/** /**
* Add the output directory to the project as a source root, so that the * Add the output directory to the project as a source root, so that the
@ -116,6 +116,9 @@ public class CodeGenMojo extends AbstractMojo {
@Parameter @Parameter
protected Map<String, String> environmentVariables = new HashMap<String, String>(); protected Map<String, String> environmentVariables = new HashMap<String, String>();
@Parameter
private boolean configHelp = false;
/** /**
* The project being built. * The project being built.
*/ */
@ -139,7 +142,9 @@ public class CodeGenMojo extends AbstractMojo {
System.setProperty(key, value); System.setProperty(key, value);
} }
} }
if (null != library) {
config.setLibrary(library);
}
if (null != templateDirectory) { if (null != templateDirectory) {
config.additionalProperties().put(TEMPLATE_DIR_PARAM, templateDirectory.getAbsolutePath()); config.additionalProperties().put(TEMPLATE_DIR_PARAM, templateDirectory.getAbsolutePath());
} }
@ -152,38 +157,56 @@ public class CodeGenMojo extends AbstractMojo {
if (null != invokerPackage) { if (null != invokerPackage) {
config.additionalProperties().put(INVOKER_PACKAGE_PARAM, invokerPackage); config.additionalProperties().put(INVOKER_PACKAGE_PARAM, invokerPackage);
} }
Set<String> definedOptions = new HashSet<String>();
for (CliOption langCliOption : config.cliOptions()) {
definedOptions.add(langCliOption.getOpt());
}
if (configOptions != null) { if (configOptions != null) {
for (CliOption langCliOption : config.cliOptions()) { if(configOptions.containsKey("import-mappings")) {
if (configOptions.containsKey(langCliOption.getOpt())) { Map<String, String> mappings = createMapFromKeyValuePairs(configOptions.remove("import-mappings").toString());
config.additionalProperties().put(langCliOption.getOpt(), config.importMapping().putAll(mappings);
configOptions.get(langCliOption.getOpt()));
}
} }
if(configOptions.containsKey("type-mappings")) {
Map<String, String> mappings = createMapFromKeyValuePairs(configOptions.remove("type-mappings").toString());
config.typeMapping().putAll(mappings);
}
if(configOptions.containsKey("instantiation-types")) {
Map<String, String> mappings = createMapFromKeyValuePairs(configOptions.remove("instantiation-types").toString());
config.instantiationTypes().putAll(mappings);
}
addAdditionalProperties(config, definedOptions, configOptions);
} }
if (null != configurationFile) { if (null != configurationFile) {
Config genConfig = ConfigParser.read(configurationFile); Config genConfig = ConfigParser.read(configurationFile);
if (null != genConfig) { if (null != genConfig) {
for (CliOption langCliOption : config.cliOptions()) { addAdditionalProperties(config, definedOptions, genConfig.getOptions());
if (genConfig.hasOption(langCliOption.getOpt())) {
config.additionalProperties().put(langCliOption.getOpt(), genConfig.getOption(langCliOption.getOpt()));
}
}
} else { } else {
throw new RuntimeException("Unable to read configuration file"); throw new RuntimeException("Unable to read configuration file");
} }
} }
ClientOptInput input = new ClientOptInput().opts(new ClientOpts()).swagger(swagger); ClientOptInput input = new ClientOptInput().opts(new ClientOpts()).swagger(swagger);
input.setConfig(config); input.setConfig(config);
if(configHelp) {
for (CliOption langCliOption : config.cliOptions()) {
System.out.println("\t" + langCliOption.getOpt());
System.out.println("\t " + langCliOption.getOptionHelp().replaceAll("\n", "\n\t "));
System.out.println();
}
return;
}
try { try {
new DefaultGenerator().opts(input).generate(); new DefaultGenerator().opts(input).generate();
} catch (Exception e) { } catch (Exception e) {
// Maven logs exceptions thrown by plugins only if invoked with -e // Maven logs exceptions thrown by plugins only if invoked with -e
// I find it annoying to jump through hoops to get basic diagnostic information, // I find it annoying to jump through hoops to get basic diagnostic information,
// so let's log it in any case: // so let's log it in any case:
getLog().error(e); getLog().error(e);
throw new MojoExecutionException("Code generation failed. See above for the full exception."); throw new MojoExecutionException("Code generation failed. See above for the full exception.");
} }
@ -192,4 +215,25 @@ public class CodeGenMojo extends AbstractMojo {
project.addCompileSourceRoot(output.toString()); project.addCompileSourceRoot(output.toString());
} }
} }
private void addAdditionalProperties(CodegenConfig config, Set<String> definedOptions, Map<?,?> configOptions) {
for(Map.Entry<?, ?> configEntry : configOptions.entrySet()) {
config.additionalProperties().put(configEntry.getKey().toString(), configEntry.getValue());
if(!definedOptions.contains(configEntry.getKey())) {
getLog().warn("Additional property: " + configEntry.getKey() + " is not defined for this language.");
}
}
}
private static Map<String, String> createMapFromKeyValuePairs(String commaSeparatedKVPairs) {
final List<Pair<String, String>> pairs = OptionUtils.parseCommaSeparatedTuples(commaSeparatedKVPairs);
Map<String, String> result = new HashMap<String, String>();
for (Pair<String, String> pair : pairs) {
result.put(pair.getLeft(), pair.getRight());
}
return result;
}
} }

View File

@ -3,7 +3,7 @@
<parent> <parent>
<groupId>io.swagger</groupId> <groupId>io.swagger</groupId>
<artifactId>swagger-codegen-project</artifactId> <artifactId>swagger-codegen-project</artifactId>
<version>2.1.5-SNAPSHOT</version> <version>2.1.6-SNAPSHOT</version>
<relativePath>../..</relativePath> <relativePath>../..</relativePath>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@ -101,7 +101,7 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId> <artifactId>maven-release-plugin</artifactId>
<version>2.1</version> <!-- <version>2.1</version> -->
</plugin> </plugin>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
@ -256,7 +256,7 @@
<dependency> <dependency>
<groupId>org.testng</groupId> <groupId>org.testng</groupId>
<artifactId>testng</artifactId> <artifactId>testng</artifactId>
<version>${testng-version}</version> <!-- <version>${testng-version}</version> -->
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
@ -268,7 +268,7 @@
<dependency> <dependency>
<groupId>org.jmockit</groupId> <groupId>org.jmockit</groupId>
<artifactId>jmockit</artifactId> <artifactId>jmockit</artifactId>
<version>${jmockit-version}</version> <!-- <version>${jmockit-version}</version> -->
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
</dependencies> </dependencies>

View File

@ -7,11 +7,16 @@ import java.io.File;
import java.util.Iterator; import java.util.Iterator;
import java.util.Map; import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ConfigParser { public class ConfigParser {
private static final Logger LOGGER = LoggerFactory.getLogger(ConfigParser.class);
public static Config read(String location) { public static Config read(String location) {
System.out.println("reading config from " + location); LOGGER.info("reading config from " + location);
ObjectMapper mapper = new ObjectMapper(); ObjectMapper mapper = new ObjectMapper();
@ -27,11 +32,11 @@ public class ConfigParser {
if (optionNode.getValue().isValueNode()) { if (optionNode.getValue().isValueNode()) {
config.setOption(optionNode.getKey(), optionNode.getValue().asText()); config.setOption(optionNode.getKey(), optionNode.getValue().asText());
} else { } else {
System.out.println("omitting non-value node " + optionNode.getKey()); LOGGER.warn("omitting non-value node " + optionNode.getKey());
} }
} }
} catch (Exception e) { } catch (Exception e) {
System.out.println(e.getMessage()); LOGGER.error(e.getMessage());
return null; return null;
} }

View File

@ -10,12 +10,18 @@ import java.io.InputStreamReader;
import java.io.OutputStreamWriter; import java.io.OutputStreamWriter;
import java.io.Reader; import java.io.Reader;
import java.io.Writer; import java.io.Writer;
import java.util.Scanner;
import java.util.regex.Pattern; import java.util.regex.Pattern;
public abstract class AbstractGenerator { import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public abstract class AbstractGenerator {
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractGenerator.class);
@SuppressWarnings("static-method")
public File writeToFile(String filename, String contents) throws IOException { public File writeToFile(String filename, String contents) throws IOException {
System.out.println("writing file " + filename); LOGGER.info("writing file " + filename);
File output = new File(filename); File output = new File(filename);
if (output.getParent() != null && !new File(output.getParent()).exists()) { if (output.getParent() != null && !new File(output.getParent()).exists()) {
@ -36,10 +42,10 @@ public abstract class AbstractGenerator {
if (reader == null) { if (reader == null) {
throw new RuntimeException("no file found"); throw new RuntimeException("no file found");
} }
java.util.Scanner s = new java.util.Scanner(reader).useDelimiter("\\A"); Scanner s = new Scanner(reader).useDelimiter("\\A");
return s.hasNext() ? s.next() : ""; return s.hasNext() ? s.next() : "";
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); LOGGER.error(e.getMessage());
} }
throw new RuntimeException("can't load template " + name); throw new RuntimeException("can't load template " + name);
} }
@ -48,14 +54,11 @@ public abstract class AbstractGenerator {
try { try {
InputStream is = this.getClass().getClassLoader().getResourceAsStream(getCPResourcePath(name)); InputStream is = this.getClass().getClassLoader().getResourceAsStream(getCPResourcePath(name));
if (is == null) { if (is == null) {
is = new FileInputStream(new File(name)); is = new FileInputStream(new File(name)); // May throw but never return a null value
}
if (is == null) {
throw new RuntimeException("no file found");
} }
return new InputStreamReader(is); return new InputStreamReader(is);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); LOGGER.error(e.getMessage());
} }
throw new RuntimeException("can't load template " + name); throw new RuntimeException("can't load template " + name);
} }
@ -63,6 +66,9 @@ public abstract class AbstractGenerator {
/** /**
* Get the template file path with template dir prepended, and use the * Get the template file path with template dir prepended, and use the
* library template if exists. * library template if exists.
*
* @param config Codegen config
* @param templateFile Template file
*/ */
public String getFullTemplateFile(CodegenConfig config, String templateFile) { public String getFullTemplateFile(CodegenConfig config, String templateFile) {
String library = config.getLibrary(); String library = config.getLibrary();
@ -96,6 +102,7 @@ public abstract class AbstractGenerator {
return this.getClass().getClassLoader().getResource(getCPResourcePath(name)) != null; return this.getClass().getClassLoader().getResource(getCPResourcePath(name)) != null;
} }
@SuppressWarnings("static-method")
public String getCPResourcePath(String name) { public String getCPResourcePath(String name) {
if (!"/".equals(File.separator)) { if (!"/".equals(File.separator)) {
return name.replaceAll(Pattern.quote(File.separator), "/"); return name.replaceAll(Pattern.quote(File.separator), "/");

View File

@ -1,6 +1,7 @@
package io.swagger.codegen; package io.swagger.codegen;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
import io.swagger.models.properties.BooleanProperty;
import io.swagger.models.properties.StringProperty; import io.swagger.models.properties.StringProperty;
import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnore;
@ -78,6 +79,14 @@ public class CliOption {
this.enumValues = enumValues; this.enumValues = enumValues;
} }
public static CliOption newBoolean(String opt, String description) {
return new CliOption(opt, description, BooleanProperty.TYPE).defaultValue(Boolean.FALSE.toString());
}
public static CliOption newString(String opt, String description) {
return new CliOption(opt, description, StringProperty.TYPE);
}
@JsonIgnore @JsonIgnore
public String getOptionHelp() { public String getOptionHelp() {
StringBuilder sb = new StringBuilder(description); StringBuilder sb = new StringBuilder(description);

View File

@ -5,13 +5,8 @@ import io.swagger.codegen.auth.AuthParser;
import io.swagger.models.Swagger; import io.swagger.models.Swagger;
import io.swagger.models.auth.AuthorizationValue; import io.swagger.models.auth.AuthorizationValue;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import static org.apache.commons.lang3.StringUtils.isNotEmpty;
public class ClientOptInput { public class ClientOptInput {
private CodegenConfig config; private CodegenConfig config;
private ClientOpts opts; private ClientOpts opts;

View File

@ -1,29 +1,34 @@
package io.swagger.codegen; package io.swagger.codegen;
import config.Config;
import config.ConfigParser;
import io.swagger.models.Swagger;
import io.swagger.parser.SwaggerParser;
import org.apache.commons.cli.BasicParser;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Options;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.ServiceLoader; import java.util.ServiceLoader;
import org.apache.commons.cli.BasicParser;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Options;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import config.Config;
import config.ConfigParser;
import io.swagger.models.Swagger;
import io.swagger.parser.SwaggerParser;
/** /**
* @deprecated use instead {@link io.swagger.codegen.DefaultGenerator} * @deprecated use instead {@link io.swagger.codegen.DefaultGenerator}
* or cli interface from https://github.com/swagger-api/swagger-codegen/pull/547 * or cli interface from https://github.com/swagger-api/swagger-codegen/pull/547
*/ */
@Deprecated @Deprecated
public class Codegen extends DefaultGenerator { public class Codegen extends DefaultGenerator {
private static final Logger LOGGER = LoggerFactory.getLogger(Codegen.class);
static Map<String, CodegenConfig> configs = new HashMap<String, CodegenConfig>(); static Map<String, CodegenConfig> configs = new HashMap<String, CodegenConfig>();
static String configString; static String configString;
static String debugInfoOptions = "\nThe following additional debug options are available for all codegen targets:" + static String debugInfoOptions = "\nThe following additional debug options are available for all codegen targets:" +
@ -32,10 +37,9 @@ public class Codegen extends DefaultGenerator {
"\n -DdebugOperations prints operations passed to the template engine" + "\n -DdebugOperations prints operations passed to the template engine" +
"\n -DdebugSupportingFiles prints additional data passed to the template engine"; "\n -DdebugSupportingFiles prints additional data passed to the template engine";
@SuppressWarnings("deprecation")
public static void main(String[] args) { public static void main(String[] args) {
StringBuilder sb = new StringBuilder();
Options options = new Options(); Options options = new Options();
options.addOption("h", "help", false, "shows this message"); options.addOption("h", "help", false, "shows this message");
options.addOption("l", "lang", true, "client language to generate.\nAvailable languages include:\n\t[" + configString + "]"); options.addOption("l", "lang", true, "client language to generate.\nAvailable languages include:\n\t[" + configString + "]");
@ -113,7 +117,7 @@ public class Codegen extends DefaultGenerator {
.swagger(swagger); .swagger(swagger);
new Codegen().opts(clientOptInput).generate(); new Codegen().opts(clientOptInput).generate();
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); LOGGER.error(e.getMessage(), e);
} }
} }
@ -138,9 +142,9 @@ public class Codegen extends DefaultGenerator {
} else { } else {
// see if it's a class // see if it's a class
try { try {
System.out.println("loading class " + name); LOGGER.debug("loading class " + name);
Class customClass = Class.forName(name); Class<?> customClass = Class.forName(name);
System.out.println("loaded"); LOGGER.debug("loaded");
return (CodegenConfig) customClass.newInstance(); return (CodegenConfig) customClass.newInstance();
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException("can't load class " + name); throw new RuntimeException("can't load class " + name);

View File

@ -18,11 +18,17 @@ public interface CodegenConfig {
String getHelp(); String getHelp();
Map<String, Object> additionalProperties(); Map<String, Object> additionalProperties();
Map<String, Object> vendorExtensions();
String testPackage();
String apiPackage(); String apiPackage();
String apiFileFolder(); String apiFileFolder();
String apiTestFileFolder();
String fileSuffix(); String fileSuffix();
String outputFolder(); String outputFolder();
@ -33,6 +39,8 @@ public interface CodegenConfig {
String modelFileFolder(); String modelFileFolder();
String modelTestFileFolder();
String modelPackage(); String modelPackage();
String toApiName(String name); String toApiName(String name);
@ -87,6 +95,10 @@ public interface CodegenConfig {
Map<String, String> modelTemplateFiles(); Map<String, String> modelTemplateFiles();
Map<String, String> apiTestTemplateFiles();
Map<String, String> modelTestTemplateFiles();
Set<String> languageSpecificPrimitives(); Set<String> languageSpecificPrimitives();
void preprocessSwagger(Swagger swagger); void preprocessSwagger(Swagger swagger);
@ -97,20 +109,32 @@ public interface CodegenConfig {
String toModelFilename(String name); String toModelFilename(String name);
String toApiTestFilename(String name);
String toModelTestFilename(String name);
String toModelImport(String name); String toModelImport(String name);
String toApiImport(String name); String toApiImport(String name);
void addOperationToGroup(String tag, String resourcePath, Operation operation, CodegenOperation co, Map<String, List<CodegenOperation>> operations); void addOperationToGroup(String tag, String resourcePath, Operation operation, CodegenOperation co, Map<String, List<CodegenOperation>> operations);
Map<String, Object> postProcessAllModels(Map<String, Object> objs);
Map<String, Object> postProcessModels(Map<String, Object> objs); Map<String, Object> postProcessModels(Map<String, Object> objs);
Map<String, Object> postProcessOperations(Map<String, Object> objs); Map<String, Object> postProcessOperations(Map<String, Object> objs);
Map<String, Object> postProcessSupportingFileData(Map<String, Object> objs); Map<String, Object> postProcessSupportingFileData(Map<String, Object> objs);
void postProcessModelProperty(CodegenModel model, CodegenProperty property);
void postProcessParameter(CodegenParameter parameter);
String apiFilename(String templateName, String tag); String apiFilename(String templateName, String tag);
String apiTestFilename(String templateName, String tag);
boolean shouldOverwrite(String filename); boolean shouldOverwrite(String filename);
boolean isSkipOverwrite(); boolean isSkipOverwrite();
@ -123,6 +147,8 @@ public interface CodegenConfig {
/** /**
* Library template (sub-template). * Library template (sub-template).
*
* @return libray template
*/ */
String getLibrary(); String getLibrary();
} }

View File

@ -28,18 +28,27 @@ public class CodegenConstants {
public static final String SOURCE_FOLDER = "sourceFolder"; public static final String SOURCE_FOLDER = "sourceFolder";
public static final String SOURCE_FOLDER_DESC = "source folder for generated code"; public static final String SOURCE_FOLDER_DESC = "source folder for generated code";
public static final String IMPL_FOLDER = "implFolder";
public static final String IMPL_FOLDER_DESC = "folder for generated implementation code";
public static final String LOCAL_VARIABLE_PREFIX = "localVariablePrefix"; public static final String LOCAL_VARIABLE_PREFIX = "localVariablePrefix";
public static final String LOCAL_VARIABLE_PREFIX_DESC = "prefix for generated code members and local variables"; public static final String LOCAL_VARIABLE_PREFIX_DESC = "prefix for generated code members and local variables";
public static final String SERIALIZABLE_MODEL = "serializableModel"; public static final String SERIALIZABLE_MODEL = "serializableModel";
public static final String SERIALIZABLE_MODEL_DESC = "boolean - toggle \"implements Serializable\" for generated models"; public static final String SERIALIZABLE_MODEL_DESC = "boolean - toggle \"implements Serializable\" for generated models";
public static final String SERIALIZE_BIG_DECIMAL_AS_STRING = "bigDecimalAsString";
public static final String SERIALIZE_BIG_DECIMAL_AS_STRING_DESC = "Treat BigDecimal values as Strings to avoid precision loss.";
public static final String LIBRARY = "library"; public static final String LIBRARY = "library";
public static final String LIBRARY_DESC = "library template (sub-template)"; public static final String LIBRARY_DESC = "library template (sub-template)";
public static final String SORT_PARAMS_BY_REQUIRED_FLAG = "sortParamsByRequiredFlag"; public static final String SORT_PARAMS_BY_REQUIRED_FLAG = "sortParamsByRequiredFlag";
public static final String SORT_PARAMS_BY_REQUIRED_FLAG_DESC = "Sort method arguments to place required parameters before optional parameters."; public static final String SORT_PARAMS_BY_REQUIRED_FLAG_DESC = "Sort method arguments to place required parameters before optional parameters.";
public static final String USE_DATETIME_OFFSET = "useDateTimeOffset";
public static final String USE_DATETIME_OFFSET_DESC = "Use DateTimeOffset to model date-time properties";
public static final String ENSURE_UNIQUE_PARAMS = "ensureUniqueParams"; public static final String ENSURE_UNIQUE_PARAMS = "ensureUniqueParams";
public static final String ENSURE_UNIQUE_PARAMS_DESC = "Whether to ensure parameter names are unique in an operation (rename parameters that are not)."; public static final String ENSURE_UNIQUE_PARAMS_DESC = "Whether to ensure parameter names are unique in an operation (rename parameters that are not).";
@ -48,4 +57,34 @@ public class CodegenConstants {
public static final String POD_VERSION = "podVersion"; public static final String POD_VERSION = "podVersion";
public static final String OPTIONAL_METHOD_ARGUMENT = "optionalMethodArgument"; public static final String OPTIONAL_METHOD_ARGUMENT = "optionalMethodArgument";
public static final String OPTIONAL_METHOD_ARGUMENT_DESC = "Optional method argument, e.g. void square(int x=10) (.net 4.0+ only).";
public static final String OPTIONAL_ASSEMBLY_INFO = "optionalAssemblyInfo";
public static final String OPTIONAL_ASSEMBLY_INFO_DESC = "Generate AssemblyInfo.cs.";
public static final String USE_COLLECTION = "useCollection";
public static final String USE_COLLECTION_DESC = "Deserialize array types to Collection<T> instead of List<T>.";
public static final String RETURN_ICOLLECTION = "returnICollection";
public static final String RETURN_ICOLLECTION_DESC = "Return ICollection<T> instead of the concrete type.";
public static final String OPTIONAL_PROJECT_FILE = "optionalProjectFile";
public static final String OPTIONAL_PROJECT_FILE_DESC = "Generate {PackageName}.csproj.";
public static final String OPTIONAL_PROJECT_GUID = "packageGuid";
public static final String OPTIONAL_PROJECT_GUID_DESC = "The GUID that will be associated with the C# project";
public static final String MODEL_PROPERTY_NAMING = "modelPropertyNaming";
public static final String MODEL_PROPERTY_NAMING_DESC = "Naming convention for the property: 'camelCase', 'PascalCase', 'snake_case' and 'original', which keeps the original name";
public static final String DOTNET_FRAMEWORK = "targetFramework";
public static final String DOTNET_FRAMEWORK_DESC = "The target .NET framework version.";
public static enum MODEL_PROPERTY_NAMING_TYPE {camelCase, PascalCase, snake_case, original}
public static final String MODEL_NAME_PREFIX = "modelNamePrefix";
public static final String MODEL_NAME_PREFIX_DESC = "Prefix that will be prepended to all model names. Default is the empty string.";
public static final String MODEL_NAME_SUFFIX = "modelNameSuffix";
public static final String MODEL_NAME_SUFFIX_DESC = "Suffix that will be appended to all model names. Default is the empty string.";
} }

View File

@ -2,13 +2,10 @@ package io.swagger.codegen;
import io.swagger.models.ExternalDocs; import io.swagger.models.ExternalDocs;
import java.util.ArrayList; import java.util.*;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class CodegenModel { public class CodegenModel {
public String parent; public String parent, parentSchema;
public String name, classname, description, classVarName, modelJson, dataType; public String name, classname, description, classVarName, modelJson, dataType;
public String unescapedDescription; public String unescapedDescription;
public String defaultValue; public String defaultValue;
@ -18,7 +15,9 @@ public class CodegenModel {
// list of all required parameters // list of all required parameters
public Set<String> mandatory = new HashSet<String>(); public Set<String> mandatory = new HashSet<String>();
public Set<String> imports = new HashSet<String>(); public Set<String> imports = new TreeSet<String>();
public Boolean hasVars, emptyVars, hasMoreModels, hasEnums, isEnum; public Boolean hasVars, emptyVars, hasMoreModels, hasEnums, isEnum;
public ExternalDocs externalDocs; public ExternalDocs externalDocs;
public Map<String, Object> vendorExtensions;
} }

View File

@ -38,7 +38,7 @@ public class CodegenOperation {
* *
* @return true if parameter exists, false otherwise * @return true if parameter exists, false otherwise
*/ */
private boolean nonempty(List<CodegenParameter> params) { private static boolean nonempty(List<CodegenParameter> params) {
return params != null && params.size() > 0; return params != null && params.size() > 0;
} }

View File

@ -7,13 +7,17 @@ import java.util.List;
public class CodegenParameter { public class CodegenParameter {
public Boolean isFormParam, isQueryParam, isPathParam, isHeaderParam, public Boolean isFormParam, isQueryParam, isPathParam, isHeaderParam,
isCookieParam, isBodyParam, isFile, notFile, hasMore, isContainer, isCookieParam, isBodyParam, hasMore, isContainer,
secondaryParam, isBinary, isCollectionFormatMulti; secondaryParam, isCollectionFormatMulti;
public String baseName, paramName, dataType, collectionFormat, description, baseType, defaultValue; public String baseName, paramName, dataType, datatypeWithEnum, collectionFormat, description, baseType, defaultValue;
public String jsonSchema; public String jsonSchema;
public Boolean isString, isInteger, isLong, isFloat, isDouble, isByteArray, isBinary, isBoolean, isDate, isDateTime;
public Boolean isListContainer, isMapContainer;
public Boolean isFile, notFile;
public boolean isEnum; public boolean isEnum;
public List<String> _enum; public List<String> _enum;
public Map<String, Object> allowableValues; public Map<String, Object> allowableValues;
public CodegenProperty items;
public Map<String, Object> vendorExtensions; public Map<String, Object> vendorExtensions;
/** /**
@ -78,6 +82,7 @@ public class CodegenParameter {
output.baseName = this.baseName; output.baseName = this.baseName;
output.paramName = this.paramName; output.paramName = this.paramName;
output.dataType = this.dataType; output.dataType = this.dataType;
output.datatypeWithEnum = this.datatypeWithEnum;
output.collectionFormat = this.collectionFormat; output.collectionFormat = this.collectionFormat;
output.isCollectionFormatMulti = this.isCollectionFormatMulti; output.isCollectionFormatMulti = this.isCollectionFormatMulti;
output.description = this.description; output.description = this.description;
@ -109,7 +114,22 @@ public class CodegenParameter {
if (this.allowableValues != null) { if (this.allowableValues != null) {
output.allowableValues = new HashMap<String, Object>(this.allowableValues); output.allowableValues = new HashMap<String, Object>(this.allowableValues);
} }
if (this.items != null) {
output.items = this.items;
}
output.vendorExtensions = this.vendorExtensions; output.vendorExtensions = this.vendorExtensions;
output.isBinary = this.isBinary;
output.isByteArray = this.isByteArray;
output.isString = this.isString;
output.isInteger = this.isInteger;
output.isLong = this.isLong;
output.isDouble = this.isDouble;
output.isFloat = this.isFloat;
output.isBoolean = this.isBoolean;
output.isDate = this.isDate;
output.isDateTime = this.isDateTime;
output.isListContainer = this.isListContainer;
output.isMapContainer = this.isMapContainer;
return output; return output;
} }

View File

@ -31,13 +31,72 @@ public class CodegenProperty {
public Double maximum; public Double maximum;
public Boolean exclusiveMinimum; public Boolean exclusiveMinimum;
public Boolean exclusiveMaximum; public Boolean exclusiveMaximum;
public Boolean hasMore = null, required = null, secondaryParam = null; public Boolean hasMore, required, secondaryParam;
public Boolean isPrimitiveType, isContainer, isNotContainer; public Boolean isPrimitiveType, isContainer, isNotContainer;
public Boolean isString, isInteger, isLong, isFloat, isDouble, isByteArray, isBinary, isBoolean, isDate, isDateTime;
public Boolean isListContainer, isMapContainer;
public boolean isEnum; public boolean isEnum;
public Boolean isReadOnly = false; public Boolean isReadOnly = false;
public List<String> _enum; public List<String> _enum;
public Map<String, Object> allowableValues; public Map<String, Object> allowableValues;
public CodegenProperty items; public CodegenProperty items;
public Map<String, Object> vendorExtensions;
@Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + ((_enum == null) ? 0 : _enum.hashCode());
result = prime * result + ((allowableValues == null) ? 0 : allowableValues.hashCode());
result = prime * result + ((baseName == null) ? 0 : baseName.hashCode());
result = prime * result + ((baseType == null) ? 0 : baseType.hashCode());
result = prime * result + ((complexType == null) ? 0 : complexType.hashCode());
result = prime * result + ((containerType == null) ? 0 : containerType.hashCode());
result = prime * result + ((datatype == null) ? 0 : datatype.hashCode());
result = prime * result + ((datatypeWithEnum == null) ? 0 : datatypeWithEnum.hashCode());
result = prime * result + ((defaultValue == null) ? 0 : defaultValue.hashCode());
result = prime * result + ((defaultValueWithParam == null) ? 0 : defaultValueWithParam.hashCode());
result = prime * result + ((description == null) ? 0 : description.hashCode());
result = prime * result + ((example == null) ? 0 : example.hashCode());
result = prime * result + ((exclusiveMaximum == null) ? 0 : exclusiveMaximum.hashCode());
result = prime * result + ((exclusiveMinimum == null) ? 0 : exclusiveMinimum.hashCode());
result = prime * result + ((getter == null) ? 0 : getter.hashCode());
result = prime * result + ((hasMore == null) ? 0 : hasMore.hashCode());
result = prime * result + ((isContainer == null) ? 0 : isContainer.hashCode());
result = prime * result + (isEnum ? 1231 : 1237);
result = prime * result + ((isNotContainer == null) ? 0 : isNotContainer.hashCode());
result = prime * result + ((isPrimitiveType == null) ? 0 : isPrimitiveType.hashCode());
result = prime * result + ((isReadOnly == null) ? 0 : isReadOnly.hashCode());
result = prime * result + ((items == null) ? 0 : items.hashCode());
result = prime * result + ((jsonSchema == null) ? 0 : jsonSchema.hashCode());
result = prime * result + ((max == null) ? 0 : max.hashCode());
result = prime * result + ((maxLength == null) ? 0 : maxLength.hashCode());
result = prime * result + ((maximum == null) ? 0 : maximum.hashCode());
result = prime * result + ((min == null) ? 0 : min.hashCode());
result = prime * result + ((minLength == null) ? 0 : minLength.hashCode());
result = prime * result + ((minimum == null) ? 0 : minimum.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + ((pattern == null) ? 0 : pattern.hashCode());
result = prime * result + ((required == null) ? 0 : required.hashCode());
result = prime * result + ((secondaryParam == null) ? 0 : secondaryParam.hashCode());
result = prime * result + ((setter == null) ? 0 : setter.hashCode());
result = prime * result + ((unescapedDescription == null) ? 0 : unescapedDescription.hashCode());
result = prime * result + ((vendorExtensions == null) ? 0 : vendorExtensions.hashCode());
result = prime * result + ((isString == null) ? 0 : isString.hashCode());
result = prime * result + ((isInteger == null) ? 0 : isInteger.hashCode());
result = prime * result + ((isLong == null) ? 0 : isLong.hashCode());
result = prime * result + ((isFloat == null) ? 0 : isFloat.hashCode());
result = prime * result + ((isDouble == null) ? 0 : isDouble.hashCode());
result = prime * result + ((isByteArray == null) ? 0 : isByteArray.hashCode());
result = prime * result + ((isBinary == null) ? 0 : isBinary.hashCode());
result = prime * result + ((isBoolean == null) ? 0 : isBoolean.hashCode());
result = prime * result + ((isDate == null) ? 0 : isDate.hashCode());
result = prime * result + ((isDateTime == null) ? 0 : isDateTime.hashCode());
result = prime * result + ((isMapContainer == null) ? 0 : isMapContainer.hashCode());
result = prime * result + ((isListContainer == null) ? 0 : isListContainer.hashCode());
return result;
}
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
@ -132,12 +191,54 @@ public class CodegenProperty {
if (this.isEnum != other.isEnum) { if (this.isEnum != other.isEnum) {
return false; return false;
} }
if (this.isReadOnly != other.isReadOnly && (this.isReadOnly == null || !this.isReadOnly.equals(other.isReadOnly))) {
return false;
}
if (this._enum != other._enum && (this._enum == null || !this._enum.equals(other._enum))) { if (this._enum != other._enum && (this._enum == null || !this._enum.equals(other._enum))) {
return false; return false;
} }
if (this.allowableValues != other.allowableValues && (this.allowableValues == null || !this.allowableValues.equals(other.allowableValues))) { if (this.allowableValues != other.allowableValues && (this.allowableValues == null || !this.allowableValues.equals(other.allowableValues))) {
return false; return false;
} }
if (this.vendorExtensions != other.vendorExtensions && (this.vendorExtensions == null || !this.vendorExtensions.equals(other.vendorExtensions))) {
return false;
}
if (this.isString != other.isString && (this.isString == null || !this.isString.equals(other.isString))) {
return false;
}
if (this.isInteger != other.isInteger && (this.isInteger == null || !this.isInteger.equals(other.isInteger))) {
return false;
}
if (this.isLong != other.isLong && (this.isLong == null || !this.isLong.equals(other.isLong))) {
return false;
}
if (this.isFloat != other.isFloat && (this.isFloat == null || !this.isFloat.equals(other.isFloat))) {
return false;
}
if (this.isDouble != other.isDouble && (this.isDouble == null || !this.isDouble.equals(other.isDouble))) {
return false;
}
if (this.isByteArray != other.isByteArray && (this.isByteArray == null || !this.isByteArray.equals(other.isByteArray))) {
return false;
}
if (this.isBoolean != other.isBoolean && (this.isBoolean == null || !this.isBoolean.equals(other.isBoolean))) {
return false;
}
if (this.isDate != other.isDate && (this.isDate == null || !this.isDate.equals(other.isDate))) {
return false;
}
if (this.isDateTime != other.isDateTime && (this.isDateTime == null || !this.isDateTime.equals(other.isDateTime))) {
return false;
}
if (this.isBinary != other.isBinary && (this.isBinary == null || !this.isBinary.equals(other.isBinary))) {
return false;
}
if (this.isListContainer != other.isListContainer && (this.isListContainer == null || !this.isListContainer.equals(other.isListContainer))) {
return false;
}
if (this.isMapContainer != other.isMapContainer && (this.isMapContainer == null || !this.isMapContainer.equals(other.isMapContainer))) {
return false;
}
return true; return true;
} }
} }

View File

@ -19,11 +19,11 @@ import static org.apache.commons.lang3.StringUtils.capitalize;
import static org.apache.commons.lang3.StringUtils.isNotEmpty; import static org.apache.commons.lang3.StringUtils.isNotEmpty;
public class DefaultGenerator extends AbstractGenerator implements Generator { public class DefaultGenerator extends AbstractGenerator implements Generator {
Logger LOGGER = LoggerFactory.getLogger(DefaultGenerator.class); protected Logger LOGGER = LoggerFactory.getLogger(DefaultGenerator.class);
protected CodegenConfig config; protected CodegenConfig config;
protected ClientOptInput opts = null; protected ClientOptInput opts;
protected Swagger swagger = null; protected Swagger swagger;
@Override @Override
public Generator opts(ClientOptInput opts) { public Generator opts(ClientOptInput opts) {
@ -129,6 +129,13 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
if (info.getVersion() != null) { if (info.getVersion() != null) {
config.additionalProperties().put("version", info.getVersion()); config.additionalProperties().put("version", info.getVersion());
} }
if (info.getTermsOfService() != null) {
config.additionalProperties().put("termsOfService", info.getTermsOfService());
}
}
if(swagger.getVendorExtensions() != null) {
config.vendorExtensions().putAll(swagger.getVendorExtensions());
} }
StringBuilder hostBuilder = new StringBuilder(); StringBuilder hostBuilder = new StringBuilder();
@ -176,6 +183,10 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
sortedModelKeys = updatedKeys; sortedModelKeys = updatedKeys;
} }
// store all processed models
Map<String,Object> allProcessedModels = new HashMap<String, Object>();
// process models only
for (String name : sortedModelKeys) { for (String name : sortedModelKeys) {
try { try {
//don't generate models that have an import mapping //don't generate models that have an import mapping
@ -188,6 +199,26 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
modelMap.put(name, model); modelMap.put(name, model);
Map<String, Object> models = processModels(config, modelMap, definitions); Map<String, Object> models = processModels(config, modelMap, definitions);
models.putAll(config.additionalProperties()); models.putAll(config.additionalProperties());
allProcessedModels.put(name, models);
} catch (Exception e) {
throw new RuntimeException("Could not process model '" + name + "'", e);
}
}
// post process all processed models
allProcessedModels = config.postProcessAllModels(allProcessedModels);
// generate files based on processed models
for (String name: allProcessedModels.keySet()) {
Map<String, Object> models = (Map<String, Object>)allProcessedModels.get(name);
try {
//don't generate models that have an import mapping
if(config.importMapping().containsKey(name)) {
continue;
}
allModels.add(((List<Object>) models.get("models")).get(0)); allModels.add(((List<Object>) models.get("models")).get(0));
@ -211,6 +242,28 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
writeToFile(filename, tmpl.execute(models)); writeToFile(filename, tmpl.execute(models));
files.add(new File(filename)); files.add(new File(filename));
} }
// to generate model test files
for (String templateName : config.modelTestTemplateFiles().keySet()) {
String suffix = config.modelTestTemplateFiles().get(templateName);
String filename = config.modelTestFileFolder() + File.separator + config.toModelTestFilename(name) + suffix;
if (!config.shouldOverwrite(filename)) {
continue;
}
String templateFile = getFullTemplateFile(config, templateName);
String template = readTemplate(templateFile);
Template tmpl = Mustache.compiler()
.withLoader(new Mustache.TemplateLoader() {
@Override
public Reader getTemplate(String name) {
return getTemplateReader(getFullTemplateFile(config, name + ".mustache"));
}
})
.defaultValue("")
.compile(template);
writeToFile(filename, tmpl.execute(models));
files.add(new File(filename));
}
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException("Could not generate model '" + name + "'", e); throw new RuntimeException("Could not generate model '" + name + "'", e);
} }
@ -218,7 +271,7 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
} }
} }
if (System.getProperty("debugModels") != null) { if (System.getProperty("debugModels") != null) {
System.out.println("############ Model info ############"); LOGGER.info("############ Model info ############");
Json.prettyPrint(allModels); Json.prettyPrint(allModels);
} }
@ -248,6 +301,10 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
operation.put("classname", config.toApiName(tag)); operation.put("classname", config.toApiName(tag));
operation.put("classVarName", config.toApiVarName(tag)); operation.put("classVarName", config.toApiVarName(tag));
operation.put("importPath", config.toApiImport(tag)); operation.put("importPath", config.toApiImport(tag));
if(!config.vendorExtensions().isEmpty()) {
operation.put("vendorExtensions", config.vendorExtensions());
}
// Pass sortParamsByRequiredFlag through to the Mustache template... // Pass sortParamsByRequiredFlag through to the Mustache template...
boolean sortParamsByRequiredFlag = true; boolean sortParamsByRequiredFlag = true;
@ -288,13 +345,37 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
writeToFile(filename, tmpl.execute(operation)); writeToFile(filename, tmpl.execute(operation));
files.add(new File(filename)); files.add(new File(filename));
} }
// to generate api test files
for (String templateName : config.apiTestTemplateFiles().keySet()) {
String filename = config.apiTestFilename(templateName, tag);
if (!config.shouldOverwrite(filename) && new File(filename).exists()) {
continue;
}
String templateFile = getFullTemplateFile(config, templateName);
String template = readTemplate(templateFile);
Template tmpl = Mustache.compiler()
.withLoader(new Mustache.TemplateLoader() {
@Override
public Reader getTemplate(String name) {
return getTemplateReader(getFullTemplateFile(config, name + ".mustache"));
}
})
.defaultValue("")
.compile(template);
writeToFile(filename, tmpl.execute(operation));
files.add(new File(filename));
}
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException("Could not generate api file for '" + tag + "'", e); throw new RuntimeException("Could not generate api file for '" + tag + "'", e);
} }
} }
} }
if (System.getProperty("debugOperations") != null) { if (System.getProperty("debugOperations") != null) {
System.out.println("############ Operation info ############"); LOGGER.info("############ Operation info ############");
Json.prettyPrint(allOperations); Json.prettyPrint(allOperations);
} }
@ -333,7 +414,7 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
config.postProcessSupportingFileData(bundle); config.postProcessSupportingFileData(bundle);
if (System.getProperty("debugSupportingFiles") != null) { if (System.getProperty("debugSupportingFiles") != null) {
System.out.println("############ Supporting file info ############"); LOGGER.info("############ Supporting file info ############");
Json.prettyPrint(bundle); Json.prettyPrint(bundle);
} }
@ -392,18 +473,14 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
} }
File outputFile = new File(outputFilename); File outputFile = new File(outputFilename);
OutputStream out = new FileOutputStream(outputFile, false); OutputStream out = new FileOutputStream(outputFile, false);
if (in != null && out != null) { if (in != null) {
System.out.println("writing file " + outputFile); LOGGER.info("writing file " + outputFile);
IOUtils.copy(in, out); IOUtils.copy(in, out);
} else { } else {
if (in == null) { if (in == null) {
System.out.println("can't open " + templateFile + " for input"); LOGGER.error("can't open " + templateFile + " for input");
}
if (out == null) {
System.out.println("can't open " + outputFile + " for output");
} }
} }
files.add(outputFile); files.add(outputFile);
} }
} }
@ -412,13 +489,11 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
} }
} }
} }
config.processSwagger(swagger); config.processSwagger(swagger);
return files; return files;
} }
private void processMimeTypes(List<String> mimeTypeList, Map<String, Object> operation, String source) { private static void processMimeTypes(List<String> mimeTypeList, Map<String, Object> operation, String source) {
if (mimeTypeList != null && mimeTypeList.size() > 0) { if (mimeTypeList != null && mimeTypeList.size() > 0) {
List<Map<String, String>> c = new ArrayList<Map<String, String>>(); List<Map<String, String>> c = new ArrayList<Map<String, String>>();
int count = 0; int count = 0;
@ -439,7 +514,7 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
} }
} }
private List<String> sortModelsByInheritance(final Map<String, Model> definitions) { private static List<String> sortModelsByInheritance(final Map<String, Model> definitions) {
List<String> sortedModelKeys = new ArrayList<String>(definitions.keySet()); List<String> sortedModelKeys = new ArrayList<String>(definitions.keySet());
Comparator<String> cmp = new Comparator<String>() { Comparator<String> cmp = new Comparator<String>() {
@Override @Override
@ -512,7 +587,8 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
public void processOperation(String resourcePath, String httpMethod, Operation operation, Map<String, List<CodegenOperation>> operations, Path path) { public void processOperation(String resourcePath, String httpMethod, Operation operation, Map<String, List<CodegenOperation>> operations, Path path) {
if (operation != null) { if (operation != null) {
if (System.getProperty("debugOperations") != null) { if (System.getProperty("debugOperations") != null) {
LOGGER.debug("processOperation: resourcePath= " + resourcePath + "\t;" + httpMethod + " " + operation + "\n"); LOGGER.info("processOperation: resourcePath= " + resourcePath + "\t;" + httpMethod + " " + operation
+ "\n");
} }
List<String> tags = operation.getTags(); List<String> tags = operation.getTags();
if (tags == null) { if (tags == null) {
@ -561,35 +637,29 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
continue; continue;
} }
Map<String, SecuritySchemeDefinition> authMethods = new HashMap<String, SecuritySchemeDefinition>(); Map<String, SecuritySchemeDefinition> authMethods = new HashMap<String, SecuritySchemeDefinition>();
// NOTE: Use only the first security requirement for now. for (Map<String, List<String>> security: securities) {
// See the "security" field of "Swagger Object": for (String securityName : security.keySet()) {
// https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md#swagger-object SecuritySchemeDefinition securityDefinition = fromSecurity(securityName);
// "there is a logical OR between the security requirements" if (securityDefinition != null) {
if (securities.size() > 1) { if(securityDefinition instanceof OAuth2Definition) {
LOGGER.warn("More than 1 security requirements are found, using only the first one"); OAuth2Definition oauth2Definition = (OAuth2Definition) securityDefinition;
} OAuth2Definition oauth2Operation = new OAuth2Definition();
Map<String, List<String>> security = securities.get(0); oauth2Operation.setType(oauth2Definition.getType());
for (String securityName : security.keySet()) { oauth2Operation.setAuthorizationUrl(oauth2Definition.getAuthorizationUrl());
SecuritySchemeDefinition securityDefinition = fromSecurity(securityName); oauth2Operation.setFlow(oauth2Definition.getFlow());
if (securityDefinition != null) { oauth2Operation.setTokenUrl(oauth2Definition.getTokenUrl());
if(securityDefinition instanceof OAuth2Definition) { oauth2Operation.setScopes(new HashMap<String, String>());
OAuth2Definition oauth2Definition = (OAuth2Definition) securityDefinition; for (String scope : security.get(securityName)) {
OAuth2Definition oauth2Operation = new OAuth2Definition(); if (oauth2Definition.getScopes().containsKey(scope)) {
oauth2Operation.setType(oauth2Definition.getType()); oauth2Operation.addScope(scope, oauth2Definition.getScopes().get(scope));
oauth2Operation.setAuthorizationUrl(oauth2Definition.getAuthorizationUrl()); }
oauth2Operation.setFlow(oauth2Definition.getFlow()); }
oauth2Operation.setTokenUrl(oauth2Definition.getTokenUrl()); authMethods.put(securityName, oauth2Operation);
oauth2Operation.setScopes(new HashMap<String, String>()); } else {
for (String scope : security.get(securityName)) { authMethods.put(securityName, securityDefinition);
if (oauth2Definition.getScopes().containsKey(scope)) { }
oauth2Operation.addScope(scope, oauth2Definition.getScopes().get(scope)); }
} }
}
authMethods.put(securityName, oauth2Operation);
} else {
authMethods.put(securityName, securityDefinition);
}
}
} }
if (!authMethods.isEmpty()) { if (!authMethods.isEmpty()) {
co.authMethods = config.fromSecurity(authMethods); co.authMethods = config.fromSecurity(authMethods);
@ -609,10 +679,11 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
} }
} }
private String generateParameterId(Parameter parameter) { private static String generateParameterId(Parameter parameter) {
return parameter.getName() + ":" + parameter.getIn(); return parameter.getName() + ":" + parameter.getIn();
} }
@SuppressWarnings("static-method")
protected String sanitizeTag(String tag) { protected String sanitizeTag(String tag) {
// remove spaces and make strong case // remove spaces and make strong case
String[] parts = tag.split(" "); String[] parts = tag.split(" ");
@ -625,6 +696,7 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
return buf.toString().replaceAll("[^a-zA-Z ]", ""); return buf.toString().replaceAll("[^a-zA-Z ]", "");
} }
@SuppressWarnings("static-method")
public Map<String, Object> processOperations(CodegenConfig config, String tag, List<CodegenOperation> ops) { public Map<String, Object> processOperations(CodegenConfig config, String tag, List<CodegenOperation> ops) {
Map<String, Object> operations = new HashMap<String, Object>(); Map<String, Object> operations = new HashMap<String, Object>();
Map<String, Object> objs = new HashMap<String, Object>(); Map<String, Object> objs = new HashMap<String, Object>();
@ -685,6 +757,7 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
return operations; return operations;
} }
@SuppressWarnings("static-method")
public Map<String, Object> processModels(CodegenConfig config, Map<String, Model> definitions, Map<String, Model> allDefinitions) { public Map<String, Object> processModels(CodegenConfig config, Map<String, Model> definitions, Map<String, Model> allDefinitions) {
Map<String, Object> objs = new HashMap<String, Object>(); Map<String, Object> objs = new HashMap<String, Object>();
objs.put("package", config.modelPackage()); objs.put("package", config.modelPackage());
@ -697,29 +770,34 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
mo.put("model", cm); mo.put("model", cm);
mo.put("importPath", config.toModelImport(key)); mo.put("importPath", config.toModelImport(key));
models.add(mo); models.add(mo);
allImports.addAll(cm.imports); allImports.addAll(cm.imports);
} }
objs.put("models", models); objs.put("models", models);
List<Map<String, String>> imports = new ArrayList<Map<String, String>>(); Set<String> importSet = new TreeSet<String>();
for (String nextImport : allImports) { for (String nextImport : allImports) {
Map<String, String> im = new LinkedHashMap<String, String>();
String mapping = config.importMapping().get(nextImport); String mapping = config.importMapping().get(nextImport);
if (mapping == null) { if (mapping == null) {
mapping = config.toModelImport(nextImport); mapping = config.toModelImport(nextImport);
} }
if (mapping != null && !config.defaultIncludes().contains(mapping)) { if (mapping != null && !config.defaultIncludes().contains(mapping)) {
im.put("import", mapping); importSet.add(mapping);
imports.add(im);
} }
// add instantiation types // add instantiation types
mapping = config.instantiationTypes().get(nextImport); mapping = config.instantiationTypes().get(nextImport);
if (mapping != null && !config.defaultIncludes().contains(mapping)) { if (mapping != null && !config.defaultIncludes().contains(mapping)) {
im.put("import", mapping); importSet.add(mapping);
imports.add(im);
} }
} }
List<Map<String, String>> imports = new ArrayList<Map<String, String>>();
for(String s: importSet) {
Map<String, String> item = new HashMap<String, String>();
item.put("import", s);
imports.add(item);
}
objs.put("imports", imports); objs.put("imports", imports);
config.postProcessModels(objs); config.postProcessModels(objs);

View File

@ -1,12 +1,12 @@
package io.swagger.codegen; package io.swagger.codegen;
import com.sun.org.apache.xpath.internal.operations.Mod;
import io.swagger.models.*; import io.swagger.models.*;
import io.swagger.models.parameters.BodyParameter; import io.swagger.models.parameters.BodyParameter;
import io.swagger.models.parameters.Parameter; import io.swagger.models.parameters.Parameter;
import io.swagger.models.parameters.RefParameter;
import io.swagger.models.properties.*; import io.swagger.models.properties.*;
import io.swagger.util.Json; import io.swagger.util.Json;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
@ -14,8 +14,9 @@ import java.util.List;
import java.util.Map; import java.util.Map;
public class InlineModelResolver { public class InlineModelResolver {
private Swagger swagger = null; private Swagger swagger;
private boolean skipMatches = false; private boolean skipMatches;
static Logger LOGGER = LoggerFactory.getLogger(InlineModelResolver.class);
Map<String, Model> addedModels = new HashMap<String, Model>(); Map<String, Model> addedModels = new HashMap<String, Model>();
Map<String, String> generatedSignature = new HashMap<String, String>(); Map<String, String> generatedSignature = new HashMap<String, String>();
@ -60,8 +61,19 @@ public class InlineModelResolver {
Property inner = am.getItems(); Property inner = am.getItems();
if(inner instanceof ObjectProperty) { if(inner instanceof ObjectProperty) {
String modelName = uniqueName(bp.getName());
ObjectProperty op = (ObjectProperty) inner; ObjectProperty op = (ObjectProperty) inner;
flattenProperties(op.getProperties(), pathname); flattenProperties(op.getProperties(), pathname);
Model innerModel = modelFromProperty(op, modelName);
String existing = matchGenerated(innerModel);
if (existing != null) {
am.setItems(new RefProperty(existing));
} else {
am.setItems(new RefProperty(modelName));
addGenerated(modelName, innerModel);
swagger.addDefinition(modelName, innerModel);
}
} }
} }
} }
@ -88,36 +100,38 @@ public class InlineModelResolver {
} }
} else if (property instanceof ArrayProperty) { } else if (property instanceof ArrayProperty) {
ArrayProperty ap = (ArrayProperty) property; ArrayProperty ap = (ArrayProperty) property;
if(ap.getItems() instanceof ObjectProperty) { Property inner = ap.getItems();
ObjectProperty op = (ObjectProperty) ap.getItems();
Map<String, Property> props = op.getProperties();
flattenProperties(props, "path");
}
} else if (property instanceof MapProperty) {
MapProperty op = (MapProperty) property;
Property innerProperty = op.getAdditionalProperties();
if(innerProperty instanceof ObjectProperty) {
ModelImpl innerModel = new ModelImpl();
// TODO: model props
innerModel.setTitle(property.getTitle());
property.getVendorExtensions();
property.getRequired();
property.getReadOnly();
property.getAccess();
innerModel.setDescription(property.getDescription());
innerModel.setExample(property.getExample());
innerModel.setName(property.getName());
innerModel.setXml(property.getXml());
innerModel.setAdditionalProperties(innerProperty);
if(inner instanceof ObjectProperty) {
String modelName = uniqueName("inline_response_" + key); String modelName = uniqueName("inline_response_" + key);
ObjectProperty op = (ObjectProperty) inner;
flattenProperties(op.getProperties(), pathname);
Model innerModel = modelFromProperty(op, modelName);
String existing = matchGenerated(innerModel); String existing = matchGenerated(innerModel);
if (existing != null) { if (existing != null) {
response.setSchema(new RefProperty(existing)); ap.setItems(new RefProperty(existing));
} else { } else {
response.setSchema(new RefProperty(modelName)); ap.setItems(new RefProperty(modelName));
addGenerated(modelName, innerModel);
swagger.addDefinition(modelName, innerModel);
}
}
} else if (property instanceof MapProperty) {
MapProperty mp = (MapProperty) property;
Property innerProperty = mp.getAdditionalProperties();
if(innerProperty instanceof ObjectProperty) {
String modelName = uniqueName("inline_response_" + key);
ObjectProperty op = (ObjectProperty) innerProperty;
flattenProperties(op.getProperties(), pathname);
Model innerModel = modelFromProperty(op, modelName);
String existing = matchGenerated(innerModel);
if (existing != null) {
mp.setAdditionalProperties(new RefProperty(existing));
} else {
mp.setAdditionalProperties(new RefProperty(modelName));
addGenerated(modelName, innerModel); addGenerated(modelName, innerModel);
swagger.addDefinition(modelName, innerModel); swagger.addDefinition(modelName, innerModel);
} }
@ -157,9 +171,7 @@ public class InlineModelResolver {
m.setItems(new RefProperty(existing)); m.setItems(new RefProperty(existing));
} }
} }
} else if (model instanceof ComposedModel) { }
ComposedModel m = (ComposedModel) model;
}
} }
} }
} }
@ -182,7 +194,7 @@ public class InlineModelResolver {
public String uniqueName(String key) { public String uniqueName(String key) {
int count = 0; int count = 0;
boolean done = false; boolean done = false;
key = key.replaceAll("[^a-z_\\.A-Z0-9 ]", ""); key = key.replaceAll("[^a-z_\\.A-Z0-9 ]", ""); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
while (!done) { while (!done) {
String name = key; String name = key;
if (count > 0) { if (count > 0) {
@ -206,7 +218,12 @@ public class InlineModelResolver {
Map<String, Model> modelsToAdd = new HashMap<String, Model>(); Map<String, Model> modelsToAdd = new HashMap<String, Model>();
for (String key : properties.keySet()) { for (String key : properties.keySet()) {
Property property = properties.get(key); Property property = properties.get(key);
if (property instanceof ObjectProperty && ((ObjectProperty)property).getProperties().size() > 0) { if(property instanceof ObjectProperty && ((ObjectProperty)property).getProperties() == null) {
MapProperty mp = new MapProperty();
mp.setAdditionalProperties(new StringProperty());
properties.put(key, mp);
}
else if (property instanceof ObjectProperty && ((ObjectProperty)property).getProperties().size() > 0) {
String modelName = uniqueName(path + "_" + key); String modelName = uniqueName(path + "_" + key);
ObjectProperty op = (ObjectProperty) property; ObjectProperty op = (ObjectProperty) property;
@ -222,6 +239,48 @@ public class InlineModelResolver {
addGenerated(modelName, model); addGenerated(modelName, model);
swagger.addDefinition(modelName, model); swagger.addDefinition(modelName, model);
} }
} else if (property instanceof ArrayProperty) {
ArrayProperty ap = (ArrayProperty) property;
Property inner = ap.getItems();
if (inner instanceof ObjectProperty) {
String modelName = uniqueName(path + "_" + key);
ObjectProperty op = (ObjectProperty) inner;
flattenProperties(op.getProperties(), path);
Model innerModel = modelFromProperty(op, modelName);
String existing = matchGenerated(innerModel);
if (existing != null) {
ap.setItems(new RefProperty(existing));
} else {
ap.setItems(new RefProperty(modelName));
addGenerated(modelName, innerModel);
swagger.addDefinition(modelName, innerModel);
}
}
} else if (property instanceof MapProperty) {
MapProperty mp = (MapProperty) property;
Property inner = mp.getAdditionalProperties();
if (inner instanceof ObjectProperty) {
String modelName = uniqueName(path + "_" + key);
ObjectProperty op = (ObjectProperty) inner;
flattenProperties(op.getProperties(), path);
Model innerModel = modelFromProperty(op, modelName);
String existing = matchGenerated(innerModel);
if (existing != null) {
mp.setAdditionalProperties(new RefProperty(existing));
} else {
mp.setAdditionalProperties(new RefProperty(modelName));
addGenerated(modelName, innerModel);
swagger.addDefinition(modelName, innerModel);
}
}
} }
} }
if (propsToUpdate.size() > 0) { if (propsToUpdate.size() > 0) {
@ -235,53 +294,36 @@ public class InlineModelResolver {
} }
} }
public Model modelFromProperty(ArrayProperty object, String path) { @SuppressWarnings("static-method")
String access = object.getAccess(); public Model modelFromProperty(ArrayProperty object, @SuppressWarnings("unused") String path) {
String description = object.getDescription(); String description = object.getDescription();
String example = object.getExample(); String example = null;
String name = object.getName();
Integer position = object.getPosition();
Boolean readOnly = object.getReadOnly();
Boolean required = object.getRequired();
String title = object.getTitle();
Map<String, Object> extensions = object.getVendorExtensions();
Xml xml = object.getXml();
// object.getItems()
// Map<String, Property> properties = object.getProperties();
Object obj = object.getExample();
if(obj != null) {
example = obj.toString();
}
Property inner = object.getItems(); Property inner = object.getItems();
if (inner instanceof ObjectProperty) { if (inner instanceof ObjectProperty) {
ArrayModel model = new ArrayModel(); ArrayModel model = new ArrayModel();
model.setDescription(description); model.setDescription(description);
model.setExample(example); model.setExample(example);
// model.setName(name);
// model.setXml(xml);
model.setItems(object.getItems()); model.setItems(object.getItems());
return model; return model;
} }
// if(properties != null) {
// flattenProperties(properties, path);
// model.setProperties(properties);
// }
return null; return null;
} }
public Model modelFromProperty(ObjectProperty object, String path) { public Model modelFromProperty(ObjectProperty object, String path) {
String access = object.getAccess();
String description = object.getDescription(); String description = object.getDescription();
String example = object.getExample(); String example = null;
String name = object.getName();
Integer position = object.getPosition();
Boolean readOnly = object.getReadOnly();
Boolean required = object.getRequired();
String title = object.getTitle();
Map<String, Object> extensions = object.getVendorExtensions();
Xml xml = object.getXml();
Object obj = object.getExample();
if(obj != null) {
example = obj.toString();
}
String name = object.getName();
Xml xml = object.getXml();
Map<String, Property> properties = object.getProperties(); Map<String, Property> properties = object.getProperties();
ModelImpl model = new ModelImpl(); ModelImpl model = new ModelImpl();
@ -298,17 +340,15 @@ public class InlineModelResolver {
return model; return model;
} }
public Model modelFromProperty(MapProperty object, String path) { @SuppressWarnings("static-method")
String access = object.getAccess(); public Model modelFromProperty(MapProperty object, @SuppressWarnings("unused") String path) {
String description = object.getDescription(); String description = object.getDescription();
String example = object.getExample(); String example = null;
String name = object.getName();
Integer position = object.getPosition(); Object obj = object.getExample();
Boolean readOnly = object.getReadOnly(); if(obj != null) {
Boolean required = object.getRequired(); example = obj.toString();
String title = object.getTitle(); }
Map<String, Object> extensions = object.getVendorExtensions();
Xml xml = object.getXml();
ArrayModel model = new ArrayModel(); ArrayModel model = new ArrayModel();
model.setDescription(description); model.setDescription(description);
@ -325,4 +365,5 @@ public class InlineModelResolver {
public void setSkipMatches(boolean skipMatches) { public void setSkipMatches(boolean skipMatches) {
this.skipMatches = skipMatches; this.skipMatches = skipMatches;
} }
} }

View File

@ -2,15 +2,17 @@ package io.swagger.codegen;
import com.samskivert.mustache.Mustache; import com.samskivert.mustache.Mustache;
import com.samskivert.mustache.Template; import com.samskivert.mustache.Template;
import io.swagger.models.Swagger;
import org.apache.commons.cli.BasicParser; import org.apache.commons.cli.BasicParser;
import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser; import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.HelpFormatter; import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Options; import org.apache.commons.cli.Options;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.io.Reader; import java.io.Reader;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
@ -25,6 +27,9 @@ import java.util.ServiceLoader;
*/ */
@Deprecated @Deprecated
public class MetaGenerator extends AbstractGenerator { public class MetaGenerator extends AbstractGenerator {
private static final Logger LOGGER = LoggerFactory.getLogger(MetaGenerator.class);
static Map<String, CodegenConfig> configs = new HashMap<String, CodegenConfig>(); static Map<String, CodegenConfig> configs = new HashMap<String, CodegenConfig>();
static String configString; static String configString;
@ -57,8 +62,6 @@ public class MetaGenerator extends AbstractGenerator {
} }
protected void generate(String[] args) { protected void generate(String[] args) {
StringBuilder sb = new StringBuilder();
String targetLanguage = null;
String outputFolder = null; String outputFolder = null;
String name = null; String name = null;
String targetPackage = "io.swagger.codegen"; String targetPackage = "io.swagger.codegen";
@ -71,12 +74,9 @@ public class MetaGenerator extends AbstractGenerator {
options.addOption("n", "name", true, "the human-readable name of the generator"); options.addOption("n", "name", true, "the human-readable name of the generator");
options.addOption("p", "package", true, "the package to put the main class into (defaults to io.swagger.codegen"); options.addOption("p", "package", true, "the package to put the main class into (defaults to io.swagger.codegen");
ClientOptInput clientOptInput = new ClientOptInput();
Swagger swagger = null;
CommandLine cmd = null; CommandLine cmd = null;
try { try {
CommandLineParser parser = new BasicParser(); CommandLineParser parser = new BasicParser();
cmd = parser.parse(options, args); cmd = parser.parse(options, args);
if (cmd.hasOption("h")) { if (cmd.hasOption("h")) {
usage(options); usage(options);
@ -85,12 +85,11 @@ public class MetaGenerator extends AbstractGenerator {
if (cmd.hasOption("n")) { if (cmd.hasOption("n")) {
name = cmd.getOptionValue("n"); name = cmd.getOptionValue("n");
} else { } else {
System.out.println("name is required"); System.out.println("name is required"); //FIXME replace by LOGGER
usage(options); usage(options);
return; return;
} }
if (cmd.hasOption("l")) { if (cmd.hasOption("l")) {
targetLanguage = cmd.getOptionValue("l");
} }
if (cmd.hasOption("p")) { if (cmd.hasOption("p")) {
targetPackage = cmd.getOptionValue("p"); targetPackage = cmd.getOptionValue("p");
@ -98,7 +97,7 @@ public class MetaGenerator extends AbstractGenerator {
if (cmd.hasOption("o")) { if (cmd.hasOption("o")) {
outputFolder = cmd.getOptionValue("o"); outputFolder = cmd.getOptionValue("o");
} else { } else {
System.out.println("output folder is required"); System.out.println("output folder is required"); // FIXME replace by LOGGER
usage(options); usage(options);
return; return;
} }
@ -106,7 +105,7 @@ public class MetaGenerator extends AbstractGenerator {
usage(options); usage(options);
return; return;
} }
System.out.println("writing to folder " + outputFolder); LOGGER.info("writing to folder " + outputFolder);
File outputFolderLocation = new File(outputFolder); File outputFolderLocation = new File(outputFolder);
if (!outputFolderLocation.exists()) { if (!outputFolderLocation.exists()) {
outputFolderLocation.mkdirs(); outputFolderLocation.mkdirs();
@ -157,11 +156,10 @@ public class MetaGenerator extends AbstractGenerator {
String template = readTemplate(templateDir + File.separator + support.templateFile); String template = readTemplate(templateDir + File.separator + support.templateFile);
Template tmpl = Mustache.compiler() Template tmpl = Mustache.compiler()
.withLoader(new Mustache.TemplateLoader() { .withLoader(new Mustache.TemplateLoader() {
@Override
public Reader getTemplate(String name) { public Reader getTemplate(String name) {
return getTemplateReader(templateDir + File.separator + name + ".mustache"); return getTemplateReader(templateDir + File.separator + name + ".mustache");
} }
;
}) })
.defaultValue("") .defaultValue("")
.compile(template); .compile(template);
@ -171,11 +169,11 @@ public class MetaGenerator extends AbstractGenerator {
} else { } else {
String template = readTemplate(templateDir + File.separator + support.templateFile); String template = readTemplate(templateDir + File.separator + support.templateFile);
FileUtils.writeStringToFile(new File(outputFilename), template); FileUtils.writeStringToFile(new File(outputFilename), template);
System.out.println("copying file to " + outputFilename); LOGGER.info("copying file to " + outputFilename);
files.add(new File(outputFilename)); files.add(new File(outputFilename));
} }
} catch (java.io.IOException e) { } catch (IOException e) {
e.printStackTrace(); LOGGER.error(e.getMessage(), e);
} }
} }
} }

View File

@ -11,6 +11,7 @@ public class SupportingFile {
this.destinationFilename = destinationFilename; this.destinationFilename = destinationFilename;
} }
@Override
public String toString() { public String toString() {
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
builder.append("SupportingFile:").append("\n"); builder.append("SupportingFile:").append("\n");

View File

@ -7,9 +7,16 @@ import java.net.URLEncoder;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import config.ConfigParser;
import static org.apache.commons.lang3.StringUtils.isNotEmpty; import static org.apache.commons.lang3.StringUtils.isNotEmpty;
public class AuthParser { public class AuthParser {
private static final Logger LOGGER = LoggerFactory.getLogger(AuthParser.class);
public static List<AuthorizationValue> parse(String urlEncodedAuthStr) { public static List<AuthorizationValue> parse(String urlEncodedAuthStr) {
List<AuthorizationValue> auths = new ArrayList<AuthorizationValue>(); List<AuthorizationValue> auths = new ArrayList<AuthorizationValue>();
@ -18,7 +25,7 @@ public class AuthParser {
for (String part : parts) { for (String part : parts) {
String[] kvPair = part.split(":"); String[] kvPair = part.split(":");
if (kvPair.length == 2) { if (kvPair.length == 2) {
auths.add(new AuthorizationValue(URLDecoder.decode(kvPair[0]), URLDecoder.decode(kvPair[1]), "header")); auths.add(new AuthorizationValue(URLDecoder.decode(kvPair[0]), URLDecoder.decode(kvPair[1]), "header")); // FIXME replace the deprecated method by decode(string, encoding). Which encoding is used ? Default UTF-8 ?
} }
} }
} }
@ -38,7 +45,7 @@ public class AuthParser {
.append(URLEncoder.encode(v.getValue(), "UTF-8")); .append(URLEncoder.encode(v.getValue(), "UTF-8"));
} catch (Exception e) { } catch (Exception e) {
// continue // continue
e.printStackTrace(); LOGGER.error(e.getMessage(), e);
} }
} }
return b.toString(); return b.toString();

View File

@ -36,18 +36,20 @@ import static org.apache.commons.lang3.StringUtils.isNotEmpty;
*/ */
public class CodegenConfigurator { public class CodegenConfigurator {
public static final Logger LOG = LoggerFactory.getLogger(CodegenConfigurator.class); public static final Logger LOGGER = LoggerFactory.getLogger(CodegenConfigurator.class);
private String lang; private String lang;
private String inputSpec; private String inputSpec;
private String outputDir; private String outputDir;
private boolean verbose = false; private boolean verbose;
private boolean skipOverwrite = false; private boolean skipOverwrite;
private String templateDir; private String templateDir;
private String auth; private String auth;
private String apiPackage; private String apiPackage;
private String modelPackage; private String modelPackage;
private String invokerPackage; private String invokerPackage;
private String modelNamePrefix;
private String modelNameSuffix;
private String groupId; private String groupId;
private String artifactId; private String artifactId;
private String artifactVersion; private String artifactVersion;
@ -97,6 +99,24 @@ public class CodegenConfigurator {
return this; return this;
} }
public String getModelNamePrefix() {
return modelNamePrefix;
}
public CodegenConfigurator setModelNamePrefix(String prefix) {
this.modelNamePrefix = prefix;
return this;
}
public String getModelNameSuffix() {
return modelNameSuffix;
}
public CodegenConfigurator setModelNameSuffix(String suffix) {
this.modelNameSuffix = suffix;
return this;
}
public boolean isVerbose() { public boolean isVerbose() {
return verbose; return verbose;
} }
@ -300,6 +320,8 @@ public class CodegenConfigurator {
checkAndSetAdditionalProperty(artifactId, CodegenConstants.ARTIFACT_ID); checkAndSetAdditionalProperty(artifactId, CodegenConstants.ARTIFACT_ID);
checkAndSetAdditionalProperty(artifactVersion, CodegenConstants.ARTIFACT_VERSION); checkAndSetAdditionalProperty(artifactVersion, CodegenConstants.ARTIFACT_VERSION);
checkAndSetAdditionalProperty(templateDir, toAbsolutePathStr(templateDir), CodegenConstants.TEMPLATE_DIR); checkAndSetAdditionalProperty(templateDir, toAbsolutePathStr(templateDir), CodegenConstants.TEMPLATE_DIR);
checkAndSetAdditionalProperty(modelNamePrefix, CodegenConstants.MODEL_NAME_PREFIX);
checkAndSetAdditionalProperty(modelNameSuffix, CodegenConstants.MODEL_NAME_SUFFIX);
handleDynamicProperties(config); handleDynamicProperties(config);
@ -349,7 +371,7 @@ public class CodegenConfigurator {
if (!verbose) { if (!verbose) {
return; return;
} }
LOG.info("\nVERBOSE MODE: ON. Additional debug options are injected" + LOGGER.info("\nVERBOSE MODE: ON. Additional debug options are injected" +
"\n - [debugSwagger] prints the swagger specification as interpreted by the codegen" + "\n - [debugSwagger] prints the swagger specification as interpreted by the codegen" +
"\n - [debugModels] prints models passed to the template engine" + "\n - [debugModels] prints models passed to the template engine" +
"\n - [debugOperations] prints operations passed to the template engine" + "\n - [debugOperations] prints operations passed to the template engine" +
@ -390,10 +412,9 @@ public class CodegenConfigurator {
if (isNotEmpty(configFile)) { if (isNotEmpty(configFile)) {
try { try {
CodegenConfigurator result = Json.mapper().readValue(new File(configFile), CodegenConfigurator.class); return Json.mapper().readValue(new File(configFile), CodegenConfigurator.class);
return result;
} catch (IOException e) { } catch (IOException e) {
LOG.error("Unable to deserialize config file: " + configFile, e); LOGGER.error("Unable to deserialize config file: " + configFile, e);
} }
} }
return null; return null;

View File

@ -42,7 +42,7 @@ public class ExampleGenerator {
if (examples == null) { if (examples == null) {
if (mediaTypes == null) { if (mediaTypes == null) {
// assume application/json for this // assume application/json for this
mediaTypes = Arrays.asList("application/json"); mediaTypes = Arrays.asList("application/json"); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
} }
for (String mediaType : mediaTypes) { for (String mediaType : mediaTypes) {
Map<String, String> kv = new HashMap<String, String>(); Map<String, String> kv = new HashMap<String, String>();
@ -88,15 +88,14 @@ public class ExampleGenerator {
} else if (property instanceof ArrayProperty) { } else if (property instanceof ArrayProperty) {
Property innerType = ((ArrayProperty) property).getItems(); Property innerType = ((ArrayProperty) property).getItems();
if (innerType != null) { if (innerType != null) {
Object[] output = new Object[]{ return new Object[]{
resolvePropertyToExample(mediaType, innerType, processedModels) resolvePropertyToExample(mediaType, innerType, processedModels)
}; };
return output;
} }
} else if (property instanceof DateProperty) { } else if (property instanceof DateProperty) {
return new java.util.Date(System.currentTimeMillis()); return "2000-01-23T04:56:07.000+0000";
} else if (property instanceof DateTimeProperty) { } else if (property instanceof DateTimeProperty) {
return new java.util.Date(System.currentTimeMillis()); return "2000-01-23T04:56:07.000+0000";
} else if (property instanceof DecimalProperty) { } else if (property instanceof DecimalProperty) {
return new BigDecimal(1.3579); return new BigDecimal(1.3579);
} else if (property instanceof DoubleProperty) { } else if (property instanceof DoubleProperty) {
@ -128,7 +127,7 @@ public class ExampleGenerator {
return resolveModelToExample(simpleName, mediaType, model, processedModels); return resolveModelToExample(simpleName, mediaType, model, processedModels);
} }
} else if (property instanceof UUIDProperty) { } else if (property instanceof UUIDProperty) {
return "046b6c7f-0b8a-43b9-b35d-6489e6daee91"; return "046b6c7f-0b8a-43b9-b35d-6489e6daee91";
} }
return ""; return "";
@ -143,16 +142,14 @@ public class ExampleGenerator {
ModelImpl impl = (ModelImpl) model; ModelImpl impl = (ModelImpl) model;
Map<String, Object> values = new HashMap<String, Object>(); Map<String, Object> values = new HashMap<String, Object>();
if (impl != null && impl.getProperties() != null) { if (impl.getProperties() != null) {
for (String propertyName : impl.getProperties().keySet()) { for (String propertyName : impl.getProperties().keySet()) {
Property property = impl.getProperties().get(propertyName); Property property = impl.getProperties().get(propertyName);
values.put(propertyName, resolvePropertyToExample(mediaType, property, processedModels)); values.put(propertyName, resolvePropertyToExample(mediaType, property, processedModels));
} }
} }
return values; return values;
} }
return ""; return "";
} }
} }

View File

@ -16,10 +16,8 @@ import io.swagger.models.properties.RefProperty;
import io.swagger.models.properties.StringProperty; import io.swagger.models.properties.StringProperty;
import org.codehaus.plexus.util.StringUtils; import org.codehaus.plexus.util.StringUtils;
import java.text.SimpleDateFormat;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
@ -33,13 +31,11 @@ public class XmlExampleGenerator {
public static String TAG_END = "</"; public static String TAG_END = "</";
private static String EMPTY = ""; private static String EMPTY = "";
protected Map<String, Model> examples; protected Map<String, Model> examples;
protected SimpleDateFormat dtFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
protected SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
public XmlExampleGenerator(Map<String, Model> examples) { public XmlExampleGenerator(Map<String, Model> examples) {
this.examples = examples; this.examples = examples;
if (examples == null) { if (examples == null) {
examples = new HashMap<String, Model>(); this.examples = new HashMap<String, Model>();
} }
} }
@ -74,10 +70,6 @@ public class XmlExampleGenerator {
Map<String, Property> elements = new LinkedHashMap<String, Property>(); Map<String, Property> elements = new LinkedHashMap<String, Property>();
String name = modelName; String name = modelName;
String namespace;
String prefix;
Boolean wrapped;
Xml xml = model.getXml(); Xml xml = model.getXml();
if (xml != null) { if (xml != null) {
if (xml.getName() != null) { if (xml.getName() != null) {
@ -117,6 +109,7 @@ public class XmlExampleGenerator {
return sb.toString(); return sb.toString();
} }
@SuppressWarnings("static-method")
protected String quote(String string) { protected String quote(String string) {
return "\"" + string + "\""; return "\"" + string + "\"";
} }
@ -173,37 +166,37 @@ public class XmlExampleGenerator {
protected String getExample(Property property) { protected String getExample(Property property) {
if (property instanceof DateTimeProperty) { if (property instanceof DateTimeProperty) {
if (property.getExample() != null) { if (property.getExample() != null) {
return property.getExample(); return property.getExample().toString();
} else { } else {
return dtFormat.format(new Date()); return "2000-01-23T04:56:07.000Z";
} }
} else if (property instanceof StringProperty) { } else if (property instanceof StringProperty) {
if (property.getExample() != null) { if (property.getExample() != null) {
return property.getExample(); return property.getExample().toString();
} else { } else {
return "string"; return "string";
} }
} else if (property instanceof DateProperty) { } else if (property instanceof DateProperty) {
if (property.getExample() != null) { if (property.getExample() != null) {
return property.getExample(); return property.getExample().toString();
} else { } else {
return dateFormat.format(new Date()); return "2000-01-23T04:56:07.000Z";
} }
} else if (property instanceof IntegerProperty) { } else if (property instanceof IntegerProperty) {
if (property.getExample() != null) { if (property.getExample() != null) {
return property.getExample(); return property.getExample().toString();
} else { } else {
return "0"; return "0";
} }
} else if (property instanceof BooleanProperty) { } else if (property instanceof BooleanProperty) {
if (property.getExample() != null) { if (property.getExample() != null) {
return property.getExample(); return property.getExample().toString();
} else { } else {
return "true"; return "true";
} }
} else if (property instanceof LongProperty) { } else if (property instanceof LongProperty) {
if (property.getExample() != null) { if (property.getExample() != null) {
return property.getExample(); return property.getExample().toString();
} else { } else {
return "123456"; return "123456";
} }
@ -211,14 +204,17 @@ public class XmlExampleGenerator {
return "not implemented " + property; return "not implemented " + property;
} }
@SuppressWarnings("static-method")
protected String openTag(String name) { protected String openTag(String name) {
return "<" + name + ">"; return "<" + name + ">";
} }
@SuppressWarnings("static-method")
protected String closeTag(String name) { protected String closeTag(String name) {
return "</" + name + ">"; return "</" + name + ">";
} }
@SuppressWarnings("static-method")
protected String indent(int indent) { protected String indent(int indent) {
StringBuffer sb = new StringBuffer(); StringBuffer sb = new StringBuffer();
for (int i = 0; i < indent; i++) { for (int i = 0; i < indent; i++) {

View File

@ -0,0 +1,518 @@
package io.swagger.codegen.languages;
import io.swagger.codegen.*;
import io.swagger.models.properties.*;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.util.*;
public abstract class AbstractCSharpCodegen extends DefaultCodegen implements CodegenConfig {
protected boolean optionalAssemblyInfoFlag = true;
protected boolean optionalProjectFileFlag = false;
protected boolean optionalMethodArgumentFlag = true;
protected boolean useDateTimeOffsetFlag = false;
protected boolean useCollection = false;
protected boolean returnICollection = false;
protected String packageVersion = "1.0.0";
protected String packageName = "IO.Swagger";
protected String sourceFolder = "src" + File.separator + packageName;
protected Set<String> collectionTypes;
protected Set<String> mapTypes;
protected Logger LOGGER = LoggerFactory.getLogger(AbstractCSharpCodegen.class);
public AbstractCSharpCodegen() {
super();
outputFolder = "generated-code" + File.separator + this.getName();
embeddedTemplateDir = templateDir = this.getName();
collectionTypes = new HashSet<String>(
Arrays.asList(
"IList", "List",
"ICollection", "Collection",
"IEnumerable")
);
mapTypes = new HashSet<String>(
Arrays.asList("IDictionary")
);
setReservedWordsLowerCase(
Arrays.asList(
// local variable names in API methods (endpoints)
"localVarPath", "localVarPathParams", "localVarQueryParams", "localVarHeaderParams",
"localVarFormParams", "localVarFileParams", "localVarStatusCode", "localVarResponse",
"localVarPostBody", "localVarHttpHeaderAccepts", "localVarHttpHeaderAccept",
"localVarHttpContentTypes", "localVarHttpContentType",
"localVarStatusCode",
// C# reserved words
"abstract", "as", "base", "bool", "break", "byte", "case", "catch", "char", "checked",
"class", "const", "continue", "decimal", "default", "delegate", "do", "double", "else",
"enum", "event", "explicit", "extern", "false", "finally", "fixed", "float", "for",
"foreach", "goto", "if", "implicit", "in", "int", "interface", "internal", "is", "lock",
"long", "namespace", "new", "null", "object", "operator", "out", "override", "params",
"private", "protected", "public", "readonly", "ref", "return", "sbyte", "sealed",
"short", "sizeof", "stackalloc", "static", "string", "struct", "switch", "this", "throw",
"true", "try", "typeof", "uint", "ulong", "unchecked", "unsafe", "ushort", "using",
"virtual", "void", "volatile", "while")
);
// TODO: Either include fully qualified names here or handle in DefaultCodegen via lastIndexOf(".") search
languageSpecificPrimitives = new HashSet<String>(
Arrays.asList(
"String",
"string",
"bool?",
"double?",
"int?",
"long?",
"float?",
"byte[]",
"ICollection",
"Collection",
"List",
"Dictionary",
"DateTime?",
"DateTimeOffset?",
"String",
"Boolean",
"Double",
"Int32",
"Int64",
"Float",
"Guid",
"Stream", // not really a primitive, we include it to avoid model import
"Object")
);
instantiationTypes.put("array", "List");
instantiationTypes.put("list", "List");
instantiationTypes.put("map", "Dictionary");
// Nullable types here assume C# 2 support is not part of base
typeMapping = new HashMap<String, String>();
typeMapping.put("string", "string");
typeMapping.put("binary", "byte[]");
typeMapping.put("boolean", "bool?");
typeMapping.put("integer", "int?");
typeMapping.put("float", "float?");
typeMapping.put("long", "long?");
typeMapping.put("double", "double?");
typeMapping.put("number", "double?");
typeMapping.put("datetime", "DateTime?");
typeMapping.put("date", "DateTime?");
typeMapping.put("file", "Stream");
typeMapping.put("array", "List");
typeMapping.put("list", "List");
typeMapping.put("map", "Dictionary");
typeMapping.put("object", "Object");
typeMapping.put("uuid", "Guid");
}
public void setReturnICollection(boolean returnICollection) {
this.returnICollection = returnICollection;
}
public void setUseCollection(boolean useCollection) {
this.useCollection = useCollection;
if (useCollection) {
typeMapping.put("array", "Collection");
typeMapping.put("list", "Collection");
instantiationTypes.put("array", "Collection");
instantiationTypes.put("list", "Collection");
}
}
public void setOptionalMethodArgumentFlag(boolean flag) {
this.optionalMethodArgumentFlag = flag;
}
protected void addOption(String key, String description, String defaultValue) {
CliOption option = new CliOption(key, description);
if (defaultValue != null) option.defaultValue(defaultValue);
cliOptions.add(option);
}
protected void addSwitch(String key, String description, Boolean defaultValue) {
CliOption option = CliOption.newBoolean(key, description);
if (defaultValue != null) option.defaultValue(defaultValue.toString());
cliOptions.add(option);
}
public void useDateTimeOffset(boolean flag) {
this.useDateTimeOffsetFlag = flag;
if (flag) typeMapping.put("datetime", "DateTimeOffset?");
else typeMapping.put("datetime", "DateTime?");
}
@Override
public void processOpts() {
super.processOpts();
// {{packageVersion}}
if (additionalProperties.containsKey(CodegenConstants.PACKAGE_VERSION)) {
setPackageVersion((String) additionalProperties.get(CodegenConstants.PACKAGE_VERSION));
} else {
additionalProperties.put(CodegenConstants.PACKAGE_VERSION, packageVersion);
}
// {{sourceFolder}}
if (additionalProperties.containsKey(CodegenConstants.SOURCE_FOLDER)) {
setSourceFolder((String) additionalProperties.get(CodegenConstants.SOURCE_FOLDER));
} else {
additionalProperties.put(CodegenConstants.SOURCE_FOLDER, this.sourceFolder);
}
// {{packageName}}
if (additionalProperties.containsKey(CodegenConstants.PACKAGE_NAME)) {
setPackageName((String) additionalProperties.get(CodegenConstants.PACKAGE_NAME));
} else {
additionalProperties.put(CodegenConstants.PACKAGE_NAME, packageName);
}
// {{useDateTimeOffset}}
if (additionalProperties.containsKey(CodegenConstants.USE_DATETIME_OFFSET)) {
useDateTimeOffset(Boolean.valueOf(additionalProperties.get(CodegenConstants.USE_DATETIME_OFFSET).toString()));
}
additionalProperties.put(CodegenConstants.USE_DATETIME_OFFSET, useDateTimeOffsetFlag);
if (additionalProperties.containsKey(CodegenConstants.USE_COLLECTION)) {
setUseCollection(Boolean.valueOf(additionalProperties.get(CodegenConstants.USE_COLLECTION).toString()));
}
if (additionalProperties.containsKey(CodegenConstants.RETURN_ICOLLECTION)) {
setReturnICollection(Boolean.valueOf(additionalProperties.get(CodegenConstants.RETURN_ICOLLECTION).toString()));
}
}
@Override
public Map<String, Object> postProcessModels(Map<String, Object> objs) {
List<Object> models = (List<Object>) objs.get("models");
for (Object _mo : models) {
Map<String, Object> mo = (Map<String, Object>) _mo;
CodegenModel cm = (CodegenModel) mo.get("model");
for (CodegenProperty var : cm.vars) {
// check to see if model name is same as the property name
// which will result in compilation error
// if found, prepend with _ to workaround the limitation
if (var.name.equals(cm.name)) {
var.name = "_" + var.name;
}
}
}
return objs;
}
@Override
public Map<String, Object> postProcessOperations(Map<String, Object> objs) {
super.postProcessOperations(objs);
if (objs != null) {
Map<String, Object> operations = (Map<String, Object>) objs.get("operations");
if (operations != null) {
List<CodegenOperation> ops = (List<CodegenOperation>) operations.get("operation");
for (CodegenOperation operation : ops) {
// Check return types for collection
if (operation.returnType != null) {
String typeMapping;
int namespaceEnd = operation.returnType.lastIndexOf(".");
if (namespaceEnd > 0) {
typeMapping = operation.returnType.substring(namespaceEnd);
} else {
typeMapping = operation.returnType;
}
if (this.collectionTypes.contains(typeMapping)) {
operation.isListContainer = true;
operation.returnContainer = operation.returnType;
if (this.returnICollection && (
typeMapping.startsWith("List") ||
typeMapping.startsWith("Collection"))) {
// NOTE: ICollection works for both List<T> and Collection<T>
int genericStart = typeMapping.indexOf("<");
if (genericStart > 0) {
operation.returnType = "ICollection" + typeMapping.substring(genericStart);
}
}
} else {
operation.returnContainer = operation.returnType;
operation.isMapContainer = this.mapTypes.contains(typeMapping);
}
}
processOperation(operation);
}
}
}
return objs;
}
protected void processOperation(CodegenOperation operation) {
// default noop
}
@Override
public String apiFileFolder() {
return outputFolder + File.separator + sourceFolder + File.separator + apiPackage().replace('.', File.separatorChar);
}
@Override
public String modelFileFolder() {
return outputFolder + File.separator + sourceFolder + File.separator + modelPackage().replace('.', File.separatorChar);
}
@Override
public String toModelFilename(String name) {
// should be the same as the model name
return toModelName(name);
}
@Override
public String toOperationId(String operationId) {
// throw exception if method name is empty (should not occur as an auto-generated method name will be used)
if (StringUtils.isEmpty(operationId)) {
throw new RuntimeException("Empty method name (operationId) not allowed");
}
// method name cannot use reserved keyword, e.g. return
if (isReservedWord(operationId)) {
LOGGER.warn(operationId + " (reserved word) cannot be used as method name. Renamed to " + camelize(sanitizeName("call_" + operationId)));
operationId = "call_" + operationId;
}
return camelize(sanitizeName(operationId));
}
@Override
public String toVarName(String name) {
// sanitize name
name = sanitizeName(name);
// if it's all uppper case, do nothing
if (name.matches("^[A-Z_]*$")) {
return name;
}
// camelize the variable name
// pet_id => PetId
name = camelize(name);
// for reserved word or word starting with number, append _
if (isReservedWord(name) || name.matches("^\\d.*")) {
name = escapeReservedWord(name);
}
return name;
}
@Override
public String toParamName(String name) {
// sanitize name
name = sanitizeName(name);
// replace - with _ e.g. created-at => created_at
name = name.replaceAll("-", "_");
// if it's all uppper case, do nothing
if (name.matches("^[A-Z_]*$")) {
return name;
}
// camelize(lower) the variable name
// pet_id => petId
name = camelize(name, true);
// for reserved word or word starting with number, append _
if (isReservedWord(name) || name.matches("^\\d.*")) {
name = escapeReservedWord(name);
}
return name;
}
@Override
public String escapeReservedWord(String name) {
return "_" + name;
}
/**
* Return the example value of the property
*
* @param p Swagger property object
* @return string presentation of the example value of the property
*/
@Override
public String toExampleValue(Property p) {
if (p instanceof StringProperty) {
StringProperty dp = (StringProperty) p;
if (dp.getExample() != null) {
return "\"" + dp.getExample().toString() + "\"";
}
} else if (p instanceof BooleanProperty) {
BooleanProperty dp = (BooleanProperty) p;
if (dp.getExample() != null) {
return dp.getExample().toString();
}
} else if (p instanceof DateProperty) {
// TODO
} else if (p instanceof DateTimeProperty) {
// TODO
} else if (p instanceof DoubleProperty) {
DoubleProperty dp = (DoubleProperty) p;
if (dp.getExample() != null) {
return dp.getExample().toString();
}
} else if (p instanceof FloatProperty) {
FloatProperty dp = (FloatProperty) p;
if (dp.getExample() != null) {
return dp.getExample().toString();
}
} else if (p instanceof IntegerProperty) {
IntegerProperty dp = (IntegerProperty) p;
if (dp.getExample() != null) {
return dp.getExample().toString();
}
} else if (p instanceof LongProperty) {
LongProperty dp = (LongProperty) p;
if (dp.getExample() != null) {
return dp.getExample().toString();
}
}
return null;
}
/**
* Return the default value of the property
*
* @param p Swagger property object
* @return string presentation of the default value of the property
*/
@Override
public String toDefaultValue(Property p) {
if (p instanceof StringProperty) {
StringProperty dp = (StringProperty) p;
if (dp.getDefault() != null) {
return "\"" + dp.getDefault().toString() + "\"";
}
} else if (p instanceof BooleanProperty) {
BooleanProperty dp = (BooleanProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
} else if (p instanceof DateProperty) {
// TODO
} else if (p instanceof DateTimeProperty) {
// TODO
} else if (p instanceof DoubleProperty) {
DoubleProperty dp = (DoubleProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
} else if (p instanceof FloatProperty) {
FloatProperty dp = (FloatProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
} else if (p instanceof IntegerProperty) {
IntegerProperty dp = (IntegerProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
} else if (p instanceof LongProperty) {
LongProperty dp = (LongProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
}
return null;
}
@Override
public String getSwaggerType(Property p) {
String swaggerType = super.getSwaggerType(p);
String type;
if (typeMapping.containsKey(swaggerType.toLowerCase())) {
type = typeMapping.get(swaggerType.toLowerCase());
if (languageSpecificPrimitives.contains(type)) {
return type;
}
} else {
type = swaggerType;
}
return toModelName(type);
}
@Override
public String getTypeDeclaration(Property p) {
if (p instanceof ArrayProperty) {
ArrayProperty ap = (ArrayProperty) p;
Property inner = ap.getItems();
return getSwaggerType(p) + "<" + getTypeDeclaration(inner) + ">";
} else if (p instanceof MapProperty) {
MapProperty mp = (MapProperty) p;
Property inner = mp.getAdditionalProperties();
return getSwaggerType(p) + "<string, " + getTypeDeclaration(inner) + ">";
}
return super.getTypeDeclaration(p);
}
@Override
public String toModelName(String name) {
name = sanitizeName(modelNamePrefix + name + modelNameSuffix);
// model name cannot use reserved keyword, e.g. return
if (isReservedWord(name)) {
LOGGER.warn(name + " (reserved word) cannot be used as model name. Renamed to " + camelize("object_" + name));
name = "object_" + name; // e.g. return => ObjectReturn (after camelize)
}
// camelize the model name
// phone_number => PhoneNumber
return camelize(name);
}
@Override
public String apiTestFileFolder() {
return outputFolder + ".Test";
}
@Override
public String modelTestFileFolder() {
return outputFolder + ".Test";
}
@Override
public String toApiTestFilename(String name) {
return toApiName(name) + "Tests";
}
@Override
public String toModelTestFilename(String name) {
return toModelName(name) + "Tests";
}
public void setPackageName(String packageName) {
this.packageName = packageName;
}
public void setPackageVersion(String packageVersion) {
this.packageVersion = packageVersion;
}
public void setSourceFolder(String sourceFolder) {
this.sourceFolder = sourceFolder;
}
}

View File

@ -0,0 +1,172 @@
package io.swagger.codegen.languages;
import io.swagger.codegen.CodegenOperation;
import io.swagger.codegen.CodegenResponse;
import io.swagger.codegen.CodegenType;
import io.swagger.models.Operation;
import io.swagger.models.Path;
import io.swagger.models.Swagger;
import java.util.*;
public abstract class AbstractJavaJAXRSServerCodegen extends JavaClientCodegen
{
/**
* Name of the sub-directory in "src/main/resource" where to find the
* Mustache template for the JAX-RS Codegen.
*/
protected static final String JAXRS_TEMPLATE_DIRECTORY_NAME = "JavaJaxRS";
protected String implFolder = "src/main/java";
protected String title = "Swagger Server";
public AbstractJavaJAXRSServerCodegen()
{
super();
}
// ================
// ABSTRACT METHODS
// ================
@Override
public abstract String getHelp();
@Override
public abstract String getName();
// ===============
// COMMONS METHODS
// ===============
@Override
public CodegenType getTag()
{
return CodegenType.SERVER;
}
@Override
public void preprocessSwagger(Swagger swagger) {
if ( "/".equals(swagger.getBasePath()) ) {
swagger.setBasePath("");
}
String host = swagger.getHost();
String port = "8080"; // Default value for a JEE Server
if ( host != null ) {
String[] parts = host.split(":");
if ( parts.length > 1 ) {
port = parts[1];
}
}
this.additionalProperties.put("serverPort", port);
if ( swagger.getPaths() != null ) {
for ( String pathname : swagger.getPaths().keySet() ) {
Path path = swagger.getPath(pathname);
if ( path.getOperations() != null ) {
for ( Operation operation : path.getOperations() ) {
if ( operation.getTags() != null ) {
List<Map<String, String>> tags = new ArrayList<Map<String, String>>();
for ( String tag : operation.getTags() ) {
Map<String, String> value = new HashMap<String, String>();
value.put("tag", tag);
value.put("hasMore", "true");
tags.add(value);
}
if ( tags.size() > 0 ) {
tags.get(tags.size() - 1).remove("hasMore");
}
if ( operation.getTags().size() > 0 ) {
String tag = operation.getTags().get(0);
operation.setTags(Arrays.asList(tag));
}
operation.setVendorExtension("x-tags", tags);
}
}
}
}
}
}
@Override
public Map<String, Object> postProcessOperations(Map<String, Object> objs) {
@SuppressWarnings("unchecked")
Map<String, Object> operations = (Map<String, Object>) objs.get("operations");
if ( operations != null ) {
@SuppressWarnings("unchecked")
List<CodegenOperation> ops = (List<CodegenOperation>) operations.get("operation");
for ( CodegenOperation operation : ops ) {
List<CodegenResponse> responses = operation.responses;
if ( responses != null ) {
for ( CodegenResponse resp : responses ) {
if ( "0".equals(resp.code) ) {
resp.code = "200";
}
}
}
if ( operation.returnType == null ) {
operation.returnType = "void";
} else if ( operation.returnType.startsWith("List") ) {
String rt = operation.returnType;
int end = rt.lastIndexOf(">");
if ( end > 0 ) {
operation.returnType = rt.substring("List<".length(), end).trim();
operation.returnContainer = "List";
}
} else if ( operation.returnType.startsWith("Map") ) {
String rt = operation.returnType;
int end = rt.lastIndexOf(">");
if ( end > 0 ) {
operation.returnType = rt.substring("Map<".length(), end).split(",")[1].trim();
operation.returnContainer = "Map";
}
} else if ( operation.returnType.startsWith("Set") ) {
String rt = operation.returnType;
int end = rt.lastIndexOf(">");
if ( end > 0 ) {
operation.returnType = rt.substring("Set<".length(), end).trim();
operation.returnContainer = "Set";
}
}
}
}
return objs;
}
@Override
public String toApiName(final String name) {
String computed = name;
if ( computed.length() == 0 ) {
return "DefaultApi";
}
computed = sanitizeName(computed);
return camelize(computed) + "Api";
}
@Override
public String apiFilename(String templateName, String tag) {
String result = super.apiFilename(templateName, tag);
if ( templateName.endsWith("Impl.mustache") ) {
int ix = result.lastIndexOf('/');
result = result.substring(0, ix) + "/impl" + result.substring(ix, result.length() - 5) + "ServiceImpl.java";
result = result.replace(apiFileFolder(), implFileFolder(implFolder));
} else if ( templateName.endsWith("Factory.mustache") ) {
int ix = result.lastIndexOf('/');
result = result.substring(0, ix) + "/factories" + result.substring(ix, result.length() - 5) + "ServiceFactory.java";
result = result.replace(apiFileFolder(), implFileFolder(implFolder));
} else if ( templateName.endsWith("Service.mustache") ) {
int ix = result.lastIndexOf('.');
result = result.substring(0, ix) + "Service.java";
}
return result;
}
private String implFileFolder(String output) {
return outputFolder + "/" + output + "/" + apiPackage().replace('.', '/');
}
@Override
public boolean shouldOverwrite(String filename) {
return super.shouldOverwrite(filename) && !filename.endsWith("ServiceImpl.java") && !filename.endsWith("ServiceFactory.java");
}
}

View File

@ -9,17 +9,21 @@ import java.io.File;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
public abstract class AbstractTypeScriptClientCodegen extends DefaultCodegen implements CodegenConfig { public abstract class AbstractTypeScriptClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override
public CodegenType getTag() { protected String modelPropertyNaming= "camelCase";
return CodegenType.CLIENT;
}
public AbstractTypeScriptClientCodegen() { public AbstractTypeScriptClientCodegen() {
super(); super();
supportsInheritance = true; supportsInheritance = true;
reservedWords = new HashSet<String>(Arrays.asList("abstract", "await", "boolean", "break", "byte", "case", "catch", "char", "class", "const", "continue", "debugger", "default", "delete", "do", "double", "else", "enum", "export", "extends", "false", "final", "finally", "float", "for", "function", "goto", "if", "implements", "import", "in", "instanceof", "int", "interface", "let", "long", "native", "new", "null", "package", "private", "protected", "public", "return", "short", "static", "super", "switch", "synchronized", "this", "throw", "transient", "true", "try", "typeof", "var", "void", "volatile", "while", "with", "yield")); setReservedWordsLowerCase(Arrays.asList(
// local variable names used in API methods (endpoints)
"varLocalPath", "queryParameters", "headerParams", "formParams", "useFormData", "varLocalDeferred",
"requestOptions",
// Typescript reserved words
"abstract", "await", "boolean", "break", "byte", "case", "catch", "char", "class", "const", "continue", "debugger", "default", "delete", "do", "double", "else", "enum", "export", "extends", "false", "final", "finally", "float", "for", "function", "goto", "if", "implements", "import", "in", "instanceof", "int", "interface", "let", "long", "native", "new", "null", "package", "private", "protected", "public", "return", "short", "static", "super", "switch", "synchronized", "this", "throw", "transient", "true", "try", "typeof", "var", "void", "volatile", "while", "with", "yield"));
languageSpecificPrimitives = new HashSet<String>(Arrays.asList( languageSpecificPrimitives = new HashSet<String>(Arrays.asList(
"string",
"String", "String",
"boolean", "boolean",
"Boolean", "Boolean",
@ -27,9 +31,14 @@ public abstract class AbstractTypeScriptClientCodegen extends DefaultCodegen imp
"Integer", "Integer",
"Long", "Long",
"Float", "Float",
"Object")); "Object",
"Array",
"Date",
"number",
"any"
));
instantiationTypes.put("array", "Array"); instantiationTypes.put("array", "Array");
typeMapping = new HashMap<String, String>(); typeMapping = new HashMap<String, String>();
typeMapping.put("Array", "Array"); typeMapping.put("Array", "Array");
typeMapping.put("array", "Array"); typeMapping.put("array", "Array");
@ -47,7 +56,27 @@ public abstract class AbstractTypeScriptClientCodegen extends DefaultCodegen imp
typeMapping.put("integer", "number"); typeMapping.put("integer", "number");
typeMapping.put("Map", "any"); typeMapping.put("Map", "any");
typeMapping.put("DateTime", "Date"); typeMapping.put("DateTime", "Date");
//TODO binary should be mapped to byte array
// mapped to String as a workaround
typeMapping.put("binary", "string");
cliOptions.add(new CliOption(CodegenConstants.MODEL_PROPERTY_NAMING, CodegenConstants.MODEL_PROPERTY_NAMING_DESC).defaultValue("camelCase"));
}
@Override
public void processOpts() {
super.processOpts();
if (additionalProperties.containsKey(CodegenConstants.MODEL_PROPERTY_NAMING)) {
setModelPropertyNaming((String) additionalProperties.get(CodegenConstants.MODEL_PROPERTY_NAMING));
}
}
@Override
public CodegenType getTag() {
return CodegenType.CLIENT;
} }
@Override @Override
@ -60,14 +89,15 @@ public abstract class AbstractTypeScriptClientCodegen extends DefaultCodegen imp
return outputFolder + "/" + apiPackage().replace('.', File.separatorChar); return outputFolder + "/" + apiPackage().replace('.', File.separatorChar);
} }
@Override
public String modelFileFolder() { public String modelFileFolder() {
return outputFolder + "/" + modelPackage().replace('.', File.separatorChar); return outputFolder + "/" + modelPackage().replace('.', File.separatorChar);
} }
@Override @Override
public String toVarName(String name) { public String toParamName(String name) {
// replace - with _ e.g. created-at => created_at // replace - with _ e.g. created-at => created_at
name = name.replaceAll("-", "_"); name = name.replaceAll("-", "_"); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
// if it's all uppper case, do nothing // if it's all uppper case, do nothing
if (name.matches("^[A-Z_]*$")) if (name.matches("^[A-Z_]*$"))
@ -78,24 +108,36 @@ public abstract class AbstractTypeScriptClientCodegen extends DefaultCodegen imp
name = camelize(name, true); name = camelize(name, true);
// for reserved word or word starting with number, append _ // for reserved word or word starting with number, append _
if (reservedWords.contains(name) || name.matches("^\\d.*")) if (isReservedWord(name) || name.matches("^\\d.*"))
name = escapeReservedWord(name); name = escapeReservedWord(name);
return name; return name;
} }
@Override @Override
public String toParamName(String name) { public String toVarName(String name) {
// should be the same as variable name // should be the same as variable name
return toVarName(name); return getNameUsingModelPropertyNaming(name);
} }
@Override @Override
public String toModelName(String name) { public String toModelName(String name) {
// model name cannot use reserved keyword, e.g. return name = sanitizeName(name); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
if (reservedWords.contains(name))
throw new RuntimeException(name if (!StringUtils.isEmpty(modelNamePrefix)) {
+ " (reserved word) cannot be used as a model name"); name = modelNamePrefix + "_" + name;
}
if (!StringUtils.isEmpty(modelNameSuffix)) {
name = name + "_" + modelNameSuffix;
}
// model name cannot use reserved keyword, e.g. return
if (isReservedWord(name)) {
String modelName = camelize("object_" + name);
LOGGER.warn(name + " (reserved word) cannot be used as model name. Renamed to " + modelName);
return modelName;
}
// camelize the model name // camelize the model name
// phone_number => PhoneNumber // phone_number => PhoneNumber
@ -134,22 +176,50 @@ public abstract class AbstractTypeScriptClientCodegen extends DefaultCodegen imp
return type; return type;
} else } else
type = swaggerType; type = swaggerType;
return type; return toModelName(type);
} }
@Override @Override
public String toOperationId(String operationId) { public String toOperationId(String operationId) {
// throw exception if method name is empty // throw exception if method name is empty
if (StringUtils.isEmpty(operationId)) { if (StringUtils.isEmpty(operationId)) {
throw new RuntimeException("Empty method name (operationId) not allowed"); throw new RuntimeException("Empty method name (operationId) not allowed");
}
// method name cannot use reserved keyword, e.g. return
// append _ at the beginning, e.g. _return
if (reservedWords.contains(operationId)) {
return escapeReservedWord(camelize(sanitizeName(operationId), true));
}
return camelize(sanitizeName(operationId), true);
} }
// method name cannot use reserved keyword, e.g. return
// append _ at the beginning, e.g. _return
if (isReservedWord(operationId)) {
return escapeReservedWord(camelize(sanitizeName(operationId), true));
}
return camelize(sanitizeName(operationId), true);
}
public void setModelPropertyNaming(String naming) {
if ("original".equals(naming) || "camelCase".equals(naming) ||
"PascalCase".equals(naming) || "snake_case".equals(naming)) {
this.modelPropertyNaming = naming;
} else {
throw new IllegalArgumentException("Invalid model property naming '" +
naming + "'. Must be 'original', 'camelCase', " +
"'PascalCase' or 'snake_case'");
}
}
public String getModelPropertyNaming() {
return this.modelPropertyNaming;
}
public String getNameUsingModelPropertyNaming(String name) {
switch (CodegenConstants.MODEL_PROPERTY_NAMING_TYPE.valueOf(getModelPropertyNaming())) {
case original: return name;
case camelCase: return camelize(name, true);
case PascalCase: return camelize(name);
case snake_case: return underscore(name);
default: throw new IllegalArgumentException("Invalid model property naming '" +
name + "'. Must be 'original', 'camelCase', " +
"'PascalCase' or 'snake_case'");
}
}
} }

View File

@ -63,7 +63,9 @@ public class AkkaScalaClientCodegen extends DefaultCodegen implements CodegenCon
* unmarshalling problems and any other RuntimeException will be considered as ApiErrors. * unmarshalling problems and any other RuntimeException will be considered as ApiErrors.
*/ */
protected boolean onlyOneSuccess = true; protected boolean onlyOneSuccess = true;
Logger LOGGER = LoggerFactory.getLogger(AkkaScalaClientCodegen.class);
@SuppressWarnings("hiding")
protected Logger LOGGER = LoggerFactory.getLogger(AkkaScalaClientCodegen.class);
public AkkaScalaClientCodegen() { public AkkaScalaClientCodegen() {
super(); super();
@ -74,7 +76,7 @@ public class AkkaScalaClientCodegen extends DefaultCodegen implements CodegenCon
apiPackage = mainPackage + ".api"; apiPackage = mainPackage + ".api";
modelPackage = mainPackage + ".model"; modelPackage = mainPackage + ".model";
reservedWords = new HashSet<String>( setReservedWordsLowerCase(
Arrays.asList( Arrays.asList(
"abstract", "case", "catch", "class", "def", "do", "else", "extends", "abstract", "case", "catch", "class", "def", "do", "else", "extends",
"false", "final", "finally", "for", "forSome", "if", "implicit", "false", "final", "finally", "for", "forSome", "if", "implicit",
@ -154,14 +156,17 @@ public class AkkaScalaClientCodegen extends DefaultCodegen implements CodegenCon
cliOptions.add(new CliOption(CodegenConstants.API_PACKAGE, CodegenConstants.API_PACKAGE_DESC)); cliOptions.add(new CliOption(CodegenConstants.API_PACKAGE, CodegenConstants.API_PACKAGE_DESC));
} }
@Override
public CodegenType getTag() { public CodegenType getTag() {
return CodegenType.CLIENT; return CodegenType.CLIENT;
} }
@Override
public String getName() { public String getName() {
return "akka-scala"; return "akka-scala";
} }
@Override
public String getHelp() { public String getHelp() {
return "Generates a Scala client library base on Akka/Spray."; return "Generates a Scala client library base on Akka/Spray.";
} }
@ -176,6 +181,7 @@ public class AkkaScalaClientCodegen extends DefaultCodegen implements CodegenCon
return outputFolder + "/" + sourceFolder + "/" + apiPackage().replace('.', File.separatorChar); return outputFolder + "/" + sourceFolder + "/" + apiPackage().replace('.', File.separatorChar);
} }
@Override
public String modelFileFolder() { public String modelFileFolder() {
return outputFolder + "/" + sourceFolder + "/" + modelPackage().replace('.', File.separatorChar); return outputFolder + "/" + sourceFolder + "/" + modelPackage().replace('.', File.separatorChar);
} }
@ -270,7 +276,7 @@ public class AkkaScalaClientCodegen extends DefaultCodegen implements CodegenCon
if (capitalized) { if (capitalized) {
identifier = StringUtils.capitalize(identifier); identifier = StringUtils.capitalize(identifier);
} }
if (identifier.matches("[a-zA-Z_$][\\w_$]+") && !reservedWords.contains(identifier)) { if (identifier.matches("[a-zA-Z_$][\\w_$]+") && !isReservedWord(identifier)) {
return identifier; return identifier;
} }
return escapeReservedWord(identifier); return escapeReservedWord(identifier);
@ -321,6 +327,7 @@ public class AkkaScalaClientCodegen extends DefaultCodegen implements CodegenCon
} }
} }
@Override
public String toDefaultValue(Property p) { public String toDefaultValue(Property p) {
if (!p.getRequired()) { if (!p.getRequired()) {
return "None"; return "None";

View File

@ -15,8 +15,11 @@ import java.util.Arrays;
import java.util.HashSet; import java.util.HashSet;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class AndroidClientCodegen extends DefaultCodegen implements CodegenConfig { public class AndroidClientCodegen extends DefaultCodegen implements CodegenConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(AndroidClientCodegen.class);
public static final String USE_ANDROID_MAVEN_GRADLE_PLUGIN = "useAndroidMavenGradlePlugin"; public static final String USE_ANDROID_MAVEN_GRADLE_PLUGIN = "useAndroidMavenGradlePlugin";
protected String invokerPackage = "io.swagger.client"; protected String invokerPackage = "io.swagger.client";
protected String groupId = "io.swagger"; protected String groupId = "io.swagger";
@ -26,24 +29,34 @@ public class AndroidClientCodegen extends DefaultCodegen implements CodegenConfi
protected String sourceFolder = projectFolder + "/java"; protected String sourceFolder = projectFolder + "/java";
protected Boolean useAndroidMavenGradlePlugin = true; protected Boolean useAndroidMavenGradlePlugin = true;
// requestPackage and authPackage are used by the "volley" template/library
protected String requestPackage = "io.swagger.client.request";
protected String authPackage = "io.swagger.client.auth";
public AndroidClientCodegen() { public AndroidClientCodegen() {
super(); super();
outputFolder = "generated-code/android"; outputFolder = "generated-code/android";
modelTemplateFiles.put("model.mustache", ".java"); modelTemplateFiles.put("model.mustache", ".java");
apiTemplateFiles.put("api.mustache", ".java"); apiTemplateFiles.put("api.mustache", ".java");
embeddedTemplateDir = templateDir = "android-java"; embeddedTemplateDir = templateDir = "android";
apiPackage = "io.swagger.client.api"; apiPackage = "io.swagger.client.api";
modelPackage = "io.swagger.client.model"; modelPackage = "io.swagger.client.model";
reservedWords = new HashSet<String>( setReservedWordsLowerCase(
Arrays.asList( Arrays.asList(
"abstract", "continue", "for", "new", "switch", "assert", // local variable names used in API methods (endpoints)
"default", "if", "package", "synchronized", "boolean", "do", "goto", "private", "postBody", "path", "queryParams", "headerParams", "formParams",
"this", "break", "double", "implements", "protected", "throw", "byte", "else", "contentTypes", "contentType", "response", "builder", "httpEntity",
"import", "public", "throws", "case", "enum", "instanceof", "return", "transient", "authNames", "basePath", "apiInvoker",
"catch", "extends", "int", "short", "try", "char", "final", "interface", "static",
"void", "class", "finally", "long", "strictfp", "volatile", "const", "float", // android reserved words
"native", "super", "while") "abstract", "continue", "for", "new", "switch", "assert",
"default", "if", "package", "synchronized", "boolean", "do", "goto", "private",
"this", "break", "double", "implements", "protected", "throw", "byte", "else",
"import", "public", "throws", "case", "enum", "instanceof", "return", "transient",
"catch", "extends", "int", "short", "try", "char", "final", "interface", "static",
"void", "class", "finally", "long", "strictfp", "volatile", "const", "float",
"native", "super", "while")
); );
languageSpecificPrimitives = new HashSet<String>( languageSpecificPrimitives = new HashSet<String>(
@ -67,18 +80,27 @@ public class AndroidClientCodegen extends DefaultCodegen implements CodegenConfi
cliOptions.add(new CliOption(CodegenConstants.ARTIFACT_ID, "artifactId for use in the generated build.gradle and pom.xml")); cliOptions.add(new CliOption(CodegenConstants.ARTIFACT_ID, "artifactId for use in the generated build.gradle and pom.xml"));
cliOptions.add(new CliOption(CodegenConstants.ARTIFACT_VERSION, "artifact version for use in the generated build.gradle and pom.xml")); cliOptions.add(new CliOption(CodegenConstants.ARTIFACT_VERSION, "artifact version for use in the generated build.gradle and pom.xml"));
cliOptions.add(new CliOption(CodegenConstants.SOURCE_FOLDER, CodegenConstants.SOURCE_FOLDER_DESC)); cliOptions.add(new CliOption(CodegenConstants.SOURCE_FOLDER, CodegenConstants.SOURCE_FOLDER_DESC));
cliOptions.add(new CliOption(USE_ANDROID_MAVEN_GRADLE_PLUGIN, "A flag to toggle android-maven gradle plugin.") cliOptions.add(CliOption.newBoolean(USE_ANDROID_MAVEN_GRADLE_PLUGIN, "A flag to toggle android-maven gradle plugin.")
.defaultValue("true")); .defaultValue(Boolean.TRUE.toString()));
supportedLibraries.put("<default>", "HTTP client: Apache HttpClient 4.3.6. JSON processing: Gson 2.3.1");
supportedLibraries.put("volley", "HTTP client: Volley 1.0.19");
CliOption library = new CliOption(CodegenConstants.LIBRARY, "library template (sub-template) to use");
library.setEnum(supportedLibraries);
cliOptions.add(library);
} }
@Override
public CodegenType getTag() { public CodegenType getTag() {
return CodegenType.CLIENT; return CodegenType.CLIENT;
} }
@Override
public String getName() { public String getName() {
return "android"; return "android";
} }
@Override
public String getHelp() { public String getHelp() {
return "Generates an Android client library."; return "Generates an Android client library.";
} }
@ -93,6 +115,7 @@ public class AndroidClientCodegen extends DefaultCodegen implements CodegenConfi
return outputFolder + "/" + sourceFolder + "/" + apiPackage().replace('.', File.separatorChar); return outputFolder + "/" + sourceFolder + "/" + apiPackage().replace('.', File.separatorChar);
} }
@Override
public String modelFileFolder() { public String modelFileFolder() {
return outputFolder + "/" + sourceFolder + "/" + modelPackage().replace('.', File.separatorChar); return outputFolder + "/" + sourceFolder + "/" + modelPackage().replace('.', File.separatorChar);
} }
@ -130,7 +153,7 @@ public class AndroidClientCodegen extends DefaultCodegen implements CodegenConfi
@Override @Override
public String toVarName(String name) { public String toVarName(String name) {
// replace - with _ e.g. created-at => created_at // replace - with _ e.g. created-at => created_at
name = name.replaceAll("-", "_"); name = name.replaceAll("-", "_"); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
// if it's all uppper case, do nothing // if it's all uppper case, do nothing
if (name.matches("^[A-Z_]*$")) { if (name.matches("^[A-Z_]*$")) {
@ -142,7 +165,7 @@ public class AndroidClientCodegen extends DefaultCodegen implements CodegenConfi
name = camelize(name, true); name = camelize(name, true);
// for reserved word or word starting with number, append _ // for reserved word or word starting with number, append _
if (reservedWords.contains(name) || name.matches("^\\d.*")) { if (isReservedWord(name) || name.matches("^\\d.*")) {
name = escapeReservedWord(name); name = escapeReservedWord(name);
} }
@ -157,14 +180,18 @@ public class AndroidClientCodegen extends DefaultCodegen implements CodegenConfi
@Override @Override
public String toModelName(String name) { public String toModelName(String name) {
// model name cannot use reserved keyword, e.g. return
if (reservedWords.contains(name)) {
throw new RuntimeException(name + " (reserved word) cannot be used as a model name");
}
// camelize the model name // camelize the model name
// phone_number => PhoneNumber // phone_number => PhoneNumber
return camelize(name); name = camelize(sanitizeName(name));
// model name cannot use reserved keyword, e.g. return
if (isReservedWord(name)) {
String modelName = "Object" + name;
LOGGER.warn(name + " (reserved word) cannot be used as model name. Renamed to " + modelName);
return modelName;
}
return name;
} }
@Override @Override
@ -180,12 +207,16 @@ public class AndroidClientCodegen extends DefaultCodegen implements CodegenConfi
throw new RuntimeException("Empty method name (operationId) not allowed"); throw new RuntimeException("Empty method name (operationId) not allowed");
} }
operationId = camelize(sanitizeName(operationId), true);
// method name cannot use reserved keyword, e.g. return // method name cannot use reserved keyword, e.g. return
if (reservedWords.contains(operationId)) { if (isReservedWord(operationId)) {
throw new RuntimeException(operationId + " (reserved word) cannot be used as method name"); String newOperationId = camelize("call_" + operationId, true);
LOGGER.warn(operationId + " (reserved word) cannot be used as method name. Renamed to " + newOperationId);
return newOperationId;
} }
return camelize(operationId, true); return operationId;
} }
@Override @Override
@ -231,22 +262,63 @@ public class AndroidClientCodegen extends DefaultCodegen implements CodegenConfi
additionalProperties.put(USE_ANDROID_MAVEN_GRADLE_PLUGIN, useAndroidMavenGradlePlugin); additionalProperties.put(USE_ANDROID_MAVEN_GRADLE_PLUGIN, useAndroidMavenGradlePlugin);
} }
supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml")); if (additionalProperties.containsKey(CodegenConstants.LIBRARY)) {
additionalProperties.put(USE_ANDROID_MAVEN_GRADLE_PLUGIN, useAndroidMavenGradlePlugin); this.setLibrary((String) additionalProperties.get(CodegenConstants.LIBRARY));
}
if (StringUtils.isEmpty(getLibrary())) {
addSupportingFilesForDefault();
} else if ("volley".equals(getLibrary())) {
addSupportingFilesForVolley();
}
}
private void addSupportingFilesForDefault() {
supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml"));
supportingFiles.add(new SupportingFile("settings.gradle.mustache", "", "settings.gradle")); supportingFiles.add(new SupportingFile("settings.gradle.mustache", "", "settings.gradle"));
supportingFiles.add(new SupportingFile("build.mustache", "", "build.gradle")); supportingFiles.add(new SupportingFile("build.mustache", "", "build.gradle"));
supportingFiles.add(new SupportingFile("manifest.mustache", projectFolder, "AndroidManifest.xml")); supportingFiles.add(new SupportingFile("manifest.mustache", projectFolder, "AndroidManifest.xml"));
supportingFiles.add(new SupportingFile("apiInvoker.mustache", supportingFiles.add(new SupportingFile("apiInvoker.mustache",
(sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "ApiInvoker.java")); (sourceFolder + File.separator + invokerPackage).replace(".", File.separator), "ApiInvoker.java"));
supportingFiles.add(new SupportingFile("httpPatch.mustache", supportingFiles.add(new SupportingFile("httpPatch.mustache",
(sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "HttpPatch.java")); (sourceFolder + File.separator + invokerPackage).replace(".", File.separator), "HttpPatch.java"));
supportingFiles.add(new SupportingFile("jsonUtil.mustache", supportingFiles.add(new SupportingFile("jsonUtil.mustache",
(sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "JsonUtil.java")); (sourceFolder + File.separator + invokerPackage).replace(".", File.separator), "JsonUtil.java"));
supportingFiles.add(new SupportingFile("apiException.mustache", supportingFiles.add(new SupportingFile("apiException.mustache",
(sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "ApiException.java")); (sourceFolder + File.separator + invokerPackage).replace(".", File.separator), "ApiException.java"));
supportingFiles.add(new SupportingFile("Pair.mustache", supportingFiles.add(new SupportingFile("Pair.mustache",
(sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "Pair.java")); (sourceFolder + File.separator + invokerPackage).replace(".", File.separator), "Pair.java"));
}
private void addSupportingFilesForVolley() {
// supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml"));
// supportingFiles.add(new SupportingFile("settings.gradle.mustache", "", "settings.gradle"));
supportingFiles.add(new SupportingFile("build.mustache", "", "build.gradle"));
supportingFiles.add(new SupportingFile("manifest.mustache", projectFolder, "AndroidManifest.xml"));
supportingFiles.add(new SupportingFile("apiInvoker.mustache",
(sourceFolder + File.separator + invokerPackage).replace(".", File.separator), "ApiInvoker.java"));
supportingFiles.add(new SupportingFile("jsonUtil.mustache",
(sourceFolder + File.separator + invokerPackage).replace(".", File.separator), "JsonUtil.java"));
supportingFiles.add(new SupportingFile("apiException.mustache",
(sourceFolder + File.separator + invokerPackage).replace(".", File.separator), "ApiException.java"));
supportingFiles.add(new SupportingFile("Pair.mustache",
(sourceFolder + File.separator + invokerPackage).replace(".", File.separator), "Pair.java"));
supportingFiles.add(new SupportingFile("request/getrequest.mustache",
(sourceFolder + File.separator + requestPackage).replace(".", File.separator), "GetRequest.java"));
supportingFiles.add(new SupportingFile("request/postrequest.mustache",
(sourceFolder + File.separator + requestPackage).replace(".", File.separator), "PostRequest.java"));
supportingFiles.add(new SupportingFile("request/putrequest.mustache",
(sourceFolder + File.separator + requestPackage).replace(".", File.separator), "PutRequest.java"));
supportingFiles.add(new SupportingFile("request/deleterequest.mustache",
(sourceFolder + File.separator + requestPackage).replace(".", File.separator), "DeleteRequest.java"));
supportingFiles.add(new SupportingFile("request/patchrequest.mustache",
(sourceFolder + File.separator + requestPackage).replace(".", File.separator), "PatchRequest.java"));
supportingFiles.add(new SupportingFile("auth/apikeyauth.mustache",
(sourceFolder + File.separator + authPackage).replace(".", File.separator), "ApiKeyAuth.java"));
supportingFiles.add(new SupportingFile("auth/httpbasicauth.mustache",
(sourceFolder + File.separator + authPackage).replace(".", File.separator), "HttpBasicAuth.java"));
supportingFiles.add(new SupportingFile("auth/authentication.mustache",
(sourceFolder + File.separator + authPackage).replace(".", File.separator), "Authentication.java"));
} }
public Boolean getUseAndroidMavenGradlePlugin() { public Boolean getUseAndroidMavenGradlePlugin() {

View File

@ -0,0 +1,127 @@
package io.swagger.codegen.languages;
import io.swagger.codegen.*;
import io.swagger.models.properties.*;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.util.*;
public class AspNet5ServerCodegen extends AbstractCSharpCodegen {
@SuppressWarnings("hiding")
protected Logger LOGGER = LoggerFactory.getLogger(AspNet5ServerCodegen.class);
public AspNet5ServerCodegen() {
super();
outputFolder = "generated-code" + File.separator + this.getName();
modelTemplateFiles.put("model.mustache", ".cs");
apiTemplateFiles.put("controller.mustache", ".cs");
// contextually reserved words
setReservedWordsLowerCase(
Arrays.asList("var", "async", "await", "dynamic", "yield")
);
cliOptions.clear();
// CLI options
addOption(CodegenConstants.PACKAGE_NAME,
"C# package name (convention: Title.Case).",
this.packageName);
addOption(CodegenConstants.PACKAGE_VERSION,
"C# package version.",
this.packageVersion);
addOption(CodegenConstants.SOURCE_FOLDER,
CodegenConstants.SOURCE_FOLDER_DESC,
sourceFolder);
// CLI Switches
addSwitch(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG,
CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG_DESC,
this.sortParamsByRequiredFlag);
addSwitch(CodegenConstants.USE_DATETIME_OFFSET,
CodegenConstants.USE_DATETIME_OFFSET_DESC,
this.useDateTimeOffsetFlag);
addSwitch(CodegenConstants.USE_COLLECTION,
CodegenConstants.USE_COLLECTION_DESC,
this.useCollection);
addSwitch(CodegenConstants.RETURN_ICOLLECTION,
CodegenConstants.RETURN_ICOLLECTION_DESC,
this.returnICollection);
}
@Override
public CodegenType getTag() {
return CodegenType.SERVER;
}
@Override
public String getName() {
return "aspnet5";
}
@Override
public String getHelp() {
return "Generates an ASP.NET 5 Web API server.";
}
@Override
public void processOpts() {
super.processOpts();
apiPackage = packageName + ".Controllers";
modelPackage = packageName + ".Models";
supportingFiles.add(new SupportingFile("global.json", "", "global.json"));
supportingFiles.add(new SupportingFile("build.mustache", "", "build.sh"));
supportingFiles.add(new SupportingFile("Dockerfile.mustache", this.sourceFolder, "Dockerfile"));
supportingFiles.add(new SupportingFile("gitignore", this.sourceFolder, ".gitignore"));
supportingFiles.add(new SupportingFile("appsettings.json", this.sourceFolder, "appsettings.json"));
supportingFiles.add(new SupportingFile("project.mustache", this.sourceFolder, "project.json"));
supportingFiles.add(new SupportingFile("Startup.mustache", this.sourceFolder, "Startup.cs"));
supportingFiles.add(new SupportingFile("Properties" + File.separator + "launchSettings.json", this.sourceFolder + File.separator + "Properties", "launchSettings.json"));
supportingFiles.add(new SupportingFile("wwwroot" + File.separator + "README.md", this.sourceFolder + File.separator + "wwwroot", "README.md"));
supportingFiles.add(new SupportingFile("wwwroot" + File.separator + "index.html", this.sourceFolder + File.separator + "wwwroot", "index.html"));
supportingFiles.add(new SupportingFile("wwwroot" + File.separator + "web.config", this.sourceFolder + File.separator + "wwwroot", "web.config"));
}
@Override
public String apiFileFolder() {
return outputFolder + File.separator + sourceFolder + File.separator + "Controllers";
}
@Override
public String modelFileFolder() {
return outputFolder + File.separator + sourceFolder + File.separator + "Models";
}
@Override
protected void processOperation(CodegenOperation operation) {
super.processOperation(operation);
// HACK: Unlikely in the wild, but we need to clean operation paths for MVC Routing
if (operation.path != null) {
String original = operation.path;
operation.path = operation.path.replace("?", "/");
if (!original.equals(operation.path)) {
LOGGER.warn("Normalized " + original + " to " + operation.path + ". Please verify generated source.");
}
}
// Converts, for example, PUT to HttpPut for controller attributes
operation.httpMethod = "Http" + operation.httpMethod.substring(0, 1) + operation.httpMethod.substring(1).toLowerCase();
}
}

View File

@ -23,8 +23,6 @@ import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import org.apache.commons.lang.StringUtils;
public class AsyncScalaClientCodegen extends DefaultCodegen implements CodegenConfig { public class AsyncScalaClientCodegen extends DefaultCodegen implements CodegenConfig {
protected String invokerPackage = "io.swagger.client"; protected String invokerPackage = "io.swagger.client";
protected String groupId = "io.swagger"; protected String groupId = "io.swagger";
@ -33,7 +31,7 @@ public class AsyncScalaClientCodegen extends DefaultCodegen implements CodegenCo
protected String sourceFolder = "src/main/scala"; protected String sourceFolder = "src/main/scala";
protected String clientName = "SwaggerClient"; protected String clientName = "SwaggerClient";
protected String authScheme = ""; protected String authScheme = "";
protected boolean authPreemptive = false; protected boolean authPreemptive;
protected boolean asyncHttpClient = !authScheme.isEmpty(); protected boolean asyncHttpClient = !authScheme.isEmpty();
public AsyncScalaClientCodegen() { public AsyncScalaClientCodegen() {
@ -45,13 +43,18 @@ public class AsyncScalaClientCodegen extends DefaultCodegen implements CodegenCo
apiPackage = "io.swagger.client.api"; apiPackage = "io.swagger.client.api";
modelPackage = "io.swagger.client.model"; modelPackage = "io.swagger.client.model";
reservedWords = new HashSet<String>( setReservedWordsLowerCase(
Arrays.asList( Arrays.asList(
"abstract", "case", "catch", "class", "def", "do", "else", "extends", // local variable names used in API methods (endpoints)
"false", "final", "finally", "for", "forSome", "if", "implicit", "config", "path", "contentTypes", "contentType", "queryParams", "headerParams",
"import", "lazy", "match", "new", "null", "object", "override", "package", "formParams", "postBody", "resFuture", "client", "reader",
"private", "protected", "return", "sealed", "super", "this", "throw",
"trait", "try", "true", "type", "val", "var", "while", "with", "yield") // scala reserved words
"abstract", "case", "catch", "class", "def", "do", "else", "extends",
"false", "final", "finally", "for", "forSome", "if", "implicit",
"import", "lazy", "match", "new", "null", "object", "override", "package",
"private", "protected", "return", "sealed", "super", "this", "throw",
"trait", "try", "true", "type", "val", "var", "while", "with", "yield")
); );
additionalProperties.put(CodegenConstants.INVOKER_PACKAGE, invokerPackage); additionalProperties.put(CodegenConstants.INVOKER_PACKAGE, invokerPackage);
@ -111,14 +114,17 @@ public class AsyncScalaClientCodegen extends DefaultCodegen implements CodegenCo
cliOptions.add(new CliOption(CodegenConstants.API_PACKAGE, CodegenConstants.API_PACKAGE_DESC)); cliOptions.add(new CliOption(CodegenConstants.API_PACKAGE, CodegenConstants.API_PACKAGE_DESC));
} }
@Override
public CodegenType getTag() { public CodegenType getTag() {
return CodegenType.CLIENT; return CodegenType.CLIENT;
} }
@Override
public String getName() { public String getName() {
return "async-scala"; return "async-scala";
} }
@Override
public String getHelp() { public String getHelp() {
return "Generates an Asynchronous Scala client library."; return "Generates an Asynchronous Scala client library.";
} }
@ -133,6 +139,7 @@ public class AsyncScalaClientCodegen extends DefaultCodegen implements CodegenCo
return outputFolder + "/" + sourceFolder + "/" + apiPackage().replace('.', File.separatorChar); return outputFolder + "/" + sourceFolder + "/" + apiPackage().replace('.', File.separatorChar);
} }
@Override
public String modelFileFolder() { public String modelFileFolder() {
return outputFolder + "/" + sourceFolder + "/" + modelPackage().replace('.', File.separatorChar); return outputFolder + "/" + sourceFolder + "/" + modelPackage().replace('.', File.separatorChar);
} }
@ -182,6 +189,7 @@ public class AsyncScalaClientCodegen extends DefaultCodegen implements CodegenCo
} }
} }
@Override
public String toDefaultValue(Property p) { public String toDefaultValue(Property p) {
if (p instanceof StringProperty) { if (p instanceof StringProperty) {
return "null"; return "null";

View File

@ -1,5 +1,7 @@
package io.swagger.codegen.languages; package io.swagger.codegen.languages;
import com.google.common.collect.ImmutableBiMap;
import com.google.common.collect.ImmutableMap;
import io.swagger.codegen.CodegenConfig; import io.swagger.codegen.CodegenConfig;
import io.swagger.codegen.CodegenConstants; import io.swagger.codegen.CodegenConstants;
import io.swagger.codegen.CodegenType; import io.swagger.codegen.CodegenType;
@ -8,6 +10,7 @@ import io.swagger.codegen.DefaultCodegen;
import io.swagger.codegen.SupportingFile; import io.swagger.codegen.SupportingFile;
import io.swagger.codegen.CodegenProperty; import io.swagger.codegen.CodegenProperty;
import io.swagger.codegen.CodegenModel; import io.swagger.codegen.CodegenModel;
import io.swagger.codegen.CodegenOperation;
import io.swagger.models.properties.*; import io.swagger.models.properties.*;
import io.swagger.codegen.CliOption; import io.swagger.codegen.CliOption;
import io.swagger.models.Model; import io.swagger.models.Model;
@ -26,264 +29,240 @@ import org.apache.commons.lang.WordUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig { public class CSharpClientCodegen extends AbstractCSharpCodegen {
@SuppressWarnings({"unused", "hiding"})
private static final Logger LOGGER = LoggerFactory.getLogger(CSharpClientCodegen.class); private static final Logger LOGGER = LoggerFactory.getLogger(CSharpClientCodegen.class);
protected boolean optionalMethodArgumentFlag = true; private static final String NET45 = "v4.5";
protected String packageName = "IO.Swagger"; private static final String NET35 = "v3.5";
protected String packageVersion = "1.0.0";
protected String packageGuid = "{" + java.util.UUID.randomUUID().toString().toUpperCase() + "}";
protected String packageTitle = "Swagger Library";
protected String packageProductName = "SwaggerLibrary";
protected String packageDescription = "A library generated from a Swagger doc";
protected String packageCompany = "Swagger";
protected String packageCopyright = "No Copyright";
protected String clientPackage = "IO.Swagger.Client"; protected String clientPackage = "IO.Swagger.Client";
protected String sourceFolder = "src" + File.separator + "main" + File.separator + "csharp";
protected String localVariablePrefix = ""; protected String localVariablePrefix = "";
protected String targetFramework = NET45;
protected String targetFrameworkNuget = "net45";
protected boolean supportsAsync = Boolean.TRUE;
protected final Map<String, String> frameworks;
public CSharpClientCodegen() { public CSharpClientCodegen() {
super(); super();
outputFolder = "generated-code" + File.separator + "csharp";
modelTemplateFiles.put("model.mustache", ".cs"); modelTemplateFiles.put("model.mustache", ".cs");
apiTemplateFiles.put("api.mustache", ".cs"); apiTemplateFiles.put("api.mustache", ".cs");
embeddedTemplateDir = templateDir = "csharp";
apiPackage = "IO.Swagger.Api";
modelPackage = "IO.Swagger.Model";
reservedWords = new HashSet<String>( modelTestTemplateFiles.put("model_test.mustache", ".cs");
Arrays.asList( apiTestTemplateFiles.put("api_test.mustache", ".cs");
"abstract", "as", "base", "bool", "break", "byte", "case", "catch", "char", "checked", "class", "const", "continue", "decimal", "default", "delegate", "do", "double", "else", "enum", "event", "explicit", "extern", "false", "finally", "fixed", "float", "for", "foreach", "goto", "if", "implicit", "in", "int", "interface", "internal", "is", "lock", "long", "namespace", "new", "null", "object", "operator", "out", "override", "params", "private", "protected", "public", "readonly", "ref", "return", "sbyte", "sealed", "short", "sizeof", "stackalloc", "static", "string", "struct", "switch", "this", "throw", "true", "try", "typeof", "uint", "ulong", "unchecked", "unsafe", "ushort", "using", "virtual", "void", "volatile", "while")
);
// C# client default
languageSpecificPrimitives = new HashSet<String>( setSourceFolder("src" + File.separator + "main" + File.separator + "csharp");
Arrays.asList(
"String",
"string",
"bool?",
"double?",
"int?",
"long?",
"float?",
"byte[]",
"List",
"Dictionary",
"DateTime?",
"String",
"Boolean",
"Double",
"Integer",
"Long",
"Float",
"Stream", // not really a primitive, we include it to avoid model import
"Object")
);
instantiationTypes.put("array", "List");
instantiationTypes.put("map", "Dictionary");
typeMapping = new HashMap<String, String>();
typeMapping.put("string", "string");
typeMapping.put("boolean", "bool?");
typeMapping.put("integer", "int?");
typeMapping.put("float", "float?");
typeMapping.put("long", "long?");
typeMapping.put("double", "double?");
typeMapping.put("number", "double?");
typeMapping.put("datetime", "DateTime?");
typeMapping.put("date", "DateTime?");
typeMapping.put("file", "Stream");
typeMapping.put("array", "List");
typeMapping.put("list", "List");
typeMapping.put("map", "Dictionary");
typeMapping.put("object", "Object");
cliOptions.clear(); cliOptions.clear();
cliOptions.add(new CliOption(CodegenConstants.PACKAGE_NAME, "C# package name (convention: Camel.Case).")
.defaultValue("IO.Swagger")); // CLI options
cliOptions.add(new CliOption(CodegenConstants.PACKAGE_VERSION, "C# package version.").defaultValue("1.0.0")); addOption(CodegenConstants.PACKAGE_NAME,
cliOptions.add(new CliOption(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG_DESC)); "C# package name (convention: Title.Case).",
cliOptions.add(new CliOption(CodegenConstants.OPTIONAL_METHOD_ARGUMENT, "C# Optional method argument, e.g. void square(int x=10) (.net 4.0+ only). Default: false").defaultValue("false")); this.packageName);
addOption(CodegenConstants.PACKAGE_VERSION,
"C# package version.",
this.packageVersion);
addOption(CodegenConstants.SOURCE_FOLDER,
CodegenConstants.SOURCE_FOLDER_DESC,
sourceFolder);
addOption(CodegenConstants.OPTIONAL_PROJECT_GUID,
CodegenConstants.OPTIONAL_PROJECT_GUID_DESC,
null);
CliOption framework = new CliOption(
CodegenConstants.DOTNET_FRAMEWORK,
CodegenConstants.DOTNET_FRAMEWORK_DESC
);
frameworks = new ImmutableMap.Builder<String, String>()
.put(NET35, ".NET Framework 3.5 compatible")
.put(NET45, ".NET Framework 4.5+ compatible")
.build();
framework.defaultValue(this.targetFramework);
framework.setEnum(frameworks);
cliOptions.add(framework);
// CLI Switches
addSwitch(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG,
CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG_DESC,
this.sortParamsByRequiredFlag);
addSwitch(CodegenConstants.USE_DATETIME_OFFSET,
CodegenConstants.USE_DATETIME_OFFSET_DESC,
this.useDateTimeOffsetFlag);
addSwitch(CodegenConstants.USE_COLLECTION,
CodegenConstants.USE_COLLECTION_DESC,
this.useCollection);
addSwitch(CodegenConstants.RETURN_ICOLLECTION,
CodegenConstants.RETURN_ICOLLECTION_DESC,
this.returnICollection);
addSwitch(CodegenConstants.OPTIONAL_METHOD_ARGUMENT,
"C# Optional method argument, e.g. void square(int x=10) (.net 4.0+ only).",
this.optionalMethodArgumentFlag);
addSwitch(CodegenConstants.OPTIONAL_ASSEMBLY_INFO,
CodegenConstants.OPTIONAL_ASSEMBLY_INFO_DESC,
this.optionalAssemblyInfoFlag);
addSwitch(CodegenConstants.OPTIONAL_PROJECT_FILE,
CodegenConstants.OPTIONAL_PROJECT_FILE_DESC,
this.optionalProjectFileFlag);
} }
@Override @Override
public void processOpts() { public void processOpts() {
super.processOpts(); super.processOpts();
if (additionalProperties.containsKey(CodegenConstants.PACKAGE_VERSION)) { apiPackage = packageName + ".Api";
setPackageVersion((String) additionalProperties.get(CodegenConstants.PACKAGE_VERSION)); modelPackage = packageName + ".Model";
} else { clientPackage = packageName + ".Client";
additionalProperties.put(CodegenConstants.PACKAGE_VERSION, packageVersion);
}
if (additionalProperties.containsKey(CodegenConstants.PACKAGE_NAME)) {
setPackageName((String) additionalProperties.get(CodegenConstants.PACKAGE_NAME));
apiPackage = packageName + ".Api";
modelPackage = packageName + ".Model";
clientPackage = packageName + ".Client";
} else {
additionalProperties.put(CodegenConstants.PACKAGE_NAME, packageName);
}
additionalProperties.put("clientPackage", clientPackage); additionalProperties.put("clientPackage", clientPackage);
// Add properties used by AssemblyInfo.mustache
additionalProperties.put("packageTitle", packageTitle);
additionalProperties.put("packageProductName", packageProductName);
additionalProperties.put("packageDescription", packageDescription);
additionalProperties.put("packageCompany", packageCompany);
additionalProperties.put("packageCopyright", packageCopyright);
if (additionalProperties.containsKey(CodegenConstants.DOTNET_FRAMEWORK)) {
setTargetFramework((String) additionalProperties.get(CodegenConstants.DOTNET_FRAMEWORK));
}
if (NET35.equals(this.targetFramework)) {
setTargetFrameworkNuget("net35");
setSupportsAsync(Boolean.FALSE);
if(additionalProperties.containsKey("supportsAsync")){
additionalProperties.remove("supportsAsync");
}
} else {
setTargetFrameworkNuget("net45");
setSupportsAsync(Boolean.TRUE);
additionalProperties.put("supportsAsync", this.supportsAsync);
}
additionalProperties.put("targetFrameworkNuget", this.targetFrameworkNuget);
if (additionalProperties.containsKey(CodegenConstants.OPTIONAL_PROJECT_FILE)) {
setOptionalProjectFileFlag(Boolean.valueOf(
additionalProperties.get(CodegenConstants.OPTIONAL_PROJECT_FILE).toString()));
}
if (additionalProperties.containsKey(CodegenConstants.OPTIONAL_PROJECT_GUID)) {
setPackageGuid((String) additionalProperties.get(CodegenConstants.OPTIONAL_PROJECT_GUID));
}
additionalProperties.put("packageGuid", packageGuid);
if (additionalProperties.containsKey(CodegenConstants.OPTIONAL_METHOD_ARGUMENT)) { if (additionalProperties.containsKey(CodegenConstants.OPTIONAL_METHOD_ARGUMENT)) {
setOptionalMethodArgumentFlag(Boolean.valueOf(additionalProperties setOptionalMethodArgumentFlag(Boolean.valueOf(additionalProperties
.get(CodegenConstants.OPTIONAL_METHOD_ARGUMENT).toString())); .get(CodegenConstants.OPTIONAL_METHOD_ARGUMENT).toString()));
} }
additionalProperties.put("optionalMethodArgument", optionalMethodArgumentFlag); additionalProperties.put("optionalMethodArgument", optionalMethodArgumentFlag);
if (additionalProperties.containsKey(CodegenConstants.OPTIONAL_ASSEMBLY_INFO)) {
setOptionalAssemblyInfoFlag(Boolean.valueOf(additionalProperties
.get(CodegenConstants.OPTIONAL_ASSEMBLY_INFO).toString()));
}
String packageFolder = sourceFolder + File.separator + packageName.replace(".", java.io.File.separator);
String clientPackageDir = sourceFolder + File.separator + clientPackage.replace(".", java.io.File.separator);
//Compute the relative path to the bin directory where the external assemblies live
//This is necessary to properly generate the project file
int packageDepth = packageFolder.length() - packageFolder.replace(java.io.File.separator, "").length();
String binRelativePath = "..\\";
for (int i = 0; i < packageDepth; i = i + 1)
binRelativePath += "..\\";
binRelativePath += "vendor\\";
additionalProperties.put("binRelativePath", binRelativePath);
supportingFiles.add(new SupportingFile("Configuration.mustache", supportingFiles.add(new SupportingFile("Configuration.mustache",
sourceFolder + File.separator + clientPackage.replace(".", java.io.File.separator), "Configuration.cs")); clientPackageDir, "Configuration.cs"));
supportingFiles.add(new SupportingFile("ApiClient.mustache", supportingFiles.add(new SupportingFile("ApiClient.mustache",
sourceFolder + File.separator + clientPackage.replace(".", java.io.File.separator), "ApiClient.cs")); clientPackageDir, "ApiClient.cs"));
supportingFiles.add(new SupportingFile("ApiException.mustache", supportingFiles.add(new SupportingFile("ApiException.mustache",
sourceFolder + File.separator + clientPackage.replace(".", java.io.File.separator), "ApiException.cs")); clientPackageDir, "ApiException.cs"));
supportingFiles.add(new SupportingFile("ApiResponse.mustache", supportingFiles.add(new SupportingFile("ApiResponse.mustache",
sourceFolder + File.separator + clientPackage.replace(".", java.io.File.separator), "ApiResponse.cs")); clientPackageDir, "ApiResponse.cs"));
supportingFiles.add(new SupportingFile("Newtonsoft.Json.dll", "bin", "Newtonsoft.Json.dll"));
supportingFiles.add(new SupportingFile("RestSharp.dll", "bin", "RestSharp.dll"));
supportingFiles.add(new SupportingFile("compile.mustache", "", "compile.bat")); supportingFiles.add(new SupportingFile("compile.mustache", "", "compile.bat"));
supportingFiles.add(new SupportingFile("compile-mono.sh.mustache", "", "compile-mono.sh"));
supportingFiles.add(new SupportingFile("packages.config.mustache", "vendor" + java.io.File.separator, "packages.config"));
supportingFiles.add(new SupportingFile("README.md", "", "README.md")); supportingFiles.add(new SupportingFile("README.md", "", "README.md"));
if (optionalAssemblyInfoFlag) {
supportingFiles.add(new SupportingFile("AssemblyInfo.mustache", packageFolder + File.separator + "Properties", "AssemblyInfo.cs"));
}
if (optionalProjectFileFlag) {
supportingFiles.add(new SupportingFile("Project.mustache", packageFolder, clientPackage + ".csproj"));
}
} }
@Override
public Map<String, Object> postProcessOperations(Map<String, Object> objs) {
super.postProcessOperations(objs);
if (objs != null) {
Map<String, Object> operations = (Map<String, Object>) objs.get("operations");
if (operations != null) {
List<CodegenOperation> ops = (List<CodegenOperation>) operations.get("operation");
for (CodegenOperation operation : ops) {
if (operation.returnType != null) {
operation.returnContainer = operation.returnType;
if (this.returnICollection && (
operation.returnType.startsWith("List") ||
operation.returnType.startsWith("Collection"))) {
// NOTE: ICollection works for both List<T> and Collection<T>
int genericStart = operation.returnType.indexOf("<");
if (genericStart > 0) {
operation.returnType = "ICollection" + operation.returnType.substring(genericStart);
}
}
}
}
}
}
return objs;
}
@Override
public CodegenType getTag() { public CodegenType getTag() {
return CodegenType.CLIENT; return CodegenType.CLIENT;
} }
@Override
public String getName() { public String getName() {
return "csharp"; return "csharp";
} }
@Override
public String getHelp() { public String getHelp() {
return "Generates a CSharp client library."; return "Generates a CSharp client library.";
} }
@Override public void setOptionalAssemblyInfoFlag(boolean flag) {
public String escapeReservedWord(String name) { this.optionalAssemblyInfoFlag = flag;
return "_" + name;
}
@Override
public String apiFileFolder() {
return outputFolder + File.separator + sourceFolder + File.separator + apiPackage().replace('.', File.separatorChar);
}
public String modelFileFolder() {
return outputFolder + File.separator + sourceFolder + File.separator + modelPackage().replace('.', File.separatorChar);
}
@Override
public String toVarName(String name) {
// sanitize name
name = sanitizeName(name);
// if it's all uppper case, do nothing
if (name.matches("^[A-Z_]*$")) {
return name;
}
// camelize the variable name
// pet_id => PetId
name = camelize(name);
// for reserved word or word starting with number, append _
if (reservedWords.contains(name) || name.matches("^\\d.*")) {
name = escapeReservedWord(name);
}
return name;
}
@Override
public String toParamName(String name) {
// replace - with _ e.g. created-at => created_at
name = name.replaceAll("-", "_");
// if it's all uppper case, do nothing
if (name.matches("^[A-Z_]*$")) {
return name;
}
// camelize(lower) the variable name
// pet_id => petId
name = camelize(name, true);
// for reserved word or word starting with number, append _
if (reservedWords.contains(name) || name.matches("^\\d.*")) {
name = escapeReservedWord(name);
}
return name;
}
@Override
public String toModelName(String name) {
// model name cannot use reserved keyword, e.g. return
if (reservedWords.contains(name)) {
throw new RuntimeException(name + " (reserved word) cannot be used as a model name");
}
// camelize the model name
// phone_number => PhoneNumber
return camelize(name);
}
@Override
public String toModelFilename(String name) {
// should be the same as the model name
return toModelName(name);
}
@Override
public String getTypeDeclaration(Property p) {
if (p instanceof ArrayProperty) {
ArrayProperty ap = (ArrayProperty) p;
Property inner = ap.getItems();
return getSwaggerType(p) + "<" + getTypeDeclaration(inner) + ">";
} else if (p instanceof MapProperty) {
MapProperty mp = (MapProperty) p;
Property inner = mp.getAdditionalProperties();
return getSwaggerType(p) + "<string, " + getTypeDeclaration(inner) + ">";
}
return super.getTypeDeclaration(p);
}
@Override
public String getSwaggerType(Property p) {
String swaggerType = super.getSwaggerType(p);
String type = null;
if (typeMapping.containsKey(swaggerType.toLowerCase())) {
type = typeMapping.get(swaggerType.toLowerCase());
if (languageSpecificPrimitives.contains(type)) {
return type;
}
} else {
type = swaggerType;
}
return toModelName(type);
}
@Override
public String toOperationId(String operationId) {
// throw exception if method name is empty
if (StringUtils.isEmpty(operationId)) {
throw new RuntimeException("Empty method name (operationId) not allowed");
}
// method name cannot use reserved keyword, e.g. return
if (reservedWords.contains(operationId)) {
throw new RuntimeException(operationId + " (reserved word) cannot be used as method name");
}
return camelize(sanitizeName(operationId));
}
public void setOptionalMethodArgumentFlag(boolean flag) {
this.optionalMethodArgumentFlag = flag;
} }
@Override @Override
public CodegenModel fromModel(String name, Model model, Map<String, Model> allDefinitions) { public CodegenModel fromModel(String name, Model model, Map<String, Model> allDefinitions) {
CodegenModel codegenModel = super.fromModel(name, model, allDefinitions); CodegenModel codegenModel = super.fromModel(name, model, allDefinitions);
if (allDefinitions != null && codegenModel != null && codegenModel.parent != null && codegenModel.hasEnums) {
if (allDefinitions != null && codegenModel != null && codegenModel.parent != null && codegenModel.hasEnums) {
final Model parentModel = allDefinitions.get(toModelName(codegenModel.parent)); final Model parentModel = allDefinitions.get(toModelName(codegenModel.parent));
final CodegenModel parentCodegenModel = super.fromModel(codegenModel.parent, parentModel); final CodegenModel parentCodegenModel = super.fromModel(codegenModel.parent, parentModel);
codegenModel = this.reconcileInlineEnums(codegenModel, parentCodegenModel); codegenModel = this.reconcileInlineEnums(codegenModel, parentCodegenModel);
@ -291,6 +270,13 @@ public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig
return codegenModel; return codegenModel;
} }
public void setOptionalProjectFileFlag(boolean flag) {
this.optionalProjectFileFlag = flag;
}
public void setPackageGuid(String packageGuid) {
this.packageGuid = packageGuid;
}
@Override @Override
public Map<String, Object> postProcessModels(Map<String, Object> objs) { public Map<String, Object> postProcessModels(Map<String, Object> objs) {
@ -349,8 +335,13 @@ public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig
} }
} }
} }
public void setTargetFramework(String dotnetFramework) {
if(!frameworks.containsKey(dotnetFramework)){
LOGGER.warn("Invalid .NET framework version, defaulting to " + this.targetFramework);
} else {
this.targetFramework = dotnetFramework;
} }
return objs; LOGGER.info("Generating code for .NET Framework " + this.targetFramework);
} }
private CodegenModel reconcileInlineEnums(CodegenModel codegenModel, CodegenModel parentCodegenModel) { private CodegenModel reconcileInlineEnums(CodegenModel codegenModel, CodegenModel parentCodegenModel) {
@ -471,7 +462,11 @@ public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig
return dp.getDefault().toString(); return dp.getDefault().toString();
} }
} }
public void setTargetFrameworkNuget(String targetFrameworkNuget) {
this.targetFrameworkNuget = targetFrameworkNuget;
}
return null; public void setSupportsAsync(Boolean supportsAsync){
this.supportsAsync = supportsAsync;
} }
} }

View File

@ -26,10 +26,10 @@ public class ClojureClientCodegen extends DefaultCodegen implements CodegenConfi
private static final String PROJECT_LICENSE_URL = "projectLicenseUrl"; private static final String PROJECT_LICENSE_URL = "projectLicenseUrl";
private static final String BASE_NAMESPACE = "baseNamespace"; private static final String BASE_NAMESPACE = "baseNamespace";
protected String projectName = null; protected String projectName;
protected String projectDescription = null; protected String projectDescription;
protected String projectVersion = null; protected String projectVersion;
protected String baseNamespace = null; protected String baseNamespace;
protected String sourceFolder = "src"; protected String sourceFolder = "src";
@ -172,7 +172,7 @@ public class ClojureClientCodegen extends DefaultCodegen implements CodegenConfi
@Override @Override
public String toVarName(String name) { public String toVarName(String name) {
name = name.replaceAll("[^a-zA-Z0-9_-]+", ""); name = name.replaceAll("[^a-zA-Z0-9_-]+", ""); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
name = dashize(name); name = dashize(name);
return name; return name;
} }
@ -196,6 +196,7 @@ public class ClojureClientCodegen extends DefaultCodegen implements CodegenConfi
return operations; return operations;
} }
@SuppressWarnings("static-method")
protected String namespaceToFolder(String ns) { protected String namespaceToFolder(String ns) {
return ns.replace(".", File.separator).replace("-", "_"); return ns.replace(".", File.separator).replace("-", "_");
} }

View File

@ -31,9 +31,13 @@ public class CsharpDotNet2ClientCodegen extends DefaultCodegen implements Codege
apiPackage = "IO.Swagger.Api"; apiPackage = "IO.Swagger.Api";
modelPackage = "IO.Swagger.Model"; modelPackage = "IO.Swagger.Model";
reservedWords = new HashSet<String>( setReservedWordsLowerCase(
Arrays.asList( Arrays.asList(
"abstract", "as", "base", "bool", "break", "byte", "case", "catch", "char", "checked", "class", "const", "continue", "decimal", "default", "delegate", "do", "double", "else", "enum", "event", "explicit", "extern", "false", "finally", "fixed", "float", "for", "foreach", "goto", "if", "implicit", "in", "int", "interface", "internal", "is", "lock", "long", "namespace", "new", "null", "object", "operator", "out", "override", "params", "private", "protected", "public", "readonly", "ref", "return", "sbyte", "sealed", "short", "sizeof", "stackalloc", "static", "string", "struct", "switch", "this", "throw", "true", "try", "typeof", "uint", "ulong", "unchecked", "unsafe", "ushort", "using", "virtual", "void", "volatile", "while") // local variable names in API methods (endpoints)
"path", "queryParams", "headerParams", "formParams", "fileParams", "postBody",
"authSettings", "response", "StatusCode",
// C# reserved word
"abstract", "as", "base", "bool", "break", "byte", "case", "catch", "char", "checked", "class", "const", "continue", "decimal", "default", "delegate", "do", "double", "else", "enum", "event", "explicit", "extern", "false", "finally", "fixed", "float", "for", "foreach", "goto", "if", "implicit", "in", "int", "interface", "internal", "is", "lock", "long", "namespace", "new", "null", "object", "operator", "out", "override", "params", "private", "protected", "public", "readonly", "ref", "return", "sbyte", "sealed", "short", "sizeof", "stackalloc", "static", "string", "struct", "switch", "this", "throw", "true", "try", "typeof", "uint", "ulong", "unchecked", "unsafe", "ushort", "using", "virtual", "void", "volatile", "while")
); );
@ -110,7 +114,7 @@ public class CsharpDotNet2ClientCodegen extends DefaultCodegen implements Codege
} else { } else {
additionalProperties.put(CLIENT_PACKAGE, clientPackage); additionalProperties.put(CLIENT_PACKAGE, clientPackage);
} }
supportingFiles.add(new SupportingFile("Configuration.mustache", supportingFiles.add(new SupportingFile("Configuration.mustache",
sourceFolder + File.separator + clientPackage.replace(".", java.io.File.separator), "Configuration.cs")); sourceFolder + File.separator + clientPackage.replace(".", java.io.File.separator), "Configuration.cs"));
supportingFiles.add(new SupportingFile("ApiClient.mustache", supportingFiles.add(new SupportingFile("ApiClient.mustache",
@ -135,14 +139,17 @@ public class CsharpDotNet2ClientCodegen extends DefaultCodegen implements Codege
this.packageVersion = packageVersion; this.packageVersion = packageVersion;
} }
@Override
public CodegenType getTag() { public CodegenType getTag() {
return CodegenType.CLIENT; return CodegenType.CLIENT;
} }
@Override
public String getName() { public String getName() {
return "CsharpDotNet2"; return "CsharpDotNet2";
} }
@Override
public String getHelp() { public String getHelp() {
return "Generates a C# .Net 2.0 client library."; return "Generates a C# .Net 2.0 client library.";
} }
@ -157,6 +164,7 @@ public class CsharpDotNet2ClientCodegen extends DefaultCodegen implements Codege
return outputFolder + File.separator + sourceFolder + File.separator + apiPackage().replace('.', File.separatorChar); return outputFolder + File.separator + sourceFolder + File.separator + apiPackage().replace('.', File.separatorChar);
} }
@Override
public String modelFileFolder() { public String modelFileFolder() {
return outputFolder + File.separator + sourceFolder + File.separator + modelPackage().replace('.', File.separatorChar); return outputFolder + File.separator + sourceFolder + File.separator + modelPackage().replace('.', File.separatorChar);
} }
@ -164,7 +172,7 @@ public class CsharpDotNet2ClientCodegen extends DefaultCodegen implements Codege
@Override @Override
public String toVarName(String name) { public String toVarName(String name) {
// replace - with _ e.g. created-at => created_at // replace - with _ e.g. created-at => created_at
name = name.replaceAll("-", "_"); name = name.replaceAll("-", "_"); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
// if it's all uppper case, do nothing // if it's all uppper case, do nothing
if (name.matches("^[A-Z_]*$")) { if (name.matches("^[A-Z_]*$")) {
@ -176,7 +184,7 @@ public class CsharpDotNet2ClientCodegen extends DefaultCodegen implements Codege
name = camelize(name); name = camelize(name);
// for reserved word or word starting with number, append _ // for reserved word or word starting with number, append _
if (reservedWords.contains(name) || name.matches("^\\d.*")) { if (isReservedWord(name) || name.matches("^\\d.*")) {
name = escapeReservedWord(name); name = escapeReservedWord(name);
} }
@ -198,7 +206,7 @@ public class CsharpDotNet2ClientCodegen extends DefaultCodegen implements Codege
name = camelize(name, true); name = camelize(name, true);
// for reserved word or word starting with number, append _ // for reserved word or word starting with number, append _
if (reservedWords.contains(name) || name.matches("^\\d.*")) { if (isReservedWord(name) || name.matches("^\\d.*")) {
name = escapeReservedWord(name); name = escapeReservedWord(name);
} }
@ -207,8 +215,10 @@ public class CsharpDotNet2ClientCodegen extends DefaultCodegen implements Codege
@Override @Override
public String toModelName(String name) { public String toModelName(String name) {
name = sanitizeName(name);
// model name cannot use reserved keyword, e.g. return // model name cannot use reserved keyword, e.g. return
if (reservedWords.contains(name)) { if (isReservedWord(name)) {
throw new RuntimeException(name + " (reserved word) cannot be used as a model name"); throw new RuntimeException(name + " (reserved word) cannot be used as a model name");
} }
@ -257,7 +267,7 @@ public class CsharpDotNet2ClientCodegen extends DefaultCodegen implements Codege
@Override @Override
public String toOperationId(String operationId) { public String toOperationId(String operationId) {
// method name cannot use reserved keyword, e.g. return // method name cannot use reserved keyword, e.g. return
if (reservedWords.contains(operationId)) { if (isReservedWord(operationId)) {
throw new RuntimeException(operationId + " (reserved word) cannot be used as method name"); throw new RuntimeException(operationId + " (reserved word) cannot be used as method name");
} }

View File

@ -35,7 +35,7 @@ public class DartClientCodegen extends DefaultCodegen implements CodegenConfig {
apiPackage = "lib.api"; apiPackage = "lib.api";
modelPackage = "lib.model"; modelPackage = "lib.model";
reservedWords = new HashSet<String>( setReservedWordsLowerCase(
Arrays.asList( Arrays.asList(
"abstract", "as", "assert", "async", "async*", "await", "abstract", "as", "assert", "async", "async*", "await",
"break", "case", "catch", "class", "const", "continue", "break", "case", "catch", "class", "const", "continue",
@ -76,6 +76,9 @@ public class DartClientCodegen extends DefaultCodegen implements CodegenConfig {
typeMapping.put("Date", "DateTime"); typeMapping.put("Date", "DateTime");
typeMapping.put("date", "DateTime"); typeMapping.put("date", "DateTime");
typeMapping.put("File", "MultipartFile"); typeMapping.put("File", "MultipartFile");
//TODO binary should be mapped to byte array
// mapped to String as a workaround
typeMapping.put("binary", "String");
cliOptions.add(new CliOption(BROWSER_CLIENT, "Is the client browser based")); cliOptions.add(new CliOption(BROWSER_CLIENT, "Is the client browser based"));
cliOptions.add(new CliOption(PUB_NAME, "Name in generated pubspec")); cliOptions.add(new CliOption(PUB_NAME, "Name in generated pubspec"));
@ -84,14 +87,17 @@ public class DartClientCodegen extends DefaultCodegen implements CodegenConfig {
cliOptions.add(new CliOption(CodegenConstants.SOURCE_FOLDER, "source folder for generated code")); cliOptions.add(new CliOption(CodegenConstants.SOURCE_FOLDER, "source folder for generated code"));
} }
@Override
public CodegenType getTag() { public CodegenType getTag() {
return CodegenType.CLIENT; return CodegenType.CLIENT;
} }
@Override
public String getName() { public String getName() {
return "dart"; return "dart";
} }
@Override
public String getHelp() { public String getHelp() {
return "Generates a Dart client library."; return "Generates a Dart client library.";
} }
@ -157,6 +163,7 @@ public class DartClientCodegen extends DefaultCodegen implements CodegenConfig {
return outputFolder + "/" + sourceFolder + "/" + apiPackage().replace('.', File.separatorChar); return outputFolder + "/" + sourceFolder + "/" + apiPackage().replace('.', File.separatorChar);
} }
@Override
public String modelFileFolder() { public String modelFileFolder() {
return outputFolder + "/" + sourceFolder + "/" + modelPackage().replace('.', File.separatorChar); return outputFolder + "/" + sourceFolder + "/" + modelPackage().replace('.', File.separatorChar);
} }
@ -164,7 +171,7 @@ public class DartClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override @Override
public String toVarName(String name) { public String toVarName(String name) {
// replace - with _ e.g. created-at => created_at // replace - with _ e.g. created-at => created_at
name = name.replaceAll("-", "_"); name = name.replaceAll("-", "_"); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
// if it's all uppper case, do nothing // if it's all uppper case, do nothing
if (name.matches("^[A-Z_]*$")) { if (name.matches("^[A-Z_]*$")) {
@ -176,7 +183,7 @@ public class DartClientCodegen extends DefaultCodegen implements CodegenConfig {
name = camelize(name, true); name = camelize(name, true);
// for reserved word or word starting with number, append _ // for reserved word or word starting with number, append _
if (reservedWords.contains(name) || name.matches("^\\d.*")) { if (isReservedWord(name) || name.matches("^\\d.*")) {
name = escapeReservedWord(name); name = escapeReservedWord(name);
} }
@ -192,7 +199,7 @@ public class DartClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override @Override
public String toModelName(String name) { public String toModelName(String name) {
// model name cannot use reserved keyword, e.g. return // model name cannot use reserved keyword, e.g. return
if (reservedWords.contains(name)) { if (isReservedWord(name)) {
throw new RuntimeException(name + " (reserved word) cannot be used as a model name"); throw new RuntimeException(name + " (reserved word) cannot be used as a model name");
} }
@ -214,15 +221,10 @@ public class DartClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override @Override
public String toDefaultValue(Property p) { public String toDefaultValue(Property p) {
if (p instanceof MapProperty) { if (p instanceof MapProperty) {
MapProperty ap = (MapProperty) p;
String inner = getSwaggerType(ap.getAdditionalProperties());
return "{}"; return "{}";
} else if (p instanceof ArrayProperty) { } else if (p instanceof ArrayProperty) {
ArrayProperty ap = (ArrayProperty) p;
String inner = getSwaggerType(ap.getItems());
return "[]"; return "[]";
} }
return super.toDefaultValue(p); return super.toDefaultValue(p);
} }
@ -259,7 +261,7 @@ public class DartClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override @Override
public String toOperationId(String operationId) { public String toOperationId(String operationId) {
// method name cannot use reserved keyword, e.g. return // method name cannot use reserved keyword, e.g. return
if (reservedWords.contains(operationId)) { if (isReservedWord(operationId)) {
throw new RuntimeException(operationId + " (reserved word) cannot be used as method name"); throw new RuntimeException(operationId + " (reserved word) cannot be used as method name");
} }

View File

@ -26,10 +26,10 @@ import java.util.HashSet;
public class FlashClientCodegen extends DefaultCodegen implements CodegenConfig { public class FlashClientCodegen extends DefaultCodegen implements CodegenConfig {
protected String packageName = "io.swagger"; protected String packageName = "io.swagger";
protected String packageVersion = null; protected String packageVersion;
protected String invokerPackage = "io.swagger"; protected String invokerPackage = "io.swagger";
protected String sourceFolder = "src/main/flex"; protected String sourceFolder = "flash";
public FlashClientCodegen() { public FlashClientCodegen() {
super(); super();
@ -63,12 +63,15 @@ public class FlashClientCodegen extends DefaultCodegen implements CodegenConfig
typeMapping.put("DateTime", "Date"); typeMapping.put("DateTime", "Date");
typeMapping.put("object", "Object"); typeMapping.put("object", "Object");
typeMapping.put("file", "File"); typeMapping.put("file", "File");
//TODO binary should be mapped to byte array
// mapped to String as a workaround
typeMapping.put("binary", "String");
importMapping = new HashMap<String, String>(); importMapping = new HashMap<String, String>();
importMapping.put("File", "flash.filesystem.File"); importMapping.put("File", "flash.filesystem.File");
// from // from
reservedWords = new HashSet<String>(Arrays.asList("add", "for", "lt", "tellTarget", "and", setReservedWordsLowerCase(Arrays.asList("add", "for", "lt", "tellTarget", "and",
"function", "ne", "this", "break", "ge", "new", "typeof", "continue", "gt", "not", "function", "ne", "this", "break", "ge", "new", "typeof", "continue", "gt", "not",
"var", "delete", "if", "on", "void", "do", "ifFrameLoaded", "onClipEvent", "while", "var", "delete", "if", "on", "void", "do", "ifFrameLoaded", "onClipEvent", "while",
"else", "in", "or", "with", "eq", "le", "return")); "else", "in", "or", "with", "eq", "le", "return"));
@ -80,7 +83,7 @@ public class FlashClientCodegen extends DefaultCodegen implements CodegenConfig
.defaultValue("1.0.0")); .defaultValue("1.0.0"));
cliOptions.add(new CliOption(CodegenConstants.INVOKER_PACKAGE, CodegenConstants.INVOKER_PACKAGE_DESC)); cliOptions.add(new CliOption(CodegenConstants.INVOKER_PACKAGE, CodegenConstants.INVOKER_PACKAGE_DESC));
cliOptions.add(new CliOption(CodegenConstants.SOURCE_FOLDER, "source folder for generated " + cliOptions.add(new CliOption(CodegenConstants.SOURCE_FOLDER, "source folder for generated " +
"code. e.g. src/main/flex")); "code. e.g. flash"));
} }
@ -121,8 +124,7 @@ public class FlashClientCodegen extends DefaultCodegen implements CodegenConfig
//modelPackage = invokerPackage + File.separatorChar + "client" + File.separatorChar + "model"; //modelPackage = invokerPackage + File.separatorChar + "client" + File.separatorChar + "model";
//apiPackage = invokerPackage + File.separatorChar + "client" + File.separatorChar + "api"; //apiPackage = invokerPackage + File.separatorChar + "client" + File.separatorChar + "api";
final String invokerFolder = (sourceFolder + File.separator + invokerPackage + File.separator final String invokerFolder = (sourceFolder + File.separator + "src/" + invokerPackage + File.separator).replace(".", File.separator).replace('.', File.separatorChar);
+ "swagger" + File.separator).replace(".", File.separator).replace('.', File.separatorChar);
supportingFiles.add(new SupportingFile("ApiInvoker.as", invokerFolder + "common", "ApiInvoker.as")); supportingFiles.add(new SupportingFile("ApiInvoker.as", invokerFolder + "common", "ApiInvoker.as"));
supportingFiles.add(new SupportingFile("ApiUrlHelper.as", invokerFolder + "common", "ApiUrlHelper.as")); supportingFiles.add(new SupportingFile("ApiUrlHelper.as", invokerFolder + "common", "ApiUrlHelper.as"));
@ -130,14 +132,15 @@ public class FlashClientCodegen extends DefaultCodegen implements CodegenConfig
supportingFiles.add(new SupportingFile("ListWrapper.as", invokerFolder + "common", "ListWrapper.as")); supportingFiles.add(new SupportingFile("ListWrapper.as", invokerFolder + "common", "ListWrapper.as"));
supportingFiles.add(new SupportingFile("SwaggerApi.as", invokerFolder + "common", "SwaggerApi.as")); supportingFiles.add(new SupportingFile("SwaggerApi.as", invokerFolder + "common", "SwaggerApi.as"));
supportingFiles.add(new SupportingFile("XMLWriter.as", invokerFolder + "common", "XMLWriter.as")); supportingFiles.add(new SupportingFile("XMLWriter.as", invokerFolder + "common", "XMLWriter.as"));
supportingFiles.add(new SupportingFile("ApiError.as", invokerFolder + "exception", "ApiErrors.as")); supportingFiles.add(new SupportingFile("ApiError.as", invokerFolder + "exception", "ApiError.as"));
supportingFiles.add(new SupportingFile("ApiErrorCodes.as", invokerFolder + "exception", "ApiErrorCodes.as")); supportingFiles.add(new SupportingFile("ApiErrorCodes.as", invokerFolder + "exception", "ApiErrorCodes.as"));
supportingFiles.add(new SupportingFile("ApiClientEvent.as", invokerFolder + "event", "ApiClientEvent.as")); supportingFiles.add(new SupportingFile("ApiClientEvent.as", invokerFolder + "event", "ApiClientEvent.as"));
supportingFiles.add(new SupportingFile("Response.as", invokerFolder + "event", "Response.as")); supportingFiles.add(new SupportingFile("Response.as", invokerFolder + "event", "Response.as"));
supportingFiles.add(new SupportingFile("build.properties", sourceFolder, "build.properties")); supportingFiles.add(new SupportingFile("build.properties", sourceFolder, "build.properties"));
supportingFiles.add(new SupportingFile("build.xml", sourceFolder, "build.xml")); supportingFiles.add(new SupportingFile("build.xml", sourceFolder, "build.xml"));
supportingFiles.add(new SupportingFile("AirExecutorApp-app.xml", sourceFolder + File.separatorChar supportingFiles.add(new SupportingFile("README.txt", sourceFolder, "README.txt"));
+ "bin", "AirExecutorApp-app.xml")); //supportingFiles.add(new SupportingFile("AirExecutorApp-app.xml", sourceFolder + File.separatorChar
// + "bin", "AirExecutorApp-app.xml"));
supportingFiles.add(new SupportingFile("ASAXB-0.1.1.swc", sourceFolder + File.separatorChar supportingFiles.add(new SupportingFile("ASAXB-0.1.1.swc", sourceFolder + File.separatorChar
+ "lib", "ASAXB-0.1.1.swc")); + "lib", "ASAXB-0.1.1.swc"));
supportingFiles.add(new SupportingFile("as3corelib.swc", sourceFolder + File.separatorChar supportingFiles.add(new SupportingFile("as3corelib.swc", sourceFolder + File.separatorChar
@ -156,14 +159,17 @@ public class FlashClientCodegen extends DefaultCodegen implements CodegenConfig
return str.replaceAll("\\.", "_"); return str.replaceAll("\\.", "_");
} }
@Override
public CodegenType getTag() { public CodegenType getTag() {
return CodegenType.CLIENT; return CodegenType.CLIENT;
} }
@Override
public String getName() { public String getName() {
return "flash"; return "flash";
} }
@Override
public String getHelp() { public String getHelp() {
return "Generates a Flash client library."; return "Generates a Flash client library.";
} }
@ -175,25 +181,19 @@ public class FlashClientCodegen extends DefaultCodegen implements CodegenConfig
@Override @Override
public String apiFileFolder() { public String apiFileFolder() {
return (outputFolder + File.separatorChar + sourceFolder + File.separatorChar return (outputFolder + File.separatorChar + sourceFolder + File.separatorChar + "src/"
+ apiPackage().replace('.', File.separatorChar)).replace('/', File.separatorChar); + apiPackage().replace('.', File.separatorChar)).replace('/', File.separatorChar);
} }
@Override
public String modelFileFolder() { public String modelFileFolder() {
return (outputFolder + File.separatorChar + sourceFolder + File.separatorChar return (outputFolder + File.separatorChar + sourceFolder + File.separatorChar + "src/"
+ modelPackage().replace('.', File.separatorChar)).replace('/', File.separatorChar); + modelPackage().replace('.', File.separatorChar)).replace('/', File.separatorChar);
} }
@Override @Override
public String getTypeDeclaration(Property p) { public String getTypeDeclaration(Property p) {
if (p instanceof ArrayProperty) { if (p instanceof ArrayProperty || p instanceof MapProperty) {
ArrayProperty ap = (ArrayProperty) p;
Property inner = ap.getItems();
return getSwaggerType(p);
} else if (p instanceof MapProperty) {
MapProperty mp = (MapProperty) p;
Property inner = mp.getAdditionalProperties();
return getSwaggerType(p); return getSwaggerType(p);
} }
return super.getTypeDeclaration(p); return super.getTypeDeclaration(p);
@ -214,6 +214,7 @@ public class FlashClientCodegen extends DefaultCodegen implements CodegenConfig
return type; return type;
} }
@Override
public String toDefaultValue(Property p) { public String toDefaultValue(Property p) {
if (p instanceof StringProperty) { if (p instanceof StringProperty) {
return "null"; return "null";
@ -248,22 +249,18 @@ public class FlashClientCodegen extends DefaultCodegen implements CodegenConfig
} }
return "0"; return "0";
} else if (p instanceof MapProperty) { } else if (p instanceof MapProperty) {
MapProperty ap = (MapProperty) p;
String inner = getSwaggerType(ap.getAdditionalProperties());
return "new Dictionary()"; return "new Dictionary()";
} else if (p instanceof ArrayProperty) { } else if (p instanceof ArrayProperty) {
ArrayProperty ap = (ArrayProperty) p;
String inner = getSwaggerType(ap.getItems());
return "new Array()"; return "new Array()";
} else { } else {
return "null"; return "NaN";
} }
} }
@Override @Override
public String toVarName(String name) { public String toVarName(String name) {
// replace - with _ e.g. created-at => created_at // replace - with _ e.g. created-at => created_at
name = name.replaceAll("-", "_"); name = name.replaceAll("-", "_"); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
// if it's all uppper case, convert to lower case // if it's all uppper case, convert to lower case
if (name.matches("^[A-Z_]*$")) { if (name.matches("^[A-Z_]*$")) {
@ -275,7 +272,7 @@ public class FlashClientCodegen extends DefaultCodegen implements CodegenConfig
name = camelize(dropDots(name), true); name = camelize(dropDots(name), true);
// for reserved word or word starting with number, append _ // for reserved word or word starting with number, append _
if (reservedWords.contains(name) || name.matches("^\\d.*")) { if (isReservedWord(name) || name.matches("^\\d.*")) {
name = escapeReservedWord(name); name = escapeReservedWord(name);
} }
@ -291,7 +288,7 @@ public class FlashClientCodegen extends DefaultCodegen implements CodegenConfig
@Override @Override
public String toModelName(String name) { public String toModelName(String name) {
// model name cannot use reserved keyword, e.g. return // model name cannot use reserved keyword, e.g. return
if (reservedWords.contains(name)) { if (isReservedWord(name)) {
throw new RuntimeException(name + " (reserved word) cannot be used as a model name"); throw new RuntimeException(name + " (reserved word) cannot be used as a model name");
} }
@ -303,7 +300,7 @@ public class FlashClientCodegen extends DefaultCodegen implements CodegenConfig
@Override @Override
public String toModelFilename(String name) { public String toModelFilename(String name) {
// model name cannot use reserved keyword, e.g. return // model name cannot use reserved keyword, e.g. return
if (reservedWords.contains(name)) { if (isReservedWord(name)) {
throw new RuntimeException(name + " (reserved word) cannot be used as a model name"); throw new RuntimeException(name + " (reserved word) cannot be used as a model name");
} }
@ -315,7 +312,7 @@ public class FlashClientCodegen extends DefaultCodegen implements CodegenConfig
@Override @Override
public String toApiFilename(String name) { public String toApiFilename(String name) {
// replace - with _ e.g. created-at => created_at // replace - with _ e.g. created-at => created_at
name = name.replaceAll("-", "_"); name = name.replaceAll("-", "_"); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
// e.g. PhoneNumberApi.rb => phone_number_api.rb // e.g. PhoneNumberApi.rb => phone_number_api.rb
return camelize(name) + "Api"; return camelize(name) + "Api";
@ -346,7 +343,7 @@ public class FlashClientCodegen extends DefaultCodegen implements CodegenConfig
} }
// method name cannot use reserved keyword, e.g. return // method name cannot use reserved keyword, e.g. return
if (reservedWords.contains(operationId)) { if (isReservedWord(operationId)) {
throw new RuntimeException(operationId + " (reserved word) cannot be used as method name"); throw new RuntimeException(operationId + " (reserved word) cannot be used as method name");
} }
@ -368,7 +365,4 @@ public class FlashClientCodegen extends DefaultCodegen implements CodegenConfig
public void setSourceFolder(String sourceFolder) { public void setSourceFolder(String sourceFolder) {
this.sourceFolder = sourceFolder; this.sourceFolder = sourceFolder;
} }
} }

View File

@ -4,6 +4,8 @@ import com.fasterxml.jackson.core.JsonProcessingException;
import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
import config.ConfigParser;
import io.swagger.codegen.*; import io.swagger.codegen.*;
import io.swagger.models.HttpMethod; import io.swagger.models.HttpMethod;
import io.swagger.models.Operation; import io.swagger.models.Operation;
@ -14,7 +16,13 @@ import io.swagger.util.Yaml;
import java.io.File; import java.io.File;
import java.util.*; import java.util.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class FlaskConnexionCodegen extends DefaultCodegen implements CodegenConfig { public class FlaskConnexionCodegen extends DefaultCodegen implements CodegenConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(FlaskConnexionCodegen.class);
public static final String CONTROLLER_PACKAGE = "controllerPackage"; public static final String CONTROLLER_PACKAGE = "controllerPackage";
public static final String DEFAULT_CONTROLLER = "defaultController"; public static final String DEFAULT_CONTROLLER = "defaultController";
@ -65,7 +73,7 @@ public class FlaskConnexionCodegen extends DefaultCodegen implements CodegenConf
embeddedTemplateDir = templateDir = "flaskConnexion"; embeddedTemplateDir = templateDir = "flaskConnexion";
// from https://docs.python.org/release/2.5.4/ref/keywords.html // from https://docs.python.org/release/2.5.4/ref/keywords.html
reservedWords = new HashSet<String>( setReservedWordsLowerCase(
Arrays.asList( Arrays.asList(
"and", "del", "from", "not", "while", "as", "elif", "global", "or", "with", "and", "del", "from", "not", "while", "as", "elif", "global", "or", "with",
"assert", "else", "if", "pass", "yield", "break", "except", "import", "assert", "else", "if", "pass", "yield", "break", "except", "import",
@ -132,6 +140,7 @@ public class FlaskConnexionCodegen extends DefaultCodegen implements CodegenConf
} }
} }
@Override
public String apiPackage() { public String apiPackage() {
return controllerPackage; return controllerPackage;
} }
@ -142,6 +151,7 @@ public class FlaskConnexionCodegen extends DefaultCodegen implements CodegenConf
* @return the CodegenType for this generator * @return the CodegenType for this generator
* @see io.swagger.codegen.CodegenType * @see io.swagger.codegen.CodegenType
*/ */
@Override
public CodegenType getTag() { public CodegenType getTag() {
return CodegenType.SERVER; return CodegenType.SERVER;
} }
@ -152,6 +162,7 @@ public class FlaskConnexionCodegen extends DefaultCodegen implements CodegenConf
* *
* @return the friendly name for the generator * @return the friendly name for the generator
*/ */
@Override
public String getName() { public String getName() {
return "python-flask"; return "python-flask";
} }
@ -162,9 +173,10 @@ public class FlaskConnexionCodegen extends DefaultCodegen implements CodegenConf
* *
* @return A string value for the help message * @return A string value for the help message
*/ */
@Override
public String getHelp() { public String getHelp() {
return "Generates a python server library using the connexion project. By default, " + return "Generates a Python server library using the Connexion project. By default, " +
"it will also generate service classes--which you can disable with the `-Dnoservice` environment variable."; "it will also generate service classes -- which you can disable with the `-Dnoservice` environment variable.";
} }
@Override @Override
@ -245,7 +257,7 @@ public class FlaskConnexionCodegen extends DefaultCodegen implements CodegenConf
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private List<Map<String, Object>> getOperations(Map<String, Object> objs) { private static List<Map<String, Object>> getOperations(Map<String, Object> objs) {
List<Map<String, Object>> result = new ArrayList<Map<String, Object>>(); List<Map<String, Object>> result = new ArrayList<Map<String, Object>>();
Map<String, Object> apiInfo = (Map<String, Object>) objs.get("apiInfo"); Map<String, Object> apiInfo = (Map<String, Object>) objs.get("apiInfo");
List<Map<String, Object>> apis = (List<Map<String, Object>>) apiInfo.get("apis"); List<Map<String, Object>> apis = (List<Map<String, Object>>) apiInfo.get("apis");
@ -255,7 +267,7 @@ public class FlaskConnexionCodegen extends DefaultCodegen implements CodegenConf
return result; return result;
} }
private List<Map<String, Object>> sortOperationsByPath(List<CodegenOperation> ops) { private static List<Map<String, Object>> sortOperationsByPath(List<CodegenOperation> ops) {
Multimap<String, CodegenOperation> opsByPath = ArrayListMultimap.create(); Multimap<String, CodegenOperation> opsByPath = ArrayListMultimap.create();
for (CodegenOperation op : ops) { for (CodegenOperation op : ops) {
@ -285,7 +297,7 @@ public class FlaskConnexionCodegen extends DefaultCodegen implements CodegenConf
try { try {
objs.put("swagger-yaml", Yaml.mapper().writeValueAsString(swagger)); objs.put("swagger-yaml", Yaml.mapper().writeValueAsString(swagger));
} catch (JsonProcessingException e) { } catch (JsonProcessingException e) {
e.printStackTrace(); LOGGER.error(e.getMessage(), e);
} }
} }
for (Map<String, Object> operations : getOperations(objs)) { for (Map<String, Object> operations : getOperations(objs)) {
@ -300,7 +312,7 @@ public class FlaskConnexionCodegen extends DefaultCodegen implements CodegenConf
@Override @Override
public String toOperationId(String operationId) { public String toOperationId(String operationId) {
operationId = super.toOperationId(operationId); operationId = super.toOperationId(operationId); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
// Use the part after the last dot, e.g. // Use the part after the last dot, e.g.
// controllers.defaultController.addPet => addPet // controllers.defaultController.addPet => addPet
operationId = operationId.replaceAll(".*\\.", ""); operationId = operationId.replaceAll(".*\\.", "");
@ -308,4 +320,4 @@ public class FlaskConnexionCodegen extends DefaultCodegen implements CodegenConf
// addPet => add_pet // addPet => add_pet
return underscore(operationId); return underscore(operationId);
} }
} }

View File

@ -0,0 +1,283 @@
package io.swagger.codegen.languages;
import io.swagger.codegen.*;
import io.swagger.models.properties.ArrayProperty;
import io.swagger.models.properties.MapProperty;
import io.swagger.models.properties.Property;
import java.io.File;
import java.util.*;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class GoClientCodegen extends DefaultCodegen implements CodegenConfig {
static Logger LOGGER = LoggerFactory.getLogger(GoClientCodegen.class);
protected String packageName = "swagger";
protected String packageVersion = "1.0.0";
public CodegenType getTag() {
return CodegenType.CLIENT;
}
public String getName() {
return "go";
}
public String getHelp() {
return "Generates a Go client library (beta).";
}
public GoClientCodegen() {
super();
outputFolder = "generated-code/go";
modelTemplateFiles.put("model.mustache", ".go");
apiTemplateFiles.put("api.mustache", ".go");
templateDir = "go";
setReservedWordsLowerCase(
Arrays.asList(
"break", "default", "func", "interface", "select",
"case", "defer", "go", "map", "struct",
"chan", "else", "goto", "package", "switch",
"const", "fallthrough", "if", "range", "type",
"continue", "for", "import", "return", "var")
);
defaultIncludes = new HashSet<String>(
Arrays.asList(
"map",
"array")
);
languageSpecificPrimitives = new HashSet<String>(
Arrays.asList(
"string",
"bool",
"uint",
"uint32",
"uint64",
"int",
"int32",
"int64",
"float32",
"float64",
"complex64",
"complex128",
"rune",
"byte")
);
instantiationTypes.clear();
/*instantiationTypes.put("array", "GoArray");
instantiationTypes.put("map", "GoMap");*/
typeMapping.clear();
typeMapping.put("integer", "int32");
typeMapping.put("long", "int64");
typeMapping.put("float", "float32");
typeMapping.put("double", "float64");
typeMapping.put("boolean", "bool");
typeMapping.put("string", "string");
typeMapping.put("Date", "time.Time");
typeMapping.put("DateTime", "time.Time");
typeMapping.put("password", "string");
typeMapping.put("File", "*os.File");
typeMapping.put("file", "*os.File");
// map binary to string as a workaround
// the correct solution is to use []byte
typeMapping.put("binary", "string");
importMapping = new HashMap<String, String>();
importMapping.put("time.Time", "time");
importMapping.put("*os.File", "os");
cliOptions.clear();
cliOptions.add(new CliOption(CodegenConstants.PACKAGE_NAME, "Go package name (convention: lowercase).")
.defaultValue("swagger"));
cliOptions.add(new CliOption(CodegenConstants.PACKAGE_VERSION, "Go package version.")
.defaultValue("1.0.0"));
}
@Override
public void processOpts() {
//super.processOpts();
if (additionalProperties.containsKey(CodegenConstants.PACKAGE_NAME)) {
setPackageName((String) additionalProperties.get(CodegenConstants.PACKAGE_NAME));
}
else {
setPackageName("swagger");
}
if (additionalProperties.containsKey(CodegenConstants.PACKAGE_VERSION)) {
setPackageVersion((String) additionalProperties.get(CodegenConstants.PACKAGE_VERSION));
}
else {
setPackageVersion("1.0.0");
}
additionalProperties.put(CodegenConstants.PACKAGE_NAME, packageName);
additionalProperties.put(CodegenConstants.PACKAGE_VERSION, packageVersion);
modelPackage = packageName;
apiPackage = packageName;
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
}
@Override
public String escapeReservedWord(String name) {
return "_" + name;
}
@Override
public String apiFileFolder() {
return outputFolder + File.separator + packageName;
}
public String modelFileFolder() {
return outputFolder + File.separator + packageName;
}
@Override
public String toVarName(String name) {
// replace - with _ e.g. created-at => created_at
name = name.replaceAll("-", "_");
// if it's all uppper case, do nothing
if (name.matches("^[A-Z_]*$"))
return name;
// camelize (lower first character) the variable name
// pet_id => PetId
name = camelize(name);
// for reserved word or word starting with number, append _
if(isReservedWord(name) || name.matches("^\\d.*"))
name = escapeReservedWord(name);
return name;
}
@Override
public String toParamName(String name) {
// should be the same as variable name
return toVarName(name);
}
@Override
public String toModelName(String name) {
// model name cannot use reserved keyword, e.g. return
if(isReservedWord(name))
throw new RuntimeException(name + " (reserved word) cannot be used as a model name");
// camelize the model name
// phone_number => PhoneNumber
return camelize(name);
}
@Override
public String toModelFilename(String name) {
// should be the same as the model name
return toModelName(name);
}
@Override
public String getTypeDeclaration(Property p) {
if(p instanceof ArrayProperty) {
ArrayProperty ap = (ArrayProperty) p;
Property inner = ap.getItems();
return "[]" + getTypeDeclaration(inner);
}
else if (p instanceof MapProperty) {
MapProperty mp = (MapProperty) p;
Property inner = mp.getAdditionalProperties();
return getSwaggerType(p) + "[string]" + getTypeDeclaration(inner);
}
return super.getTypeDeclaration(p);
}
@Override
public String getSwaggerType(Property p) {
String swaggerType = super.getSwaggerType(p);
String type = null;
if(typeMapping.containsKey(swaggerType)) {
type = typeMapping.get(swaggerType);
if(languageSpecificPrimitives.contains(type))
return (type);
}
else
type = swaggerType;
return type;
}
@Override
public String toOperationId(String operationId) {
// method name cannot use reserved keyword, e.g. return
if(isReservedWord(operationId))
throw new RuntimeException(operationId + " (reserved word) cannot be used as method name");
return camelize(operationId);
}
@Override
public Map<String, Object> postProcessOperations(Map<String, Object> objs) {
@SuppressWarnings("unchecked")
Map<String, Object> objectMap = (Map<String, Object>) objs.get("operations");
@SuppressWarnings("unchecked")
List<CodegenOperation> operations = (List<CodegenOperation>) objectMap.get("operation");
for (CodegenOperation operation : operations) {
// http method verb conversion (e.g. PUT => Put)
operation.httpMethod = camelize(operation.httpMethod.toLowerCase());
}
// remove model imports to avoid error
List<Map<String, String>> imports = (List<Map<String, String>>) objs.get("imports");
if (imports == null)
return objs;
Iterator<Map<String, String>> iterator = imports.iterator();
while (iterator.hasNext()) {
String _import = iterator.next().get("import");
if (_import.startsWith(apiPackage()))
iterator.remove();
}
return objs;
}
@Override
public Map<String, Object> postProcessModels(Map<String, Object> objs) {
// remove model imports to avoid error
List<Map<String, String>> imports = (List<Map<String, String>>) objs.get("imports");
final String prefix = modelPackage();
Iterator<Map<String, String>> iterator = imports.iterator();
while (iterator.hasNext()) {
String _import = iterator.next().get("import");
if (_import.startsWith(prefix))
iterator.remove();
}
return objs;
}
@Override
protected boolean needToImport(String type) {
return !defaultIncludes.contains(type)
&& !languageSpecificPrimitives.contains(type);
}
public void setPackageName(String packageName) {
this.packageName = packageName;
}
public void setPackageVersion(String packageVersion) {
this.packageVersion = packageVersion;
}
}

View File

@ -0,0 +1,345 @@
package io.swagger.codegen.languages;
import io.swagger.codegen.*;
import io.swagger.models.properties.*;
import io.swagger.models.Model;
import io.swagger.models.Operation;
import io.swagger.models.Swagger;
import java.util.*;
import java.io.File;
public class HaskellServantCodegen extends DefaultCodegen implements CodegenConfig {
// source folder where to write the files
protected String sourceFolder = "src";
protected String apiVersion = "0.0.1";
/**
* Configures the type of generator.
*
* @return the CodegenType for this generator
* @see io.swagger.codegen.CodegenType
*/
public CodegenType getTag() {
return CodegenType.SERVER;
}
/**
* Configures a friendly name for the generator. This will be used by the generator
* to select the library with the -l flag.
*
* @return the friendly name for the generator
*/
public String getName() {
return "haskell-servant";
}
/**
* Returns human-friendly help for the generator. Provide the consumer with help
* tips, parameters here
*
* @return A string value for the help message
*/
public String getHelp() {
return "Generates a HaskellServantCodegen library.";
}
public HaskellServantCodegen() {
super();
// set the output folder here
outputFolder = "generated-code/HaskellServantCodegen";
/**
* Models. You can write model files using the modelTemplateFiles map.
* if you want to create one template for file, you can do so here.
* for multiple files for model, just put another entry in the `modelTemplateFiles` with
* a different extension
*/
modelTemplateFiles.put(
"model.mustache", // the template to use
".hs"); // the extension for each file to write
/**
* Api classes. You can write classes for each Api file with the apiTemplateFiles map.
* as with models, add multiple entries with different extensions for multiple files per
* class
*/
apiTemplateFiles.put(
"api.mustache", // the template to use
".hs"); // the extension for each file to write
/**
* Template Location. This is the location which templates will be read from. The generator
* will use the resource stream to attempt to read the templates.
*/
embeddedTemplateDir = templateDir = "haskell-servant";
/**
* Api Package. Optional, if needed, this can be used in templates
*/
apiPackage = "Api";
/**
* Model Package. Optional, if needed, this can be used in templates
*/
modelPackage = "Model";
/**
* Reserved words. Override this with reserved words specific to your language
*/
// from https://wiki.haskell.org/Keywords
setReservedWordsLowerCase(
Arrays.asList(
"as", "case", "of",
"class", "data", // "data family", "data instance",
"default", "deriving", // "deriving instance",
"do",
"forall", "foreign", "hiding",
"id",
"if", "then", "else",
"import", "infix", "infixl", "infixr",
"instance", "let", "in",
"mdo", "module", "newtype",
"proc", "qualified", "rec",
"type", // "type family", "type instance",
"where"
)
);
/**
* Additional Properties. These values can be passed to the templates and
* are available in models, apis, and supporting files
*/
additionalProperties.put("apiVersion", apiVersion);
/**
* Supporting Files. You can write single files for the generator with the
* entire object tree available. If the input file has a suffix of `.mustache
* it will be processed by the template engine. Otherwise, it will be copied
*/
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
supportingFiles.add(new SupportingFile("stack.mustache", "", "stack.yaml"));
supportingFiles.add(new SupportingFile("haskell-servant-codegen.mustache", "", "haskell-servant-codegen.cabal"));
supportingFiles.add(new SupportingFile("Setup.mustache", "", "Setup.hs"));
supportingFiles.add(new SupportingFile("LICENSE", "", "LICENSE"));
supportingFiles.add(new SupportingFile("Apis.mustache", "lib", "Apis.hs"));
supportingFiles.add(new SupportingFile("Utils.mustache", "lib", "Utils.hs"));
supportingFiles.add(new SupportingFile("Client.mustache", "client", "Main.hs"));
supportingFiles.add(new SupportingFile("Server.mustache", "server", "Main.hs"));
/**
* Language Specific Primitives. These types will not trigger imports by
* the client generator
*/
languageSpecificPrimitives = new HashSet<String>(
Arrays.asList(
"Bool",
"String",
"Int",
"Integer",
"Float",
"Char",
"Double",
"List",
"FilePath"
)
);
typeMapping.clear();
// typeMapping.put("enum", "NSString");
typeMapping.put("array", "List");
typeMapping.put("set", "Set");
typeMapping.put("boolean", "Bool");
typeMapping.put("string", "String");
typeMapping.put("int", "Int");
typeMapping.put("long", "Integer");
typeMapping.put("float", "Float");
// typeMapping.put("byte", "Byte");
typeMapping.put("short", "Int");
typeMapping.put("char", "Char");
typeMapping.put("double", "Double");
typeMapping.put("DateTime", "Integer");
// typeMapping.put("object", "Map");
typeMapping.put("file", "FilePath");
importMapping.clear();
importMapping.put("Map", "qualified Data.Map as Map");
cliOptions.add(new CliOption(CodegenConstants.MODEL_PACKAGE, CodegenConstants.MODEL_PACKAGE_DESC));
cliOptions.add(new CliOption(CodegenConstants.API_PACKAGE, CodegenConstants.API_PACKAGE_DESC));
}
/**
* Escapes a reserved word as defined in the `reservedWords` array. Handle escaping
* those terms here. This logic is only called if a variable matches the reseved words
*
* @return the escaped term
*/
@Override
public String escapeReservedWord(String name) {
return name + "_";
}
/**
* Location to write model files. You can use the modelPackage() as defined when the class is
* instantiated
*/
public String modelFileFolder() {
return outputFolder + File.separatorChar + "lib" + File.separatorChar + modelPackage().replace('.', File.separatorChar);
}
/**
* Location to write api files. You can use the apiPackage() as defined when the class is
* instantiated
*/
@Override
public String apiFileFolder() {
return outputFolder + File.separatorChar + "lib" + File.separatorChar + apiPackage().replace('.', File.separatorChar);
}
/**
* Optional - type declaration. This is a String which is used by the templates to instantiate your
* types. There is typically special handling for different property types
*
* @return a string value used as the `dataType` field for model templates, `returnType` for api templates
*/
@Override
public String getTypeDeclaration(Property p) {
if(p instanceof ArrayProperty) {
ArrayProperty ap = (ArrayProperty) p;
Property inner = ap.getItems();
return "[" + getTypeDeclaration(inner) + "]";
}
else if (p instanceof MapProperty) {
MapProperty mp = (MapProperty) p;
Property inner = mp.getAdditionalProperties();
return "Map.Map String " + getTypeDeclaration(inner);
}
return super.getTypeDeclaration(p);
}
/**
* Optional - swagger type conversion. This is used to map swagger types in a `Property` into
* either language specific types via `typeMapping` or into complex models if there is not a mapping.
*
* @return a string value of the type or complex model for this property
* @see io.swagger.models.properties.Property
*/
@Override
public String getSwaggerType(Property p) {
String swaggerType = super.getSwaggerType(p);
String type = null;
if(typeMapping.containsKey(swaggerType)) {
type = typeMapping.get(swaggerType);
if(languageSpecificPrimitives.contains(type))
return toModelName(type);
}
else
type = swaggerType;
return toModelName(type);
}
private String capturePath(String path, List<CodegenParameter> pathParams) {
for (CodegenParameter p : pathParams) {
String pName = "{"+p.baseName+"}";
if (path.indexOf(pName) >= 0) {
path = path.replace(pName, "Capture " + "\""+p.baseName+"\" " + p.dataType);
}
}
return path;
}
private String queryPath(String path, List<CodegenParameter> queryParams) {
for (CodegenParameter p : queryParams) {
path += " :> QueryParam \"" + p.baseName + "\" " + p.dataType;
}
return path;
}
private String bodyPath(String path, List<CodegenParameter> bodyParams) {
for (CodegenParameter p : bodyParams) {
path += " :> ReqBody '[JSON] " + p.dataType;
}
return path;
}
private String formPath(String path, List<CodegenParameter> formParams) {
String names = "Form";
for (CodegenParameter p : formParams) {
if(p.dataType.equals("FilePath")){
// file data processing
}
names += p.baseName;
}
if(formParams.size() > 0){
path += " :> ReqBody '[FormUrlEncoded] " + names;
}
return path;
}
private String headerPath(String path, List<CodegenParameter> headerParams) {
for (CodegenParameter p : headerParams) {
path += " :> Header \"" + p.baseName + "\" " + p.dataType;
}
return path;
}
private String filterReturnType(String rt) {
if (rt == null || rt.equals("null")) {
return "()";
} else if (rt.indexOf(" ") >= 0) {
return "(" + rt + ")";
}
return rt;
}
private String addReturnPath(String path, String httpMethod, String returnType) {
return path + " :> " + upperCaseFirst(httpMethod) + " '[JSON] " + filterReturnType(returnType);
}
private String joinStrings(String sep, List<String> ss) {
StringBuilder sb = new StringBuilder();
for (String s : ss) {
if (sb.length() > 0) {
sb.append(sep);
}
sb.append(s);
}
return sb.toString();
}
private String replacePathSplitter(String path) {
String[] ps = path.replaceFirst("/", "").split("/", 0);
List<String> rs = new ArrayList<String>();
for (String p : ps) {
if (p.indexOf("{") < 0) {
rs.add("\"" + p + "\"");
} else {
rs.add(p);
}
}
return joinStrings(" :> ", rs);
}
private String upperCaseFirst(String str) {
char[] array = str.toLowerCase().toCharArray();
array[0] = Character.toUpperCase(array[0]);
return new String(array);
}
private String parseScheme(String basePath) {
return "Http";
}
@Override
public CodegenOperation fromOperation(String resourcePath, String httpMethod, Operation operation, Map<String, Model> definitions, Swagger swagger){
CodegenOperation op = super.fromOperation(resourcePath, httpMethod, operation, definitions, swagger);
String path = op.path;
op.nickname = addReturnPath(headerPath(formPath(bodyPath(queryPath(capturePath(replacePathSplitter(path), op.pathParams), op.queryParams), op.bodyParams), op.formParams), op.headerParams), op.httpMethod, op.returnType);
return op;
}
}

View File

@ -5,8 +5,6 @@ import io.swagger.models.Operation;
import io.swagger.models.Path; import io.swagger.models.Path;
import io.swagger.models.Swagger; import io.swagger.models.Swagger;
import io.swagger.models.properties.*; import io.swagger.models.properties.*;
import org.apache.commons.lang.StringUtils;
import java.util.*; import java.util.*;
import java.io.File; import java.io.File;
@ -22,6 +20,7 @@ public class JMeterCodegen extends DefaultCodegen implements CodegenConfig {
* @return the CodegenType for this generator * @return the CodegenType for this generator
* @see io.swagger.codegen.CodegenType * @see io.swagger.codegen.CodegenType
*/ */
@Override
public CodegenType getTag() { public CodegenType getTag() {
return CodegenType.CLIENT; return CodegenType.CLIENT;
} }
@ -32,6 +31,7 @@ public class JMeterCodegen extends DefaultCodegen implements CodegenConfig {
* *
* @return the friendly name for the generator * @return the friendly name for the generator
*/ */
@Override
public String getName() { public String getName() {
return "jmeter"; return "jmeter";
} }
@ -42,6 +42,7 @@ public class JMeterCodegen extends DefaultCodegen implements CodegenConfig {
* *
* @return A string value for the help message * @return A string value for the help message
*/ */
@Override
public String getHelp() { public String getHelp() {
return "Generates a JMeter .jmx file."; return "Generates a JMeter .jmx file.";
} }
@ -97,6 +98,7 @@ public class JMeterCodegen extends DefaultCodegen implements CodegenConfig {
// supportingFiles.add(new SupportingFile("testdata-localhost.mustache", "input", "testdata-localhost.csv")); // supportingFiles.add(new SupportingFile("testdata-localhost.mustache", "input", "testdata-localhost.csv"));
} }
@Override
public void preprocessSwagger(Swagger swagger) { public void preprocessSwagger(Swagger swagger) {
if (swagger != null && swagger.getPaths() != null) { if (swagger != null && swagger.getPaths() != null) {
for (String pathname : swagger.getPaths().keySet()) { for (String pathname : swagger.getPaths().keySet()) {
@ -126,6 +128,7 @@ public class JMeterCodegen extends DefaultCodegen implements CodegenConfig {
* Location to write model files. You can use the modelPackage() as defined when the class is * Location to write model files. You can use the modelPackage() as defined when the class is
* instantiated * instantiated
*/ */
@Override
public String modelFileFolder() { public String modelFileFolder() {
return outputFolder + "/" + sourceFolder + "/" + modelPackage().replace('.', File.separatorChar); return outputFolder + "/" + sourceFolder + "/" + modelPackage().replace('.', File.separatorChar);
} }

View File

@ -0,0 +1,74 @@
package io.swagger.codegen.languages;
import java.io.File;
import java.util.List;
import java.util.Map;
import io.swagger.codegen.CliOption;
import io.swagger.codegen.CodegenConstants;
import io.swagger.codegen.CodegenOperation;
import io.swagger.models.Operation;
public class JavaCXFServerCodegen extends AbstractJavaJAXRSServerCodegen
{
public JavaCXFServerCodegen()
{
super();
sourceFolder = "src/gen/java";
invokerPackage = "io.swagger.api";
artifactId = "swagger-jaxrs-server";
outputFolder = "generated-code/JavaJaxRS-CXF";
modelTemplateFiles.put("model.mustache", ".java");
apiTemplateFiles.put("api.mustache", ".java");
apiPackage = "io.swagger.api";
modelPackage = "io.swagger.model";
additionalProperties.put("title", title);
super.embeddedTemplateDir = templateDir = JAXRS_TEMPLATE_DIRECTORY_NAME + File.separator + "cxf";
for ( int i = 0; i < cliOptions.size(); i++ ) {
if ( CodegenConstants.LIBRARY.equals(cliOptions.get(i).getOpt()) ) {
cliOptions.remove(i);
break;
}
}
cliOptions.add(new CliOption(CodegenConstants.IMPL_FOLDER, CodegenConstants.IMPL_FOLDER_DESC));
cliOptions.add(new CliOption("title", "a title describing the application"));
}
@Override
public void processOpts()
{
super.processOpts();
sourceFolder = "gen" + File.separator + "java";
modelTemplateFiles.clear();
modelTemplateFiles.put("entityModel.mustache", ".java");
supportingFiles.clear();
}
@Override
public String getName()
{
return "jaxrs-cxf";
}
@Override
public void addOperationToGroup(String tag, String resourcePath, Operation operation, CodegenOperation co, Map<String, List<CodegenOperation>> operations) {
super.addOperationToGroup(tag, resourcePath, operation, co, operations);
co.subresourceOperation = !co.path.isEmpty();
}
@Override
public String getHelp()
{
return "Generates a Java JAXRS Server application based on Apache CXF framework.";
}
}

View File

@ -1,50 +1,35 @@
package io.swagger.codegen.languages; package io.swagger.codegen.languages;
import com.google.common.base.Strings; import com.google.common.base.Strings;
import io.swagger.codegen.CliOption; import io.swagger.codegen.*;
import io.swagger.codegen.CodegenConfig;
import io.swagger.codegen.CodegenConstants;
import io.swagger.codegen.CodegenModel;
import io.swagger.codegen.CodegenOperation;
import io.swagger.codegen.CodegenProperty;
import io.swagger.codegen.CodegenType;
import io.swagger.codegen.DefaultCodegen;
import io.swagger.codegen.SupportingFile;
import io.swagger.models.Model; import io.swagger.models.Model;
import io.swagger.models.Operation; import io.swagger.models.Operation;
import io.swagger.models.Path; import io.swagger.models.Path;
import io.swagger.models.Swagger; import io.swagger.models.Swagger;
import io.swagger.models.parameters.BodyParameter;
import io.swagger.models.parameters.FormParameter; import io.swagger.models.parameters.FormParameter;
import io.swagger.models.parameters.Parameter; import io.swagger.models.parameters.Parameter;
import io.swagger.models.properties.ArrayProperty; import io.swagger.models.properties.*;
import io.swagger.models.properties.BooleanProperty; import org.apache.commons.lang.BooleanUtils;
import io.swagger.models.properties.DoubleProperty;
import io.swagger.models.properties.FloatProperty;
import io.swagger.models.properties.IntegerProperty;
import io.swagger.models.properties.LongProperty;
import io.swagger.models.properties.MapProperty;
import io.swagger.models.properties.Property;
import io.swagger.models.properties.StringProperty;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.io.File;
import java.util.*;
import java.util.regex.Pattern;
public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig { public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
@SuppressWarnings("hiding")
private static final Logger LOGGER = LoggerFactory.getLogger(JavaClientCodegen.class); private static final Logger LOGGER = LoggerFactory.getLogger(JavaClientCodegen.class);
public static final String FULL_JAVA_UTIL = "fullJavaUtil"; public static final String FULL_JAVA_UTIL = "fullJavaUtil";
public static final String DEFAULT_LIBRARY = "<default>"; public static final String DEFAULT_LIBRARY = "<default>";
public static final String DATE_LIBRARY = "dateLibrary";
public static final String USE_RX_JAVA = "useRxJava";
public static final String RETROFIT_1 = "retrofit";
public static final String RETROFIT_2 = "retrofit2";
protected String dateLibrary = "default";
protected String invokerPackage = "io.swagger.client"; protected String invokerPackage = "io.swagger.client";
protected String groupId = "io.swagger"; protected String groupId = "io.swagger";
protected String artifactId = "swagger-java-client"; protected String artifactId = "swagger-java-client";
@ -52,9 +37,11 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
protected String projectFolder = "src" + File.separator + "main"; protected String projectFolder = "src" + File.separator + "main";
protected String sourceFolder = projectFolder + File.separator + "java"; protected String sourceFolder = projectFolder + File.separator + "java";
protected String localVariablePrefix = ""; protected String localVariablePrefix = "";
protected boolean fullJavaUtil = false; protected boolean fullJavaUtil;
protected String javaUtilPrefix = ""; protected String javaUtilPrefix = "";
protected Boolean serializableModel = false; protected Boolean serializableModel = false;
protected boolean serializeBigDecimalAsString = false;
protected boolean useRxJava = false;
public JavaClientCodegen() { public JavaClientCodegen() {
super(); super();
@ -65,15 +52,20 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
apiPackage = "io.swagger.client.api"; apiPackage = "io.swagger.client.api";
modelPackage = "io.swagger.client.model"; modelPackage = "io.swagger.client.model";
reservedWords = new HashSet<String>( setReservedWordsLowerCase(
Arrays.asList( Arrays.asList(
"abstract", "continue", "for", "new", "switch", "assert", // used as internal variables, can collide with parameter names
"default", "if", "package", "synchronized", "boolean", "do", "goto", "private", "path", "queryParams", "headerParams", "formParams", "postBody", "accepts", "accept", "contentTypes",
"this", "break", "double", "implements", "protected", "throw", "byte", "else", "contentType", "authNames",
"import", "public", "throws", "case", "enum", "instanceof", "return", "transient",
"catch", "extends", "int", "short", "try", "char", "final", "interface", "static", // language reserved words
"void", "class", "finally", "long", "strictfp", "volatile", "const", "float", "abstract", "continue", "for", "new", "switch", "assert",
"native", "super", "while") "default", "if", "package", "synchronized", "boolean", "do", "goto", "private",
"this", "break", "double", "implements", "protected", "throw", "byte", "else",
"import", "public", "throws", "case", "enum", "instanceof", "return", "transient",
"catch", "extends", "int", "short", "try", "char", "final", "interface", "static",
"void", "class", "finally", "long", "strictfp", "volatile", "const", "float",
"native", "super", "while")
); );
languageSpecificPrimitives = new HashSet<String>( languageSpecificPrimitives = new HashSet<String>(
@ -99,21 +91,32 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
cliOptions.add(new CliOption(CodegenConstants.ARTIFACT_VERSION, CodegenConstants.ARTIFACT_VERSION_DESC)); cliOptions.add(new CliOption(CodegenConstants.ARTIFACT_VERSION, CodegenConstants.ARTIFACT_VERSION_DESC));
cliOptions.add(new CliOption(CodegenConstants.SOURCE_FOLDER, CodegenConstants.SOURCE_FOLDER_DESC)); cliOptions.add(new CliOption(CodegenConstants.SOURCE_FOLDER, CodegenConstants.SOURCE_FOLDER_DESC));
cliOptions.add(new CliOption(CodegenConstants.LOCAL_VARIABLE_PREFIX, CodegenConstants.LOCAL_VARIABLE_PREFIX_DESC)); cliOptions.add(new CliOption(CodegenConstants.LOCAL_VARIABLE_PREFIX, CodegenConstants.LOCAL_VARIABLE_PREFIX_DESC));
cliOptions.add(new CliOption(CodegenConstants.SERIALIZABLE_MODEL, CodegenConstants.SERIALIZABLE_MODEL_DESC)); cliOptions.add(CliOption.newBoolean(CodegenConstants.SERIALIZABLE_MODEL, CodegenConstants.SERIALIZABLE_MODEL_DESC));
cliOptions.add(new CliOption(FULL_JAVA_UTIL, "whether to use fully qualified name for classes under java.util") cliOptions.add(CliOption.newBoolean(CodegenConstants.SERIALIZE_BIG_DECIMAL_AS_STRING, CodegenConstants
.defaultValue("false")); .SERIALIZE_BIG_DECIMAL_AS_STRING_DESC));
cliOptions.add(CliOption.newBoolean(FULL_JAVA_UTIL, "whether to use fully qualified name for classes under java.util"));
cliOptions.add(CliOption.newBoolean(USE_RX_JAVA, "Whether to use the RxJava adapter with the retrofit2 library."));
supportedLibraries.put(DEFAULT_LIBRARY, "HTTP client: Jersey client 1.18. JSON processing: Jackson 2.4.2"); supportedLibraries.put(DEFAULT_LIBRARY, "HTTP client: Jersey client 1.18. JSON processing: Jackson 2.4.2");
supportedLibraries.put("feign", "HTTP client: Netflix Feign 8.1.1"); supportedLibraries.put("feign", "HTTP client: Netflix Feign 8.1.1");
supportedLibraries.put("jersey2", "HTTP client: Jersey client 2.6"); supportedLibraries.put("jersey2", "HTTP client: Jersey client 2.6");
supportedLibraries.put("okhttp-gson", "HTTP client: OkHttp 2.4.0. JSON processing: Gson 2.3.1"); supportedLibraries.put("okhttp-gson", "HTTP client: OkHttp 2.4.0. JSON processing: Gson 2.3.1");
supportedLibraries.put("retrofit", "HTTP client: OkHttp 2.4.0. JSON processing: Gson 2.3.1 (Retrofit 1.9.0)"); supportedLibraries.put(RETROFIT_1, "HTTP client: OkHttp 2.4.0. JSON processing: Gson 2.3.1 (Retrofit 1.9.0)");
supportedLibraries.put("retrofit2", "HTTP client: OkHttp 2.5.0. JSON processing: Gson 2.4 (Retrofit 2.0.0-beta2)"); supportedLibraries.put(RETROFIT_2, "HTTP client: OkHttp 2.5.0. JSON processing: Gson 2.4 (Retrofit 2.0.0-beta2). Enable the RxJava adapter using '-DuseRxJava=true'.");
CliOption library = new CliOption(CodegenConstants.LIBRARY, "library template (sub-template) to use"); CliOption library = new CliOption(CodegenConstants.LIBRARY, "library template (sub-template) to use");
library.setDefault(DEFAULT_LIBRARY); library.setDefault(DEFAULT_LIBRARY);
library.setEnum(supportedLibraries); library.setEnum(supportedLibraries);
library.setDefault(DEFAULT_LIBRARY); library.setDefault(DEFAULT_LIBRARY);
cliOptions.add(library); cliOptions.add(library);
CliOption dateLibrary = new CliOption(DATE_LIBRARY, "Option. Date library to use");
Map<String, String> dateOptions = new HashMap<String, String>();
dateOptions.put("java8", "Java 8 native");
dateOptions.put("joda", "Joda");
dateLibrary.setEnum(dateOptions);
cliOptions.add(dateLibrary);
} }
@Override @Override
@ -167,7 +170,6 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
this.setSourceFolder((String) additionalProperties.get(CodegenConstants.SOURCE_FOLDER)); this.setSourceFolder((String) additionalProperties.get(CodegenConstants.SOURCE_FOLDER));
} }
if (additionalProperties.containsKey(CodegenConstants.LOCAL_VARIABLE_PREFIX)) { if (additionalProperties.containsKey(CodegenConstants.LOCAL_VARIABLE_PREFIX)) {
this.setLocalVariablePrefix((String) additionalProperties.get(CodegenConstants.LOCAL_VARIABLE_PREFIX)); this.setLocalVariablePrefix((String) additionalProperties.get(CodegenConstants.LOCAL_VARIABLE_PREFIX));
} }
@ -180,18 +182,28 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
this.setLibrary((String) additionalProperties.get(CodegenConstants.LIBRARY)); this.setLibrary((String) additionalProperties.get(CodegenConstants.LIBRARY));
} }
if(additionalProperties.containsKey(CodegenConstants.SERIALIZE_BIG_DECIMAL_AS_STRING)) {
this.setSerializeBigDecimalAsString(Boolean.valueOf(additionalProperties.get(CodegenConstants.SERIALIZE_BIG_DECIMAL_AS_STRING).toString()));
}
// need to put back serializableModel (boolean) into additionalProperties as value in additionalProperties is string // need to put back serializableModel (boolean) into additionalProperties as value in additionalProperties is string
additionalProperties.put(CodegenConstants.SERIALIZABLE_MODEL, serializableModel); additionalProperties.put(CodegenConstants.SERIALIZABLE_MODEL, serializableModel);
if (additionalProperties.containsKey(FULL_JAVA_UTIL)) { if (additionalProperties.containsKey(FULL_JAVA_UTIL)) {
this.setFullJavaUtil(Boolean.valueOf(additionalProperties.get(FULL_JAVA_UTIL).toString())); this.setFullJavaUtil(Boolean.valueOf(additionalProperties.get(FULL_JAVA_UTIL).toString()));
} }
if (additionalProperties.containsKey(USE_RX_JAVA)) {
this.setUseRxJava(Boolean.valueOf(additionalProperties.get(USE_RX_JAVA).toString()));
}
if (fullJavaUtil) { if (fullJavaUtil) {
javaUtilPrefix = "java.util."; javaUtilPrefix = "java.util.";
} }
additionalProperties.put(FULL_JAVA_UTIL, fullJavaUtil); additionalProperties.put(FULL_JAVA_UTIL, fullJavaUtil);
additionalProperties.put("javaUtilPrefix", javaUtilPrefix); additionalProperties.put("javaUtilPrefix", javaUtilPrefix);
importMapping.put("List", "java.util.List");
if (fullJavaUtil) { if (fullJavaUtil) {
typeMapping.put("array", "java.util.List"); typeMapping.put("array", "java.util.List");
typeMapping.put("map", "java.util.Map"); typeMapping.put("map", "java.util.Map");
@ -211,27 +223,39 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
this.sanitizeConfig(); this.sanitizeConfig();
// optional jackson mappings for BigDecimal support
importMapping.put("ToStringSerializer", "com.fasterxml.jackson.databind.ser.std.ToStringSerializer");
importMapping.put("JsonSerialize", "com.fasterxml.jackson.databind.annotation.JsonSerialize");
// imports for pojos
importMapping.put("ApiModelProperty", "io.swagger.annotations.ApiModelProperty");
importMapping.put("ApiModel", "io.swagger.annotations.ApiModel");
importMapping.put("JsonProperty", "com.fasterxml.jackson.annotation.JsonProperty");
importMapping.put("JsonValue", "com.fasterxml.jackson.annotation.JsonValue");
importMapping.put("Objects", "java.util.Objects");
importMapping.put("StringUtil", invokerPackage + ".StringUtil");
final String invokerFolder = (sourceFolder + '/' + invokerPackage).replace(".", "/"); final String invokerFolder = (sourceFolder + '/' + invokerPackage).replace(".", "/");
supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml")); writeOptional(outputFolder, new SupportingFile("pom.mustache", "", "pom.xml"));
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md")); writeOptional(outputFolder, new SupportingFile("README.mustache", "", "README.md"));
supportingFiles.add(new SupportingFile("build.gradle.mustache", "", "build.gradle")); writeOptional(outputFolder, new SupportingFile("build.gradle.mustache", "", "build.gradle"));
supportingFiles.add(new SupportingFile("settings.gradle.mustache", "", "settings.gradle")); writeOptional(outputFolder, new SupportingFile("settings.gradle.mustache", "", "settings.gradle"));
supportingFiles.add(new SupportingFile("gradle.properties.mustache", "", "gradle.properties")); writeOptional(outputFolder, new SupportingFile("gradle.properties.mustache", "", "gradle.properties"));
supportingFiles.add(new SupportingFile("manifest.mustache", projectFolder, "AndroidManifest.xml")); writeOptional(outputFolder, new SupportingFile("manifest.mustache", projectFolder, "AndroidManifest.xml"));
supportingFiles.add(new SupportingFile("ApiClient.mustache", invokerFolder, "ApiClient.java")); writeOptional(outputFolder, new SupportingFile("ApiClient.mustache", invokerFolder, "ApiClient.java"));
supportingFiles.add(new SupportingFile("StringUtil.mustache", invokerFolder, "StringUtil.java")); supportingFiles.add(new SupportingFile("StringUtil.mustache", invokerFolder, "StringUtil.java"));
final String authFolder = (sourceFolder + '/' + invokerPackage + ".auth").replace(".", "/"); final String authFolder = (sourceFolder + '/' + invokerPackage + ".auth").replace(".", "/");
if ("feign".equals(getLibrary())) { if ("feign".equals(getLibrary())) {
supportingFiles.add(new SupportingFile("FormAwareEncoder.mustache", invokerFolder, "FormAwareEncoder.java")); supportingFiles.add(new SupportingFile("FormAwareEncoder.mustache", invokerFolder, "FormAwareEncoder.java"));
} else {
supportingFiles.add(new SupportingFile("auth/HttpBasicAuth.mustache", authFolder, "HttpBasicAuth.java"));
supportingFiles.add(new SupportingFile("auth/ApiKeyAuth.mustache", authFolder, "ApiKeyAuth.java"));
supportingFiles.add(new SupportingFile("auth/OAuth.mustache", authFolder, "OAuth.java"));
supportingFiles.add(new SupportingFile("auth/OAuthFlow.mustache", authFolder, "OAuthFlow.java"));
} }
supportingFiles.add(new SupportingFile("auth/HttpBasicAuth.mustache", authFolder, "HttpBasicAuth.java"));
supportingFiles.add(new SupportingFile("auth/ApiKeyAuth.mustache", authFolder, "ApiKeyAuth.java"));
supportingFiles.add(new SupportingFile("auth/OAuth.mustache", authFolder, "OAuth.java"));
supportingFiles.add(new SupportingFile("auth/OAuthFlow.mustache", authFolder, "OAuthFlow.java"));
if (!("feign".equals(getLibrary()) || "retrofit".equals(getLibrary()) || "retrofit2".equals(getLibrary()))) { if (!("feign".equals(getLibrary()) || usesAnyRetrofitLibrary())) {
supportingFiles.add(new SupportingFile("apiException.mustache", invokerFolder, "ApiException.java")); supportingFiles.add(new SupportingFile("apiException.mustache", invokerFolder, "ApiException.java"));
supportingFiles.add(new SupportingFile("Configuration.mustache", invokerFolder, "Configuration.java")); supportingFiles.add(new SupportingFile("Configuration.mustache", invokerFolder, "Configuration.java"));
supportingFiles.add(new SupportingFile("Pair.mustache", invokerFolder, "Pair.java")); supportingFiles.add(new SupportingFile("Pair.mustache", invokerFolder, "Pair.java"));
@ -248,12 +272,40 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
supportingFiles.add(new SupportingFile("ProgressResponseBody.mustache", invokerFolder, "ProgressResponseBody.java")); supportingFiles.add(new SupportingFile("ProgressResponseBody.mustache", invokerFolder, "ProgressResponseBody.java"));
// "build.sbt" is for development with SBT // "build.sbt" is for development with SBT
supportingFiles.add(new SupportingFile("build.sbt.mustache", "", "build.sbt")); supportingFiles.add(new SupportingFile("build.sbt.mustache", "", "build.sbt"));
} else if ("retrofit".equals(getLibrary()) || "retrofit2".equals(getLibrary())) { } else if (usesAnyRetrofitLibrary()) {
supportingFiles.add(new SupportingFile("auth/OAuthOkHttpClient.mustache", authFolder, "OAuthOkHttpClient.java")); supportingFiles.add(new SupportingFile("auth/OAuthOkHttpClient.mustache", authFolder, "OAuthOkHttpClient.java"));
supportingFiles.add(new SupportingFile("CollectionFormats.mustache", invokerFolder, "CollectionFormats.java")); supportingFiles.add(new SupportingFile("CollectionFormats.mustache", invokerFolder, "CollectionFormats.java"));
} else if("jersey2".equals(getLibrary())) { } else if("jersey2".equals(getLibrary())) {
supportingFiles.add(new SupportingFile("JSON.mustache", invokerFolder, "JSON.java")); supportingFiles.add(new SupportingFile("JSON.mustache", invokerFolder, "JSON.java"));
} }
if(additionalProperties.containsKey(DATE_LIBRARY)) {
this.dateLibrary = additionalProperties.get(DATE_LIBRARY).toString();
}
if("joda".equals(dateLibrary)) {
typeMapping.put("date", "LocalDate");
typeMapping.put("DateTime", "DateTime");
importMapping.put("LocalDate", "org.joda.time.LocalDate");
importMapping.put("DateTime", "org.joda.time.DateTime");
}
else if ("java8".equals(dateLibrary)) {
additionalProperties.put("java8", "true");
additionalProperties.put("javaVersion", "1.8");
typeMapping.put("date", "LocalDate");
typeMapping.put("DateTime", "LocalDateTime");
importMapping.put("LocalDate", "java.time.LocalDate");
importMapping.put("LocalDateTime", "java.time.LocalDateTime");
}
}
private boolean usesAnyRetrofitLibrary() {
return getLibrary() != null && getLibrary().contains(RETROFIT_1);
}
private boolean usesRetrofit2Library() {
return getLibrary() != null && getLibrary().contains(RETROFIT_2);
} }
private void sanitizeConfig() { private void sanitizeConfig() {
@ -294,7 +346,7 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override @Override
public String toVarName(String name) { public String toVarName(String name) {
// sanitize name // sanitize name
name = sanitizeName(name); name = sanitizeName(name); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
if("_".equals(name)) { if("_".equals(name)) {
name = "_u"; name = "_u";
@ -310,7 +362,7 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
name = camelize(name, true); name = camelize(name, true);
// for reserved word or word starting with number, append _ // for reserved word or word starting with number, append _
if (reservedWords.contains(name) || name.matches("^\\d.*")) { if (isReservedWord(name) || name.matches("^\\d.*")) {
name = escapeReservedWord(name); name = escapeReservedWord(name);
} }
@ -324,17 +376,21 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
} }
@Override @Override
public String toModelName(String name) { public String toModelName(final String name) {
name = sanitizeName(name); final String sanitizedName = sanitizeName(modelNamePrefix + name + modelNameSuffix);
// model name cannot use reserved keyword, e.g. return
if (reservedWords.contains(name)) {
throw new RuntimeException(name + " (reserved word) cannot be used as a model name");
}
// camelize the model name // camelize the model name
// phone_number => PhoneNumber // phone_number => PhoneNumber
return camelize(name); final String camelizedName = camelize(sanitizedName);
// model name cannot use reserved keyword, e.g. return
if (isReservedWord(camelizedName)) {
final String modelName = "Object" + camelizedName;
LOGGER.warn(camelizedName + " (reserved word) cannot be used as model name. Renamed to " + modelName);
return modelName;
}
return camelizedName;
} }
@Override @Override
@ -430,7 +486,8 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
String type = null; String type = null;
if (typeMapping.containsKey(swaggerType)) { if (typeMapping.containsKey(swaggerType)) {
type = typeMapping.get(swaggerType); type = typeMapping.get(swaggerType);
if (languageSpecificPrimitives.contains(type) || type.indexOf(".") >= 0) { if (languageSpecificPrimitives.contains(type) || type.indexOf(".") >= 0 ||
type.equals("Map") || type.equals("List")) {
return type; return type;
} }
} else { } else {
@ -449,27 +506,74 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
throw new RuntimeException("Empty method/operation name (operationId) not allowed"); throw new RuntimeException("Empty method/operation name (operationId) not allowed");
} }
operationId = camelize(sanitizeName(operationId), true);
// method name cannot use reserved keyword, e.g. return // method name cannot use reserved keyword, e.g. return
if (reservedWords.contains(operationId)) { if (isReservedWord(operationId)) {
throw new RuntimeException(operationId + " (reserved word) cannot be used as method name"); String newOperationId = camelize("call_" + operationId, true);
LOGGER.warn(operationId + " (reserved word) cannot be used as method name. Renamed to " + newOperationId);
return newOperationId;
} }
return camelize(sanitizeName(operationId), true); return operationId;
} }
@Override @Override
public CodegenModel fromModel(String name, Model model, Map<String, Model> allDefinitions) { public CodegenModel fromModel(String name, Model model, Map<String, Model> allDefinitions) {
CodegenModel codegenModel = super.fromModel(name, model, allDefinitions); CodegenModel codegenModel = super.fromModel(name, model, allDefinitions);
if (allDefinitions != null && codegenModel != null && codegenModel.parent != null && codegenModel.hasEnums) { if (allDefinitions != null && codegenModel != null && codegenModel.parentSchema != null && codegenModel.hasEnums) {
final Model parentModel = allDefinitions.get(toModelName(codegenModel.parent)); final Model parentModel = allDefinitions.get(codegenModel.parentSchema);
final CodegenModel parentCodegenModel = super.fromModel(codegenModel.parent, parentModel); final CodegenModel parentCodegenModel = super.fromModel(codegenModel.parent, parentModel);
codegenModel = this.reconcileInlineEnums(codegenModel, parentCodegenModel); codegenModel = JavaClientCodegen.reconcileInlineEnums(codegenModel, parentCodegenModel);
} }
return codegenModel; return codegenModel;
} }
@Override
public void postProcessModelProperty(CodegenModel model, CodegenProperty property) {
if(serializeBigDecimalAsString) {
if (property.baseType.equals("BigDecimal")) {
// we serialize BigDecimal as `string` to avoid precision loss
property.vendorExtensions.put("extraAnnotation", "@JsonSerialize(using = ToStringSerializer.class)");
// this requires some more imports to be added for this model...
model.imports.add("ToStringSerializer");
model.imports.add("JsonSerialize");
}
}
if ("array".equals(property.containerType)) {
model.imports.add("ArrayList");
} else if ("map".equals(property.containerType)) {
model.imports.add("HashMap");
}
if(!BooleanUtils.toBoolean(model.isEnum)) {
// needed by all pojos, but not enums
model.imports.add("ApiModelProperty");
model.imports.add("ApiModel");
// comment out below as it's in the model template
//model.imports.add("Objects");
final String lib = getLibrary();
if(StringUtils.isEmpty(lib) || "feign".equals(lib) || "jersey2".equals(lib)) {
model.imports.add("JsonProperty");
if(BooleanUtils.toBoolean(model.hasEnums)) {
model.imports.add("JsonValue");
}
}
}
return;
}
@Override
public void postProcessParameter(CodegenParameter parameter) {
return;
}
@Override @Override
public Map<String, Object> postProcessModels(Map<String, Object> objs) { public Map<String, Object> postProcessModels(Map<String, Object> objs) {
List<Object> models = (List<Object>) objs.get("models"); List<Object> models = (List<Object>) objs.get("models");
@ -530,8 +634,20 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
return objs; return objs;
} }
@Override
public Map<String, Object> postProcessOperations(Map<String, Object> objs) { public Map<String, Object> postProcessOperations(Map<String, Object> objs) {
if("retrofit".equals(getLibrary()) || "retrofit2".equals(getLibrary())) { // Remove imports of List, ArrayList, Map and HashMap as they are
// imported in the template already.
List<Map<String, String>> imports = (List<Map<String, String>>) objs.get("imports");
Pattern pattern = Pattern.compile("java\\.util\\.(List|ArrayList|Map|HashMap)");
for (Iterator<Map<String, String>> itr = imports.iterator(); itr.hasNext();) {
String _import = itr.next().get("import");
if (pattern.matcher(_import).matches()) {
itr.remove();
}
}
if(usesAnyRetrofitLibrary()) {
Map<String, Object> operations = (Map<String, Object>) objs.get("operations"); Map<String, Object> operations = (Map<String, Object>) objs.get("operations");
if (operations != null) { if (operations != null) {
List<CodegenOperation> ops = (List<CodegenOperation>) operations.get("operation"); List<CodegenOperation> ops = (List<CodegenOperation>) operations.get("operation");
@ -547,7 +663,7 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
if (operation.returnType == null) { if (operation.returnType == null) {
operation.returnType = "Void"; operation.returnType = "Void";
} }
if ("retrofit2".equals(getLibrary()) && StringUtils.isNotEmpty(operation.path) && operation.path.startsWith("/")) if (usesRetrofit2Library() && StringUtils.isNotEmpty(operation.path) && operation.path.startsWith("/"))
operation.path = operation.path.substring(1); operation.path = operation.path.substring(1);
} }
} }
@ -555,6 +671,7 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
return objs; return objs;
} }
@Override
public void preprocessSwagger(Swagger swagger) { public void preprocessSwagger(Swagger swagger) {
if (swagger != null && swagger.getPaths() != null) { if (swagger != null && swagger.getPaths() != null) {
for (String pathname : swagger.getPaths().keySet()) { for (String pathname : swagger.getPaths().keySet()) {
@ -580,7 +697,7 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
} }
} }
private String getAccept(Operation operation) { private static String getAccept(Operation operation) {
String accepts = null; String accepts = null;
String defaultContentType = "application/json"; String defaultContentType = "application/json";
if (operation.getProduces() != null && !operation.getProduces().isEmpty()) { if (operation.getProduces() != null && !operation.getProduces().isEmpty()) {
@ -606,18 +723,19 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
return accepts; return accepts;
} }
@Override
protected boolean needToImport(String type) { protected boolean needToImport(String type) {
return super.needToImport(type) && type.indexOf(".") < 0; return super.needToImport(type) && type.indexOf(".") < 0;
} }
private String findCommonPrefixOfVars(List<String> vars) { private static String findCommonPrefixOfVars(List<String> vars) {
String prefix = StringUtils.getCommonPrefix(vars.toArray(new String[vars.size()])); String prefix = StringUtils.getCommonPrefix(vars.toArray(new String[vars.size()]));
// exclude trailing characters that should be part of a valid variable // exclude trailing characters that should be part of a valid variable
// e.g. ["status-on", "status-off"] => "status-" (not "status-o") // e.g. ["status-on", "status-off"] => "status-" (not "status-o")
return prefix.replaceAll("[a-zA-Z0-9]+\\z", ""); return prefix.replaceAll("[a-zA-Z0-9]+\\z", "");
} }
private String toEnumVarName(String value) { private static String toEnumVarName(String value) {
String var = value.replaceAll("\\W+", "_").toUpperCase(); String var = value.replaceAll("\\W+", "_").toUpperCase();
if (var.matches("\\d.*")) { if (var.matches("\\d.*")) {
return "_" + var; return "_" + var;
@ -626,7 +744,7 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
} }
} }
private CodegenModel reconcileInlineEnums(CodegenModel codegenModel, CodegenModel parentCodegenModel) { private static CodegenModel reconcileInlineEnums(CodegenModel codegenModel, CodegenModel parentCodegenModel) {
// This generator uses inline classes to define enums, which breaks when // This generator uses inline classes to define enums, which breaks when
// dealing with models that have subTypes. To clean this up, we will analyze // dealing with models that have subTypes. To clean this up, we will analyze
// the parent and child models, look for enums that match, and remove // the parent and child models, look for enums that match, and remove
@ -659,7 +777,7 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
} }
} }
} }
if(removedChildEnum) { if(removedChildEnum) {
// If we removed an entry from this model's vars, we need to ensure hasMore is updated // If we removed an entry from this model's vars, we need to ensure hasMore is updated
int count = 0, numVars = codegenProperties.size(); int count = 0, numVars = codegenProperties.size();
@ -698,6 +816,9 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
this.localVariablePrefix = localVariablePrefix; this.localVariablePrefix = localVariablePrefix;
} }
public void setSerializeBigDecimalAsString(boolean s) {
this.serializeBigDecimalAsString = s;
}
public Boolean getSerializableModel() { public Boolean getSerializableModel() {
return serializableModel; return serializableModel;
@ -707,8 +828,8 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
this.serializableModel = serializableModel; this.serializableModel = serializableModel;
} }
private String sanitizePackageName(String packageName) { private static String sanitizePackageName(String packageName) {
packageName = packageName.trim(); packageName = packageName.trim(); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
packageName = packageName.replaceAll("[^a-zA-Z0-9_\\.]", "_"); packageName = packageName.replaceAll("[^a-zA-Z0-9_\\.]", "_");
if(Strings.isNullOrEmpty(packageName)) { if(Strings.isNullOrEmpty(packageName)) {
return "invalidPackageName"; return "invalidPackageName";
@ -719,4 +840,12 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
public void setFullJavaUtil(boolean fullJavaUtil) { public void setFullJavaUtil(boolean fullJavaUtil) {
this.fullJavaUtil = fullJavaUtil; this.fullJavaUtil = fullJavaUtil;
} }
public void setUseRxJava(boolean useRxJava) {
this.useRxJava = useRxJava;
}
public void setDateLibrary(String library) {
this.dateLibrary = library;
}
} }

View File

@ -8,16 +8,21 @@ import io.swagger.models.properties.ArrayProperty;
import io.swagger.models.properties.MapProperty; import io.swagger.models.properties.MapProperty;
import io.swagger.models.properties.Property; import io.swagger.models.properties.Property;
import io.swagger.util.Yaml; import io.swagger.util.Yaml;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.*; import java.util.*;
public class JavaInflectorServerCodegen extends JavaClientCodegen implements CodegenConfig { public class JavaInflectorServerCodegen extends JavaClientCodegen implements CodegenConfig {
protected String title = "Swagger Inflector";
private static final Logger LOGGER = LoggerFactory.getLogger(JavaInflectorServerCodegen.class);
protected String title = "Swagger Inflector";
protected String implFolder = "src/main/java";
public JavaInflectorServerCodegen() { public JavaInflectorServerCodegen() {
super(); super();
sourceFolder = "src/main/java"; sourceFolder = "src/gen/java";
modelTemplateFiles.put("model.mustache", ".java"); modelTemplateFiles.put("model.mustache", ".java");
apiTemplateFiles.put("api.mustache", ".java"); apiTemplateFiles.put("api.mustache", ".java");
embeddedTemplateDir = templateDir = "JavaInflector"; embeddedTemplateDir = templateDir = "JavaInflector";
@ -35,6 +40,7 @@ public class JavaInflectorServerCodegen extends JavaClientCodegen implements Cod
languageSpecificPrimitives = new HashSet<String>( languageSpecificPrimitives = new HashSet<String>(
Arrays.asList( Arrays.asList(
"byte[]",
"String", "String",
"boolean", "boolean",
"Boolean", "Boolean",
@ -45,14 +51,17 @@ public class JavaInflectorServerCodegen extends JavaClientCodegen implements Cod
); );
} }
@Override
public CodegenType getTag() { public CodegenType getTag() {
return CodegenType.SERVER; return CodegenType.SERVER;
} }
@Override
public String getName() { public String getName() {
return "inflector"; return "inflector";
} }
@Override
public String getHelp() { public String getHelp() {
return "Generates a Java Inflector Server application."; return "Generates a Java Inflector Server application.";
} }
@ -62,14 +71,16 @@ public class JavaInflectorServerCodegen extends JavaClientCodegen implements Cod
super.processOpts(); super.processOpts();
supportingFiles.clear(); supportingFiles.clear();
supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml")); writeOptional(outputFolder, new SupportingFile("pom.mustache", "", "pom.xml"));
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md")); writeOptional(outputFolder, new SupportingFile("README.mustache", "", "README.md"));
supportingFiles.add(new SupportingFile("web.mustache", "src/main/webapp/WEB-INF", "web.xml")); writeOptional(outputFolder, new SupportingFile("web.mustache", "src/main/webapp/WEB-INF", "web.xml"));
supportingFiles.add(new SupportingFile("inflector.mustache", "", "inflector.yaml")); writeOptional(outputFolder, new SupportingFile("inflector.mustache", "", "inflector.yaml"));
supportingFiles.add(new SupportingFile("swagger.mustache", supportingFiles.add(new SupportingFile("swagger.mustache",
"src/main/swagger", "src/main/swagger",
"swagger.yaml") "swagger.yaml")
); );
supportingFiles.add(new SupportingFile("StringUtil.mustache",
(sourceFolder + '/' + invokerPackage).replace(".", "/"), "StringUtil.java"));
} }
@Override @Override
@ -116,21 +127,6 @@ public class JavaInflectorServerCodegen extends JavaClientCodegen implements Cod
} }
@Override @Override
public Map<String, Object> postProcessModels(Map<String, Object> objs) {
List<Object> models = (List<Object>) objs.get("models");
for (Object _mo : models) {
Map<String, Object> mo = (Map<String, Object>) _mo;
CodegenModel cm = (CodegenModel) mo.get("model");
for (CodegenProperty var : cm.vars) {
// handle default value for enum, e.g. available => StatusEnum.available
if (var.isEnum && var.defaultValue != null && !"null".equals(var.defaultValue)) {
var.defaultValue = var.datatypeWithEnum + "." + var.defaultValue;
}
}
}
return objs;
}
public Map<String, Object> postProcessOperations(Map<String, Object> objs) { public Map<String, Object> postProcessOperations(Map<String, Object> objs) {
Map<String, Object> operations = (Map<String, Object>) objs.get("operations"); Map<String, Object> operations = (Map<String, Object>) objs.get("operations");
if (operations != null) { if (operations != null) {
@ -165,6 +161,18 @@ public class JavaInflectorServerCodegen extends JavaClientCodegen implements Cod
return objs; return objs;
} }
public String apiFilename(String templateName, String tag) {
String result = super.apiFilename(templateName, tag);
if ( templateName.endsWith("api.mustache") ) {
int ix = result.indexOf(sourceFolder);
String beg = result.substring(0, ix);
String end = result.substring(ix + sourceFolder.length());
new java.io.File(beg + implFolder).mkdirs();
result = beg + implFolder + end;
}
return result;
}
@Override @Override
public Map<String, Object> postProcessSupportingFileData(Map<String, Object> objs) { public Map<String, Object> postProcessSupportingFileData(Map<String, Object> objs) {
@ -173,7 +181,7 @@ public class JavaInflectorServerCodegen extends JavaClientCodegen implements Cod
try { try {
objs.put("swagger-yaml", Yaml.mapper().writeValueAsString(swagger)); objs.put("swagger-yaml", Yaml.mapper().writeValueAsString(swagger));
} catch (JsonProcessingException e) { } catch (JsonProcessingException e) {
e.printStackTrace(); LOGGER.error(e.getMessage(), e);
} }
} }
return super.postProcessSupportingFileData(objs); return super.postProcessSupportingFileData(objs);
@ -184,11 +192,7 @@ public class JavaInflectorServerCodegen extends JavaClientCodegen implements Cod
if (name.length() == 0) { if (name.length() == 0) {
return "DefaultController"; return "DefaultController";
} }
name = name.replaceAll("[^a-zA-Z0-9]+", "_"); name = name.replaceAll("[^a-zA-Z0-9]+", "_"); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
return camelize(name)+ "Controller"; return camelize(name)+ "Controller";
} }
public boolean shouldOverwrite(String filename) {
return super.shouldOverwrite(filename);
}
} }

View File

@ -0,0 +1,132 @@
package io.swagger.codegen.languages;
import io.swagger.codegen.*;
import io.swagger.models.Operation;
import java.io.File;
import java.util.*;
public class JavaJerseyServerCodegen extends AbstractJavaJAXRSServerCodegen
{
public JavaJerseyServerCodegen()
{
super();
sourceFolder = "src/gen/java";
invokerPackage = "io.swagger.api";
artifactId = "swagger-jaxrs-server";
outputFolder = "generated-code/JavaJaxRS-Jersey";
modelTemplateFiles.put("model.mustache", ".java");
apiTemplateFiles.put("api.mustache", ".java");
apiTemplateFiles.put("apiService.mustache", ".java");
apiTemplateFiles.put("apiServiceImpl.mustache", ".java");
apiTemplateFiles.put("apiServiceFactory.mustache", ".java");
apiPackage = "io.swagger.api";
modelPackage = "io.swagger.model";
additionalProperties.put("title", title);
embeddedTemplateDir = templateDir = JAXRS_TEMPLATE_DIRECTORY_NAME + File.separator + "jersey1_18";
for ( int i = 0; i < cliOptions.size(); i++ ) {
if ( CodegenConstants.LIBRARY.equals(cliOptions.get(i).getOpt()) ) {
cliOptions.remove(i);
break;
}
}
CliOption library = new CliOption(CodegenConstants.LIBRARY, "library template (sub-template) to use");
library.setDefault(DEFAULT_LIBRARY);
Map<String, String> supportedLibraries = new LinkedHashMap<String, String>();
supportedLibraries.put(DEFAULT_LIBRARY, "Jersey core 1.18.1");
library.setEnum(supportedLibraries);
cliOptions.add(library);
cliOptions.add(new CliOption(CodegenConstants.IMPL_FOLDER, CodegenConstants.IMPL_FOLDER_DESC));
cliOptions.add(new CliOption("title", "a title describing the application"));
}
@Override
public String getName()
{
return "jaxrs"; // TODO should be renamed as "jaxrs-jersey"
}
@Override
public String getHelp()
{
return "Generates a Java JAXRS Server application based on Jersey framework.";
}
@Override
public void postProcessModelProperty(CodegenModel model, CodegenProperty property) {
super.postProcessModelProperty(model, property);
if("null".equals(property.example)) {
property.example = null;
}
}
@Override
public void processOpts() {
super.processOpts();
if ( additionalProperties.containsKey(CodegenConstants.IMPL_FOLDER) ) {
implFolder = (String) additionalProperties.get(CodegenConstants.IMPL_FOLDER);
}
supportingFiles.clear();
writeOptional(outputFolder, new SupportingFile("pom.mustache", "", "pom.xml"));
writeOptional(outputFolder, new SupportingFile("README.mustache", "", "README.md"));
supportingFiles.add(new SupportingFile("ApiException.mustache", (sourceFolder + '/' + apiPackage).replace(".", "/"), "ApiException.java"));
supportingFiles.add(new SupportingFile("ApiOriginFilter.mustache", (sourceFolder + '/' + apiPackage).replace(".", "/"), "ApiOriginFilter.java"));
supportingFiles.add(new SupportingFile("ApiResponseMessage.mustache", (sourceFolder + '/' + apiPackage).replace(".", "/"), "ApiResponseMessage.java"));
supportingFiles.add(new SupportingFile("NotFoundException.mustache", (sourceFolder + '/' + apiPackage).replace(".", "/"), "NotFoundException.java"));
writeOptional(outputFolder, new SupportingFile("web.mustache", ("src/main/webapp/WEB-INF"), "web.xml"));
supportingFiles.add(new SupportingFile("StringUtil.mustache", (sourceFolder + '/' + apiPackage).replace(".", "/"), "StringUtil.java"));
if ( additionalProperties.containsKey("dateLibrary") ) {
setDateLibrary(additionalProperties.get("dateLibrary").toString());
additionalProperties.put(dateLibrary, "true");
}
if ( "joda".equals(dateLibrary) ) {
supportingFiles.add(new SupportingFile("JodaDateTimeProvider.mustache", (sourceFolder + '/' + apiPackage).replace(".", "/"), "JodaDateTimeProvider.java"));
supportingFiles.add(new SupportingFile("JodaLocalDateProvider.mustache", (sourceFolder + '/' + apiPackage).replace(".", "/"), "JodaLocalDateProvider.java"));
} else if ( "java8".equals(dateLibrary) ) {
supportingFiles.add(new SupportingFile("LocalDateTimeProvider.mustache", (sourceFolder + '/' + apiPackage).replace(".", "/"), "LocalDateTimeProvider.java"));
supportingFiles.add(new SupportingFile("LocalDateProvider.mustache", (sourceFolder + '/' + apiPackage).replace(".", "/"), "LocalDateProvider.java"));
}
}
@Override
public void addOperationToGroup(String tag, String resourcePath, Operation operation, CodegenOperation co, Map<String, List<CodegenOperation>> operations) {
String basePath = resourcePath;
if (basePath.startsWith("/")) {
basePath = basePath.substring(1);
}
int pos = basePath.indexOf("/");
if (pos > 0) {
basePath = basePath.substring(0, pos);
}
if (basePath == "") {
basePath = "default";
} else {
if (co.path.startsWith("/" + basePath)) {
co.path = co.path.substring(("/" + basePath).length());
}
co.subresourceOperation = !co.path.isEmpty();
}
List<CodegenOperation> opList = operations.get(basePath);
if (opList == null) {
opList = new ArrayList<CodegenOperation>();
operations.put(basePath, opList);
}
opList.add(co);
co.baseName = basePath;
}
}

View File

@ -4,56 +4,95 @@ import io.swagger.codegen.*;
import io.swagger.models.Operation; import io.swagger.models.Operation;
import io.swagger.models.Path; import io.swagger.models.Path;
import io.swagger.models.Swagger; import io.swagger.models.Swagger;
import org.apache.commons.lang.StringUtils;
import java.io.File; import java.io.File;
import java.util.*; import java.util.*;
public class JaxRSServerCodegen extends JavaClientCodegen implements CodegenConfig { public class JavaResteasyServerCodegen extends JavaClientCodegen implements CodegenConfig {
protected String title = "Swagger Server";
public JaxRSServerCodegen() { protected String dateLibrary = "default";
super.processOpts(); protected String title = "Swagger Server";
protected String implFolder = "src/main/java";
public static final String DATE_LIBRARY = "dateLibrary";
public JavaResteasyServerCodegen() {
super();
sourceFolder = "src/gen/java"; sourceFolder = "src/gen/java";
invokerPackage = "io.swagger.api"; invokerPackage = "io.swagger.api";
artifactId = "swagger-jaxrs-server"; artifactId = "swagger-jaxrs-resteasy-server";
outputFolder = System.getProperty("swagger.codegen.jaxrs.genfolder", "generated-code/javaJaxRS"); outputFolder = "generated-code/javaJaxRS";
modelTemplateFiles.put("model.mustache", ".java"); modelTemplateFiles.put("model.mustache", ".java");
apiTemplateFiles.put("api.mustache", ".java"); apiTemplateFiles.put("api.mustache", ".java");
apiTemplateFiles.put("apiService.mustache", ".java"); apiTemplateFiles.put("apiService.mustache", ".java");
apiTemplateFiles.put("apiServiceImpl.mustache", ".java"); apiTemplateFiles.put("apiServiceImpl.mustache", ".java");
apiTemplateFiles.put("apiServiceFactory.mustache", ".java"); apiTemplateFiles.put("apiServiceFactory.mustache", ".java");
embeddedTemplateDir = templateDir = "JavaJaxRS"; apiPackage = "io.swagger.api";
apiPackage = System.getProperty("swagger.codegen.jaxrs.apipackage", "io.swagger.api"); modelPackage = "io.swagger.model";
modelPackage = System.getProperty("swagger.codegen.jaxrs.modelpackage", "io.swagger.model");
additionalProperties.put(CodegenConstants.INVOKER_PACKAGE, invokerPackage);
additionalProperties.put(CodegenConstants.GROUP_ID, groupId);
additionalProperties.put(CodegenConstants.ARTIFACT_ID, artifactId);
additionalProperties.put(CodegenConstants.ARTIFACT_VERSION, artifactVersion);
additionalProperties.put("title", title); additionalProperties.put("title", title);
embeddedTemplateDir = templateDir = "JavaJaxRS" + File.separator + "resteasy";
for (int i = 0; i < cliOptions.size(); i++) {
if (CodegenConstants.LIBRARY.equals(cliOptions.get(i).getOpt())) {
cliOptions.remove(i);
break;
}
}
CliOption dateLibrary = new CliOption(DATE_LIBRARY, "Option. Date library to use");
Map<String, String> dateOptions = new HashMap<String, String>();
dateOptions.put("java8", "Java 8 native");
dateOptions.put("joda", "Joda");
dateLibrary.setEnum(dateOptions);
cliOptions.add(dateLibrary);
CliOption library = new CliOption(CodegenConstants.LIBRARY, "library template (sub-template) to use");
library.setDefault(DEFAULT_LIBRARY);
Map<String, String> supportedLibraries = new LinkedHashMap<String, String>();
supportedLibraries.put(DEFAULT_LIBRARY, "Resteasy core 3.0.11");
library.setEnum(supportedLibraries);
cliOptions.add(library);
cliOptions.add(new CliOption(CodegenConstants.IMPL_FOLDER, CodegenConstants.IMPL_FOLDER_DESC));
} }
@Override
public CodegenType getTag() { public CodegenType getTag() {
return CodegenType.SERVER; return CodegenType.SERVER;
} }
@Override
public String getName() { public String getName() {
return "jaxrs"; return "jaxrs-resteasy";
} }
@Override
public String getHelp() { public String getHelp() {
return "Generates a Java JAXRS Server application."; return "Generates a Java JAXRS-Resteasy Server application.";
} }
@Override @Override
public void processOpts() { public void processOpts() {
super.processOpts(); super.processOpts();
if (additionalProperties.containsKey(CodegenConstants.IMPL_FOLDER)) {
implFolder = (String) additionalProperties.get(CodegenConstants.IMPL_FOLDER);
}
supportingFiles.clear(); supportingFiles.clear();
supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml")); writeOptional(outputFolder, new SupportingFile("pom.mustache", "", "pom.xml"));
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md")); writeOptional(outputFolder, new SupportingFile("gradle.mustache", "", "build.gradle"));
writeOptional(outputFolder, new SupportingFile("settingsGradle.mustache", "", "settings.gradle"));
writeOptional(outputFolder, new SupportingFile("README.mustache", "", "README.md"));
supportingFiles.add(new SupportingFile("ApiException.mustache", supportingFiles.add(new SupportingFile("ApiException.mustache",
(sourceFolder + '/' + apiPackage).replace(".", "/"), "ApiException.java")); (sourceFolder + '/' + apiPackage).replace(".", "/"), "ApiException.java"));
supportingFiles.add(new SupportingFile("ApiOriginFilter.mustache", supportingFiles.add(new SupportingFile("ApiOriginFilter.mustache",
@ -62,9 +101,47 @@ public class JaxRSServerCodegen extends JavaClientCodegen implements CodegenConf
(sourceFolder + '/' + apiPackage).replace(".", "/"), "ApiResponseMessage.java")); (sourceFolder + '/' + apiPackage).replace(".", "/"), "ApiResponseMessage.java"));
supportingFiles.add(new SupportingFile("NotFoundException.mustache", supportingFiles.add(new SupportingFile("NotFoundException.mustache",
(sourceFolder + '/' + apiPackage).replace(".", "/"), "NotFoundException.java")); (sourceFolder + '/' + apiPackage).replace(".", "/"), "NotFoundException.java"));
supportingFiles.add(new SupportingFile("web.mustache", writeOptional(outputFolder, new SupportingFile("web.mustache",
("src/main/webapp/WEB-INF"), "web.xml")); ("src/main/webapp/WEB-INF"), "web.xml"));
writeOptional(outputFolder, new SupportingFile("jboss-web.mustache",
("src/main/webapp/WEB-INF"), "jboss-web.xml"));
writeOptional(outputFolder, new SupportingFile("RestApplication.mustache",
(sourceFolder + '/' + invokerPackage).replace(".", "/"), "RestApplication.java"));
supportingFiles.add(new SupportingFile("StringUtil.mustache",
(sourceFolder + '/' + invokerPackage).replace(".", "/"), "StringUtil.java"));
if (additionalProperties.containsKey("dateLibrary")) {
setDateLibrary(additionalProperties.get("dateLibrary").toString());
additionalProperties.put(dateLibrary, "true");
}
if ("joda".equals(dateLibrary)) {
typeMapping.put("date", "LocalDate");
typeMapping.put("DateTime", "DateTime");
importMapping.put("LocalDate", "org.joda.time.LocalDate");
importMapping.put("DateTime", "org.joda.time.DateTime");
supportingFiles.add(new SupportingFile("JacksonConfig.mustache",
(sourceFolder + '/' + invokerPackage).replace(".", "/"), "JacksonConfig.java"));
supportingFiles.add(new SupportingFile("JodaDateTimeProvider.mustache",
(sourceFolder + '/' + apiPackage).replace(".", "/"), "JodaDateTimeProvider.java"));
supportingFiles.add(new SupportingFile("JodaLocalDateProvider.mustache",
(sourceFolder + '/' + apiPackage).replace(".", "/"), "JodaLocalDateProvider.java"));
} else if ("java8".equals(dateLibrary)) {
additionalProperties.put("java8", "true");
additionalProperties.put("javaVersion", "1.8");
typeMapping.put("date", "LocalDate");
typeMapping.put("DateTime", "LocalDateTime");
importMapping.put("LocalDate", "java.time.LocalDate");
importMapping.put("LocalDateTime", "java.time.LocalDateTime");
supportingFiles.add(new SupportingFile("LocalDateTimeProvider.mustache",
(sourceFolder + '/' + apiPackage).replace(".", "/"), "LocalDateTimeProvider.java"));
supportingFiles.add(new SupportingFile("LocalDateProvider.mustache",
(sourceFolder + '/' + apiPackage).replace(".", "/"), "LocalDateProvider.java"));
}
} }
@Override @Override
@ -95,28 +172,39 @@ public class JaxRSServerCodegen extends JavaClientCodegen implements CodegenConf
co.baseName = basePath; co.baseName = basePath;
} }
@Override @Override
public void preprocessSwagger(Swagger swagger) { public void preprocessSwagger(Swagger swagger) {
if("/".equals(swagger.getBasePath())) { if ("/".equals(swagger.getBasePath())) {
swagger.setBasePath(""); swagger.setBasePath("");
} }
if(swagger != null && swagger.getPaths() != null) {
for(String pathname : swagger.getPaths().keySet()) { String host = swagger.getHost();
String port = "8080";
if (host != null) {
String[] parts = host.split(":");
if (parts.length > 1) {
port = parts[1];
}
}
this.additionalProperties.put("serverPort", port);
if (swagger != null && swagger.getPaths() != null) {
for (String pathname : swagger.getPaths().keySet()) {
Path path = swagger.getPath(pathname); Path path = swagger.getPath(pathname);
if(path.getOperations() != null) { if (path.getOperations() != null) {
for(Operation operation : path.getOperations()) { for (Operation operation : path.getOperations()) {
if(operation.getTags() != null) { if (operation.getTags() != null) {
List<Map<String, String>> tags = new ArrayList<Map<String, String>>(); List<Map<String, String>> tags = new ArrayList<Map<String, String>>();
for(String tag : operation.getTags()) { for (String tag : operation.getTags()) {
Map<String, String> value = new HashMap<String, String>(); Map<String, String> value = new HashMap<String, String>();
value.put("tag", tag); value.put("tag", tag);
value.put("hasMore", "true"); value.put("hasMore", "true");
tags.add(value); tags.add(value);
} }
if(tags.size() > 0) { if (tags.size() > 0) {
tags.get(tags.size() - 1).remove("hasMore"); tags.get(tags.size() - 1).remove("hasMore");
} }
if(operation.getTags().size() > 0) { if (operation.getTags().size() > 0) {
String tag = operation.getTags().get(0); String tag = operation.getTags().get(0);
operation.setTags(Arrays.asList(tag)); operation.setTags(Arrays.asList(tag));
} }
@ -128,27 +216,22 @@ public class JaxRSServerCodegen extends JavaClientCodegen implements CodegenConf
} }
} }
@Override
public Map<String, Object> postProcessModels(Map<String, Object> objs) {
List<Object> models = (List<Object>) objs.get("models");
for (Object _mo : models) {
Map<String, Object> mo = (Map<String, Object>) _mo;
CodegenModel cm = (CodegenModel) mo.get("model");
for (CodegenProperty var : cm.vars) {
// handle default value for enum, e.g. available => StatusEnum.available
if (var.isEnum && var.defaultValue != null && !"null".equals(var.defaultValue)) {
var.defaultValue = var.datatypeWithEnum + "." + var.defaultValue;
}
}
}
return objs;
}
@Override
public Map<String, Object> postProcessOperations(Map<String, Object> objs) { public Map<String, Object> postProcessOperations(Map<String, Object> objs) {
Map<String, Object> operations = (Map<String, Object>) objs.get("operations"); Map<String, Object> operations = (Map<String, Object>) objs.get("operations");
if (operations != null) { if (operations != null) {
List<CodegenOperation> ops = (List<CodegenOperation>) operations.get("operation"); List<CodegenOperation> ops = (List<CodegenOperation>) operations.get("operation");
for (CodegenOperation operation : ops) { for (CodegenOperation operation : ops) {
if (operation.hasConsumes == Boolean.TRUE) {
Map<String, String> firstType = operation.consumes.get(0);
if (firstType != null) {
if ("multipart/form-data".equals(firstType.get("mediaType"))) {
operation.isMultipart = Boolean.TRUE;
}
}
}
List<CodegenResponse> responses = operation.responses; List<CodegenResponse> responses = operation.responses;
if (responses != null) { if (responses != null) {
for (CodegenResponse resp : responses) { for (CodegenResponse resp : responses) {
@ -195,6 +278,7 @@ public class JaxRSServerCodegen extends JavaClientCodegen implements CodegenConf
return camelize(name) + "Api"; return camelize(name) + "Api";
} }
@Override @Override
public String apiFilename(String templateName, String tag) { public String apiFilename(String templateName, String tag) {
@ -204,19 +288,12 @@ public class JaxRSServerCodegen extends JavaClientCodegen implements CodegenConf
int ix = result.lastIndexOf('/'); int ix = result.lastIndexOf('/');
result = result.substring(0, ix) + "/impl" + result.substring(ix, result.length() - 5) + "ServiceImpl.java"; result = result.substring(0, ix) + "/impl" + result.substring(ix, result.length() - 5) + "ServiceImpl.java";
String output = System.getProperty("swagger.codegen.jaxrs.impl.source"); result = result.replace(apiFileFolder(), implFileFolder(implFolder));
if(output == null) {
output = "src" + File.separator + "main" + File.separator + "java";
}
result = result.replace(apiFileFolder(), implFileFolder(output));
} else if (templateName.endsWith("Factory.mustache")) { } else if (templateName.endsWith("Factory.mustache")) {
int ix = result.lastIndexOf('/'); int ix = result.lastIndexOf('/');
result = result.substring(0, ix) + "/factories" + result.substring(ix, result.length() - 5) + "ServiceFactory.java"; result = result.substring(0, ix) + "/factories" + result.substring(ix, result.length() - 5) + "ServiceFactory.java";
String output = System.getProperty("swagger.codegen.jaxrs.impl.source"); result = result.replace(apiFileFolder(), implFileFolder(implFolder));
if (output != null) {
result = result.replace(apiFileFolder(), implFileFolder(output));
}
} else if (templateName.endsWith("Service.mustache")) { } else if (templateName.endsWith("Service.mustache")) {
int ix = result.lastIndexOf('.'); int ix = result.lastIndexOf('.');
result = result.substring(0, ix) + "Service.java"; result = result.substring(0, ix) + "Service.java";
@ -225,11 +302,44 @@ public class JaxRSServerCodegen extends JavaClientCodegen implements CodegenConf
return result; return result;
} }
private String implFileFolder(String output) { private String implFileFolder(String output) {
return outputFolder + "/" + output + "/" + apiPackage().replace('.', '/'); return outputFolder + "/" + output + "/" + apiPackage().replace('.', '/');
} }
@Override
public boolean shouldOverwrite(String filename) { public boolean shouldOverwrite(String filename) {
return super.shouldOverwrite(filename) && !filename.endsWith("ServiceImpl.java") && !filename.endsWith("ServiceFactory.java"); return super.shouldOverwrite(filename) && !filename.endsWith("ServiceImpl.java") && !filename.endsWith("ServiceFactory.java");
} }
}
public void setDateLibrary(String library) {
this.dateLibrary = library;
}
@Override
public void postProcessModelProperty(CodegenModel model, CodegenProperty property) {
if(serializeBigDecimalAsString) {
if (property.baseType.equals("BigDecimal")) {
// we serialize BigDecimal as `string` to avoid precision loss
property.vendorExtensions.put("extraAnnotation", "@JsonSerialize(using = ToStringSerializer.class)");
// this requires some more imports to be added for this model...
model.imports.add("ToStringSerializer");
model.imports.add("JsonSerialize");
}
}
if(model.isEnum == null || model.isEnum) {
final String lib = getLibrary();
if(StringUtils.isEmpty(lib)) {
model.imports.add("JsonProperty");
if(model.hasEnums != null || model.hasEnums == true) {
model.imports.add("JsonValue");
}
}
}
return;
}
}

View File

@ -7,16 +7,32 @@ import io.swagger.codegen.CodegenConfig;
import io.swagger.codegen.CodegenConstants; import io.swagger.codegen.CodegenConstants;
import io.swagger.codegen.CodegenModel; import io.swagger.codegen.CodegenModel;
import io.swagger.codegen.CodegenOperation; import io.swagger.codegen.CodegenOperation;
import io.swagger.codegen.CodegenParameter;
import io.swagger.codegen.CodegenProperty; import io.swagger.codegen.CodegenProperty;
import io.swagger.codegen.CodegenType; import io.swagger.codegen.CodegenType;
import io.swagger.codegen.DefaultCodegen;
import io.swagger.codegen.SupportingFile; import io.swagger.codegen.SupportingFile;
import io.swagger.models.*; import io.swagger.codegen.DefaultCodegen;
import io.swagger.models.Info;
import io.swagger.models.License;
import io.swagger.models.Model;
import io.swagger.models.Operation;
import io.swagger.models.Swagger;
import io.swagger.models.properties.ArrayProperty; import io.swagger.models.properties.ArrayProperty;
import io.swagger.models.properties.BooleanProperty;
import io.swagger.models.properties.DateProperty;
import io.swagger.models.properties.DateTimeProperty;
import io.swagger.models.properties.DoubleProperty;
import io.swagger.models.properties.FloatProperty;
import io.swagger.models.properties.IntegerProperty;
import io.swagger.models.properties.LongProperty; import io.swagger.models.properties.LongProperty;
import io.swagger.models.properties.MapProperty; import io.swagger.models.properties.MapProperty;
import io.swagger.models.properties.Property; import io.swagger.models.properties.Property;
import io.swagger.models.properties.RefProperty; import io.swagger.models.properties.RefProperty;
import io.swagger.models.properties.StringProperty;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File; import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
@ -27,11 +43,8 @@ import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class JavascriptClientCodegen extends DefaultCodegen implements CodegenConfig { public class JavascriptClientCodegen extends DefaultCodegen implements CodegenConfig {
@SuppressWarnings("hiding")
private static final Logger LOGGER = LoggerFactory.getLogger(JavascriptClientCodegen.class); private static final Logger LOGGER = LoggerFactory.getLogger(JavascriptClientCodegen.class);
private static final String PROJECT_NAME = "projectName"; private static final String PROJECT_NAME = "projectName";
@ -39,14 +52,18 @@ public class JavascriptClientCodegen extends DefaultCodegen implements CodegenCo
private static final String PROJECT_DESCRIPTION = "projectDescription"; private static final String PROJECT_DESCRIPTION = "projectDescription";
private static final String PROJECT_VERSION = "projectVersion"; private static final String PROJECT_VERSION = "projectVersion";
private static final String PROJECT_LICENSE_NAME = "projectLicenseName"; private static final String PROJECT_LICENSE_NAME = "projectLicenseName";
private static final String USE_PROMISES = "usePromises";
private static final String OMIT_MODEL_METHODS = "omitModelMethods";
protected String projectName = null; protected String projectName;
protected String moduleName = null; protected String moduleName;
protected String projectDescription = null; protected String projectDescription;
protected String projectVersion = null; protected String projectVersion;
protected String sourceFolder = "src"; protected String sourceFolder = "src";
protected String localVariablePrefix = ""; protected String localVariablePrefix = "";
protected boolean usePromises = false;
protected boolean omitModelMethods = false;
public JavascriptClientCodegen() { public JavascriptClientCodegen() {
super(); super();
@ -58,7 +75,7 @@ public class JavascriptClientCodegen extends DefaultCodegen implements CodegenCo
modelPackage = "model"; modelPackage = "model";
// reference: http://www.w3schools.com/js/js_reserved.asp // reference: http://www.w3schools.com/js/js_reserved.asp
reservedWords = new HashSet<String>( setReservedWordsLowerCase(
Arrays.asList( Arrays.asList(
"abstract", "arguments", "boolean", "break", "byte", "abstract", "arguments", "boolean", "break", "byte",
"case", "catch", "char", "class", "const", "case", "catch", "char", "class", "const",
@ -96,6 +113,12 @@ public class JavascriptClientCodegen extends DefaultCodegen implements CodegenCo
"version of the project (Default: using info.version or \"1.0.0\")")); "version of the project (Default: using info.version or \"1.0.0\")"));
cliOptions.add(new CliOption(PROJECT_LICENSE_NAME, cliOptions.add(new CliOption(PROJECT_LICENSE_NAME,
"name of the license the project uses (Default: using info.license.name)")); "name of the license the project uses (Default: using info.license.name)"));
cliOptions.add(new CliOption(USE_PROMISES,
"use Promises as return values from the client API, instead of superagent callbacks")
.defaultValue(Boolean.FALSE.toString()));
cliOptions.add(new CliOption(OMIT_MODEL_METHODS,
"omits generation of getters and setters for model classes")
.defaultValue(Boolean.FALSE.toString()));
} }
@Override @Override
@ -133,6 +156,9 @@ public class JavascriptClientCodegen extends DefaultCodegen implements CodegenCo
typeMapping.put("double", "Number"); typeMapping.put("double", "Number");
typeMapping.put("number", "Number"); typeMapping.put("number", "Number");
typeMapping.put("DateTime", "Date"); typeMapping.put("DateTime", "Date");
typeMapping.put("Date", "Date");
// binary not supported in JavaScript client right now, using String as a workaround
typeMapping.put("binary", "String");
importMapping.clear(); importMapping.clear();
} }
@ -159,14 +185,20 @@ public class JavascriptClientCodegen extends DefaultCodegen implements CodegenCo
if (additionalProperties.containsKey(CodegenConstants.SOURCE_FOLDER)) { if (additionalProperties.containsKey(CodegenConstants.SOURCE_FOLDER)) {
sourceFolder = (String) additionalProperties.get(CodegenConstants.SOURCE_FOLDER); sourceFolder = (String) additionalProperties.get(CodegenConstants.SOURCE_FOLDER);
} }
if (additionalProperties.containsKey(USE_PROMISES)) {
usePromises = Boolean.parseBoolean((String)additionalProperties.get(USE_PROMISES));
}
if (additionalProperties.containsKey(OMIT_MODEL_METHODS)) {
omitModelMethods = Boolean.parseBoolean((String)additionalProperties.get(OMIT_MODEL_METHODS));
}
if (swagger.getInfo() != null) { if (swagger.getInfo() != null) {
Info info = swagger.getInfo(); Info info = swagger.getInfo();
if (projectName == null && info.getTitle() != null) { if (StringUtils.isBlank(projectName) && info.getTitle() != null) {
// when projectName is not specified, generate it from info.title // when projectName is not specified, generate it from info.title
projectName = dashize(info.getTitle()); projectName = dashize(info.getTitle());
} }
if (projectVersion == null) { if (StringUtils.isBlank(projectVersion)) {
// when projectVersion is not specified, use info.version // when projectVersion is not specified, use info.version
projectVersion = info.getVersion(); projectVersion = info.getVersion();
} }
@ -183,13 +215,13 @@ public class JavascriptClientCodegen extends DefaultCodegen implements CodegenCo
} }
// default values // default values
if (projectName == null) { if (StringUtils.isBlank(projectName)) {
projectName = "swagger-js-client"; projectName = "swagger-js-client";
} }
if (moduleName == null) { if (StringUtils.isBlank(moduleName)) {
moduleName = camelize(underscore(projectName)); moduleName = camelize(underscore(projectName));
} }
if (projectVersion == null) { if (StringUtils.isBlank(projectVersion)) {
projectVersion = "1.0.0"; projectVersion = "1.0.0";
} }
if (projectDescription == null) { if (projectDescription == null) {
@ -202,9 +234,12 @@ public class JavascriptClientCodegen extends DefaultCodegen implements CodegenCo
additionalProperties.put(PROJECT_VERSION, projectVersion); additionalProperties.put(PROJECT_VERSION, projectVersion);
additionalProperties.put(CodegenConstants.LOCAL_VARIABLE_PREFIX, localVariablePrefix); additionalProperties.put(CodegenConstants.LOCAL_VARIABLE_PREFIX, localVariablePrefix);
additionalProperties.put(CodegenConstants.SOURCE_FOLDER, sourceFolder); additionalProperties.put(CodegenConstants.SOURCE_FOLDER, sourceFolder);
additionalProperties.put(USE_PROMISES, usePromises);
additionalProperties.put(OMIT_MODEL_METHODS, omitModelMethods);
supportingFiles.add(new SupportingFile("package.mustache", "", "package.json")); supportingFiles.add(new SupportingFile("package.mustache", "", "package.json"));
supportingFiles.add(new SupportingFile("index.mustache", sourceFolder, "index.js")); supportingFiles.add(new SupportingFile("index.mustache", sourceFolder, "index.js"));
supportingFiles.add(new SupportingFile("ApiClient.mustache", sourceFolder, "ApiClient.js"));
} }
@Override @Override
@ -225,7 +260,7 @@ public class JavascriptClientCodegen extends DefaultCodegen implements CodegenCo
@Override @Override
public String toVarName(String name) { public String toVarName(String name) {
// sanitize name // sanitize name
name = sanitizeName(name); name = sanitizeName(name); // FIXME parameter should not be assigned. Also declare it as "final"
if("_".equals(name)) { if("_".equals(name)) {
name = "_u"; name = "_u";
@ -241,7 +276,7 @@ public class JavascriptClientCodegen extends DefaultCodegen implements CodegenCo
name = camelize(name, true); name = camelize(name, true);
// for reserved word or word starting with number, append _ // for reserved word or word starting with number, append _
if (reservedWords.contains(name) || name.matches("^\\d.*")) { if (isReservedWord(name) || name.matches("^\\d.*")) {
name = escapeReservedWord(name); name = escapeReservedWord(name);
} }
@ -256,16 +291,20 @@ public class JavascriptClientCodegen extends DefaultCodegen implements CodegenCo
@Override @Override
public String toModelName(String name) { public String toModelName(String name) {
name = sanitizeName(name); name = sanitizeName(name); // FIXME parameter should not be assigned. Also declare it as "final"
// model name cannot use reserved keyword, e.g. return
if (reservedWords.contains(name)) {
throw new RuntimeException(name + " (reserved word) cannot be used as a model name");
}
// camelize the model name // camelize the model name
// phone_number => PhoneNumber // phone_number => PhoneNumber
return camelize(name); name = camelize(name);
// model name cannot use reserved keyword, e.g. return
if (isReservedWord(name)) {
String modelName = "Object" + name;
LOGGER.warn(name + " (reserved word) cannot be used as model name. Renamed to " + modelName);
return modelName;
}
return name;
} }
@Override @Override
@ -276,7 +315,7 @@ public class JavascriptClientCodegen extends DefaultCodegen implements CodegenCo
@Override @Override
public String toModelImport(String name) { public String toModelImport(String name) {
return name; return toModelName(name);
} }
@Override @Override
@ -289,58 +328,75 @@ public class JavascriptClientCodegen extends DefaultCodegen implements CodegenCo
if (p instanceof ArrayProperty) { if (p instanceof ArrayProperty) {
ArrayProperty ap = (ArrayProperty) p; ArrayProperty ap = (ArrayProperty) p;
Property inner = ap.getItems(); Property inner = ap.getItems();
return getSwaggerType(p); // TODO: + "/* <" + getTypeDeclaration(inner) + "> */"; return "[" + getTypeDeclaration(inner) + "]";
} else if (p instanceof MapProperty) { } else if (p instanceof MapProperty) {
MapProperty mp = (MapProperty) p; MapProperty mp = (MapProperty) p;
Property inner = mp.getAdditionalProperties(); Property inner = mp.getAdditionalProperties();
return "{String: " + getTypeDeclaration(inner) + "}";
return getSwaggerType(p) + "<String, " + getTypeDeclaration(inner) + ">";
} }
return super.getTypeDeclaration(p); return super.getTypeDeclaration(p);
} }
@Override @Override
public String toDefaultValue(Property p) { public String toDefaultValue(Property p) {
if (p instanceof ArrayProperty) { if (p instanceof StringProperty) {
return "[]"; StringProperty dp = (StringProperty) p;
} else if (p instanceof MapProperty) { if (dp.getDefault() != null) {
return "{}"; return "'" + dp.getDefault() + "'";
}
} else if (p instanceof BooleanProperty) {
BooleanProperty dp = (BooleanProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
} else if (p instanceof DateProperty) {
// TODO
} else if (p instanceof DateTimeProperty) {
// TODO
} else if (p instanceof DoubleProperty) {
DoubleProperty dp = (DoubleProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
} else if (p instanceof FloatProperty) {
FloatProperty dp = (FloatProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
} else if (p instanceof IntegerProperty) {
IntegerProperty dp = (IntegerProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
} else if (p instanceof LongProperty) { } else if (p instanceof LongProperty) {
LongProperty dp = (LongProperty) p; LongProperty dp = (LongProperty) p;
if (dp.getDefault() != null) { if (dp.getDefault() != null) {
return dp.getDefault().toString()+"l"; return dp.getDefault().toString();
} }
return "null";
// added for Javascript
} else if (p instanceof RefProperty) {
RefProperty rp = (RefProperty)p;
return "new " +rp.getSimpleRef() + "()";
} }
return super.toDefaultValue(p); return null;
} }
@Override @Override
public String toDefaultValueWithParam(String name, Property p) { public String toDefaultValueWithParam(String name, Property p) {
if (p instanceof ArrayProperty) { String type = normalizeType(getTypeDeclaration(p));
return " = new Array();"; if (p instanceof RefProperty) {
} else if (p instanceof MapProperty) { return " = " + type + ".constructFromObject(data['" + name + "']);";
return " = {}"; } else {
} else if (p instanceof LongProperty) { return " = ApiClient.convertToType(data['" + name + "'], " + type + ");";
LongProperty dp = (LongProperty) p;
return " = data." + name + ";";
// added for Javascript
} else if (p instanceof RefProperty) {
RefProperty rp = (RefProperty)p;
return ".constructFromObject(data." + name + ");";
} }
return super.toDefaultValueWithParam(name, p);
} }
/**
* Normalize type by wrapping primitive types with single quotes.
*
* @param type Primitive type
* @return Normalized type
*/
public String normalizeType(String type) {
return type.replaceAll("\\b(Boolean|Integer|Number|String|Date)\\b", "'$1'");
}
@Override @Override
public String getSwaggerType(Property p) { public String getSwaggerType(Property p) {
@ -367,12 +423,25 @@ public class JavascriptClientCodegen extends DefaultCodegen implements CodegenCo
throw new RuntimeException("Empty method/operation name (operationId) not allowed"); throw new RuntimeException("Empty method/operation name (operationId) not allowed");
} }
operationId = camelize(sanitizeName(operationId), true);
// method name cannot use reserved keyword, e.g. return // method name cannot use reserved keyword, e.g. return
if (reservedWords.contains(operationId)) { if (isReservedWord(operationId)) {
throw new RuntimeException(operationId + " (reserved word) cannot be used as method name"); String newOperationId = camelize("call_" + operationId, true);
LOGGER.warn(operationId + " (reserved word) cannot be used as method name. Renamed to " + newOperationId);
return newOperationId;
} }
return camelize(sanitizeName(operationId), true); return operationId;
}
@Override
public CodegenOperation fromOperation(String path, String httpMethod, Operation operation, Map<String, Model> definitions, Swagger swagger) {
CodegenOperation op = super.fromOperation(path, httpMethod, operation, definitions, swagger);
if (op.returnType != null) {
op.returnType = normalizeType(op.returnType);
}
return op;
} }
@Override @Override
@ -382,12 +451,41 @@ public class JavascriptClientCodegen extends DefaultCodegen implements CodegenCo
if (allDefinitions != null && codegenModel != null && codegenModel.parent != null && codegenModel.hasEnums) { if (allDefinitions != null && codegenModel != null && codegenModel.parent != null && codegenModel.hasEnums) {
final Model parentModel = allDefinitions.get(toModelName(codegenModel.parent)); final Model parentModel = allDefinitions.get(toModelName(codegenModel.parent));
final CodegenModel parentCodegenModel = super.fromModel(codegenModel.parent, parentModel); final CodegenModel parentCodegenModel = super.fromModel(codegenModel.parent, parentModel);
codegenModel = this.reconcileInlineEnums(codegenModel, parentCodegenModel); codegenModel = JavascriptClientCodegen.reconcileInlineEnums(codegenModel, parentCodegenModel);
} }
return codegenModel; return codegenModel;
} }
@Override
public Map<String, Object> postProcessOperations(Map<String, Object> objs) {
// Generate and store argument list string of each operation into
// vendor-extension: x-codegen-argList.
Map<String, Object> operations = (Map<String, Object>) objs.get("operations");
if (operations != null) {
List<CodegenOperation> ops = (List<CodegenOperation>) operations.get("operation");
for (CodegenOperation operation : ops) {
List<String> argList = new ArrayList();
boolean hasOptionalParams = false;
for (CodegenParameter p : operation.allParams) {
if (p.required != null && p.required) {
argList.add(p.paramName);
} else {
hasOptionalParams = true;
}
}
if (hasOptionalParams) {
argList.add("opts");
}
if (!usePromises) {
argList.add("callback");
}
operation.vendorExtensions.put("x-codegen-argList", StringUtils.join(argList, ", "));
}
}
return objs;
}
@Override @Override
public Map<String, Object> postProcessModels(Map<String, Object> objs) { public Map<String, Object> postProcessModels(Map<String, Object> objs) {
List<Object> models = (List<Object>) objs.get("models"); List<Object> models = (List<Object>) objs.get("models");
@ -431,46 +529,38 @@ public class JavascriptClientCodegen extends DefaultCodegen implements CodegenCo
} }
allowableValues.put("enumVars", enumVars); allowableValues.put("enumVars", enumVars);
} }
} // set vendor-extension: x-codegen-hasMoreRequired
return objs; CodegenProperty lastRequired = null;
} for (CodegenProperty var : cm.vars) {
if (var.required != null && var.required) {
public Map<String, Object> postProcessOperations(Map<String, Object> objs) { lastRequired = var;
if("retrofit".equals(getLibrary())) { }
Map<String, Object> operations = (Map<String, Object>) objs.get("operations"); }
if (operations != null) { for (CodegenProperty var : cm.vars) {
List<CodegenOperation> ops = (List<CodegenOperation>) operations.get("operation"); if (var == lastRequired) {
for (CodegenOperation operation : ops) { var.vendorExtensions.put("x-codegen-hasMoreRequired", false);
if (operation.hasConsumes == Boolean.TRUE) { } else if (var.required != null && var.required) {
Map<String, String> firstType = operation.consumes.get(0); var.vendorExtensions.put("x-codegen-hasMoreRequired", true);
if (firstType != null) {
if ("multipart/form-data".equals(firstType.get("mediaType"))) {
operation.isMultipart = Boolean.TRUE;
}
}
}
if (operation.returnType == null) {
operation.returnType = "Void";
}
} }
} }
} }
return objs; return objs;
} }
@Override
protected boolean needToImport(String type) { protected boolean needToImport(String type) {
return !defaultIncludes.contains(type) return !defaultIncludes.contains(type)
&& !languageSpecificPrimitives.contains(type); && !languageSpecificPrimitives.contains(type);
} }
private String findCommonPrefixOfVars(List<String> vars) { private static String findCommonPrefixOfVars(List<String> vars) {
String prefix = StringUtils.getCommonPrefix(vars.toArray(new String[vars.size()])); String prefix = StringUtils.getCommonPrefix(vars.toArray(new String[vars.size()]));
// exclude trailing characters that should be part of a valid variable // exclude trailing characters that should be part of a valid variable
// e.g. ["status-on", "status-off"] => "status-" (not "status-o") // e.g. ["status-on", "status-off"] => "status-" (not "status-o")
return prefix.replaceAll("[a-zA-Z0-9]+\\z", ""); return prefix.replaceAll("[a-zA-Z0-9]+\\z", "");
} }
private String toEnumVarName(String value) { private static String toEnumVarName(String value) {
String var = value.replaceAll("\\W+", "_").toUpperCase(); String var = value.replaceAll("\\W+", "_").toUpperCase();
if (var.matches("\\d.*")) { if (var.matches("\\d.*")) {
return "_" + var; return "_" + var;
@ -479,7 +569,7 @@ public class JavascriptClientCodegen extends DefaultCodegen implements CodegenCo
} }
} }
private CodegenModel reconcileInlineEnums(CodegenModel codegenModel, CodegenModel parentCodegenModel) { private static CodegenModel reconcileInlineEnums(CodegenModel codegenModel, CodegenModel parentCodegenModel) {
// This generator uses inline classes to define enums, which breaks when // This generator uses inline classes to define enums, which breaks when
// dealing with models that have subTypes. To clean this up, we will analyze // dealing with models that have subTypes. To clean this up, we will analyze
// the parent and child models, look for enums that match, and remove // the parent and child models, look for enums that match, and remove
@ -527,7 +617,7 @@ public class JavascriptClientCodegen extends DefaultCodegen implements CodegenCo
return codegenModel; return codegenModel;
} }
private String sanitizePackageName(String packageName) { private static String sanitizePackageName(String packageName) { // FIXME parameter should not be assigned. Also declare it as "final"
packageName = packageName.trim(); packageName = packageName.trim();
packageName = packageName.replaceAll("[^a-zA-Z0-9_\\.]", "_"); packageName = packageName.replaceAll("[^a-zA-Z0-9_\\.]", "_");
if(Strings.isNullOrEmpty(packageName)) { if(Strings.isNullOrEmpty(packageName)) {

View File

@ -0,0 +1,216 @@
package io.swagger.codegen.languages;
import io.swagger.codegen.CodegenModel;
import io.swagger.codegen.*;
import io.swagger.models.properties.*;
import java.util.TreeSet;
import java.util.*;
import java.io.File;
public class JavascriptClosureAngularClientCodegen extends DefaultCodegen implements CodegenConfig {
public JavascriptClosureAngularClientCodegen() {
super();
supportsInheritance = false;
setReservedWordsLowerCase(Arrays.asList("abstract",
"continue", "for", "new", "switch", "assert", "default", "if",
"package", "synchronized", "do", "goto", "private",
"this", "break", "double", "implements", "protected", "throw",
"byte", "else", "import", "public", "throws", "case", "enum",
"instanceof", "return", "transient", "catch", "extends", "int",
"short", "try", "char", "final", "interface", "static", "void",
"class", "finally", "const", "super", "while"));
languageSpecificPrimitives = new HashSet<String>(Arrays.asList(
"string",
"boolean",
"number",
"Object",
"Blob",
"Date"));
instantiationTypes.put("array", "Array");
typeMapping = new HashMap<String, String>();
typeMapping.put("Array", "Array");
typeMapping.put("array", "Array");
typeMapping.put("List", "Array");
typeMapping.put("boolean", "boolean");
typeMapping.put("string", "string");
typeMapping.put("int", "number");
typeMapping.put("float", "number");
typeMapping.put("number", "number");
typeMapping.put("long", "number");
typeMapping.put("short", "number");
typeMapping.put("char", "string");
typeMapping.put("double", "number");
typeMapping.put("object", "Object");
typeMapping.put("Object", "Object");
typeMapping.put("File", "Blob");
typeMapping.put("file", "Blob");
typeMapping.put("integer", "number");
typeMapping.put("Map", "Object");
typeMapping.put("map", "Object");
typeMapping.put("DateTime", "Date");
importMapping = new HashMap<String, String>();
defaultIncludes = new HashSet<String>(Arrays.asList(
"Object",
"Array",
"Blob"
));
typeMapping.put("binary", "string");
outputFolder = "generated-code/javascript-closure-angular";
modelTemplateFiles.put("model.mustache", ".js");
apiTemplateFiles.put("api.mustache", ".js");
embeddedTemplateDir = templateDir = "Javascript-Closure-Angular";
apiPackage = "API.Client";
modelPackage = "API.Client";
}
@Override
public String getName() {
return "javascript-closure-angular";
}
@Override
public String getHelp() {
return "Generates a Javascript AngularJS client library annotated with Google Closure Compiler annotations" +
"(https://developers.google.com/closure/compiler/docs/js-for-compiler?hl=en)";
}
@Override
public CodegenType getTag() {
return CodegenType.CLIENT;
}
@Override
public String escapeReservedWord(String name) {
return "_" + name;
}
@Override
public String apiFileFolder() {
return outputFolder + "/" + apiPackage().replace('.', File.separatorChar);
}
public String modelFileFolder() {
return outputFolder + "/" + modelPackage().replace('.', File.separatorChar);
}
@Override
public String toVarName(String name) {
// replace - with _ e.g. created-at => created_at
name = name.replaceAll("-", "_");
// if it's all uppper case, do nothing
if (name.matches("^[A-Z_]*$"))
return name;
// camelize the variable name
// pet_id => PetId
name = camelize(name, true);
// for reserved word or word starting with number, append _
if (isReservedWord(name) || name.matches("^\\d.*"))
name = escapeReservedWord(name);
return name;
}
@Override
public String toParamName(String name) {
// should be the same as variable name
return toVarName(name);
}
@Override
public String toModelName(String name) {
// model name cannot use reserved keyword, e.g. return
if (isReservedWord(name))
throw new RuntimeException(name
+ " (reserved word) cannot be used as a model name");
// camelize the model name
// phone_number => PhoneNumber
return camelize(name);
}
@Override
public String toModelFilename(String name) {
// should be the same as the model name
return toModelName(name);
}
@Override
public String getTypeDeclaration(Property p) {
if (p instanceof ArrayProperty) {
ArrayProperty ap = (ArrayProperty) p;
Property inner = ap.getItems();
return getSwaggerType(p) + "<!" + getTypeDeclaration(inner) + ">";
} else if (p instanceof MapProperty) {
MapProperty mp = (MapProperty) p;
Property inner = mp.getAdditionalProperties();
return "Object<!string, "+ getTypeDeclaration(inner) + ">";
} else if (p instanceof FileProperty) {
return "Object";
}
String type = super.getTypeDeclaration(p);
if (type.equals("boolean") ||
type.equals("Date") ||
type.equals("number") ||
type.equals("string")) {
return type;
}
return apiPackage + "." + type;
}
@Override
public String getSwaggerType(Property p) {
String swaggerType = super.getSwaggerType(p);
String type = null;
if (typeMapping.containsKey(swaggerType)) {
type = typeMapping.get(swaggerType);
if (languageSpecificPrimitives.contains(type)) {
return type;
}
} else
type = swaggerType;
return type;
}
@Override
public Map<String, Object> postProcessModels(Map<String, Object> objs) {
List<Object> models = (List<Object>) objs.get("models");
for (Object _mo : models) {
Map<String, Object> mo = (Map<String, Object>) _mo;
CodegenModel cm = (CodegenModel) mo.get("model");
cm.imports = new TreeSet(cm.imports);
for (CodegenProperty var : cm.vars) {
// handle default value for enum, e.g. available => StatusEnum.available
if (var.isEnum && var.defaultValue != null && !"null".equals(var.defaultValue)) {
var.defaultValue = var.datatypeWithEnum + "." + var.defaultValue;
}
}
}
return objs;
}
@Override
public Map<String, Object> postProcessOperations(Map<String, Object> objs) {
if (objs.get("imports") instanceof List) {
List<Map<String, String>> imports = (ArrayList<Map<String, String>>)objs.get("imports");
Collections.sort(imports, new Comparator<Map<String, String>>() {
public int compare(Map<String, String> o1, Map<String, String> o2) {
return o1.get("import").compareTo(o2.get("import"));
}
});
objs.put("imports", imports);
}
return objs;
}
}

View File

@ -1,18 +1,29 @@
package io.swagger.codegen.languages; package io.swagger.codegen.languages;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
import io.swagger.codegen.*; import io.swagger.codegen.*;
import io.swagger.models.Swagger; import io.swagger.models.*;
import io.swagger.util.Yaml; import io.swagger.util.Yaml;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.*; import java.util.*;
import java.util.Map.Entry; import java.util.Map.Entry;
public class NodeJSServerCodegen extends DefaultCodegen implements CodegenConfig { public class NodeJSServerCodegen extends DefaultCodegen implements CodegenConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(NodeJSServerCodegen.class);
protected String apiVersion = "1.0.0"; protected String apiVersion = "1.0.0";
protected int serverPort = 8080; protected int serverPort = 8080;
protected String projectName = "swagger-server"; protected String projectName = "swagger-server";
@ -49,7 +60,7 @@ public class NodeJSServerCodegen extends DefaultCodegen implements CodegenConfig
/** /**
* Reserved words. Override this with reserved words specific to your language * Reserved words. Override this with reserved words specific to your language
*/ */
reservedWords = new HashSet<String>( setReservedWordsLowerCase(
Arrays.asList( Arrays.asList(
"break", "case", "class", "catch", "const", "continue", "debugger", "break", "case", "class", "catch", "const", "continue", "debugger",
"default", "delete", "do", "else", "export", "extends", "finally", "default", "delete", "do", "else", "export", "extends", "finally",
@ -78,18 +89,9 @@ public class NodeJSServerCodegen extends DefaultCodegen implements CodegenConfig
"api", "api",
"swagger.yaml") "swagger.yaml")
); );
supportingFiles.add(new SupportingFile("index.mustache", writeOptional(outputFolder, new SupportingFile("index.mustache", "", "index.js"));
"", writeOptional(outputFolder, new SupportingFile("package.mustache", "", "package.json"));
"index.js") writeOptional(outputFolder, new SupportingFile("README.mustache", "", "README.md"));
);
supportingFiles.add(new SupportingFile("package.mustache",
"",
"package.json")
);
supportingFiles.add(new SupportingFile("README.mustache",
"",
"README.md")
);
if (System.getProperty("noservice") == null) { if (System.getProperty("noservice") == null) {
apiTemplateFiles.put( apiTemplateFiles.put(
"service.mustache", // the template to use "service.mustache", // the template to use
@ -97,6 +99,7 @@ public class NodeJSServerCodegen extends DefaultCodegen implements CodegenConfig
} }
} }
@Override
public String apiPackage() { public String apiPackage() {
return "controllers"; return "controllers";
} }
@ -107,6 +110,7 @@ public class NodeJSServerCodegen extends DefaultCodegen implements CodegenConfig
* @return the CodegenType for this generator * @return the CodegenType for this generator
* @see io.swagger.codegen.CodegenType * @see io.swagger.codegen.CodegenType
*/ */
@Override
public CodegenType getTag() { public CodegenType getTag() {
return CodegenType.SERVER; return CodegenType.SERVER;
} }
@ -117,6 +121,7 @@ public class NodeJSServerCodegen extends DefaultCodegen implements CodegenConfig
* *
* @return the friendly name for the generator * @return the friendly name for the generator
*/ */
@Override
public String getName() { public String getName() {
return "nodejs"; return "nodejs";
} }
@ -127,6 +132,7 @@ public class NodeJSServerCodegen extends DefaultCodegen implements CodegenConfig
* *
* @return A string value for the help message * @return A string value for the help message
*/ */
@Override
public String getHelp() { public String getHelp() {
return "Generates a nodejs server library using the swagger-tools project. By default, " + return "Generates a nodejs server library using the swagger-tools project. By default, " +
"it will also generate service classes--which you can disable with the `-Dnoservice` environment variable."; "it will also generate service classes--which you can disable with the `-Dnoservice` environment variable.";
@ -173,6 +179,7 @@ public class NodeJSServerCodegen extends DefaultCodegen implements CodegenConfig
List<CodegenOperation> operations = (List<CodegenOperation>) objectMap.get("operation"); List<CodegenOperation> operations = (List<CodegenOperation>) objectMap.get("operation");
for (CodegenOperation operation : operations) { for (CodegenOperation operation : operations) {
operation.httpMethod = operation.httpMethod.toLowerCase(); operation.httpMethod = operation.httpMethod.toLowerCase();
List<CodegenParameter> params = operation.allParams; List<CodegenParameter> params = operation.allParams;
if (params != null && params.size() == 0) { if (params != null && params.size() == 0) {
operation.allParams = null; operation.allParams = null;
@ -200,7 +207,7 @@ public class NodeJSServerCodegen extends DefaultCodegen implements CodegenConfig
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private List<Map<String, Object>> getOperations(Map<String, Object> objs) { private static List<Map<String, Object>> getOperations(Map<String, Object> objs) {
List<Map<String, Object>> result = new ArrayList<Map<String, Object>>(); List<Map<String, Object>> result = new ArrayList<Map<String, Object>>();
Map<String, Object> apiInfo = (Map<String, Object>) objs.get("apiInfo"); Map<String, Object> apiInfo = (Map<String, Object>) objs.get("apiInfo");
List<Map<String, Object>> apis = (List<Map<String, Object>>) apiInfo.get("apis"); List<Map<String, Object>> apis = (List<Map<String, Object>>) apiInfo.get("apis");
@ -210,7 +217,7 @@ public class NodeJSServerCodegen extends DefaultCodegen implements CodegenConfig
return result; return result;
} }
private List<Map<String, Object>> sortOperationsByPath(List<CodegenOperation> ops) { private static List<Map<String, Object>> sortOperationsByPath(List<CodegenOperation> ops) {
Multimap<String, CodegenOperation> opsByPath = ArrayListMultimap.create(); Multimap<String, CodegenOperation> opsByPath = ArrayListMultimap.create();
for (CodegenOperation op : ops) { for (CodegenOperation op : ops) {
@ -234,13 +241,66 @@ public class NodeJSServerCodegen extends DefaultCodegen implements CodegenConfig
} }
@Override @Override
public void preprocessSwagger(Swagger swagger) {
String host = swagger.getHost();
String port = "8080";
if (host != null) {
String[] parts = host.split(":");
if (parts.length > 1) {
port = parts[1];
}
}
this.additionalProperties.put("serverPort", port);
if (swagger.getInfo() != null) {
Info info = swagger.getInfo();
if (info.getTitle() != null) {
// when info.title is defined, use it for projectName
// used in package.json
projectName = dashize(info.getTitle());
this.additionalProperties.put("projectName", projectName);
}
}
// need vendor extensions for x-swagger-router-controller
Map<String, Path> paths = swagger.getPaths();
if(paths != null) {
for(String pathname : paths.keySet()) {
Path path = paths.get(pathname);
Map<HttpMethod, Operation> operationMap = path.getOperationMap();
if(operationMap != null) {
for(HttpMethod method : operationMap.keySet()) {
Operation operation = operationMap.get(method);
String tag = "default";
if(operation.getTags() != null && operation.getTags().size() > 0) {
tag = toApiName(operation.getTags().get(0));
}
if(operation.getOperationId() == null) {
operation.setOperationId(getOrGenerateOperationId(operation, pathname, method.toString()));
}
operation.getVendorExtensions().put("x-swagger-router-controller", toApiName(tag));
}
}
}
}
}
@Override
public Map<String, Object> postProcessSupportingFileData(Map<String, Object> objs) { public Map<String, Object> postProcessSupportingFileData(Map<String, Object> objs) {
Swagger swagger = (Swagger)objs.get("swagger"); Swagger swagger = (Swagger)objs.get("swagger");
if(swagger != null) { if(swagger != null) {
try { try {
objs.put("swagger-yaml", Yaml.mapper().writeValueAsString(swagger)); SimpleModule module = new SimpleModule();
module.addSerializer(Double.class, new JsonSerializer<Double>() {
@Override
public void serialize(Double val, JsonGenerator jgen,
SerializerProvider provider) throws IOException, JsonProcessingException {
jgen.writeNumber(new BigDecimal(val));
}
});
objs.put("swagger-yaml", Yaml.mapper().registerModule(module).writeValueAsString(swagger));
} catch (JsonProcessingException e) { } catch (JsonProcessingException e) {
e.printStackTrace(); LOGGER.error(e.getMessage(), e);
} }
} }
for (Map<String, Object> operations : getOperations(objs)) { for (Map<String, Object> operations : getOperations(objs)) {
@ -252,4 +312,4 @@ public class NodeJSServerCodegen extends DefaultCodegen implements CodegenConfig
} }
return super.postProcessSupportingFileData(objs); return super.postProcessSupportingFileData(objs);
} }
} }

View File

@ -3,6 +3,7 @@ package io.swagger.codegen.languages;
import io.swagger.codegen.CliOption; import io.swagger.codegen.CliOption;
import io.swagger.codegen.CodegenConfig; import io.swagger.codegen.CodegenConfig;
import io.swagger.codegen.CodegenConstants; import io.swagger.codegen.CodegenConstants;
import io.swagger.codegen.CodegenOperation;
import io.swagger.codegen.CodegenProperty; import io.swagger.codegen.CodegenProperty;
import io.swagger.codegen.CodegenType; import io.swagger.codegen.CodegenType;
import io.swagger.codegen.DefaultCodegen; import io.swagger.codegen.DefaultCodegen;
@ -13,6 +14,8 @@ import java.io.File;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set; import java.util.Set;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
@ -36,7 +39,7 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
public ObjcClientCodegen() { public ObjcClientCodegen() {
super(); super();
outputFolder = "generated-code" + File.separator + "objc"; outputFolder = "generated-code" + File.separator + "objc";
modelTemplateFiles.put("model-header.mustache", ".h"); modelTemplateFiles.put("model-header.mustache", ".h");
modelTemplateFiles.put("model-body.mustache", ".m"); modelTemplateFiles.put("model-body.mustache", ".m");
@ -57,7 +60,7 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
defaultIncludes.add("NSDictionary"); defaultIncludes.add("NSDictionary");
defaultIncludes.add("NSMutableArray"); defaultIncludes.add("NSMutableArray");
defaultIncludes.add("NSMutableDictionary"); defaultIncludes.add("NSMutableDictionary");
languageSpecificPrimitives.clear(); languageSpecificPrimitives.clear();
languageSpecificPrimitives.add("NSNumber"); languageSpecificPrimitives.add("NSNumber");
languageSpecificPrimitives.add("NSString"); languageSpecificPrimitives.add("NSString");
@ -84,24 +87,32 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
typeMapping.put("List", "NSArray"); typeMapping.put("List", "NSArray");
typeMapping.put("object", "NSObject"); typeMapping.put("object", "NSObject");
typeMapping.put("file", "NSURL"); typeMapping.put("file", "NSURL");
//TODO binary should be mapped to byte array
// mapped to String as a workaround
typeMapping.put("binary", "NSString");
// ref: http://www.tutorialspoint.com/objective_c/objective_c_basic_syntax.htm // ref: http://www.tutorialspoint.com/objective_c/objective_c_basic_syntax.htm
reservedWords = new HashSet<String>( setReservedWordsLowerCase(
Arrays.asList( Arrays.asList(
"auto", "else", "long", "switch", // local variable names in API methods (endpoints)
"break", "enum", "register", "typedef", "resourcePath", "pathParams", "queryParams", "headerParams",
"case", "extern", "return", "union", "responseContentType", "requestContentType", "authSettings",
"char", "float", "short", "unsigned", "formParams", "localVarFiles", "bodyParam",
"const", "for", "signed", "void", // objc reserved words
"continue", "goto", "sizeof", "volatile", "auto", "else", "long", "switch",
"default", "if", "id", "static", "while", "break", "enum", "register", "typedef",
"do", "int", "struct", "_Packed", "case", "extern", "return", "union",
"double", "protocol", "interface", "implementation", "char", "float", "short", "unsigned",
"NSObject", "NSInteger", "NSNumber", "CGFloat", "const", "for", "signed", "void",
"property", "nonatomic", "retain", "strong", "continue", "goto", "sizeof", "volatile",
"weak", "unsafe_unretained", "readwrite", "readonly", "default", "if", "id", "static", "while",
"description" "do", "int", "struct", "_Packed",
"double", "protocol", "interface", "implementation",
"NSObject", "NSInteger", "NSNumber", "CGFloat",
"property", "nonatomic", "retain", "strong",
"weak", "unsafe_unretained", "readwrite", "readonly",
"description"
)); ));
importMapping = new HashMap<String, String>(); importMapping = new HashMap<String, String>();
@ -133,14 +144,17 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
cliOptions.add(new CliOption(LICENSE, "License to use in the podspec file.").defaultValue("MIT")); cliOptions.add(new CliOption(LICENSE, "License to use in the podspec file.").defaultValue("MIT"));
} }
@Override
public CodegenType getTag() { public CodegenType getTag() {
return CodegenType.CLIENT; return CodegenType.CLIENT;
} }
@Override
public String getName() { public String getName() {
return "objc"; return "objc";
} }
@Override
public String getHelp() { public String getHelp() {
return "Generates an Objective-C client library."; return "Generates an Objective-C client library.";
} }
@ -160,19 +174,19 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
if (additionalProperties.containsKey(CLASS_PREFIX)) { if (additionalProperties.containsKey(CLASS_PREFIX)) {
setClassPrefix((String) additionalProperties.get(CLASS_PREFIX)); setClassPrefix((String) additionalProperties.get(CLASS_PREFIX));
} }
if (additionalProperties.containsKey(AUTHOR_NAME)) { if (additionalProperties.containsKey(AUTHOR_NAME)) {
setAuthorName((String) additionalProperties.get(AUTHOR_NAME)); setAuthorName((String) additionalProperties.get(AUTHOR_NAME));
} }
if (additionalProperties.containsKey(AUTHOR_EMAIL)) { if (additionalProperties.containsKey(AUTHOR_EMAIL)) {
setAuthorEmail((String) additionalProperties.get(AUTHOR_EMAIL)); setAuthorEmail((String) additionalProperties.get(AUTHOR_EMAIL));
} }
if (additionalProperties.containsKey(GIT_REPO_URL)) { if (additionalProperties.containsKey(GIT_REPO_URL)) {
setGitRepoURL((String) additionalProperties.get(GIT_REPO_URL)); setGitRepoURL((String) additionalProperties.get(GIT_REPO_URL));
} }
if (additionalProperties.containsKey(LICENSE)) { if (additionalProperties.containsKey(LICENSE)) {
setLicense((String) additionalProperties.get(LICENSE)); setLicense((String) additionalProperties.get(LICENSE));
} }
@ -211,12 +225,8 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override @Override
public String toInstantiationType(Property p) { public String toInstantiationType(Property p) {
if (p instanceof MapProperty) { if (p instanceof MapProperty) {
MapProperty ap = (MapProperty) p;
String inner = getSwaggerType(ap.getAdditionalProperties());
return instantiationTypes.get("map"); return instantiationTypes.get("map");
} else if (p instanceof ArrayProperty) { } else if (p instanceof ArrayProperty) {
ArrayProperty ap = (ArrayProperty) p;
String inner = getSwaggerType(ap.getItems());
return instantiationTypes.get("array"); return instantiationTypes.get("array");
} else { } else {
return null; return null;
@ -239,12 +249,12 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
if (typeMapping.containsKey(swaggerType)) { if (typeMapping.containsKey(swaggerType)) {
type = typeMapping.get(swaggerType); type = typeMapping.get(swaggerType);
if (languageSpecificPrimitives.contains(type) && !foundationClasses.contains(type)) { if (languageSpecificPrimitives.contains(type) && !foundationClasses.contains(type)) {
return toModelName(type); return toModelNameWithoutReservedWordCheck(type);
} }
} else { } else {
type = swaggerType; type = swaggerType;
} }
return toModelName(type); return toModelNameWithoutReservedWordCheck(type);
} }
@Override @Override
@ -304,7 +314,24 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override @Override
public String toModelName(String type) { public String toModelName(String type) {
type = type.replaceAll("[^0-9a-zA-Z_]", "_"); // model name cannot use reserved keyword
if (reservedWords.contains(type)) {
LOGGER.warn(type+ " (reserved word) cannot be used as model name. Renamed to " + ("object_" + type) + " before further processing");
type = "object_" + type; // e.g. return => ObjectReturn (after camelize)
}
return toModelNameWithoutReservedWordCheck(type);
}
/*
* Convert input to proper model name according to ObjC style guide
* without checking for reserved words
*
* @param type Model anme
* @return model Name in ObjC style guide
*/
public String toModelNameWithoutReservedWordCheck(String type) {
type = type.replaceAll("[^0-9a-zA-Z_]", "_"); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
// language build-in classes // language build-in classes
if (typeMapping.keySet().contains(type) || if (typeMapping.keySet().contains(type) ||
@ -316,7 +343,15 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
} }
// custom classes // custom classes
else { else {
return classPrefix + camelize(type); if (!StringUtils.isEmpty(modelNameSuffix)) { // set model suffix
type = type + "_" + modelNameSuffix;
}
if (!StringUtils.isEmpty(modelNamePrefix)) { // set model prefix
type = modelNamePrefix + "_" + type;
}
return classPrefix + camelize(type); // add class prefix
} }
} }
@ -356,6 +391,7 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
return classPrefix + camelize(name) + "Api"; return classPrefix + camelize(name) + "Api";
} }
@Override
public String toApiFilename(String name) { public String toApiFilename(String name) {
return classPrefix + camelize(name) + "Api"; return classPrefix + camelize(name) + "Api";
} }
@ -363,7 +399,7 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override @Override
public String toVarName(String name) { public String toVarName(String name) {
// sanitize name // sanitize name
name = sanitizeName(name); name = sanitizeName(name); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
// if it's all upper case, do noting // if it's all upper case, do noting
if (name.matches("^[A-Z_]$")) { if (name.matches("^[A-Z_]$")) {
@ -381,7 +417,7 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
name = camelize(name, true); name = camelize(name, true);
// for reserved word or word starting with number, prepend `_` // for reserved word or word starting with number, prepend `_`
if (reservedWords.contains(name) || name.matches("^\\d.*")) { if (isReservedWord(name) || name.matches("^\\d.*")) {
name = escapeReservedWord(name); name = escapeReservedWord(name);
} }
@ -395,10 +431,12 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
return toVarName(name); return toVarName(name);
} }
@Override
public String escapeReservedWord(String name) { public String escapeReservedWord(String name) {
return "_" + name; return "_" + name;
} }
@SuppressWarnings("static-method")
public String escapeSpecialWord(String name) { public String escapeSpecialWord(String name) {
return "var_" + name; return "var_" + name;
} }
@ -411,8 +449,9 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
} }
// method name cannot use reserved keyword, e.g. return // method name cannot use reserved keyword, e.g. return
if (reservedWords.contains(operationId)) { if (isReservedWord(operationId)) {
throw new RuntimeException(operationId + " (reserved word) cannot be used as method name"); LOGGER.warn(operationId + " (reserved word) cannot be used as method name. Renamed to " + camelize(sanitizeName("call_" + operationId), true));
operationId = "call_" + operationId;
} }
return camelize(sanitizeName(operationId), true); return camelize(sanitizeName(operationId), true);
@ -429,23 +468,38 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
public void setPodVersion(String podVersion) { public void setPodVersion(String podVersion) {
this.podVersion = podVersion; this.podVersion = podVersion;
} }
public void setAuthorEmail(String authorEmail) { public void setAuthorEmail(String authorEmail) {
this.authorEmail = authorEmail; this.authorEmail = authorEmail;
} }
public void setAuthorName(String authorName) { public void setAuthorName(String authorName) {
this.authorName = authorName; this.authorName = authorName;
} }
public void setGitRepoURL(String gitRepoURL) { public void setGitRepoURL(String gitRepoURL) {
this.gitRepoURL = gitRepoURL; this.gitRepoURL = gitRepoURL;
} }
public void setLicense(String license) { public void setLicense(String license) {
this.license = license; this.license = license;
} }
@Override
public Map<String, Object> postProcessOperations(Map<String, Object> objs) {
Map<String, Object> operations = (Map<String, Object>) objs.get("operations");
if (operations != null) {
List<CodegenOperation> ops = (List<CodegenOperation>) operations.get("operation");
for (CodegenOperation operation : ops) {
if (!operation.allParams.isEmpty()) {
String firstParamName = operation.allParams.get(0).paramName;
operation.vendorExtensions.put("firstParamAltName", camelize(firstParamName));
}
}
}
return objs;
}
/** /**
* Return the default value of the property * Return the default value of the property
* *

View File

@ -13,25 +13,31 @@ import io.swagger.models.properties.Property;
import java.io.File; import java.io.File;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashSet; import java.util.HashSet;
import java.util.regex.Matcher;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig { public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig {
public static final String MODULE_NAME = "moduleName"; public static final String MODULE_NAME = "moduleName";
public static final String MODULE_VERSION = "moduleVersion"; public static final String MODULE_VERSION = "moduleVersion";
protected String moduleName = "SwaggerClient"; protected String moduleName = "WWW::SwaggerClient";
protected String modulePathPart = moduleName.replaceAll("::", Matcher.quoteReplacement(File.separator));
protected String moduleVersion = "1.0.0"; protected String moduleVersion = "1.0.0";
protected static int emptyFunctionNameCounter = 0;
public PerlClientCodegen() { public PerlClientCodegen() {
super(); super();
modelPackage = File.separatorChar + "Object"; modelPackage = File.separatorChar + "Object";
outputFolder = "generated-code" + File.separatorChar + "perl"; outputFolder = "generated-code" + File.separatorChar + "perl";
modelTemplateFiles.put("object.mustache", ".pm"); modelTemplateFiles.put("object.mustache", ".pm");
apiTemplateFiles.put("api.mustache", ".pm"); apiTemplateFiles.put("api.mustache", ".pm");
modelTestTemplateFiles.put("object_test.mustache", ".t");
apiTestTemplateFiles.put("api_test.mustache", ".t");
embeddedTemplateDir = templateDir = "perl"; embeddedTemplateDir = templateDir = "perl";
reservedWords = new HashSet<String>( setReservedWordsLowerCase(
Arrays.asList( Arrays.asList(
"else", "lock", "qw", "else", "lock", "qw",
"__END__", "elsif", "lt", "qx", "__END__", "elsif", "lt", "qx",
@ -42,7 +48,8 @@ public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig {
"cmp", "ge", "package", "until", "cmp", "ge", "package", "until",
"continue", "gt", "q", "while", "continue", "gt", "q", "while",
"CORE", "if", "qq", "xor", "CORE", "if", "qq", "xor",
"do", "le", "qr", "y" "do", "le", "qr", "y",
"return"
) )
); );
@ -64,17 +71,22 @@ public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig {
typeMapping.put("boolean", "boolean"); typeMapping.put("boolean", "boolean");
typeMapping.put("string", "string"); typeMapping.put("string", "string");
typeMapping.put("date", "DateTime"); typeMapping.put("date", "DateTime");
typeMapping.put("dateTime", "DateTime"); typeMapping.put("DateTime", "DateTime");
typeMapping.put("password", "string"); typeMapping.put("password", "string");
typeMapping.put("array", "ARRAY"); typeMapping.put("array", "ARRAY");
typeMapping.put("map", "HASH"); typeMapping.put("map", "HASH");
typeMapping.put("object", "object"); typeMapping.put("object", "object");
//TODO binary should be mapped to byte array
// mapped to String as a workaround
typeMapping.put("binary", "string");
cliOptions.clear(); cliOptions.clear();
cliOptions.add(new CliOption(MODULE_NAME, "Perl module name (convention: CamelCase).").defaultValue("SwaggerClient")); cliOptions.add(new CliOption(MODULE_NAME, "Perl module name (convention: CamelCase or Long::Module).").defaultValue("SwaggerClient"));
cliOptions.add(new CliOption(MODULE_VERSION, "Perl module version.").defaultValue("1.0.0")); cliOptions.add(new CliOption(MODULE_VERSION, "Perl module version.").defaultValue("1.0.0"));
cliOptions.add(new CliOption(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG_DESC)); cliOptions.add(CliOption.newBoolean(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG,
cliOptions.add(new CliOption(CodegenConstants.ENSURE_UNIQUE_PARAMS, CodegenConstants.ENSURE_UNIQUE_PARAMS_DESC)); CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG_DESC).defaultValue(Boolean.TRUE.toString()));
cliOptions.add(CliOption.newBoolean(CodegenConstants.ENSURE_UNIQUE_PARAMS, CodegenConstants
.ENSURE_UNIQUE_PARAMS_DESC).defaultValue(Boolean.TRUE.toString()));
} }
@ -91,27 +103,31 @@ public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig {
if (additionalProperties.containsKey(MODULE_NAME)) { if (additionalProperties.containsKey(MODULE_NAME)) {
setModuleName((String) additionalProperties.get(MODULE_NAME)); setModuleName((String) additionalProperties.get(MODULE_NAME));
setModulePathPart(moduleName.replaceAll("::", Matcher.quoteReplacement(File.separator)));
} else { } else {
additionalProperties.put(MODULE_NAME, moduleName); additionalProperties.put(MODULE_NAME, moduleName);
} }
supportingFiles.add(new SupportingFile("ApiClient.mustache", ("lib/WWW/" + moduleName).replace('/', File.separatorChar), "ApiClient.pm")); supportingFiles.add(new SupportingFile("ApiClient.mustache", ("lib/" + modulePathPart).replace('/', File.separatorChar), "ApiClient.pm"));
supportingFiles.add(new SupportingFile("Configuration.mustache", ("lib/WWW/" + moduleName).replace('/', File.separatorChar), "Configuration.pm")); supportingFiles.add(new SupportingFile("Configuration.mustache", ("lib/" + modulePathPart).replace('/', File.separatorChar), "Configuration.pm"));
supportingFiles.add(new SupportingFile("BaseObject.mustache", ("lib/WWW/" + moduleName).replace('/', File.separatorChar), "Object/BaseObject.pm")); supportingFiles.add(new SupportingFile("ApiFactory.mustache", ("lib/" + modulePathPart).replace('/', File.separatorChar), "ApiFactory.pm"));
supportingFiles.add(new SupportingFile("ApiFactory.mustache", ("lib/WWW/" + moduleName).replace('/', File.separatorChar), "ApiFactory.pm")); supportingFiles.add(new SupportingFile("Role.mustache", ("lib/" + modulePathPart).replace('/', File.separatorChar), "Role.pm"));
supportingFiles.add(new SupportingFile("Role.mustache", ("lib/WWW/" + moduleName).replace('/', File.separatorChar), "Role.pm")); supportingFiles.add(new SupportingFile("AutoDoc.mustache", ("lib/" + modulePathPart + "/Role").replace('/', File.separatorChar), "AutoDoc.pm"));
supportingFiles.add(new SupportingFile("AutoDoc.mustache", ("lib/WWW/" + moduleName + "/Role").replace('/', File.separatorChar), "AutoDoc.pm")); supportingFiles.add(new SupportingFile("autodoc.script.mustache", "bin", "autodoc"));
supportingFiles.add(new SupportingFile("autodoc.script.mustache", ("bin/").replace('/', File.separatorChar), "autodoc")); supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
} }
@Override
public CodegenType getTag() { public CodegenType getTag() {
return CodegenType.CLIENT; return CodegenType.CLIENT;
} }
@Override
public String getName() { public String getName() {
return "perl"; return "perl";
} }
@Override
public String getHelp() { public String getHelp() {
return "Generates a Perl client library."; return "Generates a Perl client library.";
} }
@ -123,11 +139,23 @@ public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override @Override
public String apiFileFolder() { public String apiFileFolder() {
return (outputFolder + "/lib/WWW/" + moduleName + apiPackage()).replace('/', File.separatorChar); return (outputFolder + "/lib/" + modulePathPart + apiPackage()).replace('/', File.separatorChar);
} }
@Override
public String modelFileFolder() { public String modelFileFolder() {
return (outputFolder + "/lib/WWW/" + moduleName + modelPackage()).replace('/', File.separatorChar); return (outputFolder + "/lib/" + modulePathPart + modelPackage()).replace('/', File.separatorChar);
}
@Override
public String apiTestFileFolder() {
return (outputFolder + "/t").replace('/', File.separatorChar);
}
@Override
public String modelTestFileFolder() {
return (outputFolder + "/t").replace('/', File.separatorChar);
} }
@Override @Override
@ -159,9 +187,10 @@ public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig {
if (type == null) { if (type == null) {
return null; return null;
} }
return type; return toModelName(type);
} }
@Override
public String toDefaultValue(Property p) { public String toDefaultValue(Property p) {
return "null"; return "null";
} }
@ -171,14 +200,13 @@ public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig {
public String toVarName(String name) { public String toVarName(String name) {
// return the name in underscore style // return the name in underscore style
// PhoneNumber => phone_number // PhoneNumber => phone_number
name = underscore(name); name = underscore(name); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
// parameter name starting with number won't compile // parameter name starting with number won't compile
// need to escape it by appending _ at the beginning // need to escape it by appending _ at the beginning
if (name.matches("^\\d.*")) { if (name.matches("^\\d.*")) {
name = "_" + name; name = "_" + name;
} }
return name; return name;
} }
@ -191,10 +219,14 @@ public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override @Override
public String toModelName(String name) { public String toModelName(String name) {
// model name cannot use reserved keyword // model name cannot use reserved keyword
if (reservedWords.contains(name)) { if (isReservedWord(name)) {
escapeReservedWord(name); // e.g. return => _return LOGGER.warn(name + " (reserved word) cannot be used as model name. Renamed to " + camelize("object_" + name));
name = "object_" + name;
} }
// add prefix/suffic to model name
name = modelNamePrefix + name + modelNameSuffix;
// camelize the model name // camelize the model name
// phone_number => PhoneNumber // phone_number => PhoneNumber
return camelize(name); return camelize(name);
@ -206,10 +238,20 @@ public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig {
return toModelName(name); return toModelName(name);
} }
@Override
public String toModelTestFilename(String name) {
return toModelFilename(name) + "Test";
}
@Override
public String toApiTestFilename(String name) {
return toApiFilename(name) + "Test";
}
@Override @Override
public String toApiFilename(String name) { public String toApiFilename(String name) {
// replace - with _ e.g. created-at => created_at // replace - with _ e.g. created-at => created_at
name = name.replaceAll("-", "_"); name = name.replaceAll("-", "_"); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
// e.g. phone_number_api.rb => PhoneNumberApi.rb // e.g. phone_number_api.rb => PhoneNumberApi.rb
return camelize(name) + "Api"; return camelize(name) + "Api";
@ -226,14 +268,17 @@ public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override @Override
public String toOperationId(String operationId) { public String toOperationId(String operationId) {
// throw exception if method name is empty //rename to empty_function_name_1 (e.g.) if method name is empty
if (StringUtils.isEmpty(operationId)) { if (StringUtils.isEmpty(operationId)) {
throw new RuntimeException("Empty method name (operationId) not allowed"); operationId = underscore("empty_function_name_" + emptyFunctionNameCounter++);
LOGGER.warn("Empty method name (operationId) found. Renamed to " + operationId);
return operationId;
} }
// method name cannot use reserved keyword, e.g. return // method name cannot use reserved keyword, e.g. return
if (reservedWords.contains(operationId)) { if (isReservedWord(operationId)) {
throw new RuntimeException(operationId + " (reserved word) cannot be used as method name"); LOGGER.warn(operationId + " (reserved word) cannot be used as method name. Renamed to " + underscore("call_" + operationId));
return underscore("call_" + operationId);
} }
return underscore(operationId); return underscore(operationId);
@ -243,6 +288,10 @@ public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig {
this.moduleName = moduleName; this.moduleName = moduleName;
} }
public void setModulePathPart(String modulePathPart) {
this.modulePathPart = modulePathPart;
}
public void setModuleVersion(String moduleVersion) { public void setModuleVersion(String moduleVersion) {
this.moduleVersion = moduleVersion; this.moduleVersion = moduleVersion;
} }

View File

@ -20,6 +20,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
@SuppressWarnings("hiding")
static Logger LOGGER = LoggerFactory.getLogger(PhpClientCodegen.class); static Logger LOGGER = LoggerFactory.getLogger(PhpClientCodegen.class);
public static final String VARIABLE_NAMING_CONVENTION = "variableNamingConvention"; public static final String VARIABLE_NAMING_CONVENTION = "variableNamingConvention";
@ -41,13 +42,21 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
outputFolder = "generated-code" + File.separator + "php"; outputFolder = "generated-code" + File.separator + "php";
modelTemplateFiles.put("model.mustache", ".php"); modelTemplateFiles.put("model.mustache", ".php");
apiTemplateFiles.put("api.mustache", ".php"); apiTemplateFiles.put("api.mustache", ".php");
modelTestTemplateFiles.put("model_test.mustache", ".php");
apiTestTemplateFiles.put("api_test.mustache", ".php");
embeddedTemplateDir = templateDir = "php"; embeddedTemplateDir = templateDir = "php";
apiPackage = invokerPackage + "\\Api"; apiPackage = invokerPackage + "\\Api";
modelPackage = invokerPackage + "\\Model"; modelPackage = invokerPackage + "\\Model";
testPackage = invokerPackage + "\\Tests";
reservedWords = new HashSet<String>( setReservedWordsLowerCase(
Arrays.asList( Arrays.asList(
"__halt_compiler", "abstract", "and", "array", "as", "break", "callable", "case", "catch", "class", "clone", "const", "continue", "declare", "default", "die", "do", "echo", "else", "elseif", "empty", "enddeclare", "endfor", "endforeach", "endif", "endswitch", "endwhile", "eval", "exit", "extends", "final", "for", "foreach", "function", "global", "goto", "if", "implements", "include", "include_once", "instanceof", "insteadof", "interface", "isset", "list", "namespace", "new", "or", "print", "private", "protected", "public", "require", "require_once", "return", "static", "switch", "throw", "trait", "try", "unset", "use", "var", "while", "xor") // local variables used in api methods (endpoints)
"resourcePath", "httpBody", "queryParams", "headerParams",
"formParams", "_header_accept", "_tempBody",
// PHP reserved words
"__halt_compiler", "abstract", "and", "array", "as", "break", "callable", "case", "catch", "class", "clone", "const", "continue", "declare", "default", "die", "do", "echo", "else", "elseif", "empty", "enddeclare", "endfor", "endforeach", "endif", "endswitch", "endwhile", "eval", "exit", "extends", "final", "for", "foreach", "function", "global", "goto", "if", "implements", "include", "include_once", "instanceof", "insteadof", "interface", "isset", "list", "namespace", "new", "or", "print", "private", "protected", "public", "require", "require_once", "return", "static", "switch", "throw", "trait", "try", "unset", "use", "var", "while", "xor")
); );
// ref: http://php.net/manual/en/language.types.intro.php // ref: http://php.net/manual/en/language.types.intro.php
@ -76,7 +85,7 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
String primitives = "'" + StringUtils.join(languageSpecificPrimitives, "', '") + "'"; String primitives = "'" + StringUtils.join(languageSpecificPrimitives, "', '") + "'";
additionalProperties.put("primitives", primitives); additionalProperties.put("primitives", primitives);
// ref: https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md#data-types // ref: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#data-types
typeMapping = new HashMap<String, String>(); typeMapping = new HashMap<String, String>();
typeMapping.put("integer", "int"); typeMapping.put("integer", "int");
typeMapping.put("long", "int"); typeMapping.put("long", "int");
@ -85,14 +94,14 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
typeMapping.put("string", "string"); typeMapping.put("string", "string");
typeMapping.put("byte", "int"); typeMapping.put("byte", "int");
typeMapping.put("boolean", "bool"); typeMapping.put("boolean", "bool");
typeMapping.put("date", "\\DateTime"); typeMapping.put("Date", "\\DateTime");
typeMapping.put("datetime", "\\DateTime"); typeMapping.put("DateTime", "\\DateTime");
typeMapping.put("file", "\\SplFileObject"); typeMapping.put("file", "\\SplFileObject");
typeMapping.put("map", "map"); typeMapping.put("map", "map");
typeMapping.put("array", "array"); typeMapping.put("array", "array");
typeMapping.put("list", "array"); typeMapping.put("list", "array");
typeMapping.put("object", "object"); typeMapping.put("object", "object");
typeMapping.put("DateTime", "\\DateTime"); typeMapping.put("binary", "ByteArray");
cliOptions.add(new CliOption(CodegenConstants.MODEL_PACKAGE, CodegenConstants.MODEL_PACKAGE_DESC)); cliOptions.add(new CliOption(CodegenConstants.MODEL_PACKAGE, CodegenConstants.MODEL_PACKAGE_DESC));
cliOptions.add(new CliOption(CodegenConstants.API_PACKAGE, CodegenConstants.API_PACKAGE_DESC)); cliOptions.add(new CliOption(CodegenConstants.API_PACKAGE, CodegenConstants.API_PACKAGE_DESC));
@ -111,9 +120,9 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
} }
public String toPackagePath(String packageName, String basePath) { public String toPackagePath(String packageName, String basePath) {
packageName = packageName.replace(invokerPackage, ""); packageName = packageName.replace(invokerPackage, ""); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
if (basePath != null && basePath.length() > 0) { if (basePath != null && basePath.length() > 0) {
basePath = basePath.replaceAll("[\\\\/]?$", "") + File.separatorChar; basePath = basePath.replaceAll("[\\\\/]?$", "") + File.separatorChar; // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
} }
String regFirstPathSeparator; String regFirstPathSeparator;
@ -139,14 +148,17 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
.replaceAll(regLastPathSeparator+ "$", ""); .replaceAll(regLastPathSeparator+ "$", "");
} }
@Override
public CodegenType getTag() { public CodegenType getTag() {
return CodegenType.CLIENT; return CodegenType.CLIENT;
} }
@Override
public String getName() { public String getName() {
return "php"; return "php";
} }
@Override
public String getHelp() { public String getHelp() {
return "Generates a PHP client library."; return "Generates a PHP client library.";
} }
@ -166,13 +178,13 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
} else { } else {
additionalProperties.put(SRC_BASE_PATH, srcBasePath); additionalProperties.put(SRC_BASE_PATH, srcBasePath);
} }
if (additionalProperties.containsKey(CodegenConstants.INVOKER_PACKAGE)) { if (additionalProperties.containsKey(CodegenConstants.INVOKER_PACKAGE)) {
this.setInvokerPackage((String) additionalProperties.get(CodegenConstants.INVOKER_PACKAGE)); this.setInvokerPackage((String) additionalProperties.get(CodegenConstants.INVOKER_PACKAGE));
} else { } else {
additionalProperties.put(CodegenConstants.INVOKER_PACKAGE, invokerPackage); additionalProperties.put(CodegenConstants.INVOKER_PACKAGE, invokerPackage);
} }
if (!additionalProperties.containsKey(CodegenConstants.MODEL_PACKAGE)) { if (!additionalProperties.containsKey(CodegenConstants.MODEL_PACKAGE)) {
additionalProperties.put(CodegenConstants.MODEL_PACKAGE, modelPackage); additionalProperties.put(CodegenConstants.MODEL_PACKAGE, modelPackage);
} }
@ -180,19 +192,19 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
if (!additionalProperties.containsKey(CodegenConstants.API_PACKAGE)) { if (!additionalProperties.containsKey(CodegenConstants.API_PACKAGE)) {
additionalProperties.put(CodegenConstants.API_PACKAGE, apiPackage); additionalProperties.put(CodegenConstants.API_PACKAGE, apiPackage);
} }
if (additionalProperties.containsKey(COMPOSER_PROJECT_NAME)) { if (additionalProperties.containsKey(COMPOSER_PROJECT_NAME)) {
this.setComposerProjectName((String) additionalProperties.get(COMPOSER_PROJECT_NAME)); this.setComposerProjectName((String) additionalProperties.get(COMPOSER_PROJECT_NAME));
} else { } else {
additionalProperties.put(COMPOSER_PROJECT_NAME, composerProjectName); additionalProperties.put(COMPOSER_PROJECT_NAME, composerProjectName);
} }
if (additionalProperties.containsKey(COMPOSER_VENDOR_NAME)) { if (additionalProperties.containsKey(COMPOSER_VENDOR_NAME)) {
this.setComposerVendorName((String) additionalProperties.get(COMPOSER_VENDOR_NAME)); this.setComposerVendorName((String) additionalProperties.get(COMPOSER_VENDOR_NAME));
} else { } else {
additionalProperties.put(COMPOSER_VENDOR_NAME, composerVendorName); additionalProperties.put(COMPOSER_VENDOR_NAME, composerVendorName);
} }
if (additionalProperties.containsKey(CodegenConstants.ARTIFACT_VERSION)) { if (additionalProperties.containsKey(CodegenConstants.ARTIFACT_VERSION)) {
this.setArtifactVersion((String) additionalProperties.get(CodegenConstants.ARTIFACT_VERSION)); this.setArtifactVersion((String) additionalProperties.get(CodegenConstants.ARTIFACT_VERSION));
} else { } else {
@ -202,7 +214,7 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
if (additionalProperties.containsKey(VARIABLE_NAMING_CONVENTION)) { if (additionalProperties.containsKey(VARIABLE_NAMING_CONVENTION)) {
this.setParameterNamingConvention((String) additionalProperties.get(VARIABLE_NAMING_CONVENTION)); this.setParameterNamingConvention((String) additionalProperties.get(VARIABLE_NAMING_CONVENTION));
} }
additionalProperties.put("escapedInvokerPackage", invokerPackage.replace("\\", "\\\\")); additionalProperties.put("escapedInvokerPackage", invokerPackage.replace("\\", "\\\\"));
supportingFiles.add(new SupportingFile("configuration.mustache", toPackagePath(invokerPackage, srcBasePath), "Configuration.php")); supportingFiles.add(new SupportingFile("configuration.mustache", toPackagePath(invokerPackage, srcBasePath), "Configuration.php"));
@ -211,6 +223,8 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
supportingFiles.add(new SupportingFile("ObjectSerializer.mustache", toPackagePath(invokerPackage, srcBasePath), "ObjectSerializer.php")); supportingFiles.add(new SupportingFile("ObjectSerializer.mustache", toPackagePath(invokerPackage, srcBasePath), "ObjectSerializer.php"));
supportingFiles.add(new SupportingFile("composer.mustache", getPackagePath(), "composer.json")); supportingFiles.add(new SupportingFile("composer.mustache", getPackagePath(), "composer.json"));
supportingFiles.add(new SupportingFile("autoload.mustache", getPackagePath(), "autoload.php")); supportingFiles.add(new SupportingFile("autoload.mustache", getPackagePath(), "autoload.php"));
supportingFiles.add(new SupportingFile("README.mustache", getPackagePath(), "README.md"));
supportingFiles.add(new SupportingFile(".travis.yml", getPackagePath(), ".travis.yml"));
} }
@Override @Override
@ -223,10 +237,21 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
return (outputFolder + "/" + toPackagePath(apiPackage, srcBasePath)); return (outputFolder + "/" + toPackagePath(apiPackage, srcBasePath));
} }
@Override
public String modelFileFolder() { public String modelFileFolder() {
return (outputFolder + "/" + toPackagePath(modelPackage, srcBasePath)); return (outputFolder + "/" + toPackagePath(modelPackage, srcBasePath));
} }
@Override
public String apiTestFileFolder() {
return (outputFolder + "/" + toPackagePath(testPackage, srcBasePath));
}
@Override
public String modelTestFileFolder() {
return (outputFolder + "/" + toPackagePath(testPackage, srcBasePath));
}
@Override @Override
public String getTypeDeclaration(Property p) { public String getTypeDeclaration(Property p) {
if (p instanceof ArrayProperty) { if (p instanceof ArrayProperty) {
@ -276,7 +301,7 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
public void setInvokerPackage(String invokerPackage) { public void setInvokerPackage(String invokerPackage) {
this.invokerPackage = invokerPackage; this.invokerPackage = invokerPackage;
} }
public void setArtifactVersion(String artifactVersion) { public void setArtifactVersion(String artifactVersion) {
this.artifactVersion = artifactVersion; this.artifactVersion = artifactVersion;
} }
@ -288,7 +313,7 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
public void setSrcBasePath(String srcBasePath) { public void setSrcBasePath(String srcBasePath) {
this.srcBasePath = srcBasePath; this.srcBasePath = srcBasePath;
} }
public void setParameterNamingConvention(String variableNamingConvention) { public void setParameterNamingConvention(String variableNamingConvention) {
this.variableNamingConvention = variableNamingConvention; this.variableNamingConvention = variableNamingConvention;
} }
@ -296,7 +321,7 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
public void setComposerVendorName(String composerVendorName) { public void setComposerVendorName(String composerVendorName) {
this.composerVendorName = composerVendorName; this.composerVendorName = composerVendorName;
} }
public void setComposerProjectName(String composerProjectName) { public void setComposerProjectName(String composerProjectName) {
this.composerProjectName = composerProjectName; this.composerProjectName = composerProjectName;
} }
@ -304,7 +329,7 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override @Override
public String toVarName(String name) { public String toVarName(String name) {
// sanitize name // sanitize name
name = sanitizeName(name); name = sanitizeName(name); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
if ("camelCase".equals(variableNamingConvention)) { if ("camelCase".equals(variableNamingConvention)) {
// return the name in camelCase style // return the name in camelCase style
@ -334,16 +359,22 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override @Override
public String toModelName(String name) { public String toModelName(String name) {
// Note: backslash ("\\") is allowed for e.g. "\\DateTime" // Note: backslash ("\\") is allowed for e.g. "\\DateTime"
name = name.replaceAll("[^\\w\\\\]+", "_"); name = name.replaceAll("[^\\w\\\\]+", "_"); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
// remove dollar sign // remove dollar sign
name = name.replaceAll("$", ""); name = name.replaceAll("$", "");
// model name cannot use reserved keyword // model name cannot use reserved keyword
if (reservedWords.contains(name)) { if (isReservedWord(name)) {
escapeReservedWord(name); // e.g. return => _return LOGGER.warn(name + " (reserved word) cannot be used as model name. Renamed to " + camelize("object_" + name));
name = "object_" + name; // e.g. return => ObjectReturn (after camelize)
} }
// add prefix and/or suffic only if name does not start wth \ (e.g. \DateTime)
if (!name.matches("^\\\\.*")) {
name = modelNamePrefix + name + modelNameSuffix;
}
// camelize the model name // camelize the model name
// phone_number => PhoneNumber // phone_number => PhoneNumber
return camelize(name); return camelize(name);
@ -355,6 +386,12 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
return toModelName(name); return toModelName(name);
} }
@Override
public String toModelTestFilename(String name) {
// should be the same as the model name
return toModelName(name) + "Test";
}
@Override @Override
public String toOperationId(String operationId) { public String toOperationId(String operationId) {
// throw exception if method name is empty // throw exception if method name is empty
@ -363,8 +400,9 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
} }
// method name cannot use reserved keyword, e.g. return // method name cannot use reserved keyword, e.g. return
if (reservedWords.contains(operationId)) { if (isReservedWord(operationId)) {
throw new RuntimeException(operationId + " (reserved word) cannot be used as method name"); LOGGER.warn(operationId + " (reserved word) cannot be used as method name. Renamed to " + camelize(sanitizeName("call_" + operationId), true));
operationId = "call_" + operationId;
} }
return camelize(sanitizeName(operationId), true); return camelize(sanitizeName(operationId), true);

View File

@ -15,8 +15,8 @@ import java.util.HashSet;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig { public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig {
protected String packageName = null; protected String packageName;
protected String packageVersion = null; protected String packageVersion;
public PythonClientCodegen() { public PythonClientCodegen() {
super(); super();
@ -51,21 +51,29 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
typeMapping.put("DateTime", "datetime"); typeMapping.put("DateTime", "datetime");
typeMapping.put("object", "object"); typeMapping.put("object", "object");
typeMapping.put("file", "file"); typeMapping.put("file", "file");
//TODO binary should be mapped to byte array
// mapped to String as a workaround
typeMapping.put("binary", "str");
// from https://docs.python.org/release/2.5.4/ref/keywords.html // from https://docs.python.org/release/2.5.4/ref/keywords.html
reservedWords = new HashSet<String>( setReservedWordsLowerCase(
Arrays.asList( Arrays.asList(
"and", "del", "from", "not", "while", "as", "elif", "global", "or", "with", // local variable name used in API methods (endpoints)
"assert", "else", "if", "pass", "yield", "break", "except", "import", "all_params", "resource_path", "path_params", "query_params",
"print", "class", "exec", "in", "raise", "continue", "finally", "is", "header_params", "form_params", "local_var_files", "body_params", "auth_settings",
"return", "def", "for", "lambda", "try")); // python reserved words
"and", "del", "from", "not", "while", "as", "elif", "global", "or", "with",
"assert", "else", "if", "pass", "yield", "break", "except", "import",
"print", "class", "exec", "in", "raise", "continue", "finally", "is",
"return", "def", "for", "lambda", "try", "self"));
cliOptions.clear(); cliOptions.clear();
cliOptions.add(new CliOption(CodegenConstants.PACKAGE_NAME, "python package name (convention: snake_case).") cliOptions.add(new CliOption(CodegenConstants.PACKAGE_NAME, "python package name (convention: snake_case).")
.defaultValue("swagger_client")); .defaultValue("swagger_client"));
cliOptions.add(new CliOption(CodegenConstants.PACKAGE_VERSION, "python package version.") cliOptions.add(new CliOption(CodegenConstants.PACKAGE_VERSION, "python package version.")
.defaultValue("1.0.0")); .defaultValue("1.0.0"));
cliOptions.add(new CliOption(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG_DESC)); cliOptions.add(CliOption.newBoolean(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG,
CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG_DESC).defaultValue(Boolean.TRUE.toString()));
} }
@Override @Override
@ -108,14 +116,17 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
return str.replaceAll("\\.", "_"); return str.replaceAll("\\.", "_");
} }
@Override
public CodegenType getTag() { public CodegenType getTag() {
return CodegenType.CLIENT; return CodegenType.CLIENT;
} }
@Override
public String getName() { public String getName() {
return "python"; return "python";
} }
@Override
public String getHelp() { public String getHelp() {
return "Generates a Python client library."; return "Generates a Python client library.";
} }
@ -130,6 +141,7 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
return outputFolder + File.separatorChar + apiPackage().replace('.', File.separatorChar); return outputFolder + File.separatorChar + apiPackage().replace('.', File.separatorChar);
} }
@Override
public String modelFileFolder() { public String modelFileFolder() {
return outputFolder + File.separatorChar + modelPackage().replace('.', File.separatorChar); return outputFolder + File.separatorChar + modelPackage().replace('.', File.separatorChar);
} }
@ -167,7 +179,7 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
@Override @Override
public String toVarName(String name) { public String toVarName(String name) {
// sanitize name // sanitize name
name = sanitizeName(name); name = sanitizeName(name); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
// remove dollar sign // remove dollar sign
name = name.replaceAll("$", ""); name = name.replaceAll("$", "");
@ -185,7 +197,7 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
name = name.replaceAll("^_*", ""); name = name.replaceAll("^_*", "");
// for reserved word or word starting with number, append _ // for reserved word or word starting with number, append _
if (reservedWords.contains(name) || name.matches("^\\d.*")) { if (isReservedWord(name) || name.matches("^\\d.*")) {
name = escapeReservedWord(name); name = escapeReservedWord(name);
} }
@ -200,14 +212,15 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
@Override @Override
public String toModelName(String name) { public String toModelName(String name) {
name = sanitizeName(name); name = sanitizeName(modelNamePrefix + name + modelNameSuffix); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
// remove dollar sign // remove dollar sign
name = name.replaceAll("$", ""); name = name.replaceAll("$", "");
// model name cannot use reserved keyword, e.g. return // model name cannot use reserved keyword, e.g. return
if (reservedWords.contains(name)) { if (isReservedWord(name)) {
throw new RuntimeException(name + " (reserved word) cannot be used as a model name"); LOGGER.warn(name + " (reserved word) cannot be used as model name. Renamed to " + camelize("object_" + name));
name = "object_" + name; // e.g. return => ObjectReturn (after camelize)
} }
// camelize the model name // camelize the model name
@ -218,8 +231,17 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
@Override @Override
public String toModelFilename(String name) { public String toModelFilename(String name) {
// model name cannot use reserved keyword, e.g. return // model name cannot use reserved keyword, e.g. return
if (reservedWords.contains(name)) { if (isReservedWord(name)) {
throw new RuntimeException(name + " (reserved word) cannot be used as a model name"); LOGGER.warn(name + " (reserved word) cannot be used as model filename. Renamed to " + underscore(dropDots("object_" + name)));
name = "object_" + name; // e.g. return => ObjectReturn (after camelize)
}
if (!StringUtils.isEmpty(modelNamePrefix)) {
name = modelNamePrefix + "_" + name;
}
if (!StringUtils.isEmpty(modelNameSuffix)) {
name = name + "_" + modelNameSuffix;
} }
// underscore the model file name // underscore the model file name
@ -255,14 +277,15 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
@Override @Override
public String toOperationId(String operationId) { public String toOperationId(String operationId) {
// throw exception if method name is empty // throw exception if method name is empty (should not occur as an auto-generated method name will be used)
if (StringUtils.isEmpty(operationId)) { if (StringUtils.isEmpty(operationId)) {
throw new RuntimeException("Empty method name (operationId) not allowed"); throw new RuntimeException("Empty method name (operationId) not allowed");
} }
// method name cannot use reserved keyword, e.g. return // method name cannot use reserved keyword, e.g. return
if (reservedWords.contains(operationId)) { if (isReservedWord(operationId)) {
throw new RuntimeException(operationId + " (reserved word) cannot be used as method name"); LOGGER.warn(operationId + " (reserved word) cannot be used as method name. Renamed to " + underscore(sanitizeName("call_" + operationId)));
operationId = "call_" + operationId;
} }
return underscore(sanitizeName(operationId)); return underscore(sanitizeName(operationId));
@ -281,7 +304,11 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
* *
* (PEP 0008) Python packages should also have short, all-lowercase names, * (PEP 0008) Python packages should also have short, all-lowercase names,
* although the use of underscores is discouraged. * although the use of underscores is discouraged.
*
* @param packageName Package name
* @return Python package name that conforms to PEP 0008
*/ */
@SuppressWarnings("static-method")
public String generatePackageName(String packageName) { public String generatePackageName(String packageName) {
return underscore(packageName.replaceAll("[^\\w]+", "")); return underscore(packageName.replaceAll("[^\\w]+", ""));
} }

View File

@ -76,7 +76,7 @@ public class Qt5CPPGenerator extends DefaultCodegen implements CodegenConfig {
/** /**
* Reserved words. Override this with reserved words specific to your language * Reserved words. Override this with reserved words specific to your language
*/ */
reservedWords = new HashSet<String>( setReservedWordsLowerCase(
Arrays.asList( Arrays.asList(
"sample1", // replace with static values "sample1", // replace with static values
"sample2") "sample2")
@ -121,6 +121,9 @@ public class Qt5CPPGenerator extends DefaultCodegen implements CodegenConfig {
typeMapping.put("map", "QMap"); typeMapping.put("map", "QMap");
typeMapping.put("file", "SWGHttpRequestInputFileElement"); typeMapping.put("file", "SWGHttpRequestInputFileElement");
typeMapping.put("object", PREFIX + "Object"); typeMapping.put("object", PREFIX + "Object");
//TODO binary should be mapped to byte array
// mapped to String as a workaround
typeMapping.put("binary", "QString");
importMapping = new HashMap<String, String>(); importMapping = new HashMap<String, String>();
@ -140,6 +143,7 @@ public class Qt5CPPGenerator extends DefaultCodegen implements CodegenConfig {
* @return the CodegenType for this generator * @return the CodegenType for this generator
* @see io.swagger.codegen.CodegenType * @see io.swagger.codegen.CodegenType
*/ */
@Override
public CodegenType getTag() { public CodegenType getTag() {
return CodegenType.CLIENT; return CodegenType.CLIENT;
} }
@ -150,6 +154,7 @@ public class Qt5CPPGenerator extends DefaultCodegen implements CodegenConfig {
* *
* @return the friendly name for the generator * @return the friendly name for the generator
*/ */
@Override
public String getName() { public String getName() {
return "qt5cpp"; return "qt5cpp";
} }
@ -160,6 +165,7 @@ public class Qt5CPPGenerator extends DefaultCodegen implements CodegenConfig {
* *
* @return A string value for the help message * @return A string value for the help message
*/ */
@Override
public String getHelp() { public String getHelp() {
return "Generates a qt5 C++ client library."; return "Generates a qt5 C++ client library.";
} }
@ -189,6 +195,7 @@ public class Qt5CPPGenerator extends DefaultCodegen implements CodegenConfig {
* Location to write model files. You can use the modelPackage() as defined when the class is * Location to write model files. You can use the modelPackage() as defined when the class is
* instantiated * instantiated
*/ */
@Override
public String modelFileFolder() { public String modelFileFolder() {
return outputFolder + "/" + sourceFolder + "/" + modelPackage().replace('.', File.separatorChar); return outputFolder + "/" + sourceFolder + "/" + modelPackage().replace('.', File.separatorChar);
} }

View File

@ -14,15 +14,34 @@ import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig { public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(RubyClientCodegen.class);
public static final String GEM_NAME = "gemName"; public static final String GEM_NAME = "gemName";
public static final String MODULE_NAME = "moduleName"; public static final String MODULE_NAME = "moduleName";
public static final String GEM_VERSION = "gemVersion"; public static final String GEM_VERSION = "gemVersion";
protected String gemName = null; public static final String GEM_LICENSE = "gemLicense";
protected String moduleName = null; public static final String GEM_HOMEPAGE = "gemHomepage";
public static final String GEM_SUMMARY = "gemSummary";
public static final String GEM_DESCRIPTION = "gemDescription";
public static final String GEM_AUTHOR = "gemAuthor";
public static final String GEM_AUTHOR_EMAIL = "gemAuthorEmail";
protected String gemName;
protected String moduleName;
protected String gemVersion = "1.0.0"; protected String gemVersion = "1.0.0";
protected String specFolder = "spec";
protected String libFolder = "lib"; protected String libFolder = "lib";
protected String gemLicense = "Apache-2.0";
protected String gemHomepage = "http://swagger.io";
protected String gemSummary = "A ruby wrapper for the swagger APIs";
protected String gemDescription = "This gem maps to a swagger API";
protected String gemAuthor = "";
protected String gemAuthorEmail = "";
protected static int emptyMethodNameCounter = 0;
public RubyClientCodegen() { public RubyClientCodegen() {
super(); super();
@ -33,16 +52,23 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
apiTemplateFiles.put("api.mustache", ".rb"); apiTemplateFiles.put("api.mustache", ".rb");
embeddedTemplateDir = templateDir = "ruby"; embeddedTemplateDir = templateDir = "ruby";
modelTestTemplateFiles.put("model_test.mustache", ".rb");
apiTestTemplateFiles.put("api_test.mustache", ".rb");
typeMapping.clear(); typeMapping.clear();
languageSpecificPrimitives.clear(); languageSpecificPrimitives.clear();
reservedWords = new HashSet<String>( setReservedWordsLowerCase(
Arrays.asList( Arrays.asList(
"__FILE__", "and", "def", "end", "in", "or", "self", "unless", "__LINE__", // local variable names used in API methods (endpoints)
"begin", "defined?", "ensure", "module", "redo", "super", "until", "BEGIN", "local_var_path", "query_params", "header_params", "_header_accept", "_header_accept_result",
"break", "do", "false", "next", "rescue", "then", "when", "END", "case", "_header_content_type", "form_params", "post_body", "auth_names",
"else", "for", "nil", "retry", "true", "while", "alias", "class", "elsif", // ruby reserved keywords
"if", "not", "return", "undef", "yield") "__FILE__", "and", "def", "end", "in", "or", "self", "unless", "__LINE__",
"begin", "defined?", "ensure", "module", "redo", "super", "until", "BEGIN",
"break", "do", "false", "next", "rescue", "then", "when", "END", "case",
"else", "for", "nil", "retry", "true", "while", "alias", "class", "elsif",
"if", "not", "return", "undef", "yield")
); );
languageSpecificPrimitives.add("int"); languageSpecificPrimitives.add("int");
@ -68,6 +94,7 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
typeMapping.put("map", "Hash"); typeMapping.put("map", "Hash");
typeMapping.put("object", "Object"); typeMapping.put("object", "Object");
typeMapping.put("file", "File"); typeMapping.put("file", "File");
typeMapping.put("binary", "String");
// remove modelPackage and apiPackage added by default // remove modelPackage and apiPackage added by default
Iterator<CliOption> itr = cliOptions.iterator(); Iterator<CliOption> itr = cliOptions.iterator();
@ -83,6 +110,23 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
cliOptions.add(new CliOption(MODULE_NAME, "top module name (convention: CamelCase, usually corresponding" + cliOptions.add(new CliOption(MODULE_NAME, "top module name (convention: CamelCase, usually corresponding" +
" to gem name).").defaultValue("SwaggerClient")); " to gem name).").defaultValue("SwaggerClient"));
cliOptions.add(new CliOption(GEM_VERSION, "gem version.").defaultValue("1.0.0")); cliOptions.add(new CliOption(GEM_VERSION, "gem version.").defaultValue("1.0.0"));
cliOptions.add(new CliOption(GEM_LICENSE, "gem license. ").
defaultValue("Apache-2.0"));
cliOptions.add(new CliOption(GEM_HOMEPAGE, "gem homepage. ").
defaultValue("http://swagger.io"));
cliOptions.add(new CliOption(GEM_SUMMARY, "gem summary. ").
defaultValue("A ruby wrapper for the swagger APIs"));
cliOptions.add(new CliOption(GEM_DESCRIPTION, "gem description. ").
defaultValue("This gem maps to a swagger API"));
cliOptions.add(new CliOption(GEM_AUTHOR, "gem author (only one is supported)."));
cliOptions.add(new CliOption(GEM_AUTHOR_EMAIL, "gem author email (only one is supported)."));
} }
@Override @Override
@ -110,11 +154,36 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
if (additionalProperties.containsKey(GEM_VERSION)) { if (additionalProperties.containsKey(GEM_VERSION)) {
setGemVersion((String) additionalProperties.get(GEM_VERSION)); setGemVersion((String) additionalProperties.get(GEM_VERSION));
} else { }else {
// not set, pass the default value to template // not set, pass the default value to template
additionalProperties.put(GEM_VERSION, gemVersion); additionalProperties.put(GEM_VERSION, gemVersion);
} }
if (additionalProperties.containsKey(GEM_LICENSE)) {
setGemLicense((String) additionalProperties.get(GEM_LICENSE));
}
if (additionalProperties.containsKey(GEM_HOMEPAGE)) {
setGemHomepage((String) additionalProperties.get(GEM_HOMEPAGE));
}
if (additionalProperties.containsKey(GEM_SUMMARY)) {
setGemSummary((String) additionalProperties.get(GEM_SUMMARY));
}
if (additionalProperties.containsKey(GEM_DESCRIPTION)) {
setGemDescription((String) additionalProperties.get(GEM_DESCRIPTION));
}
if (additionalProperties.containsKey(GEM_AUTHOR)) {
setGemAuthor((String) additionalProperties.get(GEM_AUTHOR));
}
if (additionalProperties.containsKey(GEM_AUTHOR_EMAIL)) {
setGemAuthorEmail((String) additionalProperties.get(GEM_AUTHOR_EMAIL));
}
// use constant model/api package (folder path) // use constant model/api package (folder path)
setModelPackage("models"); setModelPackage("models");
setApiPackage("api"); setApiPackage("api");
@ -126,32 +195,42 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
supportingFiles.add(new SupportingFile("api_error.mustache", gemFolder, "api_error.rb")); supportingFiles.add(new SupportingFile("api_error.mustache", gemFolder, "api_error.rb"));
supportingFiles.add(new SupportingFile("configuration.mustache", gemFolder, "configuration.rb")); supportingFiles.add(new SupportingFile("configuration.mustache", gemFolder, "configuration.rb"));
supportingFiles.add(new SupportingFile("version.mustache", gemFolder, "version.rb")); supportingFiles.add(new SupportingFile("version.mustache", gemFolder, "version.rb"));
String modelFolder = gemFolder + File.separator + modelPackage.replace("/", File.separator);
supportingFiles.add(new SupportingFile("base_object.mustache", modelFolder, "base_object.rb"));
} }
@Override
public CodegenType getTag() { public CodegenType getTag() {
return CodegenType.CLIENT; return CodegenType.CLIENT;
} }
@Override
public String getName() { public String getName() {
return "ruby"; return "ruby";
} }
@Override
public String getHelp() { public String getHelp() {
return "Generates a Ruby client library."; return "Generates a Ruby client library.";
} }
/** /**
* Generate Ruby module name from the gem name, e.g. use "SwaggerClient" for "swagger_client". * Generate Ruby module name from the gem name, e.g. use "SwaggerClient" for "swagger_client".
*
* @param gemName Ruby gem name
* @return Ruby module naame
*/ */
@SuppressWarnings("static-method")
public String generateModuleName(String gemName) { public String generateModuleName(String gemName) {
return camelize(gemName.replaceAll("[^\\w]+", "_")); return camelize(gemName.replaceAll("[^\\w]+", "_"));
} }
/** /**
* Generate Ruby gem name from the module name, e.g. use "swagger_client" for "SwaggerClient". * Generate Ruby gem name from the module name, e.g. use "swagger_client" for "SwaggerClient".
*
* @param moduleName Ruby module naame
* @return Ruby gem name
*/ */
@SuppressWarnings("static-method")
public String generateGemName(String moduleName) { public String generateGemName(String moduleName) {
return underscore(moduleName.replaceAll("[^\\w]+", "")); return underscore(moduleName.replaceAll("[^\\w]+", ""));
} }
@ -166,10 +245,21 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
return outputFolder + File.separator + libFolder + File.separator + gemName + File.separator + apiPackage.replace("/", File.separator); return outputFolder + File.separator + libFolder + File.separator + gemName + File.separator + apiPackage.replace("/", File.separator);
} }
@Override
public String modelFileFolder() { public String modelFileFolder() {
return outputFolder + File.separator + libFolder + File.separator + gemName + File.separator + modelPackage.replace("/", File.separator); return outputFolder + File.separator + libFolder + File.separator + gemName + File.separator + modelPackage.replace("/", File.separator);
} }
@Override
public String apiTestFileFolder() {
return outputFolder + File.separator + specFolder + File.separator + apiPackage.replace("/", File.separator);
}
@Override
public String modelTestFileFolder() {
return outputFolder + File.separator + specFolder + File.separator + modelPackage.replace("/", File.separator);
}
@Override @Override
public String getTypeDeclaration(Property p) { public String getTypeDeclaration(Property p) {
if (p instanceof ArrayProperty) { if (p instanceof ArrayProperty) {
@ -236,13 +326,13 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
if (type == null) { if (type == null) {
return null; return null;
} }
return type; return toModelName(type);
} }
@Override @Override
public String toVarName(String name) { public String toVarName(String name) {
// sanitize name // sanitize name
name = sanitizeName(name); name = sanitizeName(name); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
// if it's all uppper case, convert to lower case // if it's all uppper case, convert to lower case
if (name.matches("^[A-Z_]*$")) { if (name.matches("^[A-Z_]*$")) {
@ -254,7 +344,7 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
name = underscore(name); name = underscore(name);
// for reserved word or word starting with number, append _ // for reserved word or word starting with number, append _
if (reservedWords.contains(name) || name.matches("^\\d.*")) { if (isReservedWord(name) || name.matches("^\\d.*")) {
name = escapeReservedWord(name); name = escapeReservedWord(name);
} }
@ -269,11 +359,13 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override @Override
public String toModelName(String name) { public String toModelName(String name) {
name = sanitizeName(name); name = sanitizeName(name); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
// model name cannot use reserved keyword, e.g. return // model name cannot use reserved keyword, e.g. return
if (reservedWords.contains(name)) { if (isReservedWord(name)) {
throw new RuntimeException(name + " (reserved word) cannot be used as a model name"); String modelName = camelize("object_" + name);
LOGGER.warn(name + " (reserved word) cannot be used as model name. Renamed to " + modelName);
return modelName;
} }
// camelize the model name // camelize the model name
@ -284,8 +376,10 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override @Override
public String toModelFilename(String name) { public String toModelFilename(String name) {
// model name cannot use reserved keyword, e.g. return // model name cannot use reserved keyword, e.g. return
if (reservedWords.contains(name)) { if (isReservedWord(name)) {
throw new RuntimeException(name + " (reserved word) cannot be used as a model name"); String filename = underscore("object_" + name);
LOGGER.warn(name + " (reserved word) cannot be used as model filename. Renamed to " + filename);
return filename;
} }
// underscore the model file name // underscore the model file name
@ -296,12 +390,22 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override @Override
public String toApiFilename(String name) { public String toApiFilename(String name) {
// replace - with _ e.g. created-at => created_at // replace - with _ e.g. created-at => created_at
name = name.replaceAll("-", "_"); name = name.replaceAll("-", "_"); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
// e.g. PhoneNumberApi.rb => phone_number_api.rb // e.g. PhoneNumberApi.rb => phone_number_api.rb
return underscore(name) + "_api"; return underscore(name) + "_api";
} }
@Override
public String toApiTestFilename(String name) {
return toApiName(name) + "_spec";
}
@Override
public String toModelTestFilename(String name) {
return toModelName(name) + "_spec";
}
@Override @Override
public String toApiName(String name) { public String toApiName(String name) {
if (name.length() == 0) { if (name.length() == 0) {
@ -313,14 +417,18 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override @Override
public String toOperationId(String operationId) { public String toOperationId(String operationId) {
// throw exception if method name is empty // rename to empty_method_name_1 (e.g.) if method name is empty
if (StringUtils.isEmpty(operationId)) { if (StringUtils.isEmpty(operationId)) {
throw new RuntimeException("Empty method name (operationId) not allowed"); operationId = underscore("empty_method_name_" + emptyMethodNameCounter++);
LOGGER.warn("Empty method name (operationId) found. Renamed to " + operationId);
return operationId;
} }
// method name cannot use reserved keyword, e.g. return // method name cannot use reserved keyword, e.g. return
if (reservedWords.contains(operationId)) { if (isReservedWord(operationId)) {
throw new RuntimeException(operationId + " (reserved word) cannot be used as method name"); String newOperationId = underscore("call_" + operationId);
LOGGER.warn(operationId + " (reserved word) cannot be used as method name. Renamed to " + newOperationId);
return newOperationId;
} }
return underscore(sanitizeName(operationId)); return underscore(sanitizeName(operationId));
@ -347,4 +455,28 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
public void setGemVersion(String gemVersion) { public void setGemVersion(String gemVersion) {
this.gemVersion = gemVersion; this.gemVersion = gemVersion;
} }
public void setGemDescription(String gemDescription) {
this.gemDescription = gemDescription;
}
public void setGemSummary(String gemSummary) {
this.gemSummary = gemSummary;
}
public void setGemLicense(String gemLicense) {
this.gemLicense = gemLicense;
}
public void setGemHomepage(String gemHomepage) {
this.gemHomepage = gemHomepage;
}
public void setGemAuthor(String gemAuthor) {
this.gemAuthor = gemAuthor;
}
public void setGemAuthorEmail(String gemAuthorEmail) {
this.gemAuthorEmail = gemAuthorEmail;
}
} }

View File

@ -35,7 +35,7 @@ public class ScalaClientCodegen extends DefaultCodegen implements CodegenConfig
protected String artifactVersion = "1.0.0"; protected String artifactVersion = "1.0.0";
protected String sourceFolder = "src/main/scala"; protected String sourceFolder = "src/main/scala";
protected String authScheme = ""; protected String authScheme = "";
protected boolean authPreemptive = false; protected boolean authPreemptive;
protected boolean asyncHttpClient = !authScheme.isEmpty(); protected boolean asyncHttpClient = !authScheme.isEmpty();
public ScalaClientCodegen() { public ScalaClientCodegen() {
@ -47,13 +47,18 @@ public class ScalaClientCodegen extends DefaultCodegen implements CodegenConfig
apiPackage = "io.swagger.client.api"; apiPackage = "io.swagger.client.api";
modelPackage = "io.swagger.client.model"; modelPackage = "io.swagger.client.model";
reservedWords = new HashSet<String>( setReservedWordsLowerCase(
Arrays.asList( Arrays.asList(
"abstract", "case", "catch", "class", "def", "do", "else", "extends", // local variable names used in API methods (endpoints)
"false", "final", "finally", "for", "forSome", "if", "implicit", "path", "contentTypes", "contentType", "queryParams", "headerParams",
"import", "lazy", "match", "new", "null", "object", "override", "package", "formParams", "postBody", "mp", "basePath", "apiInvoker",
"private", "protected", "return", "sealed", "super", "this", "throw",
"trait", "try", "true", "type", "val", "var", "while", "with", "yield") // scala reserved words
"abstract", "case", "catch", "class", "def", "do", "else", "extends",
"false", "final", "finally", "for", "forSome", "if", "implicit",
"import", "lazy", "match", "new", "null", "object", "override", "package",
"private", "protected", "return", "sealed", "super", "this", "throw",
"trait", "try", "true", "type", "val", "var", "while", "with", "yield")
); );
additionalProperties.put(CodegenConstants.INVOKER_PACKAGE, invokerPackage); additionalProperties.put(CodegenConstants.INVOKER_PACKAGE, invokerPackage);
@ -91,6 +96,9 @@ public class ScalaClientCodegen extends DefaultCodegen implements CodegenConfig
typeMapping.put("double", "Double"); typeMapping.put("double", "Double");
typeMapping.put("object", "Any"); typeMapping.put("object", "Any");
typeMapping.put("file", "File"); typeMapping.put("file", "File");
//TODO binary should be mapped to byte array
// mapped to String as a workaround
typeMapping.put("binary", "String");
languageSpecificPrimitives = new HashSet<String>( languageSpecificPrimitives = new HashSet<String>(
Arrays.asList( Arrays.asList(
@ -112,14 +120,17 @@ public class ScalaClientCodegen extends DefaultCodegen implements CodegenConfig
cliOptions.add(new CliOption(CodegenConstants.API_PACKAGE, CodegenConstants.API_PACKAGE_DESC)); cliOptions.add(new CliOption(CodegenConstants.API_PACKAGE, CodegenConstants.API_PACKAGE_DESC));
} }
@Override
public CodegenType getTag() { public CodegenType getTag() {
return CodegenType.CLIENT; return CodegenType.CLIENT;
} }
@Override
public String getName() { public String getName() {
return "scala"; return "scala";
} }
@Override
public String getHelp() { public String getHelp() {
return "Generates a Scala client library."; return "Generates a Scala client library.";
} }
@ -134,6 +145,7 @@ public class ScalaClientCodegen extends DefaultCodegen implements CodegenConfig
return outputFolder + "/" + sourceFolder + "/" + apiPackage().replace('.', File.separatorChar); return outputFolder + "/" + sourceFolder + "/" + apiPackage().replace('.', File.separatorChar);
} }
@Override
public String modelFileFolder() { public String modelFileFolder() {
return outputFolder + "/" + sourceFolder + "/" + modelPackage().replace('.', File.separatorChar); return outputFolder + "/" + sourceFolder + "/" + modelPackage().replace('.', File.separatorChar);
} }
@ -183,6 +195,7 @@ public class ScalaClientCodegen extends DefaultCodegen implements CodegenConfig
} }
} }
@Override
public String toDefaultValue(Property p) { public String toDefaultValue(Property p) {
if (p instanceof StringProperty) { if (p instanceof StringProperty) {
return "null"; return "null";
@ -222,7 +235,7 @@ public class ScalaClientCodegen extends DefaultCodegen implements CodegenConfig
} }
// method name cannot use reserved keyword, e.g. return // method name cannot use reserved keyword, e.g. return
if (reservedWords.contains(operationId)) { if (isReservedWord(operationId)) {
throw new RuntimeException(operationId + " (reserved word) cannot be used as method name"); throw new RuntimeException(operationId + " (reserved word) cannot be used as method name");
} }

View File

@ -34,7 +34,7 @@ public class ScalatraServerCodegen extends DefaultCodegen implements CodegenConf
apiPackage = "com.wordnik.client.api"; apiPackage = "com.wordnik.client.api";
modelPackage = "com.wordnik.client.model"; modelPackage = "com.wordnik.client.model";
reservedWords = new HashSet<String>( setReservedWordsLowerCase(
Arrays.asList( Arrays.asList(
"abstract", "continue", "for", "new", "switch", "assert", "abstract", "continue", "for", "new", "switch", "assert",
"default", "if", "package", "synchronized", "boolean", "do", "goto", "private", "default", "if", "package", "synchronized", "boolean", "do", "goto", "private",
@ -67,6 +67,9 @@ public class ScalatraServerCodegen extends DefaultCodegen implements CodegenConf
typeMapping.put("integer", "Int"); typeMapping.put("integer", "Int");
typeMapping.put("long", "Long"); typeMapping.put("long", "Long");
//TODO binary should be mapped to byte array
// mapped to String as a workaround
typeMapping.put("binary", "String");
additionalProperties.put("appName", "Swagger Sample"); additionalProperties.put("appName", "Swagger Sample");
additionalProperties.put("appName", "Swagger Sample"); additionalProperties.put("appName", "Swagger Sample");
@ -123,14 +126,17 @@ public class ScalatraServerCodegen extends DefaultCodegen implements CodegenConf
cliOptions.add(new CliOption(CodegenConstants.API_PACKAGE, CodegenConstants.API_PACKAGE_DESC)); cliOptions.add(new CliOption(CodegenConstants.API_PACKAGE, CodegenConstants.API_PACKAGE_DESC));
} }
@Override
public CodegenType getTag() { public CodegenType getTag() {
return CodegenType.SERVER; return CodegenType.SERVER;
} }
@Override
public String getName() { public String getName() {
return "scalatra"; return "scalatra";
} }
@Override
public String getHelp() { public String getHelp() {
return "Generates a Scala server application with Scalatra."; return "Generates a Scala server application with Scalatra.";
} }
@ -145,6 +151,7 @@ public class ScalatraServerCodegen extends DefaultCodegen implements CodegenConf
return outputFolder + "/" + sourceFolder + "/" + apiPackage().replace('.', File.separatorChar); return outputFolder + "/" + sourceFolder + "/" + apiPackage().replace('.', File.separatorChar);
} }
@Override
public String modelFileFolder() { public String modelFileFolder() {
return outputFolder + "/" + sourceFolder + "/" + modelPackage().replace('.', File.separatorChar); return outputFolder + "/" + sourceFolder + "/" + modelPackage().replace('.', File.separatorChar);
} }
@ -189,4 +196,4 @@ public class ScalatraServerCodegen extends DefaultCodegen implements CodegenConf
} }
return toModelName(type); return toModelName(type);
} }
} }

View File

@ -37,7 +37,7 @@ public class SilexServerCodegen extends DefaultCodegen implements CodegenConfig
embeddedTemplateDir = templateDir = "silex"; embeddedTemplateDir = templateDir = "silex";
reservedWords = new HashSet<String>( setReservedWordsLowerCase(
Arrays.asList( Arrays.asList(
"__halt_compiler", "abstract", "and", "array", "as", "break", "callable", "case", "catch", "class", "clone", "const", "continue", "declare", "default", "die", "do", "echo", "else", "elseif", "empty", "enddeclare", "endfor", "endforeach", "endif", "endswitch", "endwhile", "eval", "exit", "extends", "final", "for", "foreach", "function", "global", "goto", "if", "implements", "include", "include_once", "instanceof", "insteadof", "interface", "isset", "list", "namespace", "new", "or", "print", "private", "protected", "public", "require", "require_once", "return", "static", "switch", "throw", "trait", "try", "unset", "use", "var", "while", "xor") "__halt_compiler", "abstract", "and", "array", "as", "break", "callable", "case", "catch", "class", "clone", "const", "continue", "declare", "default", "die", "do", "echo", "else", "elseif", "empty", "enddeclare", "endfor", "endforeach", "endif", "endswitch", "endwhile", "eval", "exit", "extends", "final", "for", "foreach", "function", "global", "goto", "if", "implements", "include", "include_once", "instanceof", "insteadof", "interface", "isset", "list", "namespace", "new", "or", "print", "private", "protected", "public", "require", "require_once", "return", "static", "switch", "throw", "trait", "try", "unset", "use", "var", "while", "xor")
); );
@ -65,7 +65,7 @@ public class SilexServerCodegen extends DefaultCodegen implements CodegenConfig
instantiationTypes.put("array", "array"); instantiationTypes.put("array", "array");
instantiationTypes.put("map", "map"); instantiationTypes.put("map", "map");
// ref: https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md#data-types // ref: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#data-types
typeMapping = new HashMap<String, String>(); typeMapping = new HashMap<String, String>();
typeMapping.put("integer", "int"); typeMapping.put("integer", "int");
typeMapping.put("long", "int"); typeMapping.put("long", "int");
@ -81,6 +81,9 @@ public class SilexServerCodegen extends DefaultCodegen implements CodegenConfig
typeMapping.put("array", "array"); typeMapping.put("array", "array");
typeMapping.put("list", "array"); typeMapping.put("list", "array");
typeMapping.put("object", "object"); typeMapping.put("object", "object");
//TODO binary should be mapped to byte array
// mapped to String as a workaround
typeMapping.put("binary", "string");
supportingFiles.add(new SupportingFile("README.mustache", packagePath.replace('/', File.separatorChar), "README.md")); supportingFiles.add(new SupportingFile("README.mustache", packagePath.replace('/', File.separatorChar), "README.md"));
supportingFiles.add(new SupportingFile("composer.json", packagePath.replace('/', File.separatorChar), "composer.json")); supportingFiles.add(new SupportingFile("composer.json", packagePath.replace('/', File.separatorChar), "composer.json"));
@ -88,14 +91,17 @@ public class SilexServerCodegen extends DefaultCodegen implements CodegenConfig
supportingFiles.add(new SupportingFile(".htaccess", packagePath.replace('/', File.separatorChar), ".htaccess")); supportingFiles.add(new SupportingFile(".htaccess", packagePath.replace('/', File.separatorChar), ".htaccess"));
} }
@Override
public CodegenType getTag() { public CodegenType getTag() {
return CodegenType.SERVER; return CodegenType.SERVER;
} }
@Override
public String getName() { public String getName() {
return "silex-PHP"; return "silex-PHP";
} }
@Override
public String getHelp() { public String getHelp() {
return "Generates a Silex server library."; return "Generates a Silex server library.";
} }
@ -110,6 +116,7 @@ public class SilexServerCodegen extends DefaultCodegen implements CodegenConfig
return (outputFolder + "/" + apiPackage()).replace('/', File.separatorChar); return (outputFolder + "/" + apiPackage()).replace('/', File.separatorChar);
} }
@Override
public String modelFileFolder() { public String modelFileFolder() {
return (outputFolder + "/" + modelPackage()).replace('/', File.separatorChar); return (outputFolder + "/" + modelPackage()).replace('/', File.separatorChar);
} }
@ -148,6 +155,7 @@ public class SilexServerCodegen extends DefaultCodegen implements CodegenConfig
return toModelName(type); return toModelName(type);
} }
@Override
public String toDefaultValue(Property p) { public String toDefaultValue(Property p) {
return "null"; return "null";
} }
@ -157,7 +165,7 @@ public class SilexServerCodegen extends DefaultCodegen implements CodegenConfig
public String toVarName(String name) { public String toVarName(String name) {
// return the name in underscore style // return the name in underscore style
// PhoneNumber => phone_number // PhoneNumber => phone_number
name = underscore(name); name = underscore(name); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
// parameter name starting with number won't compile // parameter name starting with number won't compile
// need to escape it by appending _ at the beginning // need to escape it by appending _ at the beginning
@ -177,7 +185,7 @@ public class SilexServerCodegen extends DefaultCodegen implements CodegenConfig
@Override @Override
public String toModelName(String name) { public String toModelName(String name) {
// model name cannot use reserved keyword // model name cannot use reserved keyword
if (reservedWords.contains(name)) { if (isReservedWord(name)) {
escapeReservedWord(name); // e.g. return => _return escapeReservedWord(name); // e.g. return => _return
} }

View File

@ -2,7 +2,6 @@ package io.swagger.codegen.languages;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import io.swagger.codegen.CliOption;
import io.swagger.codegen.CodegenConfig; import io.swagger.codegen.CodegenConfig;
import io.swagger.codegen.CodegenType; import io.swagger.codegen.CodegenType;
import io.swagger.codegen.DefaultCodegen; import io.swagger.codegen.DefaultCodegen;
@ -19,10 +18,15 @@ import java.util.HashSet;
import java.util.Map; import java.util.Map;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SinatraServerCodegen extends DefaultCodegen implements CodegenConfig { public class SinatraServerCodegen extends DefaultCodegen implements CodegenConfig {
protected String gemName = null;
protected String moduleName = null; private static final Logger LOGGER = LoggerFactory.getLogger(SinatraServerCodegen.class);
protected String gemName;
protected String moduleName;
protected String gemVersion = "1.0.0"; protected String gemVersion = "1.0.0";
protected String libFolder = "lib"; protected String libFolder = "lib";
@ -39,7 +43,7 @@ public class SinatraServerCodegen extends DefaultCodegen implements CodegenConfi
typeMapping.clear(); typeMapping.clear();
languageSpecificPrimitives.clear(); languageSpecificPrimitives.clear();
reservedWords = new HashSet<String>( setReservedWordsLowerCase(
Arrays.asList( Arrays.asList(
"__FILE__", "and", "def", "end", "in", "or", "self", "unless", "__LINE__", "__FILE__", "and", "def", "end", "in", "or", "self", "unless", "__LINE__",
"begin", "defined?", "ensure", "module", "redo", "super", "until", "BEGIN", "begin", "defined?", "ensure", "module", "redo", "super", "until", "BEGIN",
@ -60,6 +64,9 @@ public class SinatraServerCodegen extends DefaultCodegen implements CodegenConfi
typeMapping.put("String", "string"); typeMapping.put("String", "string");
typeMapping.put("List", "array"); typeMapping.put("List", "array");
typeMapping.put("map", "map"); typeMapping.put("map", "map");
//TODO binary should be mapped to byte array
// mapped to String as a workaround
typeMapping.put("binary", "string");
// remove modelPackage and apiPackage added by default // remove modelPackage and apiPackage added by default
cliOptions.clear(); cliOptions.clear();
@ -81,14 +88,17 @@ public class SinatraServerCodegen extends DefaultCodegen implements CodegenConfi
supportingFiles.add(new SupportingFile("swagger.mustache","","swagger.yaml")); supportingFiles.add(new SupportingFile("swagger.mustache","","swagger.yaml"));
} }
@Override
public CodegenType getTag() { public CodegenType getTag() {
return CodegenType.SERVER; return CodegenType.SERVER;
} }
@Override
public String getName() { public String getName() {
return "sinatra"; return "sinatra";
} }
@Override
public String getHelp() { public String getHelp() {
return "Generates a Sinatra server library."; return "Generates a Sinatra server library.";
} }
@ -135,6 +145,7 @@ public class SinatraServerCodegen extends DefaultCodegen implements CodegenConfi
return type; return type;
} }
@Override
public String toDefaultValue(Property p) { public String toDefaultValue(Property p) {
return "null"; return "null";
} }
@ -142,7 +153,7 @@ public class SinatraServerCodegen extends DefaultCodegen implements CodegenConfi
@Override @Override
public String toVarName(String name) { public String toVarName(String name) {
// replace - with _ e.g. created-at => created_at // replace - with _ e.g. created-at => created_at
name = name.replaceAll("-", "_"); name = name.replaceAll("-", "_"); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
// if it's all uppper case, convert to lower case // if it's all uppper case, convert to lower case
if (name.matches("^[A-Z_]*$")) { if (name.matches("^[A-Z_]*$")) {
@ -154,7 +165,7 @@ public class SinatraServerCodegen extends DefaultCodegen implements CodegenConfi
name = underscore(name); name = underscore(name);
// for reserved word or word starting with number, append _ // for reserved word or word starting with number, append _
if (reservedWords.contains(name) || name.matches("^\\d.*")) { if (isReservedWord(name) || name.matches("^\\d.*")) {
name = escapeReservedWord(name); name = escapeReservedWord(name);
} }
@ -170,7 +181,7 @@ public class SinatraServerCodegen extends DefaultCodegen implements CodegenConfi
@Override @Override
public String toModelName(String name) { public String toModelName(String name) {
// model name cannot use reserved keyword, e.g. return // model name cannot use reserved keyword, e.g. return
if (reservedWords.contains(name)) { if (isReservedWord(name)) {
throw new RuntimeException(name + " (reserved word) cannot be used as a model name"); throw new RuntimeException(name + " (reserved word) cannot be used as a model name");
} }
@ -182,7 +193,7 @@ public class SinatraServerCodegen extends DefaultCodegen implements CodegenConfi
@Override @Override
public String toModelFilename(String name) { public String toModelFilename(String name) {
// model name cannot use reserved keyword, e.g. return // model name cannot use reserved keyword, e.g. return
if (reservedWords.contains(name)) { if (isReservedWord(name)) {
throw new RuntimeException(name + " (reserved word) cannot be used as a model name"); throw new RuntimeException(name + " (reserved word) cannot be used as a model name");
} }
@ -194,7 +205,7 @@ public class SinatraServerCodegen extends DefaultCodegen implements CodegenConfi
@Override @Override
public String toApiFilename(String name) { public String toApiFilename(String name) {
// replace - with _ e.g. created-at => created_at // replace - with _ e.g. created-at => created_at
name = name.replaceAll("-", "_"); name = name.replaceAll("-", "_"); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
// e.g. PhoneNumberApi.rb => phone_number_api.rb // e.g. PhoneNumberApi.rb => phone_number_api.rb
return underscore(name) + "_api"; return underscore(name) + "_api";
@ -212,7 +223,7 @@ public class SinatraServerCodegen extends DefaultCodegen implements CodegenConfi
@Override @Override
public String toOperationId(String operationId) { public String toOperationId(String operationId) {
// method name cannot use reserved keyword, e.g. return // method name cannot use reserved keyword, e.g. return
if (reservedWords.contains(operationId)) { if (isReservedWord(operationId)) {
throw new RuntimeException(operationId + " (reserved word) cannot be used as method name"); throw new RuntimeException(operationId + " (reserved word) cannot be used as method name");
} }
@ -226,7 +237,7 @@ public class SinatraServerCodegen extends DefaultCodegen implements CodegenConfi
try { try {
objs.put("swagger-yaml", Yaml.mapper().writeValueAsString(swagger)); objs.put("swagger-yaml", Yaml.mapper().writeValueAsString(swagger));
} catch (JsonProcessingException e) { } catch (JsonProcessingException e) {
e.printStackTrace(); LOGGER.error(e.getMessage(), e);
} }
} }
return super.postProcessSupportingFileData(objs); return super.postProcessSupportingFileData(objs);

View File

@ -39,7 +39,7 @@ public class SlimFrameworkServerCodegen extends DefaultCodegen implements Codege
embeddedTemplateDir = templateDir = "slim"; embeddedTemplateDir = templateDir = "slim";
reservedWords = new HashSet<String>( setReservedWordsLowerCase(
Arrays.asList( Arrays.asList(
"__halt_compiler", "abstract", "and", "array", "as", "break", "callable", "case", "catch", "class", "clone", "const", "continue", "declare", "default", "die", "do", "echo", "else", "elseif", "empty", "enddeclare", "endfor", "endforeach", "endif", "endswitch", "endwhile", "eval", "exit", "extends", "final", "for", "foreach", "function", "global", "goto", "if", "implements", "include", "include_once", "instanceof", "insteadof", "interface", "isset", "list", "namespace", "new", "or", "print", "private", "protected", "public", "require", "require_once", "return", "static", "switch", "throw", "trait", "try", "unset", "use", "var", "while", "xor") "__halt_compiler", "abstract", "and", "array", "as", "break", "callable", "case", "catch", "class", "clone", "const", "continue", "declare", "default", "die", "do", "echo", "else", "elseif", "empty", "enddeclare", "endfor", "endforeach", "endif", "endswitch", "endwhile", "eval", "exit", "extends", "final", "for", "foreach", "function", "global", "goto", "if", "implements", "include", "include_once", "instanceof", "insteadof", "interface", "isset", "list", "namespace", "new", "or", "print", "private", "protected", "public", "require", "require_once", "return", "static", "switch", "throw", "trait", "try", "unset", "use", "var", "while", "xor")
); );
@ -67,7 +67,7 @@ public class SlimFrameworkServerCodegen extends DefaultCodegen implements Codege
instantiationTypes.put("array", "array"); instantiationTypes.put("array", "array");
instantiationTypes.put("map", "map"); instantiationTypes.put("map", "map");
// ref: https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md#data-types // ref: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#data-types
typeMapping = new HashMap<String, String>(); typeMapping = new HashMap<String, String>();
typeMapping.put("integer", "int"); typeMapping.put("integer", "int");
typeMapping.put("long", "int"); typeMapping.put("long", "int");
@ -83,6 +83,9 @@ public class SlimFrameworkServerCodegen extends DefaultCodegen implements Codege
typeMapping.put("array", "array"); typeMapping.put("array", "array");
typeMapping.put("list", "array"); typeMapping.put("list", "array");
typeMapping.put("object", "object"); typeMapping.put("object", "object");
//TODO binary should be mapped to byte array
// mapped to String as a workaround
typeMapping.put("binary", "string");
supportingFiles.add(new SupportingFile("README.mustache", packagePath.replace('/', File.separatorChar), "README.md")); supportingFiles.add(new SupportingFile("README.mustache", packagePath.replace('/', File.separatorChar), "README.md"));
supportingFiles.add(new SupportingFile("composer.json", packagePath.replace('/', File.separatorChar), "composer.json")); supportingFiles.add(new SupportingFile("composer.json", packagePath.replace('/', File.separatorChar), "composer.json"));
@ -90,14 +93,17 @@ public class SlimFrameworkServerCodegen extends DefaultCodegen implements Codege
supportingFiles.add(new SupportingFile(".htaccess", packagePath.replace('/', File.separatorChar), ".htaccess")); supportingFiles.add(new SupportingFile(".htaccess", packagePath.replace('/', File.separatorChar), ".htaccess"));
} }
@Override
public CodegenType getTag() { public CodegenType getTag() {
return CodegenType.SERVER; return CodegenType.SERVER;
} }
@Override
public String getName() { public String getName() {
return "slim"; return "slim";
} }
@Override
public String getHelp() { public String getHelp() {
return "Generates a Slim Framework server library."; return "Generates a Slim Framework server library.";
} }
@ -112,6 +118,7 @@ public class SlimFrameworkServerCodegen extends DefaultCodegen implements Codege
return (outputFolder + "/" + apiPackage()).replace('/', File.separatorChar); return (outputFolder + "/" + apiPackage()).replace('/', File.separatorChar);
} }
@Override
public String modelFileFolder() { public String modelFileFolder() {
return (outputFolder + "/" + modelPackage()).replace('/', File.separatorChar); return (outputFolder + "/" + modelPackage()).replace('/', File.separatorChar);
} }
@ -162,6 +169,7 @@ public class SlimFrameworkServerCodegen extends DefaultCodegen implements Codege
return super.getTypeDeclaration(name); return super.getTypeDeclaration(name);
} }
@Override
public String toDefaultValue(Property p) { public String toDefaultValue(Property p) {
return "null"; return "null";
} }
@ -172,8 +180,7 @@ public class SlimFrameworkServerCodegen extends DefaultCodegen implements Codege
@Override @Override
public String toVarName(String name) { public String toVarName(String name) {
// sanitize name name = sanitizeName(name); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
name = sanitizeName(name);
if ("camelCase".equals(variableNamingConvention)) { if ("camelCase".equals(variableNamingConvention)) {
// return the name in camelCase style // return the name in camelCase style
@ -203,7 +210,7 @@ public class SlimFrameworkServerCodegen extends DefaultCodegen implements Codege
@Override @Override
public String toModelName(String name) { public String toModelName(String name) {
// model name cannot use reserved keyword // model name cannot use reserved keyword
if (reservedWords.contains(name)) { if (isReservedWord(name)) {
escapeReservedWord(name); // e.g. return => _return escapeReservedWord(name); // e.g. return => _return
} }

Some files were not shown because too many files have changed in this diff Show More