Merge pull request #1 from swagger-api/master

Merge from swagger-api
This commit is contained in:
Yonas Kolb 2016-03-08 11:00:03 +11:00
commit f83c200073
1565 changed files with 71699 additions and 43221 deletions

16
.gitignore vendored
View File

@ -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/
@ -59,6 +60,13 @@ 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
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 .settings
@ -67,3 +75,11 @@ samples/client/petstore/python/.venv/
*.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

@ -2,7 +2,7 @@
## 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 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 - 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
@ -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

227
README.md
View File

@ -1,7 +1,8 @@
# 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:
@ -22,7 +23,7 @@ Check out [Swagger-Spec](https://github.com/OAI/OpenAPI-Specification) for addit
- [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) - [Public Docker image](#public-docker-image)
- [Homebrew](#homebrew) - [Homebrew](#homebrew)
- Generators - Generators
@ -33,21 +34,26 @@ Check out [Swagger-Spec](https://github.com/OAI/OpenAPI-Specification) for addit
- [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 OpenAPI 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 2 / 3)](#java-jax-rs-apache-cxf-2--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) - [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)
@ -63,10 +69,10 @@ Swagger Codegen Version | Release Date | OpenAPI Spec compatibility | Notes
### Prerequisites ### Prerequisites
If you're looking for the latest stable version, you can grab it directly from maven central (you'll need the java 7 runtime): 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):
``` ```
wget http://repo1.maven.org/maven2/io/swagger/swagger-codegen-cli/2.1.4/swagger-codegen-cli-2.1.4.jar swagger-codegen-cli.jar 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 java -jar swagger-codegen-cli.jar help
``` ```
@ -103,19 +109,21 @@ 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 #### Public Docker image
@ -153,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>
@ -172,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"...}
@ -182,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 OpenAPI 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:
@ -237,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
``` ```
@ -304,10 +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
AndroidVolleyClientCodegen.java AspNet5ServerCodegen.java
AsyncScalaClientCodegen.java AsyncScalaClientCodegen.java
CSharpClientCodegen.java CSharpClientCodegen.java
ClojureClientCodegen.java ClojureClientCodegen.java
@ -315,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
@ -403,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"
} }
@ -419,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";
} }
} }
``` ```
@ -499,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
``` ```
@ -513,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
``` ```
@ -534,15 +610,41 @@ 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 2 / 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
```
This Codegen only generate a minimalist server stub. You must add the CXF dependency to your classpath (eg: with Maven)
If you are using CXF v2.x, you must provided a custom ```ResourceComparator``` class. This class will help CXF to choose the good resource interface for mapping an incomming request. The default behavior of CXF v2.x is not correct when many resources interface have the same global path.
See: See http://cxf.apache.org/docs/jax-rs-basics.html#JAX-RSBasics-Customselectionbetweenmultipleresources
You can found this class here: https://github.com/hiveship/CXF2-resource-comparator/blob/master/src/main/java/CXFInterfaceComparator.java
TODO: This class could be directly generated by the Codegen.
You must register this class into your JAX-RS configuration file:
```xml
<jaxrs:resourceComparator>
<bean class="your.package.CXFInterfaceComparator"/>
</jaxrs:resourceComparator>
```
This is no longer necessary if you are using CXF >=v3.x
### Java Spring MVC ### Java Spring MVC
``` ```
@ -552,6 +654,24 @@ 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.
@ -582,6 +702,34 @@ 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/)
- [CloudBoost](https://www.CloudBoost.io/)
- [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/)
- [LiveAgent](https://www.ladesk.com/)
- [nViso](http://www.nviso.ch/)
- [Okiok](https://www.okiok.com)
- [OSDN](https://osdn.jp)
- [Pixoneye](http://www.pixoneye.com/)
- [PostAffiliatePro](https://www.postaffiliatepro.com/)
- [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)
- [Svenska Spel AB](https://www.svenskaspel.se/)
- [ThoughtWorks](https://www.thoughtworks.com)
- [uShip](https://www.uship.com/)
- [Zalando](https://tech.zalando.com)
- [ZEEF.com](https://zeef.com/)
License License
------- -------
@ -596,3 +744,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

@ -23,6 +23,7 @@ cd $APP_DIR
./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

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

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

@ -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,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,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

@ -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,6 +21,7 @@ public class SwaggerCodegen {
public static void main(String[] args) { public static void main(String[] args) {
@SuppressWarnings("unchecked")
Cli.CliBuilder<Runnable> builder = Cli.<Runnable>builder("swagger-codegen-cli") 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)

View File

@ -5,18 +5,11 @@ 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.config.CodegenConfigurator; import io.swagger.codegen.config.CodegenConfigurator;
import org.apache.commons.lang3.tuple.Pair;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.util.HashMap; import static io.swagger.codegen.config.CodegenConfiguratorUtils.*;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static org.apache.commons.lang3.StringUtils.isNotEmpty; import static org.apache.commons.lang3.StringUtils.isNotEmpty;
/** /**
@ -73,6 +66,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 +155,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);
} }
@ -176,74 +183,15 @@ public class Generate implements Runnable {
configurator.setLibrary(library); configurator.setLibrary(library);
} }
setSystemProperties(configurator); applySystemPropertiesKvp(systemProperties, configurator);
setInstantiationTypes(configurator); applyInstantiationTypesKvp(instantiationTypes, configurator);
setImportMappings(configurator); applyImportMappingsKvp(importMappings, configurator);
setTypeMappings(configurator); applyTypeMappingsKvp(typeMappings, configurator);
setAdditionalProperties(configurator); applyAdditionalPropertiesKvp(additionalProperties, configurator);
setLanguageSpecificPrimitives(configurator); applyLanguageSpecificPrimitivesCsv(languageSpecificPrimitives, configurator);
final ClientOptInput clientOptInput = configurator.toClientOptInput(); final ClientOptInput clientOptInput = configurator.toClientOptInput();
new DefaultGenerator().opts(clientOptInput).generate(); new DefaultGenerator().opts(clientOptInput).generate();
} }
private void setSystemProperties(CodegenConfigurator configurator) {
final Map<String, String> map = createMapFromKeyValuePairs(systemProperties);
for (Map.Entry<String, String> entry : map.entrySet()) {
configurator.addSystemProperty(entry.getKey(), entry.getValue());
}
}
private void setInstantiationTypes(CodegenConfigurator configurator) {
final Map<String, String> map = createMapFromKeyValuePairs(instantiationTypes);
for (Map.Entry<String, String> entry : map.entrySet()) {
configurator.addInstantiationType(entry.getKey(), entry.getValue());
}
}
private void setImportMappings(CodegenConfigurator configurator) {
final Map<String, String> map = createMapFromKeyValuePairs(importMappings);
for (Map.Entry<String, String> entry : map.entrySet()) {
configurator.addImportMapping(entry.getKey(), entry.getValue());
}
}
private void setTypeMappings(CodegenConfigurator configurator) {
final Map<String, String> map = createMapFromKeyValuePairs(typeMappings);
for (Map.Entry<String, String> entry : map.entrySet()) {
configurator.addTypeMapping(entry.getKey(), entry.getValue());
}
}
private void setAdditionalProperties(CodegenConfigurator configurator) {
final Map<String, String> map = createMapFromKeyValuePairs(additionalProperties);
for (Map.Entry<String, String> entry : map.entrySet()) {
configurator.addAdditionalProperty(entry.getKey(), entry.getValue());
}
}
private void setLanguageSpecificPrimitives(CodegenConfigurator configurator) {
final Set<String> set = createSetFromCsvList(languageSpecificPrimitives);
for (String item : set) {
configurator.addLanguageSpecificPrimitive(item);
}
}
private Set<String> createSetFromCsvList(String csvProperty) {
final List<String> values = OptionUtils.splitCommaSeparatedList(csvProperty);
return new HashSet<String>(values);
}
private Map createMapFromKeyValuePairs(String commaSeparatedKVPairs) {
final List<Pair<String, String>> pairs = OptionUtils.parseCommaSeparatedTuples(commaSeparatedKVPairs);
Map result = new HashMap();
for (Pair<String, String> pair : pairs) {
result.put(pair.getLeft(), pair.getRight());
}
return result;
}
} }

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,7 +133,7 @@ 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 @Override
public Reader getTemplate(String name) { public Reader getTemplate(String name) {
@ -149,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

@ -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

@ -1,16 +0,0 @@
package io.swagger.codegen.plugin;
/**
* User: lanwen
* Date: 24.03.15
* Time: 14:47
*/
public final class AdditionalParams {
public static final String TEMPLATE_DIR_PARAM = "templateDir";
public static final String MODEL_PACKAGE_PARAM = "modelPackage";
public static final String API_PACKAGE_PARAM = "apiPackage";
public static final String INVOKER_PACKAGE_PARAM = "invokerPackage";
public static final String LIBRARY_PARAM = "library";
private AdditionalParams() {}
}

View File

@ -16,9 +16,11 @@ package io.swagger.codegen.plugin;
* limitations under the License. * limitations under the License.
*/ */
import config.Config; import io.swagger.codegen.CliOption;
import config.ConfigParser; import io.swagger.codegen.ClientOptInput;
import io.swagger.codegen.*; import io.swagger.codegen.CodegenConfig;
import io.swagger.codegen.DefaultGenerator;
import io.swagger.codegen.config.CodegenConfigurator;
import io.swagger.models.Swagger; import io.swagger.models.Swagger;
import io.swagger.parser.SwaggerParser; import io.swagger.parser.SwaggerParser;
import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.AbstractMojo;
@ -30,15 +32,28 @@ import org.apache.maven.project.MavenProject;
import java.io.File; import java.io.File;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Set;
import static io.swagger.codegen.plugin.AdditionalParams.*; import static io.swagger.codegen.config.CodegenConfiguratorUtils.*;
import static org.apache.commons.lang3.StringUtils.isNotEmpty;
/** /**
* Goal which generates client/server code from a swagger json/yaml definition. * Goal which generates client/server code from a swagger json/yaml definition.
*/ */
@Mojo(name = "generate", defaultPhase = LifecyclePhase.GENERATE_SOURCES) @Mojo(name = "generate", defaultPhase = LifecyclePhase.GENERATE_SOURCES)
public class CodeGenMojo extends AbstractMojo { public class CodeGenMojo extends AbstractMojo {
@Parameter(name="verbose", required = false, defaultValue = "false")
private boolean verbose;
/**
* Client language to generate.
*/
@Parameter(name = "language", required = true)
private String language;
/** /**
* Location of the output directory. * Location of the output directory.
*/ */
@ -60,10 +75,23 @@ public class CodeGenMojo extends AbstractMojo {
private File templateDirectory; private File templateDirectory;
/** /**
* The package to use for generated model objects/classes * Adds authorization headers when fetching the swagger definitions remotely.
" Pass in a URL-encoded string of name:header with a comma separating multiple values
*/ */
@Parameter(name = "modelPackage") @Parameter(name="auth")
private String modelPackage; private String auth;
/**
* Path to separate json configuration file.
*/
@Parameter(name = "configurationFile", required = false)
private String configurationFile;
/**
* Specifies if the existing files should be overwritten during the generation.
*/
@Parameter(name="skipOverwrite", required=false)
private Boolean skipOverwrite;
/** /**
* The package to use for generated api objects/classes * The package to use for generated api objects/classes
@ -71,6 +99,12 @@ public class CodeGenMojo extends AbstractMojo {
@Parameter(name = "apiPackage") @Parameter(name = "apiPackage")
private String apiPackage; private String apiPackage;
/**
* The package to use for generated model objects/classes
*/
@Parameter(name = "modelPackage")
private String modelPackage;
/** /**
* The package to use for the generated invoker objects * The package to use for the generated invoker objects
*/ */
@ -78,16 +112,22 @@ public class CodeGenMojo extends AbstractMojo {
private String invokerPackage; private String invokerPackage;
/** /**
* Client language to generate. * groupId in generated pom.xml
*/ */
@Parameter(name = "language", required = true) @Parameter(name = "groupId")
private String language; private String groupId;
/** /**
* Path to separate json configuration file. * artifactId in generated pom.xml
*/ */
@Parameter(name = "configurationFile", required = false) @Parameter(name = "artifactId")
private String configurationFile; private String artifactId;
/**
* artifact version in generated pom.xml
*/
@Parameter(name = "artifactVersion")
private String artifactVersion;
/** /**
* Sets the library * Sets the library
@ -99,7 +139,7 @@ public class CodeGenMojo extends AbstractMojo {
* 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
@ -122,12 +162,92 @@ public class CodeGenMojo extends AbstractMojo {
@Override @Override
public void execute() throws MojoExecutionException { public void execute() throws MojoExecutionException {
Swagger swagger = new SwaggerParser().read(inputSpec); Swagger swagger = new SwaggerParser().read(inputSpec);
CodegenConfig config = CodegenConfigLoader.forName(language); //attempt to read from config file
config.setOutputDir(output.getAbsolutePath()); CodegenConfigurator configurator = CodegenConfigurator.fromFile(configurationFile);
//if a config file wasn't specified or we were unable to read it
if(configurator == null) {
configurator = new CodegenConfigurator();
}
configurator.setVerbose(verbose);
if(skipOverwrite != null) {
configurator.setSkipOverwrite(skipOverwrite);
}
if(isNotEmpty(inputSpec)) {
configurator.setInputSpec(inputSpec);
}
configurator.setLang(language);
configurator.setOutputDir(output.getAbsolutePath());
if(isNotEmpty(auth)) {
configurator.setAuth(auth);
}
if(isNotEmpty(apiPackage)) {
configurator.setApiPackage(apiPackage);
}
if(isNotEmpty(modelPackage)) {
configurator.setModelPackage(modelPackage);
}
if(isNotEmpty(invokerPackage)) {
configurator.setInvokerPackage(invokerPackage);
}
if(isNotEmpty(groupId)) {
configurator.setGroupId(groupId);
}
if(isNotEmpty(artifactId)) {
configurator.setArtifactId(artifactId);
}
if(isNotEmpty(artifactVersion)) {
configurator.setArtifactVersion(artifactVersion);
}
if(isNotEmpty(library)) {
configurator.setLibrary(library);
}
if (null != templateDirectory) {
configurator.setTemplateDir(templateDirectory.getAbsolutePath());
}
if (configOptions != null) {
if(configOptions.containsKey("instantiation-types")) {
applyInstantiationTypesKvp(configOptions.get("instantiation-types").toString(), configurator);
}
if(configOptions.containsKey("import-mappings")) {
applyImportMappingsKvp(configOptions.get("import-mappings").toString(), configurator);
}
if(configOptions.containsKey("type-mappings")) {
applyTypeMappingsKvp(configOptions.get("type-mappings").toString(), configurator);
}
if(configOptions.containsKey("language-specific-primitives")) {
applyLanguageSpecificPrimitivesCsv(configOptions.get("language-specific-primitives").toString(), configurator);
}
if(configOptions.containsKey("additional-properties")) {
applyAdditionalPropertiesKvp(configOptions.get("additional-properties").toString(), configurator);
}
}
if (environmentVariables != null) { if (environmentVariables != null) {
for(String key : environmentVariables.keySet()) { for(String key : environmentVariables.keySet()) {
String value = environmentVariables.get(key); String value = environmentVariables.get(key);
if(value == null) { if(value == null) {
@ -135,49 +255,22 @@ public class CodeGenMojo extends AbstractMojo {
value = ""; value = "";
} }
System.setProperty(key, value); System.setProperty(key, value);
configurator.addSystemProperty(key, value);
} }
} }
if (null != library) {
config.setLibrary(library);
}
if (null != templateDirectory) {
config.additionalProperties().put(TEMPLATE_DIR_PARAM, templateDirectory.getAbsolutePath());
}
if (null != modelPackage) {
config.additionalProperties().put(MODEL_PACKAGE_PARAM, modelPackage);
}
if (null != apiPackage) {
config.additionalProperties().put(API_PACKAGE_PARAM, apiPackage);
}
if (null != invokerPackage) {
config.additionalProperties().put(INVOKER_PACKAGE_PARAM, invokerPackage);
}
if (configOptions != null) { final ClientOptInput input = configurator.toClientOptInput();
final CodegenConfig config = input.getConfig();
if(configOptions != null) {
for (CliOption langCliOption : config.cliOptions()) { for (CliOption langCliOption : config.cliOptions()) {
if (configOptions.containsKey(langCliOption.getOpt())) { if (configOptions.containsKey(langCliOption.getOpt())) {
config.additionalProperties().put(langCliOption.getOpt(), input.getConfig().additionalProperties().put(langCliOption.getOpt(),
configOptions.get(langCliOption.getOpt())); configOptions.get(langCliOption.getOpt()));
} }
} }
} }
if (null != configurationFile) {
Config genConfig = ConfigParser.read(configurationFile);
if (null != genConfig) {
for (CliOption langCliOption : config.cliOptions()) {
if (genConfig.hasOption(langCliOption.getOpt())) {
config.additionalProperties().put(langCliOption.getOpt(), genConfig.getOption(langCliOption.getOpt()));
}
}
} else {
throw new RuntimeException("Unable to read configuration file");
}
}
ClientOptInput input = new ClientOptInput().opts(new ClientOpts()).swagger(swagger);
input.setConfig(config);
if(configHelp) { if(configHelp) {
for (CliOption langCliOption : config.cliOptions()) { for (CliOption langCliOption : config.cliOptions()) {
System.out.println("\t" + langCliOption.getOpt()); System.out.println("\t" + langCliOption.getOpt());
@ -190,8 +283,8 @@ public class CodeGenMojo extends AbstractMojo {
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.");
} }

View File

@ -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

@ -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

@ -19,10 +19,16 @@ public interface CodegenConfig {
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,22 +95,34 @@ 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);
void processSwagger(Swagger swagger); void processSwagger(Swagger swagger);
String sanitizeTag(String tag);
String toApiFilename(String name); String toApiFilename(String name);
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);
@ -115,6 +135,8 @@ public interface CodegenConfig {
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();
@ -127,6 +149,8 @@ public interface CodegenConfig {
/** /**
* Library template (sub-template). * Library template (sub-template).
*
* @return libray template
*/ */
String getLibrary(); String getLibrary();
} }

View File

@ -60,6 +60,35 @@ public class CodegenConstants {
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_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 = "optionalAssemblyInfo";
public static final String OPTIONAL_ASSEMBLY_INFO_DESC = "Generate AssemblyInfo.cs (Default: true)."; 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.";
public static final String OPTIONAL_EMIT_DEFAULT_VALUES = "optionalEmitDefaultValues";
public static final String OPTIONAL_EMIT_DEFAULT_VALUES_DESC = "Set DataMember's EmitDefaultValue, default false.";
} }

View File

@ -7,7 +7,9 @@ import java.util.*;
public class CodegenModel { public class CodegenModel {
public String parent, parentSchema; public String parent, parentSchema;
public String name, classname, description, classVarName, modelJson, dataType; public String name, classname, description, classVarName, modelJson, dataType;
public String classFilename; // store the class file name, mainly used for import
public String unescapedDescription; public String unescapedDescription;
public String discriminator;
public String defaultValue; public String defaultValue;
public List<CodegenProperty> vars = new ArrayList<CodegenProperty>(); public List<CodegenProperty> vars = new ArrayList<CodegenProperty>();
public List<String> allowableValues; public List<String> allowableValues;

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

@ -33,6 +33,8 @@ public class CodegenProperty {
public Boolean exclusiveMaximum; public Boolean exclusiveMaximum;
public Boolean hasMore, required, secondaryParam; 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;
@ -40,6 +42,62 @@ public class CodegenProperty {
public CodegenProperty items; public CodegenProperty items;
public Map<String, Object> vendorExtensions; 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) {
if (obj == null) { if (obj == null) {
@ -133,6 +191,9 @@ 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;
} }
@ -142,6 +203,42 @@ public class CodegenProperty {
if (this.vendorExtensions != other.vendorExtensions && (this.vendorExtensions == null || !this.vendorExtensions.equals(other.vendorExtensions))) { if (this.vendorExtensions != other.vendorExtensions && (this.vendorExtensions == null || !this.vendorExtensions.equals(other.vendorExtensions))) {
return false; 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

@ -63,11 +63,16 @@ public class DefaultCodegen {
protected Set<String> languageSpecificPrimitives = new HashSet<String>(); protected Set<String> languageSpecificPrimitives = new HashSet<String>();
protected Map<String, String> importMapping = new HashMap<String, String>(); protected Map<String, String> importMapping = new HashMap<String, String>();
protected String modelPackage = "", apiPackage = "", fileSuffix; protected String modelPackage = "", apiPackage = "", fileSuffix;
protected String modelNamePrefix = "", modelNameSuffix = "";
protected String testPackage = "";
protected Map<String, String> apiTemplateFiles = new HashMap<String, String>(); protected Map<String, String> apiTemplateFiles = new HashMap<String, String>();
protected Map<String, String> modelTemplateFiles = new HashMap<String, String>(); protected Map<String, String> modelTemplateFiles = new HashMap<String, String>();
protected Map<String, String> apiTestTemplateFiles = new HashMap<String, String>();
protected Map<String, String> modelTestTemplateFiles = new HashMap<String, String>();
protected String templateDir; protected String templateDir;
protected String embeddedTemplateDir; protected String embeddedTemplateDir;
protected Map<String, Object> additionalProperties = new HashMap<String, Object>(); protected Map<String, Object> additionalProperties = new HashMap<String, Object>();
protected Map<String, Object> vendorExtensions = new HashMap<String, Object>();
protected List<SupportingFile> supportingFiles = new ArrayList<SupportingFile>(); protected List<SupportingFile> supportingFiles = new ArrayList<SupportingFile>();
protected List<CliOption> cliOptions = new ArrayList<CliOption>(); protected List<CliOption> cliOptions = new ArrayList<CliOption>();
protected boolean skipOverwrite; protected boolean skipOverwrite;
@ -103,41 +108,66 @@ public class DefaultCodegen {
this.setEnsureUniqueParams(Boolean.valueOf(additionalProperties this.setEnsureUniqueParams(Boolean.valueOf(additionalProperties
.get(CodegenConstants.ENSURE_UNIQUE_PARAMS).toString())); .get(CodegenConstants.ENSURE_UNIQUE_PARAMS).toString()));
} }
if(additionalProperties.containsKey(CodegenConstants.MODEL_NAME_PREFIX)){
this.setModelNamePrefix((String) additionalProperties.get(CodegenConstants.MODEL_NAME_PREFIX));
}
if(additionalProperties.containsKey(CodegenConstants.MODEL_NAME_SUFFIX)){
this.setModelNameSuffix((String) additionalProperties.get(CodegenConstants.MODEL_NAME_SUFFIX));
}
} }
// override with any special post-processing // override with any special post-processing for all models
public Map<String, Object> postProcessModels(Map<String, Object> objs) { @SuppressWarnings("static-method")
public Map<String, Object> postProcessAllModels(Map<String, Object> objs) {
return objs; return objs;
} }
// override with any special post-processing // override with any special post-processing
@SuppressWarnings("static-method")
public Map<String, Object> postProcessModels(Map<String, Object> objs) {
return objs;
}
// override with any special post-processing
@SuppressWarnings("static-method")
public Map<String, Object> postProcessOperations(Map<String, Object> objs) { public Map<String, Object> postProcessOperations(Map<String, Object> objs) {
return objs; return objs;
} }
// override with any special post-processing // override with any special post-processing
@SuppressWarnings("static-method")
public Map<String, Object> postProcessSupportingFileData(Map<String, Object> objs) { public Map<String, Object> postProcessSupportingFileData(Map<String, Object> objs) {
return objs; return objs;
} }
// override to post-process any model properties // override to post-process any model properties
public void postProcessModelProperty(CodegenModel model, CodegenProperty property){} @SuppressWarnings("unused")
public void postProcessModelProperty(CodegenModel model, CodegenProperty property){
}
// override to post-process any parameters // override to post-process any parameters
public void postProcessParameter(CodegenParameter parameter){} @SuppressWarnings("unused")
public void postProcessParameter(CodegenParameter parameter){
}
//override with any special handling of the entire swagger spec //override with any special handling of the entire swagger spec
@SuppressWarnings("unused")
public void preprocessSwagger(Swagger swagger) { public void preprocessSwagger(Swagger swagger) {
} }
// override with any special handling of the entire swagger spec // override with any special handling of the entire swagger spec
@SuppressWarnings("unused")
public void processSwagger(Swagger swagger) { public void processSwagger(Swagger swagger) {
} }
// override with any special text escaping logic // override with any special text escaping logic
@SuppressWarnings("static-method")
public String escapeText(String input) { public String escapeText(String input) {
if (input != null) { if (input != null) {
input = input.trim(); input = input.trim(); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
String output = input.replaceAll("\n", "\\\\n"); String output = input.replaceAll("\n", "\\\\n");
output = output.replace("\r", "\\r"); output = output.replace("\r", "\\r");
output = output.replace("\"", "\\\""); output = output.replace("\"", "\\\"");
@ -170,6 +200,10 @@ public class DefaultCodegen {
return importMapping; return importMapping;
} }
public String testPackage() {
return testPackage;
}
public String modelPackage() { public String modelPackage() {
return modelPackage; return modelPackage;
} }
@ -194,6 +228,14 @@ public class DefaultCodegen {
} }
} }
public Map<String, String> apiTestTemplateFiles() {
return apiTestTemplateFiles;
}
public Map<String, String> modelTestTemplateFiles() {
return modelTestTemplateFiles;
}
public Map<String, String> apiTemplateFiles() { public Map<String, String> apiTemplateFiles() {
return apiTemplateFiles; return apiTemplateFiles;
} }
@ -210,10 +252,22 @@ public class DefaultCodegen {
return outputFolder + "/" + modelPackage().replace('.', '/'); return outputFolder + "/" + modelPackage().replace('.', '/');
} }
public String apiTestFileFolder() {
return outputFolder + "/" + testPackage().replace('.', '/');
}
public String modelTestFileFolder() {
return outputFolder + "/" + testPackage().replace('.', '/');
}
public Map<String, Object> additionalProperties() { public Map<String, Object> additionalProperties() {
return additionalProperties; return additionalProperties;
} }
public Map<String, Object> vendorExtensions() {
return vendorExtensions;
}
public List<SupportingFile> supportingFiles() { public List<SupportingFile> supportingFiles() {
return supportingFiles; return supportingFiles;
} }
@ -238,6 +292,14 @@ public class DefaultCodegen {
this.modelPackage = modelPackage; this.modelPackage = modelPackage;
} }
public void setModelNamePrefix(String modelNamePrefix){
this.modelNamePrefix = modelNamePrefix;
}
public void setModelNameSuffix(String modelNameSuffix){
this.modelNameSuffix = modelNameSuffix;
}
public void setApiPackage(String apiPackage) { public void setApiPackage(String apiPackage) {
this.apiPackage = apiPackage; this.apiPackage = apiPackage;
} }
@ -251,7 +313,7 @@ public class DefaultCodegen {
} }
/** /**
* Return the file name of the Api * Return the file name of the Api Test
* *
* @param name the file name of the Api * @param name the file name of the Api
* @return the file name of the Api * @return the file name of the Api
@ -260,6 +322,16 @@ public class DefaultCodegen {
return toApiName(name); return toApiName(name);
} }
/**
* Return the file name of the Api Test
*
* @param name the file name of the Api
* @return the file name of the Api
*/
public String toApiTestFilename(String name) {
return toApiName(name) + "Test";
}
/** /**
* Return the variable name in the Api * Return the variable name in the Api
* *
@ -280,12 +352,23 @@ public class DefaultCodegen {
return initialCaps(name); return initialCaps(name);
} }
/**
* Return the capitalized file name of the model test
*
* @param name the model name
* @return the file name of the model
*/
public String toModelTestFilename(String name) {
return initialCaps(name) + "Test";
}
/** /**
* Return the operation ID (method name) * Return the operation ID (method name)
* *
* @param operationId operation ID * @param operationId operation ID
* @return the sanitized method name * @return the sanitized method name
*/ */
@SuppressWarnings("static-method")
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)) {
@ -318,7 +401,7 @@ public class DefaultCodegen {
* @return the sanitized parameter name * @return the sanitized parameter name
*/ */
public String toParamName(String name) { public String toParamName(String name) {
name = removeNonNameElementToCamelCase(name); name = removeNonNameElementToCamelCase(name); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
if (reservedWords.contains(name)) { if (reservedWords.contains(name)) {
return escapeReservedWord(name); return escapeReservedWord(name);
} }
@ -331,6 +414,7 @@ public class DefaultCodegen {
* @param property Codegen property object * @param property Codegen property object
* @return the Enum name * @return the Enum name
*/ */
@SuppressWarnings("static-method")
public String toEnumName(CodegenProperty property) { public String toEnumName(CodegenProperty property) {
return StringUtils.capitalize(property.name) + "Enum"; return StringUtils.capitalize(property.name) + "Enum";
} }
@ -343,6 +427,7 @@ public class DefaultCodegen {
* *
* throws Runtime exception as reserved word is not allowed (default behavior) * throws Runtime exception as reserved word is not allowed (default behavior)
*/ */
@SuppressWarnings("static-method")
public String escapeReservedWord(String name) { public String escapeReservedWord(String name) {
throw new RuntimeException("reserved word " + name + " not allowed"); throw new RuntimeException("reserved word " + name + " not allowed");
} }
@ -452,6 +537,7 @@ public class DefaultCodegen {
* @param operation Swagger operation object * @param operation Swagger operation object
* @return string presentation of the example path * @return string presentation of the example path
*/ */
@SuppressWarnings("static-method")
public String generateExamplePath(String path, Operation operation) { public String generateExamplePath(String path, Operation operation) {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append(path); sb.append(path);
@ -528,12 +614,61 @@ public class DefaultCodegen {
} }
} }
/**
* Return the example value of the property
*
* @param p Swagger property object
* @return string presentation of the example value of the property
*/
@SuppressWarnings("static-method")
public String toExampleValue(Property p) {
if(p.getExample() != null) {
return p.getExample().toString();
}
if (p instanceof StringProperty) {
return "null";
} else if (p instanceof BooleanProperty) {
return "null";
} else if (p instanceof DateProperty) {
return "null";
} else if (p instanceof DateTimeProperty) {
return "null";
} else if (p instanceof DoubleProperty) {
DoubleProperty dp = (DoubleProperty) p;
if (dp.getExample() != null) {
return dp.getExample().toString();
}
return "null";
} else if (p instanceof FloatProperty) {
FloatProperty dp = (FloatProperty) p;
if (dp.getExample() != null) {
return dp.getExample().toString();
}
return "null";
} else if (p instanceof IntegerProperty) {
IntegerProperty dp = (IntegerProperty) p;
if (dp.getExample() != null) {
return dp.getExample().toString();
}
return "null";
} else if (p instanceof LongProperty) {
LongProperty dp = (LongProperty) p;
if (dp.getExample() != null) {
return dp.getExample().toString();
}
return "null";
} else {
return "null";
}
}
/** /**
* Return the default value of the property * Return the default value of the property
* *
* @param p Swagger property object * @param p Swagger property object
* @return string presentation of the default value of the property * @return string presentation of the default value of the property
*/ */
@SuppressWarnings("static-method")
public String toDefaultValue(Property p) { public String toDefaultValue(Property p) {
if (p instanceof StringProperty) { if (p instanceof StringProperty) {
return "null"; return "null";
@ -580,42 +715,9 @@ public class DefaultCodegen {
* @param p Swagger property object * @param p Swagger property object
* @return string presentation of the default value of the property * @return string presentation of the default value of the property
*/ */
@SuppressWarnings("static-method")
public String toDefaultValueWithParam(String name, Property p) { public String toDefaultValueWithParam(String name, Property p) {
if (p instanceof StringProperty) { return " = data." + name + ";";
return " = data." + name + ";";
} else if (p instanceof BooleanProperty) {
return " = data." + name + ";";
} else if (p instanceof DateProperty) {
return " = data." + name + ";";
} else if (p instanceof DateTimeProperty) {
return " = data." + name + ";";
} else if (p instanceof DoubleProperty) {
DoubleProperty dp = (DoubleProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
return " = data." + name + ";";
} else if (p instanceof FloatProperty) {
FloatProperty dp = (FloatProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
return " = data." + name + ";";
} else if (p instanceof IntegerProperty) {
IntegerProperty dp = (IntegerProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
return " = data." + name + ";";
} else if (p instanceof LongProperty) {
LongProperty dp = (LongProperty) p;
if (dp.getDefault() != null) {
return dp.getDefault().toString();
}
return " = data." + name + ";";
} else {
return " = data." + name + ";";
}
} }
/** /**
@ -623,6 +725,7 @@ public class DefaultCodegen {
* @param p Swagger property object * @param p Swagger property object
* @return string presentation of the type * @return string presentation of the type
**/ **/
@SuppressWarnings("static-method")
public String getSwaggerType(Property p) { public String getSwaggerType(Property p) {
String datatype = null; String datatype = null;
if (p instanceof StringProperty && "number".equals(p.getFormat())) { if (p instanceof StringProperty && "number".equals(p.getFormat())) {
@ -651,6 +754,8 @@ public class DefaultCodegen {
datatype = "map"; datatype = "map";
} else if (p instanceof DecimalProperty) { } else if (p instanceof DecimalProperty) {
datatype = "number"; datatype = "number";
} else if ( p instanceof UUIDProperty) {
datatype = "UUID";
} else if (p instanceof RefProperty) { } else if (p instanceof RefProperty) {
try { try {
RefProperty r = (RefProperty) p; RefProperty r = (RefProperty) p;
@ -661,7 +766,7 @@ public class DefaultCodegen {
} catch (Exception e) { } catch (Exception e) {
LOGGER.warn("Error obtaining the datatype from RefProperty:" + p + ". Datatype default to Object"); LOGGER.warn("Error obtaining the datatype from RefProperty:" + p + ". Datatype default to Object");
datatype = "Object"; datatype = "Object";
e.printStackTrace(); LOGGER.error(e.getMessage(), e);
} }
} else { } else {
if (p != null) { if (p != null) {
@ -677,6 +782,7 @@ public class DefaultCodegen {
* @param name string to be snake-cased * @param name string to be snake-cased
* @return snake-cased string * @return snake-cased string
*/ */
@SuppressWarnings("static-method")
public String snakeCase(String name) { public String snakeCase(String name) {
return (name.length() > 0) ? (Character.toLowerCase(name.charAt(0)) + name.substring(1)) : ""; return (name.length() > 0) ? (Character.toLowerCase(name.charAt(0)) + name.substring(1)) : "";
} }
@ -687,6 +793,7 @@ public class DefaultCodegen {
* @param name string to be capitalized * @param name string to be capitalized
* @return capitalized string * @return capitalized string
*/ */
@SuppressWarnings("static-method")
public String initialCaps(String name) { public String initialCaps(String name) {
return StringUtils.capitalize(name); return StringUtils.capitalize(name);
} }
@ -697,6 +804,7 @@ public class DefaultCodegen {
* @param name name * @param name name
* @return a string presentation of the type * @return a string presentation of the type
*/ */
@SuppressWarnings("static-method")
public String getTypeDeclaration(String name) { public String getTypeDeclaration(String name) {
return name; return name;
} }
@ -735,8 +843,8 @@ public class DefaultCodegen {
* @param name the name of the model * @param name the name of the model
* @return capitalized model name * @return capitalized model name
*/ */
public String toModelName(String name) { public String toModelName(final String name) {
return initialCaps(name); return initialCaps(modelNamePrefix + name + modelNameSuffix);
} }
/** /**
@ -769,10 +877,15 @@ public class DefaultCodegen {
m.unescapedDescription = model.getDescription(); m.unescapedDescription = model.getDescription();
m.classname = toModelName(name); m.classname = toModelName(name);
m.classVarName = toVarName(name); m.classVarName = toVarName(name);
m.classFilename = toModelFilename(name);
m.modelJson = Json.pretty(model); m.modelJson = Json.pretty(model);
m.externalDocs = model.getExternalDocs(); m.externalDocs = model.getExternalDocs();
m.vendorExtensions = model.getVendorExtensions(); m.vendorExtensions = model.getVendorExtensions();
if (model instanceof ModelImpl) {
m.discriminator = ((ModelImpl) model).getDiscriminator();
}
if (model instanceof ArrayModel) { if (model instanceof ArrayModel) {
ArrayModel am = (ArrayModel) model; ArrayModel am = (ArrayModel) model;
@ -896,7 +1009,7 @@ public class DefaultCodegen {
property.unescapedDescription = p.getDescription(); property.unescapedDescription = p.getDescription();
property.getter = "get" + getterAndSetterCapitalize(name); property.getter = "get" + getterAndSetterCapitalize(name);
property.setter = "set" + getterAndSetterCapitalize(name); property.setter = "set" + getterAndSetterCapitalize(name);
property.example = p.getExample(); property.example = toExampleValue(p);
property.defaultValue = toDefaultValue(p); property.defaultValue = toDefaultValue(p);
property.defaultValueWithParam = toDefaultValueWithParam(name, p); property.defaultValueWithParam = toDefaultValueWithParam(name, p);
property.jsonSchema = Json.pretty(p); property.jsonSchema = Json.pretty(p);
@ -929,6 +1042,7 @@ public class DefaultCodegen {
property.maxLength = sp.getMaxLength(); property.maxLength = sp.getMaxLength();
property.minLength = sp.getMinLength(); property.minLength = sp.getMinLength();
property.pattern = sp.getPattern(); property.pattern = sp.getPattern();
property.isString = true;
if (sp.getEnum() != null) { if (sp.getEnum() != null) {
List<String> _enum = sp.getEnum(); List<String> _enum = sp.getEnum();
property._enum = _enum; property._enum = _enum;
@ -943,6 +1057,7 @@ public class DefaultCodegen {
if (p instanceof IntegerProperty) { if (p instanceof IntegerProperty) {
IntegerProperty sp = (IntegerProperty) p; IntegerProperty sp = (IntegerProperty) p;
property.isInteger = true;
if (sp.getEnum() != null) { if (sp.getEnum() != null) {
List<Integer> _enum = sp.getEnum(); List<Integer> _enum = sp.getEnum();
property._enum = new ArrayList<String>(); property._enum = new ArrayList<String>();
@ -960,6 +1075,7 @@ public class DefaultCodegen {
if (p instanceof LongProperty) { if (p instanceof LongProperty) {
LongProperty sp = (LongProperty) p; LongProperty sp = (LongProperty) p;
property.isLong = true;
if (sp.getEnum() != null) { if (sp.getEnum() != null) {
List<Long> _enum = sp.getEnum(); List<Long> _enum = sp.getEnum();
property._enum = new ArrayList<String>(); property._enum = new ArrayList<String>();
@ -975,8 +1091,21 @@ public class DefaultCodegen {
} }
} }
if (p instanceof BooleanProperty) {
property.isBoolean = true;
}
if (p instanceof BinaryProperty) {
property.isBinary = true;
}
if (p instanceof ByteArrayProperty) {
property.isByteArray = true;
}
if (p instanceof DoubleProperty) { if (p instanceof DoubleProperty) {
DoubleProperty sp = (DoubleProperty) p; DoubleProperty sp = (DoubleProperty) p;
property.isDouble = true;
if (sp.getEnum() != null) { if (sp.getEnum() != null) {
List<Double> _enum = sp.getEnum(); List<Double> _enum = sp.getEnum();
property._enum = new ArrayList<String>(); property._enum = new ArrayList<String>();
@ -994,6 +1123,7 @@ public class DefaultCodegen {
if (p instanceof FloatProperty) { if (p instanceof FloatProperty) {
FloatProperty sp = (FloatProperty) p; FloatProperty sp = (FloatProperty) p;
property.isFloat = true;
if (sp.getEnum() != null) { if (sp.getEnum() != null) {
List<Float> _enum = sp.getEnum(); List<Float> _enum = sp.getEnum();
property._enum = new ArrayList<String>(); property._enum = new ArrayList<String>();
@ -1011,6 +1141,7 @@ public class DefaultCodegen {
if (p instanceof DateProperty) { if (p instanceof DateProperty) {
DateProperty sp = (DateProperty) p; DateProperty sp = (DateProperty) p;
property.isDate = true;
if (sp.getEnum() != null) { if (sp.getEnum() != null) {
List<String> _enum = sp.getEnum(); List<String> _enum = sp.getEnum();
property._enum = new ArrayList<String>(); property._enum = new ArrayList<String>();
@ -1028,6 +1159,7 @@ public class DefaultCodegen {
if (p instanceof DateTimeProperty) { if (p instanceof DateTimeProperty) {
DateTimeProperty sp = (DateTimeProperty) p; DateTimeProperty sp = (DateTimeProperty) p;
property.isDateTime = true;
if (sp.getEnum() != null) { if (sp.getEnum() != null) {
List<String> _enum = sp.getEnum(); List<String> _enum = sp.getEnum();
property._enum = new ArrayList<String>(); property._enum = new ArrayList<String>();
@ -1055,11 +1187,12 @@ public class DefaultCodegen {
if (p instanceof ArrayProperty) { if (p instanceof ArrayProperty) {
property.isContainer = true; property.isContainer = true;
property.isListContainer = true;
property.containerType = "array"; property.containerType = "array";
ArrayProperty ap = (ArrayProperty) p; ArrayProperty ap = (ArrayProperty) p;
CodegenProperty cp = fromProperty(property.name, ap.getItems()); CodegenProperty cp = fromProperty(property.name, ap.getItems());
if (cp == null) { if (cp == null) {
LOGGER.warn("skipping invalid property " + Json.pretty(p)); LOGGER.warn("skipping invalid property " + Json.pretty(p));
} else { } else {
property.baseType = getSwaggerType(p); property.baseType = getSwaggerType(p);
if (!languageSpecificPrimitives.contains(cp.baseType)) { if (!languageSpecificPrimitives.contains(cp.baseType)) {
@ -1077,6 +1210,7 @@ public class DefaultCodegen {
} }
} else if (p instanceof MapProperty) { } else if (p instanceof MapProperty) {
property.isContainer = true; property.isContainer = true;
property.isMapContainer = true;
property.containerType = "map"; property.containerType = "map";
MapProperty ap = (MapProperty) p; MapProperty ap = (MapProperty) p;
CodegenProperty cp = fromProperty("inner", ap.getAdditionalProperties()); CodegenProperty cp = fromProperty("inner", ap.getAdditionalProperties());
@ -1102,7 +1236,12 @@ public class DefaultCodegen {
} }
} }
private Response findMethodResponse(Map<String, Response> responses) { /**
* Override with any special handling of response codes
* @param responses Swagger Operation's responses
* @return default method response or <tt>null</tt> if not found
*/
protected Response findMethodResponse(Map<String, Response> responses) {
String code = null; String code = null;
for (String responseCode : responses.keySet()) { for (String responseCode : responses.keySet()) {
@ -1329,11 +1468,14 @@ public class DefaultCodegen {
cookieParams.add(p.copy()); cookieParams.add(p.copy());
} else if (param instanceof BodyParameter) { } else if (param instanceof BodyParameter) {
p.isBodyParam = new Boolean(true); p.isBodyParam = new Boolean(true);
p.isBinary = p.dataType.toLowerCase().startsWith("byte");
bodyParam = p; bodyParam = p;
bodyParams.add(p.copy()); bodyParams.add(p.copy());
} else if (param instanceof FormParameter) { } else if (param instanceof FormParameter) {
if ("file".equalsIgnoreCase(((FormParameter) param).getType())) { if ("file".equalsIgnoreCase(((FormParameter) param).getType())) {
p.isFile = true; p.isFile = true;
} else if("file".equals(p.baseType)){
p.isFile = true;
} else { } else {
p.notFile = true; p.notFile = true;
} }
@ -1422,7 +1564,7 @@ public class DefaultCodegen {
} }
} }
r.dataType = cm.datatype; r.dataType = cm.datatype;
r.isBinary = cm.datatype.equals("byte[]"); r.isBinary = cm.datatype.toLowerCase().startsWith("byte");
if (cm.isContainer != null) { if (cm.isContainer != null) {
r.simpleType = false; r.simpleType = false;
r.containerType = cm.containerType; r.containerType = cm.containerType;
@ -1481,7 +1623,7 @@ public class DefaultCodegen {
if (null == type) { if (null == type) {
LOGGER.warn("Type is NULL for Serializable Parameter: " + param); LOGGER.warn("Type is NULL for Serializable Parameter: " + param);
} }
if ("array".equals(type)) { if ("array".equals(type)) { // for array parameter
Property inner = qp.getItems(); Property inner = qp.getItems();
if (inner == null) { if (inner == null) {
LOGGER.warn("warning! No inner type supplied for array parameter \"" + qp.getName() + "\", using String"); LOGGER.warn("warning! No inner type supplied for array parameter \"" + qp.getName() + "\", using String");
@ -1495,8 +1637,9 @@ public class DefaultCodegen {
CodegenProperty pr = fromProperty("inner", inner); CodegenProperty pr = fromProperty("inner", inner);
p.baseType = pr.datatype; p.baseType = pr.datatype;
p.isContainer = true; p.isContainer = true;
p.isListContainer = true;
imports.add(pr.baseType); imports.add(pr.baseType);
} else if ("object".equals(type)) { } else if ("object".equals(type)) { // for map parameter
Property inner = qp.getItems(); Property inner = qp.getItems();
if (inner == null) { if (inner == null) {
LOGGER.warn("warning! No inner type supplied for map parameter \"" + qp.getName() + "\", using String"); LOGGER.warn("warning! No inner type supplied for map parameter \"" + qp.getName() + "\", using String");
@ -1506,6 +1649,8 @@ public class DefaultCodegen {
collectionFormat = qp.getCollectionFormat(); collectionFormat = qp.getCollectionFormat();
CodegenProperty pr = fromProperty("inner", inner); CodegenProperty pr = fromProperty("inner", inner);
p.baseType = pr.datatype; p.baseType = pr.datatype;
p.isContainer = true;
p.isMapContainer = true;
imports.add(pr.baseType); imports.add(pr.baseType);
} else { } else {
Map<PropertyId, Object> args = new HashMap<PropertyId, Object>(); Map<PropertyId, Object> args = new HashMap<PropertyId, Object>();
@ -1513,16 +1658,28 @@ public class DefaultCodegen {
args.put(PropertyId.ENUM, qp.getEnum()); args.put(PropertyId.ENUM, qp.getEnum());
property = PropertyBuilder.build(type, format, args); property = PropertyBuilder.build(type, format, args);
} }
if (property == null) { if (property == null) {
LOGGER.warn("warning! Property type \"" + type + "\" not found for parameter \"" + param.getName() + "\", using String"); LOGGER.warn("warning! Property type \"" + type + "\" not found for parameter \"" + param.getName() + "\", using String");
property = new StringProperty().description("//TODO automatically added by swagger-codegen. Type was " + type + " but not supported"); property = new StringProperty().description("//TODO automatically added by swagger-codegen. Type was " + type + " but not supported");
} }
property.setRequired(param.getRequired()); property.setRequired(param.getRequired());
CodegenProperty model = fromProperty(qp.getName(), property); CodegenProperty model = fromProperty(qp.getName(), property);
// set boolean flag (e.g. isString)
setParameterBooleanFlagWithCodegenProperty(p, model);
p.dataType = model.datatype; p.dataType = model.datatype;
if(model.isEnum) {
p.datatypeWithEnum = model.datatypeWithEnum;
}
p.isEnum = model.isEnum; p.isEnum = model.isEnum;
p._enum = model._enum; p._enum = model._enum;
p.allowableValues = model.allowableValues; p.allowableValues = model.allowableValues;
if(model.items != null && model.items.isEnum) {
p.datatypeWithEnum = model.datatypeWithEnum;
p.items = model.items;
}
p.collectionFormat = collectionFormat; p.collectionFormat = collectionFormat;
if(collectionFormat != null && collectionFormat.equals("multi")) { if(collectionFormat != null && collectionFormat.equals("multi")) {
p.isCollectionFormatMulti = true; p.isCollectionFormatMulti = true;
@ -1567,19 +1724,16 @@ public class DefaultCodegen {
CodegenProperty cp = fromProperty("property", prop); CodegenProperty cp = fromProperty("property", prop);
if (cp != null) { if (cp != null) {
p.dataType = cp.datatype; p.dataType = cp.datatype;
if (p.dataType.equals("byte[]")) { p.isBinary = cp.datatype.toLowerCase().startsWith("byte");
p.isBinary = true;
}
else {
p.isBinary = false;
}
} }
// set boolean flag (e.g. isString)
setParameterBooleanFlagWithCodegenProperty(p, cp);
} }
} else if (model instanceof ArrayModel) { } else if (model instanceof ArrayModel) {
// to use the built-in model parsing, we unwrap the ArrayModel // to use the built-in model parsing, we unwrap the ArrayModel
// and get a single property from it // and get a single property from it
ArrayModel impl = (ArrayModel) model; ArrayModel impl = (ArrayModel) model;
CodegenModel cm = fromModel(bp.getName(), impl);
// get the single property // get the single property
ArrayProperty ap = new ArrayProperty().items(impl.getItems()); ArrayProperty ap = new ArrayProperty().items(impl.getItems());
ap.setRequired(param.getRequired()); ap.setRequired(param.getRequired());
@ -1590,6 +1744,10 @@ public class DefaultCodegen {
imports.add(cp.baseType); imports.add(cp.baseType);
p.dataType = cp.datatype; p.dataType = cp.datatype;
p.isContainer = true; p.isContainer = true;
p.isListContainer = true;
// set boolean flag (e.g. isString)
setParameterBooleanFlagWithCodegenProperty(p, cp);
} else { } else {
Model sub = bp.getSchema(); Model sub = bp.getSchema();
if (sub instanceof RefModel) { if (sub instanceof RefModel) {
@ -1620,6 +1778,7 @@ public class DefaultCodegen {
* @param schemes a map of Swagger SecuritySchemeDefinition object * @param schemes a map of Swagger SecuritySchemeDefinition object
* @return a list of Codegen Security objects * @return a list of Codegen Security objects
*/ */
@SuppressWarnings("static-method")
public List<CodegenSecurity> fromSecurity(Map<String, SecuritySchemeDefinition> schemes) { public List<CodegenSecurity> fromSecurity(Map<String, SecuritySchemeDefinition> schemes) {
if (schemes == null) { if (schemes == null) {
return Collections.emptyList(); return Collections.emptyList();
@ -1678,6 +1837,17 @@ public class DefaultCodegen {
return secs; return secs;
} }
protected void setReservedWordsLowerCase(List<String> words) {
reservedWords = new HashSet<String>();
for (String word : words) {
reservedWords.add(word.toLowerCase());
}
}
protected boolean isReservedWord(String word) {
return word != null && reservedWords.contains(word.toLowerCase());
}
/** /**
* Get operationId from the operation object, and if it's blank, generate a new one from the given parameters. * Get operationId from the operation object, and if it's blank, generate a new one from the given parameters.
* *
@ -1709,8 +1879,8 @@ public class DefaultCodegen {
builder.append(part); builder.append(part);
} }
} }
operationId = builder.toString(); operationId = sanitizeName(builder.toString());
LOGGER.info("generated operationId " + operationId + "\tfor Path: " + httpMethod + " " + path); LOGGER.warn("Empty operationId found for path: " + httpMethod + " " + path + ". Renamed to auto-generated operationId: " + operationId);
} }
return operationId; return operationId;
} }
@ -1726,6 +1896,7 @@ public class DefaultCodegen {
&& !languageSpecificPrimitives.contains(type); && !languageSpecificPrimitives.contains(type);
} }
@SuppressWarnings("static-method")
protected List<Map<String, Object>> toExamples(Map<String, Object> examples) { protected List<Map<String, Object>> toExamples(Map<String, Object> examples) {
if (examples == null) { if (examples == null) {
return null; return null;
@ -1749,7 +1920,7 @@ public class DefaultCodegen {
} }
} }
private List<CodegenParameter> addHasMore(List<CodegenParameter> objs) { private static List<CodegenParameter> addHasMore(List<CodegenParameter> objs) {
if (objs != null) { if (objs != null) {
for (int i = 0; i < objs.size(); i++) { for (int i = 0; i < objs.size(); i++) {
if (i > 0) { if (i > 0) {
@ -1763,7 +1934,7 @@ public class DefaultCodegen {
return objs; return objs;
} }
private Map<String, Object> addHasMore(Map<String, Object> objs) { private static Map<String, Object> addHasMore(Map<String, Object> objs) {
if (objs != null) { if (objs != null) {
for (int i = 0; i < objs.size() - 1; i++) { for (int i = 0; i < objs.size() - 1; i++) {
if (i > 0) { if (i > 0) {
@ -1786,6 +1957,7 @@ public class DefaultCodegen {
* @param co Codegen Operation object * @param co Codegen Operation object
* @param operations map of Codegen operations * @param operations map of Codegen operations
*/ */
@SuppressWarnings("static-method")
public void addOperationToGroup(String tag, String resourcePath, Operation operation, CodegenOperation co, Map<String, List<CodegenOperation>> operations) { public void addOperationToGroup(String tag, String resourcePath, Operation operation, CodegenOperation co, Map<String, List<CodegenOperation>> operations) {
List<CodegenOperation> opList = operations.get(tag); List<CodegenOperation> opList = operations.get(tag);
if (opList == null) { if (opList == null) {
@ -1810,8 +1982,6 @@ public class DefaultCodegen {
co.baseName = tag; co.baseName = tag;
} }
private void addParentContainer(CodegenModel m, String name, Property property) { private void addParentContainer(CodegenModel m, String name, Property property) {
final CodegenProperty tmp = fromProperty(name, property); final CodegenProperty tmp = fromProperty(name, property);
addImport(m, tmp.complexType); addImport(m, tmp.complexType);
@ -1840,7 +2010,7 @@ public class DefaultCodegen {
String secondPattern = "([a-z\\d])([A-Z])"; String secondPattern = "([a-z\\d])([A-Z])";
String replacementPattern = "$1_$2"; String replacementPattern = "$1_$2";
// Replace package separator with slash. // Replace package separator with slash.
word = word.replaceAll("\\.", "/"); word = word.replaceAll("\\.", "/"); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
// Replace $ with two underscores for inner classes. // Replace $ with two underscores for inner classes.
word = word.replaceAll("\\$", "__"); word = word.replaceAll("\\$", "__");
// Replace capital letter with _ plus lowercase letter. // Replace capital letter with _ plus lowercase letter.
@ -1857,6 +2027,7 @@ public class DefaultCodegen {
* @param word The word * @param word The word
* @return The dashized version of the word, e.g. "my-name" * @return The dashized version of the word, e.g. "my-name"
*/ */
@SuppressWarnings("static-method")
protected String dashize(String word) { protected String dashize(String word) {
return underscore(word).replaceAll("[_ ]", "-"); return underscore(word).replaceAll("[_ ]", "-");
} }
@ -1871,7 +2042,7 @@ public class DefaultCodegen {
* @param name The base name * @param name The base name
* @return The next name for the base name * @return The next name for the base name
*/ */
private String generateNextName(String name) { private static String generateNextName(String name) {
Pattern pattern = Pattern.compile("\\d+\\z"); Pattern pattern = Pattern.compile("\\d+\\z");
Matcher matcher = pattern.matcher(name); Matcher matcher = pattern.matcher(name);
if (matcher.find()) { if (matcher.find()) {
@ -1936,9 +2107,10 @@ public class DefaultCodegen {
* @param name string to be camelize * @param name string to be camelize
* @return camelized string * @return camelized string
*/ */
@SuppressWarnings("static-method")
public String removeNonNameElementToCamelCase(String name) { public String removeNonNameElementToCamelCase(String name) {
String nonNameElementPattern = "[-_:;#]"; String nonNameElementPattern = "[-_:;#]";
name = StringUtils.join(Lists.transform(Lists.newArrayList(name.split(nonNameElementPattern)), new Function<String, String>() { name = StringUtils.join(Lists.transform(Lists.newArrayList(name.split(nonNameElementPattern)), new Function<String, String>() { // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
@Nullable @Nullable
@Override @Override
public String apply(String input) { public String apply(String input) {
@ -1975,7 +2147,7 @@ public class DefaultCodegen {
Pattern p = Pattern.compile("\\/(.?)"); Pattern p = Pattern.compile("\\/(.?)");
Matcher m = p.matcher(word); Matcher m = p.matcher(word);
while (m.find()) { while (m.find()) {
word = m.replaceFirst("." + m.group(1)/*.toUpperCase()*/); word = m.replaceFirst("." + m.group(1)/*.toUpperCase()*/); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
m = p.matcher(word); m = p.matcher(word);
} }
@ -2004,14 +2176,6 @@ public class DefaultCodegen {
word = m.replaceAll(rep); word = m.replaceAll(rep);
} }
// Replace two underscores with $ to support inner classes.
p = Pattern.compile("(__)(.)");
m = p.matcher(word);
while (m.find()) {
word = m.replaceFirst("\\$" + m.group(2).toUpperCase());
m = p.matcher(word);
}
// Remove all underscores // Remove all underscores
p = Pattern.compile("(_)(.)"); p = Pattern.compile("(_)(.)");
m = p.matcher(word); m = p.matcher(word);
@ -2032,6 +2196,19 @@ public class DefaultCodegen {
return apiFileFolder() + '/' + toApiFilename(tag) + suffix; return apiFileFolder() + '/' + toApiFilename(tag) + suffix;
} }
/**
* Return the full path and API test file
*
* @param templateName template name
* @param tag tag
*
* @return the API test file name with full path
*/
public String apiTestFilename(String templateName, String tag) {
String suffix = apiTestTemplateFiles().get(templateName);
return apiTestFileFolder() + '/' + toApiTestFilename(tag) + suffix;
}
public boolean shouldOverwrite(String filename) { public boolean shouldOverwrite(String filename) {
return !(skipOverwrite && new File(filename).exists()); return !(skipOverwrite && new File(filename).exists());
} }
@ -2061,11 +2238,14 @@ public class DefaultCodegen {
/** /**
* Library template (sub-template). * Library template (sub-template).
*
* @return Library template
*/ */
public String getLibrary() { public String getLibrary() {
return library; return library;
} }
@SuppressWarnings("static-method")
protected CliOption buildLibraryCliOption(Map<String, String> supportedLibraries) { protected CliOption buildLibraryCliOption(Map<String, String> supportedLibraries) {
StringBuilder sb = new StringBuilder("library template (sub-template) to use:"); StringBuilder sb = new StringBuilder("library template (sub-template) to use:");
for (String lib : supportedLibraries.keySet()) { for (String lib : supportedLibraries.keySet()) {
@ -2080,6 +2260,7 @@ public class DefaultCodegen {
* @param name string to be sanitize * @param name string to be sanitize
* @return sanitized string * @return sanitized string
*/ */
@SuppressWarnings("static-method")
public String sanitizeName(String name) { public String sanitizeName(String name) {
// NOTE: performance wise, we should have written with 2 replaceAll to replace desired // NOTE: performance wise, we should have written with 2 replaceAll to replace desired
// character with _ or empty character. Below aims to spell out different cases we've // character with _ or empty character. Below aims to spell out different cases we've
@ -2092,8 +2273,13 @@ public class DefaultCodegen {
return "ERROR_UNKNOWN"; return "ERROR_UNKNOWN";
} }
// if the name is just '$', map it to 'value' for the time being.
if ("$".equals(name)) {
return "value";
}
// input[] => input // input[] => input
name = name.replaceAll("\\[\\]", ""); name = name.replaceAll("\\[\\]", ""); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
// input[a][b] => input_a_b // input[a][b] => input_a_b
name = name.replaceAll("\\[", "_"); name = name.replaceAll("\\[", "_");
@ -2115,6 +2301,86 @@ public class DefaultCodegen {
// remove everything else other than word, number and _ // remove everything else other than word, number and _
// $php_variable => php_variable // $php_variable => php_variable
return name.replaceAll("[^a-zA-Z0-9_]", ""); return name.replaceAll("[^a-zA-Z0-9_]", "");
}
@SuppressWarnings("static-method")
public String sanitizeTag(String tag) {
// remove spaces and make strong case
String[] parts = tag.split(" ");
StringBuilder buf = new StringBuilder();
for (String part : parts) {
if (StringUtils.isNotEmpty(part)) {
buf.append(StringUtils.capitalize(part));
}
}
return buf.toString().replaceAll("[^a-zA-Z ]", "");
}
/**
* Only write if the file doesn't exist
*
* @param outputFolder Output folder
* @param supportingFile Supporting file
*/
public void writeOptional(String outputFolder, SupportingFile supportingFile) {
String folder = "";
if(outputFolder != null && !"".equals(outputFolder)) {
folder += outputFolder + File.separator;
}
folder += supportingFile.folder;
if(!"".equals(folder)) {
folder += File.separator + supportingFile.destinationFilename;
}
else {
folder = supportingFile.destinationFilename;
}
if(!new File(folder).exists()) {
supportingFiles.add(supportingFile);
} else {
LOGGER.info("Skipped overwriting " + supportingFile.destinationFilename + " as the file already exists in " + folder);
}
}
/**
* Set CodegenParameter boolean flag using CodegenProperty.
*
* @param parameter Codegen Parameter
* @param property Codegen property
*/
public void setParameterBooleanFlagWithCodegenProperty(CodegenParameter parameter, CodegenProperty property) {
if (parameter == null) {
LOGGER.error("Codegen Parameter cannnot be null.");
return;
}
if (property == null) {
LOGGER.error("Codegen Property cannot be null.");
return;
}
if (Boolean.TRUE.equals(property.isString)) {
parameter.isString = true;
} else if (Boolean.TRUE.equals(property.isBoolean)) {
parameter.isBoolean = true;
} else if (Boolean.TRUE.equals(property.isLong)) {
parameter.isLong = true;
} else if (Boolean.TRUE.equals(property.isInteger)) {
parameter.isInteger = true;
} else if (Boolean.TRUE.equals(property.isDouble)) {
parameter.isDouble = true;
} else if (Boolean.TRUE.equals(property.isFloat)) {
parameter.isFloat = true;
} else if (Boolean.TRUE.equals(property.isByteArray)) {
parameter.isByteArray = true;
} else if (Boolean.TRUE.equals(property.isBinary)) {
parameter.isByteArray = true;
} else if (Boolean.TRUE.equals(property.isDate)) {
parameter.isDate = true;
} else if (Boolean.TRUE.equals(property.isDateTime)) {
parameter.isDateTime = true;
} else {
LOGGER.debug("Property type is not primitive: " + property.datatype);
}
} }
} }

View File

@ -15,11 +15,10 @@ import org.slf4j.LoggerFactory;
import java.io.*; import java.io.*;
import java.util.*; import java.util.*;
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; protected ClientOptInput opts;
@ -129,6 +128,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 +182,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
@ -189,6 +199,26 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
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));
for (String templateName : config.modelTemplateFiles().keySet()) { for (String templateName : config.modelTemplateFiles().keySet()) {
@ -211,6 +241,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 +270,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);
} }
@ -249,6 +301,10 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
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;
if (this.config.additionalProperties().containsKey(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG)) { if (this.config.additionalProperties().containsKey(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG)) {
@ -288,13 +344,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 +413,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 +472,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 +488,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 +513,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 +586,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) {
@ -547,8 +622,8 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
try { try {
co = config.fromOperation(resourcePath, httpMethod, operation, swagger.getDefinitions(), swagger); co = config.fromOperation(resourcePath, httpMethod, operation, swagger.getDefinitions(), swagger);
co.tags = new ArrayList<String>(); co.tags = new ArrayList<String>();
co.tags.add(sanitizeTag(tag)); co.tags.add(config.sanitizeTag(tag));
config.addOperationToGroup(sanitizeTag(tag), resourcePath, operation, co, operations); config.addOperationToGroup(config.sanitizeTag(tag), resourcePath, operation, co, operations);
List<Map<String, List<String>>> securities = operation.getSecurity(); List<Map<String, List<String>>> securities = operation.getSecurity();
if (securities == null && swagger.getSecurity() != null) { if (securities == null && swagger.getSecurity() != null) {
@ -561,35 +636,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/OAI/OpenAPI-Specification/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,22 +678,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();
} }
protected String sanitizeTag(String tag) { @SuppressWarnings("static-method")
// remove spaces and make strong case
String[] parts = tag.split(" ");
StringBuilder buf = new StringBuilder();
for (String part : parts) {
if (isNotEmpty(part)) {
buf.append(capitalize(part));
}
}
return buf.toString().replaceAll("[^a-zA-Z ]", "");
}
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 +743,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());
@ -695,7 +754,7 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
CodegenModel cm = config.fromModel(key, mm, allDefinitions); CodegenModel cm = config.fromModel(key, mm, allDefinitions);
Map<String, Object> mo = new HashMap<String, Object>(); Map<String, Object> mo = new HashMap<String, Object>();
mo.put("model", cm); mo.put("model", cm);
mo.put("importPath", config.toModelImport(key)); mo.put("importPath", config.toModelImport(cm.classname));
models.add(mo); models.add(mo);
allImports.addAll(cm.imports); allImports.addAll(cm.imports);
@ -704,7 +763,6 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
Set<String> importSet = new TreeSet<String>(); Set<String> importSet = new TreeSet<String>();
for (String nextImport : allImports) { for (String nextImport : allImports) {
Map<String, String> im = new HashMap<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);

View File

@ -1,21 +1,18 @@
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;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class InlineModelResolver { public class InlineModelResolver {
private Swagger swagger; private Swagger swagger;
private boolean skipMatches; private boolean skipMatches;
@ -51,12 +48,13 @@ public class InlineModelResolver {
if(model instanceof ModelImpl) { if(model instanceof ModelImpl) {
ModelImpl obj = (ModelImpl) model; ModelImpl obj = (ModelImpl) model;
if (obj.getType() == null || "object".equals(obj.getType())) { if (obj.getType() == null || "object".equals(obj.getType())) {
String modelName = uniqueName(bp.getName()); if (obj.getProperties() != null && obj.getProperties().size() > 0) {
flattenProperties(obj.getProperties(), pathname); flattenProperties(obj.getProperties(), pathname);
String modelName = uniqueName(bp.getName());
bp.setSchema(new RefModel(modelName)); bp.setSchema(new RefModel(modelName));
addGenerated(modelName, model); addGenerated(modelName, model);
swagger.addDefinition(modelName, model); swagger.addDefinition(modelName, model);
}
} }
} }
else if (model instanceof ArrayModel) { else if (model instanceof ArrayModel) {
@ -64,18 +62,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); if (op.getProperties() != null && op.getProperties().size() > 0) {
flattenProperties(op.getProperties(), pathname);
Model innerModel = modelFromProperty(op, modelName); String modelName = uniqueName(bp.getName());
String existing = matchGenerated(innerModel); Model innerModel = modelFromProperty(op, modelName);
if (existing != null) { String existing = matchGenerated(innerModel);
am.setItems(new RefProperty(existing)); if (existing != null) {
} else { am.setItems(new RefProperty(existing));
am.setItems(new RefProperty(modelName)); } else {
addGenerated(modelName, innerModel); am.setItems(new RefProperty(modelName));
swagger.addDefinition(modelName, innerModel); addGenerated(modelName, innerModel);
swagger.addDefinition(modelName, innerModel);
}
} }
} }
} }
@ -90,34 +89,37 @@ public class InlineModelResolver {
if (response.getSchema() != null) { if (response.getSchema() != null) {
Property property = response.getSchema(); Property property = response.getSchema();
if (property instanceof ObjectProperty) { if (property instanceof ObjectProperty) {
String modelName = uniqueName("inline_response_" + key);
ObjectProperty op = (ObjectProperty) property; ObjectProperty op = (ObjectProperty) property;
Model model = modelFromProperty(op, modelName); if (op.getProperties() != null && op.getProperties().size() > 0) {
String existing = matchGenerated(model); String modelName = uniqueName("inline_response_" + key);
if (existing != null) { Model model = modelFromProperty(op, modelName);
response.setSchema(new RefProperty(existing)); String existing = matchGenerated(model);
} else { if (existing != null) {
response.setSchema(new RefProperty(modelName)); response.setSchema(new RefProperty(existing));
addGenerated(modelName, model); } else {
swagger.addDefinition(modelName, model); response.setSchema(new RefProperty(modelName));
addGenerated(modelName, model);
swagger.addDefinition(modelName, model);
}
} }
} else if (property instanceof ArrayProperty) { } else if (property instanceof ArrayProperty) {
ArrayProperty ap = (ArrayProperty) property; ArrayProperty ap = (ArrayProperty) property;
Property inner = ap.getItems(); Property inner = ap.getItems();
if(inner instanceof ObjectProperty) { if(inner instanceof ObjectProperty) {
String modelName = uniqueName("inline_response_" + key);
ObjectProperty op = (ObjectProperty) inner; ObjectProperty op = (ObjectProperty) inner;
flattenProperties(op.getProperties(), pathname); if (op.getProperties() != null && op.getProperties().size() > 0) {
flattenProperties(op.getProperties(), pathname);
Model innerModel = modelFromProperty(op, modelName); String modelName = uniqueName("inline_response_" + key);
String existing = matchGenerated(innerModel); Model innerModel = modelFromProperty(op, modelName);
if (existing != null) { String existing = matchGenerated(innerModel);
ap.setItems(new RefProperty(existing)); if (existing != null) {
} else { ap.setItems(new RefProperty(existing));
ap.setItems(new RefProperty(modelName)); } else {
addGenerated(modelName, innerModel); ap.setItems(new RefProperty(modelName));
swagger.addDefinition(modelName, innerModel); addGenerated(modelName, innerModel);
swagger.addDefinition(modelName, innerModel);
}
} }
} }
} else if (property instanceof MapProperty) { } else if (property instanceof MapProperty) {
@ -125,18 +127,19 @@ public class InlineModelResolver {
Property innerProperty = mp.getAdditionalProperties(); Property innerProperty = mp.getAdditionalProperties();
if(innerProperty instanceof ObjectProperty) { if(innerProperty instanceof ObjectProperty) {
String modelName = uniqueName("inline_response_" + key);
ObjectProperty op = (ObjectProperty) innerProperty; ObjectProperty op = (ObjectProperty) innerProperty;
flattenProperties(op.getProperties(), pathname); if (op.getProperties() != null && op.getProperties().size() > 0) {
flattenProperties(op.getProperties(), pathname);
Model innerModel = modelFromProperty(op, modelName); String modelName = uniqueName("inline_response_" + key);
String existing = matchGenerated(innerModel); Model innerModel = modelFromProperty(op, modelName);
if (existing != null) { String existing = matchGenerated(innerModel);
mp.setAdditionalProperties(new RefProperty(existing)); if (existing != null) {
} else { mp.setAdditionalProperties(new RefProperty(existing));
mp.setAdditionalProperties(new RefProperty(modelName)); } else {
addGenerated(modelName, innerModel); mp.setAdditionalProperties(new RefProperty(modelName));
swagger.addDefinition(modelName, innerModel); addGenerated(modelName, innerModel);
swagger.addDefinition(modelName, innerModel);
}
} }
} }
} }
@ -162,20 +165,20 @@ public class InlineModelResolver {
ArrayModel m = (ArrayModel) model; ArrayModel m = (ArrayModel) model;
Property inner = m.getItems(); Property inner = m.getItems();
if (inner instanceof ObjectProperty) { if (inner instanceof ObjectProperty) {
String innerModelName = uniqueName(modelName + "_inner"); ObjectProperty op = (ObjectProperty) inner;
Model innerModel = modelFromProperty((ObjectProperty) inner, modelName); if (op.getProperties() != null && op.getProperties().size() > 0) {
String innerModelName = uniqueName(modelName + "_inner");
String existing = matchGenerated(innerModel); Model innerModel = modelFromProperty(op, innerModelName);
if (existing == null) { String existing = matchGenerated(innerModel);
swagger.addDefinition(innerModelName, innerModel); if (existing == null) {
addGenerated(innerModelName, innerModel); swagger.addDefinition(innerModelName, innerModel);
m.setItems(new RefProperty(innerModelName)); addGenerated(innerModelName, innerModel);
} else { m.setItems(new RefProperty(innerModelName));
m.setItems(new RefProperty(existing)); } else {
m.setItems(new RefProperty(existing));
}
} }
} }
} else if (model instanceof ComposedModel) {
ComposedModel m = (ComposedModel) model;
} }
} }
} }
@ -199,7 +202,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) {
@ -223,7 +226,9 @@ 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 &&
((ObjectProperty)property).getProperties().size() > 0) {
String modelName = uniqueName(path + "_" + key); String modelName = uniqueName(path + "_" + key);
ObjectProperty op = (ObjectProperty) property; ObjectProperty op = (ObjectProperty) property;
@ -244,20 +249,19 @@ public class InlineModelResolver {
Property inner = ap.getItems(); Property inner = ap.getItems();
if (inner instanceof ObjectProperty) { if (inner instanceof ObjectProperty) {
String modelName = uniqueName(path + "_" + key);
ObjectProperty op = (ObjectProperty) inner; ObjectProperty op = (ObjectProperty) inner;
flattenProperties(op.getProperties(), path); if (op.getProperties() != null && op.getProperties().size() > 0) {
flattenProperties(op.getProperties(), path);
Model innerModel = modelFromProperty(op, modelName); String modelName = uniqueName(path + "_" + key);
String existing = matchGenerated(innerModel); Model innerModel = modelFromProperty(op, modelName);
String existing = matchGenerated(innerModel);
if (existing != null) { if (existing != null) {
ap.setItems(new RefProperty(existing)); ap.setItems(new RefProperty(existing));
} else { } else {
ap.setItems(new RefProperty(modelName)); ap.setItems(new RefProperty(modelName));
addGenerated(modelName, innerModel); addGenerated(modelName, innerModel);
swagger.addDefinition(modelName, innerModel); swagger.addDefinition(modelName, innerModel);
}
} }
} }
} else if (property instanceof MapProperty) { } else if (property instanceof MapProperty) {
@ -265,23 +269,21 @@ public class InlineModelResolver {
Property inner = mp.getAdditionalProperties(); Property inner = mp.getAdditionalProperties();
if (inner instanceof ObjectProperty) { if (inner instanceof ObjectProperty) {
String modelName = uniqueName(path + "_" + key);
ObjectProperty op = (ObjectProperty) inner; ObjectProperty op = (ObjectProperty) inner;
flattenProperties(op.getProperties(), path); if (op.getProperties() != null && op.getProperties().size() > 0) {
flattenProperties(op.getProperties(), path);
Model innerModel = modelFromProperty(op, modelName); String modelName = uniqueName(path + "_" + key);
String existing = matchGenerated(innerModel); Model innerModel = modelFromProperty(op, modelName);
String existing = matchGenerated(innerModel);
if (existing != null) { if (existing != null) {
mp.setAdditionalProperties(new RefProperty(existing)); mp.setAdditionalProperties(new RefProperty(existing));
} else { } else {
mp.setAdditionalProperties(new RefProperty(modelName)); mp.setAdditionalProperties(new RefProperty(modelName));
addGenerated(modelName, innerModel); addGenerated(modelName, innerModel);
swagger.addDefinition(modelName, innerModel); swagger.addDefinition(modelName, innerModel);
}
} }
} }
} else {
} }
} }
if (propsToUpdate.size() > 0) { if (propsToUpdate.size() > 0) {
@ -295,53 +297,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();
@ -358,17 +343,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);

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();
@ -161,8 +160,6 @@ public class MetaGenerator extends AbstractGenerator {
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);
@ -172,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,10 +7,17 @@ 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>();
if (isNotEmpty(urlEncodedAuthStr)) { if (isNotEmpty(urlEncodedAuthStr)) {
@ -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,7 +36,7 @@ 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;
@ -48,6 +48,8 @@ public class CodegenConfigurator {
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" +
@ -392,7 +414,7 @@ public class CodegenConfigurator {
try { try {
return Json.mapper().readValue(new File(configFile), CodegenConfigurator.class); return Json.mapper().readValue(new File(configFile), CodegenConfigurator.class);
} 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

@ -0,0 +1,77 @@
package io.swagger.codegen.config;
import io.swagger.codegen.utils.OptionUtils;
import org.apache.commons.lang3.tuple.Pair;
import java.util.*;
/**
* Contains shared logic for applying key-value pairs and CSV strings
* to specific settings in CodegenConfigurator.
*
* <p>
* This class exists to facilitate testing. These methods could be applied
* to CodegenConfigurator, but this complicates things when mocking CodegenConfigurator.
* </p>
*/
public final class CodegenConfiguratorUtils {
public static void applySystemPropertiesKvp(String systemProperties, CodegenConfigurator configurator) {
final Map<String, String> map = createMapFromKeyValuePairs(systemProperties);
for (Map.Entry<String, String> entry : map.entrySet()) {
configurator.addSystemProperty(entry.getKey(), entry.getValue());
}
}
public static void applyInstantiationTypesKvp(String instantiationTypes, CodegenConfigurator configurator) {
final Map<String, String> map = createMapFromKeyValuePairs(instantiationTypes);
for (Map.Entry<String, String> entry : map.entrySet()) {
configurator.addInstantiationType(entry.getKey(), entry.getValue());
}
}
public static void applyImportMappingsKvp(String importMappings, CodegenConfigurator configurator) {
final Map<String, String> map = createMapFromKeyValuePairs(importMappings);
for (Map.Entry<String, String> entry : map.entrySet()) {
configurator.addImportMapping(entry.getKey(), entry.getValue());
}
}
public static void applyTypeMappingsKvp(String typeMappings, CodegenConfigurator configurator) {
final Map<String, String> map = createMapFromKeyValuePairs(typeMappings);
for (Map.Entry<String, String> entry : map.entrySet()) {
configurator.addTypeMapping(entry.getKey(), entry.getValue());
}
}
public static void applyAdditionalPropertiesKvp(String additionalProperties, CodegenConfigurator configurator) {
final Map<String, String> map = createMapFromKeyValuePairs(additionalProperties);
for (Map.Entry<String, String> entry : map.entrySet()) {
configurator.addAdditionalProperty(entry.getKey(), entry.getValue());
}
}
public static void applyLanguageSpecificPrimitivesCsv(String languageSpecificPrimitives, CodegenConfigurator configurator) {
final Set<String> set = createSetFromCsvList(languageSpecificPrimitives);
for (String item : set) {
configurator.addLanguageSpecificPrimitive(item);
}
}
private static Set<String> createSetFromCsvList(String csvProperty) {
final List<String> values = OptionUtils.splitCommaSeparatedList(csvProperty);
return new HashSet<String>(values);
}
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

@ -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>();
@ -93,9 +93,9 @@ public class ExampleGenerator {
}; };
} }
} 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) {
@ -142,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,540 @@
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 optionalEmitDefaultValue = 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 setOptionalEmitDefaultValue(boolean optionalEmitDefaultValue) {
this.optionalEmitDefaultValue = optionalEmitDefaultValue;
}
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()));
}
if (additionalProperties.containsKey(CodegenConstants.OPTIONAL_EMIT_DEFAULT_VALUES)) {
setOptionalEmitDefaultValue(Boolean.valueOf(additionalProperties.get(CodegenConstants.OPTIONAL_EMIT_DEFAULT_VALUES).toString()));
}
}
@Override
public String toEnumName(CodegenProperty property) {
return StringUtils.capitalize(property.name) + "Enum?";
}
@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) {
if (!StringUtils.isEmpty(modelNamePrefix)) {
name = modelNamePrefix + "_" + name;
}
if (!StringUtils.isEmpty(modelNameSuffix)) {
name = name + "_" + modelNameSuffix;
}
name = sanitizeName(name);
// 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("model_" + name));
name = "model_" + name; // e.g. return => ModelReturn (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,22 +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( setReservedWordsLowerCase(Arrays.asList(
// local variable names used in API methods (endpoints) // local variable names used in API methods (endpoints)
"path", "queryParameters", "headerParams", "formParams", "useFormData", "deferred", "varLocalPath", "queryParameters", "headerParams", "formParams", "useFormData", "varLocalDeferred",
"requestOptions", "requestOptions",
// Typescript reserved words // 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")); "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",
@ -32,7 +31,12 @@ 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>();
@ -52,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
@ -71,9 +95,9 @@ public abstract class AbstractTypeScriptClientCodegen extends DefaultCodegen imp
} }
@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_]*$"))
@ -84,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("model_" + 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
@ -140,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",
@ -274,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);

View File

@ -7,7 +7,6 @@ import io.swagger.codegen.CodegenType;
import io.swagger.codegen.DefaultCodegen; import io.swagger.codegen.DefaultCodegen;
import io.swagger.codegen.SupportingFile; import io.swagger.codegen.SupportingFile;
import io.swagger.models.properties.ArrayProperty; import io.swagger.models.properties.ArrayProperty;
import io.swagger.models.properties.BooleanProperty;
import io.swagger.models.properties.MapProperty; import io.swagger.models.properties.MapProperty;
import io.swagger.models.properties.Property; import io.swagger.models.properties.Property;
@ -16,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";
@ -40,12 +42,12 @@ public class AndroidClientCodegen extends DefaultCodegen implements CodegenConfi
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(
// local variable names used in API methods (endpoints) // local variable names used in API methods (endpoints)
"postBody", "path", "queryParams", "headerParams", "formParams", "localVarPostBody", "localVarPath", "localVarQueryParams", "localVarHeaderParams",
"contentTypes", "contentType", "response", "builder", "httpEntity", "localVarFormParams", "localVarContentTypes", "localVarContentType",
"authNames", "basePath", "apiInvoker", "localVarResponse", "localVarBuilder", "authNames", "basePath", "apiInvoker",
// android reserved words // android reserved words
"abstract", "continue", "for", "new", "switch", "assert", "abstract", "continue", "for", "new", "switch", "assert",
@ -66,10 +68,13 @@ public class AndroidClientCodegen extends DefaultCodegen implements CodegenConfi
"Integer", "Integer",
"Long", "Long",
"Float", "Float",
"byte[]",
"Object") "Object")
); );
instantiationTypes.put("array", "ArrayList"); instantiationTypes.put("array", "ArrayList");
instantiationTypes.put("map", "HashMap"); instantiationTypes.put("map", "HashMap");
typeMapping.put("date", "Date");
typeMapping.put("file", "File");
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));
@ -139,8 +144,10 @@ public class AndroidClientCodegen extends DefaultCodegen implements CodegenConfi
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)) { if (languageSpecificPrimitives.contains(type) || type.indexOf(".") >= 0 ||
return toModelName(type); type.equals("Map") || type.equals("List") ||
type.equals("File") || type.equals("Date")) {
return type;
} }
} else { } else {
type = swaggerType; type = swaggerType;
@ -151,7 +158,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_]*$")) {
@ -163,7 +170,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);
} }
@ -178,14 +185,27 @@ 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 // add prefix, suffix if needed
if (reservedWords.contains(name)) { if (!StringUtils.isEmpty(modelNamePrefix)) {
throw new RuntimeException(name + " (reserved word) cannot be used as a model name"); name = modelNamePrefix + "_" + name;
}
if (!StringUtils.isEmpty(modelNameSuffix)) {
name = name + "_" + modelNameSuffix;
} }
// 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 = "Model" + name;
LOGGER.warn(name + " (reserved word) cannot be used as model name. Renamed to " + modelName);
return modelName;
}
return name;
} }
@Override @Override
@ -201,12 +221,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

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";
@ -45,7 +43,7 @@ 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(
// local variable names used in API methods (endpoints) // local variable names used in API methods (endpoints)
"config", "path", "contentTypes", "contentType", "queryParams", "headerParams", "config", "path", "contentTypes", "contentType", "queryParams", "headerParams",

View File

@ -1,14 +1,19 @@
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;
import io.swagger.codegen.CodegenModel;
import io.swagger.codegen.DefaultCodegen; 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 java.io.File; import java.io.File;
import java.util.Arrays; import java.util.Arrays;
@ -16,144 +21,119 @@ import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.ArrayList;
import java.util.Iterator;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
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 optionalAssemblyInfoFlag = true; private static final String NET45 = "v4.5";
protected boolean optionalMethodArgumentFlag = true; private static final String NET35 = "v3.5";
protected boolean useDateTimeOffsetFlag = false;
protected String packageGuid = "{" + java.util.UUID.randomUUID().toString().toUpperCase() + "}";
protected String packageTitle = "Swagger Library"; protected String packageTitle = "Swagger Library";
protected String packageProductName = "SwaggerLibrary"; protected String packageProductName = "SwaggerLibrary";
protected String packageDescription = "A library generated from a Swagger doc"; protected String packageDescription = "A library generated from a Swagger doc";
protected String packageCompany = "Swagger"; protected String packageCompany = "Swagger";
protected String packageCopyright = "No Copyright"; protected String packageCopyright = "No Copyright";
protected String packageName = "IO.Swagger";
protected String packageVersion = "1.0.0";
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 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");
// local variable names in API methods (endpoints)
"path_", "pathParams", "queryParams", "headerParams", "formParams", "fileParams",
"postBody", "http_header_accepts", "http_header_accept", "apiKeyValue", "response",
"statusCode",
// 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")
);
// 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?",
"DateTimeOffset?",
"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("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");
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(CliOption.newBoolean(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, "C# package name (convention: Title.Case).",
CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG_DESC).defaultValue(Boolean.TRUE.toString())); this.packageName);
cliOptions.add(CliOption.newBoolean(CodegenConstants.OPTIONAL_METHOD_ARGUMENT, "C# Optional method argument, " +
"e.g. void square(int x=10) (.net 4.0+ only).")); addOption(CodegenConstants.PACKAGE_VERSION,
cliOptions.add(CliOption.newBoolean(CodegenConstants.OPTIONAL_ASSEMBLY_INFO, "C# package version.",
CodegenConstants.OPTIONAL_ASSEMBLY_INFO_DESC).defaultValue(Boolean.TRUE.toString())); this.packageVersion);
cliOptions.add(new CliOption(CodegenConstants.SOURCE_FOLDER, CodegenConstants.SOURCE_FOLDER_DESC).defaultValue(sourceFolder));
cliOptions.add(CliOption.newBoolean(CodegenConstants.USE_DATETIME_OFFSET, CodegenConstants.USE_DATETIME_OFFSET_DESC)); 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);
addSwitch(CodegenConstants.OPTIONAL_EMIT_DEFAULT_VALUES,
CodegenConstants.OPTIONAL_EMIT_DEFAULT_VALUES_DESC,
this.optionalEmitDefaultValue);
} }
@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.SOURCE_FOLDER)){
setSourceFolder((String) additionalProperties.get(CodegenConstants.SOURCE_FOLDER));
}
else
{
additionalProperties.put(CodegenConstants.SOURCE_FOLDER, this.sourceFolder);
}
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);
}
// Use DateTimeOffset
if (additionalProperties.containsKey(CodegenConstants.USE_DATETIME_OFFSET))
{
useDateTimeOffset(Boolean.valueOf(additionalProperties.get(CodegenConstants.USE_DATETIME_OFFSET).toString()));
}
additionalProperties.put(CodegenConstants.USE_DATETIME_OFFSET, useDateTimeOffsetFlag);
additionalProperties.put("clientPackage", clientPackage); additionalProperties.put("clientPackage", clientPackage);
@ -163,6 +143,35 @@ public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig
additionalProperties.put("packageDescription", packageDescription); additionalProperties.put("packageDescription", packageDescription);
additionalProperties.put("packageCompany", packageCompany); additionalProperties.put("packageCompany", packageCompany);
additionalProperties.put("packageCopyright", packageCopyright); additionalProperties.put("packageCopyright", packageCopyright);
additionalProperties.put("emitDefaultValue", optionalEmitDefaultValue);
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
@ -175,25 +184,65 @@ public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig
.get(CodegenConstants.OPTIONAL_ASSEMBLY_INFO).toString())); .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("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("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) { if (optionalAssemblyInfoFlag) {
supportingFiles.add(new SupportingFile("AssemblyInfo.mustache", "src" + File.separator + "Properties", "AssemblyInfo.cs")); 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 @Override
@ -211,143 +260,171 @@ public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig
return "Generates a CSharp client library."; return "Generates a CSharp client library.";
} }
@Override
public String escapeReservedWord(String name) {
return "_" + name;
}
@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 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 setOptionalAssemblyInfoFlag(boolean flag) { public void setOptionalAssemblyInfoFlag(boolean flag) {
this.optionalAssemblyInfoFlag = flag; this.optionalAssemblyInfoFlag = flag;
} }
public void setOptionalMethodArgumentFlag(boolean flag) { @Override
this.optionalMethodArgumentFlag = flag; public CodegenModel fromModel(String name, Model model, Map<String, Model> allDefinitions) {
CodegenModel codegenModel = super.fromModel(name, model, allDefinitions);
if (allDefinitions != null && codegenModel != null && codegenModel.parent != null && codegenModel.hasEnums) {
final Model parentModel = allDefinitions.get(toModelName(codegenModel.parent));
final CodegenModel parentCodegenModel = super.fromModel(codegenModel.parent, parentModel);
codegenModel = this.reconcileInlineEnums(codegenModel, parentCodegenModel);
}
return codegenModel;
} }
public void useDateTimeOffset(boolean flag) { public void setOptionalProjectFileFlag(boolean flag) {
this.useDateTimeOffsetFlag = flag; this.optionalProjectFileFlag = flag;
if (flag) }
typeMapping.put("datetime", "DateTimeOffset?");
else public void setPackageGuid(String packageGuid) {
typeMapping.put("datetime", "DateTime?"); this.packageGuid = packageGuid;
}
@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) {
Map<String, Object> allowableValues = var.allowableValues;
// handle ArrayProperty
if (var.items != null) {
allowableValues = var.items.allowableValues;
}
if (allowableValues == null) {
continue;
}
List<String> values = (List<String>) allowableValues.get("values");
if (values == null) {
continue;
}
// put "enumVars" map into `allowableValues", including `name` and `value`
List<Map<String, String>> enumVars = new ArrayList<Map<String, String>>();
String commonPrefix = findCommonPrefixOfVars(values);
int truncateIdx = commonPrefix.length();
for (String value : values) {
Map<String, String> enumVar = new HashMap<String, String>();
String enumName;
if (truncateIdx == 0) {
enumName = value;
} else {
enumName = value.substring(truncateIdx);
if ("".equals(enumName)) {
enumName = value;
}
}
enumVar.put("name", toEnumVarName(enumName));
enumVar.put("jsonname", value);
enumVar.put("value", value);
enumVars.add(enumVar);
}
allowableValues.put("enumVars", enumVars);
// handle default value for enum, e.g. available => StatusEnum.AVAILABLE
if (var.defaultValue != null) {
String enumName = null;
for (Map<String, String> enumVar : enumVars) {
if (var.defaultValue.equals(enumVar.get("value"))) {
enumName = enumVar.get("name");
break;
}
}
if (enumName != null) {
var.defaultValue = var.datatypeWithEnum + "." + enumName;
}
}
// HACK: strip ? from enum
if (var.datatypeWithEnum != null) {
var.vendorExtensions.put("plainDatatypeWithEnum", var.datatypeWithEnum.substring(0, var.datatypeWithEnum.length() - 1));
}
}
}
return objs;
}
public void setTargetFramework(String dotnetFramework) {
if(!frameworks.containsKey(dotnetFramework)){
LOGGER.warn("Invalid .NET framework version, defaulting to " + this.targetFramework);
} else {
this.targetFramework = dotnetFramework;
}
LOGGER.info("Generating code for .NET Framework " + this.targetFramework);
}
private CodegenModel reconcileInlineEnums(CodegenModel codegenModel, CodegenModel parentCodegenModel) {
// This generator uses inline classes to define enums, which breaks when
// 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
// them from the child models and leave them in the parent.
// Because the child models extend the parents, the enums will be available via the parent.
// Only bother with reconciliation if the parent model has enums.
if (parentCodegenModel.hasEnums) {
// Get the properties for the parent and child models
final List<CodegenProperty> parentModelCodegenProperties = parentCodegenModel.vars;
List<CodegenProperty> codegenProperties = codegenModel.vars;
// Iterate over all of the parent model properties
boolean removedChildEnum = false;
for (CodegenProperty parentModelCodegenPropery : parentModelCodegenProperties) {
// Look for enums
if (parentModelCodegenPropery.isEnum) {
// Now that we have found an enum in the parent class,
// and search the child class for the same enum.
Iterator<CodegenProperty> iterator = codegenProperties.iterator();
while (iterator.hasNext()) {
CodegenProperty codegenProperty = iterator.next();
if (codegenProperty.isEnum && codegenProperty.equals(parentModelCodegenPropery)) {
// We found an enum in the child class that is
// a duplicate of the one in the parent, so remove it.
iterator.remove();
removedChildEnum = true;
}
}
}
}
if(removedChildEnum) {
// If we removed an entry from this model's vars, we need to ensure hasMore is updated
int count = 0, numVars = codegenProperties.size();
for(CodegenProperty codegenProperty : codegenProperties) {
count += 1;
codegenProperty.hasMore = (count < numVars) ? true : null;
}
codegenModel.vars = codegenProperties;
}
}
return codegenModel;
}
private String findCommonPrefixOfVars(List<String> vars) {
String prefix = StringUtils.getCommonPrefix(vars.toArray(new String[vars.size()]));
// exclude trailing characters that should be part of a valid variable
// e.g. ["status-on", "status-off"] => "status-" (not "status-o")
return prefix.replaceAll("[a-zA-Z0-9]+\\z", "");
}
private String toEnumVarName(String value) {
String var = value.replaceAll("_", " ");
var = WordUtils.capitalizeFully(var);
var = var.replaceAll("\\W+", "");
if (var.matches("\\d.*")) {
return "_" + var;
} else {
return var;
}
} }
@ -359,72 +436,11 @@ public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig
this.packageVersion = packageVersion; this.packageVersion = packageVersion;
} }
public void setSourceFolder(String sourceFolder) { public void setTargetFrameworkNuget(String targetFrameworkNuget) {
this.sourceFolder = sourceFolder; this.targetFrameworkNuget = targetFrameworkNuget;
} }
@Override public void setSupportsAsync(Boolean supportsAsync){
public Map<String, Object> postProcessModels(Map<String, Object> objs) { this.supportsAsync = supportsAsync;
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;
}
/**
* 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;
} }
} }

View File

@ -145,6 +145,11 @@ public class ClojureClientCodegen extends DefaultCodegen implements CodegenConfi
supportingFiles.add(new SupportingFile("core.mustache", baseNamespaceFolder, "core.clj")); supportingFiles.add(new SupportingFile("core.mustache", baseNamespaceFolder, "core.clj"));
} }
@Override
public String sanitizeTag(String tag) {
return tag.replaceAll("[^a-zA-Z_]+", "_");
}
@Override @Override
public String apiFileFolder() { public String apiFileFolder() {
return outputFolder + File.separator + sourceFolder + File.separator + namespaceToFolder(apiPackage); return outputFolder + File.separator + sourceFolder + File.separator + namespaceToFolder(apiPackage);
@ -160,6 +165,11 @@ public class ClojureClientCodegen extends DefaultCodegen implements CodegenConfi
return dashize(sanitizeName(operationId)); return dashize(sanitizeName(operationId));
} }
@Override
public String toApiFilename(String name) {
return underscore(toApiName(name));
}
@Override @Override
public String toApiName(String name) { public String toApiName(String name) {
return dashize(name); return dashize(name);
@ -172,7 +182,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 +206,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,7 +31,7 @@ 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(
// local variable names in API methods (endpoints) // local variable names in API methods (endpoints)
"path", "queryParams", "headerParams", "formParams", "fileParams", "postBody", "path", "queryParams", "headerParams", "formParams", "fileParams", "postBody",
@ -172,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_]*$")) {
@ -184,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);
} }
@ -206,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);
} }
@ -215,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");
} }
@ -265,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"));
@ -168,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_]*$")) {
@ -180,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);
} }
@ -196,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");
} }
@ -218,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);
} }
@ -263,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

@ -29,7 +29,7 @@ public class FlashClientCodegen extends DefaultCodegen implements CodegenConfig
protected String packageVersion; 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
@ -178,26 +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 @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);
@ -253,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_]*$")) {
@ -280,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);
} }
@ -295,9 +287,20 @@ public class FlashClientCodegen extends DefaultCodegen implements CodegenConfig
@Override @Override
public String toModelName(String name) { public String toModelName(String name) {
if (!StringUtils.isEmpty(modelNamePrefix)) {
name = modelNamePrefix + "_" + name;
}
if (!StringUtils.isEmpty(modelNameSuffix)) {
name = name + "_" + modelNameSuffix;
}
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"); LOGGER.warn(name + " (reserved word) cannot be used as model name. Renamed to " + camelize("model_" + name));
name = "model_" + name; // e.g. return => ModelReturn (after camelize)
} }
// camelize the model name // camelize the model name
@ -307,20 +310,14 @@ 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 // leverage toModelName
if (reservedWords.contains(name)) { return dropDots(toModelName(name));
throw new RuntimeException(name + " (reserved word) cannot be used as a model name");
}
// underscore the model file name
// PhoneNumber => phone_number
return camelize(dropDots(name));
} }
@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";
@ -351,8 +348,9 @@ 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"); LOGGER.warn(operationId + " (reserved word) cannot be used as method name. Renamed to " + underscore(sanitizeName("call_" + operationId)));
operationId = "call_" + operationId;
} }
return underscore(operationId); return underscore(operationId);
@ -373,7 +371,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",
@ -167,8 +175,8 @@ public class FlaskConnexionCodegen extends DefaultCodegen implements CodegenConf
*/ */
@Override @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
@ -249,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");
@ -259,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) {
@ -289,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)) {
@ -304,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(".*\\.", "");

View File

@ -0,0 +1,334 @@
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", "error")
// Added "error" as it's used so frequently that it may as well be a keyword
);
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)
{
// Can't start with an underscore, as our fields need to start with an
// UppercaseLetter so that Go treats them as public/visible.
// Options?
// - MyName
// - AName
// - TheName
// - XName
// - X_Name
// ... or maybe a suffix?
// - Name_ ... think this will work.
// FIXME: This should also really be a customizable option
return camelize(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) {
// params should be lowerCamelCase. E.g. "person Person", instead of
// "Person Person".
//
// REVISIT: Actually, for idiomatic go, the param name should
// really should just be a letter, e.g. "p Person"), but we'll get
// around to that some other time... Maybe.
return camelize(toVarName(name), true);
}
@Override
public String toModelName(String name) {
if (!StringUtils.isEmpty(modelNamePrefix)) {
name = modelNamePrefix + "_" + name;
}
if (!StringUtils.isEmpty(modelNameSuffix)) {
name = name + "_" + modelNameSuffix;
}
name = sanitizeName(name);
// 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("model_" + name));
name = "model_" + name; // e.g. return => ModelReturn (after camelize)
}
// 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);
// Not using the supertype invocation, because we want to UpperCamelize
// the type.
String swaggerType = getSwaggerType(p);
if (typeMapping.containsKey(swaggerType)) {
return typeMapping.get(swaggerType);
}
if(typeMapping.containsValue(swaggerType)) {
return swaggerType;
}
if(languageSpecificPrimitives.contains(swaggerType)) {
return swaggerType;
}
return camelize(swaggerType, false);
}
@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)) {
LOGGER.warn(operationId + " (reserved word) cannot be used as method name. Renamed to " + camelize(sanitizeName("call_" + operationId)));
operationId = "call_" + operationId;
}
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;

View File

@ -0,0 +1,101 @@
package io.swagger.codegen.languages;
import java.io.File;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import io.swagger.codegen.CliOption;
import io.swagger.codegen.CodegenConstants;
import io.swagger.codegen.CodegenModel;
import io.swagger.codegen.CodegenOperation;
import io.swagger.codegen.CodegenProperty;
import io.swagger.models.Operation;
public class JavaCXFServerCodegen extends AbstractJavaJAXRSServerCodegen
{
public JavaCXFServerCodegen()
{
super();
supportsInheritance = true;
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);
typeMapping.put("date", "LocalDate");
typeMapping.put("DateTime", "javax.xml.datatype.XMLGregorianCalendar"); // Map DateTime fields to Java standart class 'XMLGregorianCalendar'
importMapping.put("LocalDate", "org.joda.time.LocalDate");
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;
}
}
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, "CXF");
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 void processOpts()
{
super.processOpts();
sourceFolder = "gen" + File.separator + "java";
supportingFiles.clear(); // Don't need extra files provided by AbstractJAX-RS & Java Codegen
//TODO
//final String invokerFolder = (sourceFolder + '/' + invokerPackage).replace(".", "/");
//supportingFiles.add(new SupportingFile("CXF2InterfaceComparator.mustache", invokerFolder, "CXF2InterfaceComparator.java"));
}
@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 void postProcessModelProperty(CodegenModel model, CodegenProperty property) {
super.postProcessModelProperty(model, property);
model.imports.remove("ApiModelProperty");
model.imports.remove("ApiModel");
model.imports.remove("JsonSerialize");
model.imports.remove("ToStringSerializer");
model.imports.remove("JsonValue");
model.imports.remove("JsonProperty");
}
@Override
public String getHelp()
{
return "Generates a Java JAXRS Server application based on Apache CXF framework.";
}
}

View File

@ -9,18 +9,27 @@ import io.swagger.models.Swagger;
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.*; import io.swagger.models.properties.*;
import org.apache.commons.lang.BooleanUtils;
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.io.File;
import java.util.*; 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";
@ -32,6 +41,7 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
protected String javaUtilPrefix = ""; protected String javaUtilPrefix = "";
protected Boolean serializableModel = false; protected Boolean serializableModel = false;
protected boolean serializeBigDecimalAsString = false; protected boolean serializeBigDecimalAsString = false;
protected boolean useRxJava = false;
public JavaClientCodegen() { public JavaClientCodegen() {
super(); super();
@ -42,20 +52,21 @@ 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(
// used as internal variables, can collide with parameter names // used as internal variables, can collide with parameter names
"path", "queryParams", "headerParams", "formParams", "postBody", "accepts", "accept", "contentTypes", "localVarPath", "localVarQueryParams", "localVarHeaderParams", "localVarFormParams",
"contentType", "authNames", "localVarPostBody", "localVarAccepts", "localVarAccept", "localVarContentTypes",
"localVarContentType", "localVarAuthNames", "localReturnType",
// language reserved words // language reserved words
"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",
"this", "break", "double", "implements", "protected", "throw", "byte", "else", "this", "break", "double", "implements", "protected", "throw", "byte", "else",
"import", "public", "throws", "case", "enum", "instanceof", "return", "transient", "import", "public", "throws", "case", "enum", "instanceof", "return", "transient",
"catch", "extends", "int", "short", "try", "char", "final", "interface", "static", "catch", "extends", "int", "short", "try", "char", "final", "interface", "static",
"void", "class", "finally", "long", "strictfp", "volatile", "const", "float", "void", "class", "finally", "long", "strictfp", "volatile", "const", "float",
"native", "super", "while") "native", "super", "while")
); );
languageSpecificPrimitives = new HashSet<String>( languageSpecificPrimitives = new HashSet<String>(
@ -72,6 +83,8 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
); );
instantiationTypes.put("array", "ArrayList"); instantiationTypes.put("array", "ArrayList");
instantiationTypes.put("map", "HashMap"); instantiationTypes.put("map", "HashMap");
typeMapping.put("date", "Date");
typeMapping.put("file", "File");
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));
@ -85,18 +98,28 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
cliOptions.add(CliOption.newBoolean(CodegenConstants.SERIALIZE_BIG_DECIMAL_AS_STRING, CodegenConstants cliOptions.add(CliOption.newBoolean(CodegenConstants.SERIALIZE_BIG_DECIMAL_AS_STRING, CodegenConstants
.SERIALIZE_BIG_DECIMAL_AS_STRING_DESC)); .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(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-beta4). 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
@ -172,12 +195,18 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
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,13 +240,13 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
importMapping.put("StringUtil", invokerPackage + ".StringUtil"); 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(".", "/");
@ -229,7 +258,7 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
supportingFiles.add(new SupportingFile("auth/OAuth.mustache", authFolder, "OAuth.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/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"));
@ -246,12 +275,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() {
@ -292,7 +349,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";
@ -308,7 +365,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);
} }
@ -322,17 +379,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 = "Model" + camelizedName;
LOGGER.warn(camelizedName + " (reserved word) cannot be used as model name. Renamed to " + modelName);
return modelName;
}
return camelizedName;
} }
@Override @Override
@ -428,7 +489,9 @@ 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") ||
type.equals("File") || type.equals("Date")) {
return type; return type;
} }
} else { } else {
@ -447,12 +510,16 @@ 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
@ -462,7 +529,7 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
if (allDefinitions != null && codegenModel != null && codegenModel.parentSchema != null && codegenModel.hasEnums) { if (allDefinitions != null && codegenModel != null && codegenModel.parentSchema != null && codegenModel.hasEnums) {
final Model parentModel = allDefinitions.get(codegenModel.parentSchema); 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;
@ -481,7 +548,13 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
} }
} }
if(model.isEnum == null || model.isEnum) { 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 // needed by all pojos, but not enums
model.imports.add("ApiModelProperty"); model.imports.add("ApiModelProperty");
model.imports.add("ApiModel"); model.imports.add("ApiModel");
@ -492,7 +565,7 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
if(StringUtils.isEmpty(lib) || "feign".equals(lib) || "jersey2".equals(lib)) { if(StringUtils.isEmpty(lib) || "feign".equals(lib) || "jersey2".equals(lib)) {
model.imports.add("JsonProperty"); model.imports.add("JsonProperty");
if(model.hasEnums != null || model.hasEnums == true) { if(BooleanUtils.toBoolean(model.hasEnums)) {
model.imports.add("JsonValue"); model.imports.add("JsonValue");
} }
} }
@ -567,7 +640,18 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override @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");
@ -583,7 +667,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);
} }
} }
@ -617,7 +701,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()) {
@ -648,14 +732,14 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
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;
@ -664,7 +748,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
@ -748,8 +832,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";
@ -760,4 +844,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 {
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",
@ -65,10 +71,10 @@ 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")
@ -155,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) {
@ -163,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);
@ -174,12 +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";
} }
@Override
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,22 +4,26 @@ 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 dateLibrary = "default"; protected String dateLibrary = "default";
protected String title = "Swagger Server"; protected String title = "Swagger Server";
protected String implFolder = "src/main/java"; protected String implFolder = "src/main/java";
public static final String DATE_LIBRARY = "dateLibrary"; public static final String DATE_LIBRARY = "dateLibrary";
public JaxRSServerCodegen() {
public JavaResteasyServerCodegen() {
super(); 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 = "generated-code/javaJaxRS"; outputFolder = "generated-code/javaJaxRS";
modelTemplateFiles.put("model.mustache", ".java"); modelTemplateFiles.put("model.mustache", ".java");
@ -32,10 +36,10 @@ public class JaxRSServerCodegen extends JavaClientCodegen implements CodegenConf
additionalProperties.put("title", title); additionalProperties.put("title", title);
embeddedTemplateDir = templateDir = "JavaJaxRS" + File.separator + "jersey1_18"; embeddedTemplateDir = templateDir = "JavaJaxRS" + File.separator + "resteasy";
for(int i = 0; i < cliOptions.size(); i++) { for (int i = 0; i < cliOptions.size(); i++) {
if(CodegenConstants.LIBRARY.equals(cliOptions.get(i).getOpt())) { if (CodegenConstants.LIBRARY.equals(cliOptions.get(i).getOpt())) {
cliOptions.remove(i); cliOptions.remove(i);
break; break;
} }
@ -54,8 +58,7 @@ public class JaxRSServerCodegen extends JavaClientCodegen implements CodegenConf
Map<String, String> supportedLibraries = new LinkedHashMap<String, String>(); Map<String, String> supportedLibraries = new LinkedHashMap<String, String>();
supportedLibraries.put(DEFAULT_LIBRARY, "Jersey core 1.18.1"); supportedLibraries.put(DEFAULT_LIBRARY, "Resteasy core 3.0.11");
// supportedLibraries.put("jersey2", "Jersey2 core library 2.x");
library.setEnum(supportedLibraries); library.setEnum(supportedLibraries);
cliOptions.add(library); cliOptions.add(library);
@ -69,29 +72,27 @@ public class JaxRSServerCodegen extends JavaClientCodegen implements CodegenConf
@Override @Override
public String getName() { public String getName() {
return "jaxrs"; return "jaxrs-resteasy";
} }
@Override @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)) { if (additionalProperties.containsKey(CodegenConstants.IMPL_FOLDER)) {
implFolder = (String) additionalProperties.get(CodegenConstants.IMPL_FOLDER); implFolder = (String) additionalProperties.get(CodegenConstants.IMPL_FOLDER);
} }
// if("jersey2".equals(getLibrary())) {
// embeddedTemplateDir = templateDir = "JavaJaxRS" + File.separator + "jersey2";
// }
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",
@ -100,29 +101,35 @@ 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", supportingFiles.add(new SupportingFile("StringUtil.mustache",
(sourceFolder + '/' + apiPackage).replace(".", "/"), "StringUtil.java")); (sourceFolder + '/' + invokerPackage).replace(".", "/"), "StringUtil.java"));
if (additionalProperties.containsKey("dateLibrary")) { if (additionalProperties.containsKey("dateLibrary")) {
setDateLibrary(additionalProperties.get("dateLibrary").toString()); setDateLibrary(additionalProperties.get("dateLibrary").toString());
additionalProperties.put(dateLibrary, "true"); additionalProperties.put(dateLibrary, "true");
} }
if("joda".equals(dateLibrary)) { if ("joda".equals(dateLibrary)) {
typeMapping.put("date", "LocalDate"); typeMapping.put("date", "LocalDate");
typeMapping.put("DateTime", "DateTime"); typeMapping.put("DateTime", "DateTime");
importMapping.put("LocalDate", "org.joda.time.LocalDate"); importMapping.put("LocalDate", "org.joda.time.LocalDate");
importMapping.put("DateTime", "org.joda.time.DateTime"); importMapping.put("DateTime", "org.joda.time.DateTime");
supportingFiles.add(new SupportingFile("JacksonConfig.mustache",
(sourceFolder + '/' + invokerPackage).replace(".", "/"), "JacksonConfig.java"));
supportingFiles.add(new SupportingFile("JodaDateTimeProvider.mustache", supportingFiles.add(new SupportingFile("JodaDateTimeProvider.mustache",
(sourceFolder + '/' + apiPackage).replace(".", "/"), "JodaDateTimeProvider.java")); (sourceFolder + '/' + apiPackage).replace(".", "/"), "JodaDateTimeProvider.java"));
supportingFiles.add(new SupportingFile("JodaLocalDateProvider.mustache", supportingFiles.add(new SupportingFile("JodaLocalDateProvider.mustache",
(sourceFolder + '/' + apiPackage).replace(".", "/"), "JodaLocalDateProvider.java")); (sourceFolder + '/' + apiPackage).replace(".", "/"), "JodaLocalDateProvider.java"));
} } else if ("java8".equals(dateLibrary)) {
else if ("java8".equals(dateLibrary)) {
additionalProperties.put("java8", "true"); additionalProperties.put("java8", "true");
additionalProperties.put("javaVersion", "1.8"); additionalProperties.put("javaVersion", "1.8");
typeMapping.put("date", "LocalDate"); typeMapping.put("date", "LocalDate");
@ -165,38 +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("");
} }
String host = swagger.getHost(); String host = swagger.getHost();
String port = "8080"; String port = "8080";
if(host != null) { if (host != null) {
String[] parts = host.split(":"); String[] parts = host.split(":");
if(parts.length > 1) { if (parts.length > 1) {
port = parts[1]; port = parts[1];
} }
} }
this.additionalProperties.put("serverPort", port); this.additionalProperties.put("serverPort", port);
if(swagger != null && swagger.getPaths() != null) { if (swagger != null && swagger.getPaths() != null) {
for(String pathname : swagger.getPaths().keySet()) { 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));
} }
@ -208,12 +216,22 @@ public class JaxRSServerCodegen extends JavaClientCodegen implements CodegenConf
} }
} }
@Override @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) {
@ -260,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) {
@ -283,6 +302,7 @@ 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('.', '/');
} }
@ -295,4 +315,31 @@ public class JaxRSServerCodegen extends JavaClientCodegen implements CodegenConf
public void setDateLibrary(String library) { public void setDateLibrary(String library) {
this.dateLibrary = 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,6 +52,8 @@ 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; protected String projectName;
protected String moduleName; protected String moduleName;
@ -47,6 +62,8 @@ public class JavascriptClientCodegen extends DefaultCodegen implements CodegenCo
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,10 @@ 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");
typeMapping.put("file", "File");
// binary not supported in JavaScript client right now, using String as a workaround
typeMapping.put("binary", "String");
importMapping.clear(); importMapping.clear();
} }
@ -159,14 +186,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 +216,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 +235,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 +261,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 +277,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 +292,28 @@ 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 (!StringUtils.isEmpty(modelNamePrefix)) {
if (reservedWords.contains(name)) { name = modelNamePrefix + "_" + name;
throw new RuntimeException(name + " (reserved word) cannot be used as a model name"); }
if (!StringUtils.isEmpty(modelNameSuffix)) {
name = name + "_" + modelNameSuffix;
} }
// 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 = "Model" + name;
LOGGER.warn(name + " (reserved word) cannot be used as model name. Renamed to " + modelName);
return modelName;
}
return name;
} }
@Override @Override
@ -289,58 +337,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 +432,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 +460,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,28 +538,18 @@ 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) {
@Override lastRequired = var;
public Map<String, Object> postProcessOperations(Map<String, Object> objs) { }
if("retrofit".equals(getLibrary())) { }
Map<String, Object> operations = (Map<String, Object>) objs.get("operations"); for (CodegenProperty var : cm.vars) {
if (operations != null) { if (var == lastRequired) {
List<CodegenOperation> ops = (List<CodegenOperation>) operations.get("operation"); var.vendorExtensions.put("x-codegen-hasMoreRequired", false);
for (CodegenOperation operation : ops) { } else if (var.required != null && var.required) {
if (operation.hasConsumes == Boolean.TRUE) { var.vendorExtensions.put("x-codegen-hasMoreRequired", true);
Map<String, String> firstType = operation.consumes.get(0);
if (firstType != null) {
if ("multipart/form-data".equals(firstType.get("mediaType"))) {
operation.isMultipart = Boolean.TRUE;
}
}
}
if (operation.returnType == null) {
operation.returnType = "Void";
}
} }
} }
} }
@ -465,14 +562,14 @@ public class JavascriptClientCodegen extends DefaultCodegen implements CodegenCo
&& !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;
@ -481,7 +578,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
@ -529,7 +626,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,227 @@
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;
import org.apache.commons.lang.StringUtils;
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) {
if (!StringUtils.isEmpty(modelNamePrefix)) {
name = modelNamePrefix + "_" + name;
}
if (!StringUtils.isEmpty(modelNameSuffix)) {
name = 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("model_" + name));
name = "model_" + name; // e.g. return => ModelReturn (after camelize)
}
// 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

@ -8,11 +8,11 @@ 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.models.Info;
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.io.IOException;
@ -21,6 +21,9 @@ 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";
@ -57,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",
@ -86,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
@ -185,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;
@ -212,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");
@ -222,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) {
@ -247,7 +242,6 @@ public class NodeJSServerCodegen extends DefaultCodegen implements CodegenConfig
@Override @Override
public void preprocessSwagger(Swagger swagger) { public void preprocessSwagger(Swagger swagger) {
String host = swagger.getHost(); String host = swagger.getHost();
String port = "8080"; String port = "8080";
if (host != null) { if (host != null) {
@ -267,6 +261,28 @@ public class NodeJSServerCodegen extends DefaultCodegen implements CodegenConfig
this.additionalProperties.put("projectName", projectName); 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 @Override
@ -284,7 +300,7 @@ public class NodeJSServerCodegen extends DefaultCodegen implements CodegenConfig
}); });
objs.put("swagger-yaml", Yaml.mapper().registerModule(module).writeValueAsString(swagger)); 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)) {

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;
@ -84,15 +87,18 @@ 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(
// local variable names in API methods (endpoints) // local variable names in API methods (endpoints)
"resourcePath", "pathParams", "queryParams", "headerParams", "resourcePath", "pathParams", "queryParams", "headerParams",
"responseContentType", "requestContentType", "authSettings", "responseContentType", "requestContentType", "authSettings",
"formParams", "files", "bodyParam", "formParams", "localVarFiles", "bodyParam",
// objc reserved words // objc reserved words
"auto", "else", "long", "switch", "auto", "else", "long", "switch",
"break", "enum", "register", "typedef", "break", "enum", "register", "typedef",
@ -219,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;
@ -247,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
@ -312,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 " + ("model_" + type) + " before further processing");
type = "model_" + type; // e.g. return => ModelReturn (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) ||
@ -324,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
} }
} }
@ -372,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_]$")) {
@ -390,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);
} }
@ -409,6 +436,7 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
return "_" + name; return "_" + name;
} }
@SuppressWarnings("static-method")
public String escapeSpecialWord(String name) { public String escapeSpecialWord(String name) {
return "var_" + name; return "var_" + name;
} }
@ -421,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);
@ -456,6 +485,21 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
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

@ -7,13 +7,13 @@ import io.swagger.codegen.SupportingFile;
import io.swagger.codegen.CodegenConstants; import io.swagger.codegen.CodegenConstants;
import io.swagger.codegen.CliOption; import io.swagger.codegen.CliOption;
import io.swagger.models.properties.ArrayProperty; import io.swagger.models.properties.ArrayProperty;
import io.swagger.models.properties.BooleanProperty;
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 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;
@ -21,19 +21,23 @@ 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 = "WWW::SwaggerClient"; protected String moduleName = "WWW::SwaggerClient";
protected String modulePathPart = moduleName.replaceAll("::",String.valueOf(File.separatorChar)); 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",
@ -44,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"
) )
); );
@ -71,6 +76,9 @@ public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig {
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 or Long::Module).").defaultValue("SwaggerClient")); cliOptions.add(new CliOption(MODULE_NAME, "Perl module name (convention: CamelCase or Long::Module).").defaultValue("SwaggerClient"));
@ -95,7 +103,7 @@ 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("::",String.valueOf(File.separatorChar))); setModulePathPart(moduleName.replaceAll("::", Matcher.quoteReplacement(File.separator)));
} else { } else {
additionalProperties.put(MODULE_NAME, moduleName); additionalProperties.put(MODULE_NAME, moduleName);
} }
@ -139,6 +147,17 @@ public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig {
return (outputFolder + "/lib/" + modulePathPart + 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
public String getTypeDeclaration(Property p) { public String getTypeDeclaration(Property p) {
if (p instanceof ArrayProperty) { if (p instanceof ArrayProperty) {
@ -168,7 +187,7 @@ public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig {
if (type == null) { if (type == null) {
return null; return null;
} }
return type; return toModelName(type);
} }
@Override @Override
@ -181,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;
} }
@ -200,9 +218,21 @@ public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override @Override
public String toModelName(String name) { public String toModelName(String name) {
name = sanitizeName(name); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
// 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("model_" + name));
name = "model_" + name;
}
// add prefix/suffic to model name
if (!StringUtils.isEmpty(modelNamePrefix)) {
name = modelNamePrefix + "_" + name;
}
if (!StringUtils.isEmpty(modelNameSuffix)) {
name = name + "_" + modelNameSuffix;
} }
// camelize the model name // camelize the model name
@ -216,10 +246,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";
@ -236,14 +276,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);

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,14 +42,17 @@ 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(
// local variables used in api methods (endpoints) // local variables used in api methods (endpoints)
"resourcePath", "method", "httpBody", "queryParams", "headerParams", "resourcePath", "httpBody", "queryParams", "headerParams",
"formParams", "_header_accept", "_tempBody", "formParams", "_header_accept", "_tempBody",
// PHP reserved words // PHP reserved words
@ -97,6 +101,7 @@ public class PhpClientCodegen 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");
typeMapping.put("binary", "string");
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));
@ -115,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;
@ -218,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
@ -235,6 +242,16 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
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) {
@ -312,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
@ -341,15 +358,24 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override @Override
public String toModelName(String name) { public String toModelName(String name) {
// remove [
name = name.replaceAll("\\]", "");
// 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("model_" + name));
name = "model_" + name; // e.g. return => ModelReturn (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
@ -363,6 +389,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
@ -371,8 +403,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

@ -51,13 +51,16 @@ 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(
// local variable name used in API methods (endpoints) // local variable name used in API methods (endpoints)
"all_params", "resource_path", "method", "path_params", "query_params", "all_params", "resource_path", "path_params", "query_params",
"header_params", "form_params", "files", "body_params", "auth_settings", "header_params", "form_params", "local_var_files", "body_params", "auth_settings",
// python reserved words // python reserved words
"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",
@ -176,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("$", "");
@ -194,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);
} }
@ -209,14 +212,22 @@ public class PythonClientCodegen 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'.
// 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("model_" + name));
name = "model_" + name; // e.g. return => ModelReturn (after camelize)
}
if (!StringUtils.isEmpty(modelNamePrefix)) {
name = modelNamePrefix + "_" + name;
}
if (!StringUtils.isEmpty(modelNameSuffix)) {
name = name + "_" + modelNameSuffix;
} }
// camelize the model name // camelize the model name
@ -226,9 +237,22 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
@Override @Override
public String toModelFilename(String name) { public String toModelFilename(String name) {
name = sanitizeName(name); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
// remove dollar sign
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 filename. Renamed to " + underscore(dropDots("model_" + name)));
name = "model_" + name; // e.g. return => ModelReturn (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
@ -264,14 +288,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));
@ -290,7 +315,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>();

View File

@ -14,8 +14,11 @@ 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";
@ -29,6 +32,7 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
protected String gemName; protected String gemName;
protected String moduleName; 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 gemLicense = "Apache-2.0";
protected String gemHomepage = "http://swagger.io"; protected String gemHomepage = "http://swagger.io";
@ -37,6 +41,7 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
protected String gemAuthor = ""; protected String gemAuthor = "";
protected String gemAuthorEmail = ""; protected String gemAuthorEmail = "";
protected static int emptyMethodNameCounter = 0;
public RubyClientCodegen() { public RubyClientCodegen() {
super(); super();
@ -47,13 +52,13 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
apiTemplateFiles.put("api.mustache", ".rb"); apiTemplateFiles.put("api.mustache", ".rb");
embeddedTemplateDir = templateDir = "ruby"; embeddedTemplateDir = templateDir = "ruby";
typeMapping.clear(); modelTestTemplateFiles.put("model_test.mustache", ".rb");
languageSpecificPrimitives.clear(); apiTestTemplateFiles.put("api_test.mustache", ".rb");
reservedWords = new HashSet<String>( setReservedWordsLowerCase(
Arrays.asList( Arrays.asList(
// local variable names used in API methods (endpoints) // local variable names used in API methods (endpoints)
"path", "query_params", "header_params", "_header_accept", "_header_accept_result", "local_var_path", "query_params", "header_params", "_header_accept", "_header_accept_result",
"_header_content_type", "form_params", "post_body", "auth_names", "_header_content_type", "form_params", "post_body", "auth_names",
// ruby reserved keywords // ruby reserved keywords
"__FILE__", "and", "def", "end", "in", "or", "self", "unless", "__LINE__", "__FILE__", "and", "def", "end", "in", "or", "self", "unless", "__LINE__",
@ -63,11 +68,25 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
"if", "not", "return", "undef", "yield") "if", "not", "return", "undef", "yield")
); );
typeMapping.clear();
languageSpecificPrimitives.clear();
// primitives in ruby lang
languageSpecificPrimitives.add("int"); languageSpecificPrimitives.add("int");
languageSpecificPrimitives.add("array"); languageSpecificPrimitives.add("array");
languageSpecificPrimitives.add("map"); languageSpecificPrimitives.add("map");
languageSpecificPrimitives.add("string"); languageSpecificPrimitives.add("string");
// primitives in the typeMapping
languageSpecificPrimitives.add("String");
languageSpecificPrimitives.add("Integer");
languageSpecificPrimitives.add("Float");
languageSpecificPrimitives.add("Date");
languageSpecificPrimitives.add("DateTime"); languageSpecificPrimitives.add("DateTime");
languageSpecificPrimitives.add("BOOLEAN");
languageSpecificPrimitives.add("Array");
languageSpecificPrimitives.add("Hash");
languageSpecificPrimitives.add("File");
languageSpecificPrimitives.add("Object");
typeMapping.put("string", "String"); typeMapping.put("string", "String");
typeMapping.put("char", "String"); typeMapping.put("char", "String");
@ -86,6 +105,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();
@ -186,7 +206,6 @@ 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);
} }
@ -207,14 +226,22 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
/** /**
* 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]+", ""));
} }
@ -234,6 +261,16 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
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) {
@ -300,14 +337,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_]*$")) {
name = name.toLowerCase(); name = name.toLowerCase();
@ -318,7 +354,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);
} }
@ -333,11 +369,21 @@ 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'.
if (!StringUtils.isEmpty(modelNamePrefix)) {
name = modelNamePrefix + "_" + name;
}
if (!StringUtils.isEmpty(modelNameSuffix)) {
name = name + "_" + modelNameSuffix;
}
// 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("Model" + 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
@ -347,9 +393,20 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override @Override
public String toModelFilename(String name) { public String toModelFilename(String name) {
name = sanitizeName(name); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
if (!StringUtils.isEmpty(modelNamePrefix)) {
name = modelNamePrefix + "_" + name;
}
if (!StringUtils.isEmpty(modelNameSuffix)) {
name = name + "_" + modelNameSuffix;
}
// 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("model_" + 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
@ -360,12 +417,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 toApiFilename(name) + "_spec";
}
@Override
public String toModelTestFilename(String name) {
return toModelFilename(name) + "_spec";
}
@Override @Override
public String toApiName(String name) { public String toApiName(String name) {
if (name.length() == 0) { if (name.length() == 0) {
@ -377,24 +444,23 @@ 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));
} }
@Override
public String toModelImport(String name) {
return gemName + "/" + modelPackage() + "/" + toModelFilename(name);
}
@Override @Override
public String toApiImport(String name) { public String toApiImport(String name) {
return gemName + "/" + apiPackage() + "/" + toApiFilename(name); return gemName + "/" + apiPackage() + "/" + toApiFilename(name);

View File

@ -47,7 +47,7 @@ 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(
// local variable names used in API methods (endpoints) // local variable names used in API methods (endpoints)
"path", "contentTypes", "contentType", "queryParams", "headerParams", "path", "contentTypes", "contentType", "queryParams", "headerParams",
@ -96,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(
@ -232,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");

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")
); );
@ -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"));
@ -162,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
@ -182,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,8 +18,13 @@ 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 {
private static final Logger LOGGER = LoggerFactory.getLogger(SinatraServerCodegen.class);
protected String gemName; protected String gemName;
protected String moduleName; protected String moduleName;
protected String gemVersion = "1.0.0"; protected String gemVersion = "1.0.0";
@ -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();
@ -146,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_]*$")) {
@ -158,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);
} }
@ -174,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");
} }
@ -186,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");
} }
@ -198,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";
@ -216,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");
} }
@ -230,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")
); );
@ -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"));
@ -177,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
@ -208,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
} }

View File

@ -6,7 +6,7 @@ import io.swagger.models.Operation;
import java.io.File; import java.io.File;
import java.util.*; import java.util.*;
public class SpringMVCServerCodegen extends JavaClientCodegen implements CodegenConfig { public class SpringMVCServerCodegen extends JavaClientCodegen {
public static final String CONFIG_PACKAGE = "configPackage"; public static final String CONFIG_PACKAGE = "configPackage";
protected String title = "Petstore Server"; protected String title = "Petstore Server";
protected String configPackage = ""; protected String configPackage = "";
@ -34,6 +34,7 @@ public class SpringMVCServerCodegen extends JavaClientCodegen implements Codegen
languageSpecificPrimitives = new HashSet<String>( languageSpecificPrimitives = new HashSet<String>(
Arrays.asList( Arrays.asList(
"byte[]",
"String", "String",
"boolean", "boolean",
"Boolean", "Boolean",

View File

@ -1,5 +1,6 @@
package io.swagger.codegen.languages; package io.swagger.codegen.languages;
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.CodegenType; import io.swagger.codegen.CodegenType;
@ -22,6 +23,11 @@ public class StaticDocCodegen extends DefaultCodegen implements CodegenConfig {
apiTemplateFiles.put("operation.mustache", ".html"); apiTemplateFiles.put("operation.mustache", ".html");
embeddedTemplateDir = templateDir = "swagger-static"; embeddedTemplateDir = templateDir = "swagger-static";
cliOptions.add(new CliOption(CodegenConstants.INVOKER_PACKAGE, CodegenConstants.INVOKER_PACKAGE_DESC));
cliOptions.add(new CliOption(CodegenConstants.GROUP_ID, CodegenConstants.GROUP_ID_DESC));
cliOptions.add(new CliOption(CodegenConstants.ARTIFACT_ID, CodegenConstants.ARTIFACT_ID_DESC));
cliOptions.add(new CliOption(CodegenConstants.ARTIFACT_VERSION, CodegenConstants.ARTIFACT_VERSION_DESC));
additionalProperties.put(CodegenConstants.INVOKER_PACKAGE, invokerPackage); additionalProperties.put(CodegenConstants.INVOKER_PACKAGE, invokerPackage);
additionalProperties.put(CodegenConstants.GROUP_ID, groupId); additionalProperties.put(CodegenConstants.GROUP_ID, groupId);
additionalProperties.put(CodegenConstants.ARTIFACT_ID, artifactId); additionalProperties.put(CodegenConstants.ARTIFACT_ID, artifactId);

View File

@ -1,5 +1,6 @@
package io.swagger.codegen.languages; package io.swagger.codegen.languages;
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.CodegenOperation;
@ -32,6 +33,17 @@ public class StaticHtmlGenerator extends DefaultCodegen implements CodegenConfig
defaultIncludes = new HashSet<String>(); defaultIncludes = new HashSet<String>();
cliOptions.add(new CliOption("appName", "short name of the application"));
cliOptions.add(new CliOption("appDescription", "description of the application"));
cliOptions.add(new CliOption("infoUrl", "a URL where users can get more information about the application"));
cliOptions.add(new CliOption("infoEmail", "an email address to contact for inquiries about the application"));
cliOptions.add(new CliOption("licenseInfo", "a short description of the license"));
cliOptions.add(new CliOption("licenseUrl", "a URL pointing to the full license"));
cliOptions.add(new CliOption(CodegenConstants.INVOKER_PACKAGE, CodegenConstants.INVOKER_PACKAGE_DESC));
cliOptions.add(new CliOption(CodegenConstants.GROUP_ID, CodegenConstants.GROUP_ID_DESC));
cliOptions.add(new CliOption(CodegenConstants.ARTIFACT_ID, CodegenConstants.ARTIFACT_ID_DESC));
cliOptions.add(new CliOption(CodegenConstants.ARTIFACT_VERSION, CodegenConstants.ARTIFACT_VERSION_DESC));
additionalProperties.put("appName", "Swagger Sample"); additionalProperties.put("appName", "Swagger Sample");
additionalProperties.put("appDescription", "A sample swagger server"); additionalProperties.put("appDescription", "A sample swagger server");
additionalProperties.put("infoUrl", "https://helloreverb.com"); additionalProperties.put("infoUrl", "https://helloreverb.com");
@ -89,20 +101,4 @@ public class StaticHtmlGenerator extends DefaultCodegen implements CodegenConfig
} }
return objs; return objs;
} }
@Override
public void addOperationToGroup(String tag, String resourcePath, Operation operation, CodegenOperation co, Map<String, List<CodegenOperation>> operations) {
List<CodegenOperation> opList = operations.get(ALL_OPERATIONS);
if (opList == null) {
opList = new ArrayList<CodegenOperation>();
operations.put(ALL_OPERATIONS, opList);
}
for (CodegenOperation addedOperation : opList) {
if (addedOperation.operationId.equals(co.operationId) && addedOperation.path.equals(co.path) && addedOperation.httpMethod.equals(co.httpMethod)) {
addedOperation.tags.addAll(co.tags);
return;
}
}
opList.add(co);
}
} }

View File

@ -1,16 +1,22 @@
package io.swagger.codegen.languages; package io.swagger.codegen.languages;
import java.io.File;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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;
import io.swagger.codegen.SupportingFile; import io.swagger.codegen.SupportingFile;
import io.swagger.models.Swagger; import io.swagger.models.Swagger;
import io.swagger.util.Json; import io.swagger.util.Json;
import org.apache.commons.io.FileUtils;
import java.io.File;
public class SwaggerGenerator extends DefaultCodegen implements CodegenConfig { public class SwaggerGenerator extends DefaultCodegen implements CodegenConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(SwaggerGenerator.class);
public SwaggerGenerator() { public SwaggerGenerator() {
super(); super();
embeddedTemplateDir = templateDir = "swagger"; embeddedTemplateDir = templateDir = "swagger";
@ -41,9 +47,9 @@ public class SwaggerGenerator extends DefaultCodegen implements CodegenConfig {
try { try {
String outputFile = outputFolder + File.separator + "swagger.json"; String outputFile = outputFolder + File.separator + "swagger.json";
FileUtils.writeStringToFile(new File(outputFile), swaggerString); FileUtils.writeStringToFile(new File(outputFile), swaggerString);
System.out.println("wrote file to " + outputFile); LOGGER.debug("wrote file to " + outputFile);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); LOGGER.error(e.getMessage(), e);
} }
} }
} }

View File

@ -1,16 +1,22 @@
package io.swagger.codegen.languages; package io.swagger.codegen.languages;
import java.io.File;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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;
import io.swagger.codegen.SupportingFile; import io.swagger.codegen.SupportingFile;
import io.swagger.models.Swagger; import io.swagger.models.Swagger;
import io.swagger.util.Yaml; import io.swagger.util.Yaml;
import org.apache.commons.io.FileUtils;
import java.io.File;
public class SwaggerYamlGenerator extends DefaultCodegen implements CodegenConfig { public class SwaggerYamlGenerator extends DefaultCodegen implements CodegenConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(SwaggerYamlGenerator.class);
public SwaggerYamlGenerator() { public SwaggerYamlGenerator() {
super(); super();
embeddedTemplateDir = templateDir = "swagger"; embeddedTemplateDir = templateDir = "swagger";
@ -40,9 +46,9 @@ public class SwaggerYamlGenerator extends DefaultCodegen implements CodegenConfi
String swaggerString = Yaml.mapper().writeValueAsString(swagger); String swaggerString = Yaml.mapper().writeValueAsString(swagger);
String outputFile = outputFolder + File.separator + "swagger.yaml"; String outputFile = outputFolder + File.separator + "swagger.yaml";
FileUtils.writeStringToFile(new File(outputFile), swaggerString); FileUtils.writeStringToFile(new File(outputFile), swaggerString);
System.out.println("wrote file to " + outputFile); LOGGER.debug("wrote file to " + outputFile);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); LOGGER.error(e.getMessage(), e);
} }
} }
} }

View File

@ -24,249 +24,312 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
public class SwiftCodegen extends DefaultCodegen implements CodegenConfig { public class SwiftCodegen extends DefaultCodegen implements CodegenConfig {
public static final String PROJECT_NAME = "projectName"; public static final String PROJECT_NAME = "projectName";
public static final String RESPONSE_AS = "responseAs"; public static final String RESPONSE_AS = "responseAs";
public static final String UNWRAP_REQUIRED = "unwrapRequired"; public static final String UNWRAP_REQUIRED = "unwrapRequired";
public static final String POD_SOURCE = "podSource"; public static final String POD_SOURCE = "podSource";
public static final String POD_AUTHORS = "podAuthors"; public static final String POD_AUTHORS = "podAuthors";
public static final String POD_SOCIAL_MEDIA_URL = "podSocialMediaURL"; public static final String POD_SOCIAL_MEDIA_URL = "podSocialMediaURL";
public static final String POD_DOCSET_URL = "podDocsetURL"; public static final String POD_DOCSET_URL = "podDocsetURL";
public static final String POD_LICENSE = "podLicense"; public static final String POD_LICENSE = "podLicense";
public static final String POD_HOMEPAGE = "podHomepage"; public static final String POD_HOMEPAGE = "podHomepage";
public static final String POD_SUMMARY = "podSummary"; public static final String POD_SUMMARY = "podSummary";
public static final String POD_DESCRIPTION = "podDescription"; public static final String POD_DESCRIPTION = "podDescription";
public static final String POD_SCREENSHOTS = "podScreenshots"; public static final String POD_SCREENSHOTS = "podScreenshots";
public static final String POD_DOCUMENTATION_URL = "podDocumentationURL"; public static final String POD_DOCUMENTATION_URL = "podDocumentationURL";
protected static final String LIBRARY_PROMISE_KIT = "PromiseKit"; public static final String SWIFT_USE_API_NAMESPACE = "swiftUseApiNamespace";
protected static final String[] RESPONSE_LIBRARIES = { LIBRARY_PROMISE_KIT }; protected static final String LIBRARY_PROMISE_KIT = "PromiseKit";
protected String projectName = "SwaggerClient"; protected static final String[] RESPONSE_LIBRARIES = { LIBRARY_PROMISE_KIT };
protected boolean unwrapRequired; protected String projectName = "SwaggerClient";
protected String[] responseAs = new String[0]; protected boolean unwrapRequired;
protected String sourceFolder = "Classes" + File.separator + "Swaggers"; protected boolean swiftUseApiNamespace;
private static final Pattern PATH_PARAM_PATTERN = Pattern.compile("\\{[a-zA-Z_]+\\}"); protected String[] responseAs = new String[0];
protected String sourceFolder = "Classes" + File.separator + "Swaggers";
private static final Pattern PATH_PARAM_PATTERN = Pattern.compile("\\{[a-zA-Z_]+\\}");
@Override @Override
public CodegenType getTag() { public CodegenType getTag() {
return CodegenType.CLIENT; return CodegenType.CLIENT;
}
@Override
public String getName() {
return "swift";
}
@Override
public String getHelp() {
return "Generates a swift client library.";
}
public SwiftCodegen() {
super();
outputFolder = "generated-code" + File.separator + "swift";
modelTemplateFiles.put("model.mustache", ".swift");
apiTemplateFiles.put("api.mustache", ".swift");
embeddedTemplateDir = templateDir = "swift";
apiPackage = File.separator + "APIs";
modelPackage = File.separator + "Models";
languageSpecificPrimitives = new HashSet<String>(
Arrays.asList(
"Int",
"Float",
"Double",
"Bool",
"Void",
"String",
"Character")
);
defaultIncludes = new HashSet<String>(
Arrays.asList(
"NSDate",
"Array",
"Dictionary",
"Set",
"Any",
"Empty",
"AnyObject")
);
reservedWords = new HashSet<String>(
Arrays.asList(
"class", "break", "as", "associativity", "deinit", "case", "dynamicType", "convenience", "enum", "continue",
"false", "dynamic", "extension", "default", "is", "didSet", "func", "do", "nil", "final", "import", "else",
"self", "get", "init", "fallthrough", "Self", "infix", "internal", "for", "super", "inout", "let", "if",
"true", "lazy", "operator", "in", "COLUMN", "left", "private", "return", "FILE", "mutating", "protocol",
"switch", "FUNCTION", "none", "public", "where", "LINE", "nonmutating", "static", "while", "optional",
"struct", "override", "subscript", "postfix", "typealias", "precedence", "var", "prefix", "Protocol",
"required", "right", "set", "Type", "unowned", "weak")
);
typeMapping = new HashMap<String, String>();
typeMapping.put("array", "Array");
typeMapping.put("List", "Array");
typeMapping.put("map", "Dictionary");
typeMapping.put("date", "NSDate");
typeMapping.put("Date", "NSDate");
typeMapping.put("DateTime", "NSDate");
typeMapping.put("boolean", "Bool");
typeMapping.put("string", "String");
typeMapping.put("char", "Character");
typeMapping.put("short", "Int");
typeMapping.put("int", "Int");
typeMapping.put("long", "Int");
typeMapping.put("integer", "Int");
typeMapping.put("Integer", "Int");
typeMapping.put("float", "Float");
typeMapping.put("number", "Double");
typeMapping.put("double", "Double");
typeMapping.put("object", "String");
typeMapping.put("file", "NSURL");
importMapping = new HashMap<String, String>();
cliOptions.add(new CliOption(PROJECT_NAME, "Project name in Xcode"));
cliOptions.add(new CliOption(RESPONSE_AS, "Optionally use libraries to manage response. Currently " +
StringUtils.join(RESPONSE_LIBRARIES, ", ") + " are available."));
cliOptions.add(new CliOption(UNWRAP_REQUIRED, "Treat 'required' properties in response as non-optional " +
"(which would crash the app if api returns null as opposed to required option specified in json schema"));
cliOptions.add(new CliOption(POD_SOURCE, "Source information used for Podspec"));
cliOptions.add(new CliOption(CodegenConstants.POD_VERSION, "Version used for Podspec"));
cliOptions.add(new CliOption(POD_AUTHORS, "Authors used for Podspec"));
cliOptions.add(new CliOption(POD_SOCIAL_MEDIA_URL, "Social Media URL used for Podspec"));
cliOptions.add(new CliOption(POD_DOCSET_URL, "Docset URL used for Podspec"));
cliOptions.add(new CliOption(POD_LICENSE, "License used for Podspec"));
cliOptions.add(new CliOption(POD_HOMEPAGE, "Homepage used for Podspec"));
cliOptions.add(new CliOption(POD_SUMMARY, "Summary used for Podspec"));
cliOptions.add(new CliOption(POD_DESCRIPTION, "Description used for Podspec"));
cliOptions.add(new CliOption(POD_SCREENSHOTS, "Screenshots used for Podspec"));
cliOptions.add(new CliOption(POD_DOCUMENTATION_URL, "Documentation URL used for Podspec"));
}
@Override
public void processOpts() {
super.processOpts();
// Setup project name
if (additionalProperties.containsKey(PROJECT_NAME)) {
setProjectName((String) additionalProperties.get(PROJECT_NAME));
} else {
additionalProperties.put(PROJECT_NAME, projectName);
}
sourceFolder = projectName + File.separator + sourceFolder;
// Setup unwrapRequired option, which makes all the properties with "required" non-optional
if (additionalProperties.containsKey(UNWRAP_REQUIRED)) {
setUnwrapRequired(Boolean.parseBoolean(String.valueOf(additionalProperties.get(UNWRAP_REQUIRED))));
}
additionalProperties.put(UNWRAP_REQUIRED, unwrapRequired);
// Setup unwrapRequired option, which makes all the properties with "required" non-optional
if (additionalProperties.containsKey(RESPONSE_AS)) {
Object responseAsObject = additionalProperties.get(RESPONSE_AS);
if (responseAsObject instanceof String) {
setResponseAs(((String)responseAsObject).split(","));
} else {
setResponseAs((String[]) responseAsObject);
}
}
additionalProperties.put(RESPONSE_AS, responseAs);
if (ArrayUtils.contains(responseAs, LIBRARY_PROMISE_KIT)) {
additionalProperties.put("usePromiseKit", true);
} }
supportingFiles.add(new SupportingFile("Podspec.mustache", "", projectName + ".podspec")); @Override
supportingFiles.add(new SupportingFile("Cartfile.mustache", "", "Cartfile")); public String getName() {
supportingFiles.add(new SupportingFile("APIHelper.mustache", sourceFolder, "APIHelper.swift")); return "swift";
supportingFiles.add(new SupportingFile("AlamofireImplementations.mustache", sourceFolder,
"AlamofireImplementations.swift"));
supportingFiles.add(new SupportingFile("Extensions.mustache", sourceFolder, "Extensions.swift"));
supportingFiles.add(new SupportingFile("Models.mustache", sourceFolder, "Models.swift"));
supportingFiles.add(new SupportingFile("APIs.mustache", sourceFolder, "APIs.swift"));
}
@Override
public String escapeReservedWord(String name) {
return "Swagger" + name; // add an underscore to the name
}
@Override
public String modelFileFolder() {
return outputFolder + File.separator + sourceFolder + modelPackage().replace('.', File.separatorChar);
}
@Override
public String apiFileFolder() {
return outputFolder + File.separator + sourceFolder + apiPackage().replace('.', File.separatorChar);
}
@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 "[String:" + getTypeDeclaration(inner) + "]";
} }
return super.getTypeDeclaration(p);
}
@Override @Override
public String getSwaggerType(Property p) { public String getHelp() {
String swaggerType = super.getSwaggerType(p); return "Generates a swift client library.";
String type = null; }
if (typeMapping.containsKey(swaggerType)) {
type = typeMapping.get(swaggerType); public SwiftCodegen() {
if (languageSpecificPrimitives.contains(type)) super();
outputFolder = "generated-code" + File.separator + "swift";
modelTemplateFiles.put("model.mustache", ".swift");
apiTemplateFiles.put("api.mustache", ".swift");
embeddedTemplateDir = templateDir = "swift";
apiPackage = File.separator + "APIs";
modelPackage = File.separator + "Models";
languageSpecificPrimitives = new HashSet<String>(
Arrays.asList(
"Int",
"Float",
"Double",
"Bool",
"Void",
"String",
"Character",
"AnyObject")
);
defaultIncludes = new HashSet<String>(
Arrays.asList(
"NSDate",
"NSURL", // for file
"Array",
"Dictionary",
"Set",
"Any",
"Empty",
"AnyObject")
);
setReservedWordsLowerCase(
Arrays.asList(
"class", "break", "as", "associativity", "deinit", "case", "dynamicType", "convenience", "enum", "continue",
"false", "dynamic", "extension", "default", "is", "didSet", "func", "do", "nil", "final", "import", "else",
"self", "get", "init", "fallthrough", "Self", "infix", "internal", "for", "super", "inout", "let", "if",
"true", "lazy", "operator", "in", "COLUMN", "left", "private", "return", "FILE", "mutating", "protocol",
"switch", "FUNCTION", "none", "public", "where", "LINE", "nonmutating", "static", "while", "optional",
"struct", "override", "subscript", "postfix", "typealias", "precedence", "var", "prefix", "Protocol",
"required", "right", "set", "Type", "unowned", "weak")
);
typeMapping = new HashMap<String, String>();
typeMapping.put("array", "Array");
typeMapping.put("List", "Array");
typeMapping.put("map", "Dictionary");
typeMapping.put("date", "NSDate");
typeMapping.put("Date", "NSDate");
typeMapping.put("DateTime", "NSDate");
typeMapping.put("boolean", "Bool");
typeMapping.put("string", "String");
typeMapping.put("char", "Character");
typeMapping.put("short", "Int");
typeMapping.put("int", "Int");
typeMapping.put("long", "Int");
typeMapping.put("integer", "Int");
typeMapping.put("Integer", "Int");
typeMapping.put("float", "Float");
typeMapping.put("number", "Double");
typeMapping.put("double", "Double");
typeMapping.put("object", "AnyObject");
typeMapping.put("file", "NSURL");
//TODO binary should be mapped to byte array
// mapped to String as a workaround
typeMapping.put("binary", "String");
importMapping = new HashMap<String, String>();
cliOptions.add(new CliOption(PROJECT_NAME, "Project name in Xcode"));
cliOptions.add(new CliOption(RESPONSE_AS, "Optionally use libraries to manage response. Currently " +
StringUtils.join(RESPONSE_LIBRARIES, ", ") + " are available."));
cliOptions.add(new CliOption(UNWRAP_REQUIRED, "Treat 'required' properties in response as non-optional " +
"(which would crash the app if api returns null as opposed to required option specified in json schema"));
cliOptions.add(new CliOption(POD_SOURCE, "Source information used for Podspec"));
cliOptions.add(new CliOption(CodegenConstants.POD_VERSION, "Version used for Podspec"));
cliOptions.add(new CliOption(POD_AUTHORS, "Authors used for Podspec"));
cliOptions.add(new CliOption(POD_SOCIAL_MEDIA_URL, "Social Media URL used for Podspec"));
cliOptions.add(new CliOption(POD_DOCSET_URL, "Docset URL used for Podspec"));
cliOptions.add(new CliOption(POD_LICENSE, "License used for Podspec"));
cliOptions.add(new CliOption(POD_HOMEPAGE, "Homepage used for Podspec"));
cliOptions.add(new CliOption(POD_SUMMARY, "Summary used for Podspec"));
cliOptions.add(new CliOption(POD_DESCRIPTION, "Description used for Podspec"));
cliOptions.add(new CliOption(POD_SCREENSHOTS, "Screenshots used for Podspec"));
cliOptions.add(new CliOption(POD_DOCUMENTATION_URL, "Documentation URL used for Podspec"));
cliOptions.add(new CliOption(SWIFT_USE_API_NAMESPACE, "Flag to make all the API classes inner-class of {{projectName}}API"));
}
@Override
public void processOpts() {
super.processOpts();
// Setup project name
if (additionalProperties.containsKey(PROJECT_NAME)) {
setProjectName((String) additionalProperties.get(PROJECT_NAME));
} else {
additionalProperties.put(PROJECT_NAME, projectName);
}
sourceFolder = projectName + File.separator + sourceFolder;
// Setup unwrapRequired option, which makes all the properties with "required" non-optional
if (additionalProperties.containsKey(UNWRAP_REQUIRED)) {
setUnwrapRequired(Boolean.parseBoolean(String.valueOf(additionalProperties.get(UNWRAP_REQUIRED))));
}
additionalProperties.put(UNWRAP_REQUIRED, unwrapRequired);
// Setup unwrapRequired option, which makes all the properties with "required" non-optional
if (additionalProperties.containsKey(RESPONSE_AS)) {
Object responseAsObject = additionalProperties.get(RESPONSE_AS);
if (responseAsObject instanceof String) {
setResponseAs(((String)responseAsObject).split(","));
} else {
setResponseAs((String[]) responseAsObject);
}
}
additionalProperties.put(RESPONSE_AS, responseAs);
if (ArrayUtils.contains(responseAs, LIBRARY_PROMISE_KIT)) {
additionalProperties.put("usePromiseKit", true);
}
// Setup swiftUseApiNamespace option, which makes all the API classes inner-class of {{projectName}}API
if (additionalProperties.containsKey(SWIFT_USE_API_NAMESPACE)) {
swiftUseApiNamespace = Boolean.parseBoolean(String.valueOf(additionalProperties.get(SWIFT_USE_API_NAMESPACE)));
}
additionalProperties.put(SWIFT_USE_API_NAMESPACE, swiftUseApiNamespace);
supportingFiles.add(new SupportingFile("Podspec.mustache", "", projectName + ".podspec"));
supportingFiles.add(new SupportingFile("Cartfile.mustache", "", "Cartfile"));
supportingFiles.add(new SupportingFile("APIHelper.mustache", sourceFolder, "APIHelper.swift"));
supportingFiles.add(new SupportingFile("AlamofireImplementations.mustache", sourceFolder,
"AlamofireImplementations.swift"));
supportingFiles.add(new SupportingFile("Extensions.mustache", sourceFolder, "Extensions.swift"));
supportingFiles.add(new SupportingFile("Models.mustache", sourceFolder, "Models.swift"));
supportingFiles.add(new SupportingFile("APIs.mustache", sourceFolder, "APIs.swift"));
}
@Override
public String escapeReservedWord(String name) {
return "_" + name; // add an underscore to the name
}
@Override
public String modelFileFolder() {
return outputFolder + File.separator + sourceFolder + modelPackage().replace('.', File.separatorChar);
}
@Override
public String apiFileFolder() {
return outputFolder + File.separator + sourceFolder + apiPackage().replace('.', File.separatorChar);
}
@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 "[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) || defaultIncludes.contains(type))
return type;
} else
type = swaggerType;
return toModelName(type); return toModelName(type);
} else
type = swaggerType;
return toModelName(type);
}
@Override
public String toDefaultValue(Property p) {
// nil
return null;
}
@Override
public String toInstantiationType(Property p) {
if (p instanceof MapProperty) {
MapProperty ap = (MapProperty) p;
String inner = getSwaggerType(ap.getAdditionalProperties());
return "[String:" + inner + "]";
} else if (p instanceof ArrayProperty) {
ArrayProperty ap = (ArrayProperty) p;
String inner = getSwaggerType(ap.getItems());
return "[" + inner + "]";
} }
return null;
}
@Override /**
public CodegenProperty fromProperty(String name, Property p) { * Output the proper model name (capitalized)
CodegenProperty codegenProperty = super.fromProperty(name, p); *
if (codegenProperty.isEnum) { * @param name the name of the model
List<Map<String, String>> swiftEnums = new ArrayList<Map<String, String>>(); * @return capitalized model name
List<String> values = (List<String>) codegenProperty.allowableValues.get("values"); */
for (String value : values) { @Override
Map<String, String> map = new HashMap<String, String>(); public String toModelName(String name) {
map.put("enum", toSwiftyEnumName(value)); name = sanitizeName(name); // FIXME parameter should not be assigned. Also declare it as "final"
map.put("raw", value);
swiftEnums.add(map); if (!StringUtils.isEmpty(modelNameSuffix)) { // set model suffix
} name = name + "_" + modelNameSuffix;
codegenProperty.allowableValues.put("values", swiftEnums); }
codegenProperty.datatypeWithEnum =
StringUtils.left(codegenProperty.datatypeWithEnum, codegenProperty.datatypeWithEnum.length() - "Enum".length()); if (!StringUtils.isEmpty(modelNamePrefix)) { // set model prefix
if (reservedWords.contains(codegenProperty.datatypeWithEnum)) { name = modelNamePrefix + "_" + name;
codegenProperty.datatypeWithEnum = escapeReservedWord(codegenProperty.datatypeWithEnum); }
}
// camelize the model name
// phone_number => PhoneNumber
name = camelize(name);
// model name cannot use reserved keyword, e.g. return
if (isReservedWord(name)) {
String modelName = "Model" + name;
LOGGER.warn(name + " (reserved word) cannot be used as model name. Renamed to " + modelName);
return modelName;
}
return name;
} }
return codegenProperty;
}
/**
* Return the capitalized file name of the model
*
* @param name the model name
* @return the file name of the model
*/
@Override
public String toModelFilename(String name) {
// should be the same as the model name
return toModelName(name);
}
@Override
public String toDefaultValue(Property p) {
// nil
return null;
}
@Override
public String toInstantiationType(Property p) {
if (p instanceof MapProperty) {
MapProperty ap = (MapProperty) p;
String inner = getSwaggerType(ap.getAdditionalProperties());
return "[String:" + inner + "]";
} else if (p instanceof ArrayProperty) {
ArrayProperty ap = (ArrayProperty) p;
String inner = getSwaggerType(ap.getItems());
return "[" + inner + "]";
}
return null;
}
@Override
public CodegenProperty fromProperty(String name, Property p) {
CodegenProperty codegenProperty = super.fromProperty(name, p);
if (codegenProperty.isEnum) {
List<Map<String, String>> swiftEnums = new ArrayList<Map<String, String>>();
List<String> values = (List<String>) codegenProperty.allowableValues.get("values");
for (String value : values) {
Map<String, String> map = new HashMap<String, String>();
map.put("enum", toSwiftyEnumName(value));
map.put("raw", value);
swiftEnums.add(map);
}
codegenProperty.allowableValues.put("values", swiftEnums);
codegenProperty.datatypeWithEnum =
StringUtils.left(codegenProperty.datatypeWithEnum, codegenProperty.datatypeWithEnum.length() - "Enum".length());
// Ensure that the enum type doesn't match a reserved word or
// the variable name doesn't match the generated enum type or the
// Swift compiler will generate an error
if (isReservedWord(codegenProperty.datatypeWithEnum) ||
name.equals(codegenProperty.datatypeWithEnum)) {
codegenProperty.datatypeWithEnum = escapeReservedWord(codegenProperty.datatypeWithEnum);
}
}
return codegenProperty;
}
@SuppressWarnings("static-method")
public String toSwiftyEnumName(String value) { public String toSwiftyEnumName(String value) {
// Prevent from breaking properly cased identifier // Prevent from breaking properly cased identifier
if (value.matches("[A-Z][a-z0-9]+[a-zA-Z0-9]*")) { if (value.matches("[A-Z][a-z0-9]+[a-zA-Z0-9]*")) {
@ -277,63 +340,129 @@ public class SwiftCodegen extends DefaultCodegen implements CodegenConfig {
} }
@Override @Override
public String toApiName(String name) { public String toApiName(String name) {
if(name.length() == 0) if(name.length() == 0)
return "DefaultAPI"; return "DefaultAPI";
return initialCaps(name) + "API"; return initialCaps(name) + "API";
}
@Override
public CodegenOperation fromOperation(String path, String httpMethod, Operation operation, Map<String, Model> definitions, Swagger swagger) {
path = normalizePath(path);
List<Parameter> parameters = operation.getParameters();
parameters = Lists.newArrayList(Iterators.filter(parameters.iterator(), new Predicate<Parameter>() {
@Override
public boolean apply(@Nullable Parameter parameter) {
return !(parameter instanceof HeaderParameter);
}
}));
operation.setParameters(parameters);
return super.fromOperation(path, httpMethod, operation, definitions, swagger);
}
private static String normalizePath(String path) {
StringBuilder builder = new StringBuilder();
int cursor = 0;
Matcher matcher = PATH_PARAM_PATTERN.matcher(path);
boolean found = matcher.find();
while (found) {
String stringBeforeMatch = path.substring(cursor, matcher.start());
builder.append(stringBeforeMatch);
String group = matcher.group().substring(1, matcher.group().length() - 1);
group = camelize(group, true);
builder
.append("{")
.append(group)
.append("}");
cursor = matcher.end();
found = matcher.find();
} }
String stringAfterMatch = path.substring(cursor); @Override
builder.append(stringAfterMatch); public String toOperationId(String operationId) {
operationId = camelize(sanitizeName(operationId), true);
return builder.toString(); // throw exception if method name is empty. This should not happen but keep the check just in case
} if (StringUtils.isEmpty(operationId)) {
throw new RuntimeException("Empty method name (operationId) not allowed");
}
public void setProjectName(String projectName) { // method name cannot use reserved keyword, e.g. return
this.projectName = projectName; if (isReservedWord(operationId)) {
} String newOperationId = camelize(("call_" + operationId), true);
LOGGER.warn(operationId + " (reserved word) cannot be used as method name. Renamed to " + newOperationId);
return newOperationId;
}
public void setUnwrapRequired(boolean unwrapRequired) { return operationId;
this.unwrapRequired = unwrapRequired; }
}
public void setResponseAs(String[] responseAs) { @Override
this.responseAs = responseAs; 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, 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) {
// 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 CodegenOperation fromOperation(String path, String httpMethod, Operation operation, Map<String, Model> definitions, Swagger swagger) {
path = normalizePath(path); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
List<Parameter> parameters = operation.getParameters();
parameters = Lists.newArrayList(Iterators.filter(parameters.iterator(), new Predicate<Parameter>() {
@Override
public boolean apply(@Nullable Parameter parameter) {
return !(parameter instanceof HeaderParameter);
}
}));
operation.setParameters(parameters);
return super.fromOperation(path, httpMethod, operation, definitions, swagger);
}
private static String normalizePath(String path) {
StringBuilder builder = new StringBuilder();
int cursor = 0;
Matcher matcher = PATH_PARAM_PATTERN.matcher(path);
boolean found = matcher.find();
while (found) {
String stringBeforeMatch = path.substring(cursor, matcher.start());
builder.append(stringBeforeMatch);
String group = matcher.group().substring(1, matcher.group().length() - 1);
group = camelize(group, true);
builder
.append("{")
.append(group)
.append("}");
cursor = matcher.end();
found = matcher.find();
}
String stringAfterMatch = path.substring(cursor);
builder.append(stringAfterMatch);
return builder.toString();
}
public void setProjectName(String projectName) {
this.projectName = projectName;
}
public void setUnwrapRequired(boolean unwrapRequired) {
this.unwrapRequired = unwrapRequired;
}
public void setResponseAs(String[] responseAs) {
this.responseAs = responseAs;
}
} }

View File

@ -53,7 +53,7 @@ public class TizenClientCodegen extends DefaultCodegen implements CodegenConfig
additionalProperties().put("prefix", PREFIX); additionalProperties().put("prefix", PREFIX);
reservedWords = new HashSet<String>( setReservedWordsLowerCase(
// VERIFY // VERIFY
Arrays.asList( Arrays.asList(
"void", "char", "short", "int", "void", "char", "short", "int", "void", "char", "short", "int", "void", "char", "short", "int",
@ -76,6 +76,9 @@ public class TizenClientCodegen extends DefaultCodegen implements CodegenConfig
typeMapping.put("map", "HashMap"); typeMapping.put("map", "HashMap");
typeMapping.put("number", "Long"); typeMapping.put("number", "Long");
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", "String");
importMapping = new HashMap<String, String>(); importMapping = new HashMap<String, String>();
@ -128,12 +131,8 @@ public class TizenClientCodegen 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;
@ -217,12 +216,8 @@ public class TizenClientCodegen extends DefaultCodegen implements CodegenConfig
} else if (p instanceof DecimalProperty) { } else if (p instanceof DecimalProperty) {
return "new Long()"; return "new Long()";
} else if (p instanceof MapProperty) { } else if (p instanceof MapProperty) {
MapProperty ap = (MapProperty) p;
String inner = getSwaggerType(ap.getAdditionalProperties());
return "new HashMap()"; return "new HashMap()";
} else if (p instanceof ArrayProperty) { } else if (p instanceof ArrayProperty) {
ArrayProperty ap = (ArrayProperty) p;
String inner = getSwaggerType(ap.getItems());
return "new ArrayList()"; return "new ArrayList()";
} }
// else // else
@ -278,7 +273,7 @@ public class TizenClientCodegen 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

@ -15,6 +15,12 @@ public class TypeScriptAngularClientCodegen extends AbstractTypeScriptClientCode
return "Generates a TypeScript AngularJS client library."; return "Generates a TypeScript AngularJS client library.";
} }
@Override
public void processOpts() {
super.processOpts();
supportingFiles.add(new SupportingFile("api.d.mustache", apiPackage().replace('.', File.separatorChar), "api.d.ts"));
}
public TypeScriptAngularClientCodegen() { public TypeScriptAngularClientCodegen() {
super(); super();
outputFolder = "generated-code/typescript-angular"; outputFolder = "generated-code/typescript-angular";
@ -23,6 +29,5 @@ public class TypeScriptAngularClientCodegen extends AbstractTypeScriptClientCode
embeddedTemplateDir = templateDir = "TypeScript-Angular"; embeddedTemplateDir = templateDir = "TypeScript-Angular";
apiPackage = "API.Client"; apiPackage = "API.Client";
modelPackage = "API.Client"; modelPackage = "API.Client";
supportingFiles.add(new SupportingFile("api.d.mustache", apiPackage().replace('.', File.separatorChar), "api.d.ts"));
} }
} }

View File

@ -14,11 +14,16 @@ public class TypeScriptNodeClientCodegen extends AbstractTypeScriptClientCodegen
return "Generates a TypeScript nodejs client library."; return "Generates a TypeScript nodejs client library.";
} }
@Override
public void processOpts() {
super.processOpts();
supportingFiles.add(new SupportingFile("api.mustache", null, "api.ts"));
}
public TypeScriptNodeClientCodegen() { public TypeScriptNodeClientCodegen() {
super(); super();
outputFolder = "generated-code/typescript-node"; outputFolder = "generated-code/typescript-node";
embeddedTemplateDir = templateDir = "TypeScript-node"; embeddedTemplateDir = templateDir = "TypeScript-node";
supportingFiles.add(new SupportingFile("api.mustache", null, "api.ts"));
} }
} }

View File

@ -1,4 +1,4 @@
package io.swagger.codegen.cmd.utils; package io.swagger.codegen.utils;
import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Pair;

View File

@ -1,5 +1,7 @@
apply plugin: 'groovy' apply plugin: 'groovy'
apply plugin: 'idea' apply plugin: 'idea'
apply plugin: 'eclipse'
def artifactory = 'buildserver.supportspace.com' def artifactory = 'buildserver.supportspace.com'
group = 'com.supportspace' group = 'com.supportspace'
archivesBaseName = 'swagger-gen-groovy' archivesBaseName = 'swagger-gen-groovy'

View File

@ -103,7 +103,7 @@
<stringProp name="HTTPSampler.response_timeout"></stringProp> <stringProp name="HTTPSampler.response_timeout"></stringProp>
<stringProp name="HTTPSampler.protocol"></stringProp> <stringProp name="HTTPSampler.protocol"></stringProp>
<stringProp name="HTTPSampler.contentEncoding"></stringProp> <stringProp name="HTTPSampler.contentEncoding"></stringProp>
<stringProp name="HTTPSampler.path">{{vendorExtensions.x-path}}</stringProp> <stringProp name="HTTPSampler.path">{{basePathWithoutHost}}{{vendorExtensions.x-path}}</stringProp>
<stringProp name="HTTPSampler.method">{{httpMethod}}</stringProp> <stringProp name="HTTPSampler.method">{{httpMethod}}</stringProp>
<boolProp name="HTTPSampler.follow_redirects">true</boolProp> <boolProp name="HTTPSampler.follow_redirects">true</boolProp>
<boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.auto_redirects">false</boolProp>

View File

@ -49,7 +49,7 @@ public class ApiClient {
private int connectionTimeout = 0; private int connectionTimeout = 0;
private Client httpClient; private Client httpClient;
private ObjectMapper mapper; private ObjectMapper objectMapper;
private Map<String, Authentication> authentications; private Map<String, Authentication> authentications;
@ -59,24 +59,16 @@ public class ApiClient {
private DateFormat dateFormat; private DateFormat dateFormat;
public ApiClient() { public ApiClient() {
mapper = new ObjectMapper(); objectMapper = new ObjectMapper();
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); objectMapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING);
mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); objectMapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING);
mapper.registerModule(new JodaModule()); objectMapper.registerModule(new JodaModule());
objectMapper.setDateFormat(ApiClient.buildDefaultDateFormat());
httpClient = buildHttpClient(debugging); dateFormat = ApiClient.buildDefaultDateFormat();
// Use RFC3339 format for date and datetime.
// See http://xml2rfc.ietf.org/public/rfc/html/rfc3339.html#anchor14
this.dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
// Use UTC as the default time zone.
this.dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
this.mapper.setDateFormat((DateFormat) dateFormat.clone());
// Set default User-Agent. // Set default User-Agent.
setUserAgent("Java-Swagger"); setUserAgent("Java-Swagger");
@ -88,6 +80,62 @@ public class ApiClient {
authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}} authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}}
// Prevent the authentications from being modified. // Prevent the authentications from being modified.
authentications = Collections.unmodifiableMap(authentications); authentications = Collections.unmodifiableMap(authentications);
rebuildHttpClient();
}
public static DateFormat buildDefaultDateFormat() {
// Use RFC3339 format for date and datetime.
// See http://xml2rfc.ietf.org/public/rfc/html/rfc3339.html#anchor14
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
// Use UTC as the default time zone.
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
return dateFormat;
}
/**
* Build the Client used to make HTTP requests with the latest settings,
* i.e. objectMapper and debugging.
* TODO: better to use the Builder Pattern?
*/
public ApiClient rebuildHttpClient() {
// Add the JSON serialization support to Jersey
JacksonJsonProvider jsonProvider = new JacksonJsonProvider(objectMapper);
DefaultClientConfig conf = new DefaultClientConfig();
conf.getSingletons().add(jsonProvider);
Client client = Client.create(conf);
if (debugging) {
client.addFilter(new LoggingFilter());
}
this.httpClient = client;
return this;
}
/**
* Returns the current object mapper used for JSON serialization/deserialization.
* <p>
* Note: If you make changes to the object mapper, remember to set it back via
* <code>setObjectMapper</code> in order to trigger HTTP client rebuilding.
* </p>
*/
public ObjectMapper getObjectMapper() {
return objectMapper;
}
public ApiClient setObjectMapper(ObjectMapper objectMapper) {
this.objectMapper = objectMapper;
// Need to rebuild the Client as it depends on object mapper.
rebuildHttpClient();
return this;
}
public Client getHttpClient() {
return httpClient;
}
public ApiClient setHttpClient(Client httpClient) {
this.httpClient = httpClient;
return this;
} }
public String getBasePath() { public String getBasePath() {
@ -228,8 +276,8 @@ public class ApiClient {
*/ */
public ApiClient setDebugging(boolean debugging) { public ApiClient setDebugging(boolean debugging) {
this.debugging = debugging; this.debugging = debugging;
// Rebuild HTTP Client according to the new "debugging" value. // Need to rebuild the Client as it depends on the value of debugging.
this.httpClient = buildHttpClient(debugging); rebuildHttpClient();
return this; return this;
} }
@ -263,8 +311,10 @@ public class ApiClient {
*/ */
public ApiClient setDateFormat(DateFormat dateFormat) { public ApiClient setDateFormat(DateFormat dateFormat) {
this.dateFormat = dateFormat; this.dateFormat = dateFormat;
// also set the date format for model (de)serialization with Date properties // Also set the date format for model (de)serialization with Date properties.
this.mapper.setDateFormat((DateFormat) dateFormat.clone()); this.objectMapper.setDateFormat((DateFormat) dateFormat.clone());
// Need to rebuild the Client as objectMapper changes.
rebuildHttpClient();
return this; return this;
} }
@ -452,34 +502,51 @@ public class ApiClient {
} }
} }
private ClientResponse getAPIResponse(String path, String method, List<Pair> queryParams, Object body, Map<String, String> headerParams, Map<String, Object> formParams, String accept, String contentType, String[] authNames) throws ApiException { /**
* Build full URL by concatenating base path, the given sub path and query parameters.
*
* @param path The sub path
* @param queryParams The query parameters
* @return The full URL
*/
private String buildUrl(String path, List<Pair> queryParams) {
final StringBuilder url = new StringBuilder();
url.append(basePath).append(path);
if (body != null && !formParams.isEmpty()){ if (queryParams != null && !queryParams.isEmpty()) {
// support (constant) query string in `path`, e.g. "/posts?draft=1"
String prefix = path.contains("?") ? "&" : "?";
for (Pair param : queryParams) {
if (param.getValue() != null) {
if (prefix != null) {
url.append(prefix);
prefix = null;
} else {
url.append("&");
}
String value = parameterToString(param.getValue());
url.append(escapeString(param.getName())).append("=").append(escapeString(value));
}
}
}
return url.toString();
}
private ClientResponse getAPIResponse(String path, String method, List<Pair> queryParams, Object body, Map<String, String> headerParams, Map<String, Object> formParams, String accept, String contentType, String[] authNames) throws ApiException {
if (body != null && !formParams.isEmpty()) {
throw new ApiException(500, "Cannot have body and form params"); throw new ApiException(500, "Cannot have body and form params");
} }
updateParamsForAuth(authNames, queryParams, headerParams); updateParamsForAuth(authNames, queryParams, headerParams);
StringBuilder b = new StringBuilder(); final String url = buildUrl(path, queryParams);
b.append("?");
if (queryParams != null){
for (Pair queryParam : queryParams){
if (!queryParam.getName().isEmpty()) {
b.append(escapeString(queryParam.getName()));
b.append("=");
b.append(escapeString(queryParam.getValue()));
b.append("&");
}
}
}
String querystring = b.substring(0, b.length() - 1);
Builder builder; Builder builder;
if (accept == null) if (accept == null) {
builder = httpClient.resource(basePath + path + querystring).getRequestBuilder(); builder = httpClient.resource(url).getRequestBuilder();
else } else {
builder = httpClient.resource(basePath + path + querystring).accept(accept); builder = httpClient.resource(url).accept(accept);
}
for (String key : headerParams.keySet()) { for (String key : headerParams.keySet()) {
builder = builder.header(key, headerParams.get(key)); builder = builder.header(key, headerParams.get(key));
@ -500,7 +567,10 @@ public class ApiClient {
response = builder.type(contentType).put(ClientResponse.class, serialize(body, contentType, formParams)); response = builder.type(contentType).put(ClientResponse.class, serialize(body, contentType, formParams));
} else if ("DELETE".equals(method)) { } else if ("DELETE".equals(method)) {
response = builder.type(contentType).delete(ClientResponse.class, serialize(body, contentType, formParams)); response = builder.type(contentType).delete(ClientResponse.class, serialize(body, contentType, formParams));
} else { } else if ("PATCH".equals(method)) {
response = builder.type(contentType).header("X-HTTP-Method-Override", "PATCH").post(ClientResponse.class, serialize(body, contentType, formParams));
}
else {
throw new ApiException(500, "unknown method type " + method); throw new ApiException(500, "unknown method type " + method);
} }
return response; return response;
@ -591,19 +661,4 @@ public class ApiClient {
return encodedFormParams; return encodedFormParams;
} }
/**
* Build the Client used to make HTTP requests.
*/
private Client buildHttpClient(boolean debugging) {
// Add the JSON serialization support to Jersey
JacksonJsonProvider jsonProvider = new JacksonJsonProvider(mapper);
DefaultClientConfig conf = new DefaultClientConfig();
conf.getSingletons().add(jsonProvider);
Client client = Client.create(conf);
if (debugging) {
client.addFilter(new LoggingFilter());
}
return client;
}
} }

View File

@ -20,7 +20,7 @@ mvn deploy
Refer to the [official documentation](https://maven.apache.org/plugins/maven-deploy-plugin/usage.html) for more information. Refer to the [official documentation](https://maven.apache.org/plugins/maven-deploy-plugin/usage.html) for more information.
After the client libarary is installed/deployed, you can use it in your Maven project by adding the following to your *pom.xml*: After the client library is installed/deployed, you can use it in your Maven project by adding the following to your *pom.xml*:
```xml ```xml
<dependency> <dependency>

View File

@ -11,7 +11,10 @@ import {{invokerPackage}}.Pair;
{{/imports}} {{/imports}}
{{^fullJavaUtil}} {{^fullJavaUtil}}
import java.util.*; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
{{/fullJavaUtil}} {{/fullJavaUtil}}
{{>generatedAnnotation}} {{>generatedAnnotation}}
@ -38,56 +41,57 @@ public class {{classname}} {
{{#operation}} {{#operation}}
/** /**
* {{summary}} * {{summary}}
* {{notes}} * {{notes}}{{#allParams}}
{{#allParams}} * @param {{paramName}} {{description}} * @param {{paramName}} {{description}}{{/allParams}}{{#returnType}}
{{/allParams}} * @return {{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}void{{/returnType}} * @return {{{returnType}}}{{/returnType}}
* @throws ApiException if fails to make API call
*/ */
public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException { public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException {
Object {{localVariablePrefix}}postBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; Object {{localVariablePrefix}}localVarPostBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}};
{{#allParams}}{{#required}} {{#allParams}}{{#required}}
// verify the required parameter '{{paramName}}' is set // verify the required parameter '{{paramName}}' is set
if ({{paramName}} == null) { if ({{paramName}} == null) {
throw new ApiException(400, "Missing the required parameter '{{paramName}}' when calling {{operationId}}"); throw new ApiException(400, "Missing the required parameter '{{paramName}}' when calling {{operationId}}");
} }
{{/required}}{{/allParams}} {{/required}}{{/allParams}}
// create path and map variables // create path and map variables
String {{localVariablePrefix}}path = "{{{path}}}".replaceAll("\\{format\\}","json"){{#pathParams}} String {{localVariablePrefix}}localVarPath = "{{{path}}}".replaceAll("\\{format\\}","json"){{#pathParams}}
.replaceAll("\\{" + "{{baseName}}" + "\\}", {{localVariablePrefix}}apiClient.escapeString({{{paramName}}}.toString())){{/pathParams}}; .replaceAll("\\{" + "{{baseName}}" + "\\}", {{localVariablePrefix}}apiClient.escapeString({{{paramName}}}.toString())){{/pathParams}};
// query params // query params
{{javaUtilPrefix}}List<Pair> {{localVariablePrefix}}queryParams = new {{javaUtilPrefix}}ArrayList<Pair>(); {{javaUtilPrefix}}List<Pair> {{localVariablePrefix}}localVarQueryParams = new {{javaUtilPrefix}}ArrayList<Pair>();
{{javaUtilPrefix}}Map<String, String> {{localVariablePrefix}}headerParams = new {{javaUtilPrefix}}HashMap<String, String>(); {{javaUtilPrefix}}Map<String, String> {{localVariablePrefix}}localVarHeaderParams = new {{javaUtilPrefix}}HashMap<String, String>();
{{javaUtilPrefix}}Map<String, Object> {{localVariablePrefix}}formParams = new {{javaUtilPrefix}}HashMap<String, Object>(); {{javaUtilPrefix}}Map<String, Object> {{localVariablePrefix}}localVarFormParams = new {{javaUtilPrefix}}HashMap<String, Object>();
{{#queryParams}} {{#queryParams}}
{{localVariablePrefix}}queryParams.addAll({{localVariablePrefix}}apiClient.parameterToPairs("{{#collectionFormat}}{{{collectionFormat}}}{{/collectionFormat}}", "{{baseName}}", {{paramName}})); {{localVariablePrefix}}localVarQueryParams.addAll({{localVariablePrefix}}apiClient.parameterToPairs("{{#collectionFormat}}{{{collectionFormat}}}{{/collectionFormat}}", "{{baseName}}", {{paramName}}));
{{/queryParams}} {{/queryParams}}
{{#headerParams}}if ({{paramName}} != null) {{#headerParams}}if ({{paramName}} != null)
{{localVariablePrefix}}headerParams.put("{{baseName}}", {{localVariablePrefix}}apiClient.parameterToString({{paramName}})); {{localVariablePrefix}}localVarHeaderParams.put("{{baseName}}", {{localVariablePrefix}}apiClient.parameterToString({{paramName}}));
{{/headerParams}} {{/headerParams}}
{{#formParams}}if ({{paramName}} != null) {{#formParams}}if ({{paramName}} != null)
{{localVariablePrefix}}formParams.put("{{baseName}}", {{paramName}}); {{localVariablePrefix}}localVarFormParams.put("{{baseName}}", {{paramName}});
{{/formParams}} {{/formParams}}
final String[] {{localVariablePrefix}}accepts = { final String[] {{localVariablePrefix}}localVarAccepts = {
{{#produces}}"{{mediaType}}"{{#hasMore}}, {{/hasMore}}{{/produces}} {{#produces}}"{{mediaType}}"{{#hasMore}}, {{/hasMore}}{{/produces}}
}; };
final String {{localVariablePrefix}}accept = {{localVariablePrefix}}apiClient.selectHeaderAccept({{localVariablePrefix}}accepts); final String {{localVariablePrefix}}localVarAccept = {{localVariablePrefix}}apiClient.selectHeaderAccept({{localVariablePrefix}}localVarAccepts);
final String[] {{localVariablePrefix}}contentTypes = { final String[] {{localVariablePrefix}}localVarContentTypes = {
{{#consumes}}"{{mediaType}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} {{#consumes}}"{{mediaType}}"{{#hasMore}}, {{/hasMore}}{{/consumes}}
}; };
final String {{localVariablePrefix}}contentType = {{localVariablePrefix}}apiClient.selectHeaderContentType({{localVariablePrefix}}contentTypes); final String {{localVariablePrefix}}localVarContentType = {{localVariablePrefix}}apiClient.selectHeaderContentType({{localVariablePrefix}}localVarContentTypes);
String[] {{localVariablePrefix}}authNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; String[] {{localVariablePrefix}}localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} };
{{#returnType}} {{#returnType}}
GenericType<{{{returnType}}}> {{localVariablePrefix}}returnType = new GenericType<{{{returnType}}}>() {}; GenericType<{{{returnType}}}> {{localVariablePrefix}}localVarReturnType = new GenericType<{{{returnType}}}>() {};
return {{localVariablePrefix}}apiClient.invokeAPI({{localVariablePrefix}}path, "{{httpMethod}}", {{localVariablePrefix}}queryParams, {{localVariablePrefix}}postBody, {{localVariablePrefix}}headerParams, {{localVariablePrefix}}formParams, {{localVariablePrefix}}accept, {{localVariablePrefix}}contentType, {{localVariablePrefix}}authNames, {{localVariablePrefix}}returnType); return {{localVariablePrefix}}apiClient.invokeAPI({{localVariablePrefix}}localVarPath, "{{httpMethod}}", {{localVariablePrefix}}localVarQueryParams, {{localVariablePrefix}}localVarPostBody, {{localVariablePrefix}}localVarHeaderParams, {{localVariablePrefix}}localVarFormParams, {{localVariablePrefix}}localVarAccept, {{localVariablePrefix}}localVarContentType, {{localVariablePrefix}}localVarAuthNames, {{localVariablePrefix}}localVarReturnType);
{{/returnType}}{{^returnType}} {{/returnType}}{{^returnType}}
{{localVariablePrefix}}apiClient.invokeAPI({{localVariablePrefix}}path, "{{httpMethod}}", {{localVariablePrefix}}queryParams, {{localVariablePrefix}}postBody, {{localVariablePrefix}}headerParams, {{localVariablePrefix}}formParams, {{localVariablePrefix}}accept, {{localVariablePrefix}}contentType, {{localVariablePrefix}}authNames, null); {{localVariablePrefix}}apiClient.invokeAPI({{localVariablePrefix}}localVarPath, "{{httpMethod}}", {{localVariablePrefix}}localVarQueryParams, {{localVariablePrefix}}localVarPostBody, {{localVariablePrefix}}localVarHeaderParams, {{localVariablePrefix}}localVarFormParams, {{localVariablePrefix}}localVarAccept, {{localVariablePrefix}}localVarContentType, {{localVariablePrefix}}localVarAuthNames, null);
{{/returnType}} {{/returnType}}
} }
{{/operation}} {{/operation}}

View File

@ -1,3 +1,6 @@
apply plugin: 'idea'
apply plugin: 'eclipse'
group = '{{groupId}}' group = '{{groupId}}'
version = '{{artifactVersion}}' version = '{{artifactVersion}}'
@ -105,7 +108,9 @@ dependencies {
compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" compile "com.fasterxml.jackson.core:jackson-core:$jackson_version"
compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version"
compile "com.fasterxml.jackson.core:jackson-databind:$jackson_version" compile "com.fasterxml.jackson.core:jackson-databind:$jackson_version"
compile "com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:$jackson_version"
compile "com.fasterxml.jackson.datatype:jackson-datatype-joda:2.1.5" compile "com.fasterxml.jackson.datatype:jackson-datatype-joda:2.1.5"
compile "joda-time:joda-time:$jodatime_version" compile "joda-time:joda-time:$jodatime_version"
compile "com.brsanthu:migbase64:2.2"
testCompile "junit:junit:$junit_version" testCompile "junit:junit:$junit_version"
} }

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